Skip to content

Commit e6cc127

Browse files
committed
Add support for resource_type in Lifespans
1 parent bf2ddbc commit e6cc127

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

src/dependency_injector/ext/starlette.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import sys
2-
from typing import Any
2+
from typing import Any, Type
33

44
if sys.version_info >= (3, 11): # pragma: no cover
55
from typing import Self
66
else: # pragma: no cover
77
from typing_extensions import Self
88

99
from dependency_injector.containers import Container
10+
from dependency_injector.providers import Resource
1011

1112

1213
class Lifespan:
@@ -29,24 +30,32 @@ class Container(DeclarativeContainer):
2930
app = Factory(Starlette, lifespan=lifespan)
3031
3132
:param container: container instance
33+
:param resource_type: A :py:class:`~dependency_injector.resources.Resource`
34+
subclass. Limits the resources to be initialized and shutdown.
3235
"""
3336

3437
container: Container
38+
resource_type: Type[Resource[Any]]
3539

36-
def __init__(self, container: Container) -> None:
40+
def __init__(
41+
self,
42+
container: Container,
43+
resource_type: Type[Resource[Any]] = Resource,
44+
) -> None:
3745
self.container = container
46+
self.resource_type = resource_type
3847

3948
def __call__(self, app: Any) -> Self:
4049
return self
4150

4251
async def __aenter__(self) -> None:
43-
result = self.container.init_resources()
52+
result = self.container.init_resources(self.resource_type)
4453

4554
if result is not None:
4655
await result
4756

4857
async def __aexit__(self, *exc_info: Any) -> None:
49-
result = self.container.shutdown_resources()
58+
result = self.container.shutdown_resources(self.resource_type)
5059

5160
if result is not None:
5261
await result

tests/unit/ext/test_starlette.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import AsyncIterator, Iterator
1+
from typing import AsyncIterator, Iterator, TypeVar
22
from unittest.mock import ANY
33

44
from pytest import mark
@@ -7,6 +7,12 @@
77
from dependency_injector.ext.starlette import Lifespan
88
from dependency_injector.providers import Resource
99

10+
T = TypeVar("T")
11+
12+
13+
class XResource(Resource[T]):
14+
"""A test provider"""
15+
1016

1117
class TestLifespan:
1218
@mark.parametrize("sync", [False, True])
@@ -28,11 +34,15 @@ async def async_resource() -> AsyncIterator[None]:
2834
yield
2935
shutdown = True
3036

37+
def nope():
38+
assert False, "should not be called"
39+
3140
class Container(DeclarativeContainer):
32-
x = Resource(sync_resource if sync else async_resource)
41+
x = XResource(sync_resource if sync else async_resource)
42+
y = Resource(nope)
3343

3444
container = Container()
35-
lifespan = Lifespan(container)
45+
lifespan = Lifespan(container, resource_type=XResource)
3646

3747
async with lifespan(ANY) as scope:
3848
assert scope is None

0 commit comments

Comments
 (0)