Skip to content

Commit

Permalink
Add a protocol for XSD attribute groups
Browse files Browse the repository at this point in the history
  - Bump minor release and update release info
  • Loading branch information
brunato committed Mar 11, 2024
1 parent 8490979 commit 004fca1
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 26 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test-elementpath.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
flake8 elementpath --max-line-length=100 --statistics
- name: Lint with mypy
run: |
pip install mypy==1.8.0 xmlschema lxml-stubs
pip install mypy==1.9.0 xmlschema lxml-stubs
mypy --show-error-codes --strict elementpath
- name: Test with unittest
run: |
Expand Down
6 changes: 4 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
CHANGELOG
*********

`v4.3.1`_ (2024-03-xx)
`v4.4.0`_ (2024-03-11)
======================
* Improve stand-alone XPath functions builder (issue #70)
* Update tokens and parsers __repr__
* Fix static typing protocols to work with etree and XSD elements

`v4.3.0`_ (2024-02-17)
Expand Down Expand Up @@ -460,4 +462,4 @@ CHANGELOG
.. _v4.2.0: https://github.com/sissaschool/elementpath/compare/v4.1.5...v4.2.0
.. _v4.2.1: https://github.com/sissaschool/elementpath/compare/v4.2.0...v4.2.1
.. _v4.3.0: https://github.com/sissaschool/elementpath/compare/v4.2.1...v4.3.0
.. _v4.3.1: https://github.com/sissaschool/elementpath/compare/v4.3.0...v4.3.1
.. _v4.4.0: https://github.com/sissaschool/elementpath/compare/v4.3.0...v4.4.0
2 changes: 1 addition & 1 deletion doc/advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ having as result a tree of tokens:
>>> isinstance(token, XPathToken)
True
>>> token
_SolidusOperator(...)
<_SolidusOperator object at 0x...
>>> str(token)
"'/' operator"
>>> token.tree
Expand Down
4 changes: 2 additions & 2 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
author = 'Davide Brunato'

# The short X.Y version
version = '4.3'
version = '4.4'
# The full version, including alpha/beta/rc tags
release = '4.3.1'
release = '4.4.0'

# -- General configuration ---------------------------------------------------

Expand Down
6 changes: 2 additions & 4 deletions elementpath/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#
# @author Davide Brunato <brunato@sissa.it>
#
__version__ = '4.3.1'
__version__ = '4.4.0'
__author__ = "Davide Brunato"
__contact__ = "brunato@sissa.it"
__copyright__ = "Copyright 2018-2024, SISSA"
Expand Down Expand Up @@ -38,16 +38,14 @@
from .schema_proxy import AbstractSchemaProxy
from .regex import RegexError, translate_pattern

TypedElement = ElementNode # for backward compatibility with xmlschema<=1.10.0

__all__ = ['datatypes', 'protocols', 'etree', 'ElementPathError', 'MissingContextError',
'ElementPathKeyError', 'ElementPathZeroDivisionError', 'ElementPathNameError',
'ElementPathOverflowError', 'ElementPathRuntimeError', 'ElementPathSyntaxError',
'ElementPathTypeError', 'ElementPathValueError', 'ElementPathLocaleError',
'XPathContext', 'XPathSchemaContext', 'XPathNode', 'DocumentNode',
'ElementNode', 'AttributeNode', 'NamespaceNode', 'CommentNode',
'ProcessingInstructionNode', 'TextNode', 'LazyElementNode',
'SchemaElementNode', 'TypedElement', 'get_node_tree', 'build_node_tree',
'SchemaElementNode', 'get_node_tree', 'build_node_tree',
'build_lxml_node_tree', 'build_schema_node_tree', 'XPathToken',
'XPathFunction', 'XPath1Parser', 'XPath2Parser', 'select', 'iter_select',
'Selector', 'AbstractSchemaProxy', 'RegexError', 'translate_pattern']
10 changes: 8 additions & 2 deletions elementpath/compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,14 @@ def etree_deep_equal(e1: ElementProtocol, e2: ElementProtocol) -> bool:
elif len(e1) != len(e2) or len(e1.attrib) != len(e2.attrib):
return False

items1 = {(cm.strxfrm(k or ''), cm.strxfrm(v)) for k, v in e1.attrib.items()}
items2 = {(cm.strxfrm(k or ''), cm.strxfrm(v)) for k, v in e2.attrib.items()}
try:
items1 = {(cm.strxfrm(k or ''), cm.strxfrm(v)) # type: ignore[arg-type]
for k, v in e1.attrib.items()}
items2 = {(cm.strxfrm(k or ''), cm.strxfrm(v)) # type: ignore[arg-type]
for k, v in e2.attrib.items()}
except TypeError:
return False

if items1 != items2:
return False
return all(etree_deep_equal(c1, c2) for c1, c2 in zip(e1, e2))
Expand Down
51 changes: 43 additions & 8 deletions elementpath/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"""
Define type hints protocols for XPath related objects.
"""
from typing import overload, Any, Dict, Iterator, Iterable, Optional, Sequence, \
from typing import overload, Any, Dict, Iterator, Iterable, Optional, Sequence, ItemsView, \
Protocol, Sized, Hashable, Union, TypeVar, Mapping, Tuple, Set, MutableMapping

_T = TypeVar("_T")
Expand All @@ -32,7 +32,10 @@ def __len__(self) -> int: ...


AttribType = Union[
MutableMapping[str, Any], MutableMapping[Optional[str], Any], LxmlAttribProtocol
MutableMapping[str, Any],
MutableMapping[Optional[str], Any],
LxmlAttribProtocol,
'XsdAttributeGroupProtocol'
]


Expand Down Expand Up @@ -67,6 +70,13 @@ def attrib(self) -> AttribType: ...

class EtreeElementProtocol(ElementProtocol, Protocol):
"""A protocol for xml.etree.ElementTree elements."""
def __iter__(self) -> Iterator['EtreeElementProtocol']: ...

def find(
self, path: str, namespaces: Optional[Dict[str, str]] = ...
) -> Optional['EtreeElementProtocol']: ...
def iter(self, tag: Optional[str] = ...) -> Iterator['EtreeElementProtocol']: ...

@property
def attrib(self) -> Dict[str, str]: ...

Expand Down Expand Up @@ -106,7 +116,7 @@ def parse(self, source: Any, *args: Any, **kwargs: Any) -> LxmlElementProtocol:
def iter(self, tag: Optional[str] = ...) -> Iterator[LxmlElementProtocol]: ...


class XsdValidatorProtocol(Protocol):
class XsdValidatorProtocol(Hashable, Protocol):
def is_matching(self, name: Optional[str],
default_namespace: Optional[str] = None) -> bool: ...

Expand Down Expand Up @@ -216,6 +226,30 @@ def ref(self) -> Optional[Any]: ...
XsdXPathNodeType = Union['XsdSchemaProtocol', 'XsdElementProtocol']


class XsdAttributeGroupProtocol(XsdComponentProtocol, Protocol):

@overload
def get(self, key: Optional[str]) -> Optional[XsdAttributeProtocol]: ...

@overload
def get(self, key: Optional[str], default: _T) -> Union[XsdAttributeProtocol, _T]: ...

def items(self) -> ItemsView[Optional[str], XsdAttributeProtocol]: ...

def __contains__(self, key: Optional[str]) -> bool: ...

def __getitem__(self, key: Optional[str]) -> XsdAttributeProtocol: ...

def __iter__(self) -> Iterator[Optional[str]]: ...

def __len__(self) -> int: ...

def __hash__(self) -> int: ...

@property
def ref(self) -> Optional[Any]: ...


class XsdElementProtocol(XsdComponentProtocol, ElementProtocol, Protocol):

def __iter__(self) -> Iterator['XsdElementProtocol']: ...
Expand All @@ -235,7 +269,7 @@ def type(self) -> Optional[XsdTypeProtocol]: ...
def ref(self) -> Optional[Any]: ...

@property
def attrib(self) -> MutableMapping[Optional[str], XsdAttributeProtocol]: ...
def attrib(self) -> XsdAttributeGroupProtocol: ...


GT = TypeVar("GT")
Expand Down Expand Up @@ -273,7 +307,8 @@ def tag(self) -> str: ...
def attrib(self) -> MutableMapping[Optional[str], 'XsdAttributeProtocol']: ...


__allx__ = ['ElementProtocol', 'EtreeElementProtocol', 'LxmlElementProtocol',
'DocumentProtocol', 'LxmlDocumentProtocol', 'XsdValidatorProtocol',
'XsdSchemaProtocol', 'XsdComponentProtocol', 'XsdTypeProtocol',
'XsdElementProtocol', 'XsdAttributeProtocol', 'GlobalMapsProtocol']
__all__ = ['ElementProtocol', 'EtreeElementProtocol', 'LxmlAttribProtocol',
'LxmlElementProtocol', 'DocumentProtocol', 'LxmlDocumentProtocol',
'XsdValidatorProtocol', 'XsdComponentProtocol', 'XsdTypeProtocol',
'XsdAttributeProtocol', 'XsdAttributeGroupProtocol',
'XsdElementProtocol', 'GlobalMapsProtocol', 'XsdSchemaProtocol',]
3 changes: 2 additions & 1 deletion elementpath/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from .xpath_nodes import XPathNode, ElementNode, AttributeNode, DocumentNode, \
NamespaceNode, TextNode, CommentNode
from .xpath_tokens import XPathToken, XPathMap, XPathArray
from .protocols import EtreeElementProtocol, LxmlElementProtocol

# XSLT and XQuery Serialization parameters
SERIALIZATION_PARAMS = '{%s}serialization-parameters' % XSLT_XQUERY_SERIALIZATION_NAMESPACE
Expand Down Expand Up @@ -135,7 +136,7 @@ def get_serialization_params(params: Union[None, ElementNode, XPathMap] = None,
kwargs[key] = value

elif isinstance(params, ElementNode):
root = params.elem
root = cast(Union[EtreeElementProtocol, LxmlElementProtocol], params.elem)
if root.tag != SERIALIZATION_PARAMS:
msg = 'output:serialization-parameters tag expected'
raise xpath_error('XPTY0004', msg, token)
Expand Down
4 changes: 2 additions & 2 deletions publiccode.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ publiccodeYmlVersion: '0.2'
name: elementpath
url: 'https://github.com/sissaschool/elementpath'
landingURL: 'https://github.com/sissaschool/elementpath'
releaseDate: '2024-03-xx'
softwareVersion: v4.3.1
releaseDate: '2024-03-11'
softwareVersion: v4.4.0
developmentStatus: stable
platforms:
- linux
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

setup(
name='elementpath',
version='4.3.1',
version='4.4.0',
packages=find_packages(include=['elementpath', 'elementpath.*']),
package_data={
'elementpath': ['py.typed'],
Expand Down
4 changes: 2 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ commands =

[testenv:mypy-py{38,39,310,311,312,py3}]
deps =
mypy==1.8.0
mypy==1.9.0
xmlschema>=3.0.1
lxml-stubs
commands =
Expand Down Expand Up @@ -92,7 +92,7 @@ allowlist_externals = tar
[testenv:w3c-xsdtests]
platform = (linux|darwin)
set_env =
VERSION = 3.0.1
VERSION = 3.0.2
COMMIT = 4293d6fb026af778aa7ad381c2a310354578cbe3
CHECKSUM = 3c7a44dbb59553d09ba96fee898255be78966960c22e9a7886c0b426a03255d7
change_dir = {env_tmp_dir}
Expand Down

0 comments on commit 004fca1

Please sign in to comment.