WIP: dev into master #184

Draft
edraft wants to merge 121 commits from dev into master
26 changed files with 90 additions and 177 deletions
Showing only changes of commit 58dbd3ed1e - Show all commits

View File

@@ -1,6 +1,6 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from cpl.dependency.service_collection_abc import ServiceCollectionABC from cpl.dependency.service_collection import ServiceCollection
class AsyncStartupABC(ABC): class AsyncStartupABC(ABC):
@@ -15,9 +15,9 @@ class AsyncStartupABC(ABC):
r"""Creates configuration of application""" r"""Creates configuration of application"""
@abstractmethod @abstractmethod
async def configure_services(self, service: ServiceCollectionABC): async def configure_services(self, service: ServiceCollection):
r"""Creates service provider r"""Creates service provider
Parameter: Parameter:
services: :class:`cpl.dependency.service_collection_abc` services: :class:`cpl.dependency.service_collection`
""" """

View File

@@ -1,7 +1,7 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from cpl.core.configuration.configuration import Configuration from cpl.core.configuration.configuration import Configuration
from cpl.dependency.service_collection_abc import ServiceCollectionABC from cpl.dependency.service_collection import ServiceCollection
from cpl.core.environment.environment import Environment from cpl.core.environment.environment import Environment
@@ -22,10 +22,10 @@ class AsyncStartupExtensionABC(ABC):
""" """
@abstractmethod @abstractmethod
async def configure_services(self, service: ServiceCollectionABC, env: Environment): async def configure_services(self, service: ServiceCollection, env: Environment):
r"""Creates service provider r"""Creates service provider
Parameter: Parameter:
services: :class:`cpl.dependency.service_collection_abc` services: :class:`cpl.dependency.service_collection`
env: :class:`cpl.core.environment.application_environment_abc` env: :class:`cpl.core.environment.application_environment_abc`
""" """

View File

@@ -1,7 +1,7 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from cpl.core.configuration import Configuration from cpl.core.configuration import Configuration
from cpl.dependency.service_collection_abc import ServiceCollectionABC from cpl.dependency.service_collection import ServiceCollection
from cpl.core.environment import Environment from cpl.core.environment import Environment
@@ -22,10 +22,10 @@ class StartupABC(ABC):
""" """
@abstractmethod @abstractmethod
def configure_services(self, service: ServiceCollectionABC, env: Environment): def configure_services(self, service: ServiceCollection, env: Environment):
r"""Creates service provider r"""Creates service provider
Parameter: Parameter:
services: :class:`cpl.dependency.service_collection_abc` services: :class:`cpl.dependency.service_collection`
env: :class:`cpl.core.environment.application_environment_abc` env: :class:`cpl.core.environment.application_environment_abc`
""" """

View File

@@ -2,7 +2,7 @@ from abc import ABC, abstractmethod
from cpl.core.configuration import Configuration from cpl.core.configuration import Configuration
from cpl.dependency.service_collection_abc import ServiceCollectionABC from cpl.dependency.service_collection import ServiceCollection
from cpl.core.environment.environment import Environment from cpl.core.environment.environment import Environment
@@ -24,10 +24,10 @@ class StartupExtensionABC(ABC):
""" """
@abstractmethod @abstractmethod
def configure_services(self, service: ServiceCollectionABC, env: Environment): def configure_services(self, service: ServiceCollection, env: Environment):
r"""Creates service provider r"""Creates service provider
Parameter: Parameter:
services: :class:`cpl.dependency.service_collection_abc` services: :class:`cpl.dependency.service_collection`
env: :class:`cpl.core.environment.application_environment_abc` env: :class:`cpl.core.environment.application_environment_abc`
""" """

View File

@@ -1,3 +1,23 @@
from .database_settings_name_enum import DatabaseSettingsNameEnum from cpl.dependency import ServiceCollection as _ServiceCollection
from . import mysql
from .database_settings import DatabaseSettings from .database_settings import DatabaseSettings
from .database_settings_name_enum import DatabaseSettingsNameEnum
from .mysql.context import DatabaseContextABC, DatabaseContext
from .table_abc import TableABC from .table_abc import TableABC
def add_mysql(collection: _ServiceCollection):
from cpl.core.console import Console
from cpl.core.configuration import Configuration
try:
collection.add_singleton(DatabaseContextABC, DatabaseContext)
database_context = collection.build_service_provider().get_service(DatabaseContextABC)
db_settings: DatabaseSettings = Configuration.get(DatabaseSettings)
database_context.connect(db_settings)
except ImportError as e:
Console.error("cpl-translation is not installed", str(e))
_ServiceCollection.with_module(add_mysql, mysql.__name__)

View File

@@ -4,7 +4,7 @@ import mysql.connector as sql
from mysql.connector.abstracts import MySQLConnectionAbstract from mysql.connector.abstracts import MySQLConnectionAbstract
from mysql.connector.cursor import MySQLCursorBuffered from mysql.connector.cursor import MySQLCursorBuffered
from cpl.database.connection.database_connection_abc import DatabaseConnectionABC from cpl.database.mysql.connection.database_connection_abc import DatabaseConnectionABC
from cpl.database.database_settings import DatabaseSettings from cpl.database.database_settings import DatabaseSettings
from cpl.core.utils.credential_manager import CredentialManager from cpl.core.utils.credential_manager import CredentialManager

View File

@@ -1,9 +1,9 @@
from typing import Optional from typing import Optional
from cpl.database.connection.database_connection import DatabaseConnection from cpl.database.mysql.connection.database_connection import DatabaseConnection
from cpl.database.connection.database_connection_abc import DatabaseConnectionABC from cpl.database.mysql.connection.database_connection_abc import DatabaseConnectionABC
from cpl.database.context.database_context_abc import DatabaseContextABC from cpl.database.mysql.context.database_context_abc import DatabaseContextABC
from cpl.database.database_settings import DatabaseSettings from cpl.database.database_settings import DatabaseSettings
from mysql.connector.cursor import MySQLCursorBuffered from mysql.connector.cursor import MySQLCursorBuffered

View File

@@ -1,7 +1,6 @@
from .scope import Scope from .scope import Scope
from .scope_abc import ScopeABC from .scope_abc import ScopeABC
from .service_collection import ServiceCollection from .service_collection import ServiceCollection
from .service_collection_abc import ServiceCollectionABC
from .service_descriptor import ServiceDescriptor from .service_descriptor import ServiceDescriptor
from .service_lifetime_enum import ServiceLifetimeEnum from .service_lifetime_enum import ServiceLifetimeEnum
from .service_provider import ServiceProvider from .service_provider import ServiceProvider

View File

@@ -1,24 +1,26 @@
from typing import Union, Type, Callable, Optional from typing import Union, Type, Callable, Optional
from cpl.database.context.database_context_abc import DatabaseContextABC
from cpl.database.database_settings import DatabaseSettings
from cpl.dependency.service_collection_abc import ServiceCollectionABC
from cpl.dependency.service_descriptor import ServiceDescriptor
from cpl.dependency.service_lifetime_enum import ServiceLifetimeEnum
from cpl.dependency.service_provider import ServiceProvider
from cpl.dependency.service_provider_abc import ServiceProviderABC
from cpl.core.log.logger import Logger from cpl.core.log.logger import Logger
from cpl.core.log.logger_abc import LoggerABC from cpl.core.log.logger_abc import LoggerABC
from cpl.core.pipes.pipe_abc import PipeABC from cpl.core.pipes.pipe_abc import PipeABC
from cpl.core.typing import T, Service from cpl.core.typing import T, Service
from cpl.dependency.service_descriptor import ServiceDescriptor
from cpl.dependency.service_lifetime_enum import ServiceLifetimeEnum
from cpl.dependency.service_provider import ServiceProvider
from cpl.dependency.service_provider_abc import ServiceProviderABC
class ServiceCollection(ServiceCollectionABC): class ServiceCollection:
r"""Representation of the collection of services""" r"""Representation of the collection of services"""
_modules: dict[str, Callable] = {}
@classmethod
def with_module(cls, func: Callable, name: str = None):
cls._modules[func.__name__ if name is None else name] = func
return cls
def __init__(self): def __init__(self):
ServiceCollectionABC.__init__(self)
self._database_context: Optional[DatabaseContextABC] = None
self._service_descriptors: list[ServiceDescriptor] = [] self._service_descriptors: list[ServiceDescriptor] = []
def _add_descriptor(self, service: Union[type, object], lifetime: ServiceLifetimeEnum, base_type: Callable = None): def _add_descriptor(self, service: Union[type, object], lifetime: ServiceLifetimeEnum, base_type: Callable = None):
@@ -44,10 +46,19 @@ class ServiceCollection(ServiceCollectionABC):
return self return self
def add_db_context(self, db_context_type: Type[DatabaseContextABC], db_settings: DatabaseSettings): def add_module(self, module: str | object):
self.add_singleton(DatabaseContextABC, db_context_type) if not isinstance(module, str):
self._database_context = self.build_service_provider().get_service(DatabaseContextABC) module = module.__name__
self._database_context.connect(db_settings)
if module not in self._modules:
raise ValueError(f"Module {module} not found")
self._modules[module](self)
# def add_mysql(self, db_context_type: Type[DatabaseContextABC], db_settings: DatabaseSettings):
# self.add_singleton(DatabaseContextABC, db_context_type)
# self._database_context = self.build_service_provider().get_service(DatabaseContextABC)
# self._database_context.connect(db_settings)
def add_logging(self): def add_logging(self):
self.add_transient(LoggerABC, Logger) self.add_transient(LoggerABC, Logger)
@@ -71,6 +82,6 @@ class ServiceCollection(ServiceCollectionABC):
return self return self
def build_service_provider(self) -> ServiceProviderABC: def build_service_provider(self) -> ServiceProviderABC:
sp = ServiceProvider(self._service_descriptors, self._database_context) sp = ServiceProvider(self._service_descriptors)
ServiceProviderABC.set_global_provider(sp) ServiceProviderABC.set_global_provider(sp)
return sp return sp

View File

@@ -1,90 +0,0 @@
from abc import abstractmethod, ABC
from typing import Type
from cpl.database.context.database_context_abc import DatabaseContextABC
from cpl.database.database_settings import DatabaseSettings
from cpl.dependency.service_provider_abc import ServiceProviderABC
from cpl.core.typing import T, Source
class ServiceCollectionABC(ABC):
r"""ABC for the class :class:`cpl.dependency.service_collection.ServiceCollection`"""
@abstractmethod
def __init__(self):
pass
@abstractmethod
def add_db_context(self, db_context_type: Type[DatabaseContextABC], db_settings: DatabaseSettings):
r"""Adds database context
Parameter:
db_context: Type[:class:`cpl.database.context.database_context_abc.DatabaseContextABC`]
Database context
"""
@abstractmethod
def add_logging(self):
r"""Adds the CPL internal logger"""
@abstractmethod
def add_pipes(self):
r"""Adds the CPL internal pipes as transient"""
def add_translation(self):
r"""Adds the CPL translation"""
raise NotImplementedError("You should install and use the cpl-translation package")
def add_mail(self):
r"""Adds the CPL mail"""
raise NotImplementedError("You should install and use the cpl-mail package")
@abstractmethod
def add_transient(self, service_type: T, service: T = None) -> "ServiceCollectionABC":
r"""Adds a service with transient lifetime
Parameter:
service_type: :class:`Type`
Type of the service
service: :class:`Callable`
Object of the service
Returns:
self: :class:`cpl.dependency.service_collection_abc.ServiceCollectionABC`
"""
@abstractmethod
def add_scoped(self, service_type: T, service: T = None) -> "ServiceCollectionABC":
r"""Adds a service with scoped lifetime
Parameter:
service_type: :class:`Type`
Type of the service
service: :class:`Callable`
Object of the service
Returns:
self: :class:`cpl.dependency.service_collection_abc.ServiceCollectionABC`
"""
@abstractmethod
def add_singleton(self, service_type: T, service: T = None) -> "ServiceCollectionABC":
r"""Adds a service with singleton lifetime
Parameter:
service_type: :class:`Type`
Type of the service
service: :class:`Callable`
Object of the service
Returns:
self: :class:`cpl.dependency.service_collection_abc.ServiceCollectionABC`
"""
@abstractmethod
def build_service_provider(self) -> ServiceProviderABC:
r"""Creates instance of the service provider
Returns:
Object of type :class:`cpl.dependency.service_provider_abc.ServiceProviderABC`
"""

View File

@@ -5,7 +5,6 @@ from typing import Optional
from cpl.core.configuration import Configuration from cpl.core.configuration import Configuration
from cpl.core.configuration.configuration_model_abc import ConfigurationModelABC from cpl.core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl.database.context.database_context_abc import DatabaseContextABC
from cpl.core.environment import Environment from cpl.core.environment import Environment
from cpl.core.typing import T, R, Source from cpl.core.typing import T, R, Source
from cpl.dependency.scope_abc import ScopeABC from cpl.dependency.scope_abc import ScopeABC
@@ -31,12 +30,10 @@ class ServiceProvider(ServiceProviderABC):
def __init__( def __init__(
self, self,
service_descriptors: list[ServiceDescriptor], service_descriptors: list[ServiceDescriptor],
db_context: Optional[DatabaseContextABC],
): ):
ServiceProviderABC.__init__(self) ServiceProviderABC.__init__(self)
self._service_descriptors: list[ServiceDescriptor] = service_descriptors self._service_descriptors: list[ServiceDescriptor] = service_descriptors
self._database_context = db_context
self._scope: Optional[ScopeABC] = None self._scope: Optional[ScopeABC] = None
def _find_service(self, service_type: type) -> Optional[ServiceDescriptor]: def _find_service(self, service_type: type) -> Optional[ServiceDescriptor]:
@@ -95,9 +92,6 @@ class ServiceProvider(ServiceProviderABC):
elif issubclass(parameter.annotation, Environment): elif issubclass(parameter.annotation, Environment):
params.append(Environment) params.append(Environment)
elif issubclass(parameter.annotation, DatabaseContextABC):
params.append(self._database_context)
elif issubclass(parameter.annotation, ConfigurationModelABC): elif issubclass(parameter.annotation, ConfigurationModelABC):
params.append(Configuration.get(parameter.annotation)) params.append(Configuration.get(parameter.annotation))

View File

@@ -1,3 +1,4 @@
from cpl.dependency import ServiceCollection as _ServiceCollection
from .abc.email_client_abc import EMailClientABC from .abc.email_client_abc import EMailClientABC
from .email_client import EMailClient from .email_client import EMailClient
from .email_client_settings import EMailClientSettings from .email_client_settings import EMailClientSettings
@@ -6,21 +7,15 @@ from .email_model import EMail
from .mail_logger import MailLogger from .mail_logger import MailLogger
def add_mail(self): def add_mail(collection: _ServiceCollection):
from cpl.core.console import Console from cpl.core.console import Console
from cpl.core.log import LoggerABC from cpl.core.log import LoggerABC
try: try:
self.add_singleton(EMailClientABC, EMailClient) collection.add_singleton(EMailClientABC, EMailClient)
self.add_transient(LoggerABC, MailLogger) collection.add_transient(LoggerABC, MailLogger)
except ImportError as e: except ImportError as e:
Console.error("cpl-translation is not installed", str(e)) Console.error("cpl-translation is not installed", str(e))
def init(): _ServiceCollection.with_module(add_mail, __name__)
from cpl.dependency import ServiceCollection
ServiceCollection.add_mail = add_mail
init()

View File

@@ -1,10 +1,11 @@
from cpl.dependency import ServiceCollection as _ServiceCollection
from .translate_pipe import TranslatePipe from .translate_pipe import TranslatePipe
from .translation_service import TranslationService from .translation_service import TranslationService
from .translation_service_abc import TranslationServiceABC from .translation_service_abc import TranslationServiceABC
from .translation_settings import TranslationSettings from .translation_settings import TranslationSettings
def add_translation(self): def add_translation(collection: _ServiceCollection):
from cpl.core.console import Console from cpl.core.console import Console
from cpl.core.pipes import PipeABC from cpl.core.pipes import PipeABC
from cpl.translation.translate_pipe import TranslatePipe from cpl.translation.translate_pipe import TranslatePipe
@@ -12,16 +13,10 @@ def add_translation(self):
from cpl.translation.translation_service_abc import TranslationServiceABC from cpl.translation.translation_service_abc import TranslationServiceABC
try: try:
self.add_singleton(TranslationServiceABC, TranslationService) collection.add_singleton(TranslationServiceABC, TranslationService)
self.add_transient(PipeABC, TranslatePipe) collection.add_transient(PipeABC, TranslatePipe)
except ImportError as e: except ImportError as e:
Console.error("cpl-translation is not installed", str(e)) Console.error("cpl-translation is not installed", str(e))
def init(): _ServiceCollection.with_module(add_translation, __name__)
from cpl.dependency import ServiceCollection
ServiceCollection.add_translation = add_translation
init()

View File

@@ -1,6 +1,6 @@
from cpl.application.async_startup_abc import AsyncStartupABC from cpl.application.async_startup_abc import AsyncStartupABC
from cpl.core.configuration import ConfigurationABC from cpl.core.configuration import ConfigurationABC
from cpl.dependency import ServiceProviderABC, ServiceCollectionABC from cpl.dependency import ServiceProviderABC, ServiceCollection
from cpl.core.environment import Environment from cpl.core.environment import Environment
@@ -13,5 +13,5 @@ class Startup(AsyncStartupABC):
) -> ConfigurationABC: ) -> ConfigurationABC:
return configuration return configuration
async def configure_services(self, services: ServiceCollectionABC, environment: Environment) -> ServiceProviderABC: async def configure_services(self, services: ServiceCollection, environment: Environment) -> ServiceProviderABC:
return services.build_service_provider() return services.build_service_provider()

View File

@@ -1,7 +0,0 @@
from cpl.database import DatabaseSettings
from cpl.database.context import DatabaseContext
class DBContext(DatabaseContext):
def __init__(self):
DatabaseContext.__init__(self)

View File

@@ -1,5 +1,5 @@
from cpl.core.console import Console from cpl.core.console import Console
from cpl.database.context import DatabaseContextABC from cpl.database.mysql.context import DatabaseContextABC
from .city_model import CityModel from .city_model import CityModel
from .user_model import UserModel from .user_model import UserModel

View File

@@ -1,11 +1,9 @@
from cpl.application import StartupABC from cpl.application import StartupABC
from cpl.core.configuration import Configuration from cpl.core.configuration import Configuration
from cpl.database import DatabaseSettings
from cpl.dependency import ServiceCollectionABC, ServiceProviderABC
from cpl.core.environment import Environment from cpl.core.environment import Environment
from cpl.core.log import Logger, LoggerABC from cpl.core.log import Logger, LoggerABC
from cpl.database import mysql
from model.db_context import DBContext from cpl.dependency import ServiceCollection
from model.user_repo import UserRepo from model.user_repo import UserRepo
from model.user_repo_abc import UserRepoABC from model.user_repo_abc import UserRepoABC
@@ -23,11 +21,8 @@ class Startup(StartupABC):
self._configuration = configuration self._configuration = configuration
def configure_services(self, services: ServiceCollectionABC, environment: Environment): def configure_services(self, services: ServiceCollection, environment: Environment):
# Create and connect to database services.add_module(mysql)
db_settings: DatabaseSettings = self._configuration.get(DatabaseSettings)
services.add_db_context(DBContext, db_settings)
services.add_singleton(UserRepoABC, UserRepo) services.add_singleton(UserRepoABC, UserRepo)
services.add_singleton(LoggerABC, Logger) services.add_singleton(LoggerABC, Logger)

View File

@@ -1,6 +1,6 @@
from cpl.application import StartupABC from cpl.application import StartupABC
from cpl.core.configuration import ConfigurationABC from cpl.core.configuration import ConfigurationABC
from cpl.dependency import ServiceProviderABC, ServiceCollectionABC from cpl.dependency import ServiceProviderABC, ServiceCollection
from cpl.core.environment import Environment from cpl.core.environment import Environment
from di.test1_service import Test1Service from di.test1_service import Test1Service
from di.test2_service import Test2Service from di.test2_service import Test2Service
@@ -17,7 +17,7 @@ class Startup(StartupABC):
def configure_configuration(self, configuration: ConfigurationABC, environment: Environment) -> ConfigurationABC: def configure_configuration(self, configuration: ConfigurationABC, environment: Environment) -> ConfigurationABC:
return configuration return configuration
def configure_services(self, services: ServiceCollectionABC, environment: Environment) -> ServiceProviderABC: def configure_services(self, services: ServiceCollection, environment: Environment) -> ServiceProviderABC:
services.add_scoped(TestService) services.add_scoped(TestService)
services.add_scoped(DITesterService) services.add_scoped(DITesterService)

View File

@@ -1,6 +1,7 @@
from cpl import mail
from cpl.application import StartupABC from cpl.application import StartupABC
from cpl.core.configuration import Configuration from cpl.core.configuration import Configuration
from cpl.dependency import ServiceCollectionABC, ServiceProviderABC from cpl.dependency import ServiceCollection, ServiceProviderABC
from cpl.core.environment import Environment from cpl.core.environment import Environment
from cpl.core.pipes import IPAddressPipe from cpl.core.pipes import IPAddressPipe
from test_service import TestService from test_service import TestService
@@ -15,8 +16,8 @@ class Startup(StartupABC):
config.add_json_file(f"appsettings.{env.get_environment()}.json") config.add_json_file(f"appsettings.{env.get_environment()}.json")
config.add_json_file(f"appsettings.{env.get_host_name()}.json", optional=True) config.add_json_file(f"appsettings.{env.get_host_name()}.json", optional=True)
def configure_services(self, services: ServiceCollectionABC, env: Environment): def configure_services(self, services: ServiceCollection, env: Environment):
services.add_logging() services.add_logging()
services.add_mail() services.add_module(mail)
services.add_transient(IPAddressPipe) services.add_transient(IPAddressPipe)
services.add_singleton(TestService) services.add_singleton(TestService)

View File

@@ -1,7 +1,7 @@
from cpl.application import StartupExtensionABC from cpl.application import StartupExtensionABC
from cpl.core.configuration import Configuration from cpl.core.configuration import Configuration
from cpl.core.console import Console from cpl.core.console import Console
from cpl.dependency import ServiceCollectionABC from cpl.dependency import ServiceCollection
from cpl.core.environment import Environment from cpl.core.environment import Environment
@@ -12,5 +12,5 @@ class TestStartupExtension(StartupExtensionABC):
def configure_configuration(self, config: Configuration, env: Environment): def configure_configuration(self, config: Configuration, env: Environment):
Console.write_line("config") Console.write_line("config")
def configure_services(self, services: ServiceCollectionABC, env: Environment): def configure_services(self, services: ServiceCollection, env: Environment):
Console.write_line("services") Console.write_line("services")

View File

@@ -1,6 +1,6 @@
from cpl.application import StartupABC from cpl.application import StartupABC
from cpl.core.configuration import ConfigurationABC from cpl.core.configuration import ConfigurationABC
from cpl.dependency import ServiceProviderABC, ServiceCollectionABC from cpl.dependency import ServiceProviderABC, ServiceCollection
from cpl.core.environment import Environment from cpl.core.environment import Environment
@@ -12,6 +12,6 @@ class Startup(StartupABC):
configuration.add_json_file("appsettings.json") configuration.add_json_file("appsettings.json")
return configuration return configuration
def configure_services(self, services: ServiceCollectionABC, environment: Environment) -> ServiceProviderABC: def configure_services(self, services: ServiceCollection, environment: Environment) -> ServiceProviderABC:
services.add_translation() services.add_translation()
return services.build_service_provider() return services.build_service_provider()