diff --git a/strictdoc/backend/excel/import_/excel_to_sdoc_converter.py b/strictdoc/backend/excel/import_/excel_to_sdoc_converter.py index ca8c3096c..a83cc544e 100644 --- a/strictdoc/backend/excel/import_/excel_to_sdoc_converter.py +++ b/strictdoc/backend/excel/import_/excel_to_sdoc_converter.py @@ -177,7 +177,9 @@ def create_requirement( comments=comments, ) if parent_uid is not None: - reference = ParentReqReference(template_requirement, parent_uid) + reference = ParentReqReference( + template_requirement, parent_uid, relation_uid=None + ) requirement_field = RequirementField( parent=template_requirement, 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 da087742e..b92b769fa 100644 --- a/strictdoc/backend/reqif/p01_sdoc/reqif_to_sdoc_converter.py +++ b/strictdoc/backend/reqif/p01_sdoc/reqif_to_sdoc_converter.py @@ -432,6 +432,7 @@ def create_requirement_from_spec_object( parent_spec_object_parent.attribute_map[ foreign_key_id_or_none ].value, + relation_uid=None, ) ) if len(parent_refs) > 0: diff --git a/strictdoc/backend/reqif/p11_polarion/reqif_to_sdoc_converter.py b/strictdoc/backend/reqif/p11_polarion/reqif_to_sdoc_converter.py index 21f6ccdaa..ed555767d 100644 --- a/strictdoc/backend/reqif/p11_polarion/reqif_to_sdoc_converter.py +++ b/strictdoc/backend/reqif/p11_polarion/reqif_to_sdoc_converter.py @@ -442,6 +442,7 @@ def _p11_create_requirement_from_spec_object( parent_spec_object_parent.attribute_map[ foreign_key_id_or_none ].value, + relation_uid=None, ) ) if len(parent_refs) > 0: diff --git a/strictdoc/backend/sdoc/grammar/type_system.py b/strictdoc/backend/sdoc/grammar/type_system.py index 4071337ff..2f3ac60ea 100644 --- a/strictdoc/backend/sdoc/grammar/type_system.py +++ b/strictdoc/backend/sdoc/grammar/type_system.py @@ -28,6 +28,7 @@ ParentReqReference[noskipws]: '- TYPE: Parent' '\n' ' VALUE: ' ref_uid = /.*$/ '\n' + (' RELATION: ' relation_uid = /.+$/ '\n')? ; ChildReqReference[noskipws]: diff --git a/strictdoc/backend/sdoc/models/reference.py b/strictdoc/backend/sdoc/models/reference.py index 6f5155163..81f0dc241 100644 --- a/strictdoc/backend/sdoc/models/reference.py +++ b/strictdoc/backend/sdoc/models/reference.py @@ -30,9 +30,17 @@ def get_file_format(self) -> Optional[str]: @auto_described class ParentReqReference(Reference): - def __init__(self, parent, ref_uid): + def __init__(self, parent, ref_uid: str, relation_uid: Optional[str]): super().__init__(ReferenceType.PARENT, parent) - self.ref_uid = ref_uid + self.ref_uid: str = ref_uid + # When RELATION: field is not provided for a parent reference, the + # textX still passes relation_uid as an empty string (instead of None + # as one could expect). + self.relation_uid: Optional[str] = ( + relation_uid + if relation_uid is not None and len(relation_uid) > 0 + else None + ) @auto_described diff --git a/strictdoc/backend/sdoc/writer.py b/strictdoc/backend/sdoc/writer.py index f9bb79d73..9b8512237 100644 --- a/strictdoc/backend/sdoc/writer.py +++ b/strictdoc/backend/sdoc/writer.py @@ -238,6 +238,10 @@ def _print_requirement_fields( output += " VALUE: " output += ref.ref_uid output += "\n" + if reference.relation_uid is not None: + output += " RELATION: " + output += ref.relation_uid + output += "\n" elif field.field_value is not None: if len(field.field_value) > 0: diff --git a/strictdoc/server/routers/main_router.py b/strictdoc/server/routers/main_router.py index 2694c8d07..19ac81c70 100644 --- a/strictdoc/server/routers/main_router.py +++ b/strictdoc/server/routers/main_router.py @@ -1035,7 +1035,9 @@ def __init__(self): for reference_field in form_object.reference_fields: ref_uid = reference_field.field_value references.append( - ParentReqReference(parent=requirement, ref_uid=ref_uid) + ParentReqReference( + parent=requirement, ref_uid=ref_uid, relation_uid=None + ) ) if len(references) > 0: requirement.ordered_fields_lookup[RequirementFieldName.REFS] = [ diff --git a/tests/unit/helpers/test_document_builder.py b/tests/unit/helpers/test_document_builder.py index 05c4c1d1a..6b83e667a 100644 --- a/tests/unit/helpers/test_document_builder.py +++ b/tests/unit/helpers/test_document_builder.py @@ -46,7 +46,9 @@ def add_requirement_parent(self, req_id, parent_req_id): ) assert requirement - reference = ParentReqReference(requirement, parent_req_id) + reference = ParentReqReference( + requirement, parent_req_id, relation_uid=None + ) requirement.references.append(reference) def build(self): diff --git a/tests/unit/strictdoc/backend/sdoc/test_dsl_passthrough.py b/tests/unit/strictdoc/backend/sdoc/test_dsl_passthrough.py index a901842fa..42546cb6a 100644 --- a/tests/unit/strictdoc/backend/sdoc/test_dsl_passthrough.py +++ b/tests/unit/strictdoc/backend/sdoc/test_dsl_passthrough.py @@ -151,6 +151,32 @@ def test_010_multiple_sections(): assert input_sdoc == output +def test_020_parent_ref_with_relation(): + input_sdoc = """ +[DOCUMENT] +TITLE: Test Doc + +[REQUIREMENT] +REFS: +- TYPE: Parent + VALUE: ID-001 + RELATION: Refines +STATEMENT: >>> +This is a statement. +<<< +""".lstrip() + + reader = SDReader() + + document = reader.read(input_sdoc) + assert isinstance(document, Document) + + writer = SDWriter() + output = writer.write(document) + + assert input_sdoc == output + + def test_030_multiline_statement(): input_sdoc = """ [DOCUMENT]