Skip to content

Commit 6676f34

Browse files
authored
Merge pull request #114 from strictdoc-project/stanislaw/develop
helpers/lxml: lxml_ prefix for all remaining methods
2 parents 7161d3a + 79aafc5 commit 6676f34

13 files changed

Lines changed: 86 additions & 53 deletions

File tree

reqif/commands/anonymize/anonymize.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from lxml.etree import tostring
99

1010
from reqif.cli.cli_arg_parser import AnonimizeCommandConfig
11-
from reqif.helpers.lxml import stringify_namespaced_children
11+
from reqif.helpers.lxml import lxml_stringify_namespaced_children
1212
from reqif.models.error_handling import ReqIFXMLParsingError
1313
from reqif.models.reqif_spec_object import ReqIFSpecObject, SpecObjectAttribute
1414
from reqif.models.reqif_specification import ReqIFSpecification
@@ -106,8 +106,8 @@ def _anonymize(config: AnonimizeCommandConfig):
106106
"//reqif:ATTRIBUTE-VALUE-XHTML/reqif:THE-VALUE", namespaces=fixns
107107
)
108108
for xml_attribute_value_xhtml in xml_attribute_value_xhtmls:
109-
xml_attribute_value_xhtml_text: str = stringify_namespaced_children(
110-
xml_attribute_value_xhtml
109+
xml_attribute_value_xhtml_text: str = (
110+
lxml_stringify_namespaced_children(xml_attribute_value_xhtml)
111111
)
112112
for child in list(xml_attribute_value_xhtml):
113113
xml_attribute_value_xhtml.remove(child)

reqif/helpers/lxml.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
from lxml.html import fragment_fromstring
77

88

9-
def dump_xml_node(node):
9+
def lxml_dump_node(node):
1010
return etree.tostring(node, method="xml").decode("utf8")
1111

1212

1313
# This code is taken from Python 3.7. The addition is escaping of the tab
1414
# character.
15-
def my_escape(string: str) -> str:
15+
def lxml_escape_for_html(string: str) -> str:
1616
"""
1717
Replace special characters "&", "<" and ">" to HTML-safe sequences.
1818
If the optional flag quote is true (the default), the quotation mark
@@ -29,7 +29,7 @@ def my_escape(string: str) -> str:
2929
return string
3030

3131

32-
def my_escape_title(string: str) -> str:
32+
def lxml_escape_title(string: str) -> str:
3333
# The only known reason for this method is the presence of &amp; in the
3434
# HEADER title of ReqIF files found at the ci.eclipse.org.
3535
string = string.replace("&", "&amp;")
@@ -43,47 +43,47 @@ def my_escape_title(string: str) -> str:
4343
# when the etree.tostring(...) method is used:
4444
# <reqif-xhtml:div xmlns:reqif-xhtml="http://www.w3.org/1999/xhtml">--</reqif-xhtml:div> # noqa: E501
4545
# FIXME: Would be great to find a better solution for this.
46-
def stringify_namespaced_children(node, namespace_tag=None) -> str:
46+
def lxml_stringify_namespaced_children(node, namespace_tag=None) -> str:
4747
if namespace_tag is None:
4848
assert (
4949
len(node.nsmap) > 0
50-
), f"This method must be called on a namespaced tag:\n{dump_xml_node(node)}" # noqa: E501
50+
), f"This method must be called on a namespaced tag:\n{lxml_dump_node(node)}" # noqa: E501
5151
nskey = next(iter(node.nsmap.keys()))
5252
else:
5353
nskey = namespace_tag
5454

55-
def _stringify_reqif_ns_node(node):
55+
def _lxml_stringify_reqif_ns_node(node):
5656
assert node is not None
5757

5858
output = ""
5959
node_no_ns_tag = etree.QName(node).localname
6060
output += f"<{nskey}:{node_no_ns_tag}"
6161
for attribute, attribute_value in node.attrib.items():
62-
output += f' {attribute}="{my_escape(attribute_value)}"'
62+
output += f' {attribute}="{lxml_escape_for_html(attribute_value)}"'
6363
if node.text is not None or len(node.getchildren()) > 0:
6464
output += ">"
6565
if node.text is not None:
66-
output += my_escape(node.text)
66+
output += lxml_escape_for_html(node.text)
6767
for child in node.getchildren():
68-
output += _stringify_reqif_ns_node(child)
68+
output += _lxml_stringify_reqif_ns_node(child)
6969
output += f"</{nskey}:{node_no_ns_tag}>"
7070
else:
7171
output += "/>"
7272

7373
if node.tail is not None:
74-
output += my_escape(node.tail)
74+
output += lxml_escape_for_html(node.tail)
7575
return output
7676

7777
string = ""
7878
if node.text is not None:
79-
string += my_escape(node.text)
79+
string += lxml_escape_for_html(node.text)
8080
for child in node.getchildren():
81-
string += _stringify_reqif_ns_node(child)
81+
string += _lxml_stringify_reqif_ns_node(child)
8282
return string
8383

8484

8585
# https://stackoverflow.com/a/28173933/598057
86-
def stringify_children(node):
86+
def lxml_stringify_children(node):
8787
return "".join(
8888
chunk
8989
for chunk in chain(
@@ -114,7 +114,7 @@ def stringify_children(node):
114114
def lxml_convert_to_reqif_ns_xhtml_string(string, reqif_xhtml=True) -> str:
115115
namespace_tag = "reqif-xhtml" if reqif_xhtml else "xhtml"
116116
node = fragment_fromstring(string, create_parent="NOT-USED")
117-
return stringify_namespaced_children(node, namespace_tag=namespace_tag)
117+
return lxml_stringify_namespaced_children(node, namespace_tag=namespace_tag)
118118

119119

120120
def lxml_convert_from_reqif_ns_xhtml_string(lxml_node) -> str:
@@ -128,10 +128,10 @@ def lxml_convert_from_reqif_ns_xhtml_string(lxml_node) -> str:
128128
def lxml_convert_children_from_reqif_ns_xhtml_string(lxml_node) -> str:
129129
lxml_node_deep_copy = deepcopy(lxml_node)
130130
lxml_strip_namespace_from_xml(lxml_node_deep_copy, full=True)
131-
return stringify_children(lxml_node_deep_copy)
131+
return lxml_stringify_children(lxml_node_deep_copy)
132132

133133

134-
def is_self_closed_tag(xml):
134+
def lxml_is_self_closed_tag(xml):
135135
# The tag cannot be closed if it has children or has a non-None text.
136136
if len(xml.getchildren()) > 0:
137137
return False

reqif/helpers/string/escape.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# This code is taken from Python 3.7. The addition is escaping of the tab
2+
# character.
3+
def reqif_escape(string: str) -> str:
4+
"""
5+
Replace special characters "&", "<" and ">" to HTML-safe sequences.
6+
If the optional flag quote is true (the default), the quotation mark
7+
characters, both double quote (") and single quote (') characters are also
8+
translated.
9+
"""
10+
string = string.replace("&", "&amp;") # Must be done first!
11+
string = string.replace("<", "&lt;")
12+
string = string.replace(">", "&gt;")
13+
string = string.replace('"', "&quot;")
14+
string = string.replace("'", "&#x27;")
15+
# Invisible tab character
16+
string = string.replace("\t", "&#9;")
17+
return string
18+
19+
20+
def reqif_escape_title(string: str) -> str:
21+
# The only known reason for this method is the presence of &amp; in the
22+
# HEADER title of ReqIF files found at the ci.eclipse.org.
23+
string = string.replace("&", "&amp;")
24+
return string

reqif/models/error_handling.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from reqif.helpers.lxml import dump_xml_node
1+
from reqif.helpers.lxml import lxml_dump_node
22

33

44
class ReqIFXMLParsingError(Exception):
@@ -34,7 +34,7 @@ def get_description(self) -> str:
3434
return (
3535
f"schema error: Tag <{self.xml_node.tag}> is missing a "
3636
f"<{self.tag}> child tag. "
37-
f"Affected fragment:\n{dump_xml_node(self.xml_node)}"
37+
f"Affected fragment:\n{lxml_dump_node(self.xml_node)}"
3838
)
3939

4040

@@ -50,7 +50,7 @@ def get_description(self) -> str:
5050
f"schema error: A <{self.xml_node.tag}>'s <{self.tag}> "
5151
"contains a link to a non-existing <SPEC-OBJECT>: "
5252
f"{self.spec_object_identifier}\n"
53-
f"Affected fragment:\n{dump_xml_node(self.xml_node)}"
53+
f"Affected fragment:\n{lxml_dump_node(self.xml_node)}"
5454
)
5555

5656

@@ -65,5 +65,5 @@ def get_description(self) -> str:
6565
f"schema error: A <SPEC-HIERARCHY>'s <SPEC-OBJECT-REF> "
6666
"contains a link to a non-existing <SPEC-OBJECT>: "
6767
f"{self.spec_object_identifier}\n"
68-
f"Affected fragment:\n{dump_xml_node(self.xml_node)}"
68+
f"Affected fragment:\n{lxml_dump_node(self.xml_node)}"
6969
)

reqif/parsers/data_type_parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from lxml import etree
44

5-
from reqif.helpers.lxml import is_self_closed_tag
5+
from reqif.helpers.lxml import lxml_is_self_closed_tag
66
from reqif.models.reqif_data_type import (
77
ReqIFDataTypeDefinitionBoolean,
88
ReqIFDataTypeDefinitionDateIdentifier,
@@ -30,7 +30,7 @@ def parse( # pylint: disable=too-many-return-statements
3030
]:
3131
assert "DATATYPE-DEFINITION-" in data_type_xml.tag, f"{data_type_xml}"
3232

33-
is_self_closed = is_self_closed_tag(data_type_xml)
33+
is_self_closed = lxml_is_self_closed_tag(data_type_xml)
3434

3535
attributes = data_type_xml.attrib
3636
identifier = attributes["IDENTIFIER"]

reqif/parsers/header_parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Optional
22

3-
from reqif.helpers.lxml import my_escape_title
3+
from reqif.helpers.lxml import lxml_escape_title
44
from reqif.models.reqif_reqif_header import ReqIFReqIFHeader
55

66

@@ -114,7 +114,7 @@ def unparse(header: ReqIFReqIFHeader) -> str:
114114
)
115115
if header.title:
116116
output += (
117-
f" <TITLE>{my_escape_title(header.title)}</TITLE>\n"
117+
f" <TITLE>{lxml_escape_title(header.title)}</TITLE>\n"
118118
)
119119

120120
output += " </REQ-IF-HEADER>\n"

reqif/parsers/spec_hierarchy_parser.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import List, Optional
22

3-
from reqif.helpers.lxml import is_self_closed_tag
3+
from reqif.helpers.lxml import lxml_is_self_closed_tag
44
from reqif.models.reqif_spec_hierarchy import (
55
ReqIFSpecHierarchy,
66
)
@@ -45,7 +45,9 @@ def parse(spec_hierarchy_xml, level=1) -> ReqIFSpecHierarchy:
4545
if xml_spec_hierarchy_children is not None:
4646
spec_hierarchy_children = []
4747
if len(xml_spec_hierarchy_children) == 0:
48-
is_self_closed = is_self_closed_tag(xml_spec_hierarchy_children)
48+
is_self_closed = lxml_is_self_closed_tag(
49+
xml_spec_hierarchy_children
50+
)
4951
for child_spec_hierarchy_xml in xml_spec_hierarchy_children:
5052
child_spec_hierarchy = ReqIFSpecHierarchyParser.parse(
5153
child_spec_hierarchy_xml, level + 1

reqif/parsers/spec_object_parser.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
from reqif.helpers.lxml import (
77
lxml_convert_children_from_reqif_ns_xhtml_string,
8-
stringify_children,
9-
stringify_namespaced_children,
8+
lxml_stringify_children,
9+
lxml_stringify_namespaced_children,
1010
)
1111
from reqif.helpers.string.xhtml_indent import reqif_unindent_xhtml_string
1212
from reqif.models.reqif_spec_object import (
@@ -209,7 +209,9 @@ def parse(spec_object_xml) -> ReqIFSpecObject:
209209

210210
# Edge: There are not <xhtml:...> or <reqif-xhtml...> tags.
211211
if len(the_value.nsmap) > 0:
212-
attribute_value = stringify_namespaced_children(the_value)
212+
attribute_value = lxml_stringify_namespaced_children(
213+
the_value
214+
)
213215
attribute_value_stripped_xhtml = (
214216
reqif_unindent_xhtml_string(
215217
lxml_convert_children_from_reqif_ns_xhtml_string(
@@ -218,7 +220,7 @@ def parse(spec_object_xml) -> ReqIFSpecObject:
218220
)
219221
)
220222
else:
221-
attribute_value = stringify_children(the_value)
223+
attribute_value = lxml_stringify_children(the_value)
222224
attribute_value_stripped_xhtml = (
223225
reqif_unindent_xhtml_string(attribute_value)
224226
)

reqif/parsers/spec_types/spec_object_type_parser.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import html
22
from typing import List, Optional, Union
33

4-
from reqif.helpers.lxml import is_self_closed_tag, stringify_namespaced_children
4+
from reqif.helpers.lxml import (
5+
lxml_is_self_closed_tag,
6+
lxml_stringify_namespaced_children,
7+
)
58
from reqif.models.reqif_spec_object_type import (
69
DefaultValueEmptySelfClosedTag,
710
ReqIFSpecObjectType,
@@ -85,7 +88,7 @@ def parse(spec_object_type_xml) -> ReqIFSpecObjectType:
8588
"DEFAULT-VALUE"
8689
)
8790
if xml_default_value is not None:
88-
if is_self_closed_tag(xml_default_value):
91+
if lxml_is_self_closed_tag(xml_default_value):
8992
default_value = DefaultValueEmptySelfClosedTag()
9093
else:
9194
xml_attribute_value = xml_default_value.find(
@@ -194,7 +197,7 @@ def parse(spec_object_type_xml) -> ReqIFSpecObjectType:
194197
)
195198
if xml_default_value is None:
196199
pass
197-
elif is_self_closed_tag(xml_default_value):
200+
elif lxml_is_self_closed_tag(xml_default_value):
198201
default_value = DefaultValueEmptySelfClosedTag()
199202
else:
200203
xml_attribute_value = xml_default_value.find(
@@ -213,7 +216,7 @@ def parse(spec_object_type_xml) -> ReqIFSpecObjectType:
213216
xml_attribute_ref.text
214217
)
215218
xml_values = xml_attribute_value.find("THE-VALUE")
216-
default_value = stringify_namespaced_children(
219+
default_value = lxml_stringify_namespaced_children(
217220
xml_values
218221
)
219222
else:
@@ -248,7 +251,7 @@ def parse(spec_object_type_xml) -> ReqIFSpecObjectType:
248251
"DEFAULT-VALUE"
249252
)
250253
if xml_default_value is not None:
251-
if is_self_closed_tag(xml_default_value):
254+
if lxml_is_self_closed_tag(xml_default_value):
252255
default_value = DefaultValueEmptySelfClosedTag()
253256
else:
254257
xml_attribute_value = xml_default_value.find(

reqif/parsers/spec_types/spec_relation_type_parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import html
22
from typing import Optional
33

4-
from reqif.helpers.lxml import is_self_closed_tag
4+
from reqif.helpers.lxml import lxml_is_self_closed_tag
55
from reqif.models.reqif_spec_relation_type import ReqIFSpecRelationType
66

77

@@ -11,7 +11,7 @@ def parse(xml_spec_relation_type_xml) -> ReqIFSpecRelationType:
1111
assert (
1212
xml_spec_relation_type_xml.tag == "SPEC-RELATION-TYPE"
1313
), f"{xml_spec_relation_type_xml}"
14-
is_self_closed = is_self_closed_tag(xml_spec_relation_type_xml)
14+
is_self_closed = lxml_is_self_closed_tag(xml_spec_relation_type_xml)
1515

1616
xml_attributes = xml_spec_relation_type_xml.attrib
1717
# Expecting all tools to implement IDENTIFIER and LONG-NAME.

0 commit comments

Comments
 (0)