From d6f2fd73bf9c00ba801b4224788049bcf921f1b8 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 9 Feb 2026 12:07:50 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=E2=80=BC=EF=B8=8F=20Make=20`needs=5Ffields?= =?UTF-8?q?`=20and=20`add=5Ffield`=20default=20to=20nullable=20and=20no=20?= =?UTF-8?q?default?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/_static/tutorial_needs.json | 2 +- docs/ubproject.toml | 1 + sphinx_needs/needs.py | 10 +++- tests/__snapshots__/test_api_usage.ambr | 5 +- .../__snapshots__/test_dynamic_functions.ambr | 7 ++- tests/__snapshots__/test_external.ambr | 14 ++++-- tests/__snapshots__/test_extra_options.ambr | 21 +++++--- tests/__snapshots__/test_field_defaults.ambr | 48 ++++++++++++++----- tests/schema/__snapshots__/test_schema.ambr | 31 ++++++------ 9 files changed, 96 insertions(+), 43 deletions(-) diff --git a/docs/_static/tutorial_needs.json b/docs/_static/tutorial_needs.json index 6d557d12f..8714f416e 100644 --- a/docs/_static/tutorial_needs.json +++ b/docs/_static/tutorial_needs.json @@ -1 +1 @@ -{"current_version": "6.3.0", "project": "Sphinx-Needs", "versions": {"6.3.0": {"creator": {"program": "sphinx_needs", "version": "6.3.0"}, "needs": {"T_001": {"constraints_passed": null, "constraints_results": null, "content": "Test case 1", "external_css": "external_link", "id": "T_001", "title": "Unit test 1", "type": "tutorial-test", "type_name": "Test Case"}, "T_002": {"constraints_passed": null, "constraints_results": null, "content": "Test case 2", "external_css": "external_link", "id": "T_002", "title": "Unit test 2", "type": "tutorial-test", "type_name": "Test Case"}, "T_003": {"constraints_passed": null, "constraints_results": null, "content": "Test case 3", "external_css": "external_link", "id": "T_003", "title": "Unit test 3", "type": "tutorial-test", "type_name": "Test Case"}, "T_004": {"constraints_passed": null, "constraints_results": null, "content": "Test case 4", "external_css": "external_link", "id": "T_004", "title": "Unit test 4", "type": "tutorial-test", "type_name": "Test Case"}}, "needs_amount": 4, "needs_defaults_removed": true, "needs_schema": {"$schema": "http://json-schema.org/draft-07/schema#", "properties": {"amount": {"default": null, "description": "Amount value", "field_type": "extra", "type": ["number", "null"]}, "another_option": {"default": "", "description": "Another custom option", "field_type": "extra", "type": "string"}, "arch": {"additionalProperties": {"type": "string"}, "default": {}, "description": "Mapping of uml key to uml content.", "field_type": "core", "type": "object"}, "author": {"default": "", "description": "Author of the need", "field_type": "extra", "type": "string"}, "avatar": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "blocks": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "blocks_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "checks": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "checks_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "closed_at": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "comment": {"default": "", "description": "Additional comments", "field_type": "extra", "type": "string"}, "completion": {"default": null, "description": "Completion in %", "field_type": "extra", "type": ["integer", "null"]}, "config": {"default": "", "description": "Configuration option", "field_type": "extra", "type": "string"}, "constraints": {"default": [], "description": "List of constraint names, which are defined for this need.", "field_type": "core", "items": {"type": "string"}, "type": "array"}, "constraints_error": {"default": null, "description": "An error message set if any constraint failed, and `error_message` field is set in config.", "field_type": "core", "type": ["string", "null"]}, "constraints_passed": {"default": true, "description": "True if all constraints passed, False if any failed, None if not yet checked.", "field_type": "core", "type": ["boolean", "null"]}, "constraints_results": {"additionalProperties": {"type": "object"}, "default": {}, "description": "Mapping of constraint name, to check name, to result, None if not yet checked.", "field_type": "core", "type": ["object", "null"]}, "content": {"default": "", "description": "The main content of the need.", "field_type": "core", "type": "string"}, "created_at": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "docname": {"default": null, "description": "Name of the document where the need is defined (None if external).", "field_type": "core", "type": ["string", "null"]}, "doctype": {"default": ".rst", "description": "The markup type of the content, denoted by the suffix of the source file, e.g. '.rst'.", "field_type": "core", "type": "string"}, "duration": {"default": null, "description": "Time in days", "field_type": "extra", "type": ["integer", "null"]}, "ends_with": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "ends_with_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "external_css": {"default": "", "description": "CSS class name, added to the external reference.", "field_type": "core", "type": "string"}, "external_url": {"default": null, "description": "URL of the need, if it is an external need.", "field_type": "core", "type": ["string", "null"]}, "github": {"default": "", "description": "GitHub reference", "field_type": "extra", "type": "string"}, "has_dead_links": {"default": false, "description": "True if any links reference need ids that are not found in the need list.", "field_type": "core", "type": "boolean"}, "has_forbidden_dead_links": {"default": false, "description": "True if any links reference need ids that are not found in the need list, and the link type does not allow dead links.", "field_type": "core", "type": "boolean"}, "hours": {"default": null, "description": "Time in hours", "field_type": "extra", "type": ["integer", "null"]}, "id": {"description": "ID of the data.", "field_type": "core", "type": "string"}, "id_prefix": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "image": {"default": "", "description": "Image reference", "field_type": "extra", "type": "string"}, "is_external": {"default": false, "description": "If true, no node is created and need is referencing external url.", "field_type": "core", "type": "boolean"}, "is_import": {"default": false, "description": "If true, the need was derived from an import.", "field_type": "core", "type": "boolean"}, "is_modified": {"default": false, "description": "Whether the need was modified by needextend.", "field_type": "core", "type": "boolean"}, "jinja_content": {"default": false, "description": "Whether the content was pre-processed by jinja.", "field_type": "core", "type": "boolean"}, "layout": {"default": null, "description": "Key of the layout, which is used to render the need.", "field_type": "core", "type": ["string", "null"]}, "lineno": {"default": null, "description": "Line number where the need is defined (None if external).", "field_type": "core", "type": ["integer", "null"]}, "links": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "links_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "max_amount": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "max_content_lines": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "modifications": {"default": 0, "description": "Number of modifications by needextend.", "field_type": "core", "type": "integer"}, "my_extra_option": {"default": "", "description": "Custom extra option", "field_type": "extra", "type": "string"}, "params": {"default": null, "description": "Added by service open-needs", "field_type": "extra", "type": ["string", "null"]}, "parent_need": {"default": null, "description": "Simply the first parent id.", "field_type": "core", "type": ["string", "null"]}, "parent_needs": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "parent_needs_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "parts": {"additionalProperties": {"type": "object"}, "default": {}, "description": "Mapping of parts, a.k.a. sub-needs, IDs to data that overrides the need's data", "field_type": "core", "type": "object"}, "post_content": {"default": null, "description": "Additional content after the need.", "field_type": "core", "type": ["string", "null"]}, "post_template": {"default": null, "description": "The template key, if the post_content was created from a jinja template.", "field_type": "core", "type": ["string", "null"]}, "pre_content": {"default": null, "description": "Additional content before the need.", "field_type": "core", "type": ["string", "null"]}, "pre_template": {"default": null, "description": "The template key, if the pre_content was created from a jinja template.", "field_type": "core", "type": ["string", "null"]}, "prefix": {"default": null, "description": "Added by service open-needs", "field_type": "extra", "type": ["string", "null"]}, "query": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "section_name": {"default": null, "description": "Simply the first section.", "field_type": "core", "type": ["string", "null"]}, "sections": {"default": [], "description": "Sections of the need.", "field_type": "core", "items": {"type": "string"}, "type": "array"}, "service": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "signature": {"default": null, "description": "Derived from a docutils desc_name node.", "field_type": "core", "type": ["string", "null"]}, "specific": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "starts_after": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "starts_after_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "starts_with": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "starts_with_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "status": {"default": null, "description": "Status of the need.", "field_type": "core", "type": ["string", "null"]}, "style": {"default": null, "description": "Comma-separated list of CSS classes (all appended by `needs_style_`).", "field_type": "core", "type": ["string", "null"]}, "tags": {"default": [], "description": "List of tags.", "field_type": "core", "items": {"type": "string"}, "type": "array"}, "template": {"default": null, "description": "The template key, if the content was created from a jinja template.", "field_type": "core", "type": ["string", "null"]}, "tests": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "tests_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "title": {"description": "Title of the need.", "field_type": "core", "type": "string"}, "triggers": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "triggers_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "tutorial_required_by": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "tutorial_required_by_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "tutorial_specifies": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "tutorial_specifies_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "tutorial_tests": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "tutorial_tests_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "type": {"default": "", "description": "Type of the need.", "field_type": "core", "type": "string"}, "type_name": {"default": "", "description": "Name of the type.", "field_type": "core", "type": "string"}, "unit": {"default": "", "description": "Unit specification", "field_type": "extra", "type": "string"}, "updated_at": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "url": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "url_postfix": {"default": null, "description": "Added by service open-needs", "field_type": "extra", "type": ["string", "null"]}, "user": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "value": {"default": "", "description": "General value field", "field_type": "extra", "type": "string"}}, "type": "object"}}}} \ No newline at end of file +{"current_version": "6.3.0", "project": "Sphinx-Needs", "versions": {"6.3.0": {"creator": {"program": "sphinx_needs", "version": "6.3.0"}, "needs": {"T_001": {"constraints_passed": null, "constraints_results": null, "content": "Test case 1", "external_css": "external_link", "id": "T_001", "title": "Unit test 1", "type": "tutorial-test", "type_name": "Test Case"}, "T_002": {"constraints_passed": null, "constraints_results": null, "content": "Test case 2", "external_css": "external_link", "id": "T_002", "title": "Unit test 2", "type": "tutorial-test", "type_name": "Test Case"}, "T_003": {"constraints_passed": null, "constraints_results": null, "content": "Test case 3", "external_css": "external_link", "id": "T_003", "title": "Unit test 3", "type": "tutorial-test", "type_name": "Test Case"}, "T_004": {"constraints_passed": null, "constraints_results": null, "content": "Test case 4", "external_css": "external_link", "id": "T_004", "title": "Unit test 4", "type": "tutorial-test", "type_name": "Test Case"}}, "needs_amount": 4, "needs_defaults_removed": true, "needs_schema": {"$schema": "http://json-schema.org/draft-07/schema#", "properties": {"amount": {"default": null, "description": "Amount value", "field_type": "extra", "type": ["number", "null"]}, "another_option": {"default": "", "description": "Another custom option", "field_type": "extra", "type": ["string", "null"]}, "arch": {"additionalProperties": {"type": "string"}, "default": {}, "description": "Mapping of uml key to uml content.", "field_type": "core", "type": "object"}, "author": {"default": null, "description": "Author of the need", "field_type": "extra", "type": ["string", "null"]}, "avatar": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "blocks": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "blocks_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "checks": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "checks_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "closed_at": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "comment": {"default": null, "description": "Additional comments", "field_type": "extra", "type": ["string", "null"]}, "completion": {"default": null, "description": "Completion in %", "field_type": "extra", "type": ["integer", "null"]}, "config": {"default": null, "description": "Configuration option", "field_type": "extra", "type": ["string", "null"]}, "constraints": {"default": [], "description": "List of constraint names, which are defined for this need.", "field_type": "core", "items": {"type": "string"}, "type": "array"}, "constraints_error": {"default": null, "description": "An error message set if any constraint failed, and `error_message` field is set in config.", "field_type": "core", "type": ["string", "null"]}, "constraints_passed": {"default": true, "description": "True if all constraints passed, False if any failed, None if not yet checked.", "field_type": "core", "type": ["boolean", "null"]}, "constraints_results": {"additionalProperties": {"type": "object"}, "default": {}, "description": "Mapping of constraint name, to check name, to result, None if not yet checked.", "field_type": "core", "type": ["object", "null"]}, "content": {"default": "", "description": "The main content of the need.", "field_type": "core", "type": "string"}, "created_at": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "docname": {"default": null, "description": "Name of the document where the need is defined (None if external).", "field_type": "core", "type": ["string", "null"]}, "doctype": {"default": ".rst", "description": "The markup type of the content, denoted by the suffix of the source file, e.g. '.rst'.", "field_type": "core", "type": "string"}, "duration": {"default": null, "description": "Time in days", "field_type": "extra", "type": ["integer", "null"]}, "ends_with": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "ends_with_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "external_css": {"default": "", "description": "CSS class name, added to the external reference.", "field_type": "core", "type": "string"}, "external_url": {"default": null, "description": "URL of the need, if it is an external need.", "field_type": "core", "type": ["string", "null"]}, "github": {"default": null, "description": "GitHub reference", "field_type": "extra", "type": ["string", "null"]}, "has_dead_links": {"default": false, "description": "True if any links reference need ids that are not found in the need list.", "field_type": "core", "type": "boolean"}, "has_forbidden_dead_links": {"default": false, "description": "True if any links reference need ids that are not found in the need list, and the link type does not allow dead links.", "field_type": "core", "type": "boolean"}, "hours": {"default": null, "description": "Time in hours", "field_type": "extra", "type": ["integer", "null"]}, "id": {"description": "ID of the data.", "field_type": "core", "type": "string"}, "id_prefix": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "image": {"default": null, "description": "Image reference", "field_type": "extra", "type": ["string", "null"]}, "is_external": {"default": false, "description": "If true, no node is created and need is referencing external url.", "field_type": "core", "type": "boolean"}, "is_import": {"default": false, "description": "If true, the need was derived from an import.", "field_type": "core", "type": "boolean"}, "is_modified": {"default": false, "description": "Whether the need was modified by needextend.", "field_type": "core", "type": "boolean"}, "jinja_content": {"default": false, "description": "Whether the content was pre-processed by jinja.", "field_type": "core", "type": "boolean"}, "layout": {"default": null, "description": "Key of the layout, which is used to render the need.", "field_type": "core", "type": ["string", "null"]}, "lineno": {"default": null, "description": "Line number where the need is defined (None if external).", "field_type": "core", "type": ["integer", "null"]}, "links": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "links_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "max_amount": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "max_content_lines": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "modifications": {"default": 0, "description": "Number of modifications by needextend.", "field_type": "core", "type": "integer"}, "my_extra_option": {"default": null, "description": "Custom extra option", "field_type": "extra", "type": ["string", "null"]}, "params": {"default": null, "description": "Added by service open-needs", "field_type": "extra", "type": ["string", "null"]}, "parent_need": {"default": null, "description": "Simply the first parent id.", "field_type": "core", "type": ["string", "null"]}, "parent_needs": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "parent_needs_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "parts": {"additionalProperties": {"type": "object"}, "default": {}, "description": "Mapping of parts, a.k.a. sub-needs, IDs to data that overrides the need's data", "field_type": "core", "type": "object"}, "post_content": {"default": null, "description": "Additional content after the need.", "field_type": "core", "type": ["string", "null"]}, "post_template": {"default": null, "description": "The template key, if the post_content was created from a jinja template.", "field_type": "core", "type": ["string", "null"]}, "pre_content": {"default": null, "description": "Additional content before the need.", "field_type": "core", "type": ["string", "null"]}, "pre_template": {"default": null, "description": "The template key, if the pre_content was created from a jinja template.", "field_type": "core", "type": ["string", "null"]}, "prefix": {"default": null, "description": "Added by service open-needs", "field_type": "extra", "type": ["string", "null"]}, "query": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "section_name": {"default": null, "description": "Simply the first section.", "field_type": "core", "type": ["string", "null"]}, "sections": {"default": [], "description": "Sections of the need.", "field_type": "core", "items": {"type": "string"}, "type": "array"}, "service": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "signature": {"default": null, "description": "Derived from a docutils desc_name node.", "field_type": "core", "type": ["string", "null"]}, "specific": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "starts_after": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "starts_after_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "starts_with": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "starts_with_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "status": {"default": null, "description": "Status of the need.", "field_type": "core", "type": ["string", "null"]}, "style": {"default": null, "description": "Comma-separated list of CSS classes (all appended by `needs_style_`).", "field_type": "core", "type": ["string", "null"]}, "tags": {"default": [], "description": "List of tags.", "field_type": "core", "items": {"type": "string"}, "type": "array"}, "template": {"default": null, "description": "The template key, if the content was created from a jinja template.", "field_type": "core", "type": ["string", "null"]}, "tests": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "tests_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "title": {"description": "Title of the need.", "field_type": "core", "type": "string"}, "triggers": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "triggers_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "tutorial_required_by": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "tutorial_required_by_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "tutorial_specifies": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "tutorial_specifies_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "tutorial_tests": {"default": [], "description": "Link field", "field_type": "links", "items": {"type": "string"}, "type": "array"}, "tutorial_tests_back": {"default": [], "description": "Backlink field", "field_type": "backlinks", "items": {"type": "string"}, "type": "array"}, "type": {"default": "", "description": "Type of the need.", "field_type": "core", "type": "string"}, "type_name": {"default": "", "description": "Name of the type.", "field_type": "core", "type": "string"}, "unit": {"default": null, "description": "Unit specification", "field_type": "extra", "type": ["string", "null"]}, "updated_at": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "url": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "url_postfix": {"default": null, "description": "Added by service open-needs", "field_type": "extra", "type": ["string", "null"]}, "user": {"default": null, "description": "Added by service github-issues", "field_type": "extra", "type": ["string", "null"]}, "value": {"default": null, "description": "General value field", "field_type": "extra", "type": ["string", "null"]}}, "type": "object"}}}} \ No newline at end of file diff --git a/docs/ubproject.toml b/docs/ubproject.toml index 0d70a64e5..472e175ee 100644 --- a/docs/ubproject.toml +++ b/docs/ubproject.toml @@ -67,6 +67,7 @@ description = "Custom extra option" [needs.fields.another_option] description = "Another custom option" +default = "" [needs.fields.author] description = "Author of the need" diff --git a/sphinx_needs/needs.py b/sphinx_needs/needs.py index 853b6b4fe..adb27cce4 100644 --- a/sphinx_needs/needs.py +++ b/sphinx_needs/needs.py @@ -909,14 +909,20 @@ def create_schema(app: Sphinx, env: BuildEnvironment, _docnames: list[str]) -> N for name, field_data in _NEEDS_CONFIG.fields.items(): try: + back_compatible = field_data.source in { + "needs_extra_options", + "add_extra_option", + } + _schema = ( deepcopy(field_data.schema) # type: ignore[arg-type] if field_data.schema is not None else {"type": "string"} ) + nullable = True if field_data.nullable is not None: nullable = field_data.nullable - else: + elif back_compatible: # follows that of legacy (pre-schema) extra option, # i.e. nullable if schema is defined nullable = field_data.schema is not None @@ -936,7 +942,7 @@ def create_schema(app: Sphinx, env: BuildEnvironment, _docnames: list[str]) -> N # note, default follows that of legacy (pre-schema) extra option, # i.e. default to "" only if no schema is defined default=None - if field_data.schema is not None + if not back_compatible or field_data.schema is not None else FieldLiteralValue(""), allow_defaults=True, allow_extend=True, diff --git a/tests/__snapshots__/test_api_usage.ambr b/tests/__snapshots__/test_api_usage.ambr index 439c1e444..a57d22bb3 100644 --- a/tests/__snapshots__/test_api_usage.ambr +++ b/tests/__snapshots__/test_api_usage.ambr @@ -286,7 +286,10 @@ 'default': 'hallo', 'description': 'My extra field', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'params': dict({ 'default': None, diff --git a/tests/__snapshots__/test_dynamic_functions.ambr b/tests/__snapshots__/test_dynamic_functions.ambr index 1d8dab3e1..e454e6d7c 100644 --- a/tests/__snapshots__/test_dynamic_functions.ambr +++ b/tests/__snapshots__/test_dynamic_functions.ambr @@ -553,10 +553,13 @@ ]), }), 'test_func': dict({ - 'default': '', + 'default': None, 'description': 'Added by needs_fields config', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'title': dict({ 'description': 'Title of the need.', diff --git a/tests/__snapshots__/test_external.ambr b/tests/__snapshots__/test_external.ambr index a140d21e8..c34b6f097 100644 --- a/tests/__snapshots__/test_external.ambr +++ b/tests/__snapshots__/test_external.ambr @@ -767,16 +767,22 @@ ]), }), 'extra1': dict({ - 'default': '', + 'default': None, 'description': 'Added by needs_fields config', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'extra2': dict({ - 'default': '', + 'default': None, 'description': 'Added by needs_fields config', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'has_dead_links': dict({ 'default': False, diff --git a/tests/__snapshots__/test_extra_options.ambr b/tests/__snapshots__/test_extra_options.ambr index f17acba87..294bfd48b 100644 --- a/tests/__snapshots__/test_extra_options.ambr +++ b/tests/__snapshots__/test_extra_options.ambr @@ -214,16 +214,22 @@ ]), }), 'impacts': dict({ - 'default': '', + 'default': None, 'description': 'What is the impact of this need?', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'introduced': dict({ - 'default': '', + 'default': None, 'description': 'When was this need introduced?', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'is_external': dict({ 'default': False, @@ -312,10 +318,13 @@ 'type': 'integer', }), 'modified': dict({ - 'default': '', + 'default': None, 'description': 'When was this need last modified?', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'params': dict({ 'default': None, diff --git a/tests/__snapshots__/test_field_defaults.ambr b/tests/__snapshots__/test_field_defaults.ambr index 317a71a1c..fbf605daf 100644 --- a/tests/__snapshots__/test_field_defaults.ambr +++ b/tests/__snapshots__/test_field_defaults.ambr @@ -139,10 +139,13 @@ ]), }), 'bad_value_type': dict({ - 'default': '', + 'default': None, 'description': 'Added by needs_fields config', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'closed_at': dict({ 'default': None, @@ -457,30 +460,46 @@ 'default': 'test_global', 'description': 'Added by needs_fields config', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'option_2': dict({ + 'default': None, 'description': 'Added by needs_fields config', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'option_3': dict({ - 'default': '', + 'default': None, 'description': 'Added by needs_fields config', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'option_4': dict({ 'default': 'STATUS_UNKNOWN', 'description': 'Added by needs_fields config', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'option_5': dict({ 'default': 'final', 'description': 'Added by needs_fields config', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'params': dict({ 'default': None, @@ -673,10 +692,13 @@ 'type': 'string', }), 'too_many_params': dict({ - 'default': '', + 'default': None, 'description': 'Added by needs_fields config', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'type': dict({ 'default': '', @@ -741,7 +763,7 @@ ), }), 'bad_value_type': dict({ - 'default': FieldLiteralValue(value=''), + 'default': None, 'predicate_defaults': tuple( ), }), @@ -839,7 +861,7 @@ ), }), 'option_3': dict({ - 'default': FieldLiteralValue(value=''), + 'default': None, 'predicate_defaults': tuple( tuple( 'status == "implemented"', @@ -943,7 +965,7 @@ ), }), 'too_many_params': dict({ - 'default': FieldLiteralValue(value=''), + 'default': None, 'predicate_defaults': tuple( ), }), diff --git a/tests/schema/__snapshots__/test_schema.ambr b/tests/schema/__snapshots__/test_schema.ambr index a0e6c1800..676a03e44 100644 --- a/tests/schema/__snapshots__/test_schema.ambr +++ b/tests/schema/__snapshots__/test_schema.ambr @@ -854,7 +854,7 @@ 'signature': None, 'specific': None, 'status': None, - 'string_option_wo_schema': '', + 'string_option_wo_schema': None, 'style': None, 'tags': list([ ]), @@ -932,7 +932,7 @@ 'signature': None, 'specific': None, 'status': None, - 'string_option_wo_schema': '', + 'string_option_wo_schema': None, 'style': None, 'tags': list([ ]), @@ -1011,7 +1011,7 @@ 'signature': None, 'specific': None, 'status': None, - 'string_option_wo_schema': '', + 'string_option_wo_schema': None, 'style': None, 'tags': list([ ]), @@ -1088,7 +1088,7 @@ 'signature': None, 'specific': None, 'status': None, - 'string_option_wo_schema': '', + 'string_option_wo_schema': None, 'style': None, 'tags': list([ ]), @@ -1166,7 +1166,7 @@ 'signature': None, 'specific': None, 'status': None, - 'string_option_wo_schema': '', + 'string_option_wo_schema': None, 'style': None, 'tags': list([ ]), @@ -1251,7 +1251,7 @@ 'signature': None, 'specific': None, 'status': None, - 'string_option_wo_schema': '', + 'string_option_wo_schema': None, 'style': None, 'tags': list([ ]), @@ -1329,7 +1329,7 @@ 'signature': None, 'specific': None, 'status': None, - 'string_option_wo_schema': '', + 'string_option_wo_schema': None, 'style': None, 'tags': list([ ]), @@ -1407,7 +1407,7 @@ 'signature': None, 'specific': None, 'status': None, - 'string_option_wo_schema': '', + 'string_option_wo_schema': None, 'style': None, 'tags': list([ ]), @@ -1484,7 +1484,7 @@ 'signature': None, 'specific': None, 'status': None, - 'string_option_wo_schema': '', + 'string_option_wo_schema': None, 'style': None, 'tags': list([ ]), @@ -1563,7 +1563,7 @@ 'signature': None, 'specific': None, 'status': None, - 'string_option_wo_schema': '', + 'string_option_wo_schema': None, 'style': None, 'tags': list([ ]), @@ -1642,7 +1642,7 @@ 'signature': None, 'specific': None, 'status': None, - 'string_option_wo_schema': '', + 'string_option_wo_schema': None, 'style': None, 'tags': list([ ]), @@ -1721,7 +1721,7 @@ 'signature': None, 'specific': None, 'status': None, - 'string_option_wo_schema': '', + 'string_option_wo_schema': None, 'style': None, 'tags': list([ ]), @@ -2201,10 +2201,13 @@ ]), }), 'string_option_wo_schema': dict({ - 'default': '', + 'default': None, 'description': 'String option', 'field_type': 'extra', - 'type': 'string', + 'type': list([ + 'string', + 'null', + ]), }), 'style': dict({ 'default': None, From ec79a3ffba62634ce85312352989f8efe9255897 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 9 Feb 2026 13:18:21 +0100 Subject: [PATCH 2/2] add warning when schema+nullable+default not set for needs_fields/add_field --- docs/ubproject.toml | 8 +++++++ sphinx_needs/needs.py | 14 +++++++++++ tests/doc_test/add_sections_sigs/conf.py | 6 ++--- .../doc_df_check_linked_values/conf.py | 2 +- tests/doc_test/doc_df_user_functions/conf.py | 2 +- tests/doc_test/doc_dynamic_functions/conf.py | 2 +- tests/doc_test/doc_field_defaults/conf.py | 7 ++++-- tests/doc_test/doc_global_options/conf.py | 14 +++++------ tests/doc_test/doc_layout/conf.py | 2 +- tests/doc_test/doc_needpie/conf.py | 2 +- tests/doc_test/doc_needreport/conf.py | 2 +- tests/doc_test/doc_needs_filter_data/conf.py | 2 +- .../conf.py | 2 +- tests/doc_test/doc_needtable/conf.py | 24 +++++++++---------- tests/doc_test/doc_schema_e2e/ubproject.toml | 1 + tests/doc_test/external_doc/conf.py | 2 +- tests/doc_test/extra_options/conf.py | 10 ++++---- tests/doc_test/import_doc_warnings/conf.py | 2 +- tests/doc_test/needs_from_toml/folder/a.toml | 2 +- tests/doc_test/parallel_doc/conf.py | 7 +++--- tests/doc_test/variant_doc/conf.py | 7 +++--- tests/doc_test/variant_options/conf.py | 22 ++++++++--------- tests/schema/fixtures/fields.yml | 12 ++++++++++ tests/schema/fixtures/network.yml | 11 +++++++++ tests/schema/fixtures/reporting.yml | 6 +++++ tests/schema/fixtures/unevaluated.yml | 4 ++++ tests/test_api_usage.py | 6 ++++- 27 files changed, 124 insertions(+), 57 deletions(-) diff --git a/docs/ubproject.toml b/docs/ubproject.toml index 472e175ee..3cb0c7fbc 100644 --- a/docs/ubproject.toml +++ b/docs/ubproject.toml @@ -64,6 +64,7 @@ parse_variants = true [needs.fields.my_extra_option] description = "Custom extra option" +nullable = true [needs.fields.another_option] description = "Another custom option" @@ -71,9 +72,11 @@ default = "" [needs.fields.author] description = "Author of the need" +nullable = true [needs.fields.comment] description = "Additional comments" +nullable = true [needs.fields.amount] description = "Amount value" @@ -93,18 +96,23 @@ schema.type = "integer" [needs.fields.image] description = "Image reference" +nullable = true [needs.fields.config] description = "Configuration option" +nullable = true [needs.fields.github] description = "GitHub reference" +nullable = true [needs.fields.value] description = "General value field" +nullable = true [needs.fields.unit] description = "Unit specification" +nullable = true [[needs.types]] directive = "int" diff --git a/sphinx_needs/needs.py b/sphinx_needs/needs.py index adb27cce4..349975658 100644 --- a/sphinx_needs/needs.py +++ b/sphinx_needs/needs.py @@ -913,6 +913,20 @@ def create_schema(app: Sphinx, env: BuildEnvironment, _docnames: list[str]) -> N "needs_extra_options", "add_extra_option", } + if ( + not back_compatible + and field_data.schema is None + and field_data.default is None + and field_data.nullable is None + ): + log_warning( + LOGGER, + f"Field {name!r} (from {field_data.source}) has no 'schema', 'nullable' or 'default' defined, " + "which defaults to a string schema with nullable=True and no default. " + "To aide with backward compatibility please define at least one.", + "config", + None, + ) _schema = ( deepcopy(field_data.schema) # type: ignore[arg-type] diff --git a/tests/doc_test/add_sections_sigs/conf.py b/tests/doc_test/add_sections_sigs/conf.py index 3eaa5eef5..02548e8b8 100644 --- a/tests/doc_test/add_sections_sigs/conf.py +++ b/tests/doc_test/add_sections_sigs/conf.py @@ -4,9 +4,9 @@ needs_json_remove_defaults = True needs_fields = { - "introduced": {}, - "updated": {}, - "impacts": {}, + "introduced": {"nullable": True}, + "updated": {"nullable": True}, + "impacts": {"nullable": True}, } needs_template_collapse = """ diff --git a/tests/doc_test/doc_df_check_linked_values/conf.py b/tests/doc_test/doc_df_check_linked_values/conf.py index 9b25c9501..1ae6531d8 100644 --- a/tests/doc_test/doc_df_check_linked_values/conf.py +++ b/tests/doc_test/doc_df_check_linked_values/conf.py @@ -31,4 +31,4 @@ }, ] -needs_fields = {"test_func": {}, "hours": {}} +needs_fields = {"test_func": {"nullable": True}, "hours": {"nullable": True}} diff --git a/tests/doc_test/doc_df_user_functions/conf.py b/tests/doc_test/doc_df_user_functions/conf.py index fa5d95609..f3aaaa20b 100644 --- a/tests/doc_test/doc_df_user_functions/conf.py +++ b/tests/doc_test/doc_df_user_functions/conf.py @@ -31,7 +31,7 @@ }, ] -needs_fields = {"test_func": {}, "hours": {}} +needs_fields = {"test_func": {"nullable": True}, "hours": {"nullable": True}} def my_own_function(app, need, needs): diff --git a/tests/doc_test/doc_dynamic_functions/conf.py b/tests/doc_test/doc_dynamic_functions/conf.py index 697f525d9..45ea42a4a 100644 --- a/tests/doc_test/doc_dynamic_functions/conf.py +++ b/tests/doc_test/doc_dynamic_functions/conf.py @@ -31,7 +31,7 @@ }, ] -needs_fields = {"test_func": {}} +needs_fields = {"test_func": {"nullable": True}} needs_build_json = True needs_json_remove_defaults = True diff --git a/tests/doc_test/doc_field_defaults/conf.py b/tests/doc_test/doc_field_defaults/conf.py index 93bfcec9c..ca068caa3 100644 --- a/tests/doc_test/doc_field_defaults/conf.py +++ b/tests/doc_test/doc_field_defaults/conf.py @@ -46,7 +46,10 @@ "layout": {"default": "clean_l"}, "option_1": {"default": "test_global"}, "option_2": {"default": "[[copy('id')]]"}, - "option_3": {"predicates": [('status == "implemented"', "STATUS_IMPL")]}, + "option_3": { + "nullable": True, + "predicates": [('status == "implemented"', "STATUS_IMPL")], + }, "option_4": { "default": "STATUS_UNKNOWN", "predicates": [('status == "closed"', "STATUS_CLOSED")], @@ -59,7 +62,7 @@ "default": "final", }, "bad_value_type": {"default": 1.27}, - "too_many_params": {"predicates": [("a", "b", "c", "d")]}, + "too_many_params": {"nullable": True, "predicates": [("a", "b", "c", "d")]}, } needs_build_json = True diff --git a/tests/doc_test/doc_global_options/conf.py b/tests/doc_test/doc_global_options/conf.py index 5a731eca8..15057219c 100644 --- a/tests/doc_test/doc_global_options/conf.py +++ b/tests/doc_test/doc_global_options/conf.py @@ -27,13 +27,13 @@ ] needs_fields = { - "option_1": {}, - "option_2": {}, - "option_3": {}, - "option_4": {}, - "option_5": {}, - "bad_value_type": {}, - "too_many_params": {}, + "option_1": {"nullable": True}, + "option_2": {"nullable": True}, + "option_3": {"nullable": True}, + "option_4": {"nullable": True}, + "option_5": {"nullable": True}, + "bad_value_type": {"nullable": True}, + "too_many_params": {"nullable": True}, } needs_global_options = { diff --git a/tests/doc_test/doc_layout/conf.py b/tests/doc_test/doc_layout/conf.py index a3a8ef43a..3bcd97402 100644 --- a/tests/doc_test/doc_layout/conf.py +++ b/tests/doc_test/doc_layout/conf.py @@ -31,7 +31,7 @@ }, ] -needs_fields = {"author": {}, "author_image": {}} +needs_fields = {"author": {"nullable": True}, "author_image": {"nullable": True}} needs_layouts = { diff --git a/tests/doc_test/doc_needpie/conf.py b/tests/doc_test/doc_needpie/conf.py index 69ba164a8..0b8e38901 100644 --- a/tests/doc_test/doc_needpie/conf.py +++ b/tests/doc_test/doc_needpie/conf.py @@ -38,4 +38,4 @@ }, ] -needs_fields = {"author": {}} +needs_fields = {"author": {"nullable": True}} diff --git a/tests/doc_test/doc_needreport/conf.py b/tests/doc_test/doc_needreport/conf.py index 98f6b0069..01ee4b16e 100644 --- a/tests/doc_test/doc_needreport/conf.py +++ b/tests/doc_test/doc_needreport/conf.py @@ -1,5 +1,5 @@ extensions = ["sphinx_needs"] -needs_fields = {"other": {}} +needs_fields = {"other": {"nullable": True}} needs_render_context = { "report_directive": "admonition", } diff --git a/tests/doc_test/doc_needs_filter_data/conf.py b/tests/doc_test/doc_needs_filter_data/conf.py index 13fb53719..e9ecf92b0 100644 --- a/tests/doc_test/doc_needs_filter_data/conf.py +++ b/tests/doc_test/doc_needs_filter_data/conf.py @@ -47,7 +47,7 @@ def custom_func(): needs_filter_data = {"current_variant": "project_x", "sphinx_tag": custom_func()} -needs_fields = {"variant": {}} +needs_fields = {"variant": {"nullable": True}} needs_warnings = { "variant_not_equal_current_variant": "variant != current_variant", diff --git a/tests/doc_test/doc_needs_filter_func_allow_dirty_filter/conf.py b/tests/doc_test/doc_needs_filter_func_allow_dirty_filter/conf.py index ab3685777..a70677d7f 100644 --- a/tests/doc_test/doc_needs_filter_func_allow_dirty_filter/conf.py +++ b/tests/doc_test/doc_needs_filter_func_allow_dirty_filter/conf.py @@ -24,7 +24,7 @@ }, ] -needs_fields = {"ti": {}, "tcl": {}} +needs_fields = {"ti": {"nullable": True}, "tcl": {"nullable": True}} needs_extra_links = [ { diff --git a/tests/doc_test/doc_needtable/conf.py b/tests/doc_test/doc_needtable/conf.py index d275fb88d..c2c96a3dc 100644 --- a/tests/doc_test/doc_needtable/conf.py +++ b/tests/doc_test/doc_needtable/conf.py @@ -36,18 +36,18 @@ ] needs_fields = { - "my_extra_option": {}, - "another_option": {}, - "author": {}, - "comment": {}, - "amount": {}, - "hours": {}, - "image": {}, - "config": {}, - "github": {}, - "value": {}, - "unit": {}, - "special-chars!": {}, + "my_extra_option": {"nullable": True}, + "another_option": {"nullable": True}, + "author": {"nullable": True}, + "comment": {"nullable": True}, + "amount": {"nullable": True}, + "hours": {"nullable": True}, + "image": {"nullable": True}, + "config": {"nullable": True}, + "github": {"nullable": True}, + "value": {"nullable": True}, + "unit": {"nullable": True}, + "special-chars!": {"nullable": True}, } needs_string_links = { diff --git a/tests/doc_test/doc_schema_e2e/ubproject.toml b/tests/doc_test/doc_schema_e2e/ubproject.toml index 005083f66..bd53864e4 100644 --- a/tests/doc_test/doc_schema_e2e/ubproject.toml +++ b/tests/doc_test/doc_schema_e2e/ubproject.toml @@ -9,6 +9,7 @@ schema_debug_active = true [needs.fields.string_option_wo_schema] description = "String option" +nullable = true [needs.fields.efforts] description = "FTE days" diff --git a/tests/doc_test/external_doc/conf.py b/tests/doc_test/external_doc/conf.py index 841f6bc63..cd8e927bd 100644 --- a/tests/doc_test/external_doc/conf.py +++ b/tests/doc_test/external_doc/conf.py @@ -47,7 +47,7 @@ }, ] -needs_fields = {"extra1": {}, "extra2": {}} +needs_fields = {"extra1": {"nullable": True}, "extra2": {"nullable": True}} test_dir = os.path.dirname(__file__) test_json = os.path.join(test_dir, "needs_test_small.json") diff --git a/tests/doc_test/extra_options/conf.py b/tests/doc_test/extra_options/conf.py index 9eb1de37a..130aad267 100644 --- a/tests/doc_test/extra_options/conf.py +++ b/tests/doc_test/extra_options/conf.py @@ -3,8 +3,8 @@ needs_extra_options = ["updated"] needs_fields = { - "introduced": {"description": "When was this need introduced?"}, - "impacts": {"description": "What is the impact of this need?"}, + "introduced": {"description": "When was this need introduced?", "nullable": True}, + "impacts": {"description": "What is the impact of this need?", "nullable": True}, 1: {}, "a": 1, } @@ -17,8 +17,10 @@ def setup(app): from sphinx_needs.api.configuration import add_field - add_field("introduced", description="When was this need introduced?") - add_field("modified", description="When was this need last modified?") + add_field("introduced", description="When was this need introduced?", nullable=True) + add_field( + "modified", description="When was this need last modified?", nullable=True + ) needs_template_collapse = """ diff --git a/tests/doc_test/import_doc_warnings/conf.py b/tests/doc_test/import_doc_warnings/conf.py index 4b4872e40..c4947bc3d 100644 --- a/tests/doc_test/import_doc_warnings/conf.py +++ b/tests/doc_test/import_doc_warnings/conf.py @@ -2,7 +2,7 @@ extensions = ["sphinx_needs"] -needs_fields = {"extra1": {}, "extra2": {}} +needs_fields = {"extra1": {"nullable": True}, "extra2": {"nullable": True}} needs_build_json = True needs_json_remove_defaults = True diff --git a/tests/doc_test/needs_from_toml/folder/a.toml b/tests/doc_test/needs_from_toml/folder/a.toml index c56b0a640..9b4aab024 100644 --- a/tests/doc_test/needs_from_toml/folder/a.toml +++ b/tests/doc_test/needs_from_toml/folder/a.toml @@ -5,7 +5,7 @@ id_regex = "^[A-Za-z0-9_]" types = [ { directive = "other", title = "Another need type", prefix = "O_", color = "#DCB239" }, ] -fields = { "custom" = {} } +fields = { "custom" = { nullable = true } } build_json = true reproducible_json = true json_remove_defaults = true diff --git a/tests/doc_test/parallel_doc/conf.py b/tests/doc_test/parallel_doc/conf.py index 14ebbd061..6c1814a60 100644 --- a/tests/doc_test/parallel_doc/conf.py +++ b/tests/doc_test/parallel_doc/conf.py @@ -38,10 +38,11 @@ "status": { "parse_variants": True, }, - "my_extra_option": {}, - "another_option": {}, + "my_extra_option": {"nullable": True}, + "another_option": {"nullable": True}, "author": { + "nullable": True, "parse_variants": True, }, - "comment": {}, + "comment": {"nullable": True}, } diff --git a/tests/doc_test/variant_doc/conf.py b/tests/doc_test/variant_doc/conf.py index 3020dc274..127ae44a9 100644 --- a/tests/doc_test/variant_doc/conf.py +++ b/tests/doc_test/variant_doc/conf.py @@ -43,12 +43,13 @@ "status": { "parse_variants": True, }, - "my_extra_option": {}, - "another_option": {}, + "my_extra_option": {"nullable": True}, + "another_option": {"nullable": True}, "author": { + "nullable": True, "parse_variants": True, }, - "value": {}, + "value": {"nullable": True}, "field_bool": { "schema": { "type": "boolean", diff --git a/tests/doc_test/variant_options/conf.py b/tests/doc_test/variant_options/conf.py index 941949260..4600b2be8 100644 --- a/tests/doc_test/variant_options/conf.py +++ b/tests/doc_test/variant_options/conf.py @@ -41,17 +41,17 @@ needs_variant_options = ["status"] needs_filter_data = {"assignee": "Randy Duodu"} needs_fields = { - "my_extra_option": {}, - "another_option": {}, - "author": {}, - "comment": {}, - "amount": {}, - "hours": {}, - "image": {}, - "config": {}, - "github": {}, - "value": {}, - "unit": {}, + "my_extra_option": {"nullable": True}, + "another_option": {"nullable": True}, + "author": {"nullable": True}, + "comment": {"nullable": True}, + "amount": {"nullable": True}, + "hours": {"nullable": True}, + "image": {"nullable": True}, + "config": {"nullable": True}, + "github": {"nullable": True}, + "value": {"nullable": True}, + "unit": {"nullable": True}, } needs_build_json = True diff --git a/tests/schema/fixtures/fields.yml b/tests/schema/fixtures/fields.yml index 9dd1cdaba..a051db61a 100644 --- a/tests/schema/fixtures/fields.yml +++ b/tests/schema/fixtures/fields.yml @@ -4,6 +4,7 @@ no_schema: needs_from_toml = "ubproject.toml" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -40,6 +41,7 @@ const: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -61,6 +63,7 @@ const_error: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -82,6 +85,7 @@ enum: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -103,6 +107,7 @@ enum_error: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -124,6 +129,7 @@ auto_inject_type: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -144,6 +150,7 @@ required: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -162,6 +169,7 @@ required_missing: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -179,6 +187,7 @@ auto_inject_type_wrong_const: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -199,6 +208,7 @@ required_based_on_select_field_missing: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true [needs.fields.efforts] schema.type = "integer" rst: | @@ -223,6 +233,7 @@ required_based_on_select_field_below_threshold: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true [needs.fields.efforts] schema.type = "integer" rst: | @@ -248,6 +259,7 @@ required_based_on_select_field_over_threshold: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true [needs.fields.efforts] schema.type = "integer" rst: | diff --git a/tests/schema/fixtures/network.yml b/tests/schema/fixtures/network.yml index fa0746760..2eb166790 100644 --- a/tests/schema/fixtures/network.yml +++ b/tests/schema/fixtures/network.yml @@ -27,6 +27,7 @@ schemas_in_conf: } ubproject: | [needs.fields.asil] + nullable = true rst: | .. spec:: title :id: SPEC_1 @@ -64,6 +65,7 @@ schemas_in_conf_error: } ubproject: | [needs.fields.asil] + nullable = true rst: | .. spec:: title :id: SPEC_1 @@ -115,6 +117,7 @@ min_contains: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. spec:: title :id: SPEC_1 @@ -146,6 +149,7 @@ min_contains_error: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. spec:: title :id: SPEC_1 @@ -177,6 +181,7 @@ max_contains: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. spec:: title :id: SPEC_1 @@ -208,6 +213,7 @@ max_contains_error: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. spec:: title :id: SPEC_1 @@ -456,6 +462,7 @@ local_min_items: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. spec:: title :id: SPEC_1 @@ -481,6 +488,7 @@ local_min_items_error: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. spec:: title :id: SPEC_1 @@ -506,6 +514,7 @@ local_max_items: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. spec:: title :id: SPEC_1 @@ -534,6 +543,7 @@ local_max_items_error: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. spec:: title :id: SPEC_1 @@ -562,6 +572,7 @@ max_network_levels: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. spec:: title :id: SPEC_1 diff --git a/tests/schema/fixtures/reporting.yml b/tests/schema/fixtures/reporting.yml index 970242346..3e7bf36d6 100644 --- a/tests/schema/fixtures/reporting.yml +++ b/tests/schema/fixtures/reporting.yml @@ -5,6 +5,7 @@ severity_rule_default: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -25,6 +26,7 @@ severity_rule_info: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -46,6 +48,7 @@ severity_rule_warning: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -67,6 +70,7 @@ severity_rule_violation: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -89,6 +93,7 @@ severity_default_suppress_severity: suppress_warnings = ["sn_schema_violation"] ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -116,6 +121,7 @@ severity_default_suppress_severity_and_rule: suppress_warnings = ["sn_schema_violation.local_fail"] ubproject: | [needs.fields.asil] + nullable = true rst: | .. impl:: title :id: IMPL_1 diff --git a/tests/schema/fixtures/unevaluated.yml b/tests/schema/fixtures/unevaluated.yml index 50ecc965e..115e734fa 100644 --- a/tests/schema/fixtures/unevaluated.yml +++ b/tests/schema/fixtures/unevaluated.yml @@ -5,7 +5,9 @@ unevaluated_error: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true [needs.fields.comment] + nullable = true rst: | .. impl:: title :id: IMPL_1 @@ -25,7 +27,9 @@ unevaluated_allof_error: needs_schema_definitions_from_json = "schemas.json" ubproject: | [needs.fields.asil] + nullable = true [needs.fields.comment] + nullable = true [needs.fields.approved] schema.type = "boolean" rst: | diff --git a/tests/test_api_usage.py b/tests/test_api_usage.py index 5298defb6..98938bf0f 100644 --- a/tests/test_api_usage.py +++ b/tests/test_api_usage.py @@ -160,7 +160,11 @@ def setup(app): app.build() warnings = get_warnings_list(app) - assert len(warnings) == 0, "\n".join(warnings) + assert warnings == [ + "Field 'my_extra_option' (from add_field) has no 'schema', 'nullable' or 'default' defined, " + "which defaults to a string schema with nullable=True and no default. " + "To aide with backward compatibility please define at least one. [needs.config]\n" + ] html = Path(app.outdir, "index.html").read_text() assert html is not None