Ambient context and testing#
The unscoped namespace and the isolation helper.
context#
- nodrill.context#
An ambient attribute namespace, isolated per thread and per asyncio task.
Set an attribute anywhere, read it anywhere below. Backed by its own
ContextVar, so a new thread starts empty and a new task inherits a snapshot then diverges.context.request_id = "r-42" ... log(f"[{context.request_id}]")
Writes are unscoped, so nothing restores them at the end of a block, and a value set in a pooled worker thread survives into that thread’s next job. Use
provider()for anything scoped.The object deliberately exposes no methods, only dunders, so no attribute name your application chooses can collide with the API. These are the supported operations.
context.nameRead. Raises
AttributeErrorlisting the names currently set if it was never assigned.context.name = valueWrite.
del context.nameDelete. Raises
AttributeErrorif the name is not set."name" in contextMembership test, without raising.
iter(context),len(context)The names currently set, in sorted order, and how many there are. Dunders cannot collide with an application’s attribute names, which is why these are safe to have and
keys()is not.
isolate#
- nodrill.isolate()#
Run a block against fresh context state, restoring the outer state on exit. Returns a context manager.
Inside the block no providers are active and the ambient namespace is empty. Registrations made with
set_default()inside the block are rolled back on exit. Registrations made outside stay visible inside, since they are configuration rather than state. Refs built withref()inside the block are rolled back the same way, so a path one test made up on purpose is not a path the next test’sresolve_refs()has to import.Intended for test fixtures.
conftest.py#import nodrill import pytest @pytest.fixture(autouse=True) def _clean_context(): with nodrill.isolate(): yield