From a679cc1b517ebd8e4715f1387e5748583faeb799 Mon Sep 17 00:00:00 2001 From: Stanislav Pankevich Date: Wed, 8 Feb 2023 18:50:56 +0100 Subject: [PATCH 1/3] ReqIFSpecHierarchy: split init parameters into mandatory/optional --- reqif/models/reqif_spec_hierarchy.py | 39 +++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/reqif/models/reqif_spec_hierarchy.py b/reqif/models/reqif_spec_hierarchy.py index e23169e..fe4677a 100644 --- a/reqif/models/reqif_spec_hierarchy.py +++ b/reqif/models/reqif_spec_hierarchy.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List, Optional, Any from reqif.helpers.debug import auto_described @@ -7,34 +7,37 @@ class ReqIFSpecHierarchy: # pylint: disable=too-many-instance-attributes def __init__( # pylint: disable=too-many-arguments self, - xml_node, - is_self_closed: bool, + *, identifier: str, - last_change: Optional[str], - long_name: Optional[str], - editable: Optional[bool], spec_object: str, - children: Optional[List], - ref_then_children_order: bool, level: int, + children: Optional[List] = None, + long_name: Optional[str] = None, + ref_then_children_order: bool = True, + last_change: Optional[str] = None, + editable: Optional[bool] = False, + is_self_closed: bool = True, + xml_node: Optional[Any] = None, ): assert level >= 0 - self.xml_node = xml_node - self.is_self_closed = is_self_closed - self.identifier = identifier - self.last_change: Optional[str] = last_change - self.long_name: Optional[str] = long_name - self.editable: Optional[bool] = editable - self.spec_object = spec_object - self.children: Optional[List] = children + # Mandatory fields. + self.identifier: str = identifier + self.spec_object: str = spec_object + # Not part of ReqIF, but helpful to calculate the section depth levels. + self.level = level + # Optional fields. + self.children: Optional[List] = children + self.long_name: Optional[str] = long_name # Not part of REqIF, but helpful for printing the # and tags depending on which tool produced the # ReqIF file. self.ref_then_children_order: bool = ref_then_children_order - # Not part of ReqIF, but helpful to calculate the section depth levels. - self.level = level + self.last_change: Optional[str] = last_change + self.editable: Optional[bool] = editable + self.is_self_closed: bool = is_self_closed + self.xml_node = xml_node def add_child(self, spec_hierarchy): assert (self.level + 1) == spec_hierarchy.level, ( From 4beea908f6ec11ca9e06f0d7ff66e89f09c402c0 Mon Sep 17 00:00:00 2001 From: Stanislav Pankevich Date: Wed, 8 Feb 2023 19:49:35 +0100 Subject: [PATCH 2/3] XHTML attributes: improve handling of multiline fields --- reqif/commands/anonymize/anonymize.py | 4 +--- reqif/helpers/lxml.py | 2 +- reqif/parsers/spec_object_parser.py | 5 ++++- reqif/parsers/spec_types/spec_object_type_parser.py | 6 ++++-- reqif/parsers/specification_parser.py | 1 + tasks.py | 2 +- .../reqif/SPECIFICATIONS/02_XHTML_attribute/sample.reqif | 6 +++++- 7 files changed, 17 insertions(+), 9 deletions(-) diff --git a/reqif/commands/anonymize/anonymize.py b/reqif/commands/anonymize/anonymize.py index edac8ff..4d4545c 100644 --- a/reqif/commands/anonymize/anonymize.py +++ b/reqif/commands/anonymize/anonymize.py @@ -79,7 +79,5 @@ def _anonymize_attribute(attribute): attribute.value = ANONYMIZED elif attribute.attribute_type == SpecObjectAttributeType.XHTML: attribute.value = ( - "\n" - f" {ANONYMIZED}\n" - " " + f"{ANONYMIZED}" ) diff --git a/reqif/helpers/lxml.py b/reqif/helpers/lxml.py index f103018..e39af94 100644 --- a/reqif/helpers/lxml.py +++ b/reqif/helpers/lxml.py @@ -16,7 +16,7 @@ def dump_xml_node(node): # when the etree.tostring(...) method is used: # -- # noqa: E501 # FIXME: Would be great to find a better solution for this. -def stringify_namespaced_children(node): +def stringify_namespaced_children(node) -> str: def _stringify_reqif_ns_node(node): assert node is not None nskey = next(iter(node.nsmap.keys())) diff --git a/reqif/parsers/spec_object_parser.py b/reqif/parsers/spec_object_parser.py index 1ba0e45..626cc36 100644 --- a/reqif/parsers/spec_object_parser.py +++ b/reqif/parsers/spec_object_parser.py @@ -68,7 +68,9 @@ {definition_ref} - {value} + + {value} + """ @@ -187,6 +189,7 @@ def parse(spec_object_xml) -> ReqIFSpecObject: elif attribute_xml.tag == "ATTRIBUTE-VALUE-XHTML": the_value = attribute_xml.find("THE-VALUE") attribute_value = stringify_namespaced_children(the_value) + attribute_value = attribute_value.strip() attribute_definition_ref = ( attribute_xml.find("DEFINITION") .find("ATTRIBUTE-DEFINITION-XHTML-REF") diff --git a/reqif/parsers/spec_types/spec_object_type_parser.py b/reqif/parsers/spec_types/spec_object_type_parser.py index c291d3e..3c0499d 100644 --- a/reqif/parsers/spec_types/spec_object_type_parser.py +++ b/reqif/parsers/spec_types/spec_object_type_parser.py @@ -216,6 +216,7 @@ def parse(spec_object_type_xml) -> ReqIFSpecObjectType: default_value = stringify_namespaced_children( xml_values ) + default_value = default_value.strip() else: raise NotImplementedError elif ( @@ -440,8 +441,9 @@ def _unparse_attribute_default_value( f"{attribute.default_value_definition_ref}" f"\n" " \n" - f" {attribute.default_value}" - "\n" + " \n" + f" {attribute.default_value}\n" + " \n" " \n" " \n" ) diff --git a/reqif/parsers/specification_parser.py b/reqif/parsers/specification_parser.py index f0c688b..a7191c4 100644 --- a/reqif/parsers/specification_parser.py +++ b/reqif/parsers/specification_parser.py @@ -94,6 +94,7 @@ def parse(specification_xml) -> ReqIFSpecification: elif xml_attribute.tag == "ATTRIBUTE-VALUE-XHTML": the_value = xml_attribute.find("THE-VALUE") attribute_value = stringify_namespaced_children(the_value) + attribute_value = attribute_value.strip() attribute_name = ( xml_attribute.find("DEFINITION") .find("ATTRIBUTE-DEFINITION-XHTML-REF") diff --git a/tasks.py b/tasks.py index 20313c6..c543025 100644 --- a/tasks.py +++ b/tasks.py @@ -135,7 +135,7 @@ def install_local(context): context, one_line_command( """ - tar -xvf dist/*.tar.gz --wildcards --no-anchored '*/setup.py' --strip=1 + tar -xvf dist/*.tar.gz '*/setup.py' """ ), ) diff --git a/tests/integration/reqif/SPECIFICATIONS/02_XHTML_attribute/sample.reqif b/tests/integration/reqif/SPECIFICATIONS/02_XHTML_attribute/sample.reqif index 31dd66e..8257388 100644 --- a/tests/integration/reqif/SPECIFICATIONS/02_XHTML_attribute/sample.reqif +++ b/tests/integration/reqif/SPECIFICATIONS/02_XHTML_attribute/sample.reqif @@ -10,7 +10,11 @@ _7f123ed4-98dd-4eed-b96a-edc8828963a8_CREATEDBY-DOORS-MODULE - susan + + A + multiline + text + From cfc6250e2a888206204f27ef879ef1762b4d22e8 Mon Sep 17 00:00:00 2001 From: Stanislav Pankevich Date: Wed, 8 Feb 2023 20:10:50 +0100 Subject: [PATCH 3/3] pyproject: remove obsolete beautifulsoup4 dependency --- pyproject.toml | 1 - reqif/commands/anonymize/anonymize.py | 4 +--- tests/unit/reqif/parsers/test_spec_object_parser.py | 4 +--- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 485932e..a94fb60 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,6 @@ keywords = [ [tool.poetry.dependencies] python = "^3.6.2" -beautifulsoup4 = '>= 4.9.3' lxml = '>= 4.6.2' jinja2 = ">= 2.11.2" toml = ">= 0.10.2" diff --git a/reqif/commands/anonymize/anonymize.py b/reqif/commands/anonymize/anonymize.py index 4d4545c..c74f8ad 100644 --- a/reqif/commands/anonymize/anonymize.py +++ b/reqif/commands/anonymize/anonymize.py @@ -78,6 +78,4 @@ def _anonymize_attribute(attribute): if attribute.attribute_type == SpecObjectAttributeType.STRING: attribute.value = ANONYMIZED elif attribute.attribute_type == SpecObjectAttributeType.XHTML: - attribute.value = ( - f"{ANONYMIZED}" - ) + attribute.value = f"{ANONYMIZED}" diff --git a/tests/unit/reqif/parsers/test_spec_object_parser.py b/tests/unit/reqif/parsers/test_spec_object_parser.py index 0dd4f11..775892d 100644 --- a/tests/unit/reqif/parsers/test_spec_object_parser.py +++ b/tests/unit/reqif/parsers/test_spec_object_parser.py @@ -67,9 +67,7 @@ def test_02_attributes_xhtml(): spec_object = SpecObjectParser.parse(spec_object_xml) assert spec_object.identifier == "TEST_SPEC_OBJECT_ID" - expected_xhtml = """ - susan\n \ -""" + expected_xhtml = "susan" assert ( spec_object.attribute_map[ "_7f123ed4-98dd-4eed-b96a-edc8828963a8_CREATEDBY"