From a6f97e92f09901dbf5a2dd69a2fcaec6565b5383 Mon Sep 17 00:00:00 2001 From: Ezeudoh Tochukwu Date: Thu, 3 Apr 2025 09:53:12 +0100 Subject: [PATCH 1/2] fixed regex error and testModule not finding internal services --- ellar/di/scopes.py | 5 ++++- ellar/testing/module.py | 8 ++++++++ requirements-tests.txt | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ellar/di/scopes.py b/ellar/di/scopes.py index a15672f6..bd83ea58 100644 --- a/ellar/di/scopes.py +++ b/ellar/di/scopes.py @@ -34,7 +34,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 Exception( + "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..76e8805e 100644 --- a/ellar/testing/module.py +++ b/ellar/testing/module.py @@ -94,6 +94,14 @@ def get_test_client( ) def get(self, interface: t.Type[T]) -> T: + # 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)) return self.create_application().injector.get(interface) # type: ignore[no-any-return] 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 From 6fdf325a2c679d1fb02ee43412900cffea0ef4df Mon Sep 17 00:00:00 2001 From: Ezeudoh Tochukwu Date: Thu, 3 Apr 2025 10:02:07 +0100 Subject: [PATCH 2/2] fixed failing tests --- ellar/di/exceptions.py | 5 +++++ ellar/di/scopes.py | 3 ++- ellar/testing/module.py | 22 +++++++++++++--------- tests/test_di/test_injector.py | 3 ++- tests/test_di/test_provider_scopes.py | 6 +++--- 5 files changed, 25 insertions(+), 14 deletions(-) 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 bd83ea58..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,7 @@ def get(self, key: t.Type[T], provider: Provider[T]) -> Provider[T]: scoped_context = self.get_context() if scoped_context is None: - raise Exception( + raise RequestScopeContextNotFound( "RequestScope is not available. Trying to access RequestScope outside request", UnsatisfiedRequirement(None, key), ) diff --git a/ellar/testing/module.py b/ellar/testing/module.py index 76e8805e..45bd837a 100644 --- a/ellar/testing/module.py +++ b/ellar/testing/module.py @@ -94,15 +94,19 @@ def get_test_client( ) def get(self, interface: t.Type[T]) -> T: - # 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)) - 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/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(