From da11dd6b019214af5b5a5f293ae10cc45de76f4b Mon Sep 17 00:00:00 2001 From: Stanislav Pankevich Date: Sun, 30 Jun 2024 15:24:57 +0200 Subject: [PATCH] backend/sdoc: SDocNode: Make MID a normal SDocField Follow-up to https://github.com/strictdoc-project/strictdoc/issues/1897#issuecomment-2187562062 --- ...trictdoc_20_L1_Open_Requirements_Tool.sdoc | 37 ++++++++++ ...trictdoc_21_L2_StrictDoc_Requirements.sdoc | 37 ++++++++++ docs/strictdoc_28_Backlog.sdoc | 37 ++++++++++ docs_extra/DO178_requirements.sdoc | 11 +++ docs_extra/Zephyr_requirements.sdoc | 37 ++++++++++ .../excel/import_/excel_to_sdoc_converter.py | 1 - .../reqif/p01_sdoc/reqif_to_sdoc_converter.py | 13 +++- .../reqif/p01_sdoc/sdoc_to_reqif_converter.py | 3 + strictdoc/backend/sdoc/error_handling.py | 19 +++++ strictdoc/backend/sdoc/grammar/grammar.py | 5 +- strictdoc/backend/sdoc/grammar_reader.py | 2 +- .../backend/sdoc/models/document_grammar.py | 7 +- strictdoc/backend/sdoc/models/node.py | 7 +- .../backend/sdoc/models/object_factory.py | 1 - strictdoc/backend/sdoc/models/type_system.py | 1 + strictdoc/backend/sdoc/processor.py | 9 +-- .../sdoc/validations/sdoc_validator.py | 20 +++++ strictdoc/backend/sdoc/writer.py | 9 +-- strictdoc/core/traceability_index_builder.py | 12 +-- .../form_objects/requirement_form_object.py | 73 ++++++------------- .../components/node_field/meta/index.jinja | 12 --- .../document/frame_requirement_form.jinja | 9 --- .../export/spdx/spdx_to_sdoc_converter.py | 4 - strictdoc/server/routers/main_router.py | 2 - .../expected_output/document.sdoc | 1 - .../update_text_node/input/document.sdoc | 1 - .../document.sdoc | 2 - .../view_document_with_text_node/test_case.py | 1 - .../expected_output/document.sdoc | 34 ++++++++- .../input/document.sdoc | 34 ++++++++- .../test_case.py | 5 +- .../input/document.sdoc | 31 ++++++++ .../test_case.py | 6 +- .../expected_output/document.sdoc | 43 +++++++++++ .../input/document.sdoc | 40 ++++++++++ .../test_case.py | 47 ++++++++++++ .../grammar.sgra | 3 + .../document.sdoc | 14 ++++ .../01_cli_option/sample.sdoc | 3 + .../02_toml_option/sample.sdoc | 3 + .../bypass/40_generate_mid/input.sdoc | 17 +++++ .../json/01_basic_json_export/input1.sdoc | 20 +++++ .../json/01_basic_json_export/input2.sdoc | 20 +++++ .../input1.sdoc | 20 +++++ .../input2.sdoc | 20 +++++ .../input.sdoc | 3 + .../lhs/input.sdoc | 20 +++++ .../rhs/input.sdoc | 20 +++++ .../test.itest | 2 +- .../test.itest | 2 +- .../input.sdoc | 15 ++++ .../test.itest | 6 ++ .../input.sdoc | 31 ++++++++ .../nested/input2.sdoc | 31 ++++++++ .../nested/subnested/input3.sdoc | 31 ++++++++ .../input.sdoc | 20 +++++ .../input2.sdoc | 20 +++++ .../reqif/02_user_provided_example/script.py | 2 +- .../backend/sdoc/test_dsl_passthrough.py | 20 ++++- 59 files changed, 823 insertions(+), 133 deletions(-) create mode 100644 tests/end2end/screens/document/create_requirement/_mid/update_requirement__mid__update_requirement_preserves_mid/expected_output/document.sdoc create mode 100644 tests/end2end/screens/document/create_requirement/_mid/update_requirement__mid__update_requirement_preserves_mid/input/document.sdoc create mode 100644 tests/end2end/screens/document/create_requirement/_mid/update_requirement__mid__update_requirement_preserves_mid/test_case.py create mode 100644 tests/integration/features/document_grammar/validation/09_ENABLE_MID_enabled_but_missing_MID_field/input.sdoc create mode 100644 tests/integration/features/document_grammar/validation/09_ENABLE_MID_enabled_but_missing_MID_field/test.itest diff --git a/docs/strictdoc_20_L1_Open_Requirements_Tool.sdoc b/docs/strictdoc_20_L1_Open_Requirements_Tool.sdoc index 85685709d..f8d846f3d 100644 --- a/docs/strictdoc_20_L1_Open_Requirements_Tool.sdoc +++ b/docs/strictdoc_20_L1_Open_Requirements_Tool.sdoc @@ -6,6 +6,43 @@ ROOT: True OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATUS + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + - TITLE: RATIONALE + TYPE: String + REQUIRED: False + - TITLE: COMMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [FREETEXT] The StrictDoc project is structured around two distinct requirement documents that guide its development: diff --git a/docs/strictdoc_21_L2_StrictDoc_Requirements.sdoc b/docs/strictdoc_21_L2_StrictDoc_Requirements.sdoc index f27d41560..a293b1697 100644 --- a/docs/strictdoc_21_L2_StrictDoc_Requirements.sdoc +++ b/docs/strictdoc_21_L2_StrictDoc_Requirements.sdoc @@ -5,6 +5,43 @@ REQ_PREFIX: SDOC-SRS- OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATUS + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + - TITLE: RATIONALE + TYPE: String + REQUIRED: False + - TITLE: COMMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [SECTION] MID: bd8a7931c1e04df9bf08d291488c67aa TITLE: SDoc data model diff --git a/docs/strictdoc_28_Backlog.sdoc b/docs/strictdoc_28_Backlog.sdoc index bf5ce18c8..3667ec078 100644 --- a/docs/strictdoc_28_Backlog.sdoc +++ b/docs/strictdoc_28_Backlog.sdoc @@ -5,6 +5,43 @@ REQ_PREFIX: SDOC-BACKLOG- OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATUS + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + - TITLE: RATIONALE + TYPE: String + REQUIRED: False + - TITLE: COMMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [FREETEXT] This document outlines the future work items for StrictDoc. diff --git a/docs_extra/DO178_requirements.sdoc b/docs_extra/DO178_requirements.sdoc index 5cc2fc786..bc7c9a9e3 100644 --- a/docs_extra/DO178_requirements.sdoc +++ b/docs_extra/DO178_requirements.sdoc @@ -10,8 +10,19 @@ OPTIONS: [GRAMMAR] ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False - TAG: REQUIREMENT FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False - TITLE: UID TYPE: String REQUIRED: False diff --git a/docs_extra/Zephyr_requirements.sdoc b/docs_extra/Zephyr_requirements.sdoc index c8dbc572b..f778d7ff4 100644 --- a/docs_extra/Zephyr_requirements.sdoc +++ b/docs_extra/Zephyr_requirements.sdoc @@ -6,6 +6,43 @@ ROOT: True OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATUS + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + - TITLE: RATIONALE + TYPE: String + REQUIRED: False + - TITLE: COMMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] MID: 68e87901205c4b0dbb6a0071479330b5 UID: ZEP-1 diff --git a/strictdoc/backend/excel/import_/excel_to_sdoc_converter.py b/strictdoc/backend/excel/import_/excel_to_sdoc_converter.py index 97927968f..df5a11331 100644 --- a/strictdoc/backend/excel/import_/excel_to_sdoc_converter.py +++ b/strictdoc/backend/excel/import_/excel_to_sdoc_converter.py @@ -215,7 +215,6 @@ def create_requirement( requirement = SDocNode( parent=template_requirement.parent, requirement_type=template_requirement.requirement_type, - mid=None, fields=list(template_requirement.enumerate_fields()), relations=template_requirement.relations, ) diff --git a/strictdoc/backend/reqif/p01_sdoc/reqif_to_sdoc_converter.py b/strictdoc/backend/reqif/p01_sdoc/reqif_to_sdoc_converter.py index 4572d0a28..2a7f5eacf 100644 --- a/strictdoc/backend/reqif/p01_sdoc/reqif_to_sdoc_converter.py +++ b/strictdoc/backend/reqif/p01_sdoc/reqif_to_sdoc_converter.py @@ -382,7 +382,6 @@ def create_section_from_spec_object( node: SDocNode = SDocNode( parent=section, requirement_type="TEXT", - mid=None, fields=[node_field], relations=[], ) @@ -499,16 +498,22 @@ def create_requirement_from_spec_object( spec_object_type.identifier ] ) - + if requirement_mid is not None: + fields.insert( + 0, + SDocNodeField.create_from_string( + None, "MID", requirement_mid, multiline=False + ), + ) requirement = SDocNode( parent=parent_section, requirement_type=grammar_element.tag, - mid=requirement_mid, fields=fields, relations=[], ) requirement.ng_level = level - + for field_ in fields: + field_.parent = requirement if foreign_key_id_or_none is not None: spec_object_parents = reqif_bundle.get_spec_object_parents( spec_object.identifier diff --git a/strictdoc/backend/reqif/p01_sdoc/sdoc_to_reqif_converter.py b/strictdoc/backend/reqif/p01_sdoc/sdoc_to_reqif_converter.py index 7fc6c5222..4c7e0d56d 100644 --- a/strictdoc/backend/reqif/p01_sdoc/sdoc_to_reqif_converter.py +++ b/strictdoc/backend/reqif/p01_sdoc/sdoc_to_reqif_converter.py @@ -465,6 +465,9 @@ def _convert_requirement_to_spec_object( attributes: List[SpecObjectAttribute] = [] for field in requirement.fields_as_parsed: + # The MID field, if exists, is extracted separately as a ReqIF Identifier. + if field.field_name == "MID": + continue grammar_field = grammar_element.fields_map[field.field_name] if isinstance(grammar_field, GrammarElementFieldSingleChoice): data_type_ref = data_types_lookup[field.field_name] diff --git a/strictdoc/backend/sdoc/error_handling.py b/strictdoc/backend/sdoc/error_handling.py index aa5188e4e..4fafe50dd 100644 --- a/strictdoc/backend/sdoc/error_handling.py +++ b/strictdoc/backend/sdoc/error_handling.py @@ -298,6 +298,25 @@ def grammar_reserved_statement_must_be_required( filename=path_to_sdoc_file, ) + @staticmethod + def grammar_element_has_no_mid_field( + grammar_element: GrammarElement, + path_to_sdoc_file: str, + ): + return StrictDocSemanticError( + title=( + f"Grammar element '{grammar_element.tag}' is missing the MID field " + f"which contradicts to the DOCUMENT's ENABLE_MID setting." + ), + hint=( + "Either disable the ENABLE_MID option or ensure that every element has the MID field defined." + ), + example=None, + line=1, + col=1, + filename=path_to_sdoc_file, + ) + @staticmethod def view_references_nonexisting_grammar_element( document: SDocDocument, diff --git a/strictdoc/backend/sdoc/grammar/grammar.py b/strictdoc/backend/sdoc/grammar/grammar.py index ba9fe747d..c7827eab2 100644 --- a/strictdoc/backend/sdoc/grammar/grammar.py +++ b/strictdoc/backend/sdoc/grammar/grammar.py @@ -175,7 +175,6 @@ SDocNode[noskipws]: '[' !'SECTION' !SDocCompositeNodeTagName requirement_type = RequirementType ']' '\n' - ('MID: ' mid = SingleLineString '\n')? fields *= SDocNodeField ( 'RELATIONS:' '\n' @@ -189,6 +188,8 @@ SDocNodeField[noskipws]: ( + field_name = 'MID' ': ' parts+=SingleLineString '\n' + | field_name = 'UID' ': ' parts+=/{REGEX_UID}/ '\n' | field_name = FieldName ':' @@ -211,8 +212,6 @@ SDocCompositeNode[noskipws]: '[COMPOSITE_' requirement_type = RequirementType ']' '\n' - ('MID: ' mid = SingleLineString '\n')? - fields *= SDocNodeField ( 'RELATIONS:' '\n' diff --git a/strictdoc/backend/sdoc/grammar_reader.py b/strictdoc/backend/sdoc/grammar_reader.py index 61c32bd3a..9e72d1092 100644 --- a/strictdoc/backend/sdoc/grammar_reader.py +++ b/strictdoc/backend/sdoc/grammar_reader.py @@ -49,7 +49,7 @@ def read( if not grammar.has_text_element(): grammar.add_element_first( - DocumentGrammar.create_default_text_element() + DocumentGrammar.create_default_text_element(grammar) ) # HACK: diff --git a/strictdoc/backend/sdoc/models/document_grammar.py b/strictdoc/backend/sdoc/models/document_grammar.py index fc9e1c276..c36a30b64 100644 --- a/strictdoc/backend/sdoc/models/document_grammar.py +++ b/strictdoc/backend/sdoc/models/document_grammar.py @@ -201,6 +201,9 @@ def __init__( self.is_default = False + self.ng_line_start: Optional[int] = None + self.ng_col_start: Optional[int] = None + @staticmethod def create_default(parent) -> "DocumentGrammar": text_element: GrammarElement = ( @@ -338,7 +341,7 @@ def update_with_elements(self, elements: List[GrammarElement]): self.elements_by_type = elements_by_type @staticmethod - def create_default_text_element() -> GrammarElement: + def create_default_text_element(parent=None) -> GrammarElement: fields: List[ Union[ GrammarElementFieldString, @@ -360,7 +363,7 @@ def create_default_text_element() -> GrammarElement: ), ] text_element = GrammarElement( - parent=None, tag="TEXT", fields=fields, relations=[] + parent=parent, tag="TEXT", fields=fields, relations=[] ) return text_element diff --git a/strictdoc/backend/sdoc/models/node.py b/strictdoc/backend/sdoc/models/node.py index 6da94d120..30c730210 100644 --- a/strictdoc/backend/sdoc/models/node.py +++ b/strictdoc/backend/sdoc/models/node.py @@ -102,7 +102,6 @@ def __init__( self, parent: Union[SDocDocument, SDocSection, "SDocCompositeNode"], requirement_type: str, - mid: Optional[str], fields: List[SDocNodeField], relations: List[Reference], requirements: Optional[List["SDocNode"]] = None, @@ -156,6 +155,12 @@ def __init__( self.ng_byte_end: Optional[int] = None self.context: SDocNodeContext = SDocNodeContext() + mid: Optional[str] = None + mid_fields: Optional[List[SDocNodeField]] = ordered_fields_lookup.get( + "MID", None + ) + if mid_fields is not None: + mid = mid_fields[0].get_text_value() self.reserved_mid: MID = MID(mid) if mid is not None else MID.create() self.mid_permanent: bool = mid is not None diff --git a/strictdoc/backend/sdoc/models/object_factory.py b/strictdoc/backend/sdoc/models/object_factory.py index d0a227b23..136039cf8 100644 --- a/strictdoc/backend/sdoc/models/object_factory.py +++ b/strictdoc/backend/sdoc/models/object_factory.py @@ -128,7 +128,6 @@ def create_requirement( requirement = SDocNode( parent=parent, requirement_type=requirement_type, - mid=None, fields=fields, relations=[], ) diff --git a/strictdoc/backend/sdoc/models/type_system.py b/strictdoc/backend/sdoc/models/type_system.py index c8049df8b..642022fe1 100644 --- a/strictdoc/backend/sdoc/models/type_system.py +++ b/strictdoc/backend/sdoc/models/type_system.py @@ -6,6 +6,7 @@ class RequirementFieldName: + MID = "MID" UID = "UID" LEVEL = "LEVEL" STATUS = "STATUS" diff --git a/strictdoc/backend/sdoc/processor.py b/strictdoc/backend/sdoc/processor.py index 338e908e1..2cc91c614 100644 --- a/strictdoc/backend/sdoc/processor.py +++ b/strictdoc/backend/sdoc/processor.py @@ -20,7 +20,6 @@ SDocNodeField, ) from strictdoc.backend.sdoc.models.section import SDocSection -from strictdoc.backend.sdoc.validations.sdoc_validator import SDocValidator from strictdoc.helpers.exception import StrictDocException from strictdoc.helpers.textx import preserve_source_location_data @@ -73,7 +72,6 @@ def rewrite_free_text_to_text_node_if_needed( text_node = SDocNode( parent=parent_node, requirement_type="TEXT", - mid=None, fields=fields, relations=[], requirements=None, @@ -122,19 +120,16 @@ def process_document_config(self, document_config: DocumentConfig): self.parse_context.document_config = document_config def process_document_grammar(self, document_grammar: DocumentGrammar): + preserve_source_location_data(document_grammar) if not document_grammar.has_text_element(): document_grammar.add_element_first( - DocumentGrammar.create_default_text_element() + DocumentGrammar.create_default_text_element(document_grammar) ) self.parse_context.document_grammar = document_grammar def process_document_grammar_element(self, grammar_element: GrammarElement): preserve_source_location_data(grammar_element) - SDocValidator.validate_grammar_element( - self.parse_context.path_to_sdoc_file, grammar_element - ) - def process_document_view(self, document_view: DocumentView): self.parse_context.document_view = document_view diff --git a/strictdoc/backend/sdoc/validations/sdoc_validator.py b/strictdoc/backend/sdoc/validations/sdoc_validator.py index daf59619b..299331d9a 100644 --- a/strictdoc/backend/sdoc/validations/sdoc_validator.py +++ b/strictdoc/backend/sdoc/validations/sdoc_validator.py @@ -41,6 +41,7 @@ def validate_document(document: SDocDocument): assert isinstance(document, SDocDocument), document SDocValidator._validate_document_config(document) SDocValidator._validate_document_view(document) + SDocValidator._validate_grammar(document) @staticmethod def validate_grammar_from_file( @@ -51,6 +52,13 @@ def validate_grammar_from_file( path_to_grammar, grammar_element_ ) + @staticmethod + def _validate_grammar(document: SDocDocument): + for grammar_element_ in document.grammar.elements: + SDocValidator.validate_grammar_element( + document.meta.input_doc_full_path, grammar_element_ + ) + @staticmethod def validate_grammar_element( path_to_grammar, grammar_element: GrammarElement @@ -62,6 +70,18 @@ def validate_grammar_element( grammar_element.ng_line_start, grammar_element.ng_col_start, ) + + # GrammarFromFile doesn't have a parent document. + document: Optional[SDocDocument] = grammar_element.parent.parent + if document is not None and document.config.enable_mid: + if ( + grammar_element.tag != "TEXT" + and "MID" not in grammar_element.fields_map + ): + raise StrictDocSemanticError.grammar_element_has_no_mid_field( + grammar_element, + path_to_grammar, + ) content_field: GrammarElementField = grammar_element.fields_map[ grammar_element.content_field[0] ] diff --git a/strictdoc/backend/sdoc/writer.py b/strictdoc/backend/sdoc/writer.py index 0309f5761..d5e527ca8 100644 --- a/strictdoc/backend/sdoc/writer.py +++ b/strictdoc/backend/sdoc/writer.py @@ -395,11 +395,6 @@ def _print_requirement_fields( ): output = "" - if section_content.mid_permanent or document.config.enable_mid: - output += "MID: " - output += section_content.reserved_mid - output += "\n" - element = document.grammar.elements_by_type[ section_content.requirement_type ] @@ -407,6 +402,10 @@ def _print_requirement_fields( for element_field in element.fields: field_name = element_field.title if field_name not in section_content.ordered_fields_lookup: + if field_name == "MID" and document.config.enable_mid: + output += "MID: " + output += section_content.reserved_mid + output += "\n" continue fields = section_content.ordered_fields_lookup[field_name] for field in fields: diff --git a/strictdoc/core/traceability_index_builder.py b/strictdoc/core/traceability_index_builder.py index 5ce6339e0..363adcfae 100644 --- a/strictdoc/core/traceability_index_builder.py +++ b/strictdoc/core/traceability_index_builder.py @@ -289,12 +289,6 @@ def create_from_document_tree( document: SDocDocument for document in document_tree.document_list: - try: - SDocValidator.validate_document(document) - except StrictDocSemanticError as exc: - print(exc.to_print_message()) # noqa: T201 - sys.exit(1) - """ First, resolve all grammars that are imported from grammar files. """ @@ -318,6 +312,12 @@ def create_from_document_tree( # this point. document.grammar.parent = document + try: + SDocValidator.validate_document(document) + except StrictDocSemanticError as exc: + print(exc.to_print_message()) # noqa: T201 + sys.exit(1) + if graph_database.has_link( link_type=GraphLinkType.MID_TO_NODE, lhs_node=document.reserved_mid, diff --git a/strictdoc/export/html/form_objects/requirement_form_object.py b/strictdoc/export/html/form_objects/requirement_form_object.py index cf5173642..650a624d3 100644 --- a/strictdoc/export/html/form_objects/requirement_form_object.py +++ b/strictdoc/export/html/form_objects/requirement_form_object.py @@ -204,7 +204,6 @@ def __init__( requirement_mid: str, document_mid: str, context_document_mid: str, - mid_field: Optional[RequirementFormField], fields: List[RequirementFormField], reference_fields: List[RequirementReferenceFormField], exiting_requirement_uid: Optional[str], @@ -220,7 +219,6 @@ def __init__( self.requirement_mid: str = requirement_mid self.document_mid: str = document_mid self.context_document_mid: str = context_document_mid - self.mid_field: Optional[RequirementFormField] = mid_field fields_dict: dict = defaultdict(list) for field in fields: fields_dict[field.field_name].append(field) @@ -306,26 +304,6 @@ def create_from_request( ) ) - # MID field is handled separately from other fields because it not part - # of any grammar, default or user-provided. - mid_field: Optional[RequirementFormField] = None - if "MID" in requirement_fields: - requirement_field_values = requirement_fields.get("MID", []) - for requirement_field_value in requirement_field_values: - sanitized_field_value: str = sanitize_html_form_field( - requirement_field_value, multiline=False - ) - mid_field: RequirementFormField = ( - RequirementFormField.create_mid_field( - MID(sanitized_field_value) - ) - ) - - # This is where the original requirement MID auto-generated - # for a new requirement by StrictDoc can change because - # a user has provided a new one in the input form. - requirement_mid = sanitized_field_value - assert document.grammar is not None grammar: DocumentGrammar = document.grammar element: GrammarElement = grammar.elements_by_type[element_type] @@ -360,7 +338,6 @@ def create_from_request( requirement_mid=requirement_mid, document_mid=document.reserved_mid, context_document_mid=context_document_mid, - mid_field=mid_field, fields=form_fields, reference_fields=form_ref_fields, exiting_requirement_uid=exiting_requirement_uid, @@ -390,14 +367,9 @@ def create_new( grammar: DocumentGrammar = document.grammar element: GrammarElement = grammar.elements_by_type[element_type] - mid_field: Optional[RequirementFormField] = None - if document.config.enable_mid: - mid_field: RequirementFormField = ( - RequirementFormField.create_mid_field(new_requirement_mid) - ) form_fields: List[RequirementFormField] = [] - fields_names = list(element.fields_map.keys()) + content_field_idx = element.get_multiline_field_index() for field_idx, field_name in enumerate(fields_names): @@ -417,6 +389,13 @@ def create_new( if form_field.field_name == "UID" and next_uid is not None: form_field.field_unescaped_value = next_uid form_field.field_escaped_value = next_uid + elif form_field.field_name == "MID" and document.config.enable_mid: + form_field.field_unescaped_value = ( + new_requirement_mid.get_string_value() + ) + form_field.field_escaped_value = ( + new_requirement_mid.get_string_value() + ) return RequirementFormObject( is_new=True, @@ -424,7 +403,6 @@ def create_new( requirement_mid=new_requirement_mid, document_mid=document.reserved_mid, context_document_mid=context_document_mid, - mid_field=mid_field, fields=form_fields, reference_fields=[], exiting_requirement_uid=None, @@ -447,12 +425,6 @@ def create_from_requirement( requirement.requirement_type ] - mid_field: Optional[RequirementFormField] = None - if document.config.enable_mid: - mid_field: RequirementFormField = ( - RequirementFormField.create_mid_field(requirement.reserved_mid) - ) - grammar_element_relations = element.get_relation_types() form_fields: List[RequirementFormField] = [] @@ -522,7 +494,6 @@ def create_from_requirement( requirement_mid=requirement.reserved_mid, document_mid=document.reserved_mid, context_document_mid=context_document_mid, - mid_field=mid_field, fields=form_fields, reference_fields=form_refs_fields, exiting_requirement_uid=requirement.reserved_uid, @@ -641,21 +612,21 @@ def validate( MID uniqueness check. FIXME: MID uniqueness if a node is updated. """ - if self.is_new and self.mid_field is not None: - existing_node_with_this_mid = ( - traceability_index.get_node_by_mid_weak( - MID(self.mid_field.field_unescaped_value) - ) - ) - if existing_node_with_this_mid is not None: - self.add_error( - "MID", - ( - f"A node with this MID already exists, " - "please select another MID: " - f"{self.mid_field.field_unescaped_value}." - ), + if self.is_new and "MID" in self.fields: + new_node_mid = self.fields["MID"][0].field_unescaped_value + if len(new_node_mid) > 0: + existing_node_with_this_mid = ( + traceability_index.get_node_by_mid_weak(MID(new_node_mid)) ) + if existing_node_with_this_mid is not None: + self.add_error( + "MID", + ( + f"A node with this MID already exists, " + "please select another MID: " + f"{new_node_mid}." + ), + ) """ UID uniqueness check. diff --git a/strictdoc/export/html/templates/components/node_field/meta/index.jinja b/strictdoc/export/html/templates/components/node_field/meta/index.jinja index 24dff340c..d4eae4bad 100644 --- a/strictdoc/export/html/templates/components/node_field/meta/index.jinja +++ b/strictdoc/export/html/templates/components/node_field/meta/index.jinja @@ -1,16 +1,4 @@ {# needs sdoc_entity, see README.txt #} -{% if sdoc_entity.mid_permanent and sdoc_entity.reserved_mid is not none %} - MID: - - {%- with field_content = sdoc_entity.reserved_mid %} - {%- include "components/field/index.jinja" -%} - {%- endwith -%} - -{% endif %} - {%- if sdoc_entity.has_meta -%} {% for meta_field in sdoc_entity.enumerate_meta_fields(skip_multi_lines=True) if view_object.current_view.includes_field(sdoc_entity.requirement_type, meta_field[0]) %} {{ meta_field[0] }}: diff --git a/strictdoc/export/html/templates/screens/document/document/frame_requirement_form.jinja b/strictdoc/export/html/templates/screens/document/document/frame_requirement_form.jinja index 302946357..fec5903e2 100644 --- a/strictdoc/export/html/templates/screens/document/document/frame_requirement_form.jinja +++ b/strictdoc/export/html/templates/screens/document/document/frame_requirement_form.jinja @@ -27,15 +27,6 @@ {% set text_field_row_context = namespace() %} - {% if form_object.mid_field is not none %} - {% set text_field_row_context.errors=form_object.get_errors("MID") %} - {% set text_field_row_context.field = form_object.mid_field %} - {% set text_field_row_context.field_editable = form_object.is_new %} - {% set text_field_row_context.field_type = "singleline" %} - {% set text_field_row_context.reference_mid = form_object.requirement_mid %} - {% include "components/form/row/row_with_text_field.jinja" %} - {% endif %} - {# Single-line #} {%- for field_values_ in form_object.enumerate_fields(multiline=False) -%} {%- for field_ in field_values_ -%} diff --git a/strictdoc/export/spdx/spdx_to_sdoc_converter.py b/strictdoc/export/spdx/spdx_to_sdoc_converter.py index 4c2ab2ee8..f12123a50 100644 --- a/strictdoc/export/spdx/spdx_to_sdoc_converter.py +++ b/strictdoc/export/spdx/spdx_to_sdoc_converter.py @@ -180,7 +180,6 @@ def _convert_document(document: SpdxDocument, sdoc_document, sdoc_parent): requirement = SDocNode( parent=sdoc_parent, requirement_type="SPDX_PACKAGE", - mid=None, fields=[], relations=[], requirements=None, @@ -211,7 +210,6 @@ def _convert_package( requirement = SDocNode( parent=sdoc_parent, requirement_type="SPDX_PACKAGE", - mid=None, fields=[], relations=[], requirements=None, @@ -252,7 +250,6 @@ def _convert_file( requirement = SDocNode( parent=sdoc_parent, requirement_type="SPDX_FILE", - mid=None, fields=fields, relations=[], requirements=None, @@ -303,7 +300,6 @@ def _convert_snippet( requirement = SDocNode( parent=sdoc_parent, requirement_type="SPDX_SNIPPET", - mid=None, fields=fields, relations=[], requirements=None, diff --git a/strictdoc/server/routers/main_router.py b/strictdoc/server/routers/main_router.py index 734ee8801..6dc80d12b 100644 --- a/strictdoc/server/routers/main_router.py +++ b/strictdoc/server/routers/main_router.py @@ -1802,7 +1802,6 @@ def document__add_comment( requirement_mid=requirement_mid, document_mid=document.reserved_mid, context_document_mid=context_document_mid, - mid_field=None, fields=[], reference_fields=[], exiting_requirement_uid=None, @@ -1858,7 +1857,6 @@ def document__add_relation( requirement_mid=requirement_mid, document_mid=document_mid, context_document_mid=context_document_mid, - mid_field=None, fields=[], reference_fields=[], exiting_requirement_uid=None, diff --git a/tests/end2end/screens/document/_cross_cutting/text_nodes/update_text_node/expected_output/document.sdoc b/tests/end2end/screens/document/_cross_cutting/text_nodes/update_text_node/expected_output/document.sdoc index 28d7d21aa..e701b1b76 100644 --- a/tests/end2end/screens/document/_cross_cutting/text_nodes/update_text_node/expected_output/document.sdoc +++ b/tests/end2end/screens/document/_cross_cutting/text_nodes/update_text_node/expected_output/document.sdoc @@ -5,7 +5,6 @@ TITLE: Document 1 TITLE: Section title [TEXT] -MID: xyz567 UID: TEXT-NODE-1 STATEMENT: >>> Modified text statement. diff --git a/tests/end2end/screens/document/_cross_cutting/text_nodes/update_text_node/input/document.sdoc b/tests/end2end/screens/document/_cross_cutting/text_nodes/update_text_node/input/document.sdoc index d69a31ef8..21f8e223e 100644 --- a/tests/end2end/screens/document/_cross_cutting/text_nodes/update_text_node/input/document.sdoc +++ b/tests/end2end/screens/document/_cross_cutting/text_nodes/update_text_node/input/document.sdoc @@ -5,7 +5,6 @@ TITLE: Document 1 TITLE: Section title [TEXT] -MID: xyz567 UID: TEXT-NODE-1 STATEMENT: >>> Text statement. diff --git a/tests/end2end/screens/document/_cross_cutting/text_nodes/view_document_with_text_node/document.sdoc b/tests/end2end/screens/document/_cross_cutting/text_nodes/view_document_with_text_node/document.sdoc index 4d7ca9b70..f70520fe2 100644 --- a/tests/end2end/screens/document/_cross_cutting/text_nodes/view_document_with_text_node/document.sdoc +++ b/tests/end2end/screens/document/_cross_cutting/text_nodes/view_document_with_text_node/document.sdoc @@ -9,14 +9,12 @@ Document free text. TITLE: Section title [TEXT] -MID: xyz567 UID: TEXT-NODE-1 STATEMENT: >>> Text statement. <<< [REQUIREMENT] -MID: abcdef123456 TITLE: Requirement title STATEMENT: >>> Requirement statement. diff --git a/tests/end2end/screens/document/_cross_cutting/text_nodes/view_document_with_text_node/test_case.py b/tests/end2end/screens/document/_cross_cutting/text_nodes/view_document_with_text_node/test_case.py index 301c20cac..e912b68f7 100644 --- a/tests/end2end/screens/document/_cross_cutting/text_nodes/view_document_with_text_node/test_case.py +++ b/tests/end2end/screens/document/_cross_cutting/text_nodes/view_document_with_text_node/test_case.py @@ -28,4 +28,3 @@ def test(self): screen_document.assert_not_empty_document() screen_document.assert_text("Text statement.") - screen_document.assert_text("abcdef123456") diff --git a/tests/end2end/screens/document/create_requirement/_mid/_validations/create_requirement__mid__create_requirement_with_duplicate_mid/expected_output/document.sdoc b/tests/end2end/screens/document/create_requirement/_mid/_validations/create_requirement__mid__create_requirement_with_duplicate_mid/expected_output/document.sdoc index 22907de10..891d3900d 100644 --- a/tests/end2end/screens/document/create_requirement/_mid/_validations/create_requirement__mid__create_requirement_with_duplicate_mid/expected_output/document.sdoc +++ b/tests/end2end/screens/document/create_requirement/_mid/_validations/create_requirement__mid__create_requirement_with_duplicate_mid/expected_output/document.sdoc @@ -4,6 +4,37 @@ TITLE: Document 1 OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] MID: ec0c9dfe29554bfda007fe072120c2c4 UID: REQ-1 @@ -11,6 +42,3 @@ TITLE: Requirement title #1 STATEMENT: >>> Requirement statement #1. <<< -RATIONALE: >>> -Requirement rationale #1. -<<< diff --git a/tests/end2end/screens/document/create_requirement/_mid/_validations/create_requirement__mid__create_requirement_with_duplicate_mid/input/document.sdoc b/tests/end2end/screens/document/create_requirement/_mid/_validations/create_requirement__mid__create_requirement_with_duplicate_mid/input/document.sdoc index 22907de10..891d3900d 100644 --- a/tests/end2end/screens/document/create_requirement/_mid/_validations/create_requirement__mid__create_requirement_with_duplicate_mid/input/document.sdoc +++ b/tests/end2end/screens/document/create_requirement/_mid/_validations/create_requirement__mid__create_requirement_with_duplicate_mid/input/document.sdoc @@ -4,6 +4,37 @@ TITLE: Document 1 OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] MID: ec0c9dfe29554bfda007fe072120c2c4 UID: REQ-1 @@ -11,6 +42,3 @@ TITLE: Requirement title #1 STATEMENT: >>> Requirement statement #1. <<< -RATIONALE: >>> -Requirement rationale #1. -<<< diff --git a/tests/end2end/screens/document/create_requirement/_mid/_validations/create_requirement__mid__create_requirement_with_duplicate_mid/test_case.py b/tests/end2end/screens/document/create_requirement/_mid/_validations/create_requirement__mid__create_requirement_with_duplicate_mid/test_case.py index 9e2244357..def238bdd 100644 --- a/tests/end2end/screens/document/create_requirement/_mid/_validations/create_requirement__mid__create_requirement_with_duplicate_mid/test_case.py +++ b/tests/end2end/screens/document/create_requirement/_mid/_validations/create_requirement__mid__create_requirement_with_duplicate_mid/test_case.py @@ -29,7 +29,7 @@ def test(self): screen_document.assert_header_document_title("Document 1") # Requirement 1 - requirement1_node = screen_document.get_requirement(1) + requirement1_node = screen_document.get_node(1) requirement1_node_menu = requirement1_node.do_open_node_menu() form_edit_requirement: Form_EditRequirement = ( requirement1_node_menu.do_node_add_requirement_below() @@ -43,9 +43,6 @@ def test(self): form_edit_requirement.do_fill_in_field_statement( "Requirement statement #2." ) - form_edit_requirement.do_fill_in_field_rationale( - "Requirement rationale #2." - ) form_edit_requirement.do_form_submit_and_catch_error( "A node with this MID already exists, " "please select another MID: ec0c9dfe29554bfda007fe072120c2c4." diff --git a/tests/end2end/screens/document/create_requirement/_mid/create_requirement__mid__create_requirement_with_mid_auto_generated/input/document.sdoc b/tests/end2end/screens/document/create_requirement/_mid/create_requirement__mid__create_requirement_with_mid_auto_generated/input/document.sdoc index a25720e14..6a3f37b29 100644 --- a/tests/end2end/screens/document/create_requirement/_mid/create_requirement__mid__create_requirement_with_mid_auto_generated/input/document.sdoc +++ b/tests/end2end/screens/document/create_requirement/_mid/create_requirement__mid__create_requirement_with_mid_auto_generated/input/document.sdoc @@ -2,3 +2,34 @@ TITLE: Document 1 OPTIONS: ENABLE_MID: True + +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File diff --git a/tests/end2end/screens/document/create_requirement/_mid/create_requirement__mid__create_requirement_with_mid_auto_generated/test_case.py b/tests/end2end/screens/document/create_requirement/_mid/create_requirement__mid__create_requirement_with_mid_auto_generated/test_case.py index 6a88dcf41..567e6f478 100644 --- a/tests/end2end/screens/document/create_requirement/_mid/create_requirement__mid__create_requirement_with_mid_auto_generated/test_case.py +++ b/tests/end2end/screens/document/create_requirement/_mid/create_requirement__mid__create_requirement_with_mid_auto_generated/test_case.py @@ -39,15 +39,11 @@ def test(self): form_edit_requirement.do_fill_in_field_statement( "Requirement statement #1." ) - form_edit_requirement.do_fill_in_field_rationale( - "Requirement rationale #1." - ) form_edit_requirement.do_form_submit() # Expected for Requirement 1: - requirement_1 = screen_document.get_requirement() - + requirement_1 = screen_document.get_node() requirement_1.assert_requirement_has_mid() # FIXME diff --git a/tests/end2end/screens/document/create_requirement/_mid/update_requirement__mid__update_requirement_preserves_mid/expected_output/document.sdoc b/tests/end2end/screens/document/create_requirement/_mid/update_requirement__mid__update_requirement_preserves_mid/expected_output/document.sdoc new file mode 100644 index 000000000..4465f88fa --- /dev/null +++ b/tests/end2end/screens/document/create_requirement/_mid/update_requirement__mid__update_requirement_preserves_mid/expected_output/document.sdoc @@ -0,0 +1,43 @@ +[DOCUMENT] +MID: 6c85e9531ebd4764a52c6fb339cad78a +TITLE: Document 1 +OPTIONS: + ENABLE_MID: True + +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + +[REQUIREMENT] +MID: ABCD1234 +TITLE: Requirement title #1 +STATEMENT: >>> +MODIFIED requirement statement #1. +<<< diff --git a/tests/end2end/screens/document/create_requirement/_mid/update_requirement__mid__update_requirement_preserves_mid/input/document.sdoc b/tests/end2end/screens/document/create_requirement/_mid/update_requirement__mid__update_requirement_preserves_mid/input/document.sdoc new file mode 100644 index 000000000..d29ea9a09 --- /dev/null +++ b/tests/end2end/screens/document/create_requirement/_mid/update_requirement__mid__update_requirement_preserves_mid/input/document.sdoc @@ -0,0 +1,40 @@ +[DOCUMENT] +MID: 6c85e9531ebd4764a52c6fb339cad78a +TITLE: Document 1 +OPTIONS: + ENABLE_MID: True + +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + +[REQUIREMENT] +MID: ABCD1234 +STATEMENT: System A shall do B. diff --git a/tests/end2end/screens/document/create_requirement/_mid/update_requirement__mid__update_requirement_preserves_mid/test_case.py b/tests/end2end/screens/document/create_requirement/_mid/update_requirement__mid__update_requirement_preserves_mid/test_case.py new file mode 100644 index 000000000..c8dffd2f3 --- /dev/null +++ b/tests/end2end/screens/document/create_requirement/_mid/update_requirement__mid__update_requirement_preserves_mid/test_case.py @@ -0,0 +1,47 @@ +from tests.end2end.e2e_case import E2ECase +from tests.end2end.end2end_test_setup import End2EndTestSetup +from tests.end2end.helpers.screens.document.form_edit_requirement import ( + Form_EditRequirement, +) +from tests.end2end.helpers.screens.project_index.screen_project_index import ( + Screen_ProjectIndex, +) +from tests.end2end.server import SDocTestServer + + +class Test(E2ECase): + def test(self): + test_setup = End2EndTestSetup(path_to_test_file=__file__) + + with SDocTestServer( + input_path=test_setup.path_to_sandbox + ) as test_server: + self.open(test_server.get_host_and_port()) + + screen_project_index = Screen_ProjectIndex(self) + + screen_project_index.assert_on_screen() + screen_project_index.assert_contains_document("Document 1") + + screen_document = screen_project_index.do_click_on_first_document() + + screen_document.assert_on_screen_document() + screen_document.assert_header_document_title("Document 1") + + # Requirement 1 + requirement_node = screen_document.get_node() + form_edit_requirement: Form_EditRequirement = ( + requirement_node.do_open_form_edit_requirement() + ) + + form_edit_requirement.do_fill_in_field_title("Requirement title #1") + form_edit_requirement.do_fill_in_field_statement( + "MODIFIED requirement statement #1." + ) + form_edit_requirement.do_form_submit() + + # Expected for Requirement 1: + requirement_1 = screen_document.get_node() + requirement_1.assert_requirement_has_mid() + + assert test_setup.compare_sandbox_and_expected_output() diff --git a/tests/end2end/screens/document/view_document/_grammar_from_file/view_document_with_grammar_from_file/grammar.sgra b/tests/end2end/screens/document/view_document/_grammar_from_file/view_document_with_grammar_from_file/grammar.sgra index d8ba85cf9..9e68cdd6e 100644 --- a/tests/end2end/screens/document/view_document/_grammar_from_file/view_document_with_grammar_from_file/grammar.sgra +++ b/tests/end2end/screens/document/view_document/_grammar_from_file/view_document_with_grammar_from_file/grammar.sgra @@ -2,6 +2,9 @@ ELEMENTS: - TAG: REQUIREMENT FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: True - TITLE: TITLE TYPE: String REQUIRED: True diff --git a/tests/end2end/screens/document/view_document/view_document_with_one_requirement/document.sdoc b/tests/end2end/screens/document/view_document/view_document_with_one_requirement/document.sdoc index a27354dbd..6e584a734 100644 --- a/tests/end2end/screens/document/view_document/view_document_with_one_requirement/document.sdoc +++ b/tests/end2end/screens/document/view_document/view_document_with_one_requirement/document.sdoc @@ -1,6 +1,20 @@ [DOCUMENT] TITLE: Document 1 +[GRAMMAR] +ELEMENTS: +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: True + - TITLE: TITLE + TYPE: String + REQUIRED: True + - TITLE: STATEMENT + TYPE: String + REQUIRED: True + [REQUIREMENT] MID: abcdef123456 TITLE: Requirement title diff --git a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/01_cli_option/sample.sdoc b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/01_cli_option/sample.sdoc index 53a7a4013..cc1a3c2bc 100644 --- a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/01_cli_option/sample.sdoc +++ b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/01_cli_option/sample.sdoc @@ -8,6 +8,9 @@ OPTIONS: ELEMENTS: - TAG: REQUIREMENT FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False - TITLE: UID TYPE: String REQUIRED: False diff --git a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/02_toml_option/sample.sdoc b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/02_toml_option/sample.sdoc index 53a7a4013..cc1a3c2bc 100644 --- a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/02_toml_option/sample.sdoc +++ b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/02_toml_option/sample.sdoc @@ -8,6 +8,9 @@ OPTIONS: ELEMENTS: - TAG: REQUIREMENT FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False - TITLE: UID TYPE: String REQUIRED: False diff --git a/tests/integration/commands/bypass/40_generate_mid/input.sdoc b/tests/integration/commands/bypass/40_generate_mid/input.sdoc index b47c1e57c..36a4c6597 100644 --- a/tests/integration/commands/bypass/40_generate_mid/input.sdoc +++ b/tests/integration/commands/bypass/40_generate_mid/input.sdoc @@ -3,6 +3,23 @@ TITLE: Hello world doc OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + [SECTION] TITLE: Section 1 diff --git a/tests/integration/commands/export/json/01_basic_json_export/input1.sdoc b/tests/integration/commands/export/json/01_basic_json_export/input1.sdoc index 4b6cde3f2..14c489df2 100644 --- a/tests/integration/commands/export/json/01_basic_json_export/input1.sdoc +++ b/tests/integration/commands/export/json/01_basic_json_export/input1.sdoc @@ -4,6 +4,26 @@ TITLE: Dummy Software Requirements Specification #1 OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] MID: c165cc52af20417e9199e30a4e17f138 UID: REQ-1 diff --git a/tests/integration/commands/export/json/01_basic_json_export/input2.sdoc b/tests/integration/commands/export/json/01_basic_json_export/input2.sdoc index e4df7f7e3..e1ed1209b 100644 --- a/tests/integration/commands/export/json/01_basic_json_export/input2.sdoc +++ b/tests/integration/commands/export/json/01_basic_json_export/input2.sdoc @@ -4,6 +4,26 @@ TITLE: Dummy Software Requirements Specification #2 OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] MID: 95e3198bbbdf44d691daa869efc79323 UID: LREQ-1 diff --git a/tests/integration/commands/export/spdx/01_minimal_document_mid_enabled/input1.sdoc b/tests/integration/commands/export/spdx/01_minimal_document_mid_enabled/input1.sdoc index 4b6cde3f2..14c489df2 100644 --- a/tests/integration/commands/export/spdx/01_minimal_document_mid_enabled/input1.sdoc +++ b/tests/integration/commands/export/spdx/01_minimal_document_mid_enabled/input1.sdoc @@ -4,6 +4,26 @@ TITLE: Dummy Software Requirements Specification #1 OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] MID: c165cc52af20417e9199e30a4e17f138 UID: REQ-1 diff --git a/tests/integration/commands/export/spdx/01_minimal_document_mid_enabled/input2.sdoc b/tests/integration/commands/export/spdx/01_minimal_document_mid_enabled/input2.sdoc index e4df7f7e3..e1ed1209b 100644 --- a/tests/integration/commands/export/spdx/01_minimal_document_mid_enabled/input2.sdoc +++ b/tests/integration/commands/export/spdx/01_minimal_document_mid_enabled/input2.sdoc @@ -4,6 +4,26 @@ TITLE: Dummy Software Requirements Specification #2 OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] MID: 95e3198bbbdf44d691daa869efc79323 UID: LREQ-1 diff --git a/tests/integration/commands/manage/auto-uid/_cross_cutting/01_issue_1630_autouid_must_preserve_relations/input.sdoc b/tests/integration/commands/manage/auto-uid/_cross_cutting/01_issue_1630_autouid_must_preserve_relations/input.sdoc index 9acddc80c..6abcde453 100644 --- a/tests/integration/commands/manage/auto-uid/_cross_cutting/01_issue_1630_autouid_must_preserve_relations/input.sdoc +++ b/tests/integration/commands/manage/auto-uid/_cross_cutting/01_issue_1630_autouid_must_preserve_relations/input.sdoc @@ -14,6 +14,9 @@ OPTIONS: ELEMENTS: - TAG: REQUIREMENT FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False - TITLE: UID TYPE: String REQUIRED: False diff --git a/tests/integration/features/diff/_mid_match/01__mid_match__requirements__from_requirement_to_requirement_no_uid/lhs/input.sdoc b/tests/integration/features/diff/_mid_match/01__mid_match__requirements__from_requirement_to_requirement_no_uid/lhs/input.sdoc index 9bdc0674f..9c0ef896c 100644 --- a/tests/integration/features/diff/_mid_match/01__mid_match__requirements__from_requirement_to_requirement_no_uid/lhs/input.sdoc +++ b/tests/integration/features/diff/_mid_match/01__mid_match__requirements__from_requirement_to_requirement_no_uid/lhs/input.sdoc @@ -1,6 +1,26 @@ [DOCUMENT] TITLE: Hello world doc +[GRAMMAR] +ELEMENTS: +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] MID: ABCD0123 TITLE: Requirement #1 diff --git a/tests/integration/features/diff/_mid_match/01__mid_match__requirements__from_requirement_to_requirement_no_uid/rhs/input.sdoc b/tests/integration/features/diff/_mid_match/01__mid_match__requirements__from_requirement_to_requirement_no_uid/rhs/input.sdoc index d65cd32da..bfb521777 100644 --- a/tests/integration/features/diff/_mid_match/01__mid_match__requirements__from_requirement_to_requirement_no_uid/rhs/input.sdoc +++ b/tests/integration/features/diff/_mid_match/01__mid_match__requirements__from_requirement_to_requirement_no_uid/rhs/input.sdoc @@ -1,6 +1,26 @@ [DOCUMENT] TITLE: Hello world doc +[GRAMMAR] +ELEMENTS: +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] MID: ABCD0123 TITLE: Modified title diff --git a/tests/integration/features/document_grammar/validation/07_grammar_missing_reserved_statement_field/test.itest b/tests/integration/features/document_grammar/validation/07_grammar_missing_reserved_statement_field/test.itest index 0519fbd8b..f6b569487 100644 --- a/tests/integration/features/document_grammar/validation/07_grammar_missing_reserved_statement_field/test.itest +++ b/tests/integration/features/document_grammar/validation/07_grammar_missing_reserved_statement_field/test.itest @@ -1,6 +1,6 @@ RUN: %expect_exit 1 %strictdoc export %S --output-dir Output/ | filecheck %s --dump-input=fail +CHECK: error: could not parse file: {{.*}}input.sdoc. CHECK: Semantic error: Grammar element 'REQUIREMENT' is missing a reserved content field declaration, one of {STATEMENT, DESCRIPTION, CONTENT}. CHECK: Location: {{.*}}input.sdoc:6:1 CHECK: Hint: A content field plays a key role in StrictDoc's HTML user interface as well as in the other export formats. It is a reserved field that any grammar element must have. -CHECK: error: Parallelizer: One of the child processes has exited prematurely. diff --git a/tests/integration/features/document_grammar/validation/08_grammar_reserved_statement_field_must_be_declared_REQUIRED_True/test.itest b/tests/integration/features/document_grammar/validation/08_grammar_reserved_statement_field_must_be_declared_REQUIRED_True/test.itest index f37adbe8b..0564725ac 100644 --- a/tests/integration/features/document_grammar/validation/08_grammar_reserved_statement_field_must_be_declared_REQUIRED_True/test.itest +++ b/tests/integration/features/document_grammar/validation/08_grammar_reserved_statement_field_must_be_declared_REQUIRED_True/test.itest @@ -1,6 +1,6 @@ RUN: %expect_exit 1 %strictdoc export %S --output-dir Output/ | filecheck %s --dump-input=fail +CHECK: error: could not parse file: {{.*}}input.sdoc. CHECK: Semantic error: Grammar element 'REQUIREMENT's DESCRIPTION field must be declared as 'REQUIRED: True'. CHECK: Location: {{.*}}input.sdoc:6:1 CHECK: Hint: A content field plays a key role in StrictDoc's HTML user interface as well as in the other export formats. It is a reserved field that any grammar element must have with 'REQUIRED: True'. -CHECK: error: Parallelizer: One of the child processes has exited prematurely. diff --git a/tests/integration/features/document_grammar/validation/09_ENABLE_MID_enabled_but_missing_MID_field/input.sdoc b/tests/integration/features/document_grammar/validation/09_ENABLE_MID_enabled_but_missing_MID_field/input.sdoc new file mode 100644 index 000000000..b47c1e57c --- /dev/null +++ b/tests/integration/features/document_grammar/validation/09_ENABLE_MID_enabled_but_missing_MID_field/input.sdoc @@ -0,0 +1,15 @@ +[DOCUMENT] +TITLE: Hello world doc +OPTIONS: + ENABLE_MID: True + +[SECTION] +TITLE: Section 1 + +[REQUIREMENT] +TITLE: Req-1 + +[REQUIREMENT] +TITLE: Req-2 + +[/SECTION] diff --git a/tests/integration/features/document_grammar/validation/09_ENABLE_MID_enabled_but_missing_MID_field/test.itest b/tests/integration/features/document_grammar/validation/09_ENABLE_MID_enabled_but_missing_MID_field/test.itest new file mode 100644 index 000000000..cfbe87957 --- /dev/null +++ b/tests/integration/features/document_grammar/validation/09_ENABLE_MID_enabled_but_missing_MID_field/test.itest @@ -0,0 +1,6 @@ +RUN: %expect_exit 1 %strictdoc export %S --output-dir Output/ | filecheck %s --dump-input=fail + +CHECK: error: could not parse file: {{.*}}input.sdoc. +CHECK: Semantic error: Grammar element 'REQUIREMENT' is missing the MID field which contradicts to the DOCUMENT's ENABLE_MID setting. +CHECK: Location: {{.*}}input.sdoc:1:1 +CHECK: Hint: Either disable the ENABLE_MID option or ensure that every element has the MID field defined. diff --git a/tests/integration/features/html2pdf/02_three_top_level_requirements/input.sdoc b/tests/integration/features/html2pdf/02_three_top_level_requirements/input.sdoc index 666c2de94..0e43e1c54 100644 --- a/tests/integration/features/html2pdf/02_three_top_level_requirements/input.sdoc +++ b/tests/integration/features/html2pdf/02_three_top_level_requirements/input.sdoc @@ -4,6 +4,37 @@ TITLE: Dummy Software Requirements Specification #1 OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] MID: c165cc52af20417e9199e30a4e17f138 UID: REQ-1 diff --git a/tests/integration/features/html2pdf/02_three_top_level_requirements/nested/input2.sdoc b/tests/integration/features/html2pdf/02_three_top_level_requirements/nested/input2.sdoc index cfb0e235f..888807daf 100644 --- a/tests/integration/features/html2pdf/02_three_top_level_requirements/nested/input2.sdoc +++ b/tests/integration/features/html2pdf/02_three_top_level_requirements/nested/input2.sdoc @@ -1,6 +1,37 @@ [DOCUMENT] TITLE: Dummy Software Requirements Specification #2 +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] TITLE: Dummy high-level requirement #1 STATEMENT: System ABC shall do 1. diff --git a/tests/integration/features/html2pdf/02_three_top_level_requirements/nested/subnested/input3.sdoc b/tests/integration/features/html2pdf/02_three_top_level_requirements/nested/subnested/input3.sdoc index 22f17211f..7cb60db9f 100644 --- a/tests/integration/features/html2pdf/02_three_top_level_requirements/nested/subnested/input3.sdoc +++ b/tests/integration/features/html2pdf/02_three_top_level_requirements/nested/subnested/input3.sdoc @@ -3,6 +3,37 @@ TITLE: Dummy Software Requirements Specification #3 OPTIONS: ENABLE_MID: True +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] TITLE: Dummy high-level requirement #1 STATEMENT: System ABC shall do 1. diff --git a/tests/integration/features/machine_identifiers_MID/_validations/03_requirement_mid_must_be_unique/input.sdoc b/tests/integration/features/machine_identifiers_MID/_validations/03_requirement_mid_must_be_unique/input.sdoc index 2b8cebb7a..eba04cb87 100644 --- a/tests/integration/features/machine_identifiers_MID/_validations/03_requirement_mid_must_be_unique/input.sdoc +++ b/tests/integration/features/machine_identifiers_MID/_validations/03_requirement_mid_must_be_unique/input.sdoc @@ -1,6 +1,26 @@ [DOCUMENT] TITLE: Doc 1 +[GRAMMAR] +ELEMENTS: +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] MID: ABC0123 TITLE: Foo diff --git a/tests/integration/features/machine_identifiers_MID/_validations/03_requirement_mid_must_be_unique/input2.sdoc b/tests/integration/features/machine_identifiers_MID/_validations/03_requirement_mid_must_be_unique/input2.sdoc index 62d3807ee..db138aa08 100644 --- a/tests/integration/features/machine_identifiers_MID/_validations/03_requirement_mid_must_be_unique/input2.sdoc +++ b/tests/integration/features/machine_identifiers_MID/_validations/03_requirement_mid_must_be_unique/input2.sdoc @@ -1,6 +1,26 @@ [DOCUMENT] TITLE: Doc 2 +[GRAMMAR] +ELEMENTS: +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + [REQUIREMENT] MID: ABC0123 TITLE: Foo diff --git a/tests/integration/scripting_examples/reqif/02_user_provided_example/script.py b/tests/integration/scripting_examples/reqif/02_user_provided_example/script.py index dee562d07..3069b0ba3 100644 --- a/tests/integration/scripting_examples/reqif/02_user_provided_example/script.py +++ b/tests/integration/scripting_examples/reqif/02_user_provided_example/script.py @@ -485,7 +485,7 @@ def create_requirement_from_spec_object( ) ) requirement = SDocNode( - parent=parent_section, requirement_type="REQUIREMENT", mid=None, fields=fields, relations=[] + parent=parent_section, requirement_type="REQUIREMENT", fields=fields, relations=[] ) if foreign_key_id_or_none is not None: diff --git a/tests/unit/strictdoc/backend/sdoc/test_dsl_passthrough.py b/tests/unit/strictdoc/backend/sdoc/test_dsl_passthrough.py index 535057843..95c048f68 100644 --- a/tests/unit/strictdoc/backend/sdoc/test_dsl_passthrough.py +++ b/tests/unit/strictdoc/backend/sdoc/test_dsl_passthrough.py @@ -149,6 +149,25 @@ def test_020_requirement_mid(): [DOCUMENT] TITLE: Test Doc +[GRAMMAR] +ELEMENTS: +- TAG: TEXT + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + FIELDS: + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: STATEMENT + TYPE: String + REQUIRED: False + [REQUIREMENT] MID: abcdef123456 STATEMENT: >>> @@ -165,7 +184,6 @@ def test_020_requirement_mid(): writer = SDWriter() output = writer.write(document) - assert input_sdoc == output