elementpath 4.8.0__tar.gz → 5.0.1__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.
- {elementpath-4.8.0 → elementpath-5.0.1}/CHANGELOG.rst +15 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/MANIFEST.in +1 -4
- {elementpath-4.8.0 → elementpath-5.0.1}/PKG-INFO +18 -27
- {elementpath-4.8.0 → elementpath-5.0.1}/README.rst +1 -1
- {elementpath-4.8.0 → elementpath-5.0.1}/doc/conf.py +2 -2
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/__init__.py +1 -1
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/aliases.py +8 -8
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/collations.py +4 -4
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/compare.py +1 -1
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/datatypes/__init__.py +6 -15
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/datatypes/atomic_types.py +32 -33
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/datatypes/binary.py +1 -2
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/datatypes/datetime.py +9 -9
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/datatypes/numeric.py +2 -2
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/datatypes/proxies.py +2 -2
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/datatypes/untyped.py +2 -2
- elementpath-5.0.1/elementpath/decoder.py +167 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/etree.py +46 -81
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/exceptions.py +10 -2
- elementpath-5.0.1/elementpath/extras/pathnodes.py +262 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/helpers.py +20 -12
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/namespaces.py +58 -2
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/protocols.py +42 -48
- elementpath-5.0.1/elementpath/regex/categories_fallback.py +76 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/regex/character_classes.py +3 -3
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/regex/codepoints.py +4 -5
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/regex/unicode_subsets.py +22 -13
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/schema_proxy.py +87 -50
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/sequence_types.py +3 -5
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/serialization.py +7 -7
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/tdop.py +33 -35
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/tree_builders.py +66 -97
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath1/_xpath1_axes.py +1 -1
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath1/_xpath1_functions.py +3 -3
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath1/_xpath1_operators.py +17 -17
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath1/xpath1_parser.py +26 -30
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath2/_xpath2_constructors.py +5 -8
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath2/_xpath2_functions.py +22 -51
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath2/_xpath2_operators.py +15 -16
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath2/xpath2_parser.py +18 -18
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath30/_xpath30_functions.py +25 -37
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath30/_xpath30_operators.py +5 -5
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath30/xpath30_helpers.py +6 -6
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath30/xpath30_parser.py +4 -4
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath31/_xpath31_functions.py +13 -13
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath31/_xpath31_operators.py +1 -1
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath31/xpath31_parser.py +3 -3
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath_context.py +34 -46
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath_nodes.py +185 -175
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath_selectors.py +5 -5
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath_tokens.py +28 -30
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath.egg-info/PKG-INFO +18 -27
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath.egg-info/SOURCES.txt +9 -7
- elementpath-5.0.1/elementpath.egg-info/requires.txt +16 -0
- elementpath-5.0.1/pyproject.toml +87 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/requirements-dev.txt +4 -4
- elementpath-5.0.1/tests/__init__.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/memory_profiling.py +27 -3
- elementpath-4.8.0/tests/test_typing.py → elementpath-5.0.1/tests/run_typing_tests.py +1 -1
- elementpath-4.8.0/tests/execute_w3c_tests.py → elementpath-5.0.1/tests/run_w3c_tests.py +1 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_datatypes.py +7 -7
- elementpath-5.0.1/tests/test_decoder.py +61 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_etree.py +77 -154
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_helpers.py +177 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_namespaces.py +44 -3
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_package.py +6 -6
- elementpath-5.0.1/tests/test_pathnodes.py +63 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_schema_proxy.py +241 -1
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_tree_builders.py +3 -3
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_validators.py +1 -1
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_xpath1_parser.py +2 -2
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_xpath2_constructors.py +3 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_xpath2_functions.py +13 -18
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_xpath2_parser.py +15 -10
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_xpath_context.py +1 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_xpath_nodes.py +10 -8
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_xpath_tokens.py +1 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tox.ini +44 -41
- elementpath-4.8.0/.coveragerc +0 -12
- elementpath-4.8.0/elementpath/_typing.py +0 -27
- elementpath-4.8.0/elementpath/decoder.py +0 -170
- elementpath-4.8.0/elementpath.egg-info/requires.txt +0 -12
- elementpath-4.8.0/mypy.ini +0 -2
- elementpath-4.8.0/setup.py +0 -59
- {elementpath-4.8.0 → elementpath-5.0.1}/LICENSE +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/doc/Makefile +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/doc/advanced.rst +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/doc/index.rst +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/doc/introduction.rst +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/doc/make.bat +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/doc/pratt_api.rst +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/doc/requirements.txt +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/doc/xpath_api.rst +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/datatypes/qname.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/datatypes/string.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/datatypes/uri.py +0 -0
- {elementpath-4.8.0/tests → elementpath-5.0.1/elementpath/extras}/__init__.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/py.typed +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/regex/__init__.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/regex/patterns.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/regex/unicode_blocks.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/regex/unicode_categories.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/validators/__init__.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/validators/analyze-string.xsd +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/validators/schema-for-json.xsd +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath1/__init__.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath2/__init__.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath3.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath30/__init__.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath30/_translation_maps.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath/xpath31/__init__.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath.egg-info/dependency_links.txt +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/elementpath.egg-info/top_level.txt +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/scripts/generate_codepoints.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/setup.cfg +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/mypy_tests/advanced.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/mypy_tests/protocols.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/mypy_tests/selectors.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/resources/analyze-string.xsd +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/resources/external_entity.xml +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/resources/sample.xml +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/resources/schema-for-json.xsd +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/resources/unparsed_entity.xml +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/resources/unused_external_entity.xml +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/resources/unused_unparsed_entity.xml +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/resources/with_entity.xml +0 -0
- /elementpath-4.8.0/tests/test_elementpath.py → /elementpath-5.0.1/tests/run_all_tests.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_collations.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_compare.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_exceptions.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_regex.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_schema_context.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_selectors.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_sequence_types.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_serialization.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_tdop_parser.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_xpath30.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/test_xpath31.py +0 -0
- {elementpath-4.8.0 → elementpath-5.0.1}/tests/xpath_test_class.py +0 -0
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
CHANGELOG
|
|
3
3
|
*********
|
|
4
4
|
|
|
5
|
+
`v5.0.1`_ (2025-05-11)
|
|
6
|
+
======================
|
|
7
|
+
* Fix XDM type labeling with element and xsi:type substitutions (issue #89)
|
|
8
|
+
|
|
9
|
+
`v5.0.0`_ (2025-04-27)
|
|
10
|
+
======================
|
|
11
|
+
* Replace SafeXMLParser with SafeExpatParser
|
|
12
|
+
* Drop compatibility with Python 3.8
|
|
13
|
+
* Restruct node trees with XPathNodeTree backbone
|
|
14
|
+
* Unicode categories fallback with a warning (issue #85)
|
|
15
|
+
* Rewriting decoder module (issue #87)
|
|
16
|
+
* Add extras subpackage for experiment XDM and XPath on Path objects
|
|
17
|
+
|
|
5
18
|
`v4.8.0`_ (2025-03-03)
|
|
6
19
|
======================
|
|
7
20
|
* Add full PSVI type labeling in XDM to solve type errors with XSD 1.1 assertions
|
|
@@ -492,3 +505,5 @@ CHANGELOG
|
|
|
492
505
|
.. _v4.6.0: https://github.com/sissaschool/elementpath/compare/v4.5.0...v4.6.0
|
|
493
506
|
.. _v4.7.0: https://github.com/sissaschool/elementpath/compare/v4.6.0...v4.7.0
|
|
494
507
|
.. _v4.8.0: https://github.com/sissaschool/elementpath/compare/v4.7.0...v4.8.0
|
|
508
|
+
.. _v5.0.0: https://github.com/sissaschool/elementpath/compare/v4.8.0...v5.0.0
|
|
509
|
+
.. _v5.0.1: https://github.com/sissaschool/elementpath/compare/v5.0.0...v5.0.1
|
|
@@ -2,12 +2,9 @@ include LICENSE
|
|
|
2
2
|
include MANIFEST.in
|
|
3
3
|
include README.rst
|
|
4
4
|
include CHANGELOG.rst
|
|
5
|
-
include
|
|
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
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: elementpath
|
|
3
|
-
Version:
|
|
3
|
+
Version: 5.0.1
|
|
4
4
|
Summary: XPath 1.0/2.0/3.0/3.1 parsers and selectors for ElementTree and lxml
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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,29 +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.
|
|
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:
|
|
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:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Dynamic: license
|
|
50
|
-
Dynamic: provides-extra
|
|
51
|
-
Dynamic: requires-python
|
|
52
|
-
Dynamic: summary
|
|
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
|
|
53
44
|
|
|
54
45
|
***********
|
|
55
46
|
elementpath
|
|
@@ -81,7 +72,7 @@ has it's own implementation of XPath 1.0.
|
|
|
81
72
|
Installation and usage
|
|
82
73
|
======================
|
|
83
74
|
|
|
84
|
-
You can install the package with *pip* in a Python 3.
|
|
75
|
+
You can install the package with *pip* in a Python 3.9+ environment::
|
|
85
76
|
|
|
86
77
|
pip install elementpath
|
|
87
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.
|
|
31
|
+
You can install the package with *pip* in a Python 3.9+ environment::
|
|
32
32
|
|
|
33
33
|
pip install elementpath
|
|
34
34
|
|
|
@@ -29,9 +29,9 @@ 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 = '
|
|
32
|
+
version = '5.0'
|
|
33
33
|
# The full version, including alpha/beta/rc tags
|
|
34
|
-
release = '
|
|
34
|
+
release = '5.0.1'
|
|
35
35
|
|
|
36
36
|
# -- General configuration ---------------------------------------------------
|
|
37
37
|
|
|
@@ -10,23 +10,23 @@
|
|
|
10
10
|
"""
|
|
11
11
|
Common type hints aliases for elementpath.
|
|
12
12
|
"""
|
|
13
|
-
from typing import Any,
|
|
13
|
+
from typing import Any, Optional, NoReturn, TYPE_CHECKING, TypeVar, Union
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from collections.abc import MutableMapping
|
|
16
16
|
|
|
17
17
|
##
|
|
18
|
-
#
|
|
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,
|
|
24
|
-
ClassCheckType = Union[
|
|
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,
|
|
28
|
-
SequenceType = Union[T,
|
|
29
|
-
InputType = Union[None, 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
|
|
@@ -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,
|
|
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,
|
|
79
|
+
lc_collate: Union[None, str, tuple[Optional[str], Optional[str]]]
|
|
80
80
|
fallback: bool = False
|
|
81
|
-
_current_lc_collate: Optional[
|
|
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[
|
|
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,7 +13,7 @@ from functools import cmp_to_key
|
|
|
13
13
|
from itertools import zip_longest
|
|
14
14
|
from typing import Any, Optional
|
|
15
15
|
|
|
16
|
-
from
|
|
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
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c), 2018-
|
|
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
|
|
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__ = ['
|
|
49
|
-
'
|
|
50
|
-
'
|
|
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', '
|
|
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
|
|
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
|
-
|
|
25
|
-
|
|
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
|
-
|
|
28
|
-
|
|
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:
|
|
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
|
-
#
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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()
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
#
|
|
10
10
|
import re
|
|
11
11
|
from abc import abstractmethod
|
|
12
|
-
from typing import
|
|
12
|
+
from typing import Union
|
|
13
13
|
import codecs
|
|
14
14
|
|
|
15
15
|
from elementpath.helpers import collapse_white_spaces
|
|
@@ -25,7 +25,6 @@ class AbstractBinary(AnyAtomicType):
|
|
|
25
25
|
:param ordered: a boolean that enable total ordering for the instance, `False` for default.
|
|
26
26
|
"""
|
|
27
27
|
value: bytes
|
|
28
|
-
invalid_type: Callable[[Any], TypeError]
|
|
29
28
|
|
|
30
29
|
def __init__(self, value: Union[str, bytes, UntypedAtomic, 'AbstractBinary'],
|
|
31
30
|
ordered: bool = False) -> None:
|
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
# @author Davide Brunato <brunato@sissa.it>
|
|
9
9
|
#
|
|
10
10
|
from abc import abstractmethod
|
|
11
|
+
from collections.abc import Callable
|
|
11
12
|
import re
|
|
12
13
|
import math
|
|
13
14
|
import operator
|
|
14
15
|
import datetime
|
|
15
16
|
from calendar import isleap
|
|
16
17
|
from decimal import Decimal, Context
|
|
17
|
-
from typing import cast, Any,
|
|
18
|
+
from typing import cast, Any, Optional, TypeVar, Union
|
|
18
19
|
|
|
19
|
-
from elementpath._typing import Callable
|
|
20
20
|
from elementpath.helpers import MONTH_DAYS_LEAP, MONTH_DAYS, DAYS_IN_4Y, \
|
|
21
21
|
DAYS_IN_100Y, DAYS_IN_400Y, days_from_common_era, adjust_day, \
|
|
22
22
|
normalized_seconds, months2days, round_number
|
|
@@ -63,7 +63,7 @@ class Timezone(datetime.tzinfo):
|
|
|
63
63
|
raise ValueError("{!r} has not an integral number of minutes".format(duration))
|
|
64
64
|
return cls(datetime.timedelta(seconds=int(duration.seconds)))
|
|
65
65
|
|
|
66
|
-
def __getinitargs__(self) ->
|
|
66
|
+
def __getinitargs__(self) -> tuple[datetime.timedelta]:
|
|
67
67
|
return self.offset,
|
|
68
68
|
|
|
69
69
|
def __hash__(self) -> int:
|
|
@@ -267,11 +267,11 @@ class AbstractDateTime(AnyAtomicType):
|
|
|
267
267
|
def astimezone(self, tz: Optional[datetime.tzinfo] = None) -> datetime.datetime:
|
|
268
268
|
return self._dt.astimezone(tz)
|
|
269
269
|
|
|
270
|
-
def isocalendar(self) ->
|
|
270
|
+
def isocalendar(self) -> tuple[int, int, int]:
|
|
271
271
|
return self._dt.isocalendar()
|
|
272
272
|
|
|
273
273
|
@classmethod
|
|
274
|
-
def fromstring(cls:
|
|
274
|
+
def fromstring(cls: type[_DT], datetime_string: str, tzinfo: Optional[Timezone] = None) \
|
|
275
275
|
-> _DT:
|
|
276
276
|
"""
|
|
277
277
|
Creates an XSD date/time instance from a string formatted value.
|
|
@@ -293,7 +293,7 @@ class AbstractDateTime(AnyAtomicType):
|
|
|
293
293
|
raise ValueError(msg.format(datetime_string, cls))
|
|
294
294
|
|
|
295
295
|
match_dict = match.groupdict()
|
|
296
|
-
kwargs:
|
|
296
|
+
kwargs: dict[str, int] = {
|
|
297
297
|
k: int(v) for k, v in match_dict.items() if k != 'tzinfo' and v is not None
|
|
298
298
|
}
|
|
299
299
|
|
|
@@ -322,7 +322,7 @@ class AbstractDateTime(AnyAtomicType):
|
|
|
322
322
|
return cls(tzinfo=tzinfo, **kwargs)
|
|
323
323
|
|
|
324
324
|
@classmethod
|
|
325
|
-
def fromdatetime(cls:
|
|
325
|
+
def fromdatetime(cls: type[_DT], dt: Union[datetime.datetime, datetime.date, datetime.time],
|
|
326
326
|
year: Optional[int] = None) -> _DT:
|
|
327
327
|
"""
|
|
328
328
|
Creates an XSD date/time instance from a datetime.datetime/date/time instance.
|
|
@@ -343,7 +343,7 @@ class AbstractDateTime(AnyAtomicType):
|
|
|
343
343
|
return cls(**kwargs)
|
|
344
344
|
|
|
345
345
|
# Python can't compare offset-naive and offset-aware datetimes
|
|
346
|
-
def _get_operands(self, other: object) ->
|
|
346
|
+
def _get_operands(self, other: object) -> tuple[datetime.datetime, datetime.datetime]:
|
|
347
347
|
if isinstance(other, (self.__class__, datetime.datetime)) or \
|
|
348
348
|
isinstance(self, other.__class__):
|
|
349
349
|
dt: datetime.datetime = getattr(other, '_dt', cast(datetime.datetime, other))
|
|
@@ -831,7 +831,7 @@ class Duration(AnyAtomicType):
|
|
|
831
831
|
return value
|
|
832
832
|
|
|
833
833
|
@classmethod
|
|
834
|
-
def fromstring(cls:
|
|
834
|
+
def fromstring(cls: type[_D], text: str) -> _D:
|
|
835
835
|
"""
|
|
836
836
|
Creates a Duration instance from a formatted XSD duration string.
|
|
837
837
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
#
|
|
10
10
|
import math
|
|
11
11
|
import re
|
|
12
|
-
from typing import Any, Optional, SupportsFloat, SupportsInt, Union
|
|
12
|
+
from typing import Any, Optional, SupportsFloat, SupportsInt, Union
|
|
13
13
|
|
|
14
14
|
from elementpath.helpers import NUMERIC_INF_OR_NAN, INVALID_NUMERIC, collapse_white_spaces
|
|
15
15
|
from .atomic_types import AnyAtomicType
|
|
@@ -166,7 +166,7 @@ class Integer(int, AnyAtomicType):
|
|
|
166
166
|
int.__init__(self)
|
|
167
167
|
|
|
168
168
|
@classmethod
|
|
169
|
-
def __subclasshook__(cls, subclass:
|
|
169
|
+
def __subclasshook__(cls, subclass: type[Any]) -> bool:
|
|
170
170
|
if cls is Integer:
|
|
171
171
|
return issubclass(subclass, int) and not issubclass(subclass, bool)
|
|
172
172
|
return NotImplemented # type: ignore[no-any-return,unused-ignore]
|
|
@@ -21,7 +21,7 @@ from .datetime import AbstractDateTime, Duration
|
|
|
21
21
|
FloatArgType = Union[SupportsFloat, str, bytes]
|
|
22
22
|
|
|
23
23
|
####
|
|
24
|
-
#
|
|
24
|
+
# type proxies for basic Python datatypes: a proxy class creates
|
|
25
25
|
# and validates its Python datatype and virtual registered types.
|
|
26
26
|
|
|
27
27
|
|
|
@@ -155,7 +155,7 @@ class StringProxy(AnyAtomicType):
|
|
|
155
155
|
|
|
156
156
|
|
|
157
157
|
####
|
|
158
|
-
#
|
|
158
|
+
# type proxies for multiple type-checking in XPath expressions
|
|
159
159
|
class NumericTypeMeta(type):
|
|
160
160
|
"""Metaclass for checking numeric classes and instances."""
|
|
161
161
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
#
|
|
10
10
|
import operator
|
|
11
11
|
from decimal import Decimal
|
|
12
|
-
from typing import Any, Optional,
|
|
12
|
+
from typing import Any, Optional, Union
|
|
13
13
|
|
|
14
14
|
from elementpath.helpers import BOOLEAN_VALUES, get_double
|
|
15
15
|
from .atomic_types import AnyAtomicType
|
|
@@ -52,7 +52,7 @@ class UntypedAtomic(AnyAtomicType):
|
|
|
52
52
|
def __repr__(self) -> str:
|
|
53
53
|
return '%s(%r)' % (self.__class__.__name__, self.value)
|
|
54
54
|
|
|
55
|
-
def _get_operands(self, other: Any, force_float: bool = True) ->
|
|
55
|
+
def _get_operands(self, other: Any, force_float: bool = True) -> tuple[Any, Any]:
|
|
56
56
|
"""
|
|
57
57
|
Returns a couple of operands, applying a cast to the instance value based on
|
|
58
58
|
the type of the *other* argument.
|