diff --git a/AGENTS.md b/AGENTS.md index 74e1c9156..e6b15c49d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -329,7 +329,7 @@ flowchart TB ```python app.connect("config-inited", load_config_from_toml, priority=10) # Load TOML config -app.connect("config-inited", load_config) # Register extra options/directives +app.connect("config-inited", load_config) # Register extra fields/directives app.connect("config-inited", merge_default_configs) # Merge defaults app.connect("config-inited", check_configuration, priority=600) # Validate config ``` @@ -343,7 +343,7 @@ app.connect("env-before-read-docs", resolve_schemas_config). # Validates schema app.connect("env-before-read-docs", load_external_needs) # Load external need files ``` -The `prepare_env` function initializes `BuildEnvironment` variables, registers services (GitHub, OpenNeeds), registers dynamic functions, initializes extra options and link types, and optionally starts process timing. +The `prepare_env` function initializes `BuildEnvironment` variables, registers services (GitHub, OpenNeeds), registers dynamic functions, initializes extra fields and links, and optionally starts process timing. #### Document Processing diff --git a/docs/api.rst b/docs/api.rst index 132e7afd9..52bceb90d 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -62,7 +62,7 @@ Schema FieldLiteralValue, LinkSchema, LinkDisplayConfig, LinksLiteralValue, AllowedTypes .. automodule:: sphinx_needs.schema.config - :members: ExtraOptionStringSchemaType, ExtraOptionBooleanSchemaType, - ExtraOptionIntegerSchemaType, ExtraOptionNumberSchemaType, - ExtraOptionMultiValueSchemaType, + :members: FieldStringSchemaType, FieldBooleanSchemaType, + FieldIntegerSchemaType, FieldNumberSchemaType, + FieldMultiValueSchemaType, ExtraLinkSchemaType, ExtraLinkItemSchemaType diff --git a/docs/conf.py b/docs/conf.py index 8d9cd8382..a568f3190 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -51,7 +51,7 @@ ("py:class", "sphinx_needs.views._LazyIndexes"), ("py:class", "sphinx_needs.config.NeedsSphinxConfig"), ("py:class", "AllowedTypes"), - ("py:class", "ExtraOptionSchemaTypes"), + ("py:class", "FieldSchemaTypes"), ] rst_epilog = """ @@ -268,6 +268,7 @@ r"http://127.0.0.1:\d+", r"../.*", r"http://sourceforge.net/projects/plantuml.*", + r"http?://beta.plantuml.net/plantuml.jar", r"https?://useblocks.com/sphinx-needs/bench/index.html", ] diff --git a/docs/filter.rst b/docs/filter.rst index 71ef434ec..d823ffacf 100644 --- a/docs/filter.rst +++ b/docs/filter.rst @@ -144,7 +144,7 @@ Additional variables for :ref:`need_part`: * **id_complete** as Python string. Contains the concatenated ids of parent need and need_part. (compare like ``id_complete != 'ABC_01.03'``) -.. note:: If extra options were specified using :ref:`needs_fields` then +.. note:: If extra fields were specified using :ref:`needs_fields` then those will be available for use in filter expressions as well. Finally, the following are available: diff --git a/docs/schema/index.rst b/docs/schema/index.rst index 4017878cf..e3266ed42 100644 --- a/docs/schema/index.rst +++ b/docs/schema/index.rst @@ -23,7 +23,7 @@ See :ref:`migration_from_warnings_constraints` for details on how to migrate. conform to their types are not created and lead to a warning. - **JSON export**: Generated :ref:`needs.json ` files honor the user provided types - - **Multi value extra options**: Array types for extra options are fully supported + - **Multi value extra fields**: Array types for extra fields are fully supported - **Gradual migration**: Existing projects can migrate step-by-step to the new system, with string types as default for untyped fields. - **Safety**: The new type system core makes it possible to configure fields individually. @@ -60,11 +60,11 @@ Schema configuration The schema is configured in multiple places: -- :ref:`needs_fields` is the place to add new extra options that are then available +- :ref:`needs_fields` is the place to add new fields that are then available for all need types. The type information for each field is globally set here, so it is valid for all the usages of that field for any need type. This is required for a coherent data storage, as it would be expected by a database system. If different data types are needed for the - same option, it means creating a new extra option with a different name and type. + same option, it means creating a new field with a different name and type. Further, the ``schema`` field in ``needs_fields`` also supports setting global schema constraints for that option, that will be checked for each need type. E.g. @@ -111,9 +111,9 @@ Imagine the following modeling of need items: There are a few things to note about this setup: -- the extra options ``efforts``, ``approval`` and +- the fields ``efforts``, ``approval`` and ``asil`` (for **A**\ utomotive **S**\ ecurity **I**\ ntegrity **L**\ evel) are typed -- the assigned extra options differ between need types +- the assigned fields differ between need types - the fields may be optional for a need type, required or even not allowed - some validation rules are local to the need itself, while others require information from other needs (network validation) @@ -180,25 +180,21 @@ For **primitive types** (string, integer, number, boolean): .. code-block:: toml - [[needs.extra_options]] - name = "efforts" + [needs.fields.efforts] schema.type = "integer" - [[needs.extra_options]] - name = "approval" + [needs.fields.approval] schema.type = "boolean" For **array types**, both the array type and the item type must be specified: .. code-block:: toml - [[needs.extra_options]] - name = "tags" + [needs.fields.tags] schema.type = "array" schema.items.type = "string" - [[needs.extra_options]] - name = "priorities" + [needs.fields.priorities] schema.type = "array" schema.items.type = "integer" @@ -209,12 +205,12 @@ Additional schema constraints can also be defined here, which will be validated .. code-block:: toml - [[needs.extra_options]] + [needs.fields.asil] name = "asil" schema.type = "string" schema.enum = ["QM", "A", "B", "C", "D"] - [[needs.extra_options]] + [needs.fields.efforts] name = "efforts" schema.type = "integer" schema.minimum = 0 @@ -229,9 +225,9 @@ The ``schemas.json`` file (or :ref:`needs_schema_definitions`) also requires typ validation, but: - **If type is not specified** in schemas.json, it will be **automatically injected** from the - ``needs.extra_options`` definition (or from core field definitions for built-in fields) + ``needs.fields`` definition (or from core field definitions for built-in fields) - **If type is specified** in schemas.json, it **must match** the type defined in - ``needs.extra_options`` (or the core field definition) + ``needs.fields`` (or the core field definition) This ensures type consistency across your entire configuration while reducing duplication. The injection to the schema rules is required for safe JSON schema validation. diff --git a/performance/performance_test.py b/performance/performance_test.py index 9d692e315..7a7cd2c9f 100644 --- a/performance/performance_test.py +++ b/performance/performance_test.py @@ -216,7 +216,7 @@ def start( @click.option( "--basic", is_flag=True, - help="Use only default config of Sphinx-Needs (e.g. no extra options)", + help="Use only default config of Sphinx-Needs (e.g. no extra fields)", ) def series( profile, diff --git a/sphinx_needs/api/configuration.py b/sphinx_needs/api/configuration.py index d54e087f7..9e73b7a00 100644 --- a/sphinx_needs/api/configuration.py +++ b/sphinx_needs/api/configuration.py @@ -16,7 +16,7 @@ from sphinx_needs.exceptions import NeedsApiConfigException from sphinx_needs.functions.functions import DynamicFunction from sphinx_needs.need_item import NeedItem -from sphinx_needs.schema.config import ExtraOptionSchemaTypes +from sphinx_needs.schema.config import FieldSchemaTypes # TODO(mh) document exactly when API calls are allowed in the Sphinx event system @@ -92,7 +92,7 @@ def add_extra_option( name: str, *, description: str = "Added by add_extra_option API", - schema: ExtraOptionSchemaTypes | None = None, + schema: FieldSchemaTypes | None = None, nullable: bool | None = None, parse_variants: bool | None = None, ) -> None: @@ -136,7 +136,7 @@ def add_field( /, description: str, *, - schema: ExtraOptionSchemaTypes | None = None, + schema: FieldSchemaTypes | None = None, nullable: bool | None = None, parse_variants: bool | None = None, ) -> None: @@ -151,9 +151,9 @@ def add_field( add_field('my_field') - :param name: Name of the extra option - :param description: Description of the extra option - :param schema: Schema definition for the extra option + :param name: Name of the field + :param description: Description of the field + :param schema: Schema definition for the field :param nullable: Whether the field allows unset values. :param parse_variants: Whether variants are parsed in this field. """ diff --git a/sphinx_needs/api/need.py b/sphinx_needs/api/need.py index a10866528..318299e35 100644 --- a/sphinx_needs/api/need.py +++ b/sphinx_needs/api/need.py @@ -113,7 +113,7 @@ def generate_need( :raises InvalidNeedException: If the data fails any validation issue. - ``kwargs`` can contain options defined in ``needs_extra_options`` and ``needs_extra_links``. + ``kwargs`` can contain options defined in ``needs_fields`` and ``needs_extra_links``. If an entry is found in ``kwargs``, which *is not* specified in the configuration or registered e.g. via ``add_field``, an exception is raised. @@ -185,7 +185,7 @@ def generate_need( if unknown_kwargs: raise InvalidNeedException( "invalid_kwargs", - f"Options {unknown_kwargs!r} not in 'needs_extra_options' or 'needs_extra_links.", + f"{unknown_kwargs!r} not in 'needs_fields' or 'needs_extra_links.", ) # get the need type data @@ -277,8 +277,8 @@ def generate_need( ) except Exception as err: raise InvalidNeedException( - "invalid_extra_option", - f"Extra option {extra_field.name!r} is invalid: {err}", + "invalid_field_value", + f"Field {extra_field.name!r} is invalid: {err}", ) from err links_no_defaults: dict[str, None | LinksLiteralValue | LinksFunctionArray] = {} @@ -488,14 +488,14 @@ def generate_need( for k, v in extras.items(): if (extra_schema := needs_schema.get_extra_field(k)) is None: raise InvalidNeedException( - "invalid_extra_option", - f"Extra option {k!r} not in 'needs_fields'.", + "invalid_field_value", + f"Field {k!r} not in 'needs_fields'.", ) if v is None: if not extra_schema.nullable: raise InvalidNeedException( - "invalid_extra_option", - f"Extra option {k!r} is not nullable, but no value or default was given.", + "invalid_field_value", + f"Field {k!r} is not nullable, but no value or default was given.", ) extras_pre[k] = None elif isinstance(v, FieldLiteralValue): @@ -515,13 +515,13 @@ def generate_need( extras_pre[k] = [] case other: raise InvalidNeedException( - "invalid_extra_option", - f"Extra option {k!r} has unknown type {other!r}.", + "invalid_field_value", + f"Field {k!r} has unknown type {other!r}.", ) else: raise InvalidNeedException( - "invalid_extra_option", - f"Extra option {k!r} has unknown value {v!r}.", + "invalid_field_value", + f"Field {k!r} has unknown value {v!r}.", ) links_pre: dict[str, list[str]] = {} @@ -765,7 +765,7 @@ def add_need( ``add_need`` allows to create needs programmatically and use its returned node to be integrated in any docutils based structure. - ``kwargs`` can contain options defined in ``needs_extra_options`` and ``needs_extra_links``. + ``kwargs`` can contain options defined in ``needs_fields`` and ``needs_extra_links``. If an entry is found in ``kwargs``, which *is not* specified in the configuration or registered e.g. via ``add_field``, an exception is raised. diff --git a/sphinx_needs/config.py b/sphinx_needs/config.py index a7eeda4ce..74b874af3 100644 --- a/sphinx_needs/config.py +++ b/sphinx_needs/config.py @@ -13,12 +13,12 @@ from sphinx_needs.logging import get_logger, log_warning from sphinx_needs.schema.config import ( ExtraLinkSchemaType, - ExtraOptionBooleanSchemaType, - ExtraOptionIntegerSchemaType, - ExtraOptionMultiValueSchemaType, - ExtraOptionNumberSchemaType, - ExtraOptionSchemaTypes, - ExtraOptionStringSchemaType, + FieldBooleanSchemaType, + FieldIntegerSchemaType, + FieldMultiValueSchemaType, + FieldNumberSchemaType, + FieldSchemaTypes, + FieldStringSchemaType, SchemasFileRootType, ) @@ -42,11 +42,11 @@ class NewFieldParams: nullable: bool | None = None """Whether the field allows unset values.""" schema: ( - ExtraOptionStringSchemaType - | ExtraOptionBooleanSchemaType - | ExtraOptionIntegerSchemaType - | ExtraOptionNumberSchemaType - | ExtraOptionMultiValueSchemaType + FieldStringSchemaType + | FieldBooleanSchemaType + | FieldIntegerSchemaType + | FieldNumberSchemaType + | FieldMultiValueSchemaType | None ) """A JSON schema for the option.""" @@ -110,11 +110,11 @@ def add_field( name: str, description: str, *, - schema: ExtraOptionStringSchemaType - | ExtraOptionBooleanSchemaType - | ExtraOptionIntegerSchemaType - | ExtraOptionNumberSchemaType - | ExtraOptionMultiValueSchemaType + schema: FieldStringSchemaType + | FieldBooleanSchemaType + | FieldIntegerSchemaType + | FieldNumberSchemaType + | FieldMultiValueSchemaType | None = None, nullable: None | bool = None, override: bool = False, @@ -311,7 +311,7 @@ class NeedFields(TypedDict): description: NotRequired[str] """A description of the field.""" - schema: NotRequired[ExtraOptionSchemaTypes] + schema: NotRequired[FieldSchemaTypes] """ A JSON schema definition for the field. @@ -328,7 +328,7 @@ class NeedFields(TypedDict): """Whether variants are parsed in this field.""" -class NeedExtraOption(NeedFields): +class NeedField(NeedFields): """Defines an extra option for needs""" name: str @@ -620,7 +620,7 @@ def get_default(cls, name: str) -> Any: _fields: dict[str, NeedFields] = field( default_factory=dict, metadata={"rebuild": "html", "types": (dict,)} ) - _extra_options: list[str | NeedExtraOption] = field( + _extra_options: list[str | NeedField] = field( default_factory=list, metadata={"rebuild": "html", "types": (list,)} ) """List of extra options for needs, that get added as directive options and need fields.""" diff --git a/sphinx_needs/directives/needservice.py b/sphinx_needs/directives/needservice.py index 44e9da500..5d6a4cb4e 100644 --- a/sphinx_needs/directives/needservice.py +++ b/sphinx_needs/directives/needservice.py @@ -118,7 +118,7 @@ def run(self) -> Sequence[nodes.Node]: del datum["title"] # We need to check if all given options from services are really available as configured - # extra_option or extra_link + # needs_fields or needs_extra_links missing_options = {} for element in datum: if element not in defined_options: diff --git a/sphinx_needs/exceptions.py b/sphinx_needs/exceptions.py index 942011a2b..e9c07443e 100644 --- a/sphinx_needs/exceptions.py +++ b/sphinx_needs/exceptions.py @@ -21,7 +21,7 @@ def __init__( type_: Literal[ "invalid_kwargs", "invalid_type", - "invalid_extra_option", + "invalid_field_value", "invalid_link_option", "missing_id", "invalid_id", @@ -50,7 +50,7 @@ def type( ) -> Literal[ "invalid_kwargs", "invalid_type", - "invalid_extra_option", + "invalid_field_value", "invalid_link_option", "missing_id", "invalid_id", diff --git a/sphinx_needs/needs.py b/sphinx_needs/needs.py index 2a6a745c9..fab600135 100644 --- a/sphinx_needs/needs.py +++ b/sphinx_needs/needs.py @@ -127,7 +127,7 @@ from sphinx_needs.roles.need_part import NeedPart, NeedPartRole, process_need_part from sphinx_needs.roles.need_ref import NeedRef, process_need_ref from sphinx_needs.schema.config import ( - ExtraOptionIntegerSchemaType, + FieldIntegerSchemaType, SchemasFileRootType, ) from sphinx_needs.schema.config_utils import ( @@ -313,7 +313,7 @@ def setup(app: Sphinx) -> dict[str, Any]: app.connect("config-inited", check_configuration, priority=600) # runs late app.connect("env-before-read-docs", prepare_env) - # note we have to place create_schema after prepare_env, as that can add extra options, + # note we have to place create_schema after prepare_env, as that can add extra fields, # but before load_external_needs, where we start to add needs. app.connect("env-before-read-docs", create_schema) # schemas type injection uses information from create_schema @@ -490,7 +490,7 @@ def load_config_from_toml(app: Sphinx, config: Config) -> None: def load_config(app: Sphinx, *_args: Any) -> None: """ - Register extra options and directive based on config from conf.py + Register extra fields and directive based on config from conf.py """ needs_config = NeedsSphinxConfig(app.config) @@ -571,9 +571,9 @@ def load_config(app: Sphinx, *_args: Any) -> None: override=True, ) - # ensure options for `needgantt` functionality are added to the extra options + # ensure fields for `needgantt` functionality are added to the fields for option in (needs_config.duration_option, needs_config.completion_option): - default_schema: ExtraOptionIntegerSchemaType = {"type": "integer"} + default_schema: FieldIntegerSchemaType = {"type": "integer"} if option not in _NEEDS_CONFIG.fields: _NEEDS_CONFIG.add_field( option, "Added for needgantt functionality", schema=default_schema @@ -738,7 +738,7 @@ def check_configuration(app: Sphinx, config: Config) -> None: E.g. defined need-option, which is already defined internally """ needs_config = NeedsSphinxConfig(config) - extra_options = _NEEDS_CONFIG.fields + fields = _NEEDS_CONFIG.fields link_types = [x["option"] for x in needs_config._extra_links] external_filter = needs_config.filter_data @@ -748,19 +748,19 @@ def check_configuration(app: Sphinx, config: Config) -> None: raise NeedsConfigException( f"External filter value: {value} from needs_filter_data {external_filter} is not a string." ) - # Check if needs external filter and extra option are using the same name - if extern_filter in extra_options: + # Check if needs external filter and field are using the same name + if extern_filter in fields: raise NeedsConfigException( - f"Same name for external filter and extra option: {extern_filter}." + f"Same name for external filter and field: {extern_filter}." " This is not allowed." ) # Check for usage of internal names for internal in NeedsCoreFields: - if internal in extra_options: + if internal in fields: raise NeedsConfigException( - f'Extra option "{internal}" already used internally. ' - " Please use another name in your config (needs_extra_options)." + f"Field {internal!r} already used internally. " + " Please use another name in your config (needs_fields)." ) if internal in link_types: raise NeedsConfigException( @@ -770,14 +770,13 @@ def check_configuration(app: Sphinx, config: Config) -> None: # Check if option and link are using the same name for link in link_types: - if link in extra_options: + if link in fields: raise NeedsConfigException( - f"Same name for link type and extra option: {link}." - " This is not allowed." + f"Same name for link and field: {link}. This is not allowed." ) - if link + "_back" in extra_options: + if link + "_back" in fields: raise NeedsConfigException( - "Same name for automatically created link type and extra option: {}." + "Same name for automatically created link and field: {}." " This is not allowed.".format(link + "_back") ) @@ -805,9 +804,9 @@ def check_configuration(app: Sphinx, config: Config) -> None: raise NeedsConfigException( f"Variant option `{option}` is a link type. This is not allowed." ) - if option not in extra_options and option not in allowed_internal_variants: + if option not in fields and option not in allowed_internal_variants: raise NeedsConfigException( - f"Variant option `{option}` is not added in needs_extra_options or needs_fields. " + f"Variant option `{option}` is not added in needs_fields. " "This is not allowed." ) @@ -925,7 +924,7 @@ def create_schema(app: Sphinx, env: BuildEnvironment, _docnames: list[str]) -> N ) schema.add_extra_field(field) except Exception as exc: - raise NeedsConfigException(f"Invalid extra option {name!r}: {exc}") from exc + raise NeedsConfigException(f"Invalid field {name!r}: {exc}") from exc for link in needs_config._extra_links: name = link["option"] diff --git a/sphinx_needs/needs_schema.py b/sphinx_needs/needs_schema.py index 0846b259d..a174c2d29 100644 --- a/sphinx_needs/needs_schema.py +++ b/sphinx_needs/needs_schema.py @@ -12,14 +12,14 @@ from sphinx_needs.exceptions import VariantParsingException from sphinx_needs.schema.config import ( ExtraLinkSchemaType, - ExtraOptionBooleanSchemaType, - ExtraOptionIntegerSchemaType, - ExtraOptionMultiValueSchemaType, - ExtraOptionNumberSchemaType, - ExtraOptionSchemaTypes, - ExtraOptionStringSchemaType, - validate_extra_link_schema_type, - validate_extra_option_schema, + FieldBooleanSchemaType, + FieldIntegerSchemaType, + FieldMultiValueSchemaType, + FieldNumberSchemaType, + FieldSchemaTypes, + FieldStringSchemaType, + validate_field_schema, + validate_link_schema_type, ) from sphinx_needs.schema.core import validate_object_schema_compiles from sphinx_needs.variants import VariantFunctionParsed @@ -37,7 +37,7 @@ class FieldSchema: name: str description: str = "" - schema: ExtraOptionSchemaTypes + schema: FieldSchemaTypes nullable: bool = False directive_option: bool = False parse_dynamic_functions: bool = False @@ -66,7 +66,7 @@ def __post_init__(self) -> None: if not isinstance(self.description, str): raise ValueError("description must be a string.") try: - validate_extra_option_schema(self.schema) + validate_field_schema(self.schema) except TypeError as exc: raise ValueError(f"Invalid schema: {exc}") from exc try: @@ -577,7 +577,7 @@ def __post_init__(self) -> None: if not isinstance(self.description, str): raise ValueError("description must be a string.") try: - validate_extra_link_schema_type(self.schema) + validate_link_schema_type(self.schema) except TypeError as exc: raise ValueError(f"Invalid schema: {exc}") from exc try: @@ -1073,7 +1073,7 @@ def create_inherited_field( def inherit_schema( - parent_schema: ExtraOptionSchemaTypes, child_schema: dict[str, Any] + parent_schema: FieldSchemaTypes, child_schema: dict[str, Any] ) -> None: """Inherit and validate constraints from parent schema to child schema. @@ -1149,7 +1149,7 @@ def inherit_schema( def _validate_boolean_constraints( - parent_schema: ExtraOptionBooleanSchemaType, child_schema: dict[str, Any] + parent_schema: FieldBooleanSchemaType, child_schema: dict[str, Any] ) -> None: """Validate and merge boolean-specific constraints from parent to child schema. @@ -1168,7 +1168,7 @@ def _validate_boolean_constraints( def _validate_string_constraints( - parent_schema: ExtraOptionStringSchemaType, child_schema: dict[str, Any] + parent_schema: FieldStringSchemaType, child_schema: dict[str, Any] ) -> None: """Validate and merge string-specific constraints from parent to child schema. @@ -1257,7 +1257,7 @@ def _validate_string_constraints( child_schema["maxLength"] = parent_schema["maxLength"] -_T = TypeVar("_T", ExtraOptionNumberSchemaType, ExtraOptionIntegerSchemaType) +_T = TypeVar("_T", FieldNumberSchemaType, FieldIntegerSchemaType) def _validate_number_or_integer_constraints( @@ -1362,7 +1362,7 @@ def _validate_number_or_integer_constraints( def _validate_array_constraints( - parent_schema: ExtraOptionMultiValueSchemaType, child_schema: dict[str, Any] + parent_schema: FieldMultiValueSchemaType, child_schema: dict[str, Any] ) -> None: """Validate and merge array-specific constraints from parent to child schema. @@ -1455,13 +1455,13 @@ def _validate_array_constraints( parent_items["type"] == "integer" and child_items["type"] == "integer" ): - # type restricted to ExtraOptionIntegerSchemaType + # type restricted to FieldIntegerSchemaType _validate_number_or_integer_constraints(parent_items, child_items) elif ( parent_items["type"] == "number" and child_items["type"] == "number" ): - # type restricted to ExtraOptionNumberSchemaType + # type restricted to FieldNumberSchemaType _validate_number_or_integer_constraints(parent_items, child_items) elif ( diff --git a/sphinx_needs/needsfile.py b/sphinx_needs/needsfile.py index ed2eaaa34..7fa40527a 100644 --- a/sphinx_needs/needsfile.py +++ b/sphinx_needs/needsfile.py @@ -34,7 +34,7 @@ def generate_needs_schema( It is based on: * the core fields defined in NeedsCoreFields - * the extra options defined dynamically + * the extra fields defined dynamically * the global options defined dynamically * the extra links defined dynamically """ @@ -53,10 +53,10 @@ def generate_needs_schema( elif field.nullable: properties[field.name]["default"] = None - # TODO currently extra options can overlap with core fields, + # TODO currently extra fields can overlap with core fields, # in which case they are ignored, # (this is the case for `type` added by the github service) - # hence this is why we add the core options after the extra options + # hence this is why we add the core options after the extra fields for name, core_params in NeedsCoreFields.items(): properties[name] = deepcopy(core_params["schema"]) properties[name]["description"] = f"{core_params['description']}" diff --git a/sphinx_needs/schema/config.py b/sphinx_needs/schema/config.py index dc98e444a..27cae9d73 100644 --- a/sphinx_needs/schema/config.py +++ b/sphinx_needs/schema/config.py @@ -2,7 +2,7 @@ Types and violations for schema validation. There are 3 places the types are used: -1. In the extra option and extra links definition. +1. In the field and links definition. 2. For the JSON schema coming from schema_definitions and schema_definitions_from_json configs. 3. For runtime type checking of the loaded JSON schema config. @@ -52,11 +52,11 @@ def _get_schema(klass: type) -> jsonschema_rs.Validator: return jsonschema_rs.validator_for(content) -class ExtraOptionStringSchemaType(TypedDict): - """String extra option schema.""" +class FieldStringSchemaType(TypedDict): + """String field schema.""" type: Literal["string"] - """Extra option string type.""" + """Field string type.""" minLength: NotRequired[int] """Minimum length of the string.""" maxLength: NotRequired[int] @@ -81,29 +81,29 @@ class ExtraOptionStringSchemaType(TypedDict): """A constant value that the string must match.""" -def validate_extra_option_string_schema(data: Any) -> ExtraOptionStringSchemaType: - """Validate that the given data is an ExtraOptionStringSchemaType. +def validate_field_string_schema(data: Any) -> FieldStringSchemaType: + """Validate that the given data is an FieldStringSchemaType. :raises TypeError: if the data is not valid. """ - schema = _get_schema(ExtraOptionStringSchemaType) + schema = _get_schema(FieldStringSchemaType) try: schema.validate(data) except jsonschema_rs.ValidationError as e: raise TypeError(str(e)) from e - return cast(ExtraOptionStringSchemaType, data) + return cast(FieldStringSchemaType, data) -class ExtraOptionNumberSchemaType(TypedDict): +class FieldNumberSchemaType(TypedDict): """ - Float extra option schema. + Float field schema. Python reads in JSON numbers as floats. The jsonschema library handles precision issues with floats using a tolerance-based approach. """ type: Literal["number"] - """Extra option integer type.""" + """Field integer type.""" minimum: NotRequired[float] """Minimum value.""" exclusiveMinimum: NotRequired[float] @@ -120,24 +120,24 @@ class ExtraOptionNumberSchemaType(TypedDict): """A constant value that the number must match.""" -def validate_extra_option_number_schema(data: Any) -> ExtraOptionNumberSchemaType: - """Validate that the given data is an ExtraOptionNumberSchemaType. +def validate_field_number_schema(data: Any) -> FieldNumberSchemaType: + """Validate that the given data is an FieldNumberSchemaType. :raises TypeError: if the data is not valid. """ - schema = _get_schema(ExtraOptionNumberSchemaType) + schema = _get_schema(FieldNumberSchemaType) try: schema.validate(data) except jsonschema_rs.ValidationError as e: raise TypeError(str(e)) from e - return cast(ExtraOptionNumberSchemaType, data) + return cast(FieldNumberSchemaType, data) -class ExtraOptionIntegerSchemaType(TypedDict): - """Integer extra option schema.""" +class FieldIntegerSchemaType(TypedDict): + """Integer field schema.""" type: Literal["integer"] - """Extra option integer type.""" + """Field integer type.""" minimum: NotRequired[int] """Minimum value.""" exclusiveMinimum: NotRequired[int] @@ -154,22 +154,22 @@ class ExtraOptionIntegerSchemaType(TypedDict): """A constant value that the integer must match.""" -def validate_extra_option_integer_schema(data: Any) -> ExtraOptionIntegerSchemaType: - """Validate that the given data is an ExtraOptionIntegerSchemaType. +def validate_field_integer_schema(data: Any) -> FieldIntegerSchemaType: + """Validate that the given data is an FieldIntegerSchemaType. :raises TypeError: if the data is not valid. """ - schema = _get_schema(ExtraOptionIntegerSchemaType) + schema = _get_schema(FieldIntegerSchemaType) try: schema.validate(data) except jsonschema_rs.ValidationError as e: raise TypeError(str(e)) from e - return cast(ExtraOptionIntegerSchemaType, data) + return cast(FieldIntegerSchemaType, data) -class ExtraOptionBooleanSchemaType(TypedDict): +class FieldBooleanSchemaType(TypedDict): """ - Boolean extra option schema. + Boolean field schema. A predefined set of truthy/falsy strings are accepted: - truthy = {"true", "yes", "y", "on", "1"} @@ -180,22 +180,22 @@ class ExtraOptionBooleanSchemaType(TypedDict): """ type: Literal["boolean"] - """Extra option boolean type.""" + """Field boolean type.""" const: NotRequired[bool] """A constant value that the integer must match.""" -def validate_extra_option_boolean_schema(data: Any) -> ExtraOptionBooleanSchemaType: - """Validate that the given data is an ExtraOptionBooleanSchemaType. +def validate_field_boolean_schema(data: Any) -> FieldBooleanSchemaType: + """Validate that the given data is an FieldBooleanSchemaType. :raises TypeError: if the data is not valid. """ - schema = _get_schema(ExtraOptionBooleanSchemaType) + schema = _get_schema(FieldBooleanSchemaType) try: schema.validate(data) except jsonschema_rs.ValidationError as e: raise TypeError(str(e)) from e - return cast(ExtraOptionBooleanSchemaType, data) + return cast(FieldBooleanSchemaType, data) RefItemType = TypedDict( @@ -217,31 +217,31 @@ class AllOfSchemaType(TypedDict): allOf: NotRequired[list[RefItemType | NeedFieldsSchemaType]] -ExtraOptionBaseSchemaTypes = ( - ExtraOptionStringSchemaType - | ExtraOptionBooleanSchemaType - | ExtraOptionIntegerSchemaType - | ExtraOptionNumberSchemaType +FieldBaseSchemaTypes = ( + FieldStringSchemaType + | FieldBooleanSchemaType + | FieldIntegerSchemaType + | FieldNumberSchemaType ) -"""Union type for all single value extra option schemas.""" +"""Union type for all single value field schemas.""" -class ExtraOptionMultiValueSchemaType(TypedDict): +class FieldMultiValueSchemaType(TypedDict): """ - Multi value extra option such as a list of strings, integers, numbers, or booleans. + Multi value field such as a list of strings, integers, numbers, or booleans. Current SN use case are tags. """ type: Literal["array"] - """Multi value extra option such as a list of strings, integers, numbers, or booleans.""" - items: ExtraOptionBaseSchemaTypes + """Multi value field such as a list of strings, integers, numbers, or booleans.""" + items: FieldBaseSchemaTypes """Schema constraints for all items.""" minItems: NotRequired[int] """Minimum number of items in the array.""" maxItems: NotRequired[int] """Maximum number of items in the array.""" - contains: NotRequired[ExtraOptionBaseSchemaTypes] + contains: NotRequired[FieldBaseSchemaTypes] """Schema constraints for some items.""" minContains: NotRequired[int] """Minimum number of contains items in the array.""" @@ -251,14 +251,14 @@ class ExtraOptionMultiValueSchemaType(TypedDict): """Whether all items in the array must be unique.""" -def validate_extra_option_multi_value_schema( +def validate_field_multi_value_schema( data: Any, -) -> ExtraOptionMultiValueSchemaType: - """Validate that the given data is an ExtraOptionMultiValueSchemaType. +) -> FieldMultiValueSchemaType: + """Validate that the given data is an FieldMultiValueSchemaType. :raises TypeError: if the data is not valid. """ - schema = _get_schema(ExtraOptionMultiValueSchemaType) + schema = _get_schema(FieldMultiValueSchemaType) try: schema.validate(data) except jsonschema_rs.ValidationError as e: @@ -271,24 +271,24 @@ def validate_extra_option_multi_value_schema( raise TypeError( f"'items' type '{items_type}' and 'contains' type '{contains_type}' must be identical." ) - return cast(ExtraOptionMultiValueSchemaType, data) + return cast(FieldMultiValueSchemaType, data) -ExtraOptionSchemaTypes = ExtraOptionBaseSchemaTypes | ExtraOptionMultiValueSchemaType -"""Union type for all extra option schemas, including multi-value options.""" +FieldSchemaTypes = FieldBaseSchemaTypes | FieldMultiValueSchemaType +"""Union type for all field schemas, including multi-value options.""" -_OPTION_VALIDATORS: Final[Mapping[str, Callable[[Any], ExtraOptionSchemaTypes]]] = { - "string": validate_extra_option_string_schema, - "boolean": validate_extra_option_boolean_schema, - "integer": validate_extra_option_integer_schema, - "number": validate_extra_option_number_schema, - "array": validate_extra_option_multi_value_schema, +_OPTION_VALIDATORS: Final[Mapping[str, Callable[[Any], FieldSchemaTypes]]] = { + "string": validate_field_string_schema, + "boolean": validate_field_boolean_schema, + "integer": validate_field_integer_schema, + "number": validate_field_number_schema, + "array": validate_field_multi_value_schema, } -def validate_extra_option_schema(data: Any) -> ExtraOptionSchemaTypes: - """Validate that the given data is an ExtraOptionBaseSchemaTypes. +def validate_field_schema(data: Any) -> FieldSchemaTypes: + """Validate that the given data is an FieldBaseSchemaTypes. :raises TypeError: if the data is not valid. """ @@ -299,7 +299,7 @@ def validate_extra_option_schema(data: Any) -> ExtraOptionSchemaTypes: type_ = data["type"] if type_ not in FIELD_BASE_TYPES_STR: raise TypeError( - f"Extra option schema has invalid type '{type_}'. " + f"Field schema has invalid type '{type_}'. " f"Must be one of {sorted(FIELD_BASE_TYPES_STR)}." ) validator = _OPTION_VALIDATORS[type_] @@ -338,7 +338,7 @@ class ExtraLinkSchemaType(TypedDict): """Maximum number of contains items in the array (outgoing link ids).""" -def validate_extra_link_schema_type(data: Any) -> ExtraLinkSchemaType: +def validate_link_schema_type(data: Any) -> ExtraLinkSchemaType: """Validate that the given data is an ExtraLinkSchemaType. :raises TypeError: if the data is not valid. @@ -355,15 +355,15 @@ def validate_extra_link_schema_type(data: Any) -> ExtraLinkSchemaType: return cast(ExtraLinkSchemaType, data) -ExtraOptionAndLinkSchemaTypes = ExtraOptionSchemaTypes | ExtraLinkSchemaType -"""Union type for all extra option and link schemas.""" +FieldAndLinkSchemaTypes = FieldSchemaTypes | ExtraLinkSchemaType +"""Union type for all field and link schemas.""" class NeedFieldsSchemaType(AllOfSchemaType): """ Schema for a set of need fields of all schema types. - This includes single value extra options, multi-value extra options, + This includes single value fields, multi-value fields, and unresolved extra links. Intented to validate multiple fields on a need type. @@ -371,7 +371,7 @@ class NeedFieldsSchemaType(AllOfSchemaType): type: NotRequired[Literal["object"]] """All fields of a need stored in a dict (not required because it's the default).""" - properties: NotRequired[dict[str, ExtraOptionAndLinkSchemaTypes]] + properties: NotRequired[dict[str, FieldAndLinkSchemaTypes]] required: NotRequired[list[str]] """List of required fields in the need.""" unevaluatedProperties: NotRequired[bool] @@ -587,7 +587,7 @@ def get_schema_name(schema: SchemasRootType) -> str: "$defs": NotRequired[ dict[ str, - AllOfSchemaType | NeedFieldsSchemaType | ExtraOptionAndLinkSchemaTypes, + AllOfSchemaType | NeedFieldsSchemaType | FieldAndLinkSchemaTypes, ] ], "schemas": NotRequired[list[SchemasRootType]], diff --git a/sphinx_needs/schema/config_utils.py b/sphinx_needs/schema/config_utils.py index d28848a5f..5d204a990 100644 --- a/sphinx_needs/schema/config_utils.py +++ b/sphinx_needs/schema/config_utils.py @@ -18,7 +18,7 @@ FIELD_BASE_TYPES_STR, USER_CONFIG_SCHEMA_SEVERITIES, AllOfSchemaType, - ExtraOptionAndLinkSchemaTypes, + FieldAndLinkSchemaTypes, NeedFieldsSchemaType, RefItemType, ResolvedLinkSchemaType, @@ -210,7 +210,7 @@ def check_network_links_against_extra_links( def resolve_refs( defs: dict[ str, - AllOfSchemaType | NeedFieldsSchemaType | ExtraOptionAndLinkSchemaTypes, + AllOfSchemaType | NeedFieldsSchemaType | FieldAndLinkSchemaTypes, ], curr_item: Any, circular_refs_guard: set[str], @@ -415,7 +415,7 @@ def _process_need_fields_schema( def _inject_field_type( field_name: str, - field_schema: ExtraOptionAndLinkSchemaTypes, + field_schema: FieldAndLinkSchemaTypes, schema_name: str, fields_schema: FieldsSchema, path: str, @@ -455,7 +455,7 @@ def _inject_field_type( if core_field_result is None: raise NeedsConfigException( f"Config error in schema '{schema_name}' at path '{path}': " - f"Field '{field_name}' is not a known extra option, extra link, or core field." + f"'{field_name}' is not a known field or link." ) field_type, item_type = core_field_result _inject_type_and_item_type( @@ -518,7 +518,7 @@ def _get_core_field_type( def _inject_type_and_item_type( - field_schema: ExtraOptionAndLinkSchemaTypes, + field_schema: FieldAndLinkSchemaTypes, expected_type: Literal["string", "boolean", "integer", "number", "array"], expected_item_type: Literal["string", "boolean", "integer", "number"] | None, field_name: str, diff --git a/sphinx_needs/schema/core.py b/sphinx_needs/schema/core.py index c3d679cad..8fd895be1 100644 --- a/sphinx_needs/schema/core.py +++ b/sphinx_needs/schema/core.py @@ -48,7 +48,7 @@ def validate_option_fields( field_properties: Mapping[str, NeedFieldProperties], needs: NeedsView, ) -> dict[str, list[OntologyWarning]]: - """Validate schema originating from extra option definitions.""" + """Validate schema originating from field definitions.""" need_2_warnings: dict[str, list[OntologyWarning]] = {} validator = compile_validator(schema) for need in needs.values(): @@ -467,7 +467,7 @@ def reduce_need( continue schema_field = field_properties[field] if not ("default" in schema_field and value == schema_field["default"]): - # keep explicitly set extra options + # keep explicitly set fields reduced_need[field] = value for field, value in need.iter_links_items(): diff --git a/sphinx_needs/schema/jsons/ExtraOptionBooleanSchemaType.schema.json b/sphinx_needs/schema/jsons/FieldBooleanSchemaType.schema.json similarity index 87% rename from sphinx_needs/schema/jsons/ExtraOptionBooleanSchemaType.schema.json rename to sphinx_needs/schema/jsons/FieldBooleanSchemaType.schema.json index 46717ae04..10d282cb2 100644 --- a/sphinx_needs/schema/jsons/ExtraOptionBooleanSchemaType.schema.json +++ b/sphinx_needs/schema/jsons/FieldBooleanSchemaType.schema.json @@ -15,6 +15,6 @@ "required": [ "type" ], - "title": "ExtraOptionBooleanSchemaTypeModel", + "title": "FieldBooleanSchemaTypeModel", "type": "object" } diff --git a/sphinx_needs/schema/jsons/ExtraOptionIntegerSchemaType.schema.json b/sphinx_needs/schema/jsons/FieldIntegerSchemaType.schema.json similarity index 94% rename from sphinx_needs/schema/jsons/ExtraOptionIntegerSchemaType.schema.json rename to sphinx_needs/schema/jsons/FieldIntegerSchemaType.schema.json index 8581b077c..3d2ddcce5 100644 --- a/sphinx_needs/schema/jsons/ExtraOptionIntegerSchemaType.schema.json +++ b/sphinx_needs/schema/jsons/FieldIntegerSchemaType.schema.json @@ -42,6 +42,6 @@ "required": [ "type" ], - "title": "ExtraOptionIntegerSchemaTypeModel", + "title": "FieldIntegerSchemaTypeModel", "type": "object" } diff --git a/sphinx_needs/schema/jsons/ExtraOptionMultiValueSchemaType.schema.json b/sphinx_needs/schema/jsons/FieldMultiValueSchemaType.schema.json similarity index 74% rename from sphinx_needs/schema/jsons/ExtraOptionMultiValueSchemaType.schema.json rename to sphinx_needs/schema/jsons/FieldMultiValueSchemaType.schema.json index 68950f13c..dbc964c93 100644 --- a/sphinx_needs/schema/jsons/ExtraOptionMultiValueSchemaType.schema.json +++ b/sphinx_needs/schema/jsons/FieldMultiValueSchemaType.schema.json @@ -1,8 +1,8 @@ { "$defs": { - "ExtraOptionBooleanSchemaType": { + "FieldBooleanSchemaType": { "additionalProperties": false, - "description": "Boolean extra option schema.\n\nA predefined set of truthy/falsy strings are accepted:\n- truthy = {\"true\", \"yes\", \"y\", \"on\", \"1\"}\n- falsy = {\"false\", \"no\", \"n\", \"off\", \"0\"}\n\nFor fixed values, the const field can be used.\nenum is not supported as const is functionally equivalent and less verbose.", + "description": "Boolean field schema.\n\nA predefined set of truthy/falsy strings are accepted:\n- truthy = {\"true\", \"yes\", \"y\", \"on\", \"1\"}\n- falsy = {\"false\", \"no\", \"n\", \"off\", \"0\"}\n\nFor fixed values, the const field can be used.\nenum is not supported as const is functionally equivalent and less verbose.", "properties": { "const": { "title": "Const", @@ -17,12 +17,12 @@ "required": [ "type" ], - "title": "ExtraOptionBooleanSchemaType", + "title": "FieldBooleanSchemaType", "type": "object" }, - "ExtraOptionIntegerSchemaType": { + "FieldIntegerSchemaType": { "additionalProperties": false, - "description": "Integer extra option schema.", + "description": "Integer field schema.", "properties": { "const": { "title": "Const", @@ -64,12 +64,12 @@ "required": [ "type" ], - "title": "ExtraOptionIntegerSchemaType", + "title": "FieldIntegerSchemaType", "type": "object" }, - "ExtraOptionNumberSchemaType": { + "FieldNumberSchemaType": { "additionalProperties": false, - "description": "Float extra option schema.\n\nPython reads in JSON numbers as floats. The jsonschema library\nhandles precision issues with floats using a tolerance-based approach.", + "description": "Float field schema.\n\nPython reads in JSON numbers as floats. The jsonschema library\nhandles precision issues with floats using a tolerance-based approach.", "properties": { "const": { "title": "Const", @@ -111,12 +111,12 @@ "required": [ "type" ], - "title": "ExtraOptionNumberSchemaType", + "title": "FieldNumberSchemaType", "type": "object" }, - "ExtraOptionStringSchemaType": { + "FieldStringSchemaType": { "additionalProperties": false, - "description": "String extra option schema.", + "description": "String field schema.", "properties": { "const": { "title": "Const", @@ -163,7 +163,7 @@ "required": [ "type" ], - "title": "ExtraOptionStringSchemaType", + "title": "FieldStringSchemaType", "type": "object" } }, @@ -173,16 +173,16 @@ "contains": { "anyOf": [ { - "$ref": "#/$defs/ExtraOptionStringSchemaType" + "$ref": "#/$defs/FieldStringSchemaType" }, { - "$ref": "#/$defs/ExtraOptionBooleanSchemaType" + "$ref": "#/$defs/FieldBooleanSchemaType" }, { - "$ref": "#/$defs/ExtraOptionIntegerSchemaType" + "$ref": "#/$defs/FieldIntegerSchemaType" }, { - "$ref": "#/$defs/ExtraOptionNumberSchemaType" + "$ref": "#/$defs/FieldNumberSchemaType" } ], "title": "Contains" @@ -190,16 +190,16 @@ "items": { "anyOf": [ { - "$ref": "#/$defs/ExtraOptionStringSchemaType" + "$ref": "#/$defs/FieldStringSchemaType" }, { - "$ref": "#/$defs/ExtraOptionBooleanSchemaType" + "$ref": "#/$defs/FieldBooleanSchemaType" }, { - "$ref": "#/$defs/ExtraOptionIntegerSchemaType" + "$ref": "#/$defs/FieldIntegerSchemaType" }, { - "$ref": "#/$defs/ExtraOptionNumberSchemaType" + "$ref": "#/$defs/FieldNumberSchemaType" } ], "title": "Items" @@ -234,6 +234,6 @@ "type", "items" ], - "title": "ExtraOptionMultiValueSchemaTypeModel", + "title": "FieldMultiValueSchemaTypeModel", "type": "object" } diff --git a/sphinx_needs/schema/jsons/ExtraOptionNumberSchemaType.schema.json b/sphinx_needs/schema/jsons/FieldNumberSchemaType.schema.json similarity index 94% rename from sphinx_needs/schema/jsons/ExtraOptionNumberSchemaType.schema.json rename to sphinx_needs/schema/jsons/FieldNumberSchemaType.schema.json index 446db46cf..312444b3d 100644 --- a/sphinx_needs/schema/jsons/ExtraOptionNumberSchemaType.schema.json +++ b/sphinx_needs/schema/jsons/FieldNumberSchemaType.schema.json @@ -42,6 +42,6 @@ "required": [ "type" ], - "title": "ExtraOptionNumberSchemaTypeModel", + "title": "FieldNumberSchemaTypeModel", "type": "object" } diff --git a/sphinx_needs/schema/jsons/ExtraOptionStringSchemaType.schema.json b/sphinx_needs/schema/jsons/FieldStringSchemaType.schema.json similarity index 95% rename from sphinx_needs/schema/jsons/ExtraOptionStringSchemaType.schema.json rename to sphinx_needs/schema/jsons/FieldStringSchemaType.schema.json index a4fe51c36..748d26cc6 100644 --- a/sphinx_needs/schema/jsons/ExtraOptionStringSchemaType.schema.json +++ b/sphinx_needs/schema/jsons/FieldStringSchemaType.schema.json @@ -47,6 +47,6 @@ "required": [ "type" ], - "title": "ExtraOptionStringSchemaTypeModel", + "title": "FieldStringSchemaTypeModel", "type": "object" } diff --git a/sphinx_needs/schema/jsons/SchemasRootType.schema.json b/sphinx_needs/schema/jsons/SchemasRootType.schema.json index b42287e86..5fe1960ba 100644 --- a/sphinx_needs/schema/jsons/SchemasRootType.schema.json +++ b/sphinx_needs/schema/jsons/SchemasRootType.schema.json @@ -87,9 +87,9 @@ "title": "ExtraLinkSchemaType", "type": "object" }, - "ExtraOptionBooleanSchemaType": { + "FieldBooleanSchemaType": { "additionalProperties": false, - "description": "Boolean extra option schema.\n\nA predefined set of truthy/falsy strings are accepted:\n- truthy = {\"true\", \"yes\", \"y\", \"on\", \"1\"}\n- falsy = {\"false\", \"no\", \"n\", \"off\", \"0\"}\n\nFor fixed values, the const field can be used.\nenum is not supported as const is functionally equivalent and less verbose.", + "description": "Boolean field schema.\n\nA predefined set of truthy/falsy strings are accepted:\n- truthy = {\"true\", \"yes\", \"y\", \"on\", \"1\"}\n- falsy = {\"false\", \"no\", \"n\", \"off\", \"0\"}\n\nFor fixed values, the const field can be used.\nenum is not supported as const is functionally equivalent and less verbose.", "properties": { "const": { "title": "Const", @@ -104,12 +104,12 @@ "required": [ "type" ], - "title": "ExtraOptionBooleanSchemaType", + "title": "FieldBooleanSchemaType", "type": "object" }, - "ExtraOptionIntegerSchemaType": { + "FieldIntegerSchemaType": { "additionalProperties": false, - "description": "Integer extra option schema.", + "description": "Integer field schema.", "properties": { "const": { "title": "Const", @@ -151,26 +151,26 @@ "required": [ "type" ], - "title": "ExtraOptionIntegerSchemaType", + "title": "FieldIntegerSchemaType", "type": "object" }, - "ExtraOptionMultiValueSchemaType": { + "FieldMultiValueSchemaType": { "additionalProperties": false, - "description": "Multi value extra option such as a list of strings, integers, numbers, or booleans.\n\nCurrent SN use case are tags.", + "description": "Multi value field such as a list of strings, integers, numbers, or booleans.\n\nCurrent SN use case are tags.", "properties": { "contains": { "anyOf": [ { - "$ref": "#/$defs/ExtraOptionStringSchemaType" + "$ref": "#/$defs/FieldStringSchemaType" }, { - "$ref": "#/$defs/ExtraOptionBooleanSchemaType" + "$ref": "#/$defs/FieldBooleanSchemaType" }, { - "$ref": "#/$defs/ExtraOptionIntegerSchemaType" + "$ref": "#/$defs/FieldIntegerSchemaType" }, { - "$ref": "#/$defs/ExtraOptionNumberSchemaType" + "$ref": "#/$defs/FieldNumberSchemaType" } ], "title": "Contains" @@ -178,16 +178,16 @@ "items": { "anyOf": [ { - "$ref": "#/$defs/ExtraOptionStringSchemaType" + "$ref": "#/$defs/FieldStringSchemaType" }, { - "$ref": "#/$defs/ExtraOptionBooleanSchemaType" + "$ref": "#/$defs/FieldBooleanSchemaType" }, { - "$ref": "#/$defs/ExtraOptionIntegerSchemaType" + "$ref": "#/$defs/FieldIntegerSchemaType" }, { - "$ref": "#/$defs/ExtraOptionNumberSchemaType" + "$ref": "#/$defs/FieldNumberSchemaType" } ], "title": "Items" @@ -222,12 +222,12 @@ "type", "items" ], - "title": "ExtraOptionMultiValueSchemaType", + "title": "FieldMultiValueSchemaType", "type": "object" }, - "ExtraOptionNumberSchemaType": { + "FieldNumberSchemaType": { "additionalProperties": false, - "description": "Float extra option schema.\n\nPython reads in JSON numbers as floats. The jsonschema library\nhandles precision issues with floats using a tolerance-based approach.", + "description": "Float field schema.\n\nPython reads in JSON numbers as floats. The jsonschema library\nhandles precision issues with floats using a tolerance-based approach.", "properties": { "const": { "title": "Const", @@ -269,12 +269,12 @@ "required": [ "type" ], - "title": "ExtraOptionNumberSchemaType", + "title": "FieldNumberSchemaType", "type": "object" }, - "ExtraOptionStringSchemaType": { + "FieldStringSchemaType": { "additionalProperties": false, - "description": "String extra option schema.", + "description": "String field schema.", "properties": { "const": { "title": "Const", @@ -321,12 +321,12 @@ "required": [ "type" ], - "title": "ExtraOptionStringSchemaType", + "title": "FieldStringSchemaType", "type": "object" }, "NeedFieldsSchemaType": { "additionalProperties": false, - "description": "Schema for a set of need fields of all schema types.\n\nThis includes single value extra options, multi-value extra options,\nand unresolved extra links.\n\nIntented to validate multiple fields on a need type.", + "description": "Schema for a set of need fields of all schema types.\n\nThis includes single value fields, multi-value fields,\nand unresolved extra links.\n\nIntented to validate multiple fields on a need type.", "properties": { "allOf": { "items": { @@ -346,19 +346,19 @@ "additionalProperties": { "anyOf": [ { - "$ref": "#/$defs/ExtraOptionStringSchemaType" + "$ref": "#/$defs/FieldStringSchemaType" }, { - "$ref": "#/$defs/ExtraOptionBooleanSchemaType" + "$ref": "#/$defs/FieldBooleanSchemaType" }, { - "$ref": "#/$defs/ExtraOptionIntegerSchemaType" + "$ref": "#/$defs/FieldIntegerSchemaType" }, { - "$ref": "#/$defs/ExtraOptionNumberSchemaType" + "$ref": "#/$defs/FieldNumberSchemaType" }, { - "$ref": "#/$defs/ExtraOptionMultiValueSchemaType" + "$ref": "#/$defs/FieldMultiValueSchemaType" }, { "$ref": "#/$defs/ExtraLinkSchemaType" diff --git a/sphinx_needs/services/manager.py b/sphinx_needs/services/manager.py index aad547abd..cb4a2b5a0 100644 --- a/sphinx_needs/services/manager.py +++ b/sphinx_needs/services/manager.py @@ -29,7 +29,7 @@ def register(self, name: str, klass: type[BaseService], **kwargs: Any) -> None: for option in klass.options: if option == "type": # TODO this should probably be done a bit more systematically; - # the github service adds a "type" option, but this is related to the core need field NOT an extra option + # the github service adds a "type" option, but this is related to the core need field NOT an extra field pass elif option not in _NEEDS_CONFIG.fields: self.log.debug(f'Register option "{option}" for service "{name}"') diff --git a/tests/__snapshots__/test_api_usage.ambr b/tests/__snapshots__/test_api_usage.ambr index 492685146..f91111b84 100644 --- a/tests/__snapshots__/test_api_usage.ambr +++ b/tests/__snapshots__/test_api_usage.ambr @@ -1,7 +1,7 @@ # serializer version: 1 # name: test_api_add_field_schema_wrong ''' - Invalid extra option 'my_extra_option': Invalid schema: Additional properties are not allowed ('not_exist' was unexpected) + Invalid field 'my_extra_option': Invalid schema: Additional properties are not allowed ('not_exist' was unexpected) Failed validating "additionalProperties" in schema diff --git a/tests/schema/__snapshots__/test_schema.ambr b/tests/schema/__snapshots__/test_schema.ambr index 514b48c17..e18c89b39 100644 --- a/tests/schema/__snapshots__/test_schema.ambr +++ b/tests/schema/__snapshots__/test_schema.ambr @@ -528,11 +528,11 @@ ''' # --- # name: test_schema_config[extra_option_empty_schema] - "Invalid extra option 'efforts': Invalid schema: Must have a 'type' field." + "Invalid field 'efforts': Invalid schema: Must have a 'type' field." # --- # name: test_schema_config[extra_option_pattern_unsafe_error] ''' - Invalid extra option 'efforts': Invalid schema: "^IMPL_(?!SAFE)" is not a "regex" + Invalid field 'efforts': Invalid schema: "^IMPL_(?!SAFE)" is not a "regex" Failed validating in schema @@ -542,7 +542,7 @@ # --- # name: test_schema_config[extra_option_unknown_keys] ''' - Invalid extra option 'efforts': Invalid schema: Additional properties are not allowed ('unknown' was unexpected) + Invalid field 'efforts': Invalid schema: Additional properties are not allowed ('unknown' was unexpected) Failed validating "additionalProperties" in schema @@ -702,7 +702,7 @@ "Invalid `needs_fields` core option override for 'title': Child 'type' 'number' does not match parent 'type' 'string'." # --- # name: test_schema_config[type_error] - "Invalid extra option 'efforts': Invalid schema: Extra option schema has invalid type 'unknown'. Must be one of ['array', 'boolean', 'integer', 'number', 'string']." + "Invalid field 'efforts': Invalid schema: Field schema has invalid type 'unknown'. Must be one of ['array', 'boolean', 'integer', 'number', 'string']." # --- # name: test_schema_config[type_mismatch_array_error] ''' @@ -3237,7 +3237,7 @@ # --- # name: test_schemas[schema/fixtures/fields-coerce_to_boolean_from_string_error] ''' - /index.rst:1: WARNING: Need could not be created: Extra option 'approved' is invalid: Cannot convert 'not-a-boolean' to boolean [needs.create_need] + /index.rst:1: WARNING: Need could not be created: Field 'approved' is invalid: Cannot convert 'not-a-boolean' to boolean [needs.create_need] ''' # --- @@ -3260,7 +3260,7 @@ # --- # name: test_schemas[schema/fixtures/fields-coerce_to_integer_from_float_error] ''' - /index.rst:1: WARNING: Need could not be created: Extra option 'efforts' is invalid: Cannot convert '1.2' to integer [needs.create_need] + /index.rst:1: WARNING: Need could not be created: Field 'efforts' is invalid: Cannot convert '1.2' to integer [needs.create_need] ''' # --- @@ -3273,7 +3273,7 @@ # --- # name: test_schemas[schema/fixtures/fields-coerce_to_integer_from_string_error] ''' - /index.rst:1: WARNING: Need could not be created: Extra option 'efforts' is invalid: Cannot convert 'QM' to integer [needs.create_need] + /index.rst:1: WARNING: Need could not be created: Field 'efforts' is invalid: Cannot convert 'QM' to integer [needs.create_need] ''' # --- @@ -3296,7 +3296,7 @@ # --- # name: test_schemas[schema/fixtures/fields-coerce_to_number_from_string_error] ''' - /index.rst:1: WARNING: Need could not be created: Extra option 'efforts' is invalid: Cannot convert 'QM' to float [needs.create_need] + /index.rst:1: WARNING: Need could not be created: Field 'efforts' is invalid: Cannot convert 'QM' to float [needs.create_need] ''' # --- @@ -3956,7 +3956,7 @@ # --- # name: test_schemas[schema/fixtures/fields-string_non_nullable] ''' - /index.rst:1: WARNING: Need could not be created: Extra option 'asil' is not nullable, but no value or default was given. [needs.create_need] + /index.rst:1: WARNING: Need could not be created: Field 'asil' is not nullable, but no value or default was given. [needs.create_need] ''' # --- @@ -4069,7 +4069,7 @@ # --- # name: test_schemas[schema/fixtures/fields-wrong_type] ''' - /index.rst:1: WARNING: Need could not be created: Extra option 'asil' is invalid: Cannot convert 'QM' to integer [needs.create_need] + /index.rst:1: WARNING: Need could not be created: Field 'asil' is invalid: Cannot convert 'QM' to integer [needs.create_need] ''' # --- diff --git a/tests/schema/test_generate_schema.py b/tests/schema/test_generate_schema.py index d3f4b00bf..9ef7f564a 100644 --- a/tests/schema/test_generate_schema.py +++ b/tests/schema/test_generate_schema.py @@ -20,11 +20,11 @@ from sphinx_needs.schema.config import ( ExtraLinkItemSchemaType, ExtraLinkSchemaType, - ExtraOptionBooleanSchemaType, - ExtraOptionIntegerSchemaType, - ExtraOptionMultiValueSchemaType, - ExtraOptionNumberSchemaType, - ExtraOptionStringSchemaType, + FieldBooleanSchemaType, + FieldIntegerSchemaType, + FieldMultiValueSchemaType, + FieldNumberSchemaType, + FieldStringSchemaType, SchemasRootType, ) @@ -112,11 +112,11 @@ def snapshot_json(snapshot): [ ExtraLinkItemSchemaType, ExtraLinkSchemaType, - ExtraOptionBooleanSchemaType, - ExtraOptionIntegerSchemaType, - ExtraOptionMultiValueSchemaType, - ExtraOptionNumberSchemaType, - ExtraOptionStringSchemaType, + FieldBooleanSchemaType, + FieldIntegerSchemaType, + FieldMultiValueSchemaType, + FieldNumberSchemaType, + FieldStringSchemaType, SchemasRootType, ], ) diff --git a/tests/schema/test_populate_field_type.py b/tests/schema/test_populate_field_type.py index 74cfe4fab..5a246499a 100644 --- a/tests/schema/test_populate_field_type.py +++ b/tests/schema/test_populate_field_type.py @@ -102,7 +102,7 @@ def test_validate_local_with_properties_injects_object_type(self) -> None: assert schema["validate"]["local"]["type"] == "object" def test_extra_field_type_injection(self) -> None: - """Test type injection for extra option fields.""" + """Test type injection for fields.""" schema: dict[str, Any] = { "idx": 0, "validate": { @@ -122,7 +122,7 @@ def test_extra_field_type_injection(self) -> None: assert schema["validate"]["local"]["properties"]["priority"]["type"] == "string" def test_extra_field_array_type_injection(self) -> None: - """Test type injection for array extra option fields with items.""" + """Test type injection for array fields with items.""" schema: dict[str, Any] = { "idx": 0, "validate": { @@ -144,7 +144,7 @@ def test_extra_field_array_type_injection(self) -> None: assert props["items"]["type"] == "string" def test_extra_field_array_contains_injection(self) -> None: - """Test type injection for array extra option fields with contains.""" + """Test type injection for array fields with contains.""" schema: dict[str, Any] = { "idx": 0, "validate": { @@ -432,9 +432,7 @@ def test_unknown_field_raises_error(self) -> None: populate_field_type(schema, "[0]", fields_schema) assert "unknown_field" in str(exc_info.value) - assert "not a known extra option, extra link, or core field" in str( - exc_info.value - ) + assert "not a known field or link" in str(exc_info.value) def test_type_mismatch_extra_field(self) -> None: """Test that type mismatch for extra field raises error.""" diff --git a/tests/test_api_usage.py b/tests/test_api_usage.py index d429bd030..606aed165 100644 --- a/tests/test_api_usage.py +++ b/tests/test_api_usage.py @@ -138,7 +138,7 @@ def test_api_add_field( def setup(app): from sphinx_needs.api import add_field - add_field('my_extra_option', description='My extra option') + add_field('my_extra_option', description='My extra field') return {'version': '0.1'} """ ), @@ -149,7 +149,7 @@ def setup(app): .. req:: a req :id: REQ_1 - :my_extra_option: extra option value + :my_extra_option: extra field value """ ), } @@ -162,7 +162,7 @@ def setup(app): html = Path(app.outdir, "index.html").read_text() assert html is not None - assert "extra option value" in html + assert "extra field value" in html assert app.statuscode == 0 @@ -182,7 +182,7 @@ def setup(app): from sphinx_needs.api import add_field add_field( 'my_extra_option', - description='My extra option', + description='My extra field', schema={ 'type': 'integer', 'maximum': 10, @@ -231,7 +231,7 @@ def setup(app): from sphinx_needs.api import add_field add_field( 'my_extra_option', - description='My extra option', + description='My extra field', schema={ 'type': 'integer', 'not_exist': 10, diff --git a/tests/test_dynamic_functions.py b/tests/test_dynamic_functions.py index 65f2e9f28..c469cafd8 100644 --- a/tests/test_dynamic_functions.py +++ b/tests/test_dynamic_functions.py @@ -147,8 +147,8 @@ def test_doc_dynamic_functions(test_app, snapshot): "srcdir/index.rst:23: WARNING: Need could not be created: 'tags' value is invalid: only one string, dynamic function or variant function allowed per array item. [needs.create_need]", 'srcdir/index.rst:40: WARNING: The `need_func` role is deprecated. Replace with :ndf:`copy("id")` instead. [needs.deprecated]', 'srcdir/index.rst:44: WARNING: The `need_func` role is deprecated. Replace with :ndf:`copy("id")` instead. [needs.deprecated]', - "srcdir/index.rst:46: WARNING: Need could not be created: Extra option 'test_func' is invalid: Error parsing dynamic function 'test': Unsupported arg 0 value type [needs.create_need]", - "srcdir/index.rst:52: WARNING: Need could not be created: Extra option 'test_func' is invalid: Error parsing dynamic function 'test': Unsupported arg 0 value type [needs.create_need]", + "srcdir/index.rst:46: WARNING: Need could not be created: Field 'test_func' is invalid: Error parsing dynamic function 'test': Unsupported arg 0 value type [needs.create_need]", + "srcdir/index.rst:52: WARNING: Need could not be created: Field 'test_func' is invalid: Error parsing dynamic function 'test': Unsupported arg 0 value type [needs.create_need]", 'srcdir/index.rst:9: WARNING: The [[copy("id")]] syntax in need content is deprecated. Replace with :ndf:`copy("id")` instead. [needs.deprecated]', "srcdir/index.rst:33: WARNING: The [[copy('id')]] syntax in need content is deprecated. Replace with :ndf:`copy('id')` instead. [needs.deprecated]", "srcdir/index.rst:38: WARNING: The [[copy('id')]] syntax in need content is deprecated. Replace with :ndf:`copy('id')` instead. [needs.deprecated]", diff --git a/tests/test_external.py b/tests/test_external.py index 16d2a5dd2..5c147265d 100644 --- a/tests/test_external.py +++ b/tests/test_external.py @@ -28,7 +28,7 @@ def test_external_html(test_app: SphinxTestApp): ) # print(warnings) assert warnings == [ - "WARNING: External need 'EXT_TEST_01' in 'needs_test_small.json' could not be added: Extra option 'extra2' is invalid: Invalid value for field 'extra2': 1 [needs.load_external_need]", + "WARNING: External need 'EXT_TEST_01' in 'needs_test_small.json' could not be added: Field 'extra2' is invalid: Invalid value for field 'extra2': 1 [needs.load_external_need]", "WARNING: External need 'EXT_TEST_03' in 'needs_test_small.json' could not be added: Unknown need type 'ask'. [needs.load_external_need]", "WARNING: Unknown keys in external need source 'needs_test_small.json': ['unknown_key'] [needs.unknown_external_keys]", "WARNING: http://my_company.com/docs/v1/index.html#TEST_02: Need 'EXT_TEST_02' has unknown outgoing link 'EXT_TEST_01' in field 'links' [needs.external_link_outgoing]", diff --git a/tests/test_needimport.py b/tests/test_needimport.py index df863270a..d0c043232 100644 --- a/tests/test_needimport.py +++ b/tests/test_needimport.py @@ -317,7 +317,7 @@ def test_need_schema_warnings(test_app, snapshot): test_app._warning.getvalue().replace(str(test_app.srcdir) + os.sep, "srcdir/") ).splitlines() assert warnings == [ - "srcdir/index.rst:4: WARNING: Need 'TEST_01' could not be imported: Extra option 'extra2' is invalid: Invalid value for field 'extra2': 1 [needs.import_need]", + "srcdir/index.rst:4: WARNING: Need 'TEST_01' could not be imported: Field 'extra2' is invalid: Invalid value for field 'extra2': 1 [needs.import_need]", "srcdir/index.rst:4: WARNING: Unknown keys in import need source: ['unknown_key'] [needs.unknown_import_keys]", ] json_data = Path(test_app.outdir, "needs.json").read_text()