diff --git a/src/cpl_cli/cli.py b/src/cpl_cli/cli.py index 9a833a86..3a11e4e7 100644 --- a/src/cpl_cli/cli.py +++ b/src/cpl_cli/cli.py @@ -33,32 +33,33 @@ class CLI(ApplicationABC): """ ApplicationABC.__init__(self, config, services) - self._command_handler: Optional[CommandHandler] = None + # self._command_handler: Optional[CommandHandler] = None self._options: list[str] = [] def configure(self): - self._command_handler: CommandHandler = self._services.get_service(CommandHandler) - - self._command_handler.add_command(CommandModel('add', ['a', 'a'], AddService, False, False, False)) - self._command_handler.add_command(CommandModel('build', ['b', 'B'], BuildService, False, True, True)) - self._command_handler.add_command(CommandModel('generate', ['g', 'G'], GenerateService, False, True, False)) - self._command_handler.add_command(CommandModel('help', ['h', 'H'], HelpService, False, False, False)) - self._command_handler.add_command(CommandModel('install', ['i', 'I'], InstallService, False, True, True)) - self._command_handler.add_command(CommandModel('new', ['n', 'N'], NewService, False, False, True)) - self._command_handler.add_command(CommandModel('publish', ['p', 'P'], PublishService, False, True, True)) - self._command_handler.add_command(CommandModel('remove', ['r', 'R'], RemoveService, True, True, False)) - self._command_handler.add_command(CommandModel('start', ['s', 'S'], StartService, False, True, True)) - self._command_handler.add_command(CommandModel('uninstall', ['ui', 'UI'], UninstallService, False, True, True)) - self._command_handler.add_command(CommandModel('update', ['u', 'U'], UpdateService, False, True, True)) - self._command_handler.add_command(CommandModel('version', ['v', 'V'], VersionService, False, False, False)) - - if os.path.isfile(os.path.join(self._environment.working_directory, 'cpl-workspace.json')): - workspace: Optional[WorkspaceSettings] = self._configuration.get_configuration(WorkspaceSettings) - for script in workspace.scripts: - self._command_handler.add_command(CommandModel(script, [], CustomScriptService, True, True, False)) - - self._command_handler.add_command(CommandModel('--help', ['-h', '-H'], HelpService, False, False, False)) - self._options.append('--help') + pass + # self._command_handler: CommandHandler = self._services.get_service(CommandHandler) + # + # self._command_handler.add_command(CommandModel('add', ['a', 'a'], AddService, False, False, False)) + # self._command_handler.add_command(CommandModel('build', ['b', 'B'], BuildService, False, True, True)) + # self._command_handler.add_command(CommandModel('generate', ['g', 'G'], GenerateService, False, True, False)) + # self._command_handler.add_command(CommandModel('help', ['h', 'H'], HelpService, False, False, False)) + # self._command_handler.add_command(CommandModel('install', ['i', 'I'], InstallService, False, True, True)) + # self._command_handler.add_command(CommandModel('new', ['n', 'N'], NewService, False, False, True)) + # self._command_handler.add_command(CommandModel('publish', ['p', 'P'], PublishService, False, True, True)) + # self._command_handler.add_command(CommandModel('remove', ['r', 'R'], RemoveService, True, True, False)) + # self._command_handler.add_command(CommandModel('start', ['s', 'S'], StartService, False, True, True)) + # self._command_handler.add_command(CommandModel('uninstall', ['ui', 'UI'], UninstallService, False, True, True)) + # self._command_handler.add_command(CommandModel('update', ['u', 'U'], UpdateService, False, True, True)) + # self._command_handler.add_command(CommandModel('version', ['v', 'V'], VersionService, False, False, False)) + # + # if os.path.isfile(os.path.join(self._environment.working_directory, 'cpl-workspace.json')): + # workspace: Optional[WorkspaceSettings] = self._configuration.get_configuration(WorkspaceSettings) + # for script in workspace.scripts: + # self._command_handler.add_command(CommandModel(script, [], CustomScriptService, True, True, False)) + # + # self._command_handler.add_command(CommandModel('--help', ['-h', '-H'], HelpService, False, False, False)) + # self._options.append('--help') def main(self): """ @@ -66,61 +67,62 @@ class CLI(ApplicationABC): :return: """ try: - command = None - args = [] - if len(self._configuration.additional_arguments) > 0: - is_option = False - for opt in self._options: - if opt in self._configuration.additional_arguments: - is_option = True - command = opt - args = self._configuration.additional_arguments - args.remove(opt) - - if not is_option: - command = self._configuration.additional_arguments[0] - if len(self._configuration.additional_arguments) > 1: - args = self._configuration.additional_arguments[1:] - else: - for cmd in self._command_handler.commands: - result = self._configuration.get_configuration(cmd.name) - result_args: list[str] = self._configuration.get_configuration(f'{cmd.name}AdditionalArguments') - is_option = False - if result is None: - continue - - for opt in self._options: - if opt == result: - is_option = True - command = opt - - elif result_args is not None and opt in result_args: - is_option = True - command = opt - result_args.remove(opt) - - if is_option: - args.append(cmd.name) - if result_args is not None: - for arg in result_args: - args.append(arg) - - elif result is not None: - command = cmd.name - args.append(result) - - for arg in result_args: - args.append(arg) - - else: - Error.error(f'Unexpected command') - return - - if command is None: - Error.error(f'Expected command') - return - - self._command_handler.handle(command, args) + pass + # command = None + # args = [] + # if len(self._configuration.additional_arguments) > 0: + # is_option = False + # for opt in self._options: + # if opt in self._configuration.additional_arguments: + # is_option = True + # command = opt + # args = self._configuration.additional_arguments + # args.remove(opt) + # + # if not is_option: + # command = self._configuration.additional_arguments[0] + # if len(self._configuration.additional_arguments) > 1: + # args = self._configuration.additional_arguments[1:] + # else: + # for cmd in self._command_handler.commands: + # result = self._configuration.get_configuration(cmd.name) + # result_args: list[str] = self._configuration.get_configuration(f'{cmd.name}AdditionalArguments') + # is_option = False + # if result is None: + # continue + # + # for opt in self._options: + # if opt == result: + # is_option = True + # command = opt + # + # elif result_args is not None and opt in result_args: + # is_option = True + # command = opt + # result_args.remove(opt) + # + # if is_option: + # args.append(cmd.name) + # if result_args is not None: + # for arg in result_args: + # args.append(arg) + # + # elif result is not None: + # command = cmd.name + # args.append(result) + # + # for arg in result_args: + # args.append(arg) + # + # else: + # Error.error(f'Unexpected command') + # return + # + # if command is None: + # Error.error(f'Expected command') + # return + # + # self._command_handler.handle(command, args) except KeyboardInterrupt: Console.write_line() sys.exit() diff --git a/src/cpl_cli/command/add_service.py b/src/cpl_cli/command/add_service.py index c4bd21f9..4cbc4133 100644 --- a/src/cpl_cli/command/add_service.py +++ b/src/cpl_cli/command/add_service.py @@ -22,7 +22,6 @@ class AddService(CommandABC): CommandABC.__init__(self) self._config = config - self._workspace = workspace @property @@ -104,15 +103,15 @@ class AddService(CommandABC): Console.error(f'Invalid target: {target}') return - if target in build_settings.project_references: - Console.error(f'Project reference already exists.') - return - if self._workspace is None: target = f'../{target}' else: target = target.replace('src', '..') + if target in build_settings.project_references: + Console.error(f'Project reference already exists.') + return + build_settings.project_references.append(target) Console.spinner( diff --git a/src/cpl_cli/command/remove_service.py b/src/cpl_cli/command/remove_service.py index 5b8fed6d..b148e7b4 100644 --- a/src/cpl_cli/command/remove_service.py +++ b/src/cpl_cli/command/remove_service.py @@ -70,7 +70,6 @@ class RemoveService(CommandABC): :param args: :return: """ - project_name = args[0] if project_name not in self._workspace.projects: Console.error(f'Project {project_name} not found in workspace.') diff --git a/src/cpl_cli/command_abc.py b/src/cpl_cli/command_abc.py index 9cdfd84b..1c2f72d5 100644 --- a/src/cpl_cli/command_abc.py +++ b/src/cpl_cli/command_abc.py @@ -1,7 +1,9 @@ from abc import abstractmethod, ABC +from cpl_core.configuration.executable_argument import ExecutableArgument -class CommandABC(ABC): + +class CommandABC(ExecutableArgument): @abstractmethod def __init__(self): @@ -10,6 +12,3 @@ class CommandABC(ABC): @property @abstractmethod def help_message(self) -> str: pass - - @abstractmethod - def run(self, args: list[str]): pass diff --git a/src/cpl_cli/cpl_cli.json b/src/cpl_cli/cpl_cli.json index e895b319..0f5f58c7 100644 --- a/src/cpl_cli/cpl_cli.json +++ b/src/cpl_cli/cpl_cli.json @@ -42,6 +42,8 @@ "*.json" ] }, - "ProjectReferences": [] + "ProjectReferences": [ + "../cpl_core/cpl_core.json" + ] } } \ No newline at end of file diff --git a/src/cpl_cli/startup.py b/src/cpl_cli/startup.py index 8243cfdc..de9692a5 100644 --- a/src/cpl_cli/startup.py +++ b/src/cpl_cli/startup.py @@ -2,8 +2,9 @@ import os from typing import Optional from cpl_core.application.startup_abc import StartupABC -from cpl_core.configuration.argument_abc import ConsoleArgument +from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum from cpl_core.configuration.configuration_abc import ConfigurationABC +from cpl_core.console import Console from cpl_core.dependency_injection.service_collection_abc import ServiceCollectionABC from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl_cli.command.add_service import AddService @@ -40,52 +41,48 @@ class Startup(StartupABC): configuration.add_environment_variables('PYTHON_') configuration.add_environment_variables('CPL_') configuration.add_json_file('appsettings.json', path=environment.runtime_directory, optional=False, output=False) + configuration.add_json_file('cpl-workspace.json', path=environment.working_directory, optional=True, output=False) - configuration.add_console_argument(ConsoleArgument('', 'add', ['a', 'a'], ' ')) - configuration.add_console_argument(ConsoleArgument('', 'build', ['b', 'B'], '')) - configuration.add_console_argument(ConsoleArgument('', 'generate', ['g', 'G'], '', console_arguments=[ - ConsoleArgument('', 'abc', ['a', 'A'], ' '), - ConsoleArgument('', 'class', ['c', 'C'], ' '), - ConsoleArgument('', 'enum', ['e', 'E'], ' '), - ConsoleArgument('', 'service', ['s', 'S'], ' '), - ConsoleArgument('', 'settings', ['st', 'ST'], ' '), - ConsoleArgument('', 'thread', ['t', 't'], ' ') - ])) - configuration.add_console_argument( - ConsoleArgument('', 'help', ['h', 'H'], ' ', is_value_token_optional=True) + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'add', ['a', 'A'], AddService) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'build', ['b', 'B'], BuildService) + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'generate', ['g', 'G'], GenerateService) \ + .add_console_argument(ArgumentTypeEnum.Variable, '', 'abc', ['a', 'A'], ' ') \ + .add_console_argument(ArgumentTypeEnum.Variable, '', 'class', ['c', 'C'], ' ') \ + .add_console_argument(ArgumentTypeEnum.Variable, '', 'enum', ['e', 'E'], ' ') \ + .add_console_argument(ArgumentTypeEnum.Variable, '', 'service', ['s', 'S'], ' ') \ + .add_console_argument(ArgumentTypeEnum.Variable, '', 'settings', ['st', 'ST'], ' ') \ + .add_console_argument(ArgumentTypeEnum.Variable, '', 'thread', ['t', 't'], ' ') + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'install', ['i', 'I'], InstallService) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'new', ['n', 'N'], NewService) \ + .add_console_argument(ArgumentTypeEnum.Variable, '', 'console', ['c', 'C'], ' ') \ + .add_console_argument(ArgumentTypeEnum.Variable, '', 'library', ['l', 'L'], ' ') + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'publish', ['p', 'P'], PublishService) + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'remove', ['r', 'R'], RemoveService) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'start', ['S', 'S'], StartService) + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'uninstall', ['ui', 'UI'], UninstallService) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'update', ['u', 'U'], UpdateService) + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'version', ['v', 'V'], VersionService) + + configuration.for_each_argument( + lambda a: a.add_console_argument(ArgumentTypeEnum.Executable, '--', 'help', ['h', 'H'], HelpService) ) - configuration.add_console_argument( - ConsoleArgument('', 'install', ['i', 'I'], ' ', is_value_token_optional=True, console_arguments= [ - ConsoleArgument('', '--virtual', ['--v', '--V'], ''), - ConsoleArgument('', '--simulate', ['--s', '--S'], ''), - ]) - ) - configuration.add_console_argument(ConsoleArgument('', 'new', ['n', 'N'], '', console_arguments=[ - ConsoleArgument('', 'console', ['c', 'C'], ' '), - ConsoleArgument('', 'library', ['l', 'L'], ' ') - ])) - configuration.add_console_argument(ConsoleArgument('', 'publish', ['p', 'P'], '')) - configuration.add_console_argument(ConsoleArgument('', 'remove', ['r', 'R'], ' ')) - configuration.add_console_argument(ConsoleArgument('', 'start', ['s', 'S'], '')) - configuration.add_console_argument(ConsoleArgument('', 'uninstall', ['ui', 'UI'], ' ')) - configuration.add_console_argument(ConsoleArgument('', 'update', ['u', 'U'], '')) - configuration.add_console_argument(ConsoleArgument('', 'version', ['v', 'V'], '')) + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'help', ['h', 'H'], HelpService) - configuration.add_console_argument(ConsoleArgument('', '--help', ['-h', '-H'], '')) - - if os.path.isfile(os.path.join(environment.working_directory, 'cpl-workspace.json')): - configuration.add_json_file('cpl-workspace.json', optional=True, output=False) - workspace: Optional[WorkspaceSettings] = configuration.get_configuration(WorkspaceSettings) + workspace: Optional[WorkspaceSettings] = configuration.get_configuration(WorkspaceSettings) + if workspace is not None: for script in workspace.scripts: - configuration.add_console_argument( - ConsoleArgument('', script, [], ' ', is_value_token_optional=True)) - - configuration.parse_console_arguments(error=False) + configuration.create_console_argument(ArgumentTypeEnum.Executable, '', script, [], CustomScriptService) return configuration def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: - services.add_singleton(CommandHandler) + # services.add_singleton(CommandHandler) services.add_transient(PublisherABC, PublisherService) services.add_transient(LiveServerService) diff --git a/src/cpl_core/application/__init__.py b/src/cpl_core/application/__init__.py index fd655602..9860b042 100644 --- a/src/cpl_core/application/__init__.py +++ b/src/cpl_core/application/__init__.py @@ -23,6 +23,7 @@ from collections import namedtuple 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_core/application/application_builder.py b/src/cpl_core/application/application_builder.py index e2e53a1d..e81f7f04 100644 --- a/src/cpl_core/application/application_builder.py +++ b/src/cpl_core/application/application_builder.py @@ -55,7 +55,7 @@ class ApplicationBuilder(ApplicationBuilderABC): config = self._configuration services = self._services.build_service_provider() config.resolve_runnable_argument_types(services) - config.parse_console_arguments(error=False) + config.parse_console_arguments() for ex in self._app_extensions: extension = ex() diff --git a/src/cpl_core/configuration/__init__.py b/src/cpl_core/configuration/__init__.py index 07c9bc68..86696a19 100644 --- a/src/cpl_core/configuration/__init__.py +++ b/src/cpl_core/configuration/__init__.py @@ -20,11 +20,17 @@ __version__ = '2022.6.3.dev2' from collections import namedtuple # imports: +from .argument_abc import ArgumentABC +from .argument_builder import ArgumentBuilder +from .argument_executable_abc import ArgumentExecutableABC +from .argument_type_enum import ArgumentTypeEnum from .configuration import Configuration from .configuration_abc import ConfigurationABC from .configuration_model_abc import ConfigurationModelABC from .configuration_variable_name_enum import ConfigurationVariableNameEnum -from .argument_abc import ArgumentABC +from .executable_argument import ExecutableArgument +from .flag_argument import FlagArgument +from .variable_argument import VariableArgument VersionInfo = namedtuple('VersionInfo', 'major minor micro') version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') diff --git a/src/cpl_core/configuration/configuration.py b/src/cpl_core/configuration/configuration.py index 0f7bfc75..2047b145 100644 --- a/src/cpl_core/configuration/configuration.py +++ b/src/cpl_core/configuration/configuration.py @@ -147,15 +147,6 @@ class Configuration(ConfigurationABC): self._print_error(__name__, f'Cannot load config file: {file}! -> {e}') return {} - def add_environment_variables(self, prefix: str): - for variable in ConfigurationVariableNameEnum.to_list(): - var_name = f'{prefix}{variable}' - if var_name in [key.upper() for key in os.environ.keys()]: - self._set_variable(variable, os.environ[var_name]) - - def add_console_argument(self, argument: ArgumentABC): - self._argument_types.append(argument) - def _parse_arguments(self, call_stack: list[Callable], arg_list: list[str], args_types: list[ArgumentABC]): for i in range(0, len(arg_list)): arg_str = arg_list[i] @@ -169,7 +160,8 @@ class Configuration(ConfigurationABC): if arg_str.startswith(arg.token) \ and arg_str_without_token == arg.name or arg_str_without_token in arg.aliases: call_stack.append(arg.run) - self._parse_arguments(call_stack, arg_list[i:], arg.console_arguments) + self._parse_arguments(call_stack, arg_list[i + 1:], arg.console_arguments) + break # variables elif isinstance(arg, VariableArgument): @@ -185,24 +177,28 @@ class Configuration(ConfigurationABC): value = arg_list[i + 1] self._set_variable(arg.name, value) self._parse_arguments(call_stack, arg_list[i + 1:], arg.console_arguments) + break + # flags elif isinstance(arg, FlagArgument): if arg_str.startswith(arg.token) \ and arg_str_without_token == arg.name or arg_str_without_token in arg.aliases: self._additional_arguments.append(arg.name) self._parse_arguments(call_stack, arg_list[i + 1:], arg.console_arguments) + break - def parse_console_arguments(self, error: bool = None): - # sets environment variables as possible arguments as: --VAR=VALUE - for arg_name in ConfigurationVariableNameEnum.to_list(): - self.add_console_argument(VariableArgument('--', str(arg_name).upper(), [str(arg_name).lower()], '=')) + # add left over values to args + if arg_str not in self._additional_arguments: + self._additional_arguments.append(arg_str) - arg_list = sys.argv[1:] - call_stack = [] - self._parse_arguments(call_stack, arg_list, self._argument_types) + def add_environment_variables(self, prefix: str): + for variable in ConfigurationVariableNameEnum.to_list(): + var_name = f'{prefix}{variable}' + if var_name in [key.upper() for key in os.environ.keys()]: + self._set_variable(variable, os.environ[var_name]) - for call in call_stack: - call(self._additional_arguments) + def add_console_argument(self, argument: ArgumentABC): + self._argument_types.append(argument) def add_json_file(self, name: str, optional: bool = None, output: bool = True, path: str = None): if os.path.isabs(name): @@ -246,6 +242,10 @@ class Configuration(ConfigurationABC): self._argument_types.append(argument) return argument + def for_each_argument(self, call: Callable): + for arg in self._argument_types: + call(arg) + def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> \ Optional[Union[str, ConfigurationModelABC]]: if type(search_type) is str: @@ -265,6 +265,18 @@ class Configuration(ConfigurationABC): if config_model == search_type: return self._config[config_model] + def parse_console_arguments(self, error: bool = None): + # sets environment variables as possible arguments as: --VAR=VALUE + for arg_name in ConfigurationVariableNameEnum.to_list(): + self.add_console_argument(VariableArgument('--', str(arg_name).upper(), [str(arg_name).lower()], '=')) + + arg_list = sys.argv[1:] + call_stack = [] + self._parse_arguments(call_stack, arg_list, self._argument_types) + + for call in call_stack: + call(self._additional_arguments) + def resolve_runnable_argument_types(self, services: ServiceProviderABC): for arg in self._argument_types: if isinstance(arg, ExecutableArgument): diff --git a/src/cpl_core/configuration/configuration_abc.py b/src/cpl_core/configuration/configuration_abc.py index a2a9c48a..1fa05a13 100644 --- a/src/cpl_core/configuration/configuration_abc.py +++ b/src/cpl_core/configuration/configuration_abc.py @@ -53,17 +53,6 @@ class ConfigurationABC(ABC): """ pass - @abstractmethod - def parse_console_arguments(self, error: bool = None): - r"""Reads the console arguments - - Parameter - --------- - error: :class:`bool` - Defines is invalid argument error will be shown or not - """ - pass - @abstractmethod def add_json_file(self, name: str, optional: bool = None, output: bool = True, path: str = None): r"""Reads and saves settings from given json file @@ -120,6 +109,17 @@ class ConfigurationABC(ABC): """ pass + @abstractmethod + def for_each_argument(self, call: Callable): + r"""Iterates through all arguments and calls the call function + + Parameter + --------- + call: :class:`Callable` + Call for each argument + """ + pass + @abstractmethod def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> Union[ str, ConfigurationModelABC]: @@ -136,6 +136,17 @@ class ConfigurationABC(ABC): """ pass + @abstractmethod + def parse_console_arguments(self, error: bool = None): + r"""Reads the console arguments + + Parameter + --------- + error: :class:`bool` + Defines is invalid argument error will be shown or not + """ + pass + @abstractmethod def resolve_runnable_argument_types(self, services: 'ServiceProviderABC'): r"""Gets all objects for given types of ConsoleArguments diff --git a/src/cpl_core/dependency_injection/__init__.py b/src/cpl_core/dependency_injection/__init__.py index d9b831dd..3eb660d7 100644 --- a/src/cpl_core/dependency_injection/__init__.py +++ b/src/cpl_core/dependency_injection/__init__.py @@ -20,6 +20,8 @@ __version__ = '2022.6.3.dev2' from collections import namedtuple # imports: +from .scope import Scope +from .scope_abc import ScopeABC from .service_collection import ServiceCollection from .service_collection_abc import ServiceCollectionABC from .service_descriptor import ServiceDescriptor diff --git a/src/tests/custom/general/src/general/parameter_startup.py b/src/tests/custom/general/src/general/parameter_startup.py index f28791a1..449956f0 100644 --- a/src/tests/custom/general/src/general/parameter_startup.py +++ b/src/tests/custom/general/src/general/parameter_startup.py @@ -28,5 +28,5 @@ class ParameterStartup(StartupExtensionABC): def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): services \ - .add_singleton(GenerateArgument) \ + .add_transient(GenerateArgument) \ .add_singleton(InstallArgument)