From 8aaba229408efe58564423e5a69330b3cc6a127e Mon Sep 17 00:00:00 2001 From: edraft Date: Wed, 17 Sep 2025 19:23:14 +0200 Subject: [PATCH] Improved application structure --- .../cpl/application/__init__.py | 5 - .../cpl/application/abc/__init__.py | 4 + .../cpl/application/abc/application_abc.py | 33 ++++++ .../{ => abc}/application_extension_abc.py | 3 +- .../startup_abc.py} | 9 +- .../application/abc/startup_extension_abc.py | 24 ++++ .../cpl/application/application_abc.py | 57 --------- .../cpl/application/application_builder.py | 109 +++++++----------- .../application/application_builder_abc.py | 47 -------- .../async_application_extension_abc.py | 14 --- .../async_startup_extension_abc.py | 31 ----- src/cpl-application/cpl/application/host.py | 17 +++ .../cpl/application/startup_abc.py | 31 ----- .../cpl/application/startup_extension_abc.py | 33 ------ src/cpl-auth/cpl/auth/__init__.py | 2 +- .../cpl/dependency/service_collection.py | 41 +++---- .../cpl/dependency/service_provider.py | 2 +- .../cpl/dependency/service_provider_abc.py | 6 +- tests/custom/async/src/async/startup.py | 2 +- tests/custom/database/src/application.py | 9 +- tests/custom/database/src/main.py | 14 +-- tests/custom/database/src/main_simplified.py | 15 +++ tests/custom/database/src/startup.py | 18 +-- tests/custom/di/src/di/startup.py | 2 +- .../custom/general/src/general/application.py | 10 +- tests/custom/general/src/general/startup.py | 12 +- .../general/src/general/test_extension.py | 5 +- .../src/general/test_startup_extension.py | 6 +- .../translation/src/translation/startup.py | 2 +- .../configuration/configuration_test_case.py | 2 +- .../console_arguments_test_case.py | 12 +- .../di/service_collection_test_case.py | 2 +- .../di/service_provider_test_case.py | 2 +- 33 files changed, 200 insertions(+), 381 deletions(-) create mode 100644 src/cpl-application/cpl/application/abc/__init__.py create mode 100644 src/cpl-application/cpl/application/abc/application_abc.py rename src/cpl-application/cpl/application/{ => abc}/application_extension_abc.py (61%) rename src/cpl-application/cpl/application/{async_startup_abc.py => abc/startup_abc.py} (65%) create mode 100644 src/cpl-application/cpl/application/abc/startup_extension_abc.py delete mode 100644 src/cpl-application/cpl/application/application_abc.py delete mode 100644 src/cpl-application/cpl/application/application_builder_abc.py delete mode 100644 src/cpl-application/cpl/application/async_application_extension_abc.py delete mode 100644 src/cpl-application/cpl/application/async_startup_extension_abc.py create mode 100644 src/cpl-application/cpl/application/host.py delete mode 100644 src/cpl-application/cpl/application/startup_abc.py delete mode 100644 src/cpl-application/cpl/application/startup_extension_abc.py create mode 100644 tests/custom/database/src/main_simplified.py diff --git a/src/cpl-application/cpl/application/__init__.py b/src/cpl-application/cpl/application/__init__.py index 5ce8988c..34366e07 100644 --- a/src/cpl-application/cpl/application/__init__.py +++ b/src/cpl-application/cpl/application/__init__.py @@ -1,6 +1 @@ -from .application_abc import ApplicationABC from .application_builder import ApplicationBuilder -from .application_builder_abc import ApplicationBuilderABC -from .application_extension_abc import ApplicationExtensionABC -from .startup_abc import StartupABC -from .startup_extension_abc import StartupExtensionABC diff --git a/src/cpl-application/cpl/application/abc/__init__.py b/src/cpl-application/cpl/application/abc/__init__.py new file mode 100644 index 00000000..a973043e --- /dev/null +++ b/src/cpl-application/cpl/application/abc/__init__.py @@ -0,0 +1,4 @@ +from .application_abc import ApplicationABC +from .application_extension_abc import ApplicationExtensionABC +from .startup_abc import StartupABC +from .startup_extension_abc import StartupExtensionABC diff --git a/src/cpl-application/cpl/application/abc/application_abc.py b/src/cpl-application/cpl/application/abc/application_abc.py new file mode 100644 index 00000000..6a97c61c --- /dev/null +++ b/src/cpl-application/cpl/application/abc/application_abc.py @@ -0,0 +1,33 @@ +from abc import ABC, abstractmethod + +from cpl.application.host import Host +from cpl.core.console.console import Console +from cpl.dependency.service_provider_abc import ServiceProviderABC + + +class ApplicationABC(ABC): + r"""ABC for the Application class + + Parameters: + services: :class:`cpl.dependency.service_provider_abc.ServiceProviderABC` + Contains instances of prepared objects + """ + + @abstractmethod + def __init__(self, services: ServiceProviderABC): + self._services = services + + def run(self): + r"""Entry point + + Called by custom Application.main + """ + try: + Host.run(self.main) + except KeyboardInterrupt: + Console.close() + + @abstractmethod + def main(self): + r"""Main method of application""" + pass diff --git a/src/cpl-application/cpl/application/application_extension_abc.py b/src/cpl-application/cpl/application/abc/application_extension_abc.py similarity index 61% rename from src/cpl-application/cpl/application/application_extension_abc.py rename to src/cpl-application/cpl/application/abc/application_extension_abc.py index 3e9015d9..5b8831bd 100644 --- a/src/cpl-application/cpl/application/application_extension_abc.py +++ b/src/cpl-application/cpl/application/abc/application_extension_abc.py @@ -1,6 +1,5 @@ from abc import ABC, abstractmethod -from cpl.core.configuration.configuration import Configuration from cpl.dependency import ServiceProviderABC @@ -10,5 +9,5 @@ class ApplicationExtensionABC(ABC): pass @abstractmethod - def run(self, config: Configuration, services: ServiceProviderABC): + def run(self, services: ServiceProviderABC): pass diff --git a/src/cpl-application/cpl/application/async_startup_abc.py b/src/cpl-application/cpl/application/abc/startup_abc.py similarity index 65% rename from src/cpl-application/cpl/application/async_startup_abc.py rename to src/cpl-application/cpl/application/abc/startup_abc.py index 093eeb3f..421f73a1 100644 --- a/src/cpl-application/cpl/application/async_startup_abc.py +++ b/src/cpl-application/cpl/application/abc/startup_abc.py @@ -3,7 +3,7 @@ from abc import ABC, abstractmethod from cpl.dependency.service_collection import ServiceCollection -class AsyncStartupABC(ABC): +class StartupABC(ABC): r"""ABC for the startup class""" @abstractmethod @@ -11,11 +11,12 @@ class AsyncStartupABC(ABC): pass @abstractmethod - async def configure_configuration(self): - r"""Creates configuration of application""" + def configure_configuration(self): + r"""Creates configuration of application + """ @abstractmethod - async def configure_services(self, service: ServiceCollection): + def configure_services(self, service: ServiceCollection): r"""Creates service provider Parameter: diff --git a/src/cpl-application/cpl/application/abc/startup_extension_abc.py b/src/cpl-application/cpl/application/abc/startup_extension_abc.py new file mode 100644 index 00000000..aab4af7a --- /dev/null +++ b/src/cpl-application/cpl/application/abc/startup_extension_abc.py @@ -0,0 +1,24 @@ +from abc import ABC, abstractmethod + +from cpl.dependency import ServiceCollection + + +class StartupExtensionABC(ABC): + r"""ABC for startup extension classes""" + + @abstractmethod + def __init__(self): + pass + + @abstractmethod + def configure_configuration(self): + r"""Creates configuration of application + + """ + + @abstractmethod + def configure_services(self, services: ServiceCollection): + r"""Creates service provider + Parameter: + services: :class:`cpl.dependency.service_collection` + """ diff --git a/src/cpl-application/cpl/application/application_abc.py b/src/cpl-application/cpl/application/application_abc.py deleted file mode 100644 index bda6e006..00000000 --- a/src/cpl-application/cpl/application/application_abc.py +++ /dev/null @@ -1,57 +0,0 @@ -from abc import ABC, abstractmethod -from typing import Optional - -from cpl.dependency.service_provider_abc import ServiceProviderABC - -from cpl.core.console.console import Console - - -class ApplicationABC(ABC): - r"""ABC for the Application class - - Parameters: - config: :class:`cpl.core.configuration.configuration_abc.ConfigurationABC` - Contains object loaded from appsettings - services: :class:`cpl.dependency.service_provider_abc.ServiceProviderABC` - Contains instances of prepared objects - """ - - @abstractmethod - def __init__(self, services: ServiceProviderABC): - self._services: Optional[ServiceProviderABC] = services - - def run(self): - r"""Entry point - - Called by custom Application.main - """ - try: - self.configure() - self.main() - except KeyboardInterrupt: - Console.close() - - async def run_async(self): - r"""Entry point - - Called by custom Application.main - """ - try: - await self.configure() - await self.main() - except KeyboardInterrupt: - Console.close() - - @abstractmethod - def configure(self): - r"""Configure the application - - Called by :class:`cpl.application.application_abc.ApplicationABC.run` - """ - - @abstractmethod - def main(self): - r"""Custom entry point - - Called by :class:`cpl.application.application_abc.ApplicationABC.run` - """ diff --git a/src/cpl-application/cpl/application/application_builder.py b/src/cpl-application/cpl/application/application_builder.py index 77a34239..74010897 100644 --- a/src/cpl-application/cpl/application/application_builder.py +++ b/src/cpl-application/cpl/application/application_builder.py @@ -1,97 +1,66 @@ -from typing import Type, Optional, Callable, Union +import asyncio +from typing import Type, Optional, Callable -from cpl.application.application_abc import ApplicationABC -from cpl.application.application_builder_abc import ApplicationBuilderABC -from cpl.application.application_extension_abc import ApplicationExtensionABC -from cpl.application.async_application_extension_abc import AsyncApplicationExtensionABC -from cpl.application.async_startup_abc import AsyncStartupABC -from cpl.application.async_startup_extension_abc import AsyncStartupExtensionABC -from cpl.application.startup_abc import StartupABC -from cpl.application.startup_extension_abc import StartupExtensionABC -from cpl.core.configuration.configuration import Configuration +from cpl.application.abc.application_abc import ApplicationABC +from cpl.application.abc.application_extension_abc import ApplicationExtensionABC +from cpl.application.abc.startup_abc import StartupABC +from cpl.application.abc.startup_extension_abc import StartupExtensionABC +from cpl.application.host import Host from cpl.dependency.service_collection import ServiceCollection -from cpl.core.environment import Environment -class ApplicationBuilder(ApplicationBuilderABC): - r"""This is class is used to build an object of :class:`cpl.application.application_abc.ApplicationABC` - - Parameter: - app: Type[:class:`cpl.application.application_abc.ApplicationABC`] - Application to build - """ +class ApplicationBuilder: + r"""A builder for constructing an application with configurable services and extensions.""" def __init__(self, app: Type[ApplicationABC]): - ApplicationBuilderABC.__init__(self) - self._app = app - self._startup: Optional[StartupABC | AsyncStartupABC] = None + assert app is not None, "app must not be None" + assert issubclass(app, ApplicationABC), "app must be an subclass of ApplicationABC or its subclass" + + self._app = app if app is not None else ApplicationABC self._services = ServiceCollection() - self._app_extensions: list[Type[ApplicationExtensionABC | AsyncApplicationExtensionABC]] = [] - self._startup_extensions: list[Type[StartupExtensionABC | AsyncStartupABC]] = [] + self._startup: Optional[StartupABC] = None + self._app_extensions: list[Type[ApplicationExtensionABC]] = [] + self._startup_extensions: list[Type[StartupExtensionABC]] = [] - def use_startup(self, startup: Type[StartupABC | AsyncStartupABC]) -> "ApplicationBuilder": + self._async_loop = asyncio.get_event_loop() + + @property + def services(self) -> ServiceCollection: + return self._services + + @property + def service_provider(self): + return self._services.build() + + def use_startup(self, startup: Type[StartupABC]) -> "ApplicationBuilder": self._startup = startup() return self def use_extension( self, - extension: Type[ - ApplicationExtensionABC | AsyncApplicationExtensionABC | StartupExtensionABC | AsyncStartupExtensionABC - ], + extension: Type[ApplicationExtensionABC | StartupExtensionABC], ) -> "ApplicationBuilder": - if ( - issubclass(extension, ApplicationExtensionABC) or issubclass(extension, AsyncApplicationExtensionABC) - ) and extension not in self._app_extensions: + if (issubclass(extension, ApplicationExtensionABC)) and extension not in self._app_extensions: self._app_extensions.append(extension) - elif ( - issubclass(extension, StartupExtensionABC) or issubclass(extension, AsyncStartupExtensionABC) - ) and extension not in self._startup_extensions: + elif (issubclass(extension, StartupExtensionABC)) and extension not in self._startup_extensions: self._startup_extensions.append(extension) return self - def _build_startup(self): - for ex in self._startup_extensions: - extension = ex() - extension.configure_configuration(Configuration, Environment) - extension.configure_services(self._services, Environment) - - if self._startup is not None: - self._startup.configure_configuration(Configuration, Environment) - self._startup.configure_services(self._services, Environment) - - async def _build_async_startup(self): - for ex in self._startup_extensions: - extension = ex() - await extension.configure_configuration(Configuration, Environment) - await extension.configure_services(self._services, Environment) - - if self._startup is not None: - await self._startup.configure_configuration(Configuration, Environment) - await self._startup.configure_services(self._services, Environment) - def build(self) -> ApplicationABC: - self._build_startup() + for ex in self._startup_extensions: + extension = ex() + Host.run(extension.configure_configuration) + Host.run(extension.configure_services, self._services) - config = Configuration - services = self._services.build_service_provider() + if self._startup is not None: + Host.run(self._startup.configure_configuration) + Host.run(self._startup.configure_services, self._services) for ex in self._app_extensions: extension = ex() - extension.run(config, services) + Host.run(extension.run, self.service_provider) - return self._app(services) - - async def build_async(self) -> ApplicationABC: - await self._build_async_startup() - - config = Configuration - services = self._services.build_service_provider() - - for ex in self._app_extensions: - extension = ex() - await extension.run(config, services) - - return self._app(services) + return self._app(self.service_provider) diff --git a/src/cpl-application/cpl/application/application_builder_abc.py b/src/cpl-application/cpl/application/application_builder_abc.py deleted file mode 100644 index 3c82e440..00000000 --- a/src/cpl-application/cpl/application/application_builder_abc.py +++ /dev/null @@ -1,47 +0,0 @@ -from abc import ABC, abstractmethod -from typing import Type - -from cpl.application.application_abc import ApplicationABC -from cpl.application.startup_abc import StartupABC - - -class ApplicationBuilderABC(ABC): - r"""ABC for the :class:`cpl.application.application_builder.ApplicationBuilder`""" - - @abstractmethod - def __init__(self, *args): - pass - - @abstractmethod - def use_startup(self, startup: Type[StartupABC]): - r"""Sets the custom startup class to use - - Parameter: - startup: Type[:class:`cpl.application.startup_abc.StartupABC`] - Startup class to use - """ - - @abstractmethod - async def use_startup(self, startup: Type[StartupABC]): - r"""Sets the custom startup class to use async - - Parameter: - startup: Type[:class:`cpl.application.startup_abc.StartupABC`] - Startup class to use - """ - - @abstractmethod - def build(self) -> ApplicationABC: - r"""Creates custom application object - - Returns: - Object of :class:`cpl.application.application_abc.ApplicationABC` - """ - - @abstractmethod - async def build_async(self) -> ApplicationABC: - r"""Creates custom application object async - - Returns: - Object of :class:`cpl.application.application_abc.ApplicationABC` - """ diff --git a/src/cpl-application/cpl/application/async_application_extension_abc.py b/src/cpl-application/cpl/application/async_application_extension_abc.py deleted file mode 100644 index b4b37d87..00000000 --- a/src/cpl-application/cpl/application/async_application_extension_abc.py +++ /dev/null @@ -1,14 +0,0 @@ -from abc import ABC, abstractmethod - -from cpl.core.configuration.configuration import Configuration -from cpl.dependency import ServiceProviderABC - - -class AsyncApplicationExtensionABC(ABC): - @abstractmethod - def __init__(self): - pass - - @abstractmethod - async def run(self, config: Configuration, services: ServiceProviderABC): - pass diff --git a/src/cpl-application/cpl/application/async_startup_extension_abc.py b/src/cpl-application/cpl/application/async_startup_extension_abc.py deleted file mode 100644 index 0d3e8907..00000000 --- a/src/cpl-application/cpl/application/async_startup_extension_abc.py +++ /dev/null @@ -1,31 +0,0 @@ -from abc import ABC, abstractmethod - -from cpl.core.configuration.configuration import Configuration -from cpl.dependency.service_collection import ServiceCollection -from cpl.core.environment.environment import Environment - - -class AsyncStartupExtensionABC(ABC): - r"""ABC for startup extension classes""" - - @abstractmethod - def __init__(self): - pass - - @abstractmethod - async def configure_configuration(self, config: Configuration, env: Environment): - r"""Creates configuration of application - - Parameter: - config: :class:`cpl.core.configuration.configuration_abc.Configuration` - env: :class:`cpl.core.environment.application_environment_abc` - """ - - @abstractmethod - async def configure_services(self, service: ServiceCollection, env: Environment): - r"""Creates service provider - - Parameter: - services: :class:`cpl.dependency.service_collection` - env: :class:`cpl.core.environment.application_environment_abc` - """ diff --git a/src/cpl-application/cpl/application/host.py b/src/cpl-application/cpl/application/host.py new file mode 100644 index 00000000..eaafd67e --- /dev/null +++ b/src/cpl-application/cpl/application/host.py @@ -0,0 +1,17 @@ +import asyncio +from typing import Callable + + +class Host: + _loop = asyncio.get_event_loop() + + @classmethod + def get_loop(cls): + return cls._loop + + @classmethod + def run(cls, func: Callable, *args, **kwargs): + if asyncio.iscoroutinefunction(func): + return cls._loop.run_until_complete(func(*args, **kwargs)) + + return func(*args, **kwargs) \ No newline at end of file diff --git a/src/cpl-application/cpl/application/startup_abc.py b/src/cpl-application/cpl/application/startup_abc.py deleted file mode 100644 index 365221d4..00000000 --- a/src/cpl-application/cpl/application/startup_abc.py +++ /dev/null @@ -1,31 +0,0 @@ -from abc import ABC, abstractmethod - -from cpl.core.configuration import Configuration -from cpl.dependency.service_collection import ServiceCollection -from cpl.core.environment import Environment - - -class StartupABC(ABC): - r"""ABC for the startup class""" - - @abstractmethod - def __init__(self): - pass - - @abstractmethod - def configure_configuration(self, config: Configuration, env: Environment): - r"""Creates configuration of application - - Parameter: - config: :class:`cpl.core.configuration.configuration_abc.ConfigurationABC` - env: :class:`cpl.core.environment.application_environment_abc` - """ - - @abstractmethod - def configure_services(self, service: ServiceCollection, env: Environment): - r"""Creates service provider - - Parameter: - services: :class:`cpl.dependency.service_collection` - env: :class:`cpl.core.environment.application_environment_abc` - """ diff --git a/src/cpl-application/cpl/application/startup_extension_abc.py b/src/cpl-application/cpl/application/startup_extension_abc.py deleted file mode 100644 index 679020f9..00000000 --- a/src/cpl-application/cpl/application/startup_extension_abc.py +++ /dev/null @@ -1,33 +0,0 @@ -from abc import ABC, abstractmethod - - -from cpl.core.configuration import Configuration -from cpl.dependency.service_collection import ServiceCollection - -from cpl.core.environment.environment import Environment - - -class StartupExtensionABC(ABC): - r"""ABC for startup extension classes""" - - @abstractmethod - def __init__(self): - pass - - @abstractmethod - def configure_configuration(self, config: Configuration, env: Environment): - r"""Creates configuration of application - - Parameter: - config: :class:`cpl.core.configuration.configuration_abc.ConfigurationABC` - env: :class:`cpl.core.environment.application_environment_abc` - """ - - @abstractmethod - def configure_services(self, service: ServiceCollection, env: Environment): - r"""Creates service provider - - Parameter: - services: :class:`cpl.dependency.service_collection` - env: :class:`cpl.core.environment.application_environment_abc` - """ diff --git a/src/cpl-auth/cpl/auth/__init__.py b/src/cpl-auth/cpl/auth/__init__.py index f5147636..8eb37acb 100644 --- a/src/cpl-auth/cpl/auth/__init__.py +++ b/src/cpl-auth/cpl/auth/__init__.py @@ -39,7 +39,7 @@ def add_auth(collection: _ServiceCollection): _add_daos(collection) - provider = collection.build_service_provider() + provider = collection.build() migration_service: MigrationService = provider.get_service(MigrationService) if ServerType.server_type == ServerTypes.POSTGRES: migration_service.with_directory( diff --git a/src/cpl-dependency/cpl/dependency/service_collection.py b/src/cpl-dependency/cpl/dependency/service_collection.py index 8d52529d..e1618cbc 100644 --- a/src/cpl-dependency/cpl/dependency/service_collection.py +++ b/src/cpl-dependency/cpl/dependency/service_collection.py @@ -1,8 +1,7 @@ -from typing import Union, Type, Callable, Optional +from typing import Union, Type, Callable from cpl.core.log.logger import Logger from cpl.core.log.logger_abc import LoggerABC -from cpl.core.pipes.pipe_abc import PipeABC from cpl.core.typing import T, Service from cpl.dependency.service_descriptor import ServiceDescriptor from cpl.dependency.service_lifetime_enum import ServiceLifetimeEnum @@ -46,29 +45,6 @@ class ServiceCollection: return self - def add_module(self, module: str | object): - if not isinstance(module, str): - module = module.__name__ - - 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): - self.add_transient(LoggerABC, Logger) - return self - - def add_pipes(self): - for pipe in PipeABC.__subclasses__(): - self.add_transient(PipeABC, pipe) - return self - def add_singleton(self, service_type: T, service: Service = None): self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.singleton, service) return self @@ -81,7 +57,20 @@ class ServiceCollection: self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.transient, service) return self - def build_service_provider(self) -> ServiceProviderABC: + def build(self) -> ServiceProviderABC: sp = ServiceProvider(self._service_descriptors) ServiceProviderABC.set_global_provider(sp) return sp + + def add_module(self, module: str | object): + if not isinstance(module, str): + module = module.__name__ + + if module not in self._modules: + raise ValueError(f"Module {module} not found") + + self._modules[module](self) + + def add_logging(self): + self.add_transient(LoggerABC, Logger) + return self diff --git a/src/cpl-dependency/cpl/dependency/service_provider.py b/src/cpl-dependency/cpl/dependency/service_provider.py index 28e54cbb..592dd54f 100644 --- a/src/cpl-dependency/cpl/dependency/service_provider.py +++ b/src/cpl-dependency/cpl/dependency/service_provider.py @@ -136,7 +136,7 @@ class ServiceProvider(ServiceProviderABC): else: descriptors.append(copy.deepcopy(descriptor)) - sb = ScopeBuilder(ServiceProvider(descriptors, self._database_context)) + sb = ScopeBuilder(ServiceProvider(descriptors)) return sb.build() def get_service(self, service_type: T, *args, **kwargs) -> Optional[R]: diff --git a/src/cpl-dependency/cpl/dependency/service_provider_abc.py b/src/cpl-dependency/cpl/dependency/service_provider_abc.py index 8e3220e7..99cf078b 100644 --- a/src/cpl-dependency/cpl/dependency/service_provider_abc.py +++ b/src/cpl-dependency/cpl/dependency/service_provider_abc.py @@ -1,7 +1,7 @@ import functools from abc import abstractmethod, ABC from inspect import Signature, signature -from typing import Optional +from typing import Optional, Type from cpl.core.typing import T, R from cpl.dependency.scope_abc import ScopeABC @@ -74,7 +74,7 @@ class ServiceProviderABC(ABC): """ @abstractmethod - def get_service(self, instance_type: T, *args, **kwargs) -> Optional[R]: + def get_service(self, instance_type: Type[T], *args, **kwargs) -> Optional[T]: r"""Returns instance of given type Parameter @@ -88,7 +88,7 @@ class ServiceProviderABC(ABC): """ @abstractmethod - def get_services(self, service_type: T, *args, **kwargs) -> list[Optional[R]]: + def get_services(self, service_type: Type[T], *args, **kwargs) -> list[Optional[T]]: r"""Returns instance of given type Parameter diff --git a/tests/custom/async/src/async/startup.py b/tests/custom/async/src/async/startup.py index 16c9dda3..52913da0 100644 --- a/tests/custom/async/src/async/startup.py +++ b/tests/custom/async/src/async/startup.py @@ -14,4 +14,4 @@ class Startup(AsyncStartupABC): return configuration async def configure_services(self, services: ServiceCollection, environment: Environment) -> ServiceProviderABC: - return services.build_service_provider() + return services.build() diff --git a/tests/custom/database/src/application.py b/tests/custom/database/src/application.py index 6343c77b..8d6e187a 100644 --- a/tests/custom/database/src/application.py +++ b/tests/custom/database/src/application.py @@ -1,6 +1,4 @@ -from typing import Optional - -from cpl.application import ApplicationABC +from cpl.application.abc.application_abc import ApplicationABC from cpl.auth import KeycloakAdmin from cpl.core.console import Console from cpl.core.environment import Environment @@ -16,7 +14,7 @@ class Application(ApplicationABC): def __init__(self, services: ServiceProviderABC): ApplicationABC.__init__(self, services) - self._logger: Optional[LoggerABC] = None + self._logger: LoggerABC = services.get_service(LoggerABC) async def test_daos(self): userDao: UserDao = self._services.get_service(UserDao) @@ -30,9 +28,6 @@ class Application(ApplicationABC): Console.write_line(await userDao.get_all()) - async def configure(self): - self._logger = self._services.get_service(LoggerABC) - async def main(self): self._logger.debug(f"Host: {Environment.get_host_name()}") self._logger.debug(f"Environment: {Environment.get_environment()}") diff --git a/tests/custom/database/src/main.py b/tests/custom/database/src/main.py index 0fcf389d..862e88aa 100644 --- a/tests/custom/database/src/main.py +++ b/tests/custom/database/src/main.py @@ -3,15 +3,11 @@ from cpl.application import ApplicationBuilder from startup import Startup -async def main(): - app_builder = ApplicationBuilder(Application) - app_builder.use_startup(Startup) - app = await app_builder.build_async() - await app.run_async() +def main(): + builder = ApplicationBuilder(Application).use_startup(Startup) + app = builder.build() + app.run() if __name__ == "__main__": - import asyncio - - loop = asyncio.get_event_loop() - loop.run_until_complete(main()) + main() diff --git a/tests/custom/database/src/main_simplified.py b/tests/custom/database/src/main_simplified.py new file mode 100644 index 00000000..cc463bf8 --- /dev/null +++ b/tests/custom/database/src/main_simplified.py @@ -0,0 +1,15 @@ +from application import Application +from cpl.application import ApplicationBuilder +from cpl.core.console import Console +from startup import Startup + + +def main(): + builder = ApplicationBuilder(Application).use_startup(Startup) + app = builder.build() + app.run() + Console.write_line("Hello from main_simplified.py!") + + +if __name__ == "__main__": + main() diff --git a/tests/custom/database/src/startup.py b/tests/custom/database/src/startup.py index d05782b5..137a7698 100644 --- a/tests/custom/database/src/startup.py +++ b/tests/custom/database/src/startup.py @@ -1,5 +1,5 @@ from cpl import auth -from cpl.application.async_startup_abc import AsyncStartupABC +from cpl.application.abc.startup_abc import StartupABC from cpl.auth import permission from cpl.auth.permission.permissions_registry import PermissionsRegistry from cpl.core.configuration import Configuration @@ -15,16 +15,16 @@ from model.city_dao import CityDao from model.user_dao import UserDao -class Startup(AsyncStartupABC): +class Startup(StartupABC): def __init__(self): - AsyncStartupABC.__init__(self) + StartupABC.__init__(self) - async def configure_configuration(self, configuration: Configuration, environment: Environment): - configuration.add_json_file(f"appsettings.json") - configuration.add_json_file(f"appsettings.{environment.get_environment()}.json") - configuration.add_json_file(f"appsettings.{environment.get_host_name()}.json", optional=True) + async def configure_configuration(self): + Configuration.add_json_file(f"appsettings.json") + Configuration.add_json_file(f"appsettings.{Environment.get_environment()}.json") + Configuration.add_json_file(f"appsettings.{Environment.get_host_name()}.json", optional=True) - async def configure_services(self, services: ServiceCollection, environment: Environment): + async def configure_services(self, services: ServiceCollection): services.add_module(mysql) services.add_module(auth) services.add_module(permission) @@ -36,7 +36,7 @@ class Startup(AsyncStartupABC): PermissionsRegistry.with_enum(CustomPermissions) - provider = services.build_service_provider() + provider = services.build() migration_service: MigrationService = provider.get_service(MigrationService) migration_service.with_directory("./scripts") diff --git a/tests/custom/di/src/di/startup.py b/tests/custom/di/src/di/startup.py index ccf5b948..771724fd 100644 --- a/tests/custom/di/src/di/startup.py +++ b/tests/custom/di/src/di/startup.py @@ -25,4 +25,4 @@ class Startup(StartupABC): services.add_singleton(TestABC, Test2Service) services.add_singleton(Tester) - return services.build_service_provider() + return services.build() diff --git a/tests/custom/general/src/general/application.py b/tests/custom/general/src/general/application.py index 8df62215..106f7fba 100644 --- a/tests/custom/general/src/general/application.py +++ b/tests/custom/general/src/general/application.py @@ -1,7 +1,7 @@ import time from typing import Optional -from cpl.application.application_abc import ApplicationABC +from cpl.application.abc import ApplicationABC from cpl.core.configuration import Configuration from cpl.core.console import Console from cpl.dependency import ServiceProviderABC @@ -18,8 +18,8 @@ class Application(ApplicationABC): def __init__(self, services: ServiceProviderABC): ApplicationABC.__init__(self, services) - self._logger: Optional[LoggerABC] = None - self._mailer: Optional[EMailClientABC] = None + self._logger = self._services.get_service(LoggerABC) + self._mailer = self._services.get_service(EMailClientABC) def test_send_mail(self): mail = EMail() @@ -35,10 +35,6 @@ class Application(ApplicationABC): def _wait(time_ms: int): time.sleep(time_ms) - def configure(self): - self._logger = self._services.get_service(LoggerABC) - self._mailer = self._services.get_service(EMailClientABC) - def main(self): self._logger.debug(f"Host: {Environment.get_host_name()}") self._logger.debug(f"Environment: {Environment.get_environment()}") diff --git a/tests/custom/general/src/general/startup.py b/tests/custom/general/src/general/startup.py index 3fb5a215..59f8cc83 100644 --- a/tests/custom/general/src/general/startup.py +++ b/tests/custom/general/src/general/startup.py @@ -1,5 +1,5 @@ from cpl import mail -from cpl.application import StartupABC +from cpl.application.abc import StartupABC from cpl.core.configuration import Configuration from cpl.dependency import ServiceCollection, ServiceProviderABC from cpl.core.environment import Environment @@ -11,12 +11,12 @@ class Startup(StartupABC): def __init__(self): StartupABC.__init__(self) - def configure_configuration(self, config: Configuration, env: Environment): - config.add_json_file(f"appsettings.json") - config.add_json_file(f"appsettings.{env.get_environment()}.json") - config.add_json_file(f"appsettings.{env.get_host_name()}.json", optional=True) + def configure_configuration(selft): + Configuration.add_json_file(f"appsettings.json") + Configuration.add_json_file(f"appsettings.{Environment.get_environment()}.json") + Configuration.add_json_file(f"appsettings.{Environment.get_host_name()}.json", optional=True) - def configure_services(self, services: ServiceCollection, env: Environment): + def configure_services(self, services: ServiceCollection): services.add_logging() services.add_module(mail) services.add_transient(IPAddressPipe) diff --git a/tests/custom/general/src/general/test_extension.py b/tests/custom/general/src/general/test_extension.py index 82c1942a..fdee87bc 100644 --- a/tests/custom/general/src/general/test_extension.py +++ b/tests/custom/general/src/general/test_extension.py @@ -1,5 +1,4 @@ -from cpl.application import ApplicationExtensionABC -from cpl.core.configuration import Configuration +from cpl.application.abc import ApplicationExtensionABC from cpl.core.console import Console from cpl.dependency import ServiceProviderABC @@ -8,5 +7,5 @@ class TestExtension(ApplicationExtensionABC): def __init__(self): ApplicationExtensionABC.__init__(self) - def run(self, config: Configuration, services: ServiceProviderABC): + def run(self, services: ServiceProviderABC): Console.write_line("Hello World from App Extension") diff --git a/tests/custom/general/src/general/test_startup_extension.py b/tests/custom/general/src/general/test_startup_extension.py index 5a912d2d..5ecdb61b 100644 --- a/tests/custom/general/src/general/test_startup_extension.py +++ b/tests/custom/general/src/general/test_startup_extension.py @@ -1,4 +1,4 @@ -from cpl.application import StartupExtensionABC +from cpl.application.abc import StartupExtensionABC from cpl.core.configuration import Configuration from cpl.core.console import Console from cpl.dependency import ServiceCollection @@ -9,8 +9,8 @@ class TestStartupExtension(StartupExtensionABC): def __init__(self): StartupExtensionABC.__init__(self) - def configure_configuration(self, config: Configuration, env: Environment): + def configure_configuration(self): Console.write_line("config") - def configure_services(self, services: ServiceCollection, env: Environment): + def configure_services(self, services: ServiceCollection): Console.write_line("services") diff --git a/tests/custom/translation/src/translation/startup.py b/tests/custom/translation/src/translation/startup.py index b0a5fa44..7d411ac3 100644 --- a/tests/custom/translation/src/translation/startup.py +++ b/tests/custom/translation/src/translation/startup.py @@ -14,4 +14,4 @@ class Startup(StartupABC): def configure_services(self, services: ServiceCollection, environment: Environment) -> ServiceProviderABC: services.add_translation() - return services.build_service_provider() + return services.build() diff --git a/unittests/unittests_core/configuration/configuration_test_case.py b/unittests/unittests_core/configuration/configuration_test_case.py index 614c0372..a3a339b6 100644 --- a/unittests/unittests_core/configuration/configuration_test_case.py +++ b/unittests/unittests_core/configuration/configuration_test_case.py @@ -61,7 +61,7 @@ class ConfigurationTestCase(unittest.TestCase): self._config.create_console_argument(ArgumentTypeEnum.Variable, "", "var", [], "=") self.assertIsNone(self._config.get_configuration("var")) - self._config.parse_console_arguments(sc.build_service_provider()) + self._config.parse_console_arguments(sc.build()) mocked_exec.run.assert_called() self.assertEqual("test", self._config.get_configuration("var")) diff --git a/unittests/unittests_core/configuration/console_arguments_test_case.py b/unittests/unittests_core/configuration/console_arguments_test_case.py index d4e2db7f..c5552024 100644 --- a/unittests/unittests_core/configuration/console_arguments_test_case.py +++ b/unittests/unittests_core/configuration/console_arguments_test_case.py @@ -31,28 +31,28 @@ class ConsoleArgumentsTestCase(unittest.TestCase): def test_flag(self): sys.argv.append("flag") - self._config.parse_console_arguments(self._sc.build_service_provider()) + self._config.parse_console_arguments(self._sc.build()) self.assertIn("flag", self._config.additional_arguments) def test_var(self): sys.argv.append("var=1") sys.argv.append("var2=1") - self._config.parse_console_arguments(self._sc.build_service_provider()) + self._config.parse_console_arguments(self._sc.build()) self.assertEqual("1", self._config.get_configuration("var")) self.assertIsNone(self._config.get_configuration("var1")) def test_exec(self): sys.argv.append("exec") - self._config.parse_console_arguments(self._sc.build_service_provider()) + self._config.parse_console_arguments(self._sc.build()) self._mocked_exec.run.assert_called() def test_exec_with_one_flag(self): sys.argv.append("exec") sys.argv.append("--dev") - self._config.parse_console_arguments(self._sc.build_service_provider()) + self._config.parse_console_arguments(self._sc.build()) self._mocked_exec.run.assert_called() self.assertIn("dev", self._config.additional_arguments) @@ -60,7 +60,7 @@ class ConsoleArgumentsTestCase(unittest.TestCase): sys.argv.append("exec") sys.argv.append("--d") - self._config.parse_console_arguments(self._sc.build_service_provider()) + self._config.parse_console_arguments(self._sc.build()) self._mocked_exec.run.assert_called() self.assertIn("dev", self._config.additional_arguments) @@ -69,7 +69,7 @@ class ConsoleArgumentsTestCase(unittest.TestCase): sys.argv.append("--dev") sys.argv.append("--virtual") - self._config.parse_console_arguments(self._sc.build_service_provider()) + self._config.parse_console_arguments(self._sc.build()) self._mocked_exec.run.assert_called() self.assertIn("dev", self._config.additional_arguments) self.assertIn("virtual", self._config.additional_arguments) diff --git a/unittests/unittests_core/di/service_collection_test_case.py b/unittests/unittests_core/di/service_collection_test_case.py index a75fda9a..b9f6453c 100644 --- a/unittests/unittests_core/di/service_collection_test_case.py +++ b/unittests/unittests_core/di/service_collection_test_case.py @@ -50,7 +50,7 @@ class ServiceCollectionTestCase(unittest.TestCase): self._sc.add_singleton(Mock) service = self._sc._service_descriptors[0] self.assertIsNone(service.implementation) - sp = self._sc.build_service_provider() + sp = self._sc.build() self.assertTrue(isinstance(sp, ServiceProviderABC)) self.assertTrue(isinstance(sp.get_service(Mock), Mock)) self.assertIsNotNone(service.implementation) diff --git a/unittests/unittests_core/di/service_provider_test_case.py b/unittests/unittests_core/di/service_provider_test_case.py index e6d6bc81..68dcc443 100644 --- a/unittests/unittests_core/di/service_provider_test_case.py +++ b/unittests/unittests_core/di/service_provider_test_case.py @@ -39,7 +39,7 @@ class ServiceProviderTestCase(unittest.TestCase): .add_singleton(TestService) .add_transient(DifferentService) .add_scoped(MoreDifferentService) - .build_service_provider() + .build() ) count = self._services.get_service(ServiceCount)