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

Fix lxml qname in argument #414

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## Fixed:

- fixed an issue where the new pat mdib is not parseable because lxml QName is unpickleable

## [2.2.0] - 2025-02-25

### Added:
Expand Down
304 changes: 304 additions & 0 deletions examples/ReferenceTestV2/PlugathonMdibV2.xml

Large diffs are not rendered by default.

283 changes: 0 additions & 283 deletions examples/ReferenceTestV2/mdib_test_sequence_2_v4(temp).xml

This file was deleted.

203 changes: 107 additions & 96 deletions examples/ReferenceTestV2/reference_provider_v2.py

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ extend-exclude = ["examples", "tools", "tutorial"] # https://docs.astral.sh/ruff
[tool.ruff.lint]
select = ["ALL"] # https://docs.astral.sh/ruff/settings/#select
extend-ignore = [# https://docs.astral.sh/ruff/settings/#extend-ignore
"ANN101", # https://docs.astral.sh/ruff/rules/missing-type-self/
"ANN102", # https://docs.astral.sh/ruff/rules/missing-type-cls/
"ANN204", # https://docs.astral.sh/ruff/rules/missing-return-type-special-method/
"ANN401", # https://docs.astral.sh/ruff/rules/any-type/
"C408", # https://docs.astral.sh/ruff/rules/unnecessary-collection-call/
Expand Down
250 changes: 130 additions & 120 deletions src/sdc11073/namespaces.py

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions src/sdc11073/xml_types/pm_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

if TYPE_CHECKING:
from lxml import etree
from sdc11073 import xml_utils

from sdc11073 import xml_utils
from sdc11073.xml_types.isoduration import DateTypeUnion, DurationType


Expand Down Expand Up @@ -305,7 +305,7 @@
TextWidth = cp.EnumAttributeProperty('TextWidth', enum_cls=LocalizedTextWidth)
_props = ('text', 'Ref', 'Lang', 'Version', 'TextWidth')

def __init__(self, text: str, # noqa: PLR0913
def __init__(self, text: str,
lang: str | None = None,
ref: str | None = None,
version: int | None = None,
Expand Down Expand Up @@ -589,7 +589,7 @@
AbsoluteAccuracy: Decimal | None = cp.DecimalAttributeProperty('AbsoluteAccuracy')
_props = ('Extension', 'Lower', 'Upper', 'StepWidth', 'RelativeAccuracy', 'AbsoluteAccuracy')

def __init__(self, # noqa: PLR0913
def __init__(self,
lower: Decimal | None = None,
upper: Decimal | None = None,
step_width: Decimal | None = None,
Expand Down Expand Up @@ -775,7 +775,7 @@

NODETYPE = pm.CauseInfo
ExtExtension = cp.ExtensionNodeProperty(ext.Extension)
RemedyInfo: RemedyInfoType = cp.SubElementProperty(pm.RemedyInfo, value_class=RemedyInfo)
RemedyInfo: RemedyInfoType | None = cp.SubElementProperty(pm.RemedyInfo, value_class=RemedyInfo)
Description: list[LocalizedText] = cp.SubElementListProperty(pm.Description, value_class=LocalizedText)
_props = ('ExtExtension', 'RemedyInfo', 'Description')

Expand All @@ -790,10 +790,10 @@
"""Represents BICEPS AbstractSetStateOperationDescriptor/Argument."""

ArgName: CodedValue = cp.SubElementProperty(pm.ArgName, value_class=CodedValue, is_optional=False)
Arg: etree.QName | None = cp.NodeTextQNameProperty(pm.Arg, is_optional=False)
Arg: xml_utils.QName | None = cp.NodeTextQNameProperty(pm.Arg, is_optional=False)
_props = ('ArgName', 'Arg')

def __init__(self, arg_name: CodedValue | None = None, arg: etree.QName | None = None):
def __init__(self, arg_name: CodedValue | None = None, arg: xml_utils.QName | None = None):
super().__init__()
self.ArgName = arg_name
self.Arg = arg
Expand Down Expand Up @@ -879,7 +879,7 @@
Title: str | None = cp.NodeStringProperty(pm.Title, is_optional=True)
_props = ('ExtExtension', 'Givenname', 'Middlename', 'Familyname', 'Birthname', 'Title')

def __init__(self, # noqa: PLR0913
def __init__(self,
given_name: str | None = None,
middle_names: list[str] | None = None,
family_name: str | None = None,
Expand Down Expand Up @@ -1035,7 +1035,7 @@
value_class=RelatedMeasurement)
_props = ('Type', 'Code', 'Criticality', 'Description', 'RelatedMeasurement')

def __init__(self, # noqa: PLR0913
def __init__(self,
type_: CodedValue | None = None,
code: CodedValue | None = None,
criticality: CriticalityType | None = None,
Expand Down Expand Up @@ -1101,7 +1101,7 @@
value_class=ImagingProcedure)
_props = ('Start', 'End', 'Performer', 'Service', 'ImagingProcedure')

def __init__(self, # noqa: PLR0913
def __init__(self,
start: str | None = None,
end: str | None = None,
performer: list[PersonParticipation] | None = None,
Expand Down Expand Up @@ -1442,4 +1442,4 @@
try:
return _name_class_lookup[qname]
except KeyError as ex:
raise KeyError(f'{qname.namespace}.{qname.localname}') from ex
raise KeyError(f'{qname.namespace}.{qname.localname}') from ex # noqa: EM102

Check warning on line 1445 in src/sdc11073/xml_types/pm_types.py

View check run for this annotation

Codecov / codecov/patch

src/sdc11073/xml_types/pm_types.py#L1445

Added line #L1445 was not covered by tests
15 changes: 13 additions & 2 deletions src/sdc11073/xml_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Module containing utilities and helper methods regarding xml."""
from __future__ import annotations

import copy
import sys
Expand All @@ -9,11 +10,11 @@
if sys.version_info >= (3, 10):
from typing import TypeAlias

LxmlElement: TypeAlias = etree._Element
LxmlElement: TypeAlias = etree._Element # noqa: SLF001
else:
from typing_extensions import TypeAlias

LxmlElement: TypeAlias = etree._Element
LxmlElement: TypeAlias = etree._Element # noqa: SLF001


def copy_element(node: LxmlElement, method: Callable[[LxmlElement], LxmlElement] = copy.deepcopy) -> LxmlElement:
Expand Down Expand Up @@ -57,3 +58,13 @@ def copy_node_wo_parent(node: LxmlElement, method: Callable[[LxmlElement], LxmlE
new_node.tail = node.tail
new_node.extend(method(child) for child in node)
return new_node


class QName(etree.QName):
"""Implements copy and deepcopy for lxml QName as it is unpickleable."""

def __copy__(self):
return QName(self.text)

def __deepcopy__(self, _: dict):
return QName(self.text)
25 changes: 25 additions & 0 deletions tests/test_xml_utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
"""Unit tests for XML utility functions in the `xml_utils` module."""

import copy
import unittest

from lxml import etree

from sdc11073 import xml_utils
from tests import utils


class TestXmlParsing(unittest.TestCase):
Expand Down Expand Up @@ -274,3 +278,24 @@ def test_lxml_element_type(self):
self.assertEqual(type(parsed_xml), xml_utils.LxmlElement)
self.assertTrue(isinstance(parsed_xml, etree._Element))
self.assertTrue(isinstance(parsed_xml, xml_utils.LxmlElement))

def test_custom_qname(self):
qname = utils.random_qname()
new_qname = xml_utils.QName(qname.text)
self.assertEqual(qname.text, new_qname.text)
self.assertEqual(qname.localname, new_qname.localname)
self.assertEqual(qname.namespace, new_qname.namespace)

def test_custom_qname_copy(self):
qname = xml_utils.QName(utils.random_qname().text)
new_qname = copy.copy(qname)
self.assertEqual(qname.text, new_qname.text)
self.assertEqual(qname.localname, new_qname.localname)
self.assertEqual(qname.namespace, new_qname.namespace)

def test_custom_qname_deepcopy(self):
qname = xml_utils.QName(utils.random_qname().text)
new_qname = copy.deepcopy(qname)
self.assertEqual(qname.text, new_qname.text)
self.assertEqual(qname.localname, new_qname.localname)
self.assertEqual(qname.namespace, new_qname.namespace)
Loading