Skip to content

Commit

Permalink
disallow_any_generics mypy flag added.
Browse files Browse the repository at this point in the history
  • Loading branch information
dapper91 committed Jun 23, 2023
1 parent b442b17 commit 88c1c3c
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 29 deletions.
65 changes: 38 additions & 27 deletions pydantic_xml/element/element.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import abc
from enum import Enum
from typing import Callable, Dict, Generic, List, Optional, Sequence, TypeVar
from typing import Any, Callable, Dict, Generic, List, Optional, Sequence, TypeVar

from pydantic_xml.typedefs import NsMap

Expand Down Expand Up @@ -47,7 +47,7 @@ def pop_attributes(self) -> Optional[Dict[str, str]]:
"""

@abc.abstractmethod
def pop_element(self, tag: str, search_mode: 'SearchMode') -> Optional['XmlElement']:
def pop_element(self, tag: str, search_mode: 'SearchMode') -> Optional['XmlElement[Any]']:
"""
Extracts a sub-element from the xml element matching `tag`.
Expand All @@ -57,7 +57,7 @@ def pop_element(self, tag: str, search_mode: 'SearchMode') -> Optional['XmlEleme
"""

@abc.abstractmethod
def find_sub_element(self, path: Sequence[str], search_mode: 'SearchMode') -> Optional['XmlElement']:
def find_sub_element(self, path: Sequence[str], search_mode: 'SearchMode') -> Optional['XmlElement[Any]']:
"""
Searches for an element at the provided path. If the element is not found returns `None`.
Expand All @@ -67,15 +67,15 @@ def find_sub_element(self, path: Sequence[str], search_mode: 'SearchMode') -> Op
"""

@abc.abstractmethod
def create_snapshot(self) -> 'XmlElement':
def create_snapshot(self) -> 'XmlElement[Any]':
"""
Creates a snapshot of the element. The snapshot can be modified not affecting the original one.
:return: created snapshot
"""

@abc.abstractmethod
def apply_snapshot(self, snapshot: 'XmlElement') -> None:
def apply_snapshot(self, snapshot: 'XmlElement[Any]') -> None:
"""
Applies a snapshot to the current element.
"""
Expand Down Expand Up @@ -121,15 +121,15 @@ def set_attributes(self, attributes: Dict[str, str]) -> None:
"""

@abc.abstractmethod
def append_element(self, element: 'XmlElement') -> None:
def append_element(self, element: 'XmlElement[Any]') -> None:
"""
Appends a new sub-element to the xml element.
:param element: sub-element to be added
"""

@abc.abstractmethod
def make_element(self, tag: str, nsmap: Optional[NsMap]) -> 'XmlElement':
def make_element(self, tag: str, nsmap: Optional[NsMap]) -> 'XmlElement[Any]':
"""
Creates an element of the current element type.
Expand All @@ -139,7 +139,7 @@ def make_element(self, tag: str, nsmap: Optional[NsMap]) -> 'XmlElement':
"""

@abc.abstractmethod
def find_element_or_create(self, tag: str, search_mode: 'SearchMode', nsmap: Optional[NsMap]) -> 'XmlElement':
def find_element_or_create(self, tag: str, search_mode: 'SearchMode', nsmap: Optional[NsMap]) -> 'XmlElement[Any]':
"""
Searches for an element with the provided tag.
If the element is found returns it otherwise creates a new one.
Expand All @@ -159,14 +159,16 @@ class XmlElement(XmlElementReader, XmlElementWriter, Generic[NativeElement]):
Xml element.
"""

class State:
NativeElementInner = TypeVar('NativeElementInner')

class State(Generic[NativeElementInner]):
__slots__ = ('text', 'attrib', 'elements', 'next_element_idx')

def __init__(
self,
text: Optional[str],
attrib: Optional[Dict[str, str]],
elements: List['XmlElement'],
elements: List['XmlElement[XmlElement.NativeElementInner]'],
next_element_idx: int,
):
self.text = text
Expand All @@ -178,7 +180,7 @@ def __init__(

@classmethod
@abc.abstractmethod
def from_native(cls, element: NativeElement) -> 'XmlElement':
def from_native(cls, element: NativeElement) -> 'XmlElement[NativeElement]':
"""
Creates a instance of `XmlElement` from native element.
Expand All @@ -199,7 +201,7 @@ def __init__(
tag: str,
text: Optional[str] = None,
attributes: Optional[Dict[str, str]] = None,
elements: Optional[List['XmlElement']] = None,
elements: Optional[List['XmlElement[NativeElement]']] = None,
nsmap: Optional[NsMap] = None,
):
self._tag = tag
Expand All @@ -215,7 +217,7 @@ def __init__(
def tag(self) -> str:
return self._tag

def create_snapshot(self) -> 'XmlElement':
def create_snapshot(self) -> 'XmlElement[NativeElement]':
element = self.__class__(
tag=self._tag,
text=self._state.text,
Expand All @@ -227,7 +229,7 @@ def create_snapshot(self) -> 'XmlElement':

return element

def apply_snapshot(self, snapshot: 'XmlElement') -> None:
def apply_snapshot(self, snapshot: 'XmlElement[NativeElement]') -> None:
self._tag = snapshot._tag
self._nsmap = snapshot._nsmap
self._state.text = snapshot._state.text
Expand All @@ -253,7 +255,7 @@ def set_attribute(self, name: str, value: str) -> None:
def set_attributes(self, attributes: Dict[str, str]) -> None:
self._state.attrib = dict(attributes)

def append_element(self, element: 'XmlElement') -> None:
def append_element(self, element: 'XmlElement[NativeElement]') -> None:
self._state.elements.append(element)

def pop_text(self) -> Optional[str]:
Expand All @@ -269,12 +271,12 @@ def pop_attributes(self) -> Optional[Dict[str, str]]:

return result

def pop_element(self, tag: str, search_mode: 'SearchMode') -> Optional['XmlElement']:
def pop_element(self, tag: str, search_mode: 'SearchMode') -> Optional['XmlElement[NativeElement]']:
searcher = get_searcher(search_mode)

return searcher(self._state, tag, False)

def find_sub_element(self, path: Sequence[str], search_mode: 'SearchMode') -> Optional['XmlElement']:
def find_sub_element(self, path: Sequence[str], search_mode: 'SearchMode') -> Optional['XmlElement[NativeElement]']:
assert len(path) > 0, "path can't be empty"

root, path = path[0], path[1:]
Expand All @@ -284,14 +286,19 @@ def find_sub_element(self, path: Sequence[str], search_mode: 'SearchMode') -> Op

return element

def find_element_or_create(self, tag: str, search_mode: 'SearchMode', nsmap: Optional[NsMap]) -> 'XmlElement':
def find_element_or_create(
self,
tag: str,
search_mode: 'SearchMode',
nsmap: Optional[NsMap],
) -> 'XmlElement[NativeElement]':
if (sub_element := self._find_element(tag, search_mode)) is None:
sub_element = self.make_element(tag=tag, nsmap=nsmap)
self._state.elements.append(sub_element)

return sub_element

def _find_element(self, tag: str, search_mode: 'SearchMode') -> Optional['XmlElement']:
def _find_element(self, tag: str, search_mode: 'SearchMode') -> Optional['XmlElement[NativeElement]']:
searcher = get_searcher(search_mode)

return searcher(self._state, tag, True)
Expand All @@ -311,7 +318,7 @@ class SearchMode(str, Enum):
UNORDERED = 'unordered'


Searcher = Callable[[XmlElement.State, str, bool], Optional[XmlElement]]
Searcher = Callable[[XmlElement.State[Any], str, bool], Optional[XmlElement]]


def get_searcher(search_mode: SearchMode) -> Searcher:
Expand All @@ -325,7 +332,7 @@ def get_searcher(search_mode: SearchMode) -> Searcher:
raise AssertionError('unreachable')


def strict_search(state: XmlElement.State, tag: str, look_behind: bool = False) -> Optional[XmlElement]:
def strict_search(state: XmlElement.State[Any], tag: str, look_behind: bool = False) -> Optional[XmlElement[Any]]:
"""
Searches for a sub-element sequentially one by one.
Expand All @@ -335,7 +342,7 @@ def strict_search(state: XmlElement.State, tag: str, look_behind: bool = False)
:return: found element or `None` if the element not found
"""

result: Optional['XmlElement'] = None
result: Optional[XmlElement[Any]] = None

if look_behind and (result := _look_behind(state, tag)) is not None:
return result
Expand All @@ -347,7 +354,7 @@ def strict_search(state: XmlElement.State, tag: str, look_behind: bool = False)
return result


def ordered_search(state: XmlElement.State, tag: str, look_behind: bool = False) -> Optional[XmlElement]:
def ordered_search(state: XmlElement.State[Any], tag: str, look_behind: bool = False) -> Optional[XmlElement[Any]]:
"""
Searches for an element sequentially skipping unmatched ones.
Expand All @@ -357,7 +364,7 @@ def ordered_search(state: XmlElement.State, tag: str, look_behind: bool = False)
:return: found element or `None` if the element not found
"""

result: Optional['XmlElement'] = None
result: Optional[XmlElement[Any]] = None

if look_behind and (result := _look_behind(state, tag)) is not None:
return result
Expand All @@ -375,7 +382,11 @@ def ordered_search(state: XmlElement.State, tag: str, look_behind: bool = False)
return result


def unordered_search(state: XmlElement.State, tag: str, look_behind: bool = False) -> Optional[XmlElement]:
def unordered_search(
state: XmlElement.State[Any],
tag: str,
look_behind: bool = False,
) -> Optional[XmlElement[Any]]:
"""
Searches search for an element ignoring elements order.
Expand All @@ -385,7 +396,7 @@ def unordered_search(state: XmlElement.State, tag: str, look_behind: bool = Fals
:return: found element or `None` if the requested element not found
"""

result: Optional['XmlElement'] = None
result: Optional[XmlElement[Any]] = None

if look_behind and (result := _look_behind(state, tag)) is not None:
return result
Expand All @@ -402,7 +413,7 @@ def unordered_search(state: XmlElement.State, tag: str, look_behind: bool = Fals
return result


def _look_behind(state: XmlElement.State, tag: str) -> Optional[XmlElement]:
def _look_behind(state: XmlElement.State[Any], tag: str) -> Optional[XmlElement[Any]]:
if state.next_element_idx != 0:
candidate = state.elements[state.next_element_idx - 1]
if candidate.tag == tag:
Expand Down
4 changes: 2 additions & 2 deletions pydantic_xml/element/native/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from typing import Type
from typing import Any, Type

from pydantic_xml import config
from pydantic_xml.element import XmlElement as BaseXmlElement

XmlElement: Type[BaseXmlElement]
XmlElement: Type[BaseXmlElement[Any]]

if config.FORCE_STD_XML:
from .std import * # noqa: F403
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ build-backend = "poetry.core.masonry.api"

[tool.mypy]
allow_redefinition = true
disallow_any_generics = true
disallow_incomplete_defs = true
disallow_untyped_decorators = false
disallow_untyped_defs = true
Expand Down

0 comments on commit 88c1c3c

Please sign in to comment.