From 1b9a83da82840ec80154a6c89af7a9393fe7a31d Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Sat, 17 Oct 2026 12:56:49 +0300 Subject: [PATCH] fix: namespace the context keys and read the request container as a local Closes #74 Closes #75 --- modern_di_faststream/main.py | 6 +++--- tests/test_faststream_di.py | 24 +++++++++++++++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/modern_di_faststream/main.py b/modern_di_faststream/main.py index c523410..f6781dd 100644 --- a/modern_di_faststream/main.py +++ b/modern_di_faststream/main.py @@ -16,8 +16,8 @@ # Keys under which the containers live in FastStream's ``ContextRepo``. Each is # written in one place and read in another; naming them keeps writer and reader # in provable agreement instead of relying on two matching string literals. -_ROOT_CONTAINER_KEY = "di_container" -_REQUEST_CONTAINER_KEY = "request_container" +_ROOT_CONTAINER_KEY = "modern_di_root_container" +_REQUEST_CONTAINER_KEY = "modern_di_request_container" _MISSING_REQUEST_CONTAINER = ( "No request container for this message, so the DI middleware did not run for it. " @@ -99,7 +99,7 @@ class Dependency(typing.Generic[T_co]): marker: integrations.Marker[T_co] async def __call__(self, context: faststream.ContextRepo) -> T_co: - request_container: Container | None = context.get(_REQUEST_CONTAINER_KEY) + request_container: Container | None = context.get_local(_REQUEST_CONTAINER_KEY) if request_container is None: raise RuntimeError(_MISSING_REQUEST_CONTAINER) return self.marker.resolve(request_container) diff --git a/tests/test_faststream_di.py b/tests/test_faststream_di.py index 95d370c..0778645 100644 --- a/tests/test_faststream_di.py +++ b/tests/test_faststream_di.py @@ -87,6 +87,28 @@ def test_fetch_di_container(app: faststream.FastStream) -> None: assert isinstance(di_container, Container) +def test_fetch_di_container_ignores_a_user_global_named_di_container() -> None: + app_ = faststream.FastStream(NatsBroker()) + container = modern_di_faststream.setup_di(app_, container=Container(groups=[Dependencies])) + app_.context.set_global("di_container", "user value") + + assert modern_di_faststream.fetch_di_container(app_) is container + + +async def test_from_di_ignores_a_user_global_named_request_container() -> None: + broker = NatsBroker() + app_ = faststream.FastStream(broker) + modern_di_faststream.setup_di(app_, container=Container(groups=[Dependencies])) + broker.context.set_global("request_container", "user value") + resolved: list[SimpleCreator] = [] + _subscribe_resolving(broker, TEST_SUBJECT, resolved) + + async with TestNatsBroker(broker) as br, TestApp(app_): + await br.publish(None, TEST_SUBJECT) + + assert [type(instance) for instance in resolved] == [SimpleCreator] + + def _app_with_two_brokers(*, add_second_after_setup: bool) -> tuple[faststream.FastStream, NatsBroker, NatsBroker]: first, second = NatsBroker(), NatsBroker() app_ = faststream.FastStream(first) if add_second_after_setup else faststream.FastStream(first, second) @@ -151,7 +173,7 @@ async def subscriber(instance: typing.Annotated[SimpleCreator, FromDI(Dependenci async def test_from_di_without_setup_di_names_the_missing_step() -> None: """INVARIANT: ``FromDI`` on a message the DI middleware never saw fails by naming ``setup_di``. - Broken by handing ``ContextRepo.get``'s ``None`` straight to the marker, which surfaces as + Broken by handing ``ContextRepo.get_local``'s ``None`` straight to the marker, which surfaces as modern-di's ``AttributeError: 'NoneType' object has no attribute 'resolve_dependency'`` and points at nothing in this package. """