diff --git a/ellar/di/exceptions.py b/ellar/di/exceptions.py index f77526c6..81d010c0 100644 --- a/ellar/di/exceptions.py +++ b/ellar/di/exceptions.py @@ -12,6 +12,10 @@ class DIImproperConfiguration(Exception): pass +class RequestScopeContextNotFound(Exception): + pass + + __all__ = [ "CallError", "CircularDependency", @@ -21,4 +25,5 @@ class DIImproperConfiguration(Exception): "UnknownProvider", "UnsatisfiedRequirement", "DIImproperConfiguration", + "RequestScopeContextNotFound", ] diff --git a/ellar/di/scopes.py b/ellar/di/scopes.py index a15672f6..567680ab 100644 --- a/ellar/di/scopes.py +++ b/ellar/di/scopes.py @@ -18,6 +18,7 @@ UnsatisfiedRequirement, ) +from .exceptions import RequestScopeContextNotFound from .providers import InstanceProvider, Provider from .types import T @@ -34,7 +35,10 @@ def get(self, key: t.Type[T], provider: Provider[T]) -> Provider[T]: scoped_context = self.get_context() if scoped_context is None: - raise UnsatisfiedRequirement(None, key) + raise RequestScopeContextNotFound( + "RequestScope is not available. Trying to access RequestScope outside request", + UnsatisfiedRequirement(None, key), + ) try: return scoped_context.context[key] except KeyError: diff --git a/ellar/testing/module.py b/ellar/testing/module.py index 083bd339..45bd837a 100644 --- a/ellar/testing/module.py +++ b/ellar/testing/module.py @@ -94,7 +94,19 @@ def get_test_client( ) def get(self, interface: t.Type[T]) -> T: - return self.create_application().injector.get(interface) # type: ignore[no-any-return] + try: + return t.cast(T, self.create_application().injector.get(interface)) + except Exception as ex: + # try to find module to which the interface belongs + module = self.create_application().injector.tree_manager.search_module_tree( + filter_item=lambda data: True, + find_predicate=lambda data: interface in data.exports + or interface in data.providers, + ) + if module: + return t.cast(T, module.value.get(interface)) + + raise ex class Test: diff --git a/requirements-tests.txt b/requirements-tests.txt index 17b11288..d18a37ed 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -13,6 +13,7 @@ pytest-asyncio pytest-cov >= 2.12.0,< 6.0.0 python-multipart >= 0.0.5 python-socketio +regex==2024.11.6 ruff ==0.6.3 types-dataclasses ==0.6.6 types-orjson ==3.6.2 diff --git a/tests/test_di/test_injector.py b/tests/test_di/test_injector.py index e38e9dbd..8d72bdda 100644 --- a/tests/test_di/test_injector.py +++ b/tests/test_di/test_injector.py @@ -10,6 +10,7 @@ request_scope, transient_scope, ) +from ellar.di.exceptions import RequestScopeContextNotFound from ellar.di.providers import ClassProvider, InstanceProvider from injector import Binder, Injector, UnsatisfiedRequirement @@ -119,7 +120,7 @@ async def test_request_service_context(): with pytest.raises(UnsatisfiedRequirement): injector.get(Foo) - with pytest.raises(UnsatisfiedRequirement): + with pytest.raises(RequestScopeContextNotFound): injector.get(Foo1) diff --git a/tests/test_di/test_provider_scopes.py b/tests/test_di/test_provider_scopes.py index 53859d37..dee79968 100644 --- a/tests/test_di/test_provider_scopes.py +++ b/tests/test_di/test_provider_scopes.py @@ -2,10 +2,10 @@ from ellar.core import HttpRequestConnectionContext from ellar.core.execution_context import HostContextFactory from ellar.di import EllarInjector, ProviderConfig, has_binding -from ellar.di.exceptions import DIImproperConfiguration +from ellar.di.exceptions import DIImproperConfiguration, RequestScopeContextNotFound from ellar.di.scopes import RequestScope, SingletonScope, TransientScope from ellar.utils.importer import get_class_import -from injector import UnsatisfiedRequirement, inject +from injector import inject from .examples import AnyContext, Foo, IContext, TransientRequestContext @@ -52,7 +52,7 @@ async def test_request_scope_instance(): # resolving RequestScope Providers outside RequestServiceProvider will behave like TransientScope - with pytest.raises(UnsatisfiedRequirement): + with pytest.raises(RequestScopeContextNotFound): assert injector.get(IContext) async with HttpRequestConnectionContext(