Skip to content

Commit 9c9283d

Browse files
add docs, small reference in resource
1 parent 36586a4 commit 9c9283d

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
.. _context-local-resource-provider:
2+
3+
Context Local Resource provider
4+
================================
5+
6+
.. meta::
7+
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Resource,Context Local,
8+
Context Variables,Singleton,Per-context
9+
:description: Context Local Resource provider provides a component with initialization and shutdown
10+
that is scoped to execution context using contextvars. This page demonstrates how to
11+
use context local resource provider.
12+
13+
.. currentmodule:: dependency_injector.providers
14+
15+
``ContextLocalResource`` inherits from :ref:`resource-provider` and uses the same initialization and shutdown logic
16+
as the standard ``Resource`` provider.
17+
It extends it with context-local storage using Python's ``contextvars`` module.
18+
This means that objects are context local singletons - the same context will
19+
receive the same instance, but different execution contexts will have their own separate instances.
20+
21+
This is particularly useful in asynchronous applications where you need per-request resource instances
22+
(such as database sessions) that are automatically cleaned up when the request context ends.
23+
Example:
24+
25+
.. literalinclude:: ../../examples/providers/context_local_resource.py
26+
:language: python
27+
:lines: 3-
28+
29+
30+
31+
.. disqus::
32+

docs/providers/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Providers module API docs - :py:mod:`dependency_injector.providers`
4646
dict
4747
configuration
4848
resource
49+
context_local_resource
4950
aggregate
5051
selector
5152
dependency

docs/providers/resource.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ Resource provider
2121
Resource providers help to initialize and configure logging, event loop, thread or process pool, etc.
2222

2323
Resource provider is similar to ``Singleton``. Resource initialization happens only once.
24+
If you need a context local singleton (where each execution context has its own instance),
25+
see :ref:`context-local-resource-provider`.
26+
2427
You can make injections and use provided instance the same way like you do with any other provider.
2528

2629
.. code-block:: python
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from uuid import uuid4
2+
3+
from fastapi import Depends, FastAPI
4+
5+
from dependency_injector import containers, providers
6+
from dependency_injector.wiring import Closing, Provide, inject
7+
8+
global_list = []
9+
10+
11+
class AsyncSessionLocal:
12+
def __init__(self):
13+
self.id = uuid4()
14+
15+
async def __aenter__(self):
16+
print("Entering session !")
17+
return self
18+
19+
async def __aexit__(self, exc_type, exc_val, exc_tb):
20+
print("Closing session !")
21+
22+
async def execute(self, user_input):
23+
return f"Executing {user_input} in session {self.id}"
24+
25+
26+
app = FastAPI()
27+
28+
29+
class Container(containers.DeclarativeContainer):
30+
db_session = providers.ContextLocalResource(AsyncSessionLocal)
31+
32+
33+
@app.get("/")
34+
@inject
35+
async def index(db: AsyncSessionLocal = Depends(Closing[Provide["db_session"]])):
36+
global global_list
37+
if db.id in global_list:
38+
raise Exception("The db session is already used") # never reaches here
39+
global_list.append(db.id)
40+
res = await db.execute("SELECT 1")
41+
return str(res)
42+
43+
44+
if __name__ == "__main__":
45+
import uvicorn
46+
47+
container = Container()
48+
container.wire(modules=["__main__"])
49+
uvicorn.run(app, host="localhost", port=8000)
50+
container.unwire()

0 commit comments

Comments
 (0)