Skip to content

Commit

Permalink
Add test for issue #418
Browse files Browse the repository at this point in the history
  - Remove useless XsdSelector.target_namespace property
  • Loading branch information
brunato committed Oct 28, 2024
1 parent 1108dd6 commit 6b4e948
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 654 deletions.
588 changes: 0 additions & 588 deletions doc/components.rst

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/test_cases/issues/issue_418/issue_418-invalid.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>

<mqttservices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="test_keys.xsd" active="true">
xsi:noNamespaceSchemaLocation="issue_418.xsd" active="true">
<events>
<event trigger="TS01" command="powu56.py" parameters="-on -ports '1,2,3'" />
<event trigger="TS08" command="powu56.py" parameters="-off -ports '1,2,3'"/>
Expand Down
13 changes: 0 additions & 13 deletions tests/test_cases/issues/issue_418/issue_418-invalid2.xml

This file was deleted.

2 changes: 1 addition & 1 deletion tests/test_cases/issues/issue_418/issue_418.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>

<mqttservices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="test_keys.xsd" active="true">
xsi:noNamespaceSchemaLocation="issue_418.xsd" active="true">
<events>
<event trigger="TS01" command="powu56.py" parameters="-on -ports '1,2,3'" />
<event trigger="TS08" command="powu56.py" parameters="-off -ports '1,2,3'"/>
Expand Down
24 changes: 2 additions & 22 deletions tests/validators/test_identities.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,22 +127,6 @@ def test_invalid_selector_path(self):

self.assertIn("XPST0003", ctx.exception.message)

def test_selector_target_namespace(self):
schema = self.check_schema("""
<xs:element name="primary_key" type="xs:string">
<xs:key name="key1">
<xs:selector xpath="xs:*"/>
<xs:field xpath="."/>
<xs:field xpath="@xs:*"/>
</xs:key>
</xs:element>""")

self.assertEqual(schema.identities['key1'].selector.target_namespace,
'http://www.w3.org/2001/XMLSchema')
self.assertEqual(schema.identities['key1'].fields[0].target_namespace, '')
self.assertEqual(schema.identities['key1'].fields[1].target_namespace,
'http://www.w3.org/2001/XMLSchema')

def test_invalid_selector_node(self):
with self.assertRaises(XMLSchemaParseError) as ctx:
self.check_schema("""
Expand Down Expand Up @@ -391,7 +375,6 @@ def test_keyref_counter(self):
self.assertIn("value ('3',) not found", str(errors[1]))
self.assertIn("(2 times)", str(errors[1]))

@unittest.skip
def test_key_multiple_values__issue_418(self):
xsd_file = self.casepath('issues/issue_418/issue_418.xsd')
schema = self.schema_class(xsd_file)
Expand All @@ -400,12 +383,9 @@ def test_key_multiple_values__issue_418(self):
self.assertIsNone(schema.validate(xml_file))

xml_file = self.casepath('issues/issue_418/issue_418-invalid.xml')
with self.assertRaises(XMLSchemaValidationError):
schema.validate(xml_file)

xml_file = self.casepath('issues/issue_418/issue_418-invalid2.xml')
with self.assertRaises(XMLSchemaValidationError):
with self.assertRaises(XMLSchemaValidationError) as ctx:
schema.validate(xml_file)
self.assertIn("field selects multiple values", str(ctx.exception))


class TestXsd11Identities(TestXsdIdentities):
Expand Down
2 changes: 1 addition & 1 deletion xmlschema/validators/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from decimal import Decimal
from types import GeneratorType
from typing import TYPE_CHECKING, cast, Any, Dict, Iterator, List, Optional, \
Set, Tuple, Type, Union, reveal_type
Set, Tuple, Type, Union
from xml.etree.ElementTree import Element, ParseError

from elementpath import XPath2Parser, ElementPathError, XPathContext, XPathToken, \
Expand Down
52 changes: 24 additions & 28 deletions xmlschema/validators/identities.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@
from ..names import XSD_UNIQUE, XSD_KEY, XSD_KEYREF, XSD_SELECTOR, XSD_FIELD
from ..translation import gettext as _
from ..helpers import get_qname, get_extended_qname
from ..aliases import ElementType, SchemaType, NamespacesType, AtomicValueType, BaseXsdType
from ..aliases import ElementType, SchemaType, NamespacesType, AtomicValueType, \
BaseXsdType, SchemaElementType, SchemaAttributeType
from ..xpath import IdentityXPathParser, XPathElement
from .exceptions import XMLSchemaNotBuiltError
from .xsdbase import XsdComponent
from .attributes import XsdAttribute
from .wildcards import XsdAnyElement
from .wildcards import XsdAnyElement, XsdWildcard
from . import elements as elements_module

if TYPE_CHECKING:
Expand All @@ -40,6 +41,7 @@
IdentityMapType = Dict[Union['XsdKey', 'XsdKeyref', str, None],
Union['IdentityCounter', 'KeyrefCounter']]
IdentityNodeType = Union[ElementNode, AttributeNode]
FieldDecoderType = Union[SchemaElementType, SchemaAttributeType]


class XsdSelector(XsdComponent):
Expand Down Expand Up @@ -105,16 +107,6 @@ def __repr__(self) -> str:
def built(self) -> bool:
return True

@property
def target_namespace(self) -> str:
if self.token is None:
pass # xpathDefaultNamespace="##targetNamespace"
elif self.token.symbol == ':':
return self.token[1].namespace or self.xpath_default_namespace
elif self.token.symbol == '@' and self.token[0].symbol == ':':
return self.token[0][1].namespace or self.xpath_default_namespace
return self.schema.target_namespace


class XsdFieldSelector(XsdSelector):
"""Class for defining an XPath field selector for an XSD identity constraint."""
Expand Down Expand Up @@ -402,6 +394,8 @@ def iter_errors(self, identities: IdentityMapType) -> Iterator[XMLSchemaValueErr

class FieldValueSelector:

skip_wildcard = False

def __init__(self, field: XsdFieldSelector, xsd_element: 'XsdElement') -> None:
if field.token is None:
msg = f"identity field {field} is not built"
Expand All @@ -411,11 +405,6 @@ def __init__(self, field: XsdFieldSelector, xsd_element: 'XsdElement') -> None:
self.xsd_element = xsd_element
self.value_constraints = {}

if isinstance(field.parent, XsdKey):
self.admit_empty = False
else:
self.admit_empty = True

self.token = copy.deepcopy(field.token)
schema_context = xsd_element.xpath_proxy.get_context()
self.decoders = []
Expand All @@ -426,13 +415,17 @@ def __init__(self, field: XsdFieldSelector, xsd_element: 'XsdElement') -> None:
"xs:field path must select only attributes and elements"
)

comp = cast(Union['XsdElement', XsdAttribute], node.value)
comp = cast(FieldDecoderType, node.value)
self.decoders.append(comp)
value_constraint = comp.value_constraint
if value_constraint is not None:
self.value_constraints[node.name] = comp.type.text_decode(value_constraint)
if isinstance(comp, XsdAttribute):
self.value_constraints[None] = self.value_constraints[node.name]
if isinstance(comp, XsdWildcard):
if comp.process_contents == 'skip':
self.skip_wildcard = True
else:
value_constraint = comp.value_constraint
if value_constraint is not None:
self.value_constraints[node.name] = comp.type.text_decode(value_constraint)
if isinstance(comp, XsdAttribute):
self.value_constraints[None] = self.value_constraints[node.name]

if len(self.decoders) > 1 and None in self.value_constraints:
self.value_constraints.pop(None)
Expand All @@ -450,7 +443,6 @@ def get_value(self, element_node: ElementNode,

empty = True
for node in cast(Iterator[IdentityNodeType], self.token.select(context)):

if empty:
empty = False
else:
Expand All @@ -464,7 +456,10 @@ def get_value(self, element_node: ElementNode,
raise XMLSchemaTypeError(msg % (self.field, type(node)))

if xsd_type is None:
value = node.string_value
if self.skip_wildcard:
value = None
else:
value = node.string_value
elif xsd_type.content_type_label not in ('simple', 'mixed'):
msg = _("%r field doesn't have a simple type!")
raise XMLSchemaTypeError(msg % self.field)
Expand All @@ -478,9 +473,10 @@ def get_value(self, element_node: ElementNode,
value = node.typed_value # type: ignore[assignment,unused-ignore]
except (KeyError, ValueError):
for decoder in self.decoders:
if node.match_name(decoder.name):
value = decoder.type.text_decode(node.string_value)
break
if not isinstance(decoder, XsdWildcard):
if decoder.is_matching(node.name):
value = decoder.type.text_decode(node.string_value)
break
else:
value = node.string_value

Expand Down

0 comments on commit 6b4e948

Please sign in to comment.