Context managers
This page describes how to work with Rodi and context managers.
How Rodi handles context managers
When a class implements the context manager protocol (__enter__, __exit__),
Rodi instantiates the class but does not enter nor exit the instance
automatically.
|  | from rodi import Container
class A:
    def __init__(self) -> None:
        print("A created")
        self.initialized = False
        self.disposed = False
    def __enter__(self) -> "A":
        print("A initialized")
        self.initialized = True
        return self
    def __exit__(self, exc_type, exc_val, exc_tb) -> None:
        self.disposed = True
        print("A destroyed")
class B:
    def __init__(self, dependency: A) -> None:
        self.dependency = dependency
    def do_work(self):
        with self.dependency:
            print("Do work")
container = Container()
container.register(A)
container.register(B)
b = container.resolve(B)
# b.dependency is instantiated and provided as is, it is not entered
# automatically
assert b.dependency.initialized is False
assert b.dependency.disposed is False
b.do_work()
assert b.dependency.initialized is True
assert b.dependency.disposed is True
 | 
Rodi does not enter and exit contexts.
There is no way to unambiguously know the intentions of the developer:
should a context be entered automatically and disposed automatically?
 
Async context managers
As described above for context managers, Rodi does not handle async context
managers in any special way either.
|  | import asyncio
from rodi import Container
class A:
    def __init__(self) -> None:
        print("A created")
        self.initialized = False
        self.disposed = False
    async def __aenter__(self) -> "A":
        print("A initialized")
        self.initialized = True
        return self
    async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
        self.disposed = True
        print("A destroyed")
class B:
    def __init__(self, dependency: A) -> None:
        self.dependency = dependency
    async def do_work(self):
        async with self.dependency:
            print("Do work")
container = Container()
container.register(A)
container.register(B)
b = container.resolve(B)
assert b.dependency.initialized is False
assert b.dependency.disposed is False
asyncio.run(b.do_work())
assert b.dependency.initialized is True
assert b.dependency.disposed is True
 | 
The next page describes support for Union types in Rodi.
Last modified on: 2025-04-12 11:00:06