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 2021-07-10 22:53:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-xmlschema (Old)
 and      /work/SRC/openSUSE:Factory/.python-xmlschema.new.2625 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-xmlschema"

Sat Jul 10 22:53:34 2021 rev:14 rq:900664 version:1.6.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-xmlschema/python-xmlschema.changes        
2021-05-20 19:23:55.542224931 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-xmlschema.new.2625/python-xmlschema.changes  
    2021-07-10 22:53:37.500164889 +0200
@@ -1,0 +2,14 @@
+Thu Jun 17 21:22:48 UTC 2021 - Dirk M??ller <[email protected]>
+
+- update to 1.6.4:
+  * Add testing config for Python 3.10 (Tox and CI)
+  * Fix internal _PurePath class with Python 3.10 (issue #251)
+  * Remove redundant xmlns="" declaration when encoding with lxml (issue #252)
+  * Refactor normalize_url() using pathlib.PurePath
+  * Support UNC paths (issue #246)
+  * Fix API docs (issue #248)
+  * Fix for issue #245 (key/keyref with dynamic types)
+  * Change default decoding of mixed content with only text to a string
+    instead of a dictionary (issue #242)
+
+-------------------------------------------------------------------

Old:
----
  xmlschema-1.6.1.tar.gz

New:
----
  xmlschema-1.6.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-xmlschema.spec ++++++
--- /var/tmp/diff_new_pack.f9GNJ7/_old  2021-07-10 22:53:38.012160938 +0200
+++ /var/tmp/diff_new_pack.f9GNJ7/_new  2021-07-10 22:53:38.012160938 +0200
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           python-xmlschema
-Version:        1.6.1
+Version:        1.6.4
 Release:        0
 Summary:        An XML Schema validator and decoder
 License:        MIT

++++++ xmlschema-1.6.1.tar.gz -> xmlschema-1.6.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/CHANGELOG.rst 
new/xmlschema-1.6.4/CHANGELOG.rst
--- old/xmlschema-1.6.1/CHANGELOG.rst   2021-04-11 22:19:21.000000000 +0200
+++ new/xmlschema-1.6.4/CHANGELOG.rst   2021-06-09 19:22:21.000000000 +0200
@@ -2,6 +2,24 @@
 CHANGELOG
 *********
 
+`v1.6.4`_ (2021-06-09)
+======================
+* Add testing config for Python 3.10 (Tox and CI)
+* Fix internal _PurePath class with Python 3.10 (issue #251)
+* Remove redundant xmlns="" declaration when encoding with lxml (issue #252)
+
+`v1.6.3`_ (2021-06-07)
+======================
+* Refactor normalize_url() using pathlib.PurePath
+* Support UNC paths (issue #246)
+* Fix API docs (issue #248)
+
+`v1.6.2`_ (2021-05-03)
+======================
+* Fix for issue #245 (key/keyref with dynamic types)
+* Change default decoding of mixed content with only text to a string
+  instead of a dictionary (issue #242)
+
 `v1.6.1`_ (2021-04-11)
 ======================
 * Add multi-source initialization and add_schema() to schema class
@@ -436,3 +454,6 @@
 .. _v1.5.3: https://github.com/brunato/xmlschema/compare/v1.5.2...v1.5.3
 .. _v1.6.0: https://github.com/brunato/xmlschema/compare/v1.5.3...v1.6.0
 .. _v1.6.1: https://github.com/brunato/xmlschema/compare/v1.6.0...v1.6.1
+.. _v1.6.2: https://github.com/brunato/xmlschema/compare/v1.6.1...v1.6.2
+.. _v1.6.3: https://github.com/brunato/xmlschema/compare/v1.6.2...v1.6.3
+.. _v1.6.4: https://github.com/brunato/xmlschema/compare/v1.6.3...v1.6.4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/PKG-INFO new/xmlschema-1.6.4/PKG-INFO
--- old/xmlschema-1.6.1/PKG-INFO        2021-04-11 23:17:40.207514000 +0200
+++ new/xmlschema-1.6.4/PKG-INFO        2021-06-09 19:41:05.674031300 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: xmlschema
-Version: 1.6.1
+Version: 1.6.4
 Summary: An XML Schema validator and decoder
 Home-page: https://github.com/sissaschool/xmlschema
 Author: Davide Brunato
@@ -181,6 +181,7 @@
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Topic :: Software Development :: Libraries
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/doc/api.rst 
new/xmlschema-1.6.4/doc/api.rst
--- old/xmlschema-1.6.1/doc/api.rst     2021-04-06 13:18:03.000000000 +0200
+++ new/xmlschema-1.6.4/doc/api.rst     2021-06-07 09:43:37.000000000 +0200
@@ -59,7 +59,9 @@
 
     .. autoattribute:: root
     .. automethod:: get_text
+    .. autoattribute:: name
     .. autoattribute:: url
+    .. autoattribute:: base_url
 
     .. autoattribute:: tag
     .. autoattribute:: id
@@ -69,9 +71,6 @@
     .. autoattribute:: no_namespace_schema_location
     .. autoattribute:: target_prefix
     .. autoattribute:: default_namespace
-    .. autoattribute:: name
-    .. autoattribute:: url
-    .. autoattribute:: base_url
     .. autoattribute:: root_elements
     .. autoattribute:: simple_types
     .. autoattribute:: complex_types
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/doc/conf.py 
new/xmlschema-1.6.4/doc/conf.py
--- old/xmlschema-1.6.1/doc/conf.py     2021-04-11 22:19:21.000000000 +0200
+++ new/xmlschema-1.6.4/doc/conf.py     2021-06-09 19:22:21.000000000 +0200
@@ -65,7 +65,7 @@
 # The short X.Y version.
 version = '1.6'
 # The full version, including alpha/beta/rc tags.
-release = '1.6.1'
+release = '1.6.4'
 
 # 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-1.6.1/requirements-dev.txt 
new/xmlschema-1.6.4/requirements-dev.txt
--- old/xmlschema-1.6.1/requirements-dev.txt    2021-04-05 23:38:16.000000000 
+0200
+++ new/xmlschema-1.6.4/requirements-dev.txt    2021-05-03 13:37:57.000000000 
+0200
@@ -2,7 +2,7 @@
 setuptools
 tox
 coverage
-elementpath>=2.2.1, <3.0.0
+elementpath>=2.2.2, <3.0.0
 lxml
 memory_profiler
 Sphinx
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/setup.py new/xmlschema-1.6.4/setup.py
--- old/xmlschema-1.6.1/setup.py        2021-04-11 22:19:21.000000000 +0200
+++ new/xmlschema-1.6.4/setup.py        2021-06-09 19:22:21.000000000 +0200
@@ -9,14 +9,16 @@
 # @author Davide Brunato <[email protected]>
 #
 from setuptools import setup, find_packages
+from pathlib import Path
 
-with open("README.rst") as readme:
+
+with Path(__file__).parent.joinpath('README.rst').open() as readme:
     long_description = readme.read()
 
 
 setup(
     name='xmlschema',
-    version='1.6.1',
+    version='1.6.4',
     packages=find_packages(include=['xmlschema', 'xmlschema.*']),
     include_package_data=True,
     entry_points={
@@ -27,12 +29,12 @@
         ]
     },
     python_requires='>=3.6',
-    install_requires=['elementpath>=2.2.1, <3.0.0'],
+    install_requires=['elementpath>=2.2.2, <3.0.0'],
     extras_require={
-        'codegen': ['elementpath>=2.2.1, <3.0.0', 'jinja2'],
-        'dev': ['tox', 'coverage', 'lxml', 'elementpath>=2.2.1, <3.0.0',
+        'codegen': ['elementpath>=2.2.2, <3.0.0', 'jinja2'],
+        'dev': ['tox', 'coverage', 'lxml', 'elementpath>=2.2.2, <3.0.0',
                 'memory_profiler', 'Sphinx', 'sphinx_rtd_theme', 'jinja2'],
-        'docs': ['elementpath>=2.1.2, <3.0.0', 'Sphinx', 'sphinx_rtd_theme', 
'jinja2']
+        'docs': ['elementpath>=2.2.2, <3.0.0', 'Sphinx', 'sphinx_rtd_theme', 
'jinja2']
     },
     author='Davide Brunato',
     author_email='[email protected]',
@@ -55,6 +57,7 @@
         'Programming Language :: Python :: 3.7',
         'Programming Language :: Python :: 3.8',
         'Programming Language :: Python :: 3.9',
+        'Programming Language :: Python :: 3.10',
         'Programming Language :: Python :: Implementation :: CPython',
         'Programming Language :: Python :: Implementation :: PyPy',
         'Topic :: Software Development :: Libraries',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xmlschema-1.6.1/tests/test_cases/issues/issue_243/issue_243.xml 
new/xmlschema-1.6.4/tests/test_cases/issues/issue_243/issue_243.xml
--- old/xmlschema-1.6.1/tests/test_cases/issues/issue_243/issue_243.xml 
1970-01-01 01:00:00.000000000 +0100
+++ new/xmlschema-1.6.4/tests/test_cases/issues/issue_243/issue_243.xml 
2021-05-03 13:37:57.000000000 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<manifest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns="http://www.test.com/XMLSchema/manifest/2021";>
+    <session anonymous="true">
+        <userId xsi:nil="true"/>
+        <sessionId xsi:nil="true"/>
+    </session>
+</manifest>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xmlschema-1.6.1/tests/test_cases/issues/issue_243/issue_243.xsd 
new/xmlschema-1.6.4/tests/test_cases/issues/issue_243/issue_243.xsd
--- old/xmlschema-1.6.1/tests/test_cases/issues/issue_243/issue_243.xsd 
1970-01-01 01:00:00.000000000 +0100
+++ new/xmlschema-1.6.4/tests/test_cases/issues/issue_243/issue_243.xsd 
2021-05-03 13:37:57.000000000 +0200
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"; 
elementFormDefault="qualified"
+    attributeFormDefault="unqualified" vc:minVersion="1.1"
+    xmlns:am="http://www.test.com/XMLSchema/manifest/2021";
+    targetNamespace="http://www.test.com/XMLSchema/manifest/2021";
+    xmlns="http://www.test.com/XMLSchema/manifest/2021";>
+    <xs:element name="manifest">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="session">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="userId" nillable="true">
+                                <xs:simpleType>
+                                    <xs:restriction base="xs:string">
+                                        <xs:minLength value="1"/>
+                                    </xs:restriction>
+                                </xs:simpleType>
+                            </xs:element>
+                            <xs:element name="sessionId" nillable="true">
+                                <xs:simpleType>
+                                    <xs:restriction base="xs:integer">
+                                        <xs:minInclusive value="0"/>
+                                    </xs:restriction>
+                                </xs:simpleType>
+                            </xs:element>
+                        </xs:sequence>
+                        <xs:attribute name="anonymous" type="xs:boolean" 
use="required">
+                        </xs:attribute>
+                        <xs:assert
+                            test="((@anonymous eq true()) and 
am:userId[@xsi:nil] and am:sessionId[@xsi:nil]) or ((@anonymous eq false()) and 
am:userId[node()] and am:sessionId[node()])"
+                        />
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+</xs:schema>
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xmlschema-1.6.1/tests/test_cases/issues/issue_245/issue_245-valid.xml 
new/xmlschema-1.6.4/tests/test_cases/issues/issue_245/issue_245-valid.xml
--- old/xmlschema-1.6.1/tests/test_cases/issues/issue_245/issue_245-valid.xml   
1970-01-01 01:00:00.000000000 +0100
+++ new/xmlschema-1.6.4/tests/test_cases/issues/issue_245/issue_245-valid.xml   
2021-05-03 13:37:57.000000000 +0200
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<assessment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+ xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning";
+ xmlns="http://www.test.com/XMLSchema/data/2021";
+ xsi:schemaLocation="http://www.test.com/XMLSchema/data/2021 issue_245.xsd">
+    <part xsi:type="ContrastVisionTest">
+        <screen_elements>
+            <contrast_circles>
+                <circle circle_id="1"/>
+                <circle circle_id="0"/>
+                <circle circle_id="2"/>
+            </contrast_circles>
+        </screen_elements>
+        <events>
+            <circle_pressed circle_id="0"/>
+            <circle_pressed circle_id="1"/>
+            <circle_pressed circle_id="2"/>
+        </events>
+    </part>
+</assessment>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xmlschema-1.6.1/tests/test_cases/issues/issue_245/issue_245.xml 
new/xmlschema-1.6.4/tests/test_cases/issues/issue_245/issue_245.xml
--- old/xmlschema-1.6.1/tests/test_cases/issues/issue_245/issue_245.xml 
1970-01-01 01:00:00.000000000 +0100
+++ new/xmlschema-1.6.4/tests/test_cases/issues/issue_245/issue_245.xml 
2021-05-03 13:37:57.000000000 +0200
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<assessment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+ xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning";
+ xmlns="http://www.test.com/XMLSchema/data/2021";
+ xsi:schemaLocation="http://www.test.com/XMLSchema/data/2021 issue_245.xsd">
+    <part xsi:type="ContrastVisionTest">
+        <screen_elements>
+            <contrast_circles>
+                <circle circle_id="1"/>
+                <circle circle_id="1"/>
+                <circle circle_id="2"/>
+            </contrast_circles>
+        </screen_elements>
+        <events>
+            <circle_pressed circle_id="0"/>
+            <circle_pressed circle_id="1"/>
+            <circle_pressed circle_id="2"/>
+        </events>
+    </part>
+</assessment>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xmlschema-1.6.1/tests/test_cases/issues/issue_245/issue_245.xsd 
new/xmlschema-1.6.4/tests/test_cases/issues/issue_245/issue_245.xsd
--- old/xmlschema-1.6.1/tests/test_cases/issues/issue_245/issue_245.xsd 
1970-01-01 01:00:00.000000000 +0100
+++ new/xmlschema-1.6.4/tests/test_cases/issues/issue_245/issue_245.xsd 
2021-05-03 13:37:57.000000000 +0200
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"; 
elementFormDefault="qualified"
+    attributeFormDefault="unqualified" vc:minVersion="1.1"
+    targetNamespace="http://www.test.com/XMLSchema/data/2021";
+    xmlns="http://www.test.com/XMLSchema/data/2021";
+    xmlns:ad="http://www.test.com/XMLSchema/data/2021";>
+    <xs:element name="assessment">
+        <xs:annotation>
+            <xs:documentation>Data about the performed 
tests.</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element maxOccurs="unbounded" minOccurs="0" name="part" 
type="AssessmentPart">
+                    <xs:key name="circle_id_key">
+                        <xs:annotation>
+                            <xs:documentation>For ContrastVisionTest. 
+
+Since all parts are types we can not add keys and keyrefs to them. As such, we 
add the constraints here.</xs:documentation>
+                        </xs:annotation>
+                        <xs:selector 
xpath="ad:screen_elements/ad:contrast_circles/ad:circle"/>
+                        <xs:field xpath="@circle_id"/>
+                    </xs:key>
+                    <xs:keyref name="circle_id_keyref" refer="circle_id_key">
+                        <xs:selector xpath="ad:events/ad:circle_pressed"/>
+                        <xs:field xpath="@circle_id"/>
+                    </xs:keyref>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+    <xs:complexType abstract="true" name="AssessmentPart">
+        <xs:annotation>
+            <xs:documentation>Base type for the assessment 
element.</xs:documentation>
+        </xs:annotation>
+    </xs:complexType>
+    <xs:complexType abstract="true" name="AssessmentTest">
+        <xs:annotation>
+            <xs:documentation>Base type for a test.</xs:documentation>
+        </xs:annotation>
+        <xs:complexContent>
+            <xs:extension base="AssessmentPart"/>
+        </xs:complexContent>
+    </xs:complexType>
+    <xs:complexType name="ContrastVisionTest">
+        <xs:complexContent>
+            <xs:extension base="AssessmentTest">
+                <xs:sequence>
+                    <xs:element name="screen_elements">
+                        <xs:complexType>
+                            <xs:sequence>
+                                <xs:element name="contrast_circles">
+                                    <xs:complexType>
+                                        <xs:sequence>
+                                            <xs:element maxOccurs="3" 
name="circle" minOccurs="3">
+                                                <xs:complexType>
+                                                  <xs:attribute 
name="circle_id" use="required">
+                                                  <xs:annotation>
+                                                  <xs:documentation>The id of 
this circle, used to reference the circle presses.</xs:documentation>
+                                                  </xs:annotation>
+                                                  <xs:simpleType>
+                                                  <xs:restriction 
base="xs:integer">
+                                                  <xs:minInclusive value="0"/>
+                                                  <xs:maxInclusive value="9"/>
+                                                  </xs:restriction>
+                                                  </xs:simpleType>
+                                                  </xs:attribute>
+                                                </xs:complexType>
+                                            </xs:element>
+                                        </xs:sequence>
+                                    </xs:complexType>
+                                </xs:element>
+                            </xs:sequence>
+                        </xs:complexType>
+                    </xs:element>
+                    <xs:element name="events">
+                        <xs:complexType>
+                            <xs:sequence>
+                                <xs:element maxOccurs="unbounded" minOccurs="0"
+                                    name="circle_pressed">
+                                    <xs:complexType>
+                                        <xs:attribute name="circle_id" 
type="xs:integer"
+                                            use="required"/>
+                                    </xs:complexType>
+                                </xs:element>
+                            </xs:sequence>
+                        </xs:complexType>
+                    </xs:element>
+                </xs:sequence>
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+</xs:schema>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/tests/test_cases/testfiles 
new/xmlschema-1.6.4/tests/test_cases/testfiles
--- old/xmlschema-1.6.1/tests/test_cases/testfiles      2021-04-06 
13:18:03.000000000 +0200
+++ new/xmlschema-1.6.4/tests/test_cases/testfiles      2021-05-03 
13:37:57.000000000 +0200
@@ -122,3 +122,6 @@
 issues/issue_222/issue_222.xml -L '' issue_222.xsd
 issues/issue_223/issue_223.xsd
 issues/issue_223/issue_223.xml -L '' issue_223.xsd --errors=1  # pattern 
matching with \n ending
+issues/issue_243/issue_243.xml --version=1.1 -L '' issue_243.xsd
+issues/issue_245/issue_245.xml --version=1.1 --errors=2  # duplicated key 
value with xsi:type
+issues/issue_245/issue_245-valid.xml --version=1.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/tests/test_resources.py 
new/xmlschema-1.6.4/tests/test_resources.py
--- old/xmlschema-1.6.1/tests/test_resources.py 2021-04-11 22:40:23.000000000 
+0200
+++ new/xmlschema-1.6.4/tests/test_resources.py 2021-06-09 19:22:21.000000000 
+0200
@@ -31,6 +31,7 @@
     fetch_schema, fetch_schema_locations, XMLResource, XMLResourceError, 
XMLSchema
 from xmlschema.etree import ElementTree, etree_element, py_etree_element, 
is_etree_element
 from xmlschema.names import XSD_NAMESPACE
+import xmlschema.resources
 from xmlschema.resources import is_url, is_local_url, is_remote_url, \
     url_path_is_file, normalize_locations, LazySelector
 from xmlschema.testing import SKIP_REMOTE_TESTS
@@ -38,6 +39,8 @@
 
 TEST_CASES_DIR = 
str(pathlib.Path(__file__).absolute().parent.joinpath('test_cases'))
 
+DRIVE_PATH = '/C:' if platform.system() == 'Windows' else ''
+
 
 def casepath(relative_path):
     return str(pathlib.Path(TEST_CASES_DIR).joinpath(relative_path))
@@ -97,6 +100,46 @@
             expected_path = PurePath(expected_parts.path)
         self.assertEqual(path, expected_path, "%r: Paths differ." % url)
 
+    def test_path_from_uri(self):
+        _PurePath = xmlschema.resources._PurePath
+        _PosixPurePath = xmlschema.resources._PosixPurePath
+        _WindowsPurePath = xmlschema.resources._WindowsPurePath
+
+        with self.assertRaises(ValueError) as ec:
+            _PurePath.from_uri('')
+        self.assertEqual(str(ec.exception), 'Empty URI provided!')
+
+        path = _PurePath.from_uri('https://example.com/names/?name=foo')
+        self.assertIsInstance(path, _PosixPurePath)
+        self.assertEqual(str(path), '/names')
+
+        path = _PosixPurePath.from_uri('file:///home/foo/names/?name=foo')
+        self.assertIsInstance(path, _PosixPurePath)
+        self.assertEqual(str(path), '/home/foo/names')
+
+        path = _PosixPurePath.from_uri('file:///home/foo/names#foo')
+        self.assertIsInstance(path, _PosixPurePath)
+        self.assertEqual(str(path), '/home/foo/names')
+
+        path = _PosixPurePath.from_uri('file:///home\\foo\\names#foo')
+        self.assertIsInstance(path, _WindowsPurePath)
+        self.assertTrue(path.as_posix().endswith('/home/foo/names'))
+
+        path = _PosixPurePath.from_uri('file:///c:/home/foo/names/')
+        self.assertIsInstance(path, _WindowsPurePath)
+        self.assertEqual(str(path), r'c:\home\foo\names')
+        self.assertEqual(path.as_uri(), 'file:///c:/home/foo/names')
+
+        path = _PosixPurePath.from_uri('file:c:/home/foo/names/')
+        self.assertIsInstance(path, _WindowsPurePath)
+        self.assertEqual(str(path), r'c:\home\foo\names')
+        self.assertEqual(path.as_uri(), 'file:///c:/home/foo/names')
+
+        with self.assertRaises(ValueError) as ec:
+            _PurePath.from_uri('file://c:/home/foo/names/')
+        self.assertEqual(str(ec.exception), "Invalid URI 
'file://c:/home/foo/names/'")
+
+    @unittest.skipIf(platform.system() == 'Windows', "Run only on posix 
systems")
     def test_normalize_url_posix(self):
         url1 = "https://example.com/xsd/other_schema.xsd";
         self.check_url(normalize_url(url1, 
base_url="/path_my_schema/schema.xsd"), url1)
@@ -114,19 +157,20 @@
         cwd = os.getcwd()
         cwd_url = 'file://{}/'.format(cwd) if cwd.startswith('/') else 
'file:///{}/'.format(cwd)
 
+        self.check_url(normalize_url('other.xsd', keep_relative=True), 
'file:other.xsd')
         self.check_url(normalize_url('file:other.xsd', keep_relative=True), 
'file:other.xsd')
         self.check_url(normalize_url('file:other.xsd'), cwd_url + 'other.xsd')
-        self.check_url(normalize_url('file:other.xsd', 'http://site/base', 
True), 'file:other.xsd')
+        self.check_url(normalize_url('file:other.xsd', 'https://site/base', 
True), 'file:other.xsd')
         self.check_url(normalize_url('file:other.xsd', 'http://site/base'), 
cwd_url + 'other.xsd')
 
-        self.check_url(normalize_url('dummy path.xsd'), cwd_url + 'dummy 
path.xsd')
+        self.check_url(normalize_url('dummy path.xsd'), cwd_url + 
'dummy%20path.xsd')
         self.check_url(normalize_url('dummy path.xsd', 'http://site/base'),
                        'http://site/base/dummy%20path.xsd')
         self.check_url(normalize_url('dummy path.xsd', 'file://host/home/'),
-                       'file://host/home/dummy path.xsd')
+                       PurePath('//host/home/dummy path.xsd').as_uri())
 
-        url = "file://c:/Downloads/file.xsd"
-        self.check_url(normalize_url(url, base_url="file://d:/Temp/"), url)
+        url = "file:///c:/Downloads/file.xsd"
+        self.check_url(normalize_url(url, base_url="file:///d:/Temp/"), url)
 
     def test_normalize_url_windows(self):
         win_abs_path1 = 'z:\\Dir_1_0\\Dir2-0\\schemas/XSD_1.0/XMLSchema.xsd'
@@ -134,42 +178,58 @@
         self.check_url(normalize_url(win_abs_path1), win_abs_path1)
 
         self.check_url(normalize_url('k:\\Dir3\\schema.xsd', win_abs_path1),
-                       'file:///k:\\Dir3\\schema.xsd')
+                       'file:///k:/Dir3/schema.xsd')
         self.check_url(normalize_url('k:\\Dir3\\schema.xsd', win_abs_path2),
-                       'file:///k:\\Dir3\\schema.xsd')
+                       'file:///k:/Dir3/schema.xsd')
+
         self.check_url(normalize_url('schema.xsd', win_abs_path2),
-                       'file:///z:\\Dir-1.0\\Dir-2_0/schema.xsd')
+                       'file:///z:/Dir-1.0/Dir-2_0/schema.xsd')
         self.check_url(normalize_url('xsd1.0/schema.xsd', win_abs_path2),
-                       'file:///z:\\Dir-1.0\\Dir-2_0/xsd1.0/schema.xsd')
-        self.check_url(normalize_url('file:///\\k:\\Dir A\\schema.xsd'),
-                       'file:///k:\\Dir A\\schema.xsd')
+                       'file:///z:/Dir-1.0/Dir-2_0/xsd1.0/schema.xsd')
+
+        with self.assertRaises(ValueError) as ec:
+            normalize_url('file:///\\k:\\Dir A\\schema.xsd')
+        self.assertIn("Invalid URI", str(ec.exception))
+
+    def test_normalize_url_unc_paths__issue_246(self):
+        url = PureWindowsPath(r'\\host\share\file.xsd').as_uri()
+        self.assertEqual(normalize_url(r'\\host\share\file.xsd'), url)  # 
file://host/share/file.xsd
 
     def test_normalize_url_slashes(self):
         # Issue #116
-        self.assertEqual(
-            normalize_url('//anaconda/envs/testenv/lib/python3.6/'
-                          'site-packages/xmlschema/validators/schemas/'),
-            'file:///anaconda/envs/testenv/lib/python3.6/'
-            'site-packages/xmlschema/validators/schemas/'
-        )
-        self.assertEqual(normalize_url('/root/dir1/schema.xsd'), 
'file:///root/dir1/schema.xsd')
-        self.assertEqual(normalize_url('//root/dir1/schema.xsd'), 
'file:///root/dir1/schema.xsd')
-        self.assertEqual(normalize_url('////root/dir1/schema.xsd'), 
'file:///root/dir1/schema.xsd')
-
-        self.assertEqual(normalize_url('dir2/schema.xsd', '//root/dir1/'),
-                         'file:///root/dir1/dir2/schema.xsd')
-        self.assertEqual(normalize_url('dir2/schema.xsd', '//root/dir1'),
-                         'file:///root/dir1/dir2/schema.xsd')
+        url = 
'//anaconda/envs/testenv/lib/python3.6/site-packages/xmlschema/validators/schemas/'
+        self.assertEqual(normalize_url(url), pathlib.PurePath(url).as_uri())
+        self.assertEqual(normalize_url('/root/dir1/schema.xsd'),
+                         f'file://{DRIVE_PATH}/root/dir1/schema.xsd')
+
+        self.assertEqual(normalize_url('////root/dir1/schema.xsd'),
+                         f'file://{DRIVE_PATH}/root/dir1/schema.xsd')
         self.assertEqual(normalize_url('dir2/schema.xsd', '////root/dir1'),
-                         'file:///root/dir1/dir2/schema.xsd')
+                         f'file://{DRIVE_PATH}/root/dir1/dir2/schema.xsd')
+
+        if platform.system() == 'Windows':
+            # On Windows // is interpreted as a network share UNC path
+            self.assertEqual(normalize_url('//root/dir1/schema.xsd'),
+                             'file://root/dir1/schema.xsd')
+            self.assertEqual(normalize_url('dir2/schema.xsd', '//root/dir1/'),
+                             f'file://root/dir1/dir2/schema.xsd')
+            self.assertEqual(normalize_url('dir2/schema.xsd', '//root/dir1'),
+                             f'file://root/dir1/dir2/schema.xsd')
+        else:
+            self.assertEqual(normalize_url('//root/dir1/schema.xsd'),
+                             'file:////root/dir1/schema.xsd')
+            self.assertEqual(normalize_url('dir2/schema.xsd', '//root/dir1/'),
+                             f'file:////root/dir1/dir2/schema.xsd')
+            self.assertEqual(normalize_url('dir2/schema.xsd', '//root/dir1'),
+                             f'file:////root/dir1/dir2/schema.xsd')
 
     def test_normalize_url_hash_character(self):
         self.check_url(normalize_url('issue #000.xml', 'file:///dir1/dir2/'),
-                       'file:///dir1/dir2/issue %23000.xml')
-        self.check_url(normalize_url('data.xml', 'file:///dir1/dir2/issue 
000'),
-                       'file:///dir1/dir2/issue 000/data.xml')
-        self.check_url(normalize_url('data.xml', '/dir1/dir2/issue #000'),
-                       '/dir1/dir2/issue %23000/data.xml')
+                       f'file://{DRIVE_PATH}/dir1/dir2/issue%20%23000.xml')
+        self.check_url(normalize_url('data.xml', 
'file:///dir1/dir2/issue%20001'),
+                       f'file://{DRIVE_PATH}/dir1/dir2/issue%20001/data.xml')
+        self.check_url(normalize_url('data.xml', '/dir1/dir2/issue #002'),
+                       f'{DRIVE_PATH}/dir1/dir2/issue%20%23002/data.xml')
 
     def test_is_url_function(self):
         self.assertTrue(is_url(self.col_xsd_file))
@@ -209,20 +269,20 @@
         locations = normalize_locations(
             [('tns0', 'alpha'), ('tns1', 'http://example.com/beta')], 
base_url='/home/user'
         )
-        self.assertListEqual(locations, [('tns0', 'file:///home/user/alpha'),
+        self.assertListEqual(locations, [('tns0', 
f'file://{DRIVE_PATH}/home/user/alpha'),
                                          ('tns1', 'http://example.com/beta')])
 
         locations = normalize_locations(
             {'tns0': 'alpha', 'tns1': 'http://example.com/beta'}, 
base_url='/home/user'
         )
-        self.assertListEqual(locations, [('tns0', 'file:///home/user/alpha'),
+        self.assertListEqual(locations, [('tns0', 
f'file://{DRIVE_PATH}/home/user/alpha'),
                                          ('tns1', 'http://example.com/beta')])
 
         locations = normalize_locations(
             {'tns0': ['alpha', 'beta'], 'tns1': 'http://example.com/beta'}, 
base_url='/home/user'
         )
-        self.assertListEqual(locations, [('tns0', 'file:///home/user/alpha'),
-                                         ('tns0', 'file:///home/user/beta'),
+        self.assertListEqual(locations, [('tns0', 
f'file://{DRIVE_PATH}/home/user/alpha'),
+                                         ('tns0', 
f'file://{DRIVE_PATH}/home/user/beta'),
                                          ('tns1', 'http://example.com/beta')])
 
         locations = normalize_locations(
@@ -243,16 +303,16 @@
         self.assertRaises(XMLResourceError, fetch_resource, wrong_path)
 
         right_path = casepath('resources/dummy file.txt')
-        self.assertTrue(fetch_resource(right_path).endswith('dummy file.txt'))
+        
self.assertTrue(fetch_resource(right_path).endswith('dummy%20file.txt'))
 
         right_path = Path(casepath('resources/dummy 
file.txt')).relative_to(os.getcwd())
-        self.assertTrue(fetch_resource(str(right_path), 
'/home').endswith('dummy file.txt'))
+        self.assertTrue(fetch_resource(str(right_path), 
'/home').endswith('dummy%20file.txt'))
 
         with self.assertRaises(XMLResourceError):
             fetch_resource(str(right_path.parent.joinpath('dummy_file.txt')), 
'/home')
 
         ambiguous_path = casepath('resources/dummy file #2.txt')
-        self.assertTrue(fetch_resource(ambiguous_path).endswith('dummy file 
%232.txt'))
+        
self.assertTrue(fetch_resource(ambiguous_path).endswith('dummy%20file%20%232.txt'))
 
         with urlopen(fetch_resource(ambiguous_path)) as res:
             self.assertEqual(res.read(), b'DUMMY CONTENT')
@@ -736,7 +796,10 @@
         resource = XMLResource(self.vh_xml_file)
         resource.close()
         xml_file = resource.open()
-        self.assertTrue(callable(xml_file.read))
+        try:
+            self.assertTrue(callable(xml_file.read))
+        finally:
+            resource.close()
 
         with open(self.vh_xml_file) as xml_file:
             resource = XMLResource(source=xml_file)
@@ -1082,11 +1145,11 @@
 
         resource = XMLResource(source)
         locations = resource.get_locations()
-        self.assertListEqual(locations, [('http://example.com/ns1', 
'file:///loc1'),
-                                         ('http://example.com/ns2', 
'file:///loc2')])
+        self.assertListEqual(locations, [('http://example.com/ns1', 
f'file://{DRIVE_PATH}/loc1'),
+                                         ('http://example.com/ns2', 
f'file://{DRIVE_PATH}/loc2')])
 
         locations = resource.get_locations(root_only=True)
-        self.assertListEqual(locations, [('http://example.com/ns1', 
'file:///loc1')])
+        self.assertListEqual(locations, [('http://example.com/ns1', 
f'file://{DRIVE_PATH}/loc1')])
 
     @unittest.skipIf(SKIP_REMOTE_TESTS or platform.system() == 'Windows',
                      "Remote networks are not accessible or avoid SSL "
@@ -1251,10 +1314,10 @@
         self.assertIs(subresource.root, resource.root[0])
 
     def test_loading_from_unrelated_dirs__issue_237(self):
-        relpath = str(pathlib.Path(__file__).parent.joinpath(
+        relative_path = str(pathlib.Path(__file__).parent.joinpath(
             'test_cases/issues/issue_237/dir1/issue_237.xsd'
         ))
-        schema = XMLSchema(relpath)
+        schema = XMLSchema(relative_path)
         self.assertEqual(schema.maps.namespaces[''][1].name, 'issue_237a.xsd')
         self.assertEqual(schema.maps.namespaces[''][2].name, 'issue_237b.xsd')
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/tests/validation/test_decoding.py 
new/xmlschema-1.6.4/tests/validation/test_decoding.py
--- old/xmlschema-1.6.1/tests/validation/test_decoding.py       2021-04-11 
22:19:21.000000000 +0200
+++ new/xmlschema-1.6.4/tests/validation/test_decoding.py       2021-05-03 
13:37:57.000000000 +0200
@@ -1034,7 +1034,7 @@
         data = schema.decode(self.casepath('issues/issue_204/issue_204_3.xml'),
                              validation='lax', keep_unknown=True)
         self.assertEqual(set(x for x in data[0] if x[0] != '@'), {'child2', 
'unknown', 'child5'})
-        self.assertEqual(data[0]['unknown'], {'a': [{'$': '1'}], 'b': [None]})
+        self.assertEqual(data[0]['unknown'], {'a': ['1'], 'b': [None]})
 
         data = 
schema.decode(self.casepath('issues/issue_204/issue_204_2.xml'), 
validation='skip')
         self.assertEqual(set(x for x in data if x[0] != '@'), {'child2', 
'child5'})
@@ -1042,7 +1042,7 @@
         data = schema.decode(self.casepath('issues/issue_204/issue_204_3.xml'),
                              validation='skip', keep_unknown=True)
         self.assertEqual(set(x for x in data if x[0] != '@'), {'child2', 
'unknown', 'child5'})
-        self.assertEqual(data['unknown'], {'a': [{'$': '1'}], 'b': [None]})
+        self.assertEqual(data['unknown'], {'a': ['1'], 'b': [None]})
 
     def test_error_message__issue_115(self):
         schema = 
self.schema_class(self.casepath('issues/issue_115/Rotation.xsd'))
@@ -1111,7 +1111,7 @@
         schema = 
self.schema_class(self.casepath('issues/issue_190/issue_190.xsd'))
         self.assertEqual(
             schema.to_dict(self.casepath('issues/issue_190/issue_190.xml')),
-            {'a': {'c': [{'$': '1'}]}, 'b': {'c': [{'$': '1'}], 'e': [{'$': 
'1'}]}}
+            {'a': {'c': ['1']}, 'b': {'c': ['1'], 'e': ['1']}}
         )
 
     def test_issue_200(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/tests/validation/test_encoding.py 
new/xmlschema-1.6.4/tests/validation/test_encoding.py
--- old/xmlschema-1.6.1/tests/validation/test_encoding.py       2021-02-11 
15:32:40.000000000 +0100
+++ new/xmlschema-1.6.4/tests/validation/test_encoding.py       2021-06-09 
19:22:21.000000000 +0200
@@ -13,6 +13,11 @@
 import unittest
 from textwrap import dedent
 
+try:
+    import lxml.etree as lxml_etree
+except ImportError:
+    lxml_etree = None
+
 from elementpath import datatypes
 
 from xmlschema import XMLSchemaEncodeError, XMLSchemaValidationError
@@ -568,6 +573,85 @@
         self.assertIsNone(elem.text)
         self.assertEqual(elem.attrib, {'b1': 'false', 'b2': 'false', 'b3': 
'false'})
 
+    def test_encode_sub_tree(self):
+        """Test encoding data of a non-root element"""
+        data = {
+            "@id": "PAR",
+            "name": "Pierre-Auguste Renoir",
+            "born": "1841-02-25",
+            "dead": "1919-12-03",
+            "qualification": "painter",
+        }
+        elem = self.col_schema.encode(
+            data,
+            path=".//author",
+            namespaces=self.col_namespaces,
+        )
+        self.assertEqual(
+            etree_tostring(elem),
+            dedent(
+                """\
+                <author id="PAR">
+                    <name>Pierre-Auguste Renoir</name>
+                    <born>1841-02-25</born>
+                    <dead>1919-12-03</dead>
+                    <qualification>painter</qualification>
+                </author>"""
+            )
+        )
+
+    @unittest.skipIf(lxml_etree is None, "The lxml library is not available.")
+    def test_lxml_encode(self):
+        """Test encode with etree_element_class=lxml.etree.Element"""
+        xd = {
+            "@xmlns:col": "http://example.com/ns/collection";,
+            "@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance";,
+            "@xsi:schemaLocation": "http://example.com/ns/collection 
collection.xsd",
+            "object": [
+                {
+                    "@id": "b0836217463",
+                    "@available": True,
+                    "position": 2,
+                    "title": None,
+                    "year": "1925",
+                    "author": {
+                        "@id": "JM",
+                        "name": "Joan Mir??",
+                        "born": "1893-04-20",
+                        "dead": "1983-12-25",
+                        "qualification": "painter, sculptor and ceramicist",
+                    },
+                },
+            ],
+        }
+
+        elem = self.col_schema.encode(
+            xd,
+            path="./col:collection",
+            namespaces=self.col_namespaces,
+            etree_element_class=lxml_etree.Element,
+        )
+
+        self.assertEqual(
+            etree_tostring(elem, namespaces=self.col_namespaces),
+            dedent(
+                """\
+                <col:collection xmlns:col="http://example.com/ns/collection"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://example.com/ns/collection collection.xsd">
+                    <object id="b0836217463" available="true">
+                        <position>2</position>
+                        <title/>
+                        <year>1925</year>
+                        <author id="JM">
+                            <name>Joan Mir??</name>
+                            <born>1893-04-20</born>
+                            <dead>1983-12-25</dead>
+                            <qualification>painter, sculptor and 
ceramicist</qualification>
+                        </author>
+                    </object>
+                </col:collection>"""
+            )
+        )
+
 
 class TestEncoding11(TestEncoding):
     schema_class = XMLSchema11
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/tox.ini new/xmlschema-1.6.4/tox.ini
--- old/xmlschema-1.6.1/tox.ini 2021-04-05 23:38:16.000000000 +0200
+++ new/xmlschema-1.6.4/tox.ini 2021-06-08 11:20:00.000000000 +0200
@@ -4,16 +4,16 @@
 # and then run "tox" from this directory.
 
 [tox]
-envlist = py{36,37,38,39}, pypy3, ep221, docs, flake8, coverage
+envlist = py{36,37,38,39,310}, pypy3, ep222, docs, flake8, coverage
 skip_missing_interpreters = true
 toxworkdir = {homedir}/.tox/xmlschema
 
 [testenv]
 deps =
-    elementpath>=2.2.1, <3.0.0
+    elementpath>=2.2.2, <3.0.0
     lxml
     jinja2
-    py{37,38,39}: memory_profiler
+    py{38,39}: memory_profiler
     docs: Sphinx
     docs: sphinx_rtd_theme
     flake8: flake8
@@ -35,9 +35,9 @@
 [testenv:pypy3]
 commands = python -m unittest
 
-[testenv:ep221]
+[testenv:ep222]
 deps =
-    elementpath==2.2.1
+    elementpath==2.2.2
     lxml
 
 [testenv:docs]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/__init__.py 
new/xmlschema-1.6.4/xmlschema/__init__.py
--- old/xmlschema-1.6.1/xmlschema/__init__.py   2021-04-11 22:19:21.000000000 
+0200
+++ new/xmlschema-1.6.4/xmlschema/__init__.py   2021-06-09 19:22:21.000000000 
+0200
@@ -30,7 +30,7 @@
     XsdComponent, XsdType, XsdElement, XsdAttribute
 )
 
-__version__ = '1.6.1'
+__version__ = '1.6.4'
 __author__ = "Davide Brunato"
 __contact__ = "[email protected]"
 __copyright__ = "Copyright 2016-2021, SISSA"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/converters/abdera.py 
new/xmlschema-1.6.4/xmlschema/converters/abdera.py
--- old/xmlschema-1.6.1/xmlschema/converters/abdera.py  2021-02-11 
15:32:40.000000000 +0100
+++ new/xmlschema-1.6.4/xmlschema/converters/abdera.py  2021-06-07 
11:47:24.000000000 +0200
@@ -24,6 +24,8 @@
     :param dict_class: Dictionary class to use for decoded data. Default is 
`dict`.
     :param list_class: List class to use for decoded data. Default is `list`.
     """
+    __slots__ = ()
+
     def __init__(self, namespaces=None, dict_class=None, list_class=None, 
**kwargs):
         kwargs.update(attr_prefix='', text_key='', cdata_prefix=None)
         super(AbderaConverter, self).__init__(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/converters/badgerfish.py 
new/xmlschema-1.6.4/xmlschema/converters/badgerfish.py
--- old/xmlschema-1.6.1/xmlschema/converters/badgerfish.py      2021-02-11 
15:32:40.000000000 +0100
+++ new/xmlschema-1.6.4/xmlschema/converters/badgerfish.py      2021-06-07 
11:47:24.000000000 +0200
@@ -23,6 +23,8 @@
     :param dict_class: Dictionary class to use for decoded data. Default is 
`dict`.
     :param list_class: List class to use for decoded data. Default is `list`.
     """
+    __slots__ = ()
+
     def __init__(self, namespaces=None, dict_class=None, list_class=None, 
**kwargs):
         kwargs.update(attr_prefix='@', text_key='$', cdata_prefix='$')
         super(BadgerFishConverter, self).__init__(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/converters/columnar.py 
new/xmlschema-1.6.4/xmlschema/converters/columnar.py
--- old/xmlschema-1.6.1/xmlschema/converters/columnar.py        2021-02-11 
15:32:40.000000000 +0100
+++ new/xmlschema-1.6.4/xmlschema/converters/columnar.py        2021-06-07 
11:47:24.000000000 +0200
@@ -23,6 +23,8 @@
     :param attr_prefix: used as separator string for renaming the decoded 
attributes. \
     Can be the empty string (the default) or a single/double underscore.
     """
+    __slots__ = ()
+
     def __init__(self, namespaces=None, dict_class=None, list_class=None,
                  attr_prefix='', **kwargs):
         kwargs.update(text_key=None, cdata_prefix=None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/converters/default.py 
new/xmlschema-1.6.4/xmlschema/converters/default.py
--- old/xmlschema-1.6.1/xmlschema/converters/default.py 2021-02-11 
15:32:40.000000000 +0100
+++ new/xmlschema-1.6.4/xmlschema/converters/default.py 2021-06-09 
11:27:09.000000000 +0200
@@ -55,12 +55,13 @@
     :param strip_namespaces: if set to `True` removes namespace declarations 
from data and \
     namespace information from names, during decoding or encoding. Defaults to 
`False`.
     :param preserve_root: if set to `True` the root element is preserved, 
wrapped into a \
-    single-item dictionary. Applicable only to default converter and to 
:class:`ParkerConverter`.
+    single-item dictionary. Applicable only to default converter, to \
+    :class:`UnorderedConverter` and to :class:`ParkerConverter`.
     :param force_dict: if set to `True` complex elements with simple content 
are decoded \
-    with a dictionary also if there are no decoded attributes. Applicable to 
default converter \
-    only. Defaults to `False`.
+    with a dictionary also if there are no decoded attributes. Applicable only 
to default \
+    converter and to :class:`UnorderedConverter`. Defaults to `False`.
     :param force_list: if set to `True` child elements are decoded within a 
list in any case. \
-    Applicable to default converter only. Defaults to `False`.
+    Applicable only to default converter and to :class:`UnorderedConverter`. 
Defaults to `False`.
 
     :ivar dict: dictionary class to use for decoded data.
     :ivar list: list class to use for decoded data.
@@ -77,7 +78,9 @@
     dict = dict
     list = list
     etree_element_class = etree_element
-    ns_prefix = None
+
+    __slots__ = ('text_key', 'ns_prefix', 'attr_prefix', 'cdata_prefix',
+                 'indent', 'preserve_root', 'force_dict', 'force_list')
 
     def __init__(self, namespaces=None, dict_class=None, list_class=None,
                  etree_element_class=None, text_key='$', attr_prefix='@',
@@ -93,6 +96,7 @@
         if etree_element_class is not None:
             self.etree_element_class = etree_element_class
 
+        self.ns_prefix = None
         self.text_key = text_key
         self.attr_prefix = attr_prefix
         self.cdata_prefix = cdata_prefix
@@ -221,7 +225,8 @@
             else:
                 elem = self.etree_element_class(tag, self.dict(attrib))
         else:
-            nsmap = {prefix if prefix else None: uri for prefix, uri in 
self._namespaces.items()}
+            nsmap = {prefix if prefix else None: uri
+                     for prefix, uri in self._namespaces.items() if uri}
             elem = self.etree_element_class(tag, nsmap=nsmap)
             elem.attrib.update(attrib)
 
@@ -294,7 +299,12 @@
                 return self.dict(
                     [(self.map_qname(data.tag), result_dict if result_dict 
else None)]
                 )
-            return result_dict if result_dict else None
+
+            if not result_dict:
+                return None
+            elif len(result_dict) == 1 and self.text_key in result_dict:
+                return result_dict[self.text_key]
+            return result_dict
 
     def element_encode(self, obj, xsd_element, level=0):
         """
@@ -308,7 +318,10 @@
         if level != 0:
             tag = xsd_element.name
         else:
-            tag = xsd_element.qualified_name
+            if xsd_element.is_global():
+                tag = xsd_element.qualified_name
+            else:
+                tag = xsd_element.name
             if self.preserve_root and isinstance(obj, MutableMapping):
                 match_local_name = self.strip_namespaces or 
self.default_namespace
                 match = xsd_element.get_matching_item(obj, self.ns_prefix, 
match_local_name)
@@ -318,8 +331,8 @@
         if not isinstance(obj, MutableMapping):
             if xsd_element.type.simple_type is not None:
                 return ElementData(tag, obj, None, {})
-            elif xsd_element.type.mixed and not isinstance(obj, 
MutableSequence):
-                return ElementData(tag, obj, None, {})
+            elif xsd_element.type.mixed and isinstance(obj, (str, bytes)):
+                return ElementData(tag, None, [(1, obj)], {})
             else:
                 return ElementData(tag, None, obj, {})
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/converters/jsonml.py 
new/xmlschema-1.6.4/xmlschema/converters/jsonml.py
--- old/xmlschema-1.6.1/xmlschema/converters/jsonml.py  2021-02-11 
15:32:40.000000000 +0100
+++ new/xmlschema-1.6.4/xmlschema/converters/jsonml.py  2021-06-07 
11:47:24.000000000 +0200
@@ -24,6 +24,8 @@
     :param dict_class: Dictionary class to use for decoded data. Default is 
`dict`.
     :param list_class: List class to use for decoded data. Default is `list`.
     """
+    __slots__ = ()
+
     def __init__(self, namespaces=None, dict_class=None, list_class=None, 
**kwargs):
         kwargs.update(attr_prefix='', text_key='', cdata_prefix='')
         super(JsonMLConverter, self).__init__(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/converters/parker.py 
new/xmlschema-1.6.4/xmlschema/converters/parker.py
--- old/xmlschema-1.6.1/xmlschema/converters/parker.py  2021-02-11 
15:32:40.000000000 +0100
+++ new/xmlschema-1.6.4/xmlschema/converters/parker.py  2021-06-07 
11:47:24.000000000 +0200
@@ -25,6 +25,8 @@
     :param preserve_root: If `True` the root element will be preserved. For 
default \
     the Parker convention remove the document root element, returning only the 
value.
     """
+    __slots__ = ()
+
     def __init__(self, namespaces=None, dict_class=None, list_class=None,
                  preserve_root=False, **kwargs):
         kwargs.update(attr_prefix=None, text_key='', cdata_prefix=None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/converters/unordered.py 
new/xmlschema-1.6.4/xmlschema/converters/unordered.py
--- old/xmlschema-1.6.1/xmlschema/converters/unordered.py       2021-02-11 
15:32:40.000000000 +0100
+++ new/xmlschema-1.6.4/xmlschema/converters/unordered.py       2021-06-07 
11:47:24.000000000 +0200
@@ -22,6 +22,8 @@
     As the order of the input dictionary is not preserved, character data
     between sibling elements are interleaved between tags.
     """
+    __slots__ = ()
+
     def element_encode(self, obj, xsd_element, level=0):
         """
         Extracts XML decoded data from a data structure for encoding into an 
ElementTree.
@@ -31,7 +33,7 @@
         :param level: the level related to the encoding process (0 means the 
root).
         :return: an ElementData instance.
         """
-        if level != 0:
+        if level:
             tag = xsd_element.name
         else:
             tag = xsd_element.qualified_name
@@ -44,6 +46,8 @@
         if not isinstance(obj, MutableMapping):
             if xsd_element.type.simple_type is not None:
                 return ElementData(tag, obj, None, {})
+            elif xsd_element.type.mixed and isinstance(obj, (str, bytes)):
+                return ElementData(tag, None, [(1, obj)], {})
             else:
                 return ElementData(tag, None, obj, {})
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/dataobjects.py 
new/xmlschema-1.6.4/xmlschema/dataobjects.py
--- old/xmlschema-1.6.1/xmlschema/dataobjects.py        2021-04-05 
23:38:16.000000000 +0200
+++ new/xmlschema-1.6.4/xmlschema/dataobjects.py        2021-06-07 
11:47:24.000000000 +0200
@@ -329,11 +329,10 @@
     :param data_element_class: MutableSequence subclass to use for decoded 
data. \
     Default is `DataElement`.
     """
-    data_element_class = DataElement
+    __slots__ = 'data_element_class',
 
     def __init__(self, namespaces=None, data_element_class=None, **kwargs):
-        if data_element_class is not None:
-            self.data_element_class = data_element_class
+        self.data_element_class = data_element_class or DataElement
         kwargs.update(attr_prefix='', text_key='', cdata_prefix='')
         super(DataElementConverter, self).__init__(namespaces, **kwargs)
 
@@ -404,6 +403,8 @@
     *data_element_class* is used for define the base for creating the missing
     XML binding classes.
     """
+    __slots__ = ()
+
     def element_decode(self, data, xsd_element, xsd_type=None, level=0):
         cls = xsd_element.get_binding(self.data_element_class)
         data_element = cls(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/documents.py 
new/xmlschema-1.6.4/xmlschema/documents.py
--- old/xmlschema-1.6.1/xmlschema/documents.py  2021-01-23 11:58:27.000000000 
+0100
+++ new/xmlschema-1.6.4/xmlschema/documents.py  2021-05-03 13:37:57.000000000 
+0200
@@ -289,7 +289,8 @@
     :param converter: an :class:`XMLSchemaConverter` subclass or instance to 
use \
     for the encoding.
     :param json_options: a dictionary with options for the JSON deserializer.
-    :param kwargs: Keyword arguments containing options for converter and 
encoding.
+    :param kwargs: other optional arguments of :meth:`XMLSchema.iter_encode` 
and \
+    options for converter.
     :return: An element tree's Element instance. If ``validation='lax'`` 
keyword argument is \
     provided the validation errors are collected and returned coupled in a 
tuple with the \
     Element instance.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/namespaces.py 
new/xmlschema-1.6.4/xmlschema/namespaces.py
--- old/xmlschema-1.6.1/xmlschema/namespaces.py 2021-02-11 15:32:40.000000000 
+0100
+++ new/xmlschema-1.6.4/xmlschema/namespaces.py 2021-06-07 11:47:24.000000000 
+0200
@@ -26,6 +26,8 @@
     lists of strings. Setting an existing value appends the string to the 
value.
     Setting a value with a list sets/replaces the value.
     """
+    __slots__ = ('_store',)
+
     def __init__(self, *args, **kwargs):
         self._store = dict()
         self.update(*args, **kwargs)
@@ -70,6 +72,8 @@
     :param strip_namespaces: if set to `True` uses name mapping methods that 
strip \
     namespace information.
     """
+    __slots__ = '_namespaces', 'strip_namespaces', '__dict__'
+
     def __init__(self, namespaces=None, strip_namespaces=False):
         if namespaces is None:
             self._namespaces = {}
@@ -230,6 +234,8 @@
     A read-only map for filtered access to a dictionary that stores
     objects mapped from QNames in extended format.
     """
+    __slots__ = 'target_dict', 'namespace', '_key_fmt'
+
     def __init__(self, qname_dict, namespace_uri):
         self.target_dict = qname_dict
         self.namespace = namespace_uri
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/resources.py 
new/xmlschema-1.6.4/xmlschema/resources.py
--- old/xmlschema-1.6.1/xmlschema/resources.py  2021-04-11 22:19:21.000000000 
+0200
+++ new/xmlschema-1.6.4/xmlschema/resources.py  2021-06-09 19:22:22.000000000 
+0200
@@ -8,13 +8,14 @@
 # @author Davide Brunato <[email protected]>
 #
 import os.path
+import pathlib
 import platform
 import re
-from string import ascii_letters
+import string
 from elementpath import iter_select, XPath1Parser, XPathContext, XPath2Parser
 from io import StringIO, BytesIO
-from urllib.request import urlopen, pathname2url
-from urllib.parse import uses_relative, urlsplit, urljoin, urlunsplit, unquote
+from urllib.request import urlopen
+from urllib.parse import urlsplit, urlunsplit, unquote, quote_from_bytes
 from urllib.error import URLError
 
 from .exceptions import XMLSchemaTypeError, XMLSchemaValueError, 
XMLResourceError
@@ -35,6 +36,8 @@
     '(string)', '(float)', '(decimal)', '(integer)', '@'
 }
 
+DRIVE_LETTERS = frozenset(string.ascii_letters)
+
 
 class LazyXPath2Parser(XPath2Parser):
     symbol_table = {
@@ -73,94 +76,120 @@
 
 ###
 # URL normalization (that fixes many headaches :)
+class _PurePath(pathlib.PurePath):
+    """
+    A version of pathlib.PurePath adapted for managing the creation
+    from URIs and the simple normalization of paths.
+    """
+    def __new__(cls, *args):
+        if cls is _PurePath:
+            cls = _WindowsPurePath if os.name == 'nt' else _PosixPurePath
+        return cls._from_parts(args)
+
+    @classmethod
+    def from_uri(cls, uri):
+        uri = uri.strip()
+        if not uri:
+            raise XMLSchemaValueError("Empty URI provided!")
+
+        if uri.startswith(r'\\'):
+            return _WindowsPurePath(uri)  # UNC path
+        elif uri.startswith('/'):
+            return cls(uri)
+
+        parts = urlsplit(uri)
+        if not parts.scheme:
+            return cls(uri)
+        elif parts.scheme in DRIVE_LETTERS and len(parts.scheme) == 1:
+            return _WindowsPurePath(uri)  # Eg. k:/Python/lib/....
+        elif parts.scheme != 'file':
+            return _PosixPurePath(unquote(parts.path))
+
+        # Get file URI path because urlsplit does not parse it well
+        start = 7 if uri.startswith('file:///') else 5
+        if parts.query:
+            path = uri[start:uri.index('?')]
+        elif parts.fragment:
+            path = uri[start:uri.index('#')]
+        else:
+            path = uri[start:]
+
+        if ':' in path:
+            # Windows path with a drive
+            pos = path.index(':')
+            if pos == 2 and path[0] == '/' and path[1] in DRIVE_LETTERS:
+                return _WindowsPurePath(unquote(path[1:]))
+
+            obj = _WindowsPurePath(unquote(path))
+            if len(obj.drive) != 2 or obj.drive[1] != ':':
+                raise XMLSchemaValueError("Invalid URI {!r}".format(uri))
+            return obj
+
+        if '\\' in path:
+            return _WindowsPurePath(unquote(path))
+        return cls(unquote(path))
+
+    def as_uri(self):
+        if not self.is_absolute():
+            uri = self._flavour.make_uri(self)
+            while uri.startswith('file:/'):
+                uri = uri.replace('file:/', 'file:', 1)
+            return uri
+        return self._flavour.make_uri(self)
+
+    def normalize(self):
+        normalized_path = self._flavour.pathmod.normpath(str(self))
+        return self._from_parts((normalized_path,))
+
+
+class _PosixPurePath(_PurePath, pathlib.PurePosixPath):
+    __slots__ = ()
+
+
+class _WindowsPurePath(_PurePath, pathlib.PureWindowsPath):
+    __slots__ = ()
+
 
 def normalize_url(url, base_url=None, keep_relative=False):
     """
-    Returns a normalized URL doing a join with a base URL. URL scheme defaults 
to 'file' and
-    backslashes are replaced with slashes. For file paths the os.path.join is 
used instead of
-    urljoin.
+    Returns a normalized URL eventually joining it to a base URL if it's a 
relative path.
+    Path names are converted to 'file' scheme URLs.
 
     :param url: a relative or absolute URL.
-    :param base_url: the reference base URL for construct the normalized URL 
from \
-    the argument. For compatibility between "os.path.join" and "urljoin" a 
trailing \
-    '/' is added to not empty paths.
+    :param base_url: a reference base URL.
     :param keep_relative: if set to `True` keeps relative file paths, which 
would \
-    not strictly conformant to URL format specification.
-    :return: A normalized URL.
-    """
-    def add_trailing_slash(x):
-        return urlunsplit(
-            (x[0], x[1], x[2] + '/' if x[2] and x[2][-1] != '/' else x[2], 
x[3], x[4])
-        )
-
-    def filter_url(x):
-        x = x.strip().replace('\\', '/')
-        while x.startswith('//'):
-            x = x.replace('//', '/', 1)
-        while x.startswith('file:////'):
-            x = x.replace('file:////', 'file:///', 1)
-        if urlsplit(x).scheme in {'', 'file'}:
-            x = x.replace('#', '%23')
-        return x
-
-    url = filter_url(url)
+    not strictly conformant to specification (RFC 8089), because *urlopen()* 
doesn't \
+    accept a simple pathname.
+    :return: a normalized URL string.
+    """
+    url_parts = urlsplit(url)
+    if not is_local_scheme(url_parts.scheme):
+        return url_parts.geturl()
+
+    path = _PurePath.from_uri(url)
+    if path.is_absolute():
+        return path.normalize().as_uri()
 
     if base_url is not None:
-        base_url = filter_url(base_url)
         base_url_parts = urlsplit(base_url)
-        base_url = add_trailing_slash(base_url_parts)
-        if base_url_parts.scheme not in uses_relative:
-            base_url_parts = urlsplit('file:///{}'.format(base_url))
-        else:
-            base_url_parts = urlsplit(base_url)
+        base_path = _PurePath.from_uri(base_url)
+        if is_local_scheme(base_url_parts.scheme):
+            path = base_path.joinpath(path)
+        elif not url_parts.scheme:
+            path = base_path.joinpath(path).normalize()
+            return urlunsplit((
+                base_url_parts.scheme,
+                base_url_parts.netloc,
+                quote_from_bytes(bytes(path)),
+                url_parts.query,
+                url_parts.fragment
+            ))
 
-        if base_url_parts.scheme not in ('', 'file'):
-            url = urljoin(base_url, url)
-        else:
-            url_parts = urlsplit(url)
-            if url_parts.scheme not in ('', 'file'):
-                url = urljoin(base_url, url)
-            elif not url_parts.netloc or base_url_parts.netloc == 
url_parts.netloc:
-                # Join paths only if host parts (netloc) are equal, using the 
os.path.join
-                # instead of urljoin for path normalization.
-                url = urlunsplit((
-                    '',
-                    base_url_parts.netloc,
-                    os.path.normpath(os.path.join(base_url_parts.path, 
url_parts.path)),
-                    url_parts.query,
-                    url_parts.fragment,
-                ))
-
-                # Add 'file' scheme if '//' prefix is added
-                if base_url_parts.netloc and not 
url.startswith(base_url_parts.netloc) \
-                        and url.startswith('//'):
-                    url = 'file:' + url
-
-    url_parts = urlsplit(url, scheme='file')
-    if url_parts.scheme not in uses_relative:
-        normalized_url = 'file:///{}'.format(url_parts.geturl())  # Eg. 
k:/Python/lib/....
-    elif url_parts.scheme != 'file':
-        normalized_url = urlunsplit((
-            url_parts.scheme,
-            url_parts.netloc,
-            pathname2url(url_parts.path),
-            url_parts.query,
-            url_parts.fragment,
-        ))
-    elif os.path.isabs(url_parts.path):
-        normalized_url = url_parts.geturl()
-    elif keep_relative:
-        # Can't use urlunsplit with a scheme because it converts relative 
paths to absolute ones.
-        normalized_url = 'file:{}'.format(urlunsplit(('',) + url_parts[1:]))
-    else:
-        normalized_url = urlunsplit((
-            url_parts.scheme,
-            url_parts.netloc,
-            os.path.abspath(url_parts.path),
-            url_parts.query,
-            url_parts.fragment,
-        ))
-    return filter_url(normalized_url)
+    if path.is_absolute() or keep_relative:
+        return path.normalize().as_uri()
+
+    base_path = _PurePath(os.getcwd())
+    return base_path.joinpath(path).normalize().as_uri()
 
 
 ###
@@ -186,18 +215,16 @@
         return True
 
 
+def is_local_scheme(scheme):
+    return not scheme or scheme == 'file' or scheme in DRIVE_LETTERS
+
+
 def is_remote_url(url):
-    if not is_url(url):
-        return False
-    scheme = urlsplit(normalize_url(url)).scheme
-    return scheme not in ('', 'file') and (len(scheme) > 1 or scheme not in 
ascii_letters)
+    return is_url(url) and not is_local_scheme(urlsplit(url.strip()).scheme)
 
 
 def is_local_url(url):
-    if not is_url(url):
-        return False
-    scheme = urlsplit(normalize_url(url)).scheme
-    return scheme in ('', 'file') or len(scheme) == 1 and scheme in 
ascii_letters
+    return is_url(url) and is_local_scheme(urlsplit(url.strip()).scheme)
 
 
 def url_path_is_file(url):
@@ -433,7 +460,7 @@
     @property
     def filepath(self):
         """
-        The resource filepath if the intance is created from a local file, 
`None` otherwise.
+        The resource filepath if the instance is created from a local file, 
`None` otherwise.
         """
         if self._url:
             url_parts = urlsplit(self._url)
@@ -759,7 +786,7 @@
             msg = "{!r} is not an element or the XML resource tree"
             raise XMLResourceError(msg.format(elem))
 
-        resource = XMLResource(elem, self._base_url, self._allow, 
self._defuse, self._timeout)
+        resource = XMLResource(elem, self.base_url, self._allow, self._defuse, 
self._timeout)
         if not hasattr(elem, 'nsmap'):
             namespaces = {}
             _nsmap = self._nsmap[elem]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/validators/elements.py 
new/xmlschema-1.6.4/xmlschema/validators/elements.py
--- old/xmlschema-1.6.1/xmlschema/validators/elements.py        2021-04-05 
23:38:16.000000000 +0200
+++ new/xmlschema-1.6.4/xmlschema/validators/elements.py        2021-05-03 
13:37:57.000000000 +0200
@@ -26,7 +26,7 @@
     raw_xml_encode, strictly_equal
 from .. import dataobjects
 from ..converters import ElementData, XMLSchemaConverter
-from ..xpath import XMLSchemaProxy, ElementPathMixin
+from ..xpath import XMLSchemaProxy, ElementPathMixin, XPathElement
 
 from .exceptions import XMLSchemaValidationError, XMLSchemaTypeTableWarning
 from .helpers import get_xsd_derivation_attribute
@@ -34,7 +34,7 @@
     XsdComponent, XsdType, ValidationMixin
 from .particles import ParticleMixin
 from .models import OccursCounter
-from .identities import XsdIdentity, XsdKeyref
+from .identities import IdentityXPathContext, XsdIdentity, XsdKeyref
 from .wildcards import XsdAnyElement
 
 
@@ -577,6 +577,14 @@
                 xsd_type = self.maps.get_instance_type(type_name, xsd_type, 
namespaces)
             except (KeyError, TypeError) as err:
                 yield self.validation_error(validation, err, elem, **kwargs)
+            else:
+                if self.identities:
+                    xpath_element = XPathElement(self.name, xsd_type)
+                    for identity in self.identities.values():
+                        context = IdentityXPathContext(self.schema, 
item=xpath_element)
+                        for e in 
identity.selector.token.select_results(context):
+                            if e not in identity.elements:
+                                identity.elements[e] = None
 
             if xsd_type.is_blocked(self):
                 reason = "usage of %r is blocked" % xsd_type
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/validators/schema.py 
new/xmlschema-1.6.4/xmlschema/validators/schema.py
--- old/xmlschema-1.6.1/xmlschema/validators/schema.py  2021-04-11 
22:19:21.000000000 +0200
+++ new/xmlschema-1.6.4/xmlschema/validators/schema.py  2021-06-06 
12:53:20.000000000 +0200
@@ -1826,7 +1826,7 @@
         :param unordered: a flag for explicitly activating unordered encoding 
mode for \
         content model data. This mode uses content models for a 
reordered-by-model \
         iteration of the child elements.
-        :param kwargs: Keyword arguments containing options for converter and 
encoding.
+        :param kwargs: keyword arguments containing options for converter.
         :return: yields an Element instance/s or validation/encoding errors.
         """
         self.check_validator(validation)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/validators/xsdbase.py 
new/xmlschema-1.6.4/xmlschema/validators/xsdbase.py
--- old/xmlschema-1.6.1/xmlschema/validators/xsdbase.py 2021-04-05 
23:38:16.000000000 +0200
+++ new/xmlschema-1.6.4/xmlschema/validators/xsdbase.py 2021-06-09 
19:22:22.000000000 +0200
@@ -120,7 +120,7 @@
     def copy(self):
         validator = object.__new__(self.__class__)
         validator.__dict__.update(self.__dict__)
-        validator.errors = self.errors[:]
+        validator.errors = self.errors[:]  # shallow copy duplicates errors 
list
         return validator
 
     __copy__ = copy
@@ -610,7 +610,7 @@
         is the primitive type. For a list is the primitive type of the item.
         For a union is the base union type. For a complex type is xs:anyType.
         """
-        if self.is_complex() and self.attributes:
+        if getattr(self, 'attributes', None):
             return self.maps.types[XSD_ANY_TYPE]
         elif self.base_type is None:
             return self if self.is_simple() else self.maps.types[XSD_ANY_TYPE]
@@ -853,7 +853,7 @@
         Element for other components.
         :param with_bindings: if `True` is provided the decoding is done using 
\
         :class:`DataBindingConverter` that used XML data binding classes. For \
-        default the objects are intances of :class:`DataElement` and uses the \
+        default the objects are instances of :class:`DataElement` and uses the 
\
         :class:`DataElementConverter`.
         :param kwargs: other optional keyword arguments for the method \
         :func:`iter_decode`, except the argument *converter*.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema/xpath.py 
new/xmlschema-1.6.4/xmlschema/xpath.py
--- old/xmlschema-1.6.1/xmlschema/xpath.py      2021-04-05 23:38:16.000000000 
+0200
+++ new/xmlschema-1.6.4/xmlschema/xpath.py      2021-05-03 13:37:57.000000000 
+0200
@@ -18,6 +18,7 @@
     XPathSchemaContext, AbstractSchemaProxy
 
 from .names import XSD_NAMESPACE
+from .helpers import get_qname, local_name, get_prefixed_qname
 from .exceptions import XMLSchemaValueError, XMLSchemaTypeError
 
 _REGEX_TAG_POSITION = re.compile(r'\b\[\d+]')
@@ -276,3 +277,49 @@
         for child in self:
             if tag is None or child.is_matching(tag):
                 yield child
+
+
+class XPathElement(ElementPathMixin):
+    """An element node for making XPath operations on schema types."""
+
+    parent = None
+
+    def __init__(self, name, xsd_type):
+        self.name = name
+        self.type = xsd_type
+        try:
+            self.attributes = xsd_type.attributes
+        except AttributeError:
+            pass
+
+    def __iter__(self):
+        if not self.type.has_simple_content():
+            yield from self.type.content.iter_elements()
+
+    @property
+    def xpath_proxy(self):
+        return XMLSchemaProxy(self.schema, self)
+
+    @property
+    def schema(self):
+        return self.type.schema
+
+    @property
+    def target_namespace(self):
+        return self.type.schema.target_namespace
+
+    @property
+    def namespaces(self):
+        return self.type.schema.namespaces
+
+    @property
+    def local_name(self):
+        return local_name(self.name)
+
+    @property
+    def qualified_name(self):
+        return get_qname(self.target_namespace, self.name)
+
+    @property
+    def prefixed_name(self):
+        return get_prefixed_qname(self.name, self.namespaces)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema.egg-info/PKG-INFO 
new/xmlschema-1.6.4/xmlschema.egg-info/PKG-INFO
--- old/xmlschema-1.6.1/xmlschema.egg-info/PKG-INFO     2021-04-11 
23:17:40.000000000 +0200
+++ new/xmlschema-1.6.4/xmlschema.egg-info/PKG-INFO     2021-06-09 
19:41:05.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: xmlschema
-Version: 1.6.1
+Version: 1.6.4
 Summary: An XML Schema validator and decoder
 Home-page: https://github.com/sissaschool/xmlschema
 Author: Davide Brunato
@@ -181,6 +181,7 @@
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Topic :: Software Development :: Libraries
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema.egg-info/SOURCES.txt 
new/xmlschema-1.6.4/xmlschema.egg-info/SOURCES.txt
--- old/xmlschema-1.6.1/xmlschema.egg-info/SOURCES.txt  2021-04-11 
23:17:40.000000000 +0200
+++ new/xmlschema-1.6.4/xmlschema.egg-info/SOURCES.txt  2021-06-09 
19:41:05.000000000 +0200
@@ -217,6 +217,11 @@
 tests/test_cases/issues/issue_237/dir2/issue_237b.xsd
 tests/test_cases/issues/issue_237/dir2/stockquote.wsdl
 tests/test_cases/issues/issue_237/dir2/stockquote.xsd
+tests/test_cases/issues/issue_243/issue_243.xml
+tests/test_cases/issues/issue_243/issue_243.xsd
+tests/test_cases/issues/issue_245/issue_245-valid.xml
+tests/test_cases/issues/issue_245/issue_245.xml
+tests/test_cases/issues/issue_245/issue_245.xsd
 tests/test_cases/resources/dummy file #2.txt
 tests/test_cases/resources/dummy file.txt
 tests/test_cases/resources/external_entity.xml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xmlschema-1.6.1/xmlschema.egg-info/requires.txt 
new/xmlschema-1.6.4/xmlschema.egg-info/requires.txt
--- old/xmlschema-1.6.1/xmlschema.egg-info/requires.txt 2021-04-11 
23:17:40.000000000 +0200
+++ new/xmlschema-1.6.4/xmlschema.egg-info/requires.txt 2021-06-09 
19:41:05.000000000 +0200
@@ -1,21 +1,21 @@
-elementpath<3.0.0,>=2.2.1
+elementpath<3.0.0,>=2.2.2
 
 [codegen]
-elementpath<3.0.0,>=2.2.1
+elementpath<3.0.0,>=2.2.2
 jinja2
 
 [dev]
 tox
 coverage
 lxml
-elementpath<3.0.0,>=2.2.1
+elementpath<3.0.0,>=2.2.2
 memory_profiler
 Sphinx
 sphinx_rtd_theme
 jinja2
 
 [docs]
-elementpath<3.0.0,>=2.1.2
+elementpath<3.0.0,>=2.2.2
 Sphinx
 sphinx_rtd_theme
 jinja2

Reply via email to