Filters

Filters are one of the two types of hooks (the other being Actions) that can be used to extend Tutor. Filters allow one to modify the application behavior by transforming data. Each filter has a name, and callback functions can be attached to it. When a filter is applied, these callback functions are called in sequence; the result of each callback function is passed as the first argument to the next callback function. The result of the final callback function is returned to the application as the filter’s output.

class tutor.core.hooks.Filter

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:

  1. Create a filter with Filter().

  2. Add callbacks with add().

  3. Call the filter callbacks with method apply().

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.

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.

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.

add(priority=None)

Decorator to add a filter callback.

Callbacks are added by increasing priority. Highest priority score are called last.

Parameters:

priority (int) – 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.

Return type:

t.Callable[[FilterCallbackFunc[T1, T2]], FilterCallbackFunc[T1, T2]]

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)

add_item(item, priority=None)

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.

Parameters:
  • item (object) – item that will be appended to the resulting list.

  • priority (int) – see Filter.add.

  • self (Filter[list[L], T2])

Return type:

None

Usage:

my_filter.add_item("item1")
my_filter.add_item("item2")

assert ["item1", "item2"] == my_filter.apply([])
add_items(items, priority=None)

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 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.

Parameters:
  • items (list[object]) – items that will be appended to the resulting list.

  • priority (int) – optional priority.

  • self (Filter[list[L], T2])

Return type:

None

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")
apply(value, *args, **kwargs)

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"])
Return type:

same as the type of value.

Parameters:
  • value (object)

  • args (T2.args)

  • kwargs (T2.kwargs)

apply_from_context(context, value, *args, **kwargs)

Same as apply() but only run the callbacks that were created in a given context.

If context is None then it is ignored.

Parameters:
  • context (t.Optional[str])

  • value (T1)

  • args (T2.args)

  • kwargs (T2.kwargs)

Return type:

T1

clear(context=None)

Clear any previously defined filter with the given context.

Parameters:

context (str | None)

Return type:

None

classmethod clear_all(context=None)

Clear any previously defined filter with the given context.

Parameters:

context (str | None)

Return type:

None

iterate(*args, **kwargs)

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

Parameters:
  • self (Filter[list[L], T2])

  • args (T2.args)

  • kwargs (T2.kwargs)

iterate_from_context(context, *args, **kwargs)

Same as Filter.iterate() but apply only callbacks from a given context.

Parameters:
  • self (Filter[list[L], T2])

  • context (t.Optional[str])

  • args (T2.args)

  • kwargs (T2.kwargs)

Return type:

t.Iterator[L]

class tutor.core.hooks.filters.T1
class tutor.core.hooks.filters.T2
class tutor.core.hooks.filters.L