refactor: annotation with __future__.annotations
Adds `from __future__ import annotations` to the top of every module,
right below the module's docstring. Replaces any usages of t.List,
t.Dict, t.Set, t.Tuple, and t.Type with their built-in equivalents:
list, dict, set, tuple, and type. Ensures that make test still passes
under Python 3.7, 3.8 and 3.9.
2023-01-17 18:57:23 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2022-02-07 17:11:43 +00:00
|
|
|
# The Tutor plugin system is licensed under the terms of the Apache 2.0 license.
|
|
|
|
__license__ = "Apache 2.0"
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import typing as t
|
2023-04-28 15:11:14 +00:00
|
|
|
from weakref import WeakSet
|
2022-02-07 17:11:43 +00:00
|
|
|
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
from typing_extensions import Concatenate, ParamSpec
|
|
|
|
|
2022-11-08 15:09:16 +00:00
|
|
|
from . import contexts, priorities
|
2022-02-07 17:11:43 +00:00
|
|
|
|
2023-01-06 18:02:17 +00:00
|
|
|
#: Filter generic return value, which is also the type of the first callback argument.
|
|
|
|
T1 = t.TypeVar("T1")
|
|
|
|
#: Filter generic signature for all arguments after the first one.
|
|
|
|
T2 = ParamSpec("T2")
|
|
|
|
#: Specialized typevar for list elements
|
|
|
|
L = t.TypeVar("L")
|
|
|
|
|
2023-02-06 21:10:33 +00:00
|
|
|
FilterCallbackFunc = t.Callable[Concatenate[T1, T2], T1]
|
2022-02-07 17:11:43 +00:00
|
|
|
|
|
|
|
|
2023-01-06 18:02:17 +00:00
|
|
|
class FilterCallback(contexts.Contextualized, t.Generic[T1, T2]):
|
2022-11-15 15:59:19 +00:00
|
|
|
def __init__(
|
2023-01-06 18:02:17 +00:00
|
|
|
self,
|
2023-02-06 21:10:33 +00:00
|
|
|
func: FilterCallbackFunc[T1, T2],
|
2023-01-06 18:02:17 +00:00
|
|
|
priority: t.Optional[int] = None,
|
2022-11-15 15:59:19 +00:00
|
|
|
):
|
2022-02-07 17:11:43 +00:00
|
|
|
super().__init__()
|
|
|
|
self.func = func
|
2022-11-08 15:09:16 +00:00
|
|
|
self.priority = priority or priorities.DEFAULT
|
2022-02-07 17:11:43 +00:00
|
|
|
|
2023-01-06 18:02:17 +00:00
|
|
|
def apply(self, value: T1, *args: T2.args, **kwargs: T2.kwargs) -> T1:
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
return self.func(value, *args, **kwargs)
|
2022-02-07 17:11:43 +00:00
|
|
|
|
|
|
|
|
2023-01-06 18:02:17 +00:00
|
|
|
class Filter(t.Generic[T1, T2]):
|
2022-02-07 17:11:43 +00:00
|
|
|
"""
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
Filter hooks have callbacks that are triggered as a chain.
|
|
|
|
|
|
|
|
Several filters are defined across the codebase. Each filters is given a unique
|
|
|
|
name. To each filter are associated zero or more callbacks, sorted by priority.
|
|
|
|
|
|
|
|
This is the typical filter lifecycle:
|
|
|
|
|
2023-04-28 15:11:14 +00:00
|
|
|
1. Create a filter with ``Filter()``.
|
|
|
|
2. Add callbacks with :py:meth:`add`.
|
2023-01-06 18:02:17 +00:00
|
|
|
3. Call the filter callbacks with method :py:meth:`apply`.
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
|
|
|
|
The result of each callback is passed as the first argument to the next one. Thus,
|
|
|
|
the type of the first argument must match the callback return type.
|
|
|
|
|
2023-04-28 15:11:14 +00:00
|
|
|
The ``T1`` and ``T2`` type parameters of the Filter class correspond to the expected
|
|
|
|
signature of the filter callbacks. ``T1`` is the type of the first argument (and thus
|
|
|
|
the return value type as well) and ``T2`` is the signature of the other arguments.
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
|
|
|
|
For instance, `Filter[str, [int]]` means that the filter callbacks are expected to
|
|
|
|
take two arguments: one string and one integer. Each callback must then return a
|
|
|
|
string.
|
|
|
|
|
|
|
|
This strong typing makes it easier for plugin developers to quickly check whether
|
|
|
|
they are adding and calling filter callbacks correctly.
|
2022-02-07 17:11:43 +00:00
|
|
|
"""
|
|
|
|
|
2023-04-28 15:11:14 +00:00
|
|
|
# Keep a weak reference to all created filters. This allows us to clear them when
|
|
|
|
# necessary.
|
|
|
|
INSTANCES: WeakSet[Filter[t.Any, t.Any]] = WeakSet()
|
2022-02-07 17:11:43 +00:00
|
|
|
|
2023-04-28 15:11:14 +00:00
|
|
|
def __init__(self) -> None:
|
2023-01-06 18:02:17 +00:00
|
|
|
self.callbacks: list[FilterCallback[T1, T2]] = []
|
2023-04-28 15:11:14 +00:00
|
|
|
self.INSTANCES.add(self)
|
2022-02-07 17:11:43 +00:00
|
|
|
|
2022-11-08 15:09:16 +00:00
|
|
|
def add(
|
|
|
|
self, priority: t.Optional[int] = None
|
2023-02-06 21:10:33 +00:00
|
|
|
) -> t.Callable[[FilterCallbackFunc[T1, T2]], FilterCallbackFunc[T1, T2]]:
|
2023-01-06 18:02:17 +00:00
|
|
|
"""
|
|
|
|
Decorator to add a filter callback.
|
|
|
|
|
|
|
|
Callbacks are added by increasing priority. Highest priority score are called
|
|
|
|
last.
|
|
|
|
|
|
|
|
:param int priority: optional order in which the filter callbacks are called. Higher
|
|
|
|
values mean that they will be performed later. The default value is
|
|
|
|
``priorities.DEFAULT`` (10). Filters that must be called last should have a
|
|
|
|
priority of 100.
|
|
|
|
|
|
|
|
The return value of each filter function callback will be passed as the first argument to the next one.
|
|
|
|
|
|
|
|
Usage::
|
|
|
|
|
|
|
|
@my_filter.add()
|
|
|
|
def my_func(value, some_other_arg):
|
|
|
|
# Do something with `value`
|
|
|
|
...
|
|
|
|
return value
|
|
|
|
|
|
|
|
After filters have been created, the result of calling all filter callbacks is obtained by running:
|
|
|
|
|
|
|
|
final_value = my_filter.apply(initial_value, some_other_argument_value)
|
|
|
|
"""
|
|
|
|
|
2023-02-06 21:10:33 +00:00
|
|
|
def inner(func: FilterCallbackFunc[T1, T2]) -> FilterCallbackFunc[T1, T2]:
|
|
|
|
callback: FilterCallback[T1, T2] = FilterCallback(func, priority=priority)
|
2022-11-08 15:09:16 +00:00
|
|
|
priorities.insert_callback(callback, self.callbacks)
|
2022-02-07 17:11:43 +00:00
|
|
|
return func
|
|
|
|
|
|
|
|
return inner
|
|
|
|
|
|
|
|
def apply(
|
|
|
|
self,
|
2023-01-06 18:02:17 +00:00
|
|
|
value: T1,
|
|
|
|
*args: T2.args,
|
|
|
|
**kwargs: T2.kwargs,
|
|
|
|
) -> T1:
|
2022-02-07 17:11:43 +00:00
|
|
|
"""
|
|
|
|
Apply all declared filters to a single value, passing along the additional arguments.
|
|
|
|
|
|
|
|
The return value of every filter is passed as the first argument to the next callback.
|
|
|
|
|
|
|
|
Usage::
|
|
|
|
|
|
|
|
results = filters.apply("my-filter", ["item0"])
|
|
|
|
|
|
|
|
:type value: object
|
|
|
|
:rtype: same as the type of ``value``.
|
|
|
|
"""
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
return self.apply_from_context(None, value, *args, **kwargs)
|
|
|
|
|
|
|
|
def apply_from_context(
|
|
|
|
self,
|
|
|
|
context: t.Optional[str],
|
2023-01-06 18:02:17 +00:00
|
|
|
value: T1,
|
|
|
|
*args: T2.args,
|
|
|
|
**kwargs: T2.kwargs,
|
|
|
|
) -> T1:
|
|
|
|
"""
|
|
|
|
Same as :py:meth:`apply` but only run the callbacks that were created in a given context.
|
|
|
|
|
|
|
|
If ``context`` is None then it is ignored.
|
|
|
|
"""
|
2022-02-07 17:11:43 +00:00
|
|
|
for callback in self.callbacks:
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
if callback.is_in_context(context):
|
|
|
|
try:
|
|
|
|
value = callback.apply(
|
|
|
|
value,
|
|
|
|
*args,
|
|
|
|
**kwargs,
|
|
|
|
)
|
|
|
|
except:
|
|
|
|
sys.stderr.write(
|
2023-04-28 15:11:14 +00:00
|
|
|
f"Error applying filter: func={callback.func} contexts={callback.contexts}'\n"
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
)
|
|
|
|
raise
|
2022-02-07 17:11:43 +00:00
|
|
|
return value
|
|
|
|
|
|
|
|
def clear(self, context: t.Optional[str] = None) -> None:
|
|
|
|
"""
|
2023-01-06 18:02:17 +00:00
|
|
|
Clear any previously defined filter with the given context.
|
2022-02-07 17:11:43 +00:00
|
|
|
"""
|
|
|
|
self.callbacks = [
|
|
|
|
callback
|
|
|
|
for callback in self.callbacks
|
|
|
|
if not callback.is_in_context(context)
|
|
|
|
]
|
|
|
|
|
2023-04-28 15:11:14 +00:00
|
|
|
@classmethod
|
|
|
|
def clear_all(cls, context: t.Optional[str] = None) -> None:
|
|
|
|
"""
|
|
|
|
Clear any previously defined filter with the given context.
|
|
|
|
"""
|
|
|
|
for filtre in cls.INSTANCES:
|
|
|
|
filtre.clear(context)
|
|
|
|
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
# The methods below are specific to filters which take lists as first arguments
|
2022-11-15 15:59:19 +00:00
|
|
|
def add_item(
|
2023-01-06 18:02:17 +00:00
|
|
|
self: "Filter[list[L], T2]", item: L, priority: t.Optional[int] = None
|
2022-11-15 15:59:19 +00:00
|
|
|
) -> None:
|
2023-01-06 18:02:17 +00:00
|
|
|
"""
|
|
|
|
Convenience decorator to add a single item to a filter that returns a list of items.
|
|
|
|
|
|
|
|
This method is only valid for filters that return list of items.
|
|
|
|
|
|
|
|
:param object item: item that will be appended to the resulting list.
|
|
|
|
:param int priority: see :py:data:`Filter.add`.
|
|
|
|
|
|
|
|
Usage::
|
|
|
|
|
|
|
|
my_filter.add_item("item1")
|
|
|
|
my_filter.add_item("item2")
|
|
|
|
|
|
|
|
assert ["item1", "item2"] == my_filter.apply([])
|
|
|
|
"""
|
2022-11-15 15:59:19 +00:00
|
|
|
self.add_items([item], priority=priority)
|
|
|
|
|
|
|
|
def add_items(
|
2023-01-06 18:02:17 +00:00
|
|
|
self: "Filter[list[L], T2]", items: list[L], priority: t.Optional[int] = None
|
2022-11-15 15:59:19 +00:00
|
|
|
) -> None:
|
2023-01-06 18:02:17 +00:00
|
|
|
"""
|
|
|
|
Convenience function to add multiple items to a filter that returns a list of items.
|
|
|
|
|
|
|
|
This method is only valid for filters that return list of items.
|
|
|
|
|
|
|
|
This is a similar method to :py:data:`Filter.add_item` except that it can be
|
|
|
|
used to add multiple items at the same time. If you find yourself calling
|
|
|
|
``add_item`` multiple times on the same filter, then you probably want to use a
|
|
|
|
single call to ``add_items`` instead.
|
|
|
|
|
|
|
|
:param list[object] items: items that will be appended to the resulting list.
|
2023-04-28 15:11:14 +00:00
|
|
|
:param int priority: optional priority.
|
2023-01-06 18:02:17 +00:00
|
|
|
|
|
|
|
Usage::
|
|
|
|
|
|
|
|
my_filter.add_items(["item1", "item2"])
|
|
|
|
my_filter.add_items(["item3", "item4"])
|
|
|
|
|
|
|
|
assert ["item1", "item2", "item3", "item4"] == my_filter.apply([])
|
|
|
|
|
|
|
|
The following are equivalent::
|
|
|
|
|
|
|
|
# Single call to add_items
|
|
|
|
my_filter.add_items(["item1", "item2"])
|
|
|
|
|
|
|
|
# Multiple calls to add_item
|
|
|
|
my_filter.add_item("item1")
|
|
|
|
my_filter.add_item("item2")
|
|
|
|
"""
|
2023-02-09 10:57:26 +00:00
|
|
|
|
2023-04-28 08:13:46 +00:00
|
|
|
@self.add(priority=priority)
|
|
|
|
def callback(
|
|
|
|
values: list[L], /, *_args: T2.args, **_kwargs: T2.kwargs
|
|
|
|
) -> list[L]:
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
return values + items
|
|
|
|
|
|
|
|
def iterate(
|
2023-01-06 18:02:17 +00:00
|
|
|
self: "Filter[list[L], T2]", *args: T2.args, **kwargs: T2.kwargs
|
|
|
|
) -> t.Iterator[L]:
|
|
|
|
"""
|
|
|
|
Convenient function to iterate over the results of a filter result list.
|
|
|
|
|
|
|
|
This method is only valid for filters that return list of items.
|
|
|
|
|
|
|
|
This pieces of code are equivalent::
|
|
|
|
|
|
|
|
for value in my_filter.apply([], *args, **kwargs):
|
|
|
|
...
|
|
|
|
|
|
|
|
for value in my_filter.iterate(*args, **kwargs):
|
|
|
|
...
|
|
|
|
|
|
|
|
:rtype iterator[T]: iterator over the list of items from the filter
|
|
|
|
"""
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
yield from self.iterate_from_context(None, *args, **kwargs)
|
|
|
|
|
|
|
|
def iterate_from_context(
|
2023-01-06 18:02:17 +00:00
|
|
|
self: "Filter[list[L], T2]",
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
context: t.Optional[str],
|
2023-01-06 18:02:17 +00:00
|
|
|
*args: T2.args,
|
|
|
|
**kwargs: T2.kwargs,
|
|
|
|
) -> t.Iterator[L]:
|
|
|
|
"""
|
|
|
|
Same as :py:func:`Filter.iterate` but apply only callbacks from a given context.
|
|
|
|
"""
|
feat: strongly typed hooks
Now that the mypy bugs have been resolved, we are able to define more precisely
and cleanly the types of Actions and Filters.
Moreover, can now strongly type named actions and hooks (in consts.py). With
such a strong typing, we get early alerts of hooks called with incorrect
arguments, which is nothing short of awesome :)
This change breaks the hooks API by removing the `context=...` argument. The
reason for that is that we cannot insert arbitrary arguments between `P.args,
P.kwargs`: https://peps.python.org/pep-0612/#the-components-of-a-paramspec
> A function declared as def inner(a: A, b: B, *args: P.args, **kwargs:
> P.kwargs) -> R has type Callable[Concatenate[A, B, P], R]. Placing
> keyword-only parameters between the *args and **kwargs is forbidden.
Getting the documentation to build in nitpicky mode is quite difficult... We
need to add `nitpick_ignore` to the docs conf.py, otherwise sphinx complains
about many missing class references. This, despite upgrading almost all doc
requirements (except docutils).
2022-10-06 10:05:01 +00:00
|
|
|
yield from self.apply_from_context(context, [], *args, **kwargs)
|