Skip to content

Improves annotations of PluginManager and contributed XPath functions #96

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 24 additions & 10 deletions _delb/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
from __future__ import annotations

import sys
from collections.abc import Callable, Iterable
from typing import TYPE_CHECKING, Any
from collections.abc import Iterable
from typing import TYPE_CHECKING, overload, Any

if sys.version_info < (3, 10): # DROPWITH Python3.9
from importlib_metadata import entry_points
Expand All @@ -27,8 +27,14 @@

if TYPE_CHECKING:
from types import SimpleNamespace

from _delb.typing import Loader, LoaderConstraint
from delb import Document
from _delb.typing import (
GenericDecorated,
Loader,
LoaderConstraint,
SecondOrderDecorator,
XPathFunction,
)


class DocumentMixinBase:
Expand Down Expand Up @@ -93,10 +99,10 @@ def _init_config(cls, config: SimpleNamespace, kwargs: dict[str, Any]):

class PluginManager:
def __init__(self):
self.document_mixins: list[type] = []
self.document_subclasses: list[type] = []
self.document_mixins: list[type[DocumentMixinBase]] = []
self.document_subclasses: list[type[Document]] = []
self.loaders: list[Loader] = []
self.xpath_functions: dict[str, Callable] = {}
self.xpath_functions: dict[str, XPathFunction] = {}

@staticmethod
def load_plugins():
Expand All @@ -108,7 +114,7 @@ def load_plugins():

def register_loader(
self, before: LoaderConstraint = None, after: LoaderConstraint = None
) -> Callable:
) -> SecondOrderDecorator:
"""
Registers a document loader.

Expand Down Expand Up @@ -200,7 +206,15 @@ def registrar(loader: Loader) -> Loader:

return registrar

def register_xpath_function(self, arg: Callable | str) -> Callable:
@overload
def register_xpath_function(self, arg: str) -> SecondOrderDecorator: ...

@overload
def register_xpath_function(self, arg: GenericDecorated) -> GenericDecorated: ...

def register_xpath_function(
self, arg: str | GenericDecorated
) -> SecondOrderDecorator | GenericDecorated:
"""
Custom XPath functions can be defined as shown in the following example. The
first argument to a function is always an instance of
Expand Down Expand Up @@ -231,7 +245,7 @@ def lowercase(_, string: str) -> str:
"""
if isinstance(arg, str):

def wrapper(func):
def wrapper(func: XPathFunction) -> XPathFunction:
self.xpath_functions[arg] = func
return func

Expand Down
10 changes: 8 additions & 2 deletions _delb/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@

import sys

from typing import TYPE_CHECKING, Any, Mapping, Union # noqa: UNT001
from typing import TYPE_CHECKING, Any, Callable, Mapping, Union, TypeVar # noqa: UNT001


if TYPE_CHECKING:
from collections.abc import Callable, Iterable
from collections.abc import Iterable
from types import SimpleNamespace

if sys.version_info < (3, 10): # DROPWITH Python 3.9
Expand All @@ -33,6 +33,7 @@
from lxml import etree

from _delb.nodes import NodeBase, _TagDefinition
from _delb.xpath.ast import EvaluationContext


if sys.version_info < (3, 11): # DROPWITH Python 3.10
Expand All @@ -41,6 +42,9 @@
from typing import Self


GenericDecorated = TypeVar("GenericDecorated", bound=Callable[..., Any])
SecondOrderDecorator: TypeAlias = "Callable[[GenericDecorated], GenericDecorated]"

Filter: TypeAlias = "Callable[[NodeBase], bool]"
NamespaceDeclarations: TypeAlias = Mapping[str | None, str]
NodeSource: TypeAlias = Union[str, "NodeBase", "_TagDefinition"]
Expand All @@ -49,6 +53,8 @@
Loader: TypeAlias = "Callable[[Any, SimpleNamespace], LoaderResult]"
LoaderConstraint: TypeAlias = Union[Loader, "Iterable[Loader]", None]

XPathFunction: TypeAlias = "Callable[[EvaluationContext, *Any], Any]"


__all__ = (
"Filter",
Expand Down
10 changes: 5 additions & 5 deletions _delb/xpath/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@


@plugin_manager.register_xpath_function
def concat(_, *strings: str) -> str:
def concat(_: EvaluationContext, *strings: str) -> str:
return "".join(strings)


@plugin_manager.register_xpath_function
def contains(_, string: str, substring: str) -> bool:
def contains(_: EvaluationContext, string: str, substring: str) -> bool:
return substring in string


@plugin_manager.register_xpath_function
def boolean(_, value: Any) -> bool:
def boolean(_: EvaluationContext, value: Any) -> bool:
return bool(value)


Expand All @@ -46,7 +46,7 @@ def last(context: EvaluationContext) -> int:


@plugin_manager.register_xpath_function("not")
def _not(_, value: Any) -> bool:
def _not(_: EvaluationContext, value: Any) -> bool:
return not value


Expand All @@ -56,7 +56,7 @@ def position(context: EvaluationContext) -> int:


@plugin_manager.register_xpath_function("starts-with")
def starts_with(_, string: str, prefix: str) -> bool:
def starts_with(_: EvaluationContext, string: str, prefix: str) -> bool:
return string.startswith(prefix)


Expand Down