From 4b829cc4842dfaeec2f92aa92493a705a10aced4 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 14 Nov 2021 12:16:50 +0100 Subject: [PATCH] Added logic to handle async applicationBase --- src/cpl_core/application/application_abc.py | 22 ++++++++++ .../application/application_builder.py | 16 ++++++- .../application/application_builder_abc.py | 21 +++++++++ .../application/application_extension_abc.py | 3 ++ src/tests/custom/async/LICENSE | 0 src/tests/custom/async/README.md | 0 src/tests/custom/async/appsettings.json | 15 +++++++ src/tests/custom/async/cpl-workspace.json | 9 ++++ src/tests/custom/async/src/async/__init__.py | 1 + .../custom/async/src/async/application.py | 16 +++++++ src/tests/custom/async/src/async/async.json | 43 +++++++++++++++++++ src/tests/custom/async/src/async/main.py | 17 ++++++++ src/tests/custom/async/src/async/startup.py | 16 +++++++ src/tests/custom/async/src/tests/__init__.py | 1 + src/tests/custom/di/src/di/application.py | 6 +-- 15 files changed, 181 insertions(+), 5 deletions(-) create mode 100644 src/tests/custom/async/LICENSE create mode 100644 src/tests/custom/async/README.md create mode 100644 src/tests/custom/async/appsettings.json create mode 100644 src/tests/custom/async/cpl-workspace.json create mode 100644 src/tests/custom/async/src/async/__init__.py create mode 100644 src/tests/custom/async/src/async/application.py create mode 100644 src/tests/custom/async/src/async/async.json create mode 100644 src/tests/custom/async/src/async/main.py create mode 100644 src/tests/custom/async/src/async/startup.py create mode 100644 src/tests/custom/async/src/tests/__init__.py diff --git a/src/cpl_core/application/application_abc.py b/src/cpl_core/application/application_abc.py index 3c64d944..37d28d26 100644 --- a/src/cpl_core/application/application_abc.py +++ b/src/cpl_core/application/application_abc.py @@ -34,6 +34,28 @@ class ApplicationABC(ABC): self.main() except KeyboardInterrupt: Console.close() + + 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): diff --git a/src/cpl_core/application/application_builder.py b/src/cpl_core/application/application_builder.py index 27ccb762..c434c6ec 100644 --- a/src/cpl_core/application/application_builder.py +++ b/src/cpl_core/application/application_builder.py @@ -1,4 +1,3 @@ -import types from typing import Type, Optional, Callable from cpl_core.application.application_abc import ApplicationABC @@ -6,7 +5,6 @@ from cpl_core.application.application_builder_abc import ApplicationBuilderABC from cpl_core.application.application_extension_abc import ApplicationExtensionABC from cpl_core.application.startup_abc import StartupABC from cpl_core.configuration.configuration import Configuration -from cpl_core.console import Console from cpl_core.dependency_injection.service_collection import ServiceCollection @@ -50,3 +48,17 @@ class ApplicationBuilder(ApplicationBuilderABC): extension.run(config, services) return self._app(config, services) + + async def build_async(self) -> ApplicationABC: + if self._startup is not None: + await self._startup.configure_configuration(self._configuration, self._environment) + await self._startup.configure_services(self._services, self._environment) + + config = self._configuration + services = self._services.build_service_provider() + + for ex in self._extensions: + extension = ex() + await extension.run(config, services) + + return self._app(config, services) diff --git a/src/cpl_core/application/application_builder_abc.py b/src/cpl_core/application/application_builder_abc.py index dff8e6f8..2ced6ad1 100644 --- a/src/cpl_core/application/application_builder_abc.py +++ b/src/cpl_core/application/application_builder_abc.py @@ -23,6 +23,17 @@ class ApplicationBuilderABC(ABC): """ pass + @abstractmethod + async def use_startup(self, startup: Type[StartupABC]): + r"""Sets the custom startup class to use async + + Parameter + --------- + startup: Type[:class:`cpl_core.application.startup_abc.StartupABC`] + Startup class to use + """ + pass + @abstractmethod def build(self) -> ApplicationABC: r"""Creates custom application object @@ -32,3 +43,13 @@ class ApplicationBuilderABC(ABC): Object of :class:`cpl_core.application.application_abc.ApplicationABC` """ pass + + @abstractmethod + async def build_async(self) -> ApplicationABC: + r"""Creates custom application object async + + Returns + ------- + Object of :class:`cpl_core.application.application_abc.ApplicationABC` + """ + pass diff --git a/src/cpl_core/application/application_extension_abc.py b/src/cpl_core/application/application_extension_abc.py index 0a6dfc20..a7092fcf 100644 --- a/src/cpl_core/application/application_extension_abc.py +++ b/src/cpl_core/application/application_extension_abc.py @@ -11,3 +11,6 @@ class ApplicationExtensionABC(ABC): @abstractmethod def run(self, config: ConfigurationABC, services: ServiceProviderABC): pass + + @abstractmethod + async def run(self, config: ConfigurationABC, services: ServiceProviderABC): pass diff --git a/src/tests/custom/async/LICENSE b/src/tests/custom/async/LICENSE new file mode 100644 index 00000000..e69de29b diff --git a/src/tests/custom/async/README.md b/src/tests/custom/async/README.md new file mode 100644 index 00000000..e69de29b diff --git a/src/tests/custom/async/appsettings.json b/src/tests/custom/async/appsettings.json new file mode 100644 index 00000000..629e6ebd --- /dev/null +++ b/src/tests/custom/async/appsettings.json @@ -0,0 +1,15 @@ +{ + "TimeFormatSettings": { + "DateFormat": "%Y-%m-%d", + "TimeFormat": "%H:%M:%S", + "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", + "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" + }, + + "LoggingSettings": { + "Path": "logs/", + "Filename": "log_$start_time.log", + "ConsoleLogLevel": "ERROR", + "FileLogLevel": "WARN" + } +} diff --git a/src/tests/custom/async/cpl-workspace.json b/src/tests/custom/async/cpl-workspace.json new file mode 100644 index 00000000..fc78d6ed --- /dev/null +++ b/src/tests/custom/async/cpl-workspace.json @@ -0,0 +1,9 @@ +{ + "WorkspaceSettings": { + "DefaultProject": "async", + "Projects": { + "async": "src/async/async.json" + }, + "Scripts": {} + } +} \ No newline at end of file diff --git a/src/tests/custom/async/src/async/__init__.py b/src/tests/custom/async/src/async/__init__.py new file mode 100644 index 00000000..ad5eca30 --- /dev/null +++ b/src/tests/custom/async/src/async/__init__.py @@ -0,0 +1 @@ +# imports: diff --git a/src/tests/custom/async/src/async/application.py b/src/tests/custom/async/src/async/application.py new file mode 100644 index 00000000..b2df0250 --- /dev/null +++ b/src/tests/custom/async/src/async/application.py @@ -0,0 +1,16 @@ +from cpl_core.application import ApplicationABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.console import Console +from cpl_core.dependency_injection import ServiceProviderABC + + +class Application(ApplicationABC): + + def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): + ApplicationABC.__init__(self, config, services) + + async def configure(self): + pass + + async def main(self): + Console.write_line('Hello World') diff --git a/src/tests/custom/async/src/async/async.json b/src/tests/custom/async/src/async/async.json new file mode 100644 index 00000000..7e632a65 --- /dev/null +++ b/src/tests/custom/async/src/async/async.json @@ -0,0 +1,43 @@ +{ + "ProjectSettings": { + "Name": "async", + "Version": { + "Major": "0", + "Minor": "0", + "Micro": "0" + }, + "Author": "", + "AuthorEmail": "", + "Description": "", + "LongDescription": "", + "URL": "", + "CopyrightDate": "", + "CopyrightName": "", + "LicenseName": "", + "LicenseDescription": "", + "Dependencies": [ + "sh_cpl>=2021.10.0.post1" + ], + "PythonVersion": ">=3.9.2", + "PythonPath": { + "linux": "" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "console", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "async.main", + "EntryPoint": "async", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/src/tests/custom/async/src/async/main.py b/src/tests/custom/async/src/async/main.py new file mode 100644 index 00000000..0cde844e --- /dev/null +++ b/src/tests/custom/async/src/async/main.py @@ -0,0 +1,17 @@ +import asyncio +from cpl_core.application import ApplicationBuilder + +from application import Application +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() + + +if __name__ == '__main__': + loop = asyncio.get_event_loop() + loop.run_until_complete(main()) diff --git a/src/tests/custom/async/src/async/startup.py b/src/tests/custom/async/src/async/startup.py new file mode 100644 index 00000000..dadaee3b --- /dev/null +++ b/src/tests/custom/async/src/async/startup.py @@ -0,0 +1,16 @@ +from cpl_core.application import StartupABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC +from cpl_core.environment import ApplicationEnvironment + + +class Startup(StartupABC): + + def __init__(self): + StartupABC.__init__(self) + + async def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: + return configuration + + async def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: + return services.build_service_provider() diff --git a/src/tests/custom/async/src/tests/__init__.py b/src/tests/custom/async/src/tests/__init__.py new file mode 100644 index 00000000..ad5eca30 --- /dev/null +++ b/src/tests/custom/async/src/tests/__init__.py @@ -0,0 +1 @@ +# imports: diff --git a/src/tests/custom/di/src/di/application.py b/src/tests/custom/di/src/di/application.py index e9f0b4bf..ec91c6ad 100644 --- a/src/tests/custom/di/src/di/application.py +++ b/src/tests/custom/di/src/di/application.py @@ -30,9 +30,9 @@ class Application(ApplicationABC): b = t.service_provider scope1.dispose() - Console.write_line('Disposed:') - ts1: TestService = scope1.service_provider.get_service(TestService) - ts1.run() + #Console.write_line('Disposed:') + #ts1: TestService = scope1.service_provider.get_service(TestService) + #ts1.run() Console.write_line('Scope2') scope2: Scope = self._services.create_scope()