Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move xml_indent, xml_quote and xml_unquote to osc.util.xml module #1482

Merged
merged 1 commit into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 4 additions & 38 deletions osc/_private/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
import xml.sax.saxutils
from xml.etree import ElementTree as ET

from ..util.xml import xml_escape
Dismissed Show dismissed Hide dismissed
from ..util.xml import xml_indent
from ..util.xml import xml_unescape
Dismissed Show dismissed Hide dismissed


def get(apiurl, path, query=None):
"""
Expand Down Expand Up @@ -205,41 +209,3 @@
if indent:
xml_indent(node)
ET.ElementTree(node).write(path)


def xml_escape(string):
"""
Escape the string so it's safe to use in XML and xpath.
"""
entities = {
"\"": """,
"'": "'",
}
if isinstance(string, bytes):
return xml.sax.saxutils.escape(string.decode("utf-8"), entities=entities).encode("utf-8")
return xml.sax.saxutils.escape(string, entities=entities)


def xml_unescape(string):
"""
Decode XML entities in the string.
"""
entities = {
""": "\"",
"'": "'",
}
if isinstance(string, bytes):
return xml.sax.saxutils.unescape(string.decode("utf-8"), entities=entities).encode("utf-8")
return xml.sax.saxutils.unescape(string, entities=entities)


def xml_indent(root):
"""
Indent XML so it looks pretty after printing or saving to file.
"""
if hasattr(ET, "indent"):
# ElementTree supports indent() in Python 3.9 and newer
ET.indent(root)
else:
from .. import core as osc_core
osc_core.xmlindent(root)
21 changes: 1 addition & 20 deletions osc/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
from .connection import http_request, http_GET, http_POST, http_PUT, http_DELETE
from .store import Store
from .util.helper import decode_list, decode_it, raw_input, _html_escape
from .util.xml import xml_indent_compat as xmlindent


ET_ENCODING = "unicode"
Expand Down Expand Up @@ -636,26 +637,6 @@
def haserror(self):
return self.error is not None

# http://effbot.org/zone/element-lib.htm#prettyprint


def xmlindent(elem, level=0):
i = "\n" + level * " "
if isinstance(elem, ET.ElementTree):
elem = elem.getroot()
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + " "
for e in elem:
xmlindent(e, level + 1)
if not e.tail or not e.tail.strip():
e.tail = i + " "
if not e.tail or not e.tail.strip():
e.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i


class Project:
"""
Expand Down Expand Up @@ -6137,27 +6118,27 @@
# BEGIN: Error out on branching scmsync packages; this should be properly handled in the API

# read src_package meta
m = b"".join(show_package_meta(apiurl, src_project, src_package))
root = ET.fromstring(m)

Check warning on line 6122 in osc/core.py

View check run for this annotation

Codecov / codecov/patch

osc/core.py#L6121-L6122

Added lines #L6121 - L6122 were not covered by tests

devel_project = None
devel_package = None
if not nodevelproject:
devel_node = root.find("devel")
if devel_node is not None:
devel_project = devel_node.get("project")
devel_package = devel_node.get("package", src_package)
if devel_project:

Check warning on line 6131 in osc/core.py

View check run for this annotation

Codecov / codecov/patch

osc/core.py#L6124-L6131

Added lines #L6124 - L6131 were not covered by tests
# replace src_package meta with devel_package meta because we're about branch from devel
m = b"".join(show_package_meta(apiurl, devel_project, devel_package))
root = ET.fromstring(m)

Check warning on line 6134 in osc/core.py

View check run for this annotation

Codecov / codecov/patch

osc/core.py#L6133-L6134

Added lines #L6133 - L6134 were not covered by tests

# error out if we're branching a scmsync package (we'd end up with garbage anyway)
if root.find("scmsync") is not None:
msg = "Cannot branch a package with <scmsync> set."
if devel_project:
raise oscerr.PackageError(devel_project, devel_package, msg)
raise oscerr.PackageError(src_project, src_package, msg)

Check warning on line 6141 in osc/core.py

View check run for this annotation

Codecov / codecov/patch

osc/core.py#L6137-L6141

Added lines #L6137 - L6141 were not covered by tests

# END: Error out on branching scmsync packages; this should be properly handled in the API

Expand Down
81 changes: 81 additions & 0 deletions osc/util/xml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""
Functions that manipulate with XML.
"""


import xml.sax.saxutils
from xml.etree import ElementTree as ET


def xml_escape(string):
"""
Escape the string so it's safe to use in XML and xpath.
"""
entities = {
'"': "&quot;",
"'": "&apos;",
}
if isinstance(string, bytes):
return xml.sax.saxutils.escape(string.decode("utf-8"), entities=entities).encode("utf-8")

Check warning on line 19 in osc/util/xml.py

View check run for this annotation

Codecov / codecov/patch

osc/util/xml.py#L19

Added line #L19 was not covered by tests
return xml.sax.saxutils.escape(string, entities=entities)


def xml_unescape(string):
"""
Decode XML entities in the string.
"""
entities = {

Check warning on line 27 in osc/util/xml.py

View check run for this annotation

Codecov / codecov/patch

osc/util/xml.py#L27

Added line #L27 was not covered by tests
"&quot;": '"',
"&apos;": "'",
}
if isinstance(string, bytes):
return xml.sax.saxutils.unescape(string.decode("utf-8"), entities=entities).encode("utf-8")
return xml.sax.saxutils.unescape(string, entities=entities)

Check warning on line 33 in osc/util/xml.py

View check run for this annotation

Codecov / codecov/patch

osc/util/xml.py#L31-L33

Added lines #L31 - L33 were not covered by tests


def xml_strip_text(node):
"""
Recursively strip inner text in nodes:
- if text contains only whitespaces
- if node contains child nodes
"""
if node.text and not node.text.strip():
node.text = None

Check warning on line 43 in osc/util/xml.py

View check run for this annotation

Codecov / codecov/patch

osc/util/xml.py#L43

Added line #L43 was not covered by tests
elif len(node) != 0:
node.text = None
for child in node:

Check failure

Code scanning / CodeQL

Suspicious unused loop iteration variable Error

For loop variable 'child' is not used in the loop body.
xml_strip_text(child)


def xml_indent_compat(elem, level=0):
"""
XML indentation code for python < 3.9.
Source: http://effbot.org/zone/element-lib.htm#prettyprint
"""
i = "\n" + level * " "
if isinstance(elem, ET.ElementTree):
elem = elem.getroot()

Check warning on line 57 in osc/util/xml.py

View check run for this annotation

Codecov / codecov/patch

osc/util/xml.py#L57

Added line #L57 was not covered by tests
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + " "
for e in elem:
xml_indent_compat(e, level + 1)
if not e.tail or not e.tail.strip():
e.tail = i + " "
if not e.tail or not e.tail.strip():
e.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i


def xml_indent(root):
"""
Indent XML so it looks pretty after printing or saving to file.
"""
if hasattr(ET, "indent"):
# ElementTree supports indent() in Python 3.9 and newer
xml_strip_text(root)
ET.indent(root)
else:
xml_indent_compat(root)

Check warning on line 81 in osc/util/xml.py

View check run for this annotation

Codecov / codecov/patch

osc/util/xml.py#L81

Added line #L81 was not covered by tests
Loading