New implementation of scopes #186

This commit is contained in:
2025-09-24 21:27:28 +02:00
parent 4c8cd988cc
commit 287f5e3149
12 changed files with 92 additions and 25 deletions

View File

@@ -0,0 +1,13 @@
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)

View File

@@ -114,12 +114,15 @@ class String:
characters = []
if letters:
characters.append(string.ascii_letters)
characters.extend(string.ascii_letters)
if digits:
characters.append(string.digits)
characters.extend(string.digits)
if special_characters:
characters.append(string.punctuation)
characters.extend(string.punctuation)
return "".join(random.choice(characters) for _ in range(length)) if characters else ""
x = "".join(random.choice(list(characters)) for _ in range(length)) if characters else ""
if len(x) != length:
raise Exception("No characters selected to generate random string")
return x

View File

@@ -1,4 +1,6 @@
import copy
import typing
from contextlib import contextmanager
from inspect import signature, Parameter, Signature
from typing import Optional, Type
@@ -6,6 +8,7 @@ from cpl.core.configuration import Configuration
from cpl.core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl.core.environment import Environment
from cpl.core.typing import T, R, Source
from cpl.dependency import use_provider
from cpl.dependency.service_descriptor import ServiceDescriptor
from cpl.dependency.service_lifetime import ServiceLifetimeEnum
@@ -132,6 +135,19 @@ class ServiceProvider:
return service_type(*params, *args, **kwargs)
@contextmanager
def create_scope(self):
scoped_descriptors = []
for d in self._service_descriptors:
if d.lifetime == ServiceLifetimeEnum.singleton:
scoped_descriptors.append(d)
else:
scoped_descriptors.append(copy.deepcopy(d))
scoped_provider = ServiceProvider(scoped_descriptors)
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)
@@ -143,7 +159,7 @@ class ServiceProvider:
implementation = self._build_service(service_type, *args, **kwargs)
if (
result.lifetime == ServiceLifetimeEnum.singleton
result.lifetime in (ServiceLifetimeEnum.singleton, ServiceLifetimeEnum.scoped)
):
result.implementation = implementation