API reference

Task factories

aiocontext.wrap_task_factory(loop)[source]

Wrap the loop task factory to make it context-aware.

Internally, this replaces the loop task factory by a wrapper function that manages context sharing between tasks. When a new task is spawned, the original task factory is called, then for each attached context, data is copied from the parent task to the child one. How copy is performed is specified in Context.copy_func().

If loop uses a custom task factory, this function must be called after setting it:

class CustomTask(asyncio.Task):
    pass

def custom_task_factory(loop, coro):
    return CustomTask(coro, loop=loop)

loop.set_task_factory(custom_task_factory)
wrap_task_factory(loop)

This function has no effect if the task factory is already context-aware.

aiocontext.unwrap_task_factory(loop)[source]

Restore the original task factory of loop.

This function cancels the effect of wrap_task_factory(). After calling it, the loop task factory is no longer context-aware. Context registration is lost.

This function has no effect if the task factory is not context-aware.

Contexts

class aiocontext.Context(copy_func=<class 'dict'>)[source]

Bases: collections.abc.MutableMapping

Create an empty, asynchronous execution context.

The context must be attached to an event loop. It behaves like a dictionnary:

>>> context = Context()
>>> context.attach(loop)
>>> context['key1'] = 'value'
>>> context['key1']
'value'
>>> context.get('key2', 'defaut')
'default'

Upon initialization, an optional argument copy_func can be passed to specify how context data are copied between tasks. Relevant values are:

copy_func

Copy function, called when a new task is spawned.

get_data(task=None)[source]

Return the dict of task data.

If task is omitted or None, return data of the task being currently executed. If no task is running, an EventLoopError is raised.

This method raises TaskContextError if no context data is stored in task. This usually indicates that the context task factory was not set in the event loop.

>>> context['key'] = 'value'
>>> context.get_data()
{'key': 'value'}
attach(loop)[source]

Attach the execution context to loop.

When new tasks are spawned by the loop, they will inherit context data from the parent task. The loop must use a context-aware task factory; if not, a TaskFactoryError is raised.

This method has no effect if the context is already attached to loop.

detach(loop)[source]

Detach the execution context from loop.

This method has no effect if the context is not attached to loop.

aiocontext.chainmap_copy(data)[source]

Context copy function based on collections.ChainMap.

context = Context(copy_func=chainmap_copy)

On nested copies, collections.ChainMap instances are flattened for efficiency purposes.

aiocontext.get_loop_contexts(loop)[source]

Return the list of contexts attached to loop.

>>> context1 = Context()
>>> context1.attach(loop)
>>> context2 = Context()
>>> context2.attach(loop)
>>> get_loop_contexts(loop)
[<Context object at 0x10>, <Context object at 0x20>]
>>> context2.detach(loop)
[<Context object at 0x10>]

Raises TaskFactoryError if the loop is not context-aware, i.e. the task factory was not set.

Exceptions

exception aiocontext.AioContextError[source]

Bases: Exception

Base class for aiocontext errors.

exception aiocontext.EventLoopError[source]

Bases: aiocontext.errors.AioContextError

Raised when the current running task cannot be determined.

This generally means that the context is manipulated with no event loop running, e.g. in synchronous code.

exception aiocontext.TaskFactoryError[source]

Bases: aiocontext.errors.AioContextError

Raised when no context-aware task factory was set for the current loop.

This generally means the following code was not executed:

wrap_task_factory(loop)
exception aiocontext.TaskContextError[source]

Bases: aiocontext.errors.AioContextError

Raised when no context data is stored in the current task.

This generally means the context is not registered in the current loop, i.e. the following code was not executed:

context.attach(loop)