Scope¶
Scope ¶
Bases: Enum
How long a provider's value lives and when it is rebuilt.
Attributes:
| Name | Type | Description |
|---|---|---|
SINGLETON |
Built once, on first resolution, and cached on the
|
|
SCOPED |
Built once per active scope
( |
|
TRANSIENT |
Built fresh on every resolution and never cached. Generator and context-manager providers cannot be transient. |
ScopeFrame ¶
The per-scope store yielded by FrozenContainer.scope().
Holds the scope's cached instances and pending teardowns, and chains to its
parent so nested scopes inherit outer instances. Scope-setup code — ASGI
middleware, a CLI entry point — uses provide() to seed values that
Container.scope_value() then exposes as providers.
A frame is safe to use from several threads and several tasks at once. The root frame caches singletons and is shared by every caller of the container, so its bookkeeping is guarded by a mutex and construction of a given key is single-flighted.
provide ¶
provide(
key: object, value: object, *, tag: str | None = None
) -> None
Place value into this frame under key.
The counterpart of Container.scope_value(): whoever opens the scope
supplies the value, and providers declared with scope_value read it
back. Overwrites any value already stored under key in this frame.
Seed before anything resolves: a scope_value key is cached in the
scope on first use, so a later call here does not replace what a
parameter already read.
Example
>>> from depin import Container
>>> class Request: ...
>>> di = Container().scope_value(Request).freeze()
>>> with di.scope() as frame:
... frame.provide(Request, Request())
... isinstance(di[Request], Request)
True
get ¶
get(key: object) -> object
Return the value stored under key here or in an ancestor frame.
Raises:
| Type | Description |
|---|---|
KeyError
|
No frame in the chain holds |
lookup ¶
lookup(key: object) -> object
Return the value for key, or MISSING when no frame holds it.
Unlike get() this reports absence without raising, so a caller can
distinguish "not cached" from "cached as None" in one traversal.
drain_sync ¶
drain_sync() -> None
Run every pending teardown, newest first, without an event loop.
Raises:
| Type | Description |
|---|---|
ExceptionGroup
|
One or more teardowns failed. Every failure is
reported; none is allowed to hide another. Protocol violations,
including an async teardown in this synchronous drain, appear as
|
drain_async
async
¶
drain_async() -> None
Run every pending teardown, newest first, inside an event loop.
Raises:
| Type | Description |
|---|---|
ExceptionGroup
|
One or more teardowns failed. |
drain_async_errors
async
¶
drain_async_errors() -> tuple[Exception, ...]
Drain pending teardowns and return every failure without grouping it.
drop_sync ¶
drop_sync() -> None
Drain every pending teardown, newest first, and drop the cache, without an event loop.
The counterpart to drain_sync(): where that leaves the cache
populated with whatever it just drained, this drops it too, so a key
resolved afterwards is rebuilt rather than handed the drained value.
Do not call this while another thread or task may be resolving through
this frame: the cache is dropped without coordinating with an in-flight
construction, so a resolution racing with the drop can be handed a
value whose teardown already ran. FrozenContainer.reset() is this
operation on the root frame and carries the same hazard.
Raises:
| Type | Description |
|---|---|
ExceptionGroup
|
One or more teardowns failed. Every failure is
reported, and the cache is dropped either way. Protocol
violations, including an async teardown in this synchronous
drain, appear as |
drop_async
async
¶
drop_async() -> None
Drain every pending teardown and drop the cache, inside an event loop.
The counterpart to drop_sync(), for a frame holding an async
provider's teardown, and carrying the same hazard: do not call it while
another thread or task may be resolving through this frame, because the
cache is dropped without coordinating with an in-flight construction.
Raises:
| Type | Description |
|---|---|
ExceptionGroup
|
One or more teardowns failed. Every failure is reported, and the cache is dropped either way. |
claim_cached ¶
claim_cached(
key: object,
provided_identity: tuple[object, str | None]
| None = None,
*,
asynchronous: bool = False,
) -> tuple[object, _Flight | _Leader | None]
Atomically return a cached value or claim/join its construction flight.
publish ¶
publish(
key: object,
leader: object,
value: object,
*,
signal: bool = False,
) -> _Flight | None
Cache a leader's value and return any followers after unlocking.
abort ¶
abort(
key: object, leader: object, *, signal: bool = False
) -> _Flight | None
Remove a failed leader's flight and return any followers after unlocking.
start_flight ¶
start_flight(key: object) -> tuple[_Flight | _Leader, bool]
Join a per-key construction flight, or start one when none is active.
finish_flight ¶
finish_flight(
key: object, flight: _Flight | _Leader
) -> None
Finish flight and remove it only when it remains active for key.