API scoped requests #186
Some checks failed
Test before pr merge / test-lint (pull_request) Failing after 6s
Build on push / prepare (push) Successful in 9s
Build on push / query (push) Successful in 18s
Build on push / core (push) Successful in 21s
Build on push / dependency (push) Successful in 14s
Build on push / api (push) Has been cancelled
Build on push / auth (push) Has been cancelled
Build on push / application (push) Has been cancelled
Build on push / database (push) Has been cancelled
Build on push / mail (push) Has been cancelled
Build on push / translation (push) Has been cancelled
Some checks failed
Test before pr merge / test-lint (pull_request) Failing after 6s
Build on push / prepare (push) Successful in 9s
Build on push / query (push) Successful in 18s
Build on push / core (push) Successful in 21s
Build on push / dependency (push) Successful in 14s
Build on push / api (push) Has been cancelled
Build on push / auth (push) Has been cancelled
Build on push / application (push) Has been cancelled
Build on push / database (push) Has been cancelled
Build on push / mail (push) Has been cancelled
Build on push / translation (push) Has been cancelled
This commit is contained in:
@@ -30,7 +30,6 @@ from cpl.core.configuration import Configuration
|
||||
from cpl.dependency.inject import inject
|
||||
from cpl.dependency.service_provider import ServiceProvider
|
||||
|
||||
|
||||
PolicyInput = Union[dict[str, PolicyResolver], Policy]
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
from cpl.api.abc import ASGIMiddleware
|
||||
from cpl.dependency.service_provider import ServiceProvider
|
||||
|
||||
|
||||
class ScopeMiddleware(ASGIMiddleware):
|
||||
def __init__(self, app, provider: ServiceProvider):
|
||||
ASGIMiddleware.__init__(self, app)
|
||||
self._app = app
|
||||
self._provider = provider
|
||||
|
||||
async def __call__(self, scope, receive, send):
|
||||
with self._provider.create_scope():
|
||||
await self._app(scope, receive, send)
|
||||
@@ -9,15 +9,18 @@ from starlette.types import Scope, Receive, Send
|
||||
from cpl.api.abc.asgi_middleware_abc import ASGIMiddleware
|
||||
from cpl.api.logger import APILogger
|
||||
from cpl.api.typing import TRequest
|
||||
from cpl.dependency.inject import inject
|
||||
from cpl.dependency.service_provider import ServiceProvider
|
||||
|
||||
_request_context: ContextVar[Union[TRequest, None]] = ContextVar("request", default=None)
|
||||
|
||||
|
||||
class RequestMiddleware(ASGIMiddleware):
|
||||
|
||||
def __init__(self, app, logger: APILogger):
|
||||
def __init__(self, app, provider: ServiceProvider, logger: APILogger):
|
||||
ASGIMiddleware.__init__(self, app)
|
||||
|
||||
self._provider = provider
|
||||
self._logger = logger
|
||||
|
||||
self._ctx_token = None
|
||||
@@ -27,7 +30,8 @@ class RequestMiddleware(ASGIMiddleware):
|
||||
await self.set_request_data(request)
|
||||
|
||||
try:
|
||||
await self._app(scope, receive, send)
|
||||
with self._provider.create_scope():
|
||||
inject(await self._app(scope, receive, send))
|
||||
finally:
|
||||
await self.clean_request_data()
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ def inject(f=None):
|
||||
return functools.partial(inject)
|
||||
|
||||
if iscoroutinefunction(f):
|
||||
|
||||
@functools.wraps(f)
|
||||
async def async_inner(*args, **kwargs):
|
||||
from cpl.dependency.service_provider import ServiceProvider
|
||||
|
||||
@@ -14,23 +14,9 @@ from cpl.dependency.service_lifetime import ServiceLifetimeEnum
|
||||
|
||||
|
||||
class ServiceProvider:
|
||||
r"""Provider for the services
|
||||
|
||||
Parameter
|
||||
---------
|
||||
service_descriptors: list[:class:`cpl.dependency.service_descriptor.ServiceDescriptor`]
|
||||
Descriptor of the service
|
||||
config: :class:`cpl.core.configuration.configuration_abc.ConfigurationABC`
|
||||
CPL Configuration
|
||||
db_context: Optional[:class:`cpl.database.context.database_context_abc.DatabaseContextABC`]
|
||||
Database representation
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
service_descriptors: list[ServiceDescriptor],
|
||||
):
|
||||
def __init__(self, service_descriptors: list[ServiceDescriptor], is_scope: bool = False):
|
||||
self._service_descriptors: list[ServiceDescriptor] = service_descriptors
|
||||
self._is_scope = is_scope
|
||||
|
||||
def _find_service(self, service_type: type) -> Optional[ServiceDescriptor]:
|
||||
origin_type = typing.get_origin(service_type) or service_type
|
||||
@@ -57,13 +43,13 @@ class ServiceProvider:
|
||||
def _get_service(self, parameter: Parameter, origin_service_type: type = None) -> Optional[object]:
|
||||
for descriptor in self._service_descriptors:
|
||||
if descriptor.service_type == parameter.annotation or issubclass(
|
||||
descriptor.service_type, parameter.annotation
|
||||
descriptor.service_type, parameter.annotation
|
||||
):
|
||||
if descriptor.implementation is not None:
|
||||
return descriptor.implementation
|
||||
|
||||
implementation = self._build_service(descriptor.service_type, origin_service_type=origin_service_type)
|
||||
if descriptor.lifetime == ServiceLifetimeEnum.singleton:
|
||||
if descriptor.lifetime in (ServiceLifetimeEnum.singleton, ServiceLifetimeEnum.scoped):
|
||||
descriptor.implementation = implementation
|
||||
|
||||
return implementation
|
||||
@@ -81,7 +67,7 @@ class ServiceProvider:
|
||||
implementation = self._build_service(
|
||||
descriptor.service_type, origin_service_type=service_type, **kwargs
|
||||
)
|
||||
if descriptor.lifetime == ServiceLifetimeEnum.singleton:
|
||||
if descriptor.lifetime in (ServiceLifetimeEnum.singleton, ServiceLifetimeEnum.scoped):
|
||||
descriptor.implementation = implementation
|
||||
|
||||
implementations.append(implementation)
|
||||
@@ -127,12 +113,10 @@ class ServiceProvider:
|
||||
service_type = type(descriptor.implementation)
|
||||
else:
|
||||
service_type = descriptor.service_type
|
||||
|
||||
break
|
||||
|
||||
sig = signature(service_type.__init__)
|
||||
params = self._build_by_signature(sig, origin_service_type)
|
||||
|
||||
return service_type(*params, *args, **kwargs)
|
||||
|
||||
@contextmanager
|
||||
@@ -144,13 +128,12 @@ class ServiceProvider:
|
||||
else:
|
||||
scoped_descriptors.append(copy.deepcopy(d))
|
||||
|
||||
scoped_provider = ServiceProvider(scoped_descriptors)
|
||||
scoped_provider = ServiceProvider(scoped_descriptors, is_scope=True)
|
||||
with use_provider(scoped_provider):
|
||||
yield scoped_provider
|
||||
|
||||
def get_service(self, service_type: T, *args, **kwargs) -> Optional[R]:
|
||||
result = self._find_service(service_type)
|
||||
|
||||
if result is None:
|
||||
return None
|
||||
|
||||
@@ -158,9 +141,10 @@ class ServiceProvider:
|
||||
return result.implementation
|
||||
|
||||
implementation = self._build_service(service_type, *args, **kwargs)
|
||||
if (
|
||||
result.lifetime in (ServiceLifetimeEnum.singleton, ServiceLifetimeEnum.scoped)
|
||||
):
|
||||
|
||||
if result.lifetime == ServiceLifetimeEnum.singleton:
|
||||
result.implementation = implementation
|
||||
elif result.lifetime == ServiceLifetimeEnum.scoped and self._is_scope:
|
||||
result.implementation = implementation
|
||||
|
||||
return implementation
|
||||
@@ -173,12 +157,9 @@ class ServiceProvider:
|
||||
|
||||
def get_services(self, service_type: T, *args, **kwargs) -> list[Optional[R]]:
|
||||
implementations = []
|
||||
|
||||
if typing.get_origin(service_type) == list:
|
||||
raise Exception(f"Invalid type {service_type}! Expected single type not list of type")
|
||||
|
||||
implementations.extend(self._get_services(service_type))
|
||||
|
||||
return implementations
|
||||
|
||||
def get_service_types(self, service_type: Type[T]) -> list[Type[T]]:
|
||||
|
||||
Reference in New Issue
Block a user