Skip to content

Commit

Permalink
Fix some type issues (and likely introduce a few 😅) 🪛
Browse files Browse the repository at this point in the history
  • Loading branch information
todofixthis committed Oct 19, 2024
1 parent ffc480a commit 5908247
Showing 1 changed file with 34 additions and 28 deletions.
62 changes: 34 additions & 28 deletions src/filters/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
]

T = typing.TypeVar("T")
U = typing.TypeVar("U")

FilterCompatible = typing.Optional[
FilterCompatible = (
typing.Union[
"BaseFilter[T]",
typing.Callable[[], "BaseFilter[T]"],
]
]
| None
)
"""
Used in PEP-484 type hints to indicate a value that can be normalized
into an instance of a :py:class:`filters.base.BaseFilter` subclass.
Expand All @@ -38,12 +40,12 @@ class BaseFilter(typing.Generic[T]):
CODE_EXCEPTION: "An error occurred while processing this value.",
}

def __init__(self):
def __init__(self) -> None:
super().__init__()

self._parent: typing.Optional[BaseFilter] = None
self._handler: typing.Optional[BaseInvalidValueHandler] = None
self._key: typing.Optional[str] = None
self._parent: BaseFilter[T] | None = None
self._handler: BaseInvalidValueHandler | None = None
self._key: str | None = None

#
# Indicates whether the Filter detected any invalid values.
Expand All @@ -63,7 +65,7 @@ def __init_subclass__(cls, **kwargs: typing.Any) -> None:
Pre-compute some values to improve performance in derived classes.
"""
if not hasattr(cls, "templates"):
cls.templates: dict[str, str] = {}
cls.templates = {}

# Copy error templates from base class to derived class, but in the
# event of a conflict, preserve the derived class' template.
Expand All @@ -77,19 +79,19 @@ def __init_subclass__(cls, **kwargs: typing.Any) -> None:
cls.templates = templates

@classmethod
def __copy__(cls, the_filter: "BaseFilter") -> "BaseFilter":
def __copy__(cls, the_filter: "BaseFilter[T]") -> "BaseFilter[T]":
"""
Creates a shallow copy of the object.
"""
new_filter: BaseFilter = type(the_filter)()
new_filter: BaseFilter[T] = type(the_filter)()

new_filter._parent = the_filter._parent
new_filter._key = the_filter._key
new_filter._handler = the_filter._handler

return new_filter

def __or__(self, next_filter: FilterCompatible) -> "FilterChain":
def __or__(self, next_filter: FilterCompatible) -> "FilterChain[T]":
"""
Chains another filter with this one.
"""
Expand All @@ -109,7 +111,7 @@ def __or__(self, next_filter: FilterCompatible) -> "FilterChain":
else:
return self if isinstance(self, FilterChain) else FilterChain(self)

def __str__(self):
def __str__(self) -> str:
"""
Returns a string representation of the Filter.
Expand All @@ -124,7 +126,7 @@ def __str__(self):
)

@property
def parent(self) -> typing.Optional["BaseFilter"]:
def parent(self) -> "BaseFilter[typing.Any] | None":
"""
Returns the parent Filter.
"""
Expand All @@ -138,7 +140,7 @@ def parent(self) -> typing.Optional["BaseFilter"]:
return self._parent

@parent.setter
def parent(self, parent: "BaseFilter") -> None:
def parent(self, parent: "BaseFilter[typing.Any]") -> None:
"""
Sets the parent Filter.
"""
Expand Down Expand Up @@ -172,21 +174,22 @@ def sub_key(self, sub_key: str) -> str:
return self._make_key(self._key_parts + [sub_key])

@property
def _key_parts(self) -> typing.List[str]:
def _key_parts(self) -> list[str]:
"""
Assembles each key part in the filter hierarchy.
"""
key_parts = []
key_parts: list[str] = []

# Iterate up the parent chain and collect key parts.
# Alternatively, we could just get ``self.parent._key_parts``,
# but that is way less efficient.
parent = self
parent: BaseFilter[typing.Any] | None = self
while parent:
# As we move up the chain, push key parts onto the front of
# the path (otherwise the key parts would be in reverse
# order).
key_parts.insert(0, parent._key)
if parent._key is not None:
key_parts.insert(0, parent._key)
parent = parent.parent

return key_parts
Expand Down Expand Up @@ -261,7 +264,7 @@ def _filter(
self,
value: typing.Any,
filter_chain: FilterCompatible,
sub_key: typing.Optional[str] = None,
sub_key: str | None = None,
) -> typing.Any:
"""
Applies another filter to a value in the same context as the
Expand Down Expand Up @@ -295,11 +298,11 @@ def _invalid_value(
self,
value: typing.Any,
reason: typing.Union[str, Exception],
replacement: typing.Optional[typing.Any] = None,
replacement: typing.Any = None,
exc_info: bool = False,
context: typing.Optional[typing.MutableMapping] = None,
sub_key: typing.Optional[str] = None,
template_vars: typing.Optional[typing.Mapping] = None,
context: typing.MutableMapping[str, typing.Any] | None = None,
sub_key: str | None = None,
template_vars: typing.Mapping[str, str] | None = None,
) -> typing.Any:
"""
Handles an invalid value.
Expand Down Expand Up @@ -398,9 +401,9 @@ def _format_message(
def resolve_filter(
cls,
the_filter: FilterCompatible,
parent: typing.Optional["BaseFilter"] = None,
key: typing.Optional[str] = None,
) -> typing.Optional["FilterChain"]:
parent: "BaseFilter[typing.Any] | None" = None,
key: str | None = None,
) -> "FilterChain[U] | None":
"""
Converts a filter-compatible value into a consistent type.
"""
Expand Down Expand Up @@ -440,7 +443,7 @@ def _make_key(key_parts: typing.Iterable[str]) -> str:
return ".".join(filter(None, key_parts))


class FilterChain(BaseFilter):
class FilterChain(BaseFilter[T]):
"""
Allows you to chain multiple filters together so that they are
treated as a single filter.
Expand All @@ -459,7 +462,10 @@ def __str__(self):
filters=" | ".join(map(str, self._filters)),
)

def __or__(self, next_filter: FilterCompatible) -> "FilterChain":
@typing.overload
def __or__(self, next_filter: None) -> "FilterChain[T]": ...

def __or__(self, next_filter: FilterCompatible) -> "FilterChain[U]":
"""
Chains a filter with this one.
Expand All @@ -469,7 +475,7 @@ def __or__(self, next_filter: FilterCompatible) -> "FilterChain":
resolved = self.resolve_filter(next_filter)

if resolved:
new_chain: FilterChain = copy(self)
new_chain: FilterChain[U] = copy(self)
new_chain._add(next_filter)
return new_chain
else:
Expand Down

0 comments on commit 5908247

Please sign in to comment.