diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 0496c66f3..e2a666663 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -16,7 +16,7 @@ on: paths: ['docker/**'] env: - NEEDS_VERSION: 6.3.0 + NEEDS_VERSION: 7.0.0 DEPLOY_IMAGE: ${{ github.event_name != 'pull_request' }} jobs: diff --git a/docs/_static/tutorial_needs.json b/docs/_static/tutorial_needs.json index 8714f416e..df8c2f672 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", "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 +{"current_version": "7.0.0", "project": "Sphinx-Needs", "versions": {"7.0.0": {"creator": {"program": "sphinx_needs", "version": "7.0.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/changelog.rst b/docs/changelog.rst index 1eb44b7a1..59f139774 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,260 @@ Changelog ========= +.. _`release:7.0.0`: + +7.0.0 +----- + +:Released: Unreleased +:Full Changelog: `v6.3.0...v7.0.0 `__ + +This is a major release that consolidates field, link, and default configuration +into a single, composable schema system — inspired by +`SysML2 `__. +See the `extensible schema proposal `__ +for the full design rationale. + +This release completes the first two phases of the proposal: +migrating fields (``needs_extra_options`` → :ref:`needs_fields`) and +links (``needs_extra_links`` → :ref:`needs_links`). +The next potential phase is **per-type schemas with type inheritance**, +allowing individual need types to specialize fields and links +(see `discussion comment `__ +for the implementation plan). + +All deprecated configuration options continue to work in this release but emit warnings. +We recommend migrating to the new options as soon as possible; +deprecated options will be removed in a future major release. + +Consolidated field & link configuration +........................................ + +The core theme of this release is moving from many scattered configuration options +to a **unified per-field / per-link definition**. +This makes the configuration more explicit, easier to understand, and +lays the groundwork for future per-type schemas. + +- ✨ Add :ref:`needs_fields` configuration, deprecate ``needs_extra_options`` (:pr:`1611`) + + The new :ref:`needs_fields` is a **dictionary** mapping field names to their full configuration. + It replaces the flat list ``needs_extra_options`` and also allows **specializing core fields** + (e.g. ``status``, ``tags``) by narrowing their type constraints + (following the `Liskov substitution principle `__). + + .. code-block:: toml + :caption: Before (deprecated) + + needs_extra_options = ["priority", "verified"] + + .. code-block:: toml + :caption: After + + [needs.fields.priority] + description = "Priority level" + schema.type = "integer" + schema.minimum = 1 + schema.maximum = 5 + + [needs.fields.verified] + schema.type = "boolean" + +- ⚠️ Migrate ``needs_extra_links`` to :ref:`needs_links` (:pr:`1649`) + + The new :ref:`needs_links` uses the same dict-based pattern as :ref:`needs_fields`, + replacing the list-based ``needs_extra_links``. + The redundant ``option`` key is no longer needed. + + .. code-block:: toml + :caption: Before (deprecated) + + [[needs.extra_links]] + option = "blocks" + incoming = "is blocked by" + + .. code-block:: toml + :caption: After + + [needs.links.blocks] + incoming = "is blocked by" + +- ✨ Add ``default`` and ``predicates`` keys to :ref:`needs_fields` and :ref:`needs_links`, + deprecate ``needs_global_options`` (:pr:`1612`) + + Field defaults and conditional (predicate-based) defaults can now be set + **directly on each field or link**, replacing the separate ``needs_global_options`` configuration. + + .. code-block:: toml + :caption: Before (deprecated) + + [needs.global_options.status] + default = "draft" + predicates = [['status == "open"', "active"]] + + .. code-block:: toml + :caption: After + + [needs.fields.status] + default = "draft" + predicates = [['status == "open"', "active"]] + +- ✨ Add ``nullable`` key to :ref:`needs_fields` items (:pr:`1613`) + + Individual fields can now declare whether ``null`` (``None``) is a valid value. + +- ✨ Add ``parse_variants`` to :ref:`needs_fields` / :ref:`needs_links`, + deprecate ``needs_variant_options`` (:pr:`1614`) + + Variant parsing is now enabled per-field/link instead of via a separate global list. + + .. code-block:: toml + :caption: Before (deprecated) + + needs_variant_options = ["author", "status"] + + .. code-block:: toml + :caption: After + + [needs.fields.author] + parse_variants = true + + [needs.fields.status] + parse_variants = true + +- ♻️ Move ``needs_statuses`` and ``needs_tags`` checking to schema validation (:pr:`1605`) + + ``needs_statuses`` and ``needs_tags`` are now deprecated. + Use schema ``enum`` constraints on the ``status`` and ``tags`` fields instead: + + .. code-block:: toml + :caption: Before (deprecated) + + needs_statuses = [{name = "draft"}, {name = "approved"}] + needs_tags = [{name = "security"}, {name = "usability"}] + + .. code-block:: toml + :caption: After + + [needs.fields.status] + schema.enum = ["draft", "approved"] + + [needs.fields.tags] + schema.items.enum = ["security", "usability"] + +API changes +........... + +- ✨ Add ``add_field`` API; deprecate ``add_extra_option`` (:pr:`1641`) + + Extensions that programmatically add fields should migrate from + :py:func:`~sphinx_needs.api.configuration.add_extra_option` to the new + :py:func:`~sphinx_needs.api.configuration.add_field`, + which accepts the same schema, default, and predicate options as :ref:`needs_fields`. + +- 👌 Allow ``add_field`` API to set defaults/predicates (:pr:`1643`) + +Breaking changes +................ + +- ‼️ ``needs_fields`` and ``add_field`` default to **nullable with no default** (:pr:`1645`) + + When defining a field via :ref:`needs_fields` or ``add_field`` **without** an explicit ``schema``, + the field now defaults to ``nullable=True`` with no default value (i.e. ``null``). + + Previously, fields without an explicit schema defaulted to ``nullable=False`` with a + default of ``""`` (empty string). This was a legacy of the untyped ``needs_extra_options`` era + and caused confusion when users expected unset fields to be ``null`` rather than an empty string. + + The old ``needs_extra_options`` / ``add_extra_option`` APIs retain their legacy behaviour, + so **only** users who have already migrated to ``needs_fields`` / ``add_field`` are affected. + + To restore the old behaviour explicitly: + + .. code-block:: toml + + [needs.fields.my_field] + nullable = false + default = "" + +- ‼️ Need fields added by services default to nullable and null (:pr:`1644`) + + Fields registered by built-in services (e.g. GitHub) now default to nullable with no default, + matching the new ``needs_fields`` convention. + +- ⚠️ Separate reduced vs full need representation for schema validation (:pr:`1652`) + + Schema validation now distinguishes between a **reduced** need representation + (for type-specific ``local``/``network`` schemas, where default-valued and empty fields are + stripped) and a **full** representation (for global field/link constraints). + + Previously, fields with default ``[]`` values (link fields, ``tags``) were stripped before + validation, silently bypassing constraints like ``minItems``, ``contains``, and ``minContains``. + These fields are now retained as ``[]`` in global constraint validation, so such constraints + will now correctly trigger on needs that have empty link/tag lists. + +- ♻️ Replace ``jinja2`` with ``minijinja`` for template rendering (:pr:`1659`) + + The ``jinja2`` dependency has been replaced by ``minijinja`` (``minijinja-py``), + a lightweight, Rust-based Jinja2-compatible template engine. + This provides faster template rendering and a smaller dependency footprint. + + **Standard Jinja2 syntax is fully supported** — most custom templates will work without changes. + Notable differences: + + - ``None`` renders as ``"none"`` (lowercase) instead of ``"None"``. + Use ``{% if field %}{{ field }}{% endif %}`` to guard against ``None`` output. + - A few Jinja2-only filters are not available: ``wordcount``, ``center``, ``urlize``, + ``xmlattr``, ``forceescape``. See the ``minijinja`` + `documentation `__ for alternatives. + +Compatibility changes +..................... + +- ⬆️ Support Sphinx 9 and Docutils 0.22 (:pr:`1653`) + + Sphinx-Needs now supports Sphinx 7.4 through 9.x and Docutils 0.22. + +Bug fixes +......... + +- 🐛 Fix ``needs.json`` read/write when no needs are present (:pr:`1661`) +- 🐛 Fix ``needextend`` data purging and deterministic ordering (:pr:`1657`) +- 🐛 Fix schema validation returning per-need errors (:pr:`1640`) + +Improvements +............ + +- 👌 Default values of extra fields now checked against schema definitions (:pr:`1647`) +- 👌 Expose ``parse_dynamic_functions`` in field and link configuration (:pr:`1660`) +- 👌 Minor improvements for ``needs_fields`` inheritance (:pr:`1635`) +- ✨ Add ``uniqueItems`` to ``array`` schema validation (:pr:`1610`) + +Internal changes +................ + +These changes do not affect user-facing behaviour but improve the codebase: + +- ♻️ Migrate use of ``extra_links`` to Schema-Based Access (:pr:`1638`) +- 🔧 Refactor schema validation: separate select filtering from local validation (:pr:`1655`) +- 🔧 Simplify field/link validation (:pr:`1654`) +- 🔧 Simplify ``generate_needs`` function (:pr:`1651`) +- 🔧 Rename "option" to "field" internally (:pr:`1642`) +- 🔧 Refactor ``populate_field_type`` to use type-directed schema walking (:pr:`1639`) +- 🔧 Store full schema on ``FieldSchema`` (:pr:`1603`) +- 🔧 Add ``validate_extra_option_schema`` (:pr:`1602`) +- 🔧 Remove use of ``extra_options`` after config resolution (:pr:`1607`) +- 🔧 Move link ``schema`` to ``LinkSchema`` (:pr:`1617`) +- 🔧 Simplify ``import_prefix_link_edit`` (:pr:`1615`) +- 🔧 Add ``AGENTS.md`` (:pr:`1621`) +- 🧪 Add tests for ``create_inherited_field`` (:pr:`1636`) + +Documentation fixes +................... + +- 📚 Fix typo in sort of ``needtable`` documentation (:pr:`1619`) +- 📚 Fix small grammatical error in ``need.rst`` (:pr:`1637`) +- 📚 Fix typo in documentation for GitHub service example (:pr:`1634`) + .. _`release:6.3.0`: 6.3.0 diff --git a/sphinx_needs/__init__.py b/sphinx_needs/__init__.py index df2e59bea..14d072f4f 100644 --- a/sphinx_needs/__init__.py +++ b/sphinx_needs/__init__.py @@ -1,6 +1,6 @@ """Sphinx needs extension for managing needs/requirements and specifications""" -__version__ = "6.3.0" +__version__ = "7.0.0" def setup(app): # type: ignore[no-untyped-def]