diff --git a/strictdoc/__init__.py b/strictdoc/__init__.py index 516a7994d..69d62fa39 100644 --- a/strictdoc/__init__.py +++ b/strictdoc/__init__.py @@ -1,6 +1,6 @@ from strictdoc.core.environment import SDocRuntimeEnvironment -__version__ = "0.0.57" +__version__ = "0.0.58a1" environment = SDocRuntimeEnvironment(__file__) diff --git a/strictdoc/backend/sdoc/validations/sdoc_validator.py b/strictdoc/backend/sdoc/validations/sdoc_validator.py index 6faf7a829..daf59619b 100644 --- a/strictdoc/backend/sdoc/validations/sdoc_validator.py +++ b/strictdoc/backend/sdoc/validations/sdoc_validator.py @@ -136,6 +136,7 @@ def validate_node( requirement: SDocNode, document_grammar: DocumentGrammar, path_to_sdoc_file: str, + auto_uid_mode: bool = True, ): if ( requirement.requirement_type @@ -185,6 +186,7 @@ def validate_node( requirement_field=requirement_field, grammar_field=grammar_field, path_to_sdoc_file=path_to_sdoc_file, + auto_uid_mode=auto_uid_mode, ) ) except StopIteration: @@ -205,7 +207,9 @@ def validate_node( grammar_field = next(grammar_fields_iterator, None) requirement_field = next(requirement_field_iterator, None) else: - assert not grammar_field.required + assert not grammar_field.required or ( + grammar_field.title == "UID" and auto_uid_mode + ) grammar_field = next(grammar_fields_iterator, None) # REFS validation. @@ -227,6 +231,7 @@ def validate_requirement_field( requirement_field: SDocNodeField, grammar_field: GrammarElementField, path_to_sdoc_file: str, + auto_uid_mode: bool = True, ) -> bool: if grammar_field is None: if requirement_field is None: @@ -256,6 +261,25 @@ def validate_requirement_field( if grammar_field.title != requirement_field.field_name: if grammar_field.required: + if ( + grammar_field.title + not in requirement.ordered_fields_lookup.keys() + ): + # A special case: The Manage UID command auto-generates the UID, + # so the field presence validation has to be relaxed. + # The GitHub issue report: + # manage auto-uid: UID field REQUIRED True leads to an error + # https://github.com/strictdoc-project/strictdoc/issues/1896 + if grammar_field.title == "UID" and auto_uid_mode: + return False + + raise StrictDocSemanticError.missing_required_field( + node=requirement, + grammar_field=grammar_field, + document_grammar=document_grammar, + path_to_sdoc_file=path_to_sdoc_file, + ) + raise StrictDocSemanticError.wrong_field_order( node=requirement, document_grammar=document_grammar, diff --git a/strictdoc/commands/manage_autouid_command.py b/strictdoc/commands/manage_autouid_command.py index 8d50e6efa..bdb7758f1 100644 --- a/strictdoc/commands/manage_autouid_command.py +++ b/strictdoc/commands/manage_autouid_command.py @@ -28,6 +28,7 @@ def execute(*, project_config: ProjectConfig, parallelizer: Parallelizer): TraceabilityIndexBuilder.create( project_config=project_config, parallelizer=parallelizer, + auto_uid_mode=True, ) ) except DocumentTreeError as exc: diff --git a/strictdoc/core/traceability_index_builder.py b/strictdoc/core/traceability_index_builder.py index 4d52fcdb7..5ce6339e0 100644 --- a/strictdoc/core/traceability_index_builder.py +++ b/strictdoc/core/traceability_index_builder.py @@ -62,7 +62,8 @@ def create( *, project_config: ProjectConfig, parallelizer, - skip_source_files=False, + skip_source_files: bool = False, + auto_uid_mode: bool = False, ) -> TraceabilityIndex: # TODO: It would be great to hide this code behind --development flag. # There is no need for this to be activated in the Pip-released builds. @@ -102,7 +103,9 @@ def create( # - assets # - runtime configuration traceability_index: TraceabilityIndex = ( - TraceabilityIndexBuilder.create_from_document_tree(document_tree) + TraceabilityIndexBuilder.create_from_document_tree( + document_tree, auto_uid_mode + ) ) traceability_index.document_tree = document_tree traceability_index.asset_manager = asset_manager @@ -193,6 +196,7 @@ def create( @timing_decorator("Build traceability graph") def create_from_document_tree( document_tree: DocumentTree, + auto_uid_mode: bool = True, ) -> TraceabilityIndex: # FIXME: Too many things going on below. Would be great to simplify this # workflow. @@ -360,6 +364,7 @@ def create_from_document_tree( node, document_grammar=document.grammar, path_to_sdoc_file=document.meta.input_doc_full_path, + auto_uid_mode=auto_uid_mode, ) except StrictDocSemanticError as exc: print(exc.to_print_message()) # noqa: T201 diff --git a/tests/end2end/__init__.py b/tests/end2end/__init__.py index 4e2048858..1df4b49af 100644 --- a/tests/end2end/__init__.py +++ b/tests/end2end/__init__.py @@ -1 +1 @@ -# Dummy comment to trigger CI. +# Dummy comment to trigger CI diff --git a/tests/integration/commands/manage/auto-uid/requirement_uids/09_edge_grammar_UID_required/input.expected.sdoc b/tests/integration/commands/manage/auto-uid/requirement_uids/09_edge_grammar_UID_required/input.expected.sdoc new file mode 100644 index 000000000..9608e662d --- /dev/null +++ b/tests/integration/commands/manage/auto-uid/requirement_uids/09_edge_grammar_UID_required/input.expected.sdoc @@ -0,0 +1,35 @@ +[DOCUMENT] +TITLE: Hello world doc + +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: True + - TITLE: STATEMENT + TYPE: String + REQUIRED: True + RELATIONS: + - TYPE: Parent + +[REQUIREMENT] +UID: REQ-1 +STATEMENT: System shall do 1. + +[REQUIREMENT] +UID: REQ-2 +STATEMENT: System shall do 2. + +[REQUIREMENT] +UID: REQ-3 +STATEMENT: System shall do 3. diff --git a/tests/integration/commands/manage/auto-uid/requirement_uids/09_edge_grammar_UID_required/input.sdoc b/tests/integration/commands/manage/auto-uid/requirement_uids/09_edge_grammar_UID_required/input.sdoc new file mode 100644 index 000000000..ba480e540 --- /dev/null +++ b/tests/integration/commands/manage/auto-uid/requirement_uids/09_edge_grammar_UID_required/input.sdoc @@ -0,0 +1,34 @@ +[DOCUMENT] +TITLE: Hello world doc + +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: True + - TITLE: STATEMENT + TYPE: String + REQUIRED: True + RELATIONS: + - TYPE: Parent + +[REQUIREMENT] +UID: REQ-1 +STATEMENT: System shall do 1. + +[REQUIREMENT] +UID: REQ-2 +STATEMENT: System shall do 2. + +[REQUIREMENT] +STATEMENT: System shall do 3. diff --git a/tests/integration/commands/manage/auto-uid/requirement_uids/09_edge_grammar_UID_required/test.itest b/tests/integration/commands/manage/auto-uid/requirement_uids/09_edge_grammar_UID_required/test.itest new file mode 100644 index 000000000..99184af50 --- /dev/null +++ b/tests/integration/commands/manage/auto-uid/requirement_uids/09_edge_grammar_UID_required/test.itest @@ -0,0 +1,3 @@ +RUN: cp %S/input.sdoc %S/Output/ +RUN: %strictdoc manage auto-uid %S/Output/ +RUN: %diff %S/input.expected.sdoc %S/Output/input.sdoc diff --git a/tests/integration/features/document_grammar/validation/03b_valid_field_but_incorrect_order_UID/input.sdoc b/tests/integration/features/document_grammar/validation/03b_valid_field_but_incorrect_order_UID/input.sdoc new file mode 100644 index 000000000..d37e0cc4f --- /dev/null +++ b/tests/integration/features/document_grammar/validation/03b_valid_field_but_incorrect_order_UID/input.sdoc @@ -0,0 +1,27 @@ +[DOCUMENT] +TITLE: Hello world doc + +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: True + - TITLE: STATEMENT + TYPE: String + REQUIRED: True + RELATIONS: + - TYPE: Parent + +[REQUIREMENT] +STATEMENT: System shall do 1. +UID: REQ-1 diff --git a/tests/integration/features/document_grammar/validation/03b_valid_field_but_incorrect_order_UID/test.itest b/tests/integration/features/document_grammar/validation/03b_valid_field_but_incorrect_order_UID/test.itest new file mode 100644 index 000000000..2b8182a94 --- /dev/null +++ b/tests/integration/features/document_grammar/validation/03b_valid_field_but_incorrect_order_UID/test.itest @@ -0,0 +1,11 @@ +RUN: %expect_exit 1 %strictdoc passthrough %S/input.sdoc --output-dir %S/Output/ | filecheck %s + +# The same validation message should be produced even if the auto-uid command is executed. +# https://github.com/strictdoc-project/strictdoc/issues/1896 +RUN: cp %S/input.sdoc %S/Output/ +RUN: %expect_exit 1 %strictdoc manage auto-uid %S/Output/ + +CHECK: error: could not parse file: {{.*}}/input.sdoc. +CHECK: Semantic error: Wrong field order for requirement: [STATEMENT, UID]. +CHECK: Location: {{.*}}/input.sdoc:25:1 +CHECK: Hint: Problematic field: STATEMENT. Compare with the document grammar: [UID, STATEMENT] for type: REQUIREMENT. diff --git a/tests/integration/features/document_grammar/validation/04_missing_required_grammar_field/input.sdoc b/tests/integration/features/document_grammar/validation/04a_missing_required_grammar_field_node_has_less_fields_than_grammar/input.sdoc similarity index 100% rename from tests/integration/features/document_grammar/validation/04_missing_required_grammar_field/input.sdoc rename to tests/integration/features/document_grammar/validation/04a_missing_required_grammar_field_node_has_less_fields_than_grammar/input.sdoc diff --git a/tests/integration/features/document_grammar/validation/04_missing_required_grammar_field/test.itest b/tests/integration/features/document_grammar/validation/04a_missing_required_grammar_field_node_has_less_fields_than_grammar/test.itest similarity index 100% rename from tests/integration/features/document_grammar/validation/04_missing_required_grammar_field/test.itest rename to tests/integration/features/document_grammar/validation/04a_missing_required_grammar_field_node_has_less_fields_than_grammar/test.itest diff --git a/tests/integration/features/document_grammar/validation/04b_missing_required_grammar_field/input.sdoc b/tests/integration/features/document_grammar/validation/04b_missing_required_grammar_field/input.sdoc new file mode 100644 index 000000000..60c287fa2 --- /dev/null +++ b/tests/integration/features/document_grammar/validation/04b_missing_required_grammar_field/input.sdoc @@ -0,0 +1,26 @@ +[DOCUMENT] +TITLE: Hello world doc + +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: True + - TITLE: STATEMENT + TYPE: String + REQUIRED: True + RELATIONS: + - TYPE: Parent + +[REQUIREMENT] +STATEMENT: System shall do 1. diff --git a/tests/integration/features/document_grammar/validation/04b_missing_required_grammar_field/test.itest b/tests/integration/features/document_grammar/validation/04b_missing_required_grammar_field/test.itest new file mode 100644 index 000000000..3831480c1 --- /dev/null +++ b/tests/integration/features/document_grammar/validation/04b_missing_required_grammar_field/test.itest @@ -0,0 +1,6 @@ +RUN: %expect_exit 1 %strictdoc passthrough %S/input.sdoc --output-dir %S/Output/ | filecheck %s + +CHECK: error: could not parse file: {{.*}}/input.sdoc. +CHECK: Semantic error: Requirement is missing a field that is required by grammar: UID. +CHECK: Location: {{.*}}/input.sdoc:25:1 +CHECK: Hint: Requirement fields: [STATEMENT], grammar fields: [UID, STATEMENT].