diff --git a/cpl-workspace.json b/cpl-workspace.json index 75cdad9d..116affef 100644 --- a/cpl-workspace.json +++ b/cpl-workspace.json @@ -7,7 +7,65 @@ "cpl_query": "src/cpl_query/cpl_query.json" }, "Scripts": { - "hello-world": "echo 'Hello World'" + "hello-world": "echo 'Hello World'", + "docs-build": "echo 'Build Documentation'; cd docs/; sphinx-apidoc -o source/ ../src/cpl_core; sphinx-apidoc -o source/ ../src/cpl_query; make clean; make html; rm source/cpl_query.tests.rst;", + "db": "cpl build-docs", + "docs-open": "xdg-open $PWD/docs/build/html/index.html &", + "do": "cpl docs-open", + + "build-all": "cpl build-cli; cpl build-core; cpl build-query;", + "ba": "cpl build-all", + "build-cli": "echo 'Build cpl_cli'; cd ./src/cpl_cli; cpl build; cd ../../;", + "build-core": "echo 'Build cpl_core'; cd ./src/cpl_core; cpl build; cd ../../;", + "build-query": "echo 'Build cpl_query'; cd ./src/cpl_query; cpl build; cd ../../;", + + "publish-all": "cpl publish-cli; cpl publish-core; cpl publish-query;", + "pa": "cpl build-all", + "publish-cli": "echo 'Publish cpl_cli'; cd ./src/cpl_cli; cpl publish; cd ../../;", + "publish-core": "echo 'Publish cpl_core'; cd ./src/cpl_core; cpl publish; cd ../../;", + "publish-query": "echo 'Publish cpl_query'; cd ./src/cpl_query; cpl publish; cd ../../;", + + "upload-prod-cli": "echo 'PROD Upload cpl_cli'; cpl upl-prod-cli;", + "upload-prod-core": "echo 'PROD Upload cpl_core'; cpl upl-prod-core;", + "upload-prod-query": "echo 'PROD Upload cpl_query'; cpl upl-prod-query;", + + "upload-exp-cli": "echo 'EXP Upload cpl_cli'; cpl upl-exp-cli;", + "upload-exp-core": "echo 'EXP Upload cpl_core'; cpl upl-exp-core;", + "upload-exp-query": "echo 'EXP Upload cpl_query'; cpl upl-exp-query;", + + "upload-dev-cli": "echo 'DEV Upload cpl_cli'; cpl upl-dev-cli;", + "upload-dev-core": "echo 'DEV Upload cpl_core'; cpl upl-dev-core;", + "upload-dev-query": "echo 'DEV Upload cpl_query'; cpl upl-dev-query;", + + "upl-prod-cli": "twine upload -r pip.sh-edraft.de dist/cpl-cli/publish/setup/*", + "upl-prod-core": "twine upload -r pip.sh-edraft.de dist/cpl-core/publish/setup/*", + "upl-prod-query": "twine upload -r pip.sh-edraft.de dist/cpl-query/publish/setup/*", + + "upl-exp-cli": "twine upload -r pip-exp.sh-edraft.de dist/cpl-cli/publish/setup/*", + "upl-exp-core": "twine upload -r pip-exp.sh-edraft.de dist/cpl-core/publish/setup/*", + "upl-exp-query": "twine upload -r pip-exp.sh-edraft.de dist/cpl-query/publish/setup/*", + + "upl-dev-cli": "twine upload -r pip-dev.sh-edraft.de dist/cpl-cli/publish/setup/*", + "upl-dev-core": "twine upload -r pip-dev.sh-edraft.de dist/cpl-core/publish/setup/*", + "upl-dev-query": "twine upload -r pip-dev.sh-edraft.de dist/cpl-query/publish/setup/*", + + "deploy-prod": "cpl deploy-prod-cli; cpl deploy-prod-core; cpl deploy-prod-query;", + "dp": "cpl deploy-prod", + "deploy-prod-cli": "cpl publish-cli; cpl upload-prod-cli", + "deploy-prod-core": "cpl publish-core; cpl upload-prod-core", + "deploy-prod-query": "cpl publish-query; cpl upload-prod-query", + + "deploy-exp": "cpl deploy-exp-cli; cpl deploy-exp-core; cpl deploy-exp-query;", + "de": "cpl deploy-exp", + "deploy-exp-cli": "cpl publish-cli; cpl upload-exp-cli", + "deploy-exp-core": "cpl publish-core; cpl upload-exp-core", + "deploy-exp-query": "cpl publish-query; cpl upload-exp-query", + + "deploy-dev": "cpl deploy-dev-cli; cpl deploy-dev-core; cpl deploy-dev-query;", + "dd": "cpl deploy-dev", + "deploy-dev-cli": "cpl publish-cli; cpl upload-dev-cli", + "deploy-dev-core": "cpl publish-core; cpl upload-dev-core", + "deploy-dev-query": "cpl publish-query; cpl upload-dev-query" } } } \ No newline at end of file diff --git a/scripts/upload.sh b/scripts/upload.sh index 19e38a46..825782d5 100644 --- a/scripts/upload.sh +++ b/scripts/upload.sh @@ -7,7 +7,7 @@ if [ $1 == "-prod" ]; then elif [ $1 == "-exp" ]; then twine upload -r pip-exp.sh-edraft.de dist/cpl-cli/publish/setup/* twine upload -r pip-exp.sh-edraft.de dist/cpl-core/publish/setup/* - twine upload -r pip-.sh-edraft.de dist/cpl-query/publish/setup/* + twine upload -r pip-exp.sh-edraft.de dist/cpl-query/publish/setup/* else twine upload -r pip-dev.sh-edraft.de dist/cpl-cli/publish/setup/* diff --git a/src/cpl_cli/__init__.py b/src/cpl_cli/__init__.py index 283a11c1..25bcdc48 100644 --- a/src/cpl_cli/__init__.py +++ b/src/cpl_cli/__init__.py @@ -15,18 +15,16 @@ __title__ = 'cpl_cli' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: from .cli import CLI from .command_abc import CommandABC -from .command_handler_service import CommandHandler -from .command_model import CommandModel from .error import Error from .main import main from .startup import Startup VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/__init__.py b/src/cpl_cli/_templates/__init__.py index 8b1fd416..10cb5c3c 100644 --- a/src/cpl_cli/_templates/__init__.py +++ b/src/cpl_cli/_templates/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/build/__init__.py b/src/cpl_cli/_templates/build/__init__.py index 6e99f636..1f8a42e0 100644 --- a/src/cpl_cli/_templates/build/__init__.py +++ b/src/cpl_cli/_templates/build/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.build' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/generate/__init__.py b/src/cpl_cli/_templates/generate/__init__.py index 85c86198..825d010c 100644 --- a/src/cpl_cli/_templates/generate/__init__.py +++ b/src/cpl_cli/_templates/generate/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.generate' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/generate/validator_template.py b/src/cpl_cli/_templates/generate/validator_template.py new file mode 100644 index 00000000..e5ed47a5 --- /dev/null +++ b/src/cpl_cli/_templates/generate/validator_template.py @@ -0,0 +1,41 @@ +import textwrap +from string import Template + +from cpl_core.utils.string import String +from cpl_cli._templates.template_file_abc import TemplateFileABC + + +class ValidatorTemplate(TemplateFileABC): + + def __init__(self, name: str, schematic: str, schematic_upper: str, path: str): + TemplateFileABC.__init__(self) + + self._name = f'{String.convert_to_snake_case(name)}_{schematic}.py' + self._class_name = f'{String.first_to_upper(name)}{schematic_upper}' + self._path = path + self._value = textwrap.dedent("""\ + from cpl_core.configuration.validator_abc import ValidatorABC + + + class $Name(ValidatorABC): + + def __init__(self): + ValidatorABC.__init__(self) + + def validate(self) -> bool: + return True + """) + + @property + def name(self) -> str: + return self._name + + @property + def path(self) -> str: + return self._path + + @property + def value(self) -> str: + return Template(self._value).substitute( + Name=self._class_name + ) diff --git a/src/cpl_cli/_templates/new/__init__.py b/src/cpl_cli/_templates/new/__init__.py index 89efbf46..389c8635 100644 --- a/src/cpl_cli/_templates/new/__init__.py +++ b/src/cpl_cli/_templates/new/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/new/console/__init__.py b/src/cpl_cli/_templates/new/console/__init__.py index 8f8455f7..e5d81735 100644 --- a/src/cpl_cli/_templates/new/console/__init__.py +++ b/src/cpl_cli/_templates/new/console/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/new/console/source/__init__.py b/src/cpl_cli/_templates/new/console/source/__init__.py index 3a71ce79..b3ffaa60 100644 --- a/src/cpl_cli/_templates/new/console/source/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.console.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/new/console/source/name/__init__.py b/src/cpl_cli/_templates/new/console/source/name/__init__.py index 14611e2c..9c3e5b97 100644 --- a/src/cpl_cli/_templates/new/console/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/name/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.console.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/new/console/source/tests/__init__.py b/src/cpl_cli/_templates/new/console/source/tests/__init__.py index 38d68d91..1f397f13 100644 --- a/src/cpl_cli/_templates/new/console/source/tests/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/tests/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.console.source.tests' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/new/library/__init__.py b/src/cpl_cli/_templates/new/library/__init__.py index c0ee86ea..66570b7d 100644 --- a/src/cpl_cli/_templates/new/library/__init__.py +++ b/src/cpl_cli/_templates/new/library/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.library' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/new/library/source/__init__.py b/src/cpl_cli/_templates/new/library/source/__init__.py index 8611f624..a51a0cc9 100644 --- a/src/cpl_cli/_templates/new/library/source/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.library.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/new/library/source/name/__init__.py b/src/cpl_cli/_templates/new/library/source/name/__init__.py index 9b6f5be1..e8896599 100644 --- a/src/cpl_cli/_templates/new/library/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/name/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.library.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/new/library/source/tests/__init__.py b/src/cpl_cli/_templates/new/library/source/tests/__init__.py index cd64ce74..5c06dd3f 100644 --- a/src/cpl_cli/_templates/new/library/source/tests/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/tests/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.library.source.tests' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/_templates/publish/__init__.py b/src/cpl_cli/_templates/publish/__init__.py index c1dc353c..925a726a 100644 --- a/src/cpl_cli/_templates/publish/__init__.py +++ b/src/cpl_cli/_templates/publish/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/cli.py b/src/cpl_cli/cli.py index a373778d..8a0f8f60 100644 --- a/src/cpl_cli/cli.py +++ b/src/cpl_cli/cli.py @@ -1,29 +1,10 @@ -import os import sys -from typing import Optional +import traceback from cpl_core.application.application_abc import ApplicationABC -from cpl_core.configuration.console_argument import ConsoleArgument from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.console.console import Console from cpl_core.dependency_injection import ServiceProviderABC -from cpl_cli.command.add_service import AddService -from cpl_cli.command.build_service import BuildService -from cpl_cli.command.custom_script_service import CustomScriptService -from cpl_cli.command.generate_service import GenerateService -from cpl_cli.command.install_service import InstallService -from cpl_cli.command.new_service import NewService -from cpl_cli.command.publish_service import PublishService -from cpl_cli.command.remove_service import RemoveService -from cpl_cli.command.start_service import StartService -from cpl_cli.command.uninstall_service import UninstallService -from cpl_cli.command.update_service import UpdateService -from cpl_cli.command_handler_service import CommandHandler -from cpl_cli.command_model import CommandModel -from cpl_cli.configuration.workspace_settings import WorkspaceSettings -from cpl_cli.error import Error -from cpl_cli.command.help_service import HelpService -from cpl_cli.command.version_service import VersionService class CLI(ApplicationABC): @@ -34,32 +15,10 @@ class CLI(ApplicationABC): """ ApplicationABC.__init__(self, config, services) - 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 def main(self): """ @@ -67,61 +26,10 @@ 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) + self._configuration.parse_console_arguments(self._services) except KeyboardInterrupt: Console.write_line() sys.exit() + except Exception as e: + Console.error(str(e), traceback.format_exc()) + sys.exit() diff --git a/src/cpl_cli/command/__init__.py b/src/cpl_cli/command/__init__.py index e993d293..eaaf9a10 100644 --- a/src/cpl_cli/command/__init__.py +++ b/src/cpl_cli/command/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.command' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple @@ -28,4 +28,4 @@ from .publish_service import PublishService from .version_service import VersionService VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/command/add_service.py b/src/cpl_cli/command/add_service.py index c4bd21f9..f2dc15f3 100644 --- a/src/cpl_cli/command/add_service.py +++ b/src/cpl_cli/command/add_service.py @@ -22,8 +22,8 @@ class AddService(CommandABC): CommandABC.__init__(self) self._config = config - self._workspace = workspace + self._is_simulation = False @property def help_message(self) -> str: @@ -36,8 +36,9 @@ class AddService(CommandABC): target-project: Name of the project to be referenced """) - @staticmethod - def _edit_project_file(source: str, project_settings: ProjectSettings, build_settings: BuildSettings): + def _edit_project_file(self, source: str, project_settings: ProjectSettings, build_settings: BuildSettings): + if self._is_simulation: + return with open(source, 'w') as file: file.write(json.dumps({ ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(project_settings), @@ -51,6 +52,11 @@ class AddService(CommandABC): :param args: :return: """ + if 'simulate' in args: + args.remove('simulate') + Console.write_line('Running in simulation mode:') + self._is_simulation = True + if len(args) == 0: Console.error('Expected source and target project') return @@ -60,7 +66,7 @@ class AddService(CommandABC): return elif len(args) > 2: - Console.error(f'Unexpected argument: {" ".join(args[2:])}') + Console.error(f'Unexpected argument(s): {", ".join(args[2:])}') return # file names @@ -104,15 +110,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/custom_script_service.py b/src/cpl_cli/command/custom_script_service.py index b3f27b7a..3e8f2dbc 100644 --- a/src/cpl_cli/command/custom_script_service.py +++ b/src/cpl_cli/command/custom_script_service.py @@ -1,6 +1,5 @@ import os import subprocess -import sys from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.console.console import Console @@ -24,7 +23,7 @@ class CustomScriptService(CommandABC): return '' def run(self, args: list[str]): - cmd = args[0] if len(args) > 0 else self._config.additional_arguments[0] + cmd = self._config.get_configuration('ACTIVE_EXECUTABLE') for script in self._workspace.scripts: if script == cmd: diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index 65715d79..4ec3dc86 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -2,6 +2,7 @@ import os import sys import textwrap +from cpl_cli._templates.generate.validator_template import ValidatorTemplate from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.console.console import Console @@ -32,7 +33,7 @@ class GenerateService(CommandABC): "Template": ABCTemplate }, "class": { - "Upper": "", + "Upper": "Class", "Template": ClassTemplate }, "enum": { @@ -50,6 +51,10 @@ class GenerateService(CommandABC): "thread": { "Upper": "Thread", "Template": ThreadTemplate + }, + "validator": { + "Upper": "Validator", + "Template": ValidatorTemplate } } @@ -73,6 +78,7 @@ class GenerateService(CommandABC): service settings thread + validator """) @staticmethod @@ -89,7 +95,9 @@ class GenerateService(CommandABC): 'class (c|C)', 'enum (e|E)', 'service (s|S)', - 'settings (st|ST)' + 'settings (st|ST)', + 'thread (t|T)', + 'validator (v|V)' ] Console.write_line('Available Schematics:') for name in schematics: @@ -145,7 +153,7 @@ class GenerateService(CommandABC): ) if os.path.isfile(file_path): - Console.error(f'{String.first_to_upper(schematic)} already exists!') + Console.error(f'{String.first_to_upper(schematic)} already exists!\n') sys.exit() message = f'Creating {self._env.working_directory}/{template.path}/{template.name}' @@ -167,12 +175,19 @@ class GenerateService(CommandABC): :param args: :return: """ - if len(args) == 0: + schematic = None + value = None + for s in self._schematics: + value = self._config.get_configuration(s) + if value is not None: + schematic = s + break + + if schematic is None: self._help('Usage: cpl generate [options]') sys.exit() - schematic = args[0] - name = self._config.get_configuration(schematic) + name = value if name is None: name = Console.read(f'Name for the {args[0]}: ') diff --git a/src/cpl_cli/command/help_service.py b/src/cpl_cli/command/help_service.py index 0d857ed8..51a4d02b 100644 --- a/src/cpl_cli/command/help_service.py +++ b/src/cpl_cli/command/help_service.py @@ -1,32 +1,27 @@ +import sys import textwrap -from typing import Optional from cpl_core.console.console import Console from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC -from cpl_cli.command_handler_service import CommandHandler from cpl_cli.command_abc import CommandABC class HelpService(CommandABC): - def __init__(self, services: ServiceProviderABC, cmd_handler: CommandHandler): + def __init__(self, services: ServiceProviderABC): """ Service for CLI command help """ CommandABC.__init__(self) self._services = services - self._commands = cmd_handler.commands @property def help_message(self) -> str: return textwrap.dedent("""\ Lists available command and their short descriptions. - Usage: cpl help - - Arguments: - command The command to display the help message for + Usage: cpl help """) def run(self, args: list[str]): @@ -36,19 +31,8 @@ class HelpService(CommandABC): :return: """ if len(args) > 0: - command_name = args[0] - command: Optional[CommandABC] = None - for cmd in self._commands: - if cmd.name == command_name or command_name in cmd.aliases: - command = self._services.get_service(cmd.command) - - if command is None: - Console.error(f'Invalid argument: {command_name}') - return - - Console.write_line(command.help_message) - - return + Console.error(f'Unexpected argument(s): {", ".join(args)}') + sys.exit() Console.write_line('Available Commands:') commands = [ @@ -70,3 +54,4 @@ class HelpService(CommandABC): Console.write(f'\n\t{name} ') Console.set_foreground_color(ForegroundColorEnum.default) Console.write(f'{description}') + Console.write_line('\nRun \'cpl --help\' for command specific information\'s\n') diff --git a/src/cpl_cli/command/install_service.py b/src/cpl_cli/command/install_service.py index b1b52725..ac8184b4 100644 --- a/src/cpl_cli/command/install_service.py +++ b/src/cpl_cli/command/install_service.py @@ -39,7 +39,7 @@ class InstallService(CommandABC): self._project_settings = project_settings self._cli_settings = cli_settings - self._is_simulating = False + self._is_simulation = False self._is_virtual = False self._project_file = f'{self._config.get_configuration("ProjectName")}.json' @@ -172,7 +172,7 @@ class InstallService(CommandABC): self._project_settings.dependencies.append(new_name) - if not self._is_simulating: + if not self._is_simulation: config = { ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings), BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings) @@ -190,14 +190,14 @@ class InstallService(CommandABC): :param args: :return: """ - if '--virtual' in args: + if 'virtual' in args: self._is_virtual = True - args.remove('--virtual') + args.remove('virtual') Console.write_line('Running in virtual mode:') - if '--simulate' in args: - self._is_virtual = True - args.remove('--simulate') + if 'simulate' in args: + self._is_simulation = True + args.remove('simulate') Console.write_line('Running in simulation mode:') if len(args) == 0: diff --git a/src/cpl_cli/command/new_service.py b/src/cpl_cli/command/new_service.py index e23b893d..da23c198 100644 --- a/src/cpl_cli/command/new_service.py +++ b/src/cpl_cli/command/new_service.py @@ -42,7 +42,8 @@ class NewService(CommandABC): self._build_dict = {} self._project_json = {} - self._command: str = '' + self._name: str = '' + self._schematic: ProjectTypeEnum = ProjectTypeEnum.console self._use_application_api: bool = False self._use_startup: bool = False self._use_service_providing: bool = False @@ -111,11 +112,11 @@ class NewService(CommandABC): def _create_build_settings(self): main = f'{String.convert_to_snake_case(self._project.name)}.main' - if self._command == ProjectTypeEnum.library.value: + if self._schematic == ProjectTypeEnum.library.value: main = f'{String.convert_to_snake_case(self._project.name)}.main' self._build_dict = { - BuildSettingsNameEnum.project_type.value: self._command, + BuildSettingsNameEnum.project_type.value: self._schematic, BuildSettingsNameEnum.source_path.value: '', BuildSettingsNameEnum.output_path.value: '../../dist', BuildSettingsNameEnum.main.value: main, @@ -191,9 +192,7 @@ class NewService(CommandABC): :param args: :return: """ - name = self._config.get_configuration(self._command) - - self._create_project_settings(name) + self._create_project_settings(self._name) self._create_build_settings() self._create_project_json() path = self._get_project_path() @@ -221,9 +220,7 @@ class NewService(CommandABC): :param args: :return: """ - name = self._config.get_configuration(self._command) - - self._create_project_settings(name) + self._create_project_settings(self._name) self._create_build_settings() self._create_project_json() path = self._get_project_path() @@ -251,15 +248,16 @@ class NewService(CommandABC): :param args: :return: """ - if len(args) == 0: - self._help('Usage: cpl new [options]') - return - - self._command = str(args[0]).lower() - if self._command == ProjectTypeEnum.console.value: + console = self._config.get_configuration(ProjectTypeEnum.console.value) + library = self._config.get_configuration(ProjectTypeEnum.library.value) + if console is not None and library is None: + self._name = console + self._schematic = ProjectTypeEnum.console.value self._console(args) - elif self._command == ProjectTypeEnum.library.value: + elif console is None and library is not None: + self._name = library + self._schematic = ProjectTypeEnum.library.value self._library(args) else: diff --git a/src/cpl_cli/command/remove_service.py b/src/cpl_cli/command/remove_service.py index 5b8fed6d..6dc20a25 100644 --- a/src/cpl_cli/command/remove_service.py +++ b/src/cpl_cli/command/remove_service.py @@ -25,6 +25,7 @@ class RemoveService(CommandABC): self._env = env self._workspace: WorkspaceSettings = self._config.get_configuration(WorkspaceSettings) + self._is_simulation = False @property def help_message(self) -> str: @@ -36,8 +37,10 @@ class RemoveService(CommandABC): project The name of the project to delete """) - @staticmethod - def _create_file(file_name: str, content: dict): + def _create_file(self, file_name: str, content: dict): + if self._is_simulation: + return + if not os.path.isabs(file_name): file_name = os.path.abspath(file_name) @@ -70,6 +73,10 @@ class RemoveService(CommandABC): :param args: :return: """ + if 'simulate' in args: + args.remove('simulate') + Console.write_line('Running in simulation mode:') + self._is_simulation = True project_name = args[0] if project_name not in self._workspace.projects: diff --git a/src/cpl_cli/command/update_service.py b/src/cpl_cli/command/update_service.py index 412956e5..a454312b 100644 --- a/src/cpl_cli/command/update_service.py +++ b/src/cpl_cli/command/update_service.py @@ -38,6 +38,7 @@ class UpdateService(CommandABC): self._build_settings = build_settings self._project_settings = project_settings self._cli_settings = cli_settings + self._is_simulation = False @property def help_message(self) -> str: @@ -132,6 +133,9 @@ class UpdateService(CommandABC): :param new_package: :return: """ + if self._is_simulation: + return + if old_package in self._project_settings.dependencies: index = self._project_settings.dependencies.index(old_package) if '/' in new_package: @@ -158,6 +162,11 @@ class UpdateService(CommandABC): :param args: :return: """ + if 'simulate' in args: + args.remove('simulate') + Console.write_line('Running in simulation mode:') + self._is_simulation = True + Pip.set_executable(self._project_settings.python_executable) self._check_project_dependencies() self._check_outdated() diff --git a/src/cpl_cli/command_abc.py b/src/cpl_cli/command_abc.py index 9cdfd84b..2fe70f72 100644 --- a/src/cpl_cli/command_abc.py +++ b/src/cpl_cli/command_abc.py @@ -1,7 +1,10 @@ from abc import abstractmethod, ABC +from cpl_core.configuration.executable_argument import ExecutableArgument +from cpl_core.console import Console -class CommandABC(ABC): + +class CommandABC(ExecutableArgument): @abstractmethod def __init__(self): @@ -11,5 +14,12 @@ class CommandABC(ABC): @abstractmethod def help_message(self) -> str: pass + def execute(self, args: list[str]): + if 'help' in args: + Console.write_line(self.help_message) + return + + self.run(args) + @abstractmethod def run(self, args: list[str]): pass diff --git a/src/cpl_cli/command_handler_service.py b/src/cpl_cli/command_handler_service.py deleted file mode 100644 index e1d86879..00000000 --- a/src/cpl_cli/command_handler_service.py +++ /dev/null @@ -1,137 +0,0 @@ -import os -from abc import ABC -from typing import Optional - -from cpl_core.configuration.configuration_abc import ConfigurationABC -from cpl_core.console.console import Console -from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC -from cpl_core.utils.string import String -from cpl_cli.command.custom_script_service import CustomScriptService -from cpl_cli.configuration.workspace_settings import WorkspaceSettings -from cpl_cli.error import Error -from cpl_cli.command_model import CommandModel - - -class CommandHandler(ABC): - - def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): - """ - Service to handle incoming commands and args - :param config: - :param services: - """ - ABC.__init__(self) - - self._config = config - self._env = self._config.environment - self._services = services - - self._commands: list[CommandModel] = [] - - @property - def commands(self) -> list[CommandModel]: - return self._commands - - @staticmethod - def _project_not_found(): - Error.error( - 'The command requires to be run in an CPL project, but a project could not be found.' - ) - - def add_command(self, cmd: CommandModel): - self._commands.append(cmd) - - def remove_command(self, cmd: CommandModel): - self._commands.remove(cmd) - - def handle(self, cmd: str, args: list[str]): - """ - Handles incoming commands and args - :param cmd: - :param args: - :return: - """ - for command in self._commands: - if cmd == command.name or cmd in command.aliases: - error = None - project_name: Optional[str] = None - workspace: Optional[WorkspaceSettings] = None - - if os.path.isfile(os.path.join(self._env.working_directory, 'cpl-workspace.json')): - workspace = self._config.get_configuration(WorkspaceSettings) - - if command.is_project_needed: - name = os.path.basename(self._env.working_directory) - for r, d, f in os.walk(self._env.working_directory): - for file in f: - if file.endswith('.json'): - f_name = file.split('.json')[0] - if f_name == name or \ - String.convert_to_camel_case(f_name).lower() == String.convert_to_camel_case( - name).lower(): - project_name = f_name - break - - if not command.is_workspace_needed and project_name is None and workspace is None: - self._project_not_found() - return - - elif command.is_workspace_needed or project_name is None: - if workspace is None: - Error.error( - 'The command requires to be run in an CPL workspace or project, ' - 'but a workspace or project could not be found.' - ) - return - - if project_name is None: - project_name = workspace.default_project - - self._config.add_configuration('ProjectName', project_name) - project_json = f'{project_name}.json' - - if workspace is not None: - if project_name not in workspace.projects: - Error.error( - f'Project {project_name} not found.' - ) - return - project_json = workspace.projects[project_name] - - if not os.path.isfile(os.path.join(self._env.working_directory, project_json)): - self._project_not_found() - return - - project_json = os.path.join(self._env.working_directory, project_json) - - if command.change_cwd: - self._env.set_working_directory( - os.path.join(self._env.working_directory, os.path.dirname(project_json)) - ) - - self._config.add_json_file(project_json, optional=True, output=False) - - # pre scripts - Console.write('\n') - self._handle_pre_or_post_scripts(True, workspace, command) - self._services.get_service(command.command).run(args) - # post scripts - Console.write('\n\n') - self._handle_pre_or_post_scripts(False, workspace, command) - Console.write('\n') - - def _handle_pre_or_post_scripts(self, pre: bool, workspace: WorkspaceSettings, command: CommandModel): - script_type = 'pre-' if pre else 'post-' - if workspace is not None and len(workspace.scripts) > 0: - for script in workspace.scripts: - if script_type in script and script.split(script_type)[1] == command.name: - script_name = script - script_cmd = workspace.scripts[script] - if script_cmd in workspace.scripts: - script_name = workspace.scripts[script] - - css: CustomScriptService = self._services.get_service(CustomScriptService) - if css is None: - continue - - css.run([script_name]) diff --git a/src/cpl_cli/command_model.py b/src/cpl_cli/command_model.py deleted file mode 100644 index fd9542d4..00000000 --- a/src/cpl_cli/command_model.py +++ /dev/null @@ -1,37 +0,0 @@ -from cpl_cli.command_abc import CommandABC - - -class CommandModel: - - def __init__(self, name: str, aliases: list[str], command: CommandABC, is_workspace_needed: bool, - is_project_needed: bool, change_cwd: bool): - self._name = name - self._aliases = aliases - self._command = command - self._is_workspace_needed = is_workspace_needed - self._is_project_needed = is_project_needed - self._change_cwd = change_cwd - - @property - def name(self) -> str: - return self._name - - @property - def aliases(self) -> list[str]: - return self._aliases - - @property - def command(self) -> CommandABC: - return self._command - - @property - def is_workspace_needed(self) -> bool: - return self._is_workspace_needed - - @property - def is_project_needed(self) -> bool: - return self._is_project_needed - - @property - def change_cwd(self) -> bool: - return self._change_cwd diff --git a/src/cpl_cli/configuration/__init__.py b/src/cpl_cli/configuration/__init__.py index b170c452..ad494b69 100644 --- a/src/cpl_cli/configuration/__init__.py +++ b/src/cpl_cli/configuration/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple @@ -30,4 +30,4 @@ from .workspace_settings import WorkspaceSettings from .workspace_settings_name_enum import WorkspaceSettingsNameEnum VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/cpl_cli.json b/src/cpl_cli/cpl_cli.json index c543514f..80f3612d 100644 --- a/src/cpl_cli/cpl_cli.json +++ b/src/cpl_cli/cpl_cli.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "6", - "Micro": "1" + "Micro": "3" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", @@ -16,7 +16,7 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core>=2022.6.2" + "cpl-core>=2022.6.3" ], "PythonVersion": ">=3.10", "PythonPath": {}, diff --git a/src/cpl_cli/live_server/__init__.py b/src/cpl_cli/live_server/__init__.py index 199a7712..29527f0b 100644 --- a/src/cpl_cli/live_server/__init__.py +++ b/src/cpl_cli/live_server/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli.live_server' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/main.py b/src/cpl_cli/main.py index b96f89b6..192a18ae 100644 --- a/src/cpl_cli/main.py +++ b/src/cpl_cli/main.py @@ -1,3 +1,4 @@ +from cpl_cli.startup_argument_extension import StartupArgumentExtension from cpl_core.application.application_builder import ApplicationBuilder from cpl_cli.cli import CLI from cpl_cli.startup import Startup @@ -6,6 +7,7 @@ from cpl_cli.startup import Startup def main(): app_builder = ApplicationBuilder(CLI) app_builder.use_startup(Startup) + app_builder.use_extension(StartupArgumentExtension) app_builder.build().run() diff --git a/src/cpl_cli/publish/__init__.py b/src/cpl_cli/publish/__init__.py index 0b194ade..1acb5cf6 100644 --- a/src/cpl_cli/publish/__init__.py +++ b/src/cpl_cli/publish/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple @@ -24,4 +24,4 @@ from .publisher_abc import PublisherABC from .publisher_service import PublisherService VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/publish/publisher_service.py b/src/cpl_cli/publish/publisher_service.py index c41fb907..ba1047e7 100644 --- a/src/cpl_cli/publish/publisher_service.py +++ b/src/cpl_cli/publish/publisher_service.py @@ -434,6 +434,7 @@ class PublisherService(PublisherABC): spinner_foreground_color=ForegroundColorEnum.blue) Console.spinner('Building application:', self._dist_files, text_foreground_color=ForegroundColorEnum.green, spinner_foreground_color=ForegroundColorEnum.blue) + Console.write_line() def publish(self): """ @@ -487,3 +488,4 @@ class PublisherService(PublisherABC): text_foreground_color=ForegroundColorEnum.green, spinner_foreground_color=ForegroundColorEnum.blue ) + Console.write_line() diff --git a/src/cpl_cli/source_creator/__init__.py b/src/cpl_cli/source_creator/__init__.py index 1f86e0c5..6393c5bb 100644 --- a/src/cpl_cli/source_creator/__init__.py +++ b/src/cpl_cli/source_creator/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_cli.source_creator' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.1' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='1') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/startup.py b/src/cpl_cli/startup.py index e3a67712..6c90f01c 100644 --- a/src/cpl_cli/startup.py +++ b/src/cpl_cli/startup.py @@ -1,30 +1,13 @@ import os -from typing import Optional +from cpl_cli.error import Error +from cpl_cli.live_server.live_server_service import LiveServerService +from cpl_cli.publish.publisher_abc import PublisherABC +from cpl_cli.publish.publisher_service import PublisherService from cpl_core.application.startup_abc import StartupABC -from cpl_core.configuration.console_argument import ConsoleArgument from cpl_core.configuration.configuration_abc import ConfigurationABC 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 -from cpl_cli.command.build_service import BuildService -from cpl_cli.command.custom_script_service import CustomScriptService -from cpl_cli.command.generate_service import GenerateService -from cpl_cli.command.install_service import InstallService -from cpl_cli.command.new_service import NewService -from cpl_cli.command.publish_service import PublishService -from cpl_cli.command.remove_service import RemoveService -from cpl_cli.command.start_service import StartService -from cpl_cli.command.uninstall_service import UninstallService -from cpl_cli.command.update_service import UpdateService -from cpl_cli.command_handler_service import CommandHandler -from cpl_cli.command.help_service import HelpService -from cpl_cli.command.version_service import VersionService -from cpl_cli.configuration.workspace_settings import WorkspaceSettings -from cpl_cli.error import Error -from cpl_cli.live_server.live_server_service import LiveServerService -from cpl_cli.publish.publisher_service import PublisherService -from cpl_cli.publish.publisher_abc import PublisherABC from cpl_core.environment import ApplicationEnvironment @@ -41,67 +24,10 @@ class Startup(StartupABC): configuration.add_environment_variables('CPL_') configuration.add_json_file('appsettings.json', path=environment.runtime_directory, optional=False, 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.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.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) - for script in workspace.scripts: - configuration.add_console_argument( - ConsoleArgument('', script, [], ' ', is_value_token_optional=True)) - - configuration.add_console_arguments(error=False) - return configuration def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: - services.add_singleton(CommandHandler) - services.add_transient(PublisherABC, PublisherService) services.add_transient(LiveServerService) - services.add_transient(AddService) - services.add_transient(BuildService) - services.add_transient(CustomScriptService) - services.add_transient(GenerateService) - services.add_transient(HelpService) - services.add_transient(InstallService) - services.add_transient(NewService) - services.add_transient(PublishService) - services.add_transient(RemoveService) - services.add_transient(StartService) - services.add_transient(UninstallService) - services.add_transient(UpdateService) - services.add_transient(VersionService) - return services.build_service_provider() diff --git a/src/cpl_cli/startup_argument_extension.py b/src/cpl_cli/startup_argument_extension.py new file mode 100644 index 00000000..026e572a --- /dev/null +++ b/src/cpl_cli/startup_argument_extension.py @@ -0,0 +1,111 @@ +import os +from typing import Optional + +from cpl_cli.command.add_service import AddService +from cpl_cli.command.build_service import BuildService +from cpl_cli.command.custom_script_service import CustomScriptService +from cpl_cli.command.generate_service import GenerateService +from cpl_cli.command.help_service import HelpService +from cpl_cli.command.install_service import InstallService +from cpl_cli.command.new_service import NewService +from cpl_cli.command.publish_service import PublishService +from cpl_cli.command.remove_service import RemoveService +from cpl_cli.command.start_service import StartService +from cpl_cli.command.uninstall_service import UninstallService +from cpl_cli.command.update_service import UpdateService +from cpl_cli.command.version_service import VersionService +from cpl_cli.configuration.workspace_settings import WorkspaceSettings +from cpl_cli.validators.project_validator import ProjectValidator +from cpl_cli.validators.workspace_validator import WorkspaceValidator +from cpl_core.application import StartupExtensionABC +from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum +from cpl_core.configuration.configuration_abc import ConfigurationABC +from cpl_core.dependency_injection.service_collection_abc import ServiceCollectionABC +from cpl_core.environment import ApplicationEnvironmentABC +from cpl_core.utils import String + + +class StartupArgumentExtension(StartupExtensionABC): + + def __init__(self): + pass + + @staticmethod + def _search_project_json(env: ApplicationEnvironmentABC) -> Optional[str]: + project_name = None + name = os.path.basename(env.working_directory) + for r, d, f in os.walk(env.working_directory): + for file in f: + if file.endswith('.json'): + f_name = file.split('.json')[0] + if f_name == name or String.convert_to_camel_case(f_name).lower() == String.convert_to_camel_case(name).lower(): + project_name = f_name + break + + return project_name + + def _read_cpl_environment(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): + workspace: Optional[WorkspaceSettings] = config.get_configuration(WorkspaceSettings) + if workspace is not None: + for script in workspace.scripts: + config.create_console_argument(ArgumentTypeEnum.Executable, '', script, [], CustomScriptService) + + project = workspace.projects[workspace.default_project] + else: + project = f'{self._search_project_json(env)}.json' + + config.add_json_file(project, optional=True, output=False) + + def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): + config.add_json_file('cpl-workspace.json', path=env.working_directory, optional=True, output=False) + + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'add', ['a', 'A'], AddService, True) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'build', ['b', 'B'], BuildService, True, validators=[ProjectValidator]) + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'generate', ['g', 'G'], GenerateService, True) \ + .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'], ' ') \ + .add_console_argument(ArgumentTypeEnum.Variable, '', 'validator', ['v', 'V'], ' ') + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'install', ['i', 'I'], InstallService, True) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'new', ['n', 'N'], NewService, True) \ + .add_console_argument(ArgumentTypeEnum.Variable, '', 'console', ['c', 'C'], ' ') \ + .add_console_argument(ArgumentTypeEnum.Variable, '', 'library', ['l', 'L'], ' ') + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'publish', ['p', 'P'], PublishService, True) + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'remove', ['r', 'R'], RemoveService, True) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'start', ['s', 'S'], StartService, True) + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'uninstall', ['ui', 'UI'], UninstallService, True) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'update', ['u', 'U'], UpdateService, True) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'version', ['v', 'V'], VersionService, True) + + config.for_each_argument(lambda a: a.add_console_argument(ArgumentTypeEnum.Flag, '--', 'help', ['h', 'H'])) + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'help', ['h', 'H'], HelpService) + + self._read_cpl_environment(config, env) + + def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): + services.add_transient(WorkspaceValidator) + services.add_transient(ProjectValidator) + + services.add_transient(AddService) + services.add_transient(BuildService) + services.add_transient(CustomScriptService) + services.add_transient(GenerateService) + services.add_transient(HelpService) + services.add_transient(InstallService) + services.add_transient(NewService) + services.add_transient(PublishService) + services.add_transient(RemoveService) + services.add_transient(StartService) + services.add_transient(UninstallService) + services.add_transient(UpdateService) + services.add_transient(VersionService) diff --git a/src/cpl_cli/validators/__init__.py b/src/cpl_cli/validators/__init__.py new file mode 100644 index 00000000..aac26b89 --- /dev/null +++ b/src/cpl_cli/validators/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +cpl-cli sh-edraft Common Python library CLI +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Common Python library Command Line Interface + +:copyright: (c) 2020 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'cpl_cli.validators' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' +__version__ = '2022.6.3' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_cli/validators/project_validator.py b/src/cpl_cli/validators/project_validator.py new file mode 100644 index 00000000..4f21d0e2 --- /dev/null +++ b/src/cpl_cli/validators/project_validator.py @@ -0,0 +1,18 @@ +from cpl_cli import Error +from cpl_cli.configuration import WorkspaceSettings, ProjectSettings +from cpl_core.configuration.validator_abc import ValidatorABC + + +class ProjectValidator(ValidatorABC): + + def __init__(self, workspace: WorkspaceSettings, project: ProjectSettings): + self._workspace = workspace + self._project = project + + ValidatorABC.__init__(self) + + def validate(self) -> bool: + result = self._project is not None or self._workspace is not None + if not result: + Error.error('The command requires to be run in an CPL project, but a project could not be found.') + return result diff --git a/src/cpl_cli/validators/workspace_validator.py b/src/cpl_cli/validators/workspace_validator.py new file mode 100644 index 00000000..d8c50033 --- /dev/null +++ b/src/cpl_cli/validators/workspace_validator.py @@ -0,0 +1,17 @@ +from cpl_cli import Error +from cpl_cli.configuration import WorkspaceSettings +from cpl_core.configuration.validator_abc import ValidatorABC + + +class WorkspaceValidator(ValidatorABC): + + def __init__(self, workspace: WorkspaceSettings): + self._workspace = workspace + + ValidatorABC.__init__(self) + + def validate(self) -> bool: + result = self._workspace is not None + if not result: + Error.error('The command requires to be run in an CPL workspace, but a workspace could not be found.') + return result diff --git a/src/cpl_core/__init__.py b/src/cpl_core/__init__.py index e741b291..f6a6761f 100644 --- a/src/cpl_core/__init__.py +++ b/src/cpl_core/__init__.py @@ -15,11 +15,11 @@ __title__ = 'cpl_core' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_core/application/__init__.py b/src/cpl_core/application/__init__.py index 155bb71f..641e09f3 100644 --- a/src/cpl_core/application/__init__.py +++ b/src/cpl_core/application/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.application' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' from collections import namedtuple @@ -23,8 +23,9 @@ 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 VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_core/application/application_builder.py b/src/cpl_core/application/application_builder.py index 379e1216..23f8e956 100644 --- a/src/cpl_core/application/application_builder.py +++ b/src/cpl_core/application/application_builder.py @@ -10,7 +10,7 @@ from cpl_core.dependency_injection.service_collection import ServiceCollection class ApplicationBuilder(ApplicationBuilderABC): - r"""This is class is used to build a object of :class:`cpl_core.application.application_abc.ApplicationABC` + r"""This is class is used to build an object of :class:`cpl_core.application.application_abc.ApplicationABC` Parameter --------- diff --git a/src/cpl_core/configuration/__init__.py b/src/cpl_core/configuration/__init__.py index de358f22..e0fd7816 100644 --- a/src/cpl_core/configuration/__init__.py +++ b/src/cpl_core/configuration/__init__.py @@ -15,16 +15,23 @@ __title__ = 'cpl_core.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' 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 .console_argument import ConsoleArgument +from .executable_argument import ExecutableArgument +from .flag_argument import FlagArgument +from .validator_abc import ValidatorABC +from .variable_argument import VariableArgument VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_core/configuration/argument_abc.py b/src/cpl_core/configuration/argument_abc.py new file mode 100644 index 00000000..50f7cfa6 --- /dev/null +++ b/src/cpl_core/configuration/argument_abc.py @@ -0,0 +1,66 @@ +from abc import ABC, abstractmethod + +from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum + + +class ArgumentABC(ABC): + + @abstractmethod + def __init__(self, + token: str, + name: str, + aliases: list[str], + prevent_next_executable: bool = False, + console_arguments: list['ArgumentABC'] = None + ): + r"""Representation of an console argument + + Parameter + --------- + token: :class:`str` + name: :class:`str` + aliases: list[:class:`str`] + console_arguments: List[:class:`cpl_core.configuration.console_argument.ConsoleArgument`] + """ + self._token = token + self._name = name + self._aliases = aliases + self._prevent_next_executable = prevent_next_executable + self._console_arguments = console_arguments if console_arguments is not None else [] + + @property + def token(self) -> str: + return self._token + + @property + def name(self) -> str: + return self._name + + @property + def aliases(self) -> list[str]: + return self._aliases + + @property + def prevent_next_executable(self) -> bool: + return self._prevent_next_executable + + @property + def console_arguments(self) -> list['ArgumentABC']: + return self._console_arguments + + def add_console_argument(self, arg_type: ArgumentTypeEnum, *args, **kwargs) -> 'ArgumentABC': + r"""Creates and adds a console argument to known console arguments + + Parameter + --------- + arg_type: :class:`str` + Specifies the specific type of the argument + + Returns + ------ + self :class:`cpl_core.configuration.console_argument.ConsoleArgument` not created argument! + """ + from cpl_core.configuration.argument_builder import ArgumentBuilder + argument = ArgumentBuilder.build_argument(arg_type, *args, *kwargs) + self._console_arguments.append(argument) + return self diff --git a/src/cpl_core/configuration/argument_builder.py b/src/cpl_core/configuration/argument_builder.py new file mode 100644 index 00000000..9d797d76 --- /dev/null +++ b/src/cpl_core/configuration/argument_builder.py @@ -0,0 +1,30 @@ +from typing import Union + +from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum +from cpl_core.configuration.executable_argument import ExecutableArgument +from cpl_core.configuration.flag_argument import FlagArgument +from cpl_core.configuration.variable_argument import VariableArgument +from cpl_core.console import Console + + +class ArgumentBuilder: + + @staticmethod + def build_argument(arg_type: ArgumentTypeEnum, *args, **kwargs) -> Union[ + ExecutableArgument, FlagArgument, VariableArgument]: + argument = None + try: + match arg_type: + case ArgumentTypeEnum.Flag: + argument = FlagArgument(*args, **kwargs) + case ArgumentTypeEnum.Executable: + argument = ExecutableArgument(*args, **kwargs) + case ArgumentTypeEnum.Variable: + argument = VariableArgument(*args, **kwargs) + case _: + Console.error('Invalid argument type') + Console.close() + except TypeError as e: + Console.error(str(e)) + Console.close() + return argument diff --git a/src/cpl_core/configuration/argument_executable_abc.py b/src/cpl_core/configuration/argument_executable_abc.py new file mode 100644 index 00000000..d7f3319a --- /dev/null +++ b/src/cpl_core/configuration/argument_executable_abc.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod + + +class ArgumentExecutableABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + def run(self, args: list[str]): pass diff --git a/src/cpl_core/configuration/argument_type_enum.py b/src/cpl_core/configuration/argument_type_enum.py new file mode 100644 index 00000000..d8acc8fb --- /dev/null +++ b/src/cpl_core/configuration/argument_type_enum.py @@ -0,0 +1,8 @@ +from enum import Enum + + +class ArgumentTypeEnum(Enum): + + Flag = 0 + Executable = 1 + Variable = 3 diff --git a/src/cpl_core/configuration/configuration.py b/src/cpl_core/configuration/configuration.py index e11b5771..93becd5f 100644 --- a/src/cpl_core/configuration/configuration.py +++ b/src/cpl_core/configuration/configuration.py @@ -1,15 +1,24 @@ import json import os import sys +import traceback from collections.abc import Callable from typing import Union, Type, Optional +from cpl_cli.command_abc import CommandABC +from cpl_core.configuration.argument_abc import ArgumentABC +from cpl_core.configuration.argument_builder import ArgumentBuilder +from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum 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.executable_argument import ExecutableArgument +from cpl_core.configuration.flag_argument import FlagArgument +from cpl_core.configuration.validator_abc import ValidatorABC +from cpl_core.configuration.variable_argument import VariableArgument from cpl_core.console.console import Console from cpl_core.console.foreground_color_enum import ForegroundColorEnum +from cpl_core.dependency_injection.service_provider_abc 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 @@ -24,7 +33,7 @@ class Configuration(ConfigurationABC): self._application_environment = ApplicationEnvironment() self._config: dict[Union[type, str], Union[ConfigurationModelABC, str]] = {} - self._argument_types: list[ConsoleArgument] = [] + self._argument_types: list[ArgumentABC] = [] self._additional_arguments: list[str] = [] self._argument_error_function: Optional[Callable] = None @@ -47,6 +56,10 @@ class Configuration(ConfigurationABC): def argument_error_function(self, argument_error_function: Callable): self._argument_error_function = argument_error_function + @property + def arguments(self) -> list[ArgumentABC]: + return self._argument_types + @staticmethod def _print_info(name: str, message: str): r"""Prints an info message @@ -114,155 +127,6 @@ class Configuration(ConfigurationABC): else: self._config[name] = value - def _validate_argument_by_argument_type(self, argument: str, argument_type: ConsoleArgument, - next_arguments: list[str] = None) -> bool: - r"""Validate argument by argument type - - Parameter - --------- - argument: :class:`str` - Command as string - argument_type: :class:`cpl_core.configuration.console_argument.ConsoleArgument` - Command type as ConsoleArgument - next_arguments: list[:class:`str`] - Following arguments of argument - - Returns - ------- - Object of :class:`bool` - - Raises - ------ - Exception: An error occurred getting an argument for a command - """ - argument_name = '' - value = '' - result = False - - if argument_type.value_token != '' and argument_type.value_token in argument: - # ?new=value - found = False - for alias in argument_type.aliases: - if alias in argument: - found = True - - if argument_type.name not in argument_name and not found: - return False - - if argument_type.is_value_token_optional is not None and argument_type.is_value_token_optional: - if argument_type.name not in self._additional_arguments: - self._additional_arguments.append(argument_type.name) - result = True - - if argument_type.token != '' and argument.startswith(argument_type.token): - # --new=value - if len(argument.split(argument_type.token)[1].split(argument_type.value_token)) == 0: - raise Exception(f'Expected argument for command: {argument}') - - argument_name = argument.split(argument_type.token)[1].split(argument_type.value_token)[0] - else: - # new=value - argument_name = argument.split(argument_type.value_token)[1] - - if argument_name == '': - raise Exception(f'Expected argument for command: {argument_type.name}') - - result = True - - if argument_type.is_value_token_optional is True: - is_valid = False - - name_list = argument.split(argument_type.token) - if len(name_list) > 1: - value_list = name_list[1].split(argument_type.value_token) - if len(value_list) > 1: - is_valid = True - value = argument.split(argument_type.token)[1].split(argument_type.value_token)[1] - - if not is_valid: - if argument_type.name not in self._additional_arguments: - self._additional_arguments.append(argument_type.name) - result = True - else: - value = argument.split(argument_type.token)[1].split(argument_type.value_token)[1] - - if argument_name != argument_type.name and argument_name not in argument_type.aliases: - return False - - self._set_variable(argument_type.name, value) - result = True - - elif argument_type.value_token == ' ': - # ?new value - found = False - for alias in argument_type.aliases: - if alias == argument or f' {alias} ' == argument: - found = True - - if (argument_type.token != '' and f'{argument_type.token}{argument_type.name}' != argument - or argument_type.name not in argument) and not found: - return False - - if (next_arguments is None or len(next_arguments) == 0) and \ - argument_type.is_value_token_optional is not True: - raise Exception(f'Expected argument for command: {argument_type.name}') - - if (next_arguments is None or len(next_arguments) == 0) and argument_type.is_value_token_optional is True: - value = '' - else: - value = next_arguments[0] - # next_arguments.remove(value) - self._handled_args.append(value) - - if argument_type.token != '' and argument.startswith(argument_type.token): - # --new value - argument_name = argument.split(argument_type.token)[1] - else: - # new value - argument_name = argument - - if argument_name != argument_type.name and argument_name not in argument_type.aliases: - return False - - if value == '': - if argument_type.name not in self._additional_arguments: - self._additional_arguments.append(argument_type.name) - else: - self._set_variable(argument_type.name, value) - - result = True - - elif argument_type.name == argument or argument in argument_type.aliases: - # new - self._additional_arguments.append(argument_type.name) - result = True - - if result: - self._handled_args.append(argument) - if next_arguments is not None and len(next_arguments) > 0: - next_args = [] - if len(next_arguments) > 1: - next_args = next_arguments[1:] - - if argument_type.console_arguments is not None and len(argument_type.console_arguments) > 0: - found_child = False - for child_argument_type in argument_type.console_arguments: - found_child = self._validate_argument_by_argument_type( - next_arguments[0], - child_argument_type, - next_args - ) - if found_child and child_argument_type.name not in self._additional_arguments: - self._additional_arguments.append(child_argument_type.name) - - if found_child: - break - - if not found_child: - result = self._validate_argument_by_argument_type(next_arguments[0], argument_type, next_args) - - return result - def _load_json_file(self, file: str, output: bool) -> dict: r"""Reads the json file @@ -290,58 +154,61 @@ class Configuration(ConfigurationABC): self._print_error(__name__, f'Cannot load config file: {file}! -> {e}') return {} + def _parse_arguments(self, executables: list[ArgumentABC], arg_list: list[str], args_types: list[ArgumentABC]): + for i in range(0, len(arg_list)): + arg_str = arg_list[i] + for n in range(0, len(args_types)): + arg = args_types[n] + arg_str_without_token = arg_str + if arg.token != "" and arg.token in arg_str: + arg_str_without_token = arg_str.split(arg.token)[1] + + # executable + if isinstance(arg, ExecutableArgument): + if arg_str.startswith(arg.token) \ + and arg_str_without_token == arg.name or arg_str_without_token in arg.aliases: + executables.append(arg) + self._handled_args.append(arg_str) + self._parse_arguments(executables, arg_list[i + 1:], arg.console_arguments) + + # variables + elif isinstance(arg, VariableArgument): + arg_str_without_value = arg_str_without_token + if arg.value_token in arg_str_without_value: + arg_str_without_value = arg_str_without_token.split(arg.value_token)[0] + + if arg_str.startswith(arg.token) \ + and arg_str_without_value == arg.name or arg_str_without_value in arg.aliases: + if arg.value_token != ' ': + value = arg_str_without_token.split(arg.value_token)[1] + else: + value = arg_list[i + 1] + self._set_variable(arg.name, value) + self._handled_args.append(arg_str) + self._handled_args.append(value) + self._parse_arguments(executables, arg_list[i + 1:], arg.console_arguments) + + # 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._handled_args.append(arg_str) + self._parse_arguments(executables, arg_list[i + 1:], arg.console_arguments) + + # add left over values to args + if arg_str not in self._additional_arguments and arg_str not in self._handled_args: + self._additional_arguments.append(arg_str) + 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: ConsoleArgument): + def add_console_argument(self, argument: ArgumentABC): self._argument_types.append(argument) - def add_console_arguments(self, error: bool = None): - for arg_name in ConfigurationVariableNameEnum.to_list(): - self.add_console_argument(ConsoleArgument('--', str(arg_name).upper(), [str(arg_name).lower()], '=')) - - arg_list = sys.argv[1:] - for i in range(0, len(arg_list)): - argument = arg_list[i] - next_arguments = [] - error_message = '' - - if argument in self._handled_args: - break - - if i + 1 < len(arg_list): - next_arguments = arg_list[i + 1:] - - found = False - for argument_type in self._argument_types: - try: - found = self._validate_argument_by_argument_type(argument, argument_type, next_arguments) - if found: - break - except Exception as e: - error_message = e - - if not found and error_message == '' and error is not False: - error_message = f'Invalid argument: {argument}' - - if error_message != '': - if self._argument_error_function is not None: - self._argument_error_function(error_message) - else: - self._print_error(__name__, error_message) - - sys.exit() - - add_args = [] - for next_arg in next_arguments: - if next_arg not in self._handled_args and next_arg not in self._additional_arguments: - add_args.append(next_arg) - - self._set_variable(f'{argument}AdditionalArguments', add_args) - def add_json_file(self, name: str, optional: bool = None, output: bool = True, path: str = None): if os.path.isabs(name): file_path = name @@ -375,11 +242,21 @@ class Configuration(ConfigurationABC): configuration.from_dict(value) self.add_configuration(sub, configuration) - def add_configuration(self, key_type: Union[str, type], value: ConfigurationModelABC): + def add_configuration(self, key_type: Union[str, type], value: Union[str, ConfigurationModelABC]): self._config[key_type] = value + def create_console_argument(self, arg_type: ArgumentTypeEnum, token: str, name: str, aliases: list[str], + *args, **kwargs) -> ArgumentABC: + argument = ArgumentBuilder.build_argument(arg_type, token, name, aliases, *args, **kwargs) + 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]]) -> \ - 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 +273,41 @@ class Configuration(ConfigurationABC): for config_model in self._config: if config_model == search_type: return self._config[config_model] + + def parse_console_arguments(self, services: ServiceProviderABC, 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()], '=')) + + try: + arg_list = sys.argv[1:] + executables: list[ExecutableArgument] = [] + self._parse_arguments(executables, arg_list, self._argument_types) + except Exception as e: + Console.error('An error occurred while parsing arguments.') + exit() + + try: + prevent = False + for exe in executables: + if prevent: + continue + + if exe.validators is not None: + abort = False + for validator_type in exe.validators: + validator: ValidatorABC = services.get_service(validator_type) + result = validator.validate() + abort = not result + if abort: + break + + if abort: + continue + + cmd: CommandABC = services.get_service(exe.executable_type) + self.add_configuration('ACTIVE_EXECUTABLE', exe.name) + cmd.execute(self._additional_arguments) + prevent = exe.prevent_next_executable + except Exception as e: + Console.error('An error occurred while executing arguments.') diff --git a/src/cpl_core/configuration/configuration_abc.py b/src/cpl_core/configuration/configuration_abc.py index a2961cda..733e86ce 100644 --- a/src/cpl_core/configuration/configuration_abc.py +++ b/src/cpl_core/configuration/configuration_abc.py @@ -2,8 +2,9 @@ from abc import abstractmethod, ABC from collections.abc import Callable 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.argument_abc import ArgumentABC +from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC @@ -30,6 +31,10 @@ class ConfigurationABC(ABC): @abstractmethod def argument_error_function(self, argument_error_function: Callable): pass + @property + @abstractmethod + def arguments(self) -> list[ArgumentABC]: pass + @abstractmethod def add_environment_variables(self, prefix: str): r"""Reads the environment variables @@ -42,27 +47,16 @@ class ConfigurationABC(ABC): pass @abstractmethod - def add_console_argument(self, argument: ConsoleArgument): + def add_console_argument(self, argument: ArgumentABC): r"""Adds console argument to known console arguments Parameter --------- - argument: :class:`cpl_core.configuration.console_argument.ConsoleArgument` + argument: :class:`cpl_core.configuration.console_argument.ConsoleArgumentABC` Specifies the console argument """ pass - @abstractmethod - def add_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 @@ -94,7 +88,45 @@ class ConfigurationABC(ABC): pass @abstractmethod - def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> Union[str, ConfigurationModelABC]: + def create_console_argument(self, arg_type: ArgumentTypeEnum, token: str, name: str, aliases: list[str], + *args, **kwargs) -> ArgumentABC: + 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.ConsoleArgumentABC` + Specifies class to run when called if value is not None + + Returns + ------ + Object of :class:`cpl_core.configuration.console_argument.ConsoleArgumentABC` + """ + 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]: r"""Returns value from configuration by given type Parameter @@ -107,3 +139,14 @@ class ConfigurationABC(ABC): Object of Union[:class:`str`, :class:`cpl_core.configuration.configuration_model_abc.ConfigurationModelABC`] """ pass + + @abstractmethod + def parse_console_arguments(self, services: 'ServiceProviderABC', error: bool = None): + r"""Reads the console arguments + + Parameter + --------- + error: :class:`bool` + Defines is invalid argument error will be shown or not + """ + pass diff --git a/src/cpl_core/configuration/console_argument.py b/src/cpl_core/configuration/console_argument.py deleted file mode 100644 index 6407aa5f..00000000 --- a/src/cpl_core/configuration/console_argument.py +++ /dev/null @@ -1,51 +0,0 @@ -class ConsoleArgument: - - def __init__(self, - token: str, - name: str, - aliases: list[str], - value_token: str, - is_value_token_optional: bool = None, - console_arguments: list['ConsoleArgument'] = None - ): - r"""Representation of an console argument - - Parameter - --------- - token: :class:`str` - name: :class:`str` - aliases: list[:class:`str`] - value_token: :class:`str` - is_value_token_optional: :class:`bool` - console_arguments: List[:class:`cpl_core.configuration.console_argument.ConsoleArgument`] - """ - self._token = token - self._name = name - self._aliases = aliases - self._value_token = value_token - self._is_value_token_optional = is_value_token_optional - self._console_arguments = console_arguments - - @property - def token(self) -> str: - return self._token - - @property - def name(self) -> str: - return self._name - - @property - def aliases(self) -> list[str]: - return self._aliases - - @property - def value_token(self) -> str: - return self._value_token - - @property - def is_value_token_optional(self) -> bool: - return self._is_value_token_optional - - @property - def console_arguments(self) -> list['ConsoleArgument']: - return self._console_arguments diff --git a/src/cpl_core/configuration/executable_argument.py b/src/cpl_core/configuration/executable_argument.py new file mode 100644 index 00000000..fd061a8e --- /dev/null +++ b/src/cpl_core/configuration/executable_argument.py @@ -0,0 +1,43 @@ +from typing import Type, Optional + +from cpl_core.configuration.argument_executable_abc import ArgumentExecutableABC +from cpl_core.configuration.argument_abc import ArgumentABC +from cpl_core.configuration.validator_abc import ValidatorABC +from cpl_core.console import Console + + +class ExecutableArgument(ArgumentABC): + + def __init__(self, + token: str, + name: str, + aliases: list[str], + executable: Type[ArgumentExecutableABC], + prevent_next_executable: bool = False, + validators: list[Type[ValidatorABC]] = None, + console_arguments: list['ArgumentABC'] = None + ): + + self._executable_type = executable + self._validators = validators + self._executable: Optional[ArgumentExecutableABC] = None + + ArgumentABC.__init__(self, token, name, aliases, prevent_next_executable, console_arguments) + + @property + def executable_type(self) -> type: + return self._executable_type + + def set_executable(self, executable: ArgumentExecutableABC): + self._executable = executable + + @property + def validators(self) -> list[Type[ValidatorABC]]: + return self._validators + + def run(self, args: list[str]): + r"""Executes runnable if exists + """ + if self._executable is None: + return + self._executable.run(args) diff --git a/src/cpl_core/configuration/flag_argument.py b/src/cpl_core/configuration/flag_argument.py new file mode 100644 index 00000000..c22c5689 --- /dev/null +++ b/src/cpl_core/configuration/flag_argument.py @@ -0,0 +1,14 @@ +from cpl_core.configuration.argument_abc import ArgumentABC + + +class FlagArgument(ArgumentABC): + + def __init__(self, + token: str, + name: str, + aliases: list[str], + prevent_next_executable: bool = False, + console_arguments: list['ArgumentABC'] = None + ): + + ArgumentABC.__init__(self, token, name, aliases, prevent_next_executable, console_arguments) diff --git a/src/cpl_core/configuration/validator_abc.py b/src/cpl_core/configuration/validator_abc.py new file mode 100644 index 00000000..a79e8621 --- /dev/null +++ b/src/cpl_core/configuration/validator_abc.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod + + +class ValidatorABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + def validate(self) -> bool: pass diff --git a/src/cpl_core/configuration/variable_argument.py b/src/cpl_core/configuration/variable_argument.py new file mode 100644 index 00000000..1f8597e5 --- /dev/null +++ b/src/cpl_core/configuration/variable_argument.py @@ -0,0 +1,28 @@ +from cpl_core.configuration.argument_abc import ArgumentABC + + +class VariableArgument(ArgumentABC): + + def __init__(self, + token: str, + name: str, + aliases: list[str], + value_token: str, + prevent_next_executable: bool = False, + console_arguments: list['ArgumentABC'] = None + ): + self._value_token = value_token + self._value: str = '' + + ArgumentABC.__init__(self, token, name, aliases, prevent_next_executable, console_arguments) + + @property + def value_token(self) -> str: + return self._value_token + + @property + def value(self) -> str: + return self._value + + def set_value(self, value: str): + self._value = value diff --git a/src/cpl_core/console/__init__.py b/src/cpl_core/console/__init__.py index 928c0904..fe05277d 100644 --- a/src/cpl_core/console/__init__.py +++ b/src/cpl_core/console/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' from collections import namedtuple @@ -27,4 +27,4 @@ from .foreground_color_enum import ForegroundColorEnum from .spinner_thread import SpinnerThread VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_core/cpl_core.json b/src/cpl_core/cpl_core.json index e171d838..3e3db7a5 100644 --- a/src/cpl_core/cpl_core.json +++ b/src/cpl_core/cpl_core.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "6", - "Micro": "2" + "Micro": "3" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_core/database/__init__.py b/src/cpl_core/database/__init__.py index 55bc3f3c..c0c1ebf1 100644 --- a/src/cpl_core/database/__init__.py +++ b/src/cpl_core/database/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.database' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' from collections import namedtuple @@ -25,4 +25,4 @@ from .database_settings import DatabaseSettings from .table_abc import TableABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_core/database/connection/__init__.py b/src/cpl_core/database/connection/__init__.py index accbfaa6..5815d9d6 100644 --- a/src/cpl_core/database/connection/__init__.py +++ b/src/cpl_core/database/connection/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.database.connection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' from collections import namedtuple @@ -24,4 +24,4 @@ from .database_connection import DatabaseConnection from .database_connection_abc import DatabaseConnectionABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_core/database/context/__init__.py b/src/cpl_core/database/context/__init__.py index e1684eea..c8e89de1 100644 --- a/src/cpl_core/database/context/__init__.py +++ b/src/cpl_core/database/context/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.database.context' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' from collections import namedtuple @@ -24,4 +24,4 @@ from .database_context import DatabaseContext from .database_context_abc import DatabaseContextABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_core/dependency_injection/__init__.py b/src/cpl_core/dependency_injection/__init__.py index 044ec621..afe969a5 100644 --- a/src/cpl_core/dependency_injection/__init__.py +++ b/src/cpl_core/dependency_injection/__init__.py @@ -15,11 +15,13 @@ __title__ = 'cpl_core.dependency_injection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' 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 @@ -28,4 +30,4 @@ from .service_provider import ServiceProvider from .service_provider_abc import ServiceProviderABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_core/dependency_injection/service_collection.py b/src/cpl_core/dependency_injection/service_collection.py index 337f172a..1b428a8c 100644 --- a/src/cpl_core/dependency_injection/service_collection.py +++ b/src/cpl_core/dependency_injection/service_collection.py @@ -10,7 +10,6 @@ from cpl_core.dependency_injection.service_lifetime_enum import ServiceLifetimeE from cpl_core.dependency_injection.service_provider import ServiceProvider from cpl_core.logging.logger_service import Logger from cpl_core.logging.logger_abc import LoggerABC -from cpl_core.utils.credential_manager import CredentialManager class ServiceCollection(ServiceCollectionABC): @@ -59,12 +58,15 @@ class ServiceCollection(ServiceCollectionABC): self._add_descriptor(impl, ServiceLifetimeEnum.singleton) + return self + def add_scoped(self, service_type: Type, service: Callable = None): if service is not None: self._add_descriptor(service, ServiceLifetimeEnum.scoped) else: self._add_descriptor(service_type, ServiceLifetimeEnum.scoped) - + + return self def add_transient(self, service_type: type, service: type = None): if service is not None: @@ -72,5 +74,7 @@ class ServiceCollection(ServiceCollectionABC): else: self._add_descriptor(service_type, ServiceLifetimeEnum.transient) + return self + def build_service_provider(self) -> ServiceProviderABC: return ServiceProvider(self._service_descriptors, self._configuration, self._database_context) diff --git a/src/cpl_core/dependency_injection/service_collection_abc.py b/src/cpl_core/dependency_injection/service_collection_abc.py index 2f69691a..13ddca96 100644 --- a/src/cpl_core/dependency_injection/service_collection_abc.py +++ b/src/cpl_core/dependency_injection/service_collection_abc.py @@ -31,7 +31,7 @@ class ServiceCollectionABC(ABC): pass @abstractmethod - def add_transient(self, service_type: Type, service: Callable = None): + def add_transient(self, service_type: Type, service: Callable = None) -> 'ServiceCollectionABC': r"""Adds a service with transient lifetime Parameter @@ -40,11 +40,15 @@ class ServiceCollectionABC(ABC): Type of the service service: :class:`Callable` Object of the service + + Returns + ------ + self: :class:`cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC """ pass @abstractmethod - def add_scoped(self, service_type: Type, service: Callable = None): + def add_scoped(self, service_type: Type, service: Callable = None) -> 'ServiceCollectionABC': r"""Adds a service with scoped lifetime Parameter @@ -53,11 +57,15 @@ class ServiceCollectionABC(ABC): Type of the service service: :class:`Callable` Object of the service + + Returns + ------ + self: :class:`cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC """ pass @abstractmethod - def add_singleton(self, service_type: Type, service: Callable = None): + def add_singleton(self, service_type: Type, service: Callable = None) -> 'ServiceCollectionABC': r"""Adds a service with singleton lifetime Parameter @@ -66,6 +74,10 @@ class ServiceCollectionABC(ABC): Type of the service service: :class:`Callable` Object of the service + + Returns + ------ + self: :class:`cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC """ pass diff --git a/src/cpl_core/dependency_injection/service_provider.py b/src/cpl_core/dependency_injection/service_provider.py index a1535f98..39f298b7 100644 --- a/src/cpl_core/dependency_injection/service_provider.py +++ b/src/cpl_core/dependency_injection/service_provider.py @@ -34,7 +34,7 @@ class ServiceProvider(ServiceProviderABC): self._database_context = db_context self._scope: Optional[ScopeABC] = None - def _find_service(self, service_type: type) -> ServiceDescriptor: + def _find_service(self, service_type: type) -> Optional[ServiceDescriptor]: for descriptor in self._service_descriptors: if descriptor.service_type == service_type or issubclass(descriptor.service_type, service_type): return descriptor diff --git a/src/cpl_core/environment/__init__.py b/src/cpl_core/environment/__init__.py index 3c96a3bf..59b62db7 100644 --- a/src/cpl_core/environment/__init__.py +++ b/src/cpl_core/environment/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.environment' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' from collections import namedtuple @@ -25,4 +25,4 @@ from .environment_name_enum import EnvironmentNameEnum from .application_environment import ApplicationEnvironment VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_core/logging/__init__.py b/src/cpl_core/logging/__init__.py index 3e341963..1d30290c 100644 --- a/src/cpl_core/logging/__init__.py +++ b/src/cpl_core/logging/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.logging' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' from collections import namedtuple @@ -27,4 +27,4 @@ from .logging_settings import LoggingSettings from .logging_settings_name_enum import LoggingSettingsNameEnum VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_core/mailing/__init__.py b/src/cpl_core/mailing/__init__.py index 0eeefc95..a773c1d1 100644 --- a/src/cpl_core/mailing/__init__.py +++ b/src/cpl_core/mailing/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.mailing' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' from collections import namedtuple @@ -27,4 +27,4 @@ from .email_client_settings import EMailClientSettings from .email_client_settings_name_enum import EMailClientSettingsNameEnum VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_core/time/__init__.py b/src/cpl_core/time/__init__.py index 4dea9c68..b4712aac 100644 --- a/src/cpl_core/time/__init__.py +++ b/src/cpl_core/time/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.time' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' from collections import namedtuple @@ -24,4 +24,4 @@ from .time_format_settings import TimeFormatSettings from .time_format_settings_names_enum import TimeFormatSettingsNamesEnum VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/cpl_core/utils/__init__.py b/src/cpl_core/utils/__init__.py index 5d9e5653..934ebe3f 100644 --- a/src/cpl_core/utils/__init__.py +++ b/src/cpl_core/utils/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.utils' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.6.2' +__version__ = '2022.6.3' from collections import namedtuple @@ -25,4 +25,4 @@ from .string import String from .pip import Pip VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='2') +version_info = VersionInfo(major='2022', minor='6', micro='3') diff --git a/src/tests/custom/database/src/startup.py b/src/tests/custom/database/src/startup.py index 112c1ae4..9ceecabf 100644 --- a/src/tests/custom/database/src/startup.py +++ b/src/tests/custom/database/src/startup.py @@ -21,7 +21,7 @@ class Startup(StartupABC): def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironmentABC) -> ConfigurationABC: configuration.add_environment_variables('PYTHON_') configuration.add_environment_variables('CPL_') - configuration.add_console_arguments() + configuration.parse_console_arguments() configuration.add_json_file(f'appsettings.json') configuration.add_json_file(f'appsettings.{configuration.environment.environment_name}.json') configuration.add_json_file(f'appsettings.{configuration.environment.host_name}.json', optional=True) 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..58a35467 --- /dev/null +++ b/src/tests/custom/general/src/general/arguments/generate_argument.py @@ -0,0 +1,16 @@ +from cpl_core.configuration import ConfigurationABC +from cpl_core.configuration.argument_executable_abc import ArgumentExecutableABC +from cpl_core.console import Console +from cpl_core.environment import ApplicationEnvironmentABC + + +class GenerateArgument(ArgumentExecutableABC): + + def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): + ArgumentExecutableABC.__init__(self) + self._config = config + self._env = env + + def run(self, args: list[str]): + Console.error('Generate:') + Console.write_line(args, self._env.environment_name) 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..aca00937 --- /dev/null +++ b/src/tests/custom/general/src/general/arguments/install_argument.py @@ -0,0 +1,11 @@ +from cpl_core.configuration.argument_executable_abc import ArgumentExecutableABC +from cpl_core.console import Console + + +class InstallArgument(ArgumentExecutableABC): + + def __init__(self): + ArgumentExecutableABC.__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..449956f0 --- /dev/null +++ b/src/tests/custom/general/src/general/parameter_startup.py @@ -0,0 +1,32 @@ +from cpl_core.application import StartupExtensionABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum +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(ArgumentTypeEnum.Executable, '', 'generate', ['g', 'G'], GenerateArgument) \ + .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'], ' ') \ + .add_console_argument(ArgumentTypeEnum.Variable, '-', 'o', ['o', 'O'], '=') \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'install', ['i', 'I'], InstallArgument) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) + + def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): + services \ + .add_transient(GenerateArgument) \ + .add_singleton(InstallArgument)