Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-xmlschema for openSUSE:Factory checked in at 2023-02-11 22:20:05 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-xmlschema (Old) and /work/SRC/openSUSE:Factory/.python-xmlschema.new.1848 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-xmlschema" Sat Feb 11 22:20:05 2023 rev:19 rq:1064241 version:2.2.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-xmlschema/python-xmlschema.changes 2022-10-04 20:37:17.748879628 +0200 +++ /work/SRC/openSUSE:Factory/.python-xmlschema.new.1848/python-xmlschema.changes 2023-02-11 22:20:07.168048762 +0100 @@ -1,0 +2,11 @@ +Fri Feb 10 12:46:13 UTC 2023 - Dirk Müller <dmuel...@suse.com> + +- update to 2.2.0: + * Refine string serialization of XML resources and data + elements + * Switch to use elementpath v4 + * Fix sequence_type property for XSD types + * Remove *XsdElement.get_attribute()*: unused and doesn't work + as expected + +------------------------------------------------------------------- Old: ---- xmlschema-2.1.1.tar.gz New: ---- xmlschema-2.2.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-xmlschema.spec ++++++ --- /var/tmp/diff_new_pack.vp5zlv/_old 2023-02-11 22:20:07.740052262 +0100 +++ /var/tmp/diff_new_pack.vp5zlv/_new 2023-02-11 22:20:07.756052360 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-xmlschema # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-xmlschema -Version: 2.1.1 +Version: 2.2.0 Release: 0 Summary: An XML Schema validator and decoder License: MIT ++++++ xmlschema-2.1.1.tar.gz -> xmlschema-2.2.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/CHANGELOG.rst new/xmlschema-2.2.0/CHANGELOG.rst --- old/xmlschema-2.1.1/CHANGELOG.rst 2022-10-01 15:42:01.000000000 +0200 +++ new/xmlschema-2.2.0/CHANGELOG.rst 2023-02-06 07:20:42.000000000 +0100 @@ -2,6 +2,13 @@ CHANGELOG ********* +`v2.2.0`_ (2023-02-06) +====================== +* Refine string serialization of XML resources and data elements +* Switch to use elementpath v4 +* Fix sequence_type property for XSD types +* Remove *XsdElement.get_attribute()*: unused and doesn't work as expected + `v2.1.1`_ (2022-10-01) ====================== * Fix *schema_path* usage in `XMLSchemaBase.iter_errors()` @@ -591,3 +598,4 @@ .. _v2.0.4: https://github.com/brunato/xmlschema/compare/v2.0.3...v2.0.4 .. _v2.1.0: https://github.com/brunato/xmlschema/compare/v2.0.4...v2.1.0 .. _v2.1.1: https://github.com/brunato/xmlschema/compare/v2.1.0...v2.1.1 +.. _v2.2.0: https://github.com/brunato/xmlschema/compare/v2.1.1...v2.2.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/PKG-INFO new/xmlschema-2.2.0/PKG-INFO --- old/xmlschema-2.1.1/PKG-INFO 2022-10-01 19:02:18.985521600 +0200 +++ new/xmlschema-2.2.0/PKG-INFO 2023-02-06 10:06:40.856029000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: xmlschema -Version: 2.1.1 +Version: 2.2.0 Summary: An XML Schema validator and decoder Home-page: https://github.com/sissaschool/xmlschema Author: Davide Brunato diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/doc/conf.py new/xmlschema-2.2.0/doc/conf.py --- old/xmlschema-2.1.1/doc/conf.py 2022-10-01 15:42:01.000000000 +0200 +++ new/xmlschema-2.2.0/doc/conf.py 2023-02-06 07:20:42.000000000 +0100 @@ -79,9 +79,9 @@ # built documents. # # The short X.Y version. -version = '2.1' +version = '2.2' # The full version, including alpha/beta/rc tags. -release = '2.1.1' +release = '2.2.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/requirements-dev.txt new/xmlschema-2.2.0/requirements-dev.txt --- old/xmlschema-2.1.1/requirements-dev.txt 2022-07-18 16:19:15.000000000 +0200 +++ new/xmlschema-2.2.0/requirements-dev.txt 2023-02-06 07:20:42.000000000 +0100 @@ -1,8 +1,8 @@ # Requirements for setup a development environment for the xmlschema package. setuptools -tox +tox>=4.0 coverage -elementpath>=3.0.0, <4.0.0 +elementpath>=4.0.0, <5.0.0 lxml jinja2 memory_profiler diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/setup.py new/xmlschema-2.2.0/setup.py --- old/xmlschema-2.1.1/setup.py 2022-10-01 15:42:01.000000000 +0200 +++ new/xmlschema-2.2.0/setup.py 2023-02-06 07:20:42.000000000 +0100 @@ -18,7 +18,7 @@ setup( name='xmlschema', - version='2.1.1', + version='2.2.0', packages=find_packages(include=['xmlschema*']), package_data={ 'xmlschema': ['py.typed', 'locale/**/*.mo', 'locale/**/*.po', 'schemas/*/*.xsd'], @@ -32,13 +32,13 @@ ] }, python_requires='>=3.7', - install_requires=['elementpath>=3.0.0, <4.0.0'], + install_requires=['elementpath>=4.0.0, <5.0.0'], extras_require={ - 'codegen': ['elementpath>=3.0.0, <4.0.0', 'jinja2'], - 'dev': ['tox', 'coverage', 'lxml', 'elementpath>=3.0.0, <4.0.0', + 'codegen': ['elementpath>=4.0.0, <5.0.0', 'jinja2'], + 'dev': ['tox', 'coverage', 'lxml', 'elementpath>=4.0.0, <5.0.0', 'memory_profiler', 'Sphinx', 'sphinx_rtd_theme', 'jinja2', 'flake8', 'mypy', 'lxml-stubs'], - 'docs': ['elementpath>=3.0.0, <4.0.0', 'Sphinx', 'sphinx_rtd_theme', 'jinja2'] + 'docs': ['elementpath>=4.0.0, <5.0.0', 'Sphinx', 'sphinx_rtd_theme', 'jinja2'] }, author='Davide Brunato', author_email='brun...@sissa.it', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/tests/test_dataobjects.py new/xmlschema-2.2.0/tests/test_dataobjects.py --- old/xmlschema-2.1.1/tests/test_dataobjects.py 2022-07-21 11:40:50.000000000 +0200 +++ new/xmlschema-2.2.0/tests/test_dataobjects.py 2023-02-06 09:55:27.000000000 +0100 @@ -14,8 +14,10 @@ from typing import Dict from xmlschema import XMLSchema10, XMLSchema11, fetch_namespaces, etree_tostring, \ - XMLSchemaValidationError, DataElement, DataElementConverter, XMLResource + XMLSchemaValidationError, DataElement, DataElementConverter, XMLResource, \ + XsdElement, XsdAttribute, XsdType +from xmlschema.validators import XsdAttributeGroup from xmlschema.helpers import is_etree_element from xmlschema.names import XSI_TYPE from xmlschema.dataobjects import DataBindingMeta, DataBindingConverter @@ -45,10 +47,11 @@ self.assertIsNone(data_element.get('a')) self.assertEqual(data_element.get('b'), 9) - def test_namespaces(self): + def test_nsmap(self): self.assertEqual(DataElement('foo').nsmap, {}) nsmap = {'tns': 'http://xmlschema.test/ns'} self.assertEqual(DataElement('foo', nsmap=nsmap).nsmap, nsmap) + self.assertIsNot(DataElement('foo', nsmap=nsmap).nsmap, nsmap) def test_attributes_with_namespaces(self): nsmap = {'tns': 'http://xmlschema.test/ns'} @@ -265,12 +268,72 @@ self.assertIsInstance(etree_tostring(obj), str) self.assertIsNone(etree_elements_assert_equal(obj, root, strict=False)) + def test_collapsed_namespace_map(self): + col_data = self.col_schema.decode(self.col_xml_filename) + + namespaces = col_data.get_namespaces() + self.assertDictEqual( + namespaces, + {'col': 'http://example.com/ns/collection', + 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'} + ) + + namespaces = col_data.get_namespaces({'': 'http://xmlschema.test/ns'}) + self.assertDictEqual( + namespaces, + {'': 'http://xmlschema.test/ns', + 'col': 'http://example.com/ns/collection', + 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'} + ) + + namespaces = col_data.get_namespaces({'tns': 'http://xmlschema.test/ns'}) + self.assertDictEqual( + namespaces, + {'tns': 'http://xmlschema.test/ns', + 'col': 'http://example.com/ns/collection', + 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'} + ) + + namespaces = col_data.get_namespaces({'xsi': 'http://xmlschema.test/ns'}) + self.assertDictEqual( + namespaces, + {'xsi': 'http://xmlschema.test/ns', + 'col': 'http://example.com/ns/collection', + 'xsi0': 'http://www.w3.org/2001/XMLSchema-instance'} + ) + + xsd_filename = self.casepath('examples/collection/collection5.xsd') + col_schema = self.schema_class(xsd_filename, converter=self.converter) + xml_filename = self.casepath('examples/collection/collection-default.xml') + col_data = col_schema.decode(xml_filename) + + namespaces = col_data.get_namespaces() + self.assertDictEqual( + namespaces, + {'': 'http://example.com/ns/collection', + 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'} + ) + + namespaces = col_data.get_namespaces({'': 'http://xmlschema.test/ns'}) + self.assertDictEqual( + namespaces, + {'': 'http://xmlschema.test/ns', + 'default': 'http://example.com/ns/collection', + 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'} + ) + def test_serialize_to_xml_source(self): col_data = self.col_schema.decode(self.col_xml_filename) - xml_source = col_data.tostring() - self.assertTrue(xml_source.startswith('<col:collection ')) - self.assertTrue(xml_source.endswith('</col:collection>')) + with Path(self.col_xml_filename).open() as fp: + _ = fp.read() + + result = col_data.tostring() + self.assertTrue(result.startswith('<col:collection ')) + self.assertTrue(result.endswith('</col:collection>')) + + result = col_data.tostring(xml_declaration=True) + self.assertTrue(self.col_schema.is_valid(result)) def test_validation(self): with self.assertRaises(ValueError) as ec: @@ -433,6 +496,21 @@ self.assertEqual(data_element[0][0].get('b:type'), 'p:ConcreteContainterItemInfo') self.assertIsNone(data_element[0][0].get('xsi:type')) + def test_xsd_attribute_access__issue_331(self): + col_data = self.col_schema.decode(self.col_xml_filename) + self.assertIsInstance(col_data[0].xsd_element, XsdElement) + self.assertEqual(col_data[0].xsd_element.name, 'object') + self.assertIsInstance( + col_data[0].xsd_element.attributes, XsdAttributeGroup + ) + xsd_attribute = col_data[0].xsd_element.attributes.get('id') + self.assertIsInstance(xsd_attribute, XsdAttribute) + + xsd_attribute = col_data[0].xsd_element.find('@id') + self.assertIsInstance(xsd_attribute, XsdAttribute) + self.assertIsInstance(xsd_attribute.type, XsdType) + self.assertIsNone(col_data[0].xsd_element.find('@unknown')) + class TestDataBindings(TestDataObjects): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/tests/test_documents.py new/xmlschema-2.2.0/tests/test_documents.py --- old/xmlschema-2.1.1/tests/test_documents.py 2022-09-25 09:58:42.000000000 +0200 +++ new/xmlschema-2.2.0/tests/test_documents.py 2023-02-06 07:20:42.000000000 +0100 @@ -458,7 +458,7 @@ xml_document = XmlDocument(self.col_xml_file, lazy=True) with self.assertRaises(XMLResourceError) as ctx: xml_document.write(str(col_file_path)) - self.assertEqual(str(ctx.exception), "cannot serialize a lazy XML document") + self.assertEqual(str(ctx.exception), "cannot serialize a lazy XML resource") def test_xml_document_etree_interface(self): xml_document = XmlDocument(self.vh_xml_file) @@ -471,7 +471,8 @@ xml_document = XmlDocument(self.vh_xml_file, lazy=1) with self.assertRaises(XMLResourceError) as ctx: xml_document.get_etree_document() - self.assertIn('cannot create an ElementTree from a lazy resource', str(ctx.exception)) + self.assertIn('cannot create an ElementTree instance from a lazy XML resource', + str(ctx.exception)) vh_tree = ElementTree.parse(self.vh_xml_file) xml_document = XmlDocument(vh_tree, base_url=self.vh_dir) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/tests/test_resources.py new/xmlschema-2.2.0/tests/test_resources.py --- old/xmlschema-2.1.1/tests/test_resources.py 2022-07-18 16:19:15.000000000 +0200 +++ new/xmlschema-2.2.0/tests/test_resources.py 2023-02-06 07:20:42.000000000 +0100 @@ -43,6 +43,10 @@ DRIVE_REGEX = '/[a-zA-Z]:' if platform.system() == 'Windows' else '' +XML_WITH_NAMESPACES = '<pfa:root xmlns:pfa="http://xmlschema.test/nsa">\n' \ + ' <pfb:elem xmlns:pfb="http://xmlschema.test/nsb"/>\n' \ + '</pfa:root>' + def casepath(relative_path): return str(pathlib.Path(TEST_CASES_DIR).joinpath(relative_path)) @@ -456,7 +460,7 @@ self.assertIsNone(resource.text) with self.assertRaises(XMLResourceError) as ctx: resource.load() - self.assertIn('cannot load a lazy resource', str(ctx.exception)) + self.assertIn('cannot load a lazy XML resource', str(ctx.exception)) self.assertIsNone(resource.text) resource = XMLResource(self.vh_xml_file, lazy=False) @@ -492,7 +496,7 @@ self.assertIsNone(resource.text) with self.assertRaises(XMLResourceError) as ctx: resource.load() - self.assertIn('cannot load a lazy resource', str(ctx.exception)) + self.assertIn('cannot load a lazy XML resource', str(ctx.exception)) self.assertIsNone(resource.text) resource = XMLResource(path, lazy=False) @@ -605,7 +609,7 @@ with self.assertRaises(XMLResourceError) as ctx: resource.load() - self.assertEqual("cannot load a lazy resource", str(ctx.exception)) + self.assertEqual("cannot load a lazy XML resource", str(ctx.exception)) self.assertFalse(schema_file.closed) for _ in resource.iter(): @@ -962,7 +966,24 @@ resource = XMLResource(self.vh_xml_file, lazy=True) with self.assertRaises(XMLResourceError) as ctx: resource.tostring() - self.assertEqual("cannot serialize a lazy resource", str(ctx.exception)) + self.assertEqual("cannot serialize a lazy XML resource", str(ctx.exception)) + + resource = XMLResource(XML_WITH_NAMESPACES) + result = resource.tostring() + self.assertNotEqual(result, XML_WITH_NAMESPACES) + + # With xml.etree.ElementTree namespace declarations are serialized + # with a loss of information (all collapsed into the root element). + self.assertEqual(result, '<pfa:root xmlns:pfa="http://xmlschema.test/nsa" ' + 'xmlns:pfb="http://xmlschema.test/nsb">\n' + ' <pfb:elem />\n</pfa:root>') + + if lxml_etree is not None: + root = lxml_etree.XML(XML_WITH_NAMESPACES) + resource = XMLResource(root) + + # With lxml.etree there is no information loss. + self.assertEqual(resource.tostring(), XML_WITH_NAMESPACES) def test_xml_resource_open(self): resource = XMLResource(self.vh_xml_file) @@ -1459,7 +1480,8 @@ resource = XMLResource(StringIO('<a><b1><c1/><c2/></b1><b2/></a>'), lazy=True) with self.assertRaises(XMLResourceError) as ctx: _ = resource.parent_map - self.assertEqual("cannot create the parent map of a lazy resource", str(ctx.exception)) + self.assertEqual("cannot create the parent map of a lazy XML resource", + str(ctx.exception)) def test_get_nsmap(self): source = '<a xmlns="uri1"><b1 xmlns:x="uri2"><c1/><c2/></b1><b2 xmlns="uri3"/></a>' @@ -1502,7 +1524,8 @@ resource = XMLResource(self.vh_xml_file, lazy=True) with self.assertRaises(XMLResourceError) as ctx: resource.subresource(resource.root) - self.assertEqual("cannot create a subresource from a lazy resource", str(ctx.exception)) + self.assertEqual("cannot create a subresource from a lazy XML resource", + str(ctx.exception)) resource = XMLResource(self.vh_xml_file) root = resource.root diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/tests/validation/test_decoding.py new/xmlschema-2.2.0/tests/validation/test_decoding.py --- old/xmlschema-2.1.1/tests/validation/test_decoding.py 2022-08-26 17:33:28.000000000 +0200 +++ new/xmlschema-2.2.0/tests/validation/test_decoding.py 2023-02-06 07:20:42.000000000 +0100 @@ -866,8 +866,8 @@ self.assertIsInstance(obj, str) obj = xs.decode('<hex> 9AFD </hex>', binary_types=True) - self.assertEqual(obj, '9AFD') self.assertIsInstance(obj, datatypes.HexBinary) + self.assertEqual(obj.value, b'9AFD') xs = self.get_schema('<xs:attribute name="hex" type="xs:hexBinary"/>') @@ -876,8 +876,8 @@ self.assertIsInstance(obj, str) obj = xs.attributes['hex'].decode(' 9AFD ', binary_types=True) - self.assertEqual(obj, '9AFD') self.assertIsInstance(obj, datatypes.HexBinary) + self.assertEqual(obj.value, b'9AFD') def test_base64_binary_type(self): base64_code_type = self.st_schema.types['base64Code'] @@ -891,7 +891,7 @@ xs = self.get_schema('<xs:attribute name="b64" type="xs:base64Binary"/>') obj = xs.attributes['b64'].decode(base64_value.decode()) - self.assertEqual(obj, expected_value) + self.assertEqual(obj, str(expected_value)) self.assertIsInstance(obj, str) obj = xs.attributes['b64'].decode(base64_value.decode(), binary_types=True) @@ -902,7 +902,7 @@ xs = self.get_schema('<xs:element name="b64" type="xs:base64Binary"/>') obj = xs.decode('<b64>{}</b64>'.format(base64_value.decode())) - self.assertEqual(obj, expected_value) + self.assertEqual(obj, str(expected_value)) self.assertIsInstance(obj, str) obj = xs.decode('<b64>{}</b64>'.format(base64_value.decode()), binary_types=True) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/tests/validators/test_identities.py new/xmlschema-2.2.0/tests/validators/test_identities.py --- old/xmlschema-2.1.1/tests/validators/test_identities.py 2022-07-18 16:19:15.000000000 +0200 +++ new/xmlschema-2.2.0/tests/validators/test_identities.py 2023-02-06 07:20:42.000000000 +0100 @@ -122,7 +122,7 @@ </xs:key> </xs:element>""") - self.assertIn("a QName cannot contains spaces", ctx.exception.message) + self.assertIn("XPST0003", ctx.exception.message) def test_selector_target_namespace(self): schema = self.check_schema(""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/tox.ini new/xmlschema-2.2.0/tox.ini --- old/xmlschema-2.1.1/tox.ini 2022-10-01 15:42:01.000000000 +0200 +++ new/xmlschema-2.2.0/tox.ini 2023-02-06 07:20:42.000000000 +0100 @@ -1,28 +1,28 @@ [tox] -envlist = py{37,38,39,310,311}, pypy3, ep{300}, docs, +envlist = py{37,38,39,310,311}, pypy3, ep{40}, docs, flake8, mypy-py{37,38,39,310,311}, coverage, pytest skip_missing_interpreters = true -toxworkdir = {homedir}/.tox/xmlschema +work_dir = {tox_root}/../.tox/xmlschema [testenv] deps = - elementpath>=3.0.0, <4.0.0 + elementpath>=4.0.0, <5.0.0 lxml jinja2 - py{39,310}: memory_profiler + py{310,311}: memory_profiler docs: Sphinx docs: sphinx_rtd_theme coverage: coverage commands = python -m unittest -whitelist_externals = make +allowlist_externals = make [testenv:pypy3] commands = python -m unittest -[testenv:ep300] +[testenv:ep40] deps = - elementpath~=3.0.0 + elementpath~=4.0.0 lxml [testenv:docs] @@ -44,8 +44,8 @@ [testenv:mypy-py37] deps = - mypy==0.981 - elementpath==3.0.1 + mypy==0.991 + elementpath==4.0.1 lxml-stubs jinja2 commands = @@ -53,8 +53,8 @@ [testenv:mypy-py{38,39,310,311}] deps = - mypy==0.981 - elementpath==3.0.1 + mypy==0.991 + elementpath==4.0.1 lxml-stubs jinja2 commands = @@ -71,10 +71,10 @@ deps = pytest pytest-randomly - elementpath>=3.0.0, <4.0.0 + elementpath>=4.0.0, <5.0.0 lxml jinja2 - mypy==0.981 + mypy==0.991 lxml-stubs commands = pytest tests -ra diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema/__init__.py new/xmlschema-2.2.0/xmlschema/__init__.py --- old/xmlschema-2.1.1/xmlschema/__init__.py 2022-10-01 15:42:01.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema/__init__.py 2023-02-06 07:20:42.000000000 +0100 @@ -31,10 +31,10 @@ XsdComponent, XsdType, XsdElement, XsdAttribute ) -__version__ = '2.1.1' +__version__ = '2.2.0' __author__ = "Davide Brunato" __contact__ = "brun...@sissa.it" -__copyright__ = "Copyright 2016-2022, SISSA" +__copyright__ = "Copyright 2016-2023, SISSA" __license__ = "MIT" __status__ = "Production/Stable" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema/dataobjects.py new/xmlschema-2.2.0/xmlschema/dataobjects.py --- old/xmlschema-2.1.1/xmlschema/dataobjects.py 2022-07-21 11:40:50.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema/dataobjects.py 2023-02-06 09:54:57.000000000 +0100 @@ -7,7 +7,9 @@ # # @author Davide Brunato <brun...@sissa.it> # +import re from abc import ABCMeta +from copy import copy from itertools import count from typing import TYPE_CHECKING, cast, overload, Any, Dict, List, Iterator, \ Optional, Union, Tuple, Type, MutableMapping, MutableSequence @@ -188,6 +190,71 @@ """The local part of the tag.""" return local_name(self.tag) + def iter(self, tag: Optional[str] = None) -> Iterator['DataElement']: + """ + Creates an iterator for the data element and its subelements. If tag + is not `None` or '*', only data elements whose matches tag are returned + from the iterator. + """ + if tag == '*': + tag = None + if tag is None or tag == self.tag: + yield self + for child in self._children: + yield from child.iter(tag) + + def iterchildren(self, tag: Optional[str] = None) -> Iterator['DataElement']: + """ + Creates an iterator for the child data elements. If *tag* is not `None` or '*', + only data elements whose name matches tag are returned from the iterator. + """ + if tag == '*': + tag = None + for child in self: + if tag is None or tag == child.tag: + yield child + + def get_namespaces(self, namespaces: Optional[NamespacesType] = None) -> NamespacesType: + """ + Returns an overall namespace map for DetaElement and its descendants, + resolving prefix redefinitions. + + :param namespaces: builds the namespace map starting over the dictionary provided. + """ + namespaces = copy(namespaces) if namespaces is not None else {} + nsmap = None + + for elem in self.iter(): + if nsmap is elem.nsmap: + continue + else: + nsmap = elem.nsmap + for prefix, uri in nsmap.items(): + if not prefix: + if not uri: + continue + elif '' not in namespaces: + if self.namespace: + namespaces[prefix] = uri + continue + elif namespaces[''] == uri: + continue + prefix = 'default' + + while prefix in namespaces: + if namespaces[prefix] == uri: + break + match = re.search(r'(\d+)$', prefix) + if match: + index = int(match.group()) + 1 + prefix = prefix[:match.span()[0]] + str(index) + else: + prefix += '0' + else: + namespaces[prefix] = uri + + return namespaces + def validate(self, use_defaults: bool = True, namespaces: Optional[NamespacesType] = None, max_depth: Optional[int] = None) -> None: @@ -228,11 +295,10 @@ raise XMLSchemaValueError("%r has no schema bindings" % self) kwargs: Dict[str, Any] = { + 'namespaces': self.get_namespaces(namespaces), 'converter': DataElementConverter, 'use_defaults': use_defaults, } - if namespaces: - kwargs['namespaces'] = namespaces if isinstance(max_depth, int) and max_depth >= 0: kwargs['max_depth'] = max_depth @@ -256,6 +322,7 @@ :raises: :exc:`XMLSchemaValidationError` if the object is invalid \ and ``validation='strict'``. """ + kwargs['namespaces'] = self.get_namespaces(kwargs.get('namespaces')) if 'converter' not in kwargs: kwargs['converter'] = DataElementConverter @@ -271,11 +338,44 @@ to_etree = encode - def tostring(self, indent: str = '', max_lines: Optional[int] = None, - spaces_for_tab: int = 4) -> Any: - """Serializes the data element tree to an XML source string.""" - root, errors = self.encode(validation='lax') - return etree_tostring(root, self.nsmap, indent, max_lines, spaces_for_tab) + def tostring(self, namespaces: Optional[MutableMapping[str, str]] = None, + indent: str = '', max_lines: Optional[int] = None, + spaces_for_tab: int = 4, xml_declaration: bool = False, + encoding: str = 'unicode', method: str = 'xml') -> str: + """ + Serializes the data element tree to an XML source string. + + :param namespaces: is an optional mapping from namespace prefix to URI. \ + Provided namespaces are registered before serialization. Ignored if the \ + provided *elem* argument is a lxml Element instance. + :param indent: the base line indentation. + :param max_lines: if truncate serialization after a number of lines \ + (default: do not truncate). + :param spaces_for_tab: number of spaces for replacing tab characters. For \ + default tabs are replaced with 4 spaces, provide `None` to keep tab characters. + :param xml_declaration: if set to `True` inserts the XML declaration at the head. + :param encoding: if "unicode" (the default) the output is a string, \ + otherwise itâs binary. + :param method: is either "xml" (the default), "html" or "text". + :return: a Unicode string. + """ + root, _ = self.encode(validation='lax') + if not hasattr(root, 'nsmap'): + namespaces = self.get_namespaces(namespaces) + + _string = etree_tostring( + elem=root, + namespaces=namespaces, + indent=indent, + max_lines=max_lines, + spaces_for_tab=spaces_for_tab, + xml_declaration=xml_declaration, + encoding=encoding, + method=method + ) + if isinstance(_string, bytes): + return _string.decode('utf-8') + return _string def _get_xpath_context(self) -> XPathContext: xpath_root = build_node_tree(cast(protocols.ElementProtocol, self)) @@ -326,30 +426,6 @@ results = parser.parse(path).select_results(context) yield from filter(lambda x: isinstance(x, DataElement), results) - def iter(self, tag: Optional[str] = None) -> Iterator['DataElement']: - """ - Creates an iterator for the data element and its subelements. If tag - is not `None` or '*', only data elements whose matches tag are returned - from the iterator. - """ - if tag == '*': - tag = None - if tag is None or tag == self.tag: - yield self - for child in self._children: - yield from child.iter(tag) - - def iterchildren(self, tag: Optional[str] = None) -> Iterator['DataElement']: - """ - Creates an iterator for the child data elements. If *tag* is not `None` or '*', - only data elements whose name matches tag are returned from the iterator. - """ - if tag == '*': - tag = None - for child in self: - if tag is None or tag == child.tag: - yield child - class DataBindingMeta(ABCMeta): """Metaclass for creating classes with bindings to XSD elements.""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema/documents.py new/xmlschema-2.2.0/xmlschema/documents.py --- old/xmlschema-2.1.1/xmlschema/documents.py 2022-09-25 09:58:42.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema/documents.py 2023-02-06 07:20:42.000000000 +0100 @@ -8,6 +8,7 @@ # @author Davide Brunato <brun...@sissa.it> # import json +import copy from io import IOBase, TextIOBase from typing import Any, Dict, List, Optional, Type, Union, Tuple, \ IO, BinaryIO, TextIO, Iterator @@ -616,7 +617,7 @@ def parse(self, source: XMLSourceType, lazy: LazyType = False) -> None: super(XmlDocument, self).parse(source, lazy) - self.namespaces = self.get_namespaces(self._namespaces) + self.namespaces = self.get_namespaces() if self.schema is None: pass @@ -625,40 +626,38 @@ elif self.validation == 'lax': self.errors = [e for e in self.schema.iter_errors(self, namespaces=self.namespaces)] + def get_namespaces(self, namespaces: Optional[NamespacesType] = None, + root_only: Optional[bool] = None) -> NamespacesType: + if not self._namespaces: + _namespaces = namespaces + elif not namespaces: + _namespaces = self._namespaces + else: + _namespaces = copy.copy(self._namespaces) + _namespaces.update(namespaces) + + return super().get_namespaces(_namespaces, root_only) + def getroot(self) -> ElementType: """Get the root element of the XML document.""" return self._root def get_etree_document(self) -> Any: """ - The resource as ElementTree XML document. If the resource is lazy raises a resource error. + The resource as ElementTree XML document. If the resource is lazy + raises a resource error. """ if is_etree_document(self._source): return self._source elif self._lazy: - raise XMLResourceError("cannot create an ElementTree from a lazy resource") + raise XMLResourceError( + "cannot create an ElementTree instance from a lazy XML resource" + ) elif hasattr(self._root, 'nsmap'): return self._root.getroottree() # type: ignore[attr-defined] else: return ElementTree.ElementTree(self._root) - def tostring(self, indent: str = '', max_lines: Optional[int] = None, - spaces_for_tab: int = 4, xml_declaration: bool = False, - encoding: str = 'unicode', method: str = 'xml') -> str: - if self._lazy: - raise XMLResourceError("cannot serialize a lazy XML document") - - _string = etree_tostring( - elem=self._root, - namespaces=self.namespaces, - xml_declaration=xml_declaration, - encoding=encoding, - method=method - ) - if isinstance(_string, bytes): - return _string.decode('utf-8') - return _string - def decode(self, **kwargs: Any) -> DecodeType[Any]: """ Decode the XML document to a nested Python dictionary. @@ -731,7 +730,7 @@ default_namespace: Optional[str] = None, method: str = "xml") -> None: """Serialize an XML resource to a file. Cannot be used with lazy resources.""" if self._lazy: - raise XMLResourceError("cannot serialize a lazy XML document") + raise XMLResourceError("cannot serialize a lazy XML resource") kwargs: Dict[str, Any] = { 'xml_declaration': xml_declaration, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema/resources.py new/xmlschema-2.2.0/xmlschema/resources.py --- old/xmlschema-2.1.1/xmlschema/resources.py 2022-09-08 12:16:11.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema/resources.py 2023-02-06 07:20:42.000000000 +0100 @@ -27,7 +27,7 @@ from .exceptions import XMLSchemaTypeError, XMLSchemaValueError, XMLResourceError from .names import XML_NAMESPACE -from .aliases import ElementType, ElementTreeType, NamespacesType, XMLSourceType, \ +from .aliases import ElementType, NamespacesType, XMLSourceType, \ NormalizedLocationsType, LocationsType, NsmapType, ParentMapType from .helpers import get_namespace, is_etree_document, etree_iter_location_hints @@ -536,15 +536,15 @@ if self._allow == 'all': return elif self._allow == 'none': - raise XMLResourceError("block access to resource {}".format(url)) + raise XMLResourceError(f"block access to resource {url}") elif self._allow == 'remote': if is_local_url(url): - raise XMLResourceError("block access to local resource {}".format(url)) + raise XMLResourceError(f"block access to local resource {url}") elif is_remote_url(url): - raise XMLResourceError("block access to remote resource {}".format(url)) + raise XMLResourceError(f"block access to remote resource {url}") elif self._allow == 'sandbox' and self._base_url is not None: if not url.startswith(normalize_url(self._base_url)): - raise XMLResourceError("block access to out of sandbox file {}".format(url)) + raise XMLResourceError(f"block access to out of sandbox file {url}") def _track_nsmap(self, elements: Iterator[ElementType], nsmap: NsmapType) -> Iterator[ElementType]: @@ -793,7 +793,7 @@ self._root = cast(ElementType, source) elif is_etree_document(source): # Could be only an ElementTree object at last - self._root = cast(ElementTreeType, source).getroot() + self._root = source.getroot() else: raise XMLSchemaTypeError( "wrong type %r for 'source' attribute: an ElementTree object or " @@ -827,7 +827,7 @@ @property def parent_map(self) -> Dict[ElementType, Optional[ElementType]]: if self._lazy: - raise XMLResourceError("cannot create the parent map of a lazy resource") + raise XMLResourceError("cannot create the parent map of a lazy XML resource") if self._parent_map is None: assert self._root is not None self._parent_map = {child: elem for elem in self._root.iter() for child in elem} @@ -917,23 +917,51 @@ return self.tostring(xml_declaration=True) - def tostring(self, indent: str = '', max_lines: Optional[int] = None, - spaces_for_tab: int = 4, xml_declaration: bool = False) -> str: - """Generates a string representation of the XML resource.""" + def tostring(self, namespaces: Optional[MutableMapping[str, str]] = None, + indent: str = '', max_lines: Optional[int] = None, + spaces_for_tab: int = 4, xml_declaration: bool = False, + encoding: str = 'unicode', method: str = 'xml') -> str: + """ + Serialize an XML resource to a string. + + :param namespaces: is an optional mapping from namespace prefix to URI. \ + Provided namespaces are registered before serialization. Ignored if the \ + provided *elem* argument is a lxml Element instance. + :param indent: the base line indentation. + :param max_lines: if truncate serialization after a number of lines \ + (default: do not truncate). + :param spaces_for_tab: number of spaces for replacing tab characters. For \ + default tabs are replaced with 4 spaces, provide `None` to keep tab characters. + :param xml_declaration: if set to `True` inserts the XML declaration at the head. + :param encoding: if "unicode" (the default) the output is a string, \ + otherwise itâs binary. + :param method: is either "xml" (the default), "html" or "text". + :return: a Unicode string. + """ if self._lazy: - raise XMLResourceError("cannot serialize a lazy resource") + raise XMLResourceError("cannot serialize a lazy XML resource") - elem = self._root - namespaces = self.get_namespaces(root_only=False) - _string = etree_tostring(elem, namespaces, indent, max_lines, - spaces_for_tab, xml_declaration) + if not hasattr(self._root, 'nsmap'): + namespaces = self.get_namespaces(namespaces) - return _string.decode('utf-8') if isinstance(_string, bytes) else _string + _string = etree_tostring( + elem=self._root, + namespaces=namespaces, + indent=indent, + max_lines=max_lines, + spaces_for_tab=spaces_for_tab, + xml_declaration=xml_declaration, + encoding=encoding, + method=method + ) + if isinstance(_string, bytes): + return _string.decode('utf-8') + return _string def subresource(self, elem: ElementType) -> 'XMLResource': """Create an XMLResource instance from a subelement of a non-lazy XML tree.""" if self._lazy: - raise XMLResourceError("cannot create a subresource from a lazy resource") + raise XMLResourceError("cannot create a subresource from a lazy XML resource") for e in self._root.iter(): # pragma: no cover if e is elem: @@ -969,7 +997,7 @@ if self.seek(0) == 0: return cast(IO[AnyStr], self._source) elif self._url is None: - raise XMLResourceError("can't open, the resource has no URL associated.") + raise XMLResourceError(f"can't open, {self!r} has no URL associated") try: return cast(IO[AnyStr], urlopen(self._url, timeout=self._timeout)) @@ -1013,7 +1041,7 @@ if self._url is None and not hasattr(self._source, 'read'): return # Created from Element or text source --> already loaded elif self._lazy: - raise XMLResourceError("cannot load a lazy resource") + raise XMLResourceError("cannot load a lazy XML resource") resource = self.open() try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema/validators/complex_types.py new/xmlschema-2.2.0/xmlschema/validators/complex_types.py --- old/xmlschema-2.1.1/xmlschema/validators/complex_types.py 2022-09-25 09:58:42.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema/validators/complex_types.py 2023-02-06 07:20:42.000000000 +0100 @@ -15,12 +15,12 @@ from ..names import XSD_GROUP, XSD_ATTRIBUTE_GROUP, XSD_SEQUENCE, XSD_OVERRIDE, \ XSD_ALL, XSD_CHOICE, XSD_ANY_ATTRIBUTE, XSD_ATTRIBUTE, XSD_COMPLEX_CONTENT, \ XSD_RESTRICTION, XSD_COMPLEX_TYPE, XSD_EXTENSION, XSD_ANY_TYPE, XSD_ASSERT, \ - XSD_UNTYPED_ATOMIC, XSD_SIMPLE_CONTENT, XSD_OPEN_CONTENT, XSD_ANNOTATION + XSD_SIMPLE_CONTENT, XSD_OPEN_CONTENT, XSD_ANNOTATION from ..aliases import ElementType, NamespacesType, SchemaType, ComponentClassType, \ DecodeType, IterDecodeType, IterEncodeType, BaseXsdType, AtomicValueType, \ ExtraValidatorType from ..translation import gettext as _ -from ..helpers import get_prefixed_qname, get_qname, local_name +from ..helpers import get_qname, local_name from .exceptions import XMLSchemaDecodeError from .helpers import get_xsd_derivation_attribute @@ -537,15 +537,14 @@ if self.is_empty(): return 'empty-sequence()' elif not self.has_simple_content(): - st = get_prefixed_qname(XSD_UNTYPED_ATOMIC, self.namespaces) + st = 'xs:untypedAtomic' else: try: - st = self.content.primitive_type.prefixed_name # type: ignore[union-attr] + name = self.content.primitive_type.local_name # type: ignore[union-attr] except AttributeError: - st = get_prefixed_qname(XSD_UNTYPED_ATOMIC, self.namespaces) + st = 'xs:untypedAtomic' else: - if st is None: - st = 'item()' + st = 'item()' if name is None else f'xs:{name}' return f"{st}{'*' if self.is_emptiable() else '+'}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema/validators/elements.py new/xmlschema-2.2.0/xmlschema/validators/elements.py --- old/xmlschema-2.1.1/xmlschema/validators/elements.py 2022-10-01 12:20:15.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema/validators/elements.py 2023-02-06 07:20:42.000000000 +0100 @@ -37,7 +37,8 @@ ElementPathMixin, XPathElement from ..resources import XMLResource -from .exceptions import XMLSchemaValidationError, XMLSchemaTypeTableWarning +from .exceptions import XMLSchemaNotBuiltError, XMLSchemaValidationError, \ + XMLSchemaTypeTableWarning from .helpers import get_xsd_derivation_attribute from .xsdbase import XSD_TYPE_DERIVATIONS, XSD_ELEMENT_DERIVATIONS, \ XsdComponent, ValidationMixin @@ -472,15 +473,6 @@ dataobjects.DataBindingMeta(class_name, bases, attrs)) return self.binding - def get_attribute(self, name: str) -> Optional[XsdAttribute]: - if name[0] != '{': - name = get_qname(self.type.target_namespace, name) - if not isinstance(self.type, XsdSimpleType): - xsd_attribute = self.type.attributes[name] - assert isinstance(xsd_attribute, XsdAttribute) - return xsd_attribute - return None - def get_type(self, elem: Union[ElementType, ElementData], inherited: Optional[Dict[str, Any]] = None) -> BaseXsdType: return self._head_type or self.type @@ -675,8 +667,13 @@ if self.identities: xpath_element = XPathElement(self.name, xsd_type) for identity in self.identities.values(): - if isinstance(identity.elements, tuple): - continue # Skip unbuilt identities + if isinstance(identity.elements, tuple) \ + or identity.selector is None: + continue # Skip unbuilt or incomplete identities + elif identity.selector.token is None: + raise XMLSchemaNotBuiltError( + identity, "identity selector is not built" + ) context = XPathContext( root=self.schema.xpath_node, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema/validators/exceptions.py new/xmlschema-2.2.0/xmlschema/validators/exceptions.py --- old/xmlschema-2.1.1/xmlschema/validators/exceptions.py 2022-07-18 16:19:15.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema/validators/exceptions.py 2023-02-06 07:20:42.000000000 +0100 @@ -240,7 +240,7 @@ msg.append('Reason: %s\n' % self.reason) if hasattr(self.validator, 'tostring'): - chunk = self.validator.tostring(' ', 20) # type: ignore[union-attr] + chunk = self.validator.tostring(' ', 20) msg.append("Schema:\n\n%s\n" % chunk) if self.elem is not None and is_etree_element(self.elem): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema/validators/identities.py new/xmlschema-2.2.0/xmlschema/validators/identities.py --- old/xmlschema-2.1.1/xmlschema/validators/identities.py 2022-07-18 16:19:15.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema/validators/identities.py 2023-02-06 07:20:42.000000000 +0100 @@ -22,6 +22,7 @@ from ..translation import gettext as _ from ..helpers import get_qname, get_extended_qname from ..aliases import ElementType, SchemaType, NamespacesType, AtomicValueType +from .exceptions import XMLSchemaNotBuiltError from .xsdbase import XsdComponent from .attributes import XsdAttribute @@ -68,8 +69,8 @@ lazy_quantifiers=False, anchors=False ) - token = None # type: XPathToken - parser = None # type: IdentityXPathParser + token: Optional[XPathToken] = None + parser: Optional[IdentityXPathParser] = None def __init__(self, elem: ElementType, schema: SchemaType, parent: Optional['XsdIdentity']) -> None: @@ -161,8 +162,8 @@ parent: 'XsdElement' ref: Optional['XsdIdentity'] - selector = None # type: XsdSelector - fields = () # type: Union[Tuple[()], List[XsdFieldSelector]] + selector: Optional[XsdSelector] = None + fields: Union[Tuple[()], List[XsdFieldSelector]] = () # XSD elements bound by selector (for speed-up and for lazy mode) elements: Union[Tuple[()], Dict['XsdElement', Optional[IdentityCounterType]]] = () @@ -206,34 +207,37 @@ self.fields = ref.fields self.ref = ref + if self.selector is None: + return # Do not raise, already found by meta-schema validation. + elif self.selector.token is None: + raise XMLSchemaNotBuiltError(self, "identity selector is not built") + context = XPathContext(self.schema.xpath_node, item=self.parent.xpath_node) self.elements = {} - try: - for e in self.selector.token.select_results(context): - if not isinstance(e, XsdComponent) or isinstance(e, XsdAttribute): - msg = _("selector xpath expression can only select elements") - self.parse_error(msg) - elif e.name is not None: - if TYPE_CHECKING: - assert isinstance(e, XsdElement) # for mypy checks with Python 3.7 - self.elements[e] = None - except AttributeError: - pass - else: - if not self.elements: - # Try to detect target XSD elements extracting QNames - # of the leaf elements from the XPath expression and - # use them to match global elements. - - qname: Any - for qname in self.selector.token.iter_leaf_elements(): - xsd_element = self.maps.elements.get( - get_extended_qname(qname, self.namespaces) - ) - if xsd_element is not None and \ - not isinstance(xsd_element, tuple) and \ - xsd_element not in self.elements: - self.elements[xsd_element] = None + + for e in self.selector.token.select_results(context): + if not isinstance(e, XsdComponent) or isinstance(e, XsdAttribute): + msg = _("selector xpath expression can only select elements") + self.parse_error(msg) + elif e.name is not None: + if TYPE_CHECKING: + assert isinstance(e, XsdElement) # for mypy checks with Python 3.7 + self.elements[e] = None + + if not self.elements: + # Try to detect target XSD elements extracting QNames + # of the leaf elements from the XPath expression and + # use them to match global elements. + + qname: Any + for qname in self.selector.token.iter_leaf_elements(): + xsd_element = self.maps.elements.get( + get_extended_qname(qname, self.namespaces) + ) + if xsd_element is not None and \ + not isinstance(xsd_element, tuple) and \ + xsd_element not in self.elements: + self.elements[xsd_element] = None @property def built(self) -> bool: @@ -268,6 +272,10 @@ value: Union[AtomicValueType, None] for k, field in enumerate(self.fields): + if field.token is None: + msg = f"identity field {field} is not built" + raise XMLSchemaNotBuiltError(self, msg) + context = XPathContext(element_node) result = field.token.get_results(context) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema/validators/schemas.py new/xmlschema-2.2.0/xmlschema/validators/schemas.py --- old/xmlschema-2.1.1/xmlschema/validators/schemas.py 2022-10-01 15:42:01.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema/validators/schemas.py 2023-02-06 07:20:42.000000000 +0100 @@ -208,7 +208,6 @@ belong the declarations/definitions of the schema. If it's empty no namespace is associated \ with the schema. In this case the schema declarations can be reused from other namespaces as \ *chameleon* definitions. - :ivar validation: validation mode, can be 'strict', 'lax' or 'skip'. :ivar maps: XSD global declarations/definitions maps. This is an instance of \ :class:`XsdGlobals`, that stores the *global_maps* argument or a new object \ when this argument is not provided. @@ -350,7 +349,7 @@ self.imports = {} self.includes = {} self.warnings = [] - self._root_elements = None # type: Optional[Set[str]] + self._root_elements: Optional[Set[str]] = None self.name = self.source.name root = self.source.root diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema/validators/simple_types.py new/xmlschema-2.2.0/xmlschema/validators/simple_types.py --- old/xmlschema-2.1.1/xmlschema/validators/simple_types.py 2022-09-25 09:58:42.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema/validators/simple_types.py 2023-02-06 07:20:42.000000000 +0100 @@ -12,7 +12,7 @@ """ from decimal import DecimalException from typing import cast, Any, Callable, Dict, Iterator, List, \ - Optional, Pattern, Set, Union, Tuple, Type + Optional, Set, Union, Tuple, Type from xml.etree import ElementTree from ..aliases import ElementType, AtomicValueType, ComponentClassType, \ @@ -25,9 +25,9 @@ XSD_LENGTH, XSD_MIN_LENGTH, XSD_MAX_LENGTH, XSD_WHITE_SPACE, XSD_ENUMERATION,\ XSD_LIST, XSD_ANY_SIMPLE_TYPE, XSD_UNION, XSD_RESTRICTION, XSD_ANNOTATION, \ XSD_ASSERTION, XSD_ID, XSD_IDREF, XSD_FRACTION_DIGITS, XSD_TOTAL_DIGITS, \ - XSD_EXPLICIT_TIMEZONE, XSD_ERROR, XSD_ASSERT, XSD_QNAME, XSD_UNTYPED_ATOMIC + XSD_EXPLICIT_TIMEZONE, XSD_ERROR, XSD_ASSERT, XSD_QNAME from ..translation import gettext as _ -from ..helpers import get_prefixed_qname, local_name +from ..helpers import local_name from .exceptions import XMLSchemaValidationError, XMLSchemaEncodeError, \ XMLSchemaDecodeError, XMLSchemaParseError @@ -96,7 +96,6 @@ if white_space is not None: self.white_space = white_space - p: Pattern[str] patterns = self.get_facet(XSD_PATTERN) if isinstance(patterns, XsdPatternFacets): self.patterns = patterns @@ -353,16 +352,16 @@ root_type = self.root_type if root_type.name is not None: - sequence_type = cast(str, root_type.prefixed_name) + sequence_type = f'xs:{root_type.local_name}' else: - sequence_type = get_prefixed_qname(XSD_UNTYPED_ATOMIC, self.namespaces) + sequence_type = 'xs:untypedAtomic' if not self.is_list(): return sequence_type elif self.is_emptiable(): - return '{}*'.format(sequence_type) + return f'{sequence_type}*' else: - return '{}+'.format(sequence_type) + return f'{sequence_type}+' def is_empty(self) -> bool: return self.max_length == 0 or \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema/validators/xsdbase.py new/xmlschema-2.2.0/xmlschema/validators/xsdbase.py --- old/xmlschema-2.1.1/xmlschema/validators/xsdbase.py 2022-09-08 12:16:11.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema/validators/xsdbase.py 2023-02-06 07:20:42.000000000 +0100 @@ -768,6 +768,7 @@ @staticmethod def is_complex() -> bool: """Returns `True` if the instance is a complexType, `False` otherwise.""" + return False def is_atomic(self) -> bool: """Returns `True` if the instance is an atomic simpleType, `False` otherwise.""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema.egg-info/PKG-INFO new/xmlschema-2.2.0/xmlschema.egg-info/PKG-INFO --- old/xmlschema-2.1.1/xmlschema.egg-info/PKG-INFO 2022-10-01 19:02:18.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema.egg-info/PKG-INFO 2023-02-06 10:06:40.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: xmlschema -Version: 2.1.1 +Version: 2.2.0 Summary: An XML Schema validator and decoder Home-page: https://github.com/sissaschool/xmlschema Author: Davide Brunato diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmlschema-2.1.1/xmlschema.egg-info/requires.txt new/xmlschema-2.2.0/xmlschema.egg-info/requires.txt --- old/xmlschema-2.1.1/xmlschema.egg-info/requires.txt 2022-10-01 19:02:18.000000000 +0200 +++ new/xmlschema-2.2.0/xmlschema.egg-info/requires.txt 2023-02-06 10:06:40.000000000 +0100 @@ -1,14 +1,14 @@ -elementpath<4.0.0,>=3.0.0 +elementpath<5.0.0,>=4.0.0 [codegen] -elementpath<4.0.0,>=3.0.0 +elementpath<5.0.0,>=4.0.0 jinja2 [dev] tox coverage lxml -elementpath<4.0.0,>=3.0.0 +elementpath<5.0.0,>=4.0.0 memory_profiler Sphinx sphinx_rtd_theme @@ -18,7 +18,7 @@ lxml-stubs [docs] -elementpath<4.0.0,>=3.0.0 +elementpath<5.0.0,>=4.0.0 Sphinx sphinx_rtd_theme jinja2