diff --git a/.coveragerc b/.coveragerc index 4add1e8d..6463262c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,7 +1,9 @@ [run] branch = True source = xmlschema/ -omit = xmlschema/testing/* +omit = + xmlschema/testing/* + xmlschema/aliases.py [report] exclude_lines = diff --git a/tests/test_helpers.py b/tests/test_helpers.py index de7840ae..3c372ba3 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -235,7 +235,7 @@ def test_get_prefixed_qname(self): self.assertEqual(get_prefixed_qname('', namespaces), '') self.assertEqual(get_prefixed_qname(None, namespaces), None) - # self.assertEqual(get_prefixed_qname(0, namespaces), 0) + self.assertEqual(get_prefixed_qname('{uri}element', namespaces), '{uri}element') self.assertEqual(get_prefixed_qname(XSI_TYPE, {}), XSI_TYPE) self.assertEqual(get_prefixed_qname(None, {}), None) diff --git a/tests/test_namespaces.py b/tests/test_namespaces.py index f17c7239..e37d77ef 100644 --- a/tests/test_namespaces.py +++ b/tests/test_namespaces.py @@ -205,6 +205,17 @@ def test_repr(self): ns_view = NamespaceView(qnames, 'tns0') self.assertEqual(repr(ns_view), "NamespaceView({'name0': 0})") + def test_contains(self): + qnames = {'{tns0}name0': 0, '{tns1}name1': 1, 'name2': 2} + ns_view = NamespaceView(qnames, 'tns1') + + self.assertIn('name1', ns_view) + self.assertNotIn('{tns1}name1', ns_view) + self.assertNotIn('{tns0}name0', ns_view) + self.assertNotIn('name0', ns_view) + self.assertNotIn('name2', ns_view) + self.assertNotIn(1, ns_view) + def test_as_dict(self): qnames = {'{tns0}name0': 0, '{tns1}name1': 1, '{tns1}name2': 2, 'name3': 3} ns_view = NamespaceView(qnames, 'tns1') diff --git a/tests/test_resources.py b/tests/test_resources.py index d3579bb4..6451f6c8 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -321,20 +321,39 @@ def test_is_url_function(self): def test_is_local_url_function(self): self.assertTrue(is_local_url(self.col_xsd_file)) + self.assertTrue(is_local_url(Path(self.col_xsd_file))) + self.assertTrue(is_local_url('/home/user/')) + self.assertFalse(is_local_url('')) self.assertTrue(is_local_url('/home/user/schema.xsd')) self.assertTrue(is_local_url(' /home/user/schema.xsd ')) self.assertTrue(is_local_url('C:\\Users\\foo\\schema.xsd')) self.assertTrue(is_local_url(' file:///home/user/schema.xsd')) self.assertFalse(is_local_url('http://example.com/schema.xsd')) + self.assertTrue(is_local_url(b'/home/user/')) + self.assertFalse(is_local_url(b'')) + self.assertTrue(is_local_url(b'/home/user/schema.xsd')) + self.assertTrue(is_local_url(b' /home/user/schema.xsd ')) + self.assertTrue(is_local_url(b'C:\\Users\\foo\\schema.xsd')) + self.assertTrue(is_local_url(b' file:///home/user/schema.xsd')) + self.assertFalse(is_local_url(b'http://example.com/schema.xsd')) + def test_is_remote_url_function(self): self.assertFalse(is_remote_url(self.col_xsd_file)) + self.assertFalse(is_remote_url('/home/user/')) + self.assertFalse(is_remote_url('')) self.assertFalse(is_remote_url('/home/user/schema.xsd')) self.assertFalse(is_remote_url(' file:///home/user/schema.xsd')) self.assertTrue(is_remote_url(' http://example.com/schema.xsd')) + self.assertFalse(is_remote_url(b'/home/user/')) + self.assertFalse(is_remote_url(b'')) + self.assertFalse(is_remote_url(b'/home/user/schema.xsd')) + self.assertFalse(is_remote_url(b' file:///home/user/schema.xsd')) + self.assertTrue(is_remote_url(b' http://example.com/schema.xsd')) + def test_url_path_is_file_function(self): self.assertTrue(url_path_is_file(self.col_xml_file)) self.assertTrue(url_path_is_file(normalize_url(self.col_xml_file))) @@ -449,6 +468,15 @@ def test_xml_resource_from_url(self): with self.assertRaises(XMLResourceError): resource.load() + def test_xml_resource_from_url_in_bytes(self): + resource = XMLResource(self.vh_xml_file.encode('utf-8'), lazy=False) + self.assertEqual(resource.source, self.vh_xml_file.encode('utf-8')) + self.assertEqual(resource.root.tag, '{http://example.com/vehicles}vehicles') + self.check_url(resource.url, self.vh_xml_file) + self.assertIsNone(resource.text) + resource.load() + self.assertTrue(resource.text.startswith('') + with self.assertRaises(ValueError): + XMLResource(self.vh_xml_file, base_url=b'') + def test_xml_resource_is_local(self): resource = XMLResource(self.vh_xml_file) self.assertTrue(resource.is_local()) diff --git a/tests/validators/test_particles.py b/tests/validators/test_particles.py index 4b5c3bd7..de738ddb 100644 --- a/tests/validators/test_particles.py +++ b/tests/validators/test_particles.py @@ -120,6 +120,11 @@ def test_has_occurs_restriction(self): self.assertTrue(xsd_group[9].has_occurs_restriction(xsd_group[1])) self.assertTrue(xsd_group[9].has_occurs_restriction(xsd_group[2])) + def test_default_parse_error(self): + with self.assertRaises(ValueError) as ctx: + ParticleMixin().parse_error('unexpected error') + self.assertEqual(str(ctx.exception), 'unexpected error') + def test_parse_particle(self): schema = XMLSchema10(""" diff --git a/xmlschema/resources.py b/xmlschema/resources.py index ac91dfd0..24a9c40e 100644 --- a/xmlschema/resources.py +++ b/xmlschema/resources.py @@ -890,9 +890,8 @@ def tostring(self, indent: str = '', max_lines: Optional[int] = None, namespaces = self.get_namespaces(root_only=False) _string = etree_tostring(elem, namespaces, indent, max_lines, spaces_for_tab, xml_declaration) - if isinstance(_string, bytes): - return _string.decode('utf-8') - return _string + + return _string.decode('utf-8') if isinstance(_string, bytes) else _string def subresource(self, elem: ElementType) -> 'XMLResource': """Create an XMLResource instance from a subelement of a non-lazy XML tree.""" diff --git a/xmlschema/validators/builtins.py b/xmlschema/validators/builtins.py index f2017a6e..64492665 100644 --- a/xmlschema/validators/builtins.py +++ b/xmlschema/validators/builtins.py @@ -15,7 +15,7 @@ """ from decimal import Decimal from elementpath import datatypes -from typing import Any, Dict, Optional, Type, Tuple, Union +from typing import cast, Any, Dict, Optional, Type, Tuple, Union from ..exceptions import XMLSchemaValueError from ..names import XSD_LENGTH, XSD_MIN_LENGTH, XSD_MAX_LENGTH, XSD_ENUMERATION, \ @@ -83,7 +83,7 @@ ) -XSD_COMMON_BUILTIN_TYPES = ( +XSD_COMMON_BUILTIN_TYPES: Tuple[Dict[str, Any], ...] = ( # *********************** # *** Primitive types *** # *********************** @@ -491,15 +491,12 @@ def xsd_builtin_types_factory( item = item.copy() name: str = item['name'] try: - value = xsd_types[name] + value = cast(Tuple[ElementType, SchemaType], xsd_types[name]) except KeyError: # If builtin type element is missing create a dummy element. Necessary for the # meta-schema XMLSchema.xsd of XSD 1.1, that not includes builtins declarations. elem = etree_element(XSD_SIMPLE_TYPE, name=name, id=name) else: - if not isinstance(value, tuple): - continue - elem, schema = value if schema is not meta_schema: raise XMLSchemaValueError("loaded entry schema is not the meta-schema!") diff --git a/xmlschema/validators/xsdbase.py b/xmlschema/validators/xsdbase.py index 5a5a6556..5cad9f9d 100644 --- a/xmlschema/validators/xsdbase.py +++ b/xmlschema/validators/xsdbase.py @@ -466,7 +466,7 @@ def _parse_target_namespace(self) -> None: "must have the same namespace as its parent schema") if self.name is None: - pass + pass # pragma: no cover elif not self._target_namespace: self.name = local_name(self.name) else: @@ -581,7 +581,7 @@ def get_global(self) -> 'XsdComponent': return component component = component.parent else: - return self + raise XMLSchemaValueError(f"parent circularity from {self}") # pragma: no cover def get_parent_type(self) -> Optional['XsdType']: """ @@ -745,7 +745,7 @@ def simple_type(self) -> Optional['XsdSimpleType']: complexType is the instance's *content* if this is a simpleType or `None` if the instance's *content* is a model group. """ - return None + raise NotImplementedError() @property def model_group(self) -> Optional['XsdGroup']: @@ -968,7 +968,7 @@ def decode(self, obj: ST, validation: str = 'strict', **kwargs: Any) -> DecodeTy else: errors.append(result) - return (None, errors) if validation == 'lax' else None + return (None, errors) if validation == 'lax' else None # fallback: pragma: no cover def encode(self, obj: Any, validation: str = 'strict', **kwargs: Any) -> EncodeType[Any]: """