elementpath 5.0.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-5.0.0 → elementpath-5.0.1}/CHANGELOG.rst +5 -0
- {elementpath-5.0.0/elementpath.egg-info → elementpath-5.0.1}/PKG-INFO +1 -1
- {elementpath-5.0.0 → elementpath-5.0.1}/doc/conf.py +1 -1
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/__init__.py +1 -1
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/protocols.py +35 -41
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/regex/categories_fallback.py +0 -1
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/schema_proxy.py +84 -47
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/tree_builders.py +10 -6
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath2/_xpath2_operators.py +1 -2
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath_context.py +16 -16
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath_nodes.py +40 -44
- {elementpath-5.0.0 → elementpath-5.0.1/elementpath.egg-info}/PKG-INFO +1 -1
- {elementpath-5.0.0 → elementpath-5.0.1}/pyproject.toml +1 -1
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_schema_proxy.py +241 -1
- {elementpath-5.0.0 → elementpath-5.0.1}/LICENSE +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/MANIFEST.in +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/README.rst +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/doc/Makefile +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/doc/advanced.rst +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/doc/index.rst +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/doc/introduction.rst +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/doc/make.bat +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/doc/pratt_api.rst +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/doc/requirements.txt +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/doc/xpath_api.rst +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/aliases.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/collations.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/compare.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/datatypes/__init__.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/datatypes/atomic_types.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/datatypes/binary.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/datatypes/datetime.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/datatypes/numeric.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/datatypes/proxies.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/datatypes/qname.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/datatypes/string.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/datatypes/untyped.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/datatypes/uri.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/decoder.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/etree.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/exceptions.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/extras/__init__.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/extras/pathnodes.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/helpers.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/namespaces.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/py.typed +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/regex/__init__.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/regex/character_classes.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/regex/codepoints.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/regex/patterns.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/regex/unicode_blocks.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/regex/unicode_categories.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/regex/unicode_subsets.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/sequence_types.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/serialization.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/tdop.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/validators/__init__.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/validators/analyze-string.xsd +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/validators/schema-for-json.xsd +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath1/__init__.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath1/_xpath1_axes.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath1/_xpath1_functions.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath1/_xpath1_operators.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath1/xpath1_parser.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath2/__init__.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath2/_xpath2_constructors.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath2/_xpath2_functions.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath2/xpath2_parser.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath3.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath30/__init__.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath30/_translation_maps.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath30/_xpath30_functions.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath30/_xpath30_operators.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath30/xpath30_helpers.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath30/xpath30_parser.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath31/__init__.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath31/_xpath31_functions.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath31/_xpath31_operators.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath31/xpath31_parser.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath_selectors.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath/xpath_tokens.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath.egg-info/SOURCES.txt +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath.egg-info/dependency_links.txt +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath.egg-info/requires.txt +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/elementpath.egg-info/top_level.txt +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/requirements-dev.txt +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/scripts/generate_codepoints.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/setup.cfg +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/__init__.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/memory_profiling.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/mypy_tests/advanced.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/mypy_tests/protocols.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/mypy_tests/selectors.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/resources/analyze-string.xsd +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/resources/external_entity.xml +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/resources/sample.xml +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/resources/schema-for-json.xsd +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/resources/unparsed_entity.xml +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/resources/unused_external_entity.xml +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/resources/unused_unparsed_entity.xml +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/resources/with_entity.xml +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/run_all_tests.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/run_typing_tests.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/run_w3c_tests.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_collations.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_compare.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_datatypes.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_decoder.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_etree.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_exceptions.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_helpers.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_namespaces.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_package.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_pathnodes.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_regex.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_schema_context.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_selectors.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_sequence_types.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_serialization.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_tdop_parser.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_tree_builders.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_validators.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_xpath1_parser.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_xpath2_constructors.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_xpath2_functions.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_xpath2_parser.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_xpath30.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_xpath31.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_xpath_context.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_xpath_nodes.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/test_xpath_tokens.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tests/xpath_test_class.py +0 -0
- {elementpath-5.0.0 → elementpath-5.0.1}/tox.ini +0 -0
|
@@ -2,6 +2,10 @@
|
|
|
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
|
+
|
|
5
9
|
`v5.0.0`_ (2025-04-27)
|
|
6
10
|
======================
|
|
7
11
|
* Replace SafeXMLParser with SafeExpatParser
|
|
@@ -502,3 +506,4 @@ CHANGELOG
|
|
|
502
506
|
.. _v4.7.0: https://github.com/sissaschool/elementpath/compare/v4.6.0...v4.7.0
|
|
503
507
|
.. _v4.8.0: https://github.com/sissaschool/elementpath/compare/v4.7.0...v4.8.0
|
|
504
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
|
|
@@ -11,15 +11,12 @@
|
|
|
11
11
|
Define type hints protocols for XPath related objects.
|
|
12
12
|
"""
|
|
13
13
|
from collections.abc import Hashable, Iterator, Iterable, ItemsView, Mapping, Sequence, Sized
|
|
14
|
-
from typing import overload, Any, Optional, Protocol, Union, TypeVar
|
|
14
|
+
from typing import overload, Any, Optional, Protocol, Union, TypeVar
|
|
15
15
|
from xml.etree.ElementTree import Element, ElementTree
|
|
16
16
|
|
|
17
17
|
from collections.abc import MutableMapping
|
|
18
18
|
from elementpath.aliases import NamespacesType, NsmapType
|
|
19
19
|
|
|
20
|
-
if TYPE_CHECKING:
|
|
21
|
-
from elementpath.schema_proxy import AbstractSchemaProxy
|
|
22
|
-
|
|
23
20
|
_T = TypeVar("_T")
|
|
24
21
|
_AnyStr = Union[str, bytes]
|
|
25
22
|
|
|
@@ -146,6 +143,9 @@ class XsdComponentProtocol(XsdValidatorProtocol, Protocol):
|
|
|
146
143
|
@property
|
|
147
144
|
def parent(self) -> Optional['XsdComponentProtocol']: ...
|
|
148
145
|
|
|
146
|
+
@property
|
|
147
|
+
def ref(self) -> Optional['XsdComponentProtocol']: ...
|
|
148
|
+
|
|
149
149
|
|
|
150
150
|
class XsdTypeProtocol(XsdComponentProtocol, Protocol):
|
|
151
151
|
|
|
@@ -260,17 +260,29 @@ class XsdTypeProtocol(XsdComponentProtocol, Protocol):
|
|
|
260
260
|
"""
|
|
261
261
|
...
|
|
262
262
|
|
|
263
|
+
@property
|
|
264
|
+
def model_group(self) -> Optional['XsdGroupProtocol']:
|
|
265
|
+
"""
|
|
266
|
+
A model group if it's a complexType with mixed or element-only content, `None` otherwise.
|
|
267
|
+
"""
|
|
268
|
+
...
|
|
263
269
|
|
|
264
|
-
class XsdAttributeProtocol(XsdComponentProtocol, Protocol):
|
|
265
270
|
|
|
266
|
-
|
|
267
|
-
def type(self) -> Optional[XsdTypeProtocol]: ...
|
|
271
|
+
class XsdComplexTypeProtocol(XsdComponentProtocol, Protocol):
|
|
268
272
|
|
|
269
273
|
@property
|
|
270
|
-
def
|
|
274
|
+
def attributes(self) -> 'XsdAttributeGroupProtocol': ...
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class XsdGroupProtocol(XsdComponentProtocol, Protocol):
|
|
278
|
+
|
|
279
|
+
def iter_elements(self) -> Iterator['XsdElementProtocol']: ...
|
|
271
280
|
|
|
272
281
|
|
|
273
|
-
|
|
282
|
+
class XsdAttributeProtocol(XsdComponentProtocol, Protocol):
|
|
283
|
+
|
|
284
|
+
@property
|
|
285
|
+
def type(self) -> Optional[XsdTypeProtocol]: ...
|
|
274
286
|
|
|
275
287
|
|
|
276
288
|
class XsdAttributeGroupProtocol(XsdComponentProtocol, Protocol):
|
|
@@ -296,62 +308,40 @@ class XsdAttributeGroupProtocol(XsdComponentProtocol, Protocol):
|
|
|
296
308
|
|
|
297
309
|
def __hash__(self) -> int: ...
|
|
298
310
|
|
|
299
|
-
@property
|
|
300
|
-
def ref(self) -> Optional[Any]: ...
|
|
301
|
-
|
|
302
311
|
|
|
303
312
|
class XsdElementProtocol(XsdComponentProtocol, ElementProtocol, Protocol):
|
|
304
313
|
|
|
305
|
-
def __iter__(self) -> Iterator['XsdElementProtocol']: ...
|
|
306
|
-
|
|
307
|
-
def find(
|
|
308
|
-
self, path: str, namespaces: Optional[NamespacesType] = ...
|
|
309
|
-
) -> Optional[XsdXPathNodeType]: ...
|
|
310
|
-
def iter(self, tag: Optional[str] = ...) -> Iterator['XsdElementProtocol']: ...
|
|
311
|
-
|
|
312
314
|
@property
|
|
313
315
|
def name(self) -> Optional[str]: ...
|
|
314
316
|
|
|
315
317
|
@property
|
|
316
318
|
def type(self) -> Optional[XsdTypeProtocol]: ...
|
|
317
319
|
|
|
318
|
-
@property
|
|
319
|
-
def ref(self) -> Optional[Any]: ...
|
|
320
|
-
|
|
321
320
|
@property
|
|
322
321
|
def attrib(self) -> XsdAttributeGroupProtocol: ...
|
|
323
322
|
|
|
324
|
-
|
|
325
|
-
def xpath_proxy(self) -> 'AbstractSchemaProxy': ...
|
|
326
|
-
|
|
323
|
+
def __iter__(self) -> Iterator['XsdElementProtocol']: ...
|
|
327
324
|
|
|
328
|
-
|
|
329
|
-
|
|
325
|
+
def find(self, path: str, namespaces: Optional[NamespacesType] = ...) \
|
|
326
|
+
-> Union['XsdElementProtocol', None]: ...
|
|
330
327
|
|
|
331
328
|
|
|
332
329
|
class GlobalMapsProtocol(Protocol):
|
|
333
330
|
|
|
334
331
|
@property
|
|
335
|
-
def types(self) -> Mapping[str,
|
|
332
|
+
def types(self) -> Mapping[str, XsdTypeProtocol]: ...
|
|
336
333
|
|
|
337
334
|
@property
|
|
338
|
-
def attributes(self) -> Mapping[str,
|
|
335
|
+
def attributes(self) -> Mapping[str, XsdAttributeProtocol]: ...
|
|
339
336
|
|
|
340
337
|
@property
|
|
341
|
-
def elements(self) -> Mapping[str,
|
|
338
|
+
def elements(self) -> Mapping[str, XsdElementProtocol]: ...
|
|
342
339
|
|
|
343
340
|
@property
|
|
344
341
|
def substitution_groups(self) -> Mapping[str, set[Any]]: ...
|
|
345
342
|
|
|
346
343
|
|
|
347
|
-
class XsdSchemaProtocol(XsdValidatorProtocol,
|
|
348
|
-
|
|
349
|
-
def __iter__(self) -> Iterator[XsdXPathNodeType]: ...
|
|
350
|
-
|
|
351
|
-
def find(
|
|
352
|
-
self, path: str, namespaces: Optional[NamespacesType] = ...
|
|
353
|
-
) -> Optional[XsdXPathNodeType]: ...
|
|
354
|
-
def iter(self, tag: Optional[str] = ...) -> Iterator[XsdXPathNodeType]: ...
|
|
344
|
+
class XsdSchemaProtocol(XsdValidatorProtocol, Protocol):
|
|
355
345
|
|
|
356
346
|
@property
|
|
357
347
|
def validity(self) -> str: ...
|
|
@@ -365,10 +355,13 @@ class XsdSchemaProtocol(XsdValidatorProtocol, ElementProtocol, Protocol):
|
|
|
365
355
|
@property
|
|
366
356
|
def attrib(self) -> MutableMapping[Optional[str], 'XsdAttributeProtocol']: ...
|
|
367
357
|
|
|
368
|
-
|
|
369
|
-
|
|
358
|
+
def __iter__(self) -> Iterator['XsdXPathNodeType']: ...
|
|
359
|
+
|
|
360
|
+
def find(self, path: str, namespaces: Optional[NamespacesType] = ...) \
|
|
361
|
+
-> Union['XsdSchemaProtocol', 'XsdElementProtocol', None]: ...
|
|
370
362
|
|
|
371
363
|
|
|
364
|
+
XsdXPathNodeType = Union[XsdSchemaProtocol, XsdElementProtocol]
|
|
372
365
|
DocumentType = Union[ElementTree, DocumentProtocol]
|
|
373
366
|
ElementType = Union[Element, ElementProtocol]
|
|
374
367
|
SchemaElemType = Union[XsdSchemaProtocol, XsdElementProtocol]
|
|
@@ -386,4 +379,5 @@ __all__ = ['ElementProtocol', 'EtreeElementProtocol', 'LxmlAttribProtocol',
|
|
|
386
379
|
'XsdValidatorProtocol', 'XsdComponentProtocol', 'XsdTypeProtocol',
|
|
387
380
|
'XsdAttributeProtocol', 'XsdAttributeGroupProtocol', 'XsdElementProtocol',
|
|
388
381
|
'GlobalMapsProtocol', 'XsdSchemaProtocol', 'DocumentType', 'ElementType',
|
|
389
|
-
'SchemaElemType', 'CommentType', 'ProcessingInstructionType',
|
|
382
|
+
'SchemaElemType', 'CommentType', 'ProcessingInstructionType',
|
|
383
|
+
'AttribType', 'XsdXPathNodeType']
|
|
@@ -10,19 +10,20 @@
|
|
|
10
10
|
from abc import ABCMeta, abstractmethod
|
|
11
11
|
from collections.abc import Iterator
|
|
12
12
|
from functools import lru_cache
|
|
13
|
-
from typing import
|
|
13
|
+
from typing import cast, Any, Optional, Union
|
|
14
14
|
|
|
15
15
|
from elementpath.exceptions import ElementPathTypeError
|
|
16
16
|
from elementpath.protocols import XsdTypeProtocol, XsdAttributeProtocol, \
|
|
17
|
-
XsdElementProtocol, XsdSchemaProtocol
|
|
17
|
+
XsdElementProtocol, XsdSchemaProtocol, XsdAttributeGroupProtocol
|
|
18
|
+
from elementpath.namespaces import XSD_ANY_ATOMIC_TYPE
|
|
18
19
|
from elementpath.datatypes import AtomicType
|
|
19
20
|
from elementpath.etree import is_etree_element
|
|
20
21
|
from elementpath.xpath_context import XPathSchemaContext
|
|
21
|
-
|
|
22
|
-
if TYPE_CHECKING:
|
|
23
|
-
from elementpath.xpath_tokens import XPath2ParserType
|
|
22
|
+
from elementpath.xpath_tokens import XPath2ParserType
|
|
24
23
|
|
|
25
24
|
PathResult = Union[XsdSchemaProtocol, XsdElementProtocol, XsdAttributeProtocol]
|
|
25
|
+
FindAttrType = Optional[XsdAttributeProtocol]
|
|
26
|
+
FindElemType = Optional[XsdElementProtocol]
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
class AbstractSchemaProxy(metaclass=ABCMeta):
|
|
@@ -33,7 +34,7 @@ class AbstractSchemaProxy(metaclass=ABCMeta):
|
|
|
33
34
|
:param schema: a schema instance compatible with the XsdSchemaProtocol.
|
|
34
35
|
:param base_element: the schema element used as base item for static analysis.
|
|
35
36
|
"""
|
|
36
|
-
__slots__ = ('_schema', '_base_element', '
|
|
37
|
+
__slots__ = ('_schema', '_base_element', '_is_fully_valid')
|
|
37
38
|
|
|
38
39
|
def __init__(self, schema: XsdSchemaProtocol,
|
|
39
40
|
base_element: Optional[XsdElementProtocol] = None) -> None:
|
|
@@ -48,12 +49,6 @@ class AbstractSchemaProxy(metaclass=ABCMeta):
|
|
|
48
49
|
|
|
49
50
|
self._schema = schema
|
|
50
51
|
self._base_element: Optional[XsdElementProtocol] = base_element
|
|
51
|
-
|
|
52
|
-
if self._base_element is not None:
|
|
53
|
-
self._find = self._base_element.find
|
|
54
|
-
else:
|
|
55
|
-
self._find = self._schema.find
|
|
56
|
-
|
|
57
52
|
self._is_fully_valid = False
|
|
58
53
|
|
|
59
54
|
@property
|
|
@@ -109,24 +104,26 @@ class AbstractSchemaProxy(metaclass=ABCMeta):
|
|
|
109
104
|
def find(self, path: str, namespaces: Optional[dict[str, str]] = None) \
|
|
110
105
|
-> Optional[PathResult]:
|
|
111
106
|
"""
|
|
112
|
-
Find a schema element or attribute using an XPath expression.
|
|
107
|
+
Find a schema element or attribute using an XPath expression. Currently unused
|
|
108
|
+
in the code, it may be deprecated in the future.
|
|
113
109
|
|
|
114
110
|
:param path: an XPath expression that selects an element or an attribute node.
|
|
115
111
|
:param namespaces: an optional mapping from namespace prefix to namespace URI.
|
|
116
112
|
:return: The first matching schema component, or ``None`` if there is no match.
|
|
117
113
|
"""
|
|
118
|
-
|
|
114
|
+
if self._base_element is not None:
|
|
115
|
+
return self._base_element.find(path, namespaces=namespaces)
|
|
116
|
+
return self._schema.find(path, namespaces)
|
|
119
117
|
|
|
120
118
|
@lru_cache(maxsize=None)
|
|
121
119
|
def cached_find(self, expanded_path: str) -> Optional[PathResult]:
|
|
122
120
|
"""
|
|
123
|
-
Find a schema element or attribute using an expanded
|
|
124
|
-
|
|
125
|
-
:param expanded_path: an XPath expression with qualified names already resolved \
|
|
126
|
-
to expanded form.
|
|
127
|
-
:return: The first matching schema component, or ``None`` if there is no match.
|
|
121
|
+
Find a schema element or attribute using an expanded XPath expression.
|
|
122
|
+
Currently unused in the code, it may be deprecated in the future.
|
|
128
123
|
"""
|
|
129
|
-
|
|
124
|
+
if self._base_element is not None:
|
|
125
|
+
return self._base_element.find(expanded_path)
|
|
126
|
+
return self._schema.find(expanded_path)
|
|
130
127
|
|
|
131
128
|
@property
|
|
132
129
|
def xsd_version(self) -> str:
|
|
@@ -139,58 +136,98 @@ class AbstractSchemaProxy(metaclass=ABCMeta):
|
|
|
139
136
|
|
|
140
137
|
def get_type(self, qname: str) -> Optional[XsdTypeProtocol]:
|
|
141
138
|
"""
|
|
142
|
-
Get the XSD global type from the schema's scope.
|
|
143
|
-
return an object that supports the protocols `XsdTypeProtocol`, or `None` if
|
|
144
|
-
the global type is not found.
|
|
139
|
+
Get the XSD global type from the schema's scope.
|
|
145
140
|
|
|
146
141
|
:param qname: the fully qualified name of the type to retrieve.
|
|
147
142
|
:returns: an object that represents an XSD type or `None`.
|
|
148
143
|
"""
|
|
149
|
-
|
|
150
|
-
if isinstance(xsd_type, tuple):
|
|
151
|
-
return None
|
|
152
|
-
return xsd_type
|
|
144
|
+
return self._schema.maps.types.get(qname)
|
|
153
145
|
|
|
154
146
|
def get_attribute(self, qname: str) -> Optional[XsdAttributeProtocol]:
|
|
155
147
|
"""
|
|
156
|
-
Get the XSD global attribute from the schema's scope.
|
|
157
|
-
return an object that supports the protocol `XsdAttributeProtocol`, or `None` if
|
|
158
|
-
the global attribute is not found.
|
|
148
|
+
Get the XSD global attribute from the schema's scope.
|
|
159
149
|
|
|
160
150
|
:param qname: the fully qualified name of the attribute to retrieve.
|
|
161
|
-
:returns: an object that represents an XSD
|
|
151
|
+
:returns: an object that represents an XSD type or `None`.
|
|
162
152
|
"""
|
|
163
|
-
|
|
164
|
-
if isinstance(xsd_attribute, tuple):
|
|
165
|
-
return None
|
|
166
|
-
return xsd_attribute
|
|
153
|
+
return self._schema.maps.attributes.get(qname)
|
|
167
154
|
|
|
168
155
|
def get_element(self, qname: str) -> Optional[XsdElementProtocol]:
|
|
169
156
|
"""
|
|
170
|
-
Get the XSD global element from the schema's scope.
|
|
171
|
-
return an object that supports the protocol `XsdElementProtocol` interface, or
|
|
172
|
-
`None` if the global element is not found.
|
|
157
|
+
Get the XSD global element from the schema's scope.
|
|
173
158
|
|
|
174
159
|
:param qname: the fully qualified name of the element to retrieve.
|
|
175
|
-
:returns: an object that represents an XSD
|
|
160
|
+
:returns: an object that represents an XSD type or `None`.
|
|
176
161
|
"""
|
|
177
|
-
|
|
178
|
-
if isinstance(xsd_element, tuple):
|
|
179
|
-
return None
|
|
180
|
-
return xsd_element
|
|
162
|
+
return self._schema.maps.elements.get(qname)
|
|
181
163
|
|
|
182
164
|
def get_substitution_group(self, qname: str) -> Optional[set[XsdElementProtocol]]:
|
|
183
165
|
"""
|
|
184
|
-
Get a substitution group.
|
|
185
|
-
|
|
186
|
-
each item of the returned list must be an object that implements the
|
|
187
|
-
`AbstractXsdElement` interface.
|
|
166
|
+
Get a substitution group. Currently unused in the code, it may be deprecated
|
|
167
|
+
in the future.
|
|
188
168
|
|
|
189
169
|
:param qname: the fully qualified name of the substitution group to retrieve.
|
|
190
170
|
:returns: a list containing substitution elements or `None`.
|
|
191
171
|
"""
|
|
192
172
|
return self._schema.maps.substitution_groups.get(qname)
|
|
193
173
|
|
|
174
|
+
def get_attribute_type(self, name: str, parent_type: Optional[XsdTypeProtocol] = None) \
|
|
175
|
+
-> Optional[XsdTypeProtocol]:
|
|
176
|
+
"""
|
|
177
|
+
Get the XSD attribute type if the provided name is matching in the scope,
|
|
178
|
+
otherwise return None.
|
|
179
|
+
|
|
180
|
+
:param name: the name of the attribute to retrieve.
|
|
181
|
+
:param parent_type: an optional XSD type that represents the scope where matching \
|
|
182
|
+
the attribute name. If not provided, the scope is assumed to be the global scope.
|
|
183
|
+
"""
|
|
184
|
+
if parent_type is None:
|
|
185
|
+
try:
|
|
186
|
+
return self._schema.maps.attributes[name].type
|
|
187
|
+
except KeyError:
|
|
188
|
+
return None
|
|
189
|
+
elif hasattr(parent_type, 'attributes'):
|
|
190
|
+
attributes = cast(XsdAttributeGroupProtocol, parent_type.attributes)
|
|
191
|
+
if name in attributes:
|
|
192
|
+
return attributes[name].type
|
|
193
|
+
elif None in attributes and attributes[None].is_matching(name):
|
|
194
|
+
try:
|
|
195
|
+
return self._schema.maps.attributes[name].type
|
|
196
|
+
except KeyError:
|
|
197
|
+
return None
|
|
198
|
+
elif name.startswith('{http://www.w3.org/2001/XMLSchema-instance}'):
|
|
199
|
+
return self._schema.maps.types.get(XSD_ANY_ATOMIC_TYPE)
|
|
200
|
+
|
|
201
|
+
return None
|
|
202
|
+
|
|
203
|
+
def get_child_type(self, name: str, parent_type: Optional[XsdTypeProtocol] = None) \
|
|
204
|
+
-> Optional[XsdTypeProtocol]:
|
|
205
|
+
"""
|
|
206
|
+
Get the child XSD type if the provided name is matching in the scope,
|
|
207
|
+
otherwise return None.
|
|
208
|
+
|
|
209
|
+
:param name: the name of the child element to match.
|
|
210
|
+
:param parent_type: an optional XSD type that represents the scope where matching \
|
|
211
|
+
the child element name. If `None` or not provided the scope is the schema.
|
|
212
|
+
"""
|
|
213
|
+
if parent_type is None:
|
|
214
|
+
try:
|
|
215
|
+
return self._schema.maps.elements[name].type
|
|
216
|
+
except KeyError:
|
|
217
|
+
return None
|
|
218
|
+
elif (content := parent_type.model_group) is not None:
|
|
219
|
+
for xsd_element in content.iter_elements():
|
|
220
|
+
if xsd_element.is_matching(name):
|
|
221
|
+
if xsd_element.name == name:
|
|
222
|
+
return xsd_element.type
|
|
223
|
+
else:
|
|
224
|
+
# a wildcard or a substitute
|
|
225
|
+
try:
|
|
226
|
+
return self._schema.maps.elements[name].type
|
|
227
|
+
except KeyError:
|
|
228
|
+
return None
|
|
229
|
+
return None
|
|
230
|
+
|
|
194
231
|
@abstractmethod
|
|
195
232
|
def is_instance(self, obj: Any, type_qname: str) -> bool:
|
|
196
233
|
"""
|
|
@@ -61,7 +61,7 @@ def get_node_tree(root: RootArgType,
|
|
|
61
61
|
elif fragment is False and \
|
|
62
62
|
isinstance(root, ElementNode) and \
|
|
63
63
|
is_etree_element_instance(root.obj):
|
|
64
|
-
return root.get_document_node(
|
|
64
|
+
return root.get_document_node()
|
|
65
65
|
|
|
66
66
|
return root
|
|
67
67
|
|
|
@@ -186,7 +186,7 @@ def build_node_tree(root: ElementTreeRootType,
|
|
|
186
186
|
elif fragment is False and \
|
|
187
187
|
isinstance(root_node, ElementNode) and \
|
|
188
188
|
is_etree_element_instance(root_node.elem):
|
|
189
|
-
return root_node.get_document_node(
|
|
189
|
+
return root_node.get_document_node()
|
|
190
190
|
else:
|
|
191
191
|
return root_node
|
|
192
192
|
else:
|
|
@@ -350,8 +350,8 @@ def build_schema_node_tree(root: SchemaElemType,
|
|
|
350
350
|
:param global_elements: a list for schema global elements, used for linking \
|
|
351
351
|
the elements declared by reference.
|
|
352
352
|
"""
|
|
353
|
-
parent:
|
|
354
|
-
elem:
|
|
353
|
+
parent: SchemaElementNode
|
|
354
|
+
elem: XsdElementProtocol
|
|
355
355
|
child: SchemaElementNode
|
|
356
356
|
children: Iterator[Any]
|
|
357
357
|
|
|
@@ -381,7 +381,11 @@ def build_schema_node_tree(root: SchemaElemType,
|
|
|
381
381
|
local_nodes = {root: root_node} # Irrelevant even if it's the schema
|
|
382
382
|
ref_nodes: list[SchemaElementNode] = []
|
|
383
383
|
|
|
384
|
-
|
|
384
|
+
if is_schema(root):
|
|
385
|
+
children = iter(e for e in root.maps.elements.values() if e.maps is root.maps)
|
|
386
|
+
else:
|
|
387
|
+
children = iter(root)
|
|
388
|
+
|
|
385
389
|
iterators: list[Any] = []
|
|
386
390
|
ancestors: list[Any] = []
|
|
387
391
|
parent = root_node
|
|
@@ -412,7 +416,7 @@ def build_schema_node_tree(root: SchemaElemType,
|
|
|
412
416
|
except IndexError:
|
|
413
417
|
# connect references to proper nodes
|
|
414
418
|
for element_node in ref_nodes:
|
|
415
|
-
elem = element_node.elem
|
|
419
|
+
elem = cast(XsdElementProtocol, element_node.elem)
|
|
416
420
|
ref = cast(XsdElementProtocol, elem.ref)
|
|
417
421
|
|
|
418
422
|
other: Any
|
|
@@ -848,8 +848,7 @@ def select_schema_element_kind_test(self: XPathFunction, context: ContextType =
|
|
|
848
848
|
|
|
849
849
|
if self.parser.schema is not None:
|
|
850
850
|
for _ in context.iter_children_or_self():
|
|
851
|
-
if self.parser.schema.get_element(qname) is None
|
|
852
|
-
and self.parser.schema.get_substitution_group(qname) is None:
|
|
851
|
+
if self.parser.schema.get_element(qname) is None:
|
|
853
852
|
raise self.error('XPST0008', "element %r not found in schema" % element_name)
|
|
854
853
|
|
|
855
854
|
if isinstance(context.item, ElementNode) and context.item.name == qname:
|
|
@@ -23,7 +23,7 @@ from elementpath.datatypes import AnyAtomicType, AtomicType, Timezone, Language
|
|
|
23
23
|
from elementpath.etree import is_etree_element, is_etree_element_instance, is_etree_document
|
|
24
24
|
from elementpath.xpath_nodes import ChildNodeType, XPathNode, AttributeNode, NamespaceNode, \
|
|
25
25
|
CommentNode, ProcessingInstructionNode, ElementNode, DocumentNode, RootNodeType, \
|
|
26
|
-
RootArgType
|
|
26
|
+
RootArgType
|
|
27
27
|
from elementpath.tree_builders import get_node_tree
|
|
28
28
|
|
|
29
29
|
if TYPE_CHECKING:
|
|
@@ -144,9 +144,6 @@ class XPathContext:
|
|
|
144
144
|
else:
|
|
145
145
|
self.item = self.root
|
|
146
146
|
|
|
147
|
-
if schema is not None:
|
|
148
|
-
self.root.apply_schema(schema)
|
|
149
|
-
|
|
150
147
|
elif item is not None:
|
|
151
148
|
self.root = None
|
|
152
149
|
self.item = self.get_context_item(item, self.namespaces, uri, fragment)
|
|
@@ -159,7 +156,7 @@ class XPathContext:
|
|
|
159
156
|
isinstance(self.root, ElementNode) and \
|
|
160
157
|
is_etree_element_instance(self.root.obj):
|
|
161
158
|
# Creates a dummy document that will be not included in results
|
|
162
|
-
self.document = self.root.get_document_node(
|
|
159
|
+
self.document = self.root.get_document_node(as_parent=False)
|
|
163
160
|
else:
|
|
164
161
|
self.document = None
|
|
165
162
|
|
|
@@ -180,7 +177,9 @@ class XPathContext:
|
|
|
180
177
|
if v is not None else v for k, v in documents.items()
|
|
181
178
|
}
|
|
182
179
|
|
|
183
|
-
|
|
180
|
+
if schema is not None:
|
|
181
|
+
self.schema = schema
|
|
182
|
+
|
|
184
183
|
self.variables = {}
|
|
185
184
|
if variables is not None:
|
|
186
185
|
for varname, value in variables.items():
|
|
@@ -243,11 +242,21 @@ class XPathContext:
|
|
|
243
242
|
@schema.setter
|
|
244
243
|
def schema(self, schema: Optional['AbstractSchemaProxy']) -> None:
|
|
245
244
|
self._schema = schema
|
|
246
|
-
if schema is
|
|
245
|
+
if schema is None:
|
|
246
|
+
if self.root is not None:
|
|
247
|
+
self.root.clear_types()
|
|
248
|
+
elif isinstance(self.item, XPathNode):
|
|
249
|
+
self.item.clear_types()
|
|
250
|
+
elif hasattr(schema, 'is_assertion_based'):
|
|
247
251
|
if self.root is not None:
|
|
252
|
+
self.root.clear_types()
|
|
248
253
|
self.root.apply_schema(schema)
|
|
249
254
|
elif isinstance(self.item, XPathNode):
|
|
255
|
+
self.item.clear_types()
|
|
250
256
|
self.item.apply_schema(schema)
|
|
257
|
+
else:
|
|
258
|
+
msg = f"{schema!r} is not an instance of AbstractSchemaProxy"
|
|
259
|
+
raise ElementPathTypeError(msg)
|
|
251
260
|
|
|
252
261
|
def get_root(self, node: Any) -> Optional[RootNodeType]:
|
|
253
262
|
if isinstance(self.root, (DocumentNode, ElementNode)):
|
|
@@ -622,15 +631,6 @@ class XPathSchemaContext(XPathContext):
|
|
|
622
631
|
"""
|
|
623
632
|
root: ElementNode
|
|
624
633
|
|
|
625
|
-
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
626
|
-
super().__init__(*args, **kwargs)
|
|
627
|
-
if self.schema is None:
|
|
628
|
-
if isinstance(self.root, SchemaElementNode):
|
|
629
|
-
try:
|
|
630
|
-
self._schema = self.root.obj.xpath_proxy
|
|
631
|
-
except AttributeError:
|
|
632
|
-
pass
|
|
633
|
-
|
|
634
634
|
@property
|
|
635
635
|
def schema(self) -> Optional['AbstractSchemaProxy']:
|
|
636
636
|
return self._schema
|