elementpath 4.7.0__tar.gz → 5.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. {elementpath-4.7.0 → elementpath-5.0.0}/CHANGELOG.rst +18 -0
  2. {elementpath-4.7.0 → elementpath-5.0.0}/MANIFEST.in +1 -4
  3. {elementpath-4.7.0 → elementpath-5.0.0}/PKG-INFO +18 -17
  4. {elementpath-4.7.0 → elementpath-5.0.0}/README.rst +1 -1
  5. {elementpath-4.7.0 → elementpath-5.0.0}/doc/advanced.rst +13 -8
  6. {elementpath-4.7.0 → elementpath-5.0.0}/doc/conf.py +3 -3
  7. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/__init__.py +11 -12
  8. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/aliases.py +9 -10
  9. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/collations.py +4 -4
  10. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/compare.py +34 -34
  11. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/datatypes/__init__.py +6 -15
  12. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/datatypes/atomic_types.py +32 -33
  13. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/datatypes/binary.py +1 -2
  14. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/datatypes/datetime.py +17 -10
  15. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/datatypes/numeric.py +3 -3
  16. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/datatypes/proxies.py +2 -2
  17. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/datatypes/untyped.py +2 -2
  18. elementpath-5.0.0/elementpath/decoder.py +167 -0
  19. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/etree.py +46 -81
  20. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/exceptions.py +10 -2
  21. elementpath-5.0.0/elementpath/extras/pathnodes.py +262 -0
  22. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/helpers.py +20 -12
  23. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/namespaces.py +58 -2
  24. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/protocols.py +49 -20
  25. elementpath-5.0.0/elementpath/regex/categories_fallback.py +77 -0
  26. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/regex/character_classes.py +3 -3
  27. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/regex/codepoints.py +4 -5
  28. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/regex/unicode_subsets.py +22 -13
  29. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/schema_proxy.py +67 -11
  30. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/sequence_types.py +12 -13
  31. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/serialization.py +13 -13
  32. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/tdop.py +33 -35
  33. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/tree_builders.py +75 -102
  34. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath1/_xpath1_axes.py +7 -5
  35. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath1/_xpath1_functions.py +15 -13
  36. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath1/_xpath1_operators.py +49 -137
  37. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath1/xpath1_parser.py +41 -28
  38. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath2/_xpath2_constructors.py +5 -8
  39. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath2/_xpath2_functions.py +60 -87
  40. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath2/_xpath2_operators.py +36 -47
  41. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath2/xpath2_parser.py +18 -39
  42. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath30/_xpath30_functions.py +47 -102
  43. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath30/_xpath30_operators.py +6 -10
  44. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath30/xpath30_helpers.py +6 -6
  45. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath30/xpath30_parser.py +4 -4
  46. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath31/_xpath31_functions.py +18 -18
  47. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath31/_xpath31_operators.py +16 -9
  48. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath31/xpath31_parser.py +3 -3
  49. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath_context.py +134 -45
  50. elementpath-5.0.0/elementpath/xpath_nodes.py +1766 -0
  51. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath_selectors.py +18 -11
  52. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath_tokens.py +212 -291
  53. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath.egg-info/PKG-INFO +18 -17
  54. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath.egg-info/SOURCES.txt +9 -7
  55. elementpath-5.0.0/elementpath.egg-info/requires.txt +16 -0
  56. elementpath-5.0.0/pyproject.toml +87 -0
  57. {elementpath-4.7.0 → elementpath-5.0.0}/requirements-dev.txt +4 -4
  58. elementpath-5.0.0/tests/__init__.py +0 -0
  59. {elementpath-4.7.0 → elementpath-5.0.0}/tests/memory_profiling.py +27 -3
  60. elementpath-4.7.0/tests/test_typing.py → elementpath-5.0.0/tests/run_typing_tests.py +1 -1
  61. elementpath-4.7.0/tests/execute_w3c_tests.py → elementpath-5.0.0/tests/run_w3c_tests.py +8 -3
  62. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_compare.py +5 -5
  63. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_datatypes.py +42 -16
  64. elementpath-5.0.0/tests/test_decoder.py +61 -0
  65. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_etree.py +77 -154
  66. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_helpers.py +177 -0
  67. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_namespaces.py +44 -3
  68. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_package.py +6 -6
  69. elementpath-5.0.0/tests/test_pathnodes.py +63 -0
  70. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_schema_context.py +0 -79
  71. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_schema_proxy.py +39 -57
  72. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_sequence_types.py +1 -1
  73. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_serialization.py +2 -2
  74. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_tree_builders.py +3 -3
  75. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_validators.py +1 -1
  76. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_xpath1_parser.py +8 -8
  77. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_xpath2_constructors.py +12 -7
  78. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_xpath2_functions.py +20 -24
  79. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_xpath2_parser.py +60 -41
  80. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_xpath30.py +10 -5
  81. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_xpath_context.py +23 -18
  82. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_xpath_nodes.py +86 -69
  83. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_xpath_tokens.py +39 -285
  84. {elementpath-4.7.0 → elementpath-5.0.0}/tests/xpath_test_class.py +5 -4
  85. {elementpath-4.7.0 → elementpath-5.0.0}/tox.ini +46 -33
  86. elementpath-4.7.0/.coveragerc +0 -12
  87. elementpath-4.7.0/elementpath/_typing.py +0 -27
  88. elementpath-4.7.0/elementpath/decoder.py +0 -176
  89. elementpath-4.7.0/elementpath/xpath_nodes.py +0 -1055
  90. elementpath-4.7.0/elementpath.egg-info/requires.txt +0 -12
  91. elementpath-4.7.0/mypy.ini +0 -2
  92. elementpath-4.7.0/setup.py +0 -59
  93. {elementpath-4.7.0 → elementpath-5.0.0}/LICENSE +0 -0
  94. {elementpath-4.7.0 → elementpath-5.0.0}/doc/Makefile +0 -0
  95. {elementpath-4.7.0 → elementpath-5.0.0}/doc/index.rst +0 -0
  96. {elementpath-4.7.0 → elementpath-5.0.0}/doc/introduction.rst +0 -0
  97. {elementpath-4.7.0 → elementpath-5.0.0}/doc/make.bat +0 -0
  98. {elementpath-4.7.0 → elementpath-5.0.0}/doc/pratt_api.rst +0 -0
  99. {elementpath-4.7.0 → elementpath-5.0.0}/doc/requirements.txt +0 -0
  100. {elementpath-4.7.0 → elementpath-5.0.0}/doc/xpath_api.rst +0 -0
  101. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/datatypes/qname.py +0 -0
  102. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/datatypes/string.py +0 -0
  103. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/datatypes/uri.py +0 -0
  104. {elementpath-4.7.0/tests → elementpath-5.0.0/elementpath/extras}/__init__.py +0 -0
  105. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/py.typed +0 -0
  106. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/regex/__init__.py +0 -0
  107. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/regex/patterns.py +0 -0
  108. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/regex/unicode_blocks.py +0 -0
  109. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/regex/unicode_categories.py +0 -0
  110. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/validators/__init__.py +0 -0
  111. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/validators/analyze-string.xsd +0 -0
  112. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/validators/schema-for-json.xsd +0 -0
  113. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath1/__init__.py +0 -0
  114. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath2/__init__.py +0 -0
  115. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath3.py +0 -0
  116. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath30/__init__.py +0 -0
  117. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath30/_translation_maps.py +0 -0
  118. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath/xpath31/__init__.py +0 -0
  119. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath.egg-info/dependency_links.txt +0 -0
  120. {elementpath-4.7.0 → elementpath-5.0.0}/elementpath.egg-info/top_level.txt +0 -0
  121. {elementpath-4.7.0 → elementpath-5.0.0}/scripts/generate_codepoints.py +0 -0
  122. {elementpath-4.7.0 → elementpath-5.0.0}/setup.cfg +0 -0
  123. {elementpath-4.7.0 → elementpath-5.0.0}/tests/mypy_tests/advanced.py +0 -0
  124. {elementpath-4.7.0 → elementpath-5.0.0}/tests/mypy_tests/protocols.py +0 -0
  125. {elementpath-4.7.0 → elementpath-5.0.0}/tests/mypy_tests/selectors.py +0 -0
  126. {elementpath-4.7.0 → elementpath-5.0.0}/tests/resources/analyze-string.xsd +0 -0
  127. {elementpath-4.7.0 → elementpath-5.0.0}/tests/resources/external_entity.xml +0 -0
  128. {elementpath-4.7.0 → elementpath-5.0.0}/tests/resources/sample.xml +0 -0
  129. {elementpath-4.7.0 → elementpath-5.0.0}/tests/resources/schema-for-json.xsd +0 -0
  130. {elementpath-4.7.0 → elementpath-5.0.0}/tests/resources/unparsed_entity.xml +0 -0
  131. {elementpath-4.7.0 → elementpath-5.0.0}/tests/resources/unused_external_entity.xml +0 -0
  132. {elementpath-4.7.0 → elementpath-5.0.0}/tests/resources/unused_unparsed_entity.xml +0 -0
  133. {elementpath-4.7.0 → elementpath-5.0.0}/tests/resources/with_entity.xml +0 -0
  134. /elementpath-4.7.0/tests/test_elementpath.py → /elementpath-5.0.0/tests/run_all_tests.py +0 -0
  135. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_collations.py +0 -0
  136. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_exceptions.py +0 -0
  137. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_regex.py +0 -0
  138. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_selectors.py +0 -0
  139. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_tdop_parser.py +0 -0
  140. {elementpath-4.7.0 → elementpath-5.0.0}/tests/test_xpath31.py +0 -0
@@ -2,6 +2,22 @@
2
2
  CHANGELOG
3
3
  *********
4
4
 
5
+ `v5.0.0`_ (2025-04-27)
6
+ ======================
7
+ * Replace SafeXMLParser with SafeExpatParser
8
+ * Drop compatibility with Python 3.8
9
+ * Restruct node trees with XPathNodeTree backbone
10
+ * Unicode categories fallback with a warning (issue #85)
11
+ * Rewriting decoder module (issue #87)
12
+ * Add extras subpackage for experiment XDM and XPath on Path objects
13
+
14
+ `v4.8.0`_ (2025-03-03)
15
+ ======================
16
+ * Add full PSVI type labeling in XDM to solve type errors with XSD 1.1 assertions
17
+ * Add *schema* optional argument to dynamic context
18
+ * Add a RootToken as a proxy of the parsed token tree for compatibility with xmlschema<=3.4.3
19
+ * Extend XDM to split ElementTree/lxml processing from schema nodes and to allow future extensions
20
+
5
21
  `v4.7.0`_ (2024-12-20)
6
22
  ======================
7
23
  * Fix *fragment* argument usage (issue #81)
@@ -484,3 +500,5 @@ CHANGELOG
484
500
  .. _v4.5.0: https://github.com/sissaschool/elementpath/compare/v4.4.0...v4.5.0
485
501
  .. _v4.6.0: https://github.com/sissaschool/elementpath/compare/v4.5.0...v4.6.0
486
502
  .. _v4.7.0: https://github.com/sissaschool/elementpath/compare/v4.6.0...v4.7.0
503
+ .. _v4.8.0: https://github.com/sissaschool/elementpath/compare/v4.7.0...v4.8.0
504
+ .. _v5.0.0: https://github.com/sissaschool/elementpath/compare/v4.8.0...v5.0.0
@@ -2,12 +2,9 @@ include LICENSE
2
2
  include MANIFEST.in
3
3
  include README.rst
4
4
  include CHANGELOG.rst
5
- include setup.py
6
- include setup.cfg
5
+ include pyproject.toml
7
6
  include requirements-dev.txt
8
7
  include tox.ini
9
- include .coveragerc
10
- include mypy.ini
11
8
  include doc/*
12
9
 
13
10
  recursive-include elementpath *
@@ -1,22 +1,18 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: elementpath
3
- Version: 4.7.0
3
+ Version: 5.0.0
4
4
  Summary: XPath 1.0/2.0/3.0/3.1 parsers and selectors for ElementTree and lxml
5
- Home-page: https://github.com/sissaschool/elementpath
6
- Author: Davide Brunato
7
- Author-email: brunato@sissa.it
8
- License: MIT
9
- Keywords: XPath,XPath2,XPath3,XPath31,Pratt-parser,ElementTree,lxml
5
+ Author-email: Davide Brunato <brunato@sissa.it>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/sissaschool/elementpath
10
8
  Classifier: Development Status :: 5 - Production/Stable
11
9
  Classifier: Intended Audience :: Developers
12
10
  Classifier: Intended Audience :: Information Technology
13
11
  Classifier: Intended Audience :: Science/Research
14
- Classifier: License :: OSI Approved :: MIT License
15
12
  Classifier: Operating System :: OS Independent
16
13
  Classifier: Programming Language :: Python
17
14
  Classifier: Programming Language :: Python :: 3
18
15
  Classifier: Programming Language :: Python :: 3 :: Only
19
- Classifier: Programming Language :: Python :: 3.8
20
16
  Classifier: Programming Language :: Python :: 3.9
21
17
  Classifier: Programming Language :: Python :: 3.10
22
18
  Classifier: Programming Language :: Python :: 3.11
@@ -27,19 +23,24 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
27
23
  Classifier: Programming Language :: Python :: Implementation :: PyPy
28
24
  Classifier: Topic :: Software Development :: Libraries
29
25
  Classifier: Topic :: Text Processing :: Markup :: XML
30
- Requires-Python: >=3.8
26
+ Requires-Python: >=3.9
27
+ Description-Content-Type: text/x-rst
31
28
  License-File: LICENSE
32
29
  Provides-Extra: dev
33
- Requires-Dist: tox; extra == "dev"
34
30
  Requires-Dist: coverage; extra == "dev"
31
+ Requires-Dist: flake8; extra == "dev"
35
32
  Requires-Dist: lxml; extra == "dev"
36
- Requires-Dist: xmlschema>=3.3.2; extra == "dev"
37
- Requires-Dist: Sphinx; extra == "dev"
38
- Requires-Dist: memory-profiler; extra == "dev"
33
+ Requires-Dist: lxml-stubs; extra == "dev"
39
34
  Requires-Dist: memray; extra == "dev"
40
- Requires-Dist: flake8; extra == "dev"
41
35
  Requires-Dist: mypy; extra == "dev"
42
- Requires-Dist: lxml-stubs; extra == "dev"
36
+ Requires-Dist: psutil; extra == "dev"
37
+ Requires-Dist: sphinx; extra == "dev"
38
+ Requires-Dist: tox; extra == "dev"
39
+ Requires-Dist: xmlschema>=4.0.1; extra == "dev"
40
+ Provides-Extra: docs
41
+ Requires-Dist: sphinx; extra == "docs"
42
+ Requires-Dist: readthedocs-sphinx-search; extra == "docs"
43
+ Dynamic: license-file
43
44
 
44
45
  ***********
45
46
  elementpath
@@ -71,7 +72,7 @@ has it's own implementation of XPath 1.0.
71
72
  Installation and usage
72
73
  ======================
73
74
 
74
- You can install the package with *pip* in a Python 3.8+ environment::
75
+ You can install the package with *pip* in a Python 3.9+ environment::
75
76
 
76
77
  pip install elementpath
77
78
 
@@ -28,7 +28,7 @@ has it's own implementation of XPath 1.0.
28
28
  Installation and usage
29
29
  ======================
30
30
 
31
- You can install the package with *pip* in a Python 3.8+ environment::
31
+ You can install the package with *pip* in a Python 3.9+ environment::
32
32
 
33
33
  pip install elementpath
34
34
 
@@ -22,6 +22,11 @@ having as result a tree of tokens:
22
22
  >>> token = parser.parse('/root/(: comment :) child[@attr]')
23
23
  >>> isinstance(token, XPathToken)
24
24
  True
25
+
26
+ That token is a proxy token for the tree produced by TDOP parsing:
27
+
28
+ .. doctest::
29
+
25
30
  >>> token
26
31
  <_SolidusOperator object at 0x...
27
32
  >>> str(token)
@@ -73,7 +78,7 @@ represented by *XPathContext* objects.
73
78
  >>> root = ElementTree.XML('<root><child/><child attr="10"/></root>')
74
79
  >>> context = XPathContext(root)
75
80
  >>> token.evaluate(context)
76
- [ElementNode(elem=<Element 'child' at ...)]
81
+ [EtreeElementNode(elem=<Element 'child' at ...)]
77
82
 
78
83
  In this case an error is raised if you don't provide a context:
79
84
 
@@ -124,9 +129,9 @@ Node trees are automatically created at dynamic context initialization:
124
129
  >>> root = ElementTree.XML('<root><child/><child attr="10"/></root>')
125
130
  >>> context = XPathContext(root)
126
131
  >>> context.root
127
- ElementNode(elem=<Element 'root' at ...>)
132
+ EtreeElementNode(elem=<Element 'root' at ...>)
128
133
  >>> context.root.children
129
- [ElementNode(elem=<Element 'child' at ...>), ElementNode(elem=<Element 'child' at ...>)]
134
+ [EtreeElementNode(elem=<Element 'child' at ...>), EtreeElementNode(elem=<Element 'child' at ...>)]
130
135
 
131
136
  If the same XML data is applied several times for dynamic evaluation it maybe
132
137
  convenient to build the node tree before, in the way to create it only once:
@@ -232,7 +237,7 @@ context item is set to context root:
232
237
 
233
238
  >>> context = XPathContext(doc)
234
239
  >>> context.root
235
- DocumentNode(document=<xml.etree.ElementTree.ElementTree object at ...>)
240
+ EtreeDocumentNode(document=<xml.etree.ElementTree.ElementTree object at ...>)
236
241
  >>> context.item is context.root
237
242
  True
238
243
  >>> context.document is context.root
@@ -246,11 +251,11 @@ set to root element node. In this case the context document is a dummy document:
246
251
  >>> root = ElementTree.XML('<root><child1/><child2/><child3/></root>')
247
252
  >>> context = XPathContext(root)
248
253
  >>> context.root
249
- ElementNode(elem=<Element 'root' at ...>)
254
+ EtreeElementNode(elem=<Element 'root' at ...>)
250
255
  >>> context.item is context.root
251
256
  True
252
257
  >>> context.document
253
- DocumentNode(document=<xml.etree.ElementTree.ElementTree object at ...>)
258
+ EtreeDocumentNode(document=<xml.etree.ElementTree.ElementTree object at ...>)
254
259
  >>> context.root.parent is None
255
260
  True
256
261
 
@@ -263,7 +268,7 @@ the data with lxml:
263
268
  >>> root = etree.XML('<!-- comment --><root><child/></root>')
264
269
  >>> context = XPathContext(root)
265
270
  >>> context.root
266
- DocumentNode(document=<lxml.etree._ElementTree object at ...>)
271
+ EtreeDocumentNode(document=<lxml.etree._ElementTree object at ...>)
267
272
  >>> context.item is context.root
268
273
  True
269
274
  >>> context.document is context.root
@@ -278,7 +283,7 @@ is set to `None`:
278
283
  >>> root = ElementTree.XML('<root><child1/><child2/><child3/></root>')
279
284
  >>> context = XPathContext(root, fragment=True)
280
285
  >>> context.root
281
- ElementNode(elem=<Element 'root' at ...>)
286
+ EtreeElementNode(elem=<Element 'root' at ...>)
282
287
  >>> context.item is context.root
283
288
  True
284
289
  >>> context.document is None
@@ -25,13 +25,13 @@ sys.path.insert(0, os.path.abspath('..'))
25
25
  # -- Project information -----------------------------------------------------
26
26
 
27
27
  project = 'elementpath'
28
- copyright = '2018-2024, SISSA (International School for Advanced Studies)'
28
+ copyright = '2018-2025, SISSA (International School for Advanced Studies)'
29
29
  author = 'Davide Brunato'
30
30
 
31
31
  # The short X.Y version
32
- version = '4.7'
32
+ version = '5.0'
33
33
  # The full version, including alpha/beta/rc tags
34
- release = '4.7.0'
34
+ release = '5.0.0'
35
35
 
36
36
  # -- General configuration ---------------------------------------------------
37
37
 
@@ -7,10 +7,10 @@
7
7
  #
8
8
  # @author Davide Brunato <brunato@sissa.it>
9
9
  #
10
- __version__ = '4.7.0'
10
+ __version__ = '5.0.0'
11
11
  __author__ = "Davide Brunato"
12
12
  __contact__ = "brunato@sissa.it"
13
- __copyright__ = "Copyright 2018-2024, SISSA"
13
+ __copyright__ = "Copyright 2018-2025, SISSA"
14
14
  __license__ = "MIT"
15
15
  __status__ = "Production/Stable"
16
16
 
@@ -26,9 +26,9 @@ from .exceptions import ElementPathError, MissingContextError, ElementPathKeyErr
26
26
  ElementPathValueError, ElementPathLocaleError, UnsupportedFeatureError
27
27
 
28
28
  from .xpath_context import XPathContext, XPathSchemaContext
29
- from .xpath_nodes import XPathNode, DocumentNode, ElementNode, AttributeNode, \
30
- NamespaceNode, CommentNode, ProcessingInstructionNode, TextNode, \
31
- LazyElementNode, SchemaElementNode
29
+ from .xpath_nodes import XPathNode, AttributeNode, NamespaceNode, CommentNode, \
30
+ ProcessingInstructionNode, TextNode, ElementNode, LazyElementNode, \
31
+ SchemaElementNode, DocumentNode
32
32
  from .tree_builders import get_node_tree, build_node_tree, build_lxml_node_tree, \
33
33
  build_schema_node_tree
34
34
  from .xpath_tokens import XPathToken, XPathFunction
@@ -39,15 +39,14 @@ from .schema_proxy import AbstractSchemaProxy
39
39
  from .regex import RegexError, translate_pattern, install_unicode_data, unicode_version
40
40
 
41
41
  __all__ = ['datatypes', 'protocols', 'etree', 'ElementPathError', 'MissingContextError',
42
- 'UnsupportedFeatureError', 'ElementPathKeyError',
42
+ 'UnsupportedFeatureError', 'ElementPathKeyError', 'ElementPathLocaleError',
43
43
  'ElementPathZeroDivisionError', 'ElementPathNameError',
44
44
  'ElementPathOverflowError', 'ElementPathRuntimeError', 'ElementPathSyntaxError',
45
- 'ElementPathTypeError', 'ElementPathValueError', 'ElementPathLocaleError',
46
- 'XPathContext', 'XPathSchemaContext', 'XPathNode', 'DocumentNode',
47
- 'ElementNode', 'AttributeNode', 'NamespaceNode', 'CommentNode',
48
- 'ProcessingInstructionNode', 'TextNode', 'LazyElementNode',
49
- 'SchemaElementNode', 'get_node_tree', 'build_node_tree',
50
- 'build_lxml_node_tree', 'build_schema_node_tree', 'XPathToken',
45
+ 'ElementPathTypeError', 'ElementPathValueError', 'XPathContext',
46
+ 'XPathSchemaContext', 'XPathNode', 'AttributeNode', 'NamespaceNode',
47
+ 'CommentNode', 'ProcessingInstructionNode', 'TextNode', 'ElementNode',
48
+ 'LazyElementNode', 'SchemaElementNode', 'DocumentNode', 'get_node_tree',
49
+ 'build_node_tree', 'build_lxml_node_tree', 'build_schema_node_tree', 'XPathToken',
51
50
  'XPathFunction', 'XPath1Parser', 'XPath2Parser', 'select', 'iter_select',
52
51
  'Selector', 'AbstractSchemaProxy', 'RegexError', 'translate_pattern',
53
52
  'install_unicode_data', 'unicode_version']
@@ -10,28 +10,27 @@
10
10
  """
11
11
  Common type hints aliases for elementpath.
12
12
  """
13
- from typing import Any, List, Optional, NoReturn, Tuple, Type, TYPE_CHECKING, TypeVar, Union
13
+ from typing import Any, Optional, NoReturn, TYPE_CHECKING, TypeVar, Union
14
14
 
15
- from elementpath._typing import MutableMapping
15
+ from collections.abc import MutableMapping
16
16
 
17
17
  ##
18
- # Type aliases
18
+ # type aliases
19
19
  NamespacesType = MutableMapping[str, str]
20
20
  NsmapType = MutableMapping[Optional[str], str] # compatible with the nsmap of lxml Element
21
21
  AnyNsmapType = Union[NamespacesType, NsmapType, None] # for composition and function arguments
22
22
 
23
- NargsType = Optional[Union[int, Tuple[int, Optional[int]]]]
24
- ClassCheckType = Union[Type[Any], Tuple[Type[Any], ...]]
23
+ NargsType = Optional[Union[int, tuple[int, Optional[int]]]]
24
+ ClassCheckType = Union[type[Any], tuple[type[Any], ...]]
25
25
 
26
26
  T = TypeVar('T')
27
- Emptiable = Union[T, List[NoReturn]]
28
- SequenceType = Union[T, List[T]]
29
- InputType = Union[None, T, List[T], Tuple[T, ...]]
27
+ Emptiable = Union[T, list[NoReturn]]
28
+ SequenceType = Union[T, list[T]]
29
+ InputType = Union[None, T, list[T], tuple[T, ...]]
30
30
 
31
31
  if TYPE_CHECKING:
32
32
  from elementpath.datatypes import AtomicType, ArithmeticType, NumericType
33
- from elementpath.xpath_nodes import ChildNodeType, ParentNodeType
34
- from elementpath.tree_builders import RootArgType
33
+ from elementpath.xpath_nodes import ChildNodeType, ParentNodeType, RootArgType
35
34
  from elementpath.xpath_context import ContextType, FunctionArgType, ItemType, \
36
35
  ItemArgType, ValueType
37
36
  from elementpath.xpath_tokens import XPathParserType, XPathTokenType
@@ -11,7 +11,7 @@ import locale
11
11
  import threading
12
12
  from contextlib import AbstractContextManager
13
13
  from types import TracebackType
14
- from typing import TYPE_CHECKING, Any, Optional, Tuple, Type, Union
14
+ from typing import TYPE_CHECKING, Any, Optional, Union
15
15
  from urllib.parse import urljoin, urlsplit
16
16
 
17
17
  from elementpath.exceptions import xpath_error
@@ -76,9 +76,9 @@ class CollationManager(context_class_base):
76
76
  """
77
77
  Context Manager for collations. Provide helper operators as methods.
78
78
  """
79
- lc_collate: Union[None, str, Tuple[Optional[str], Optional[str]]]
79
+ lc_collate: Union[None, str, tuple[Optional[str], Optional[str]]]
80
80
  fallback: bool = False
81
- _current_lc_collate: Optional[Tuple[Optional[str], Optional[str]]] = None
81
+ _current_lc_collate: Optional[tuple[Optional[str], Optional[str]]] = None
82
82
 
83
83
  def __init__(self,
84
84
  collation: Optional[str],
@@ -149,7 +149,7 @@ class CollationManager(context_class_base):
149
149
 
150
150
  return self
151
151
 
152
- def __exit__(self, exc_type: Optional[Type[BaseException]],
152
+ def __exit__(self, exc_type: Optional[type[BaseException]],
153
153
  exc_val: Optional[BaseException],
154
154
  exc_tb: Optional[TracebackType]) -> None:
155
155
  if self._current_lc_collate is not None:
@@ -13,13 +13,13 @@ from functools import cmp_to_key
13
13
  from itertools import zip_longest
14
14
  from typing import Any, Optional
15
15
 
16
- from elementpath._typing import Callable, Iterable, Iterator
16
+ from collections.abc import Callable, Iterable, Iterator
17
17
  from elementpath.protocols import ElementProtocol
18
18
  from elementpath.exceptions import xpath_error
19
19
  from elementpath.datatypes import UntypedAtomic, AnyURI, AbstractQName
20
20
  from elementpath.collations import UNICODE_CODEPOINT_COLLATION, CollationManager
21
- from elementpath.xpath_nodes import XPathNode, ElementNode, AttributeNode, \
22
- NamespaceNode, TextNode, CommentNode, ProcessingInstructionNode, DocumentNode
21
+ from elementpath.xpath_nodes import XPathNode, EtreeElementNode, TextAttributeNode, \
22
+ NamespaceNode, TextNode, CommentNode, ProcessingInstructionNode, EtreeDocumentNode
23
23
  from elementpath.xpath_tokens import XPathToken, XPathFunction, XPathMap, XPathArray
24
24
 
25
25
 
@@ -28,7 +28,7 @@ def deep_equal(seq1: Iterable[Any],
28
28
  collation: Optional[str] = None,
29
29
  token: Optional[XPathToken] = None) -> bool:
30
30
 
31
- etree_node_types = (ElementNode, CommentNode, ProcessingInstructionNode)
31
+ etree_node_types = (EtreeElementNode, CommentNode, ProcessingInstructionNode)
32
32
 
33
33
  def etree_deep_equal(e1: ElementProtocol, e2: ElementProtocol) -> bool:
34
34
  if cm.ne(e1.tag, e2.tag):
@@ -72,31 +72,31 @@ def deep_equal(seq1: Iterable[Any],
72
72
  return False
73
73
  elif isinstance(value1, XPathNode):
74
74
  assert isinstance(value2, XPathNode)
75
- if value1.kind != value2.kind:
75
+ if value1.__class__ != value2.__class__:
76
76
  return False
77
77
  elif isinstance(value1, etree_node_types):
78
78
  assert isinstance(value2, etree_node_types)
79
- if not etree_deep_equal(value1.elem, value2.elem):
79
+ if not etree_deep_equal(value1.obj, value2.obj):
80
80
  return False
81
- elif isinstance(value1, DocumentNode):
82
- assert isinstance(value2, DocumentNode)
81
+ elif isinstance(value1, EtreeDocumentNode):
82
+ assert isinstance(value2, EtreeDocumentNode)
83
83
  for child1, child2 in zip_longest(value1, value2):
84
84
  if child1 is None or child2 is None:
85
85
  return False
86
- elif child1.kind != child2.kind:
86
+ elif child1.__class__ != child2.__class__:
87
87
  return False
88
88
  elif isinstance(child1, etree_node_types):
89
89
  assert isinstance(child2, etree_node_types)
90
- if not etree_deep_equal(child1.elem, child2.elem):
90
+ if not etree_deep_equal(child1.obj, child2.obj):
91
91
  return False
92
92
  elif isinstance(child1, TextNode):
93
93
  assert isinstance(child2, TextNode)
94
- if cm.ne(child1.value, child2.value):
94
+ if cm.ne(child1.obj, child2.obj):
95
95
  return False
96
96
 
97
- elif cm.ne(value1.value, value2.value):
97
+ elif cm.ne(value1.obj, value2.obj):
98
98
  return False
99
- elif isinstance(value1, AttributeNode):
99
+ elif isinstance(value1, TextAttributeNode):
100
100
  if cm.ne(value1.name, value2.name):
101
101
  return False
102
102
  elif isinstance(value1, NamespaceNode):
@@ -174,7 +174,7 @@ def deep_compare(obj1: Any,
174
174
  token: Optional[XPathToken] = None) -> int:
175
175
 
176
176
  msg_tmpl = "Sorting failed, cannot compare {!r} with {!r}"
177
- etree_node_types = (ElementNode, CommentNode, ProcessingInstructionNode)
177
+ etree_node_types = (EtreeElementNode, CommentNode, ProcessingInstructionNode)
178
178
  result: int = 0
179
179
 
180
180
  def iter_object(obj: Any) -> Iterator[Any]:
@@ -244,51 +244,51 @@ def deep_compare(obj1: Any,
244
244
  raise xpath_error('XPTY0004', msg, token=token)
245
245
  elif isinstance(value1, XPathNode):
246
246
  assert isinstance(value2, XPathNode)
247
- if value1.kind != value2.kind:
247
+ if value1.__class__ != value2.__class__:
248
248
  msg = f"cannot compare {type(value1)} with {type(value2)}"
249
249
  raise xpath_error('XPTY0004', msg, token=token)
250
250
  elif isinstance(value1, etree_node_types):
251
251
  assert isinstance(value2, etree_node_types)
252
- result = etree_deep_compare(value1.elem, value2.elem)
252
+ result = etree_deep_compare(value1.obj, value2.obj)
253
253
  if result:
254
254
  return result
255
- elif isinstance(value1, DocumentNode):
256
- assert isinstance(value2, DocumentNode)
255
+ elif isinstance(value1, EtreeDocumentNode):
256
+ assert isinstance(value2, EtreeDocumentNode)
257
257
  for child1, child2 in zip_longest(value1, value2):
258
258
  if child1 is None:
259
259
  return -1
260
260
  elif child2 is None:
261
261
  return 1
262
- elif child1.kind != child2.kind:
262
+ elif child1.__class__ != child2.__class__:
263
263
  msg = f"cannot compare {type(child1)} with {type(child2)}"
264
264
  raise xpath_error('XPTY0004', msg, token=token)
265
265
  elif isinstance(child1, etree_node_types):
266
266
  assert isinstance(child2, etree_node_types)
267
- result = etree_deep_compare(child1.elem, child2.elem)
267
+ result = etree_deep_compare(child1.obj, child2.obj)
268
268
  if result:
269
269
  return result
270
270
  elif isinstance(child1, TextNode):
271
271
  assert isinstance(child2, TextNode)
272
272
  result = cm.strcoll(
273
- child1.value.strip(), child2.value.strip()
273
+ child1.obj.strip(), child2.obj.strip()
274
274
  )
275
275
  if result:
276
276
  return result
277
- else:
278
- result = cm.strcoll(value1.value, value2.value)
277
+ elif isinstance(value1, TextNode):
278
+ assert isinstance(value2, TextNode)
279
+ result = cm.strcoll(value1.obj, value2.obj)
280
+ if result:
281
+ return result
282
+ elif isinstance(value1, TextAttributeNode):
283
+ assert isinstance(value2, TextAttributeNode)
284
+ result = cm.strcoll(value1.name or '', value2.name or '')
285
+ if result:
286
+ return result
287
+ elif isinstance(value1, NamespaceNode):
288
+ assert isinstance(value2, NamespaceNode)
289
+ result = cm.strcoll(value1.prefix or '', value2.prefix or '')
279
290
  if result:
280
291
  return result
281
-
282
- if isinstance(value1, AttributeNode):
283
- assert isinstance(value2, AttributeNode)
284
- result = cm.strcoll(value1.name or '', value2.name or '')
285
- if result:
286
- return result
287
- elif isinstance(value1, NamespaceNode):
288
- assert isinstance(value2, NamespaceNode)
289
- result = cm.strcoll(value1.prefix or '', value2.prefix or '')
290
- if result:
291
- return result
292
292
  else:
293
293
  try:
294
294
  if isinstance(value1, bool):
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2020, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
3
3
  # All rights reserved.
4
4
  # This file is distributed under the terms of the MIT License.
5
5
  # See the file 'LICENSE' in the root directory of the present
@@ -15,8 +15,7 @@ exceptions in order to be reusable in other packages.
15
15
  from decimal import Decimal
16
16
  from typing import Union
17
17
 
18
- from .atomic_types import xsd10_atomic_types, xsd11_atomic_types, \
19
- AtomicTypeMeta, AnyAtomicType
18
+ from .atomic_types import xsd_atomic_types, AtomicTypeMeta, AnyAtomicType
20
19
  from .untyped import UntypedAtomic
21
20
  from .qname import AbstractQName, QName, Notation
22
21
  from .numeric import Float10, Float, Integer, Int, NegativeInteger, \
@@ -33,22 +32,15 @@ from .datetime import AbstractDateTime, DateTime10, DateTime, DateTimeStamp, \
33
32
  from .proxies import BooleanProxy, DecimalProxy, DoubleProxy10, DoubleProxy, \
34
33
  StringProxy, NumericProxy, ArithmeticProxy
35
34
 
36
-
37
- xsd11_atomic_types.update(
38
- (k, v) for k, v in xsd10_atomic_types.items() if k not in xsd11_atomic_types
39
- )
40
-
41
35
  ###
42
36
  # Aliases for type annotations
43
37
  AtomicType = Union[str, int, float, Decimal, bool, AnyAtomicType]
44
38
  NumericType = Union[int, float, Decimal]
45
39
  ArithmeticType = Union[NumericType, AbstractDateTime, Duration, UntypedAtomic]
46
- DatetimeValueType = AbstractDateTime # keep until v5.0 for backward compatibility
47
40
 
48
- __all__ = ['xsd10_atomic_types', 'xsd11_atomic_types',
49
- 'AtomicTypeMeta', 'AnyAtomicType', 'NumericProxy', 'ArithmeticProxy',
50
- 'AbstractDateTime', 'DateTime10', 'DateTime', 'DateTimeStamp', 'Date10',
51
- 'Date', 'Time', 'GregorianDay', 'GregorianMonth', 'GregorianMonthDay',
41
+ __all__ = ['xsd_atomic_types', 'AtomicTypeMeta', 'AnyAtomicType', 'NumericProxy',
42
+ 'ArithmeticProxy', 'AbstractDateTime', 'DateTime10', 'DateTime', 'DateTimeStamp',
43
+ 'Date10', 'Date', 'Time', 'GregorianDay', 'GregorianMonth', 'GregorianMonthDay',
52
44
  'GregorianYear10', 'GregorianYear', 'GregorianYearMonth10', 'GregorianYearMonth',
53
45
  'Timezone', 'Duration', 'YearMonthDuration', 'DayTimeDuration', 'StringProxy',
54
46
  'NormalizedString', 'XsdToken', 'Language', 'Name', 'NCName', 'Id', 'Idref',
@@ -57,5 +49,4 @@ __all__ = ['xsd10_atomic_types', 'xsd11_atomic_types',
57
49
  'Byte', 'NonNegativeInteger', 'PositiveInteger', 'UnsignedLong', 'UnsignedInt',
58
50
  'UnsignedShort', 'UnsignedByte', 'AnyURI', 'Notation', 'QName', 'BooleanProxy',
59
51
  'DecimalProxy', 'DoubleProxy10', 'DoubleProxy', 'UntypedAtomic', 'AbstractBinary',
60
- 'AtomicType', 'DatetimeValueType', 'OrderedDateTime', 'AbstractQName',
61
- 'NumericType', 'ArithmeticType']
52
+ 'AtomicType', 'OrderedDateTime', 'AbstractQName', 'NumericType', 'ArithmeticType']
@@ -8,11 +8,10 @@
8
8
  # @author Davide Brunato <brunato@sissa.it>
9
9
  #
10
10
  from abc import ABCMeta, abstractmethod
11
- from typing import Any, Dict, Optional, Tuple, Type
11
+ from types import MappingProxyType
12
+ from typing import Any, Optional
12
13
  import re
13
14
 
14
- from elementpath._typing import Pattern
15
-
16
15
  XSD_NAMESPACE = "http://www.w3.org/2001/XMLSchema"
17
16
 
18
17
  ###
@@ -21,11 +20,16 @@ XSD_NAMESPACE = "http://www.w3.org/2001/XMLSchema"
21
20
  # into a dictionary. Some classes of XSD primitive types are defined
22
21
  # as proxies of basic Python datatypes.
23
22
 
24
- xsd10_atomic_types: Dict[Optional[str], 'AtomicTypeMeta'] = {}
25
- """Dictionary of builtin XSD 1.0 atomic types."""
23
+ _xsd_atomic_types: dict[str, dict[Optional[str], 'AtomicTypeMeta']] = {
24
+ '1.0': {},
25
+ '1.1': {}
26
+ }
27
+ """Registry of builtin XSD 1.0/1.1 atomic types."""
26
28
 
27
- xsd11_atomic_types: Dict[Optional[str], 'AtomicTypeMeta'] = {}
28
- """Dictionary of builtin XSD 1.1 atomic types."""
29
+ xsd_atomic_types = MappingProxyType({
30
+ '1.0': MappingProxyType(_xsd_atomic_types['1.0']),
31
+ '1.1': MappingProxyType(_xsd_atomic_types['1.1']),
32
+ })
29
33
 
30
34
 
31
35
  class AtomicTypeMeta(ABCMeta):
@@ -36,10 +40,8 @@ class AtomicTypeMeta(ABCMeta):
36
40
  of XSD atomic types and also the expanded name is added.
37
41
  """
38
42
  xsd_version: str
39
- pattern: Pattern[str]
40
- name: Optional[str] = None
41
43
 
42
- def __new__(mcs, class_name: str, bases: Tuple[Type[Any], ...], dict_: Dict[str, Any]) \
44
+ def __new__(mcs, class_name: str, bases: tuple[type[Any], ...], dict_: dict[str, Any]) \
43
45
  -> 'AtomicTypeMeta':
44
46
  try:
45
47
  name = dict_['name']
@@ -49,28 +51,26 @@ class AtomicTypeMeta(ABCMeta):
49
51
  if name is not None and not isinstance(name, str):
50
52
  raise TypeError("attribute 'name' must be a string or None")
51
53
 
52
- dict_['is_valid'] = classmethod(mcs.is_valid)
53
- dict_['invalid_type'] = classmethod(mcs.invalid_type)
54
- dict_['invalid_value'] = classmethod(mcs.invalid_value)
55
54
  cls = super(AtomicTypeMeta, mcs).__new__(mcs, class_name, bases, dict_)
56
55
 
57
- # Add missing attributes and methods
58
- if not hasattr(cls, 'xsd_version'):
59
- cls.xsd_version = '1.0'
60
- if not hasattr(cls, 'pattern'):
61
- cls.pattern = re.compile(r'^$')
62
-
63
- # Register class with a name
56
+ # Register ony derived classes with a name
64
57
  if name:
65
- expanded_name = '{%s}%s' % (XSD_NAMESPACE, name)
66
- if cls.xsd_version == '1.0':
67
- xsd10_atomic_types[name] = xsd10_atomic_types[expanded_name] = cls
68
- else:
69
- xsd11_atomic_types[name] = xsd11_atomic_types[expanded_name] = cls
58
+ for xsd_version, atomic_types in _xsd_atomic_types.items():
59
+ if cls.xsd_version <= xsd_version and (
60
+ name not in atomic_types or atomic_types[name].xsd_version < cls.xsd_version
61
+ ):
62
+ atomic_types[name] = cls
70
63
 
71
64
  return cls
72
65
 
73
- def validate(cls: Type[Any], value: object) -> None:
66
+
67
+ class AnyAtomicType(metaclass=AtomicTypeMeta):
68
+ name: Optional[str] = 'anyAtomicType'
69
+ xsd_version: str = '1.0'
70
+ pattern: re.Pattern[str] = re.compile(r'^$')
71
+
72
+ @classmethod
73
+ def validate(cls, value: object) -> None:
74
74
  if isinstance(value, cls):
75
75
  return
76
76
  elif isinstance(value, str):
@@ -79,7 +79,8 @@ class AtomicTypeMeta(ABCMeta):
79
79
  else:
80
80
  raise cls.invalid_type(value)
81
81
 
82
- def is_valid(cls: Type[Any], value: object) -> bool:
82
+ @classmethod
83
+ def is_valid(cls, value: object) -> bool:
83
84
  try:
84
85
  cls.validate(value)
85
86
  except (TypeError, ValueError):
@@ -87,20 +88,18 @@ class AtomicTypeMeta(ABCMeta):
87
88
  else:
88
89
  return True
89
90
 
90
- def invalid_type(cls: Type[Any], value: object) -> TypeError:
91
+ @classmethod
92
+ def invalid_type(cls, value: object) -> TypeError:
91
93
  if cls.name:
92
94
  return TypeError('invalid type {!r} for xs:{}'.format(type(value), cls.name))
93
95
  return TypeError('invalid type {!r} for {!r}'.format(type(value), cls))
94
96
 
95
- def invalid_value(cls: Type[Any], value: object) -> ValueError:
97
+ @classmethod
98
+ def invalid_value(cls, value: object) -> ValueError:
96
99
  if cls.name:
97
100
  return ValueError('invalid value {!r} for xs:{}'.format(value, cls.name))
98
101
  return ValueError('invalid value {!r} for {!r}'.format(value, cls))
99
102
 
100
-
101
- class AnyAtomicType(metaclass=AtomicTypeMeta):
102
- name = 'anyAtomicType'
103
-
104
103
  @abstractmethod
105
104
  def __init__(self, value: Any) -> None:
106
105
  raise NotImplementedError()