diff --git a/src/cpl_core/application/application_builder.py b/src/cpl_core/application/application_builder.py index 379e1216..c879ae69 100644 --- a/src/cpl_core/application/application_builder.py +++ b/src/cpl_core/application/application_builder.py @@ -54,6 +54,7 @@ class ApplicationBuilder(ApplicationBuilderABC): config = self._configuration services = self._services.build_service_provider() + config.resolve_runnable_argument_types(services) for ex in self._app_extensions: extension = ex() diff --git a/src/cpl_core/configuration/configuration.py b/src/cpl_core/configuration/configuration.py index e11b5771..573793bb 100644 --- a/src/cpl_core/configuration/configuration.py +++ b/src/cpl_core/configuration/configuration.py @@ -8,8 +8,10 @@ from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl_core.configuration.configuration_variable_name_enum import ConfigurationVariableNameEnum from cpl_core.configuration.console_argument import ConsoleArgument +from cpl_core.configuration.runnable_argument_abc import RunnableArgumentABC from cpl_core.console.console import Console from cpl_core.console.foreground_color_enum import ForegroundColorEnum +from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.environment.application_environment import ApplicationEnvironment from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC from cpl_core.environment.environment_name_enum import EnvironmentNameEnum @@ -378,8 +380,15 @@ class Configuration(ConfigurationABC): def add_configuration(self, key_type: Union[str, type], value: ConfigurationModelABC): self._config[key_type] = value + def create_console_argument(self, token: str, name: str, aliases: list[str], value_token: str, + is_value_token_optional: bool = None, + runnable: Type[RunnableArgumentABC] = None) -> ConsoleArgument: + argument = ConsoleArgument(token, name, aliases, value_token, is_value_token_optional, runnable) + self.add_console_argument(argument) + return argument + def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> \ - Union[str, ConfigurationModelABC]: + Optional[Union[str, ConfigurationModelABC]]: if type(search_type) is str: if search_type == ConfigurationVariableNameEnum.environment.value: return self._application_environment.environment_name @@ -396,3 +405,7 @@ class Configuration(ConfigurationABC): for config_model in self._config: if config_model == search_type: return self._config[config_model] + + def resolve_runnable_argument_types(self, services: ServiceProviderABC): + for arg in self._argument_types: + arg.set_runnable(services.get_service(arg.runnable_type)) diff --git a/src/cpl_core/configuration/configuration_abc.py b/src/cpl_core/configuration/configuration_abc.py index a2961cda..5307f924 100644 --- a/src/cpl_core/configuration/configuration_abc.py +++ b/src/cpl_core/configuration/configuration_abc.py @@ -4,6 +4,7 @@ from typing import Type, Union, Optional from cpl_core.configuration.console_argument import ConsoleArgument from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC +from cpl_core.configuration.runnable_argument_abc import RunnableArgumentABC from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC @@ -94,7 +95,35 @@ class ConfigurationABC(ABC): pass @abstractmethod - def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> Union[str, ConfigurationModelABC]: + def create_console_argument(self, token: str, name: str, aliases: list[str], value_token: str, + is_value_token_optional: bool = None, + runnable: Type[RunnableArgumentABC] = None) -> ConsoleArgument: + r"""Creates and adds a console argument to known console arguments + + Parameter + --------- + token: :class:`str` + Specifies optional beginning of argument + name :class:`str` + Specifies name of argument + aliases list[:class:`str`] + Specifies possible aliases of name + value_token :class:`str` + Specifies were the value begins + is_value_token_optional :class:`bool` + Specifies if values are optional + runnable: :class:`cpl_core.configuration.console_argument.ConsoleArgument` + Specifies class to run when called if value is not None + + Returns + ------ + Object of :class:`cpl_core.configuration.console_argument.ConsoleArgument` + """ + pass + + @abstractmethod + def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> Union[ + str, ConfigurationModelABC]: r"""Returns value from configuration by given type Parameter @@ -107,3 +136,14 @@ class ConfigurationABC(ABC): Object of Union[:class:`str`, :class:`cpl_core.configuration.configuration_model_abc.ConfigurationModelABC`] """ pass + + @abstractmethod + def resolve_runnable_argument_types(self, services: 'ServiceProviderABC'): + r"""Gets all objects for given types of ConsoleArguments + + Parameter + --------- + services: :class:`cpl_core.dependency_injection.service_provider_abc.ServiceProviderABC` + Provides services + """ + pass diff --git a/src/cpl_core/configuration/console_argument.py b/src/cpl_core/configuration/console_argument.py index 6407aa5f..5508d73a 100644 --- a/src/cpl_core/configuration/console_argument.py +++ b/src/cpl_core/configuration/console_argument.py @@ -1,3 +1,8 @@ +from typing import Type, Optional + +from cpl_core.configuration.runnable_argument_abc import RunnableArgumentABC + + class ConsoleArgument: def __init__(self, @@ -6,6 +11,7 @@ class ConsoleArgument: aliases: list[str], value_token: str, is_value_token_optional: bool = None, + runnable: Type[RunnableArgumentABC] = None, console_arguments: list['ConsoleArgument'] = None ): r"""Representation of an console argument @@ -17,6 +23,7 @@ class ConsoleArgument: aliases: list[:class:`str`] value_token: :class:`str` is_value_token_optional: :class:`bool` + runnable: :class:`cpl_core.configuration.console_argument.ConsoleArgument` console_arguments: List[:class:`cpl_core.configuration.console_argument.ConsoleArgument`] """ self._token = token @@ -24,7 +31,9 @@ class ConsoleArgument: self._aliases = aliases self._value_token = value_token self._is_value_token_optional = is_value_token_optional - self._console_arguments = console_arguments + self._console_arguments = console_arguments if console_arguments is not None else [] + self._runnable_type = runnable + self._runnable: Optional[RunnableArgumentABC] = None @property def token(self) -> str: @@ -41,7 +50,7 @@ class ConsoleArgument: @property def value_token(self) -> str: return self._value_token - + @property def is_value_token_optional(self) -> bool: return self._is_value_token_optional @@ -49,3 +58,42 @@ class ConsoleArgument: @property def console_arguments(self) -> list['ConsoleArgument']: return self._console_arguments + + @property + def runnable_type(self) -> Type[RunnableArgumentABC]: + return self._runnable_type + + def set_runnable(self, runnable: RunnableArgumentABC): + self._runnable = runnable + + def add_console_argument(self, token: str, name: str, aliases: list[str], value_token: str, + is_value_token_optional: bool = None) -> 'ConsoleArgument': + r"""Creates and adds a console argument to known console arguments + + Parameter + --------- + token: :class:`str` + Specifies optional beginning of argument + name :class:`str` + Specifies name of argument + aliases list[:class:`str`] + Specifies possible aliases of name + value_token :class:`str` + Specifies were the value begins + is_value_token_optional :class:`bool` + Specifies if values are optional + + Returns + ------ + self :class:`cpl_core.configuration.console_argument.ConsoleArgument` not created argument! + """ + argument = ConsoleArgument(token, name, aliases, value_token, is_value_token_optional) + self._console_arguments.append(argument) + return self + + def run(self, args: list[str]): + r"""Executes runnable if exists + """ + if self._runnable is None: + return + self._runnable.run(args) diff --git a/src/cpl_core/configuration/runnable_argument_abc.py b/src/cpl_core/configuration/runnable_argument_abc.py new file mode 100644 index 00000000..ae1a7c25 --- /dev/null +++ b/src/cpl_core/configuration/runnable_argument_abc.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod + + +class RunnableArgumentABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + def run(self, args: list[str]): pass diff --git a/src/tests/custom/general/src/general/arguments/__init__.py b/src/tests/custom/general/src/general/arguments/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/tests/custom/general/src/general/arguments/generate_argument.py b/src/tests/custom/general/src/general/arguments/generate_argument.py new file mode 100644 index 00000000..da71112f --- /dev/null +++ b/src/tests/custom/general/src/general/arguments/generate_argument.py @@ -0,0 +1,11 @@ +from cpl_core.configuration.runnable_argument_abc import RunnableArgumentABC +from cpl_core.console import Console + + +class GenerateArgument(RunnableArgumentABC): + + def __init__(self): + RunnableArgumentABC.__init__(self) + + def run(self, args: list[str]): + Console.write_line('Generate:', args) diff --git a/src/tests/custom/general/src/general/arguments/install_argument.py b/src/tests/custom/general/src/general/arguments/install_argument.py new file mode 100644 index 00000000..8f62c3b7 --- /dev/null +++ b/src/tests/custom/general/src/general/arguments/install_argument.py @@ -0,0 +1,11 @@ +from cpl_core.configuration.runnable_argument_abc import RunnableArgumentABC +from cpl_core.console import Console + + +class InstallArgument(RunnableArgumentABC): + + def __init__(self): + RunnableArgumentABC.__init__(self) + + def run(self, args: list[str]): + Console.write_line('Install:', args) diff --git a/src/tests/custom/general/src/general/main.py b/src/tests/custom/general/src/general/main.py index 67191b28..369279de 100644 --- a/src/tests/custom/general/src/general/main.py +++ b/src/tests/custom/general/src/general/main.py @@ -3,11 +3,13 @@ from cpl_core.application import ApplicationBuilder from test_extension import TestExtension from startup import Startup from test_startup_extension import TestStartupExtension +from parameter_startup import ParameterStartup def main(): app_builder = ApplicationBuilder(Application) app_builder.use_startup(Startup) + app_builder.use_extension(ParameterStartup) app_builder.use_extension(TestStartupExtension) app_builder.use_extension(TestExtension) app_builder.build().run() diff --git a/src/tests/custom/general/src/general/parameter_startup.py b/src/tests/custom/general/src/general/parameter_startup.py new file mode 100644 index 00000000..629f1758 --- /dev/null +++ b/src/tests/custom/general/src/general/parameter_startup.py @@ -0,0 +1,31 @@ +from cpl_core.application import StartupExtensionABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceCollectionABC +from cpl_core.environment import ApplicationEnvironmentABC +from arguments.generate_argument import GenerateArgument +from arguments.install_argument import InstallArgument + + +class ParameterStartup(StartupExtensionABC): + + def __init__(self): + StartupExtensionABC.__init__(self) + + def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): + config.create_console_argument('', 'generate', ['g', 'G'], '', runnable=GenerateArgument) \ + .add_console_argument('', 'abc', ['a', 'A'], ' ') \ + .add_console_argument('', 'class', ['c', 'C'], ' ') \ + .add_console_argument('', 'enum', ['e', 'E'], ' ') \ + .add_console_argument('', 'service', ['s', 'S'], ' ') \ + .add_console_argument('', 'settings', ['st', 'ST'], ' ') \ + .add_console_argument('', 'thread', ['t', 'T'], ' ') \ + .add_console_argument('-', 'o', ['o', 'O'], '=') + config.create_console_argument('', 'install', ['i', 'I'], ' ', is_value_token_optional=True, + runnable=InstallArgument) \ + .add_console_argument('--', 'virtual', ['v', 'V'], '') \ + .add_console_argument('--', 'simulate', ['s', 'S'], '') + + def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): + services \ + .add_singleton(GenerateArgument) \ + .add_singleton(InstallArgument)