Updated docs
This commit is contained in:
@@ -1,21 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
cpl-core sh-edraft Common Python library
|
||||
cpl-core CPL core
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Common Python library
|
||||
CPL core package
|
||||
|
||||
:copyright: (c) 2020 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'cpl_core.dependency_injection'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
|
||||
__version__ = '2022.12.1'
|
||||
__title__ = "cpl_core.dependency_injection"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
|
||||
__version__ = "2023.2.0"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -30,5 +30,5 @@ from .service_lifetime_enum import ServiceLifetimeEnum
|
||||
from .service_provider import ServiceProvider
|
||||
from .service_provider_abc import ServiceProviderABC
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='2022', minor='12', micro='1')
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="2023", minor="2", micro="0")
|
||||
|
@@ -1,11 +1,9 @@
|
||||
|
||||
from cpl_core.console.console import Console
|
||||
from cpl_core.dependency_injection.scope_abc import ScopeABC
|
||||
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
|
||||
|
||||
|
||||
class Scope(ScopeABC):
|
||||
|
||||
def __init__(self, service_provider: ServiceProviderABC):
|
||||
self._service_provider = service_provider
|
||||
self._service_provider.set_scope(self)
|
||||
@@ -20,6 +18,6 @@ class Scope(ScopeABC):
|
||||
@property
|
||||
def service_provider(self) -> ServiceProviderABC:
|
||||
return self._service_provider
|
||||
|
||||
|
||||
def dispose(self):
|
||||
self._service_provider = None
|
||||
|
@@ -1,24 +1,23 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class ScopeABC(ABC):
|
||||
r"""ABC for the class :class:`cpl_core.dependency_injection.scope.Scope`"""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def service_provider(self):
|
||||
r"""Returns to service provider of scope
|
||||
|
||||
Returns
|
||||
-------
|
||||
Returns:
|
||||
Object of type :class:`cpl_core.dependency_injection.service_provider_abc.ServiceProviderABC`
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@abstractmethod
|
||||
def dispose(self):
|
||||
r"""Sets service_provider to None
|
||||
"""
|
||||
pass
|
||||
r"""Sets service_provider to None"""
|
||||
pass
|
||||
|
@@ -5,15 +5,14 @@ from cpl_core.dependency_injection.service_provider_abc import ServiceProviderAB
|
||||
|
||||
class ScopeBuilder:
|
||||
r"""Class to build :class:`cpl_core.dependency_injection.scope.Scope`"""
|
||||
|
||||
|
||||
def __init__(self, service_provider: ServiceProviderABC) -> None:
|
||||
self._service_provider = service_provider
|
||||
|
||||
|
||||
def build(self) -> ScopeABC:
|
||||
r"""Returns scope
|
||||
|
||||
Returns
|
||||
-------
|
||||
Returns:
|
||||
Object of type :class:`cpl_core.dependency_injection.scope.Scope`
|
||||
"""
|
||||
return Scope(self._service_provider)
|
||||
|
@@ -35,7 +35,7 @@ class ServiceCollection(ServiceCollectionABC):
|
||||
if not isinstance(service, type):
|
||||
service_type = type(service)
|
||||
|
||||
raise Exception(f'Service of type {service_type} already exists')
|
||||
raise Exception(f"Service of type {service_type} already exists")
|
||||
|
||||
self._service_descriptors.append(ServiceDescriptor(service, lifetime, base_type))
|
||||
|
||||
|
@@ -19,8 +19,7 @@ class ServiceCollectionABC(ABC):
|
||||
def add_db_context(self, db_context_type: Type[DatabaseContextABC], db_settings: DatabaseSettings):
|
||||
r"""Adds database context
|
||||
|
||||
Parameter
|
||||
---------
|
||||
Parameter:
|
||||
db_context: Type[:class:`cpl_core.database.context.database_context_abc.DatabaseContextABC`]
|
||||
Database context
|
||||
"""
|
||||
@@ -38,62 +37,56 @@ class ServiceCollectionABC(ABC):
|
||||
|
||||
def add_discord(self):
|
||||
r"""Adds the CPL discord"""
|
||||
raise NotImplementedError('You should install and use the cpl-discord package')
|
||||
raise NotImplementedError("You should install and use the cpl-discord package")
|
||||
pass
|
||||
|
||||
def add_translation(self):
|
||||
r"""Adds the CPL translation"""
|
||||
raise NotImplementedError('You should install and use the cpl-translation package')
|
||||
raise NotImplementedError("You should install and use the cpl-translation package")
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def add_transient(self, service_type: T, service: T = None) -> 'ServiceCollectionABC':
|
||||
def add_transient(self, service_type: T, service: T = None) -> "ServiceCollectionABC":
|
||||
r"""Adds a service with transient lifetime
|
||||
|
||||
Parameter
|
||||
---------
|
||||
Parameter:
|
||||
service_type: :class:`Type`
|
||||
Type of the service
|
||||
service: :class:`Callable`
|
||||
Object of the service
|
||||
|
||||
Returns
|
||||
------
|
||||
self: :class:`cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC
|
||||
Returns:
|
||||
self: :class:`cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC`
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def add_scoped(self, service_type: T, service: T = None) -> 'ServiceCollectionABC':
|
||||
def add_scoped(self, service_type: T, service: T = None) -> "ServiceCollectionABC":
|
||||
r"""Adds a service with scoped lifetime
|
||||
|
||||
Parameter
|
||||
---------
|
||||
Parameter:
|
||||
service_type: :class:`Type`
|
||||
Type of the service
|
||||
service: :class:`Callable`
|
||||
Object of the service
|
||||
|
||||
Returns
|
||||
------
|
||||
self: :class:`cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC
|
||||
Returns:
|
||||
self: :class:`cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC`
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def add_singleton(self, service_type: T, service: T = None) -> 'ServiceCollectionABC':
|
||||
def add_singleton(self, service_type: T, service: T = None) -> "ServiceCollectionABC":
|
||||
r"""Adds a service with singleton lifetime
|
||||
|
||||
Parameter
|
||||
---------
|
||||
Parameter:
|
||||
service_type: :class:`Type`
|
||||
Type of the service
|
||||
service: :class:`Callable`
|
||||
Object of the service
|
||||
|
||||
Returns
|
||||
------
|
||||
self: :class:`cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC
|
||||
Returns:
|
||||
self: :class:`cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC`
|
||||
"""
|
||||
pass
|
||||
|
||||
@@ -101,8 +94,7 @@ class ServiceCollectionABC(ABC):
|
||||
def build_service_provider(self) -> ServiceProviderABC:
|
||||
r"""Creates instance of the service provider
|
||||
|
||||
Returns
|
||||
-------
|
||||
Returns:
|
||||
Object of type :class:`cpl_core.dependency_injection.service_provider_abc.ServiceProviderABC`
|
||||
"""
|
||||
pass
|
||||
|
@@ -7,8 +7,7 @@ from cpl_core.dependency_injection.service_lifetime_enum import ServiceLifetimeE
|
||||
class ServiceDescriptor:
|
||||
r"""Descriptor of a service
|
||||
|
||||
Parameter
|
||||
---------
|
||||
Parameter:
|
||||
implementation: Union[:class:`type`, Optional[:class:`object`]]
|
||||
Object or type of service
|
||||
lifetime: :class:`cpl_core.dependency_injection.service_lifetime_enum.ServiceLifetimeEnum`
|
||||
@@ -16,7 +15,6 @@ class ServiceDescriptor:
|
||||
"""
|
||||
|
||||
def __init__(self, implementation: Union[type, Optional[object]], lifetime: ServiceLifetimeEnum, base_type=None):
|
||||
|
||||
self._service_type = implementation
|
||||
self._implementation = implementation
|
||||
self._lifetime = lifetime
|
||||
|
@@ -2,7 +2,6 @@ from enum import Enum
|
||||
|
||||
|
||||
class ServiceLifetimeEnum(Enum):
|
||||
|
||||
singleton = 0
|
||||
scoped = 1
|
||||
transient = 2
|
||||
|
@@ -18,8 +18,7 @@ from cpl_core.type import T
|
||||
class ServiceProvider(ServiceProviderABC):
|
||||
r"""Provider for the services
|
||||
|
||||
Parameter
|
||||
---------
|
||||
Parameter:
|
||||
service_descriptors: list[:class:`cpl_core.dependency_injection.service_descriptor.ServiceDescriptor`]
|
||||
Descriptor of the service
|
||||
config: :class:`cpl_core.configuration.configuration_abc.ConfigurationABC`
|
||||
@@ -28,7 +27,12 @@ class ServiceProvider(ServiceProviderABC):
|
||||
Database representation
|
||||
"""
|
||||
|
||||
def __init__(self, service_descriptors: list[ServiceDescriptor], config: ConfigurationABC, db_context: Optional[DatabaseContextABC]):
|
||||
def __init__(
|
||||
self,
|
||||
service_descriptors: list[ServiceDescriptor],
|
||||
config: ConfigurationABC,
|
||||
db_context: Optional[DatabaseContextABC],
|
||||
):
|
||||
ServiceProviderABC.__init__(self)
|
||||
|
||||
self._service_descriptors: list[ServiceDescriptor] = service_descriptors
|
||||
@@ -45,7 +49,9 @@ class ServiceProvider(ServiceProviderABC):
|
||||
|
||||
def _get_service(self, parameter: Parameter) -> Optional[object]:
|
||||
for descriptor in self._service_descriptors:
|
||||
if descriptor.service_type == parameter.annotation or issubclass(descriptor.service_type, parameter.annotation):
|
||||
if descriptor.service_type == parameter.annotation or issubclass(
|
||||
descriptor.service_type, parameter.annotation
|
||||
):
|
||||
if descriptor.implementation is not None:
|
||||
return descriptor.implementation
|
||||
|
||||
@@ -77,8 +83,7 @@ class ServiceProvider(ServiceProviderABC):
|
||||
params = []
|
||||
for param in sig.parameters.items():
|
||||
parameter = param[1]
|
||||
if parameter.name != 'self' and parameter.annotation != Parameter.empty:
|
||||
|
||||
if parameter.name != "self" and parameter.annotation != Parameter.empty:
|
||||
if typing.get_origin(parameter.annotation) == list:
|
||||
params.append(self._get_services(typing.get_args(parameter.annotation)[0]))
|
||||
|
||||
@@ -121,7 +126,9 @@ class ServiceProvider(ServiceProviderABC):
|
||||
self._scope = scope
|
||||
|
||||
def create_scope(self) -> ScopeABC:
|
||||
sb = ScopeBuilder(ServiceProvider(copy.deepcopy(self._service_descriptors), self._configuration, self._database_context))
|
||||
sb = ScopeBuilder(
|
||||
ServiceProvider(copy.deepcopy(self._service_descriptors), self._configuration, self._database_context)
|
||||
)
|
||||
return sb.build()
|
||||
|
||||
def get_service(self, service_type: T) -> Optional[T]:
|
||||
@@ -134,7 +141,11 @@ class ServiceProvider(ServiceProviderABC):
|
||||
return result.implementation
|
||||
|
||||
implementation = self.build_service(service_type)
|
||||
if result.lifetime == ServiceLifetimeEnum.singleton or result.lifetime == ServiceLifetimeEnum.scoped and self._scope is not None:
|
||||
if (
|
||||
result.lifetime == ServiceLifetimeEnum.singleton
|
||||
or result.lifetime == ServiceLifetimeEnum.scoped
|
||||
and self._scope is not None
|
||||
):
|
||||
result.implementation = implementation
|
||||
|
||||
return implementation
|
||||
@@ -143,7 +154,7 @@ class ServiceProvider(ServiceProviderABC):
|
||||
implementations = []
|
||||
|
||||
if typing.get_origin(service_type) != list:
|
||||
raise Exception(f'Invalid type {service_type}! Expected list of type')
|
||||
raise Exception(f"Invalid type {service_type}! Expected list of type")
|
||||
|
||||
implementations.extend(self._get_services(typing.get_args(service_type)[0]))
|
||||
|
||||
|
@@ -10,29 +10,29 @@ from cpl_core.type import T
|
||||
class ServiceProviderABC(ABC):
|
||||
r"""ABC for the class :class:`cpl_core.dependency_injection.service_provider.ServiceProvider`"""
|
||||
|
||||
_provider: Optional['ServiceProviderABC'] = None
|
||||
_provider: Optional["ServiceProviderABC"] = None
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def set_global_provider(cls, provider: 'ServiceProviderABC'):
|
||||
def set_global_provider(cls, provider: "ServiceProviderABC"):
|
||||
cls._provider = provider
|
||||
|
||||
@abstractmethod
|
||||
def build_by_signature(self, sig: Signature) -> list[T]: pass
|
||||
def build_by_signature(self, sig: Signature) -> list[T]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def build_service(self, service_type: type) -> object:
|
||||
r"""Creates instance of given type
|
||||
|
||||
Parameter
|
||||
---------
|
||||
Parameter:
|
||||
instance_type: :class:`type`
|
||||
The type of the searched instance
|
||||
|
||||
Returns
|
||||
-------
|
||||
Returns:
|
||||
Object of the given type
|
||||
"""
|
||||
pass
|
||||
@@ -41,8 +41,7 @@ class ServiceProviderABC(ABC):
|
||||
def set_scope(self, scope: ScopeABC):
|
||||
r"""Sets the scope of service provider
|
||||
|
||||
Parameter
|
||||
---------
|
||||
Parameter:
|
||||
Object of type :class:`cpl_core.dependency_injection.scope_abc.ScopeABC`
|
||||
Service scope
|
||||
"""
|
||||
@@ -52,23 +51,20 @@ class ServiceProviderABC(ABC):
|
||||
def create_scope(self) -> ScopeABC:
|
||||
r"""Creates a service scope
|
||||
|
||||
Returns
|
||||
-------
|
||||
Returns:
|
||||
Object of type :class:`cpl_core.dependency_injection.scope_abc.ScopeABC`
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_service(self, instance_type: T) -> Optional[T]:
|
||||
def get_service(self, instance_type: Type[T]) -> Optional[T]:
|
||||
r"""Returns instance of given type
|
||||
|
||||
Parameter
|
||||
---------
|
||||
Parameter:
|
||||
instance_type: :class:`cpl_core.type.T`
|
||||
The type of the searched instance
|
||||
|
||||
Returns
|
||||
-------
|
||||
Returns:
|
||||
Object of type Optional[:class:`cpl_core.type.T`]
|
||||
"""
|
||||
pass
|
||||
@@ -77,13 +73,11 @@ class ServiceProviderABC(ABC):
|
||||
def get_services(self, service_type: T) -> list[Optional[T]]:
|
||||
r"""Returns instance of given type
|
||||
|
||||
Parameter
|
||||
---------
|
||||
Parameter:
|
||||
instance_type: :class:`cpl_core.type.T`
|
||||
The type of the searched instance
|
||||
|
||||
Returns
|
||||
-------
|
||||
Returns:
|
||||
Object of type list[Optional[:class:`cpl_core.type.T`]
|
||||
"""
|
||||
pass
|
||||
@@ -92,12 +86,10 @@ class ServiceProviderABC(ABC):
|
||||
def inject(cls, f=None):
|
||||
r"""Decorator to allow injection into static and class methods
|
||||
|
||||
Parameter
|
||||
---------
|
||||
Parameter:
|
||||
f: Callable
|
||||
|
||||
Returns
|
||||
-------
|
||||
Returns:
|
||||
function
|
||||
"""
|
||||
if f is None:
|
||||
@@ -106,7 +98,7 @@ class ServiceProviderABC(ABC):
|
||||
@functools.wraps(f)
|
||||
def inner(*args, **kwargs):
|
||||
if cls._provider is None:
|
||||
raise Exception(f'{cls.__name__} not build!')
|
||||
raise Exception(f"{cls.__name__} not build!")
|
||||
|
||||
injection = cls._provider.build_by_signature(signature(f))
|
||||
return f(*injection, *args, **kwargs)
|
||||
|
Reference in New Issue
Block a user