elementpath 5.1.0__tar.gz → 5.1.2__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 (143) hide show
  1. {elementpath-5.1.0 → elementpath-5.1.2}/CHANGELOG.rst +12 -0
  2. {elementpath-5.1.0 → elementpath-5.1.2}/LICENSE +1 -1
  3. {elementpath-5.1.0/elementpath.egg-info → elementpath-5.1.2}/PKG-INFO +1 -1
  4. {elementpath-5.1.0 → elementpath-5.1.2}/doc/conf.py +2 -2
  5. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/__init__.py +3 -3
  6. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/aliases.py +1 -1
  7. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/collations.py +1 -1
  8. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/compare.py +1 -1
  9. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/datatypes/__init__.py +1 -1
  10. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/datatypes/any_types.py +3 -2
  11. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/datatypes/binary.py +1 -1
  12. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/datatypes/datetime.py +1 -1
  13. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/datatypes/lists.py +1 -1
  14. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/datatypes/numeric.py +1 -1
  15. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/datatypes/proxies.py +1 -1
  16. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/datatypes/qname.py +1 -1
  17. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/datatypes/string.py +1 -1
  18. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/datatypes/untyped.py +2 -2
  19. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/datatypes/uri.py +1 -1
  20. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/decoder.py +1 -1
  21. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/etree.py +1 -1
  22. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/exceptions.py +1 -1
  23. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/extras/pathnodes.py +1 -1
  24. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/helpers.py +8 -1
  25. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/namespaces.py +1 -1
  26. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/protocols.py +1 -1
  27. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/regex/__init__.py +1 -1
  28. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/regex/categories_fallback.py +1 -1
  29. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/regex/character_classes.py +28 -4
  30. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/regex/codepoints.py +1 -1
  31. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/regex/patterns.py +1 -1
  32. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/regex/unicode_blocks.py +1 -1
  33. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/regex/unicode_categories.py +1 -1
  34. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/regex/unicode_subsets.py +1 -1
  35. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/schema_proxy.py +1 -1
  36. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/sequence_types.py +49 -2
  37. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/sequences.py +1 -1
  38. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/serialization.py +26 -9
  39. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/tdop.py +11 -6
  40. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/tree_builders.py +1 -1
  41. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/validators/__init__.py +1 -1
  42. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath1/__init__.py +1 -1
  43. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath1/_xpath1_axes.py +1 -1
  44. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath1/_xpath1_functions.py +1 -1
  45. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath1/_xpath1_operators.py +1 -1
  46. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath1/xpath1_parser.py +5 -21
  47. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath2/__init__.py +1 -1
  48. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath2/_xpath2_constructors.py +1 -1
  49. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath2/_xpath2_functions.py +1 -1
  50. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath2/_xpath2_operators.py +1 -1
  51. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath2/xpath2_parser.py +92 -152
  52. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath3.py +1 -1
  53. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath30/__init__.py +1 -1
  54. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath30/_translation_maps.py +1 -1
  55. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath30/_xpath30_functions.py +1 -1
  56. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath30/_xpath30_operators.py +1 -1
  57. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath30/xpath30_helpers.py +1 -1
  58. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath30/xpath30_parser.py +1 -1
  59. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath31/__init__.py +1 -1
  60. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath31/_xpath31_functions.py +1 -1
  61. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath31/_xpath31_operators.py +1 -1
  62. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath31/xpath31_parser.py +1 -1
  63. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath_context.py +1 -1
  64. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath_nodes.py +1 -1
  65. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath_selectors.py +1 -1
  66. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath_tokens/__init__.py +9 -5
  67. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath_tokens/arrays.py +1 -1
  68. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath_tokens/axes.py +1 -1
  69. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath_tokens/base.py +7 -3
  70. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath_tokens/contructors.py +37 -2
  71. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath_tokens/functions.py +35 -7
  72. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath_tokens/maps.py +1 -1
  73. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/xpath_tokens/tokens.py +1 -1
  74. {elementpath-5.1.0 → elementpath-5.1.2/elementpath.egg-info}/PKG-INFO +1 -1
  75. {elementpath-5.1.0 → elementpath-5.1.2}/pyproject.toml +1 -1
  76. {elementpath-5.1.0 → elementpath-5.1.2}/scripts/generate_codepoints.py +1 -1
  77. {elementpath-5.1.0 → elementpath-5.1.2}/tests/memory_profiling.py +1 -1
  78. {elementpath-5.1.0 → elementpath-5.1.2}/tests/run_all_tests.py +1 -1
  79. {elementpath-5.1.0 → elementpath-5.1.2}/tests/run_typing_tests.py +1 -1
  80. {elementpath-5.1.0 → elementpath-5.1.2}/tests/run_w3c_tests.py +1 -1
  81. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_collations.py +1 -1
  82. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_compare.py +1 -1
  83. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_datatypes.py +1 -1
  84. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_decoder.py +1 -1
  85. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_etree.py +1 -1
  86. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_exceptions.py +1 -1
  87. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_helpers.py +1 -1
  88. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_namespaces.py +1 -1
  89. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_package.py +2 -2
  90. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_pathnodes.py +1 -1
  91. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_regex.py +5 -1
  92. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_schema_context.py +1 -1
  93. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_schema_proxy.py +1 -1
  94. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_selectors.py +1 -1
  95. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_sequence_types.py +1 -1
  96. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_sequences.py +1 -1
  97. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_serialization.py +1 -1
  98. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_tdop_parser.py +19 -16
  99. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_tree_builders.py +1 -1
  100. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_validators.py +1 -1
  101. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_xpath1_parser.py +1 -1
  102. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_xpath2_constructors.py +1 -1
  103. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_xpath2_functions.py +1 -1
  104. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_xpath2_parser.py +85 -20
  105. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_xpath30.py +1 -1
  106. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_xpath31.py +1 -1
  107. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_xpath_context.py +1 -1
  108. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_xpath_nodes.py +1 -1
  109. {elementpath-5.1.0 → elementpath-5.1.2}/tests/test_xpath_tokens.py +1 -1
  110. {elementpath-5.1.0 → elementpath-5.1.2}/tests/xpath_test_class.py +1 -1
  111. {elementpath-5.1.0 → elementpath-5.1.2}/tox.ini +18 -7
  112. {elementpath-5.1.0 → elementpath-5.1.2}/MANIFEST.in +0 -0
  113. {elementpath-5.1.0 → elementpath-5.1.2}/README.rst +0 -0
  114. {elementpath-5.1.0 → elementpath-5.1.2}/doc/Makefile +0 -0
  115. {elementpath-5.1.0 → elementpath-5.1.2}/doc/advanced.rst +0 -0
  116. {elementpath-5.1.0 → elementpath-5.1.2}/doc/index.rst +0 -0
  117. {elementpath-5.1.0 → elementpath-5.1.2}/doc/introduction.rst +0 -0
  118. {elementpath-5.1.0 → elementpath-5.1.2}/doc/make.bat +0 -0
  119. {elementpath-5.1.0 → elementpath-5.1.2}/doc/pratt_api.rst +0 -0
  120. {elementpath-5.1.0 → elementpath-5.1.2}/doc/requirements.txt +0 -0
  121. {elementpath-5.1.0 → elementpath-5.1.2}/doc/xpath_api.rst +0 -0
  122. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/extras/__init__.py +0 -0
  123. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/py.typed +0 -0
  124. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/validators/analyze-string.xsd +0 -0
  125. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath/validators/schema-for-json.xsd +0 -0
  126. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath.egg-info/SOURCES.txt +0 -0
  127. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath.egg-info/dependency_links.txt +0 -0
  128. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath.egg-info/requires.txt +0 -0
  129. {elementpath-5.1.0 → elementpath-5.1.2}/elementpath.egg-info/top_level.txt +0 -0
  130. {elementpath-5.1.0 → elementpath-5.1.2}/requirements-dev.txt +0 -0
  131. {elementpath-5.1.0 → elementpath-5.1.2}/setup.cfg +0 -0
  132. {elementpath-5.1.0 → elementpath-5.1.2}/tests/__init__.py +0 -0
  133. {elementpath-5.1.0 → elementpath-5.1.2}/tests/mypy_tests/advanced.py +0 -0
  134. {elementpath-5.1.0 → elementpath-5.1.2}/tests/mypy_tests/protocols.py +0 -0
  135. {elementpath-5.1.0 → elementpath-5.1.2}/tests/mypy_tests/selectors.py +0 -0
  136. {elementpath-5.1.0 → elementpath-5.1.2}/tests/resources/analyze-string.xsd +0 -0
  137. {elementpath-5.1.0 → elementpath-5.1.2}/tests/resources/external_entity.xml +0 -0
  138. {elementpath-5.1.0 → elementpath-5.1.2}/tests/resources/sample.xml +0 -0
  139. {elementpath-5.1.0 → elementpath-5.1.2}/tests/resources/schema-for-json.xsd +0 -0
  140. {elementpath-5.1.0 → elementpath-5.1.2}/tests/resources/unparsed_entity.xml +0 -0
  141. {elementpath-5.1.0 → elementpath-5.1.2}/tests/resources/unused_external_entity.xml +0 -0
  142. {elementpath-5.1.0 → elementpath-5.1.2}/tests/resources/unused_unparsed_entity.xml +0 -0
  143. {elementpath-5.1.0 → elementpath-5.1.2}/tests/resources/with_entity.xml +0 -0
@@ -2,6 +2,16 @@
2
2
  CHANGELOG
3
3
  *********
4
4
 
5
+ `v5.1.2`_ (2026-06-13)
6
+ ======================
7
+ * Include PR #101 (invalid sequence type error code for external functions)
8
+ * Fix issues #100 and #102
9
+
10
+ `v5.1.1`_ (2026-01-20)
11
+ ======================
12
+ * Fix external function registrations (issue #099)
13
+ * Add ExternalFunction and SchemaConstructor token classes
14
+
5
15
  `v5.1.0`_ (2025-12-28)
6
16
  ======================
7
17
  * Drop Python 3.9 compatibility and add Pyton 3.15 support
@@ -531,3 +541,5 @@ CHANGELOG
531
541
  .. _v5.0.3: https://github.com/sissaschool/elementpath/compare/v5.0.2...v5.0.3
532
542
  .. _v5.0.4: https://github.com/sissaschool/elementpath/compare/v5.0.3...v5.0.4
533
543
  .. _v5.1.0: https://github.com/sissaschool/elementpath/compare/v5.0.4...v5.1.0
544
+ .. _v5.1.1: https://github.com/sissaschool/elementpath/compare/v5.1.0...v5.1.1
545
+ .. _v5.1.2: https://github.com/sissaschool/elementpath/compare/v5.1.1...v5.1.2
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c), 2018-2025, SISSA (Scuola Internazionale Superiore di Studi Avanzati)
3
+ Copyright (c), 2018-2026, SISSA (Scuola Internazionale Superiore di Studi Avanzati)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: elementpath
3
- Version: 5.1.0
3
+ Version: 5.1.2
4
4
  Summary: XPath 1.0/2.0/3.0/3.1 parsers and selectors for ElementTree and lxml
5
5
  Author-email: Davide Brunato <brunato@sissa.it>
6
6
  License-Expression: MIT
@@ -25,13 +25,13 @@ sys.path.insert(0, os.path.abspath('..'))
25
25
  # -- Project information -----------------------------------------------------
26
26
 
27
27
  project = 'elementpath'
28
- copyright = '2018-2025, SISSA (International School for Advanced Studies)'
28
+ copyright = '2018-2026, SISSA (International School for Advanced Studies)'
29
29
  author = 'Davide Brunato'
30
30
 
31
31
  # The short X.Y version
32
32
  version = '5.1'
33
33
  # The full version, including alpha/beta/rc tags
34
- release = '5.1.0'
34
+ release = '5.1.2'
35
35
 
36
36
  # -- General configuration ---------------------------------------------------
37
37
 
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -7,10 +7,10 @@
7
7
  #
8
8
  # @author Davide Brunato <brunato@sissa.it>
9
9
  #
10
- __version__ = '5.1.0'
10
+ __version__ = '5.1.2'
11
11
  __author__ = "Davide Brunato"
12
12
  __contact__ = "brunato@sissa.it"
13
- __copyright__ = "Copyright 2018-2025, SISSA"
13
+ __copyright__ = "Copyright 2018-2026, SISSA"
14
14
  __license__ = "MIT"
15
15
  __status__ = "Production/Stable"
16
16
 
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2025-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2025-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2022-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2022-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2022-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2022-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -7,6 +7,7 @@
7
7
  #
8
8
  # @author Davide Brunato <brunato@sissa.it>
9
9
  #
10
+ import sys
10
11
  from abc import ABCMeta, abstractmethod
11
12
  from types import MappingProxyType
12
13
  from typing import Any
@@ -58,7 +59,7 @@ class AtomicTypeMeta(ABCMeta):
58
59
  extended_name = f'{{{namespace}}}{name}' if namespace else name
59
60
  prefixed_name = f'{prefix}:{name}' if prefix else name
60
61
 
61
- if not cls.__doc__:
62
+ if not cls.__doc__ and sys.flags.optimize < 2:
62
63
  if ver := getattr(cls, '_xsd_version', ''):
63
64
  ver = ver + ' '
64
65
  params = getattr(cls, '__init__', None).__doc__ or ''
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -32,7 +32,7 @@ class UntypedAtomic(AnyAtomicType):
32
32
  name = 'untypedAtomic'
33
33
  value: str
34
34
 
35
- __slots__ = ('value', '_xsd_version', 'parser')
35
+ __slots__ = ('value', 'parser')
36
36
 
37
37
  @classmethod
38
38
  def make(cls, value: Any, **kwargs: Any) -> 'UntypedAtomic':
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2024-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2024-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2016-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2016-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2025-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -112,6 +112,13 @@ class LazyPattern:
112
112
  self._compiled = re.compile(self._pattern, self._flags)
113
113
  return self._compiled.search(string)
114
114
 
115
+ def split(self, string: str) -> list[str]:
116
+ try:
117
+ return self._compiled.split(string)
118
+ except AttributeError:
119
+ self._compiled = re.compile(self._pattern, self._flags)
120
+ return self._compiled.split(string)
121
+
115
122
 
116
123
  class Patterns:
117
124
  """
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2021-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2021-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2025-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2016-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2016-2026, 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
@@ -14,6 +14,7 @@ from collections.abc import Callable, Iterator, MutableSet
14
14
  from itertools import chain
15
15
  from typing import AbstractSet, Any, Optional, Union
16
16
 
17
+ from elementpath.helpers import LazyPattern
17
18
  from .codepoints import RegexError
18
19
  from .unicode_subsets import UnicodeSubset, lazy_subset, unicode_subset, unicode_category
19
20
 
@@ -87,6 +88,29 @@ CHARACTER_ESCAPES: dict[str, Union[str, Callable[[], UnicodeSubset]]] = {
87
88
  '\\W': w_shortcut,
88
89
  }
89
90
 
91
+ re_char_set = LazyPattern(r'(\\[nrt|.\-^?*+{}()\]sSdDiIcCwW]|\\[pP]{[a-zA-Z\-0-9]+})')
92
+
93
+
94
+ def get_charset_parts(charset: str) -> list[str]:
95
+ parts: list[str] = []
96
+ prev = ''
97
+ for part in re_char_set.split(charset):
98
+ if not part:
99
+ continue
100
+ elif part.endswith('-') and part != '\\-':
101
+ prev = part
102
+ elif part.startswith('-') and parts:
103
+ parts[-1] += prev + part
104
+ prev = ''
105
+ else:
106
+ parts.append(prev + part)
107
+ prev = ''
108
+ else:
109
+ if prev:
110
+ parts.append(prev)
111
+
112
+ return parts
113
+
90
114
 
91
115
  class CharacterClass(MutableSet[int]):
92
116
  """
@@ -96,7 +120,7 @@ class CharacterClass(MutableSet[int]):
96
120
  :param xsd_version: the reference XSD version for syntax variants. Defaults to '1.0'.
97
121
  TODO: implement __ior__, __iand__, __ixor__ operators for a full mutable set class.
98
122
  """
99
- _re_char_set = re.compile(r'(?<!.-)(\\[nrt|.\-^?*+{}()\]sSdDiIcCwW]|\\[pP]{[a-zA-Z\-0-9]+})')
123
+ _re_char_set = re.compile(r'(\\[nrt|.\-^?*+{}()\]sSdDiIcCwW]|\\[pP]{[a-zA-Z\-0-9]+})')
100
124
  _re_unicode_ref = re.compile(r'\\([pP]){([\w-]+)}')
101
125
 
102
126
  __slots__ = 'xsd_version', 'positive', 'negative'
@@ -172,7 +196,7 @@ class CharacterClass(MutableSet[int]):
172
196
  if isinstance(charset, int):
173
197
  charset = chr(charset)
174
198
 
175
- for part in self._re_char_set.split(charset):
199
+ for part in get_charset_parts(charset):
176
200
  if part in CHARACTER_ESCAPES:
177
201
  value = CHARACTER_ESCAPES[part]
178
202
  if isinstance(value, str):
@@ -204,7 +228,7 @@ class CharacterClass(MutableSet[int]):
204
228
  if isinstance(charset, int):
205
229
  charset = chr(charset)
206
230
 
207
- for part in self._re_char_set.split(charset):
231
+ for part in get_charset_parts(charset):
208
232
  if part in CHARACTER_ESCAPES:
209
233
  value = CHARACTER_ESCAPES[part]
210
234
  if isinstance(value, str):
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2016-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2016-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2016-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2016-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2016-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2016-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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,7 +15,7 @@ import elementpath.aliases as ta
15
15
 
16
16
  from elementpath.datatypes import builtin_atomic_types, builtin_list_types, QName, \
17
17
  NumericProxy, AnyAtomicType
18
- from elementpath.exceptions import ElementPathKeyError, xpath_error
18
+ from elementpath.exceptions import ElementPathKeyError, ElementPathValueError, xpath_error
19
19
  from elementpath.namespaces import XSD_NAMESPACE, XSD_ERROR, XSD_DATETIME_STAMP, \
20
20
  XSD_NUMERIC, XSD_UNTYPED, XSD_UNTYPED_ATOMIC, get_expanded_name
21
21
  from elementpath.helpers import collapse_white_spaces, Patterns
@@ -36,6 +36,53 @@ XSD11_ONLY_TYPES = frozenset(
36
36
  )
37
37
 
38
38
 
39
+ def get_function_signatures(qname: QName,
40
+ nargs: ta.NargsType,
41
+ sequence_types: tuple[str, ...] = ()) -> dict[tuple[QName, int], str]:
42
+ """
43
+ Returns the signatures for a function.
44
+
45
+ :param qname: A QName instance that represents the FQDN of the function.
46
+ :param nargs: The number of arguments that the function takes, could the `None`, \
47
+ a non-negative integer or a couple non-negative integers or a non-negative integer \
48
+ followed by `None`.
49
+ :param sequence_types: A sequence of sequence type specifications, must match \
50
+ the number of arguments that the function takes plus the return type.
51
+ """
52
+ function_signatures: dict[tuple[QName, int], str] = {}
53
+ if not sequence_types:
54
+ return function_signatures
55
+
56
+ if any(not is_sequence_type(st) for st in sequence_types):
57
+ msg = "Error in provided sequence types: {!r}"
58
+ raise ElementPathValueError(msg.format(sequence_types))
59
+ elif nargs is None:
60
+ if len(sequence_types) != 1:
61
+ raise ElementPathValueError("Mismatched number of sequence types provided")
62
+ function_signatures[(qname, 0)] = f'function() as {sequence_types[0]}'
63
+ elif isinstance(nargs, int):
64
+ if len(sequence_types) != nargs + 1:
65
+ raise ElementPathValueError("Mismatched number of sequence types provided")
66
+ function_signatures[(qname, nargs)] = 'function({}) as {}'.format(
67
+ ', '.join(sequence_types[:-1]), sequence_types[-1]
68
+ )
69
+ elif nargs[1] is None:
70
+ if len(sequence_types) != nargs[0] + 1:
71
+ raise ElementPathValueError("Mismatched number of sequence types provided")
72
+ function_signatures[(qname, nargs[0])] = 'function({}, ...) as {}'.format(
73
+ ', '.join(sequence_types[:-1]), sequence_types[-1]
74
+ )
75
+ else:
76
+ if len(sequence_types) != nargs[1] + 1:
77
+ raise ElementPathValueError("Mismatched number of sequence types provided")
78
+ for arity in range(nargs[0], nargs[1] + 1):
79
+ function_signatures[(qname, arity)] = 'function({}) as {}'.format(
80
+ ', '.join(sequence_types[:arity]), sequence_types[-1]
81
+ )
82
+
83
+ return function_signatures
84
+
85
+
39
86
  ###
40
87
  # Sequence type checking
41
88
  @cache
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2022-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2022-2026, 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
@@ -38,6 +38,31 @@ SER_PARAM_STANDALONE = '{%s}standalone' % XSLT_XQUERY_SERIALIZATION_NAMESPACE
38
38
  SER_PARAM_ITEM_SEPARATOR = '{%s}item-separator' % XSLT_XQUERY_SERIALIZATION_NAMESPACE
39
39
 
40
40
 
41
+ class MapEncodingDict(dict[AnyAtomicType | None, Any]):
42
+ """
43
+ A bridge dict-type for encoding XPath maps to JSON.
44
+ """
45
+ def __init__(self, items: Any) -> None:
46
+ self[None] = None
47
+ self._items = items
48
+
49
+ def __getitem__(self, key: AnyAtomicType | None, /) -> Any:
50
+ for k, v in self._items:
51
+ if key == k:
52
+ return v
53
+ raise KeyError(key)
54
+
55
+ def __iter__(self) -> Iterator[AnyAtomicType | None]:
56
+ for k, _ in self._items:
57
+ yield k
58
+
59
+ def __len__(self) -> int:
60
+ return len(self._items)
61
+
62
+ def items(self) -> Any:
63
+ return self._items
64
+
65
+
41
66
  def get_serialization_params(params: Union[None, ElementNode, XPathMap] = None,
42
67
  token: Optional[XPathToken] = None) -> dict['str', Any]:
43
68
 
@@ -337,14 +362,6 @@ def serialize_to_json(elements: Iterable[Any],
337
362
  if etree_module is None:
338
363
  etree_module = ElementTree
339
364
 
340
- class MapEncodingDict(dict): # type: ignore[type-arg]
341
- def __init__(self, items: Any) -> None:
342
- self[None] = None
343
- self._items = items
344
-
345
- def items(self) -> Any:
346
- return self._items
347
-
348
365
  class XPathEncoder(json.JSONEncoder):
349
366
 
350
367
  def default(self, obj: Any) -> Any:
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -14,9 +14,9 @@ import sys
14
14
  import re
15
15
  from abc import ABCMeta
16
16
  from collections.abc import Callable, Iterator, MutableMapping, MutableSequence
17
- from unicodedata import name as unicode_name
18
17
  from decimal import Decimal, DecimalException
19
18
  from typing import Any, cast, overload, Generic, TypeVar
19
+ from unicodedata import name as unicode_name
20
20
 
21
21
  #
22
22
  # Simple top-down parser based on Vaughan Pratt's algorithm (Top Down Operator Precedence).
@@ -49,7 +49,7 @@ class ParseError(SyntaxError):
49
49
  """An error when parsing source with TDOP parser."""
50
50
 
51
51
 
52
- def _symbol_to_classname(symbol: str) -> str:
52
+ def symbol_to_classname(symbol: str) -> str:
53
53
  """
54
54
  Converts a symbol string to an identifier (only alphanumeric and '_').
55
55
  """
@@ -693,7 +693,7 @@ class Parser(Generic[TK_co], metaclass=ParserMeta):
693
693
  token_class_name = kwargs.pop('class_name')
694
694
  else:
695
695
  token_class_name = "_%s%s" % (
696
- _symbol_to_classname(symbol),
696
+ symbol_to_classname(symbol),
697
697
  str(label).title().replace(' ', '')
698
698
  )
699
699
 
@@ -713,8 +713,13 @@ class Parser(Generic[TK_co], metaclass=ParserMeta):
713
713
  raise TypeError("A string or a %r subclass requested, not %r." % (Token, symbol))
714
714
  else:
715
715
  token_class = symbol
716
- if cls.symbol_table.get(symbol.lookup_name) is not token_class:
717
- raise ValueError("Token class %r is not registered." % token_class)
716
+ lookup_name = token_class.lookup_name
717
+
718
+ if lookup_name not in cls.symbol_table:
719
+ cls.symbol_table[lookup_name] = token_class
720
+ elif cls.symbol_table[lookup_name] is not token_class:
721
+ msg = "Token class {!r} collide on key {!r} with a different token class."
722
+ raise ValueError(msg.format(token_class, lookup_name))
718
723
 
719
724
  for key, value in kwargs.items():
720
725
  if key == 'lbp' and value > token_class.lbp:
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c), 2018-2025, SISSA (International School for Advanced Studies).
2
+ # Copyright (c), 2018-2026, 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