From db28645e988bddc2a6344ab5990f1963cad00ea0 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 30 Nov 2022 15:17:08 +0100 Subject: [PATCH 01/63] Fixed logging #123 --- src/cpl_core/logging/logger_service.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpl_core/logging/logger_service.py b/src/cpl_core/logging/logger_service.py index b3309f96..86feda55 100644 --- a/src/cpl_core/logging/logger_service.py +++ b/src/cpl_core/logging/logger_service.py @@ -169,7 +169,7 @@ class Logger(LoggerABC): # check if message can be shown in console if self._console.value >= LoggingLevelEnum.TRACE.value: - Console.set_foreground_color(ForegroundColorEnum.green) + Console.set_foreground_color(ForegroundColorEnum.grey) Console.write_line(output) Console.set_foreground_color(ForegroundColorEnum.default) @@ -182,7 +182,7 @@ class Logger(LoggerABC): # check if message can be shown in console if self._console.value >= LoggingLevelEnum.DEBUG.value: - Console.set_foreground_color(ForegroundColorEnum.green) + Console.set_foreground_color(ForegroundColorEnum.blue) Console.write_line(output) Console.set_foreground_color(ForegroundColorEnum.default) -- 2.45.1 From f450102c932fee9c09555f1cf476e3b1f3b7e812 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 30 Nov 2022 18:04:40 +0100 Subject: [PATCH 02/63] Fixed cpl g path problems & package names #93 --- cpl-workspace.json | 10 +++- src/cpl_cli/__init__.py | 2 +- src/cpl_cli/_templates/__init__.py | 2 +- src/cpl_cli/_templates/build/__init__.py | 2 +- src/cpl_cli/_templates/generate/__init__.py | 2 +- src/cpl_cli/_templates/new/__init__.py | 2 +- .../_templates/new/console/__init__.py | 2 +- .../_templates/new/console/source/__init__.py | 2 +- .../new/console/source/name/__init__.py | 2 +- .../_templates/new/library/__init__.py | 2 +- .../_templates/new/library/source/__init__.py | 2 +- .../new/library/source/name/__init__.py | 2 +- .../_templates/new/unittest/__init__.py | 2 +- .../new/unittest/source/__init__.py | 2 +- .../new/unittest/source/name/__init__.py | 2 +- src/cpl_cli/_templates/publish/__init__.py | 2 +- src/cpl_cli/command/__init__.py | 2 +- src/cpl_cli/command/generate_service.py | 55 +++++++++++-------- src/cpl_cli/configuration/__init__.py | 2 +- src/cpl_cli/live_server/__init__.py | 2 +- src/cpl_cli/migrations/__init__.py | 2 +- src/cpl_cli/migrations/base/__init__.py | 2 +- src/cpl_cli/migrations/service/__init__.py | 2 +- src/cpl_cli/publish/__init__.py | 2 +- src/cpl_cli/source_creator/__init__.py | 2 +- src/cpl_cli/validators/__init__.py | 2 +- src/cpl_core/__init__.py | 2 +- src/cpl_core/application/__init__.py | 2 +- src/cpl_core/configuration/__init__.py | 2 +- src/cpl_core/console/__init__.py | 2 +- src/cpl_core/database/__init__.py | 2 +- src/cpl_core/database/connection/__init__.py | 2 +- src/cpl_core/database/context/__init__.py | 2 +- src/cpl_core/dependency_injection/__init__.py | 2 +- src/cpl_core/environment/__init__.py | 2 +- src/cpl_core/logging/__init__.py | 2 +- src/cpl_core/mailing/__init__.py | 2 +- src/cpl_core/pipes/__init__.py | 2 +- src/cpl_core/time/__init__.py | 2 +- src/cpl_core/utils/__init__.py | 2 +- src/cpl_discord/__init__.py | 2 +- src/cpl_discord/application/__init__.py | 2 +- src/cpl_discord/command/__init__.py | 2 +- src/cpl_discord/configuration/__init__.py | 2 +- src/cpl_discord/container/__init__.py | 2 +- src/cpl_discord/events/__init__.py | 2 +- src/cpl_discord/helper/__init__.py | 2 +- src/cpl_discord/service/__init__.py | 2 +- src/cpl_query/__init__.py | 2 +- src/cpl_query/base/__init__.py | 2 +- src/cpl_query/enumerable/__init__.py | 2 +- src/cpl_query/extension/__init__.py | 2 +- src/cpl_query/iterable/__init__.py | 2 +- src/cpl_translation/__init__.py | 2 +- tools/set_pip_urls/__init__.py | 2 +- tools/set_version/__init__.py | 2 +- unittests/unittests_cli/build_test_case.py | 2 +- unittests/unittests_cli/cli_test_suite.py | 4 +- unittests/unittests_cli/generate_test_case.py | 54 +++++++++++++++++- unittests/unittests_cli/publish_test_case.py | 4 +- unittests/unittests_cli/update_test_case.py | 2 +- 61 files changed, 153 insertions(+), 86 deletions(-) diff --git a/cpl-workspace.json b/cpl-workspace.json index d07c8cae..081ff298 100644 --- a/cpl-workspace.json +++ b/cpl-workspace.json @@ -131,7 +131,15 @@ "di-cli": "pip install cpl-cli --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de", "di-discord": "pip install cpl-discord --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de", "di-query": "pip install cpl-query --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de", - "di-translation": "pip install cpl-translation --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de" + "di-translation": "pip install cpl-translation --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de", + + "prod-install": "cpl pi-core; cpl pi-cli; cpl pi-query; cpl pi-translation;", + "pi": "cpl prod-install", + "pi-core": "pip install cpl-core --pre --upgrade --extra-index-url https://pip.sh-edraft.de", + "pi-cli": "pip install cpl-cli --pre --upgrade --extra-index-url https://pip.sh-edraft.de", + "pi-discord": "pip install cpl-discord --pre --upgrade --extra-index-url https://pip.sh-edraft.de", + "pi-query": "pip install cpl-query --pre --upgrade --extra-index-url https://pip.sh-edraft.de", + "pi-translation": "pip install cpl-translation --pre --upgrade --extra-index-url https://pip.sh-edraft.de" } } } \ No newline at end of file diff --git a/src/cpl_cli/__init__.py b/src/cpl_cli/__init__.py index 13f8b234..c0ac06e8 100644 --- a/src/cpl_cli/__init__.py +++ b/src/cpl_cli/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli' +__title__ = 'cpl-cli' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/__init__.py b/src/cpl_cli/_templates/__init__.py index d3712583..b4ebc2fe 100644 --- a/src/cpl_cli/_templates/__init__.py +++ b/src/cpl_cli/_templates/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates' +__title__ = '_templates' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/build/__init__.py b/src/cpl_cli/_templates/build/__init__.py index 7f7326a5..b47f7895 100644 --- a/src/cpl_cli/_templates/build/__init__.py +++ b/src/cpl_cli/_templates/build/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.build' +__title__ = '_templates.build' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/generate/__init__.py b/src/cpl_cli/_templates/generate/__init__.py index efb7c762..85fbb8fc 100644 --- a/src/cpl_cli/_templates/generate/__init__.py +++ b/src/cpl_cli/_templates/generate/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.generate' +__title__ = '_templates.generate' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/__init__.py b/src/cpl_cli/_templates/new/__init__.py index f6295997..a1b25a8a 100644 --- a/src/cpl_cli/_templates/new/__init__.py +++ b/src/cpl_cli/_templates/new/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new' +__title__ = '_templates.new' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/console/__init__.py b/src/cpl_cli/_templates/new/console/__init__.py index 72d7f848..a4d26886 100644 --- a/src/cpl_cli/_templates/new/console/__init__.py +++ b/src/cpl_cli/_templates/new/console/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.console' +__title__ = '_templates.new.console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/console/source/__init__.py b/src/cpl_cli/_templates/new/console/source/__init__.py index bd4a870a..ca98b380 100644 --- a/src/cpl_cli/_templates/new/console/source/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.console.source' +__title__ = '_templates.new.console.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' 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 49720a92..07799ad5 100644 --- a/src/cpl_cli/_templates/new/console/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/name/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.console.source.name' +__title__ = '_templates.new.console.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/library/__init__.py b/src/cpl_cli/_templates/new/library/__init__.py index ce0a260c..94c58e91 100644 --- a/src/cpl_cli/_templates/new/library/__init__.py +++ b/src/cpl_cli/_templates/new/library/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.library' +__title__ = '_templates.new.library' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/library/source/__init__.py b/src/cpl_cli/_templates/new/library/source/__init__.py index 9c720806..0cce4499 100644 --- a/src/cpl_cli/_templates/new/library/source/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.library.source' +__title__ = '_templates.new.library.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' 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 0358f17b..92a0debb 100644 --- a/src/cpl_cli/_templates/new/library/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/name/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.library.source.name' +__title__ = '_templates.new.library.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/unittest/__init__.py b/src/cpl_cli/_templates/new/unittest/__init__.py index 346a3785..f51260ef 100644 --- a/src/cpl_cli/_templates/new/unittest/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.unittest' +__title__ = '_templates.new.unittest' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/unittest/source/__init__.py b/src/cpl_cli/_templates/new/unittest/source/__init__.py index 6527f05d..a2fb7c3d 100644 --- a/src/cpl_cli/_templates/new/unittest/source/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/source/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.unittest.source' +__title__ = '_templates.new.unittest.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/unittest/source/name/__init__.py b/src/cpl_cli/_templates/new/unittest/source/name/__init__.py index 1d64ec9a..274c7fb7 100644 --- a/src/cpl_cli/_templates/new/unittest/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/source/name/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.unittest.source.name' +__title__ = '_templates.new.unittest.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/publish/__init__.py b/src/cpl_cli/_templates/publish/__init__.py index 65de0113..f55bb002 100644 --- a/src/cpl_cli/_templates/publish/__init__.py +++ b/src/cpl_cli/_templates/publish/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.publish' +__title__ = '_templates.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/command/__init__.py b/src/cpl_cli/command/__init__.py index 35d87879..f8d8e4f2 100644 --- a/src/cpl_cli/command/__init__.py +++ b/src/cpl_cli/command/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.command' +__title__ = 'command' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index 18b9505c..12236c83 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -14,6 +14,7 @@ from cpl_cli._templates.generate.thread_template import ThreadTemplate from cpl_cli._templates.generate.validator_template import ValidatorTemplate from cpl_cli._templates.template_file_abc import TemplateFileABC from cpl_cli.command_abc import CommandABC +from cpl_cli.configuration import WorkspaceSettings from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.console.console import Console from cpl_core.console.foreground_color_enum import ForegroundColorEnum @@ -22,13 +23,20 @@ from cpl_core.utils.string import String class GenerateService(CommandABC): - def __init__(self, configuration: ConfigurationABC): + def __init__( + self, + configuration: ConfigurationABC, + workspace: WorkspaceSettings, + ): """ Service for the CLI command generate :param configuration: """ CommandABC.__init__(self) + self._config = configuration + self._workspace = workspace + self._schematics = { "abc": { "Upper": "ABC", @@ -129,27 +137,7 @@ class GenerateService(CommandABC): template.write(value) template.close() - def _generate(self, schematic: str, name: str, template: TemplateFileABC): - """ - Generates files by given schematic, name and template - :param schematic: - :param name: - :param template: - :return: - """ - class_name = name - rel_path = '' - if '/' in name: - parts = name.split('/') - rel_path = '/'.join(parts[:-1]) - class_name = parts[len(parts) - 1] - - if 'src' not in rel_path and not os.path.exists(os.path.join(self._env.working_directory, rel_path)): - rel_path = f'src/{rel_path}' - - template = template(class_name, schematic, self._schematics[schematic]["Upper"], rel_path) - - file_path = os.path.join(self._env.working_directory, template.path, template.name) + def _create_init_files(self, file_path: str, template: TemplateFileABC, class_name: str, schematic: str, rel_path: str): if not os.path.isdir(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) directory = '' @@ -171,6 +159,29 @@ class GenerateService(CommandABC): spinner_foreground_color=ForegroundColorEnum.cyan ) + def _generate(self, schematic: str, name: str, template: TemplateFileABC): + """ + Generates files by given schematic, name and template + :param schematic: + :param name: + :param template: + :return: + """ + class_name = name + rel_path = '' + if '/' in name: + parts = name.split('/') + rel_path = '/'.join(parts[:-1]) + class_name = parts[len(parts) - 1] + + if self._workspace is not None and parts[0] in self._workspace.projects: + rel_path = os.path.dirname(self._workspace.projects[parts[0]]) + + template = template(class_name, schematic, self._schematics[schematic]["Upper"], rel_path) + + file_path = os.path.join(self._env.working_directory, template.path, template.name) + self._create_init_files(file_path, template, class_name, schematic, rel_path) + if os.path.isfile(file_path): Console.error(f'{String.first_to_upper(schematic)} already exists!\n') sys.exit() diff --git a/src/cpl_cli/configuration/__init__.py b/src/cpl_cli/configuration/__init__.py index 3b14d039..89471726 100644 --- a/src/cpl_cli/configuration/__init__.py +++ b/src/cpl_cli/configuration/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.configuration' +__title__ = 'configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/live_server/__init__.py b/src/cpl_cli/live_server/__init__.py index 86e9bded..fdf9cdd8 100644 --- a/src/cpl_cli/live_server/__init__.py +++ b/src/cpl_cli/live_server/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.live_server' +__title__ = 'live_server' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/migrations/__init__.py b/src/cpl_cli/migrations/__init__.py index 196cafd0..2292d1d6 100644 --- a/src/cpl_cli/migrations/__init__.py +++ b/src/cpl_cli/migrations/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.migrations' +__title__ = 'migrations' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/migrations/base/__init__.py b/src/cpl_cli/migrations/base/__init__.py index c9c00535..59143532 100644 --- a/src/cpl_cli/migrations/base/__init__.py +++ b/src/cpl_cli/migrations/base/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.migrations.base' +__title__ = 'migrations.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/migrations/service/__init__.py b/src/cpl_cli/migrations/service/__init__.py index 4dc93e5a..87152def 100644 --- a/src/cpl_cli/migrations/service/__init__.py +++ b/src/cpl_cli/migrations/service/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.migrations.service' +__title__ = 'migrations.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/publish/__init__.py b/src/cpl_cli/publish/__init__.py index e02b1c63..7ef12225 100644 --- a/src/cpl_cli/publish/__init__.py +++ b/src/cpl_cli/publish/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.publish' +__title__ = 'publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/source_creator/__init__.py b/src/cpl_cli/source_creator/__init__.py index edcf1ee3..88a53b8d 100644 --- a/src/cpl_cli/source_creator/__init__.py +++ b/src/cpl_cli/source_creator/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.source_creator' +__title__ = 'source_creator' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/validators/__init__.py b/src/cpl_cli/validators/__init__.py index 6e3e2300..a247d409 100644 --- a/src/cpl_cli/validators/__init__.py +++ b/src/cpl_cli/validators/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.validators' +__title__ = 'validators' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/__init__.py b/src/cpl_core/__init__.py index b9b5c269..831d4cdb 100644 --- a/src/cpl_core/__init__.py +++ b/src/cpl_core/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core' +__title__ = 'cpl-core' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/application/__init__.py b/src/cpl_core/application/__init__.py index 025c205a..6c4785bb 100644 --- a/src/cpl_core/application/__init__.py +++ b/src/cpl_core/application/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.application' +__title__ = 'application' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/configuration/__init__.py b/src/cpl_core/configuration/__init__.py index cef5c5dd..3b3742eb 100644 --- a/src/cpl_core/configuration/__init__.py +++ b/src/cpl_core/configuration/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.configuration' +__title__ = 'configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/console/__init__.py b/src/cpl_core/console/__init__.py index 18525b46..41363ef7 100644 --- a/src/cpl_core/console/__init__.py +++ b/src/cpl_core/console/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.console' +__title__ = 'console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/database/__init__.py b/src/cpl_core/database/__init__.py index c2e5b49a..2b59e2e1 100644 --- a/src/cpl_core/database/__init__.py +++ b/src/cpl_core/database/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.database' +__title__ = 'database' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/database/connection/__init__.py b/src/cpl_core/database/connection/__init__.py index c1851618..f27d336e 100644 --- a/src/cpl_core/database/connection/__init__.py +++ b/src/cpl_core/database/connection/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.database.connection' +__title__ = 'database.connection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/database/context/__init__.py b/src/cpl_core/database/context/__init__.py index 224ddb32..728be14a 100644 --- a/src/cpl_core/database/context/__init__.py +++ b/src/cpl_core/database/context/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.database.context' +__title__ = 'database.context' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/dependency_injection/__init__.py b/src/cpl_core/dependency_injection/__init__.py index b35fb03e..4f2322e3 100644 --- a/src/cpl_core/dependency_injection/__init__.py +++ b/src/cpl_core/dependency_injection/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.dependency_injection' +__title__ = 'dependency_injection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/environment/__init__.py b/src/cpl_core/environment/__init__.py index 587fd780..4ac8db8b 100644 --- a/src/cpl_core/environment/__init__.py +++ b/src/cpl_core/environment/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.environment' +__title__ = 'environment' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/logging/__init__.py b/src/cpl_core/logging/__init__.py index 6afacdbe..0d92764a 100644 --- a/src/cpl_core/logging/__init__.py +++ b/src/cpl_core/logging/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.logging' +__title__ = 'logging' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/mailing/__init__.py b/src/cpl_core/mailing/__init__.py index a63daf4a..077fb36d 100644 --- a/src/cpl_core/mailing/__init__.py +++ b/src/cpl_core/mailing/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.mailing' +__title__ = 'mailing' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/pipes/__init__.py b/src/cpl_core/pipes/__init__.py index 6afcae2a..7502f6c5 100644 --- a/src/cpl_core/pipes/__init__.py +++ b/src/cpl_core/pipes/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.pipes' +__title__ = 'pipes' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/time/__init__.py b/src/cpl_core/time/__init__.py index 45aacf77..55c05086 100644 --- a/src/cpl_core/time/__init__.py +++ b/src/cpl_core/time/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.time' +__title__ = 'time' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/utils/__init__.py b/src/cpl_core/utils/__init__.py index 64179a2b..893d5903 100644 --- a/src/cpl_core/utils/__init__.py +++ b/src/cpl_core/utils/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.utils' +__title__ = 'utils' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/__init__.py b/src/cpl_discord/__init__.py index 9e01b9a4..9b4f67d8 100644 --- a/src/cpl_discord/__init__.py +++ b/src/cpl_discord/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord' +__title__ = 'cpl-discord' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/application/__init__.py b/src/cpl_discord/application/__init__.py index b513d032..f7cc5b3e 100644 --- a/src/cpl_discord/application/__init__.py +++ b/src/cpl_discord/application/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.application' +__title__ = 'application' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/command/__init__.py b/src/cpl_discord/command/__init__.py index 9ccd88da..15b8bd13 100644 --- a/src/cpl_discord/command/__init__.py +++ b/src/cpl_discord/command/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.command' +__title__ = 'command' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/configuration/__init__.py b/src/cpl_discord/configuration/__init__.py index 51110c41..c0b7cfcd 100644 --- a/src/cpl_discord/configuration/__init__.py +++ b/src/cpl_discord/configuration/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.configuration' +__title__ = 'configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/container/__init__.py b/src/cpl_discord/container/__init__.py index 009623c6..c9d25138 100644 --- a/src/cpl_discord/container/__init__.py +++ b/src/cpl_discord/container/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.container' +__title__ = 'container' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/events/__init__.py b/src/cpl_discord/events/__init__.py index d961d3ad..9c7f7f8c 100644 --- a/src/cpl_discord/events/__init__.py +++ b/src/cpl_discord/events/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.events' +__title__ = 'events' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/helper/__init__.py b/src/cpl_discord/helper/__init__.py index 5eb30f53..db6a6d9c 100644 --- a/src/cpl_discord/helper/__init__.py +++ b/src/cpl_discord/helper/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.helper' +__title__ = 'helper' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/service/__init__.py b/src/cpl_discord/service/__init__.py index 4223e0f8..5756e668 100644 --- a/src/cpl_discord/service/__init__.py +++ b/src/cpl_discord/service/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.service' +__title__ = 'service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 86fe8082..2e2559f6 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'cpl_query' +__title__ = 'cpl-query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/base/__init__.py b/src/cpl_query/base/__init__.py index ab831d0a..23c921da 100644 --- a/src/cpl_query/base/__init__.py +++ b/src/cpl_query/base/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'cpl_query.base' +__title__ = 'base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index 9bd1147e..14d10619 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'cpl_query.enumerable' +__title__ = 'enumerable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index c47d1d20..54cdcac2 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'cpl_query.extension' +__title__ = 'extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index d129a1c1..45cde067 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'cpl_query.iterable' +__title__ = 'iterable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_translation/__init__.py b/src/cpl_translation/__init__.py index d789a358..2c3eedb0 100644 --- a/src/cpl_translation/__init__.py +++ b/src/cpl_translation/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python Translation """ -__title__ = 'cpl_translation' +__title__ = 'cpl-translation' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' diff --git a/tools/set_pip_urls/__init__.py b/tools/set_pip_urls/__init__.py index 293c4a42..290901d9 100644 --- a/tools/set_pip_urls/__init__.py +++ b/tools/set_pip_urls/__init__.py @@ -11,7 +11,7 @@ CPL internal tool to set pip URL for CLI by environment """ -__title__ = 'set_pip_urls' +__title__ = 'set-pip-urls' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' diff --git a/tools/set_version/__init__.py b/tools/set_version/__init__.py index ef7b39f6..47ab1c7b 100644 --- a/tools/set_version/__init__.py +++ b/tools/set_version/__init__.py @@ -11,7 +11,7 @@ CPL internal tool to set version from branch name """ -__title__ = 'set_version' +__title__ = 'set-version' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' diff --git a/unittests/unittests_cli/build_test_case.py b/unittests/unittests_cli/build_test_case.py index e35d5cbd..6594bd08 100644 --- a/unittests/unittests_cli/build_test_case.py +++ b/unittests/unittests_cli/build_test_case.py @@ -78,7 +78,7 @@ class BuildTestCase(unittest.TestCase): def test_build(self): CLICommands.build() dist_path = './dist' - full_dist_path = f'{dist_path}/{self._source}/build/{String.convert_to_snake_case(self._source)}' + full_dist_path = f'{dist_path}/{self._source}/build/' self.assertTrue(os.path.exists(dist_path)) self.assertTrue(os.path.exists(full_dist_path)) self.assertFalse(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) diff --git a/unittests/unittests_cli/cli_test_suite.py b/unittests/unittests_cli/cli_test_suite.py index f26f3f3a..65cb6355 100644 --- a/unittests/unittests_cli/cli_test_suite.py +++ b/unittests/unittests_cli/cli_test_suite.py @@ -32,8 +32,8 @@ class CLITestSuite(unittest.TestSuite): active_tests = [ # nothing needed VersionTestCase, - GenerateTestCase, NewTestCase, + GenerateTestCase, # project needed BuildTestCase, PublishTestCase, @@ -75,4 +75,4 @@ class CLITestSuite(unittest.TestSuite): def run(self, *args): self._setup() self._result = super().run(*args) - self._cleanup() + # self._cleanup() diff --git a/unittests/unittests_cli/generate_test_case.py b/unittests/unittests_cli/generate_test_case.py index 53c03839..c53f28d5 100644 --- a/unittests/unittests_cli/generate_test_case.py +++ b/unittests/unittests_cli/generate_test_case.py @@ -1,41 +1,89 @@ import os.path import unittest +from cpl_core.utils import String from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands class GenerateTestCase(unittest.TestCase): + _project = 'test-console' + _t_path = 'test' - def _test_file(self, schematic: str, suffix: str): - CLICommands.generate(schematic, 'GeneratedFile') - file_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, f'generated_file{suffix}.py')) + @classmethod + def setUpClass(cls): + CLICommands.new('console', cls._project, '--ab', '--s', '--venv') + + def setUp(self): + os.chdir(PLAYGROUND_PATH) + + def _test_file(self, schematic: str, suffix: str, path=None): + file = 'GeneratedFile' + expected_path = f'generated_file{suffix}.py' + if path is not None: + file = f'{path}/{file}' + expected_path = f'{path}/{expected_path}' + CLICommands.generate(schematic, file) + file_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, expected_path)) file_exists = os.path.exists(file_path) self.assertTrue(file_exists) + def _test_file_with_project(self, schematic: str, suffix: str, path=None, enter=True): + file = f'GeneratedFile' + excepted_path = f'generated_file{suffix}.py' + if path is not None: + excepted_path = f'{self._project}/src/{String.convert_to_snake_case(self._project)}/{path}/generated_file_in_project{suffix}.py' + if enter: + os.chdir(path) + excepted_path = f'{path}/src/{String.convert_to_snake_case(self._project)}/generated_file_in_project{suffix}.py' + + file = f'{path}/GeneratedFileInProject' + + CLICommands.generate(schematic, file) + file_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, excepted_path)) + self.assertTrue(os.path.exists(file_path)) + def test_abc(self): self._test_file('abc', '_abc') + self._test_file('abc', '_abc', path=self._t_path) + self._test_file('abc', '_abc', path=f'{self._t_path}/{self._t_path}') + self._test_file_with_project('abc', '_abc', path=self._project) + os.chdir(f'src/{String.convert_to_snake_case(self._project)}') + self._test_file_with_project('abc', '_abc', path='test', enter=False) def test_class(self): self._test_file('class', '') + self._test_file('class', '', path=self._t_path) + self._test_file_with_project('class', '', path=self._project) def test_enum(self): self._test_file('enum', '_enum') + self._test_file('enum', '_enum', path=self._t_path) + self._test_file_with_project('enum', '_enum', path=self._project) + os.chdir(f'src/{String.convert_to_snake_case(self._project)}') + self._test_file_with_project('enum', '_enum', path='test', enter=False) def test_pipe(self): self._test_file('pipe', '_pipe') + self._test_file('pipe', '_pipe', path=self._t_path) + self._test_file_with_project('pipe', '_pipe', path=self._project) def test_service(self): self._test_file('service', '_service') + self._test_file_with_project('service', '_service', path=self._project) def test_settings(self): self._test_file('settings', '_settings') + self._test_file_with_project('settings', '_settings', path=self._project) def test_test_case(self): self._test_file('test_case', '_test_case') + self._test_file_with_project('test_case', '_test_case', path=self._project) def test_thread(self): self._test_file('thread', '_thread') + self._test_file_with_project('thread', '_thread', path=self._project) def test_validator(self): self._test_file('validator', '_validator') + self._test_file_with_project('validator', '_validator', path=self._project) diff --git a/unittests/unittests_cli/publish_test_case.py b/unittests/unittests_cli/publish_test_case.py index 7c828ced..b24531c5 100644 --- a/unittests/unittests_cli/publish_test_case.py +++ b/unittests/unittests_cli/publish_test_case.py @@ -79,7 +79,7 @@ class PublishTestCase(unittest.TestCase): CLICommands.publish() dist_path = './dist' setup_path = f'{dist_path}/{self._source}/publish/setup' - full_dist_path = f'{dist_path}/{self._source}/publish/build/lib/{String.convert_to_snake_case(self._source)}' + full_dist_path = f'{dist_path}/{self._source}/publish/' self.assertTrue(os.path.exists(dist_path)) self.assertTrue(os.path.exists(setup_path)) self.assertTrue(os.path.exists(os.path.join(setup_path, f'{self._source}-0.0.0.tar.gz'))) @@ -89,4 +89,4 @@ class PublishTestCase(unittest.TestCase): with open(f'{full_dist_path}/{self._source}.json', 'w') as file: file.write(json.dumps(self._get_project_settings(), indent=2)) file.close() - self.assertTrue(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) + # self.assertTrue(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) diff --git a/unittests/unittests_cli/update_test_case.py b/unittests/unittests_cli/update_test_case.py index de21bf6b..3b50b38c 100644 --- a/unittests/unittests_cli/update_test_case.py +++ b/unittests/unittests_cli/update_test_case.py @@ -22,7 +22,7 @@ class UpdateTestCase(unittest.TestCase): self._old_package = f'{self._old_package_name}=={self._old_version}' # todo: better way to do shit required - self._new_version = '2.0.1' + self._new_version = '2.1.0' self._new_package_name = 'discord.py' self._new_package = f'{self._new_package_name}=={self._new_version}' -- 2.45.1 From abd03527507e462ea41965c9f5eaedd1960b5879 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 30 Nov 2022 19:05:11 +0100 Subject: [PATCH 03/63] Repaired build & publish #93 --- src/cpl_cli/__init__.py | 2 +- src/cpl_cli/_templates/__init__.py | 2 +- src/cpl_cli/_templates/build/__init__.py | 2 +- src/cpl_cli/_templates/generate/__init__.py | 2 +- src/cpl_cli/_templates/new/__init__.py | 2 +- src/cpl_cli/_templates/new/console/__init__.py | 2 +- src/cpl_cli/_templates/new/console/source/__init__.py | 2 +- src/cpl_cli/_templates/new/console/source/name/__init__.py | 2 +- src/cpl_cli/_templates/new/library/__init__.py | 2 +- src/cpl_cli/_templates/new/library/source/__init__.py | 2 +- src/cpl_cli/_templates/new/library/source/name/__init__.py | 2 +- src/cpl_cli/_templates/new/unittest/__init__.py | 2 +- src/cpl_cli/_templates/new/unittest/source/__init__.py | 2 +- src/cpl_cli/_templates/new/unittest/source/name/__init__.py | 2 +- src/cpl_cli/_templates/publish/__init__.py | 2 +- src/cpl_cli/command/__init__.py | 2 +- src/cpl_cli/configuration/__init__.py | 2 +- src/cpl_cli/live_server/__init__.py | 2 +- src/cpl_cli/migrations/__init__.py | 2 +- src/cpl_cli/migrations/base/__init__.py | 2 +- src/cpl_cli/migrations/service/__init__.py | 2 +- src/cpl_cli/publish/__init__.py | 2 +- src/cpl_cli/publish/publisher_service.py | 4 ++-- src/cpl_cli/source_creator/__init__.py | 2 +- src/cpl_cli/validators/__init__.py | 2 +- unittests/unittests_cli/build_test_case.py | 2 +- unittests/unittests_cli/publish_test_case.py | 4 ++-- 27 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/cpl_cli/__init__.py b/src/cpl_cli/__init__.py index c0ac06e8..13f8b234 100644 --- a/src/cpl_cli/__init__.py +++ b/src/cpl_cli/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl-cli' +__title__ = 'cpl_cli' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/__init__.py b/src/cpl_cli/_templates/__init__.py index b4ebc2fe..d3712583 100644 --- a/src/cpl_cli/_templates/__init__.py +++ b/src/cpl_cli/_templates/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates' +__title__ = 'cpl_cli._templates' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/build/__init__.py b/src/cpl_cli/_templates/build/__init__.py index b47f7895..7f7326a5 100644 --- a/src/cpl_cli/_templates/build/__init__.py +++ b/src/cpl_cli/_templates/build/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.build' +__title__ = 'cpl_cli._templates.build' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/generate/__init__.py b/src/cpl_cli/_templates/generate/__init__.py index 85fbb8fc..efb7c762 100644 --- a/src/cpl_cli/_templates/generate/__init__.py +++ b/src/cpl_cli/_templates/generate/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.generate' +__title__ = 'cpl_cli._templates.generate' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/__init__.py b/src/cpl_cli/_templates/new/__init__.py index a1b25a8a..f6295997 100644 --- a/src/cpl_cli/_templates/new/__init__.py +++ b/src/cpl_cli/_templates/new/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new' +__title__ = 'cpl_cli._templates.new' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/console/__init__.py b/src/cpl_cli/_templates/new/console/__init__.py index a4d26886..72d7f848 100644 --- a/src/cpl_cli/_templates/new/console/__init__.py +++ b/src/cpl_cli/_templates/new/console/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.console' +__title__ = 'cpl_cli._templates.new.console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/console/source/__init__.py b/src/cpl_cli/_templates/new/console/source/__init__.py index ca98b380..bd4a870a 100644 --- a/src/cpl_cli/_templates/new/console/source/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.console.source' +__title__ = 'cpl_cli._templates.new.console.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' 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 07799ad5..49720a92 100644 --- a/src/cpl_cli/_templates/new/console/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/name/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.console.source.name' +__title__ = 'cpl_cli._templates.new.console.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/library/__init__.py b/src/cpl_cli/_templates/new/library/__init__.py index 94c58e91..ce0a260c 100644 --- a/src/cpl_cli/_templates/new/library/__init__.py +++ b/src/cpl_cli/_templates/new/library/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.library' +__title__ = 'cpl_cli._templates.new.library' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/library/source/__init__.py b/src/cpl_cli/_templates/new/library/source/__init__.py index 0cce4499..9c720806 100644 --- a/src/cpl_cli/_templates/new/library/source/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.library.source' +__title__ = 'cpl_cli._templates.new.library.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' 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 92a0debb..0358f17b 100644 --- a/src/cpl_cli/_templates/new/library/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/name/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.library.source.name' +__title__ = 'cpl_cli._templates.new.library.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/unittest/__init__.py b/src/cpl_cli/_templates/new/unittest/__init__.py index f51260ef..346a3785 100644 --- a/src/cpl_cli/_templates/new/unittest/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.unittest' +__title__ = 'cpl_cli._templates.new.unittest' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/unittest/source/__init__.py b/src/cpl_cli/_templates/new/unittest/source/__init__.py index a2fb7c3d..6527f05d 100644 --- a/src/cpl_cli/_templates/new/unittest/source/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/source/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.unittest.source' +__title__ = 'cpl_cli._templates.new.unittest.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/unittest/source/name/__init__.py b/src/cpl_cli/_templates/new/unittest/source/name/__init__.py index 274c7fb7..1d64ec9a 100644 --- a/src/cpl_cli/_templates/new/unittest/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/source/name/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.unittest.source.name' +__title__ = 'cpl_cli._templates.new.unittest.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/publish/__init__.py b/src/cpl_cli/_templates/publish/__init__.py index f55bb002..65de0113 100644 --- a/src/cpl_cli/_templates/publish/__init__.py +++ b/src/cpl_cli/_templates/publish/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.publish' +__title__ = 'cpl_cli._templates.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/command/__init__.py b/src/cpl_cli/command/__init__.py index f8d8e4f2..35d87879 100644 --- a/src/cpl_cli/command/__init__.py +++ b/src/cpl_cli/command/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'command' +__title__ = 'cpl_cli.command' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/configuration/__init__.py b/src/cpl_cli/configuration/__init__.py index 89471726..3b14d039 100644 --- a/src/cpl_cli/configuration/__init__.py +++ b/src/cpl_cli/configuration/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'configuration' +__title__ = 'cpl_cli.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/live_server/__init__.py b/src/cpl_cli/live_server/__init__.py index fdf9cdd8..86e9bded 100644 --- a/src/cpl_cli/live_server/__init__.py +++ b/src/cpl_cli/live_server/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'live_server' +__title__ = 'cpl_cli.live_server' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/migrations/__init__.py b/src/cpl_cli/migrations/__init__.py index 2292d1d6..196cafd0 100644 --- a/src/cpl_cli/migrations/__init__.py +++ b/src/cpl_cli/migrations/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'migrations' +__title__ = 'cpl_cli.migrations' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/migrations/base/__init__.py b/src/cpl_cli/migrations/base/__init__.py index 59143532..c9c00535 100644 --- a/src/cpl_cli/migrations/base/__init__.py +++ b/src/cpl_cli/migrations/base/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'migrations.base' +__title__ = 'cpl_cli.migrations.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/migrations/service/__init__.py b/src/cpl_cli/migrations/service/__init__.py index 87152def..4dc93e5a 100644 --- a/src/cpl_cli/migrations/service/__init__.py +++ b/src/cpl_cli/migrations/service/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'migrations.service' +__title__ = 'cpl_cli.migrations.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/publish/__init__.py b/src/cpl_cli/publish/__init__.py index 7ef12225..e02b1c63 100644 --- a/src/cpl_cli/publish/__init__.py +++ b/src/cpl_cli/publish/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'publish' +__title__ = 'cpl_cli.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/publish/publisher_service.py b/src/cpl_cli/publish/publisher_service.py index 72596219..b1639023 100644 --- a/src/cpl_cli/publish/publisher_service.py +++ b/src/cpl_cli/publish/publisher_service.py @@ -433,7 +433,7 @@ class PublisherService(PublisherABC): 3. Copies all included source files to dist_path/build :return: """ - # self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) # probably causing some errors (#125) + self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) # probably causing some errors (#125) self.exclude(f'*/{self._project_settings.name}.json') self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, 'build')) @@ -456,7 +456,7 @@ class PublisherService(PublisherABC): 4. Remove all included source from dist_path/publish :return: """ - # self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) # probably causing some errors (#125) + self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) # probably causing some errors (#125) self.exclude(f'*/{self._project_settings.name}.json') self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, 'publish')) diff --git a/src/cpl_cli/source_creator/__init__.py b/src/cpl_cli/source_creator/__init__.py index 88a53b8d..edcf1ee3 100644 --- a/src/cpl_cli/source_creator/__init__.py +++ b/src/cpl_cli/source_creator/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'source_creator' +__title__ = 'cpl_cli.source_creator' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/validators/__init__.py b/src/cpl_cli/validators/__init__.py index a247d409..6e3e2300 100644 --- a/src/cpl_cli/validators/__init__.py +++ b/src/cpl_cli/validators/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'validators' +__title__ = 'cpl_cli.validators' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/unittests/unittests_cli/build_test_case.py b/unittests/unittests_cli/build_test_case.py index 6594bd08..e35d5cbd 100644 --- a/unittests/unittests_cli/build_test_case.py +++ b/unittests/unittests_cli/build_test_case.py @@ -78,7 +78,7 @@ class BuildTestCase(unittest.TestCase): def test_build(self): CLICommands.build() dist_path = './dist' - full_dist_path = f'{dist_path}/{self._source}/build/' + full_dist_path = f'{dist_path}/{self._source}/build/{String.convert_to_snake_case(self._source)}' self.assertTrue(os.path.exists(dist_path)) self.assertTrue(os.path.exists(full_dist_path)) self.assertFalse(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) diff --git a/unittests/unittests_cli/publish_test_case.py b/unittests/unittests_cli/publish_test_case.py index b24531c5..7c828ced 100644 --- a/unittests/unittests_cli/publish_test_case.py +++ b/unittests/unittests_cli/publish_test_case.py @@ -79,7 +79,7 @@ class PublishTestCase(unittest.TestCase): CLICommands.publish() dist_path = './dist' setup_path = f'{dist_path}/{self._source}/publish/setup' - full_dist_path = f'{dist_path}/{self._source}/publish/' + full_dist_path = f'{dist_path}/{self._source}/publish/build/lib/{String.convert_to_snake_case(self._source)}' self.assertTrue(os.path.exists(dist_path)) self.assertTrue(os.path.exists(setup_path)) self.assertTrue(os.path.exists(os.path.join(setup_path, f'{self._source}-0.0.0.tar.gz'))) @@ -89,4 +89,4 @@ class PublishTestCase(unittest.TestCase): with open(f'{full_dist_path}/{self._source}.json', 'w') as file: file.write(json.dumps(self._get_project_settings(), indent=2)) file.close() - # self.assertTrue(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) + self.assertTrue(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) -- 2.45.1 From 2e8be741cc498f1de5f6647903ff124bfd000633 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 1 Dec 2022 12:17:26 +0100 Subject: [PATCH 04/63] Repaired build & publish #93 --- src/cpl_core/__init__.py | 2 +- src/cpl_core/application/__init__.py | 2 +- src/cpl_core/configuration/__init__.py | 2 +- src/cpl_core/console/__init__.py | 2 +- src/cpl_core/database/__init__.py | 2 +- src/cpl_core/database/connection/__init__.py | 2 +- src/cpl_core/database/context/__init__.py | 2 +- src/cpl_core/dependency_injection/__init__.py | 2 +- src/cpl_core/environment/__init__.py | 2 +- src/cpl_core/logging/__init__.py | 2 +- src/cpl_core/mailing/__init__.py | 2 +- src/cpl_core/pipes/__init__.py | 2 +- src/cpl_core/time/__init__.py | 2 +- src/cpl_core/utils/__init__.py | 2 +- src/cpl_discord/__init__.py | 2 +- src/cpl_discord/application/__init__.py | 2 +- src/cpl_discord/command/__init__.py | 2 +- src/cpl_discord/configuration/__init__.py | 2 +- src/cpl_discord/container/__init__.py | 2 +- src/cpl_discord/events/__init__.py | 2 +- src/cpl_discord/helper/__init__.py | 2 +- src/cpl_discord/service/__init__.py | 2 +- src/cpl_query/__init__.py | 2 +- src/cpl_query/base/__init__.py | 2 +- src/cpl_query/enumerable/__init__.py | 2 +- src/cpl_query/extension/__init__.py | 2 +- src/cpl_query/iterable/__init__.py | 2 +- src/cpl_translation/__init__.py | 2 +- tools/set_pip_urls/__init__.py | 2 +- tools/set_version/__init__.py | 2 +- 30 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/cpl_core/__init__.py b/src/cpl_core/__init__.py index 831d4cdb..b9b5c269 100644 --- a/src/cpl_core/__init__.py +++ b/src/cpl_core/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl-core' +__title__ = 'cpl_core' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/application/__init__.py b/src/cpl_core/application/__init__.py index 6c4785bb..025c205a 100644 --- a/src/cpl_core/application/__init__.py +++ b/src/cpl_core/application/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'application' +__title__ = 'cpl_core.application' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/configuration/__init__.py b/src/cpl_core/configuration/__init__.py index 3b3742eb..cef5c5dd 100644 --- a/src/cpl_core/configuration/__init__.py +++ b/src/cpl_core/configuration/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'configuration' +__title__ = 'cpl_core.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/console/__init__.py b/src/cpl_core/console/__init__.py index 41363ef7..18525b46 100644 --- a/src/cpl_core/console/__init__.py +++ b/src/cpl_core/console/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'console' +__title__ = 'cpl_core.console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/database/__init__.py b/src/cpl_core/database/__init__.py index 2b59e2e1..c2e5b49a 100644 --- a/src/cpl_core/database/__init__.py +++ b/src/cpl_core/database/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'database' +__title__ = 'cpl_core.database' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/database/connection/__init__.py b/src/cpl_core/database/connection/__init__.py index f27d336e..c1851618 100644 --- a/src/cpl_core/database/connection/__init__.py +++ b/src/cpl_core/database/connection/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'database.connection' +__title__ = 'cpl_core.database.connection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/database/context/__init__.py b/src/cpl_core/database/context/__init__.py index 728be14a..224ddb32 100644 --- a/src/cpl_core/database/context/__init__.py +++ b/src/cpl_core/database/context/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'database.context' +__title__ = 'cpl_core.database.context' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/dependency_injection/__init__.py b/src/cpl_core/dependency_injection/__init__.py index 4f2322e3..b35fb03e 100644 --- a/src/cpl_core/dependency_injection/__init__.py +++ b/src/cpl_core/dependency_injection/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'dependency_injection' +__title__ = 'cpl_core.dependency_injection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/environment/__init__.py b/src/cpl_core/environment/__init__.py index 4ac8db8b..587fd780 100644 --- a/src/cpl_core/environment/__init__.py +++ b/src/cpl_core/environment/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'environment' +__title__ = 'cpl_core.environment' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/logging/__init__.py b/src/cpl_core/logging/__init__.py index 0d92764a..6afacdbe 100644 --- a/src/cpl_core/logging/__init__.py +++ b/src/cpl_core/logging/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'logging' +__title__ = 'cpl_core.logging' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/mailing/__init__.py b/src/cpl_core/mailing/__init__.py index 077fb36d..a63daf4a 100644 --- a/src/cpl_core/mailing/__init__.py +++ b/src/cpl_core/mailing/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'mailing' +__title__ = 'cpl_core.mailing' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/pipes/__init__.py b/src/cpl_core/pipes/__init__.py index 7502f6c5..6afcae2a 100644 --- a/src/cpl_core/pipes/__init__.py +++ b/src/cpl_core/pipes/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'pipes' +__title__ = 'cpl_core.pipes' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/time/__init__.py b/src/cpl_core/time/__init__.py index 55c05086..45aacf77 100644 --- a/src/cpl_core/time/__init__.py +++ b/src/cpl_core/time/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'time' +__title__ = 'cpl_core.time' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/utils/__init__.py b/src/cpl_core/utils/__init__.py index 893d5903..64179a2b 100644 --- a/src/cpl_core/utils/__init__.py +++ b/src/cpl_core/utils/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'utils' +__title__ = 'cpl_core.utils' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/__init__.py b/src/cpl_discord/__init__.py index 9b4f67d8..9e01b9a4 100644 --- a/src/cpl_discord/__init__.py +++ b/src/cpl_discord/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl-discord' +__title__ = 'cpl_discord' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/application/__init__.py b/src/cpl_discord/application/__init__.py index f7cc5b3e..b513d032 100644 --- a/src/cpl_discord/application/__init__.py +++ b/src/cpl_discord/application/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'application' +__title__ = 'cpl_discord.application' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/command/__init__.py b/src/cpl_discord/command/__init__.py index 15b8bd13..9ccd88da 100644 --- a/src/cpl_discord/command/__init__.py +++ b/src/cpl_discord/command/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'command' +__title__ = 'cpl_discord.command' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/configuration/__init__.py b/src/cpl_discord/configuration/__init__.py index c0b7cfcd..51110c41 100644 --- a/src/cpl_discord/configuration/__init__.py +++ b/src/cpl_discord/configuration/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'configuration' +__title__ = 'cpl_discord.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/container/__init__.py b/src/cpl_discord/container/__init__.py index c9d25138..009623c6 100644 --- a/src/cpl_discord/container/__init__.py +++ b/src/cpl_discord/container/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'container' +__title__ = 'cpl_discord.container' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/events/__init__.py b/src/cpl_discord/events/__init__.py index 9c7f7f8c..d961d3ad 100644 --- a/src/cpl_discord/events/__init__.py +++ b/src/cpl_discord/events/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'events' +__title__ = 'cpl_discord.events' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/helper/__init__.py b/src/cpl_discord/helper/__init__.py index db6a6d9c..5eb30f53 100644 --- a/src/cpl_discord/helper/__init__.py +++ b/src/cpl_discord/helper/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'helper' +__title__ = 'cpl_discord.helper' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/service/__init__.py b/src/cpl_discord/service/__init__.py index 5756e668..4223e0f8 100644 --- a/src/cpl_discord/service/__init__.py +++ b/src/cpl_discord/service/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'service' +__title__ = 'cpl_discord.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 2e2559f6..86fe8082 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'cpl-query' +__title__ = 'cpl_query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/base/__init__.py b/src/cpl_query/base/__init__.py index 23c921da..ab831d0a 100644 --- a/src/cpl_query/base/__init__.py +++ b/src/cpl_query/base/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'base' +__title__ = 'cpl_query.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index 14d10619..9bd1147e 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'enumerable' +__title__ = 'cpl_query.enumerable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index 54cdcac2..c47d1d20 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'extension' +__title__ = 'cpl_query.extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index 45cde067..d129a1c1 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'iterable' +__title__ = 'cpl_query.iterable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_translation/__init__.py b/src/cpl_translation/__init__.py index 2c3eedb0..d789a358 100644 --- a/src/cpl_translation/__init__.py +++ b/src/cpl_translation/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python Translation """ -__title__ = 'cpl-translation' +__title__ = 'cpl_translation' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' diff --git a/tools/set_pip_urls/__init__.py b/tools/set_pip_urls/__init__.py index 290901d9..293c4a42 100644 --- a/tools/set_pip_urls/__init__.py +++ b/tools/set_pip_urls/__init__.py @@ -11,7 +11,7 @@ CPL internal tool to set pip URL for CLI by environment """ -__title__ = 'set-pip-urls' +__title__ = 'set_pip_urls' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' diff --git a/tools/set_version/__init__.py b/tools/set_version/__init__.py index 47ab1c7b..ef7b39f6 100644 --- a/tools/set_version/__init__.py +++ b/tools/set_version/__init__.py @@ -11,7 +11,7 @@ CPL internal tool to set version from branch name """ -__title__ = 'set-version' +__title__ = 'set_version' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' -- 2.45.1 From 8bd237206cfc0a0d58e0617f3f3e328d24c2737f Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 30 Nov 2022 15:17:08 +0100 Subject: [PATCH 05/63] Fixed logging #123 --- src/cpl_core/logging/logger_service.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpl_core/logging/logger_service.py b/src/cpl_core/logging/logger_service.py index b3309f96..86feda55 100644 --- a/src/cpl_core/logging/logger_service.py +++ b/src/cpl_core/logging/logger_service.py @@ -169,7 +169,7 @@ class Logger(LoggerABC): # check if message can be shown in console if self._console.value >= LoggingLevelEnum.TRACE.value: - Console.set_foreground_color(ForegroundColorEnum.green) + Console.set_foreground_color(ForegroundColorEnum.grey) Console.write_line(output) Console.set_foreground_color(ForegroundColorEnum.default) @@ -182,7 +182,7 @@ class Logger(LoggerABC): # check if message can be shown in console if self._console.value >= LoggingLevelEnum.DEBUG.value: - Console.set_foreground_color(ForegroundColorEnum.green) + Console.set_foreground_color(ForegroundColorEnum.blue) Console.write_line(output) Console.set_foreground_color(ForegroundColorEnum.default) -- 2.45.1 From 1bbec27d1af3570fef29e48a62aa00882f75ad7c Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 30 Nov 2022 18:04:40 +0100 Subject: [PATCH 06/63] Fixed cpl g path problems & package names #93 --- cpl-workspace.json | 10 +++- src/cpl_cli/__init__.py | 2 +- src/cpl_cli/_templates/__init__.py | 2 +- src/cpl_cli/_templates/build/__init__.py | 2 +- src/cpl_cli/_templates/generate/__init__.py | 2 +- src/cpl_cli/_templates/new/__init__.py | 2 +- .../_templates/new/console/__init__.py | 2 +- .../_templates/new/console/source/__init__.py | 2 +- .../new/console/source/name/__init__.py | 2 +- .../_templates/new/library/__init__.py | 2 +- .../_templates/new/library/source/__init__.py | 2 +- .../new/library/source/name/__init__.py | 2 +- .../_templates/new/unittest/__init__.py | 2 +- .../new/unittest/source/__init__.py | 2 +- .../new/unittest/source/name/__init__.py | 2 +- src/cpl_cli/_templates/publish/__init__.py | 2 +- src/cpl_cli/command/__init__.py | 2 +- src/cpl_cli/command/generate_service.py | 55 +++++++++++-------- src/cpl_cli/configuration/__init__.py | 2 +- src/cpl_cli/live_server/__init__.py | 2 +- src/cpl_cli/migrations/__init__.py | 2 +- src/cpl_cli/migrations/base/__init__.py | 2 +- src/cpl_cli/migrations/service/__init__.py | 2 +- src/cpl_cli/publish/__init__.py | 2 +- src/cpl_cli/source_creator/__init__.py | 2 +- src/cpl_cli/validators/__init__.py | 2 +- src/cpl_core/__init__.py | 2 +- src/cpl_core/application/__init__.py | 2 +- src/cpl_core/configuration/__init__.py | 2 +- src/cpl_core/console/__init__.py | 2 +- src/cpl_core/database/__init__.py | 2 +- src/cpl_core/database/connection/__init__.py | 2 +- src/cpl_core/database/context/__init__.py | 2 +- src/cpl_core/dependency_injection/__init__.py | 2 +- src/cpl_core/environment/__init__.py | 2 +- src/cpl_core/logging/__init__.py | 2 +- src/cpl_core/mailing/__init__.py | 2 +- src/cpl_core/pipes/__init__.py | 2 +- src/cpl_core/time/__init__.py | 2 +- src/cpl_core/utils/__init__.py | 2 +- src/cpl_discord/__init__.py | 2 +- src/cpl_discord/application/__init__.py | 2 +- src/cpl_discord/command/__init__.py | 2 +- src/cpl_discord/configuration/__init__.py | 2 +- src/cpl_discord/container/__init__.py | 2 +- src/cpl_discord/events/__init__.py | 2 +- src/cpl_discord/helper/__init__.py | 2 +- src/cpl_discord/service/__init__.py | 2 +- src/cpl_query/__init__.py | 2 +- src/cpl_query/base/__init__.py | 2 +- src/cpl_query/enumerable/__init__.py | 2 +- src/cpl_query/extension/__init__.py | 2 +- src/cpl_query/iterable/__init__.py | 2 +- src/cpl_translation/__init__.py | 2 +- tools/set_pip_urls/__init__.py | 2 +- tools/set_version/__init__.py | 2 +- unittests/unittests_cli/build_test_case.py | 2 +- unittests/unittests_cli/cli_test_suite.py | 4 +- unittests/unittests_cli/generate_test_case.py | 54 +++++++++++++++++- unittests/unittests_cli/publish_test_case.py | 4 +- unittests/unittests_cli/update_test_case.py | 2 +- 61 files changed, 153 insertions(+), 86 deletions(-) diff --git a/cpl-workspace.json b/cpl-workspace.json index d07c8cae..081ff298 100644 --- a/cpl-workspace.json +++ b/cpl-workspace.json @@ -131,7 +131,15 @@ "di-cli": "pip install cpl-cli --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de", "di-discord": "pip install cpl-discord --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de", "di-query": "pip install cpl-query --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de", - "di-translation": "pip install cpl-translation --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de" + "di-translation": "pip install cpl-translation --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de", + + "prod-install": "cpl pi-core; cpl pi-cli; cpl pi-query; cpl pi-translation;", + "pi": "cpl prod-install", + "pi-core": "pip install cpl-core --pre --upgrade --extra-index-url https://pip.sh-edraft.de", + "pi-cli": "pip install cpl-cli --pre --upgrade --extra-index-url https://pip.sh-edraft.de", + "pi-discord": "pip install cpl-discord --pre --upgrade --extra-index-url https://pip.sh-edraft.de", + "pi-query": "pip install cpl-query --pre --upgrade --extra-index-url https://pip.sh-edraft.de", + "pi-translation": "pip install cpl-translation --pre --upgrade --extra-index-url https://pip.sh-edraft.de" } } } \ No newline at end of file diff --git a/src/cpl_cli/__init__.py b/src/cpl_cli/__init__.py index cacc83ee..227afbda 100644 --- a/src/cpl_cli/__init__.py +++ b/src/cpl_cli/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli' +__title__ = 'cpl-cli' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/__init__.py b/src/cpl_cli/_templates/__init__.py index c46a6fd5..1742ddf9 100644 --- a/src/cpl_cli/_templates/__init__.py +++ b/src/cpl_cli/_templates/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates' +__title__ = '_templates' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/build/__init__.py b/src/cpl_cli/_templates/build/__init__.py index 21ad75d9..17140905 100644 --- a/src/cpl_cli/_templates/build/__init__.py +++ b/src/cpl_cli/_templates/build/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.build' +__title__ = '_templates.build' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/generate/__init__.py b/src/cpl_cli/_templates/generate/__init__.py index 84b734d1..25d1efa5 100644 --- a/src/cpl_cli/_templates/generate/__init__.py +++ b/src/cpl_cli/_templates/generate/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.generate' +__title__ = '_templates.generate' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/__init__.py b/src/cpl_cli/_templates/new/__init__.py index db2618ea..b06174cb 100644 --- a/src/cpl_cli/_templates/new/__init__.py +++ b/src/cpl_cli/_templates/new/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new' +__title__ = '_templates.new' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/console/__init__.py b/src/cpl_cli/_templates/new/console/__init__.py index 6c1afdc0..1f8490fd 100644 --- a/src/cpl_cli/_templates/new/console/__init__.py +++ b/src/cpl_cli/_templates/new/console/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.console' +__title__ = '_templates.new.console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/console/source/__init__.py b/src/cpl_cli/_templates/new/console/source/__init__.py index 78bef3d1..21378df3 100644 --- a/src/cpl_cli/_templates/new/console/source/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.console.source' +__title__ = '_templates.new.console.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' 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 3fbf8c29..b892426a 100644 --- a/src/cpl_cli/_templates/new/console/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/name/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.console.source.name' +__title__ = '_templates.new.console.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/library/__init__.py b/src/cpl_cli/_templates/new/library/__init__.py index 24146cb0..d585cb0b 100644 --- a/src/cpl_cli/_templates/new/library/__init__.py +++ b/src/cpl_cli/_templates/new/library/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.library' +__title__ = '_templates.new.library' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/library/source/__init__.py b/src/cpl_cli/_templates/new/library/source/__init__.py index 6f010ead..7c8b2755 100644 --- a/src/cpl_cli/_templates/new/library/source/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.library.source' +__title__ = '_templates.new.library.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' 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 30965706..bf9076ae 100644 --- a/src/cpl_cli/_templates/new/library/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/name/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.library.source.name' +__title__ = '_templates.new.library.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/unittest/__init__.py b/src/cpl_cli/_templates/new/unittest/__init__.py index bfb4c039..58469b8b 100644 --- a/src/cpl_cli/_templates/new/unittest/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.unittest' +__title__ = '_templates.new.unittest' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/unittest/source/__init__.py b/src/cpl_cli/_templates/new/unittest/source/__init__.py index 324cfbf6..51f76f0e 100644 --- a/src/cpl_cli/_templates/new/unittest/source/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/source/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.unittest.source' +__title__ = '_templates.new.unittest.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/unittest/source/name/__init__.py b/src/cpl_cli/_templates/new/unittest/source/name/__init__.py index ed6c3518..7bf46294 100644 --- a/src/cpl_cli/_templates/new/unittest/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/source/name/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.new.unittest.source.name' +__title__ = '_templates.new.unittest.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/publish/__init__.py b/src/cpl_cli/_templates/publish/__init__.py index 0b0c9ee4..5258b787 100644 --- a/src/cpl_cli/_templates/publish/__init__.py +++ b/src/cpl_cli/_templates/publish/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli._templates.publish' +__title__ = '_templates.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/command/__init__.py b/src/cpl_cli/command/__init__.py index 350b8f8d..f54559ac 100644 --- a/src/cpl_cli/command/__init__.py +++ b/src/cpl_cli/command/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.command' +__title__ = 'command' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index 18b9505c..12236c83 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -14,6 +14,7 @@ from cpl_cli._templates.generate.thread_template import ThreadTemplate from cpl_cli._templates.generate.validator_template import ValidatorTemplate from cpl_cli._templates.template_file_abc import TemplateFileABC from cpl_cli.command_abc import CommandABC +from cpl_cli.configuration import WorkspaceSettings from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.console.console import Console from cpl_core.console.foreground_color_enum import ForegroundColorEnum @@ -22,13 +23,20 @@ from cpl_core.utils.string import String class GenerateService(CommandABC): - def __init__(self, configuration: ConfigurationABC): + def __init__( + self, + configuration: ConfigurationABC, + workspace: WorkspaceSettings, + ): """ Service for the CLI command generate :param configuration: """ CommandABC.__init__(self) + self._config = configuration + self._workspace = workspace + self._schematics = { "abc": { "Upper": "ABC", @@ -129,27 +137,7 @@ class GenerateService(CommandABC): template.write(value) template.close() - def _generate(self, schematic: str, name: str, template: TemplateFileABC): - """ - Generates files by given schematic, name and template - :param schematic: - :param name: - :param template: - :return: - """ - class_name = name - rel_path = '' - if '/' in name: - parts = name.split('/') - rel_path = '/'.join(parts[:-1]) - class_name = parts[len(parts) - 1] - - if 'src' not in rel_path and not os.path.exists(os.path.join(self._env.working_directory, rel_path)): - rel_path = f'src/{rel_path}' - - template = template(class_name, schematic, self._schematics[schematic]["Upper"], rel_path) - - file_path = os.path.join(self._env.working_directory, template.path, template.name) + def _create_init_files(self, file_path: str, template: TemplateFileABC, class_name: str, schematic: str, rel_path: str): if not os.path.isdir(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) directory = '' @@ -171,6 +159,29 @@ class GenerateService(CommandABC): spinner_foreground_color=ForegroundColorEnum.cyan ) + def _generate(self, schematic: str, name: str, template: TemplateFileABC): + """ + Generates files by given schematic, name and template + :param schematic: + :param name: + :param template: + :return: + """ + class_name = name + rel_path = '' + if '/' in name: + parts = name.split('/') + rel_path = '/'.join(parts[:-1]) + class_name = parts[len(parts) - 1] + + if self._workspace is not None and parts[0] in self._workspace.projects: + rel_path = os.path.dirname(self._workspace.projects[parts[0]]) + + template = template(class_name, schematic, self._schematics[schematic]["Upper"], rel_path) + + file_path = os.path.join(self._env.working_directory, template.path, template.name) + self._create_init_files(file_path, template, class_name, schematic, rel_path) + if os.path.isfile(file_path): Console.error(f'{String.first_to_upper(schematic)} already exists!\n') sys.exit() diff --git a/src/cpl_cli/configuration/__init__.py b/src/cpl_cli/configuration/__init__.py index d175531d..104a3809 100644 --- a/src/cpl_cli/configuration/__init__.py +++ b/src/cpl_cli/configuration/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.configuration' +__title__ = 'configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/live_server/__init__.py b/src/cpl_cli/live_server/__init__.py index 8f6d1272..d7af8e7c 100644 --- a/src/cpl_cli/live_server/__init__.py +++ b/src/cpl_cli/live_server/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.live_server' +__title__ = 'live_server' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/migrations/__init__.py b/src/cpl_cli/migrations/__init__.py index 63cd6250..d9aa0412 100644 --- a/src/cpl_cli/migrations/__init__.py +++ b/src/cpl_cli/migrations/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.migrations' +__title__ = 'migrations' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/migrations/base/__init__.py b/src/cpl_cli/migrations/base/__init__.py index c69bac92..19179a2c 100644 --- a/src/cpl_cli/migrations/base/__init__.py +++ b/src/cpl_cli/migrations/base/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.migrations.base' +__title__ = 'migrations.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/migrations/service/__init__.py b/src/cpl_cli/migrations/service/__init__.py index 92ffaa26..9cb4d5ff 100644 --- a/src/cpl_cli/migrations/service/__init__.py +++ b/src/cpl_cli/migrations/service/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.migrations.service' +__title__ = 'migrations.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/publish/__init__.py b/src/cpl_cli/publish/__init__.py index 4cc2e9aa..736a41fb 100644 --- a/src/cpl_cli/publish/__init__.py +++ b/src/cpl_cli/publish/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.publish' +__title__ = 'publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/source_creator/__init__.py b/src/cpl_cli/source_creator/__init__.py index af5e211e..fd32c0c0 100644 --- a/src/cpl_cli/source_creator/__init__.py +++ b/src/cpl_cli/source_creator/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.source_creator' +__title__ = 'source_creator' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/validators/__init__.py b/src/cpl_cli/validators/__init__.py index b3cf1671..13642c80 100644 --- a/src/cpl_cli/validators/__init__.py +++ b/src/cpl_cli/validators/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl_cli.validators' +__title__ = 'validators' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/__init__.py b/src/cpl_core/__init__.py index b9b5c269..831d4cdb 100644 --- a/src/cpl_core/__init__.py +++ b/src/cpl_core/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core' +__title__ = 'cpl-core' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/application/__init__.py b/src/cpl_core/application/__init__.py index 025c205a..6c4785bb 100644 --- a/src/cpl_core/application/__init__.py +++ b/src/cpl_core/application/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.application' +__title__ = 'application' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/configuration/__init__.py b/src/cpl_core/configuration/__init__.py index cef5c5dd..3b3742eb 100644 --- a/src/cpl_core/configuration/__init__.py +++ b/src/cpl_core/configuration/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.configuration' +__title__ = 'configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/console/__init__.py b/src/cpl_core/console/__init__.py index 18525b46..41363ef7 100644 --- a/src/cpl_core/console/__init__.py +++ b/src/cpl_core/console/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.console' +__title__ = 'console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/database/__init__.py b/src/cpl_core/database/__init__.py index c2e5b49a..2b59e2e1 100644 --- a/src/cpl_core/database/__init__.py +++ b/src/cpl_core/database/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.database' +__title__ = 'database' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/database/connection/__init__.py b/src/cpl_core/database/connection/__init__.py index c1851618..f27d336e 100644 --- a/src/cpl_core/database/connection/__init__.py +++ b/src/cpl_core/database/connection/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.database.connection' +__title__ = 'database.connection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/database/context/__init__.py b/src/cpl_core/database/context/__init__.py index 224ddb32..728be14a 100644 --- a/src/cpl_core/database/context/__init__.py +++ b/src/cpl_core/database/context/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.database.context' +__title__ = 'database.context' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/dependency_injection/__init__.py b/src/cpl_core/dependency_injection/__init__.py index b35fb03e..4f2322e3 100644 --- a/src/cpl_core/dependency_injection/__init__.py +++ b/src/cpl_core/dependency_injection/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.dependency_injection' +__title__ = 'dependency_injection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/environment/__init__.py b/src/cpl_core/environment/__init__.py index 587fd780..4ac8db8b 100644 --- a/src/cpl_core/environment/__init__.py +++ b/src/cpl_core/environment/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.environment' +__title__ = 'environment' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/logging/__init__.py b/src/cpl_core/logging/__init__.py index 6afacdbe..0d92764a 100644 --- a/src/cpl_core/logging/__init__.py +++ b/src/cpl_core/logging/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.logging' +__title__ = 'logging' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/mailing/__init__.py b/src/cpl_core/mailing/__init__.py index a63daf4a..077fb36d 100644 --- a/src/cpl_core/mailing/__init__.py +++ b/src/cpl_core/mailing/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.mailing' +__title__ = 'mailing' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/pipes/__init__.py b/src/cpl_core/pipes/__init__.py index 6afcae2a..7502f6c5 100644 --- a/src/cpl_core/pipes/__init__.py +++ b/src/cpl_core/pipes/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.pipes' +__title__ = 'pipes' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/time/__init__.py b/src/cpl_core/time/__init__.py index 45aacf77..55c05086 100644 --- a/src/cpl_core/time/__init__.py +++ b/src/cpl_core/time/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.time' +__title__ = 'time' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/utils/__init__.py b/src/cpl_core/utils/__init__.py index 64179a2b..893d5903 100644 --- a/src/cpl_core/utils/__init__.py +++ b/src/cpl_core/utils/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl_core.utils' +__title__ = 'utils' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/__init__.py b/src/cpl_discord/__init__.py index 9e01b9a4..9b4f67d8 100644 --- a/src/cpl_discord/__init__.py +++ b/src/cpl_discord/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord' +__title__ = 'cpl-discord' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/application/__init__.py b/src/cpl_discord/application/__init__.py index b513d032..f7cc5b3e 100644 --- a/src/cpl_discord/application/__init__.py +++ b/src/cpl_discord/application/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.application' +__title__ = 'application' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/command/__init__.py b/src/cpl_discord/command/__init__.py index 9ccd88da..15b8bd13 100644 --- a/src/cpl_discord/command/__init__.py +++ b/src/cpl_discord/command/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.command' +__title__ = 'command' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/configuration/__init__.py b/src/cpl_discord/configuration/__init__.py index 51110c41..c0b7cfcd 100644 --- a/src/cpl_discord/configuration/__init__.py +++ b/src/cpl_discord/configuration/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.configuration' +__title__ = 'configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/container/__init__.py b/src/cpl_discord/container/__init__.py index 009623c6..c9d25138 100644 --- a/src/cpl_discord/container/__init__.py +++ b/src/cpl_discord/container/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.container' +__title__ = 'container' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/events/__init__.py b/src/cpl_discord/events/__init__.py index d961d3ad..9c7f7f8c 100644 --- a/src/cpl_discord/events/__init__.py +++ b/src/cpl_discord/events/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.events' +__title__ = 'events' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/helper/__init__.py b/src/cpl_discord/helper/__init__.py index 5eb30f53..db6a6d9c 100644 --- a/src/cpl_discord/helper/__init__.py +++ b/src/cpl_discord/helper/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.helper' +__title__ = 'helper' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/service/__init__.py b/src/cpl_discord/service/__init__.py index 4223e0f8..5756e668 100644 --- a/src/cpl_discord/service/__init__.py +++ b/src/cpl_discord/service/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl_discord.service' +__title__ = 'service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 86fe8082..2e2559f6 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'cpl_query' +__title__ = 'cpl-query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/base/__init__.py b/src/cpl_query/base/__init__.py index ab831d0a..23c921da 100644 --- a/src/cpl_query/base/__init__.py +++ b/src/cpl_query/base/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'cpl_query.base' +__title__ = 'base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index 9bd1147e..14d10619 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'cpl_query.enumerable' +__title__ = 'enumerable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index c47d1d20..54cdcac2 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'cpl_query.extension' +__title__ = 'extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index d129a1c1..45cde067 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'cpl_query.iterable' +__title__ = 'iterable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_translation/__init__.py b/src/cpl_translation/__init__.py index d789a358..2c3eedb0 100644 --- a/src/cpl_translation/__init__.py +++ b/src/cpl_translation/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python Translation """ -__title__ = 'cpl_translation' +__title__ = 'cpl-translation' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' diff --git a/tools/set_pip_urls/__init__.py b/tools/set_pip_urls/__init__.py index 293c4a42..290901d9 100644 --- a/tools/set_pip_urls/__init__.py +++ b/tools/set_pip_urls/__init__.py @@ -11,7 +11,7 @@ CPL internal tool to set pip URL for CLI by environment """ -__title__ = 'set_pip_urls' +__title__ = 'set-pip-urls' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' diff --git a/tools/set_version/__init__.py b/tools/set_version/__init__.py index ef7b39f6..47ab1c7b 100644 --- a/tools/set_version/__init__.py +++ b/tools/set_version/__init__.py @@ -11,7 +11,7 @@ CPL internal tool to set version from branch name """ -__title__ = 'set_version' +__title__ = 'set-version' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' diff --git a/unittests/unittests_cli/build_test_case.py b/unittests/unittests_cli/build_test_case.py index e35d5cbd..6594bd08 100644 --- a/unittests/unittests_cli/build_test_case.py +++ b/unittests/unittests_cli/build_test_case.py @@ -78,7 +78,7 @@ class BuildTestCase(unittest.TestCase): def test_build(self): CLICommands.build() dist_path = './dist' - full_dist_path = f'{dist_path}/{self._source}/build/{String.convert_to_snake_case(self._source)}' + full_dist_path = f'{dist_path}/{self._source}/build/' self.assertTrue(os.path.exists(dist_path)) self.assertTrue(os.path.exists(full_dist_path)) self.assertFalse(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) diff --git a/unittests/unittests_cli/cli_test_suite.py b/unittests/unittests_cli/cli_test_suite.py index f26f3f3a..65cb6355 100644 --- a/unittests/unittests_cli/cli_test_suite.py +++ b/unittests/unittests_cli/cli_test_suite.py @@ -32,8 +32,8 @@ class CLITestSuite(unittest.TestSuite): active_tests = [ # nothing needed VersionTestCase, - GenerateTestCase, NewTestCase, + GenerateTestCase, # project needed BuildTestCase, PublishTestCase, @@ -75,4 +75,4 @@ class CLITestSuite(unittest.TestSuite): def run(self, *args): self._setup() self._result = super().run(*args) - self._cleanup() + # self._cleanup() diff --git a/unittests/unittests_cli/generate_test_case.py b/unittests/unittests_cli/generate_test_case.py index 53c03839..c53f28d5 100644 --- a/unittests/unittests_cli/generate_test_case.py +++ b/unittests/unittests_cli/generate_test_case.py @@ -1,41 +1,89 @@ import os.path import unittest +from cpl_core.utils import String from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands class GenerateTestCase(unittest.TestCase): + _project = 'test-console' + _t_path = 'test' - def _test_file(self, schematic: str, suffix: str): - CLICommands.generate(schematic, 'GeneratedFile') - file_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, f'generated_file{suffix}.py')) + @classmethod + def setUpClass(cls): + CLICommands.new('console', cls._project, '--ab', '--s', '--venv') + + def setUp(self): + os.chdir(PLAYGROUND_PATH) + + def _test_file(self, schematic: str, suffix: str, path=None): + file = 'GeneratedFile' + expected_path = f'generated_file{suffix}.py' + if path is not None: + file = f'{path}/{file}' + expected_path = f'{path}/{expected_path}' + CLICommands.generate(schematic, file) + file_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, expected_path)) file_exists = os.path.exists(file_path) self.assertTrue(file_exists) + def _test_file_with_project(self, schematic: str, suffix: str, path=None, enter=True): + file = f'GeneratedFile' + excepted_path = f'generated_file{suffix}.py' + if path is not None: + excepted_path = f'{self._project}/src/{String.convert_to_snake_case(self._project)}/{path}/generated_file_in_project{suffix}.py' + if enter: + os.chdir(path) + excepted_path = f'{path}/src/{String.convert_to_snake_case(self._project)}/generated_file_in_project{suffix}.py' + + file = f'{path}/GeneratedFileInProject' + + CLICommands.generate(schematic, file) + file_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, excepted_path)) + self.assertTrue(os.path.exists(file_path)) + def test_abc(self): self._test_file('abc', '_abc') + self._test_file('abc', '_abc', path=self._t_path) + self._test_file('abc', '_abc', path=f'{self._t_path}/{self._t_path}') + self._test_file_with_project('abc', '_abc', path=self._project) + os.chdir(f'src/{String.convert_to_snake_case(self._project)}') + self._test_file_with_project('abc', '_abc', path='test', enter=False) def test_class(self): self._test_file('class', '') + self._test_file('class', '', path=self._t_path) + self._test_file_with_project('class', '', path=self._project) def test_enum(self): self._test_file('enum', '_enum') + self._test_file('enum', '_enum', path=self._t_path) + self._test_file_with_project('enum', '_enum', path=self._project) + os.chdir(f'src/{String.convert_to_snake_case(self._project)}') + self._test_file_with_project('enum', '_enum', path='test', enter=False) def test_pipe(self): self._test_file('pipe', '_pipe') + self._test_file('pipe', '_pipe', path=self._t_path) + self._test_file_with_project('pipe', '_pipe', path=self._project) def test_service(self): self._test_file('service', '_service') + self._test_file_with_project('service', '_service', path=self._project) def test_settings(self): self._test_file('settings', '_settings') + self._test_file_with_project('settings', '_settings', path=self._project) def test_test_case(self): self._test_file('test_case', '_test_case') + self._test_file_with_project('test_case', '_test_case', path=self._project) def test_thread(self): self._test_file('thread', '_thread') + self._test_file_with_project('thread', '_thread', path=self._project) def test_validator(self): self._test_file('validator', '_validator') + self._test_file_with_project('validator', '_validator', path=self._project) diff --git a/unittests/unittests_cli/publish_test_case.py b/unittests/unittests_cli/publish_test_case.py index 7c828ced..b24531c5 100644 --- a/unittests/unittests_cli/publish_test_case.py +++ b/unittests/unittests_cli/publish_test_case.py @@ -79,7 +79,7 @@ class PublishTestCase(unittest.TestCase): CLICommands.publish() dist_path = './dist' setup_path = f'{dist_path}/{self._source}/publish/setup' - full_dist_path = f'{dist_path}/{self._source}/publish/build/lib/{String.convert_to_snake_case(self._source)}' + full_dist_path = f'{dist_path}/{self._source}/publish/' self.assertTrue(os.path.exists(dist_path)) self.assertTrue(os.path.exists(setup_path)) self.assertTrue(os.path.exists(os.path.join(setup_path, f'{self._source}-0.0.0.tar.gz'))) @@ -89,4 +89,4 @@ class PublishTestCase(unittest.TestCase): with open(f'{full_dist_path}/{self._source}.json', 'w') as file: file.write(json.dumps(self._get_project_settings(), indent=2)) file.close() - self.assertTrue(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) + # self.assertTrue(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) diff --git a/unittests/unittests_cli/update_test_case.py b/unittests/unittests_cli/update_test_case.py index de21bf6b..3b50b38c 100644 --- a/unittests/unittests_cli/update_test_case.py +++ b/unittests/unittests_cli/update_test_case.py @@ -22,7 +22,7 @@ class UpdateTestCase(unittest.TestCase): self._old_package = f'{self._old_package_name}=={self._old_version}' # todo: better way to do shit required - self._new_version = '2.0.1' + self._new_version = '2.1.0' self._new_package_name = 'discord.py' self._new_package = f'{self._new_package_name}=={self._new_version}' -- 2.45.1 From 186b336bf34cf50814c5f1500a337830ab1af218 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 30 Nov 2022 19:05:11 +0100 Subject: [PATCH 07/63] Repaired build & publish #93 --- src/cpl_cli/__init__.py | 2 +- src/cpl_cli/_templates/__init__.py | 2 +- src/cpl_cli/_templates/build/__init__.py | 2 +- src/cpl_cli/_templates/generate/__init__.py | 2 +- src/cpl_cli/_templates/new/__init__.py | 2 +- src/cpl_cli/_templates/new/console/__init__.py | 2 +- src/cpl_cli/_templates/new/console/source/__init__.py | 2 +- src/cpl_cli/_templates/new/console/source/name/__init__.py | 2 +- src/cpl_cli/_templates/new/library/__init__.py | 2 +- src/cpl_cli/_templates/new/library/source/__init__.py | 2 +- src/cpl_cli/_templates/new/library/source/name/__init__.py | 2 +- src/cpl_cli/_templates/new/unittest/__init__.py | 2 +- src/cpl_cli/_templates/new/unittest/source/__init__.py | 2 +- src/cpl_cli/_templates/new/unittest/source/name/__init__.py | 2 +- src/cpl_cli/_templates/publish/__init__.py | 2 +- src/cpl_cli/command/__init__.py | 2 +- src/cpl_cli/configuration/__init__.py | 2 +- src/cpl_cli/live_server/__init__.py | 2 +- src/cpl_cli/migrations/__init__.py | 2 +- src/cpl_cli/migrations/base/__init__.py | 2 +- src/cpl_cli/migrations/service/__init__.py | 2 +- src/cpl_cli/publish/__init__.py | 2 +- src/cpl_cli/publish/publisher_service.py | 4 ++-- src/cpl_cli/source_creator/__init__.py | 2 +- src/cpl_cli/validators/__init__.py | 2 +- unittests/unittests_cli/build_test_case.py | 2 +- unittests/unittests_cli/publish_test_case.py | 4 ++-- 27 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/cpl_cli/__init__.py b/src/cpl_cli/__init__.py index 227afbda..cacc83ee 100644 --- a/src/cpl_cli/__init__.py +++ b/src/cpl_cli/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'cpl-cli' +__title__ = 'cpl_cli' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/__init__.py b/src/cpl_cli/_templates/__init__.py index 1742ddf9..c46a6fd5 100644 --- a/src/cpl_cli/_templates/__init__.py +++ b/src/cpl_cli/_templates/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates' +__title__ = 'cpl_cli._templates' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/build/__init__.py b/src/cpl_cli/_templates/build/__init__.py index 17140905..21ad75d9 100644 --- a/src/cpl_cli/_templates/build/__init__.py +++ b/src/cpl_cli/_templates/build/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.build' +__title__ = 'cpl_cli._templates.build' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/generate/__init__.py b/src/cpl_cli/_templates/generate/__init__.py index 25d1efa5..84b734d1 100644 --- a/src/cpl_cli/_templates/generate/__init__.py +++ b/src/cpl_cli/_templates/generate/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.generate' +__title__ = 'cpl_cli._templates.generate' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/__init__.py b/src/cpl_cli/_templates/new/__init__.py index b06174cb..db2618ea 100644 --- a/src/cpl_cli/_templates/new/__init__.py +++ b/src/cpl_cli/_templates/new/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new' +__title__ = 'cpl_cli._templates.new' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/console/__init__.py b/src/cpl_cli/_templates/new/console/__init__.py index 1f8490fd..6c1afdc0 100644 --- a/src/cpl_cli/_templates/new/console/__init__.py +++ b/src/cpl_cli/_templates/new/console/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.console' +__title__ = 'cpl_cli._templates.new.console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/console/source/__init__.py b/src/cpl_cli/_templates/new/console/source/__init__.py index 21378df3..78bef3d1 100644 --- a/src/cpl_cli/_templates/new/console/source/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.console.source' +__title__ = 'cpl_cli._templates.new.console.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' 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 b892426a..3fbf8c29 100644 --- a/src/cpl_cli/_templates/new/console/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/name/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.console.source.name' +__title__ = 'cpl_cli._templates.new.console.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/library/__init__.py b/src/cpl_cli/_templates/new/library/__init__.py index d585cb0b..24146cb0 100644 --- a/src/cpl_cli/_templates/new/library/__init__.py +++ b/src/cpl_cli/_templates/new/library/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.library' +__title__ = 'cpl_cli._templates.new.library' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/library/source/__init__.py b/src/cpl_cli/_templates/new/library/source/__init__.py index 7c8b2755..6f010ead 100644 --- a/src/cpl_cli/_templates/new/library/source/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.library.source' +__title__ = 'cpl_cli._templates.new.library.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' 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 bf9076ae..30965706 100644 --- a/src/cpl_cli/_templates/new/library/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/name/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.library.source.name' +__title__ = 'cpl_cli._templates.new.library.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/unittest/__init__.py b/src/cpl_cli/_templates/new/unittest/__init__.py index 58469b8b..bfb4c039 100644 --- a/src/cpl_cli/_templates/new/unittest/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.unittest' +__title__ = 'cpl_cli._templates.new.unittest' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/unittest/source/__init__.py b/src/cpl_cli/_templates/new/unittest/source/__init__.py index 51f76f0e..324cfbf6 100644 --- a/src/cpl_cli/_templates/new/unittest/source/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/source/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.unittest.source' +__title__ = 'cpl_cli._templates.new.unittest.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/new/unittest/source/name/__init__.py b/src/cpl_cli/_templates/new/unittest/source/name/__init__.py index 7bf46294..ed6c3518 100644 --- a/src/cpl_cli/_templates/new/unittest/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/source/name/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.new.unittest.source.name' +__title__ = 'cpl_cli._templates.new.unittest.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/_templates/publish/__init__.py b/src/cpl_cli/_templates/publish/__init__.py index 5258b787..0b0c9ee4 100644 --- a/src/cpl_cli/_templates/publish/__init__.py +++ b/src/cpl_cli/_templates/publish/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = '_templates.publish' +__title__ = 'cpl_cli._templates.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/command/__init__.py b/src/cpl_cli/command/__init__.py index f54559ac..350b8f8d 100644 --- a/src/cpl_cli/command/__init__.py +++ b/src/cpl_cli/command/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'command' +__title__ = 'cpl_cli.command' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/configuration/__init__.py b/src/cpl_cli/configuration/__init__.py index 104a3809..d175531d 100644 --- a/src/cpl_cli/configuration/__init__.py +++ b/src/cpl_cli/configuration/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'configuration' +__title__ = 'cpl_cli.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/live_server/__init__.py b/src/cpl_cli/live_server/__init__.py index d7af8e7c..8f6d1272 100644 --- a/src/cpl_cli/live_server/__init__.py +++ b/src/cpl_cli/live_server/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'live_server' +__title__ = 'cpl_cli.live_server' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/migrations/__init__.py b/src/cpl_cli/migrations/__init__.py index d9aa0412..63cd6250 100644 --- a/src/cpl_cli/migrations/__init__.py +++ b/src/cpl_cli/migrations/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'migrations' +__title__ = 'cpl_cli.migrations' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/migrations/base/__init__.py b/src/cpl_cli/migrations/base/__init__.py index 19179a2c..c69bac92 100644 --- a/src/cpl_cli/migrations/base/__init__.py +++ b/src/cpl_cli/migrations/base/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'migrations.base' +__title__ = 'cpl_cli.migrations.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/migrations/service/__init__.py b/src/cpl_cli/migrations/service/__init__.py index 9cb4d5ff..92ffaa26 100644 --- a/src/cpl_cli/migrations/service/__init__.py +++ b/src/cpl_cli/migrations/service/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'migrations.service' +__title__ = 'cpl_cli.migrations.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/publish/__init__.py b/src/cpl_cli/publish/__init__.py index 736a41fb..4cc2e9aa 100644 --- a/src/cpl_cli/publish/__init__.py +++ b/src/cpl_cli/publish/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'publish' +__title__ = 'cpl_cli.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/publish/publisher_service.py b/src/cpl_cli/publish/publisher_service.py index e7d59ad9..b1639023 100644 --- a/src/cpl_cli/publish/publisher_service.py +++ b/src/cpl_cli/publish/publisher_service.py @@ -433,7 +433,7 @@ class PublisherService(PublisherABC): 3. Copies all included source files to dist_path/build :return: """ - self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) # probably causing some errors (#125) + self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) # probably causing some errors (#125) self.exclude(f'*/{self._project_settings.name}.json') self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, 'build')) @@ -456,7 +456,7 @@ class PublisherService(PublisherABC): 4. Remove all included source from dist_path/publish :return: """ - self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) # probably causing some errors (#125) + self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) # probably causing some errors (#125) self.exclude(f'*/{self._project_settings.name}.json') self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, 'publish')) diff --git a/src/cpl_cli/source_creator/__init__.py b/src/cpl_cli/source_creator/__init__.py index fd32c0c0..af5e211e 100644 --- a/src/cpl_cli/source_creator/__init__.py +++ b/src/cpl_cli/source_creator/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'source_creator' +__title__ = 'cpl_cli.source_creator' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_cli/validators/__init__.py b/src/cpl_cli/validators/__init__.py index 13642c80..b3cf1671 100644 --- a/src/cpl_cli/validators/__init__.py +++ b/src/cpl_cli/validators/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Command Line Interface """ -__title__ = 'validators' +__title__ = 'cpl_cli.validators' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/unittests/unittests_cli/build_test_case.py b/unittests/unittests_cli/build_test_case.py index 6594bd08..e35d5cbd 100644 --- a/unittests/unittests_cli/build_test_case.py +++ b/unittests/unittests_cli/build_test_case.py @@ -78,7 +78,7 @@ class BuildTestCase(unittest.TestCase): def test_build(self): CLICommands.build() dist_path = './dist' - full_dist_path = f'{dist_path}/{self._source}/build/' + full_dist_path = f'{dist_path}/{self._source}/build/{String.convert_to_snake_case(self._source)}' self.assertTrue(os.path.exists(dist_path)) self.assertTrue(os.path.exists(full_dist_path)) self.assertFalse(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) diff --git a/unittests/unittests_cli/publish_test_case.py b/unittests/unittests_cli/publish_test_case.py index b24531c5..7c828ced 100644 --- a/unittests/unittests_cli/publish_test_case.py +++ b/unittests/unittests_cli/publish_test_case.py @@ -79,7 +79,7 @@ class PublishTestCase(unittest.TestCase): CLICommands.publish() dist_path = './dist' setup_path = f'{dist_path}/{self._source}/publish/setup' - full_dist_path = f'{dist_path}/{self._source}/publish/' + full_dist_path = f'{dist_path}/{self._source}/publish/build/lib/{String.convert_to_snake_case(self._source)}' self.assertTrue(os.path.exists(dist_path)) self.assertTrue(os.path.exists(setup_path)) self.assertTrue(os.path.exists(os.path.join(setup_path, f'{self._source}-0.0.0.tar.gz'))) @@ -89,4 +89,4 @@ class PublishTestCase(unittest.TestCase): with open(f'{full_dist_path}/{self._source}.json', 'w') as file: file.write(json.dumps(self._get_project_settings(), indent=2)) file.close() - # self.assertTrue(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) + self.assertTrue(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) -- 2.45.1 From 6aef49de4037a31bfc2166f8baa94c28543c611c Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 1 Dec 2022 12:17:26 +0100 Subject: [PATCH 08/63] Repaired build & publish #93 --- src/cpl_core/__init__.py | 2 +- src/cpl_core/application/__init__.py | 2 +- src/cpl_core/configuration/__init__.py | 2 +- src/cpl_core/console/__init__.py | 2 +- src/cpl_core/database/__init__.py | 2 +- src/cpl_core/database/connection/__init__.py | 2 +- src/cpl_core/database/context/__init__.py | 2 +- src/cpl_core/dependency_injection/__init__.py | 2 +- src/cpl_core/environment/__init__.py | 2 +- src/cpl_core/logging/__init__.py | 2 +- src/cpl_core/mailing/__init__.py | 2 +- src/cpl_core/pipes/__init__.py | 2 +- src/cpl_core/time/__init__.py | 2 +- src/cpl_core/utils/__init__.py | 2 +- src/cpl_discord/__init__.py | 2 +- src/cpl_discord/application/__init__.py | 2 +- src/cpl_discord/command/__init__.py | 2 +- src/cpl_discord/configuration/__init__.py | 2 +- src/cpl_discord/container/__init__.py | 2 +- src/cpl_discord/events/__init__.py | 2 +- src/cpl_discord/helper/__init__.py | 2 +- src/cpl_discord/service/__init__.py | 2 +- src/cpl_query/__init__.py | 2 +- src/cpl_query/base/__init__.py | 2 +- src/cpl_query/enumerable/__init__.py | 2 +- src/cpl_query/extension/__init__.py | 2 +- src/cpl_query/iterable/__init__.py | 2 +- src/cpl_translation/__init__.py | 2 +- tools/set_pip_urls/__init__.py | 2 +- tools/set_version/__init__.py | 2 +- 30 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/cpl_core/__init__.py b/src/cpl_core/__init__.py index 831d4cdb..b9b5c269 100644 --- a/src/cpl_core/__init__.py +++ b/src/cpl_core/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'cpl-core' +__title__ = 'cpl_core' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/application/__init__.py b/src/cpl_core/application/__init__.py index 6c4785bb..025c205a 100644 --- a/src/cpl_core/application/__init__.py +++ b/src/cpl_core/application/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'application' +__title__ = 'cpl_core.application' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/configuration/__init__.py b/src/cpl_core/configuration/__init__.py index 3b3742eb..cef5c5dd 100644 --- a/src/cpl_core/configuration/__init__.py +++ b/src/cpl_core/configuration/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'configuration' +__title__ = 'cpl_core.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/console/__init__.py b/src/cpl_core/console/__init__.py index 41363ef7..18525b46 100644 --- a/src/cpl_core/console/__init__.py +++ b/src/cpl_core/console/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'console' +__title__ = 'cpl_core.console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/database/__init__.py b/src/cpl_core/database/__init__.py index 2b59e2e1..c2e5b49a 100644 --- a/src/cpl_core/database/__init__.py +++ b/src/cpl_core/database/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'database' +__title__ = 'cpl_core.database' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/database/connection/__init__.py b/src/cpl_core/database/connection/__init__.py index f27d336e..c1851618 100644 --- a/src/cpl_core/database/connection/__init__.py +++ b/src/cpl_core/database/connection/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'database.connection' +__title__ = 'cpl_core.database.connection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/database/context/__init__.py b/src/cpl_core/database/context/__init__.py index 728be14a..224ddb32 100644 --- a/src/cpl_core/database/context/__init__.py +++ b/src/cpl_core/database/context/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'database.context' +__title__ = 'cpl_core.database.context' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/dependency_injection/__init__.py b/src/cpl_core/dependency_injection/__init__.py index 4f2322e3..b35fb03e 100644 --- a/src/cpl_core/dependency_injection/__init__.py +++ b/src/cpl_core/dependency_injection/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'dependency_injection' +__title__ = 'cpl_core.dependency_injection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/environment/__init__.py b/src/cpl_core/environment/__init__.py index 4ac8db8b..587fd780 100644 --- a/src/cpl_core/environment/__init__.py +++ b/src/cpl_core/environment/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'environment' +__title__ = 'cpl_core.environment' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/logging/__init__.py b/src/cpl_core/logging/__init__.py index 0d92764a..6afacdbe 100644 --- a/src/cpl_core/logging/__init__.py +++ b/src/cpl_core/logging/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'logging' +__title__ = 'cpl_core.logging' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/mailing/__init__.py b/src/cpl_core/mailing/__init__.py index 077fb36d..a63daf4a 100644 --- a/src/cpl_core/mailing/__init__.py +++ b/src/cpl_core/mailing/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'mailing' +__title__ = 'cpl_core.mailing' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/pipes/__init__.py b/src/cpl_core/pipes/__init__.py index 7502f6c5..6afcae2a 100644 --- a/src/cpl_core/pipes/__init__.py +++ b/src/cpl_core/pipes/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'pipes' +__title__ = 'cpl_core.pipes' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/time/__init__.py b/src/cpl_core/time/__init__.py index 55c05086..45aacf77 100644 --- a/src/cpl_core/time/__init__.py +++ b/src/cpl_core/time/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'time' +__title__ = 'cpl_core.time' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_core/utils/__init__.py b/src/cpl_core/utils/__init__.py index 893d5903..64179a2b 100644 --- a/src/cpl_core/utils/__init__.py +++ b/src/cpl_core/utils/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'utils' +__title__ = 'cpl_core.utils' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/__init__.py b/src/cpl_discord/__init__.py index 9b4f67d8..9e01b9a4 100644 --- a/src/cpl_discord/__init__.py +++ b/src/cpl_discord/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'cpl-discord' +__title__ = 'cpl_discord' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/application/__init__.py b/src/cpl_discord/application/__init__.py index f7cc5b3e..b513d032 100644 --- a/src/cpl_discord/application/__init__.py +++ b/src/cpl_discord/application/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'application' +__title__ = 'cpl_discord.application' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/command/__init__.py b/src/cpl_discord/command/__init__.py index 15b8bd13..9ccd88da 100644 --- a/src/cpl_discord/command/__init__.py +++ b/src/cpl_discord/command/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'command' +__title__ = 'cpl_discord.command' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/configuration/__init__.py b/src/cpl_discord/configuration/__init__.py index c0b7cfcd..51110c41 100644 --- a/src/cpl_discord/configuration/__init__.py +++ b/src/cpl_discord/configuration/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'configuration' +__title__ = 'cpl_discord.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/container/__init__.py b/src/cpl_discord/container/__init__.py index c9d25138..009623c6 100644 --- a/src/cpl_discord/container/__init__.py +++ b/src/cpl_discord/container/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'container' +__title__ = 'cpl_discord.container' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/events/__init__.py b/src/cpl_discord/events/__init__.py index 9c7f7f8c..d961d3ad 100644 --- a/src/cpl_discord/events/__init__.py +++ b/src/cpl_discord/events/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'events' +__title__ = 'cpl_discord.events' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/helper/__init__.py b/src/cpl_discord/helper/__init__.py index db6a6d9c..5eb30f53 100644 --- a/src/cpl_discord/helper/__init__.py +++ b/src/cpl_discord/helper/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'helper' +__title__ = 'cpl_discord.helper' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_discord/service/__init__.py b/src/cpl_discord/service/__init__.py index 5756e668..4223e0f8 100644 --- a/src/cpl_discord/service/__init__.py +++ b/src/cpl_discord/service/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library link between discord.py and CPL """ -__title__ = 'service' +__title__ = 'cpl_discord.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 2e2559f6..86fe8082 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'cpl-query' +__title__ = 'cpl_query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/base/__init__.py b/src/cpl_query/base/__init__.py index 23c921da..ab831d0a 100644 --- a/src/cpl_query/base/__init__.py +++ b/src/cpl_query/base/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'base' +__title__ = 'cpl_query.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index 14d10619..9bd1147e 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'enumerable' +__title__ = 'cpl_query.enumerable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index 54cdcac2..c47d1d20 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'extension' +__title__ = 'cpl_query.extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index 45cde067..d129a1c1 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python integrated Queries """ -__title__ = 'iterable' +__title__ = 'cpl_query.iterable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' diff --git a/src/cpl_translation/__init__.py b/src/cpl_translation/__init__.py index 2c3eedb0..d789a358 100644 --- a/src/cpl_translation/__init__.py +++ b/src/cpl_translation/__init__.py @@ -11,7 +11,7 @@ sh-edraft Common Python library Python Translation """ -__title__ = 'cpl-translation' +__title__ = 'cpl_translation' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' diff --git a/tools/set_pip_urls/__init__.py b/tools/set_pip_urls/__init__.py index 290901d9..293c4a42 100644 --- a/tools/set_pip_urls/__init__.py +++ b/tools/set_pip_urls/__init__.py @@ -11,7 +11,7 @@ CPL internal tool to set pip URL for CLI by environment """ -__title__ = 'set-pip-urls' +__title__ = 'set_pip_urls' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' diff --git a/tools/set_version/__init__.py b/tools/set_version/__init__.py index 47ab1c7b..ef7b39f6 100644 --- a/tools/set_version/__init__.py +++ b/tools/set_version/__init__.py @@ -11,7 +11,7 @@ CPL internal tool to set version from branch name """ -__title__ = 'set-version' +__title__ = 'set_version' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' -- 2.45.1 From 9e84c8359bfde853c3b536feaf4a6bb790558851 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 1 Dec 2022 12:25:36 +0100 Subject: [PATCH 09/63] Removed empty PythonPath #93 --- src/cpl_discord/cpl-discord.json | 4 +--- tests/custom/async/src/async/async.json | 4 +--- tests/custom/database/cpl.json | 4 +--- tests/custom/di/src/di/di.json | 4 +--- tests/custom/discord/src/discord_bot/discord-bot.json | 4 +--- tests/custom/discord/src/modules/hello_world/hello-world.json | 4 +--- tests/custom/translation/src/translation/translation.json | 4 +--- tests/generated/simple-app/cpl.json | 4 +--- tests/generated/simple-app/src/simple_app/simple-app.json | 4 +--- tests/generated/simple-console/cpl.json | 4 +--- .../simple-console/src/simple_console/simple-console.json | 4 +--- tests/generated/simple-di/cpl.json | 4 +--- tests/generated/simple-di/src/simple_di/simple-di.json | 4 +--- .../src/simple_startup_app/simple-startup-app.json | 4 +--- tests/generated/startup-app/cpl.json | 4 +--- unittests/unittests/unittests.json | 4 +--- unittests/unittests_cli/unittests_cli.json | 4 +--- unittests/unittests_core/unittests_core.json | 4 +--- unittests/unittests_query/unittests_query.json | 4 +--- unittests/unittests_shared/unittests_shared.json | 4 +--- unittests/unittests_translation/unittests_translation.json | 4 +--- 21 files changed, 21 insertions(+), 63 deletions(-) diff --git a/src/cpl_discord/cpl-discord.json b/src/cpl_discord/cpl-discord.json index cdaed19b..dabf8aab 100644 --- a/src/cpl_discord/cpl-discord.json +++ b/src/cpl_discord/cpl-discord.json @@ -24,9 +24,7 @@ "cpl-cli>=2022.10.0" ], "PythonVersion": ">=3.10.4", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/custom/async/src/async/async.json b/tests/custom/async/src/async/async.json index 7e632a65..ab459429 100644 --- a/tests/custom/async/src/async/async.json +++ b/tests/custom/async/src/async/async.json @@ -19,9 +19,7 @@ "sh_cpl>=2021.10.0.post1" ], "PythonVersion": ">=3.9.2", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/custom/database/cpl.json b/tests/custom/database/cpl.json index e964c144..ee84d745 100644 --- a/tests/custom/database/cpl.json +++ b/tests/custom/database/cpl.json @@ -19,9 +19,7 @@ "sh_cpl==2021.4.2.dev1" ], "PythonVersion": ">=3.9.2", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/custom/di/src/di/di.json b/tests/custom/di/src/di/di.json index cd4e3ff2..67ca9bd5 100644 --- a/tests/custom/di/src/di/di.json +++ b/tests/custom/di/src/di/di.json @@ -19,9 +19,7 @@ "sh_cpl>=2021.10.0.post1" ], "PythonVersion": ">=3.9.2", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/custom/discord/src/discord_bot/discord-bot.json b/tests/custom/discord/src/discord_bot/discord-bot.json index d91dbfcc..c543ea19 100644 --- a/tests/custom/discord/src/discord_bot/discord-bot.json +++ b/tests/custom/discord/src/discord_bot/discord-bot.json @@ -22,9 +22,7 @@ "cpl-cli>=2022.7.0" ], "PythonVersion": ">=3.10.4", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/custom/discord/src/modules/hello_world/hello-world.json b/tests/custom/discord/src/modules/hello_world/hello-world.json index 869a7901..f5dd8fcc 100644 --- a/tests/custom/discord/src/modules/hello_world/hello-world.json +++ b/tests/custom/discord/src/modules/hello_world/hello-world.json @@ -22,9 +22,7 @@ "cpl-cli>=2022.7.0.post1" ], "PythonVersion": ">=3.10.4", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/custom/translation/src/translation/translation.json b/tests/custom/translation/src/translation/translation.json index f857761d..dbbe2dcd 100644 --- a/tests/custom/translation/src/translation/translation.json +++ b/tests/custom/translation/src/translation/translation.json @@ -22,9 +22,7 @@ "cpl-cli>=2022.6.0" ], "PythonVersion": ">=3.10.4", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/generated/simple-app/cpl.json b/tests/generated/simple-app/cpl.json index f223da45..1af0f6e6 100644 --- a/tests/generated/simple-app/cpl.json +++ b/tests/generated/simple-app/cpl.json @@ -19,9 +19,7 @@ "sh_cpl==2021.4.2" ], "PythonVersion": ">=3.9.2", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/generated/simple-app/src/simple_app/simple-app.json b/tests/generated/simple-app/src/simple_app/simple-app.json index 5375d662..3aa9d743 100644 --- a/tests/generated/simple-app/src/simple_app/simple-app.json +++ b/tests/generated/simple-app/src/simple_app/simple-app.json @@ -19,9 +19,7 @@ "sh_cpl==2021.4.1rc2" ], "PythonVersion": ">=3.9.2", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/generated/simple-console/cpl.json b/tests/generated/simple-console/cpl.json index 63fe1a4d..5ddc2f0f 100644 --- a/tests/generated/simple-console/cpl.json +++ b/tests/generated/simple-console/cpl.json @@ -19,9 +19,7 @@ "sh_cpl==2021.4.2" ], "PythonVersion": ">=3.9.2", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/generated/simple-console/src/simple_console/simple-console.json b/tests/generated/simple-console/src/simple_console/simple-console.json index e05e9201..24d5c821 100644 --- a/tests/generated/simple-console/src/simple_console/simple-console.json +++ b/tests/generated/simple-console/src/simple_console/simple-console.json @@ -19,9 +19,7 @@ "sh_cpl==2021.4.1rc2" ], "PythonVersion": ">=3.9.2", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/generated/simple-di/cpl.json b/tests/generated/simple-di/cpl.json index 8804958a..a048da7f 100644 --- a/tests/generated/simple-di/cpl.json +++ b/tests/generated/simple-di/cpl.json @@ -19,9 +19,7 @@ "sh_cpl==2021.4.2.dev1" ], "PythonVersion": ">=3.9.2", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/generated/simple-di/src/simple_di/simple-di.json b/tests/generated/simple-di/src/simple_di/simple-di.json index b5591ebf..54751fcc 100644 --- a/tests/generated/simple-di/src/simple_di/simple-di.json +++ b/tests/generated/simple-di/src/simple_di/simple-di.json @@ -19,9 +19,7 @@ "sh_cpl==2021.4.1rc2" ], "PythonVersion": ">=3.9.2", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/generated/simple-startup-app/src/simple_startup_app/simple-startup-app.json b/tests/generated/simple-startup-app/src/simple_startup_app/simple-startup-app.json index 6c036f08..80e4786f 100644 --- a/tests/generated/simple-startup-app/src/simple_startup_app/simple-startup-app.json +++ b/tests/generated/simple-startup-app/src/simple_startup_app/simple-startup-app.json @@ -19,9 +19,7 @@ "sh_cpl==2021.4.1rc2" ], "PythonVersion": ">=3.9.2", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/tests/generated/startup-app/cpl.json b/tests/generated/startup-app/cpl.json index 086c70ae..39de3a85 100644 --- a/tests/generated/startup-app/cpl.json +++ b/tests/generated/startup-app/cpl.json @@ -19,9 +19,7 @@ "sh_cpl==2021.4.2" ], "PythonVersion": ">=3.9.2", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/unittests/unittests/unittests.json b/unittests/unittests/unittests.json index a3f1e8b3..bae65fc0 100644 --- a/unittests/unittests/unittests.json +++ b/unittests/unittests/unittests.json @@ -19,9 +19,7 @@ "cpl-core>=2022.10.0" ], "PythonVersion": ">=3.10.4", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [], "DevDependencies": [] }, diff --git a/unittests/unittests_cli/unittests_cli.json b/unittests/unittests_cli/unittests_cli.json index aa975a3f..7b81087c 100644 --- a/unittests/unittests_cli/unittests_cli.json +++ b/unittests/unittests_cli/unittests_cli.json @@ -20,9 +20,7 @@ "cpl-cli>=2022.10.0" ], "PythonVersion": ">=3.10.4", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [], "DevDependencies": [] }, diff --git a/unittests/unittests_core/unittests_core.json b/unittests/unittests_core/unittests_core.json index 1e875549..143b7da1 100644 --- a/unittests/unittests_core/unittests_core.json +++ b/unittests/unittests_core/unittests_core.json @@ -19,9 +19,7 @@ "cpl-core>=2022.10.0" ], "PythonVersion": ">=3.10.4", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [], "DevDependencies": [] }, diff --git a/unittests/unittests_query/unittests_query.json b/unittests/unittests_query/unittests_query.json index d125ef96..bf5c4041 100644 --- a/unittests/unittests_query/unittests_query.json +++ b/unittests/unittests_query/unittests_query.json @@ -20,9 +20,7 @@ "cpl-query>=2022.10.0" ], "PythonVersion": ">=3.10.4", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [], "DevDependencies": [] }, diff --git a/unittests/unittests_shared/unittests_shared.json b/unittests/unittests_shared/unittests_shared.json index 795691a5..881cf7b1 100644 --- a/unittests/unittests_shared/unittests_shared.json +++ b/unittests/unittests_shared/unittests_shared.json @@ -19,9 +19,7 @@ "cpl-core>=2022.10.0" ], "PythonVersion": ">=3.10.4", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [], "DevDependencies": [] }, diff --git a/unittests/unittests_translation/unittests_translation.json b/unittests/unittests_translation/unittests_translation.json index f609a6d4..28396a27 100644 --- a/unittests/unittests_translation/unittests_translation.json +++ b/unittests/unittests_translation/unittests_translation.json @@ -23,9 +23,7 @@ "cpl-cli>=2022.10.0" ], "PythonVersion": ">=3.10.4", - "PythonPath": { - "linux": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { -- 2.45.1 From 703a2c91b5eb7e8effe2155ed94304344bde7fd5 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 1 Dec 2022 13:55:55 +0100 Subject: [PATCH 10/63] Added logic to change base path for cpl n #120 --- src/cpl_cli/command/new_service.py | 10 ++++++++- src/cpl_cli/startup_argument_extension.py | 3 ++- unittests/unittests_cli/new_test_case.py | 25 ++++++++++++++++++++--- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/cpl_cli/command/new_service.py b/src/cpl_cli/command/new_service.py index f7f843dd..9740a324 100644 --- a/src/cpl_cli/command/new_service.py +++ b/src/cpl_cli/command/new_service.py @@ -54,6 +54,7 @@ class NewService(CommandABC): self._use_service_providing: bool = False self._use_async: bool = False self._use_venv: bool = False + self._use_base: bool = False @property def help_message(self) -> str: @@ -159,7 +160,8 @@ class NewService(CommandABC): if self._workspace is None: project_path = os.path.join(self._env.working_directory, self._rel_path, self._project.name) else: - project_path = os.path.join(self._env.working_directory, 'src', self._rel_path, String.convert_to_snake_case(self._project.name)) + base = '' if self._use_base else 'src' + project_path = os.path.join(self._env.working_directory, base, self._rel_path, String.convert_to_snake_case(self._project.name)) if os.path.isdir(project_path) and len(os.listdir(project_path)) > 0: Console.write_line(project_path) @@ -292,6 +294,9 @@ class NewService(CommandABC): if self._env.working_directory.endswith(project): project = '' + if self._workspace is None and self._use_base: + project = f'{self._rel_path}/{project}' + VenvHelper.init_venv( False, self._env, @@ -335,6 +340,9 @@ class NewService(CommandABC): if 'venv' in args: self._use_venv = True args.remove('venv') + if 'base' in args: + self._use_base = True + args.remove('base') console = self._config.get_configuration(ProjectTypeEnum.console.value) library = self._config.get_configuration(ProjectTypeEnum.library.value) diff --git a/src/cpl_cli/startup_argument_extension.py b/src/cpl_cli/startup_argument_extension.py index 765ceafa..de57d9c3 100644 --- a/src/cpl_cli/startup_argument_extension.py +++ b/src/cpl_cli/startup_argument_extension.py @@ -55,7 +55,8 @@ class StartupArgumentExtension(StartupExtensionABC): .add_console_argument(ArgumentTypeEnum.Flag, '--', 'startup', ['s', 'S']) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'service-providing', ['sp', 'SP']) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'nothing', ['n', 'N']) \ - .add_console_argument(ArgumentTypeEnum.Flag, '--', 'venv', ['v', 'V']) + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'venv', ['v', 'V']) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'base', ['b', 'B']) config.create_console_argument(ArgumentTypeEnum.Executable, '', 'publish', ['p', 'P'], PublishService, True, validators=[ProjectValidator]) config.create_console_argument(ArgumentTypeEnum.Executable, '', 'remove', ['r', 'R'], RemoveService, True, validators=[WorkspaceValidator]) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) diff --git a/unittests/unittests_cli/new_test_case.py b/unittests/unittests_cli/new_test_case.py index b2b24177..5c05334e 100644 --- a/unittests/unittests_cli/new_test_case.py +++ b/unittests/unittests_cli/new_test_case.py @@ -12,7 +12,7 @@ class NewTestCase(unittest.TestCase): def setUp(self): os.chdir(os.path.abspath(PLAYGROUND_PATH)) - def _test_project(self, project_type: str, name: str, *args, test_venv=False): + def _test_project(self, project_type: str, name: str, *args, test_venv=False, without_ws=False): CLICommands.new(project_type, name, *args) workspace_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, name)) self.assertTrue(os.path.exists(workspace_path)) @@ -22,7 +22,15 @@ class NewTestCase(unittest.TestCase): self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv/bin/python'))) self.assertTrue(os.path.islink(os.path.join(workspace_path, 'venv/bin/python'))) - project_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, name, 'src', String.convert_to_snake_case(name))) + base = 'src' + if '--base' in args and '/' in name: + base = name.split('/')[0] + name = name.replace(f'{name.split("/")[0]}/', '') + + project_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, name, base, String.convert_to_snake_case(name))) + if without_ws: + project_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, base, name, 'src/', String.convert_to_snake_case(name))) + self.assertTrue(os.path.exists(project_path)) self.assertTrue(os.path.join(project_path, f'{name}.json')) self.assertTrue(os.path.join(project_path, f'main.py')) @@ -54,7 +62,12 @@ class NewTestCase(unittest.TestCase): self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv/bin/python'))) self.assertTrue(os.path.islink(os.path.join(workspace_path, 'venv/bin/python'))) - project_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, workspace_name, 'src', String.convert_to_snake_case(name))) + base = 'src' + if '--base' in args and '/' in name: + base = name.split('/')[0] + name = name.replace(f'{name.split("/")[0]}/', '') + + project_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, workspace_name, base, String.convert_to_snake_case(name))) self.assertTrue(os.path.exists(project_path)) self.assertTrue(os.path.join(project_path, f'{name}.json')) os.chdir(os.path.abspath(os.path.join(os.getcwd(), '../'))) @@ -88,6 +101,9 @@ class NewTestCase(unittest.TestCase): def test_console(self): self._test_project('console', 'test-console', '--ab', '--s', '--venv', test_venv=True) + def test_console_with_other_base(self): + self._test_project('console', 'tools/test-console', '--ab', '--s', '--venv', '--base', test_venv=True, without_ws=True) + def test_console_without_s(self): self._test_project('console', 'test-console-without-s', '--ab') @@ -100,6 +116,9 @@ class NewTestCase(unittest.TestCase): def test_sub_console(self): self._test_sub_project('console', 'test-sub-console', 'test-console', '--ab', '--s', '--sp', '--venv', test_venv=True) + def test_sub_console_with_other_base(self): + self._test_sub_project('console', 'tools/test-sub-console', 'test-console', '--ab', '--s', '--sp', '--venv', '--base', test_venv=True) + def test_library(self): self._test_project('library', 'test-library', '--ab', '--s', '--sp') -- 2.45.1 From d8f7e0381572ad38c9f5b8a326c8bfa18fc1bf6e Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 1 Dec 2022 16:27:29 +0100 Subject: [PATCH 11/63] Added group by & refactored Iterable #129 --- src/cpl_query/base/default_lambda.py | 2 + src/cpl_query/base/queryable_abc.py | 9 + src/cpl_query/iterable/iterable.py | 191 ++++++------------ unittests/unittests/application.py | 4 +- .../iterable_query_test_case.py | 38 +++- 5 files changed, 111 insertions(+), 133 deletions(-) create mode 100644 src/cpl_query/base/default_lambda.py diff --git a/src/cpl_query/base/default_lambda.py b/src/cpl_query/base/default_lambda.py new file mode 100644 index 00000000..3d985ff2 --- /dev/null +++ b/src/cpl_query/base/default_lambda.py @@ -0,0 +1,2 @@ +def default_lambda(x: object): + return x diff --git a/src/cpl_query/base/queryable_abc.py b/src/cpl_query/base/queryable_abc.py index 976c9ab4..fa22ab83 100644 --- a/src/cpl_query/base/queryable_abc.py +++ b/src/cpl_query/base/queryable_abc.py @@ -155,6 +155,15 @@ class QueryableABC(ABC): """ pass + def group_by(self, _func: Callable = None) -> 'QueryableABC': + r"""Groups by func + + Returns + ------- + Grouped list[list[any]]: any + """ + pass + @abstractmethod def last(self) -> any: r"""Returns last element diff --git a/src/cpl_query/iterable/iterable.py b/src/cpl_query/iterable/iterable.py index c8e54573..6f7ce73f 100644 --- a/src/cpl_query/iterable/iterable.py +++ b/src/cpl_query/iterable/iterable.py @@ -16,59 +16,36 @@ class Iterable(IterableABC): IterableABC.__init__(self, t, values) def all(self, _func: Callable = None) -> bool: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - if _func is None: _func = _default_lambda - result = self.where(_func) - return len(result) == len(self) + return self.where(_func).count() == self.count() def any(self, _func: Callable = None) -> bool: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - if _func is None: _func = _default_lambda - result = self.where(_func) - return len(result) > 0 + return self.where(_func).count() > 0 def average(self, _func: Callable = None) -> Union[int, float, complex]: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - if _func is None and not is_number(self.type): raise InvalidTypeException() - if _func is None: - _func = _default_lambda - - return float(self.sum(_func)) / float(self.count()) + return self.sum(_func) / self.count() def contains(self, _value: object) -> bool: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - if _value is None: raise ArgumentNoneException(ExceptionArgument.value) return self.where(lambda x: x == _value).count() > 0 def count(self, _func: Callable = None) -> int: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - if _func is None: - return len(self) + return self.__len__() - return len(self.where(_func)) - - def distinct(self, _func: Callable = None) -> IterableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) + return self.where(_func).__len__() + def distinct(self, _func: Callable = None) -> 'Iterable': if _func is None: _func = _default_lambda @@ -85,18 +62,12 @@ class Iterable(IterableABC): return result def element_at(self, _index: int) -> any: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - if _index is None: raise ArgumentNoneException(ExceptionArgument.index) return self[_index] def element_at_or_default(self, _index: int) -> any: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - if _index is None: raise ArgumentNoneException(ExceptionArgument.index) @@ -105,56 +76,52 @@ class Iterable(IterableABC): except IndexError: return None - def first(self: IterableABC) -> any: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - + def first(self) -> any: if len(self) == 0: raise IndexOutOfRangeException() return self[0] - def first_or_default(self: IterableABC) -> Optional[any]: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - + def first_or_default(self) -> Optional[any]: if len(self) == 0: return None return self[0] - def last(self: IterableABC) -> any: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if len(self) == 0: - raise IndexOutOfRangeException() - - return self[len(self) - 1] - - def last_or_default(self: IterableABC) -> Optional[any]: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if len(self) == 0: - return None - - return self[len(self) - 1] - - def for_each(self, _func: Callable = None): - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - + def group_by(self, _func: Callable = None) -> 'Iterable': if _func is None: _func = _default_lambda + groups = {} - for element in self: - _func(element) + for v in self: + value = _func(v) + if v not in groups: + groups[value] = Iterable(type(v)) + + groups[value].append(v) + + return Iterable(Iterable).extend(groups.values()) + + def last(self) -> any: + if len(self) == 0: + raise IndexOutOfRangeException() + + return self[len(self) - 1] + + def last_or_default(self) -> Optional[any]: + if len(self) == 0: + return None + + return self[len(self) - 1] + + def for_each(self, _func: Callable = None) -> 'Iterable': + if _func is not None: + for element in self: + _func(element) + + return self def max(self, _func: Callable = None) -> Union[int, float, complex]: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - if _func is None and not is_number(self.type): raise InvalidTypeException() @@ -166,6 +133,7 @@ class Iterable(IterableABC): def median(self, _func=None) -> Union[int, float]: if _func is None: _func = _default_lambda + result = self.order_by(_func).select(_func).to_list() length = len(result) i = int(length / 2) @@ -176,9 +144,6 @@ class Iterable(IterableABC): ) def min(self, _func: Callable = None) -> Union[int, float, complex]: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - if _func is None and not is_number(self.type): raise InvalidTypeException() @@ -188,9 +153,6 @@ class Iterable(IterableABC): return _func(min(self, key=_func)) def order_by(self, _func: Callable = None) -> OrderedIterableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - if _func is None: _func = _default_lambda @@ -198,22 +160,16 @@ class Iterable(IterableABC): return OrderedIterable(self.type, _func, sorted(self, key=_func)) def order_by_descending(self, _func: Callable = None) -> OrderedIterableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - if _func is None: _func = _default_lambda from cpl_query.iterable.ordered_iterable import OrderedIterable return OrderedIterable(self.type, _func, sorted(self, key=_func, reverse=True)) - def reverse(self: IterableABC) -> IterableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) + def reverse(self) -> 'Iterable': + return Iterable().extend(reversed(self)) - return Iterable().extend(reversed(self.to_list())) - - def select(self, _func: Callable = None) -> IterableABC: + def select(self, _func: Callable = None) -> 'Iterable': if _func is None: _func = _default_lambda @@ -221,10 +177,7 @@ class Iterable(IterableABC): result.extend(_func(_o) for _o in self) return result - def select_many(self, _func: Callable = None) -> IterableABC: - if _func is None: - _func = _default_lambda - + def select_many(self, _func: Callable = None) -> 'Iterable': result = Iterable() # The line below is pain. I don't understand anything of it... # written on 09.11.2022 by Sven Heidemann @@ -233,10 +186,7 @@ class Iterable(IterableABC): result.extend(elements) return result - def single(self: IterableABC) -> any: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - + def single(self) -> any: if len(self) > 1: raise Exception('Found more than one element') elif len(self) == 0: @@ -244,10 +194,7 @@ class Iterable(IterableABC): return self[0] - def single_or_default(self: IterableABC) -> Optional[any]: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - + def single_or_default(self) -> Optional[any]: if len(self) > 1: raise Exception('Index out of range') elif len(self) == 0: @@ -255,19 +202,13 @@ class Iterable(IterableABC): return self[0] - def skip(self, _index: int) -> IterableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - + def skip(self, _index: int) -> 'Iterable': if _index is None: raise ArgumentNoneException(ExceptionArgument.index) return Iterable(self.type, values=self[_index:]) - def skip_last(self, _index: int) -> IterableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - + def skip_last(self, _index: int) -> 'Iterable': if _index is None: raise ArgumentNoneException(ExceptionArgument.index) @@ -277,10 +218,20 @@ class Iterable(IterableABC): result.extend(self[:index]) return result - def take(self, _index: int) -> IterableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) + def sum(self, _func: Callable = None) -> Union[int, float, complex]: + if _func is None and not is_number(self.type): + raise InvalidTypeException() + if _func is None: + _func = _default_lambda + + result = 0 + for x in self: + result += _func(x) + + return result + + def take(self, _index: int) -> 'Iterable': if _index is None: raise ArgumentNoneException(ExceptionArgument.index) @@ -288,10 +239,7 @@ class Iterable(IterableABC): result.extend(self[:_index]) return result - def take_last(self, _index: int) -> IterableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - + def take_last(self, _index: int) -> 'Iterable': index = len(self) - _index if index >= len(self) or index < 0: @@ -301,22 +249,7 @@ class Iterable(IterableABC): result.extend(self[index:]) return result - def sum(self, _func: Callable = None) -> Union[int, float, complex]: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None and not is_number(self.type): - raise InvalidTypeException() - - if _func is None: - _func = _default_lambda - - return sum([_func(x) for x in self]) - - def where(self, _func: Callable = None) -> IterableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - + def where(self, _func: Callable = None) -> 'Iterable': if _func is None: raise ArgumentNoneException(ExceptionArgument.func) @@ -328,4 +261,4 @@ class Iterable(IterableABC): if _func(element): result.append(element) - return result \ No newline at end of file + return result diff --git a/unittests/unittests/application.py b/unittests/unittests/application.py index 0ba34799..c9547c15 100644 --- a/unittests/unittests/application.py +++ b/unittests/unittests/application.py @@ -18,6 +18,6 @@ class Application(ApplicationABC): def main(self): runner = unittest.TextTestRunner() - runner.run(CLITestSuite()) + # runner.run(CLITestSuite()) runner.run(QueryTestSuite()) - runner.run(TranslationTestSuite()) + # runner.run(TranslationTestSuite()) diff --git a/unittests/unittests_query/iterable_query_test_case.py b/unittests/unittests_query/iterable_query_test_case.py index 626a4905..c48fc9ea 100644 --- a/unittests/unittests_query/iterable_query_test_case.py +++ b/unittests/unittests_query/iterable_query_test_case.py @@ -5,6 +5,7 @@ from random import randint from cpl_core.utils import String from cpl_query.exceptions import InvalidTypeException, ArgumentNoneException from cpl_query.extension.list import List +from cpl_query.iterable import Iterable from unittests_query.models import User, Address @@ -102,8 +103,18 @@ class IterableQueryTestCase(unittest.TestCase): self.assertEqual(1, self._tests.count(lambda u: u == self._t_user)) def test_distinct(self): - res = self._tests.distinct(lambda u: u.address.nr).where(lambda u: u.address.nr == 5) - self.assertEqual(1, len(res)) + res = self._tests.select(lambda u: u.address.nr).where(lambda a: a == 5).distinct() + self.assertEqual(1, res.count()) + + addresses = [] + for u in self._tests: + if u.address.nr in addresses: + continue + + addresses.append(u.address.nr) + + res2 = self._tests.distinct(lambda x: x.address.nr).select(lambda x: x.address.nr) + self.assertEqual(addresses, res2) def test_element_at(self): index = randint(0, len(self._tests) - 1) @@ -168,6 +179,29 @@ class IterableQueryTestCase(unittest.TestCase): self.assertEqual(res[0], s_res) self.assertIsNone(sn_res) + def test_group_by(self): + def by_adr(u): + return u.address.nr + + t = self._tests.select(by_adr).group_by() + res = self._tests.group_by(by_adr) + self.assertTrue(isinstance(res.first_or_default(), Iterable)) + self.assertNotEqual(self._tests.count(), res.count()) + self.assertEqual(self._tests.distinct(by_adr).count(), res.count()) + + elements = List(int) + groups = {} + for x in range(0, 1000): + v = randint(1, 100) + if v not in groups: + groups[v] = [] + + groups[v].append(v) + elements.append(v) + + r1, r2 = list(groups.values()), elements.group_by() + self.assertEqual(r1, r2) + def test_for_each(self): users = [] self._tests.for_each(lambda user: ( -- 2.45.1 From e8ae635c88170351aef35d31e21c636234080a79 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 1 Dec 2022 17:00:17 +0100 Subject: [PATCH 12/63] Improved tests #129 --- unittests/unittests/application.py | 4 ++-- unittests/unittests_cli/add_test_case.py | 5 ++++- unittests/unittests_cli/build_test_case.py | 5 ++++- unittests/unittests_cli/cli_test_suite.py | 2 +- unittests/unittests_cli/constants.py | 10 +++++++--- unittests/unittests_cli/install_test_case.py | 5 ++++- unittests/unittests_cli/new_test_case.py | 5 ++++- unittests/unittests_cli/publish_test_case.py | 5 ++++- unittests/unittests_cli/remove_test_case.py | 5 ++++- unittests/unittests_cli/run_test_case.py | 5 ++++- unittests/unittests_cli/start_test_case.py | 5 ++++- unittests/unittests_cli/uninstall_test_case.py | 5 ++++- unittests/unittests_query/query_test_suite.py | 2 +- 13 files changed, 47 insertions(+), 16 deletions(-) diff --git a/unittests/unittests/application.py b/unittests/unittests/application.py index c9547c15..0ba34799 100644 --- a/unittests/unittests/application.py +++ b/unittests/unittests/application.py @@ -18,6 +18,6 @@ class Application(ApplicationABC): def main(self): runner = unittest.TextTestRunner() - # runner.run(CLITestSuite()) + runner.run(CLITestSuite()) runner.run(QueryTestSuite()) - # runner.run(TranslationTestSuite()) + runner.run(TranslationTestSuite()) diff --git a/unittests/unittests_cli/add_test_case.py b/unittests/unittests_cli/add_test_case.py index 27964fbe..d1b64503 100644 --- a/unittests/unittests_cli/add_test_case.py +++ b/unittests/unittests_cli/add_test_case.py @@ -26,7 +26,10 @@ class AddTestCase(unittest.TestCase): return project_json def setUp(self): - os.chdir(os.path.abspath(PLAYGROUND_PATH)) + if not os.path.exists(PLAYGROUND_PATH): + os.makedirs(PLAYGROUND_PATH) + + os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) diff --git a/unittests/unittests_cli/build_test_case.py b/unittests/unittests_cli/build_test_case.py index e35d5cbd..d01de06f 100644 --- a/unittests/unittests_cli/build_test_case.py +++ b/unittests/unittests_cli/build_test_case.py @@ -31,7 +31,10 @@ class BuildTestCase(unittest.TestCase): project_file.close() def setUp(self): - os.chdir(os.path.abspath(PLAYGROUND_PATH)) + if not os.path.exists(PLAYGROUND_PATH): + os.makedirs(PLAYGROUND_PATH) + + os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) diff --git a/unittests/unittests_cli/cli_test_suite.py b/unittests/unittests_cli/cli_test_suite.py index 65cb6355..228fa366 100644 --- a/unittests/unittests_cli/cli_test_suite.py +++ b/unittests/unittests_cli/cli_test_suite.py @@ -75,4 +75,4 @@ class CLITestSuite(unittest.TestSuite): def run(self, *args): self._setup() self._result = super().run(*args) - # self._cleanup() + self._cleanup() diff --git a/unittests/unittests_cli/constants.py b/unittests/unittests_cli/constants.py index f585a27f..c8318dab 100644 --- a/unittests/unittests_cli/constants.py +++ b/unittests/unittests_cli/constants.py @@ -1,5 +1,9 @@ import os -PLAYGROUND_PATH = os.path.abspath(os.path.join(os.getcwd(), '../test_cli_playground')) -TRANSLATION_PATH = os.path.abspath(os.path.join(os.getcwd(), '../unittests_translation')) -CLI_PATH = os.path.abspath(os.path.join(os.getcwd(), '../../src/cpl_cli/main.py')) +base = '' +if not os.getcwd().endswith('unittests'): + base = '../' + +PLAYGROUND_PATH = os.path.abspath(os.path.join(os.getcwd(), f'{base}test_cli_playground')) +TRANSLATION_PATH = os.path.abspath(os.path.join(os.getcwd(), f'{base}unittests_translation')) +CLI_PATH = os.path.abspath(os.path.join(os.getcwd(), f'{base}../src/cpl_cli/main.py')) diff --git a/unittests/unittests_cli/install_test_case.py b/unittests/unittests_cli/install_test_case.py index 527256d1..516a44e4 100644 --- a/unittests/unittests_cli/install_test_case.py +++ b/unittests/unittests_cli/install_test_case.py @@ -31,7 +31,10 @@ class InstallTestCase(unittest.TestCase): project_file.close() def setUp(self): - os.chdir(os.path.abspath(PLAYGROUND_PATH)) + if not os.path.exists(PLAYGROUND_PATH): + os.makedirs(PLAYGROUND_PATH) + + os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) diff --git a/unittests/unittests_cli/new_test_case.py b/unittests/unittests_cli/new_test_case.py index 5c05334e..5d0eb0a3 100644 --- a/unittests/unittests_cli/new_test_case.py +++ b/unittests/unittests_cli/new_test_case.py @@ -10,7 +10,10 @@ from unittests_shared.cli_commands import CLICommands class NewTestCase(unittest.TestCase): def setUp(self): - os.chdir(os.path.abspath(PLAYGROUND_PATH)) + if not os.path.exists(PLAYGROUND_PATH): + os.makedirs(PLAYGROUND_PATH) + + os.chdir(PLAYGROUND_PATH) def _test_project(self, project_type: str, name: str, *args, test_venv=False, without_ws=False): CLICommands.new(project_type, name, *args) diff --git a/unittests/unittests_cli/publish_test_case.py b/unittests/unittests_cli/publish_test_case.py index 7c828ced..141e374e 100644 --- a/unittests/unittests_cli/publish_test_case.py +++ b/unittests/unittests_cli/publish_test_case.py @@ -31,7 +31,10 @@ class PublishTestCase(unittest.TestCase): project_file.close() def setUp(self): - os.chdir(os.path.abspath(PLAYGROUND_PATH)) + if not os.path.exists(PLAYGROUND_PATH): + os.makedirs(PLAYGROUND_PATH) + + os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) diff --git a/unittests/unittests_cli/remove_test_case.py b/unittests/unittests_cli/remove_test_case.py index 81aa8ee0..f618e4b8 100644 --- a/unittests/unittests_cli/remove_test_case.py +++ b/unittests/unittests_cli/remove_test_case.py @@ -24,7 +24,10 @@ class RemoveTestCase(unittest.TestCase): return project_json def setUp(self): - os.chdir(os.path.abspath(PLAYGROUND_PATH)) + if not os.path.exists(PLAYGROUND_PATH): + os.makedirs(PLAYGROUND_PATH) + + os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) diff --git a/unittests/unittests_cli/run_test_case.py b/unittests/unittests_cli/run_test_case.py index 1d86b68d..7ec9b9dd 100644 --- a/unittests/unittests_cli/run_test_case.py +++ b/unittests/unittests_cli/run_test_case.py @@ -50,7 +50,10 @@ class RunTestCase(unittest.TestCase): project_file.close() def setUp(self): - os.chdir(os.path.abspath(PLAYGROUND_PATH)) + if not os.path.exists(PLAYGROUND_PATH): + os.makedirs(PLAYGROUND_PATH) + + os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) diff --git a/unittests/unittests_cli/start_test_case.py b/unittests/unittests_cli/start_test_case.py index f41eb450..3ff09294 100644 --- a/unittests/unittests_cli/start_test_case.py +++ b/unittests/unittests_cli/start_test_case.py @@ -50,7 +50,10 @@ class StartTestCase(unittest.TestCase): project_file.close() def setUp(self): - os.chdir(os.path.abspath(PLAYGROUND_PATH)) + if not os.path.exists(PLAYGROUND_PATH): + os.makedirs(PLAYGROUND_PATH) + + os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) diff --git a/unittests/unittests_cli/uninstall_test_case.py b/unittests/unittests_cli/uninstall_test_case.py index d81bddf9..a552bfc2 100644 --- a/unittests/unittests_cli/uninstall_test_case.py +++ b/unittests/unittests_cli/uninstall_test_case.py @@ -29,7 +29,10 @@ class UninstallTestCase(unittest.TestCase): return project_json def setUp(self): - os.chdir(os.path.abspath(PLAYGROUND_PATH)) + if not os.path.exists(PLAYGROUND_PATH): + os.makedirs(PLAYGROUND_PATH) + + os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) diff --git a/unittests/unittests_query/query_test_suite.py b/unittests/unittests_query/query_test_suite.py index e1c307b4..c8b0d7c1 100644 --- a/unittests/unittests_query/query_test_suite.py +++ b/unittests/unittests_query/query_test_suite.py @@ -25,4 +25,4 @@ class QueryTestSuite(unittest.TestSuite): if __name__ == "__main__": runner = unittest.TextTestRunner() - runner.run(QueryTestSuite()) \ No newline at end of file + runner.run(QueryTestSuite()) -- 2.45.1 From f0f79e7e3bebbad3834d3a7f17a1ae2f44202527 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 1 Dec 2022 21:09:39 +0100 Subject: [PATCH 13/63] Refactored cpl-query Iterable & Enumerable #129 --- src/cpl_query/base/ordered_queryable.py | 34 ++ .../ordered_queryable_abc.py} | 12 +- src/cpl_query/base/queryable_abc.py | 292 ++++++++++++----- src/cpl_query/base/sequence_abc.py | 86 +++++ src/cpl_query/base/sequence_values.py | 10 +- src/cpl_query/enumerable/__init__.py | 3 - src/cpl_query/enumerable/enumerable.py | 296 +----------------- src/cpl_query/enumerable/enumerable_abc.py | 81 +---- .../enumerable/ordered_enumerable.py | 36 --- .../enumerable/ordered_enumerable_abc.py | 43 --- src/cpl_query/iterable/__init__.py | 2 - src/cpl_query/iterable/iterable.py | 253 +-------------- src/cpl_query/iterable/iterable_abc.py | 47 ++- src/cpl_query/iterable/ordered_iterable.py | 35 --- unittests/unittests_cli/constants.py | 2 +- .../enumerable_query_test_case.py | 29 +- .../unittests_query/enumerable_test_case.py | 33 +- .../iterable_query_test_case.py | 4 +- unittests/unittests_query/models.py | 8 +- 19 files changed, 390 insertions(+), 916 deletions(-) create mode 100644 src/cpl_query/base/ordered_queryable.py rename src/cpl_query/{iterable/ordered_iterable_abc.py => base/ordered_queryable_abc.py} (69%) create mode 100644 src/cpl_query/base/sequence_abc.py delete mode 100644 src/cpl_query/enumerable/ordered_enumerable.py delete mode 100644 src/cpl_query/enumerable/ordered_enumerable_abc.py delete mode 100644 src/cpl_query/iterable/ordered_iterable.py diff --git a/src/cpl_query/base/ordered_queryable.py b/src/cpl_query/base/ordered_queryable.py new file mode 100644 index 00000000..c7b3dbf7 --- /dev/null +++ b/src/cpl_query/base/ordered_queryable.py @@ -0,0 +1,34 @@ +from collections.abc import Callable + +from cpl_query.base.ordered_queryable_abc import OrderedQueryableABC +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument +from cpl_query.iterable.iterable import Iterable + + +class OrderedQueryable(OrderedQueryableABC): + r"""Implementation of :class: `cpl_query.extension.Iterable` `cpl_query.extension.OrderedIterableABC` + """ + + def __init__(self, _t: type, _values: Iterable = None, _func: Callable = None): + OrderedQueryableABC.__init__(self, _t, _values, _func) + + def then_by(self: OrderedQueryableABC, _func: Callable) -> OrderedQueryableABC: + if self is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + + self._funcs.append(_func) + + return OrderedQueryable(self.type, sorted(self, key=lambda *args: [f(*args) for f in self._funcs]), _func) + + def then_by_descending(self: OrderedQueryableABC, _func: Callable) -> OrderedQueryableABC: + if self is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + + self._funcs.append(_func) + return OrderedQueryable(self.type, sorted(self, key=lambda *args: [f(*args) for f in self._funcs], reverse=True), _func) diff --git a/src/cpl_query/iterable/ordered_iterable_abc.py b/src/cpl_query/base/ordered_queryable_abc.py similarity index 69% rename from src/cpl_query/iterable/ordered_iterable_abc.py rename to src/cpl_query/base/ordered_queryable_abc.py index eba32559..f3ec56fc 100644 --- a/src/cpl_query/iterable/ordered_iterable_abc.py +++ b/src/cpl_query/base/ordered_queryable_abc.py @@ -2,20 +2,20 @@ from abc import abstractmethod from collections.abc import Callable from typing import Iterable -from cpl_query.iterable.iterable_abc import IterableABC +from cpl_query.base.queryable_abc import QueryableABC -class OrderedIterableABC(IterableABC): +class OrderedQueryableABC(QueryableABC): @abstractmethod - def __init__(self, _t: type, _func: Callable = None, _values: Iterable = None): - IterableABC.__init__(self, _t, _values) + def __init__(self, _t: type, _values: Iterable = None, _func: Callable = None): + QueryableABC.__init__(self, _t, _values) self._funcs: list[Callable] = [] if _func is not None: self._funcs.append(_func) @abstractmethod - def then_by(self, func: Callable) -> 'OrderedIterableABC': + def then_by(self, func: Callable) -> 'OrderedQueryableABC': r"""Sorts OrderedList in ascending order by function Parameter @@ -29,7 +29,7 @@ class OrderedIterableABC(IterableABC): pass @abstractmethod - def then_by_descending(self, func: Callable) -> 'OrderedIterableABC': + def then_by_descending(self, func: Callable) -> 'OrderedQueryableABC': r"""Sorts OrderedList in descending order by function Parameter diff --git a/src/cpl_query/base/queryable_abc.py b/src/cpl_query/base/queryable_abc.py index fa22ab83..117397c6 100644 --- a/src/cpl_query/base/queryable_abc.py +++ b/src/cpl_query/base/queryable_abc.py @@ -1,10 +1,19 @@ -from abc import abstractmethod, ABC from typing import Optional, Callable, Union +from cpl_query._helper import is_number +from cpl_query.base.sequence_abc import SequenceABC +from cpl_query.exceptions import InvalidTypeException, ArgumentNoneException, ExceptionArgument, IndexOutOfRangeException -class QueryableABC(ABC): - @abstractmethod +def _default_lambda(x: object): + return x + + +class QueryableABC(SequenceABC): + + def __init__(self, t: type = None, values: list = None): + SequenceABC.__init__(self, t, values) + def all(self, _func: Callable = None) -> bool: r"""Checks if every element of list equals result found by function @@ -17,9 +26,11 @@ class QueryableABC(ABC): ------- bool """ - pass + if _func is None: + _func = _default_lambda + + return self.count(_func) == self.count() - @abstractmethod def any(self, _func: Callable = None) -> bool: r"""Checks if list contains result found by function @@ -32,9 +43,11 @@ class QueryableABC(ABC): ------- bool """ - pass + if _func is None: + _func = _default_lambda + + return self.where(_func).count() > 0 - @abstractmethod def average(self, _func: Callable = None) -> Union[int, float, complex]: r"""Returns average value of list @@ -47,10 +60,12 @@ class QueryableABC(ABC): ------- Union[int, float, complex] """ - pass + if _func is None and not is_number(self.type): + raise InvalidTypeException() - @abstractmethod - def contains(self, value: object) -> bool: + return self.sum(_func) / self.count() + + def contains(self, _value: object) -> bool: r"""Checks if list contains value given by function Parameter @@ -62,9 +77,11 @@ class QueryableABC(ABC): ------- bool """ - pass + if _value is None: + raise ArgumentNoneException(ExceptionArgument.value) + + return self.where(lambda x: x == _value).count() > 0 - @abstractmethod def count(self, _func: Callable = None) -> int: r"""Returns length of list or count of found elements @@ -77,9 +94,11 @@ class QueryableABC(ABC): ------- int """ - pass + if _func is None: + return self.__len__() + + return self.where(_func).__len__() - @abstractmethod def distinct(self, _func: Callable = None) -> 'QueryableABC': r"""Returns list without redundancies @@ -92,39 +111,62 @@ class QueryableABC(ABC): ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - pass + if _func is None: + _func = _default_lambda - @abstractmethod - def element_at(self, index: int) -> any: + result = [] + known_values = [] + for element in self: + value = _func(element) + if value in known_values: + continue + + known_values.append(value) + result.append(element) + + return type(self)(self._type, result) + + def element_at(self, _index: int) -> any: r"""Returns element at given index Parameter --------- - index: :class:`int` + _index: :class:`int` index Returns ------- - Value at index: any + Value at _index: any """ - pass + if _index is None: + raise ArgumentNoneException(ExceptionArgument.index) - @abstractmethod - def element_at_or_default(self, index: int) -> Optional[any]: + result = self[_index] + if result is None: + raise IndexOutOfRangeException + + return result + + def element_at_or_default(self, _index: int) -> Optional[any]: r"""Returns element at given index or None Parameter --------- - index: :class:`int` + _index: :class:`int` index Returns ------- - Value at index: Optional[any] + Value at _index: Optional[any] """ - pass + if _index is None: + raise ArgumentNoneException(ExceptionArgument.index) + + try: + return self[_index] + except IndexError: + return None - @abstractmethod def first(self) -> any: r"""Returns first element @@ -132,9 +174,11 @@ class QueryableABC(ABC): ------- First element of list: any """ - pass + if len(self) == 0: + raise IndexOutOfRangeException() + + return self[0] - @abstractmethod def first_or_default(self) -> any: r"""Returns first element or None @@ -142,9 +186,11 @@ class QueryableABC(ABC): ------- First element of list: Optional[any] """ - pass + if len(self) == 0: + return None + + return self[0] - @abstractmethod def for_each(self, _func: Callable = None): r"""Runs given function for each element of list @@ -153,7 +199,11 @@ class QueryableABC(ABC): func: :class: `Callable` function to call """ - pass + if _func is not None: + for element in self: + _func(element) + + return self def group_by(self, _func: Callable = None) -> 'QueryableABC': r"""Groups by func @@ -162,9 +212,23 @@ class QueryableABC(ABC): ------- Grouped list[list[any]]: any """ - pass + if _func is None: + _func = _default_lambda + groups = {} + + for v in self: + value = _func(v) + if v not in groups: + groups[value] = [] + + groups[value].append(v) + + v = [] + for g in groups.values(): + v.append(type(self)(None, g)) + x = type(self)(type(self), v) + return x - @abstractmethod def last(self) -> any: r"""Returns last element @@ -172,9 +236,11 @@ class QueryableABC(ABC): ------- Last element of list: any """ - pass + if len(self) == 0: + raise IndexOutOfRangeException() + + return self[len(self) - 1] - @abstractmethod def last_or_default(self) -> any: r"""Returns last element or None @@ -182,9 +248,11 @@ class QueryableABC(ABC): ------- Last element of list: Optional[any] """ - pass + if len(self) == 0: + return None + + return self[len(self) - 1] - @abstractmethod def max(self, _func: Callable = None) -> Union[int, float, complex]: r"""Returns the highest value @@ -197,19 +265,33 @@ class QueryableABC(ABC): ------- Union[int, float, complex] """ - pass + if _func is None and not is_number(self.type): + raise InvalidTypeException() - @abstractmethod - def median(self) -> Union[int, float]: + if _func is None: + _func = _default_lambda + + return _func(max(self, key=_func)) + + def median(self, _func=None) -> Union[int, float]: r"""Return the median value of data elements Returns ------- Union[int, float] """ - pass + if _func is None: + _func = _default_lambda + + result = self.order_by(_func).select(_func).to_list() + length = len(result) + i = int(length / 2) + return ( + result[i] + if length % 2 == 1 + else (float(result[i - 1]) + float(result[i])) / float(2) + ) - @abstractmethod def min(self, _func: Callable = None) -> Union[int, float, complex]: r"""Returns the lowest value @@ -222,9 +304,14 @@ class QueryableABC(ABC): ------- Union[int, float, complex] """ - pass + if _func is None and not is_number(self.type): + raise InvalidTypeException() + + if _func is None: + _func = _default_lambda + + return _func(min(self, key=_func)) - @abstractmethod def order_by(self, _func: Callable = None) -> 'QueryableABC': r"""Sorts elements by function in ascending order @@ -237,9 +324,12 @@ class QueryableABC(ABC): ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - pass + if _func is None: + _func = _default_lambda + + from cpl_query.base.ordered_queryable import OrderedQueryable + return OrderedQueryable(self.type, sorted(self, key=_func), _func) - @abstractmethod def order_by_descending(self, _func: Callable = None) -> 'QueryableABC': r"""Sorts elements by function in descending order @@ -252,9 +342,12 @@ class QueryableABC(ABC): ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - pass + if _func is None: + _func = _default_lambda + + from cpl_query.base.ordered_queryable import OrderedQueryable + return OrderedQueryable(self.type, sorted(self, key=_func, reverse=True), _func) - @abstractmethod def reverse(self) -> 'QueryableABC': r"""Reverses list @@ -262,29 +355,31 @@ class QueryableABC(ABC): ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - pass + return type(self)(self._type, list(reversed(self))) - @abstractmethod - def select(self, _f: Callable) -> 'QueryableABC': + def select(self, _func: Callable) -> 'QueryableABC': r"""Formats each element of list to a given format Returns ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - pass + if _func is None: + _func = _default_lambda - @abstractmethod - def select_many(self, _f: Callable) -> 'QueryableABC': + return type(self)(any, [_func(_o) for _o in self]) + + def select_many(self, _func: Callable) -> 'QueryableABC': r"""Flattens resulting lists to one Returns ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - pass + # The line below is pain. I don't understand anything of it... + # written on 09.11.2022 by Sven Heidemann + return type(self)(any, [_a for _o in self for _a in _func(_o)]) - @abstractmethod def single(self) -> any: r"""Returns one single element of list @@ -297,9 +392,13 @@ class QueryableABC(ABC): ArgumentNoneException: when argument is None Exception: when argument is None or found more than one element """ - pass + if len(self) > 1: + raise Exception('Found more than one element') + elif len(self) == 0: + raise Exception('Found no element') + + return self[0] - @abstractmethod def single_or_default(self) -> Optional[any]: r"""Returns one single element of list @@ -307,39 +406,48 @@ class QueryableABC(ABC): ------- Found value: Optional[any] """ - pass + if len(self) > 1: + raise Exception('Index out of range') + elif len(self) == 0: + return None - @abstractmethod - def skip(self, index: int) -> 'QueryableABC': + return self[0] + + def skip(self, _index: int) -> 'QueryableABC': r"""Skips all elements from index Parameter --------- - index: :class:`int` + _index: :class:`int` index Returns ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - pass + if _index is None: + raise ArgumentNoneException(ExceptionArgument.index) - @abstractmethod - def skip_last(self, index: int) -> 'QueryableABC': + return type(self)(self.type, values=self[_index:]) + + def skip_last(self, _index: int) -> 'QueryableABC': r"""Skips all elements after index Parameter --------- - index: :class:`int` + _index: :class:`int` index Returns ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - pass + if _index is None: + raise ArgumentNoneException(ExceptionArgument.index) + + index = len(self) - _index + return type(self)(self._type, self[:index]) - @abstractmethod def sum(self, _func: Callable = None) -> Union[int, float, complex]: r"""Sum of all values @@ -352,39 +460,54 @@ class QueryableABC(ABC): ------- Union[int, float, complex] """ - pass + if _func is None and not is_number(self.type): + raise InvalidTypeException() - @abstractmethod - def take(self, index: int) -> 'QueryableABC': + if _func is None: + _func = _default_lambda + + result = 0 + for x in self: + result += _func(x) + + return result + + def take(self, _index: int) -> 'QueryableABC': r"""Takes all elements from index Parameter --------- - index: :class:`int` + _index: :class:`int` index Returns ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - pass + if _index is None: + raise ArgumentNoneException(ExceptionArgument.index) - @abstractmethod - def take_last(self, index: int) -> 'QueryableABC': + return type(self)(self._type, self[:_index]) + + def take_last(self, _index: int) -> 'QueryableABC': r"""Takes all elements after index Parameter --------- - index: :class:`int` + _index: :class:`int` index Returns ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - pass + index = len(self) - _index + + if index >= len(self) or index < 0: + raise IndexOutOfRangeException() + + return type(self)(self._type, self[index:]) - @abstractmethod def where(self, _func: Callable = None) -> 'QueryableABC': r"""Select element by function @@ -397,4 +520,15 @@ class QueryableABC(ABC): ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - pass + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + + if _func is None: + _func = _default_lambda + + result = [] + for element in self: + if _func(element): + result.append(element) + + return type(self)(self.type, result) diff --git a/src/cpl_query/base/sequence_abc.py b/src/cpl_query/base/sequence_abc.py new file mode 100644 index 00000000..8e3a01aa --- /dev/null +++ b/src/cpl_query/base/sequence_abc.py @@ -0,0 +1,86 @@ +from abc import ABC, abstractmethod +from itertools import islice + +from cpl_query.base.sequence_values import SequenceValues + + +class SequenceABC(ABC): + + @abstractmethod + def __init__(self, t: type = None, values: list = None): + ABC.__init__(self) + if values is None: + values = [] + + if t is None and len(values) > 0: + t = type(values[0]) + + if t is None: + t = any + + self._type = t + self._set_values(values) + + def __len__(self): + return len(self._values) + + def __iter__(self): + return iter(self._values) + + def next(self): + return next(self._values) + + def __next__(self): + return self.next() + + def __getitem__(self, n): + values = [x for x in self] + if isinstance(n, slice): + try: + return values[n] + except Exception as e: + raise e + + for i in range(len(values)): + if i == n: + return values[i] + + def __repr__(self): + return f'<{type(self).__name__} {list(self).__repr__()}>' + + @property + def type(self) -> type: + return self._type + + def _check_type(self, __object: any): + if self._type == any: + return + + if self._type is not None and type(__object) != self._type and not isinstance(type(__object), self._type) and not issubclass(type(__object), self._type): + raise Exception(f'Unexpected type: {type(__object)}\nExpected type: {self._type}') + + def _set_values(self, values: list): + self._values = SequenceValues(values, self._type) + + def to_list(self) -> list: + r"""Converts :class: `cpl_query.base.sequence_abc.SequenceABC` to :class: `list` + + Returns + ------- + :class: `list` + """ + return [x for x in self] + + @classmethod + def empty(cls) -> 'SequenceABC': + r"""Returns an empty sequence + + Returns + ------- + Sequence object that contains no elements + """ + return cls() + + @classmethod + def range(cls, start: int, length: int) -> 'SequenceABC': + return cls(int, list(range(start, length))) diff --git a/src/cpl_query/base/sequence_values.py b/src/cpl_query/base/sequence_values.py index 9e2a485e..6298a685 100644 --- a/src/cpl_query/base/sequence_values.py +++ b/src/cpl_query/base/sequence_values.py @@ -5,15 +5,13 @@ from cpl_query.exceptions import IndexOutOfRangeException class SequenceValues: - def __init__(self, data, _t: type): - if data is None: - data = [] - + def __init__(self, data: list, _t: type): if len(data) > 0: def type_check(_t: type, _l: list): - return all(isinstance(x, _t) for x in _l) + return all([_t == any or isinstance(x, _t) for x in _l]) if not type_check(_t, data): + print([type(x) for x in data]) raise Exception(f'Unexpected type\nExpected type: {_t}') if not hasattr(data, '__iter__'): @@ -30,7 +28,7 @@ class SequenceValues: def __iter__(self): i = 0 - while i < len(self): + while i < self._len(): yield next(self._cycle) i += 1 diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index 9bd1147e..f7ff2517 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -19,12 +19,9 @@ __version__ = '2022.10.0.post2' from collections import namedtuple - # imports: from .enumerable import Enumerable from .enumerable_abc import EnumerableABC -from .ordered_enumerable import OrderedEnumerable -from .ordered_enumerable_abc import OrderedEnumerableABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') version_info = VersionInfo(major='2022', minor='10', micro='0.post2') diff --git a/src/cpl_query/enumerable/enumerable.py b/src/cpl_query/enumerable/enumerable.py index 81b3647b..7b99518a 100644 --- a/src/cpl_query/enumerable/enumerable.py +++ b/src/cpl_query/enumerable/enumerable.py @@ -1,9 +1,4 @@ -from typing import Union, Callable, Optional - -from cpl_query._helper import is_number from cpl_query.enumerable.enumerable_abc import EnumerableABC -from cpl_query.enumerable.ordered_enumerable_abc import OrderedEnumerableABC -from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument, InvalidTypeException, IndexOutOfRangeException def _default_lambda(x: object): @@ -14,294 +9,5 @@ class Enumerable(EnumerableABC): r"""Implementation of :class: `cpl_query.enumerable.enumerable_abc.EnumerableABC` """ - def __init__(self, t: type = None, values: Union[list, iter] = None): + def __init__(self, t: type = None, values: list = None): EnumerableABC.__init__(self, t, values) - - def all(self, _func: Callable = None) -> bool: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None: - _func = _default_lambda - - result = self.where(_func) - return len(result) == len(self) - - def any(self, _func: Callable = None) -> bool: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None: - _func = _default_lambda - - result = self.where(_func) - return len(result) > 0 - - def average(self, _func: Callable = None) -> Union[int, float, complex]: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None and not is_number(self.type): - raise InvalidTypeException() - - if _func is None: - _func = _default_lambda - - return float(self.sum(_func)) / float(self.count()) - - def contains(self, _value: object) -> bool: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _value is None: - raise ArgumentNoneException(ExceptionArgument.value) - - return self.where(lambda x: x == _value).count() > 0 - - def count(self, _func: Callable = None) -> int: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None: - return len(self) - - return len(self.where(_func)) - - def distinct(self, _func: Callable = None) -> EnumerableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None: - _func = _default_lambda - - result = Enumerable() - known_values = [] - for element in self: - value = _func(element) - if value in known_values: - continue - - known_values.append(value) - result.add(element) - - return result - - def element_at(self, _index: int) -> any: - self._values.reset() - while _index >= 0: - current = self.next() - if _index == 0: - return current - _index -= 1 - - def element_at_or_default(self, _index: int) -> any: - try: - return self.element_at(_index) - except IndexOutOfRangeException: - return None - - @staticmethod - def empty() -> 'EnumerableABC': - r"""Returns an empty enumerable - - Returns - ------- - Enumerable object that contains no elements - """ - return Enumerable() - - def first(self: EnumerableABC, _func=None) -> any: - if _func is not None: - return self.where(_func).element_at(0) - return self.element_at(0) - - def first_or_default(self: EnumerableABC, _func=None) -> Optional[any]: - if _func is not None: - return self.where(_func).element_at_or_default(0) - return self.element_at_or_default(0) - - def for_each(self, _func: Callable = None): - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None: - _func = _default_lambda - - for element in self: - _func(element) - - def last(self: EnumerableABC) -> any: - return self.element_at(self.count() - 1) - - def last_or_default(self: EnumerableABC) -> Optional[any]: - return self.element_at_or_default(self.count() - 1) - - def max(self, _func: Callable = None) -> Union[int, float, complex]: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None and not is_number(self.type): - raise InvalidTypeException() - - if _func is None: - _func = _default_lambda - - return _func(max(self, key=_func)) - - def median(self, _func=None) -> Union[int, float]: - if _func is None: - _func = _default_lambda - result = self.order_by(_func).select(_func).to_list() - length = len(result) - i = int(length / 2) - return ( - result[i] - if length % 2 == 1 - else (float(result[i - 1]) + float(result[i])) / float(2) - ) - - def min(self, _func: Callable = None) -> Union[int, float, complex]: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None and not is_number(self.type): - raise InvalidTypeException() - - if _func is None: - _func = _default_lambda - - return _func(min(self, key=_func)) - - def order_by(self, _func: Callable = None) -> OrderedEnumerableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None: - _func = _default_lambda - - from cpl_query.enumerable.ordered_enumerable import OrderedEnumerable - return OrderedEnumerable(self.type, _func, sorted(self, key=_func)) - - def order_by_descending(self, _func: Callable = None) -> OrderedEnumerableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None: - _func = _default_lambda - - from cpl_query.enumerable.ordered_enumerable import OrderedEnumerable - return OrderedEnumerable(self.type, _func, sorted(self, key=_func, reverse=True)) - - @staticmethod - def range(start: int, length: int) -> 'EnumerableABC': - return Enumerable(int, range(start, length)) - - def reverse(self: EnumerableABC) -> EnumerableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - return Enumerable(self.type, list(reversed(self.to_list()))) - - def select(self, _func: Callable = None) -> EnumerableABC: - if _func is None: - _func = _default_lambda - - _l = [_func(_o) for _o in self] - return Enumerable(self._type if len(_l) < 1 else type(_l[0]), _l) - - def select_many(self, _func: Callable = None) -> EnumerableABC: - if _func is None: - _func = _default_lambda - - # The line below is pain. I don't understand anything of the list comprehension... - # written on 09.11.2022 by Sven Heidemann - _l = [_a for _o in self for _a in _func(_o)] - return Enumerable(self._type if len(_l) < 1 else type(_l[0]), _l) - - def single(self: EnumerableABC) -> any: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if len(self) > 1: - raise IndexError('Found more than one element') - elif len(self) == 0: - raise IndexOutOfRangeException(f'{type(self).__name__} is empty') - - return self.element_at(0) - - def single_or_default(self: EnumerableABC) -> Optional[any]: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if len(self) > 1: - raise IndexError('Found more than one element') - elif len(self) == 0: - return None - - return self.element_at(0) - - def skip(self, _index: int) -> EnumerableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _index is None: - raise ArgumentNoneException(ExceptionArgument.index) - - _list = self.to_list() - - return Enumerable(self.type, _list[_index:]) - - def skip_last(self, _index: int) -> EnumerableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _index is None: - raise ArgumentNoneException(ExceptionArgument.index) - - index = len(self) - _index - - return self.take(len(self) - _index) - - def take(self, _index: int) -> EnumerableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _index is None: - raise ArgumentNoneException(ExceptionArgument.index) - - _list = self.to_list() - - return Enumerable(self.type, _list[:_index]) - - def take_last(self, _index: int) -> EnumerableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _index is None: - raise ArgumentNoneException(ExceptionArgument.index) - - _list = self.to_list() - index = len(_list) - _index - - return self.skip(index) - - def sum(self, _func: Callable = None) -> Union[int, float, complex]: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None and not is_number(self.type): - raise InvalidTypeException() - - if _func is None: - _func = _default_lambda - - return sum([_func(x) for x in self]) - - def where(self, _func: Callable = None) -> EnumerableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None: - raise ArgumentNoneException(ExceptionArgument.func) - - return Enumerable(self.type, list(filter(_func, self._values))) diff --git a/src/cpl_query/enumerable/enumerable_abc.py b/src/cpl_query/enumerable/enumerable_abc.py index ff587f1a..b59054d9 100644 --- a/src/cpl_query/enumerable/enumerable_abc.py +++ b/src/cpl_query/enumerable/enumerable_abc.py @@ -1,8 +1,6 @@ from abc import abstractmethod -from typing import Iterable from cpl_query.base.queryable_abc import QueryableABC -from cpl_query.base.sequence_values import SequenceValues class EnumerableABC(QueryableABC): @@ -11,81 +9,15 @@ class EnumerableABC(QueryableABC): @abstractmethod def __init__(self, t: type = None, values: list = None): - if t == any or t is None and values is not None: - t = type(values[0]) + QueryableABC.__init__(self, t, values) - self._type, self._values, self._remove_error_check = t, SequenceValues(values, t), True - - def __len__(self): - return len(self._values) - - def __iter__(self): - return iter(self._values) - - def next(self): - return next(self._values) - - def __next__(self): - return self.next() - - def __repr__(self): - return f'<{type(self).__name__} {list(self).__repr__()}>' - - @property - def type(self) -> type: - return self._type + self._remove_error_check = True def set_remove_error_check(self, _value: bool): r"""Set flag to check if element exists before removing """ self._remove_error_check = _value - def add(self, __object: object) -> None: - r"""Adds an element to the enumerable. - """ - if self._type is not None and type(__object) != self._type and not isinstance(type(__object), self._type) and not issubclass(type(__object), self._type): - raise Exception(f'Unexpected type: {type(__object)}\nExpected type: {self._type}') - - if len(self) == 0 and self._type is None: - self._type = type(__object) - - self._values = SequenceValues([*self._values, __object], self._type) - - def clear(self): - r"""Removes all elements - """ - del self._values - self._values = [] - - def extend(self, __list: Iterable) -> 'EnumerableABC': - r"""Adds elements of given list to enumerable - - Parameter - --------- - __enumerable: :class: `cpl_query.enumerable.enumerable_abc.EnumerableABC` - index - """ - self._values = SequenceValues([*self._values, *__list], self._type) - return self - - def remove(self, __object: object) -> None: - r"""Removes element from list - - Parameter - --------- - __object: :class:`object` - value - - Raises - --------- - `Element not found` when element does not exist. Check can be deactivated by calling .set_remove_error_check(False) - """ - if self._remove_error_check and __object not in self._values: - raise Exception('Element not found') - - # self._values.remove(__object) - self._values = SequenceValues([x for x in self.to_list() if x != __object], self._type) - def to_iterable(self) -> 'IterableABC': r"""Converts :class: `cpl_query.enumerable.enumerable_abc.EnumerableABC` to :class: `cpl_query.iterable.iterable_abc.IterableABC` @@ -95,12 +27,3 @@ class EnumerableABC(QueryableABC): """ from cpl_query.iterable.iterable import Iterable return Iterable(self._type, self.to_list()) - - def to_list(self) -> list: - r"""Converts :class: `cpl_query.base.sequence_abc.SequenceABC` to :class: `list` - - Returns - ------- - :class: `list` - """ - return [x for x in self] diff --git a/src/cpl_query/enumerable/ordered_enumerable.py b/src/cpl_query/enumerable/ordered_enumerable.py deleted file mode 100644 index 28628da0..00000000 --- a/src/cpl_query/enumerable/ordered_enumerable.py +++ /dev/null @@ -1,36 +0,0 @@ -from collections.abc import Callable -from typing import Iterable - -from cpl_query.enumerable.enumerable import Enumerable -from cpl_query.enumerable.ordered_enumerable_abc import OrderedEnumerableABC -from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument - - -class OrderedEnumerable(Enumerable, OrderedEnumerableABC): - r"""Implementation of :class: `cpl_query.extension.Enumerable` `cpl_query.extension.OrderedEnumerableABC` - """ - - def __init__(self, _t: type, _func: Callable = None, _values: Iterable = None): - Enumerable.__init__(self, _t) - OrderedEnumerableABC.__init__(self, _t, _func, _values) - - def then_by(self: OrderedEnumerableABC, _func: Callable) -> OrderedEnumerableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None: - raise ArgumentNoneException(ExceptionArgument.func) - - self._funcs.append(_func) - - return OrderedEnumerable(self.type, _func, sorted(self, key=lambda *args: [f(*args) for f in self._funcs])) - - def then_by_descending(self: OrderedEnumerableABC, _func: Callable) -> OrderedEnumerableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None: - raise ArgumentNoneException(ExceptionArgument.func) - - self._funcs.append(_func) - return OrderedEnumerable(self.type, _func, sorted(self, key=lambda *args: [f(*args) for f in self._funcs], reverse=True)) diff --git a/src/cpl_query/enumerable/ordered_enumerable_abc.py b/src/cpl_query/enumerable/ordered_enumerable_abc.py deleted file mode 100644 index ef83f07b..00000000 --- a/src/cpl_query/enumerable/ordered_enumerable_abc.py +++ /dev/null @@ -1,43 +0,0 @@ -from abc import abstractmethod -from collections.abc import Callable -from typing import Iterable - -from cpl_query.enumerable.enumerable_abc import EnumerableABC - - -class OrderedEnumerableABC(EnumerableABC): - - @abstractmethod - def __init__(self, _t: type, _func: Callable = None, _values: Iterable = None): - EnumerableABC.__init__(self, _t, _values) - self._funcs: list[Callable] = [] - if _func is not None: - self._funcs.append(_func) - - @abstractmethod - def then_by(self, func: Callable) -> 'OrderedEnumerableABC': - r"""Sorts OrderedList in ascending order by function - - Parameter - --------- - func: :class:`Callable` - - Returns - ------- - list of :class:`cpl_query.extension.OrderedEnumerableABC` - """ - pass - - @abstractmethod - def then_by_descending(self, func: Callable) -> 'OrderedEnumerableABC': - r"""Sorts OrderedList in descending order by function - - Parameter - --------- - func: :class:`Callable` - - Returns - ------- - list of :class:`cpl_query.extension.OrderedEnumerableABC` - """ - pass diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index d129a1c1..2f6ae095 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -23,8 +23,6 @@ from collections import namedtuple # imports: from .iterable_abc import IterableABC from .iterable import Iterable -from .ordered_iterable_abc import OrderedIterableABC -from .ordered_iterable import OrderedIterable VersionInfo = namedtuple('VersionInfo', 'major minor micro') version_info = VersionInfo(major='2022', minor='10', micro='0.post2') diff --git a/src/cpl_query/iterable/iterable.py b/src/cpl_query/iterable/iterable.py index 6f7ce73f..38367269 100644 --- a/src/cpl_query/iterable/iterable.py +++ b/src/cpl_query/iterable/iterable.py @@ -1,9 +1,6 @@ -from typing import Callable, Optional, Union, Iterable as IterableType +from typing import Iterable as IterableType -from cpl_query._helper import is_number -from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument, InvalidTypeException, IndexOutOfRangeException from cpl_query.iterable.iterable_abc import IterableABC -from cpl_query.iterable.ordered_iterable_abc import OrderedIterableABC def _default_lambda(x: object): @@ -14,251 +11,3 @@ class Iterable(IterableABC): def __init__(self, t: type = None, values: IterableType = None): IterableABC.__init__(self, t, values) - - def all(self, _func: Callable = None) -> bool: - if _func is None: - _func = _default_lambda - - return self.where(_func).count() == self.count() - - def any(self, _func: Callable = None) -> bool: - if _func is None: - _func = _default_lambda - - return self.where(_func).count() > 0 - - def average(self, _func: Callable = None) -> Union[int, float, complex]: - if _func is None and not is_number(self.type): - raise InvalidTypeException() - - return self.sum(_func) / self.count() - - def contains(self, _value: object) -> bool: - if _value is None: - raise ArgumentNoneException(ExceptionArgument.value) - - return self.where(lambda x: x == _value).count() > 0 - - def count(self, _func: Callable = None) -> int: - if _func is None: - return self.__len__() - - return self.where(_func).__len__() - - def distinct(self, _func: Callable = None) -> 'Iterable': - if _func is None: - _func = _default_lambda - - result = Iterable() - known_values = [] - for element in self: - value = _func(element) - if value in known_values: - continue - - known_values.append(value) - result.append(element) - - return result - - def element_at(self, _index: int) -> any: - if _index is None: - raise ArgumentNoneException(ExceptionArgument.index) - - return self[_index] - - def element_at_or_default(self, _index: int) -> any: - if _index is None: - raise ArgumentNoneException(ExceptionArgument.index) - - try: - return self[_index] - except IndexError: - return None - - def first(self) -> any: - if len(self) == 0: - raise IndexOutOfRangeException() - - return self[0] - - def first_or_default(self) -> Optional[any]: - if len(self) == 0: - return None - - return self[0] - - def group_by(self, _func: Callable = None) -> 'Iterable': - if _func is None: - _func = _default_lambda - groups = {} - - for v in self: - value = _func(v) - if v not in groups: - groups[value] = Iterable(type(v)) - - groups[value].append(v) - - return Iterable(Iterable).extend(groups.values()) - - def last(self) -> any: - if len(self) == 0: - raise IndexOutOfRangeException() - - return self[len(self) - 1] - - def last_or_default(self) -> Optional[any]: - if len(self) == 0: - return None - - return self[len(self) - 1] - - def for_each(self, _func: Callable = None) -> 'Iterable': - if _func is not None: - for element in self: - _func(element) - - return self - - def max(self, _func: Callable = None) -> Union[int, float, complex]: - if _func is None and not is_number(self.type): - raise InvalidTypeException() - - if _func is None: - _func = _default_lambda - - return _func(max(self, key=_func)) - - def median(self, _func=None) -> Union[int, float]: - if _func is None: - _func = _default_lambda - - result = self.order_by(_func).select(_func).to_list() - length = len(result) - i = int(length / 2) - return ( - result[i] - if length % 2 == 1 - else (float(result[i - 1]) + float(result[i])) / float(2) - ) - - def min(self, _func: Callable = None) -> Union[int, float, complex]: - if _func is None and not is_number(self.type): - raise InvalidTypeException() - - if _func is None: - _func = _default_lambda - - return _func(min(self, key=_func)) - - def order_by(self, _func: Callable = None) -> OrderedIterableABC: - if _func is None: - _func = _default_lambda - - from cpl_query.iterable.ordered_iterable import OrderedIterable - return OrderedIterable(self.type, _func, sorted(self, key=_func)) - - def order_by_descending(self, _func: Callable = None) -> OrderedIterableABC: - if _func is None: - _func = _default_lambda - - from cpl_query.iterable.ordered_iterable import OrderedIterable - return OrderedIterable(self.type, _func, sorted(self, key=_func, reverse=True)) - - def reverse(self) -> 'Iterable': - return Iterable().extend(reversed(self)) - - def select(self, _func: Callable = None) -> 'Iterable': - if _func is None: - _func = _default_lambda - - result = Iterable() - result.extend(_func(_o) for _o in self) - return result - - def select_many(self, _func: Callable = None) -> 'Iterable': - result = Iterable() - # The line below is pain. I don't understand anything of it... - # written on 09.11.2022 by Sven Heidemann - elements = [_a for _o in self for _a in _func(_o)] - - result.extend(elements) - return result - - def single(self) -> any: - if len(self) > 1: - raise Exception('Found more than one element') - elif len(self) == 0: - raise Exception('Found no element') - - return self[0] - - def single_or_default(self) -> Optional[any]: - if len(self) > 1: - raise Exception('Index out of range') - elif len(self) == 0: - return None - - return self[0] - - def skip(self, _index: int) -> 'Iterable': - if _index is None: - raise ArgumentNoneException(ExceptionArgument.index) - - return Iterable(self.type, values=self[_index:]) - - def skip_last(self, _index: int) -> 'Iterable': - if _index is None: - raise ArgumentNoneException(ExceptionArgument.index) - - index = len(self) - _index - - result = Iterable() - result.extend(self[:index]) - return result - - def sum(self, _func: Callable = None) -> Union[int, float, complex]: - if _func is None and not is_number(self.type): - raise InvalidTypeException() - - if _func is None: - _func = _default_lambda - - result = 0 - for x in self: - result += _func(x) - - return result - - def take(self, _index: int) -> 'Iterable': - if _index is None: - raise ArgumentNoneException(ExceptionArgument.index) - - result = Iterable() - result.extend(self[:_index]) - return result - - def take_last(self, _index: int) -> 'Iterable': - index = len(self) - _index - - if index >= len(self) or index < 0: - raise IndexOutOfRangeException() - - result = Iterable() - result.extend(self[index:]) - return result - - def where(self, _func: Callable = None) -> 'Iterable': - if _func is None: - raise ArgumentNoneException(ExceptionArgument.func) - - if _func is None: - _func = _default_lambda - - result = Iterable(self.type) - for element in self: - if _func(element): - result.append(element) - - return result diff --git a/src/cpl_query/iterable/iterable_abc.py b/src/cpl_query/iterable/iterable_abc.py index 5c6c47db..dcae50b3 100644 --- a/src/cpl_query/iterable/iterable_abc.py +++ b/src/cpl_query/iterable/iterable_abc.py @@ -4,54 +4,45 @@ from typing import Iterable from cpl_query.base.queryable_abc import QueryableABC -class IterableABC(list, QueryableABC): +class IterableABC(QueryableABC): r"""ABC to define functions on list """ @abstractmethod def __init__(self, t: type = None, values: Iterable = None): - values = [] if values is None else values - list.__init__(self, values) + QueryableABC.__init__(self, t, values) - if t is None and len(values) > 0: - t = type(values[0]) + def __setitem__(self, i, val): + self._check_type(val) + values = [*self._values] + values[i] = val + self._set_values(values) - self._type = t - - def __repr__(self): - return f'<{type(self).__name__} {list(self).__repr__()}>' + def __delitem__(self, i): + values = [*self._values] + del values[i] + self._set_values(values) @property def type(self) -> type: return self._type - def to_list(self) -> list: - r"""Converts :class: `cpl_query.base.sequence_abc.SequenceABC` to :class: `list` - - Returns - ------- - :class: `list` - """ - return [x for x in self] - def __str__(self): return str(self.to_list()) - def append(self, __object: object) -> None: + def append(self, _object: object): + self.add(_object) + + def add(self, _object: object): r"""Adds element to list Parameter --------- - __object: :class:`object` + _object: :class:`object` value """ - if self._type is not None and type(__object) != self._type and not isinstance(type(__object), self._type) and not issubclass(type(__object), self._type): - raise Exception(f'Unexpected type: {type(__object)}\nExpected type: {self._type}') - - if len(self) == 0 and self._type is None: - self._type = type(__object) - - # self._values = SequenceValues([*self._values, __object], self._type) - super().append(__object) + self._check_type(_object) + values = [*self._values, _object] + self._set_values(values) def extend(self, __iterable: Iterable) -> 'IterableABC': r"""Adds elements of given list to list diff --git a/src/cpl_query/iterable/ordered_iterable.py b/src/cpl_query/iterable/ordered_iterable.py deleted file mode 100644 index 9fe50079..00000000 --- a/src/cpl_query/iterable/ordered_iterable.py +++ /dev/null @@ -1,35 +0,0 @@ -from collections.abc import Callable - -from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument -from cpl_query.iterable.iterable import Iterable -from cpl_query.iterable.ordered_iterable_abc import OrderedIterableABC - - -class OrderedIterable(Iterable, OrderedIterableABC): - r"""Implementation of :class: `cpl_query.extension.Iterable` `cpl_query.extension.OrderedIterableABC` - """ - - def __init__(self, _t: type, _func: Callable = None, _values: Iterable = None): - Iterable.__init__(self, _t) - OrderedIterableABC.__init__(self, _t, _func, _values) - - def then_by(self: OrderedIterableABC, _func: Callable) -> OrderedIterableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None: - raise ArgumentNoneException(ExceptionArgument.func) - - self._funcs.append(_func) - - return OrderedIterable(self.type, _func, sorted(self, key=lambda *args: [f(*args) for f in self._funcs])) - - def then_by_descending(self: OrderedIterableABC, _func: Callable) -> OrderedIterableABC: - if self is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if _func is None: - raise ArgumentNoneException(ExceptionArgument.func) - - self._funcs.append(_func) - return OrderedIterable(self.type, _func, sorted(self, key=lambda *args: [f(*args) for f in self._funcs], reverse=True)) diff --git a/unittests/unittests_cli/constants.py b/unittests/unittests_cli/constants.py index c8318dab..13986be9 100644 --- a/unittests/unittests_cli/constants.py +++ b/unittests/unittests_cli/constants.py @@ -6,4 +6,4 @@ if not os.getcwd().endswith('unittests'): PLAYGROUND_PATH = os.path.abspath(os.path.join(os.getcwd(), f'{base}test_cli_playground')) TRANSLATION_PATH = os.path.abspath(os.path.join(os.getcwd(), f'{base}unittests_translation')) -CLI_PATH = os.path.abspath(os.path.join(os.getcwd(), f'{base}../src/cpl_cli/main.py')) +CLI_PATH = os.path.abspath(os.path.join(os.getcwd(), f'../../src/cpl_cli/main.py')) diff --git a/unittests/unittests_query/enumerable_query_test_case.py b/unittests/unittests_query/enumerable_query_test_case.py index d95275e0..ffe71576 100644 --- a/unittests/unittests_query/enumerable_query_test_case.py +++ b/unittests/unittests_query/enumerable_query_test_case.py @@ -11,7 +11,16 @@ from unittests_query.models import User, Address class EnumerableQueryTestCase(unittest.TestCase): def setUp(self) -> None: - self._tests = Enumerable(User) + users = [] + for i in range(0, 100): + users.append(User( + String.random_string(string.ascii_letters, 8).lower(), + Address( + String.random_string(string.ascii_letters, 10).lower(), + randint(1, 10) + ) + )) + self._t_user = User( 'Test user', Address( @@ -27,22 +36,10 @@ class EnumerableQueryTestCase(unittest.TestCase): ) ) - self._generate_test_data() + users.append(self._t_user) + users.append(self._t_user2) - def _generate_test_data(self): - for i in range(0, 100): - user = User( - String.random_string(string.ascii_letters, 8).lower(), - Address( - String.random_string(string.ascii_letters, 10).lower(), - randint(1, 10) - ) - ) - - self._tests.add(user) - - self._tests.add(self._t_user) - self._tests.add(self._t_user2) + self._tests = Enumerable(User, users) def test_any(self): results = [] diff --git a/unittests/unittests_query/enumerable_test_case.py b/unittests/unittests_query/enumerable_test_case.py index 60fe056e..b8605493 100644 --- a/unittests/unittests_query/enumerable_test_case.py +++ b/unittests/unittests_query/enumerable_test_case.py @@ -6,17 +6,9 @@ from cpl_query.enumerable.enumerable import Enumerable class EnumerableTestCase(unittest.TestCase): def setUp(self) -> None: - self._list = Enumerable(int) - - def _clear(self): - self._list.clear() - self.assertEqual(self._list, []) + self._list = Enumerable(int, list(range(1, 4))) def test_append(self): - self._list.add(1) - self._list.add(2) - self._list.add(3) - self.assertEqual(self._list.to_list(), [1, 2, 3]) self.assertRaises(Exception, lambda v: self._list.add(v), '3') @@ -38,30 +30,7 @@ class EnumerableTestCase(unittest.TestCase): n += 1 def test_get(self): - self._list.add(1) - self._list.add(2) - self._list.add(3) - self.assertEqual(self._list.element_at(2), [1, 2, 3][2]) def test_count(self): - self._list.add(1) - self._list.add(2) - self._list.add(3) - self.assertEqual(self._list.count(), 3) - - def test_remove(self): - old_values = self._list._values - self._list.add(1) - self.assertNotEqual(old_values, self._list._values) - self._list.add(2) - self._list.add(3) - - self.assertEqual(self._list.to_list(), [1, 2, 3]) - self.assertRaises(Exception, lambda v: self._list.add(v), '3') - old_values = self._list._values - self._list.remove(3) - self.assertNotEqual(old_values, self._list._values) - self.assertEqual(self._list.to_list(), [1, 2]) - self.assertRaises(Exception, lambda v: self._list.add(v), '3') diff --git a/unittests/unittests_query/iterable_query_test_case.py b/unittests/unittests_query/iterable_query_test_case.py index c48fc9ea..8ea3a0b8 100644 --- a/unittests/unittests_query/iterable_query_test_case.py +++ b/unittests/unittests_query/iterable_query_test_case.py @@ -113,7 +113,7 @@ class IterableQueryTestCase(unittest.TestCase): addresses.append(u.address.nr) - res2 = self._tests.distinct(lambda x: x.address.nr).select(lambda x: x.address.nr) + res2 = self._tests.distinct(lambda x: x.address.nr).select(lambda x: x.address.nr).to_list() self.assertEqual(addresses, res2) def test_element_at(self): @@ -199,7 +199,7 @@ class IterableQueryTestCase(unittest.TestCase): groups[v].append(v) elements.append(v) - r1, r2 = list(groups.values()), elements.group_by() + r1, r2 = list(groups.values()), elements.group_by().select(lambda l: l.to_list()).to_list() self.assertEqual(r1, r2) def test_for_each(self): diff --git a/unittests/unittests_query/models.py b/unittests/unittests_query/models.py index d3b147dd..54c9522c 100644 --- a/unittests/unittests_query/models.py +++ b/unittests/unittests_query/models.py @@ -4,9 +4,15 @@ class User: self.name = name self.address = address + def __repr__(self): + return f'<{type(self).__name__} {self.name} {self.address}>' + class Address: def __init__(self, street, nr): self.street = street - self.nr = nr \ No newline at end of file + self.nr = nr + + def __repr__(self): + return f'<{type(self).__name__} {self.street} {self.nr}>' -- 2.45.1 From 2840628443584c18a2a016ac3419612c142c2e36 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 1 Dec 2022 23:23:48 +0100 Subject: [PATCH 14/63] Improved tests #129 --- unittests/unittests_cli/abc/__init__.py | 0 .../unittests_cli/abc/command_test_case.py | 35 +++++++++++++++++++ unittests/unittests_cli/add_test_case.py | 20 +++-------- unittests/unittests_cli/build_test_case.py | 16 +++------ unittests/unittests_cli/cli_test_suite.py | 5 +++ unittests/unittests_cli/constants.py | 2 +- unittests/unittests_cli/custom_test_case.py | 4 +-- unittests/unittests_cli/generate_test_case.py | 5 +-- unittests/unittests_cli/install_test_case.py | 14 +++----- unittests/unittests_cli/new_test_case.py | 14 +++----- unittests/unittests_cli/publish_test_case.py | 14 +++----- unittests/unittests_cli/remove_test_case.py | 7 ++-- unittests/unittests_cli/run_test_case.py | 19 +++------- unittests/unittests_cli/start_test_case.py | 14 +++----- .../unittests_cli/uninstall_test_case.py | 16 +++------ unittests/unittests_cli/update_test_case.py | 34 +++++++----------- unittests/unittests_cli/version_test_case.py | 7 ++-- unittests/unittests_shared/cli_commands.py | 4 ++- .../translation_test_suite.py | 26 -------------- 19 files changed, 103 insertions(+), 153 deletions(-) create mode 100644 unittests/unittests_cli/abc/__init__.py create mode 100644 unittests/unittests_cli/abc/command_test_case.py diff --git a/unittests/unittests_cli/abc/__init__.py b/unittests/unittests_cli/abc/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/unittests/unittests_cli/abc/command_test_case.py b/unittests/unittests_cli/abc/command_test_case.py new file mode 100644 index 00000000..3b609cab --- /dev/null +++ b/unittests/unittests_cli/abc/command_test_case.py @@ -0,0 +1,35 @@ +import os +import shutil +import traceback +import unittest + +from unittests_cli.constants import PLAYGROUND_PATH + + +class CommandTestCase(unittest.TestCase): + + def __init__(self, method_name: str): + unittest.TestCase.__init__(self, method_name) + + @classmethod + def setUpClass(cls): + + try: + if os.path.exists(PLAYGROUND_PATH): + shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH))) + + os.makedirs(PLAYGROUND_PATH) + os.chdir(PLAYGROUND_PATH) + except Exception as e: + print(f'Setup of {__name__} failed: {traceback.format_exc()}') + + def setUp(self): + os.chdir(PLAYGROUND_PATH) + + @classmethod + def tearDownClass(cls): + try: + if os.path.exists(PLAYGROUND_PATH): + shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH))) + except Exception as e: + print(f'Cleanup of {__name__} failed: {traceback.format_exc()}') diff --git a/unittests/unittests_cli/add_test_case.py b/unittests/unittests_cli/add_test_case.py index d1b64503..18efb1bd 100644 --- a/unittests/unittests_cli/add_test_case.py +++ b/unittests/unittests_cli/add_test_case.py @@ -1,18 +1,16 @@ import json import os -import shutil -import unittest from cpl_core.utils import String - +from unittests_cli.abc.command_test_case import CommandTestCase from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands -class AddTestCase(unittest.TestCase): +class AddTestCase(CommandTestCase): - def __init__(self, methodName: str): - unittest.TestCase.__init__(self, methodName) + def __init__(self, method_name: str): + CommandTestCase.__init__(self, method_name) self._source = 'add-test-project' self._target = 'add-test-library' self._project_file = f'src/{String.convert_to_snake_case(self._source)}/{self._source}.json' @@ -26,22 +24,12 @@ class AddTestCase(unittest.TestCase): return project_json def setUp(self): - if not os.path.exists(PLAYGROUND_PATH): - os.makedirs(PLAYGROUND_PATH) - os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) CLICommands.new('console', self._target, '--ab', '--s') - def cleanUp(self): - # remove projects - if not os.path.exists(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))): - return - - shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))) - def test_add(self): CLICommands.add(self._source, self._target) settings = self._get_project_settings() diff --git a/unittests/unittests_cli/build_test_case.py b/unittests/unittests_cli/build_test_case.py index d01de06f..a0117712 100644 --- a/unittests/unittests_cli/build_test_case.py +++ b/unittests/unittests_cli/build_test_case.py @@ -2,18 +2,17 @@ import filecmp import json import os import shutil -import unittest from cpl_core.utils import String - +from unittests_cli.abc.command_test_case import CommandTestCase from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands -class BuildTestCase(unittest.TestCase): +class BuildTestCase(CommandTestCase): - def __init__(self, methodName: str): - unittest.TestCase.__init__(self, methodName) + def __init__(self, method_name: str): + CommandTestCase.__init__(self, method_name) self._source = 'build-test-source' self._project_file = f'src/{String.convert_to_snake_case(self._source)}/{self._source}.json' @@ -39,13 +38,6 @@ class BuildTestCase(unittest.TestCase): CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) - def cleanUp(self): - # remove projects - if not os.path.exists(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))): - return - - shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))) - def _are_dir_trees_equal(self, dir1, dir2): """ found at https://stackoverflow.com/questions/4187564/recursively-compare-two-directories-to-ensure-they-have-the-same-files-and-subdi diff --git a/unittests/unittests_cli/cli_test_suite.py b/unittests/unittests_cli/cli_test_suite.py index 228fa366..9ca8b469 100644 --- a/unittests/unittests_cli/cli_test_suite.py +++ b/unittests/unittests_cli/cli_test_suite.py @@ -76,3 +76,8 @@ class CLITestSuite(unittest.TestSuite): self._setup() self._result = super().run(*args) self._cleanup() + + +if __name__ == "__main__": + runner = unittest.TextTestRunner() + runner.run(CLITestSuite()) diff --git a/unittests/unittests_cli/constants.py b/unittests/unittests_cli/constants.py index 13986be9..c8318dab 100644 --- a/unittests/unittests_cli/constants.py +++ b/unittests/unittests_cli/constants.py @@ -6,4 +6,4 @@ if not os.getcwd().endswith('unittests'): PLAYGROUND_PATH = os.path.abspath(os.path.join(os.getcwd(), f'{base}test_cli_playground')) TRANSLATION_PATH = os.path.abspath(os.path.join(os.getcwd(), f'{base}unittests_translation')) -CLI_PATH = os.path.abspath(os.path.join(os.getcwd(), f'../../src/cpl_cli/main.py')) +CLI_PATH = os.path.abspath(os.path.join(os.getcwd(), f'{base}../src/cpl_cli/main.py')) diff --git a/unittests/unittests_cli/custom_test_case.py b/unittests/unittests_cli/custom_test_case.py index db59be7d..9088cc44 100644 --- a/unittests/unittests_cli/custom_test_case.py +++ b/unittests/unittests_cli/custom_test_case.py @@ -1,7 +1,7 @@ -import unittest +from unittests_cli.abc.command_test_case import CommandTestCase -class CustomTestCase(unittest.TestCase): +class CustomTestCase(CommandTestCase): def setUp(self): pass diff --git a/unittests/unittests_cli/generate_test_case.py b/unittests/unittests_cli/generate_test_case.py index c53f28d5..cba7d8a7 100644 --- a/unittests/unittests_cli/generate_test_case.py +++ b/unittests/unittests_cli/generate_test_case.py @@ -1,17 +1,18 @@ import os.path -import unittest from cpl_core.utils import String +from unittests_cli.abc.command_test_case import CommandTestCase from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands -class GenerateTestCase(unittest.TestCase): +class GenerateTestCase(CommandTestCase): _project = 'test-console' _t_path = 'test' @classmethod def setUpClass(cls): + CommandTestCase.setUpClass() CLICommands.new('console', cls._project, '--ab', '--s', '--venv') def setUp(self): diff --git a/unittests/unittests_cli/install_test_case.py b/unittests/unittests_cli/install_test_case.py index 516a44e4..eaa2a367 100644 --- a/unittests/unittests_cli/install_test_case.py +++ b/unittests/unittests_cli/install_test_case.py @@ -6,14 +6,15 @@ import sys import unittest from cpl_core.utils import String +from unittests_cli.abc.command_test_case import CommandTestCase from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands -class InstallTestCase(unittest.TestCase): +class InstallTestCase(CommandTestCase): - def __init__(self, methodName: str): - unittest.TestCase.__init__(self, methodName) + def __init__(self, method_name: str): + CommandTestCase.__init__(self, method_name) self._source = 'install-test-source' self._project_file = f'src/{String.convert_to_snake_case(self._source)}/{self._source}.json' @@ -39,13 +40,6 @@ class InstallTestCase(unittest.TestCase): CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) - def cleanUp(self): - # remove projects - if not os.path.exists(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))): - return - - shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))) - def _get_installed_packages(self) -> dict: reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze']) return dict([tuple(r.decode().split('==')) for r in reqs.split()]) diff --git a/unittests/unittests_cli/new_test_case.py b/unittests/unittests_cli/new_test_case.py index 5d0eb0a3..21191333 100644 --- a/unittests/unittests_cli/new_test_case.py +++ b/unittests/unittests_cli/new_test_case.py @@ -1,19 +1,16 @@ import json import os -import unittest from cpl_core.utils import String +from unittests_cli.abc.command_test_case import CommandTestCase from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands -class NewTestCase(unittest.TestCase): +class NewTestCase(CommandTestCase): - def setUp(self): - if not os.path.exists(PLAYGROUND_PATH): - os.makedirs(PLAYGROUND_PATH) - - os.chdir(PLAYGROUND_PATH) + def __init__(self, method_name: str): + CommandTestCase.__init__(self, method_name) def _test_project(self, project_type: str, name: str, *args, test_venv=False, without_ws=False): CLICommands.new(project_type, name, *args) @@ -73,7 +70,6 @@ class NewTestCase(unittest.TestCase): project_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, workspace_name, base, String.convert_to_snake_case(name))) self.assertTrue(os.path.exists(project_path)) self.assertTrue(os.path.join(project_path, f'{name}.json')) - os.chdir(os.path.abspath(os.path.join(os.getcwd(), '../'))) def _test_sub_directory_project(self, project_type: str, directory: str, name: str, workspace_name: str, *args): os.chdir(os.path.abspath(os.path.join(os.getcwd(), workspace_name))) @@ -99,8 +95,6 @@ class NewTestCase(unittest.TestCase): self.assertEqual(build_settings['Main'], f'{String.convert_to_snake_case(name)}.main') self.assertEqual(build_settings['EntryPoint'], name) - os.chdir(os.path.abspath(os.path.join(os.getcwd(), '../'))) - def test_console(self): self._test_project('console', 'test-console', '--ab', '--s', '--venv', test_venv=True) diff --git a/unittests/unittests_cli/publish_test_case.py b/unittests/unittests_cli/publish_test_case.py index 141e374e..9992626b 100644 --- a/unittests/unittests_cli/publish_test_case.py +++ b/unittests/unittests_cli/publish_test_case.py @@ -5,15 +5,16 @@ import shutil import unittest from cpl_core.utils import String +from unittests_cli.abc.command_test_case import CommandTestCase from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands -class PublishTestCase(unittest.TestCase): +class PublishTestCase(CommandTestCase): - def __init__(self, methodName: str): - unittest.TestCase.__init__(self, methodName) + def __init__(self, method_name: str): + CommandTestCase.__init__(self, method_name) self._source = 'publish-test-source' self._project_file = f'src/{String.convert_to_snake_case(self._source)}/{self._source}.json' @@ -39,13 +40,6 @@ class PublishTestCase(unittest.TestCase): CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) - def cleanUp(self): - # remove projects - if not os.path.exists(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))): - return - - shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))) - def _are_dir_trees_equal(self, dir1, dir2): """ found at https://stackoverflow.com/questions/4187564/recursively-compare-two-directories-to-ensure-they-have-the-same-files-and-subdi diff --git a/unittests/unittests_cli/remove_test_case.py b/unittests/unittests_cli/remove_test_case.py index f618e4b8..ac2732f3 100644 --- a/unittests/unittests_cli/remove_test_case.py +++ b/unittests/unittests_cli/remove_test_case.py @@ -3,14 +3,15 @@ import os import unittest from cpl_core.utils import String +from unittests_cli.abc.command_test_case import CommandTestCase from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands -class RemoveTestCase(unittest.TestCase): +class RemoveTestCase(CommandTestCase): - def __init__(self, methodName: str): - unittest.TestCase.__init__(self, methodName) + def __init__(self, method_name: str): + CommandTestCase.__init__(self, method_name) self._source = 'add-test-project' self._target = 'add-test-library' self._project_file = f'src/{String.convert_to_snake_case(self._source)}/{self._source}.json' diff --git a/unittests/unittests_cli/run_test_case.py b/unittests/unittests_cli/run_test_case.py index 7ec9b9dd..23841a79 100644 --- a/unittests/unittests_cli/run_test_case.py +++ b/unittests/unittests_cli/run_test_case.py @@ -1,22 +1,18 @@ import json import os import shutil -import subprocess -import sys import unittest -import pkg_resources - from cpl_core.utils import String - +from unittests_cli.abc.command_test_case import CommandTestCase from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands -class RunTestCase(unittest.TestCase): +class RunTestCase(CommandTestCase): - def __init__(self, methodName: str): - unittest.TestCase.__init__(self, methodName) + def __init__(self, method_name: str): + CommandTestCase.__init__(self, method_name) self._source = 'run-test' self._project_file = f'src/{String.convert_to_snake_case(self._source)}/{self._source}.json' self._appsettings = f'src/{String.convert_to_snake_case(self._source)}/appsettings.json' @@ -63,13 +59,6 @@ class RunTestCase(unittest.TestCase): file.write(f'\t\t{self._test_code}') file.close() - def cleanUp(self): - # remove projects - if not os.path.exists(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))): - return - - shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))) - def test_run(self): CLICommands.run() settings = self._get_appsettings() diff --git a/unittests/unittests_cli/start_test_case.py b/unittests/unittests_cli/start_test_case.py index 3ff09294..b0949f14 100644 --- a/unittests/unittests_cli/start_test_case.py +++ b/unittests/unittests_cli/start_test_case.py @@ -5,15 +5,16 @@ import time import unittest from cpl_core.utils import String +from unittests_cli.abc.command_test_case import CommandTestCase from unittests_cli.constants import PLAYGROUND_PATH from unittests_cli.threads.start_test_thread import StartTestThread from unittests_shared.cli_commands import CLICommands -class StartTestCase(unittest.TestCase): +class StartTestCase(CommandTestCase): - def __init__(self, methodName: str): - unittest.TestCase.__init__(self, methodName) + def __init__(self, method_name: str): + CommandTestCase.__init__(self, method_name) self._source = 'start-test' self._project_file = f'src/{String.convert_to_snake_case(self._source)}/{self._source}.json' self._appsettings = f'src/{String.convert_to_snake_case(self._source)}/appsettings.json' @@ -63,13 +64,6 @@ class StartTestCase(unittest.TestCase): file.write(f'\t\t{self._test_code}') file.close() - def cleanUp(self): - # remove projects - if not os.path.exists(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))): - return - - shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))) - def test_start(self): thread = StartTestThread() thread.start() diff --git a/unittests/unittests_cli/uninstall_test_case.py b/unittests/unittests_cli/uninstall_test_case.py index a552bfc2..b61dfafa 100644 --- a/unittests/unittests_cli/uninstall_test_case.py +++ b/unittests/unittests_cli/uninstall_test_case.py @@ -6,14 +6,15 @@ import sys import unittest from cpl_core.utils import String +from unittests_cli.abc.command_test_case import CommandTestCase from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands -class UninstallTestCase(unittest.TestCase): +class UninstallTestCase(CommandTestCase): - def __init__(self, methodName: str): - unittest.TestCase.__init__(self, methodName) + def __init__(self, method_name: str): + CommandTestCase.__init__(self, method_name) self._source = 'uninstall-test-source' self._project_file = f'src/{String.convert_to_snake_case(self._source)}/{self._source}.json' self._version = '1.7.3' @@ -31,19 +32,12 @@ class UninstallTestCase(unittest.TestCase): def setUp(self): if not os.path.exists(PLAYGROUND_PATH): os.makedirs(PLAYGROUND_PATH) - + os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) - def cleanUp(self): - # remove projects - if not os.path.exists(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))): - return - - shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))) - def _get_installed_packages(self) -> dict: reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze']) return dict([tuple(r.decode().split('==')) for r in reqs.split()]) diff --git a/unittests/unittests_cli/update_test_case.py b/unittests/unittests_cli/update_test_case.py index 3b50b38c..b6e40243 100644 --- a/unittests/unittests_cli/update_test_case.py +++ b/unittests/unittests_cli/update_test_case.py @@ -6,14 +6,15 @@ import sys import unittest from cpl_core.utils import String +from unittests_cli.abc.command_test_case import CommandTestCase from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands -class UpdateTestCase(unittest.TestCase): +class UpdateTestCase(CommandTestCase): - def __init__(self, methodName: str): - unittest.TestCase.__init__(self, methodName) + def __init__(self, method_name: str): + CommandTestCase.__init__(self, method_name) self._source = 'install-test-source' self._project_file = f'src/{String.convert_to_snake_case(self._source)}/{self._source}.json' @@ -26,6 +27,15 @@ class UpdateTestCase(unittest.TestCase): self._new_package_name = 'discord.py' self._new_package = f'{self._new_package_name}=={self._new_version}' + def setUp(self): + CLICommands.uninstall(self._old_package) + CLICommands.uninstall(self._new_package) + os.chdir(PLAYGROUND_PATH) + # create projects + CLICommands.new('console', self._source, '--ab', '--s') + os.chdir(os.path.join(os.getcwd(), self._source)) + CLICommands.install(self._old_package) + def _get_project_settings(self): with open(os.path.join(os.getcwd(), self._project_file), 'r', encoding='utf-8') as cfg: # load json @@ -39,22 +49,6 @@ class UpdateTestCase(unittest.TestCase): project_file.write(json.dumps(settings, indent=2)) project_file.close() - def setUp(self): - CLICommands.uninstall(self._old_package) - CLICommands.uninstall(self._new_package) - os.chdir(os.path.abspath(PLAYGROUND_PATH)) - # create projects - CLICommands.new('console', self._source, '--ab', '--s') - os.chdir(os.path.join(os.getcwd(), self._source)) - CLICommands.install(self._old_package) - - def cleanUp(self): - # remove projects - if not os.path.exists(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))): - return - - shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH, self._source))) - def _get_installed_packages(self) -> dict: reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze']) return dict([tuple(r.decode().split('==')) for r in reqs.split()]) @@ -85,5 +79,3 @@ class UpdateTestCase(unittest.TestCase): packages = self._get_installed_packages() self.assertIn(self._new_package_name, packages) self.assertEqual(self._new_version, packages[self._new_package_name]) - - diff --git a/unittests/unittests_cli/version_test_case.py b/unittests/unittests_cli/version_test_case.py index 18e63b14..d409db77 100644 --- a/unittests/unittests_cli/version_test_case.py +++ b/unittests/unittests_cli/version_test_case.py @@ -12,13 +12,14 @@ import cpl_cli from cpl_core.console import ForegroundColorEnum from termcolor import colored +from unittests_cli.abc.command_test_case import CommandTestCase from unittests_shared.cli_commands import CLICommands -class VersionTestCase(unittest.TestCase): +class VersionTestCase(CommandTestCase): - def __init__(self, methodName: str): - unittest.TestCase.__init__(self, methodName) + def __init__(self, method_name: str): + CommandTestCase.__init__(self, method_name) self._block_banner = "" self._block_version = "" self._block_package_header = "" diff --git a/unittests/unittests_shared/cli_commands.py b/unittests/unittests_shared/cli_commands.py index 8ca6ccfc..ee7821f4 100644 --- a/unittests/unittests_shared/cli_commands.py +++ b/unittests/unittests_shared/cli_commands.py @@ -1,5 +1,6 @@ import os import subprocess +import sys from unittests_cli.constants import CLI_PATH @@ -29,7 +30,8 @@ class CLICommands: for arg in args: command.append(arg) - return subprocess.run(command, env=env_vars, check=True, capture_output=True, text=True).stdout + with subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True) as process: + return process.stdout.read() @classmethod def add(cls, source: str, target: str, output=False): diff --git a/unittests/unittests_translation/translation_test_suite.py b/unittests/unittests_translation/translation_test_suite.py index f1e15132..f0d5a3da 100644 --- a/unittests/unittests_translation/translation_test_suite.py +++ b/unittests/unittests_translation/translation_test_suite.py @@ -1,11 +1,7 @@ -import os -import shutil -import traceback import unittest from typing import Optional from unittest import TestResult -from unittests_cli.constants import PLAYGROUND_PATH from unittests_translation.translation_test_case import TranslationTestCase @@ -25,27 +21,5 @@ class TranslationTestSuite(unittest.TestSuite): for test in active_tests: self.addTests(loader.loadTestsFromTestCase(test)) - def _setup(self): - try: - if os.path.exists(PLAYGROUND_PATH): - shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH))) - - os.makedirs(PLAYGROUND_PATH) - os.chdir(PLAYGROUND_PATH) - except Exception as e: - print(f'Setup of {__name__} failed: {traceback.format_exc()}') - - def _cleanup(self): - try: - if self._result is not None and (len(self._result.errors) > 0 or len(self._result.failures) > 0): - return - - if os.path.exists(PLAYGROUND_PATH): - shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH))) - except Exception as e: - print(f'Cleanup of {__name__} failed: {traceback.format_exc()}') - def run(self, *args): - self._setup() self._result = super().run(*args) - self._cleanup() -- 2.45.1 From 2fe3912a07409abdc641cc9e25399a840f41938d Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 1 Dec 2022 23:34:00 +0100 Subject: [PATCH 15/63] Fixed version test #129 --- unittests/unittests_shared/cli_commands.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/unittests/unittests_shared/cli_commands.py b/unittests/unittests_shared/cli_commands.py index ee7821f4..eb0f2f1f 100644 --- a/unittests/unittests_shared/cli_commands.py +++ b/unittests/unittests_shared/cli_commands.py @@ -24,14 +24,13 @@ class CLICommands: @staticmethod def _run_with_output(cmd: str, *args) -> str: env_vars = os.environ - # env_vars['CPL_IS_UNITTEST'] = 'NO' + env_vars['CPL_IS_UNITTEST'] = 'NO' command = ['python', CLI_PATH, cmd] for arg in args: command.append(arg) - with subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True) as process: - return process.stdout.read() + return subprocess.run(command, env=env_vars, check=True, capture_output=True, text=True).stdout @classmethod def add(cls, source: str, target: str, output=False): -- 2.45.1 From 05bd5e859366c303a7693182292462321b7216ca Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 1 Dec 2022 23:41:06 +0100 Subject: [PATCH 16/63] Improved query performance test #129 --- unittests/unittests_query/performance_test_case.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/unittests/unittests_query/performance_test_case.py b/unittests/unittests_query/performance_test_case.py index 904cc4e9..d3f9c205 100644 --- a/unittests/unittests_query/performance_test_case.py +++ b/unittests/unittests_query/performance_test_case.py @@ -19,9 +19,9 @@ class PerformanceTestCase(unittest.TestCase): i += 1 def test_range(self): - default = timeit.timeit(lambda: list(self.values), number=COUNT) - enumerable = timeit.timeit(lambda: Enumerable(int, self.values), number=COUNT) - iterable = timeit.timeit(lambda: Iterable(int, self.values), number=COUNT) + default = timeit.timeit(lambda: list(range(0, VALUES)), number=COUNT) + iterable = timeit.timeit(lambda: Iterable.range(0, VALUES), number=COUNT) + enumerable = timeit.timeit(lambda: Enumerable.range(0, VALUES), number=COUNT) print('Range') print(f'd: {default}s') @@ -32,9 +32,9 @@ class PerformanceTestCase(unittest.TestCase): self.assertLess(default, iterable) def test_where_single(self): - default = timeit.timeit(lambda: [x for x in list(self.values) if x == 50], number=COUNT) - iterable = timeit.timeit(lambda: Iterable(int, self.values).where(lambda x: x == 50).single(), number=COUNT) - enumerable = timeit.timeit(lambda: Enumerable(int, self.values).where(lambda x: x == 50).single(), number=COUNT) + default = timeit.timeit(lambda: [x for x in list(range(0, VALUES)) if x == 50], number=COUNT) + iterable = timeit.timeit(lambda: Iterable.range(0, VALUES).where(lambda x: x == 50).single(), number=COUNT) + enumerable = timeit.timeit(lambda: Enumerable.range(0, VALUES).where(lambda x: x == 50).single(), number=COUNT) print('Where single') print(f'd: {default}s') @@ -55,7 +55,7 @@ class PerformanceTestCase(unittest.TestCase): for i in range(VALUES): values.append(TestModel(i, TestModel(i + 1))) - default = timeit.timeit(lambda: [x for x in list(values) if x.tm.value == 50], number=COUNT) + default = timeit.timeit(lambda: [x for x in values if x.tm.value == 50], number=COUNT) iterable = timeit.timeit(lambda: Iterable(TestModel, values).where(lambda x: x.tm.value == 50).single(), number=COUNT) enumerable = timeit.timeit(lambda: Enumerable(TestModel, values).where(lambda x: x.tm.value == 50).single(), number=COUNT) -- 2.45.1 From 3c20ab296a70f4a1424c11e4192af74d838dd1c1 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Fri, 2 Dec 2022 17:48:35 +0100 Subject: [PATCH 17/63] Added --dev flag to cpl run & start #124 --- src/cpl_cli/command/run_service.py | 17 +++++++++++- .../live_server/live_server_service.py | 23 ++++++++++++++-- src/cpl_cli/startup_argument_extension.py | 6 +++-- .../general/src/general/arguments/__init__.py | 26 +++++++++++++++++++ .../custom/general/src/general/db/__init__.py | 7 ++--- tests/custom/general/src/general/general.json | 8 +++--- unittests/unittests_cli/run_test_case.py | 7 ++--- unittests/unittests_shared/cli_commands.py | 10 ++++--- 8 files changed, 84 insertions(+), 20 deletions(-) diff --git a/src/cpl_cli/command/run_service.py b/src/cpl_cli/command/run_service.py index 7aa4e456..92583f95 100644 --- a/src/cpl_cli/command/run_service.py +++ b/src/cpl_cli/command/run_service.py @@ -8,6 +8,7 @@ from cpl_cli.configuration import WorkspaceSettings from cpl_cli.configuration.build_settings import BuildSettings from cpl_cli.configuration.project_settings import ProjectSettings from cpl_cli.live_server.start_executable import StartExecutable +from cpl_cli.publish import PublisherService from cpl_core.configuration import ConfigurationABC from cpl_core.console.console import Console from cpl_core.dependency_injection import ServiceProviderABC @@ -22,7 +23,8 @@ class RunService(CommandABC): services: ServiceProviderABC, project_settings: ProjectSettings, build_settings: BuildSettings, - workspace: WorkspaceSettings + workspace: WorkspaceSettings, + publisher: PublisherService, ): """ Service for the CLI command start @@ -41,8 +43,10 @@ class RunService(CommandABC): self._project_settings = project_settings self._build_settings = build_settings self._workspace = workspace + self._publisher = publisher self._src_dir = os.path.join(self._env.working_directory, self._build_settings.source_path) + self._is_dev = False @property def help_message(self) -> str: @@ -80,16 +84,27 @@ class RunService(CommandABC): self._src_dir = os.path.dirname(json_file) + def _build(self): + if self._is_dev: + return + self._publisher.build() + def execute(self, args: list[str]): """ Entry point of command :param args: :return: """ + if 'dev' in args: + self._is_dev = True + args.remove('dev') + if len(args) >= 1: self._set_project_by_args(args[0]) args.remove(args[0]) + self._build() + start_service = StartExecutable(self._env, self._build_settings) start_service.run(args, self._project_settings.python_executable, self._src_dir, output=False) Console.write_line() diff --git a/src/cpl_cli/live_server/live_server_service.py b/src/cpl_cli/live_server/live_server_service.py index e9bb40b6..c51c9c58 100644 --- a/src/cpl_cli/live_server/live_server_service.py +++ b/src/cpl_cli/live_server/live_server_service.py @@ -6,6 +6,7 @@ import psutil as psutil from watchdog.events import FileSystemEventHandler from watchdog.observers import Observer +from cpl_cli.publish import PublisherService from cpl_core.console.console import Console from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC from cpl_cli.configuration.build_settings import BuildSettings @@ -15,8 +16,13 @@ from cpl_cli.live_server.live_server_thread import LiveServerThread class LiveServerService(FileSystemEventHandler): - def __init__(self, env: ApplicationEnvironmentABC, project_settings: ProjectSettings, - build_settings: BuildSettings): + def __init__( + self, + env: ApplicationEnvironmentABC, + project_settings: ProjectSettings, + build_settings: BuildSettings, + publisher: PublisherService, + ): """ Service for the live development server :param env: @@ -28,12 +34,14 @@ class LiveServerService(FileSystemEventHandler): self._env = env self._project_settings = project_settings self._build_settings = build_settings + self._publisher = publisher self._src_dir = os.path.join(self._env.working_directory, self._build_settings.source_path) self._ls_thread = None self._observer = None self._args: list[str] = [] + self._is_dev = False def _start_observer(self): """ @@ -87,6 +95,11 @@ class LiveServerService(FileSystemEventHandler): self._ls_thread.join() Console.close() + def _build(self): + if self._is_dev: + return + self._publisher.build() + def start(self, args: list[str]): """ Starts the CPL live development server @@ -97,6 +110,12 @@ class LiveServerService(FileSystemEventHandler): Console.error('Project has no entry point.') return + if 'dev' in args: + self._is_dev = True + args.remove('dev') + + self._build() + self._args = args Console.write_line('** CPL live development server is running **') self._start() diff --git a/src/cpl_cli/startup_argument_extension.py b/src/cpl_cli/startup_argument_extension.py index de57d9c3..16bd5449 100644 --- a/src/cpl_cli/startup_argument_extension.py +++ b/src/cpl_cli/startup_argument_extension.py @@ -60,8 +60,10 @@ class StartupArgumentExtension(StartupExtensionABC): config.create_console_argument(ArgumentTypeEnum.Executable, '', 'publish', ['p', 'P'], PublishService, True, validators=[ProjectValidator]) config.create_console_argument(ArgumentTypeEnum.Executable, '', 'remove', ['r', 'R'], RemoveService, True, validators=[WorkspaceValidator]) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) - config.create_console_argument(ArgumentTypeEnum.Executable, '', 'run', [], RunService, True, validators=[ProjectValidator]) - config.create_console_argument(ArgumentTypeEnum.Executable, '', 'start', ['s', 'S'], StartService, True, validators=[ProjectValidator]) + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'run', [], RunService, True, validators=[ProjectValidator]) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D']) + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'start', ['s', 'S'], StartService, True, validators=[ProjectValidator]) \ + .add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D']) config.create_console_argument(ArgumentTypeEnum.Executable, '', 'uninstall', ['ui', 'UI'], UninstallService, True, validators=[ProjectValidator]) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D']) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \ diff --git a/tests/custom/general/src/general/arguments/__init__.py b/tests/custom/general/src/general/arguments/__init__.py index e69de29b..a1515376 100644 --- a/tests/custom/general/src/general/arguments/__init__.py +++ b/tests/custom/general/src/general/arguments/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +""" +general sh-edraft Common Python library +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Common Python library + +:copyright: (c) 2020 - 2021 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'general.arguments' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' +__version__ = '2021.4.1' + +from collections import namedtuple + + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='2021', minor='04', micro='01') diff --git a/tests/custom/general/src/general/db/__init__.py b/tests/custom/general/src/general/db/__init__.py index 746ca0b0..099d021f 100644 --- a/tests/custom/general/src/general/db/__init__.py +++ b/tests/custom/general/src/general/db/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +general sh-edraft Common Python library ~~~~~~~~~~~~~~~~~~~ sh-edraft Common Python library @@ -11,7 +11,7 @@ sh-edraft Common Python library """ -__title__ = 'tests.db' +__title__ = 'general.db' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' @@ -19,7 +19,8 @@ __version__ = '2021.4.1' from collections import namedtuple + # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major=2021, minor=4, micro=1) +version_info = VersionInfo(major='2021', minor='04', micro='01') diff --git a/tests/custom/general/src/general/general.json b/tests/custom/general/src/general/general.json index 0bf4dded..aa7ce5d7 100644 --- a/tests/custom/general/src/general/general.json +++ b/tests/custom/general/src/general/general.json @@ -16,12 +16,12 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core==2022.10rc2", - "cpl-translation==2022.10rc2", - "cpl-query==2022.10rc2" + "cpl-core==2022.10.0.post9", + "cpl-translation==2022.10.0.post2", + "cpl-query==2022.10.0.post2" ], "DevDependencies": [ - "cpl-cli==2022.10.rc2" + "cpl-cli==2022.10" ], "PythonVersion": ">=3.10", "PythonPath": { diff --git a/unittests/unittests_cli/run_test_case.py b/unittests/unittests_cli/run_test_case.py index 23841a79..eeaf05b5 100644 --- a/unittests/unittests_cli/run_test_case.py +++ b/unittests/unittests_cli/run_test_case.py @@ -46,9 +46,6 @@ class RunTestCase(CommandTestCase): project_file.close() def setUp(self): - if not os.path.exists(PLAYGROUND_PATH): - os.makedirs(PLAYGROUND_PATH) - os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') @@ -60,7 +57,7 @@ class RunTestCase(CommandTestCase): file.close() def test_run(self): - CLICommands.run() + CLICommands.run(is_dev=True, output=True) settings = self._get_appsettings() self.assertNotEqual(settings, {}) self.assertIn('RunTest', settings) @@ -72,7 +69,7 @@ class RunTestCase(CommandTestCase): def test_run_by_project(self): os.chdir(os.path.join(os.getcwd())) - CLICommands.run(self._source) + CLICommands.run(self._source, is_dev=True) settings = self._get_appsettings() self.assertNotEqual(settings, {}) self.assertIn('RunTest', settings) diff --git a/unittests/unittests_shared/cli_commands.py b/unittests/unittests_shared/cli_commands.py index eb0f2f1f..3d2b0442 100644 --- a/unittests/unittests_shared/cli_commands.py +++ b/unittests/unittests_shared/cli_commands.py @@ -65,11 +65,15 @@ class CLICommands: cls._run('remove', project, output=output) @classmethod - def run(cls, project: str = None, output=False): + def run(cls, project: str = None, is_dev=False, output=False): + dev = '' + if is_dev: + dev = '--dev' + if project is None: - cls._run('run', output=output) + cls._run('run', dev, output=output) return - cls._run('run', project, output=output) + cls._run('run', project, dev, output=output) @classmethod def start(cls, output=False): -- 2.45.1 From d0877a4ea634223d71bb5ca8a2ba2a63a025fa74 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Fri, 2 Dec 2022 18:41:58 +0100 Subject: [PATCH 18/63] Added logic to run build code to cpl run #124 --- src/cpl_cli/command/run_service.py | 10 ++++ unittests/unittests_cli/run_test_case.py | 64 +++++++++++++++++++--- unittests/unittests_shared/cli_commands.py | 8 +-- 3 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/cpl_cli/command/run_service.py b/src/cpl_cli/command/run_service.py index 92583f95..e3740e00 100644 --- a/src/cpl_cli/command/run_service.py +++ b/src/cpl_cli/command/run_service.py @@ -13,6 +13,7 @@ from cpl_core.configuration import ConfigurationABC from cpl_core.console.console import Console from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC +from cpl_core.utils import String class RunService(CommandABC): @@ -87,7 +88,16 @@ class RunService(CommandABC): def _build(self): if self._is_dev: return + + self._env.set_working_directory(self._src_dir) self._publisher.build() + self._src_dir = os.path.abspath(os.path.join( + self._src_dir, + self._build_settings.output_path, + self._project_settings.name, + 'build', + String.convert_to_snake_case(self._project_settings.name) + )) def execute(self, args: list[str]): """ diff --git a/unittests/unittests_cli/run_test_case.py b/unittests/unittests_cli/run_test_case.py index eeaf05b5..a44ded36 100644 --- a/unittests/unittests_cli/run_test_case.py +++ b/unittests/unittests_cli/run_test_case.py @@ -15,10 +15,10 @@ class RunTestCase(CommandTestCase): CommandTestCase.__init__(self, method_name) self._source = 'run-test' self._project_file = f'src/{String.convert_to_snake_case(self._source)}/{self._source}.json' - self._appsettings = f'src/{String.convert_to_snake_case(self._source)}/appsettings.json' self._application = f'src/{String.convert_to_snake_case(self._source)}/application.py' self._test_code = f""" import json + import os settings = dict() with open('appsettings.json', 'r', encoding='utf-8') as cfg: # load json @@ -26,14 +26,19 @@ class RunTestCase(CommandTestCase): cfg.close() settings['RunTest']['WasStarted'] = 'True' + settings['RunTest']['Path'] = os.path.dirname(os.path.realpath(__file__)) with open('appsettings.json', 'w', encoding='utf-8') as project_file: project_file.write(json.dumps(settings, indent=2)) project_file.close() """ - def _get_appsettings(self): - with open(os.path.join(os.getcwd(), self._appsettings), 'r', encoding='utf-8') as cfg: + def _get_appsettings(self, is_dev=False): + appsettings = f'dist/{self._source}/build/{String.convert_to_snake_case(self._source)}/appsettings.json' + if is_dev: + appsettings = f'src/{String.convert_to_snake_case(self._source)}/appsettings.json' + + with open(os.path.join(os.getcwd(), appsettings), 'r', encoding='utf-8') as cfg: # load json project_json = json.load(cfg) cfg.close() @@ -41,7 +46,7 @@ class RunTestCase(CommandTestCase): return project_json def _save_appsettings(self, settings: dict): - with open(os.path.join(os.getcwd(), self._appsettings), 'w', encoding='utf-8') as project_file: + with open(os.path.join(os.getcwd(), f'src/{String.convert_to_snake_case(self._source)}/appsettings.json'), 'w', encoding='utf-8') as project_file: project_file.write(json.dumps(settings, indent=2)) project_file.close() @@ -57,7 +62,7 @@ class RunTestCase(CommandTestCase): file.close() def test_run(self): - CLICommands.run(is_dev=True, output=True) + CLICommands.run() settings = self._get_appsettings() self.assertNotEqual(settings, {}) self.assertIn('RunTest', settings) @@ -66,10 +71,17 @@ class RunTestCase(CommandTestCase): 'True', settings['RunTest']['WasStarted'] ) + self.assertNotEqual( + os.path.join(os.getcwd(), f'src/{String.convert_to_snake_case(self._source)}'), + settings['RunTest']['Path'] + ) + self.assertEqual( + os.path.join(os.getcwd(), f'dist/{self._source}/build/{String.convert_to_snake_case(self._source)}'), + settings['RunTest']['Path'] + ) def test_run_by_project(self): - os.chdir(os.path.join(os.getcwd())) - CLICommands.run(self._source, is_dev=True) + CLICommands.run(self._source) settings = self._get_appsettings() self.assertNotEqual(settings, {}) self.assertIn('RunTest', settings) @@ -78,3 +90,41 @@ class RunTestCase(CommandTestCase): 'True', settings['RunTest']['WasStarted'] ) + self.assertNotEqual( + os.path.join(os.getcwd(), f'src/{String.convert_to_snake_case(self._source)}'), + settings['RunTest']['Path'] + ) + self.assertEqual( + os.path.join(os.getcwd(), f'dist/{self._source}/build/{String.convert_to_snake_case(self._source)}'), + settings['RunTest']['Path'] + ) + + def test_run_dev(self): + CLICommands.run(is_dev=True) + settings = self._get_appsettings(is_dev=True) + self.assertNotEqual(settings, {}) + self.assertIn('RunTest', settings) + self.assertIn('WasStarted', settings['RunTest']) + self.assertEqual( + 'True', + settings['RunTest']['WasStarted'] + ) + self.assertEqual( + os.path.join(os.getcwd(), f'src/{String.convert_to_snake_case(self._source)}'), + settings['RunTest']['Path'] + ) + + def test_run_dev_by_project(self): + CLICommands.run(self._source, is_dev=True) + settings = self._get_appsettings(is_dev=True) + self.assertNotEqual(settings, {}) + self.assertIn('RunTest', settings) + self.assertIn('WasStarted', settings['RunTest']) + self.assertEqual( + 'True', + settings['RunTest']['WasStarted'] + ) + self.assertEqual( + os.path.join(os.getcwd(), f'src/{String.convert_to_snake_case(self._source)}'), + settings['RunTest']['Path'] + ) diff --git a/unittests/unittests_shared/cli_commands.py b/unittests/unittests_shared/cli_commands.py index 3d2b0442..12a3a70d 100644 --- a/unittests/unittests_shared/cli_commands.py +++ b/unittests/unittests_shared/cli_commands.py @@ -66,14 +66,14 @@ class CLICommands: @classmethod def run(cls, project: str = None, is_dev=False, output=False): - dev = '' + args = [] if is_dev: - dev = '--dev' + args.append('--dev') if project is None: - cls._run('run', dev, output=output) + cls._run('run', *args, output=output) return - cls._run('run', project, dev, output=output) + cls._run('run', project, *args, output=output) @classmethod def start(cls, output=False): -- 2.45.1 From 856960d7992d1a4066f64c4fa6d01310d003dff7 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Fri, 2 Dec 2022 19:38:03 +0100 Subject: [PATCH 19/63] Added logic to run build code to cpl start #124 --- .../live_server/live_server_service.py | 18 +++++-- unittests/unittests_cli/start_test_case.py | 49 +++++++++++++++++-- .../threads/start_test_thread.py | 5 +- unittests/unittests_shared/cli_commands.py | 8 ++- 4 files changed, 68 insertions(+), 12 deletions(-) diff --git a/src/cpl_cli/live_server/live_server_service.py b/src/cpl_cli/live_server/live_server_service.py index c51c9c58..7eadc8cc 100644 --- a/src/cpl_cli/live_server/live_server_service.py +++ b/src/cpl_cli/live_server/live_server_service.py @@ -12,6 +12,7 @@ from cpl_core.environment.application_environment_abc import ApplicationEnvironm from cpl_cli.configuration.build_settings import BuildSettings from cpl_cli.configuration.project_settings import ProjectSettings from cpl_cli.live_server.live_server_thread import LiveServerThread +from cpl_core.utils import String class LiveServerService(FileSystemEventHandler): @@ -37,6 +38,7 @@ class LiveServerService(FileSystemEventHandler): self._publisher = publisher self._src_dir = os.path.join(self._env.working_directory, self._build_settings.source_path) + self._wd = self._src_dir self._ls_thread = None self._observer = None @@ -83,10 +85,11 @@ class LiveServerService(FileSystemEventHandler): self._restart() def _start(self): + self._build() self._start_observer() self._ls_thread = LiveServerThread( self._project_settings.python_executable, - self._src_dir, + self._wd, self._args, self._env, self._build_settings @@ -98,7 +101,18 @@ class LiveServerService(FileSystemEventHandler): def _build(self): if self._is_dev: return + + self._env.set_working_directory(self._src_dir) + Console.disable() self._publisher.build() + Console.enable() + self._wd = os.path.abspath(os.path.join( + self._src_dir, + self._build_settings.output_path, + self._project_settings.name, + 'build', + String.convert_to_snake_case(self._project_settings.name) + )) def start(self, args: list[str]): """ @@ -114,8 +128,6 @@ class LiveServerService(FileSystemEventHandler): self._is_dev = True args.remove('dev') - self._build() - self._args = args Console.write_line('** CPL live development server is running **') self._start() diff --git a/unittests/unittests_cli/start_test_case.py b/unittests/unittests_cli/start_test_case.py index b0949f14..308450a5 100644 --- a/unittests/unittests_cli/start_test_case.py +++ b/unittests/unittests_cli/start_test_case.py @@ -21,6 +21,7 @@ class StartTestCase(CommandTestCase): self._application = f'src/{String.convert_to_snake_case(self._source)}/application.py' self._test_code = f""" import json + import os settings = dict() with open('appsettings.json', 'r', encoding='utf-8') as cfg: # load json @@ -31,14 +32,19 @@ class StartTestCase(CommandTestCase): settings['RunTest']['WasRestarted'] = 'True' settings['RunTest']['WasStarted'] = 'True' + settings['RunTest']['Path'] = os.path.dirname(os.path.realpath(__file__)) with open('appsettings.json', 'w', encoding='utf-8') as project_file: project_file.write(json.dumps(settings, indent=2)) project_file.close() """ - def _get_appsettings(self): - with open(os.path.join(os.getcwd(), self._appsettings), 'r', encoding='utf-8') as cfg: + def _get_appsettings(self, is_dev=False): + appsettings = f'dist/{self._source}/build/{String.convert_to_snake_case(self._source)}/appsettings.json' + if is_dev: + appsettings = f'src/{String.convert_to_snake_case(self._source)}/appsettings.json' + + with open(os.path.join(os.getcwd(), appsettings), 'r', encoding='utf-8') as cfg: # load json project_json = json.load(cfg) cfg.close() @@ -46,14 +52,14 @@ class StartTestCase(CommandTestCase): return project_json def _save_appsettings(self, settings: dict): - with open(os.path.join(os.getcwd(), self._appsettings), 'w', encoding='utf-8') as project_file: + with open(os.path.join(os.getcwd(), f'src/{String.convert_to_snake_case(self._source)}/appsettings.json'), 'w', encoding='utf-8') as project_file: project_file.write(json.dumps(settings, indent=2)) project_file.close() def setUp(self): if not os.path.exists(PLAYGROUND_PATH): os.makedirs(PLAYGROUND_PATH) - + os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') @@ -67,6 +73,39 @@ class StartTestCase(CommandTestCase): def test_start(self): thread = StartTestThread() thread.start() + time.sleep(5) + settings = self._get_appsettings() + self.assertNotEqual(settings, {}) + self.assertIn('RunTest', settings) + self.assertIn('WasStarted', settings['RunTest']) + self.assertEqual( + 'True', + settings['RunTest']['WasStarted'] + ) + + with open(os.path.join(os.getcwd(), self._application), 'a', encoding='utf-8') as file: + file.write(f'# trigger restart (comment generated by unittest)') + file.close() + + time.sleep(5) + + settings = self._get_appsettings() + self.assertNotEqual(settings, {}) + self.assertIn('RunTest', settings) + self.assertIn('WasStarted', settings['RunTest']) + self.assertIn('WasRestarted', settings['RunTest']) + self.assertEqual( + 'True', + settings['RunTest']['WasStarted'] + ) + self.assertEqual( + 'True', + settings['RunTest']['WasRestarted'] + ) + + def test_start_dev(self): + thread = StartTestThread(is_dev=True) + thread.start() time.sleep(1) settings = self._get_appsettings() self.assertNotEqual(settings, {}) @@ -83,7 +122,7 @@ class StartTestCase(CommandTestCase): time.sleep(1) - settings = self._get_appsettings() + settings = self._get_appsettings(is_dev=True) self.assertNotEqual(settings, {}) self.assertIn('RunTest', settings) self.assertIn('WasStarted', settings['RunTest']) diff --git a/unittests/unittests_cli/threads/start_test_thread.py b/unittests/unittests_cli/threads/start_test_thread.py index 6c413e6d..e6884ed9 100644 --- a/unittests/unittests_cli/threads/start_test_thread.py +++ b/unittests/unittests_cli/threads/start_test_thread.py @@ -5,8 +5,9 @@ from unittests_shared.cli_commands import CLICommands class StartTestThread(threading.Thread): - def __init__(self): + def __init__(self, is_dev=False): threading.Thread.__init__(self, daemon=True) + self._is_dev = is_dev def run(self): - CLICommands.start(True) + CLICommands.start(is_dev=self._is_dev, output=True) diff --git a/unittests/unittests_shared/cli_commands.py b/unittests/unittests_shared/cli_commands.py index 12a3a70d..ad7c39ce 100644 --- a/unittests/unittests_shared/cli_commands.py +++ b/unittests/unittests_shared/cli_commands.py @@ -76,8 +76,12 @@ class CLICommands: cls._run('run', project, *args, output=output) @classmethod - def start(cls, output=False): - cls._run('start', output=output) + def start(cls, is_dev=False, output=False): + args = [] + if is_dev: + args.append('--dev') + + cls._run('start', *args, output=output) @classmethod def uninstall(cls, package: str, is_dev=False, output=False): -- 2.45.1 From e4aedb354bb0fb6d8259550101826ca2fcc8caf2 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 3 Dec 2022 23:30:54 +0100 Subject: [PATCH 20/63] Fixed invalid output after console spinner #122 --- src/cpl_core/console/console.py | 8 +++--- tests/custom/console/main.py | 43 ++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/cpl_core/console/console.py b/src/cpl_core/console/console.py index 3475b64d..c10b3590 100644 --- a/src/cpl_core/console/console.py +++ b/src/cpl_core/console/console.py @@ -500,7 +500,7 @@ class Console: return if cls._hold_back: - cls._hold_back_calls.append(ConsoleCall(cls.write, args)) + cls._hold_back_calls.append(ConsoleCall(cls.write, *args)) return string = ' '.join(map(str, args)) @@ -523,7 +523,7 @@ class Console: return if cls._hold_back: - cls._hold_back_calls.append(ConsoleCall(cls.write_at, x, y, args)) + cls._hold_back_calls.append(ConsoleCall(cls.write_at, x, y, *args)) return string = ' '.join(map(str, args)) @@ -542,7 +542,7 @@ class Console: return if cls._hold_back: - cls._hold_back_calls.append(ConsoleCall(cls.write_line, args)) + cls._hold_back_calls.append(ConsoleCall(cls.write_line, *args)) return string = ' '.join(map(str, args)) @@ -567,7 +567,7 @@ class Console: return if cls._hold_back: - cls._hold_back_calls.append(ConsoleCall(cls.write_line_at, x, y, args)) + cls._hold_back_calls.append(ConsoleCall(cls.write_line_at, x, y, *args)) return string = ' '.join(map(str, args)) diff --git a/tests/custom/console/main.py b/tests/custom/console/main.py index 12889c57..dc2fcb5b 100644 --- a/tests/custom/console/main.py +++ b/tests/custom/console/main.py @@ -3,7 +3,12 @@ from cpl_core.console import Console, ForegroundColorEnum def test_spinner(): + Console.write_line('test1') + Console.write_line('test2', 2) + Console.write_line('test3', 2, 3) + Console.write_line('test4', 2, 3, 4) time.sleep(2) + Console.write_line('test5') def test_console(): @@ -17,22 +22,22 @@ def test_console(): if __name__ == '__main__': Console.write_line('Hello World\n') - # Console.spinner('Test:', test_spinner, spinner_foreground_color=ForegroundColorEnum.cyan, text_foreground_color='green') - opts = [ - 'Option 1', - 'Option 2', - 'Option 3', - 'Option 4' - ] - selected = Console.select( - '>', - 'Select item:', - opts, - header_foreground_color=ForegroundColorEnum.blue, - option_foreground_color=ForegroundColorEnum.green, - cursor_foreground_color=ForegroundColorEnum.red - ) - Console.write_line(f'You selected: {selected}') - # test_console() - - Console.write_line() + Console.spinner('Test:', test_spinner, spinner_foreground_color=ForegroundColorEnum.cyan, text_foreground_color='green') + # opts = [ + # 'Option 1', + # 'Option 2', + # 'Option 3', + # 'Option 4' + # ] + # selected = Console.select( + # '>', + # 'Select item:', + # opts, + # header_foreground_color=ForegroundColorEnum.blue, + # option_foreground_color=ForegroundColorEnum.green, + # cursor_foreground_color=ForegroundColorEnum.red + # ) + # Console.write_line(f'You selected: {selected}') + # # test_console() + # + # Console.write_line() -- 2.45.1 From b02aebef356c7b1e6c8999e9e3a5f98f4a137dec Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 3 Dec 2022 23:42:23 +0100 Subject: [PATCH 21/63] Improved set-version tool & set version --- src/cpl_cli/cpl-cli.json | 6 +-- src/cpl_core/cpl-core.json | 4 +- src/cpl_discord/cpl-discord.json | 8 ++-- src/cpl_query/cpl-query.json | 4 +- src/cpl_translation/cpl-translation.json | 4 +- tools/set_pip_urls/set-pip-urls.json | 4 +- tools/set_version/application.py | 46 ++++++++++++------- tools/set_version/git_service.py | 3 +- tools/set_version/set-version.json | 4 +- unittests/unittests/unittests.json | 4 +- unittests/unittests_cli/unittests_cli.json | 6 +-- unittests/unittests_core/unittests_core.json | 4 +- .../unittests_query/unittests_query.json | 6 +-- .../unittests_shared/unittests_shared.json | 4 +- .../unittests_translation.json | 8 ++-- 15 files changed, 65 insertions(+), 50 deletions(-) diff --git a/src/cpl_cli/cpl-cli.json b/src/cpl_cli/cpl-cli.json index d6a9068b..3c57ece9 100644 --- a/src/cpl_cli/cpl-cli.json +++ b/src/cpl_cli/cpl-cli.json @@ -3,8 +3,8 @@ "Name": "cpl-cli", "Version": { "Major": "2022", - "Minor": "10", - "Micro": "1.post1" + "Minor": "12", + "Micro": "0" }, "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.10.0" + "cpl-core>=2022.12.0" ], "DevDependencies": [], "PythonVersion": ">=3.10", diff --git a/src/cpl_core/cpl-core.json b/src/cpl_core/cpl-core.json index 0da1d6d3..c4a70de3 100644 --- a/src/cpl_core/cpl-core.json +++ b/src/cpl_core/cpl-core.json @@ -3,8 +3,8 @@ "Name": "cpl-core", "Version": { "Major": "2022", - "Minor": "10", - "Micro": "0.post9" + "Minor": "12", + "Micro": "0" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_discord/cpl-discord.json b/src/cpl_discord/cpl-discord.json index dabf8aab..08fb8870 100644 --- a/src/cpl_discord/cpl-discord.json +++ b/src/cpl_discord/cpl-discord.json @@ -16,12 +16,12 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core>=2022.10.0", - "discord.py==2.0.1", - "cpl-query>=2022.10.0" + "cpl-core>=2022.12.0", + "discord.py==2.1.0", + "cpl-query>=2022.12.0" ], "DevDependencies": [ - "cpl-cli>=2022.10.0" + "cpl-cli>=2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, diff --git a/src/cpl_query/cpl-query.json b/src/cpl_query/cpl-query.json index b115cc05..b06705f3 100644 --- a/src/cpl_query/cpl-query.json +++ b/src/cpl_query/cpl-query.json @@ -3,8 +3,8 @@ "Name": "cpl-query", "Version": { "Major": "2022", - "Minor": "10", - "Micro": "0.post2" + "Minor": "12", + "Micro": "0" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_translation/cpl-translation.json b/src/cpl_translation/cpl-translation.json index 346daf70..182fa5ed 100644 --- a/src/cpl_translation/cpl-translation.json +++ b/src/cpl_translation/cpl-translation.json @@ -16,10 +16,10 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core>=2022.10.0" + "cpl-core>=2022.12.0" ], "DevDependencies": [ - "cpl-cli>=2022.10.0" + "cpl-cli>=2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": { diff --git a/tools/set_pip_urls/set-pip-urls.json b/tools/set_pip_urls/set-pip-urls.json index 69c91652..aed7da44 100644 --- a/tools/set_pip_urls/set-pip-urls.json +++ b/tools/set_pip_urls/set-pip-urls.json @@ -3,7 +3,7 @@ "Name": "set-pip-urls", "Version": { "Major": "2022", - "Minor": "6", + "Minor": "12", "Micro": "0" }, "Author": "Sven Heidemann", @@ -16,7 +16,7 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core>=2022.10.0" + "cpl-core>=2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, diff --git a/tools/set_version/application.py b/tools/set_version/application.py index 2a22e73b..6b61c7f1 100644 --- a/tools/set_version/application.py +++ b/tools/set_version/application.py @@ -1,6 +1,7 @@ import os import traceback +from cpl_cli.configuration import ProjectSettings from cpl_core.utils import String from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum @@ -45,51 +46,64 @@ class Application(ApplicationABC): return if len(args) == 1: - suffix = f'.{args[0]}' + suffix = args[0] try: branch = self._git_service.get_active_branch_name() Console.write_line(f'Found branch: {branch}') except Exception as e: - Console.error('Branch could not be found', traceback.format_exc()) + Console.error('Branch not found', traceback.format_exc()) return try: + if branch.startswith('#'): + self._configuration.add_json_file(self._workspace.projects[self._workspace.default_project], optional=False, output=False) + ps: ProjectSettings = self._configuration.get_configuration(ProjectSettings) - version[VersionSettingsNameEnum.major.value] = branch.split('.')[0] - version[VersionSettingsNameEnum.minor.value] = branch.split('.')[1] - if len(branch.split('.')) == 2: - version[VersionSettingsNameEnum.micro.value] = f'0{suffix}' + version[VersionSettingsNameEnum.major.value] = ps.version.major + version[VersionSettingsNameEnum.minor.value] = ps.version.minor + version[VersionSettingsNameEnum.micro.value] = f'dev{branch.split("#")[1]}' else: - branch_version = branch.split(".")[2] - if '-#' in branch_version: - branch_version = branch_version.split('-#')[0] - version[VersionSettingsNameEnum.micro.value] = f'{branch_version}{suffix}' + version[VersionSettingsNameEnum.major.value] = branch.split('.')[0] + version[VersionSettingsNameEnum.minor.value] = branch.split('.')[1] + if len(branch.split('.')) == 2: + if suffix == '': + suffix = '0' + version[VersionSettingsNameEnum.micro.value] = f'{suffix}' + else: + if not suffix.startswith('.') and suffix != '': + suffix = f'.{suffix}' + version[VersionSettingsNameEnum.micro.value] = f'{branch.split(".")[2]}{suffix}' except Exception as e: Console.error(f'Branch {branch} does not contain valid version') return diff_paths = [] for file in self._git_service.get_diff_files(): + if file.startswith('tools'): + continue + if '/' in file: - diff_paths.append(file.split('/')[1]) + file = file.split('/')[1] else: - diff_paths.append(os.path.basename(os.path.dirname(file))) + file = os.path.basename(os.path.dirname(file)) + + if file in diff_paths: + continue + + diff_paths.append(file) try: skipped = [] for project in self._workspace.projects: if project not in diff_paths and String.convert_to_snake_case(project) not in diff_paths and not force: - Console.write_line(f'Skipping {project} due to missing changes') + # Console.write_line(f'Skipping {project} due to missing changes') skipped.append(project) continue Console.write_line(f'Set dependencies {self._version_pipe.transform(version)} for {project}') self._version_setter.set_dependencies(self._workspace.projects[project], version, 'Dependencies', skipped=skipped) self._version_setter.set_dependencies(self._workspace.projects[project], version, 'DevDependencies', skipped=skipped) - if not project.startswith('cpl') and not project.startswith('unittest'): - Console.write_line(f'Skipping {project}') - continue Console.write_line(f'Set version {self._version_pipe.transform(version)} for {project}') self._version_setter.set_version(self._workspace.projects[project], version) diff --git a/tools/set_version/git_service.py b/tools/set_version/git_service.py index 0e43b226..b3521bb8 100644 --- a/tools/set_version/git_service.py +++ b/tools/set_version/git_service.py @@ -1,6 +1,7 @@ -from git import Repo, DiffIndex +import os from cpl_core.environment import ApplicationEnvironmentABC +from git import Repo class GitService: diff --git a/tools/set_version/set-version.json b/tools/set_version/set-version.json index 801e202a..60132668 100644 --- a/tools/set_version/set-version.json +++ b/tools/set_version/set-version.json @@ -3,7 +3,7 @@ "Name": "set-version", "Version": { "Major": "2022", - "Minor": "7", + "Minor": "12", "Micro": "0" }, "Author": "Sven Heidemann", @@ -16,7 +16,7 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core>=2022.10.0", + "cpl-core>=2022.12.0", "gitpython==3.1.27" ], "PythonVersion": ">=3.10.4", diff --git a/unittests/unittests/unittests.json b/unittests/unittests/unittests.json index bae65fc0..7d4a72ee 100644 --- a/unittests/unittests/unittests.json +++ b/unittests/unittests/unittests.json @@ -3,7 +3,7 @@ "Name": "unittests", "Version": { "Major": "2022", - "Minor": "10", + "Minor": "12", "Micro": "0" }, "Author": "", @@ -16,7 +16,7 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.10.0" + "cpl-core>=2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, diff --git a/unittests/unittests_cli/unittests_cli.json b/unittests/unittests_cli/unittests_cli.json index 7b81087c..b25c355a 100644 --- a/unittests/unittests_cli/unittests_cli.json +++ b/unittests/unittests_cli/unittests_cli.json @@ -3,7 +3,7 @@ "Name": "unittest_cli", "Version": { "Major": "2022", - "Minor": "10", + "Minor": "12", "Micro": "0" }, "Author": "", @@ -16,8 +16,8 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.10.0", - "cpl-cli>=2022.10.0" + "cpl-core>=2022.12.0", + "cpl-cli>=2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, diff --git a/unittests/unittests_core/unittests_core.json b/unittests/unittests_core/unittests_core.json index 143b7da1..882abcc0 100644 --- a/unittests/unittests_core/unittests_core.json +++ b/unittests/unittests_core/unittests_core.json @@ -3,7 +3,7 @@ "Name": "unittest_core", "Version": { "Major": "2022", - "Minor": "10", + "Minor": "12", "Micro": "0" }, "Author": "", @@ -16,7 +16,7 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.10.0" + "cpl-core>=2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, diff --git a/unittests/unittests_query/unittests_query.json b/unittests/unittests_query/unittests_query.json index bf5c4041..855bab31 100644 --- a/unittests/unittests_query/unittests_query.json +++ b/unittests/unittests_query/unittests_query.json @@ -3,7 +3,7 @@ "Name": "unittest_query", "Version": { "Major": "2022", - "Minor": "10", + "Minor": "12", "Micro": "0" }, "Author": "", @@ -16,8 +16,8 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.10.0", - "cpl-query>=2022.10.0" + "cpl-core>=2022.12.0", + "cpl-query>=2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, diff --git a/unittests/unittests_shared/unittests_shared.json b/unittests/unittests_shared/unittests_shared.json index 881cf7b1..a7789f4b 100644 --- a/unittests/unittests_shared/unittests_shared.json +++ b/unittests/unittests_shared/unittests_shared.json @@ -3,7 +3,7 @@ "Name": "unittest_shared", "Version": { "Major": "2022", - "Minor": "10", + "Minor": "12", "Micro": "0" }, "Author": "", @@ -16,7 +16,7 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.10.0" + "cpl-core>=2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, diff --git a/unittests/unittests_translation/unittests_translation.json b/unittests/unittests_translation/unittests_translation.json index 28396a27..8fdfacba 100644 --- a/unittests/unittests_translation/unittests_translation.json +++ b/unittests/unittests_translation/unittests_translation.json @@ -3,7 +3,7 @@ "Name": "unittests_translation", "Version": { "Major": "2022", - "Minor": "10", + "Minor": "12", "Micro": "0" }, "Author": "", @@ -16,11 +16,11 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.10.0", - "cpl-translation>=2022.10.0" + "cpl-core>=2022.12.0", + "cpl-translation>=2022.12.0" ], "DevDependencies": [ - "cpl-cli>=2022.10.0" + "cpl-cli>=2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, -- 2.45.1 From 2e0a8bb1ff18265cdc8dff85a4374241f63f1a47 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 4 Dec 2022 00:08:16 +0100 Subject: [PATCH 22/63] Minor fixes to cpl query --- src/cpl_discord/cpl-discord.json | 4 +-- src/cpl_query/base/sequence_abc.py | 30 +++++++++++++++++++ src/cpl_query/iterable/iterable_abc.py | 14 +++++++++ .../iterable_query_test_case.py | 2 +- 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/cpl_discord/cpl-discord.json b/src/cpl_discord/cpl-discord.json index 08fb8870..a515bca1 100644 --- a/src/cpl_discord/cpl-discord.json +++ b/src/cpl_discord/cpl-discord.json @@ -3,8 +3,8 @@ "Name": "cpl-discord", "Version": { "Major": "2022", - "Minor": "10", - "Micro": "0.post6" + "Minor": "12", + "Micro": "0" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_query/base/sequence_abc.py b/src/cpl_query/base/sequence_abc.py index 8e3a01aa..b33a8082 100644 --- a/src/cpl_query/base/sequence_abc.py +++ b/src/cpl_query/base/sequence_abc.py @@ -21,6 +21,10 @@ class SequenceABC(ABC): self._type = t self._set_values(values) + @classmethod + def __class_getitem__(cls, _t: type): + return _t + def __len__(self): return len(self._values) @@ -71,6 +75,15 @@ class SequenceABC(ABC): """ return [x for x in self] + def copy(self) -> 'SequenceABC': + r"""Creates a copy of sequence + + Returns + ------- + SequenceABC + """ + return type(self)(self._type, self.to_list()) + @classmethod def empty(cls) -> 'SequenceABC': r"""Returns an empty sequence @@ -81,6 +94,23 @@ class SequenceABC(ABC): """ return cls() + def index(self, _object: object) -> int: + r"""Returns the index of given element + + Returns + ------- + Index of object + + Raises + ------- + IndexError if object not in sequence + """ + for i, o in enumerate(self): + if o == _object: + return i + + raise IndexError + @classmethod def range(cls, start: int, length: int) -> 'SequenceABC': return cls(int, list(range(start, length))) diff --git a/src/cpl_query/iterable/iterable_abc.py b/src/cpl_query/iterable/iterable_abc.py index dcae50b3..5758b03c 100644 --- a/src/cpl_query/iterable/iterable_abc.py +++ b/src/cpl_query/iterable/iterable_abc.py @@ -56,6 +56,20 @@ class IterableABC(QueryableABC): return self + def remove(self, _object: object): + r"""Removes element from list + Parameter + --------- + _object: :class:`object` + value + """ + if _object not in self: + raise ValueError + + values = [*self._values] + values.remove(_object) + self._set_values(values) + def to_enumerable(self) -> 'EnumerableABC': r"""Converts :class: `cpl_query.iterable.iterable_abc.IterableABC` to :class: `cpl_query.enumerable.enumerable_abc.EnumerableABC` diff --git a/unittests/unittests_query/iterable_query_test_case.py b/unittests/unittests_query/iterable_query_test_case.py index 8ea3a0b8..6dfa36f0 100644 --- a/unittests/unittests_query/iterable_query_test_case.py +++ b/unittests/unittests_query/iterable_query_test_case.py @@ -342,7 +342,7 @@ class IterableQueryTestCase(unittest.TestCase): self.assertEqual(skipped.to_list(), self._tests[:-5]) self.assertEqual(skipped.last(), self._tests[:-5][len(self._tests[:-5]) - 1]) - def test_sum(self): + def test_sum(self) -> List['int']: res = self._tests.sum(lambda u: u.address.nr) s_res = 0 -- 2.45.1 From 68e01afb5b98363620034247c2092ea0448521fa Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 4 Dec 2022 00:12:40 +0100 Subject: [PATCH 23/63] Release 2022.12.0 --- src/cpl_cli/__init__.py | 4 ++-- src/cpl_cli/_templates/__init__.py | 4 ++-- src/cpl_cli/_templates/build/__init__.py | 4 ++-- src/cpl_cli/_templates/generate/__init__.py | 4 ++-- src/cpl_cli/_templates/new/__init__.py | 4 ++-- src/cpl_cli/_templates/new/console/__init__.py | 4 ++-- src/cpl_cli/_templates/new/console/source/__init__.py | 4 ++-- src/cpl_cli/_templates/new/console/source/name/__init__.py | 4 ++-- src/cpl_cli/_templates/new/console/source/tests/__init__.py | 4 ++-- src/cpl_cli/_templates/new/library/__init__.py | 4 ++-- src/cpl_cli/_templates/new/library/source/__init__.py | 4 ++-- src/cpl_cli/_templates/new/library/source/name/__init__.py | 4 ++-- src/cpl_cli/_templates/new/library/source/tests/__init__.py | 4 ++-- src/cpl_cli/_templates/new/unittest/__init__.py | 4 ++-- src/cpl_cli/_templates/new/unittest/source/__init__.py | 4 ++-- src/cpl_cli/_templates/new/unittest/source/name/__init__.py | 4 ++-- src/cpl_cli/_templates/publish/__init__.py | 4 ++-- src/cpl_cli/command/__init__.py | 4 ++-- src/cpl_cli/configuration/__init__.py | 4 ++-- src/cpl_cli/live_server/__init__.py | 4 ++-- src/cpl_cli/migrations/__init__.py | 4 ++-- src/cpl_cli/migrations/base/__init__.py | 4 ++-- src/cpl_cli/migrations/service/__init__.py | 4 ++-- src/cpl_cli/publish/__init__.py | 4 ++-- src/cpl_cli/source_creator/__init__.py | 4 ++-- src/cpl_cli/validators/__init__.py | 4 ++-- src/cpl_core/__init__.py | 4 ++-- src/cpl_core/application/__init__.py | 4 ++-- src/cpl_core/configuration/__init__.py | 4 ++-- src/cpl_core/console/__init__.py | 4 ++-- src/cpl_core/database/__init__.py | 4 ++-- src/cpl_core/database/connection/__init__.py | 4 ++-- src/cpl_core/database/context/__init__.py | 4 ++-- src/cpl_core/dependency_injection/__init__.py | 4 ++-- src/cpl_core/environment/__init__.py | 4 ++-- src/cpl_core/logging/__init__.py | 4 ++-- src/cpl_core/mailing/__init__.py | 4 ++-- src/cpl_core/pipes/__init__.py | 4 ++-- src/cpl_core/time/__init__.py | 4 ++-- src/cpl_core/utils/__init__.py | 4 ++-- src/cpl_discord/__init__.py | 4 ++-- src/cpl_discord/application/__init__.py | 4 ++-- src/cpl_discord/command/__init__.py | 4 ++-- src/cpl_discord/configuration/__init__.py | 4 ++-- src/cpl_discord/container/__init__.py | 4 ++-- src/cpl_discord/events/__init__.py | 4 ++-- src/cpl_discord/helper/__init__.py | 4 ++-- src/cpl_discord/service/__init__.py | 4 ++-- src/cpl_query/__init__.py | 4 ++-- src/cpl_query/base/__init__.py | 4 ++-- src/cpl_query/enumerable/__init__.py | 5 +++-- src/cpl_query/extension/__init__.py | 4 ++-- src/cpl_query/iterable/__init__.py | 4 ++-- 53 files changed, 107 insertions(+), 106 deletions(-) diff --git a/src/cpl_cli/__init__.py b/src/cpl_cli/__init__.py index cacc83ee..a2165c57 100644 --- a/src/cpl_cli/__init__.py +++ b/src/cpl_cli/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -28,4 +28,4 @@ from .main import main from .startup import Startup VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/__init__.py b/src/cpl_cli/_templates/__init__.py index c46a6fd5..46d358eb 100644 --- a/src/cpl_cli/_templates/__init__.py +++ b/src/cpl_cli/_templates/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/build/__init__.py b/src/cpl_cli/_templates/build/__init__.py index 21ad75d9..9bc534ca 100644 --- a/src/cpl_cli/_templates/build/__init__.py +++ b/src/cpl_cli/_templates/build/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.build' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/generate/__init__.py b/src/cpl_cli/_templates/generate/__init__.py index 84b734d1..07d118a6 100644 --- a/src/cpl_cli/_templates/generate/__init__.py +++ b/src/cpl_cli/_templates/generate/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.generate' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/__init__.py b/src/cpl_cli/_templates/new/__init__.py index db2618ea..6ab3639e 100644 --- a/src/cpl_cli/_templates/new/__init__.py +++ b/src/cpl_cli/_templates/new/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.new' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/console/__init__.py b/src/cpl_cli/_templates/new/console/__init__.py index 6c1afdc0..f9bacfd9 100644 --- a/src/cpl_cli/_templates/new/console/__init__.py +++ b/src/cpl_cli/_templates/new/console/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.new.console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/console/source/__init__.py b/src/cpl_cli/_templates/new/console/source/__init__.py index 78bef3d1..406a219a 100644 --- a/src/cpl_cli/_templates/new/console/source/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.new.console.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') 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 3fbf8c29..162a07c3 100644 --- a/src/cpl_cli/_templates/new/console/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/name/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.new.console.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') 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 8c39f002..5c376a46 100644 --- a/src/cpl_cli/_templates/new/console/source/tests/__init__.py +++ b/src/cpl_cli/_templates/new/console/source/tests/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.new.console.source.tests' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/library/__init__.py b/src/cpl_cli/_templates/new/library/__init__.py index 24146cb0..e1cc62fe 100644 --- a/src/cpl_cli/_templates/new/library/__init__.py +++ b/src/cpl_cli/_templates/new/library/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.new.library' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/library/source/__init__.py b/src/cpl_cli/_templates/new/library/source/__init__.py index 6f010ead..e13d13b4 100644 --- a/src/cpl_cli/_templates/new/library/source/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.new.library.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') 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 30965706..a688ce5f 100644 --- a/src/cpl_cli/_templates/new/library/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/name/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.new.library.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') 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 b4400b42..c030a958 100644 --- a/src/cpl_cli/_templates/new/library/source/tests/__init__.py +++ b/src/cpl_cli/_templates/new/library/source/tests/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.new.library.source.tests' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/unittest/__init__.py b/src/cpl_cli/_templates/new/unittest/__init__.py index bfb4c039..869714c3 100644 --- a/src/cpl_cli/_templates/new/unittest/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.new.unittest' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/unittest/source/__init__.py b/src/cpl_cli/_templates/new/unittest/source/__init__.py index 324cfbf6..00b558a0 100644 --- a/src/cpl_cli/_templates/new/unittest/source/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/source/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.new.unittest.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/unittest/source/name/__init__.py b/src/cpl_cli/_templates/new/unittest/source/name/__init__.py index ed6c3518..38c212d0 100644 --- a/src/cpl_cli/_templates/new/unittest/source/name/__init__.py +++ b/src/cpl_cli/_templates/new/unittest/source/name/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.new.unittest.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/publish/__init__.py b/src/cpl_cli/_templates/publish/__init__.py index 0b0c9ee4..1778daf8 100644 --- a/src/cpl_cli/_templates/publish/__init__.py +++ b/src/cpl_cli/_templates/publish/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/command/__init__.py b/src/cpl_cli/command/__init__.py index 350b8f8d..49b2f0c6 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.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -29,4 +29,4 @@ from .publish_service import PublishService from .version_service import VersionService VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/configuration/__init__.py b/src/cpl_cli/configuration/__init__.py index d175531d..7b7a2e32 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.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -31,4 +31,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='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/live_server/__init__.py b/src/cpl_cli/live_server/__init__.py index 8f6d1272..de32b9f4 100644 --- a/src/cpl_cli/live_server/__init__.py +++ b/src/cpl_cli/live_server/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.live_server' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/migrations/__init__.py b/src/cpl_cli/migrations/__init__.py index 63cd6250..83b95050 100644 --- a/src/cpl_cli/migrations/__init__.py +++ b/src/cpl_cli/migrations/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.migrations' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/migrations/base/__init__.py b/src/cpl_cli/migrations/base/__init__.py index c69bac92..db9830c8 100644 --- a/src/cpl_cli/migrations/base/__init__.py +++ b/src/cpl_cli/migrations/base/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.migrations.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/migrations/service/__init__.py b/src/cpl_cli/migrations/service/__init__.py index 92ffaa26..ad460fb4 100644 --- a/src/cpl_cli/migrations/service/__init__.py +++ b/src/cpl_cli/migrations/service/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.migrations.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/publish/__init__.py b/src/cpl_cli/publish/__init__.py index 4cc2e9aa..4ddae317 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.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -25,4 +25,4 @@ from .publisher_abc import PublisherABC from .publisher_service import PublisherService VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/source_creator/__init__.py b/src/cpl_cli/source_creator/__init__.py index af5e211e..c15325b7 100644 --- a/src/cpl_cli/source_creator/__init__.py +++ b/src/cpl_cli/source_creator/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.source_creator' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/validators/__init__.py b/src/cpl_cli/validators/__init__.py index b3cf1671..cf262422 100644 --- a/src/cpl_cli/validators/__init__.py +++ b/src/cpl_cli/validators/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.validators' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.1.post1' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/__init__.py b/src/cpl_core/__init__.py index b9b5c269..e8905cca 100644 --- a/src/cpl_core/__init__.py +++ b/src/cpl_core/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/application/__init__.py b/src/cpl_core/application/__init__.py index 025c205a..1c504a19 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.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -29,4 +29,4 @@ from .startup_abc import StartupABC from .startup_extension_abc import StartupExtensionABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/configuration/__init__.py b/src/cpl_core/configuration/__init__.py index cef5c5dd..771be169 100644 --- a/src/cpl_core/configuration/__init__.py +++ b/src/cpl_core/configuration/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -35,4 +35,4 @@ from .validator_abc import ValidatorABC from .variable_argument import VariableArgument VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/console/__init__.py b/src/cpl_core/console/__init__.py index 18525b46..e4b83bae 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.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -28,4 +28,4 @@ from .foreground_color_enum import ForegroundColorEnum from .spinner_thread import SpinnerThread VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/database/__init__.py b/src/cpl_core/database/__init__.py index c2e5b49a..bbfd6279 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.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -26,4 +26,4 @@ from .database_settings import DatabaseSettings from .table_abc import TableABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/database/connection/__init__.py b/src/cpl_core/database/connection/__init__.py index c1851618..54819c76 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.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -25,4 +25,4 @@ from .database_connection import DatabaseConnection from .database_connection_abc import DatabaseConnectionABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/database/context/__init__.py b/src/cpl_core/database/context/__init__.py index 224ddb32..3667031d 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.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -25,4 +25,4 @@ from .database_context import DatabaseContext from .database_context_abc import DatabaseContextABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/dependency_injection/__init__.py b/src/cpl_core/dependency_injection/__init__.py index b35fb03e..ed9acc99 100644 --- a/src/cpl_core/dependency_injection/__init__.py +++ b/src/cpl_core/dependency_injection/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.dependency_injection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -31,4 +31,4 @@ from .service_provider import ServiceProvider from .service_provider_abc import ServiceProviderABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/environment/__init__.py b/src/cpl_core/environment/__init__.py index 587fd780..eba19d0c 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.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -26,4 +26,4 @@ from .environment_name_enum import EnvironmentNameEnum from .application_environment import ApplicationEnvironment VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/logging/__init__.py b/src/cpl_core/logging/__init__.py index 6afacdbe..8aad5906 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.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -28,4 +28,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='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/mailing/__init__.py b/src/cpl_core/mailing/__init__.py index a63daf4a..9ce6603f 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.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -28,4 +28,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='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/pipes/__init__.py b/src/cpl_core/pipes/__init__.py index 6afcae2a..ed6ffe40 100644 --- a/src/cpl_core/pipes/__init__.py +++ b/src/cpl_core/pipes/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.pipes' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -30,4 +30,4 @@ from .to_camel_case_pipe import ToCamelCasePipe from .to_snake_case_pipe import ToSnakeCasePipe VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/time/__init__.py b/src/cpl_core/time/__init__.py index 45aacf77..f3246353 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.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -25,4 +25,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='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_core/utils/__init__.py b/src/cpl_core/utils/__init__.py index 64179a2b..ae0c8ac9 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.10.0.post9' +__version__ = '2022.12.0' from collections import namedtuple @@ -26,4 +26,4 @@ from .string import String from .pip import Pip VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post9') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_discord/__init__.py b/src/cpl_discord/__init__.py index 9e01b9a4..6a44e988 100644 --- a/src/cpl_discord/__init__.py +++ b/src/cpl_discord/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post6' +__version__ = '2022.12.0' from collections import namedtuple @@ -55,4 +55,4 @@ def get_discord_collection(services: 'ServiceCollectionABC') -> 'DiscordCollecti # build-ignore-end VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post6') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_discord/application/__init__.py b/src/cpl_discord/application/__init__.py index b513d032..219df343 100644 --- a/src/cpl_discord/application/__init__.py +++ b/src/cpl_discord/application/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.application' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post6' +__version__ = '2022.12.0' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .discord_bot_application_abc import DiscordBotApplicationABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post6') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_discord/command/__init__.py b/src/cpl_discord/command/__init__.py index 9ccd88da..e434da8a 100644 --- a/src/cpl_discord/command/__init__.py +++ b/src/cpl_discord/command/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.command' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post6' +__version__ = '2022.12.0' from collections import namedtuple @@ -25,4 +25,4 @@ from .discord_command_abc import DiscordCommandABC from .discord_commands_meta import DiscordCogMeta VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post6') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_discord/configuration/__init__.py b/src/cpl_discord/configuration/__init__.py index 51110c41..94b3d0c0 100644 --- a/src/cpl_discord/configuration/__init__.py +++ b/src/cpl_discord/configuration/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post6' +__version__ = '2022.12.0' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .discord_bot_settings import DiscordBotSettings VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post6') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_discord/container/__init__.py b/src/cpl_discord/container/__init__.py index 009623c6..e8f95ae8 100644 --- a/src/cpl_discord/container/__init__.py +++ b/src/cpl_discord/container/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.container' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post6' +__version__ = '2022.12.0' from collections import namedtuple @@ -31,4 +31,4 @@ from .thread import Thread from .voice_channel import VoiceChannel VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post6') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_discord/events/__init__.py b/src/cpl_discord/events/__init__.py index d961d3ad..524123f4 100644 --- a/src/cpl_discord/events/__init__.py +++ b/src/cpl_discord/events/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.events' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post6' +__version__ = '2022.12.0' from collections import namedtuple @@ -69,4 +69,4 @@ from .on_voice_state_update_abc import OnVoiceStateUpdateABC from .on_webhooks_update_abc import OnWebhooksUpdateABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post6') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_discord/helper/__init__.py b/src/cpl_discord/helper/__init__.py index 5eb30f53..7b11a291 100644 --- a/src/cpl_discord/helper/__init__.py +++ b/src/cpl_discord/helper/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.helper' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post6' +__version__ = '2022.12.0' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .to_containers_converter import ToContainersConverter VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post6') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_discord/service/__init__.py b/src/cpl_discord/service/__init__.py index 4223e0f8..2d370a83 100644 --- a/src/cpl_discord/service/__init__.py +++ b/src/cpl_discord/service/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post6' +__version__ = '2022.12.0' from collections import namedtuple @@ -29,4 +29,4 @@ from .discord_service import DiscordService from .discord_service_abc import DiscordServiceABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post6') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 86fe8082..405c7a25 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post2' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post2') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_query/base/__init__.py b/src/cpl_query/base/__init__.py index ab831d0a..e6923714 100644 --- a/src/cpl_query/base/__init__.py +++ b/src/cpl_query/base/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post2' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post2') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index f7ff2517..498f2a86 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -15,13 +15,14 @@ __title__ = 'cpl_query.enumerable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post2' +__version__ = '2022.12.0' from collections import namedtuple + # imports: from .enumerable import Enumerable from .enumerable_abc import EnumerableABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post2') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index c47d1d20..014d5d95 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post2' +__version__ = '2022.12.0' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .list import List VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post2') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index 2f6ae095..2f388931 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.iterable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.10.0.post2' +__version__ = '2022.12.0' from collections import namedtuple @@ -25,4 +25,4 @@ from .iterable_abc import IterableABC from .iterable import Iterable VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post2') +version_info = VersionInfo(major='2022', minor='12', micro='0') -- 2.45.1 From e054ac364e873776e86b459397fb8423cfc98f23 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 4 Dec 2022 00:50:24 +0100 Subject: [PATCH 24/63] Updated docs --- cpl-workspace.json | 6 +- docs/build/doctrees/cli.generate.doctree | Bin 20024 -> 21443 bytes docs/build/doctrees/cli.new.doctree | Bin 18247 -> 19666 bytes docs/build/doctrees/cli.run.doctree | Bin 0 -> 7079 bytes docs/build/doctrees/cli.start.doctree | Bin 3944 -> 6133 bytes docs/build/doctrees/contributing.doctree | Bin 23989 -> 23971 bytes docs/build/doctrees/cpl_cli.doctree | Bin 2978 -> 2978 bytes .../doctrees/cpl_core.application.doctree | Bin 74914 -> 75853 bytes docs/build/doctrees/cpl_core.database.doctree | Bin 50089 -> 49411 bytes docs/build/doctrees/cpl_core.doctree | Bin 3493 -> 3493 bytes docs/build/doctrees/cpl_core.pipes.doctree | Bin 61778 -> 52248 bytes .../doctrees/cpl_discord.application.doctree | Bin 0 -> 9865 bytes .../doctrees/cpl_discord.command.doctree | Bin 0 -> 12501 bytes .../cpl_discord.configuration.doctree | Bin 0 -> 13139 bytes .../doctrees/cpl_discord.container.doctree | Bin 0 -> 161304 bytes docs/build/doctrees/cpl_discord.doctree | Bin 0 -> 2967 bytes .../build/doctrees/cpl_discord.events.doctree | Bin 0 -> 308142 bytes .../build/doctrees/cpl_discord.helper.doctree | Bin 0 -> 11418 bytes .../doctrees/cpl_discord.service.doctree | Bin 0 -> 342247 bytes docs/build/doctrees/cpl_query.base.doctree | Bin 0 -> 208470 bytes docs/build/doctrees/cpl_query.doctree | Bin 3271 -> 3323 bytes .../doctrees/cpl_query.enumerable.doctree | Bin 0 -> 21864 bytes .../doctrees/cpl_query.exceptions.doctree | Bin 23263 -> 0 bytes .../doctrees/cpl_query.extension.doctree | Bin 303500 -> 15861 bytes .../build/doctrees/cpl_query.iterable.doctree | Bin 0 -> 32376 bytes docs/build/doctrees/cpl_translation.doctree | Bin 0 -> 45878 bytes docs/build/doctrees/environment.pickle | Bin 290395 -> 543750 bytes docs/build/doctrees/index.doctree | Bin 27875 -> 27923 bytes docs/build/doctrees/modules.doctree | Bin 2775 -> 2817 bytes docs/build/doctrees/setup.doctree | Bin 20612 -> 20594 bytes docs/build/html/.buildinfo | 2 +- docs/build/html/_sources/cli.generate.md.txt | 9 +- docs/build/html/_sources/cli.new.md.txt | 9 +- docs/build/html/_sources/cli.run.md.txt | 12 + docs/build/html/_sources/cli.start.md.txt | 4 + docs/build/html/_sources/contributing.md.txt | 6 +- docs/build/html/_sources/cpl_cli.rst.txt | 2 +- .../html/_sources/cpl_core.database.rst.txt | 3 +- .../html/_sources/cpl_core.pipes.rst.txt | 27 +- docs/build/html/_sources/cpl_core.rst.txt | 2 +- .../_sources/cpl_discord.application.rst.txt | 12 + .../html/_sources/cpl_discord.command.rst.txt | 20 + .../cpl_discord.configuration.rst.txt | 12 + .../_sources/cpl_discord.container.rst.txt | 68 + .../html/_sources/cpl_discord.events.rst.txt | 412 ++++ .../html/_sources/cpl_discord.helper.rst.txt | 12 + docs/build/html/_sources/cpl_discord.rst.txt | 13 + .../html/_sources/cpl_discord.service.rst.txt | 60 + .../html/_sources/cpl_query.base.rst.txt | 52 + .../_sources/cpl_query.enumerable.rst.txt | 20 + .../_sources/cpl_query.exceptions.rst.txt | 10 - .../html/_sources/cpl_query.extension.rst.txt | 38 +- .../html/_sources/cpl_query.iterable.rst.txt | 20 + docs/build/html/_sources/cpl_query.rst.txt | 10 +- .../html/_sources/cpl_translation.rst.txt | 34 + docs/build/html/_sources/index.rst.txt | 2 + docs/build/html/_sources/modules.rst.txt | 2 +- docs/build/html/_sources/setup.md.txt | 6 +- docs/build/html/cli.add.html | 12 +- docs/build/html/cli.build.html | 12 +- docs/build/html/cli.generate.html | 16 +- docs/build/html/cli.help.html | 12 +- docs/build/html/cli.install.html | 12 +- docs/build/html/cli.new.html | 16 +- docs/build/html/cli.overview.html | 16 +- docs/build/html/cli.publish.html | 12 +- docs/build/html/cli.remove.html | 12 +- docs/build/html/cli.run.html | 128 ++ docs/build/html/cli.start.html | 26 +- docs/build/html/cli.uninstall.html | 12 +- docs/build/html/cli.update.html | 12 +- docs/build/html/cli.version.html | 16 +- docs/build/html/contributing.html | 20 +- docs/build/html/cpl_cli.html | 16 +- docs/build/html/cpl_core.application.html | 20 +- docs/build/html/cpl_core.configuration.html | 12 +- docs/build/html/cpl_core.console.html | 12 +- .../html/cpl_core.database.connection.html | 13 +- .../build/html/cpl_core.database.context.html | 13 +- docs/build/html/cpl_core.database.html | 16 +- .../html/cpl_core.dependency_injection.html | 12 +- docs/build/html/cpl_core.environment.html | 12 +- docs/build/html/cpl_core.html | 38 +- docs/build/html/cpl_core.logging.html | 12 +- docs/build/html/cpl_core.mailing.html | 12 +- docs/build/html/cpl_core.pipes.html | 93 +- docs/build/html/cpl_core.time.html | 12 +- docs/build/html/cpl_core.utils.html | 16 +- docs/build/html/cpl_discord.application.html | 138 ++ docs/build/html/cpl_discord.command.html | 143 ++ .../build/html/cpl_discord.configuration.html | 152 ++ docs/build/html/cpl_discord.container.html | 674 ++++++ docs/build/html/cpl_discord.events.html | 888 ++++++++ docs/build/html/cpl_discord.helper.html | 138 ++ docs/build/html/cpl_discord.html | 216 ++ docs/build/html/cpl_discord.service.html | 780 +++++++ docs/build/html/cpl_query.base.html | 725 +++++++ docs/build/html/cpl_query.enumerable.html | 161 ++ docs/build/html/cpl_query.exceptions.html | 178 -- docs/build/html/cpl_query.extension.html | 936 +------- docs/build/html/cpl_query.html | 55 +- docs/build/html/cpl_query.iterable.html | 206 ++ docs/build/html/cpl_translation.html | 225 ++ docs/build/html/genindex.html | 1895 +++++++++++++++-- docs/build/html/getting_started.html | 10 +- docs/build/html/index.html | 18 +- docs/build/html/introduction.html | 10 +- docs/build/html/modules.html | 163 +- docs/build/html/objects.inv | Bin 4219 -> 7181 bytes docs/build/html/py-modindex.html | 449 +++- docs/build/html/quickstart.html | 10 +- docs/build/html/search.html | 10 +- docs/build/html/searchindex.js | 2 +- docs/build/html/setup.html | 16 +- docs/build/html/tutorials.appsettings.html | 10 +- .../html/tutorials.console-arguments.html | 10 +- docs/build/html/tutorials.console.html | 10 +- docs/build/html/tutorials.create-startup.html | 10 +- .../html/tutorials.extend-application.html | 10 +- docs/build/html/tutorials.extend-startup.html | 10 +- docs/build/html/tutorials.html | 10 +- docs/build/html/tutorials.logging.html | 10 +- docs/build/html/tutorials.mail.html | 10 +- docs/source/cli.generate.md | 9 +- docs/source/cli.new.md | 9 +- docs/source/cli.run.md | 12 + docs/source/cli.start.md | 4 + docs/source/conf.py | 6 +- docs/source/cpl_cli.rst | 2 +- docs/source/cpl_core.database.rst | 3 +- docs/source/cpl_core.pipes.rst | 27 +- docs/source/cpl_core.rst | 2 +- docs/source/cpl_discord.application.rst | 12 + docs/source/cpl_discord.command.rst | 20 + docs/source/cpl_discord.configuration.rst | 12 + docs/source/cpl_discord.container.rst | 68 + docs/source/cpl_discord.events.rst | 412 ++++ docs/source/cpl_discord.helper.rst | 12 + docs/source/cpl_discord.rst | 13 + docs/source/cpl_discord.service.rst | 60 + docs/source/cpl_query.base.rst | 52 + docs/source/cpl_query.enumerable.rst | 20 + docs/source/cpl_query.exceptions.rst | 10 - docs/source/cpl_query.extension.rst | 38 +- docs/source/cpl_query.iterable.rst | 20 + docs/source/cpl_query.rst | 10 +- docs/source/cpl_translation.rst | 34 + docs/source/index.rst | 2 + docs/source/modules.rst | 2 +- 149 files changed, 8860 insertions(+), 1827 deletions(-) create mode 100644 docs/build/doctrees/cli.run.doctree create mode 100644 docs/build/doctrees/cpl_discord.application.doctree create mode 100644 docs/build/doctrees/cpl_discord.command.doctree create mode 100644 docs/build/doctrees/cpl_discord.configuration.doctree create mode 100644 docs/build/doctrees/cpl_discord.container.doctree create mode 100644 docs/build/doctrees/cpl_discord.doctree create mode 100644 docs/build/doctrees/cpl_discord.events.doctree create mode 100644 docs/build/doctrees/cpl_discord.helper.doctree create mode 100644 docs/build/doctrees/cpl_discord.service.doctree create mode 100644 docs/build/doctrees/cpl_query.base.doctree create mode 100644 docs/build/doctrees/cpl_query.enumerable.doctree delete mode 100644 docs/build/doctrees/cpl_query.exceptions.doctree create mode 100644 docs/build/doctrees/cpl_query.iterable.doctree create mode 100644 docs/build/doctrees/cpl_translation.doctree create mode 100644 docs/build/html/_sources/cli.run.md.txt create mode 100644 docs/build/html/_sources/cpl_discord.application.rst.txt create mode 100644 docs/build/html/_sources/cpl_discord.command.rst.txt create mode 100644 docs/build/html/_sources/cpl_discord.configuration.rst.txt create mode 100644 docs/build/html/_sources/cpl_discord.container.rst.txt create mode 100644 docs/build/html/_sources/cpl_discord.events.rst.txt create mode 100644 docs/build/html/_sources/cpl_discord.helper.rst.txt create mode 100644 docs/build/html/_sources/cpl_discord.rst.txt create mode 100644 docs/build/html/_sources/cpl_discord.service.rst.txt create mode 100644 docs/build/html/_sources/cpl_query.base.rst.txt create mode 100644 docs/build/html/_sources/cpl_query.enumerable.rst.txt delete mode 100644 docs/build/html/_sources/cpl_query.exceptions.rst.txt create mode 100644 docs/build/html/_sources/cpl_query.iterable.rst.txt create mode 100644 docs/build/html/_sources/cpl_translation.rst.txt create mode 100644 docs/build/html/cli.run.html create mode 100644 docs/build/html/cpl_discord.application.html create mode 100644 docs/build/html/cpl_discord.command.html create mode 100644 docs/build/html/cpl_discord.configuration.html create mode 100644 docs/build/html/cpl_discord.container.html create mode 100644 docs/build/html/cpl_discord.events.html create mode 100644 docs/build/html/cpl_discord.helper.html create mode 100644 docs/build/html/cpl_discord.html create mode 100644 docs/build/html/cpl_discord.service.html create mode 100644 docs/build/html/cpl_query.base.html create mode 100644 docs/build/html/cpl_query.enumerable.html delete mode 100644 docs/build/html/cpl_query.exceptions.html create mode 100644 docs/build/html/cpl_query.iterable.html create mode 100644 docs/build/html/cpl_translation.html create mode 100644 docs/source/cli.run.md create mode 100644 docs/source/cpl_discord.application.rst create mode 100644 docs/source/cpl_discord.command.rst create mode 100644 docs/source/cpl_discord.configuration.rst create mode 100644 docs/source/cpl_discord.container.rst create mode 100644 docs/source/cpl_discord.events.rst create mode 100644 docs/source/cpl_discord.helper.rst create mode 100644 docs/source/cpl_discord.rst create mode 100644 docs/source/cpl_discord.service.rst create mode 100644 docs/source/cpl_query.base.rst create mode 100644 docs/source/cpl_query.enumerable.rst delete mode 100644 docs/source/cpl_query.exceptions.rst create mode 100644 docs/source/cpl_query.iterable.rst create mode 100644 docs/source/cpl_translation.rst diff --git a/cpl-workspace.json b/cpl-workspace.json index 081ff298..6d34e2bd 100644 --- a/cpl-workspace.json +++ b/cpl-workspace.json @@ -25,7 +25,11 @@ "spu": "cpl set-pip-urls", "set-pip-urls": "cpl run set-pip-urls $ARGS; echo '';", - "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;", + "docs-build": "echo 'Build Documentation'; cpl db-core; cpl db-discord; cpl db-query; cpl db-translation; cd docs/; make clean; make html; # rm source/cpl_query.tests.rst;", + "db-core": "cd docs/; sphinx-apidoc -o source/ ../src/cpl_core; cd ../", + "db-discord": "cd docs/; sphinx-apidoc -o source/ ../src/cpl_discord; cd ../", + "db-query": "cd docs/; sphinx-apidoc -o source/ ../src/cpl_query; cd ../", + "db-translation": "cd docs/; sphinx-apidoc -o source/ ../src/cpl_translation; cd ../", "db": "cpl docs-build", "docs-open": "xdg-open $PWD/docs/build/html/index.html &", diff --git a/docs/build/doctrees/cli.generate.doctree b/docs/build/doctrees/cli.generate.doctree index 8148d5007190513dac0e5643c97c7a5f5158c5e6..bd1c7d8ba4e8a16785ea9460071d10516ebb95e0 100644 GIT binary patch delta 2186 zcmbVNYiJx*6yAGxH~VO89-6dyZSI;To6SCwZQQL%8k?GzbmO8lzABY$k};F%CL8x* zT1nZoQvDMs-Mc=j7LpcPEGR9D5K)9!i{KAS)%*}G)f5y2Awd!GkDhz)%p_aZ^h%XKbADhl zkxUUOCQV7xDH4C4%tTW%nVpQq$f!ipNokx!lY}YzxMw<^BCcd&%;hHo@dS~MMyFt1lJkBfSf3ROs2?eJRKWn%HY&M zyv}AQboT!wyEgwOD6Y+)y(?j`kIiK6${Aq)mUXVMwP%e6gIp^c<+_OMh@?lAJT@5I zYV#LtdV$&l+F~grTGF0TMtepYb$S%)trp!`o2RV*1?~Ay8JT$}wQSV8f=sZI*HS6o znhHH$+GMIxUN_RHyHCuFf>t%CK3O;UWZ^G43?=BzhETSqoSt?$@|PVUgey#R!|o}O zOJqm5MxDlT6Rjml++?C>$nciGZs$CHjN`LyX8b5zIfM9siA^i5Dr?0Pnh%ZB5qH0E zwNigW3(n}SInA|E8N`E(!*A<@hXh*yf<3#k_&tX8W*aRu-fTth(iM*fUu3`_z97WT zH}1n<=!~CpM%8tzy&wNnK(NLL&}|I_vS^VaPcQw`^)M=m+RUO50xif&fel{v(3_px1}8od2{4 zRPBuaeI9mMgk93z8t))|+uw!0z#CwL@+tDEa1<+GE zi|S&MFBZfnczk>-a8qt57)DDR-qu-)&T;5lTj0>ue}$^ir{MC?o;^ow zyVQPs!b3jN+0`(X#_u}sItTr_6(mwP(Qy*jTeNx1?6cw;3!jmlV1$9Ju<&}n?)2fk z4CY~*(P80pqWVAyKV3jEEGQn=VVmXd=s zX=<&!K~*{wH1Q&=WToGBL0|NZ$`<-}?|ry|Ew;m@6qyW$sN4u&O&9#!hjVG!qf|4v zBV4B@2=ApseFLZ_ztoq++g`C63=7+(L?WJ`KMvfR-#xf$tnUbD?@|nxrwTs1*R2K` zHCE8Ba6P(4pA9?EXY{48%eboAKMXs;{#`f-Q&cvz6MaKlhFUUFkWrpv$87}1_v|Qw zyc8olN+4~em>thB$dhoS7i`nfDJgYqMoO}ezQPzHJUYT7BRnd?BO+B&f|-!G5C_H19)4Z5BGV<|D>7b>n(Uop=Em=*?0Tk7t!D3eHSeUt7Okdi%)sr zKhb++=%tE+xRFV-b)d<_CSd40)gM4L?cQ5Uez!H>l^(6qOoJ^REHfMUZnNNfYr@dQ zECG!0zT~HS1HMjpZChNwj5}(Ovys3-ZQgS*r5k9v){5^*@p&WrUCExUD~CnFUdV=} zdz^jC5cRo?`ph8Jxe@xxABL1}$S+C1`(M)Zhmrp~;|Gr7PL)#mHB?Zo!V@$T>_ooK z{u9PVk4mx9`btvaw*?8_kxpdHi`3ND^KsCod#NJpor%8)##@e3TdU)M_VnU(9ZNu`qym7_5~KP@L0Fe^>!=!8u?Z{GJqelct5R2{OGV` z&Xb*D5&7D@oxmmwKTbRY8!X}|1#|^I%;i4rjNdI{(6!;tVw=HOsN2Ry2w1=egwB$(2Ks0%<~j3|#bk>Az{}6T%8$I{vGL*xFYha? zT;SzfF1g3b=%j6E@Xh0iQ^UtcI5^G|qQV^&&Zuxjg(Etum2wRSXgfr@=9SS8IO#$G R&$e+C&t_No>d@gM@IL^^)Z737 diff --git a/docs/build/doctrees/cli.new.doctree b/docs/build/doctrees/cli.new.doctree index 9dbd6b989574c7389d40770078ef85493eda56a8..449ea977000f906d8c53b913daaa063093297031 100644 GIT binary patch delta 1750 zcmbVNTWlLe6!pyR+DT-!K|m=nw#T8wb{yMHoHcnkP-t8t8XN^RAW=owaTnGrCpPh# z@OC2cR0FDXT|`rf4^&?2BejAANIWWjDuLi55-1W4DuE9u5<>Yv;tOVGz23Uw2Y#-1 z=H7eGz31MMFTRG>PatVgI(~7yCOHZ8`1{(N>2x|Ap2?IHsL8whcH_IMI;N}Yu4VK1 zLUpP7Y&D=ts$F$yM+K<4V$PdYx7tIGF9|jq{3vvZF70^%t_#R$2|jm6D{mdh&6jkd z_SB8i` zTg;P3NtWnJNsk_)#@|56&MO(60qKNxLX)FBh<;aS45c#~A~~Hb6w3J{jF~#kAl_(z zcDnF?irrd#gEDR{p17u9dY>&;uBn-Z{ae-5W^Lc2Vyd^Og6dAGo>X~8JB4kwU|s#? z)<%Qogs!@220D-Ulq%+wOyKei?Y6_vW@{0c`c2~er+Or=qghM+)KrI{ebKxvtPWUp z5NN-t1;5Sq#RKU?m$5Uj=}F+9n-eZu>$TYk$4dhEWO?mxZxP`=B0T2X+vck8qfdm> zz7m#2Af1Ph4Cg`*z*n8Uc#4Jfz~zXD?uYh398ZXF!5x7O91*m<<;+p1m)A4_lffuV z$PP44@1iX-odsQZ87_qngZ;Kqydv_K;H@*iE*dXEaB099ju{LcU6c4ji{OI>!LbIx ztKjk<#g_~`Qpek{@V@1E>jvKAfe`-7!uzv3#5`*5GcW$di`q7s*Jzrxw9gDdmT2Lb`LY(BWgC7@z533T+H;)`DsCB?q(r(Qd3@T zoy*KB`jbVa#Qr}thLGafDV~|)St*{8Dyu#g!w6I-M_0oJ^bd?F*v_zhjEZ4vQE6>E HIfecKgh(I$ delta 1085 zcmaizT}V@57{~X%=WKI1(!!6JZBA^uPdB%n*>rwQr8#3HWuI!zGL9pisUy0OHliSq zU_FaSSac%%> zB6(bX+jn3=uGYh7sV?)#(1P%N4!TX&odu$fp}nW4~8iROrzjZLy5*D}kqNoM)YNuum6<5AETo6u*L?4uNT zodoVjzu2pvQrPwFuxmVw%?XSXwFg#xOw2xKYkg!mbbU|w|E{lcdpC+U zAF9Z-wGCnXU6GmV_`&I&&XlMmD=(SiYRU7pR3bH*GKz9hLC%O-DT9qY#qhSXTyIp8 z!$AI**ud1TOVP1&XQQ!^3ES|{NNi$oJQXoPQLvh;&j}6(E07UlK|xbZWd9U+;YHAV zWl15EMV{000g>{amT7VpBX?+dz>_jV%OY)gOiFA@H4+{koVYwnTuIUhC4`td#FQbX m3Nb|}CRWfMY9Oi^U9?H)Pt<9qkh0U%in1fKd}gw%2mJwdmq};< diff --git a/docs/build/doctrees/cli.run.doctree b/docs/build/doctrees/cli.run.doctree new file mode 100644 index 0000000000000000000000000000000000000000..c1463960f06799092504121e126822edb4ef0ce2 GIT binary patch literal 7079 zcmcgxTW=&s74~gxkFVEAE(1E$q!zp+aMCQw zbr+IOJl0v^%)AnOpdM5Ii4CzJ3? z`!UOXp>1C90wM&2cy2@_ES?tqEE&9XhZpa{*a}6MVPRLx~CU&cNfm=?mDk_ z(uYf>p#J)3ch}gt!#35N?vdB+d2QGp05LCQ8b`fh6lQJ6Y%23ypW)lXGhFV`x8PBu z^vEa%_M2+@Dw}4J6T=40X?H91iK_$$e@ZYek1J_JFwXkH`PE;U+4c$9ycuj z`|moimzTv)FyLSH0qoO}l^B@3{7ovnlqY86FRiZ0YKHe4(^FH|vb{fJM^tf9H(xDF z?7}S%;Lv2ED{cyTYYXvoR9X^Nq;@?n}|ppHLJMnA3%Q<+iDgqRUn$@ zx_3{ltrK`R8iGG52Tu}$?^#995R@wmNdN0&YOj;`%fPhN^6Am}*fvaCg>Ly)$M<(u z|26PkDO3En*TDBTR?+$Ro|odk9vgE>iof=DtS`I{jt(|SyJ;Lc#dXjjk#CaO$b2rO zgR3LTKqtek+otbloTU!#->m%;fNN6ouXe=wC{2)>*8=Ucq~?FDtrK`xrDhd6AD4qC zNzIR}qGt%o|C5@Rj_E(tW{#b+FCK$CIu7>v{;WQs{}ChqaM@u(tyO1w(IT0Q#}8w_ z$L8BCZ`|dbW1!sdJ}rH_Cl&uNpn}LS6|sbAK*a#+EwC4cG`aX#V+kU5UwbhPE3;Hn zNv= zYuJ@|;(BqYDLaA5wh9RisFAqGT!L~c2`}g>2Ux*MN|QL1Za|M{knhi^B}M}K+E5$x zL~~e@$V^n78mi&bPS%6EwPTV-KnXokNv1OQvoy>sx!N9S8JVKLKQlF@){1!tHdLc; z*BeF#s~g$}0ieL=C4nJeRs$0CGSZ_!+y@~u0}@m{mr^fIeXx58A_HnT2*m?6@5NCU zZUPbRyI^j*{3Hj5xu&zi9f;HnM>wteS(vysn?T{eaVL-rIia+DzN)%11x@{ z?ed^tOE>islz@)Xmp-hpp3TRSFM}DguL#i%oll6IsE0rdc*te`=8c!sT0#>SpipF? zX8>E#k`96GIxWD>?Nm?#nE1z_S(6+rF$9!(9@MP#PUePkI|&{!pjeU z=UUqJMyA)2!SpXy(<4oZ4%tJR?r|!+Mh6nUt@$@7Yk~|x78#OaQEemNLf59Jb-*ns zx-)e{oJNwIxQzE$fS+da0?l5k6%pbH?*1r4UJC&AoOv%^-5~Zz3GKGWaQ64G@I}4> zWdk8bAA)*0Gn~62(#tw6PhkS1R6@xuP}=0sr6J*gi_ZgK9yMkDRBe<5KY}&r76t80trRnu=>hosEH6A&<e_#Ck@j;Yy+D7aZq_g;zE|jP8)F{yKY+S(?ftp7LoZCX8m{Jbbppum z;^T-G7SH_`(X;JLkbeuxR=P}qqBn`Wl#7e<7(ce6HQv(jn?-K@=T?!bE6yfr#k*)pY;P?$~F=^bbp zN0|We3LkI^Sa@BBBjg_fg7@=BC^ERDqg>$wl0aG&3T=I^iI=U|WWq9!ydd*+CiZj^ PEctp1DXVR9mf8CstaSdy literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/cli.start.doctree b/docs/build/doctrees/cli.start.doctree index 85ccbbd03517abd583c6359268b2e1ed2dc5a02f..1bde7025eb2db9000fb996dc8847c113b6c27738 100644 GIT binary patch delta 1876 zcmcIl-)qxQ6kgM%Tb&&Yr`xPuQ|8tc?L?e{4~n9Qqd13bzDQ+hbGMt2CMCIX?qO^L z1t0Pt=KAXYFp3B=nD`I)Ck(+~o1jm=dv467O*4k`$3xrO^WEI@o$q|-=F9MpGvb=~ ze0N|&oK4)pNmnFtMMu=5g>||@$FYbLxT{P7NsvX$bm|dk9I&pcsoQl_jey?M&Y?-S z8{j2XA()nO4nBpqa2jvo6F81D_%t3abvPCLCY-bQ@vC=;Xzf_!Zi#G4T$c?Y7O zTB9J-F3%J6rJ1+qIn<##v^89JGI=Ox+%W z9+F}e3PTo^@hF7z@F|ojJK|tu58ah@2T5ePo=2Q)GlpoGYbM}&k8?f#&$%KnT&C{> zDE_`x1lEVu?LF+u%u_LyJ)H0{+@bOPS~fpFUo0x<0sQ__0Y*tzL0?&KTC5tSXXZLy-(Kh$*T~BzXa9lPZp?D-*mLe#+Dz9ut;9XQj5BeyquYG}^wWUm2QiZh0tCq#@T3Tw4IIP#>7K OaSoOYZXD^Ii~R(N-*5T= delta 183 zcmeyW|3Z$nfpuyu|3=mjw#|3>1Q|JcSX1*#iYljU{=o0S$dvJ5v#sEJW(7mjDH-gs zQ!>PQn1IaIDUDNVr)XrbX0T;QXUQ`%FiZ|$5}BMJD$gX#IJr?&mPw9r@&Zvc7JZo1 zJyAuF6r-4lv@~2LcgruzRw&6xRVdETO-(6EOe@h#N!3p-$WbUtEy&lK zlEEH3B}1$Shq}#dhWEJ`wI|EkC<+7hSmh=bm!uZKG=ar8JKB5|W?Vb@V?fm8i2@{#za?3BuRw&6xRVdETO-(6EOe@h#N!2gTh)*uaQ7B3+ z$k&^a!5%v$L#zk4(oKfoBe}AxB<$&J465g diff --git a/docs/build/doctrees/cpl_cli.doctree b/docs/build/doctrees/cpl_cli.doctree index 3aff0849113eef39f11024a3971739c073087628..46b5c41556ae3d30e0c65b873f41f0f7f746b6ec 100644 GIT binary patch delta 43 zcmZ1^zDRt+B!!~XwA7;1yyVm=8SJrBGB|r!LQ*SArc9pF!|UwhsZg|W(+4g9aWoMb delta 43 zcmZ1^zDRt+B!!^VwA7;1yyVm=8SJrBGB|r!LQ*SArc9pF!|UwhsSvbr(+4g9Y!ndL diff --git a/docs/build/doctrees/cpl_core.application.doctree b/docs/build/doctrees/cpl_core.application.doctree index 22d735eff07e0c4441f666d274b286a6b9059499..bdf49dbabee76c5e1ef182af756c16f4d7f092a3 100644 GIT binary patch delta 6569 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 TrimoA474%OGH?!gkPZJomci!f delta 6477 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 Hva$aMx0|=6 diff --git a/docs/build/doctrees/cpl_core.database.doctree b/docs/build/doctrees/cpl_core.database.doctree index a8966e311ffa6c676828951f71b0b8a2c69d9f2c..208ae505b64c0121ac393ecbb809825a035e8162 100644 GIT binary patch literal 49411 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 cx!0W*xq(eca5s9db-

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 diff --git a/docs/build/doctrees/cpl_discord.application.doctree b/docs/build/doctrees/cpl_discord.application.doctree new file mode 100644 index 0000000000000000000000000000000000000000..64d0f8cc1e41bc4466efa7fe985bc993ef409485 GIT binary patch literal 9865 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 literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/cpl_discord.command.doctree b/docs/build/doctrees/cpl_discord.command.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d0fe4f61bd874010b5e8fe425d807ab2d4da6ac3 GIT binary patch literal 12501 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 literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/cpl_discord.container.doctree b/docs/build/doctrees/cpl_discord.container.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a3f5ee12869218003c02a58452875d6f0e796b92 GIT binary patch literal 161304 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ℑN5|_KSnk8 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 literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/cpl_discord.doctree b/docs/build/doctrees/cpl_discord.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a373b278156008c64d159d65d69deeaa714ff455 GIT binary patch literal 2967 zcmZuz&2Jk;6i<`bu@lFM6T*ku02L}tMPnnx0dYc5Aw<9jiZ~!uquJfDXO!8UWo9;U z4wc~0su6SR@c;6g-Sv7Mh-78wea-v$y*KaA&OdH%qx^FRCg&nsjA@c&Dq+UEUZUb6 zWtsJF{gc1^OMmA2nqC`K=$Lu80g0FknP`^z7v2qnxE0cjYyBO=Vk=bEsPhi*@|_p{ zjQ3r~3M*NQ-os_N#i`< za^2eJsoRz!V}4ph)a_DhwTKFfSVL@EA~7M3omf(1K*V<^qiOZkONxATh-iEXH-k*! zb}XF-mgfijJ|FN0e2bsD-zQw9Y+|lhHkrczSgIl+&%^O~%rz5{MZA167nT@)&Js;$ zmL$;NB+lgo{+mhV_XKB>RM{D8g8)Cg*eoJsrWdO;S4Ebz5?SS#Z@@1VTg}=@u6Z9J zUj7id{RF>9_&vt&34Zt8Uh6L80_oJE%)r^yz1QN6X`V|F)3U&?{nQ<|nQ$wm@G3Aq zSZ8E2F)#E=@8k~KQdCHnnn!IGL*}gcFP$@)*YayF7^bfTF!b6pHxOAYi-gUDtYYEc z@NfAu{yqPJ|Hyx0u9wn9!g9;~#Wnyy^D->JWiD0ZZ(Wy*BmvBC-F|JVA@s5$jeyt0 zUu?MD64gd!@&>ZI=$2Ii3;r4Zf}irIsNOb!G64vAyAtl8F4+0CMs^VtZ5Jo#pRWKG z>;T8CG2uovM9xI z(FRLO)o`w7n6)CCW3G&vK{3-RvkW+K-QTDzP@CnX;RjRKpEDqVTBU)aenQcxmZmul zd(|}rwl8tqt&fG4IPD{gBs6H?;<`>K!HsuEGo@^%ENd|@?z#OirBFk%m?@olP=*GW z&q=^=3Aw4eUs0H3C52oIizcnd1a7Pq8p1%cTxm-rKr8*lrrYIIHph+|u|?>5OKoA6 zLLJvhSX9gr!SI^u47q}YW;6w*Z#9is2+F^4Ly_f$C76&Zfs}Xs!p_dWIyVB}57wE4 zX{|KjXhsP@p>T*Tw%#46!meBClvcbuy~DX=upLOMi3a-du+Jny<8EvzCd zlG_wO)P7Q=IcZRbtd;};!0C+2VDO-%AhnqZwO^5P!-_a)!YMQYB91LN$%b7g-bBE!tg8N1Zf$P9o=iYCsAusV^MSH5|LM{^I+X^zUNSuv%+AU?(DM^+ zQ;Ey^mPTlyBuv|$I|U$9()4B%05N$$$gMjxH<_gi!o{3R`~cojdkS;>hsfLAJ7wPM&WEQ~DhuBE>*DUszx0XsrYxXf~wGG4lMmhX(bpE^G$L8hNiFmnGY) W_Xj{`9;&sQgjrXQh4B6s(fD7Xx1Nsx literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/cpl_discord.events.doctree b/docs/build/doctrees/cpl_discord.events.doctree new file mode 100644 index 0000000000000000000000000000000000000000..00bf809b93e88d36e385b81af1f5f4226e29f5e6 GIT binary patch literal 308142 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

    ?%TuGKVQbiJHr#WRm5+h;&n%$XMNy+1ei~)qbK> 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 literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/cpl_discord.helper.doctree b/docs/build/doctrees/cpl_discord.helper.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e661717e72b5189b3d434d2b4920dc1b258ce375 GIT binary patch literal 11418 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 SyVOj(Xi|_!{i#ZKJO2a2LTAAM literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/cpl_discord.service.doctree b/docs/build/doctrees/cpl_discord.service.doctree new file mode 100644 index 0000000000000000000000000000000000000000..8e13fbf26d7a8f52e16e67723ec4929a4781b0a2 GIT binary patch literal 342247 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 QmQ&L>EyHFoXy57ke*-J-S^xk5 literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/cpl_query.base.doctree b/docs/build/doctrees/cpl_query.base.doctree new file mode 100644 index 0000000000000000000000000000000000000000..3d440b8e8a88eb4f170b615dd1b45d34edd78476 GIT binary patch literal 208470 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 literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/cpl_query.doctree b/docs/build/doctrees/cpl_query.doctree index a505b70115838edc2ba6fa36574483a651490302..3f98dae19defa8aa2106cd9149e5c16204f99101 100644 GIT binary patch delta 284 zcmX>u`CF2ufpzMKi7XQsizZH0U@Y3Wt&p*vFS#HmzOXd4s8TN}u{d=~+Z4YZ5rkN3 zUTJP>QDRaKL`E1%rlKS@uQ)S553EH9A(2@E*O1!7lbM&CQ<{>RmYI`UJSBFDMutO% zQ-({1TWSwSZem3WS872?#uTsrKrp$MX*H8K*Je%T0w%`R&9hiPFw4Ye#1!{%<|XE) zmQ)r14XB-x5${)=p$Md7HZS9x!pQh;vNg9B>zfSejF*$MxYZboCQsy629u(bPjT}x o{+ryuEIaudw-nDGkeUqH44u-X)X5(iB`2Hm7&AVfoXHah0Ov$-Pyhe` delta 209 zcmew@d0djEfpzMhi7XQsgC zaSvx+Vs2_lWkG83l-em7(SF4liahq{PV|86_uc@<{Xi04d3k&Cn@LN(BpM@)$Edo;;T)4gdpwPyPS^ diff --git a/docs/build/doctrees/cpl_query.enumerable.doctree b/docs/build/doctrees/cpl_query.enumerable.doctree new file mode 100644 index 0000000000000000000000000000000000000000..db8a26cb658f0aca56a6f09fbeff73f0aa1605c0 GIT binary patch literal 21864 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 literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/cpl_query.exceptions.doctree b/docs/build/doctrees/cpl_query.exceptions.doctree deleted file mode 100644 index cc1ecc2ce04c3a03b87babb525649556e9ac6280..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23263 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 diff --git a/docs/build/doctrees/cpl_query.extension.doctree b/docs/build/doctrees/cpl_query.extension.doctree index 64add856d99659f03621a02c9347b0361d5e6d47..6e010bdc8033a963f1d6c811077466fc0c026f22 100644 GIT binary patch literal 15861 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 PfZ{0`dJvDZe((PPAB925 literal 303500 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 W^O&5`Tdrhlh4Mh78z|R%=Keo3AO6t* diff --git a/docs/build/doctrees/cpl_query.iterable.doctree b/docs/build/doctrees/cpl_query.iterable.doctree new file mode 100644 index 0000000000000000000000000000000000000000..38b30928e5c908af0366cb8cbf775257e88fce5d GIT binary patch literal 32376 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 C9fP9) literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/cpl_translation.doctree b/docs/build/doctrees/cpl_translation.doctree new file mode 100644 index 0000000000000000000000000000000000000000..c70dfd3f21c0a91043d68d5acb5ddef94e0347ca GIT binary patch literal 45878 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�jO%3y zi_BJ2EN@?cWJ+(4x->x1uoG-pM&3W>jhc#Nm@c{Gz40Oppd9i3UEZKsRQvY2Q>gX# zZH(}*V?}jqsF)%C&{!ed+EDFA-?i6#Upe-6#z&NQPQPnV) zME$%s0;*CqU!p3A3MK02yg{?b`()iI=1$&4Yk`i2aUW{77Mf!y8fta2OEmZP6XJHZ zNH1TUjYDMFDbr`=E>aG-0K{6Rmw3Zu(eY5-DNH)nFm9E7%&e*!Qz$4}bs3V|$De^L zeXdzI`#`s&JV)0Y$wSgWe$bmjZaIQ4SY{wU;QcI%q3)+Caxr-%nQ0Lfy;Qb{>MFVZ zMd1@hi~CxE)8)=P#!z9HQ+{*`-YGc)f1aX>qJKJ%iXw>}EQ!pN7Ihg3XKm`Lq@sMZ z_`pM%S;<^*KaX8<`{_*tZ_B3&Z+i^qwxs=5Z{v;A3!%VzlExc}wL+%Xs@R19^{D(n zQA&Hu-*p|P~2DdMYwtO#jQ23ij9DbrPY#_*4}GpW8&kx zmRVZ6yq{(9)^?hrz|xwv0>9O1H*w2Kict(oN^?uc^t9S|^rhu^rWTHRBg-u+EW%8m zpD!vD6!O({$SfW4Y;Pbfiax9E6l$Gb&zNG?q<@|_=^bh5YLn>n*OSw)_C`)sCU{X@ zCUB>yk9z}ZF~YIBQ<#iUL*^^B!30c=DHIeJ)O``IHa@tuYNNn2)FoLmkUHbLy4~54Mo>j!Om8a` z5t-LPB|$J*8sf*i!L#W1qjjfHOY(;q3(Q(WINSh^2%FFj-B4k;q_(aV-sg>wswB5d zmZW=RzL+4nTOa(EH;5M5f4%M$CfREUbEOZM@Tf6`g5vdcUxe#}Pi?I}Q29I90L^zx zE@;~&b%B*UDwV>8*UiR}z_%?^3g>x0%i^vDnqmu;!fi?^xX`*ZiqduHWe9i6=RE8 zD~hl2C%!{pxMnHg09|d|=Z&7KY~XMvsMo3lKI~)i3Vh-9%xUA*>^WGp@WPfMfDdtZ0 z=TG$e6kF&ss#YBu zGPB)Avp-%Lj`fQ@dk<_H_M~GEiCSVaXdni;6eZ zokFe2Ba9Jd?IkM9J_k2w4N8(ZbVKO`8Jg>g;kDjKsY-a;HPGH6kMM4_@Sr!47V#gb zJH_0If3vg=bo^+a^Q%!xhdL@z&UhoDD#7ivf%Xzh+UKG&lyz_LEK-l^PGOR|hWb_( z0Mi*YrchAqsQV&3e!TCzEwuplOGXwA^D^51UrO!&^WN{}WWZfy| zPDj$%NxBzkW6@kR=2i)xX9oFlg8dSX8~l8!n5g zhw4r-cdA}zswk4IL{)b^ckTdH?aS-(U+n$TRafYZg;ExPFR0~yp*K_(HNU3r6mzGh zYR+dcc$G@-+`)>n4(qw)jf|>PzP&P)i_GV5@`lf%_czv^!lZW%+gF*-%;>5yg@WQI z>M9p*K7V3s18B;87M-Ot=JStB^Z8$S6Ufbj_yuw0Lm}x(aZtwfd#Hgwgsa*PUYSv{juXGR&^l zs@sCj8Kx7LZ=__@yKiyjE zdLOVime_)+!H#IrHBj;{XEm zY|Int%)hh}Lmv$IrQ5 zO50}_(iX@{z~qqilipxiWc^s(DdtXA>Q8H&b3@Qc~~8Dj2v z=4?DEOW94InM2HYC;-VJL-ZVwlp)Pz*(B8yb=0udNXf4-u2Kd~i&LdMHV04E{3$ zLedy!1ijY#)vHp{4pQM`M@t|{2^fMUXB9r^4V6XH2kK7o)X;R)Z=J+Fcs?|xF%FuZ z@qYCg(3F5FqUpLfR2EG~b*Gp+P4T49%sS=g1iRKJ-kVvU{NBvE{MX*ET9t-&(F|Lc z9EzM3`LDd;v8ea`b*C_?S0iqqLJ!Pitucjy;!IsjjfWo2J8w(t;*5h}Gl7R+m4Syp z@TQKN;qc|k0uR6E{Va=_eut*m!oY*-tcTmnn&5%t7px|@3Gd})b7S7U(F;o1)4{BRao8-T68~DcM6m4HDt9C_e@UI zm_kAEzPb#|#r>DJHqyKo%nKIxWQTlbyvFKj8f=i<|DJDYj7F ztI9h<<5D|~;QaP++yXmqt<`TqJ#^OX${zp?bol`0b3NjXj*6(C+CG;FyadG(^?h%s zEFzt(JB3k2E@!Kj76S>*XXZ!j$Kyt(ca zb0^Qm26;x~6zWQ|6w0}W5$Tt`U#%*UuFfG62hpO_zxRg3qSG(box-G34Yj8?r}4;_~h=M-BrOw%inITQI1E7L1!h$63Ce6pOq5kes3(hB@Di2nS{B|`&pKRxre66moT%o z=ddH06Q4^Q#|zEn0oLyhhrPJn8pngaBhQ7ioN!S^%yI%}fy9@ZMbCnr^u}978cj1D zjT~Gf;6w0q=-e5yt~Z<(eWSWlC}Uu`?i5OHFfQAa+_-ZyP)wGSy<2ONU{@2x=R!MX zWX2by%=kCn@8;%5e8)1G@gv^PvUutTX^LE#aU}N~sAP0#Vd2KtZ#)Y6_yzkH7P=24 zFNA*{-bha8U3f8EpFZ1#OtF+OdqcK|Lr&m8B`5fOVj!k+XrL|{e$^X26-hD8lpqPw zV1Ohba*Koi>J6Jky8l#n3MCHy1Ec<|6$2|Z%fXAJF@$s1qH!zhV6sxPoS~A+5Xq&X z%Y=oFqpxA^=0$wdGVy=4_p>a{x`L+275_7r{+O-N zRjGziA!Epon~ z?i6Z?KCkW+N>DJS+LWNUbTd#)mfyCpaLxk$mprkxE++0M&G0u5h-9S2rBYg)_I^z_ zSK?ciNsEd1vn=*XX^LEFF?(YX_l-HwxdhH+v^q%7fGyE&!O=;^zFr)bkrIpwav0bV zd>9iB-|vl@ie$(h1+NJQ10V^HB@{NiL9?j#mbz0Yq42$o@UylPvGI+Qyl|cf3nc36 zW{S5v$trJW zA-k2)@5A0NT9tm8vOAl83|IVwyC^ykER3DKn*vwk$wk z^39o7c!On;^zOP-%$=lpqIBF%qn4ou^F%4Xm#xQv_p4SVVu>i_P*^Ln=M9iWzPRob zb0;6$=3{g8`hcCxTIPSyX*f-6>3})`%LY zzytG7YfPb_7}VADJVN=gt&KNe(S*_>yvjm%nvxr2u;IPlG;*^azG7Lh;WxdXWwF%% zpeeR6*ns`hOXxB!dKvAQOObxZL@wPkBRV5%d#vr%h8N~HXf0+@Uo@GHg$PM(oNCb-cVT--BEXnxl5KpX4LmfP8) zf&yVpLv*^n&iloy(lxU$#I=M87B@vtdqZVWbW(SUxls`pD*C8#sY zqX=3cc>k+6OcpKwQ{5@%PRndER^nr!xtb0p(2OV<#IE|@Y%*33JHdvXpkew#{WEU_ zRHbXlLZ#OraNG;^Qx25mWdn5r@49(j z?og(=tF2)fff+z<5^whg%_8vyb*Gp+iSbN8r!1zlCzws^&>+3F+;dSG$2!F_jRoq8 zu{xm}-l(X$lAU##lJ}Yfl!D1k>zloyvuJ%|-6`fy>)T6c&Ff#l4TjW&Gnj=l6j7Yd z009r0L8tpe-e{>xcW14gNp}tz2h2_US9ybI5&xBSr#O3vpBu@nOnf_(dCD6tb0Izh z%uW2UH;5MTAE`UV+=>5!sw;mO_n`uRGVHk5Kh9HW{o_2?Boyb-rNBG9QB;)?oEx+9 zqyU1)p>uP?+r8nmxZ!PerSGhQ7XQb*ky4fPndV9k8y`y!n+&kRW&fw%5L%S~ zP~9o!PWk7TD1o>S_0uWs$StBjPE(`<^l4mNuP|6t zUdRvI;8Lj(w!vX`*ybj01XNw|Wnmjy@fdt^i})knfLX-7q3#rOCvJY&h7q?$*oKkU z4%m*OWpf>l!(C4N$QvP5 z$(=dmGEajeScM+^&>KFB=4*AQI7?`r>%Lc`x$V1uzc)f=PxB(jeZw0*i{@{sJH=T- z^ISiz8qIAd?N_`JGJBdAd1&wUhR>q;yXsCccbYd!?DR=r2G$*A4LG{UJl96+fte3` zqhqEN*PwD6Y=7(xpGEN}>P|6tikBH|x$8SW&&CWkdu5-uG%xR~lEGHAs299Jvq=2K zvzElUWoU7KJ;q#1Zq6mQ42_L+nQ71R#$?sSTvCR{Kq@rRuJ?w`qVlzMr}T)|Vh|PDK-rbJ|^kx;RcJ?_0f5P?fxy z!>Vmxnv*v_IQFGT{3;O0p$8trqps*bt`z3EQRHbo=BIYzMijV!G zH*6M_f3EHnbEk5yMJ=d2>AQt=u0<_~Oat|G{6TLdRHbo=Ma^kU0J#PA2fRVENc{VC zr)?~#NT^EWQXNbXH4z~9 zTJCy-W|26mJH^~d{MWguvin1WD!uSup(NvWkUhF3kN^6Y&mp7yqPyBA(Ddx@-9-1N7PxBB9w#W7bZ`4%f z15eFRH;@(!e7^1!b7z6vJa*bTwa|nOLT%n?qXPwpmKT?s$A-}-=x7^+r%tCU~L8%4bYKz`0qW;|-?83az?R%$*f-HUbb0=|b;8x%TikNaVdv4%X429SZ4%OxP?|CDlDw#_Hw*n>xl3R-ZjyG@? zq2E_`in$XycYmnBj3jiPF3;T`DrS)Mw$%9Fc%!8%*-Q3^3eY&&3sm@DdxK~Z|1axK zF?ZtUHUts)LDwy(?MrS$5HS`VHyo?4^DA$im&aDp5JUjQVRA3@%e#uyjksulPSuxszjW1QT+)b(AaT?3Mcy!3w0uF`DdtYg!+Am2G#X9T zTsgfrO6M(EURd%t#7Y91-^tq6EGIsd6QP!>5Kt~&> zknHdE2GAn=Z`Pe+?qtt3mQO{?-NE2wQ6G(5V_A%Kk^8T_QBjrLCC0J(ADm!lZSL13%Q6A?%om8dE4Jezoqw2K>yBzke#v4CzL_p>fVza=Sb;lk$Yyy%#Sn93I&GBrSSlQCgLPW5DV~mJxa$0lBZdrAjd+uM2@A; zd@S22bj%w^ZlPe&W9rO#N~koTwD;loS7)8S!W%q`gm>4SLaoP_*PTL11;$95k_v}6 z1I1)HIk>fFonMr3D#5~Ahf}XIZS<2n4vJIGzr*|8+-!*NSSA);@BJ)`r~VmDkt-Hv ze{ONMB!(k%NuE8zo1a6iW2c8cfeYKyY)OnU#|d`)!-*!J1I$KFF(xN|)Ej9P2{e6y z%ZoRl<7ZQF*d%C{xcFgjC@s?d>$+1Yaq+Jhcg*@wp=_E=V2JP0lZV{f%WRrWlNkf$ z>Go_OqxP?RBcUp_om*B6kod9o3?Pff|J@rli^l(d-6`fy<80lNftM_e9bueo-IFmo zOK3f$^XJ~^s7h^TXC?zKo!ai`&ZoTLvnc+Fx>L-Z;@J)125!*S>-FFa8aP!dqdKSA zLlBH%Xy(abY(?+8eKvNtrC{AB(i;Hj@K_6aw>M}Od3V&EV(#S48uSKQbn-fubJn0Y z#_BZI7xV4jsHnP_od&%Dl}2dyTE4{_Jd4;z>rOFuVrLJ0HBggdm1PfnHO81$*w=f% zdR5{&4}3MC$+x>+;|-TZ)mPV@V(wHevAZ~u9P78l?&1UW#rryMBvhquCA*75WDtIiy`VJ&yV#wCQljL3IJTd5Hnhba&iu_a>caCGN2& zCQrZ%Cm+N=AHqK$hCk7C`&#RCCmN2s8~^Cb@ZWS>yEPp87aAVYM!W%a_gZ8K~ z8cfo5gnkQ0S~>z;zYOL-c0My)e+yo6vfT2Z8HZFYc*ZB2TJS%$87Lt3_Mt6a@PN<- zoi#Hjct0!`{PySgBGG2n`V2SNh`r{6Yz0wfGh&OsqPeWC*aj40Y?#_ z1KbS<{qWul{lvXG`F_d!RjZQka1Qwd6mIJMqBlGi^?t7I6mzHEVm|fOTfGT*AQ>fz zx91R$-_BIz2fbgoDh;1mMnet5pu! zBxluOoZ>PZni1q@q#%FX``z69hwoS>$lv7sEQ_bUo2JMWHY2%@jP9$jWq)TOJx7FH!v0W_MKd~;rvz}uw6?s!wl&3yQhWfHsP{Va>AzKN#TLW#}X>ajxU zlK2df&|y5xZi1MyNSe3>iUQQ_C)n*wa(}xwDk`FVnu(-20by`h!u#92L9(dxXx%B) zV*6%B;8_cA=2g4U0W>Ns=F1sl7W4hM_p4VWXvV9~fhND0@85XCWl{A<>P|6tsd^sQq`nr|%Z+OFI(fHTuPBC{HKaVeV@{fP_F#Aasmw&GhtWMssQ|-6~agS5H?>cU4nWJ%_#Unf1Yr-CoN} zV=rFc_qF!od)I4!zSekIv&*;s>~FF0iLo)ZS&YHvFz`i0zI+*x8TnqmSJfl!{LwvC z{qh&TjEIbkJl{Ux-aCLl?t>qEujQVnpRllcEh&d!NMAy)7ml~Y#A?gw#*#dyJZLLah1*Zy+t$r%G!0* zyAZ5vRWm+STUOAF#{>~=#?znpx@c#oJzj(R#DoIZ-PfikeoyVHC8}}#;wu*|gP@!J z*4k17g}$pPgzMm*FgA&ee6H?|o)_5xe>(PuJ7C-U`i1-2{WXk=e9qQ=YZU*>wfUzi z{-P^aa`}PY|5I(Df!=??C~YaGfvKJvpvEctBiPpOf(3O$mw8c{zI+be+A-|TtzoW8 z-&_b8DqJwyr4JX;hr!UCEqFG5%1?sRpD)HQXmyP~UWOl8G6`R5-Q8b+YI=W(KR$*( zK8`>B7JqyKe|!>udEDCeO?cSAxYtCzpJ~<& zAYArrqIClZ7hK*ti7ucIe%`sA!%Xjk;T+I*h;qHFw$?Sa9>B1oRUPnaYRd}Z)~g8O z9CpB$=N<4CxO5lpV(6R_-GSBO&e}Cg)Z+ScZU1|1K_KW4W@<|h^m=zw2-j5ZFs6z1 z!;QP)+0(1b7~*+1Z1vu)O*>WZ7hT!OFYn~RU8F*Sg2EMC#H zBKhpXGtO;%yZ}-F;YhvTDTX57Te~W{FJYCcBH?${mKC_rzaxlfB%JPy0@X=oaB9A` z`PtcTLA86ojX&OxKYj;){CE8ELHHqZvU4{#acqh?*$RxH;q)oX%JL(izX0`{Fe@`I zGf{j0x0A4deCVIf?VQAmyxGJpr@G@MoRknj!1gAet6e!g0$?SpBEUb^mK8*Re;|lx z1epG0#B-0}L8L8%#Vs>1EQ3?ga%^nX_@Z0tdTOE?*RQy8j0~g(bD_4c|K=oT|iw;zOV^fGt zSN#<;@MeT@ho&`Ghl3tmNTo)R$7QJZ|K{x7xqZ(mE&1J%F1w&+0hU)2<1^HqQUQhWU8U;UoZmOkuS zR#pE4waKTd{yA5k0_oR|t|i%l;=i}H;6U-;)fB>4e1rVT4arQO-T=a}_+-<}A|H}{ z^4z9q+2MS_cWsqI>+)c}y}YH57m|xxZ3X%#8WSE`$FxiC8{wkarzmzPcE)}BAnKCaIuZmV5|RR8~qE4zk+N!@Y| zxenc->^o}{2+VL>Q;1DB!)4qIGkbTd8N@ldY>-VUH8p=LxbAt!`ua^hMkK2uWm%67{+TG>IX1rCJ9-;xIN{Q-@!E+3&-O`Jz|!x<=XR^d3yzM!)iAfVUYzydQfD=<`{CME z(?bweu_^@pKy6t;2>M=vh=-tQ&s{xdX0Wn?${Y( zg_|<@joOj}b^dBo2-hk9a#IMG8W^Ka)Iz^&5*E-xFFdy`^kqj!9X$69uS*$r;5BYE z0?lU3Z?&C%sdfc*H^YinwbL)umK8YGX9?n|)J|W1d)=NSQGu21^d+?=2kLxbQwY~i zzoIFGYp2Gj6SdRNGU>#K2-iAa+!VsKPGi)GTIc5{Y@L^!+tzt$ z-a73}sMazcs;yYvv9M}YE%W}`vI18+LJ&`-mU*Ujr4kib*)mVomK>;a)D*(C%+;n4 zu4NjdPSi5*n}h}QoBwcb^V%zLj%aSJy9^fqY{BJ&&QP5hdT;G&>CT1Kt7@G;SzA`% zPCrf%Po>uR!P=EdRA6Q6{6KBVfjZyc6vDO6_ceuZtR(VzJO6jdKP+(=Nd`+3;cR&BU^UuS7 zJ?(X|fnHx#hE)dPn&&H;Lb&E>tUFQj{PJYYb8Y>y@nF6MFPm+_qB*@n7hk~pchKkT zc}DM3`0Ik+Md0i3=~?*e>Aeq|zx|2%^$GlSVebp($@9&VAIDGU_x{oR`WyW9jNV`4 zuc!4sXTE$oKKZQPUztyzF~9x*e?6mj9{%l_y=R(Ve~Vu}z4t}@bwTeB&99H)uM2yh zHh;U!Jo!=l^vvF$;;)N)7vPr{^uBB!c{YAJzxP@E^t9fk=5Lqduc!4sWD0x)f8Egg zym{mb{M$wJdSNJsFH!}0`05+L#P?M|IlOBfKH+`Iz#6Z(gD3H3A@~w6AAw(ZN*%t$ z(7DiY6O% z=FKaDNAMzL^VMSaIQ!~ycxpWCbXxhVh4HzoN#XF47731Hbwj{PA`83C+sN5&qPvt)0#;W4e+WIB<9(8C# z6z4`8-@LK@T>IK|@$It~29Oc<7uw@CHna8f=jqq8hl2sU1O3d(++ca5_k8e!^=BS7 zpWd~Rzn~s(q}sp!oKbgf8FqYZn}aKlU|*U2yuGtLI0c`d(S_HzkKsShUg*F&$I$G2 z+rNGxyiC2{UV$R??)3fZmvu*nI{cZl>le4?m!SQ_+w9@(_3M|k+WkR)#(lFkw|?PZ z4v%(Y0AD)1=e)J`i|3cx{o@_jMMU+uF#iZ2)-Sj|dlTSXz5b%n>Qc9VIx|%tWvG+2=odCjZ+OA_OK}@Sesvx0gcySYJHzZa#j5p7?!n*L z7~Ut}UKnjG9r*f<_2=#HoZ13o;v8-ZFv&K?8}HcY{W_#dF**2FXGP8!b^?N8+WmfK z8K95AM`R735`}g~MpqZjcgMyYV0rusw3mNFJ?AC%69nQ#{AO((uH;!o#rA#_c=uie ze$o3e_@DHN-cQ0;`+GlyKi4lN`yUt{SOp)rblh24g_kyT4uT`BjNqH+*l)HC;d<-+ zz4ublpQfL8L%`bK`x*HE+1}5>&qp_UKTp44?1ZUoZu6zCrC;p5M248CK?zLM;1?!p z@Cy?)_=SlY{K7;Heqo{pzc5jQUzn)DFHF?n7ba@(3llZ?g^3#c!bA;zVWI}Vut$Pl zrql0XqW0*<)mN`SeYM>kZmhr2+!1q|+dIQn6*BgJy7heh4d(G{i=8&?iQws_1N+C| zrO(8@bIYBL^*gt@1&eLlXSQ5T3ybJ@DR8gfSbs~(bD5L^9*!(}UjWmr?}Fw4xfa}k zdiCo;yxlHTQV9r&f{Ex|o@C-dg*7`Z#cI_)Nh z1b@A)(kA({+~aeJRs+8*UKt4x><-aaHT))p<2@5|G=v1xBWt5h z3pz*h(!iZZsP0#k0nyr*d@s_$TY^gOn zx!e^I85->NR72wPN}~ngRxi|U4-{hQq&s3G*?RCctPb(tn zZ3Q62<6BY!2n}w0dA9bH^d8Hz1efTfdcBJ6y52pF`PqcQQ4)+F%o#Tdb`_-EfT_X& zGB*SxTGE1*;Qbi#X2GX^mQz9g@MIcSsfij;Mp>jBQ}UCfyh5!xsl1>gn4*sanMYb@ zql((X5~0a_Bw!_YKVtI>FA13v_4_99kc8}Lzh$489aXB@4WR2c$KsGEkG+pX5|kg3%VR+bGbQa#(4z#DB;z2VdGZ+tlmz2PB8knEcu(NR z5n`4-Wn4D}Q-@{E8y@b!I2I=oZ}cY;)5`G(aA1aKU;7ZdK?+uIfX>Ul-b8l^0aWz3?xQt zE3n*e5ZqpYngHC=j|)p5%cqp~gRohU1@RM)D2ts0^@M@xk0wRWu%gljd}>yw9jMP^n^K?5RzXw@?(K3{tS3$P6bZBQm>P9!Z%*A< zEkyMe(W?_X>ADUgZ1&LR)QdK<@#Zvu-K)#pQF=(KT`O2l8F%MhsCsmBYL?f-SgS)D z&)ot>riCyZ(`9pTY4-8qV6Bf6|L{V45H;G|$E`s2_ z!_LCg$cdTsnq~zag4o_uOYnBEsZpE6F#DwZDQ&|9J% zP!7Mb{>oUFW1rxi%o}D*5P|w?`7T*HF9%(T+f|!?hb#8! zv^NJmg!gdJ=L+dt=WvJk&>tf48ew{fpUrhdF0;5QK{8?sc{k55ciN4_y{=LmLHp7M zqhMV*rE)3K09r`9!=yArJY~>Cp>M3NA>~XYKuEp?P95MnG8--IVbnpE|*l@5f+Le_2g4Gc;8 zjeO^tB!L7kq~1d=+?rn-j$jP1I)L|J!bXcGRlX^K0W?Qnlwh-U)LDkZLQTY1`?A3n z@^&I2Kk7G;eq&|jHA#ZYtfHJIRBlM3;u%~pA+7lBq6w8Wt@x4zm%C6aOM~SFGE);0 zS&}{q5kmScqt$NHPPsao=iox(&GbgzCiSe2t^_Tmof<-ByE)PbT1dNzi-IvJ%cZRtIoj*021-2_2>bc*CME`2W8~9zzVFl_{#I5pfFFzqxuUWC$1N?DSxHtt*)KkA=LgHGX*>OSZqeDDMTV6$ZKoot({}2UnIg{CoopVP zwo68<$hcwC)nyJqadX}e^cOqsUJk2uMtZ|cbM zq_t&kPuN(0T`Yz09^_rl*25;PK0-Gzl%)|81bP{ZzxcA|c!? zTiB_Wm4mlQb;m;f?f$uPn@X0!IPu~1Vp+M&KTEz7mfcrdR0QrKP*eUgJjcVGqE6wT z39&{W#q~+~DXaWO1?Fsc*~wgc)XD6B;C$E^uB?PKZT%YG;p{WY!`$ia+L41E&Y?8F zi(`TBxsi4JvCNkuTwqUoZM@W4U0#FNcCm@98gM+rbrGosK*lHtZoB5z78g5m4WK?d81-9Sw<;WVCoRmAEQUd^QoKe@N7t8jN*zzPn#^aRW-=n@~cUD8up+m@u%c5=U&pcxTXrlswmbA62UY@4F+ zX$3^aQ|dgq2Y#}2?z-s?-Ms9!!)`VGuGU|}V73oS&#?IInw9%*WBul6m+hWXOY&ZO z|Bk%Zo++e(4+I;TiUwW|4PCZ7QI=Sy2*i$ouY-FbXjtwX2e+{LG`A~0AR5xXs)m#V=^Bn(0ISVQZ76$78%i2Eb{^lYXue zyhZNa;nGI5R6@U}8WagZ!>pkhKN{xJh24%cYM&8gXFqp~Ym&nJ5CS?@6CZyGYR za@NhImB|7E!l;kneLo9xco7!*wRFd(5?pg<`CwBpxYCpbTVo-&$;s}|+iiNv`CN^7==BU{H!7B=ap<9j8yf--#1oK$Zm@WW16_%8xmkT=77l>k(^)!!DUAhoqhK<5sRH%!B?w*#!h7rXy6)|M3AJgm=)nbDF zGAeP?YN7R>bVp(1-ZP;N?vBE#SR(98Ta)#r2~{{U-BzLWtaB6htO?b)f6CQR`&p_< z(Tz3fXU~023c8|wFQ856Pw=uY|HS8{zU~>ElvY#-N!TFIcykxHfSB9Cl`|-8QX%J5wOP3Ot3{w$!=51+~ znBaUYzjvA%*fc38c1=;roR?sH6mLe(!~Zl1vu!O+JRxJW1YcO&0lql7J59E1ZKo02 zf|TV-tvc`iQaev;JRF0-3n^;#ouVvn-3Pta-DDb$gF_>CmzWdpbn+xJfcOjuU9_~JL6b1YHVebTye`;#nvJ;$P z*j!xV{uK6fpQWh719-q^bI7~Zcg8@pJN~^M*XaBa(G#p6hx-c1(-*o!*j6(b@>`TS zDvw3{dtDm$ceiTB%hkifYZW9-QHuraV}eIScivpK>k!?ndUG_`$fQsWYXfJcPr!&D zUf+@1<*8enfU2m?gYp|@l0;Y*tO&5OeaHSgzKGX^1v2lAX<}hTEkwc{K!KQJ2ST{S5bpS zrk)1r&XdzZe9odqaL;X{%q_htwZ>WHu#r6Oc#!>UmV-Sq#lRJi7IrzIrb>15pmKG( zYL|0#6~hzq+t-ZbMY*J|T2ML8_ol&0o?$Ae1#pU|QL z($+GR4Ti@WnNRaKnp0rU7qf$7jn!p%2Dp3HjqUAKHK57TNj4_IF%ipb>>d9aGRK_ZrALL3bZSgcm-scAA6+~QjB5`>RJ_PDS{M_;DO*X=E49MhGW zIa-45A!t{4>SL;0-Bn4=xaOQB(Q#*lcN{*Yh~}IO(N6EO3;2<#E6v-y(66nRJ4 z^U!(#UP=sKoKl8RTVnX~l$#de+~~6C%%>`m;6)v8UV@jHc!xLAM7}Xitp;Dnys_I~ z95krpHE9wNUC6r$wvf!r)$g<_CVCFR3yC+LY7gZ*S<(b1))3LHJnEjq+kZWI`F;iE z_TR{ZynVlUFSTz7b3xy$mxc!JUT&d3k~eZ&3+h<6nzhz4&&cbMmv$}A-7;J%E?>0$b79a~KkwtkWQz>s((NvjXY`M8Iwn*CbWropZYjt#q2~D-A5?^kriZ3yl z(e^G2WI=?vxiZ2?g!;M-W6VueF(xK5wU$AY39o(TPK#>}%b0=Y*?(~DbIHRz+T69* z9QxghSh0PpaV&^E?%L=0V-!Jvav?>;gq=HPw;#QS<#jcHL`v_jRH=cGk#tFD_RygN zhn_S-BwZ5Px$Vfdy-yk;k}e3%?%u!iz!dnnD|zc!4226iI}YsJIR!Rb)s#mzwZN4# zkS)mUJaTB;%O&&{{Xw z_L+>t3f*j5ZI72GB;wvPnXDF+YI#r#%{T2uCN6lhbMtK*>-nsuo=Qdv@m9NkuWYqt zvyid6IX=*i-A=#i$9>ng!mVDYW#gTN*uYHYm0&1GCx$Qb7q{iCIbj%fcgT88Z9~1$b1rr&f47Ajj712}tB_jZ#)$8$KwldCD%DG{m zd-<*M7@eF}#B4oiVwOY!akAX29F@mNmcjx z5KExnGQZTBKhZ+a%9_C3`?x#rDpamK2P_1>1$V;JRaoAAJ6gSpF8%7#S}{l=D>KGp zu|X5U_Vip?Dn@aIx0vtX_0Zx~Efr$QYr`N#ZQf+vBfUOudS77#?|m~aETr6MzpYs( zH)UETia>?D>qcvHctu=#rCw8Nq#RDjcni$h^hc($>2k`g#2~G#$QVZGqcy*bH%*xZ zo?r|UeUt~!+bH(U5Kd&RCx!z7^-a3=7%vlB3w&EU%5!F*<>E!+@mLWDa)HB*rej1s z4(f%J@ZN9OD31t}v2o*Q*4S*TtxqbydW0y;7k9;sABTf*25iC0&yH`S-& z#*3+CanZP2EJTrw;7#<&Z9}P?Q;Zu+C$lL;Td$$k5x$u@0%#|A^5*0Qjpfht_A$#` z*G|OLXeWjNG?a?SP)u(q;%wc?8ux*Z!gZ+QZhM)(l)JP-JOUPVV5y4RNKqRGUDwhP zJP+tIFtr6Z_t{b2+mvZAGADDd_nx5oNuLH#SyoYf3H2W5)eTBeqjLwPS~42T{aL zBqZ|Ely9k6ol#s_U=2CdvW{Ar7%}5z z+ztf~LOCrOcm<)=yLlMzZ<)mr?t^=y`XhMt_=*_J#LBuJ*6kvQJ)0HKRw4!5>mvGD z><-~D1-=2XH6FB<2dALxKPC{!a{Js# z+Bz~gicl%G5l~>3w-jwVO3tW`$q?4qRc#F+GeC1ja4#56=MvHV>mseByNVag4m+b! zuJ_mKvBZCl>-^^32e%oFa)o;splrAM%v8{OA``$u%iGGdTngjV>lP9dq(}6chu*-a z5z$PJFOlibdwa3`biGl=n){Q|+I!97O2rhBAHmC7p`gTt7ZD%KRrI zS_wBmnBw60^RSAv3_sykO#E(RJ(xU$i0X^B)G^))`~w@<+9N>ViLKk8}xFd`*s+yl}z?mYxr5&~*zyaKCK z;}vBi8V}Dt7!$%;+6eAb&b>Q0`=C6;wS4_CQ~Y45PjeZdTepA}qGt?HX!Q0nALar$ zg43hlf?_3n?R9z=h$AFnQh?WMWOT;{rjc#D9M8_B1xZ2tS+3N(j{xLO0xPDVlTUUd-6eLaSRV0WK8Dn2!eE{Uv95lgfb zo<|)|m@dwrn1VXpVY!A}9UGz7d-b`eL8THvhJD7JSzMF2z)ce*j9fD%j!5>`(%_-ogU zDoj~rGQ`B0yB=mz>e2AC=$dtU_-Rs?hpGd4A}qW5Oo>xHS0NV}Qkq$!bYY;!HltFG zwsbi3ff{kQNqwg1aEz^~MyK~>F~1g$Ro2Gc;_% zGf3bE!D4p|3POjQlZZW(1tNsa4&}GIj)$<%O-vG{18(uRP2F8MT{?)pzm$-htSj%$nk6`Factu1)4kXaG!pvSn%eXYEn~3Sa@|H(t-=D^i0$;AO*1#W&x-s>yr5>myh)JX zR+Z)7wdMw}U37JIxjRoU95b`y`~@|23-bnc{|+O0`(Vs&Jq)MPYs!EIN!uQ37RzF6 zgaPM9;{hzcjL!7ut@WlQ$4wc~Yw@N93s+QG#?~h;6|;F_G1f|*AFMzIy-+wp{@FMH zUyMyDz>U6RhcWt$5fHa_2?MY&?chw1ZLR9WS#wfvkzY?`dW#CUQ42DlHtb?%JxE#+ zUjLb*{>S$LoY%V~;X(Cj&uG%aP5~s(y1?ba1#aSLse|n=c8{+OspS`rfDr*Y`1~Yn zKI20(H#N#}h3wr?M1jNl$=GyY&cqO4K9ohpem{-fq zJW;|-`-@t27XrVEi1q=++}C!`M2Q$qyWIsraMy8s>(x}K(H5Wj`pSrbAT>KBWqDm) z%+|ibGfzkN^kG7LDk`FBng%LD0zyOgz^=1XPc9`OASmrw9gMnTSPPyCEn53&peaj2 zP&+X0oTklj7z*;e{PnSUq@dyq%%8)j^I@F6~BTmk@rnzrqfJdzc#qAp@fLs;B|C2^f&>>*xT;kXL8V&8F}x~D5Zc9`f~*V#JJG1YPJL+(opb^XBEE zyfp8YmGQMcRh54L&N7JQxF$1|;D0$+%p#Xp_wE_7f@-Q*oDJf2aT zM1osIBndhNo*f5_bpJvH)OU=8w3}BJ+x+sJQeP3SMU&^Hk7ot85P5ysK!WiV z(&#SOa%sWvU@Hy}npG~LPjKL(b~g=9!8pEEzo{lf1q&?%-ih-fa8+w(0aiig+xCXG zQe6qv(qd5Q<23ccMF;}-0)dt8+6pw^!Ep$Oqt+apzk%D?U{N?arjFT}-ep}$CMr%4 z+hvKty&9wWVRvbextOmA2q7~P9z+3U!uXcn0A}$QTJ7k}fItu;OYM~_H7oE% zEpO;Uw69;u$QV#i%n(`#yLlBZhk*@^_2otKRVgn=7b5SlUFxU{^BnaBN5Y>cIM1O- zh7f;4X}>K{_^d{f4~2dAT{r`^fLrZa_|jWkGLp-HqPg3)%R3s{xLVOX>8KBrVk=C6 zCOL1+jtbjUKS0sb{Z9Ltu1%bQEvcu__) zHrn`BB0y=|Z(bS{*YuT?tS5#rMQvcwCuVWIDzx>ngpj|A^cJ(Px~7y!8d^|-(LL_g zmWz7Vo3;_n&5F{z*;GqX2hn&z(tvv9dg_Y=rGi?9F9^$#g`wV5Hi#~Y3wMaj1r-lx z!2tROyN*<^Qjw711X);FBY0z1f~|O{sjLw~3L%g|cQJ)+(ez@yYDKz8S1o~U#ZpKU z2Oh)L!p9e|kW(7k#Iroa-Est$_fi-7ISNF)NRq>!${4(@8wJ3f35)wNAmN{p<%w9? z=wki@cDB5|20KIB!}%q+>$bI!Z$ygOJSIj^6#D{Un{3`0#>&Fk0<%7#G7(z5yR;jL z2@vEWgPd4drIWcM9{pn|fd)8XaupmWCksUC%8l=l44~uPqr}5 zwu+u42Fg2@$Ud4_Q3(9F&?lqUU1dQ(h9tBSNzP(r!!F^jvMm=en8_&kTP$X5_c2jZ zj;y-Hs*qWs!ZCJ_VBTcLM43}<4@_{G|-o@7qY9!GrBW2#g@UEJ-$e-fqL1SzF=V;CzmmXP05e2MtnY`bY z3oTno5ip|GkvUyaz{*7lqQ0|gZ(U#Yk@Y~2gqEWSI^~l{0!`>3G65h8C^^9OB{=|h z8X+sPIwxg$YQCiluV$u`gY{J#NyR;R7GJ3IF0Z4nFFe+Va_y9+6F0#+-HG_pn5czN zb7Xx)6o3nr5nR+6M#A;0nPgLML+0%!Ybjr26LdxWA`{f2K%N*G5u%niRb^@1K)kDq z48k?BG9SCc=BlM@iULQ}H})3$b^~+^T+!BTMSS6Cw#5}=y=fK?BGQ4djZ;p`gcVIszz3iOdKa*aJo8rKM{&qm$XTWz5cKm2tB_%MA*qdEh zAk*awlP&5h@Q*PzmF12$J_U ztUEg#4u*9MTQC5dR`_`Fs8g~PXX{RuJjyIdWvY!>0_{w9Z@KA8Fu1|!G0QhC_R+hN zjFqZlpL>+shhiW7Da|wmN?GhH9wKvCbXzkP`{++)Hqeor;-h|{7c|>Re+M3fCae^NODxd2m}+y4P(BB07h-H(N%Q-l4YF2hz2e}1qJkXy_4Mc?~(7PDbD?&i! z7T4B>w0$R3lyKsTF2pblr(Q9UQ7#yjN??{jifo0$DbjK$8>&~F`0B9dhv3~t zcvzF#ns&uWLOE{D`*OwRQ#Ek!BcP{SG-L&4rF)vGpBye^)qJdNeF|1bWM3S)8FfpM zRYsOia|`+6oVDrt)5-Zevr7`TUiEFyCx+_So|P-HefrdpG=xJ>wY@9h*}kA)bri9^ z0Z6rdwYZwLuLcZlZ_3zuk?qy1&SLFl6)q=)H`>rOz|{D)tIkpjb1!&EMu3AL=O~G( z9|b&);0_1M0;g>jUNO%n1R<+G@{3bJOkhZ<&cTW((Lo4zUa~ypYK88?XxTc~j~Cos z>ck6Hj(dvNS2Xn!hn^ZQTnW!N3JO+7k$7PMQeC22ob!aFzM>j1bO2Mv){AUkv4&ux zvN_x?B1QQcLaZ3K{DC}1%+itkqcy`rKnd&~Swo1Bv1a$=TkVk5aScH!US;%vTtt>L zd1MVik<9~&N8K4*5U@2$?;pB-xYf&Cgjc_Rh!y6xe>k`OZYHR%2Snt6ACzX+kz&?D zDkG~w@`=-hPbg4To}m=s234gyFIg$;BAP%uk5Nk7T9e;Y%nKSvO`bcUflKi;_Y9mn z!M`TYod_r}er)bUJZG()OR+U2`_kM=@pP3zZ6!QJXS3McNg;vTKj-7jg7B6d*`aFg zgkas&fqoyKpVG1Cxh-(+1n~|*I5}Bk0O#Pq9^;Kv9YT6c%fe|*=mGr_jnO6SMl$Har=eb2~4s^8U_|(CH9ZPc{_hey0E6diJtmkqdQ=-yvgd%Kaahd}5$-ORfh7wh$-k+?djPurNk0$kvyvalokpD^+O@TXP@O86+}OTS1DM z1VvbmDRC@EcJl&NaV#vr?E-zyK58Mwq(G`=9D{fq3uG6HEX3Km7jaCKskD$|5kfmF zMfw~eO0>Iz9J493t48&KqSU8tnN8^_w! z>acqfwWeHpfL5r3 z#BHoUpW7-T)R}!jZ=6j)(G&D?wvJ7F!UY+~)N1(zD_QCjJCZ}NUppru-6vd`z$XeK zR$oz{Fd*qZks`FVPo#iqK4Hq)I+9P^Q7=xgt!^f)-(Jfx{Nmg@9`hTj+|O4xYIvf+ zO%A6uIIm#fD}t8QCHc$SlxE1#(w&ACQlp8W;JjzJ2^G}bh|#n4ZxUZza$YySu#((^ zf8_F@)Oko^pOXTrIff}`>qtJ4uhhr# zkYW2&3yv|s#oW+#+6!>}1(yr+gEEl}UoFG^VE2Lkq4udmIqbHDg_M+0Lj~K5`vYB? zuRRS`55!tski8#;I{F3UmiC{_BS9d-S@)3M{!@X_qW-g%KiRV4{JtnVzubYhe~>lH z&+kV{aeM9)ik(5^+7>PNfK4OkNp&XDs#dtw3)ywvR~!jTv}{347v!w_K!SBEzyb@? z^R_NzMd&dFc9mUjm zWfvcz1WplIHHj3ERw?9L?T|0v{&uB!q8qr1M`StcNA|ZXvcvA9pdJ|A5U@2OdsnP2 zgnfAVd{6K^w=m52)a|^z6atJISzGW0qlQJIU~5fw#I*%pqQrn6g8u2T;g# z{Q+FJSKfbG!>}UU;&30pq5P2|`lnmlfr6nU_W>xRnbHfP!oGMPfLAWTw2qA?z*#hM zYRMDm8M7cN3~5AK?$mxO?vep13ujD&eO;C1@&~!S;4Ya%h>(=|T2Ww}Ya&UZeZ**t zaBXd^R?9I_@gsgTgh)!$W4E5j1=8EjJR&yGoX|L+SaMit$8f2TOFoSw|X(ut@(@PLAtHj zyM}KP7Uz7+_pbSmb1lQ(wWEM`GbKCXQBP#$9i zsIx+36jo6l&A}eA9LXjX^Ht`0Sh!Fh)meuZp}b|vt=ZQO2k1k zdXF0Jo!;lg#mnkq!BS^=wKL4%9Zul4=1of@{4cx?cH9~2iv<;BxHR6J8R1;E;#SJ zM>np%x#$iJsV%{Vfpt`+WbxDP?I2U2@C1@%_Ilk#9mFDdK=rk*VO)ZxPR!T4~JxfKRrWU;}qM0OU4vvsGyyoXK=dv7$X z1;=l?7xASQih0M2d~pR{)T$2mY9Tw95{XJJ4D=sjB6N2UV%8A$501|C=VJ{)FTr5Xwf$H@MCCFwJs2#JfD#Tmjo}g*OM}`%+ ze&1U0c<2Hk*=mH^<)NDGl9D8~KI{eWVrst$MXi+{v2CM96Ns}d`v2XDEg=e}x7qty zGnp=7wbxaeZk#ZqCVb(TYcw}ee@at1GL zla*X0Bg>fDq&j+ybHp&Ek6tUv@V0qx&^FV1SXWo10!{R;vS=lr4qKGpzaC@FBi+e( z?4Bv&4c4jXw-W6aMT)lDBMsVZREpzU+Rr9vmH39O_tc@0bd)(m5upM6c-z0>Y*{;ZIYsrPwHDX;im~ z(1xfj_Xd?o&Dc;|j)2e>&d8ZRnY|{HvMU`sSS5zG~N8kGvZ`Z2>akuFM4g|9p`Nb%;OK)>ur*rZApuOUdQ zF?KCd$&62hrp?O#q@<^!X+uTu#SF;QjP@|vb?iy$Hq3w&CW5W=3+3ADNjXpC7YZN2 zocaWcDB4X-X9`EZ@Umfw zTOQNt1lh@%DiPLWI-MXjIa4JOz*AHhLrkTIN2+nJ1^(rz%0=eJnFwPcejuwfi`1cdh3<%`qkWW?o*HX>Fhqd7T# z(I3S|v~B*k>2xyE@YaNVPoHO6a>HfL5Kbw7UoW;Ntu?e z2E=u#ld0r9oo;1HoR$9N5k=2ztU0N&?<-q@OIJ2yRH^algsLfNT!~rtfyTvgW>}@0 zRL$a$qE%~k*Xh#`y2W{R@c^CmoRn$9dG?Tq;QFA-RllkrO+9YxyT6$Whm7TcNy<@Z zCltRiW;&Tl!`To)*)S1W#y$h~G!}Q;OzH~_`wUJ&@WXz$_~TT(wPC+2NeGTOlPmu` z9WQM-U#C$Kd~trfcxXD_*>HZ`VFvUWD7?35F_n~WZn34d&Brc z$2bE{`q9F3#7Q1AqzH&(NOs(9Qu{R=Lox_g$3gBbf_JBql*EvJxq8J~_3?n=RtiNML7vNIJltS{(QMTI&#!upu+Pt)ot`F@;aXl+`l84lJ~TQ#Pi zbpg)clW8)t3x-y`iD|7Ax{7PcI8Vnwt4H_5;M|*88Lzu1Mi=Ikn=-4SV-R6lXeu}f zU&VPWxnrW%Y@sgH5l@-N(lH!yxpk+4eXV&zUGnCzSLP7i>mqFx*?e7M4q8B`V-ct?g zQ{$~fbdUE`!{F3-D>2aVW_xC)6hEfHo3Rpp;#%WWRXt&T7~9uV`RdwQ{j*C`CL0yT zclj{BQ*D7$;j6Sh>_zfT8R>g|^bqBgJK4C#(Gh-&^P~Bnrr6=7%#Z5T#fZ%K2(IV_ z`QN76DEB$>)^_@prUMiJ|#nls~aaa1mjm}jj0C1=~_dHir9XOb@udqNqVf9 zR-eNO34LRHEdE$$zeg3{$>O7=BpBl?rTlZP-5*uFC!1l?hza&MFI+q{)f{TFd0~%} z;GFMSO5Pb#rQ*rfFo3DM9-L-2_LEL)>=UUXn6k%O$G|>k815QDhP8H$=;$sQOvX^z zLxQ6awu56zea2*?5XMLNBd!I98#$&#d9t4?(F(ulQwSJG2;oRx{1zp73 z`y+85?`zFX*yaw`x2|=DXEMBpDO>0)w%3-&t>yO0+(LU}{Wa{y?D%7Rr^&4n0yWd^ zZ!s`ia0gcu2KJY{vGf6-T`rck(}=eVFcENDXlK}2FjCud%bksNegl5#le}8DA22}o zp{@|eyD6;<2rBkwuVMkM%*Pilw`082fvqXUuD&v90g?+iw0);m*(?_<*c`~egtv!} z<~#ibc(;IU0JXp!F&Z+~Dr<=`4wfVNLw*Z?;NXGcF-UK$=lB26y~Jfa=xOd3Grrxz ztyNWc;2v~^Ue$AfVf}4Ydun(I^-UW0Vq+B@k!!-qn#S6Ly7yzve5RTvrKpq8jCoKV z`T`FkSr`F~=Uk~rNcj}^m>cf1A*9q*1OT|m>%9mf{+@A6q4%xrP_AU?(Vua*7VB6HV+n;YLyhhEfBq9GU zc-j0)rw`XjH)U``di9+w!Qo!_eQPj;m_m6}!vyCRfL;>DKWj3O;u%f@R>?&Qe3O)bLX)Ny;}H&D1oGtZjQ05zbvBts&n^67p|Z zZZ~#>EZqhuMabQO-%RcXe)bwyS>_28Y__hnPd9Xc8a*Ni5mIkk=`3{Jy#+~)+gbii z>Do7PgzT*=-QvQ8nu6=pxZ4*}@1Rs$AGE|x=jvR;+pQ!af0zB1C3p?(PDkRCG?ytt z1*_YKaN+CF-FTdY>XcF=N67^V>9>ubzi8Y~*YH9kN65b0eAilOH_i>|?Pf_D%a}01 z;Var5k%G}JqZ8fLhK-^|kAPBy+&l3bm}F|) z9nsq;6E$E(2?kqXrnzCoYs5qlBBb6jZl7rCdo}cpQiR+)@tbp`??RMdaOn!}))L01^(yhvo^qrlR)p0GM^U#<_PPE@fqM}KVsPEQpf1#sg zXfcciQb~l6dUL;XS{o!)3r*HCN)R&d9Jc%FY(-RPQ!SGqA^TQ%>)tX9+m#j>m0nB@ z`t31R0$=TiLWJa-Vc`mA&*f4;41&KRD_PSh!OElzZxMPglj5(cI}b#%4Lf0c1E32 z@2Mc*_uv%-U_G{z`%$O&=VC2Oyr|pc1f4#-A$f?y>CF9iW1YXKyX--3-Wz8NEY-9Q zpNRt7UgI2GeI#?Z*0AKN;!Ol4B+cyeH9@zf3ZsX4t!{VHV;xu&2r9>hA<@TJ1^tDJ z!(dBTVaL-A=3HfKeyKBmLdK#*VCT}bPF; zhsmb>n|p{G<+|Ou1FD7z%7SfPoSBF(-_o`h&a%H(8mnXrn?v zMVJGqj}(>hW6Z5=*PaOqmF1n=u>_~G6u!mBYSMJg?bTIS6_;LD3FCybuDP;QW@JhE zS_M6K0t=@1*1dw4ZcJW5;<6bK3=T7 z*9Uj(=zv�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%0Dk6whprL2NymtpVSm8HAi4ys; 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�R~adYnjVTc^F5Sl72TLK9%GW%|s_#pc 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 diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree index 0286932c2f9e58c20ef2322994486302651a7a45..60583e3cc601446aab58d974793a7da5f7627263 100644 GIT binary patch delta 206 zcmaESlX3DbM%D(_sT{c*Sq~-}a3>e!#HVByC+8QXOlh0q*TV@CC@f7asswZSLEMs} z#Ju91#FEVXyvY|5P1v)Za4;}rJ=@HfG>e&0ck`UoFU+CroIoKK5V05}xd24`2N8dO zL}?FaUSe))No7H5@s!#r8d)IKeqfb;U{!vl8ImAzkO3JwVBHz9S${S^%~WP$n!-8x ZpuQf9Sk^=!LsxEcRE_~-|K#qR2msBgMezUt delta 160 zcmbPyi}CSIM%D(_sW);qvK~z2;!G~ci7zZoEvlUSEzxANNz!y?M$OGu0-$AGbW^6s1n0PLF3#kFocO}h)S}AC*-Ubqdzplo8Cy3mVEw=>6Q2=N+{2ld dn44NsS&&*hrFKe2ykBvKB9M;RyoNKB5dg{S8t(uA diff --git a/docs/build/doctrees/setup.doctree b/docs/build/doctrees/setup.doctree index ae9229c28dabf9dd824557342e8dd68ef11134ee..68420c76ff639b5284e94de6aeb0b8ff0e1046a0 100644 GIT binary patch delta 145 zcmZo!$oOdiBTED8)bx!kxzfB21(^j3nR&$}i8(n6lN+UNFhooz*DLdF7La+y%xjOL nI8ebvB!fM6N`_buip1tXh1pEJjwovXDA{6&m~F0CX4M4%YU(oT delta 164 zcmeygfU#vEBTED8)XI%4xzYm81(^j3nR&$}i8(n6#ToIF>!fY437SsMRp#5wCG(6~ kzzJQ;UwLb6f+k=s?Fx}h0xsxU-YVH*6ExeLtIVnk01x6jcK`qY diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo index c200e742..f883c950 100644 --- a/docs/build/html/.buildinfo +++ b/docs/build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 9ea51a00cf3559575c97b7efd7a002e5 +config: 7051b788adc6d655ae340e56640c6925 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/html/_sources/cli.generate.md.txt b/docs/build/html/_sources/cli.generate.md.txt index 40d79fdf..95a1cb51 100644 --- a/docs/build/html/_sources/cli.generate.md.txt +++ b/docs/build/html/_sources/cli.generate.md.txt @@ -18,10 +18,11 @@ Generates files based on a schematic. ## Arguments -| Argument | Description | Value type | -| ----------------- |:---------------------------------:|:-------------:| -| `````` | The schematic to generate. | ```str``` | -| `````` | The name of the generated file. | ```str``` | +| Argument | Description | Value type | +|-------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------:| +| `````` | The schematic to generate. | ```str``` | +| `````` | The name of the generated file. | ```str``` | +| ```--base``` | First element of path will be used as base-path not 'src'. For example: 'cpl g c test/Test' will be created at ```src/test/``` with --base it would be ```test/``` | ```str``` | ## Schematics diff --git a/docs/build/html/_sources/cli.new.md.txt b/docs/build/html/_sources/cli.new.md.txt index 2ddcb9e7..f000dcd6 100644 --- a/docs/build/html/_sources/cli.new.md.txt +++ b/docs/build/html/_sources/cli.new.md.txt @@ -18,10 +18,11 @@ Generates a workspace and initial project or add a project to workspace. If the command is running in a CPL workspace, it will add the new project to the workspace. -| Argument | Description | Value type | -|--------------|:----------------------------------------------------:|:----------:| -| `````` | The type of the project, see [types](#project-types) | ```str``` | -| `````` | The name of the project | ```str``` | +| Argument | Description | Value type | +|--------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:----------:| +| `````` | The type of the project, see [types](#project-types) | ```str``` | +| `````` | The name of the project | ```str``` | +| ```--base``` | First element of path will be used as base-path not 'src'. For example: 'cpl g c test/Test' will be created at ```src/test/``` with --base it would be ```test/``` | ```str``` | ## Project types diff --git a/docs/build/html/_sources/cli.run.md.txt b/docs/build/html/_sources/cli.run.md.txt new file mode 100644 index 00000000..5782a7a4 --- /dev/null +++ b/docs/build/html/_sources/cli.run.md.txt @@ -0,0 +1,12 @@ +# cpl run + +Starts your application once. + +cpl **run**
    +cpl **r**
    +cpl **R** + +| Argument | Description | Value type | +|-----------------|:----------------------------------------------------------------------------------------------------:|:----------:| +| `````` | Optional parameter to specify which project to start, if not set default project will be started. | ```str``` | +| ```--dev``` | To run the project from source and not from dist after build. | ```str``` | \ No newline at end of file diff --git a/docs/build/html/_sources/cli.start.md.txt b/docs/build/html/_sources/cli.start.md.txt index 2b067bfb..961feef1 100644 --- a/docs/build/html/_sources/cli.start.md.txt +++ b/docs/build/html/_sources/cli.start.md.txt @@ -5,3 +5,7 @@ Starts your application, restarting on file changes. cpl **start**
    cpl **s**
    cpl **S** + +| Argument | Description | Value type | +|-----------------|:----------------------------------------------------------------------------------------------------:|:----------:| +| ```--dev``` | To run the project from source and not from dist after build. | ```str``` | \ No newline at end of file diff --git a/docs/build/html/_sources/contributing.md.txt b/docs/build/html/_sources/contributing.md.txt index 85456726..249c41d6 100644 --- a/docs/build/html/_sources/contributing.md.txt +++ b/docs/build/html/_sources/contributing.md.txt @@ -44,7 +44,7 @@ Before you submit your Pull Request (PR) consider the following guidelines: 2. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add. Discussing the design upfront helps to ensure that we're ready to accept your work. -3. Fork the sh-edraft.de/sh_cpl repo. +3. Fork the sh-edraft.de/cpl repo. 4. In your forked repository, make your changes in a new git branch: @@ -70,7 +70,7 @@ Before you submit your Pull Request (PR) consider the following guidelines: git push origin my-fix-branch ``` -8. In Gitea, send a pull request to sh_cpl:master +8. In Gitea, send a pull request to cpl:master ### Reviewing a Pull Request @@ -104,7 +104,7 @@ To ensure consistency throughout the source code, keep these rules in mind as yo ## License By contributing, you agree that your contributions will be licensed under its MIT License. -See [LICENSE](https://git.sh-edraft.de/sh-edraft.de/sh_cpl/src/branch/master/LICENSE) +See [LICENSE](https://git.sh-edraft.de/sh-edraft.de/cpl/src/branch/master/LICENSE) [gitea-repo]: https://git.sh-edraft.de/sh-edraft.de/sh_cpl/ diff --git a/docs/build/html/_sources/cpl_cli.rst.txt b/docs/build/html/_sources/cpl_cli.rst.txt index 338ba5c2..cec12291 100644 --- a/docs/build/html/_sources/cpl_cli.rst.txt +++ b/docs/build/html/_sources/cpl_cli.rst.txt @@ -1,4 +1,4 @@ -CLI Reference +CLI reference ============= .. toctree:: diff --git a/docs/build/html/_sources/cpl_core.database.rst.txt b/docs/build/html/_sources/cpl_core.database.rst.txt index fb55c962..cdcb0ce8 100644 --- a/docs/build/html/_sources/cpl_core.database.rst.txt +++ b/docs/build/html/_sources/cpl_core.database.rst.txt @@ -7,8 +7,7 @@ cpl_core.database cpl_core.database.connection cpl_core.database.context -Submodules ----------- + cpl_core.database.database\_model ----------------------------------- diff --git a/docs/build/html/_sources/cpl_core.pipes.rst.txt b/docs/build/html/_sources/cpl_core.pipes.rst.txt index 8af5814b..0a8bba4d 100644 --- a/docs/build/html/_sources/cpl_core.pipes.rst.txt +++ b/docs/build/html/_sources/cpl_core.pipes.rst.txt @@ -1,10 +1,9 @@ cpl\_core.pipes ======================= -Submodules ----------- -cpl\_core.pipes.bool\_pipe module + +cpl\_core.pipes.bool\_pipe --------------------------------- .. automodule:: cpl_core.pipes.bool_pipe @@ -12,7 +11,7 @@ cpl\_core.pipes.bool\_pipe module :undoc-members: :show-inheritance: -cpl\_core.pipes.first\_char\_to\_lower\_pipe module +cpl\_core.pipes.first\_char\_to\_lower\_pipe --------------------------------------------------- .. automodule:: cpl_core.pipes.first_char_to_lower_pipe @@ -20,7 +19,7 @@ cpl\_core.pipes.first\_char\_to\_lower\_pipe module :undoc-members: :show-inheritance: -cpl\_core.pipes.first\_to\_upper\_pipe module +cpl\_core.pipes.first\_to\_upper\_pipe --------------------------------------------- .. automodule:: cpl_core.pipes.first_to_upper_pipe @@ -28,7 +27,7 @@ cpl\_core.pipes.first\_to\_upper\_pipe module :undoc-members: :show-inheritance: -cpl\_core.pipes.ip\_address\_pipe module +cpl\_core.pipes.ip\_address\_pipe ---------------------------------------- .. automodule:: cpl_core.pipes.ip_address_pipe @@ -36,7 +35,7 @@ cpl\_core.pipes.ip\_address\_pipe module :undoc-members: :show-inheritance: -cpl\_core.pipes.pipe\_abc module +cpl\_core.pipes.pipe\_abc -------------------------------- .. automodule:: cpl_core.pipes.pipe_abc @@ -44,7 +43,7 @@ cpl\_core.pipes.pipe\_abc module :undoc-members: :show-inheritance: -cpl\_core.pipes.to\_camel\_case\_pipe module +cpl\_core.pipes.to\_camel\_case\_pipe -------------------------------------------- .. automodule:: cpl_core.pipes.to_camel_case_pipe @@ -52,7 +51,7 @@ cpl\_core.pipes.to\_camel\_case\_pipe module :undoc-members: :show-inheritance: -cpl\_core.pipes.to\_snake\_case\_pipe module +cpl\_core.pipes.to\_snake\_case\_pipe -------------------------------------------- .. automodule:: cpl_core.pipes.to_snake_case_pipe @@ -60,18 +59,10 @@ cpl\_core.pipes.to\_snake\_case\_pipe module :undoc-members: :show-inheritance: -cpl\_core.pipes.version\_pipe module +cpl\_core.pipes.version\_pipe ------------------------------------ .. automodule:: cpl_core.pipes.version_pipe :members: :undoc-members: :show-inheritance: - -Module contents ---------------- - -.. automodule:: cpl_core.pipes - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/cpl_core.rst.txt b/docs/build/html/_sources/cpl_core.rst.txt index a71547b3..e1e9b11a 100644 --- a/docs/build/html/_sources/cpl_core.rst.txt +++ b/docs/build/html/_sources/cpl_core.rst.txt @@ -1,4 +1,4 @@ -API Reference +API reference =========== .. toctree:: diff --git a/docs/build/html/_sources/cpl_discord.application.rst.txt b/docs/build/html/_sources/cpl_discord.application.rst.txt new file mode 100644 index 00000000..ef077d22 --- /dev/null +++ b/docs/build/html/_sources/cpl_discord.application.rst.txt @@ -0,0 +1,12 @@ +cpl\_discord.application +================================ + + + +cpl\_discord.application.discord\_bot\_application\_abc +-------------------------------------------------------------- + +.. automodule:: cpl_discord.application.discord_bot_application_abc + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/html/_sources/cpl_discord.command.rst.txt b/docs/build/html/_sources/cpl_discord.command.rst.txt new file mode 100644 index 00000000..5f495733 --- /dev/null +++ b/docs/build/html/_sources/cpl_discord.command.rst.txt @@ -0,0 +1,20 @@ +cpl\_discord.command +============================ + + + +cpl\_discord.command.discord\_command\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.command.discord_command_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.command.discord\_commands\_meta +--------------------------------------------------- + +.. automodule:: cpl_discord.command.discord_commands_meta + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/html/_sources/cpl_discord.configuration.rst.txt b/docs/build/html/_sources/cpl_discord.configuration.rst.txt new file mode 100644 index 00000000..eb855d14 --- /dev/null +++ b/docs/build/html/_sources/cpl_discord.configuration.rst.txt @@ -0,0 +1,12 @@ +cpl\_discord.configuration +================================== + + + +cpl\_discord.configuration.discord\_bot\_settings +-------------------------------------------------------- + +.. automodule:: cpl_discord.configuration.discord_bot_settings + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/html/_sources/cpl_discord.container.rst.txt b/docs/build/html/_sources/cpl_discord.container.rst.txt new file mode 100644 index 00000000..a47f50b1 --- /dev/null +++ b/docs/build/html/_sources/cpl_discord.container.rst.txt @@ -0,0 +1,68 @@ +cpl\_discord.container +============================== + + + +cpl\_discord.container.category\_channel +----------------------------------------------- + +.. automodule:: cpl_discord.container.category_channel + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.container +--------------------------------------- + +.. automodule:: cpl_discord.container.container + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.guild +----------------------------------- + +.. automodule:: cpl_discord.container.guild + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.member +------------------------------------ + +.. automodule:: cpl_discord.container.member + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.role +---------------------------------- + +.. automodule:: cpl_discord.container.role + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.text\_channel +------------------------------------------- + +.. automodule:: cpl_discord.container.text_channel + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.thread +------------------------------------ + +.. automodule:: cpl_discord.container.thread + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.voice\_channel +-------------------------------------------- + +.. automodule:: cpl_discord.container.voice_channel + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/html/_sources/cpl_discord.events.rst.txt b/docs/build/html/_sources/cpl_discord.events.rst.txt new file mode 100644 index 00000000..d26aa744 --- /dev/null +++ b/docs/build/html/_sources/cpl_discord.events.rst.txt @@ -0,0 +1,412 @@ +cpl\_discord.events +=========================== + + + +cpl\_discord.events.on\_bulk\_message\_delete\_abc +--------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_bulk_message_delete_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_command\_abc +------------------------------------------- + +.. automodule:: cpl_discord.events.on_command_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_command\_completion\_abc +------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_command_completion_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_command\_error\_abc +-------------------------------------------------- + +.. automodule:: cpl_discord.events.on_command_error_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_connect\_abc +------------------------------------------- + +.. automodule:: cpl_discord.events.on_connect_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_disconnect\_abc +---------------------------------------------- + +.. automodule:: cpl_discord.events.on_disconnect_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_error\_abc +----------------------------------------- + +.. automodule:: cpl_discord.events.on_error_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_group\_join\_abc +----------------------------------------------- + +.. automodule:: cpl_discord.events.on_group_join_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_group\_remove\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.events.on_group_remove_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_available\_abc +---------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_available_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_channel\_create\_abc +---------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_channel_create_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_channel\_delete\_abc +---------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_channel_delete_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_channel\_pins\_update\_abc +---------------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_channel_pins_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_channel\_update\_abc +---------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_channel_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_emojis\_update\_abc +--------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_emojis_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_integrations\_update\_abc +--------------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_integrations_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_join\_abc +----------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_join_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_remove\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_remove_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_role\_create\_abc +------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_role_create_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_role\_delete\_abc +------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_role_delete_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_role\_update\_abc +------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_role_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_unavailable\_abc +------------------------------------------------------ + +.. automodule:: cpl_discord.events.on_guild_unavailable_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_update\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_invite\_create\_abc +-------------------------------------------------- + +.. automodule:: cpl_discord.events.on_invite_create_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_invite\_delete\_abc +-------------------------------------------------- + +.. automodule:: cpl_discord.events.on_invite_delete_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_member\_ban\_abc +----------------------------------------------- + +.. automodule:: cpl_discord.events.on_member_ban_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_member\_join\_abc +------------------------------------------------ + +.. automodule:: cpl_discord.events.on_member_join_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_member\_remove\_abc +-------------------------------------------------- + +.. automodule:: cpl_discord.events.on_member_remove_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_member\_unban\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.events.on_member_unban_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_member\_update\_abc +-------------------------------------------------- + +.. automodule:: cpl_discord.events.on_member_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_message\_abc +------------------------------------------- + +.. automodule:: cpl_discord.events.on_message_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_message\_delete\_abc +--------------------------------------------------- + +.. automodule:: cpl_discord.events.on_message_delete_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_message\_edit\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.events.on_message_edit_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_private\_channel\_create\_abc +------------------------------------------------------------ + +.. automodule:: cpl_discord.events.on_private_channel_create_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_private\_channel\_delete\_abc +------------------------------------------------------------ + +.. automodule:: cpl_discord.events.on_private_channel_delete_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_private\_channel\_pins\_update\_abc +------------------------------------------------------------------ + +.. automodule:: cpl_discord.events.on_private_channel_pins_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_private\_channel\_update\_abc +------------------------------------------------------------ + +.. automodule:: cpl_discord.events.on_private_channel_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_raw\_reaction\_add\_abc +------------------------------------------------------ + +.. automodule:: cpl_discord.events.on_raw_reaction_add_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_raw\_reaction\_clear\_abc +-------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_raw_reaction_clear_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_raw\_reaction\_clear\_emoji\_abc +--------------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_raw_reaction_clear_emoji_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_raw\_reaction\_remove\_abc +--------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_raw_reaction_remove_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_reaction\_add\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.events.on_reaction_add_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_reaction\_clear\_abc +--------------------------------------------------- + +.. automodule:: cpl_discord.events.on_reaction_clear_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_reaction\_clear\_emoji\_abc +---------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_reaction_clear_emoji_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_reaction\_remove\_abc +---------------------------------------------------- + +.. automodule:: cpl_discord.events.on_reaction_remove_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_ready\_abc +----------------------------------------- + +.. automodule:: cpl_discord.events.on_ready_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_resume\_abc +------------------------------------------ + +.. automodule:: cpl_discord.events.on_resume_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_typing\_abc +------------------------------------------ + +.. automodule:: cpl_discord.events.on_typing_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_user\_update\_abc +------------------------------------------------ + +.. automodule:: cpl_discord.events.on_user_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_voice\_state\_update\_abc +-------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_voice_state_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_webhooks\_update\_abc +---------------------------------------------------- + +.. automodule:: cpl_discord.events.on_webhooks_update_abc + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/build/html/_sources/cpl_discord.helper.rst.txt b/docs/build/html/_sources/cpl_discord.helper.rst.txt new file mode 100644 index 00000000..396b4c89 --- /dev/null +++ b/docs/build/html/_sources/cpl_discord.helper.rst.txt @@ -0,0 +1,12 @@ +cpl\_discord.helper +=========================== + + + +cpl\_discord.helper.to\_containers\_converter +---------------------------------------------------- + +.. automodule:: cpl_discord.helper.to_containers_converter + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/html/_sources/cpl_discord.rst.txt b/docs/build/html/_sources/cpl_discord.rst.txt new file mode 100644 index 00000000..5d10fb20 --- /dev/null +++ b/docs/build/html/_sources/cpl_discord.rst.txt @@ -0,0 +1,13 @@ +Discord reference +==================== + +.. toctree:: + :maxdepth: 4 + + cpl_discord.application + cpl_discord.command + cpl_discord.configuration + cpl_discord.container + cpl_discord.events + cpl_discord.helper + cpl_discord.service diff --git a/docs/build/html/_sources/cpl_discord.service.rst.txt b/docs/build/html/_sources/cpl_discord.service.rst.txt new file mode 100644 index 00000000..a6898292 --- /dev/null +++ b/docs/build/html/_sources/cpl_discord.service.rst.txt @@ -0,0 +1,60 @@ +cpl\_discord.service +============================ + + + +cpl\_discord.service.command\_error\_handler\_service +------------------------------------------------------------ + +.. automodule:: cpl_discord.service.command_error_handler_service + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.service.discord\_bot\_service +------------------------------------------------- + +.. automodule:: cpl_discord.service.discord_bot_service + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.service.discord\_bot\_service\_abc +------------------------------------------------------ + +.. automodule:: cpl_discord.service.discord_bot_service_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.service.discord\_collection +----------------------------------------------- + +.. automodule:: cpl_discord.service.discord_collection + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.service.discord\_collection\_abc +---------------------------------------------------- + +.. automodule:: cpl_discord.service.discord_collection_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.service.discord\_service +-------------------------------------------- + +.. automodule:: cpl_discord.service.discord_service + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.service.discord\_service\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.service.discord_service_abc + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/html/_sources/cpl_query.base.rst.txt b/docs/build/html/_sources/cpl_query.base.rst.txt new file mode 100644 index 00000000..156985e5 --- /dev/null +++ b/docs/build/html/_sources/cpl_query.base.rst.txt @@ -0,0 +1,52 @@ +cpl\_query.base +======================= + + + +cpl\_query.base.default\_lambda +-------------------------------------- + +.. automodule:: cpl_query.base.default_lambda + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.base.ordered\_queryable +----------------------------------------- + +.. automodule:: cpl_query.base.ordered_queryable + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.base.ordered\_queryable\_abc +---------------------------------------------- + +.. automodule:: cpl_query.base.ordered_queryable_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.base.queryable\_abc +------------------------------------- + +.. automodule:: cpl_query.base.queryable_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.base.sequence\_abc +------------------------------------ + +.. automodule:: cpl_query.base.sequence_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.base.sequence\_values +--------------------------------------- + +.. automodule:: cpl_query.base.sequence_values + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/html/_sources/cpl_query.enumerable.rst.txt b/docs/build/html/_sources/cpl_query.enumerable.rst.txt new file mode 100644 index 00000000..37e58add --- /dev/null +++ b/docs/build/html/_sources/cpl_query.enumerable.rst.txt @@ -0,0 +1,20 @@ +cpl\_query.enumerable +============================= + + + +cpl\_query.enumerable.enumerable +--------------------------------------- + +.. automodule:: cpl_query.enumerable.enumerable + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.enumerable.enumerable\_abc +-------------------------------------------- + +.. automodule:: cpl_query.enumerable.enumerable_abc + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/html/_sources/cpl_query.exceptions.rst.txt b/docs/build/html/_sources/cpl_query.exceptions.rst.txt deleted file mode 100644 index d492c637..00000000 --- a/docs/build/html/_sources/cpl_query.exceptions.rst.txt +++ /dev/null @@ -1,10 +0,0 @@ -cpl_query.exceptions -================================= - -cpl_query.exceptions ----------------------------------------------------- - -.. automodule:: cpl_query.exceptions - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/cpl_query.extension.rst.txt b/docs/build/html/_sources/cpl_query.extension.rst.txt index 9dfaa401..a0bba3e0 100644 --- a/docs/build/html/_sources/cpl_query.extension.rst.txt +++ b/docs/build/html/_sources/cpl_query.extension.rst.txt @@ -1,42 +1,12 @@ -cpl_query.extension -================================= +cpl\_query.extension +============================ -cpl_query.extension.iterable_abc ----------------------------------------------------- -.. automodule:: cpl_query.extension.iterable_abc - :members: - :undoc-members: - :show-inheritance: -cpl_query.extension.iterable ----------------------------------------------------- - -.. automodule:: cpl_query.extension.iterable - :members: - :undoc-members: - :show-inheritance: - -cpl_query.extension.list ----------------------------------------------------- +cpl\_query.extension.list +-------------------------------- .. automodule:: cpl_query.extension.list :members: :undoc-members: :show-inheritance: - -cpl_query.extension.ordered_iterable_abc ----------------------------------------------------- - -.. automodule:: cpl_query.extension.ordered_iterable_abc - :members: - :undoc-members: - :show-inheritance: - -cpl_query.extension.ordered_iterable ----------------------------------------------------- - -.. automodule:: cpl_query.extension.ordered_iterable - :members: - :undoc-members: - :show-inheritance: \ No newline at end of file diff --git a/docs/build/html/_sources/cpl_query.iterable.rst.txt b/docs/build/html/_sources/cpl_query.iterable.rst.txt new file mode 100644 index 00000000..8a7bc919 --- /dev/null +++ b/docs/build/html/_sources/cpl_query.iterable.rst.txt @@ -0,0 +1,20 @@ +cpl\_query.iterable +=========================== + + + +cpl\_query.iterable.iterable +----------------------------------- + +.. automodule:: cpl_query.iterable.iterable + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.iterable.iterable\_abc +---------------------------------------- + +.. automodule:: cpl_query.iterable.iterable_abc + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/html/_sources/cpl_query.rst.txt b/docs/build/html/_sources/cpl_query.rst.txt index 10d6f0d8..5a362b26 100644 --- a/docs/build/html/_sources/cpl_query.rst.txt +++ b/docs/build/html/_sources/cpl_query.rst.txt @@ -1,8 +1,10 @@ -Query Reference +Query reference =========== .. toctree:: :maxdepth: 4 - - cpl_query.extension - cpl_query.exceptions + + cpl_query.base + cpl_query.enumerable + cpl_query.extension + cpl_query.iterable diff --git a/docs/build/html/_sources/cpl_translation.rst.txt b/docs/build/html/_sources/cpl_translation.rst.txt new file mode 100644 index 00000000..365356e8 --- /dev/null +++ b/docs/build/html/_sources/cpl_translation.rst.txt @@ -0,0 +1,34 @@ +Translation reference +======================== + +cpl\_translation.translate\_pipe +--------------------------------------- + +.. automodule:: cpl_translation.translate_pipe + :members: + :undoc-members: + :show-inheritance: + +cpl\_translation.translation\_service +-------------------------------------------- + +.. automodule:: cpl_translation.translation_service + :members: + :undoc-members: + :show-inheritance: + +cpl\_translation.translation\_service\_abc +------------------------------------------------- + +.. automodule:: cpl_translation.translation_service_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_translation.translation\_settings +--------------------------------------------- + +.. automodule:: cpl_translation.translation_settings + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/html/_sources/index.rst.txt b/docs/build/html/_sources/index.rst.txt index 0d0ef798..921b7964 100644 --- a/docs/build/html/_sources/index.rst.txt +++ b/docs/build/html/_sources/index.rst.txt @@ -89,4 +89,6 @@ These pages go into great detail about everything the Library can do. contributing cpl_cli cpl_core + cpl_discord cpl_query + cpl_translation diff --git a/docs/build/html/_sources/modules.rst.txt b/docs/build/html/_sources/modules.rst.txt index d1ae65e0..5a411fa4 100644 --- a/docs/build/html/_sources/modules.rst.txt +++ b/docs/build/html/_sources/modules.rst.txt @@ -9,4 +9,4 @@ cpl cpl_core cpl_discord cpl_query - cpl_translate + cpl_translation diff --git a/docs/build/html/_sources/setup.md.txt b/docs/build/html/_sources/setup.md.txt index 6d0be37c..be16fa9b 100644 --- a/docs/build/html/_sources/setup.md.txt +++ b/docs/build/html/_sources/setup.md.txt @@ -27,7 +27,7 @@ Also you need to have the following installed. To install the package, open a terminal window and run the following command: ```sh -pip install sh_cpl-core --extra-index-url https://pip.sh-edraft.de +pip install cpl-core --extra-index-url https://pip.sh-edraft.de ``` ## Install the CLI @@ -37,7 +37,7 @@ You use the CPL CLI to create projects, generate application and library code. Y To install the CLI, open a terminal window and run the following command: ```sh -pip install sh_cpl-cli --extra-index-url https://pip.sh-edraft.de +pip install cpl-cli --extra-index-url https://pip.sh-edraft.de ``` ## Install the query @@ -45,7 +45,7 @@ pip install sh_cpl-cli --extra-index-url https://pip.sh-edraft.de To install the package, open a terminal window and run the following command: ```sh -pip install sh_cpl-query --extra-index-url https://pip.sh-edraft.de +pip install cpl-query --extra-index-url https://pip.sh-edraft.de ``` ## Create initial console app diff --git a/docs/build/html/cli.add.html b/docs/build/html/cli.add.html index 683a3330..54bff940 100644 --- a/docs/build/html/cli.add.html +++ b/docs/build/html/cli.add.html @@ -42,7 +42,7 @@
  1. Getting started
  2. Contributing to CPL
  3. -
  4. CLI Reference
  5. -
  6. CLI Reference
  7. -
  8. API Reference
  9. -
  10. Query Reference
  11. +
  12. CLI reference
  13. +
  14. API reference
  15. +
  16. Discord reference
  17. +
  18. Query reference
  19. +
  20. Translation reference
  21. @@ -123,7 +125,7 @@
    1. Search the repository for an open or closed PR that relates to your submission. You don’t want to duplicate existing efforts.

    2. Be sure that an issue describes the problem you’re fixing, or documents the design for the feature you’d like to add. Discussing the design upfront helps to ensure that we’re ready to accept your work.

    3. -
    4. Fork the sh-edraft.de/sh_cpl repo.

    5. +
    6. Fork the sh-edraft.de/cpl repo.

    7. In your forked repository, make your changes in a new git branch:

      git checkout -b my-fix-branch master
       
      @@ -144,7 +146,7 @@
    8. -
    9. In Gitea, send a pull request to sh_cpl:master

    10. +
    11. In Gitea, send a pull request to cpl:master

    @@ -178,7 +180,7 @@ git push

    License

    By contributing, you agree that your contributions will be licensed under its MIT License. -See LICENSE

    +See LICENSE

    @@ -188,13 +190,13 @@ See - +
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/cpl_cli.html b/docs/build/html/cpl_cli.html index 657a2b49..4ac7954e 100644 --- a/docs/build/html/cpl_cli.html +++ b/docs/build/html/cpl_cli.html @@ -4,7 +4,7 @@ - CLI Reference — Common Python Library documentation + CLI reference — Common Python Library documentation + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    cpl_discord.application

    +
    +

    cpl_discord.application.discord_bot_application_abc

    +
    +
    +class cpl_discord.application.discord_bot_application_abc.DiscordBotApplicationABC(config: ConfigurationABC, services: ServiceProviderABC)
    +

    Bases: ApplicationABC

    +
    +
    +abstract stop_async()
    +
    + +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/build/html/cpl_discord.command.html b/docs/build/html/cpl_discord.command.html new file mode 100644 index 00000000..6dba3ee5 --- /dev/null +++ b/docs/build/html/cpl_discord.command.html @@ -0,0 +1,143 @@ + + + + + + + cpl_discord.command — Common Python Library documentation + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    cpl_discord.command

    +
    +

    cpl_discord.command.discord_command_abc

    +
    +
    +class cpl_discord.command.discord_command_abc.DiscordCommandABC(*args: Any, **kwargs: Any)
    +

    Bases: ABC, Cog

    +
    + +
    +
    +

    cpl_discord.command.discord_commands_meta

    +
    +
    +class cpl_discord.command.discord_commands_meta.DiscordCogMeta(name, bases, namespace, **kwargs)
    +

    Bases: ABCMeta, CogMeta

    +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/build/html/cpl_discord.configuration.html b/docs/build/html/cpl_discord.configuration.html new file mode 100644 index 00000000..591e7eee --- /dev/null +++ b/docs/build/html/cpl_discord.configuration.html @@ -0,0 +1,152 @@ + + + + + + + cpl_discord.configuration — Common Python Library documentation + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    cpl_discord.configuration

    +
    +

    cpl_discord.configuration.discord_bot_settings

    +
    +
    +class cpl_discord.configuration.discord_bot_settings.DiscordBotSettings
    +

    Bases: ConfigurationModelABC

    +
    +
    +from_dict(settings: dict)
    +

    Converts attributes to dict

    +
    +

    settings: dict

    +
    +
    + +
    +
    +property prefix: str
    +
    + +
    +
    +property token: str
    +
    + +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/build/html/cpl_discord.container.html b/docs/build/html/cpl_discord.container.html new file mode 100644 index 00000000..9490fdb6 --- /dev/null +++ b/docs/build/html/cpl_discord.container.html @@ -0,0 +1,674 @@ + + + + + + + cpl_discord.container — Common Python Library documentation + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    cpl_discord.container

    +
    +

    cpl_discord.container.category_channel

    +
    +
    +class cpl_discord.container.category_channel.CategoryChannel(_t: CategoryChannel)
    +

    Bases: CategoryChannel, Container

    +
    +
    +category_id: Optional[int]
    +
    + +
    +
    +guild: Guild
    +
    + +
    +
    +id: int
    +
    + +
    +
    +name: str
    +
    + +
    +
    +nsfw
    +
    + +
    +
    +position: int
    +
    + +
    +
    +property text_channels: TextChannel
    +

    List[TextChannel]: Returns the text channels that are under this category.

    +
    + +
    +
    +property voice_channels: VoiceChannel
    +

    List[VoiceChannel]: Returns the voice channels that are under this category.

    +
    + +
    + +
    +
    +

    cpl_discord.container.container

    +
    +
    +class cpl_discord.container.container.Container(_o: object, _t: type)
    +

    Bases: object

    +
    + +
    +
    +

    cpl_discord.container.guild

    +
    +
    +class cpl_discord.container.guild.Guild(_t: Guild)
    +

    Bases: Container, Guild

    +
    +
    +afk_channel
    +
    + +
    +
    +afk_timeout
    +
    + +
    +
    +approximate_member_count
    +
    + +
    +
    +approximate_presence_count
    +
    + +
    +
    +property categories: CategoryChannel
    +

    List[CategoryChannel]: A list of categories that belongs to this guild.

    +

    This is sorted by the position and are in UI order from top to bottom.

    +
    + +
    +
    +default_notifications
    +
    + +
    +
    +description
    +
    + +
    +
    +emojis
    +
    + +
    +
    +explicit_content_filter
    +
    + +
    +
    +features
    +
    + +
    +
    +id: int
    +
    + +
    +
    +max_members
    +
    + +
    +
    +max_presences
    +
    + +
    +
    +max_video_channel_users
    +
    + +
    +
    +property members: Member
    +

    Sequence[Member]: A list of members that belong to this guild.

    +
    + +
    +
    +mfa_level
    +
    + +
    +
    +name
    +
    + +
    +
    +nsfw_level
    +
    + +
    +
    +owner_id
    +
    + +
    +
    +preferred_locale
    +
    + +
    +
    +premium_progress_bar_enabled
    +
    + +
    +
    +premium_subscription_count
    +
    + +
    +
    +premium_tier
    +
    + +
    +
    +property roles: Role
    +

    Sequence[Role]: Returns a sequence of the guild’s roles in hierarchy order.

    +

    The first element of this sequence will be the lowest role in the +hierarchy.

    +
    + +
    +
    +stickers
    +
    + +
    +
    +property text_channels: TextChannel
    +

    List[TextChannel]: A list of text channels that belongs to this guild.

    +

    This is sorted by the position and are in UI order from top to bottom.

    +
    + +
    +
    +property threads: TextChannel
    +

    Sequence[Thread]: A list of threads that you have permission to view.

    +
    +

    New in version 2.0.

    +
    +
    + +
    +
    +unavailable
    +
    + +
    +
    +vanity_url_code
    +
    + +
    +
    +verification_level
    +
    + +
    +
    +property voice_channels: VoiceChannel
    +

    List[VoiceChannel]: A list of voice channels that belongs to this guild.

    +

    This is sorted by the position and are in UI order from top to bottom.

    +
    + +
    +
    +widget_enabled
    +
    + +
    + +
    +
    +

    cpl_discord.container.member

    +
    +
    +class cpl_discord.container.member.Member(_t: Member)
    +

    Bases: Member, Container

    +
    +
    +activities: Tuple[ActivityTypes, ...]
    +
    + +
    +
    +guild: Guild
    +
    + +
    +
    +joined_at: Optional[datetime.datetime]
    +
    + +
    +
    +nick: Optional[str]
    +
    + +
    +
    +pending: bool
    +
    + +
    +
    +premium_since: Optional[datetime.datetime]
    +
    + +
    +
    +property roles: Role
    +

    List[Role]: A list of Role that the member belongs to. Note +that the first element of this list is always the default @everyone’ +role.

    +

    These roles are sorted by their position in the role hierarchy.

    +
    + +
    +
    +timed_out_until: Optional[datetime.datetime]
    +
    + +
    + +
    +
    +

    cpl_discord.container.role

    +
    +
    +class cpl_discord.container.role.Role(_t: Role)
    +

    Bases: Role, Container

    +
    +
    +guild: Guild
    +
    + +
    +
    +hoist
    +
    + +
    +
    +id: int
    +
    + +
    +
    +managed
    +
    + +
    +
    +property members: Member
    +

    List[Member]: Returns all the members with this role.

    +
    + +
    +
    +mentionable
    +
    + +
    +
    +name
    +
    + +
    +
    +position
    +
    + +
    +
    +tags
    +
    + +
    +
    +unicode_emoji
    +
    + +
    + +
    +
    +

    cpl_discord.container.text_channel

    +
    +
    +class cpl_discord.container.text_channel.TextChannel(_t: TextChannel)
    +

    Bases: TextChannel, Container

    +
    +
    +category_id: Optional[int]
    +
    + +
    +
    +default_auto_archive_duration
    +
    + +
    +
    +guild: Guild
    +
    + +
    +
    +id: int
    +
    + +
    +
    +last_message_id
    +
    + +
    +
    +property members: Member
    +

    List[Member]: Returns all members that can see this channel.

    +
    + +
    +
    +name: str
    +
    + +
    +
    +nsfw
    +
    + +
    +
    +position: int
    +
    + +
    +
    +slowmode_delay
    +
    + +
    +
    +property threads: Thread
    +

    List[Thread]: Returns all the threads that you can see.

    +
    +

    New in version 2.0.

    +
    +
    + +
    +
    +topic
    +
    + +
    + +
    +
    +

    cpl_discord.container.thread

    +
    +
    +class cpl_discord.container.thread.Thread(_t: Thread)
    +

    Bases: Thread, Container

    +
    +
    +archive_timestamp
    +
    + +
    +
    +archived
    +
    + +
    +
    +archiver_id
    +
    + +
    +
    +auto_archive_duration
    +
    + +
    +
    +guild: Guild
    +
    + +
    +
    +id: int
    +
    + +
    +
    +invitable
    +
    + +
    +
    +last_message_id
    +
    + +
    +
    +locked
    +
    + +
    +
    +me
    +
    + +
    +
    +member_count
    +
    + +
    +
    +property members: Member
    +

    List[ThreadMember]: A list of thread members in this thread.

    +

    This requires Intents.members to be properly filled. Most of the time however, +this data is not provided by the gateway and a call to fetch_members() is +needed.

    +
    + +
    +
    +message_count
    +
    + +
    +
    +name
    +
    + +
    +
    +owner_id
    +
    + +
    +
    +parent_id
    +
    + +
    +
    +slowmode_delay
    +
    + +
    + +
    +
    +

    cpl_discord.container.voice_channel

    +
    +
    +class cpl_discord.container.voice_channel.VoiceChannel(_t: VoiceChannel)
    +

    Bases: VoiceChannel, Container

    +
    +
    +property members: Member
    +

    List[Member]: Returns all members that are currently inside this voice channel.

    +
    + +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/build/html/cpl_discord.events.html b/docs/build/html/cpl_discord.events.html new file mode 100644 index 00000000..7633c306 --- /dev/null +++ b/docs/build/html/cpl_discord.events.html @@ -0,0 +1,888 @@ + + + + + + + cpl_discord.events — Common Python Library documentation + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    cpl_discord.events

    +
    +

    cpl_discord.events.on_bulk_message_delete_abc

    +
    +
    +class cpl_discord.events.on_bulk_message_delete_abc.OnBulkMessageDeleteABC
    +

    Bases: ABC

    +
    +
    +abstract async on_bulk_message_delete(messages: list[discord.message.Message])
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_command_abc

    +
    +
    +class cpl_discord.events.on_command_abc.OnCommandABC
    +

    Bases: ABC

    +
    +
    +abstract async on_command(ctx: Context)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_command_completion_abc

    +
    +
    +class cpl_discord.events.on_command_completion_abc.OnCommandCompletionABC
    +

    Bases: ABC

    +
    +
    +abstract async on_command_completion(ctx: Context)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_command_error_abc

    +
    +
    +class cpl_discord.events.on_command_error_abc.OnCommandErrorABC
    +

    Bases: ABC

    +
    +
    +abstract async on_command_error(ctx: Context, error: CommandError)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_connect_abc

    +
    +
    +class cpl_discord.events.on_connect_abc.OnConnectABC
    +

    Bases: ABC

    +
    +
    +abstract async on_connect()
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_disconnect_abc

    +
    +
    +class cpl_discord.events.on_disconnect_abc.OnDisconnectABC
    +

    Bases: ABC

    +
    +
    +abstract async on_disconnect()
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_error_abc

    +
    +
    +class cpl_discord.events.on_error_abc.OnErrorABC
    +

    Bases: ABC

    +
    +
    +abstract async on_error(event: str, *args, **kwargs)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_group_join_abc

    +
    +
    +class cpl_discord.events.on_group_join_abc.OnGroupJoinABC
    +

    Bases: ABC

    +
    +
    +abstract async on_group_join(chhanel: GroupChannel, user: User)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_group_remove_abc

    +
    +
    +class cpl_discord.events.on_group_remove_abc.OnGroupRemoveABC
    +

    Bases: ABC

    +
    +
    +abstract async on_group_remove(chhanel: GroupChannel, user: User)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_available_abc

    +
    +
    +class cpl_discord.events.on_guild_available_abc.OnGuildAvailableABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_available(guild: Guild)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_channel_create_abc

    +
    +
    +class cpl_discord.events.on_guild_channel_create_abc.OnGuildChannelCreateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_channel_create(channel: GuildChannel)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_channel_delete_abc

    +
    +
    +class cpl_discord.events.on_guild_channel_delete_abc.OnGuildChannelDeleteABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_channel_delete(channel: GuildChannel)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_channel_pins_update_abc

    +
    +
    +class cpl_discord.events.on_guild_channel_pins_update_abc.OnGuildChannelPinsUpdateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_channel_pins_update(channel: GuildChannel, list_pin: Optional[datetime])
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_channel_update_abc

    +
    +
    +class cpl_discord.events.on_guild_channel_update_abc.OnGuildChannelUpdateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_channel_update(before: GuildChannel, after: GuildChannel)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_emojis_update_abc

    +
    +
    +class cpl_discord.events.on_guild_emojis_update_abc.OnGuildEmojisUpdateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_emojis_update(guild: Guild, before: Sequence[Emoji], after: Sequence[Emoji])
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_integrations_update_abc

    +
    +
    +class cpl_discord.events.on_guild_integrations_update_abc.OnGuildIntegrationsUpdateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_integrations_update(guild: Guild)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_join_abc

    +
    +
    +class cpl_discord.events.on_guild_join_abc.OnGuildJoinABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_join(guild: Guild)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_remove_abc

    +
    +
    +class cpl_discord.events.on_guild_remove_abc.OnGuildRemoveABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_remove(guild: Guild)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_role_create_abc

    +
    +
    +class cpl_discord.events.on_guild_role_create_abc.OnGuildRoleCreateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_role_create(role: Role)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_role_delete_abc

    +
    +
    +class cpl_discord.events.on_guild_role_delete_abc.OnGuildRoleDeleteABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_role_delete(role: Role)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_role_update_abc

    +
    +
    +class cpl_discord.events.on_guild_role_update_abc.OnGuildRoleUpdateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_role_update(before: Role, after: Role)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_unavailable_abc

    +
    +
    +class cpl_discord.events.on_guild_unavailable_abc.OnGuildUnavailableABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_unavailable(guild: Guild)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_guild_update_abc

    +
    +
    +class cpl_discord.events.on_guild_update_abc.OnGuildUpdateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_guild_update(before: Guild, after: Guild)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_invite_create_abc

    +
    +
    +class cpl_discord.events.on_invite_create_abc.OnInviteCreateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_invite_create(invite: Invite)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_invite_delete_abc

    +
    +
    +class cpl_discord.events.on_invite_delete_abc.OnInviteDeleteABC
    +

    Bases: ABC

    +
    +
    +abstract async on_invite_delete(invite: Invite)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_member_ban_abc

    +
    +
    +class cpl_discord.events.on_member_ban_abc.OnMemberBanABC
    +

    Bases: ABC

    +
    +
    +abstract async on_member_ban(guild: Guild, user: User)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_member_join_abc

    +
    +
    +class cpl_discord.events.on_member_join_abc.OnMemberJoinABC
    +

    Bases: ABC

    +
    +
    +abstract async on_member_join(member: Member)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_member_remove_abc

    +
    +
    +class cpl_discord.events.on_member_remove_abc.OnMemberRemoveABC
    +

    Bases: ABC

    +
    +
    +abstract async on_member_remove(member: Member)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_member_unban_abc

    +
    +
    +class cpl_discord.events.on_member_unban_abc.OnMemberUnbanABC
    +

    Bases: ABC

    +
    +
    +abstract async on_member_unban(guild: Guild, user: User)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_member_update_abc

    +
    +
    +class cpl_discord.events.on_member_update_abc.OnMemberUpdateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_member_update(before: Member, after: Member)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_message_abc

    +
    +
    +class cpl_discord.events.on_message_abc.OnMessageABC
    +

    Bases: ABC

    +
    +
    +abstract async on_message(message: Message)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_message_delete_abc

    +
    +
    +class cpl_discord.events.on_message_delete_abc.OnMessageDeleteABC
    +

    Bases: ABC

    +
    +
    +abstract async on_message_delete(message: Message)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_message_edit_abc

    +
    +
    +class cpl_discord.events.on_message_edit_abc.OnMessageEditABC
    +

    Bases: ABC

    +
    +
    +abstract async on_message_edit(before: Message, after: Message)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_private_channel_create_abc

    +
    +
    +class cpl_discord.events.on_private_channel_create_abc.OnPrivateChannelCreateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_private_channel_create(channel: PrivateChannel)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_private_channel_delete_abc

    +
    +
    +class cpl_discord.events.on_private_channel_delete_abc.OnPrivateChannelDeleteABC
    +

    Bases: ABC

    +
    +
    +abstract async on_private_channel_delete(channel: PrivateChannel)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_private_channel_pins_update_abc

    +
    +
    +class cpl_discord.events.on_private_channel_pins_update_abc.OnPrivateChannelPinsUpdateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_private_channel_pins_update(channel: PrivateChannel, list_pin: Optional[datetime])
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_private_channel_update_abc

    +
    +
    +class cpl_discord.events.on_private_channel_update_abc.OnPrivateChannelUpdateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_private_channel_update(before: GroupChannel, after: GroupChannel)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_raw_reaction_add_abc

    +
    +
    +class cpl_discord.events.on_raw_reaction_add_abc.OnRawReactionAddABC
    +

    Bases: ABC

    +
    +
    +abstract async on_raw_reaction_add(payload: RawReactionActionEvent)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_raw_reaction_clear_abc

    +
    +
    +class cpl_discord.events.on_raw_reaction_clear_abc.OnRawReactionClearABC
    +

    Bases: ABC

    +
    +
    +abstract async on_raw_reaction_clear(payload: RawReactionActionEvent)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_raw_reaction_clear_emoji_abc

    +
    +
    +class cpl_discord.events.on_raw_reaction_clear_emoji_abc.OnRawReactionClearEmojiABC
    +

    Bases: ABC

    +
    +
    +abstract async on_raw_reaction_clear_emoji(payload: RawReactionActionEvent)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_raw_reaction_remove_abc

    +
    +
    +class cpl_discord.events.on_raw_reaction_remove_abc.OnRawReactionRemoveABC
    +

    Bases: ABC

    +
    +
    +abstract async on_raw_reaction_remove(payload: RawReactionActionEvent)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_reaction_add_abc

    +
    +
    +class cpl_discord.events.on_reaction_add_abc.OnReactionAddABC
    +

    Bases: ABC

    +
    +
    +abstract async on_reaction_add(reaction: Reaction, user: User)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_reaction_clear_abc

    +
    +
    +class cpl_discord.events.on_reaction_clear_abc.OnReactionClearABC
    +

    Bases: ABC

    +
    +
    +abstract async on_reaction_clear(message: Message, reactions: list[discord.reaction.Reaction])
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_reaction_clear_emoji_abc

    +
    +
    +class cpl_discord.events.on_reaction_clear_emoji_abc.OnReactionClearEmojiABC
    +

    Bases: ABC

    +
    +
    +abstract async on_reaction_clear_emoji(reaction: Reaction)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_reaction_remove_abc

    +
    +
    +class cpl_discord.events.on_reaction_remove_abc.OnReactionRemoveABC
    +

    Bases: ABC

    +
    +
    +abstract async on_reaction_remove(reaction: Reaction, user: User)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_ready_abc

    +
    +
    +class cpl_discord.events.on_ready_abc.OnReadyABC
    +

    Bases: ABC

    +
    +
    +abstract async on_ready()
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_resume_abc

    +
    +
    +class cpl_discord.events.on_resume_abc.OnResumeABC
    +

    Bases: ABC

    +
    +
    +abstract async on_resume()
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_typing_abc

    +
    +
    +class cpl_discord.events.on_typing_abc.OnTypingABC
    +

    Bases: ABC

    +
    +
    +abstract async on_typing(channel: Messageable, user: Union[User, Member], when: datetime)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_user_update_abc

    +
    +
    +class cpl_discord.events.on_user_update_abc.OnUserUpdateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_user_update(before: User, after: User)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_voice_state_update_abc

    +
    +
    +class cpl_discord.events.on_voice_state_update_abc.OnVoiceStateUpdateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_voice_state_update(member: Member, before: VoiceState, after: VoiceState)
    +
    + +
    + +
    +
    +

    cpl_discord.events.on_webhooks_update_abc

    +
    +
    +class cpl_discord.events.on_webhooks_update_abc.OnWebhooksUpdateABC
    +

    Bases: ABC

    +
    +
    +abstract async on_webhooks_update(channel: GuildChannel)
    +
    + +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/build/html/cpl_discord.helper.html b/docs/build/html/cpl_discord.helper.html new file mode 100644 index 00000000..7f128e82 --- /dev/null +++ b/docs/build/html/cpl_discord.helper.html @@ -0,0 +1,138 @@ + + + + + + + cpl_discord.helper — Common Python Library documentation + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    cpl_discord.helper

    +
    +

    cpl_discord.helper.to_containers_converter

    +
    +
    +class cpl_discord.helper.to_containers_converter.ToContainersConverter
    +

    Bases: object

    +
    +
    +static convert(_l: Union[list[object], Sequence[object]], _t: type) list[cpl_discord.container.container.Container]
    +
    + +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/build/html/cpl_discord.html b/docs/build/html/cpl_discord.html new file mode 100644 index 00000000..c32b0593 --- /dev/null +++ b/docs/build/html/cpl_discord.html @@ -0,0 +1,216 @@ + + + + + + + Discord reference — Common Python Library documentation + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Discord reference

    +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/build/html/cpl_discord.service.html b/docs/build/html/cpl_discord.service.html new file mode 100644 index 00000000..b40cbeb9 --- /dev/null +++ b/docs/build/html/cpl_discord.service.html @@ -0,0 +1,780 @@ + + + + + + + cpl_discord.service — Common Python Library documentation + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    cpl_discord.service

    +
    +

    cpl_discord.service.command_error_handler_service

    +
    +
    +class cpl_discord.service.command_error_handler_service.CommandErrorHandlerService(logger: LoggerABC)
    +

    Bases: OnCommandErrorABC

    +
    +
    +async on_command_error(ctx: Context, error: CommandError)
    +
    + +
    + +
    +
    +

    cpl_discord.service.discord_bot_service

    +
    +
    +class cpl_discord.service.discord_bot_service.DiscordBotService(config: ConfigurationABC, logger: LoggerABC, discord_bot_settings: DiscordBotSettings, env: ApplicationEnvironmentABC, logging_st: LoggingSettings, discord_service: DiscordServiceABC)
    +

    Bases: DiscordBotServiceABC

    +
    +
    +property guilds: Guild
    +

    Sequence[Guild]: The guilds that the connected client is a member of.

    +
    + +
    +
    +async on_ready()
    +
    + +
    +
    +async start_async()
    +
    + +
    +
    +async stop_async()
    +
    + +
    + +
    +
    +

    cpl_discord.service.discord_bot_service_abc

    +
    +
    +class cpl_discord.service.discord_bot_service_abc.DiscordBotServiceABC(**kwargs)
    +

    Bases: Bot

    +
    +
    +abstract property guilds: Guild
    +

    Sequence[Guild]: The guilds that the connected client is a member of.

    +
    + +
    +
    +abstract async on_ready()
    +
    + +
    +
    +abstract async start_async()
    +
    + +
    +
    +abstract async stop_async()
    +
    + +
    + +
    +
    +

    cpl_discord.service.discord_collection

    +
    +
    +class cpl_discord.service.discord_collection.DiscordCollection(service_collection: ServiceCollectionABC)
    +

    Bases: DiscordCollectionABC

    +
    +
    +add_command(_t: Type[DiscordCommandABC])
    +
    + +
    +
    +add_event(_t_event: Type, _t: Type)
    +
    + +
    +
    +get_commands() DiscordCommandABC
    +
    + +
    +
    +get_events_by_base(_t_event: Type) Optional[List]
    +
    + +
    + +
    +
    +

    cpl_discord.service.discord_collection_abc

    +
    +
    +class cpl_discord.service.discord_collection_abc.DiscordCollectionABC
    +

    Bases: ABC

    +
    +
    +abstract add_command(_t: Type[DiscordCommandABC])
    +
    + +
    +
    +abstract add_event(_t_event: Type, _t: Type)
    +
    + +
    +
    +abstract get_commands() DiscordCommandABC
    +
    + +
    +
    +abstract get_events_by_base(_t_event: Type)
    +
    + +
    + +
    +
    +

    cpl_discord.service.discord_service

    +
    +
    +class cpl_discord.service.discord_service.DiscordService(*args: Any, **kwargs: Any)
    +

    Bases: DiscordServiceABC, Cog

    +
    +
    +async init(bot: Bot)
    +
    + +
    +
    +async on_bulk_message_delete(messages: list[discord.message.Message])
    +
    + +
    +
    +async on_command(ctx: Context)
    +
    + +
    +
    +async on_command_completion(ctx: Context)
    +
    + +
    +
    +async on_command_error(ctx: Context, error: CommandError)
    +
    + +
    +
    +async on_connect()
    +
    + +
    +
    +async on_disconnect()
    +
    + +
    +
    +async on_error(event: str, *args, **kwargs)
    +
    + +
    +
    +async on_group_join(channel: GroupChannel, user: User)
    +
    + +
    +
    +async on_group_remove(channel: GroupChannel, user: User)
    +
    + +
    +
    +async on_guild_available(guild: Guild)
    +
    + +
    +
    +async on_guild_channel_create(channel: GuildChannel)
    +
    + +
    +
    +async on_guild_channel_delete(channel: GuildChannel)
    +
    + +
    +
    +async on_guild_channel_pins_update(channel: GuildChannel, list_pin: Optional[datetime])
    +
    + +
    +
    +async on_guild_channel_update(before: GuildChannel, after: GuildChannel)
    +
    + +
    +
    +async on_guild_emojis_update(guild: Guild, before: Sequence[Emoji], after: Sequence[Emoji])
    +
    + +
    +
    +async on_guild_integrations_update(guild: Guild)
    +
    + +
    +
    +async on_guild_join(guild: Guild)
    +
    + +
    +
    +async on_guild_remove(guild: Guild)
    +
    + +
    +
    +async on_guild_role_create(role: Role)
    +
    + +
    +
    +async on_guild_role_delete(role: Role)
    +
    + +
    +
    +async on_guild_role_update(before: Role, after: Role)
    +
    + +
    +
    +async on_guild_unavailable(guild: Guild)
    +
    + +
    +
    +async on_guild_update(before: Guild, after: Guild)
    +
    + +
    +
    +async on_invite_create(invite: Invite)
    +
    + +
    +
    +async on_invite_delete(invite: Invite)
    +
    + +
    +
    +async on_member_ban(guild: Guild, user: User)
    +
    + +
    +
    +async on_member_join(member: Member)
    +
    + +
    +
    +async on_member_remove(member: Member)
    +
    + +
    +
    +async on_member_unban(guild: Guild, user: User)
    +
    + +
    +
    +async on_member_update(before: Member, after: Member)
    +
    + +
    +
    +async on_message(message: Message)
    +
    + +
    +
    +async on_message_delete(message: Message)
    +
    + +
    +
    +async on_message_edit(before: Message, after: Message)
    +
    + +
    +
    +async on_private_channel_create(channel: PrivateChannel)
    +
    + +
    +
    +async on_private_channel_delete(channel: PrivateChannel)
    +
    + +
    +
    +async on_private_channel_pins_update(channel: PrivateChannel, list_pin: Optional[datetime])
    +
    + +
    +
    +async on_private_channel_update(before: GroupChannel, after: GroupChannel)
    +
    + +
    +
    +async on_raw_reaction_add(payload: RawReactionActionEvent)
    +
    + +
    +
    +async on_raw_reaction_clear(payload: RawReactionActionEvent)
    +
    + +
    +
    +async on_raw_reaction_clear_emoji(payload: RawReactionActionEvent)
    +
    + +
    +
    +async on_raw_reaction_remove(payload: RawReactionActionEvent)
    +
    + +
    +
    +async on_reaction_add(reaction: Reaction, user: User)
    +
    + +
    +
    +async on_reaction_clear(message: Message, reactions: list[discord.reaction.Reaction])
    +
    + +
    +
    +async on_reaction_clear_emoji(reaction: Reaction)
    +
    + +
    +
    +async on_reaction_remove(reaction: Reaction, user: User)
    +
    + +
    +
    +async on_ready()
    +
    + +
    +
    +async on_resume()
    +
    + +
    +
    +async on_typing(channel: Messageable, user: Union[User, Member], when: datetime)
    +
    + +
    +
    +async on_user_update(before: User, after: User)
    +
    + +
    +
    +async on_voice_state_update(member: Member, before: VoiceState, after: VoiceState)
    +
    + +
    +
    +async on_webhooks_update(channel: GuildChannel)
    +
    + +
    + +
    +
    +

    cpl_discord.service.discord_service_abc

    +
    +
    +class cpl_discord.service.discord_service_abc.DiscordServiceABC
    +

    Bases: ABC

    +
    +
    +abstract init(bot: Bot)
    +
    + +
    +
    +abstract async on_bulk_message_delete(messages: list[discord.message.Message])
    +
    + +
    +
    +abstract async on_command()
    +
    + +
    +
    +abstract async on_command_completion()
    +
    + +
    +
    +abstract async on_command_error()
    +
    + +
    +
    +abstract async on_connect()
    +
    + +
    +
    +abstract async on_disconnect()
    +
    + +
    +
    +abstract async on_error(event: str, *args, **kwargs)
    +
    + +
    +
    +abstract async on_group_join(chhanel: GroupChannel, user: User)
    +
    + +
    +
    +abstract async on_group_remove(chhanel: GroupChannel, user: User)
    +
    + +
    +
    +abstract async on_guild_available(guild: Guild)
    +
    + +
    +
    +abstract async on_guild_channel_create(channel: GuildChannel)
    +
    + +
    +
    +abstract async on_guild_channel_delete(channel: GuildChannel)
    +
    + +
    +
    +abstract async on_guild_channel_pins_update(channel: GuildChannel, list_pin: Optional[datetime])
    +
    + +
    +
    +abstract async on_guild_channel_update(before: GuildChannel, after: GuildChannel)
    +
    + +
    +
    +abstract async on_guild_emojis_update(guild: Guild, before: Sequence[Emoji], after: Sequence[Emoji])
    +
    + +
    +
    +abstract async on_guild_integrations_update(guild: Guild)
    +
    + +
    +
    +abstract async on_guild_join(guild: Guild)
    +
    + +
    +
    +abstract async on_guild_remove(guild: Guild)
    +
    + +
    +
    +abstract async on_guild_role_create(role: Role)
    +
    + +
    +
    +abstract async on_guild_role_delete(role: Role)
    +
    + +
    +
    +abstract async on_guild_role_update(before: Role, after: Role)
    +
    + +
    +
    +abstract async on_guild_unavailable(guild: Guild)
    +
    + +
    +
    +abstract async on_guild_update(before: Guild, after: Guild)
    +
    + +
    +
    +abstract async on_invite_create(invite: Invite)
    +
    + +
    +
    +abstract async on_invite_delete(invite: Invite)
    +
    + +
    +
    +abstract async on_member_ban(guild: Guild, user: User)
    +
    + +
    +
    +abstract async on_member_join(member: Member)
    +
    + +
    +
    +abstract async on_member_remove(member: Member)
    +
    + +
    +
    +abstract async on_member_unban(guild: Guild, user: User)
    +
    + +
    +
    +abstract async on_member_update(before: Member, after: Member)
    +
    + +
    +
    +abstract async on_message(message: Message)
    +
    + +
    +
    +abstract async on_message_delete(message: Message)
    +
    + +
    +
    +abstract async on_message_edit(before: Message, after: Message)
    +
    + +
    +
    +abstract async on_private_channel_create(channel: PrivateChannel)
    +
    + +
    +
    +abstract async on_private_channel_delete(channel: PrivateChannel)
    +
    + +
    +
    +abstract async on_private_channel_pins_update(channel: PrivateChannel, list_pin: Optional[datetime])
    +
    + +
    +
    +abstract async on_private_channel_update(before: GroupChannel, after: GroupChannel)
    +
    + +
    +
    +abstract async on_reaction_add(reaction: Reaction, user: User)
    +
    + +
    +
    +abstract async on_reaction_clear(message: Message, reactions: list[discord.reaction.Reaction])
    +
    + +
    +
    +abstract async on_reaction_clear_emoji(reaction: Reaction)
    +
    + +
    +
    +abstract async on_reaction_remove(reaction: Reaction, user: User)
    +
    + +
    +
    +abstract async on_ready()
    +
    + +
    +
    +abstract async on_resume()
    +
    + +
    +
    +abstract async on_typing(channel: Messageable, user: Union[User, Member], when: datetime)
    +
    + +
    +
    +abstract async on_user_update(before: User, after: User)
    +
    + +
    +
    +abstract async on_voice_state_update(member: Member, before: VoiceState, after: VoiceState)
    +
    + +
    +
    +abstract async on_webhooks_update(channel: GuildChannel)
    +
    + +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/build/html/cpl_query.base.html b/docs/build/html/cpl_query.base.html new file mode 100644 index 00000000..2e00c6d8 --- /dev/null +++ b/docs/build/html/cpl_query.base.html @@ -0,0 +1,725 @@ + + + + + + + cpl_query.base — Common Python Library documentation + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    cpl_query.base

    +
    +

    cpl_query.base.default_lambda

    +
    +
    +cpl_query.base.default_lambda.default_lambda(x: object)
    +
    + +
    +
    +

    cpl_query.base.ordered_queryable

    +
    +
    +class cpl_query.base.ordered_queryable.OrderedQueryable(_t: type, _values: Optional[Iterable] = None, _func: Optional[Callable] = None)
    +

    Bases: OrderedQueryableABC

    +

    Implementation of :class: cpl_query.extension.Iterable cpl_query.extension.OrderedIterableABC

    +
    +
    +then_by(_func: Callable) OrderedQueryableABC
    +

    Sorts OrderedList in ascending order by function

    +
    +

    func: Callable

    +
    +
    +

    list of cpl_query.iterable.ordered_iterable_abc.OrderedIterableABC

    +
    +
    + +
    +
    +then_by_descending(_func: Callable) OrderedQueryableABC
    +

    Sorts OrderedList in descending order by function

    +
    +

    func: Callable

    +
    +
    +

    list of cpl_query.iterable.ordered_iterable_abc.OrderedIterableABC

    +
    +
    + +
    + +
    +
    +

    cpl_query.base.ordered_queryable_abc

    +
    +
    +class cpl_query.base.ordered_queryable_abc.OrderedQueryableABC(_t: type, _values: Optional[Iterable] = None, _func: Optional[Callable] = None)
    +

    Bases: QueryableABC

    +
    +
    +abstract then_by(func: Callable) OrderedQueryableABC
    +

    Sorts OrderedList in ascending order by function

    +
    +

    func: Callable

    +
    +
    +

    list of cpl_query.iterable.ordered_iterable_abc.OrderedIterableABC

    +
    +
    + +
    +
    +abstract then_by_descending(func: Callable) OrderedQueryableABC
    +

    Sorts OrderedList in descending order by function

    +
    +

    func: Callable

    +
    +
    +

    list of cpl_query.iterable.ordered_iterable_abc.OrderedIterableABC

    +
    +
    + +
    + +
    +
    +

    cpl_query.base.queryable_abc

    +
    +
    +class cpl_query.base.queryable_abc.QueryableABC(t: Optional[type] = None, values: Optional[list] = None)
    +

    Bases: SequenceABC

    +
    +
    +all(_func: Optional[Callable] = None) bool
    +

    Checks if every element of list equals result found by function

    +
    +
    +
    func: Callable

    selected value

    +
    +
    +
    +
    +

    bool

    +
    +
    + +
    +
    +any(_func: Optional[Callable] = None) bool
    +

    Checks if list contains result found by function

    +
    +
    +
    func: Callable

    selected value

    +
    +
    +
    +
    +

    bool

    +
    +
    + +
    +
    +average(_func: Optional[Callable] = None) Union[int, float, complex]
    +

    Returns average value of list

    +
    +
    +
    func: Callable

    selected value

    +
    +
    +
    +
    +

    Union[int, float, complex]

    +
    +
    + +
    +
    +contains(_value: object) bool
    +

    Checks if list contains value given by function

    +
    +
    +
    value: object

    value

    +
    +
    +
    +
    +

    bool

    +
    +
    + +
    +
    +count(_func: Optional[Callable] = None) int
    +

    Returns length of list or count of found elements

    +
    +
    +
    func: Callable

    selected value

    +
    +
    +
    +
    +

    int

    +
    +
    + +
    +
    +distinct(_func: Optional[Callable] = None) QueryableABC
    +

    Returns list without redundancies

    +
    +
    +
    func: Callable

    selected value

    +
    +
    +
    +
    +
    +
    class
    +

    cpl_query.base.queryable_abc.QueryableABC

    +
    +
    +
    +
    + +
    +
    +element_at(_index: int) any
    +

    Returns element at given index

    +
    +
    +
    _index: int

    index

    +
    +
    +
    +
    +

    Value at _index: any

    +
    +
    + +
    +
    +element_at_or_default(_index: int) Optional[any]
    +

    Returns element at given index or None

    +
    +
    +
    _index: int

    index

    +
    +
    +
    +
    +

    Value at _index: Optional[any]

    +
    +
    + +
    +
    +first() any
    +

    Returns first element

    +
    +

    First element of list: any

    +
    +
    + +
    +
    +first_or_default() any
    +

    Returns first element or None

    +
    +

    First element of list: Optional[any]

    +
    +
    + +
    +
    +for_each(_func: Optional[Callable] = None)
    +

    Runs given function for each element of list

    +
    +
    +
    func: :class: Callable

    function to call

    +
    +
    +
    +
    + +
    +
    +group_by(_func: Optional[Callable] = None) QueryableABC
    +

    Groups by func

    +
    +

    Grouped list[list[any]]: any

    +
    +
    + +
    +
    +last() any
    +

    Returns last element

    +
    +

    Last element of list: any

    +
    +
    + +
    +
    +last_or_default() any
    +

    Returns last element or None

    +
    +

    Last element of list: Optional[any]

    +
    +
    + +
    +
    +max(_func: Optional[Callable] = None) Union[int, float, complex]
    +

    Returns the highest value

    +
    +
    +
    func: Callable

    selected value

    +
    +
    +
    +
    +

    Union[int, float, complex]

    +
    +
    + +
    +
    +median(_func=None) Union[int, float]
    +

    Return the median value of data elements

    +
    +

    Union[int, float]

    +
    +
    + +
    +
    +min(_func: Optional[Callable] = None) Union[int, float, complex]
    +

    Returns the lowest value

    +
    +
    +
    func: Callable

    selected value

    +
    +
    +
    +
    +

    Union[int, float, complex]

    +
    +
    + +
    +
    +order_by(_func: Optional[Callable] = None) QueryableABC
    +

    Sorts elements by function in ascending order

    +
    +
    +
    func: Callable

    selected value

    +
    +
    +
    +
    +
    +
    class
    +

    cpl_query.base.queryable_abc.QueryableABC

    +
    +
    +
    +
    + +
    +
    +order_by_descending(_func: Optional[Callable] = None) QueryableABC
    +

    Sorts elements by function in descending order

    +
    +
    +
    func: Callable

    selected value

    +
    +
    +
    +
    +
    +
    class
    +

    cpl_query.base.queryable_abc.QueryableABC

    +
    +
    +
    +
    + +
    +
    +reverse() QueryableABC
    +

    Reverses list

    +
    +
    +
    class
    +

    cpl_query.base.queryable_abc.QueryableABC

    +
    +
    +
    +
    + +
    +
    +select(_func: Callable) QueryableABC
    +

    Formats each element of list to a given format

    +
    +
    +
    class
    +

    cpl_query.base.queryable_abc.QueryableABC

    +
    +
    +
    +
    + +
    +
    +select_many(_func: Callable) QueryableABC
    +

    Flattens resulting lists to one

    +
    +
    +
    class
    +

    cpl_query.base.queryable_abc.QueryableABC

    +
    +
    +
    +
    + +
    +
    +single() any
    +

    Returns one single element of list

    +
    +

    Found value: any

    +
    +
    +

    ArgumentNoneException: when argument is None +Exception: when argument is None or found more than one element

    +
    +
    + +
    +
    +single_or_default() Optional[any]
    +

    Returns one single element of list

    +
    +

    Found value: Optional[any]

    +
    +
    + +
    +
    +skip(_index: int) QueryableABC
    +

    Skips all elements from index

    +
    +
    +
    _index: int

    index

    +
    +
    +
    +
    +
    +
    class
    +

    cpl_query.base.queryable_abc.QueryableABC

    +
    +
    +
    +
    + +
    +
    +skip_last(_index: int) QueryableABC
    +

    Skips all elements after index

    +
    +
    +
    _index: int

    index

    +
    +
    +
    +
    +
    +
    class
    +

    cpl_query.base.queryable_abc.QueryableABC

    +
    +
    +
    +
    + +
    +
    +sum(_func: Optional[Callable] = None) Union[int, float, complex]
    +

    Sum of all values

    +
    +
    +
    func: Callable

    selected value

    +
    +
    +
    +
    +

    Union[int, float, complex]

    +
    +
    + +
    +
    +take(_index: int) QueryableABC
    +

    Takes all elements from index

    +
    +
    +
    _index: int

    index

    +
    +
    +
    +
    +
    +
    class
    +

    cpl_query.base.queryable_abc.QueryableABC

    +
    +
    +
    +
    + +
    +
    +take_last(_index: int) QueryableABC
    +

    Takes all elements after index

    +
    +
    +
    _index: int

    index

    +
    +
    +
    +
    +
    +
    class
    +

    cpl_query.base.queryable_abc.QueryableABC

    +
    +
    +
    +
    + +
    +
    +where(_func: Optional[Callable] = None) QueryableABC
    +

    Select element by function

    +
    +
    +
    func: Callable

    selected value

    +
    +
    +
    +
    +
    +
    class
    +

    cpl_query.base.queryable_abc.QueryableABC

    +
    +
    +
    +
    + +
    + +
    +
    +

    cpl_query.base.sequence_abc

    +
    +
    +class cpl_query.base.sequence_abc.SequenceABC(t: Optional[type] = None, values: Optional[list] = None)
    +

    Bases: ABC

    +
    +
    +copy() SequenceABC
    +

    Creates a copy of sequence

    +
    +

    SequenceABC

    +
    +
    + +
    +
    +classmethod empty() SequenceABC
    +

    Returns an empty sequence

    +
    +

    Sequence object that contains no elements

    +
    +
    + +
    +
    +index(_object: object) int
    +

    Returns the index of given element

    +
    +

    Index of object

    +
    +
    +

    IndexError if object not in sequence

    +
    +
    + +
    +
    +next()
    +
    + +
    +
    +classmethod range(start: int, length: int) SequenceABC
    +
    + +
    +
    +to_list() list
    +

    Converts :class: cpl_query.base.sequence_abc.SequenceABC to :class: list

    +
    +
    +
    class
    +

    list

    +
    +
    +
    +
    + +
    +
    +property type: type
    +
    + +
    + +
    +
    +

    cpl_query.base.sequence_values

    +
    +
    +class cpl_query.base.sequence_values.SequenceValues(data: list, _t: type)
    +

    Bases: object

    +
    +
    +next()
    +
    + +
    +
    +reset()
    +
    + +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/build/html/cpl_query.enumerable.html b/docs/build/html/cpl_query.enumerable.html new file mode 100644 index 00000000..36b65ec3 --- /dev/null +++ b/docs/build/html/cpl_query.enumerable.html @@ -0,0 +1,161 @@ + + + + + + + cpl_query.enumerable — Common Python Library documentation + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    cpl_query.enumerable

    +
    +

    cpl_query.enumerable.enumerable

    +
    +
    +class cpl_query.enumerable.enumerable.Enumerable(t: Optional[type] = None, values: Optional[list] = None)
    +

    Bases: EnumerableABC

    +

    Implementation of :class: cpl_query.enumerable.enumerable_abc.EnumerableABC

    +
    + +
    +
    +

    cpl_query.enumerable.enumerable_abc

    +
    +
    +class cpl_query.enumerable.enumerable_abc.EnumerableABC(t: Optional[type] = None, values: Optional[list] = None)
    +

    Bases: QueryableABC

    +

    ABC to define functions on list

    +
    +
    +set_remove_error_check(_value: bool)
    +

    Set flag to check if element exists before removing

    +
    + +
    +
    +to_iterable() IterableABC
    +

    Converts :class: cpl_query.enumerable.enumerable_abc.EnumerableABC to :class: cpl_query.iterable.iterable_abc.IterableABC

    +
    +
    +
    class
    +

    cpl_query.iterable.iterable_abc.IterableABC

    +
    +
    +
    +
    + +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/build/html/cpl_query.exceptions.html b/docs/build/html/cpl_query.exceptions.html deleted file mode 100644 index 67a3674a..00000000 --- a/docs/build/html/cpl_query.exceptions.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - cpl_query.exceptions — Common Python Library documentation - - - - - - - - - - - - - - - - -
    - - -
    - -
    -
    -
    - -
    -
    -
    -
    - -
    -

    cpl_query.exceptions

    -
    -

    cpl_query.exceptions

    -
    -
    -exception cpl_query.exceptions.ArgumentNoneException(arg: ExceptionArgument)
    -

    Bases: Exception

    -

    Exception when argument is None

    -
    - -
    -
    -class cpl_query.exceptions.ExceptionArgument(value)
    -

    Bases: Enum

    -

    An enumeration.

    -
    -
    -func = 'func'
    -
    - -
    -
    -index = 'index'
    -
    - -
    -
    -list = 'list'
    -
    - -
    -
    -type = 'type'
    -
    - -
    -
    -value = 'value'
    -
    - -
    - -
    -
    -exception cpl_query.exceptions.IndexOutOfRangeException
    -

    Bases: Exception

    -

    Exception when index is out of range

    -
    - -
    -
    -exception cpl_query.exceptions.InvalidTypeException
    -

    Bases: Exception

    -

    Exception when type is invalid

    -
    - -
    -
    -exception cpl_query.exceptions.WrongTypeException
    -

    Bases: Exception

    -

    Exception when type is unexpected

    -
    - -
    -
    - - -
    -
    - -
    -
    -
    -
    - - - - \ No newline at end of file diff --git a/docs/build/html/cpl_query.extension.html b/docs/build/html/cpl_query.extension.html index d374cce7..0056ee6e 100644 --- a/docs/build/html/cpl_query.extension.html +++ b/docs/build/html/cpl_query.extension.html @@ -19,8 +19,8 @@ - - + + @@ -42,20 +42,20 @@
  22. Introduction to the CPL Docs
  23. Getting started
  24. Contributing to CPL
  25. -
  26. CLI Reference
  27. -
  28. API Reference
  29. -
  30. Query Reference @@ -72,7 +72,7 @@
    • »
    • -
    • Query Reference »
    • +
    • Query reference »
    • cpl_query.extension
    • View page source @@ -85,908 +85,36 @@

      cpl_query.extension

      -
      -

      cpl_query.extension.iterable_abc

      -
      -
      -class cpl_query.extension.iterable_abc.IterableABC(t: Optional[type] = None, values: Optional[list] = None)
      -

      Bases: ABC, list

      -

      ABC to define functions on list

      -
      -
      -abstract all(func: Callable) bool
      -

      Checks if every element of list equals result found by function

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      bool

      -
      -
      - -
      -
      -abstract any(func: Callable) bool
      -

      Checks if list contains result found by function

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      bool

      -
      -
      - -
      -
      -append(_IterableABC__object: object) None
      -

      Adds element to list

      -
      -
      -
      __object: object

      value

      -
      -
      -
      -
      - -
      -
      -abstract average(func: Optional[Callable] = None) Union[int, float, complex]
      -

      Returns average value of list

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      Union[int, float, complex]

      -
      -
      - -
      -
      -abstract contains(value: object) bool
      -

      Checks if list contains value given by function

      -
      -
      -
      value: object

      value

      -
      -
      -
      -
      -

      bool

      -
      -
      - -
      -
      -abstract count(func: Optional[Callable] = None) int
      -

      Returns length of list or count of found elements

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      int

      -
      -
      - -
      -
      -abstract distinct(func: Optional[Callable] = None) IterableABC
      -

      Returns list without redundancies

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -abstract element_at(index: int) any
      -

      Returns element at given index

      -
      -
      -
      index: int

      index

      -
      -
      -
      -
      -

      Value at index: any

      -
      -
      - -
      -
      -abstract element_at_or_default(index: int) Optional[any]
      -

      Returns element at given index or None

      -
      -
      -
      index: int

      index

      -
      -
      -
      -
      -

      Value at index: Optional[any]

      -
      -
      - -
      -
      -extend(_IterableABC__iterable: Iterable) None
      -

      Adds elements of given list to list

      -
      -
      -
      __iterable: :class: cpl_query.extension.iterable.Iterable

      index

      -
      -
      -
      -
      - -
      -
      -abstract first() any
      -

      Returns first element

      -
      -

      First element of list: any

      -
      -
      - -
      -
      -abstract first_or_default() any
      -

      Returns first element or None

      -
      -

      First element of list: Optional[any]

      -
      -
      - -
      -
      -abstract for_each(func: Callable)
      -

      Runs given function for each element of list

      -
      -
      -
      func: :class: Callable

      function to call

      -
      -
      -
      -
      - -
      -
      -abstract last() any
      -

      Returns last element

      -
      -

      Last element of list: any

      -
      -
      - -
      -
      -abstract last_or_default() any
      -

      Returns last element or None

      -
      -

      Last element of list: Optional[any]

      -
      -
      - -
      -
      -abstract max(func: Optional[Callable] = None) Union[int, float, complex]
      -

      Returns highest value

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      Union[int, float, complex]

      -
      -
      - -
      -
      -abstract min(func: Optional[Callable] = None) Union[int, float, complex]
      -

      Returns highest value

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      Union[int, float, complex]

      -
      -
      - -
      -
      -abstract order_by(func: Callable) IterableABC
      -

      Sorts elements by function in ascending order

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -abstract order_by_descending(func: Callable) IterableABC
      -

      Sorts elements by function in descending order

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -abstract reverse() IterableABC
      -

      Reverses list

      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -abstract single() any
      -

      Returns one single element of list

      -
      -

      Found value: any

      -
      -
      -

      ArgumentNoneException: when argument is None -Exception: when argument is None or found more than one element

      -
      -
      - -
      -
      -abstract single_or_default() Optional[any]
      -

      Returns one single element of list

      -
      -

      Found value: Optional[any]

      -
      -
      - -
      -
      -abstract skip(index: int) IterableABC
      -

      Skips all elements from index

      -
      -
      -
      index: int

      index

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -abstract skip_last(index: int) IterableABC
      -

      Skips all elements after index

      -
      -
      -
      index: int

      index

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -abstract sum(func: Optional[Callable] = None) Union[int, float, complex]
      -

      Sum of all values

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      Union[int, float, complex]

      -
      -
      - -
      -
      -abstract take(index: int) IterableABC
      -

      Takes all elements from index

      -
      -
      -
      index: int

      index

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -abstract take_last(index: int) IterableABC
      -

      Takes all elements after index

      -
      -
      -
      index: int

      index

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -to_list() list
      -

      Converts :class: cpl_query.extension.iterable_abc.IterableABC to :class: list

      -
      -
      -
      class
      -

      list

      -
      -
      -
      -
      - -
      -
      -property type: type
      -
      - -
      -
      -abstract where(func: Callable) IterableABC
      -

      Select element by function

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      - -
      -
      -

      cpl_query.extension.iterable

      -
      -
      -class cpl_query.extension.iterable.Iterable(t: Optional[type] = None, values: Optional[list] = None)
      -

      Bases: IterableABC

      -
      -
      -all(func: Callable) bool
      -

      Checks if every element of list equals result found by function

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      bool

      -
      -
      - -
      -
      -any(func: Callable) bool
      -

      Checks if list contains result found by function

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      bool

      -
      -
      - -
      -
      -average(func: Optional[Callable] = None) Union[int, float, complex]
      -

      Returns average value of list

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      Union[int, float, complex]

      -
      -
      - -
      -
      -contains(value: object) bool
      -

      Checks if list contains value given by function

      -
      -
      -
      value: object

      value

      -
      -
      -
      -
      -

      bool

      -
      -
      - -
      -
      -count(func: Optional[Callable] = None) int
      -

      Returns length of list or count of found elements

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      int

      -
      -
      - -
      -
      -distinct(func: Optional[Callable] = None) IterableABC
      -

      Returns list without redundancies

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -element_at(index: int) any
      -

      Returns element at given index

      -
      -
      -
      index: int

      index

      -
      -
      -
      -
      -

      Value at index: any

      -
      -
      - -
      -
      -element_at_or_default(index: int) Optional[any]
      -

      Returns element at given index or None

      -
      -
      -
      index: int

      index

      -
      -
      -
      -
      -

      Value at index: Optional[any]

      -
      -
      - -
      -
      -first() any
      -

      Returns first element

      -
      -

      First element of list: any

      -
      -
      - -
      -
      -first_or_default() Optional[any]
      -

      Returns first element or None

      -
      -

      First element of list: Optional[any]

      -
      -
      - -
      -
      -for_each(func: Callable)
      -

      Runs given function for each element of list

      -
      -
      -
      func: :class: Callable

      function to call

      -
      -
      -
      -
      - -
      -
      -last() any
      -

      Returns last element

      -
      -

      Last element of list: any

      -
      -
      - -
      -
      -last_or_default() Optional[any]
      -

      Returns last element or None

      -
      -

      Last element of list: Optional[any]

      -
      -
      - -
      -
      -max(func: Optional[Callable] = None) Union[int, float, complex]
      -

      Returns highest value

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      Union[int, float, complex]

      -
      -
      - -
      -
      -min(func: Optional[Callable] = None) Union[int, float, complex]
      -

      Returns highest value

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      Union[int, float, complex]

      -
      -
      - -
      -
      -order_by(func: Callable) OrderedIterableABC
      -

      Sorts elements by function in ascending order

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -order_by_descending(func: Callable) OrderedIterableABC
      -

      Sorts elements by function in descending order

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -reverse() IterableABC
      -

      Reverses list

      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -single() any
      -

      Returns one single element of list

      -
      -

      Found value: any

      -
      -
      -

      ArgumentNoneException: when argument is None -Exception: when argument is None or found more than one element

      -
      -
      - -
      -
      -single_or_default() Optional[any]
      -

      Returns one single element of list

      -
      -

      Found value: Optional[any]

      -
      -
      - -
      -
      -skip(index: int) IterableABC
      -

      Skips all elements from index

      -
      -
      -
      index: int

      index

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -skip_last(index: int) IterableABC
      -

      Skips all elements after index

      -
      -
      -
      index: int

      index

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -sum(func: Optional[Callable] = None) Union[int, float, complex]
      -

      Sum of all values

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -

      Union[int, float, complex]

      -
      -
      - -
      -
      -take(index: int) IterableABC
      -

      Takes all elements from index

      -
      -
      -
      index: int

      index

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -take_last(index: int) IterableABC
      -

      Takes all elements after index

      -
      -
      -
      index: int

      index

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      -
      -where(func: Callable) IterableABC
      -

      Select element by function

      -
      -
      -
      func: Callable

      selected value

      -
      -
      -
      -
      -
      -
      class
      -

      cpl_query.extension.iterable_abc.IterableABC

      -
      -
      -
      -
      - -
      - -

      cpl_query.extension.list

      -class cpl_query.extension.list.List(t: Optional[type] = None, values: Optional[list] = None)
      -

      Bases: Iterable

      +class cpl_query.extension.list.List(t: Optional[type] = None, values: Optional[Iterable] = None) +

      Bases: Iterable

      Implementation of :class: cpl_query.extension.iterable.Iterable

      -
      - -
      -
      -

      cpl_query.extension.ordered_iterable_abc

      -
      -
      -class cpl_query.extension.ordered_iterable_abc.OrderedIterableABC(_t: type, _func: Optional[Callable] = None)
      -

      Bases: IterableABC

      -
      -abstract then_by(func: Callable) OrderedIterableABC
      -

      Sorts OrderedList in ascending order by function

      +
      +to_enumerable() EnumerableABC
      +

      Converts :class: cpl_query.iterable.iterable_abc.IterableABC to :class: cpl_query.enumerable.enumerable_abc.EnumerableABC

      -

      func: Callable

      -
      -
      -

      list of cpl_query.extension.OrderedIterableABC

      +
      +
      class
      +

      cpl_query.enumerable.enumerable_abc.EnumerableABC

      +
      +
      -
      -abstract then_by_descending(func: Callable) OrderedIterableABC
      -

      Sorts OrderedList in descending order by function

      +
      +to_iterable() IterableABC
      +

      Converts :class: cpl_query.enumerable.enumerable_abc.EnumerableABC to :class: cpl_query.iterable.iterable_abc.IterableABC

      -

      func: Callable

      -
      -
      -

      list of cpl_query.extension.OrderedIterableABC

      -
      -
      - -
      - -
      -
      -

      cpl_query.extension.ordered_iterable

      -
      -
      -class cpl_query.extension.ordered_iterable.OrderedIterable(_t: Optional[type] = None)
      -

      Bases: Iterable, OrderedIterableABC

      -

      Implementation of :class: cpl_query.extension.Iterable cpl_query.extension.OrderedIterableABC

      -
      -
      -then_by(_func: Callable) OrderedIterableABC
      -

      Sorts OrderedList in ascending order by function

      -
      -

      func: Callable

      -
      -
      -

      list of cpl_query.extension.OrderedIterableABC

      -
      -
      - -
      -
      -then_by_descending(_func: Callable) OrderedIterableABC
      -

      Sorts OrderedList in descending order by function

      -
      -

      func: Callable

      -
      -
      -

      list of cpl_query.extension.OrderedIterableABC

      +
      +
      class
      +

      cpl_query.iterable.iterable_abc.IterableABC

      +
      +
      @@ -999,14 +127,14 @@ Exception: when argument is None or found more than one element

  31. +
  32. features (cpl_discord.container.guild.Guild attribute) +
  33. file_level (cpl_core.logging.logging_settings_name_enum.LoggingSettingsNameEnum attribute)
  34. filename (cpl_core.logging.logging_settings.LoggingSettings property) @@ -989,34 +1602,22 @@
  35. (cpl_core.logging.logging_settings_name_enum.LoggingSettingsNameEnum attribute)
  36. -
  37. first() (cpl_query.extension.iterable.Iterable method) - -
  38. -
  39. first_or_default() (cpl_query.extension.iterable.Iterable method) - -
  40. first_to_lower() (cpl_core.utils.string.String static method)
  41. first_to_upper() (cpl_core.utils.string.String static method)
  42. FirstCharToLowerPipe (class in cpl_core.pipes.first_char_to_lower_pipe)
  43. - -
  44. function (cpl_core.console.console_call.ConsoleCall property)
  45. @@ -1049,6 +1652,12 @@

    G

    - + @@ -1099,6 +1736,10 @@
  46. header_list (cpl_core.mailing.email.EMail property)
  47. +
  48. hoist (cpl_discord.container.role.Role attribute) +
  49. + + -

    P

    - +
    +
    +

    Q

    + + +
    +

    R

    + -
    -
  50. reset_cursor_position() (cpl_core.console.console.Console class method) +
  51. remove() (cpl_query.iterable.iterable_abc.IterableABC method) +
  52. +
  53. reset() (cpl_query.base.sequence_values.SequenceValues method)
  54. +
  55. select_many() (cpl_query.base.queryable_abc.QueryableABC method) +
  56. send_mail() (cpl_core.mailing.email_client_abc.EMailClientABC method)
  57. +
  58. SequenceABC (class in cpl_query.base.sequence_abc) +
  59. +
  60. SequenceValues (class in cpl_query.base.sequence_values) +
  61. server (cpl_core.database.connection.database_connection.DatabaseConnection property)
  62. -
    @@ -1604,30 +3059,40 @@ +
  63. timed_out_until (cpl_discord.container.member.Member attribute) +
  64. TimeFormatSettings (class in cpl_core.time.time_format_settings)
  65. TimeFormatSettingsNamesEnum (class in cpl_core.time.time_format_settings_names_enum)
  66. +
  67. to_enumerable() (cpl_query.extension.list.List method) + +
  68. +
  69. to_iterable() (cpl_query.enumerable.enumerable_abc.EnumerableABC method) + +
  70. to_list() (cpl_core.configuration.configuration_variable_name_enum.ConfigurationVariableNameEnum static method)
  71. transient (cpl_core.dependency_injection.service_lifetime_enum.ServiceLifetimeEnum attribute)
  72. -
  73. type (cpl_query.exceptions.ExceptionArgument attribute) +
  74. translate() (cpl_translation.translation_service.TranslationService method)
  75. +
  76. TranslatePipe (class in cpl_translation.translate_pipe) +
  77. +
  78. TranslationService (class in cpl_translation.translation_service) +
  79. +
  80. TranslationServiceABC (class in cpl_translation.translation_service_abc) +
  81. +
  82. TranslationSettings (class in cpl_translation.translation_settings) +
  83. +
  84. type (cpl_query.base.sequence_abc.SequenceABC property) + +
  85. @@ -1694,6 +3195,10 @@

    U

    + -
    +
    @@ -1806,7 +3315,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/getting_started.html b/docs/build/html/getting_started.html index 4a2ad194..30d07942 100644 --- a/docs/build/html/getting_started.html +++ b/docs/build/html/getting_started.html @@ -47,9 +47,11 @@
  86. Contributing to CPL
  87. -
  88. CLI Reference
  89. -
  90. API Reference
  91. -
  92. Query Reference
  93. +
  94. CLI reference
  95. +
  96. API reference
  97. +
  98. Discord reference
  99. +
  100. Query reference
  101. +
  102. Translation reference
  103. @@ -150,7 +152,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/index.html b/docs/build/html/index.html index 644661a1..0bf47481 100644 --- a/docs/build/html/index.html +++ b/docs/build/html/index.html @@ -41,9 +41,11 @@
  104. Introduction to the CPL Docs
  105. Getting started
  106. Contributing to CPL
  107. -
  108. CLI Reference
  109. -
  110. API Reference
  111. -
  112. Query Reference
  113. +
  114. CLI reference
  115. +
  116. API reference
  117. +
  118. Discord reference
  119. +
  120. Query reference
  121. +
  122. Translation reference
  123. @@ -234,9 +236,11 @@
  124. Introduction to the CPL Docs
  125. Getting started
  126. Contributing to CPL
  127. -
  128. CLI Reference
  129. -
  130. API Reference
  131. -
  132. Query Reference
  133. +
  134. CLI reference
  135. +
  136. API reference
  137. +
  138. Discord reference
  139. +
  140. Query reference
  141. +
  142. Translation reference
  143. @@ -252,7 +256,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/introduction.html b/docs/build/html/introduction.html index 9b2551b5..6db361f3 100644 --- a/docs/build/html/introduction.html +++ b/docs/build/html/introduction.html @@ -46,9 +46,11 @@
  144. Getting started
  145. Contributing to CPL
  146. -
  147. CLI Reference
  148. -
  149. API Reference
  150. -
  151. Query Reference
  152. +
  153. CLI reference
  154. +
  155. API reference
  156. +
  157. Discord reference
  158. +
  159. Query reference
  160. +
  161. Translation reference
  162. @@ -187,7 +189,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/modules.html b/docs/build/html/modules.html index fee698ea..f31637d2 100644 --- a/docs/build/html/modules.html +++ b/docs/build/html/modules.html @@ -40,9 +40,11 @@
  163. Introduction to the CPL Docs
  164. Getting started
  165. Contributing to CPL
  166. -
  167. CLI Reference
  168. -
  169. API Reference
  170. -
  171. Query Reference
  172. +
  173. CLI reference
  174. +
  175. API reference
  176. +
  177. Discord reference
  178. +
  179. Query reference
  180. +
  181. Translation reference
  182. @@ -131,7 +133,7 @@ -
  183. CLI Reference @@ -90,7 +92,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js index 72e5880f..a2b6df51 100644 --- a/docs/build/html/searchindex.js +++ b/docs/build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["cli.add", "cli.build", "cli.generate", "cli.help", "cli.install", "cli.new", "cli.overview", "cli.publish", "cli.remove", "cli.start", "cli.uninstall", "cli.update", "cli.version", "contributing", "cpl_cli", "cpl_core", "cpl_core.application", "cpl_core.configuration", "cpl_core.console", "cpl_core.database", "cpl_core.database.connection", "cpl_core.database.context", "cpl_core.dependency_injection", "cpl_core.environment", "cpl_core.logging", "cpl_core.mailing", "cpl_core.pipes", "cpl_core.time", "cpl_core.utils", "cpl_query", "cpl_query.exceptions", "cpl_query.extension", "getting_started", "index", "introduction", "modules", "quickstart", "setup", "tutorials", "tutorials.appsettings", "tutorials.console", "tutorials.console-arguments", "tutorials.create-startup", "tutorials.extend-application", "tutorials.extend-startup", "tutorials.logging", "tutorials.mail"], "filenames": ["cli.add.md", "cli.build.md", "cli.generate.md", "cli.help.md", "cli.install.md", "cli.new.md", "cli.overview.md", "cli.publish.md", "cli.remove.md", "cli.start.md", "cli.uninstall.md", "cli.update.md", "cli.version.md", "contributing.md", "cpl_cli.rst", "cpl_core.rst", "cpl_core.application.rst", "cpl_core.configuration.rst", "cpl_core.console.rst", "cpl_core.database.rst", "cpl_core.database.connection.rst", "cpl_core.database.context.rst", "cpl_core.dependency_injection.rst", "cpl_core.environment.rst", "cpl_core.logging.rst", "cpl_core.mailing.rst", "cpl_core.pipes.rst", "cpl_core.time.rst", "cpl_core.utils.rst", "cpl_query.rst", "cpl_query.exceptions.rst", "cpl_query.extension.rst", "getting_started.rst", "index.rst", "introduction.md", "modules.rst", "quickstart.md", "setup.md", "tutorials.rst", "tutorials.appsettings.md", "tutorials.console.md", "tutorials.console-arguments.md", "tutorials.create-startup.md", "tutorials.extend-application.md", "tutorials.extend-startup.md", "tutorials.logging.md", "tutorials.mail.md"], "titles": ["cpl add", "cpl build", "cpl generate", "cpl help", "cpl install", "cpl new", "CLI Overview and Command Reference", "cpl publish", "cpl remove", "cpl start", "cpl uninstall", "cpl update", "cpl version", "Contributing to CPL", "CLI Reference", "API Reference", "cpl_core.application", "cpl_core.configuration", "cpl_core.console", "cpl_core.database", "cpl_core.database.connection", "cpl_core.database.context", "cpl_core.dependency_injection", "cpl_core.environment", "cpl_core.logging", "cpl_core.mailing", "cpl_core.pipes", "cpl_core.time", "cpl_core.utils", "Query Reference", "cpl_query.exceptions", "cpl_query.extension", "Getting started", "Introduction to the CPL Docs", "Introduction to the CPL Docs", "cpl", "Getting started with CPL", "Setting up the local environment and workspace", "Tutorials", "Using appsettings.json", "Use cpl_core.console.Console", "Handle console arguments", "Create startup class", "Extend application", "Extend startup", "Use builtin logger", "Send mails"], "terms": {"remov": [0, 6, 7, 14, 35], "project": [0, 1, 4, 6, 7, 8, 10, 11, 13, 14, 32, 35, 37], "from": [0, 6, 7, 8, 10, 12, 13, 16, 17, 18, 19, 31, 33, 34, 36], "workspac": [0, 1, 5, 6, 8, 32, 35], "sourc": [0, 1, 7, 13, 28, 36, 37], "target": [0, 1], "A": [0, 5, 13], "refer": [0, 8, 33, 34, 35], "given": [0, 1, 4, 6, 7, 10, 17, 18, 19, 22, 28, 31], "If": [0, 5, 8, 13, 18, 37], "you": [0, 1, 6, 8, 13, 33, 34, 36, 37], "call": [0, 8, 16, 17, 18, 31], "command": [0, 1, 3, 4, 5, 7, 8, 10, 11, 13, 14, 28, 33, 34, 35, 37], "can": [0, 1, 6, 7, 8, 13, 33, 37], "us": [0, 1, 5, 6, 7, 8, 13, 16, 18, 25, 28, 32, 33, 34, 35, 36, 37, 38], "name": [0, 1, 2, 5, 6, 7, 8, 17, 23, 24, 28, 37], "otherwis": [0, 8, 18], "path": [0, 1, 7, 8, 14, 17, 23, 24, 35, 37], "must": [0, 1, 6, 8, 13, 18], "specifi": [0, 4, 5, 6, 8, 10, 11, 17, 18], "valu": [0, 1, 2, 3, 4, 5, 7, 8, 10, 17, 18, 19, 22, 23, 24, 25, 26, 27, 30, 31], "type": [0, 1, 2, 3, 4, 7, 8, 10, 14, 16, 17, 22, 30, 31, 35], "which": [0, 6, 17, 18, 28, 37], "ha": [0, 18], "ad": [0, 13], "str": [0, 1, 2, 3, 4, 5, 7, 8, 10, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 36], "referenc": 0, "simul": [0, 4, 8, 10, 11], "whether": [0, 4, 5, 8, 10, 11, 17], "copi": 1, "an": [1, 6, 7, 16, 17, 18, 19, 22, 23, 24, 25, 27, 30, 36, 37], "python": [1, 13, 15, 28, 33, 34, 35, 36, 37], "app": [1, 6, 16, 32, 33, 34, 35, 36], "output": [1, 6, 7, 17, 18, 33, 34, 36, 37], "directori": [1, 6, 7, 23, 33, 34, 36], "execut": [1, 6, 7, 17, 28], "within": [1, 6, 13], "b": [1, 6, 13], "The": [1, 2, 4, 5, 6, 7, 8, 10, 13, 22, 25, 28, 33, 34, 36, 37], "consol": [1, 3, 5, 6, 7, 15, 17, 24, 32, 33, 34, 35, 36, 38], "librari": [1, 5, 6, 7, 15, 32, 33, 34, 35], "all": [1, 7, 12, 13, 17, 31], "includ": [1, 13, 37], "file": [1, 2, 6, 7, 8, 9, 13, 17, 33, 37], "run": [1, 5, 16, 17, 18, 21, 28, 31, 33, 34, 36, 37], "directli": [1, 13], "prepar": [1, 6, 7, 13, 16, 33], "publish": [1, 6, 14, 33, 35, 37], "them": 1, "argument": [1, 5, 6, 7, 11, 14, 17, 18, 28, 30, 31, 32, 33, 34, 35, 38], "base": [2, 5, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 33, 34, 36], "g": [2, 6], "abc": [2, 16, 17, 20, 21, 22, 23, 24, 25, 26, 31], "abstract": [2, 16, 17, 20, 21, 22, 23, 24, 25, 26, 31], "class": [2, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 35, 38], "enum": [2, 17, 18, 19, 22, 23, 24, 25, 27, 30], "pipe": [2, 15, 22, 33, 34, 35], "servic": [2, 5, 16, 17, 22, 24, 25, 33, 34, 36], "set": [2, 16, 17, 18, 19, 21, 22, 23, 24, 25, 27, 28, 32, 35, 36], "configmodel": 2, "test": [2, 13, 23, 33, 34, 36], "thread": [2, 18], "valid": [2, 25, 36], "list": [3, 6, 12, 17, 18, 21, 22, 25, 26, 28, 29, 30, 33, 35], "avail": [3, 6, 13], "short": [3, 6], "h": [3, 6], "show": [3, 18], "messag": [3, 18, 24], "thi": [3, 13, 16, 33, 34, 36, 37], "packag": [4, 5, 6, 10, 12, 28, 32, 33, 34, 35, 36], "via": [4, 10, 13, 33, 34], "pip": [4, 10, 12, 15, 33, 34, 35, 36, 37], "i": [4, 6, 36], "without": [4, 6, 13, 31], "deped": 4, "your": [4, 6, 9, 13, 33, 34, 37], "dev": [4, 10], "develop": [4, 6, 10, 13, 23, 33, 34, 36, 37], "mode": [4, 10], "virtual": [4, 10], "gener": [5, 6, 7, 14, 33, 35, 36, 37], "initi": [5, 32, 35], "add": [5, 6, 13, 14, 17, 22, 25, 31, 35, 36], "n": [5, 6, 36, 37], "see": [5, 13, 20, 26, 36, 37], "simpl": [5, 33, 34, 37], "applic": [5, 9, 15, 18, 23, 24, 25, 32, 33, 34, 35, 36, 37, 38], "async": [5, 16], "startup": [5, 16, 32, 33, 34, 35, 38], "provid": [5, 13, 16, 22, 33, 34, 36, 37], "noth": 5, "venv": 5, "instal": [6, 12, 14, 28, 32, 35, 36], "cpl": [6, 14, 15, 22, 32, 37], "To": [6, 13, 36, 37], "creat": [6, 7, 13, 16, 17, 18, 22, 24, 25, 28, 32, 33, 34, 35, 38], "build": [6, 7, 14, 16, 28, 33, 35, 36, 37], "serv": 6, "new": [6, 13, 14, 18, 35, 36, 37], "server": [6, 20, 25, 33, 34, 37], "go": [6, 13, 33], "parent": 6, "follow": [6, 13, 36, 37], "my": [6, 13, 37], "first": [6, 13, 26, 28, 31, 33, 34], "cd": [6, 37], "start": [6, 14, 33, 34, 35], "In": [6, 13, 36], "termin": [6, 18, 36, 37], "commandnameoralia": 6, "requiredarg": 6, "optionalsarg": 6, "most": [6, 36, 37], "some": 6, "option": [6, 13, 17, 18, 19, 22, 24, 25, 28, 31, 33, 34, 36], "have": [6, 13, 36, 37], "alias": [6, 17], "ar": [6, 7, 13, 17], "shown": [6, 17, 37], "statement": [6, 21], "each": [6, 17, 31], "prefix": [6, 17], "absolut": 6, "current": [6, 23], "work": [6, 13, 23, 33, 34], "either": 6, "root": 6, "take": [6, 17, 31], "artifact": 6, "addit": [6, 13], "ani": [6, 18, 26, 31], "defin": [6, 17, 18, 31, 37], "its": [6, 13], "own": 6, "suppli": 6, "same": 6, "format": [6, 24, 27], "immedi": 6, "alia": [6, 26], "descript": [6, 11, 14, 35], "dist": [6, 7], "help": [6, 13, 14, 33, 34, 35], "With": 6, "depend": [6, 11, 33, 34, 36], "p": [6, 7], "setup": [6, 7, 34, 37], "py": [6, 7, 28, 33, 36], "r": [6, 8], "s": [6, 9, 13, 32, 35], "restart": [6, 9, 37], "chang": [6, 9, 13, 21, 36], "uninstal": [6, 14, 28, 35], "ui": [6, 10], "updat": [6, 13, 14, 35], "u": [6, 11], "version": [6, 14, 35], "v": [6, 12], "data": [7, 18], "cpl_core": [7, 15, 32, 35, 36, 37, 38], "json": [7, 17, 32, 33, 34, 35, 36, 37, 38], "delet": 8, "cli": [12, 32, 33, 34, 35, 36], "we": [13, 36], "would": 13, "love": 13, "make": [13, 37], "even": 13, "better": 13, "than": [13, 31], "todai": 13, "As": 13, "contributor": 13, "here": [13, 37], "like": [13, 33, 36], "issus": 13, "find": 13, "our": 13, "gitea": 13, "repositori": 13, "fix": 13, "implement": [13, 22, 31], "pleas": 13, "consid": 13, "size": 13, "order": [13, 31], "determin": 13, "right": 13, "step": 13, "proce": 13, "For": 13, "major": [13, 26], "open": [13, 36, 37], "outlin": 13, "propos": 13, "so": [13, 37], "discuss": 13, "process": 13, "allow": 13, "coordin": [13, 18], "effort": 13, "prevent": 13, "duplic": 13, "craft": 13, "successfulli": 13, "accept": 13, "note": 13, "topic": 13, "document": 13, "significantli": 13, "re": 13, "write": [13, 18, 24, 33, 34], "count": [13, 31], "small": 13, "befor": [13, 18], "search": [13, 17, 22], "tracker": 13, "mayb": 13, "problem": 13, "alreadi": [13, 36, 37], "exist": 13, "might": 13, "inform": [13, 24, 37], "workaround": 13, "readili": 13, "want": [13, 36], "soon": [13, 32, 35, 38], "possibl": [13, 17], "need": [13, 36, 37], "reproduc": 13, "confirm": 13, "requir": 13, "minim": 13, "reproduct": 13, "scenario": 13, "give": 13, "wealth": 13, "import": [13, 36], "back": [13, 18], "forth": 13, "question": 13, "quickli": 13, "point": [13, 16, 18], "out": [13, 30, 36, 37], "well": 13, "save": [13, 17, 21], "maintain": 13, "time": [13, 15, 24, 35], "ultim": 13, "abl": 13, "more": [13, 26, 31, 37], "often": 13, "themselv": 13, "while": 13, "understand": [13, 33, 34, 36, 37], "sometim": 13, "hard": 13, "extract": 13, "essenti": [13, 36], "bit": 13, "larger": 13, "codebas": 13, "realli": 13, "isol": 13, "unfortun": 13, "investig": 13, "don": [13, 36], "t": [13, 31, 36], "hear": 13, "close": [13, 18], "doesn": 13, "enough": 13, "info": [13, 24, 33, 34], "pr": 13, "relat": 13, "Be": 13, "sure": 13, "describ": 13, "design": 13, "d": 13, "upfront": 13, "ensur": 13, "readi": [13, 37], "fork": 13, "sh": [13, 15, 35, 37], "edraft": [13, 15, 35, 37], "de": [13, 26, 37], "sh_cpl": [13, 37], "repo": 13, "git": 13, "branch": 13, "checkout": 13, "master": 13, "patch": 13, "appropri": 13, "case": [13, 26, 28, 36], "commit": 13, "line": [13, 18, 36], "automat": 13, "rm": 13, "edit": 13, "push": 13, "origin": 13, "send": [13, 25, 32, 33, 34, 35, 38], "team": 13, "reserv": 13, "commun": 13, "member": 13, "who": 13, "haven": 13, "been": 13, "good": 13, "citizen": 13, "Such": 13, "behavior": 13, "appli": 13, "outsid": 13, "manag": [13, 33, 34], "channel": 13, "ask": 13, "fixup": 13, "head": 13, "That": 13, "thank": 13, "consist": 13, "throughout": 13, "keep": 13, "mind": 13, "one": [13, 31], "unit": 13, "public": 13, "api": [13, 33, 34, 35], "method": 13, "pep": 13, "8": 13, "style": 13, "guid": 13, "By": 13, "agre": 13, "under": 13, "mit": [13, 26], "overview": [14, 35, 37], "tabl": [14, 18, 28, 32, 33, 34, 35], "content": [14, 15, 32, 35], "basic": [14, 35, 36, 37], "workflow": [14, 35], "languag": [14, 35], "syntax": [14, 35], "rel": [14, 35], "schemat": [14, 35], "flag": [14, 35], "application_abc": [15, 35], "application_build": [15, 35], "application_builder_abc": [15, 35], "startup_abc": [15, 35], "configur": [15, 16, 22, 33, 34, 35], "configuration_abc": [15, 16, 22, 35], "configuration_model_abc": [15, 35], "configuration_variable_name_enum": [15, 35], "console_argu": [15, 35], "background_color_enum": [15, 35], "console_cal": [15, 35], "foreground_color_enum": [15, 35], "spinner_thread": [15, 35], "databas": [15, 22, 35], "connect": [15, 19, 21, 25, 35], "database_connect": [15, 19, 35], "database_connection_abc": [15, 19, 35], "context": [15, 19, 22, 35, 37], "database_context": [15, 19, 35], "database_context_abc": [15, 19, 22, 35], "submodul": [15, 35], "database_model": [15, 35], "database_set": [15, 20, 21, 35], "database_settings_name_enum": [15, 35], "dependency_inject": [15, 16, 35], "service_collect": [15, 35], "service_collection_abc": [15, 16, 35], "service_descriptor": [15, 35], "service_lifetime_enum": [15, 35], "service_provid": [15, 35], "service_provider_abc": [15, 16, 35], "environ": [15, 16, 17, 24, 25, 32, 33, 34, 35], "application_environ": [15, 35], "application_environment_abc": [15, 16, 24, 25, 35], "environment_name_enum": [15, 35], "log": [15, 25, 33, 34, 35], "logger_abc": [15, 25, 35], "logger_servic": [15, 35], "logging_level_enum": [15, 35], "logging_set": [15, 35], "logging_settings_name_enum": [15, 35], "mail": [15, 32, 33, 34, 35, 38], "email": [15, 35], "email_client_abc": [15, 35], "email_client_servic": [15, 35], "email_client_set": [15, 35], "email_client_settings_name_enum": [15, 35], "bool_pip": [15, 35], "modul": [15, 35], "first_char_to_lower_pip": [15, 35], "first_to_upper_pip": [15, 35], "ip_address_pip": [15, 35], "pipe_abc": [15, 35], "to_camel_case_pip": [15, 35], "to_snake_case_pip": [15, 35], "version_pip": [15, 35], "core": [15, 20, 33, 35, 37], "common": [15, 33, 34, 35], "time_format_set": [15, 24, 35], "time_format_settings_names_enum": [15, 35], "util": [15, 33, 34, 35], "credential_manag": [15, 35], "string": [15, 18, 20, 24, 25, 26, 33, 34, 35, 36], "applicationabc": 16, "config": [16, 22], "configurationabc": [16, 17, 22], "serviceproviderabc": [16, 17, 22], "contain": [16, 31], "object": [16, 17, 18, 22, 25, 28, 31, 33, 34], "load": 16, "appset": [16, 32, 35, 36, 38], "instanc": [16, 22], "main": [16, 36], "custom": [16, 17, 23, 33, 34], "entri": [16, 18], "run_async": 16, "applicationbuild": 16, "applicationbuilderabc": 16, "build_async": 16, "use_extens": 16, "extens": [16, 29, 33, 34, 35], "union": [16, 17, 18, 22, 31], "applicationextensionabc": 16, "startupextensionabc": 16, "use_startup": 16, "startupabc": 16, "arg": [16, 17, 18, 21, 26, 28, 30], "configure_configur": 16, "env": [16, 24], "applicationenvironmentabc": [16, 17, 23, 24, 25], "configure_servic": 16, "servicecollectionabc": [16, 22], "add_configur": 17, "key_typ": 17, "configurationmodelabc": [17, 19, 24, 25, 27], "add_console_argu": 17, "argumentabc": 17, "known": 17, "consoleargumentabc": 17, "add_environment_vari": 17, "read": [17, 18, 36], "variabl": [17, 28], "add_json_fil": 17, "bool": [17, 18, 19, 25, 26, 31], "none": [17, 18, 22, 24, 25, 28, 30, 31], "true": 17, "error": [17, 18, 24, 33, 34], "should": [17, 36, 37], "occur": 17, "wa": [17, 37], "found": [17, 31], "place": 17, "store": 17, "properti": [17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 31], "additional_argu": 17, "argument_error_funct": 17, "callabl": [17, 18, 22, 31], "argument_abc": 17, "create_console_argu": 17, "arg_typ": 17, "argumenttypeenum": 17, "token": 17, "kwarg": [17, 18], "begin": 17, "value_token": 17, "were": 17, "is_value_token_opt": 17, "runnabl": 17, "when": [17, 18, 30, 31], "for_each_argu": 17, "iter": [17, 29, 35], "through": [17, 36], "function": [17, 18, 28, 31, 33, 36], "get_configur": 17, "search_typ": 17, "return": [17, 18, 22, 25, 31, 36], "parse_console_argu": 17, "invalid": [17, 30], "from_dict": [17, 19, 24, 25, 27], "dict": [17, 18, 19, 24, 25, 26, 27], "convert": [17, 24, 25, 26, 27, 28, 31, 33, 34], "attribut": [17, 19, 24, 25, 27], "configurationvariablenameenum": 17, "enumer": [17, 18, 19, 22, 23, 24, 25, 27, 30], "static": [17, 25, 28], "to_list": [17, 31], "backgroundcolorenum": 18, "blue": 18, "on_blu": 18, "cyan": 18, "on_cyan": 18, "default": [18, 37], "on_default": 18, "green": 18, "on_green": 18, "grei": 18, "on_grei": 18, "magenta": 18, "on_magenta": 18, "red": 18, "on_r": 18, "white": 18, "on_whit": 18, "yellow": 18, "on_yellow": 18, "handl": [18, 28, 32, 33, 34, 35, 38], "input": [18, 33, 34, 36], "background_color": 18, "bytes_or_buff": 18, "encod": [18, 28], "expos": 18, "buffer": [18, 19], "decod": [18, 28], "handler": 18, "result": [18, 25, 28, 31], "__str__": 18, "repr": 18, "sy": 18, "getdefaultencod": 18, "strict": 18, "classmethod": [18, 28], "banner": [18, 33, 34], "print": [18, 36], "clear": 18, "color_reset": 18, "reset": [18, 28], "color": 18, "disabl": 18, "interact": 18, "enabl": [18, 36], "tb": 18, "traceback": 18, "foreground_color": 18, "read_lin": 18, "next": [18, 32, 35], "reset_cursor_posit": 18, "cursor": [18, 20, 21], "posit": 18, "select": [18, 21, 31, 36], "char": [18, 26, 28], "header_foreground_color": 18, "foregroundcolorenum": 18, "header_background_color": 18, "option_foreground_color": 18, "option_background_color": 18, "cursor_foreground_color": 18, "cursor_background_color": 18, "menu": [18, 32, 33, 34, 35], "charact": 18, "element": [18, 21, 31], "header": [18, 24, 25], "foreground": 18, "background": 18, "set_background_color": 18, "set_cursor_posit": 18, "x": 18, "int": [18, 19, 25, 26, 28, 31, 36], "y": [18, 36], "set_foreground_color": 18, "set_hold_back": 18, "spinner": [18, 33, 34], "text_foreground_color": 18, "spinner_foreground_color": 18, "text_background_color": 18, "spinner_background_color": 18, "end": [18, 24], "stop": 18, "text": 18, "keyword": 18, "activ": 18, "last": [18, 31], "write_at": [18, 33, 34], "write_lin": [18, 33, 34, 36], "write_line_at": [18, 33, 34], "consolecal": 18, "repres": [18, 19, 23, 25], "hold": 18, "spinnerthread": 18, "msg_len": 18, "length": [18, 28, 31, 36], "exit": [18, 36], "stop_spin": 18, "databaseset": [19, 20, 21, 22], "auth_plugin": 19, "charset": 19, "host": [19, 25], "password": [19, 36], "port": [19, 25], "use_unicod": 19, "user": [19, 36], "databasesettingsnameenum": 19, "authplugin": 19, "useunicod": 19, "databaseconnect": 20, "databaseconnectionabc": 20, "represent": [20, 21, 22, 24, 25, 27], "connection_str": 20, "http": [20, 37], "doc": 20, "sqlalchemi": 20, "org": 20, "en": 20, "14": 20, "engin": 20, "html": 20, "mysqlcursorbuff": [20, 21], "mysqlconnectionabstract": 20, "databasecontext": 21, "databasecontextabc": [21, 22], "save_chang": 21, "tupl": [21, 26], "sql": 21, "fetch": 21, "servicecollect": 22, "collect": 22, "add_db_context": 22, "db_context_typ": 22, "db_set": 22, "db_context": 22, "add_log": 22, "intern": 22, "logger": [22, 24, 25, 32, 33, 34, 35, 38], "add_pip": 22, "transient": [22, 33, 34], "add_scop": 22, "service_typ": 22, "scope": [22, 33, 34], "lifetim": [22, 33, 34], "self": 22, "add_singleton": 22, "singleton": [22, 33, 34], "add_transi": 22, "build_service_provid": 22, "add_discord": 22, "discord": [22, 33], "add_transl": 22, "translat": [22, 33], "servicedescriptor": 22, "servicelifetimeenum": 22, "base_typ": 22, "descriptor": 22, "1": [22, 24, 26, 36], "0": [22, 24, 26, 36], "2": [22, 24, 26, 36], "serviceprovid": 22, "build_servic": 22, "instance_typ": 22, "create_scop": 22, "scopeabc": 22, "get_servic": 22, "set_scop": 22, "applicationenviron": 23, "environmentnameenum": 23, "product": [23, 33, 34], "application_nam": 23, "date_time_now": 23, "datetim": 23, "end_tim": 23, "environment_nam": 23, "host_nam": 23, "runtime_directori": 23, "set_runtime_directori": 23, "runtim": [23, 33, 34], "set_working_directori": 23, "working_directori": 23, "start_tim": 23, "stage": [23, 33, 34], "loggerabc": [24, 25], "debug": [24, 33, 34], "ex": 24, "except": [24, 29, 31, 35], "thrown": 24, "fatal": [24, 33, 34], "program": 24, "trace": [24, 33, 34], "warn": [24, 33, 34], "loggingset": 24, "time_format": [24, 27], "timeformatset": [24, 27], "tree": 24, "logfil": 24, "logginglevelenum": 24, "5": [24, 36], "4": 24, "off": 24, "6": 24, "3": 24, "filenam": 24, "level": [24, 33, 34], "loggingsettingsnameenum": 24, "console_level": 24, "consoleloglevel": 24, "file_level": 24, "fileloglevel": 24, "subject": 25, "bodi": 25, "transceiv": 25, "receiv": 25, "e": 25, "add_head": 25, "add_receiv": 25, "check_mail": 25, "address": 25, "check": [25, 31], "get_cont": 25, "header_list": 25, "receiver_list": 25, "emailclientabc": 25, "emailcli": 25, "send_mail": 25, "mail_set": 25, "emailclientset": 25, "login": 25, "credenti": [25, 28, 33, 34], "user_nam": 25, "emailclientsettingsnameenum": 25, "usernam": 25, "boolpip": 26, "pipeabc": 26, "transform": 26, "firstchartolowerpip": 26, "lower": [26, 28, 36], "firsttoupperpip": 26, "upper": [26, 28, 36], "ipaddresspip": 26, "tocamelcasepip": 26, "camel": [26, 28], "camelcas": [26, 28], "tosnakecasepip": 26, "snake": [26, 28], "snake_cas": [26, 28], "versionpip": 26, "copyright": 26, "2020": 26, "2022": 26, "licens": [26, 36], "detail": [26, 33], "versioninfo": 26, "minor": 26, "micro": 26, "field": 26, "number": 26, "date_format": 27, "date_time_format": 27, "date_time_log_format": 27, "timeformatsettingsnamesenum": 27, "dateformat": 27, "datetimeformat": 27, "datetimelogformat": 27, "timeformat": 27, "credentialmanag": 28, "encrypt": [28, 33, 34], "decrypt": 28, "build_str": 28, "replac": 28, "base64": [28, 33, 34], "get_execut": 28, "get_outd": 28, "byte": 28, "get": [28, 33, 34, 35, 37], "outdat": 28, "get_packag": 28, "local": [28, 32, 35], "stdout": 28, "stderr": 28, "extra": [28, 37], "index": [28, 30, 31, 36, 37], "url": [28, 37], "subprocess": [28, 33, 34], "reset_execut": 28, "system": 28, "standard": [28, 33, 34], "set_execut": 28, "convert_to_camel_cas": 28, "convert_to_snake_cas": 28, "first_to_low": 28, "first_to_upp": 28, "random_str": 28, "random": [28, 36], "cpl_queri": [29, 35], "iterable_abc": [29, 35], "ordered_iterable_abc": [29, 35], "ordered_iter": [29, 35], "argumentnoneexcept": [30, 31], "exceptionargu": 30, "func": [30, 31], "indexoutofrangeexcept": 30, "rang": [30, 36], "invalidtypeexcept": 30, "wrongtypeexcept": 30, "unexpect": 30, "iterableabc": 31, "everi": 31, "equal": 31, "append": 31, "_iterableabc__object": 31, "__object": 31, "averag": 31, "float": 31, "complex": [31, 33, 34], "distinct": 31, "redund": 31, "element_at": 31, "element_at_or_default": 31, "extend": [31, 32, 35, 38], "_iterableabc__iter": 31, "__iter": 31, "first_or_default": 31, "for_each": 31, "last_or_default": 31, "max": 31, "highest": 31, "min": 31, "order_bi": 31, "sort": [31, 33], "ascend": 31, "order_by_descend": 31, "descend": 31, "revers": 31, "singl": 31, "single_or_default": 31, "skip": 31, "skip_last": 31, "after": 31, "sum": 31, "take_last": 31, "where": 31, "orderediterableabc": 31, "_t": 31, "_func": 31, "then_bi": 31, "orderedlist": 31, "then_by_descend": 31, "orderediter": 31, "prerequisit": [32, 35], "what": [32, 35], "up": [32, 35], "queri": [32, 33, 34, 35], "tutori": [32, 35, 36, 37], "com": [32, 35, 38], "builtin": [32, 35, 38], "platform": [33, 34], "meant": [33, 34], "effici": [33, 34], "desktop": [33, 34], "learn": [33, 34, 37], "enterpris": [33, 34], "expandl": [33, 34], "builder": [33, 34], "map": [33, 34], "inject": [33, 34, 36], "appnam": [33, 34], "hostnam": [33, 34], "wrapper": [33, 34], "differ": [33, 34], "variant": [33, 34], "to_lower_cas": [33, 34], "to_camel_cas": [33, 34], "code": [33, 36, 37], "connector": 33, "between": 33, "filter": 33, "linq": 33, "c": 33, "xd": 33, "kei": [33, 37], "dot": 33, "notat": 33, "These": 33, "page": 33, "great": 33, "about": [33, 37], "everyth": 33, "do": [33, 36], "contribut": 33, "welcom": 36, "introduc": 36, "walk": 36, "also": [36, 37], "sampl": 36, "ouput": 36, "look": 36, "done": 36, "readm": 36, "md": 36, "src": 36, "__init__": 36, "projectmain": 36, "id": 36, "vs": 36, "pycharm": 36, "folder": 36, "hello": [36, 37], "world": [36, 37], "emul": 36, "def": 36, "onli": 36, "__name__": 36, "__main__": 36, "generate_password": 36, "letter": 36, "join": 36, "choic": 36, "ascii_lowercas": 36, "elif": 36, "ascii_uppercas": 36, "ascii_lett": 36, "len": 36, "full": 36, "section": 36, "ve": 36, "continu": 36, "explor": 36, "window": 37, "prompt": 37, "featur": 37, "declin": 37, "enter": 37, "press": 37, "lib": 37, "live": 37, "navig": 37, "launch": 37, "watch": 37, "chnage": 37, "those": 37, "success": 37, "similar": 37, "fore": 37, "pyhton": 37}, "objects": {"cpl_core.application": [[16, 0, 0, "-", "application_abc"], [16, 0, 0, "-", "application_builder"], [16, 0, 0, "-", "application_builder_abc"], [16, 0, 0, "-", "startup_abc"]], "cpl_core.application.application_abc": [[16, 1, 1, "", "ApplicationABC"]], "cpl_core.application.application_abc.ApplicationABC": [[16, 2, 1, "", "configure"], [16, 2, 1, "", "main"], [16, 2, 1, "", "run"], [16, 2, 1, "", "run_async"]], "cpl_core.application.application_builder": [[16, 1, 1, "", "ApplicationBuilder"]], "cpl_core.application.application_builder.ApplicationBuilder": [[16, 2, 1, "", "build"], [16, 2, 1, "", "build_async"], [16, 2, 1, "", "use_extension"], [16, 2, 1, "", "use_startup"]], "cpl_core.application.application_builder_abc": [[16, 1, 1, "", "ApplicationBuilderABC"]], "cpl_core.application.application_builder_abc.ApplicationBuilderABC": [[16, 2, 1, "", "build"], [16, 2, 1, "", "build_async"], [16, 2, 1, "", "use_startup"]], "cpl_core.application.startup_abc": [[16, 1, 1, "", "StartupABC"]], "cpl_core.application.startup_abc.StartupABC": [[16, 2, 1, "", "configure_configuration"], [16, 2, 1, "", "configure_services"]], "cpl_core.configuration": [[17, 0, 0, "-", "configuration"], [17, 0, 0, "-", "configuration_abc"], [17, 0, 0, "-", "configuration_model_abc"], [17, 0, 0, "-", "configuration_variable_name_enum"]], "cpl_core.configuration.configuration": [[17, 1, 1, "", "Configuration"]], "cpl_core.configuration.configuration.Configuration": [[17, 2, 1, "", "add_configuration"], [17, 2, 1, "", "add_console_argument"], [17, 2, 1, "", "add_environment_variables"], [17, 2, 1, "", "add_json_file"], [17, 3, 1, "", "additional_arguments"], [17, 3, 1, "", "argument_error_function"], [17, 3, 1, "", "arguments"], [17, 2, 1, "", "create_console_argument"], [17, 3, 1, "", "environment"], [17, 2, 1, "", "for_each_argument"], [17, 2, 1, "", "get_configuration"], [17, 2, 1, "", "parse_console_arguments"]], "cpl_core.configuration.configuration_abc": [[17, 1, 1, "", "ConfigurationABC"]], "cpl_core.configuration.configuration_abc.ConfigurationABC": [[17, 2, 1, "", "add_configuration"], [17, 2, 1, "", "add_console_argument"], [17, 2, 1, "", "add_environment_variables"], [17, 2, 1, "", "add_json_file"], [17, 3, 1, "", "additional_arguments"], [17, 3, 1, "", "argument_error_function"], [17, 3, 1, "", "arguments"], [17, 2, 1, "", "create_console_argument"], [17, 3, 1, "", "environment"], [17, 2, 1, "", "for_each_argument"], [17, 2, 1, "", "get_configuration"], [17, 2, 1, "", "parse_console_arguments"]], "cpl_core.configuration.configuration_model_abc": [[17, 1, 1, "", "ConfigurationModelABC"]], "cpl_core.configuration.configuration_model_abc.ConfigurationModelABC": [[17, 2, 1, "", "from_dict"]], "cpl_core.configuration.configuration_variable_name_enum": [[17, 1, 1, "", "ConfigurationVariableNameEnum"]], "cpl_core.configuration.configuration_variable_name_enum.ConfigurationVariableNameEnum": [[17, 4, 1, "", "customer"], [17, 4, 1, "", "environment"], [17, 4, 1, "", "name"], [17, 2, 1, "", "to_list"]], "cpl_core.console": [[18, 0, 0, "-", "background_color_enum"], [18, 0, 0, "-", "console"], [18, 0, 0, "-", "console_call"], [18, 0, 0, "-", "foreground_color_enum"], [18, 0, 0, "-", "spinner_thread"]], "cpl_core.console.background_color_enum": [[18, 1, 1, "", "BackgroundColorEnum"]], "cpl_core.console.background_color_enum.BackgroundColorEnum": [[18, 4, 1, "", "blue"], [18, 4, 1, "", "cyan"], [18, 4, 1, "", "default"], [18, 4, 1, "", "green"], [18, 4, 1, "", "grey"], [18, 4, 1, "", "magenta"], [18, 4, 1, "", "red"], [18, 4, 1, "", "white"], [18, 4, 1, "", "yellow"]], "cpl_core.console.console": [[18, 1, 1, "", "Console"]], "cpl_core.console.console.Console": [[18, 3, 1, "", "background_color"], [18, 2, 1, "", "banner"], [18, 2, 1, "", "clear"], [18, 2, 1, "", "close"], [18, 2, 1, "", "color_reset"], [18, 2, 1, "", "disable"], [18, 2, 1, "", "enable"], [18, 2, 1, "", "error"], [18, 3, 1, "", "foreground_color"], [18, 2, 1, "", "read"], [18, 2, 1, "", "read_line"], [18, 2, 1, "", "reset_cursor_position"], [18, 2, 1, "", "select"], [18, 2, 1, "", "set_background_color"], [18, 2, 1, "", "set_cursor_position"], [18, 2, 1, "", "set_foreground_color"], [18, 2, 1, "", "set_hold_back"], [18, 2, 1, "", "spinner"], [18, 2, 1, "", "table"], [18, 2, 1, "", "write"], [18, 2, 1, "", "write_at"], [18, 2, 1, "", "write_line"], [18, 2, 1, "", "write_line_at"]], "cpl_core.console.console_call": [[18, 1, 1, "", "ConsoleCall"]], "cpl_core.console.console_call.ConsoleCall": [[18, 3, 1, "", "args"], [18, 3, 1, "", "function"]], "cpl_core.console.foreground_color_enum": [[18, 1, 1, "", "ForegroundColorEnum"]], "cpl_core.console.foreground_color_enum.ForegroundColorEnum": [[18, 4, 1, "", "blue"], [18, 4, 1, "", "cyan"], [18, 4, 1, "", "default"], [18, 4, 1, "", "green"], [18, 4, 1, "", "grey"], [18, 4, 1, "", "magenta"], [18, 4, 1, "", "red"], [18, 4, 1, "", "white"], [18, 4, 1, "", "yellow"]], "cpl_core.console.spinner_thread": [[18, 1, 1, "", "SpinnerThread"]], "cpl_core.console.spinner_thread.SpinnerThread": [[18, 2, 1, "", "exit"], [18, 2, 1, "", "run"], [18, 2, 1, "", "stop_spinning"]], "cpl_core.database.connection": [[20, 0, 0, "-", "database_connection"], [20, 0, 0, "-", "database_connection_abc"]], "cpl_core.database.connection.database_connection": [[20, 1, 1, "", "DatabaseConnection"]], "cpl_core.database.connection.database_connection.DatabaseConnection": [[20, 2, 1, "", "connect"], [20, 3, 1, "", "cursor"], [20, 3, 1, "", "server"]], "cpl_core.database.connection.database_connection_abc": [[20, 1, 1, "", "DatabaseConnectionABC"]], "cpl_core.database.connection.database_connection_abc.DatabaseConnectionABC": [[20, 2, 1, "", "connect"], [20, 3, 1, "", "cursor"], [20, 3, 1, "", "server"]], "cpl_core.database.context": [[21, 0, 0, "-", "database_context"], [21, 0, 0, "-", "database_context_abc"]], "cpl_core.database.context.database_context": [[21, 1, 1, "", "DatabaseContext"]], "cpl_core.database.context.database_context.DatabaseContext": [[21, 2, 1, "", "connect"], [21, 3, 1, "", "cursor"], [21, 2, 1, "", "save_changes"], [21, 2, 1, "", "select"]], "cpl_core.database.context.database_context_abc": [[21, 1, 1, "", "DatabaseContextABC"]], "cpl_core.database.context.database_context_abc.DatabaseContextABC": [[21, 2, 1, "", "connect"], [21, 3, 1, "", "cursor"], [21, 2, 1, "", "save_changes"], [21, 2, 1, "", "select"]], "cpl_core.database": [[19, 0, 0, "-", "database_settings"], [19, 0, 0, "-", "database_settings_name_enum"]], "cpl_core.database.database_settings": [[19, 1, 1, "", "DatabaseSettings"]], "cpl_core.database.database_settings.DatabaseSettings": [[19, 3, 1, "", "auth_plugin"], [19, 3, 1, "", "buffered"], [19, 3, 1, "", "charset"], [19, 3, 1, "", "database"], [19, 2, 1, "", "from_dict"], [19, 3, 1, "", "host"], [19, 3, 1, "", "password"], [19, 3, 1, "", "port"], [19, 3, 1, "", "use_unicode"], [19, 3, 1, "", "user"]], "cpl_core.database.database_settings_name_enum": [[19, 1, 1, "", "DatabaseSettingsNameEnum"]], "cpl_core.database.database_settings_name_enum.DatabaseSettingsNameEnum": [[19, 4, 1, "", "auth_plugin"], [19, 4, 1, "", "buffered"], [19, 4, 1, "", "charset"], [19, 4, 1, "", "database"], [19, 4, 1, "", "host"], [19, 4, 1, "", "password"], [19, 4, 1, "", "port"], [19, 4, 1, "", "use_unicode"], [19, 4, 1, "", "user"]], "cpl_core.dependency_injection": [[22, 0, 0, "-", "service_collection"], [22, 0, 0, "-", "service_collection_abc"], [22, 0, 0, "-", "service_descriptor"], [22, 0, 0, "-", "service_lifetime_enum"], [22, 0, 0, "-", "service_provider"], [22, 0, 0, "-", "service_provider_abc"]], "cpl_core.dependency_injection.service_collection": [[22, 1, 1, "", "ServiceCollection"]], "cpl_core.dependency_injection.service_collection.ServiceCollection": [[22, 2, 1, "", "add_db_context"], [22, 2, 1, "", "add_logging"], [22, 2, 1, "", "add_pipes"], [22, 2, 1, "", "add_scoped"], [22, 2, 1, "", "add_singleton"], [22, 2, 1, "", "add_transient"], [22, 2, 1, "", "build_service_provider"]], "cpl_core.dependency_injection.service_collection_abc": [[22, 1, 1, "", "ServiceCollectionABC"]], "cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC": [[22, 2, 1, "", "add_db_context"], [22, 2, 1, "", "add_discord"], [22, 2, 1, "", "add_logging"], [22, 2, 1, "", "add_pipes"], [22, 2, 1, "", "add_scoped"], [22, 2, 1, "", "add_singleton"], [22, 2, 1, "", "add_transient"], [22, 2, 1, "", "add_translation"], [22, 2, 1, "", "build_service_provider"]], "cpl_core.dependency_injection.service_descriptor": [[22, 1, 1, "", "ServiceDescriptor"]], "cpl_core.dependency_injection.service_descriptor.ServiceDescriptor": [[22, 3, 1, "", "base_type"], [22, 3, 1, "", "implementation"], [22, 3, 1, "", "lifetime"], [22, 3, 1, "", "service_type"]], "cpl_core.dependency_injection.service_lifetime_enum": [[22, 1, 1, "", "ServiceLifetimeEnum"]], "cpl_core.dependency_injection.service_lifetime_enum.ServiceLifetimeEnum": [[22, 4, 1, "", "scoped"], [22, 4, 1, "", "singleton"], [22, 4, 1, "", "transient"]], "cpl_core.dependency_injection.service_provider": [[22, 1, 1, "", "ServiceProvider"]], "cpl_core.dependency_injection.service_provider.ServiceProvider": [[22, 2, 1, "", "build_service"], [22, 2, 1, "", "create_scope"], [22, 2, 1, "", "get_service"], [22, 2, 1, "", "set_scope"]], "cpl_core.dependency_injection.service_provider_abc": [[22, 1, 1, "", "ServiceProviderABC"]], "cpl_core.dependency_injection.service_provider_abc.ServiceProviderABC": [[22, 2, 1, "", "build_service"], [22, 2, 1, "", "create_scope"], [22, 2, 1, "", "get_service"], [22, 2, 1, "", "set_scope"]], "cpl_core.environment": [[23, 0, 0, "-", "application_environment"], [23, 0, 0, "-", "application_environment_abc"], [23, 0, 0, "-", "environment_name_enum"]], "cpl_core.environment.application_environment": [[23, 1, 1, "", "ApplicationEnvironment"]], "cpl_core.environment.application_environment.ApplicationEnvironment": [[23, 3, 1, "", "application_name"], [23, 3, 1, "", "customer"], [23, 3, 1, "", "date_time_now"], [23, 3, 1, "", "end_time"], [23, 3, 1, "", "environment_name"], [23, 3, 1, "", "host_name"], [23, 3, 1, "", "runtime_directory"], [23, 2, 1, "", "set_runtime_directory"], [23, 2, 1, "", "set_working_directory"], [23, 3, 1, "", "start_time"], [23, 3, 1, "", "working_directory"]], "cpl_core.environment.application_environment_abc": [[23, 1, 1, "", "ApplicationEnvironmentABC"]], "cpl_core.environment.application_environment_abc.ApplicationEnvironmentABC": [[23, 3, 1, "", "application_name"], [23, 3, 1, "", "customer"], [23, 3, 1, "", "date_time_now"], [23, 3, 1, "", "end_time"], [23, 3, 1, "", "environment_name"], [23, 3, 1, "", "host_name"], [23, 3, 1, "", "runtime_directory"], [23, 2, 1, "", "set_runtime_directory"], [23, 2, 1, "", "set_working_directory"], [23, 3, 1, "", "start_time"], [23, 3, 1, "", "working_directory"]], "cpl_core.environment.environment_name_enum": [[23, 1, 1, "", "EnvironmentNameEnum"]], "cpl_core.environment.environment_name_enum.EnvironmentNameEnum": [[23, 4, 1, "", "development"], [23, 4, 1, "", "production"], [23, 4, 1, "", "staging"], [23, 4, 1, "", "testing"]], "cpl_core.logging": [[24, 0, 0, "-", "logger_abc"], [24, 0, 0, "-", "logger_service"], [24, 0, 0, "-", "logging_level_enum"], [24, 0, 0, "-", "logging_settings"], [24, 0, 0, "-", "logging_settings_name_enum"]], "cpl_core.logging.logger_abc": [[24, 1, 1, "", "LoggerABC"]], "cpl_core.logging.logger_abc.LoggerABC": [[24, 2, 1, "", "debug"], [24, 2, 1, "", "error"], [24, 2, 1, "", "fatal"], [24, 2, 1, "", "header"], [24, 2, 1, "", "info"], [24, 2, 1, "", "trace"], [24, 2, 1, "", "warn"]], "cpl_core.logging.logger_service": [[24, 1, 1, "", "Logger"]], "cpl_core.logging.logger_service.Logger": [[24, 2, 1, "", "create"], [24, 2, 1, "", "debug"], [24, 2, 1, "", "error"], [24, 2, 1, "", "fatal"], [24, 2, 1, "", "header"], [24, 2, 1, "", "info"], [24, 2, 1, "", "trace"], [24, 2, 1, "", "warn"]], "cpl_core.logging.logging_level_enum": [[24, 1, 1, "", "LoggingLevelEnum"]], "cpl_core.logging.logging_level_enum.LoggingLevelEnum": [[24, 4, 1, "", "DEBUG"], [24, 4, 1, "", "ERROR"], [24, 4, 1, "", "FATAL"], [24, 4, 1, "", "INFO"], [24, 4, 1, "", "OFF"], [24, 4, 1, "", "TRACE"], [24, 4, 1, "", "WARN"]], "cpl_core.logging.logging_settings": [[24, 1, 1, "", "LoggingSettings"]], "cpl_core.logging.logging_settings.LoggingSettings": [[24, 3, 1, "", "console"], [24, 3, 1, "", "filename"], [24, 2, 1, "", "from_dict"], [24, 3, 1, "", "level"], [24, 3, 1, "", "path"]], "cpl_core.logging.logging_settings_name_enum": [[24, 1, 1, "", "LoggingSettingsNameEnum"]], "cpl_core.logging.logging_settings_name_enum.LoggingSettingsNameEnum": [[24, 4, 1, "", "console_level"], [24, 4, 1, "", "file_level"], [24, 4, 1, "", "filename"], [24, 4, 1, "", "path"]], "cpl_core.mailing": [[25, 0, 0, "-", "email"], [25, 0, 0, "-", "email_client_abc"], [25, 0, 0, "-", "email_client_service"], [25, 0, 0, "-", "email_client_settings"], [25, 0, 0, "-", "email_client_settings_name_enum"]], "cpl_core.mailing.email": [[25, 1, 1, "", "EMail"]], "cpl_core.mailing.email.EMail": [[25, 2, 1, "", "add_header"], [25, 2, 1, "", "add_receiver"], [25, 3, 1, "", "body"], [25, 2, 1, "", "check_mail"], [25, 2, 1, "", "get_content"], [25, 3, 1, "", "header"], [25, 3, 1, "", "header_list"], [25, 3, 1, "", "receiver"], [25, 3, 1, "", "receiver_list"], [25, 3, 1, "", "subject"], [25, 3, 1, "", "transceiver"]], "cpl_core.mailing.email_client_abc": [[25, 1, 1, "", "EMailClientABC"]], "cpl_core.mailing.email_client_abc.EMailClientABC": [[25, 2, 1, "", "connect"], [25, 2, 1, "", "send_mail"]], "cpl_core.mailing.email_client_service": [[25, 1, 1, "", "EMailClient"]], "cpl_core.mailing.email_client_service.EMailClient": [[25, 2, 1, "", "connect"], [25, 2, 1, "", "create"], [25, 2, 1, "", "login"], [25, 2, 1, "", "send_mail"]], "cpl_core.mailing.email_client_settings": [[25, 1, 1, "", "EMailClientSettings"]], "cpl_core.mailing.email_client_settings.EMailClientSettings": [[25, 3, 1, "", "credentials"], [25, 2, 1, "", "from_dict"], [25, 3, 1, "", "host"], [25, 3, 1, "", "port"], [25, 3, 1, "", "user_name"]], "cpl_core.mailing.email_client_settings_name_enum": [[25, 1, 1, "", "EMailClientSettingsNameEnum"]], "cpl_core.mailing.email_client_settings_name_enum.EMailClientSettingsNameEnum": [[25, 4, 1, "", "credentials"], [25, 4, 1, "", "host"], [25, 4, 1, "", "port"], [25, 4, 1, "", "user_name"]], "cpl_core": [[26, 0, 0, "-", "pipes"]], "cpl_core.pipes": [[26, 1, 1, "", "VersionInfo"], [26, 0, 0, "-", "bool_pipe"], [26, 0, 0, "-", "first_char_to_lower_pipe"], [26, 0, 0, "-", "first_to_upper_pipe"], [26, 0, 0, "-", "ip_address_pipe"], [26, 0, 0, "-", "pipe_abc"], [26, 0, 0, "-", "to_camel_case_pipe"], [26, 0, 0, "-", "to_snake_case_pipe"], [26, 0, 0, "-", "version_pipe"]], "cpl_core.pipes.VersionInfo": [[26, 4, 1, "", "major"], [26, 4, 1, "", "micro"], [26, 4, 1, "", "minor"]], "cpl_core.pipes.bool_pipe": [[26, 1, 1, "", "BoolPipe"]], "cpl_core.pipes.bool_pipe.BoolPipe": [[26, 2, 1, "", "transform"]], "cpl_core.pipes.first_char_to_lower_pipe": [[26, 1, 1, "", "FirstCharToLowerPipe"]], "cpl_core.pipes.first_char_to_lower_pipe.FirstCharToLowerPipe": [[26, 2, 1, "", "transform"]], "cpl_core.pipes.first_to_upper_pipe": [[26, 1, 1, "", "FirstToUpperPipe"]], "cpl_core.pipes.first_to_upper_pipe.FirstToUpperPipe": [[26, 2, 1, "", "transform"]], "cpl_core.pipes.ip_address_pipe": [[26, 1, 1, "", "IPAddressPipe"]], "cpl_core.pipes.ip_address_pipe.IPAddressPipe": [[26, 2, 1, "", "transform"]], "cpl_core.pipes.pipe_abc": [[26, 1, 1, "", "PipeABC"]], "cpl_core.pipes.pipe_abc.PipeABC": [[26, 2, 1, "", "transform"]], "cpl_core.pipes.to_camel_case_pipe": [[26, 1, 1, "", "ToCamelCasePipe"]], "cpl_core.pipes.to_camel_case_pipe.ToCamelCasePipe": [[26, 2, 1, "", "transform"]], "cpl_core.pipes.to_snake_case_pipe": [[26, 1, 1, "", "ToSnakeCasePipe"]], "cpl_core.pipes.to_snake_case_pipe.ToSnakeCasePipe": [[26, 2, 1, "", "transform"]], "cpl_core.pipes.version_pipe": [[26, 1, 1, "", "VersionPipe"]], "cpl_core.pipes.version_pipe.VersionPipe": [[26, 2, 1, "", "transform"]], "cpl_core.time": [[27, 0, 0, "-", "time_format_settings"], [27, 0, 0, "-", "time_format_settings_names_enum"]], "cpl_core.time.time_format_settings": [[27, 1, 1, "", "TimeFormatSettings"]], "cpl_core.time.time_format_settings.TimeFormatSettings": [[27, 3, 1, "", "date_format"], [27, 3, 1, "", "date_time_format"], [27, 3, 1, "", "date_time_log_format"], [27, 2, 1, "", "from_dict"], [27, 3, 1, "", "time_format"]], "cpl_core.time.time_format_settings_names_enum": [[27, 1, 1, "", "TimeFormatSettingsNamesEnum"]], "cpl_core.time.time_format_settings_names_enum.TimeFormatSettingsNamesEnum": [[27, 4, 1, "", "date_format"], [27, 4, 1, "", "date_time_format"], [27, 4, 1, "", "date_time_log_format"], [27, 4, 1, "", "time_format"]], "cpl_core.utils": [[28, 0, 0, "-", "credential_manager"], [28, 0, 0, "-", "pip"], [28, 0, 0, "-", "string"]], "cpl_core.utils.credential_manager": [[28, 1, 1, "", "CredentialManager"]], "cpl_core.utils.credential_manager.CredentialManager": [[28, 2, 1, "", "build_string"], [28, 2, 1, "", "decrypt"], [28, 2, 1, "", "encrypt"]], "cpl_core.utils.pip": [[28, 1, 1, "", "Pip"]], "cpl_core.utils.pip.Pip": [[28, 2, 1, "", "get_executable"], [28, 2, 1, "", "get_outdated"], [28, 2, 1, "", "get_package"], [28, 2, 1, "", "install"], [28, 2, 1, "", "reset_executable"], [28, 2, 1, "", "set_executable"], [28, 2, 1, "", "uninstall"]], "cpl_core.utils.string": [[28, 1, 1, "", "String"]], "cpl_core.utils.string.String": [[28, 2, 1, "", "convert_to_camel_case"], [28, 2, 1, "", "convert_to_snake_case"], [28, 2, 1, "", "first_to_lower"], [28, 2, 1, "", "first_to_upper"], [28, 2, 1, "", "random_string"]], "cpl_query": [[30, 0, 0, "-", "exceptions"]], "cpl_query.exceptions": [[30, 5, 1, "", "ArgumentNoneException"], [30, 1, 1, "", "ExceptionArgument"], [30, 5, 1, "", "IndexOutOfRangeException"], [30, 5, 1, "", "InvalidTypeException"], [30, 5, 1, "", "WrongTypeException"]], "cpl_query.exceptions.ExceptionArgument": [[30, 4, 1, "", "func"], [30, 4, 1, "", "index"], [30, 4, 1, "", "list"], [30, 4, 1, "", "type"], [30, 4, 1, "", "value"]], "cpl_query.extension": [[31, 0, 0, "-", "iterable"], [31, 0, 0, "-", "iterable_abc"], [31, 0, 0, "-", "list"], [31, 0, 0, "-", "ordered_iterable"], [31, 0, 0, "-", "ordered_iterable_abc"]], "cpl_query.extension.iterable": [[31, 1, 1, "", "Iterable"]], "cpl_query.extension.iterable.Iterable": [[31, 2, 1, "", "all"], [31, 2, 1, "", "any"], [31, 2, 1, "", "average"], [31, 2, 1, "", "contains"], [31, 2, 1, "", "count"], [31, 2, 1, "", "distinct"], [31, 2, 1, "", "element_at"], [31, 2, 1, "", "element_at_or_default"], [31, 2, 1, "", "first"], [31, 2, 1, "", "first_or_default"], [31, 2, 1, "", "for_each"], [31, 2, 1, "", "last"], [31, 2, 1, "", "last_or_default"], [31, 2, 1, "", "max"], [31, 2, 1, "", "min"], [31, 2, 1, "", "order_by"], [31, 2, 1, "", "order_by_descending"], [31, 2, 1, "", "reverse"], [31, 2, 1, "", "single"], [31, 2, 1, "", "single_or_default"], [31, 2, 1, "", "skip"], [31, 2, 1, "", "skip_last"], [31, 2, 1, "", "sum"], [31, 2, 1, "", "take"], [31, 2, 1, "", "take_last"], [31, 2, 1, "", "where"]], "cpl_query.extension.iterable_abc": [[31, 1, 1, "", "IterableABC"]], "cpl_query.extension.iterable_abc.IterableABC": [[31, 2, 1, "", "all"], [31, 2, 1, "", "any"], [31, 2, 1, "", "append"], [31, 2, 1, "", "average"], [31, 2, 1, "", "contains"], [31, 2, 1, "", "count"], [31, 2, 1, "", "distinct"], [31, 2, 1, "", "element_at"], [31, 2, 1, "", "element_at_or_default"], [31, 2, 1, "", "extend"], [31, 2, 1, "", "first"], [31, 2, 1, "", "first_or_default"], [31, 2, 1, "", "for_each"], [31, 2, 1, "", "last"], [31, 2, 1, "", "last_or_default"], [31, 2, 1, "", "max"], [31, 2, 1, "", "min"], [31, 2, 1, "", "order_by"], [31, 2, 1, "", "order_by_descending"], [31, 2, 1, "", "reverse"], [31, 2, 1, "", "single"], [31, 2, 1, "", "single_or_default"], [31, 2, 1, "", "skip"], [31, 2, 1, "", "skip_last"], [31, 2, 1, "", "sum"], [31, 2, 1, "", "take"], [31, 2, 1, "", "take_last"], [31, 2, 1, "", "to_list"], [31, 3, 1, "", "type"], [31, 2, 1, "", "where"]], "cpl_query.extension.list": [[31, 1, 1, "", "List"]], "cpl_query.extension.ordered_iterable": [[31, 1, 1, "", "OrderedIterable"]], "cpl_query.extension.ordered_iterable.OrderedIterable": [[31, 2, 1, "", "then_by"], [31, 2, 1, "", "then_by_descending"]], "cpl_query.extension.ordered_iterable_abc": [[31, 1, 1, "", "OrderedIterableABC"]], "cpl_query.extension.ordered_iterable_abc.OrderedIterableABC": [[31, 2, 1, "", "then_by"], [31, 2, 1, "", "then_by_descending"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:property", "4": "py:attribute", "5": "py:exception"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "property", "Python property"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "exception", "Python exception"]}, "titleterms": {"cpl": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 26, 33, 34, 35, 36], "add": 0, "content": [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 26, 36, 37], "descript": [0, 1, 2, 3, 4, 5, 7, 8, 10], "argument": [0, 2, 3, 4, 8, 10, 41], "flag": [0, 4, 5, 8, 10, 11], "build": 1, "gener": 2, "schemat": [2, 6], "help": 3, "instal": [4, 37], "new": 5, "project": [5, 36], "type": 5, "cli": [6, 14, 37], "overview": [6, 34], "command": 6, "refer": [6, 14, 15, 29], "tabl": [6, 36, 37], "basic": 6, "workflow": 6, "languag": 6, "syntax": 6, "rel": 6, "path": 6, "publish": 7, "remov": 8, "start": [9, 32, 36, 37], "uninstal": 10, "updat": 11, "version": 12, "contribut": 13, "found": 13, "bug": 13, "featur": [13, 33, 34], "request": 13, "submiss": 13, "guidelin": 13, "submit": 13, "an": 13, "issu": 13, "pull": 13, "review": 13, "address": 13, "feedback": 13, "code": 13, "rule": 13, "licens": 13, "api": 15, "cpl_core": [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 40], "applic": [16, 43], "application_abc": 16, "application_build": 16, "application_builder_abc": 16, "startup_abc": 16, "configur": 17, "configuration_abc": 17, "configuration_model_abc": 17, "configuration_variable_name_enum": 17, "console_argu": 17, "consol": [18, 37, 40, 41], "background_color_enum": 18, "console_cal": 18, "foreground_color_enum": 18, "spinner_thread": 18, "databas": [19, 20, 21], "submodul": [19, 26], "database_model": 19, "database_set": 19, "database_settings_name_enum": 19, "connect": 20, "database_connect": 20, "database_connection_abc": 20, "context": 21, "database_context": 21, "database_context_abc": 21, "dependency_inject": 22, "service_collect": 22, "service_collection_abc": 22, "service_descriptor": 22, "service_lifetime_enum": 22, "service_provid": 22, "service_provider_abc": 22, "environ": [23, 37], "application_environ": 23, "application_environment_abc": 23, "environment_name_enum": 23, "log": 24, "logger_abc": 24, "logger_servic": 24, "logging_level_enum": 24, "logging_set": 24, "logging_settings_name_enum": 24, "mail": [25, 46], "email": 25, "email_client_abc": 25, "email_client_servic": 25, "email_client_set": 25, "email_client_settings_name_enum": 25, "pipe": 26, "bool_pip": 26, "modul": 26, "first_char_to_lower_pip": 26, "first_to_upper_pip": 26, "ip_address_pip": 26, "pipe_abc": 26, "to_camel_case_pip": 26, "to_snake_case_pip": 26, "version_pip": 26, "core": 26, "sh": 26, "edraft": 26, "common": 26, "python": 26, "librari": [26, 37], "time": 27, "time_format_set": 27, "time_format_settings_names_enum": 27, "util": 28, "credential_manag": 28, "pip": 28, "string": 28, "queri": [29, 37], "cpl_queri": [30, 31], "except": 30, "extens": 31, "iterable_abc": 31, "iter": 31, "list": 31, "ordered_iterable_abc": 31, "ordered_iter": 31, "get": [32, 36], "introduct": [33, 34], "doc": [33, 34], "manual": 33, "explor": 34, "prerequisit": [36, 37], "creat": [36, 37, 42], "menu": 36, "what": [36, 37], "s": [36, 37], "next": [36, 37], "set": 37, "up": 37, "local": 37, "workspac": 37, "packag": 37, "initi": 37, "app": 37, "tutori": 38, "us": [39, 40, 45], "appset": 39, "json": 39, "com": [39, 40, 41, 42, 43, 44, 45, 46], "soon": [39, 40, 41, 42, 43, 44, 45, 46], "handl": 41, "startup": [42, 44], "class": 42, "extend": [43, 44], "builtin": 45, "logger": 45, "send": 46}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 56}}) \ No newline at end of file +Search.setIndex({"docnames": ["cli.add", "cli.build", "cli.generate", "cli.help", "cli.install", "cli.new", "cli.overview", "cli.publish", "cli.remove", "cli.run", "cli.start", "cli.uninstall", "cli.update", "cli.version", "contributing", "cpl_cli", "cpl_core", "cpl_core.application", "cpl_core.configuration", "cpl_core.console", "cpl_core.database", "cpl_core.database.connection", "cpl_core.database.context", "cpl_core.dependency_injection", "cpl_core.environment", "cpl_core.logging", "cpl_core.mailing", "cpl_core.pipes", "cpl_core.time", "cpl_core.utils", "cpl_discord", "cpl_discord.application", "cpl_discord.command", "cpl_discord.configuration", "cpl_discord.container", "cpl_discord.events", "cpl_discord.helper", "cpl_discord.service", "cpl_query", "cpl_query.base", "cpl_query.enumerable", "cpl_query.extension", "cpl_query.iterable", "cpl_translation", "getting_started", "index", "introduction", "modules", "quickstart", "setup", "tutorials", "tutorials.appsettings", "tutorials.console", "tutorials.console-arguments", "tutorials.create-startup", "tutorials.extend-application", "tutorials.extend-startup", "tutorials.logging", "tutorials.mail"], "filenames": ["cli.add.md", "cli.build.md", "cli.generate.md", "cli.help.md", "cli.install.md", "cli.new.md", "cli.overview.md", "cli.publish.md", "cli.remove.md", "cli.run.md", "cli.start.md", "cli.uninstall.md", "cli.update.md", "cli.version.md", "contributing.md", "cpl_cli.rst", "cpl_core.rst", "cpl_core.application.rst", "cpl_core.configuration.rst", "cpl_core.console.rst", "cpl_core.database.rst", "cpl_core.database.connection.rst", "cpl_core.database.context.rst", "cpl_core.dependency_injection.rst", "cpl_core.environment.rst", "cpl_core.logging.rst", "cpl_core.mailing.rst", "cpl_core.pipes.rst", "cpl_core.time.rst", "cpl_core.utils.rst", "cpl_discord.rst", "cpl_discord.application.rst", "cpl_discord.command.rst", "cpl_discord.configuration.rst", "cpl_discord.container.rst", "cpl_discord.events.rst", "cpl_discord.helper.rst", "cpl_discord.service.rst", "cpl_query.rst", "cpl_query.base.rst", "cpl_query.enumerable.rst", "cpl_query.extension.rst", "cpl_query.iterable.rst", "cpl_translation.rst", "getting_started.rst", "index.rst", "introduction.md", "modules.rst", "quickstart.md", "setup.md", "tutorials.rst", "tutorials.appsettings.md", "tutorials.console.md", "tutorials.console-arguments.md", "tutorials.create-startup.md", "tutorials.extend-application.md", "tutorials.extend-startup.md", "tutorials.logging.md", "tutorials.mail.md"], "titles": ["cpl add", "cpl build", "cpl generate", "cpl help", "cpl install", "cpl new", "CLI Overview and Command Reference", "cpl publish", "cpl remove", "cpl run", "cpl start", "cpl uninstall", "cpl update", "cpl version", "Contributing to CPL", "CLI reference", "API reference", "cpl_core.application", "cpl_core.configuration", "cpl_core.console", "cpl_core.database", "cpl_core.database.connection", "cpl_core.database.context", "cpl_core.dependency_injection", "cpl_core.environment", "cpl_core.logging", "cpl_core.mailing", "cpl_core.pipes", "cpl_core.time", "cpl_core.utils", "Discord reference", "cpl_discord.application", "cpl_discord.command", "cpl_discord.configuration", "cpl_discord.container", "cpl_discord.events", "cpl_discord.helper", "cpl_discord.service", "Query reference", "cpl_query.base", "cpl_query.enumerable", "cpl_query.extension", "cpl_query.iterable", "Translation reference", "Getting started", "Introduction to the CPL Docs", "Introduction to the CPL Docs", "cpl", "Getting started with CPL", "Setting up the local environment and workspace", "Tutorials", "Using appsettings.json", "Use cpl_core.console.Console", "Handle console arguments", "Create startup class", "Extend application", "Extend startup", "Use builtin logger", "Send mails"], "terms": {"remov": [0, 6, 7, 15, 40, 42, 47], "project": [0, 1, 4, 6, 7, 8, 9, 10, 11, 12, 14, 15, 44, 47, 49], "from": [0, 6, 7, 8, 9, 10, 11, 13, 14, 17, 18, 19, 20, 34, 39, 42, 45, 46, 48], "workspac": [0, 1, 5, 6, 8, 44, 47], "sourc": [0, 1, 7, 9, 10, 14, 29, 48, 49], "target": [0, 1], "A": [0, 5, 14, 34], "refer": [0, 8, 45, 46, 47], "given": [0, 1, 4, 6, 7, 11, 18, 19, 20, 23, 29, 39, 42], "If": [0, 5, 8, 14, 19, 49], "you": [0, 1, 6, 8, 14, 34, 45, 46, 48, 49], "call": [0, 8, 17, 18, 19, 34, 39], "command": [0, 1, 3, 4, 5, 7, 8, 11, 12, 14, 15, 29, 30, 45, 46, 47, 49], "can": [0, 1, 6, 7, 8, 14, 34, 45, 49], "us": [0, 1, 2, 5, 6, 7, 8, 14, 17, 19, 26, 29, 44, 45, 46, 47, 48, 49, 50], "name": [0, 1, 2, 5, 6, 7, 8, 18, 24, 25, 29, 32, 34, 49], "otherwis": [0, 8, 19], "path": [0, 1, 2, 5, 7, 8, 15, 18, 24, 25, 47, 49], "must": [0, 1, 6, 8, 14, 19], "specifi": [0, 4, 5, 6, 8, 9, 11, 12, 18, 19], "valu": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 18, 19, 20, 23, 24, 25, 26, 27, 28, 39, 40, 41, 42, 43], "type": [0, 1, 2, 3, 4, 7, 8, 9, 10, 11, 15, 17, 18, 23, 34, 36, 37, 39, 40, 41, 42, 47], "which": [0, 6, 9, 18, 19, 29, 49], "ha": [0, 19], "ad": [0, 14], "str": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 33, 34, 35, 37, 43, 48], "referenc": 0, "simul": [0, 4, 8, 11, 12], "whether": [0, 4, 5, 8, 11, 12, 18], "copi": [1, 39], "an": [1, 6, 7, 17, 18, 19, 20, 23, 24, 25, 26, 28, 39, 48, 49], "python": [1, 14, 29, 45, 46, 48, 49], "app": [1, 6, 17, 44, 45, 46, 47, 48], "output": [1, 6, 7, 18, 19, 45, 46, 48, 49], "directori": [1, 6, 7, 24, 45, 46, 48], "execut": [1, 6, 7, 18, 29], "within": [1, 6, 14], "b": [1, 6, 14], "The": [1, 2, 4, 5, 6, 7, 8, 11, 14, 23, 26, 29, 34, 37, 45, 46, 48, 49], "consol": [1, 3, 5, 6, 7, 16, 18, 25, 44, 45, 46, 47, 48, 50], "librari": [1, 5, 6, 7, 44, 45, 46, 47], "all": [1, 7, 13, 14, 18, 34, 39], "includ": [1, 14, 49], "file": [1, 2, 6, 7, 8, 10, 14, 18, 45, 49], "run": [1, 5, 10, 17, 18, 19, 22, 29, 39, 45, 46, 48, 49], "directli": [1, 14], "prepar": [1, 6, 7, 14, 17, 45], "publish": [1, 6, 15, 45, 47, 49], "them": 1, "argument": [1, 5, 6, 7, 9, 10, 12, 15, 18, 19, 29, 39, 44, 45, 46, 47, 50], "base": [2, 5, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 36, 37, 38, 40, 41, 42, 43, 45, 46, 47, 48], "g": [2, 5, 6], "first": [2, 5, 6, 14, 27, 29, 34, 39, 45, 46], "element": [2, 5, 19, 22, 34, 39, 40, 42], "src": [2, 5, 48], "For": [2, 5, 14], "exampl": [2, 5], "c": [2, 5, 45], "test": [2, 5, 14, 24, 45, 46, 48], "creat": [2, 5, 6, 7, 14, 17, 18, 19, 23, 25, 26, 29, 39, 44, 45, 46, 47, 50], "would": [2, 5, 14], "abc": [2, 17, 18, 21, 22, 23, 24, 25, 26, 27, 32, 35, 37, 39, 40, 42, 43], "abstract": [2, 17, 18, 21, 22, 23, 24, 25, 26, 27, 31, 35, 37, 39, 43], "class": [2, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 44, 45, 46, 47, 50], "enum": [2, 18, 19, 20, 23, 24, 25, 26, 28], "pipe": [2, 16, 23, 45, 46, 47], "servic": [2, 5, 17, 18, 23, 25, 26, 30, 31, 45, 46, 47, 48], "set": [2, 9, 17, 18, 19, 20, 22, 23, 24, 25, 26, 28, 29, 33, 40, 43, 44, 47, 48], "configmodel": 2, "thread": [2, 19, 30, 47], "valid": [2, 26, 48], "list": [3, 6, 13, 18, 19, 22, 23, 26, 27, 29, 34, 35, 36, 37, 38, 39, 40, 42, 43, 45, 47], "avail": [3, 6, 14], "short": [3, 6], "h": [3, 6], "show": [3, 19], "messag": [3, 19, 25, 35, 37], "thi": [3, 14, 17, 34, 45, 46, 48, 49], "packag": [4, 5, 6, 11, 13, 29, 44, 45, 46, 47, 48], "via": [4, 11, 14, 45, 46], "pip": [4, 11, 13, 16, 45, 46, 47, 48, 49], "i": [4, 6, 48], "without": [4, 6, 14, 39], "deped": 4, "your": [4, 6, 9, 10, 14, 45, 46, 49], "dev": [4, 9, 10, 11], "develop": [4, 6, 11, 14, 24, 45, 46, 48, 49], "mode": [4, 11], "virtual": [4, 11], "gener": [5, 6, 7, 15, 45, 47, 48, 49], "initi": [5, 44, 47], "add": [5, 6, 14, 15, 18, 23, 26, 42, 47, 48], "n": [5, 6, 48, 49], "see": [5, 14, 21, 34, 48, 49], "simpl": [5, 45, 46, 49], "applic": [5, 9, 10, 16, 19, 24, 25, 26, 30, 44, 45, 46, 47, 48, 49, 50], "async": [5, 17, 35, 37], "startup": [5, 17, 44, 45, 46, 47, 50], "provid": [5, 14, 17, 23, 34, 45, 46, 48, 49], "noth": 5, "venv": 5, "instal": [6, 13, 15, 29, 44, 47, 48], "cpl": [6, 15, 23, 44, 49], "To": [6, 9, 10, 14, 48, 49], "build": [6, 7, 9, 10, 15, 17, 29, 45, 47, 48, 49], "serv": 6, "new": [6, 14, 15, 19, 34, 47, 48, 49], "server": [6, 21, 26, 45, 46, 49], "go": [6, 14, 45], "parent": 6, "follow": [6, 14, 48, 49], "my": [6, 14, 49], "cd": [6, 49], "start": [6, 9, 15, 39, 45, 46, 47], "In": [6, 14, 48], "termin": [6, 19, 48, 49], "commandnameoralia": 6, "requiredarg": 6, "optionalsarg": 6, "most": [6, 34, 48, 49], "some": 6, "option": [6, 9, 14, 18, 19, 20, 23, 25, 26, 29, 34, 35, 37, 39, 40, 41, 42, 45, 46, 48], "have": [6, 14, 34, 48, 49], "alias": [6, 18], "ar": [6, 7, 14, 18, 34], "shown": [6, 18, 49], "statement": [6, 22], "each": [6, 18, 39], "prefix": [6, 18, 33], "absolut": 6, "current": [6, 24, 34], "work": [6, 14, 24, 45, 46], "either": 6, "root": 6, "take": [6, 18, 39], "artifact": 6, "addit": [6, 14], "ani": [6, 19, 27, 32, 37, 39, 43], "defin": [6, 18, 19, 40, 42, 49], "its": [6, 14], "own": 6, "suppli": 6, "same": 6, "format": [6, 25, 28, 39], "immedi": 6, "alia": 6, "descript": [6, 9, 10, 12, 15, 34, 47], "dist": [6, 7, 9, 10], "help": [6, 14, 15, 45, 46, 47], "With": 6, "depend": [6, 12, 45, 46, 48], "p": [6, 7], "setup": [6, 7, 46, 49], "py": [6, 7, 29, 45, 48], "r": [6, 8, 9], "s": [6, 10, 14, 34, 44, 47], "restart": [6, 10, 49], "chang": [6, 10, 14, 22, 48], "uninstal": [6, 15, 29, 47], "ui": [6, 11, 34], "updat": [6, 14, 15, 47], "u": [6, 12], "version": [6, 15, 34, 47], "v": [6, 13], "data": [7, 19, 34, 39], "cpl_core": [7, 16, 44, 47, 48, 49, 50], "json": [7, 18, 44, 45, 46, 47, 48, 49, 50], "delet": 8, "onc": 9, "paramet": [9, 42], "default": [9, 19, 34, 49], "after": [9, 10, 35, 37, 39], "cli": [13, 44, 45, 46, 47, 48], "we": [14, 48], "love": 14, "make": [14, 49], "even": 14, "better": 14, "than": [14, 39], "todai": 14, "As": 14, "contributor": 14, "here": [14, 49], "like": [14, 45, 48], "issus": 14, "find": 14, "our": 14, "gitea": 14, "repositori": 14, "fix": 14, "implement": [14, 23, 39, 40, 41], "pleas": 14, "consid": 14, "size": 14, "order": [14, 34, 39], "determin": 14, "right": 14, "step": 14, "proce": 14, "major": 14, "open": [14, 48, 49], "outlin": 14, "propos": 14, "so": [14, 49], "discuss": 14, "process": 14, "allow": 14, "coordin": [14, 19], "effort": 14, "prevent": 14, "duplic": 14, "craft": 14, "successfulli": 14, "accept": 14, "note": [14, 34], "topic": [14, 34], "document": 14, "significantli": 14, "re": 14, "write": [14, 19, 25, 45, 46], "count": [14, 39], "small": 14, "befor": [14, 19, 35, 37, 40], "search": [14, 18, 23], "tracker": 14, "mayb": 14, "problem": 14, "alreadi": [14, 48, 49], "exist": [14, 40], "might": 14, "inform": [14, 25, 49], "workaround": 14, "readili": 14, "want": [14, 48], "soon": [14, 44, 47, 50], "possibl": [14, 18], "need": [14, 34, 48, 49], "reproduc": 14, "confirm": 14, "requir": [14, 34], "minim": 14, "reproduct": 14, "scenario": 14, "give": 14, "wealth": 14, "import": [14, 48], "back": [14, 19], "forth": 14, "question": 14, "quickli": 14, "point": [14, 17, 19], "out": [14, 48, 49], "well": 14, "save": [14, 18, 22], "maintain": 14, "time": [14, 16, 25, 34, 47], "ultim": 14, "abl": 14, "more": [14, 39, 49], "often": 14, "themselv": 14, "while": 14, "understand": [14, 45, 46, 48, 49], "sometim": 14, "hard": 14, "extract": 14, "essenti": [14, 48], "bit": 14, "larger": 14, "codebas": 14, "realli": 14, "isol": 14, "unfortun": 14, "investig": 14, "don": [14, 48], "t": [14, 39, 40, 41, 42, 48], "hear": 14, "close": [14, 19], "doesn": 14, "enough": 14, "info": [14, 25, 45, 46], "pr": 14, "relat": 14, "Be": 14, "sure": 14, "describ": 14, "design": 14, "d": 14, "upfront": 14, "ensur": 14, "readi": [14, 49], "fork": 14, "sh": [14, 49], "edraft": [14, 49], "de": [14, 49], "repo": 14, "git": 14, "branch": 14, "checkout": 14, "master": 14, "patch": 14, "appropri": 14, "case": [14, 27, 29, 48], "commit": 14, "line": [14, 19, 48], "automat": 14, "rm": 14, "edit": 14, "push": 14, "origin": 14, "send": [14, 26, 44, 45, 46, 47, 50], "team": 14, "reserv": 14, "commun": 14, "member": [14, 30, 35, 37, 47], "who": 14, "haven": 14, "been": 14, "good": 14, "citizen": 14, "Such": 14, "behavior": 14, "appli": 14, "outsid": 14, "manag": [14, 34, 45, 46], "channel": [14, 34, 35, 37], "ask": 14, "fixup": 14, "head": 14, "That": 14, "thank": 14, "consist": 14, "throughout": 14, "keep": 14, "mind": 14, "one": [14, 39], "unit": 14, "public": 14, "api": [14, 45, 46, 47], "method": 14, "pep": 14, "8": 14, "style": 14, "guid": 14, "By": 14, "agre": 14, "under": [14, 34], "mit": 14, "overview": [15, 47, 49], "tabl": [15, 19, 29, 44, 45, 46, 47], "content": [15, 44, 47], "basic": [15, 47, 48, 49], "workflow": [15, 47], "languag": [15, 43, 47], "syntax": [15, 47], "rel": [15, 47], "schemat": [15, 47], "flag": [15, 40, 47], "application_abc": [16, 47], "application_build": [16, 47], "application_builder_abc": [16, 47], "startup_abc": [16, 47], "configur": [16, 17, 23, 30, 45, 46, 47], "configuration_abc": [16, 17, 23, 47], "configuration_model_abc": [16, 47], "configuration_variable_name_enum": [16, 47], "console_argu": [16, 47], "background_color_enum": [16, 47], "console_cal": [16, 47], "foreground_color_enum": [16, 47], "spinner_thread": [16, 47], "databas": [16, 23, 47], "connect": [16, 20, 22, 26, 37, 47], "database_connect": [16, 20, 47], "database_connection_abc": [16, 20, 47], "context": [16, 20, 23, 35, 37, 47, 49], "database_context": [16, 20, 47], "database_context_abc": [16, 20, 23, 47], "database_model": [16, 47], "database_set": [16, 21, 22, 47], "database_settings_name_enum": [16, 47], "dependency_inject": [16, 17, 47], "service_collect": [16, 37, 47], "service_collection_abc": [16, 17, 47], "service_descriptor": [16, 47], "service_lifetime_enum": [16, 47], "service_provid": [16, 47], "service_provider_abc": [16, 17, 47], "environ": [16, 17, 18, 25, 26, 44, 45, 46, 47], "application_environ": [16, 47], "application_environment_abc": [16, 17, 25, 26, 47], "environment_name_enum": [16, 47], "log": [16, 26, 45, 46, 47], "logger_abc": [16, 26, 47], "logger_servic": [16, 47], "logging_level_enum": [16, 47], "logging_set": [16, 47], "logging_settings_name_enum": [16, 47], "mail": [16, 44, 45, 46, 47, 50], "email": [16, 47], "email_client_abc": [16, 47], "email_client_servic": [16, 47], "email_client_set": [16, 47], "email_client_settings_name_enum": [16, 47], "bool_pip": [16, 47], "first_char_to_lower_pip": [16, 47], "first_to_upper_pip": [16, 47], "ip_address_pip": [16, 47], "pipe_abc": [16, 47], "to_camel_case_pip": [16, 47], "to_snake_case_pip": [16, 47], "version_pip": [16, 47], "time_format_set": [16, 25, 47], "time_format_settings_names_enum": [16, 47], "util": [16, 45, 46, 47], "credential_manag": [16, 47], "string": [16, 19, 21, 25, 26, 27, 45, 46, 47, 48], "applicationabc": [17, 31], "config": [17, 23, 31, 37], "configurationabc": [17, 18, 23, 31, 37], "serviceproviderabc": [17, 18, 23, 31], "contain": [17, 30, 36, 39, 47], "object": [17, 18, 19, 23, 26, 29, 34, 36, 39, 42, 45, 46], "load": [17, 43], "appset": [17, 44, 47, 48, 50], "instanc": [17, 23], "main": [17, 48], "custom": [17, 18, 24, 45, 46], "entri": [17, 19], "run_async": 17, "applicationbuild": 17, "applicationbuilderabc": 17, "build_async": 17, "use_extens": 17, "extens": [17, 38, 39, 42, 45, 46, 47], "union": [17, 18, 19, 23, 35, 36, 37, 39], "applicationextensionabc": 17, "startupextensionabc": 17, "use_startup": 17, "startupabc": 17, "arg": [17, 18, 19, 22, 27, 29, 32, 35, 37, 43], "configure_configur": 17, "env": [17, 25, 37], "applicationenvironmentabc": [17, 18, 24, 25, 26, 37], "configure_servic": 17, "servicecollectionabc": [17, 23, 37], "add_configur": 18, "key_typ": 18, "configurationmodelabc": [18, 20, 25, 26, 28, 33, 43], "add_console_argu": 18, "argumentabc": 18, "known": 18, "consoleargumentabc": 18, "add_environment_vari": 18, "read": [18, 19, 48], "variabl": [18, 29], "add_json_fil": 18, "bool": [18, 19, 20, 26, 27, 34, 39, 40], "none": [18, 19, 23, 25, 26, 29, 39, 40, 41, 42], "true": 18, "error": [18, 19, 25, 35, 37, 45, 46], "should": [18, 48, 49], "occur": 18, "wa": [18, 49], "found": [18, 39], "place": 18, "store": 18, "properti": [18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 33, 34, 37, 39, 42, 43], "additional_argu": 18, "argument_error_funct": 18, "callabl": [18, 19, 23, 39], "argument_abc": 18, "create_console_argu": 18, "arg_typ": 18, "argumenttypeenum": 18, "token": [18, 33], "kwarg": [18, 19, 32, 35, 37], "begin": 18, "value_token": 18, "were": 18, "is_value_token_opt": 18, "runnabl": 18, "when": [18, 19, 35, 37, 39], "for_each_argu": 18, "iter": [18, 38, 39, 40, 41, 47], "through": [18, 48], "function": [18, 19, 29, 39, 40, 42, 45, 48], "get_configur": 18, "search_typ": 18, "return": [18, 19, 23, 26, 34, 39, 48], "parse_console_argu": 18, "invalid": 18, "from_dict": [18, 20, 25, 26, 28, 33, 43], "dict": [18, 19, 20, 25, 26, 27, 28, 33, 43], "convert": [18, 25, 26, 27, 28, 29, 33, 36, 39, 40, 41, 42, 43, 45, 46], "attribut": [18, 20, 25, 26, 28, 33, 43], "configurationvariablenameenum": 18, "enumer": [18, 19, 20, 23, 24, 25, 26, 28, 38, 41, 42, 47], "static": [18, 26, 29, 36], "to_list": [18, 39], "backgroundcolorenum": 19, "blue": 19, "on_blu": 19, "cyan": 19, "on_cyan": 19, "on_default": 19, "green": 19, "on_green": 19, "grei": 19, "on_grei": 19, "magenta": 19, "on_magenta": 19, "red": 19, "on_r": 19, "white": 19, "on_whit": 19, "yellow": 19, "on_yellow": 19, "handl": [19, 29, 44, 45, 46, 47, 50], "input": [19, 45, 46, 48], "background_color": 19, "bytes_or_buff": 19, "encod": [19, 29], "expos": 19, "buffer": [19, 20], "decod": [19, 29], "handler": 19, "result": [19, 26, 29, 39], "__str__": 19, "repr": 19, "sy": 19, "getdefaultencod": 19, "strict": 19, "classmethod": [19, 29, 39], "banner": [19, 45, 46], "print": [19, 48], "clear": 19, "color_reset": 19, "reset": [19, 29, 39], "color": 19, "disabl": 19, "interact": 19, "enabl": [19, 48], "tb": 19, "traceback": 19, "foreground_color": 19, "read_lin": 19, "next": [19, 39, 44, 47], "reset_cursor_posit": 19, "cursor": [19, 21, 22], "posit": [19, 34], "select": [19, 22, 39, 48], "char": [19, 27, 29], "header_foreground_color": 19, "foregroundcolorenum": 19, "header_background_color": 19, "option_foreground_color": 19, "option_background_color": 19, "cursor_foreground_color": 19, "cursor_background_color": 19, "menu": [19, 44, 45, 46, 47], "charact": 19, "header": [19, 25, 26], "foreground": 19, "background": 19, "set_background_color": 19, "set_cursor_posit": 19, "x": [19, 39], "int": [19, 20, 26, 27, 29, 34, 39, 48], "y": [19, 48], "set_foreground_color": 19, "set_hold_back": 19, "spinner": [19, 45, 46], "text_foreground_color": 19, "spinner_foreground_color": 19, "text_background_color": 19, "spinner_background_color": 19, "end": [19, 25], "stop": 19, "text": [19, 34], "keyword": 19, "activ": [19, 34], "last": [19, 39], "write_at": [19, 45, 46], "write_lin": [19, 45, 46, 48], "write_line_at": [19, 45, 46], "consolecal": 19, "repres": [19, 20, 24, 26], "hold": 19, "spinnerthread": 19, "msg_len": 19, "length": [19, 29, 39, 48], "exit": [19, 48], "stop_spin": 19, "databaseset": [20, 21, 22, 23], "auth_plugin": 20, "charset": 20, "host": [20, 26], "password": [20, 48], "port": [20, 26], "use_unicod": 20, "user": [20, 35, 37, 48], "databasesettingsnameenum": 20, "authplugin": 20, "useunicod": 20, "databaseconnect": 21, "databaseconnectionabc": 21, "represent": [21, 22, 23, 25, 26, 28], "connection_str": 21, "http": [21, 49], "doc": 21, "sqlalchemi": 21, "org": 21, "en": 21, "14": 21, "core": [21, 45, 49], "engin": 21, "html": 21, "mysqlcursorbuff": [21, 22], "mysqlconnectionabstract": 21, "databasecontext": 22, "databasecontextabc": [22, 23], "save_chang": 22, "tupl": [22, 34], "sql": 22, "fetch": 22, "servicecollect": 23, "collect": 23, "add_db_context": 23, "db_context_typ": 23, "db_set": 23, "db_context": 23, "add_log": 23, "intern": 23, "logger": [23, 25, 26, 37, 44, 45, 46, 47, 50], "add_pip": 23, "transient": [23, 45, 46], "add_scop": 23, "service_typ": 23, "scope": [23, 45, 46], "lifetim": [23, 45, 46], "self": 23, "add_singleton": 23, "singleton": [23, 45, 46], "add_transi": 23, "build_service_provid": 23, "add_discord": 23, "discord": [23, 35, 37, 45, 47], "add_transl": 23, "translat": [23, 45, 47], "servicedescriptor": 23, "servicelifetimeenum": 23, "base_typ": 23, "descriptor": 23, "1": [23, 25, 48], "0": [23, 25, 34, 48], "2": [23, 25, 34, 48], "serviceprovid": 23, "build_servic": 23, "instance_typ": 23, "create_scop": 23, "scopeabc": 23, "get_servic": 23, "set_scop": 23, "applicationenviron": 24, "environmentnameenum": 24, "product": [24, 45, 46], "application_nam": 24, "date_time_now": 24, "datetim": [24, 34, 35, 37], "end_tim": 24, "environment_nam": 24, "host_nam": 24, "runtime_directori": 24, "set_runtime_directori": 24, "runtim": [24, 45, 46], "set_working_directori": 24, "working_directori": 24, "start_tim": 24, "stage": [24, 45, 46], "loggerabc": [25, 26, 37], "debug": [25, 45, 46], "ex": 25, "except": [25, 39], "thrown": 25, "fatal": [25, 45, 46], "program": 25, "trace": [25, 45, 46], "warn": [25, 45, 46], "loggingset": [25, 37], "time_format": [25, 28], "timeformatset": [25, 28], "tree": 25, "logfil": 25, "logginglevelenum": 25, "5": [25, 48], "4": 25, "off": 25, "6": 25, "3": 25, "filenam": 25, "level": [25, 45, 46], "loggingsettingsnameenum": 25, "console_level": 25, "consoleloglevel": 25, "file_level": 25, "fileloglevel": 25, "subject": 26, "bodi": 26, "transceiv": 26, "receiv": 26, "e": 26, "add_head": 26, "add_receiv": 26, "check_mail": 26, "address": 26, "check": [26, 39, 40], "get_cont": 26, "header_list": 26, "receiver_list": 26, "emailclientabc": 26, "emailcli": 26, "send_mail": 26, "mail_set": 26, "emailclientset": 26, "login": 26, "credenti": [26, 29, 45, 46], "user_nam": 26, "emailclientsettingsnameenum": 26, "usernam": 26, "boolpip": 27, "pipeabc": [27, 43], "transform": [27, 43], "firstchartolowerpip": 27, "lower": [27, 29, 48], "firsttoupperpip": 27, "upper": [27, 29, 48], "ipaddresspip": 27, "tocamelcasepip": 27, "camel": [27, 29], "camelcas": [27, 29], "tosnakecasepip": 27, "snake": [27, 29], "snake_cas": [27, 29], "versionpip": 27, "date_format": 28, "date_time_format": 28, "date_time_log_format": 28, "timeformatsettingsnamesenum": 28, "dateformat": 28, "datetimeformat": 28, "datetimelogformat": 28, "timeformat": 28, "credentialmanag": 29, "encrypt": [29, 45, 46], "decrypt": 29, "build_str": 29, "replac": 29, "base64": [29, 45, 46], "get_execut": 29, "get_outd": 29, "byte": 29, "get": [29, 45, 46, 47, 49], "outdat": 29, "get_packag": 29, "local": [29, 44, 47], "stdout": 29, "stderr": 29, "extra": [29, 49], "index": [29, 39, 42, 48, 49], "url": [29, 49], "subprocess": [29, 45, 46], "reset_execut": 29, "system": 29, "standard": [29, 45, 46], "set_execut": 29, "convert_to_camel_cas": 29, "convert_to_snake_cas": 29, "first_to_low": 29, "first_to_upp": 29, "random_str": 29, "random": [29, 48], "cpl_discord": [30, 47], "discord_bot_application_abc": [30, 47], "discord_command_abc": [30, 47], "discord_commands_meta": [30, 47], "discord_bot_set": [30, 37, 47], "category_channel": [30, 47], "guild": [30, 35, 37, 47], "role": [30, 35, 37, 47], "text_channel": [30, 47], "voice_channel": [30, 47], "event": [30, 37, 47], "on_bulk_message_delete_abc": [30, 47], "on_command_abc": [30, 47], "on_command_completion_abc": [30, 47], "on_command_error_abc": [30, 47], "on_connect_abc": [30, 47], "on_disconnect_abc": [30, 47], "on_error_abc": [30, 47], "on_group_join_abc": [30, 47], "on_group_remove_abc": [30, 47], "on_guild_available_abc": [30, 47], "on_guild_channel_create_abc": [30, 47], "on_guild_channel_delete_abc": [30, 47], "on_guild_channel_pins_update_abc": [30, 47], "on_guild_channel_update_abc": [30, 47], "on_guild_emojis_update_abc": [30, 47], "on_guild_integrations_update_abc": [30, 47], "on_guild_join_abc": [30, 47], "on_guild_remove_abc": [30, 47], "on_guild_role_create_abc": [30, 47], "on_guild_role_delete_abc": [30, 47], "on_guild_role_update_abc": [30, 47], "on_guild_unavailable_abc": [30, 47], "on_guild_update_abc": [30, 47], "on_invite_create_abc": [30, 47], "on_invite_delete_abc": [30, 47], "on_member_ban_abc": [30, 47], "on_member_join_abc": [30, 47], "on_member_remove_abc": [30, 47], "on_member_unban_abc": [30, 47], "on_member_update_abc": [30, 47], "on_message_abc": [30, 47], "on_message_delete_abc": [30, 47], "on_message_edit_abc": [30, 47], "on_private_channel_create_abc": [30, 47], "on_private_channel_delete_abc": [30, 47], "on_private_channel_pins_update_abc": [30, 47], "on_private_channel_update_abc": [30, 47], "on_raw_reaction_add_abc": [30, 47], "on_raw_reaction_clear_abc": [30, 47], "on_raw_reaction_clear_emoji_abc": [30, 47], "on_raw_reaction_remove_abc": [30, 47], "on_reaction_add_abc": [30, 47], "on_reaction_clear_abc": [30, 47], "on_reaction_clear_emoji_abc": [30, 47], "on_reaction_remove_abc": [30, 47], "on_ready_abc": [30, 47], "on_resume_abc": [30, 47], "on_typing_abc": [30, 47], "on_user_update_abc": [30, 47], "on_voice_state_update_abc": [30, 47], "on_webhooks_update_abc": [30, 47], "helper": [30, 47], "to_containers_convert": [30, 47], "command_error_handler_servic": [30, 47], "discord_bot_servic": [30, 47], "discord_bot_service_abc": [30, 47], "discord_collect": [30, 47], "discord_collection_abc": [30, 47], "discord_servic": [30, 47], "discord_service_abc": [30, 47], "discordbotapplicationabc": 31, "stop_async": [31, 37], "discordcommandabc": [32, 37], "cog": [32, 37], "discordcogmeta": 32, "namespac": 32, "abcmeta": 32, "cogmeta": 32, "discordbotset": [33, 37], "categorychannel": 34, "_t": [34, 36, 37, 39], "category_id": 34, "id": [34, 48], "nsfw": 34, "textchannel": 34, "categori": 34, "voicechannel": 34, "voic": 34, "_o": 34, "afk_channel": 34, "afk_timeout": 34, "approximate_member_count": 34, "approximate_presence_count": 34, "belong": 34, "sort": [34, 39, 45], "top": 34, "bottom": 34, "default_notif": 34, "emoji": [34, 35, 37], "explicit_content_filt": 34, "featur": [34, 49], "max_memb": 34, "max_pres": 34, "max_video_channel_us": 34, "sequenc": [34, 35, 36, 37, 39], "mfa_level": 34, "nsfw_level": 34, "owner_id": 34, "preferred_local": 34, "premium_progress_bar_en": 34, "premium_subscription_count": 34, "premium_ti": 34, "hierarchi": 34, "lowest": [34, 39], "sticker": 34, "permiss": 34, "view": 34, "unavail": 34, "vanity_url_cod": 34, "verification_level": 34, "widget_en": 34, "activitytyp": 34, "joined_at": 34, "nick": 34, "pend": 34, "premium_sinc": 34, "alwai": 34, "everyon": 34, "These": [34, 45], "timed_out_until": 34, "hoist": 34, "mention": 34, "tag": 34, "unicode_emoji": 34, "default_auto_archive_dur": 34, "last_message_id": 34, "slowmode_delai": 34, "archive_timestamp": 34, "archiv": 34, "archiver_id": 34, "auto_archive_dur": 34, "invit": [34, 35, 37], "lock": 34, "me": 34, "member_count": 34, "threadmemb": 34, "intent": 34, "properli": 34, "fill": 34, "howev": 34, "gatewai": 34, "fetch_memb": 34, "message_count": 34, "parent_id": 34, "insid": 34, "onbulkmessagedeleteabc": 35, "on_bulk_message_delet": [35, 37], "oncommandabc": 35, "on_command": [35, 37], "ctx": [35, 37], "oncommandcompletionabc": 35, "on_command_complet": [35, 37], "oncommanderrorabc": [35, 37], "on_command_error": [35, 37], "commanderror": [35, 37], "onconnectabc": 35, "on_connect": [35, 37], "ondisconnectabc": 35, "on_disconnect": [35, 37], "onerrorabc": 35, "on_error": [35, 37], "ongroupjoinabc": 35, "on_group_join": [35, 37], "chhanel": [35, 37], "groupchannel": [35, 37], "ongroupremoveabc": 35, "on_group_remov": [35, 37], "onguildavailableabc": 35, "on_guild_avail": [35, 37], "onguildchannelcreateabc": 35, "on_guild_channel_cr": [35, 37], "guildchannel": [35, 37], "onguildchanneldeleteabc": 35, "on_guild_channel_delet": [35, 37], "onguildchannelpinsupdateabc": 35, "on_guild_channel_pins_upd": [35, 37], "list_pin": [35, 37], "onguildchannelupdateabc": 35, "on_guild_channel_upd": [35, 37], "onguildemojisupdateabc": 35, "on_guild_emojis_upd": [35, 37], "onguildintegrationsupdateabc": 35, "on_guild_integrations_upd": [35, 37], "onguildjoinabc": 35, "on_guild_join": [35, 37], "onguildremoveabc": 35, "on_guild_remov": [35, 37], "onguildrolecreateabc": 35, "on_guild_role_cr": [35, 37], "onguildroledeleteabc": 35, "on_guild_role_delet": [35, 37], "onguildroleupdateabc": 35, "on_guild_role_upd": [35, 37], "onguildunavailableabc": 35, "on_guild_unavail": [35, 37], "onguildupdateabc": 35, "on_guild_upd": [35, 37], "oninvitecreateabc": 35, "on_invite_cr": [35, 37], "oninvitedeleteabc": 35, "on_invite_delet": [35, 37], "onmemberbanabc": 35, "on_member_ban": [35, 37], "onmemberjoinabc": 35, "on_member_join": [35, 37], "onmemberremoveabc": 35, "on_member_remov": [35, 37], "onmemberunbanabc": 35, "on_member_unban": [35, 37], "onmemberupdateabc": 35, "on_member_upd": [35, 37], "onmessageabc": 35, "on_messag": [35, 37], "onmessagedeleteabc": 35, "on_message_delet": [35, 37], "onmessageeditabc": 35, "on_message_edit": [35, 37], "onprivatechannelcreateabc": 35, "on_private_channel_cr": [35, 37], "privatechannel": [35, 37], "onprivatechanneldeleteabc": 35, "on_private_channel_delet": [35, 37], "onprivatechannelpinsupdateabc": 35, "on_private_channel_pins_upd": [35, 37], "onprivatechannelupdateabc": 35, "on_private_channel_upd": [35, 37], "onrawreactionaddabc": 35, "on_raw_reaction_add": [35, 37], "payload": [35, 37], "rawreactionactionev": [35, 37], "onrawreactionclearabc": 35, "on_raw_reaction_clear": [35, 37], "onrawreactionclearemojiabc": 35, "on_raw_reaction_clear_emoji": [35, 37], "onrawreactionremoveabc": 35, "on_raw_reaction_remov": [35, 37], "onreactionaddabc": 35, "on_reaction_add": [35, 37], "reaction": [35, 37], "onreactionclearabc": 35, "on_reaction_clear": [35, 37], "onreactionclearemojiabc": 35, "on_reaction_clear_emoji": [35, 37], "onreactionremoveabc": 35, "on_reaction_remov": [35, 37], "onreadyabc": 35, "on_readi": [35, 37], "onresumeabc": 35, "on_resum": [35, 37], "ontypingabc": 35, "on_typ": [35, 37], "onuserupdateabc": 35, "on_user_upd": [35, 37], "onvoicestateupdateabc": 35, "on_voice_state_upd": [35, 37], "voicest": [35, 37], "onwebhooksupdateabc": 35, "on_webhooks_upd": [35, 37], "tocontainersconvert": 36, "_l": 36, "commanderrorhandlerservic": 37, "discordbotservic": 37, "logging_st": 37, "discordserviceabc": 37, "discordbotserviceabc": 37, "client": 37, "start_async": 37, "bot": 37, "discordcollect": 37, "discordcollectionabc": 37, "add_command": 37, "add_ev": 37, "_t_event": 37, "get_command": 37, "get_events_by_bas": 37, "discordservic": 37, "init": 37, "cpl_queri": [38, 47], "default_lambda": [38, 47], "ordered_query": [38, 47], "ordered_queryable_abc": [38, 47], "queryable_abc": [38, 47], "sequence_abc": [38, 47], "sequence_valu": [38, 47], "enumerable_abc": [38, 41, 42, 47], "iterable_abc": [38, 40, 41, 47], "orderedquery": 39, "_valu": [39, 40], "_func": 39, "orderedqueryableabc": 39, "orderediterableabc": 39, "then_bi": 39, "orderedlist": 39, "ascend": 39, "func": 39, "ordered_iterable_abc": 39, "then_by_descend": 39, "descend": 39, "queryableabc": [39, 40, 42], "sequenceabc": 39, "everi": 39, "equal": 39, "averag": 39, "float": 39, "complex": [39, 45, 46], "distinct": 39, "redund": 39, "element_at": 39, "_index": 39, "element_at_or_default": 39, "first_or_default": 39, "for_each": 39, "group_bi": 39, "group": 39, "last_or_default": 39, "max": 39, "highest": 39, "median": 39, "min": 39, "order_bi": 39, "order_by_descend": 39, "revers": 39, "select_mani": 39, "flatten": 39, "singl": 39, "argumentnoneexcept": 39, "single_or_default": 39, "skip": 39, "skip_last": 39, "sum": 39, "take_last": 39, "where": 39, "empti": 39, "_object": [39, 42], "indexerror": 39, "rang": [39, 48], "sequencevalu": 39, "enumerableabc": [40, 41, 42], "set_remove_error_check": 40, "to_iter": [40, 41], "iterableabc": [40, 41, 42], "to_enumer": [41, 42], "append": 42, "extend": [42, 44, 47, 50], "_iterableabc__iter": 42, "__iter": 42, "translatepip": 43, "translationserviceabc": 43, "translationservic": 43, "lang": 43, "load_by_set": 43, "translationset": 43, "set_default_lang": 43, "set_lang": 43, "kei": [43, 45, 49], "default_languag": 43, "prerequisit": [44, 47], "what": [44, 47], "up": [44, 47], "queri": [44, 45, 46, 47], "tutori": [44, 47, 48, 49], "com": [44, 47, 50], "builtin": [44, 47, 50], "common": [45, 46], "platform": [45, 46], "meant": [45, 46], "effici": [45, 46], "desktop": [45, 46], "learn": [45, 46, 49], "enterpris": [45, 46], "expandl": [45, 46], "builder": [45, 46], "map": [45, 46], "inject": [45, 46, 48], "appnam": [45, 46], "hostnam": [45, 46], "wrapper": [45, 46], "differ": [45, 46], "variant": [45, 46], "to_lower_cas": [45, 46], "to_camel_cas": [45, 46], "code": [45, 48, 49], "connector": 45, "between": 45, "filter": 45, "linq": 45, "xd": 45, "dot": 45, "notat": 45, "page": 45, "great": 45, "detail": 45, "about": [45, 49], "everyth": 45, "do": [45, 48], "contribut": 45, "cpl_translat": 47, "translate_pip": 47, "translation_servic": 47, "translation_service_abc": 47, "translation_set": 47, "welcom": 48, "introduc": 48, "walk": 48, "also": [48, 49], "sampl": 48, "ouput": 48, "look": 48, "licens": 48, "done": 48, "readm": 48, "md": 48, "__init__": 48, "projectmain": 48, "vs": 48, "pycharm": 48, "folder": 48, "hello": [48, 49], "world": [48, 49], "emul": 48, "def": 48, "onli": 48, "__name__": 48, "__main__": 48, "generate_password": 48, "letter": 48, "join": 48, "choic": 48, "ascii_lowercas": 48, "elif": 48, "ascii_uppercas": 48, "ascii_lett": 48, "len": 48, "full": 48, "section": 48, "ve": 48, "continu": 48, "explor": 48, "window": 49, "prompt": 49, "declin": 49, "enter": 49, "press": 49, "lib": 49, "live": 49, "navig": 49, "launch": 49, "watch": 49, "chnage": 49, "those": 49, "success": 49, "similar": 49, "fore": 49, "pyhton": 49}, "objects": {"cpl_core.application": [[17, 0, 0, "-", "application_abc"], [17, 0, 0, "-", "application_builder"], [17, 0, 0, "-", "application_builder_abc"], [17, 0, 0, "-", "startup_abc"]], "cpl_core.application.application_abc": [[17, 1, 1, "", "ApplicationABC"]], "cpl_core.application.application_abc.ApplicationABC": [[17, 2, 1, "", "configure"], [17, 2, 1, "", "main"], [17, 2, 1, "", "run"], [17, 2, 1, "", "run_async"]], "cpl_core.application.application_builder": [[17, 1, 1, "", "ApplicationBuilder"]], "cpl_core.application.application_builder.ApplicationBuilder": [[17, 2, 1, "", "build"], [17, 2, 1, "", "build_async"], [17, 2, 1, "", "use_extension"], [17, 2, 1, "", "use_startup"]], "cpl_core.application.application_builder_abc": [[17, 1, 1, "", "ApplicationBuilderABC"]], "cpl_core.application.application_builder_abc.ApplicationBuilderABC": [[17, 2, 1, "", "build"], [17, 2, 1, "", "build_async"], [17, 2, 1, "", "use_startup"]], "cpl_core.application.startup_abc": [[17, 1, 1, "", "StartupABC"]], "cpl_core.application.startup_abc.StartupABC": [[17, 2, 1, "", "configure_configuration"], [17, 2, 1, "", "configure_services"]], "cpl_core.configuration": [[18, 0, 0, "-", "configuration"], [18, 0, 0, "-", "configuration_abc"], [18, 0, 0, "-", "configuration_model_abc"], [18, 0, 0, "-", "configuration_variable_name_enum"]], "cpl_core.configuration.configuration": [[18, 1, 1, "", "Configuration"]], "cpl_core.configuration.configuration.Configuration": [[18, 2, 1, "", "add_configuration"], [18, 2, 1, "", "add_console_argument"], [18, 2, 1, "", "add_environment_variables"], [18, 2, 1, "", "add_json_file"], [18, 3, 1, "", "additional_arguments"], [18, 3, 1, "", "argument_error_function"], [18, 3, 1, "", "arguments"], [18, 2, 1, "", "create_console_argument"], [18, 3, 1, "", "environment"], [18, 2, 1, "", "for_each_argument"], [18, 2, 1, "", "get_configuration"], [18, 2, 1, "", "parse_console_arguments"]], "cpl_core.configuration.configuration_abc": [[18, 1, 1, "", "ConfigurationABC"]], "cpl_core.configuration.configuration_abc.ConfigurationABC": [[18, 2, 1, "", "add_configuration"], [18, 2, 1, "", "add_console_argument"], [18, 2, 1, "", "add_environment_variables"], [18, 2, 1, "", "add_json_file"], [18, 3, 1, "", "additional_arguments"], [18, 3, 1, "", "argument_error_function"], [18, 3, 1, "", "arguments"], [18, 2, 1, "", "create_console_argument"], [18, 3, 1, "", "environment"], [18, 2, 1, "", "for_each_argument"], [18, 2, 1, "", "get_configuration"], [18, 2, 1, "", "parse_console_arguments"]], "cpl_core.configuration.configuration_model_abc": [[18, 1, 1, "", "ConfigurationModelABC"]], "cpl_core.configuration.configuration_model_abc.ConfigurationModelABC": [[18, 2, 1, "", "from_dict"]], "cpl_core.configuration.configuration_variable_name_enum": [[18, 1, 1, "", "ConfigurationVariableNameEnum"]], "cpl_core.configuration.configuration_variable_name_enum.ConfigurationVariableNameEnum": [[18, 4, 1, "", "customer"], [18, 4, 1, "", "environment"], [18, 4, 1, "", "name"], [18, 2, 1, "", "to_list"]], "cpl_core.console": [[19, 0, 0, "-", "background_color_enum"], [19, 0, 0, "-", "console"], [19, 0, 0, "-", "console_call"], [19, 0, 0, "-", "foreground_color_enum"], [19, 0, 0, "-", "spinner_thread"]], "cpl_core.console.background_color_enum": [[19, 1, 1, "", "BackgroundColorEnum"]], "cpl_core.console.background_color_enum.BackgroundColorEnum": [[19, 4, 1, "", "blue"], [19, 4, 1, "", "cyan"], [19, 4, 1, "", "default"], [19, 4, 1, "", "green"], [19, 4, 1, "", "grey"], [19, 4, 1, "", "magenta"], [19, 4, 1, "", "red"], [19, 4, 1, "", "white"], [19, 4, 1, "", "yellow"]], "cpl_core.console.console": [[19, 1, 1, "", "Console"]], "cpl_core.console.console.Console": [[19, 3, 1, "", "background_color"], [19, 2, 1, "", "banner"], [19, 2, 1, "", "clear"], [19, 2, 1, "", "close"], [19, 2, 1, "", "color_reset"], [19, 2, 1, "", "disable"], [19, 2, 1, "", "enable"], [19, 2, 1, "", "error"], [19, 3, 1, "", "foreground_color"], [19, 2, 1, "", "read"], [19, 2, 1, "", "read_line"], [19, 2, 1, "", "reset_cursor_position"], [19, 2, 1, "", "select"], [19, 2, 1, "", "set_background_color"], [19, 2, 1, "", "set_cursor_position"], [19, 2, 1, "", "set_foreground_color"], [19, 2, 1, "", "set_hold_back"], [19, 2, 1, "", "spinner"], [19, 2, 1, "", "table"], [19, 2, 1, "", "write"], [19, 2, 1, "", "write_at"], [19, 2, 1, "", "write_line"], [19, 2, 1, "", "write_line_at"]], "cpl_core.console.console_call": [[19, 1, 1, "", "ConsoleCall"]], "cpl_core.console.console_call.ConsoleCall": [[19, 3, 1, "", "args"], [19, 3, 1, "", "function"]], "cpl_core.console.foreground_color_enum": [[19, 1, 1, "", "ForegroundColorEnum"]], "cpl_core.console.foreground_color_enum.ForegroundColorEnum": [[19, 4, 1, "", "blue"], [19, 4, 1, "", "cyan"], [19, 4, 1, "", "default"], [19, 4, 1, "", "green"], [19, 4, 1, "", "grey"], [19, 4, 1, "", "magenta"], [19, 4, 1, "", "red"], [19, 4, 1, "", "white"], [19, 4, 1, "", "yellow"]], "cpl_core.console.spinner_thread": [[19, 1, 1, "", "SpinnerThread"]], "cpl_core.console.spinner_thread.SpinnerThread": [[19, 2, 1, "", "exit"], [19, 2, 1, "", "run"], [19, 2, 1, "", "stop_spinning"]], "cpl_core.database.connection": [[21, 0, 0, "-", "database_connection"], [21, 0, 0, "-", "database_connection_abc"]], "cpl_core.database.connection.database_connection": [[21, 1, 1, "", "DatabaseConnection"]], "cpl_core.database.connection.database_connection.DatabaseConnection": [[21, 2, 1, "", "connect"], [21, 3, 1, "", "cursor"], [21, 3, 1, "", "server"]], "cpl_core.database.connection.database_connection_abc": [[21, 1, 1, "", "DatabaseConnectionABC"]], "cpl_core.database.connection.database_connection_abc.DatabaseConnectionABC": [[21, 2, 1, "", "connect"], [21, 3, 1, "", "cursor"], [21, 3, 1, "", "server"]], "cpl_core.database.context": [[22, 0, 0, "-", "database_context"], [22, 0, 0, "-", "database_context_abc"]], "cpl_core.database.context.database_context": [[22, 1, 1, "", "DatabaseContext"]], "cpl_core.database.context.database_context.DatabaseContext": [[22, 2, 1, "", "connect"], [22, 3, 1, "", "cursor"], [22, 2, 1, "", "save_changes"], [22, 2, 1, "", "select"]], "cpl_core.database.context.database_context_abc": [[22, 1, 1, "", "DatabaseContextABC"]], "cpl_core.database.context.database_context_abc.DatabaseContextABC": [[22, 2, 1, "", "connect"], [22, 3, 1, "", "cursor"], [22, 2, 1, "", "save_changes"], [22, 2, 1, "", "select"]], "cpl_core.database": [[20, 0, 0, "-", "database_settings"], [20, 0, 0, "-", "database_settings_name_enum"]], "cpl_core.database.database_settings": [[20, 1, 1, "", "DatabaseSettings"]], "cpl_core.database.database_settings.DatabaseSettings": [[20, 3, 1, "", "auth_plugin"], [20, 3, 1, "", "buffered"], [20, 3, 1, "", "charset"], [20, 3, 1, "", "database"], [20, 2, 1, "", "from_dict"], [20, 3, 1, "", "host"], [20, 3, 1, "", "password"], [20, 3, 1, "", "port"], [20, 3, 1, "", "use_unicode"], [20, 3, 1, "", "user"]], "cpl_core.database.database_settings_name_enum": [[20, 1, 1, "", "DatabaseSettingsNameEnum"]], "cpl_core.database.database_settings_name_enum.DatabaseSettingsNameEnum": [[20, 4, 1, "", "auth_plugin"], [20, 4, 1, "", "buffered"], [20, 4, 1, "", "charset"], [20, 4, 1, "", "database"], [20, 4, 1, "", "host"], [20, 4, 1, "", "password"], [20, 4, 1, "", "port"], [20, 4, 1, "", "use_unicode"], [20, 4, 1, "", "user"]], "cpl_core.dependency_injection": [[23, 0, 0, "-", "service_collection"], [23, 0, 0, "-", "service_collection_abc"], [23, 0, 0, "-", "service_descriptor"], [23, 0, 0, "-", "service_lifetime_enum"], [23, 0, 0, "-", "service_provider"], [23, 0, 0, "-", "service_provider_abc"]], "cpl_core.dependency_injection.service_collection": [[23, 1, 1, "", "ServiceCollection"]], "cpl_core.dependency_injection.service_collection.ServiceCollection": [[23, 2, 1, "", "add_db_context"], [23, 2, 1, "", "add_logging"], [23, 2, 1, "", "add_pipes"], [23, 2, 1, "", "add_scoped"], [23, 2, 1, "", "add_singleton"], [23, 2, 1, "", "add_transient"], [23, 2, 1, "", "build_service_provider"]], "cpl_core.dependency_injection.service_collection_abc": [[23, 1, 1, "", "ServiceCollectionABC"]], "cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC": [[23, 2, 1, "", "add_db_context"], [23, 2, 1, "", "add_discord"], [23, 2, 1, "", "add_logging"], [23, 2, 1, "", "add_pipes"], [23, 2, 1, "", "add_scoped"], [23, 2, 1, "", "add_singleton"], [23, 2, 1, "", "add_transient"], [23, 2, 1, "", "add_translation"], [23, 2, 1, "", "build_service_provider"]], "cpl_core.dependency_injection.service_descriptor": [[23, 1, 1, "", "ServiceDescriptor"]], "cpl_core.dependency_injection.service_descriptor.ServiceDescriptor": [[23, 3, 1, "", "base_type"], [23, 3, 1, "", "implementation"], [23, 3, 1, "", "lifetime"], [23, 3, 1, "", "service_type"]], "cpl_core.dependency_injection.service_lifetime_enum": [[23, 1, 1, "", "ServiceLifetimeEnum"]], "cpl_core.dependency_injection.service_lifetime_enum.ServiceLifetimeEnum": [[23, 4, 1, "", "scoped"], [23, 4, 1, "", "singleton"], [23, 4, 1, "", "transient"]], "cpl_core.dependency_injection.service_provider": [[23, 1, 1, "", "ServiceProvider"]], "cpl_core.dependency_injection.service_provider.ServiceProvider": [[23, 2, 1, "", "build_service"], [23, 2, 1, "", "create_scope"], [23, 2, 1, "", "get_service"], [23, 2, 1, "", "set_scope"]], "cpl_core.dependency_injection.service_provider_abc": [[23, 1, 1, "", "ServiceProviderABC"]], "cpl_core.dependency_injection.service_provider_abc.ServiceProviderABC": [[23, 2, 1, "", "build_service"], [23, 2, 1, "", "create_scope"], [23, 2, 1, "", "get_service"], [23, 2, 1, "", "set_scope"]], "cpl_core.environment": [[24, 0, 0, "-", "application_environment"], [24, 0, 0, "-", "application_environment_abc"], [24, 0, 0, "-", "environment_name_enum"]], "cpl_core.environment.application_environment": [[24, 1, 1, "", "ApplicationEnvironment"]], "cpl_core.environment.application_environment.ApplicationEnvironment": [[24, 3, 1, "", "application_name"], [24, 3, 1, "", "customer"], [24, 3, 1, "", "date_time_now"], [24, 3, 1, "", "end_time"], [24, 3, 1, "", "environment_name"], [24, 3, 1, "", "host_name"], [24, 3, 1, "", "runtime_directory"], [24, 2, 1, "", "set_runtime_directory"], [24, 2, 1, "", "set_working_directory"], [24, 3, 1, "", "start_time"], [24, 3, 1, "", "working_directory"]], "cpl_core.environment.application_environment_abc": [[24, 1, 1, "", "ApplicationEnvironmentABC"]], "cpl_core.environment.application_environment_abc.ApplicationEnvironmentABC": [[24, 3, 1, "", "application_name"], [24, 3, 1, "", "customer"], [24, 3, 1, "", "date_time_now"], [24, 3, 1, "", "end_time"], [24, 3, 1, "", "environment_name"], [24, 3, 1, "", "host_name"], [24, 3, 1, "", "runtime_directory"], [24, 2, 1, "", "set_runtime_directory"], [24, 2, 1, "", "set_working_directory"], [24, 3, 1, "", "start_time"], [24, 3, 1, "", "working_directory"]], "cpl_core.environment.environment_name_enum": [[24, 1, 1, "", "EnvironmentNameEnum"]], "cpl_core.environment.environment_name_enum.EnvironmentNameEnum": [[24, 4, 1, "", "development"], [24, 4, 1, "", "production"], [24, 4, 1, "", "staging"], [24, 4, 1, "", "testing"]], "cpl_core.logging": [[25, 0, 0, "-", "logger_abc"], [25, 0, 0, "-", "logger_service"], [25, 0, 0, "-", "logging_level_enum"], [25, 0, 0, "-", "logging_settings"], [25, 0, 0, "-", "logging_settings_name_enum"]], "cpl_core.logging.logger_abc": [[25, 1, 1, "", "LoggerABC"]], "cpl_core.logging.logger_abc.LoggerABC": [[25, 2, 1, "", "debug"], [25, 2, 1, "", "error"], [25, 2, 1, "", "fatal"], [25, 2, 1, "", "header"], [25, 2, 1, "", "info"], [25, 2, 1, "", "trace"], [25, 2, 1, "", "warn"]], "cpl_core.logging.logger_service": [[25, 1, 1, "", "Logger"]], "cpl_core.logging.logger_service.Logger": [[25, 2, 1, "", "create"], [25, 2, 1, "", "debug"], [25, 2, 1, "", "error"], [25, 2, 1, "", "fatal"], [25, 2, 1, "", "header"], [25, 2, 1, "", "info"], [25, 2, 1, "", "trace"], [25, 2, 1, "", "warn"]], "cpl_core.logging.logging_level_enum": [[25, 1, 1, "", "LoggingLevelEnum"]], "cpl_core.logging.logging_level_enum.LoggingLevelEnum": [[25, 4, 1, "", "DEBUG"], [25, 4, 1, "", "ERROR"], [25, 4, 1, "", "FATAL"], [25, 4, 1, "", "INFO"], [25, 4, 1, "", "OFF"], [25, 4, 1, "", "TRACE"], [25, 4, 1, "", "WARN"]], "cpl_core.logging.logging_settings": [[25, 1, 1, "", "LoggingSettings"]], "cpl_core.logging.logging_settings.LoggingSettings": [[25, 3, 1, "", "console"], [25, 3, 1, "", "filename"], [25, 2, 1, "", "from_dict"], [25, 3, 1, "", "level"], [25, 3, 1, "", "path"]], "cpl_core.logging.logging_settings_name_enum": [[25, 1, 1, "", "LoggingSettingsNameEnum"]], "cpl_core.logging.logging_settings_name_enum.LoggingSettingsNameEnum": [[25, 4, 1, "", "console_level"], [25, 4, 1, "", "file_level"], [25, 4, 1, "", "filename"], [25, 4, 1, "", "path"]], "cpl_core.mailing": [[26, 0, 0, "-", "email"], [26, 0, 0, "-", "email_client_abc"], [26, 0, 0, "-", "email_client_service"], [26, 0, 0, "-", "email_client_settings"], [26, 0, 0, "-", "email_client_settings_name_enum"]], "cpl_core.mailing.email": [[26, 1, 1, "", "EMail"]], "cpl_core.mailing.email.EMail": [[26, 2, 1, "", "add_header"], [26, 2, 1, "", "add_receiver"], [26, 3, 1, "", "body"], [26, 2, 1, "", "check_mail"], [26, 2, 1, "", "get_content"], [26, 3, 1, "", "header"], [26, 3, 1, "", "header_list"], [26, 3, 1, "", "receiver"], [26, 3, 1, "", "receiver_list"], [26, 3, 1, "", "subject"], [26, 3, 1, "", "transceiver"]], "cpl_core.mailing.email_client_abc": [[26, 1, 1, "", "EMailClientABC"]], "cpl_core.mailing.email_client_abc.EMailClientABC": [[26, 2, 1, "", "connect"], [26, 2, 1, "", "send_mail"]], "cpl_core.mailing.email_client_service": [[26, 1, 1, "", "EMailClient"]], "cpl_core.mailing.email_client_service.EMailClient": [[26, 2, 1, "", "connect"], [26, 2, 1, "", "create"], [26, 2, 1, "", "login"], [26, 2, 1, "", "send_mail"]], "cpl_core.mailing.email_client_settings": [[26, 1, 1, "", "EMailClientSettings"]], "cpl_core.mailing.email_client_settings.EMailClientSettings": [[26, 3, 1, "", "credentials"], [26, 2, 1, "", "from_dict"], [26, 3, 1, "", "host"], [26, 3, 1, "", "port"], [26, 3, 1, "", "user_name"]], "cpl_core.mailing.email_client_settings_name_enum": [[26, 1, 1, "", "EMailClientSettingsNameEnum"]], "cpl_core.mailing.email_client_settings_name_enum.EMailClientSettingsNameEnum": [[26, 4, 1, "", "credentials"], [26, 4, 1, "", "host"], [26, 4, 1, "", "port"], [26, 4, 1, "", "user_name"]], "cpl_core.pipes": [[27, 0, 0, "-", "bool_pipe"], [27, 0, 0, "-", "first_char_to_lower_pipe"], [27, 0, 0, "-", "first_to_upper_pipe"], [27, 0, 0, "-", "ip_address_pipe"], [27, 0, 0, "-", "pipe_abc"], [27, 0, 0, "-", "to_camel_case_pipe"], [27, 0, 0, "-", "to_snake_case_pipe"], [27, 0, 0, "-", "version_pipe"]], "cpl_core.pipes.bool_pipe": [[27, 1, 1, "", "BoolPipe"]], "cpl_core.pipes.bool_pipe.BoolPipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.first_char_to_lower_pipe": [[27, 1, 1, "", "FirstCharToLowerPipe"]], "cpl_core.pipes.first_char_to_lower_pipe.FirstCharToLowerPipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.first_to_upper_pipe": [[27, 1, 1, "", "FirstToUpperPipe"]], "cpl_core.pipes.first_to_upper_pipe.FirstToUpperPipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.ip_address_pipe": [[27, 1, 1, "", "IPAddressPipe"]], "cpl_core.pipes.ip_address_pipe.IPAddressPipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.pipe_abc": [[27, 1, 1, "", "PipeABC"]], "cpl_core.pipes.pipe_abc.PipeABC": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.to_camel_case_pipe": [[27, 1, 1, "", "ToCamelCasePipe"]], "cpl_core.pipes.to_camel_case_pipe.ToCamelCasePipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.to_snake_case_pipe": [[27, 1, 1, "", "ToSnakeCasePipe"]], "cpl_core.pipes.to_snake_case_pipe.ToSnakeCasePipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.version_pipe": [[27, 1, 1, "", "VersionPipe"]], "cpl_core.pipes.version_pipe.VersionPipe": [[27, 2, 1, "", "transform"]], "cpl_core.time": [[28, 0, 0, "-", "time_format_settings"], [28, 0, 0, "-", "time_format_settings_names_enum"]], "cpl_core.time.time_format_settings": [[28, 1, 1, "", "TimeFormatSettings"]], "cpl_core.time.time_format_settings.TimeFormatSettings": [[28, 3, 1, "", "date_format"], [28, 3, 1, "", "date_time_format"], [28, 3, 1, "", "date_time_log_format"], [28, 2, 1, "", "from_dict"], [28, 3, 1, "", "time_format"]], "cpl_core.time.time_format_settings_names_enum": [[28, 1, 1, "", "TimeFormatSettingsNamesEnum"]], "cpl_core.time.time_format_settings_names_enum.TimeFormatSettingsNamesEnum": [[28, 4, 1, "", "date_format"], [28, 4, 1, "", "date_time_format"], [28, 4, 1, "", "date_time_log_format"], [28, 4, 1, "", "time_format"]], "cpl_core.utils": [[29, 0, 0, "-", "credential_manager"], [29, 0, 0, "-", "pip"], [29, 0, 0, "-", "string"]], "cpl_core.utils.credential_manager": [[29, 1, 1, "", "CredentialManager"]], "cpl_core.utils.credential_manager.CredentialManager": [[29, 2, 1, "", "build_string"], [29, 2, 1, "", "decrypt"], [29, 2, 1, "", "encrypt"]], "cpl_core.utils.pip": [[29, 1, 1, "", "Pip"]], "cpl_core.utils.pip.Pip": [[29, 2, 1, "", "get_executable"], [29, 2, 1, "", "get_outdated"], [29, 2, 1, "", "get_package"], [29, 2, 1, "", "install"], [29, 2, 1, "", "reset_executable"], [29, 2, 1, "", "set_executable"], [29, 2, 1, "", "uninstall"]], "cpl_core.utils.string": [[29, 1, 1, "", "String"]], "cpl_core.utils.string.String": [[29, 2, 1, "", "convert_to_camel_case"], [29, 2, 1, "", "convert_to_snake_case"], [29, 2, 1, "", "first_to_lower"], [29, 2, 1, "", "first_to_upper"], [29, 2, 1, "", "random_string"]], "cpl_discord.application": [[31, 0, 0, "-", "discord_bot_application_abc"]], "cpl_discord.application.discord_bot_application_abc": [[31, 1, 1, "", "DiscordBotApplicationABC"]], "cpl_discord.application.discord_bot_application_abc.DiscordBotApplicationABC": [[31, 2, 1, "", "stop_async"]], "cpl_discord.command": [[32, 0, 0, "-", "discord_command_abc"], [32, 0, 0, "-", "discord_commands_meta"]], "cpl_discord.command.discord_command_abc": [[32, 1, 1, "", "DiscordCommandABC"]], "cpl_discord.command.discord_commands_meta": [[32, 1, 1, "", "DiscordCogMeta"]], "cpl_discord.configuration": [[33, 0, 0, "-", "discord_bot_settings"]], "cpl_discord.configuration.discord_bot_settings": [[33, 1, 1, "", "DiscordBotSettings"]], "cpl_discord.configuration.discord_bot_settings.DiscordBotSettings": [[33, 2, 1, "", "from_dict"], [33, 3, 1, "", "prefix"], [33, 3, 1, "", "token"]], "cpl_discord.container": [[34, 0, 0, "-", "category_channel"], [34, 0, 0, "-", "container"], [34, 0, 0, "-", "guild"], [34, 0, 0, "-", "member"], [34, 0, 0, "-", "role"], [34, 0, 0, "-", "text_channel"], [34, 0, 0, "-", "thread"], [34, 0, 0, "-", "voice_channel"]], "cpl_discord.container.category_channel": [[34, 1, 1, "", "CategoryChannel"]], "cpl_discord.container.category_channel.CategoryChannel": [[34, 4, 1, "", "category_id"], [34, 4, 1, "", "guild"], [34, 4, 1, "", "id"], [34, 4, 1, "", "name"], [34, 4, 1, "", "nsfw"], [34, 4, 1, "", "position"], [34, 3, 1, "", "text_channels"], [34, 3, 1, "", "voice_channels"]], "cpl_discord.container.container": [[34, 1, 1, "", "Container"]], "cpl_discord.container.guild": [[34, 1, 1, "", "Guild"]], "cpl_discord.container.guild.Guild": [[34, 4, 1, "", "afk_channel"], [34, 4, 1, "", "afk_timeout"], [34, 4, 1, "", "approximate_member_count"], [34, 4, 1, "", "approximate_presence_count"], [34, 3, 1, "", "categories"], [34, 4, 1, "", "default_notifications"], [34, 4, 1, "", "description"], [34, 4, 1, "", "emojis"], [34, 4, 1, "", "explicit_content_filter"], [34, 4, 1, "", "features"], [34, 4, 1, "", "id"], [34, 4, 1, "", "max_members"], [34, 4, 1, "", "max_presences"], [34, 4, 1, "", "max_video_channel_users"], [34, 3, 1, "", "members"], [34, 4, 1, "", "mfa_level"], [34, 4, 1, "", "name"], [34, 4, 1, "", "nsfw_level"], [34, 4, 1, "", "owner_id"], [34, 4, 1, "", "preferred_locale"], [34, 4, 1, "", "premium_progress_bar_enabled"], [34, 4, 1, "", "premium_subscription_count"], [34, 4, 1, "", "premium_tier"], [34, 3, 1, "", "roles"], [34, 4, 1, "", "stickers"], [34, 3, 1, "", "text_channels"], [34, 3, 1, "", "threads"], [34, 4, 1, "", "unavailable"], [34, 4, 1, "", "vanity_url_code"], [34, 4, 1, "", "verification_level"], [34, 3, 1, "", "voice_channels"], [34, 4, 1, "", "widget_enabled"]], "cpl_discord.container.member": [[34, 1, 1, "", "Member"]], "cpl_discord.container.member.Member": [[34, 4, 1, "", "activities"], [34, 4, 1, "", "guild"], [34, 4, 1, "", "joined_at"], [34, 4, 1, "", "nick"], [34, 4, 1, "", "pending"], [34, 4, 1, "", "premium_since"], [34, 3, 1, "", "roles"], [34, 4, 1, "", "timed_out_until"]], "cpl_discord.container.role": [[34, 1, 1, "", "Role"]], "cpl_discord.container.role.Role": [[34, 4, 1, "", "guild"], [34, 4, 1, "", "hoist"], [34, 4, 1, "", "id"], [34, 4, 1, "", "managed"], [34, 3, 1, "", "members"], [34, 4, 1, "", "mentionable"], [34, 4, 1, "", "name"], [34, 4, 1, "", "position"], [34, 4, 1, "", "tags"], [34, 4, 1, "", "unicode_emoji"]], "cpl_discord.container.text_channel": [[34, 1, 1, "", "TextChannel"]], "cpl_discord.container.text_channel.TextChannel": [[34, 4, 1, "", "category_id"], [34, 4, 1, "", "default_auto_archive_duration"], [34, 4, 1, "", "guild"], [34, 4, 1, "", "id"], [34, 4, 1, "", "last_message_id"], [34, 3, 1, "", "members"], [34, 4, 1, "", "name"], [34, 4, 1, "", "nsfw"], [34, 4, 1, "", "position"], [34, 4, 1, "", "slowmode_delay"], [34, 3, 1, "", "threads"], [34, 4, 1, "", "topic"]], "cpl_discord.container.thread": [[34, 1, 1, "", "Thread"]], "cpl_discord.container.thread.Thread": [[34, 4, 1, "", "archive_timestamp"], [34, 4, 1, "", "archived"], [34, 4, 1, "", "archiver_id"], [34, 4, 1, "", "auto_archive_duration"], [34, 4, 1, "", "guild"], [34, 4, 1, "", "id"], [34, 4, 1, "", "invitable"], [34, 4, 1, "", "last_message_id"], [34, 4, 1, "", "locked"], [34, 4, 1, "", "me"], [34, 4, 1, "", "member_count"], [34, 3, 1, "", "members"], [34, 4, 1, "", "message_count"], [34, 4, 1, "", "name"], [34, 4, 1, "", "owner_id"], [34, 4, 1, "", "parent_id"], [34, 4, 1, "", "slowmode_delay"]], "cpl_discord.container.voice_channel": [[34, 1, 1, "", "VoiceChannel"]], "cpl_discord.container.voice_channel.VoiceChannel": [[34, 3, 1, "", "members"]], "cpl_discord.events": [[35, 0, 0, "-", "on_bulk_message_delete_abc"], [35, 0, 0, "-", "on_command_abc"], [35, 0, 0, "-", "on_command_completion_abc"], [35, 0, 0, "-", "on_command_error_abc"], [35, 0, 0, "-", "on_connect_abc"], [35, 0, 0, "-", "on_disconnect_abc"], [35, 0, 0, "-", "on_error_abc"], [35, 0, 0, "-", "on_group_join_abc"], [35, 0, 0, "-", "on_group_remove_abc"], [35, 0, 0, "-", "on_guild_available_abc"], [35, 0, 0, "-", "on_guild_channel_create_abc"], [35, 0, 0, "-", "on_guild_channel_delete_abc"], [35, 0, 0, "-", "on_guild_channel_pins_update_abc"], [35, 0, 0, "-", "on_guild_channel_update_abc"], [35, 0, 0, "-", "on_guild_emojis_update_abc"], [35, 0, 0, "-", "on_guild_integrations_update_abc"], [35, 0, 0, "-", "on_guild_join_abc"], [35, 0, 0, "-", "on_guild_remove_abc"], [35, 0, 0, "-", "on_guild_role_create_abc"], [35, 0, 0, "-", "on_guild_role_delete_abc"], [35, 0, 0, "-", "on_guild_role_update_abc"], [35, 0, 0, "-", "on_guild_unavailable_abc"], [35, 0, 0, "-", "on_guild_update_abc"], [35, 0, 0, "-", "on_invite_create_abc"], [35, 0, 0, "-", "on_invite_delete_abc"], [35, 0, 0, "-", "on_member_ban_abc"], [35, 0, 0, "-", "on_member_join_abc"], [35, 0, 0, "-", "on_member_remove_abc"], [35, 0, 0, "-", "on_member_unban_abc"], [35, 0, 0, "-", "on_member_update_abc"], [35, 0, 0, "-", "on_message_abc"], [35, 0, 0, "-", "on_message_delete_abc"], [35, 0, 0, "-", "on_message_edit_abc"], [35, 0, 0, "-", "on_private_channel_create_abc"], [35, 0, 0, "-", "on_private_channel_delete_abc"], [35, 0, 0, "-", "on_private_channel_pins_update_abc"], [35, 0, 0, "-", "on_private_channel_update_abc"], [35, 0, 0, "-", "on_raw_reaction_add_abc"], [35, 0, 0, "-", "on_raw_reaction_clear_abc"], [35, 0, 0, "-", "on_raw_reaction_clear_emoji_abc"], [35, 0, 0, "-", "on_raw_reaction_remove_abc"], [35, 0, 0, "-", "on_reaction_add_abc"], [35, 0, 0, "-", "on_reaction_clear_abc"], [35, 0, 0, "-", "on_reaction_clear_emoji_abc"], [35, 0, 0, "-", "on_reaction_remove_abc"], [35, 0, 0, "-", "on_ready_abc"], [35, 0, 0, "-", "on_resume_abc"], [35, 0, 0, "-", "on_typing_abc"], [35, 0, 0, "-", "on_user_update_abc"], [35, 0, 0, "-", "on_voice_state_update_abc"], [35, 0, 0, "-", "on_webhooks_update_abc"]], "cpl_discord.events.on_bulk_message_delete_abc": [[35, 1, 1, "", "OnBulkMessageDeleteABC"]], "cpl_discord.events.on_bulk_message_delete_abc.OnBulkMessageDeleteABC": [[35, 2, 1, "", "on_bulk_message_delete"]], "cpl_discord.events.on_command_abc": [[35, 1, 1, "", "OnCommandABC"]], "cpl_discord.events.on_command_abc.OnCommandABC": [[35, 2, 1, "", "on_command"]], "cpl_discord.events.on_command_completion_abc": [[35, 1, 1, "", "OnCommandCompletionABC"]], "cpl_discord.events.on_command_completion_abc.OnCommandCompletionABC": [[35, 2, 1, "", "on_command_completion"]], "cpl_discord.events.on_command_error_abc": [[35, 1, 1, "", "OnCommandErrorABC"]], "cpl_discord.events.on_command_error_abc.OnCommandErrorABC": [[35, 2, 1, "", "on_command_error"]], "cpl_discord.events.on_connect_abc": [[35, 1, 1, "", "OnConnectABC"]], "cpl_discord.events.on_connect_abc.OnConnectABC": [[35, 2, 1, "", "on_connect"]], "cpl_discord.events.on_disconnect_abc": [[35, 1, 1, "", "OnDisconnectABC"]], "cpl_discord.events.on_disconnect_abc.OnDisconnectABC": [[35, 2, 1, "", "on_disconnect"]], "cpl_discord.events.on_error_abc": [[35, 1, 1, "", "OnErrorABC"]], "cpl_discord.events.on_error_abc.OnErrorABC": [[35, 2, 1, "", "on_error"]], "cpl_discord.events.on_group_join_abc": [[35, 1, 1, "", "OnGroupJoinABC"]], "cpl_discord.events.on_group_join_abc.OnGroupJoinABC": [[35, 2, 1, "", "on_group_join"]], "cpl_discord.events.on_group_remove_abc": [[35, 1, 1, "", "OnGroupRemoveABC"]], "cpl_discord.events.on_group_remove_abc.OnGroupRemoveABC": [[35, 2, 1, "", "on_group_remove"]], "cpl_discord.events.on_guild_available_abc": [[35, 1, 1, "", "OnGuildAvailableABC"]], "cpl_discord.events.on_guild_available_abc.OnGuildAvailableABC": [[35, 2, 1, "", "on_guild_available"]], "cpl_discord.events.on_guild_channel_create_abc": [[35, 1, 1, "", "OnGuildChannelCreateABC"]], "cpl_discord.events.on_guild_channel_create_abc.OnGuildChannelCreateABC": [[35, 2, 1, "", "on_guild_channel_create"]], "cpl_discord.events.on_guild_channel_delete_abc": [[35, 1, 1, "", "OnGuildChannelDeleteABC"]], "cpl_discord.events.on_guild_channel_delete_abc.OnGuildChannelDeleteABC": [[35, 2, 1, "", "on_guild_channel_delete"]], "cpl_discord.events.on_guild_channel_pins_update_abc": [[35, 1, 1, "", "OnGuildChannelPinsUpdateABC"]], "cpl_discord.events.on_guild_channel_pins_update_abc.OnGuildChannelPinsUpdateABC": [[35, 2, 1, "", "on_guild_channel_pins_update"]], "cpl_discord.events.on_guild_channel_update_abc": [[35, 1, 1, "", "OnGuildChannelUpdateABC"]], "cpl_discord.events.on_guild_channel_update_abc.OnGuildChannelUpdateABC": [[35, 2, 1, "", "on_guild_channel_update"]], "cpl_discord.events.on_guild_emojis_update_abc": [[35, 1, 1, "", "OnGuildEmojisUpdateABC"]], "cpl_discord.events.on_guild_emojis_update_abc.OnGuildEmojisUpdateABC": [[35, 2, 1, "", "on_guild_emojis_update"]], "cpl_discord.events.on_guild_integrations_update_abc": [[35, 1, 1, "", "OnGuildIntegrationsUpdateABC"]], "cpl_discord.events.on_guild_integrations_update_abc.OnGuildIntegrationsUpdateABC": [[35, 2, 1, "", "on_guild_integrations_update"]], "cpl_discord.events.on_guild_join_abc": [[35, 1, 1, "", "OnGuildJoinABC"]], "cpl_discord.events.on_guild_join_abc.OnGuildJoinABC": [[35, 2, 1, "", "on_guild_join"]], "cpl_discord.events.on_guild_remove_abc": [[35, 1, 1, "", "OnGuildRemoveABC"]], "cpl_discord.events.on_guild_remove_abc.OnGuildRemoveABC": [[35, 2, 1, "", "on_guild_remove"]], "cpl_discord.events.on_guild_role_create_abc": [[35, 1, 1, "", "OnGuildRoleCreateABC"]], "cpl_discord.events.on_guild_role_create_abc.OnGuildRoleCreateABC": [[35, 2, 1, "", "on_guild_role_create"]], "cpl_discord.events.on_guild_role_delete_abc": [[35, 1, 1, "", "OnGuildRoleDeleteABC"]], "cpl_discord.events.on_guild_role_delete_abc.OnGuildRoleDeleteABC": [[35, 2, 1, "", "on_guild_role_delete"]], "cpl_discord.events.on_guild_role_update_abc": [[35, 1, 1, "", "OnGuildRoleUpdateABC"]], "cpl_discord.events.on_guild_role_update_abc.OnGuildRoleUpdateABC": [[35, 2, 1, "", "on_guild_role_update"]], "cpl_discord.events.on_guild_unavailable_abc": [[35, 1, 1, "", "OnGuildUnavailableABC"]], "cpl_discord.events.on_guild_unavailable_abc.OnGuildUnavailableABC": [[35, 2, 1, "", "on_guild_unavailable"]], "cpl_discord.events.on_guild_update_abc": [[35, 1, 1, "", "OnGuildUpdateABC"]], "cpl_discord.events.on_guild_update_abc.OnGuildUpdateABC": [[35, 2, 1, "", "on_guild_update"]], "cpl_discord.events.on_invite_create_abc": [[35, 1, 1, "", "OnInviteCreateABC"]], "cpl_discord.events.on_invite_create_abc.OnInviteCreateABC": [[35, 2, 1, "", "on_invite_create"]], "cpl_discord.events.on_invite_delete_abc": [[35, 1, 1, "", "OnInviteDeleteABC"]], "cpl_discord.events.on_invite_delete_abc.OnInviteDeleteABC": [[35, 2, 1, "", "on_invite_delete"]], "cpl_discord.events.on_member_ban_abc": [[35, 1, 1, "", "OnMemberBanABC"]], "cpl_discord.events.on_member_ban_abc.OnMemberBanABC": [[35, 2, 1, "", "on_member_ban"]], "cpl_discord.events.on_member_join_abc": [[35, 1, 1, "", "OnMemberJoinABC"]], "cpl_discord.events.on_member_join_abc.OnMemberJoinABC": [[35, 2, 1, "", "on_member_join"]], "cpl_discord.events.on_member_remove_abc": [[35, 1, 1, "", "OnMemberRemoveABC"]], "cpl_discord.events.on_member_remove_abc.OnMemberRemoveABC": [[35, 2, 1, "", "on_member_remove"]], "cpl_discord.events.on_member_unban_abc": [[35, 1, 1, "", "OnMemberUnbanABC"]], "cpl_discord.events.on_member_unban_abc.OnMemberUnbanABC": [[35, 2, 1, "", "on_member_unban"]], "cpl_discord.events.on_member_update_abc": [[35, 1, 1, "", "OnMemberUpdateABC"]], "cpl_discord.events.on_member_update_abc.OnMemberUpdateABC": [[35, 2, 1, "", "on_member_update"]], "cpl_discord.events.on_message_abc": [[35, 1, 1, "", "OnMessageABC"]], "cpl_discord.events.on_message_abc.OnMessageABC": [[35, 2, 1, "", "on_message"]], "cpl_discord.events.on_message_delete_abc": [[35, 1, 1, "", "OnMessageDeleteABC"]], "cpl_discord.events.on_message_delete_abc.OnMessageDeleteABC": [[35, 2, 1, "", "on_message_delete"]], "cpl_discord.events.on_message_edit_abc": [[35, 1, 1, "", "OnMessageEditABC"]], "cpl_discord.events.on_message_edit_abc.OnMessageEditABC": [[35, 2, 1, "", "on_message_edit"]], "cpl_discord.events.on_private_channel_create_abc": [[35, 1, 1, "", "OnPrivateChannelCreateABC"]], "cpl_discord.events.on_private_channel_create_abc.OnPrivateChannelCreateABC": [[35, 2, 1, "", "on_private_channel_create"]], "cpl_discord.events.on_private_channel_delete_abc": [[35, 1, 1, "", "OnPrivateChannelDeleteABC"]], "cpl_discord.events.on_private_channel_delete_abc.OnPrivateChannelDeleteABC": [[35, 2, 1, "", "on_private_channel_delete"]], "cpl_discord.events.on_private_channel_pins_update_abc": [[35, 1, 1, "", "OnPrivateChannelPinsUpdateABC"]], "cpl_discord.events.on_private_channel_pins_update_abc.OnPrivateChannelPinsUpdateABC": [[35, 2, 1, "", "on_private_channel_pins_update"]], "cpl_discord.events.on_private_channel_update_abc": [[35, 1, 1, "", "OnPrivateChannelUpdateABC"]], "cpl_discord.events.on_private_channel_update_abc.OnPrivateChannelUpdateABC": [[35, 2, 1, "", "on_private_channel_update"]], "cpl_discord.events.on_raw_reaction_add_abc": [[35, 1, 1, "", "OnRawReactionAddABC"]], "cpl_discord.events.on_raw_reaction_add_abc.OnRawReactionAddABC": [[35, 2, 1, "", "on_raw_reaction_add"]], "cpl_discord.events.on_raw_reaction_clear_abc": [[35, 1, 1, "", "OnRawReactionClearABC"]], "cpl_discord.events.on_raw_reaction_clear_abc.OnRawReactionClearABC": [[35, 2, 1, "", "on_raw_reaction_clear"]], "cpl_discord.events.on_raw_reaction_clear_emoji_abc": [[35, 1, 1, "", "OnRawReactionClearEmojiABC"]], "cpl_discord.events.on_raw_reaction_clear_emoji_abc.OnRawReactionClearEmojiABC": [[35, 2, 1, "", "on_raw_reaction_clear_emoji"]], "cpl_discord.events.on_raw_reaction_remove_abc": [[35, 1, 1, "", "OnRawReactionRemoveABC"]], "cpl_discord.events.on_raw_reaction_remove_abc.OnRawReactionRemoveABC": [[35, 2, 1, "", "on_raw_reaction_remove"]], "cpl_discord.events.on_reaction_add_abc": [[35, 1, 1, "", "OnReactionAddABC"]], "cpl_discord.events.on_reaction_add_abc.OnReactionAddABC": [[35, 2, 1, "", "on_reaction_add"]], "cpl_discord.events.on_reaction_clear_abc": [[35, 1, 1, "", "OnReactionClearABC"]], "cpl_discord.events.on_reaction_clear_abc.OnReactionClearABC": [[35, 2, 1, "", "on_reaction_clear"]], "cpl_discord.events.on_reaction_clear_emoji_abc": [[35, 1, 1, "", "OnReactionClearEmojiABC"]], "cpl_discord.events.on_reaction_clear_emoji_abc.OnReactionClearEmojiABC": [[35, 2, 1, "", "on_reaction_clear_emoji"]], "cpl_discord.events.on_reaction_remove_abc": [[35, 1, 1, "", "OnReactionRemoveABC"]], "cpl_discord.events.on_reaction_remove_abc.OnReactionRemoveABC": [[35, 2, 1, "", "on_reaction_remove"]], "cpl_discord.events.on_ready_abc": [[35, 1, 1, "", "OnReadyABC"]], "cpl_discord.events.on_ready_abc.OnReadyABC": [[35, 2, 1, "", "on_ready"]], "cpl_discord.events.on_resume_abc": [[35, 1, 1, "", "OnResumeABC"]], "cpl_discord.events.on_resume_abc.OnResumeABC": [[35, 2, 1, "", "on_resume"]], "cpl_discord.events.on_typing_abc": [[35, 1, 1, "", "OnTypingABC"]], "cpl_discord.events.on_typing_abc.OnTypingABC": [[35, 2, 1, "", "on_typing"]], "cpl_discord.events.on_user_update_abc": [[35, 1, 1, "", "OnUserUpdateABC"]], "cpl_discord.events.on_user_update_abc.OnUserUpdateABC": [[35, 2, 1, "", "on_user_update"]], "cpl_discord.events.on_voice_state_update_abc": [[35, 1, 1, "", "OnVoiceStateUpdateABC"]], "cpl_discord.events.on_voice_state_update_abc.OnVoiceStateUpdateABC": [[35, 2, 1, "", "on_voice_state_update"]], "cpl_discord.events.on_webhooks_update_abc": [[35, 1, 1, "", "OnWebhooksUpdateABC"]], "cpl_discord.events.on_webhooks_update_abc.OnWebhooksUpdateABC": [[35, 2, 1, "", "on_webhooks_update"]], "cpl_discord.helper": [[36, 0, 0, "-", "to_containers_converter"]], "cpl_discord.helper.to_containers_converter": [[36, 1, 1, "", "ToContainersConverter"]], "cpl_discord.helper.to_containers_converter.ToContainersConverter": [[36, 2, 1, "", "convert"]], "cpl_discord.service": [[37, 0, 0, "-", "command_error_handler_service"], [37, 0, 0, "-", "discord_bot_service"], [37, 0, 0, "-", "discord_bot_service_abc"], [37, 0, 0, "-", "discord_collection"], [37, 0, 0, "-", "discord_collection_abc"], [37, 0, 0, "-", "discord_service"], [37, 0, 0, "-", "discord_service_abc"]], "cpl_discord.service.command_error_handler_service": [[37, 1, 1, "", "CommandErrorHandlerService"]], "cpl_discord.service.command_error_handler_service.CommandErrorHandlerService": [[37, 2, 1, "", "on_command_error"]], "cpl_discord.service.discord_bot_service": [[37, 1, 1, "", "DiscordBotService"]], "cpl_discord.service.discord_bot_service.DiscordBotService": [[37, 3, 1, "", "guilds"], [37, 2, 1, "", "on_ready"], [37, 2, 1, "", "start_async"], [37, 2, 1, "", "stop_async"]], "cpl_discord.service.discord_bot_service_abc": [[37, 1, 1, "", "DiscordBotServiceABC"]], "cpl_discord.service.discord_bot_service_abc.DiscordBotServiceABC": [[37, 3, 1, "", "guilds"], [37, 2, 1, "", "on_ready"], [37, 2, 1, "", "start_async"], [37, 2, 1, "", "stop_async"]], "cpl_discord.service.discord_collection": [[37, 1, 1, "", "DiscordCollection"]], "cpl_discord.service.discord_collection.DiscordCollection": [[37, 2, 1, "", "add_command"], [37, 2, 1, "", "add_event"], [37, 2, 1, "", "get_commands"], [37, 2, 1, "", "get_events_by_base"]], "cpl_discord.service.discord_collection_abc": [[37, 1, 1, "", "DiscordCollectionABC"]], "cpl_discord.service.discord_collection_abc.DiscordCollectionABC": [[37, 2, 1, "", "add_command"], [37, 2, 1, "", "add_event"], [37, 2, 1, "", "get_commands"], [37, 2, 1, "", "get_events_by_base"]], "cpl_discord.service.discord_service": [[37, 1, 1, "", "DiscordService"]], "cpl_discord.service.discord_service.DiscordService": [[37, 2, 1, "", "init"], [37, 2, 1, "", "on_bulk_message_delete"], [37, 2, 1, "", "on_command"], [37, 2, 1, "", "on_command_completion"], [37, 2, 1, "", "on_command_error"], [37, 2, 1, "", "on_connect"], [37, 2, 1, "", "on_disconnect"], [37, 2, 1, "", "on_error"], [37, 2, 1, "", "on_group_join"], [37, 2, 1, "", "on_group_remove"], [37, 2, 1, "", "on_guild_available"], [37, 2, 1, "", "on_guild_channel_create"], [37, 2, 1, "", "on_guild_channel_delete"], [37, 2, 1, "", "on_guild_channel_pins_update"], [37, 2, 1, "", "on_guild_channel_update"], [37, 2, 1, "", "on_guild_emojis_update"], [37, 2, 1, "", "on_guild_integrations_update"], [37, 2, 1, "", "on_guild_join"], [37, 2, 1, "", "on_guild_remove"], [37, 2, 1, "", "on_guild_role_create"], [37, 2, 1, "", "on_guild_role_delete"], [37, 2, 1, "", "on_guild_role_update"], [37, 2, 1, "", "on_guild_unavailable"], [37, 2, 1, "", "on_guild_update"], [37, 2, 1, "", "on_invite_create"], [37, 2, 1, "", "on_invite_delete"], [37, 2, 1, "", "on_member_ban"], [37, 2, 1, "", "on_member_join"], [37, 2, 1, "", "on_member_remove"], [37, 2, 1, "", "on_member_unban"], [37, 2, 1, "", "on_member_update"], [37, 2, 1, "", "on_message"], [37, 2, 1, "", "on_message_delete"], [37, 2, 1, "", "on_message_edit"], [37, 2, 1, "", "on_private_channel_create"], [37, 2, 1, "", "on_private_channel_delete"], [37, 2, 1, "", "on_private_channel_pins_update"], [37, 2, 1, "", "on_private_channel_update"], [37, 2, 1, "", "on_raw_reaction_add"], [37, 2, 1, "", "on_raw_reaction_clear"], [37, 2, 1, "", "on_raw_reaction_clear_emoji"], [37, 2, 1, "", "on_raw_reaction_remove"], [37, 2, 1, "", "on_reaction_add"], [37, 2, 1, "", "on_reaction_clear"], [37, 2, 1, "", "on_reaction_clear_emoji"], [37, 2, 1, "", "on_reaction_remove"], [37, 2, 1, "", "on_ready"], [37, 2, 1, "", "on_resume"], [37, 2, 1, "", "on_typing"], [37, 2, 1, "", "on_user_update"], [37, 2, 1, "", "on_voice_state_update"], [37, 2, 1, "", "on_webhooks_update"]], "cpl_discord.service.discord_service_abc": [[37, 1, 1, "", "DiscordServiceABC"]], "cpl_discord.service.discord_service_abc.DiscordServiceABC": [[37, 2, 1, "", "init"], [37, 2, 1, "", "on_bulk_message_delete"], [37, 2, 1, "", "on_command"], [37, 2, 1, "", "on_command_completion"], [37, 2, 1, "", "on_command_error"], [37, 2, 1, "", "on_connect"], [37, 2, 1, "", "on_disconnect"], [37, 2, 1, "", "on_error"], [37, 2, 1, "", "on_group_join"], [37, 2, 1, "", "on_group_remove"], [37, 2, 1, "", "on_guild_available"], [37, 2, 1, "", "on_guild_channel_create"], [37, 2, 1, "", "on_guild_channel_delete"], [37, 2, 1, "", "on_guild_channel_pins_update"], [37, 2, 1, "", "on_guild_channel_update"], [37, 2, 1, "", "on_guild_emojis_update"], [37, 2, 1, "", "on_guild_integrations_update"], [37, 2, 1, "", "on_guild_join"], [37, 2, 1, "", "on_guild_remove"], [37, 2, 1, "", "on_guild_role_create"], [37, 2, 1, "", "on_guild_role_delete"], [37, 2, 1, "", "on_guild_role_update"], [37, 2, 1, "", "on_guild_unavailable"], [37, 2, 1, "", "on_guild_update"], [37, 2, 1, "", "on_invite_create"], [37, 2, 1, "", "on_invite_delete"], [37, 2, 1, "", "on_member_ban"], [37, 2, 1, "", "on_member_join"], [37, 2, 1, "", "on_member_remove"], [37, 2, 1, "", "on_member_unban"], [37, 2, 1, "", "on_member_update"], [37, 2, 1, "", "on_message"], [37, 2, 1, "", "on_message_delete"], [37, 2, 1, "", "on_message_edit"], [37, 2, 1, "", "on_private_channel_create"], [37, 2, 1, "", "on_private_channel_delete"], [37, 2, 1, "", "on_private_channel_pins_update"], [37, 2, 1, "", "on_private_channel_update"], [37, 2, 1, "", "on_reaction_add"], [37, 2, 1, "", "on_reaction_clear"], [37, 2, 1, "", "on_reaction_clear_emoji"], [37, 2, 1, "", "on_reaction_remove"], [37, 2, 1, "", "on_ready"], [37, 2, 1, "", "on_resume"], [37, 2, 1, "", "on_typing"], [37, 2, 1, "", "on_user_update"], [37, 2, 1, "", "on_voice_state_update"], [37, 2, 1, "", "on_webhooks_update"]], "cpl_query.base": [[39, 0, 0, "-", "default_lambda"], [39, 0, 0, "-", "ordered_queryable"], [39, 0, 0, "-", "ordered_queryable_abc"], [39, 0, 0, "-", "queryable_abc"], [39, 0, 0, "-", "sequence_abc"], [39, 0, 0, "-", "sequence_values"]], "cpl_query.base.default_lambda": [[39, 5, 1, "", "default_lambda"]], "cpl_query.base.ordered_queryable": [[39, 1, 1, "", "OrderedQueryable"]], "cpl_query.base.ordered_queryable.OrderedQueryable": [[39, 2, 1, "", "then_by"], [39, 2, 1, "", "then_by_descending"]], "cpl_query.base.ordered_queryable_abc": [[39, 1, 1, "", "OrderedQueryableABC"]], "cpl_query.base.ordered_queryable_abc.OrderedQueryableABC": [[39, 2, 1, "", "then_by"], [39, 2, 1, "", "then_by_descending"]], "cpl_query.base.queryable_abc": [[39, 1, 1, "", "QueryableABC"]], "cpl_query.base.queryable_abc.QueryableABC": [[39, 2, 1, "", "all"], [39, 2, 1, "", "any"], [39, 2, 1, "", "average"], [39, 2, 1, "", "contains"], [39, 2, 1, "", "count"], [39, 2, 1, "", "distinct"], [39, 2, 1, "", "element_at"], [39, 2, 1, "", "element_at_or_default"], [39, 2, 1, "", "first"], [39, 2, 1, "", "first_or_default"], [39, 2, 1, "", "for_each"], [39, 2, 1, "", "group_by"], [39, 2, 1, "", "last"], [39, 2, 1, "", "last_or_default"], [39, 2, 1, "", "max"], [39, 2, 1, "", "median"], [39, 2, 1, "", "min"], [39, 2, 1, "", "order_by"], [39, 2, 1, "", "order_by_descending"], [39, 2, 1, "", "reverse"], [39, 2, 1, "", "select"], [39, 2, 1, "", "select_many"], [39, 2, 1, "", "single"], [39, 2, 1, "", "single_or_default"], [39, 2, 1, "", "skip"], [39, 2, 1, "", "skip_last"], [39, 2, 1, "", "sum"], [39, 2, 1, "", "take"], [39, 2, 1, "", "take_last"], [39, 2, 1, "", "where"]], "cpl_query.base.sequence_abc": [[39, 1, 1, "", "SequenceABC"]], "cpl_query.base.sequence_abc.SequenceABC": [[39, 2, 1, "", "copy"], [39, 2, 1, "", "empty"], [39, 2, 1, "", "index"], [39, 2, 1, "", "next"], [39, 2, 1, "", "range"], [39, 2, 1, "", "to_list"], [39, 3, 1, "", "type"]], "cpl_query.base.sequence_values": [[39, 1, 1, "", "SequenceValues"]], "cpl_query.base.sequence_values.SequenceValues": [[39, 2, 1, "", "next"], [39, 2, 1, "", "reset"]], "cpl_query.enumerable": [[40, 0, 0, "-", "enumerable"], [40, 0, 0, "-", "enumerable_abc"]], "cpl_query.enumerable.enumerable": [[40, 1, 1, "", "Enumerable"]], "cpl_query.enumerable.enumerable_abc": [[40, 1, 1, "", "EnumerableABC"]], "cpl_query.enumerable.enumerable_abc.EnumerableABC": [[40, 2, 1, "", "set_remove_error_check"], [40, 2, 1, "", "to_iterable"]], "cpl_query.extension": [[41, 0, 0, "-", "list"]], "cpl_query.extension.list": [[41, 1, 1, "", "List"]], "cpl_query.extension.list.List": [[41, 2, 1, "", "to_enumerable"], [41, 2, 1, "", "to_iterable"]], "cpl_query.iterable": [[42, 0, 0, "-", "iterable"], [42, 0, 0, "-", "iterable_abc"]], "cpl_query.iterable.iterable": [[42, 1, 1, "", "Iterable"]], "cpl_query.iterable.iterable_abc": [[42, 1, 1, "", "IterableABC"]], "cpl_query.iterable.iterable_abc.IterableABC": [[42, 2, 1, "", "add"], [42, 2, 1, "", "append"], [42, 2, 1, "", "extend"], [42, 2, 1, "", "remove"], [42, 2, 1, "", "to_enumerable"], [42, 3, 1, "", "type"]], "cpl_translation": [[43, 0, 0, "-", "translate_pipe"], [43, 0, 0, "-", "translation_service"], [43, 0, 0, "-", "translation_service_abc"], [43, 0, 0, "-", "translation_settings"]], "cpl_translation.translate_pipe": [[43, 1, 1, "", "TranslatePipe"]], "cpl_translation.translate_pipe.TranslatePipe": [[43, 2, 1, "", "transform"]], "cpl_translation.translation_service": [[43, 1, 1, "", "TranslationService"]], "cpl_translation.translation_service.TranslationService": [[43, 2, 1, "", "load"], [43, 2, 1, "", "load_by_settings"], [43, 2, 1, "", "set_default_lang"], [43, 2, 1, "", "set_lang"], [43, 2, 1, "", "translate"]], "cpl_translation.translation_service_abc": [[43, 1, 1, "", "TranslationServiceABC"]], "cpl_translation.translation_service_abc.TranslationServiceABC": [[43, 2, 1, "", "load"], [43, 2, 1, "", "load_by_settings"], [43, 2, 1, "", "set_default_lang"], [43, 2, 1, "", "set_lang"], [43, 2, 1, "", "translate"]], "cpl_translation.translation_settings": [[43, 1, 1, "", "TranslationSettings"]], "cpl_translation.translation_settings.TranslationSettings": [[43, 3, 1, "", "default_language"], [43, 2, 1, "", "from_dict"], [43, 3, 1, "", "languages"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:property", "4": "py:attribute", "5": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "property", "Python property"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "function", "Python function"]}, "titleterms": {"cpl": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 45, 46, 47, 48], "add": 0, "content": [0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 48, 49], "descript": [0, 1, 2, 3, 4, 5, 7, 8, 11], "argument": [0, 2, 3, 4, 8, 11, 53], "flag": [0, 4, 5, 8, 11, 12], "build": 1, "gener": 2, "schemat": [2, 6], "help": 3, "instal": [4, 49], "new": 5, "project": [5, 48], "type": 5, "cli": [6, 15, 49], "overview": [6, 46], "command": [6, 32], "refer": [6, 15, 16, 30, 38, 43], "tabl": [6, 48, 49], "basic": 6, "workflow": 6, "languag": 6, "syntax": 6, "rel": 6, "path": 6, "publish": 7, "remov": 8, "run": 9, "start": [10, 44, 48, 49], "uninstal": 11, "updat": 12, "version": 13, "contribut": 14, "found": 14, "bug": 14, "featur": [14, 45, 46], "request": 14, "submiss": 14, "guidelin": 14, "submit": 14, "an": 14, "issu": 14, "pull": 14, "review": 14, "address": 14, "feedback": 14, "code": 14, "rule": 14, "licens": 14, "api": 16, "cpl_core": [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 52], "applic": [17, 31, 55], "application_abc": 17, "application_build": 17, "application_builder_abc": 17, "startup_abc": 17, "configur": [18, 33], "configuration_abc": 18, "configuration_model_abc": 18, "configuration_variable_name_enum": 18, "console_argu": 18, "consol": [19, 49, 52, 53], "background_color_enum": 19, "console_cal": 19, "foreground_color_enum": 19, "spinner_thread": 19, "databas": [20, 21, 22], "database_model": 20, "database_set": 20, "database_settings_name_enum": 20, "connect": 21, "database_connect": 21, "database_connection_abc": 21, "context": 22, "database_context": 22, "database_context_abc": 22, "dependency_inject": 23, "service_collect": 23, "service_collection_abc": 23, "service_descriptor": 23, "service_lifetime_enum": 23, "service_provid": 23, "service_provider_abc": 23, "environ": [24, 49], "application_environ": 24, "application_environment_abc": 24, "environment_name_enum": 24, "log": 25, "logger_abc": 25, "logger_servic": 25, "logging_level_enum": 25, "logging_set": 25, "logging_settings_name_enum": 25, "mail": [26, 58], "email": 26, "email_client_abc": 26, "email_client_servic": 26, "email_client_set": 26, "email_client_settings_name_enum": 26, "pipe": 27, "bool_pip": 27, "first_char_to_lower_pip": 27, "first_to_upper_pip": 27, "ip_address_pip": 27, "pipe_abc": 27, "to_camel_case_pip": 27, "to_snake_case_pip": 27, "version_pip": 27, "time": 28, "time_format_set": 28, "time_format_settings_names_enum": 28, "util": 29, "credential_manag": 29, "pip": 29, "string": 29, "discord": 30, "cpl_discord": [31, 32, 33, 34, 35, 36, 37], "discord_bot_application_abc": 31, "discord_command_abc": 32, "discord_commands_meta": 32, "discord_bot_set": 33, "contain": 34, "category_channel": 34, "guild": 34, "member": 34, "role": 34, "text_channel": 34, "thread": 34, "voice_channel": 34, "event": 35, "on_bulk_message_delete_abc": 35, "on_command_abc": 35, "on_command_completion_abc": 35, "on_command_error_abc": 35, "on_connect_abc": 35, "on_disconnect_abc": 35, "on_error_abc": 35, "on_group_join_abc": 35, "on_group_remove_abc": 35, "on_guild_available_abc": 35, "on_guild_channel_create_abc": 35, "on_guild_channel_delete_abc": 35, "on_guild_channel_pins_update_abc": 35, "on_guild_channel_update_abc": 35, "on_guild_emojis_update_abc": 35, "on_guild_integrations_update_abc": 35, "on_guild_join_abc": 35, "on_guild_remove_abc": 35, "on_guild_role_create_abc": 35, "on_guild_role_delete_abc": 35, "on_guild_role_update_abc": 35, "on_guild_unavailable_abc": 35, "on_guild_update_abc": 35, "on_invite_create_abc": 35, "on_invite_delete_abc": 35, "on_member_ban_abc": 35, "on_member_join_abc": 35, "on_member_remove_abc": 35, "on_member_unban_abc": 35, "on_member_update_abc": 35, "on_message_abc": 35, "on_message_delete_abc": 35, "on_message_edit_abc": 35, "on_private_channel_create_abc": 35, "on_private_channel_delete_abc": 35, "on_private_channel_pins_update_abc": 35, "on_private_channel_update_abc": 35, "on_raw_reaction_add_abc": 35, "on_raw_reaction_clear_abc": 35, "on_raw_reaction_clear_emoji_abc": 35, "on_raw_reaction_remove_abc": 35, "on_reaction_add_abc": 35, "on_reaction_clear_abc": 35, "on_reaction_clear_emoji_abc": 35, "on_reaction_remove_abc": 35, "on_ready_abc": 35, "on_resume_abc": 35, "on_typing_abc": 35, "on_user_update_abc": 35, "on_voice_state_update_abc": 35, "on_webhooks_update_abc": 35, "helper": 36, "to_containers_convert": 36, "servic": 37, "command_error_handler_servic": 37, "discord_bot_servic": 37, "discord_bot_service_abc": 37, "discord_collect": 37, "discord_collection_abc": 37, "discord_servic": 37, "discord_service_abc": 37, "queri": [38, 49], "cpl_queri": [39, 40, 41, 42], "base": 39, "default_lambda": 39, "ordered_query": 39, "ordered_queryable_abc": 39, "queryable_abc": 39, "sequence_abc": 39, "sequence_valu": 39, "enumer": 40, "enumerable_abc": 40, "extens": 41, "list": 41, "iter": 42, "iterable_abc": 42, "translat": 43, "cpl_translat": 43, "translate_pip": 43, "translation_servic": 43, "translation_service_abc": 43, "translation_set": 43, "get": [44, 48], "introduct": [45, 46], "doc": [45, 46], "manual": 45, "explor": 46, "prerequisit": [48, 49], "creat": [48, 49, 54], "menu": 48, "what": [48, 49], "s": [48, 49], "next": [48, 49], "set": 49, "up": 49, "local": 49, "workspac": 49, "packag": 49, "initi": 49, "app": 49, "librari": 49, "tutori": 50, "us": [51, 52, 57], "appset": 51, "json": 51, "com": [51, 52, 53, 54, 55, 56, 57, 58], "soon": [51, 52, 53, 54, 55, 56, 57, 58], "handl": 53, "startup": [54, 56], "class": 54, "extend": [55, 56], "builtin": 57, "logger": 57, "send": 58}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 56}}) \ No newline at end of file diff --git a/docs/build/html/setup.html b/docs/build/html/setup.html index 4fd1c85a..330b7c84 100644 --- a/docs/build/html/setup.html +++ b/docs/build/html/setup.html @@ -58,9 +58,11 @@
  184. Contributing to CPL
  185. -
  186. CLI Reference
  187. -
  188. API Reference
  189. -
  190. Query Reference
  191. +
  192. CLI reference
  193. +
  194. API reference
  195. +
  196. Discord reference
  197. +
  198. Query reference
  199. +
  200. Translation reference
  201. @@ -118,7 +120,7 @@

    Install the package

    To install the package, open a terminal window and run the following command:

    -
    pip install sh_cpl-core --extra-index-url https://pip.sh-edraft.de
    +
    pip install cpl-core --extra-index-url https://pip.sh-edraft.de
     
    @@ -126,14 +128,14 @@

    Install the CLI

    You use the CPL CLI to create projects, generate application and library code. You also use the CLI to build and publish your python packages.

    To install the CLI, open a terminal window and run the following command:

    -
    pip install sh_cpl-cli --extra-index-url https://pip.sh-edraft.de
    +
    pip install cpl-cli --extra-index-url https://pip.sh-edraft.de
     

    Install the query

    To install the package, open a terminal window and run the following command:

    -
    pip install sh_cpl-query --extra-index-url https://pip.sh-edraft.de
    +
    pip install cpl-query --extra-index-url https://pip.sh-edraft.de
     
    @@ -206,7 +208,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/tutorials.appsettings.html b/docs/build/html/tutorials.appsettings.html index f3326ff6..0b42a876 100644 --- a/docs/build/html/tutorials.appsettings.html +++ b/docs/build/html/tutorials.appsettings.html @@ -60,9 +60,11 @@
  202. Contributing to CPL
  203. -
  204. CLI Reference
  205. -
  206. API Reference
  207. -
  208. Query Reference
  209. +
  210. CLI reference
  211. +
  212. API reference
  213. +
  214. Discord reference
  215. +
  216. Query reference
  217. +
  218. Translation reference
  219. @@ -109,7 +111,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/tutorials.console-arguments.html b/docs/build/html/tutorials.console-arguments.html index 435572ca..01cb18f3 100644 --- a/docs/build/html/tutorials.console-arguments.html +++ b/docs/build/html/tutorials.console-arguments.html @@ -60,9 +60,11 @@
  220. Contributing to CPL
  221. -
  222. CLI Reference
  223. -
  224. API Reference
  225. -
  226. Query Reference
  227. +
  228. CLI reference
  229. +
  230. API reference
  231. +
  232. Discord reference
  233. +
  234. Query reference
  235. +
  236. Translation reference
  237. @@ -109,7 +111,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/tutorials.console.html b/docs/build/html/tutorials.console.html index a3442f07..7b9ef50b 100644 --- a/docs/build/html/tutorials.console.html +++ b/docs/build/html/tutorials.console.html @@ -60,9 +60,11 @@
  238. Contributing to CPL
  239. -
  240. CLI Reference
  241. -
  242. API Reference
  243. -
  244. Query Reference
  245. +
  246. CLI reference
  247. +
  248. API reference
  249. +
  250. Discord reference
  251. +
  252. Query reference
  253. +
  254. Translation reference
  255. @@ -109,7 +111,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/tutorials.create-startup.html b/docs/build/html/tutorials.create-startup.html index 2feee349..98beb078 100644 --- a/docs/build/html/tutorials.create-startup.html +++ b/docs/build/html/tutorials.create-startup.html @@ -60,9 +60,11 @@
  256. Contributing to CPL
  257. -
  258. CLI Reference
  259. -
  260. API Reference
  261. -
  262. Query Reference
  263. +
  264. CLI reference
  265. +
  266. API reference
  267. +
  268. Discord reference
  269. +
  270. Query reference
  271. +
  272. Translation reference
  273. @@ -109,7 +111,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/tutorials.extend-application.html b/docs/build/html/tutorials.extend-application.html index ecdb0e88..40d36232 100644 --- a/docs/build/html/tutorials.extend-application.html +++ b/docs/build/html/tutorials.extend-application.html @@ -60,9 +60,11 @@
  274. Contributing to CPL
  275. -
  276. CLI Reference
  277. -
  278. API Reference
  279. -
  280. Query Reference
  281. +
  282. CLI reference
  283. +
  284. API reference
  285. +
  286. Discord reference
  287. +
  288. Query reference
  289. +
  290. Translation reference
  291. @@ -109,7 +111,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/tutorials.extend-startup.html b/docs/build/html/tutorials.extend-startup.html index 4a37bfaf..660a1afb 100644 --- a/docs/build/html/tutorials.extend-startup.html +++ b/docs/build/html/tutorials.extend-startup.html @@ -60,9 +60,11 @@
  292. Contributing to CPL
  293. -
  294. CLI Reference
  295. -
  296. API Reference
  297. -
  298. Query Reference
  299. +
  300. CLI reference
  301. +
  302. API reference
  303. +
  304. Discord reference
  305. +
  306. Query reference
  307. +
  308. Translation reference
  309. @@ -109,7 +111,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/tutorials.html b/docs/build/html/tutorials.html index 458940a3..141e20c5 100644 --- a/docs/build/html/tutorials.html +++ b/docs/build/html/tutorials.html @@ -57,9 +57,11 @@
  310. Contributing to CPL
  311. -
  312. CLI Reference
  313. -
  314. API Reference
  315. -
  316. Query Reference
  317. +
  318. CLI reference
  319. +
  320. API reference
  321. +
  322. Discord reference
  323. +
  324. Query reference
  325. +
  326. Translation reference
  327. @@ -138,7 +140,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/tutorials.logging.html b/docs/build/html/tutorials.logging.html index bb948b54..d88b255f 100644 --- a/docs/build/html/tutorials.logging.html +++ b/docs/build/html/tutorials.logging.html @@ -60,9 +60,11 @@
  328. Contributing to CPL
  329. -
  330. CLI Reference
  331. -
  332. API Reference
  333. -
  334. Query Reference
  335. +
  336. CLI reference
  337. +
  338. API reference
  339. +
  340. Discord reference
  341. +
  342. Query reference
  343. +
  344. Translation reference
  345. @@ -109,7 +111,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/build/html/tutorials.mail.html b/docs/build/html/tutorials.mail.html index 65cf0ca5..c1c39f37 100644 --- a/docs/build/html/tutorials.mail.html +++ b/docs/build/html/tutorials.mail.html @@ -60,9 +60,11 @@
  346. Contributing to CPL
  347. -
  348. CLI Reference
  349. -
  350. API Reference
  351. -
  352. Query Reference
  353. +
  354. CLI reference
  355. +
  356. API reference
  357. +
  358. Discord reference
  359. +
  360. Query reference
  361. +
  362. Translation reference
  363. @@ -109,7 +111,7 @@
    -

    © Copyright 2021, Sven Heidemann.

    +

    © Copyright 2021 - 2023, Sven Heidemann.

    Built with Sphinx using a diff --git a/docs/source/cli.generate.md b/docs/source/cli.generate.md index 40d79fdf..95a1cb51 100644 --- a/docs/source/cli.generate.md +++ b/docs/source/cli.generate.md @@ -18,10 +18,11 @@ Generates files based on a schematic. ## Arguments -| Argument | Description | Value type | -| ----------------- |:---------------------------------:|:-------------:| -| `````` | The schematic to generate. | ```str``` | -| `````` | The name of the generated file. | ```str``` | +| Argument | Description | Value type | +|-------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------:| +| `````` | The schematic to generate. | ```str``` | +| `````` | The name of the generated file. | ```str``` | +| ```--base``` | First element of path will be used as base-path not 'src'. For example: 'cpl g c test/Test' will be created at ```src/test/``` with --base it would be ```test/``` | ```str``` | ## Schematics diff --git a/docs/source/cli.new.md b/docs/source/cli.new.md index 2ddcb9e7..f000dcd6 100644 --- a/docs/source/cli.new.md +++ b/docs/source/cli.new.md @@ -18,10 +18,11 @@ Generates a workspace and initial project or add a project to workspace. If the command is running in a CPL workspace, it will add the new project to the workspace. -| Argument | Description | Value type | -|--------------|:----------------------------------------------------:|:----------:| -| `````` | The type of the project, see [types](#project-types) | ```str``` | -| `````` | The name of the project | ```str``` | +| Argument | Description | Value type | +|--------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:----------:| +| `````` | The type of the project, see [types](#project-types) | ```str``` | +| `````` | The name of the project | ```str``` | +| ```--base``` | First element of path will be used as base-path not 'src'. For example: 'cpl g c test/Test' will be created at ```src/test/``` with --base it would be ```test/``` | ```str``` | ## Project types diff --git a/docs/source/cli.run.md b/docs/source/cli.run.md new file mode 100644 index 00000000..5782a7a4 --- /dev/null +++ b/docs/source/cli.run.md @@ -0,0 +1,12 @@ +# cpl run + +Starts your application once. + +cpl **run**
    +cpl **r**
    +cpl **R** + +| Argument | Description | Value type | +|-----------------|:----------------------------------------------------------------------------------------------------:|:----------:| +| `````` | Optional parameter to specify which project to start, if not set default project will be started. | ```str``` | +| ```--dev``` | To run the project from source and not from dist after build. | ```str``` | \ No newline at end of file diff --git a/docs/source/cli.start.md b/docs/source/cli.start.md index 2b067bfb..961feef1 100644 --- a/docs/source/cli.start.md +++ b/docs/source/cli.start.md @@ -5,3 +5,7 @@ Starts your application, restarting on file changes. cpl **start**
    cpl **s**
    cpl **S** + +| Argument | Description | Value type | +|-----------------|:----------------------------------------------------------------------------------------------------:|:----------:| +| ```--dev``` | To run the project from source and not from dist after build. | ```str``` | \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index 6954834c..00747705 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -15,16 +15,15 @@ # sys.path.insert(0, os.path.abspath('.')) import os import sys -sys.path.insert(0, os.path.abspath('../../src/')) +sys.path.insert(0, os.path.abspath('../../src/')) # -- Project information ----------------------------------------------------- project = 'Common Python Library' -copyright = '2021, Sven Heidemann' +copyright = '2021 - 2023, Sven Heidemann' author = 'Sven Heidemann' - # -- General configuration --------------------------------------------------- # Add any Sphinx extension names here, as strings. They can be @@ -56,7 +55,6 @@ exclude_patterns = [ 'tests/*' ] - # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for diff --git a/docs/source/cpl_cli.rst b/docs/source/cpl_cli.rst index 338ba5c2..cec12291 100644 --- a/docs/source/cpl_cli.rst +++ b/docs/source/cpl_cli.rst @@ -1,4 +1,4 @@ -CLI Reference +CLI reference ============= .. toctree:: diff --git a/docs/source/cpl_core.database.rst b/docs/source/cpl_core.database.rst index fb55c962..cdcb0ce8 100644 --- a/docs/source/cpl_core.database.rst +++ b/docs/source/cpl_core.database.rst @@ -7,8 +7,7 @@ cpl_core.database cpl_core.database.connection cpl_core.database.context -Submodules ----------- + cpl_core.database.database\_model ----------------------------------- diff --git a/docs/source/cpl_core.pipes.rst b/docs/source/cpl_core.pipes.rst index 8af5814b..0a8bba4d 100644 --- a/docs/source/cpl_core.pipes.rst +++ b/docs/source/cpl_core.pipes.rst @@ -1,10 +1,9 @@ cpl\_core.pipes ======================= -Submodules ----------- -cpl\_core.pipes.bool\_pipe module + +cpl\_core.pipes.bool\_pipe --------------------------------- .. automodule:: cpl_core.pipes.bool_pipe @@ -12,7 +11,7 @@ cpl\_core.pipes.bool\_pipe module :undoc-members: :show-inheritance: -cpl\_core.pipes.first\_char\_to\_lower\_pipe module +cpl\_core.pipes.first\_char\_to\_lower\_pipe --------------------------------------------------- .. automodule:: cpl_core.pipes.first_char_to_lower_pipe @@ -20,7 +19,7 @@ cpl\_core.pipes.first\_char\_to\_lower\_pipe module :undoc-members: :show-inheritance: -cpl\_core.pipes.first\_to\_upper\_pipe module +cpl\_core.pipes.first\_to\_upper\_pipe --------------------------------------------- .. automodule:: cpl_core.pipes.first_to_upper_pipe @@ -28,7 +27,7 @@ cpl\_core.pipes.first\_to\_upper\_pipe module :undoc-members: :show-inheritance: -cpl\_core.pipes.ip\_address\_pipe module +cpl\_core.pipes.ip\_address\_pipe ---------------------------------------- .. automodule:: cpl_core.pipes.ip_address_pipe @@ -36,7 +35,7 @@ cpl\_core.pipes.ip\_address\_pipe module :undoc-members: :show-inheritance: -cpl\_core.pipes.pipe\_abc module +cpl\_core.pipes.pipe\_abc -------------------------------- .. automodule:: cpl_core.pipes.pipe_abc @@ -44,7 +43,7 @@ cpl\_core.pipes.pipe\_abc module :undoc-members: :show-inheritance: -cpl\_core.pipes.to\_camel\_case\_pipe module +cpl\_core.pipes.to\_camel\_case\_pipe -------------------------------------------- .. automodule:: cpl_core.pipes.to_camel_case_pipe @@ -52,7 +51,7 @@ cpl\_core.pipes.to\_camel\_case\_pipe module :undoc-members: :show-inheritance: -cpl\_core.pipes.to\_snake\_case\_pipe module +cpl\_core.pipes.to\_snake\_case\_pipe -------------------------------------------- .. automodule:: cpl_core.pipes.to_snake_case_pipe @@ -60,18 +59,10 @@ cpl\_core.pipes.to\_snake\_case\_pipe module :undoc-members: :show-inheritance: -cpl\_core.pipes.version\_pipe module +cpl\_core.pipes.version\_pipe ------------------------------------ .. automodule:: cpl_core.pipes.version_pipe :members: :undoc-members: :show-inheritance: - -Module contents ---------------- - -.. automodule:: cpl_core.pipes - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/cpl_core.rst b/docs/source/cpl_core.rst index a71547b3..e1e9b11a 100644 --- a/docs/source/cpl_core.rst +++ b/docs/source/cpl_core.rst @@ -1,4 +1,4 @@ -API Reference +API reference =========== .. toctree:: diff --git a/docs/source/cpl_discord.application.rst b/docs/source/cpl_discord.application.rst new file mode 100644 index 00000000..ef077d22 --- /dev/null +++ b/docs/source/cpl_discord.application.rst @@ -0,0 +1,12 @@ +cpl\_discord.application +================================ + + + +cpl\_discord.application.discord\_bot\_application\_abc +-------------------------------------------------------------- + +.. automodule:: cpl_discord.application.discord_bot_application_abc + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/cpl_discord.command.rst b/docs/source/cpl_discord.command.rst new file mode 100644 index 00000000..5f495733 --- /dev/null +++ b/docs/source/cpl_discord.command.rst @@ -0,0 +1,20 @@ +cpl\_discord.command +============================ + + + +cpl\_discord.command.discord\_command\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.command.discord_command_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.command.discord\_commands\_meta +--------------------------------------------------- + +.. automodule:: cpl_discord.command.discord_commands_meta + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/cpl_discord.configuration.rst b/docs/source/cpl_discord.configuration.rst new file mode 100644 index 00000000..eb855d14 --- /dev/null +++ b/docs/source/cpl_discord.configuration.rst @@ -0,0 +1,12 @@ +cpl\_discord.configuration +================================== + + + +cpl\_discord.configuration.discord\_bot\_settings +-------------------------------------------------------- + +.. automodule:: cpl_discord.configuration.discord_bot_settings + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/cpl_discord.container.rst b/docs/source/cpl_discord.container.rst new file mode 100644 index 00000000..a47f50b1 --- /dev/null +++ b/docs/source/cpl_discord.container.rst @@ -0,0 +1,68 @@ +cpl\_discord.container +============================== + + + +cpl\_discord.container.category\_channel +----------------------------------------------- + +.. automodule:: cpl_discord.container.category_channel + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.container +--------------------------------------- + +.. automodule:: cpl_discord.container.container + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.guild +----------------------------------- + +.. automodule:: cpl_discord.container.guild + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.member +------------------------------------ + +.. automodule:: cpl_discord.container.member + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.role +---------------------------------- + +.. automodule:: cpl_discord.container.role + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.text\_channel +------------------------------------------- + +.. automodule:: cpl_discord.container.text_channel + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.thread +------------------------------------ + +.. automodule:: cpl_discord.container.thread + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.container.voice\_channel +-------------------------------------------- + +.. automodule:: cpl_discord.container.voice_channel + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/cpl_discord.events.rst b/docs/source/cpl_discord.events.rst new file mode 100644 index 00000000..d26aa744 --- /dev/null +++ b/docs/source/cpl_discord.events.rst @@ -0,0 +1,412 @@ +cpl\_discord.events +=========================== + + + +cpl\_discord.events.on\_bulk\_message\_delete\_abc +--------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_bulk_message_delete_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_command\_abc +------------------------------------------- + +.. automodule:: cpl_discord.events.on_command_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_command\_completion\_abc +------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_command_completion_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_command\_error\_abc +-------------------------------------------------- + +.. automodule:: cpl_discord.events.on_command_error_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_connect\_abc +------------------------------------------- + +.. automodule:: cpl_discord.events.on_connect_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_disconnect\_abc +---------------------------------------------- + +.. automodule:: cpl_discord.events.on_disconnect_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_error\_abc +----------------------------------------- + +.. automodule:: cpl_discord.events.on_error_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_group\_join\_abc +----------------------------------------------- + +.. automodule:: cpl_discord.events.on_group_join_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_group\_remove\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.events.on_group_remove_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_available\_abc +---------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_available_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_channel\_create\_abc +---------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_channel_create_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_channel\_delete\_abc +---------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_channel_delete_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_channel\_pins\_update\_abc +---------------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_channel_pins_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_channel\_update\_abc +---------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_channel_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_emojis\_update\_abc +--------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_emojis_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_integrations\_update\_abc +--------------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_integrations_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_join\_abc +----------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_join_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_remove\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_remove_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_role\_create\_abc +------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_role_create_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_role\_delete\_abc +------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_role_delete_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_role\_update\_abc +------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_role_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_unavailable\_abc +------------------------------------------------------ + +.. automodule:: cpl_discord.events.on_guild_unavailable_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_guild\_update\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.events.on_guild_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_invite\_create\_abc +-------------------------------------------------- + +.. automodule:: cpl_discord.events.on_invite_create_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_invite\_delete\_abc +-------------------------------------------------- + +.. automodule:: cpl_discord.events.on_invite_delete_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_member\_ban\_abc +----------------------------------------------- + +.. automodule:: cpl_discord.events.on_member_ban_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_member\_join\_abc +------------------------------------------------ + +.. automodule:: cpl_discord.events.on_member_join_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_member\_remove\_abc +-------------------------------------------------- + +.. automodule:: cpl_discord.events.on_member_remove_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_member\_unban\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.events.on_member_unban_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_member\_update\_abc +-------------------------------------------------- + +.. automodule:: cpl_discord.events.on_member_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_message\_abc +------------------------------------------- + +.. automodule:: cpl_discord.events.on_message_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_message\_delete\_abc +--------------------------------------------------- + +.. automodule:: cpl_discord.events.on_message_delete_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_message\_edit\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.events.on_message_edit_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_private\_channel\_create\_abc +------------------------------------------------------------ + +.. automodule:: cpl_discord.events.on_private_channel_create_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_private\_channel\_delete\_abc +------------------------------------------------------------ + +.. automodule:: cpl_discord.events.on_private_channel_delete_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_private\_channel\_pins\_update\_abc +------------------------------------------------------------------ + +.. automodule:: cpl_discord.events.on_private_channel_pins_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_private\_channel\_update\_abc +------------------------------------------------------------ + +.. automodule:: cpl_discord.events.on_private_channel_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_raw\_reaction\_add\_abc +------------------------------------------------------ + +.. automodule:: cpl_discord.events.on_raw_reaction_add_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_raw\_reaction\_clear\_abc +-------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_raw_reaction_clear_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_raw\_reaction\_clear\_emoji\_abc +--------------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_raw_reaction_clear_emoji_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_raw\_reaction\_remove\_abc +--------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_raw_reaction_remove_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_reaction\_add\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.events.on_reaction_add_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_reaction\_clear\_abc +--------------------------------------------------- + +.. automodule:: cpl_discord.events.on_reaction_clear_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_reaction\_clear\_emoji\_abc +---------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_reaction_clear_emoji_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_reaction\_remove\_abc +---------------------------------------------------- + +.. automodule:: cpl_discord.events.on_reaction_remove_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_ready\_abc +----------------------------------------- + +.. automodule:: cpl_discord.events.on_ready_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_resume\_abc +------------------------------------------ + +.. automodule:: cpl_discord.events.on_resume_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_typing\_abc +------------------------------------------ + +.. automodule:: cpl_discord.events.on_typing_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_user\_update\_abc +------------------------------------------------ + +.. automodule:: cpl_discord.events.on_user_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_voice\_state\_update\_abc +-------------------------------------------------------- + +.. automodule:: cpl_discord.events.on_voice_state_update_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.events.on\_webhooks\_update\_abc +---------------------------------------------------- + +.. automodule:: cpl_discord.events.on_webhooks_update_abc + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/source/cpl_discord.helper.rst b/docs/source/cpl_discord.helper.rst new file mode 100644 index 00000000..396b4c89 --- /dev/null +++ b/docs/source/cpl_discord.helper.rst @@ -0,0 +1,12 @@ +cpl\_discord.helper +=========================== + + + +cpl\_discord.helper.to\_containers\_converter +---------------------------------------------------- + +.. automodule:: cpl_discord.helper.to_containers_converter + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/cpl_discord.rst b/docs/source/cpl_discord.rst new file mode 100644 index 00000000..5d10fb20 --- /dev/null +++ b/docs/source/cpl_discord.rst @@ -0,0 +1,13 @@ +Discord reference +==================== + +.. toctree:: + :maxdepth: 4 + + cpl_discord.application + cpl_discord.command + cpl_discord.configuration + cpl_discord.container + cpl_discord.events + cpl_discord.helper + cpl_discord.service diff --git a/docs/source/cpl_discord.service.rst b/docs/source/cpl_discord.service.rst new file mode 100644 index 00000000..a6898292 --- /dev/null +++ b/docs/source/cpl_discord.service.rst @@ -0,0 +1,60 @@ +cpl\_discord.service +============================ + + + +cpl\_discord.service.command\_error\_handler\_service +------------------------------------------------------------ + +.. automodule:: cpl_discord.service.command_error_handler_service + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.service.discord\_bot\_service +------------------------------------------------- + +.. automodule:: cpl_discord.service.discord_bot_service + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.service.discord\_bot\_service\_abc +------------------------------------------------------ + +.. automodule:: cpl_discord.service.discord_bot_service_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.service.discord\_collection +----------------------------------------------- + +.. automodule:: cpl_discord.service.discord_collection + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.service.discord\_collection\_abc +---------------------------------------------------- + +.. automodule:: cpl_discord.service.discord_collection_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.service.discord\_service +-------------------------------------------- + +.. automodule:: cpl_discord.service.discord_service + :members: + :undoc-members: + :show-inheritance: + +cpl\_discord.service.discord\_service\_abc +------------------------------------------------- + +.. automodule:: cpl_discord.service.discord_service_abc + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/cpl_query.base.rst b/docs/source/cpl_query.base.rst new file mode 100644 index 00000000..156985e5 --- /dev/null +++ b/docs/source/cpl_query.base.rst @@ -0,0 +1,52 @@ +cpl\_query.base +======================= + + + +cpl\_query.base.default\_lambda +-------------------------------------- + +.. automodule:: cpl_query.base.default_lambda + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.base.ordered\_queryable +----------------------------------------- + +.. automodule:: cpl_query.base.ordered_queryable + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.base.ordered\_queryable\_abc +---------------------------------------------- + +.. automodule:: cpl_query.base.ordered_queryable_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.base.queryable\_abc +------------------------------------- + +.. automodule:: cpl_query.base.queryable_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.base.sequence\_abc +------------------------------------ + +.. automodule:: cpl_query.base.sequence_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.base.sequence\_values +--------------------------------------- + +.. automodule:: cpl_query.base.sequence_values + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/cpl_query.enumerable.rst b/docs/source/cpl_query.enumerable.rst new file mode 100644 index 00000000..37e58add --- /dev/null +++ b/docs/source/cpl_query.enumerable.rst @@ -0,0 +1,20 @@ +cpl\_query.enumerable +============================= + + + +cpl\_query.enumerable.enumerable +--------------------------------------- + +.. automodule:: cpl_query.enumerable.enumerable + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.enumerable.enumerable\_abc +-------------------------------------------- + +.. automodule:: cpl_query.enumerable.enumerable_abc + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/cpl_query.exceptions.rst b/docs/source/cpl_query.exceptions.rst deleted file mode 100644 index d492c637..00000000 --- a/docs/source/cpl_query.exceptions.rst +++ /dev/null @@ -1,10 +0,0 @@ -cpl_query.exceptions -================================= - -cpl_query.exceptions ----------------------------------------------------- - -.. automodule:: cpl_query.exceptions - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/cpl_query.extension.rst b/docs/source/cpl_query.extension.rst index 9dfaa401..a0bba3e0 100644 --- a/docs/source/cpl_query.extension.rst +++ b/docs/source/cpl_query.extension.rst @@ -1,42 +1,12 @@ -cpl_query.extension -================================= +cpl\_query.extension +============================ -cpl_query.extension.iterable_abc ----------------------------------------------------- -.. automodule:: cpl_query.extension.iterable_abc - :members: - :undoc-members: - :show-inheritance: -cpl_query.extension.iterable ----------------------------------------------------- - -.. automodule:: cpl_query.extension.iterable - :members: - :undoc-members: - :show-inheritance: - -cpl_query.extension.list ----------------------------------------------------- +cpl\_query.extension.list +-------------------------------- .. automodule:: cpl_query.extension.list :members: :undoc-members: :show-inheritance: - -cpl_query.extension.ordered_iterable_abc ----------------------------------------------------- - -.. automodule:: cpl_query.extension.ordered_iterable_abc - :members: - :undoc-members: - :show-inheritance: - -cpl_query.extension.ordered_iterable ----------------------------------------------------- - -.. automodule:: cpl_query.extension.ordered_iterable - :members: - :undoc-members: - :show-inheritance: \ No newline at end of file diff --git a/docs/source/cpl_query.iterable.rst b/docs/source/cpl_query.iterable.rst new file mode 100644 index 00000000..8a7bc919 --- /dev/null +++ b/docs/source/cpl_query.iterable.rst @@ -0,0 +1,20 @@ +cpl\_query.iterable +=========================== + + + +cpl\_query.iterable.iterable +----------------------------------- + +.. automodule:: cpl_query.iterable.iterable + :members: + :undoc-members: + :show-inheritance: + +cpl\_query.iterable.iterable\_abc +---------------------------------------- + +.. automodule:: cpl_query.iterable.iterable_abc + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/cpl_query.rst b/docs/source/cpl_query.rst index 10d6f0d8..5a362b26 100644 --- a/docs/source/cpl_query.rst +++ b/docs/source/cpl_query.rst @@ -1,8 +1,10 @@ -Query Reference +Query reference =========== .. toctree:: :maxdepth: 4 - - cpl_query.extension - cpl_query.exceptions + + cpl_query.base + cpl_query.enumerable + cpl_query.extension + cpl_query.iterable diff --git a/docs/source/cpl_translation.rst b/docs/source/cpl_translation.rst new file mode 100644 index 00000000..365356e8 --- /dev/null +++ b/docs/source/cpl_translation.rst @@ -0,0 +1,34 @@ +Translation reference +======================== + +cpl\_translation.translate\_pipe +--------------------------------------- + +.. automodule:: cpl_translation.translate_pipe + :members: + :undoc-members: + :show-inheritance: + +cpl\_translation.translation\_service +-------------------------------------------- + +.. automodule:: cpl_translation.translation_service + :members: + :undoc-members: + :show-inheritance: + +cpl\_translation.translation\_service\_abc +------------------------------------------------- + +.. automodule:: cpl_translation.translation_service_abc + :members: + :undoc-members: + :show-inheritance: + +cpl\_translation.translation\_settings +--------------------------------------------- + +.. automodule:: cpl_translation.translation_settings + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/index.rst b/docs/source/index.rst index 0d0ef798..921b7964 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -89,4 +89,6 @@ These pages go into great detail about everything the Library can do. contributing cpl_cli cpl_core + cpl_discord cpl_query + cpl_translation diff --git a/docs/source/modules.rst b/docs/source/modules.rst index d1ae65e0..5a411fa4 100644 --- a/docs/source/modules.rst +++ b/docs/source/modules.rst @@ -9,4 +9,4 @@ cpl cpl_core cpl_discord cpl_query - cpl_translate + cpl_translation -- 2.45.1 From 4afe5c458194b4d4b04f115b9909813d60ea260d Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 5 Dec 2022 14:12:20 +0100 Subject: [PATCH 25/63] Fixed cpl query for now #134 --- src/cpl_query/__init__.py | 4 +- src/cpl_query/base/__init__.py | 4 +- src/cpl_query/base/queryable_abc.py | 9 ++-- .../base/{sequence_abc.py => sequence.py} | 45 ++++--------------- src/cpl_query/cpl-query.json | 2 +- src/cpl_query/enumerable/__init__.py | 4 +- src/cpl_query/enumerable/enumerable_abc.py | 7 --- src/cpl_query/extension/__init__.py | 4 +- src/cpl_query/iterable/__init__.py | 4 +- src/cpl_query/iterable/iterable_abc.py | 27 +++++------ .../unittests_query/enumerable_test_case.py | 12 ++--- .../unittests_query/unittests_query.json | 4 +- 12 files changed, 45 insertions(+), 81 deletions(-) rename src/cpl_query/base/{sequence_abc.py => sequence.py} (66%) diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 405c7a25..2253a6bb 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev134' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev134') diff --git a/src/cpl_query/base/__init__.py b/src/cpl_query/base/__init__.py index e6923714..f25a4e57 100644 --- a/src/cpl_query/base/__init__.py +++ b/src/cpl_query/base/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev134' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev134') diff --git a/src/cpl_query/base/queryable_abc.py b/src/cpl_query/base/queryable_abc.py index 117397c6..b14f63b2 100644 --- a/src/cpl_query/base/queryable_abc.py +++ b/src/cpl_query/base/queryable_abc.py @@ -1,7 +1,7 @@ from typing import Optional, Callable, Union from cpl_query._helper import is_number -from cpl_query.base.sequence_abc import SequenceABC +from cpl_query.base.sequence import Sequence from cpl_query.exceptions import InvalidTypeException, ArgumentNoneException, ExceptionArgument, IndexOutOfRangeException @@ -9,10 +9,10 @@ def _default_lambda(x: object): return x -class QueryableABC(SequenceABC): +class QueryableABC(Sequence): def __init__(self, t: type = None, values: list = None): - SequenceABC.__init__(self, t, values) + Sequence.__init__(self, t, values) def all(self, _func: Callable = None) -> bool: r"""Checks if every element of list equals result found by function @@ -141,6 +141,9 @@ class QueryableABC(SequenceABC): if _index is None: raise ArgumentNoneException(ExceptionArgument.index) + if _index < 0 or _index >= self.count(): + raise IndexOutOfRangeException + result = self[_index] if result is None: raise IndexOutOfRangeException diff --git a/src/cpl_query/base/sequence_abc.py b/src/cpl_query/base/sequence.py similarity index 66% rename from src/cpl_query/base/sequence_abc.py rename to src/cpl_query/base/sequence.py index b33a8082..ecb6cc5d 100644 --- a/src/cpl_query/base/sequence_abc.py +++ b/src/cpl_query/base/sequence.py @@ -4,13 +4,14 @@ from itertools import islice from cpl_query.base.sequence_values import SequenceValues -class SequenceABC(ABC): +class Sequence(list): @abstractmethod def __init__(self, t: type = None, values: list = None): + list.__init__(self) ABC.__init__(self) - if values is None: - values = [] + values = [] if values is None else values + list.__init__(self, values) if t is None and len(values) > 0: t = type(values[0]) @@ -19,36 +20,11 @@ class SequenceABC(ABC): t = any self._type = t - self._set_values(values) @classmethod def __class_getitem__(cls, _t: type): return _t - def __len__(self): - return len(self._values) - - def __iter__(self): - return iter(self._values) - - def next(self): - return next(self._values) - - def __next__(self): - return self.next() - - def __getitem__(self, n): - values = [x for x in self] - if isinstance(n, slice): - try: - return values[n] - except Exception as e: - raise e - - for i in range(len(values)): - if i == n: - return values[i] - def __repr__(self): return f'<{type(self).__name__} {list(self).__repr__()}>' @@ -63,9 +39,6 @@ class SequenceABC(ABC): if self._type is not None and type(__object) != self._type and not isinstance(type(__object), self._type) and not issubclass(type(__object), self._type): raise Exception(f'Unexpected type: {type(__object)}\nExpected type: {self._type}') - def _set_values(self, values: list): - self._values = SequenceValues(values, self._type) - def to_list(self) -> list: r"""Converts :class: `cpl_query.base.sequence_abc.SequenceABC` to :class: `list` @@ -75,17 +48,17 @@ class SequenceABC(ABC): """ return [x for x in self] - def copy(self) -> 'SequenceABC': + def copy(self) -> 'Sequence': r"""Creates a copy of sequence Returns ------- - SequenceABC + Sequence """ return type(self)(self._type, self.to_list()) @classmethod - def empty(cls) -> 'SequenceABC': + def empty(cls) -> 'Sequence': r"""Returns an empty sequence Returns @@ -94,7 +67,7 @@ class SequenceABC(ABC): """ return cls() - def index(self, _object: object) -> int: + def index_of(self, _object: object) -> int: r"""Returns the index of given element Returns @@ -112,5 +85,5 @@ class SequenceABC(ABC): raise IndexError @classmethod - def range(cls, start: int, length: int) -> 'SequenceABC': + def range(cls, start: int, length: int) -> 'Sequence': return cls(int, list(range(start, length))) diff --git a/src/cpl_query/cpl-query.json b/src/cpl_query/cpl-query.json index b06705f3..c1b48dbb 100644 --- a/src/cpl_query/cpl-query.json +++ b/src/cpl_query/cpl-query.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "0" + "Micro": "dev134" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index 498f2a86..1846b666 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.enumerable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev134' from collections import namedtuple @@ -25,4 +25,4 @@ from .enumerable import Enumerable from .enumerable_abc import EnumerableABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev134') diff --git a/src/cpl_query/enumerable/enumerable_abc.py b/src/cpl_query/enumerable/enumerable_abc.py index b59054d9..c222973d 100644 --- a/src/cpl_query/enumerable/enumerable_abc.py +++ b/src/cpl_query/enumerable/enumerable_abc.py @@ -11,13 +11,6 @@ class EnumerableABC(QueryableABC): def __init__(self, t: type = None, values: list = None): QueryableABC.__init__(self, t, values) - self._remove_error_check = True - - def set_remove_error_check(self, _value: bool): - r"""Set flag to check if element exists before removing - """ - self._remove_error_check = _value - def to_iterable(self) -> 'IterableABC': r"""Converts :class: `cpl_query.enumerable.enumerable_abc.EnumerableABC` to :class: `cpl_query.iterable.iterable_abc.IterableABC` diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index 014d5d95..b1ea2035 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev134' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .list import List VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev134') diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index 2f388931..f7a876f0 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.iterable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev134' from collections import namedtuple @@ -25,4 +25,4 @@ from .iterable_abc import IterableABC from .iterable import Iterable VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev134') diff --git a/src/cpl_query/iterable/iterable_abc.py b/src/cpl_query/iterable/iterable_abc.py index 5758b03c..57e13ae5 100644 --- a/src/cpl_query/iterable/iterable_abc.py +++ b/src/cpl_query/iterable/iterable_abc.py @@ -12,17 +12,6 @@ class IterableABC(QueryableABC): def __init__(self, t: type = None, values: Iterable = None): QueryableABC.__init__(self, t, values) - def __setitem__(self, i, val): - self._check_type(val) - values = [*self._values] - values[i] = val - self._set_values(values) - - def __delitem__(self, i): - values = [*self._values] - del values[i] - self._set_values(values) - @property def type(self) -> type: return self._type @@ -41,8 +30,7 @@ class IterableABC(QueryableABC): value """ self._check_type(_object) - values = [*self._values, _object] - self._set_values(values) + super().append(_object) def extend(self, __iterable: Iterable) -> 'IterableABC': r"""Adds elements of given list to list @@ -66,9 +54,16 @@ class IterableABC(QueryableABC): if _object not in self: raise ValueError - values = [*self._values] - values.remove(_object) - self._set_values(values) + self.remove(_object) + + def remove_at(self, _index: int): + r"""Removes element from list + Parameter + --------- + _object: :class:`object` + value + """ + self.pop(_index) def to_enumerable(self) -> 'EnumerableABC': r"""Converts :class: `cpl_query.iterable.iterable_abc.IterableABC` to :class: `cpl_query.enumerable.enumerable_abc.EnumerableABC` diff --git a/unittests/unittests_query/enumerable_test_case.py b/unittests/unittests_query/enumerable_test_case.py index b8605493..2f7c5a73 100644 --- a/unittests/unittests_query/enumerable_test_case.py +++ b/unittests/unittests_query/enumerable_test_case.py @@ -16,12 +16,12 @@ class EnumerableTestCase(unittest.TestCase): self.assertEqual(Enumerable.empty().to_list(), []) self.assertEqual(Enumerable.range(0, 100).to_list(), list(range(0, 100))) - def test_iter(self): - n = 0 - elements = Enumerable.range(0, 100) - while n < 100: - self.assertEqual(elements.next(), n) - n += 1 + # def test_iter(self): + # n = 0 + # elements = Enumerable.range(0, 100) + # while n < 100: + # self.assertEqual(elements.next(), n) + # n += 1 def test_for(self): n = 0 diff --git a/unittests/unittests_query/unittests_query.json b/unittests/unittests_query/unittests_query.json index 855bab31..78ed0d58 100644 --- a/unittests/unittests_query/unittests_query.json +++ b/unittests/unittests_query/unittests_query.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "0" + "Micro": "dev134" }, "Author": "", "AuthorEmail": "", @@ -17,7 +17,7 @@ "LicenseDescription": "", "Dependencies": [ "cpl-core>=2022.12.0", - "cpl-query>=2022.12.0" + "cpl-query>=2022.12.dev134" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, -- 2.45.1 From d5e5bfe69d7c55a0eef6f0a26a251a62ede0eedb Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 5 Dec 2022 14:15:01 +0100 Subject: [PATCH 26/63] Removed old file #134 --- src/cpl_query/base/sequence.py | 3 -- src/cpl_query/base/sequence_values.py | 47 --------------------------- 2 files changed, 50 deletions(-) delete mode 100644 src/cpl_query/base/sequence_values.py diff --git a/src/cpl_query/base/sequence.py b/src/cpl_query/base/sequence.py index ecb6cc5d..15f7fc4a 100644 --- a/src/cpl_query/base/sequence.py +++ b/src/cpl_query/base/sequence.py @@ -1,7 +1,4 @@ from abc import ABC, abstractmethod -from itertools import islice - -from cpl_query.base.sequence_values import SequenceValues class Sequence(list): diff --git a/src/cpl_query/base/sequence_values.py b/src/cpl_query/base/sequence_values.py deleted file mode 100644 index 6298a685..00000000 --- a/src/cpl_query/base/sequence_values.py +++ /dev/null @@ -1,47 +0,0 @@ -import io -import itertools - -from cpl_query.exceptions import IndexOutOfRangeException - - -class SequenceValues: - def __init__(self, data: list, _t: type): - if len(data) > 0: - def type_check(_t: type, _l: list): - return all([_t == any or isinstance(x, _t) for x in _l]) - - if not type_check(_t, data): - print([type(x) for x in data]) - raise Exception(f'Unexpected type\nExpected type: {_t}') - - if not hasattr(data, '__iter__'): - raise TypeError(f'{type(self).__name__} must be instantiated with an iterable object') - - self._new_cycle = lambda: itertools.cycle(data) - self._len = lambda: len(data) - - self._index = 0 - self._cycle = self._new_cycle() - - def __len__(self): - return self._len() - - def __iter__(self): - i = 0 - while i < self._len(): - yield next(self._cycle) - i += 1 - - def __next__(self): - if self._index >= len(self): - raise IndexOutOfRangeException() - self._index += 1 - - return self.next() - - def next(self): - return next(self._cycle) - - def reset(self): - self._index = 0 - self._cycle = self._new_cycle() -- 2.45.1 From 9840779af40d6640642589cf9ad407ca6c6492e8 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 5 Dec 2022 14:30:33 +0100 Subject: [PATCH 27/63] build new cpl version --- src/cpl_query/__init__.py | 4 ++-- src/cpl_query/base/__init__.py | 4 ++-- src/cpl_query/cpl-query.json | 2 +- src/cpl_query/enumerable/__init__.py | 4 ++-- src/cpl_query/extension/__init__.py | 4 ++-- src/cpl_query/iterable/__init__.py | 4 ++-- tools/set_pip_urls/__init__.py | 4 ++-- tools/set_version/__init__.py | 4 ++-- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 2253a6bb..23786d94 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.dev134' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev134') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_query/base/__init__.py b/src/cpl_query/base/__init__.py index f25a4e57..012cbb4e 100644 --- a/src/cpl_query/base/__init__.py +++ b/src/cpl_query/base/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.dev134' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev134') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_query/cpl-query.json b/src/cpl_query/cpl-query.json index c1b48dbb..61531ad4 100644 --- a/src/cpl_query/cpl-query.json +++ b/src/cpl_query/cpl-query.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "dev134" + "Micro": "1" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index 1846b666..57aceb91 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.enumerable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.dev134' +__version__ = '2022.12.1' from collections import namedtuple @@ -25,4 +25,4 @@ from .enumerable import Enumerable from .enumerable_abc import EnumerableABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev134') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index b1ea2035..6916fb55 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.dev134' +__version__ = '2022.12.1' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .list import List VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev134') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index f7a876f0..3f0db70a 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.iterable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.dev134' +__version__ = '2022.12.1' from collections import namedtuple @@ -25,4 +25,4 @@ from .iterable_abc import IterableABC from .iterable import Iterable VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev134') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/tools/set_pip_urls/__init__.py b/tools/set_pip_urls/__init__.py index 293c4a42..95b27626 100644 --- a/tools/set_pip_urls/__init__.py +++ b/tools/set_pip_urls/__init__.py @@ -15,7 +15,7 @@ __title__ = 'set_pip_urls' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' -__version__ = '2022.6.0' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='6', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/tools/set_version/__init__.py b/tools/set_version/__init__.py index ef7b39f6..3604926a 100644 --- a/tools/set_version/__init__.py +++ b/tools/set_version/__init__.py @@ -15,7 +15,7 @@ __title__ = 'set_version' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' -__version__ = '2022.7.0' +__version__ = '2022.12.0' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='7', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='0') -- 2.45.1 From d6e3b37f7fe8ce78f3844f6ce74907c61ddab743 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 5 Dec 2022 14:37:25 +0100 Subject: [PATCH 28/63] Fixed recursion in cpl --- src/cpl_query/__init__.py | 4 ++-- src/cpl_query/base/__init__.py | 4 ++-- src/cpl_query/cpl-query.json | 2 +- src/cpl_query/enumerable/__init__.py | 4 ++-- src/cpl_query/extension/__init__.py | 4 ++-- src/cpl_query/iterable/__init__.py | 4 ++-- src/cpl_query/iterable/iterable_abc.py | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 23786d94..90568d75 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1' +__version__ = '2022.12.1.post1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1') +version_info = VersionInfo(major='2022', minor='12', micro='1.post1') diff --git a/src/cpl_query/base/__init__.py b/src/cpl_query/base/__init__.py index 012cbb4e..6c298ed1 100644 --- a/src/cpl_query/base/__init__.py +++ b/src/cpl_query/base/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1' +__version__ = '2022.12.1.post1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1') +version_info = VersionInfo(major='2022', minor='12', micro='1.post1') diff --git a/src/cpl_query/cpl-query.json b/src/cpl_query/cpl-query.json index 61531ad4..198b1699 100644 --- a/src/cpl_query/cpl-query.json +++ b/src/cpl_query/cpl-query.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "1" + "Micro": "1.post1" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index 57aceb91..13ad7c57 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.enumerable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1' +__version__ = '2022.12.1.post1' from collections import namedtuple @@ -25,4 +25,4 @@ from .enumerable import Enumerable from .enumerable_abc import EnumerableABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1') +version_info = VersionInfo(major='2022', minor='12', micro='1.post1') diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index 6916fb55..9851b59c 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1' +__version__ = '2022.12.1.post1' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .list import List VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1') +version_info = VersionInfo(major='2022', minor='12', micro='1.post1') diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index 3f0db70a..3855dde6 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.iterable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1' +__version__ = '2022.12.1.post1' from collections import namedtuple @@ -25,4 +25,4 @@ from .iterable_abc import IterableABC from .iterable import Iterable VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1') +version_info = VersionInfo(major='2022', minor='12', micro='1.post1') diff --git a/src/cpl_query/iterable/iterable_abc.py b/src/cpl_query/iterable/iterable_abc.py index 57e13ae5..571a61e1 100644 --- a/src/cpl_query/iterable/iterable_abc.py +++ b/src/cpl_query/iterable/iterable_abc.py @@ -54,7 +54,7 @@ class IterableABC(QueryableABC): if _object not in self: raise ValueError - self.remove(_object) + super().remove(_object) def remove_at(self, _index: int): r"""Removes element from list -- 2.45.1 From d1c93abe2ca8bcc6b42be376eb68bdf8d76749da Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 5 Dec 2022 19:57:27 +0100 Subject: [PATCH 29/63] Improved cpl g templating & added custom templating #137 --- src/cpl_cli/.cpl/__init__.py | 0 src/cpl_cli/.cpl/abc_schematic.py | 30 ++++ src/cpl_cli/.cpl/class_schematic.py | 28 ++++ src/cpl_cli/.cpl/configmodel_schematic.py | 46 ++++++ src/cpl_cli/.cpl/enum_schematic.py | 29 ++++ src/cpl_cli/.cpl/init_schematic.py | 25 ++++ src/cpl_cli/.cpl/pipe_schematic.py | 32 ++++ src/cpl_cli/.cpl/service_schematic.py | 27 ++++ src/cpl_cli/.cpl/test_case_schematic.py | 33 +++++ src/cpl_cli/.cpl/thread_schematic.py | 33 +++++ src/cpl_cli/.cpl/validator_schematic.py | 33 +++++ src/cpl_cli/_templates/generate/__init__.py | 26 ---- .../_templates/generate/abc_template.py | 44 ------ .../_templates/generate/class_template.py | 35 ----- .../generate/configmodel_template.py | 60 -------- .../_templates/generate/enum_template.py | 43 ------ .../_templates/generate/init_template.py | 35 ----- .../_templates/generate/pipe_template.py | 46 ------ .../_templates/generate/service_template.py | 41 ------ .../_templates/generate/test_case_template.py | 47 ------ .../_templates/generate/thread_template.py | 47 ------ .../_templates/generate/validator_template.py | 47 ------ src/cpl_cli/abc/__init__.py | 1 + src/cpl_cli/abc/file_template_abc.py | 28 ++++ src/cpl_cli/abc/generate_schematic_abc.py | 37 +++++ src/cpl_cli/command/generate_service.py | 139 +++++++++++------- .../configuration/schematic_collection.py | 16 ++ src/cpl_cli/startup_argument_extension.py | 20 +-- src/cpl_cli/test_enum.py | 1 + src/cpl_cli/test_init.py | 1 + tests/custom/general/.cpl/custom_schematic.py | 27 ++++ tests/custom/general/test/__init__.py | 1 + tests/custom/general/test/custom.py | 4 + unittests/unittests_cli/generate_test_case.py | 4 +- 34 files changed, 527 insertions(+), 539 deletions(-) create mode 100644 src/cpl_cli/.cpl/__init__.py create mode 100644 src/cpl_cli/.cpl/abc_schematic.py create mode 100644 src/cpl_cli/.cpl/class_schematic.py create mode 100644 src/cpl_cli/.cpl/configmodel_schematic.py create mode 100644 src/cpl_cli/.cpl/enum_schematic.py create mode 100644 src/cpl_cli/.cpl/init_schematic.py create mode 100644 src/cpl_cli/.cpl/pipe_schematic.py create mode 100644 src/cpl_cli/.cpl/service_schematic.py create mode 100644 src/cpl_cli/.cpl/test_case_schematic.py create mode 100644 src/cpl_cli/.cpl/thread_schematic.py create mode 100644 src/cpl_cli/.cpl/validator_schematic.py delete mode 100644 src/cpl_cli/_templates/generate/__init__.py delete mode 100644 src/cpl_cli/_templates/generate/abc_template.py delete mode 100644 src/cpl_cli/_templates/generate/class_template.py delete mode 100644 src/cpl_cli/_templates/generate/configmodel_template.py delete mode 100644 src/cpl_cli/_templates/generate/enum_template.py delete mode 100644 src/cpl_cli/_templates/generate/init_template.py delete mode 100644 src/cpl_cli/_templates/generate/pipe_template.py delete mode 100644 src/cpl_cli/_templates/generate/service_template.py delete mode 100644 src/cpl_cli/_templates/generate/test_case_template.py delete mode 100644 src/cpl_cli/_templates/generate/thread_template.py delete mode 100644 src/cpl_cli/_templates/generate/validator_template.py create mode 100644 src/cpl_cli/abc/__init__.py create mode 100644 src/cpl_cli/abc/file_template_abc.py create mode 100644 src/cpl_cli/abc/generate_schematic_abc.py create mode 100644 src/cpl_cli/configuration/schematic_collection.py create mode 100644 src/cpl_cli/test_enum.py create mode 100644 src/cpl_cli/test_init.py create mode 100644 tests/custom/general/.cpl/custom_schematic.py create mode 100644 tests/custom/general/test/__init__.py create mode 100644 tests/custom/general/test/custom.py diff --git a/src/cpl_cli/.cpl/__init__.py b/src/cpl_cli/.cpl/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_cli/.cpl/abc_schematic.py b/src/cpl_cli/.cpl/abc_schematic.py new file mode 100644 index 00000000..917a60a6 --- /dev/null +++ b/src/cpl_cli/.cpl/abc_schematic.py @@ -0,0 +1,30 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class ABC(GenerateSchematicABC): + + def __init__(self, *args): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + from abc import ABC, abstractmethod + + + class $Name(ABC): + + @abstractmethod + def __init__(self): pass + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'abc', + ['a', 'A'] + ) diff --git a/src/cpl_cli/.cpl/class_schematic.py b/src/cpl_cli/.cpl/class_schematic.py new file mode 100644 index 00000000..f5cdb462 --- /dev/null +++ b/src/cpl_cli/.cpl/class_schematic.py @@ -0,0 +1,28 @@ +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC +from cpl_core.utils import String + + +class Class(GenerateSchematicABC): + + def __init__(self, name: str, path: str, schematic: str): + GenerateSchematicABC.__init__(self, name, path, schematic) + self._name = f'{String.convert_to_snake_case(name)}.py' + self._class_name = f'{String.first_to_upper(name)}' + + def get_code(self) -> str: + code = """\ + class $Name: + + def __init__(self): + pass + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'class', + ['c', 'C'] + ) diff --git a/src/cpl_cli/.cpl/configmodel_schematic.py b/src/cpl_cli/.cpl/configmodel_schematic.py new file mode 100644 index 00000000..e692f1e1 --- /dev/null +++ b/src/cpl_cli/.cpl/configmodel_schematic.py @@ -0,0 +1,46 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class ConfigModel(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + import traceback + + from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC + from cpl_core.console import Console + + + class $Name(ConfigurationModelABC): + + def __init__(self): + ConfigurationModelABC.__init__(self) + + self._atr = '' + + @property + def atr(self) -> str: + return self._atr + + def from_dict(self, settings: dict): + try: + self._atr = settings['atr'] + except Exception as e: + Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings') + Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'settings', + ['st', 'ST'] + ) diff --git a/src/cpl_cli/.cpl/enum_schematic.py b/src/cpl_cli/.cpl/enum_schematic.py new file mode 100644 index 00000000..bd838159 --- /dev/null +++ b/src/cpl_cli/.cpl/enum_schematic.py @@ -0,0 +1,29 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Enum(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + from enum import Enum + + + class $Name(Enum): + + atr = 0 + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'enum', + ['e', 'E'] + ) diff --git a/src/cpl_cli/.cpl/init_schematic.py b/src/cpl_cli/.cpl/init_schematic.py new file mode 100644 index 00000000..f089ac18 --- /dev/null +++ b/src/cpl_cli/.cpl/init_schematic.py @@ -0,0 +1,25 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Init(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + self._name = f'__init__.py' + + def get_code(self) -> str: + code = """\ + # imports + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'init', + [] + ) diff --git a/src/cpl_cli/.cpl/pipe_schematic.py b/src/cpl_cli/.cpl/pipe_schematic.py new file mode 100644 index 00000000..fe7ab972 --- /dev/null +++ b/src/cpl_cli/.cpl/pipe_schematic.py @@ -0,0 +1,32 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Pipe(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + from cpl_core.pipes.pipe_abc import PipeABC + + + class $Name(PipeABC): + + def __init__(self): pass + + def transform(self, value: any, *args): + return value + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'pipe', + ['p', 'P'] + ) diff --git a/src/cpl_cli/.cpl/service_schematic.py b/src/cpl_cli/.cpl/service_schematic.py new file mode 100644 index 00000000..9651f7de --- /dev/null +++ b/src/cpl_cli/.cpl/service_schematic.py @@ -0,0 +1,27 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Service(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + class $Name: + + def __init__(self): + pass + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'service', + ['s', 'S'] + ) diff --git a/src/cpl_cli/.cpl/test_case_schematic.py b/src/cpl_cli/.cpl/test_case_schematic.py new file mode 100644 index 00000000..63ffe56c --- /dev/null +++ b/src/cpl_cli/.cpl/test_case_schematic.py @@ -0,0 +1,33 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class TestCase(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + import unittest + + + class $Name(unittest.TestCase): + + def setUp(self): + pass + + def test_equal(self): + pass + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'test-case', + ['tc', 'TC'] + ) diff --git a/src/cpl_cli/.cpl/thread_schematic.py b/src/cpl_cli/.cpl/thread_schematic.py new file mode 100644 index 00000000..4bb19e98 --- /dev/null +++ b/src/cpl_cli/.cpl/thread_schematic.py @@ -0,0 +1,33 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Thread(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + import threading + + + class $Name(threading.Thread): + + def __init__(self): + threading.Thread.__init__(self) + + def run(self) -> None: + pass + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'thread', + ['t', 'T'] + ) diff --git a/src/cpl_cli/.cpl/validator_schematic.py b/src/cpl_cli/.cpl/validator_schematic.py new file mode 100644 index 00000000..a7a17cb1 --- /dev/null +++ b/src/cpl_cli/.cpl/validator_schematic.py @@ -0,0 +1,33 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Validator(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + from cpl_core.configuration.validator_abc import ValidatorABC + + + class $Name(ValidatorABC): + + def __init__(self): + ValidatorABC.__init__(self) + + def validate(self) -> bool: + return True + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'validator', + ['v', 'V'] + ) diff --git a/src/cpl_cli/_templates/generate/__init__.py b/src/cpl_cli/_templates/generate/__init__.py deleted file mode 100644 index 07d118a6..00000000 --- a/src/cpl_cli/_templates/generate/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.generate' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/generate/abc_template.py b/src/cpl_cli/_templates/generate/abc_template.py deleted file mode 100644 index 3e292182..00000000 --- a/src/cpl_cli/_templates/generate/abc_template.py +++ /dev/null @@ -1,44 +0,0 @@ -import textwrap -from string import Template - -from cpl_core.utils.string import String -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class ABCTemplate(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' - if schematic in name.lower(): - self._name = f'{String.convert_to_snake_case(name)}.py' - - self._class_name = f'{String.first_to_upper(name)}{schematic_upper}' - if schematic in name.lower(): - self._class_name = f'{String.first_to_upper(name)}' - - self._path = path - self._value = textwrap.dedent("""\ - from abc import ABC, abstractmethod - - - class $Name(ABC): - - @abstractmethod - def __init__(self): pass - """) - - @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/generate/class_template.py b/src/cpl_cli/_templates/generate/class_template.py deleted file mode 100644 index 6d01d659..00000000 --- a/src/cpl_cli/_templates/generate/class_template.py +++ /dev/null @@ -1,35 +0,0 @@ -import textwrap -from string import Template - -from cpl_core.utils.string import String -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class ClassTemplate(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)}.py' - self._class_name = f'{String.first_to_upper(name)}' - self._path = path - self._value = textwrap.dedent("""\ - class $Name: - - def __init__(self): - pass - """) - - @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/generate/configmodel_template.py b/src/cpl_cli/_templates/generate/configmodel_template.py deleted file mode 100644 index f4b9ce41..00000000 --- a/src/cpl_cli/_templates/generate/configmodel_template.py +++ /dev/null @@ -1,60 +0,0 @@ -import textwrap -from string import Template - -from cpl_core.utils.string import String -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class ConfigModelTemplate(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' - if schematic in name.lower(): - self._name = f'{String.convert_to_snake_case(name)}.py' - - self._class_name = f'{String.first_to_upper(name)}{schematic_upper}' - if schematic in name.lower(): - self._class_name = f'{String.first_to_upper(name)}' - - self._path = path - self._value = textwrap.dedent("""\ - import traceback - - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC - from cpl_core.console import Console - - - class $Name(ConfigurationModelABC): - - def __init__(self): - ConfigurationModelABC.__init__(self) - - self._atr = '' - - @property - def atr(self) -> str: - return self._atr - - def from_dict(self, settings: dict): - try: - self._atr = settings['atr'] - except Exception as e: - Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings') - Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') - """) - - @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/generate/enum_template.py b/src/cpl_cli/_templates/generate/enum_template.py deleted file mode 100644 index b8c04b49..00000000 --- a/src/cpl_cli/_templates/generate/enum_template.py +++ /dev/null @@ -1,43 +0,0 @@ -import textwrap -from string import Template - -from cpl_core.utils.string import String -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class EnumTemplate(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' - if schematic in name.lower(): - self._name = f'{String.convert_to_snake_case(name)}.py' - - self._class_name = f'{String.first_to_upper(name)}{schematic_upper}' - if schematic in name.lower(): - self._class_name = f'{String.first_to_upper(name)}' - - self._path = path - self._value = textwrap.dedent("""\ - from enum import Enum - - - class $Name(Enum): - - atr = 0 - """) - - @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/generate/init_template.py b/src/cpl_cli/_templates/generate/init_template.py deleted file mode 100644 index 48c2e2da..00000000 --- a/src/cpl_cli/_templates/generate/init_template.py +++ /dev/null @@ -1,35 +0,0 @@ -import textwrap -from string import Template - -from cpl_core.utils.string import String -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class InitTemplate(TemplateFileABC): - - def __init__(self, name: str, schematic: str, schematic_upper: str, path: str): - TemplateFileABC.__init__(self) - - self._name = f'__init__.py' - self._class_name = f'{String.first_to_upper(name)}{schematic_upper}' - if schematic in name.lower(): - self._class_name = f'{String.first_to_upper(name)}' - - self._path = path - self._value = textwrap.dedent("""\ - # imports - """) - - @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/generate/pipe_template.py b/src/cpl_cli/_templates/generate/pipe_template.py deleted file mode 100644 index 6a33035b..00000000 --- a/src/cpl_cli/_templates/generate/pipe_template.py +++ /dev/null @@ -1,46 +0,0 @@ -import textwrap -from string import Template - -from cpl_core.utils.string import String -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class PipeTemplate(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' - if schematic in name.lower(): - self._name = f'{String.convert_to_snake_case(name)}.py' - - self._class_name = f'{String.first_to_upper(name)}{schematic_upper}' - if schematic in name.lower(): - self._class_name = f'{String.first_to_upper(name)}' - - self._path = path - self._value = textwrap.dedent("""\ - from cpl_core.pipes.pipe_abc import PipeABC - - - class $Name(PipeABC): - - def __init__(self): pass - - def transform(self, value: any, *args): - return value - """) - - @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/generate/service_template.py b/src/cpl_cli/_templates/generate/service_template.py deleted file mode 100644 index 24846155..00000000 --- a/src/cpl_cli/_templates/generate/service_template.py +++ /dev/null @@ -1,41 +0,0 @@ -import textwrap -from string import Template - -from cpl_core.utils.string import String -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class ServiceTemplate(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' - if schematic in name.lower(): - self._name = f'{String.convert_to_snake_case(name)}.py' - - self._class_name = f'{String.first_to_upper(name)}{schematic_upper}' - if schematic in name.lower(): - self._class_name = f'{String.first_to_upper(name)}' - - self._path = path - self._value = textwrap.dedent("""\ - class $Name: - - def __init__(self): - pass - """) - - @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/generate/test_case_template.py b/src/cpl_cli/_templates/generate/test_case_template.py deleted file mode 100644 index 5888bb5c..00000000 --- a/src/cpl_cli/_templates/generate/test_case_template.py +++ /dev/null @@ -1,47 +0,0 @@ -import textwrap -from string import Template - -from cpl_core.utils.string import String -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class TestCaseTemplate(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' - if schematic in name.lower(): - self._name = f'{String.convert_to_snake_case(name)}.py' - - self._class_name = f'{String.first_to_upper(name)}{schematic_upper}' - if schematic in name.lower(): - self._class_name = f'{String.first_to_upper(name)}' - - self._path = path - self._value = textwrap.dedent("""\ - import unittest - - - class $Name(unittest.TestCase): - - def setUp(self): - pass - - def test_equal(self): - pass - """) - - @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/generate/thread_template.py b/src/cpl_cli/_templates/generate/thread_template.py deleted file mode 100644 index 4609d678..00000000 --- a/src/cpl_cli/_templates/generate/thread_template.py +++ /dev/null @@ -1,47 +0,0 @@ -import textwrap -from string import Template - -from cpl_core.utils.string import String -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class ThreadTemplate(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' - if schematic in name.lower(): - self._name = f'{String.convert_to_snake_case(name)}.py' - - self._class_name = f'{String.first_to_upper(name)}{schematic_upper}' - if schematic in name.lower(): - self._class_name = f'{String.first_to_upper(name)}' - - self._path = path - self._value = textwrap.dedent("""\ - import threading - - - class $Name(threading.Thread): - - def __init__(self): - threading.Thread.__init__(self) - - def run(self) -> None: - pass - """) - - @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/generate/validator_template.py b/src/cpl_cli/_templates/generate/validator_template.py deleted file mode 100644 index 683cea5e..00000000 --- a/src/cpl_cli/_templates/generate/validator_template.py +++ /dev/null @@ -1,47 +0,0 @@ -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' - if schematic in name.lower(): - self._name = f'{String.convert_to_snake_case(name)}.py' - - self._class_name = f'{String.first_to_upper(name)}{schematic_upper}' - if schematic in name.lower(): - self._class_name = f'{String.first_to_upper(name)}' - - 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/abc/__init__.py b/src/cpl_cli/abc/__init__.py new file mode 100644 index 00000000..425ab6c1 --- /dev/null +++ b/src/cpl_cli/abc/__init__.py @@ -0,0 +1 @@ +# imports diff --git a/src/cpl_cli/abc/file_template_abc.py b/src/cpl_cli/abc/file_template_abc.py new file mode 100644 index 00000000..09e39f23 --- /dev/null +++ b/src/cpl_cli/abc/file_template_abc.py @@ -0,0 +1,28 @@ +from abc import ABC, abstractmethod + +from cpl_core.utils import String + + +class FileTemplateABC(ABC): + + @abstractmethod + def __init__(self, name: str, path: str, code: str): + self._name = f'{String.convert_to_snake_case(name)}.py' + self._path = path + self._code = code + + @property + def name(self) -> str: + return self._name + + @property + def path(self) -> str: + return self._path + + @property + def value(self) -> str: + return self.get_code() + + @abstractmethod + def get_code(self) -> str: + return self._code diff --git a/src/cpl_cli/abc/generate_schematic_abc.py b/src/cpl_cli/abc/generate_schematic_abc.py new file mode 100644 index 00000000..7254e176 --- /dev/null +++ b/src/cpl_cli/abc/generate_schematic_abc.py @@ -0,0 +1,37 @@ +import textwrap +from abc import abstractmethod +from string import Template + +from cpl_cli.abc.file_template_abc import FileTemplateABC +from cpl_cli.configuration.schematic_collection import SchematicCollection +from cpl_core.utils import String + + +class GenerateSchematicABC(FileTemplateABC): + + def __init__(self, name: str, schematic: str, path: str): + FileTemplateABC.__init__(self, name, path, '') + self._name = f'{String.convert_to_snake_case(name)}_{schematic}.py' + if schematic in name.lower(): + self._name = f'{String.convert_to_snake_case(name)}.py' + + self._class_name = f'{String.first_to_upper(name)}{String.first_to_upper(schematic)}' + if schematic in name.lower(): + self._class_name = f'{String.first_to_upper(name)}' + + @property + def class_name(self) -> str: + return self._class_name + + @abstractmethod + def get_code(self) -> str: pass + + @classmethod + def build_code_str(cls, code: str, **kwargs) -> str: + text = textwrap.dedent(code) + return Template(text).substitute(**kwargs) + + @classmethod + @abstractmethod + def register(cls, *args): + SchematicCollection.register(*args) diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index 12236c83..41783b66 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -2,19 +2,10 @@ import os import sys import textwrap -from cpl_cli._templates.generate.abc_template import ABCTemplate -from cpl_cli._templates.generate.class_template import ClassTemplate -from cpl_cli._templates.generate.configmodel_template import ConfigModelTemplate -from cpl_cli._templates.generate.enum_template import EnumTemplate -from cpl_cli._templates.generate.init_template import InitTemplate -from cpl_cli._templates.generate.pipe_template import PipeTemplate -from cpl_cli._templates.generate.service_template import ServiceTemplate -from cpl_cli._templates.generate.test_case_template import TestCaseTemplate -from cpl_cli._templates.generate.thread_template import ThreadTemplate -from cpl_cli._templates.generate.validator_template import ValidatorTemplate -from cpl_cli._templates.template_file_abc import TemplateFileABC +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC from cpl_cli.command_abc import CommandABC from cpl_cli.configuration import WorkspaceSettings +from cpl_cli.configuration.schematic_collection import SchematicCollection from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.console.console import Console from cpl_core.console.foreground_color_enum import ForegroundColorEnum @@ -37,44 +28,44 @@ class GenerateService(CommandABC): self._config = configuration self._workspace = workspace - self._schematics = { - "abc": { - "Upper": "ABC", - "Template": ABCTemplate - }, - "class": { - "Upper": "Class", - "Template": ClassTemplate - }, - "enum": { - "Upper": "Enum", - "Template": EnumTemplate - }, - "pipe": { - "Upper": "Pipe", - "Template": PipeTemplate - }, - "service": { - "Upper": "Service", - "Template": ServiceTemplate - }, - "settings": { - "Upper": "Settings", - "Template": ConfigModelTemplate - }, - "test_case": { - "Upper": "TestCase", - "Template": TestCaseTemplate - }, - "thread": { - "Upper": "Thread", - "Template": ThreadTemplate - }, - "validator": { - "Upper": "Validator", - "Template": ValidatorTemplate - } - } + self._schematics = {} + # "abc": { + # "Upper": "ABC", + # "Template": ABCTemplate + # }, + # "class": { + # "Upper": "Class", + # "Template": ClassTemplate + # }, + # "enum": { + # "Upper": "Enum", + # "Template": EnumTemplate + # }, + # "pipe": { + # "Upper": "Pipe", + # "Template": PipeTemplate + # }, + # "service": { + # "Upper": "Service", + # "Template": ServiceTemplate + # }, + # "settings": { + # "Upper": "Settings", + # "Template": ConfigModelTemplate + # }, + # "test_case": { + # "Upper": "TestCase", + # "Template": TestCaseTemplate + # }, + # "thread": { + # "Upper": "Thread", + # "Template": ThreadTemplate + # }, + # "validator": { + # "Upper": "Validator", + # "Template": ValidatorTemplate + # } + # } self._config = configuration self._env = self._config.environment @@ -137,7 +128,7 @@ class GenerateService(CommandABC): template.write(value) template.close() - def _create_init_files(self, file_path: str, template: TemplateFileABC, class_name: str, schematic: str, rel_path: str): + def _create_init_files(self, file_path: str, template: GenerateSchematicABC, class_name: str, schematic: str, rel_path: str): if not os.path.isdir(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) directory = '' @@ -146,7 +137,7 @@ class GenerateService(CommandABC): if subdir == 'src': continue - file = InitTemplate(class_name, schematic, self._schematics[schematic]["Upper"], rel_path) + file = self._schematics['init']['Template'](class_name, 'init', rel_path) if os.path.exists(os.path.join(os.path.abspath(directory), file.name)): continue @@ -154,12 +145,12 @@ class GenerateService(CommandABC): f'Creating {os.path.abspath(directory)}/{file.name}', self._create_file, os.path.join(os.path.abspath(directory), file.name), - file.value, + file.get_code(), text_foreground_color=ForegroundColorEnum.green, spinner_foreground_color=ForegroundColorEnum.cyan ) - def _generate(self, schematic: str, name: str, template: TemplateFileABC): + def _generate(self, schematic: str, name: str, template: type): """ Generates files by given schematic, name and template :param schematic: @@ -175,9 +166,9 @@ class GenerateService(CommandABC): class_name = parts[len(parts) - 1] if self._workspace is not None and parts[0] in self._workspace.projects: - rel_path = os.path.dirname(self._workspace.projects[parts[0]]) + rel_path = os.path.join(os.path.dirname(self._workspace.projects[parts[0]]), *parts[1:-1]) - template = template(class_name, schematic, self._schematics[schematic]["Upper"], rel_path) + template = template(class_name, String.convert_to_snake_case(schematic), rel_path) file_path = os.path.join(self._env.working_directory, template.path, template.name) self._create_init_files(file_path, template, class_name, schematic, rel_path) @@ -194,17 +185,47 @@ class GenerateService(CommandABC): message, self._create_file, file_path, - template.value, + template.get_code(), text_foreground_color=ForegroundColorEnum.green, spinner_foreground_color=ForegroundColorEnum.cyan ) + @staticmethod + def _read_custom_schematics_from_path(path: str): + if not os.path.exists(os.path.join(path, '.cpl')): + return + + for r, d, f in os.walk(os.path.join(path, '.cpl')): + for file in f: + if not file.endswith('_schematic.py'): + continue + + code = '' + with open(os.path.join(r, file), 'r') as py_file: + code = py_file.read() + py_file.close() + + exec(code) + + def _get_schematic_by_alias(self, schematic: str) -> str: + for key in self._schematics: + if schematic in self._schematics[key]['Aliases']: + return key + + return schematic + def execute(self, args: list[str]): """ Entry point of command :param args: :return: """ + self._read_custom_schematics_from_path(self._env.runtime_directory) + self._read_custom_schematics_from_path(self._env.working_directory) + for schematic in GenerateSchematicABC.__subclasses__(): + schematic.register() + self._schematics = SchematicCollection.get_schematics() + schematic = None value = None for s in self._schematics: @@ -213,6 +234,12 @@ class GenerateService(CommandABC): schematic = s break + schematic_by_alias = self._get_schematic_by_alias(args[0]) + if schematic is None and len(args) >= 1 and (args[0] in self._schematics or schematic_by_alias != args[0]): + schematic = schematic_by_alias + self._config.add_configuration(schematic, args[1]) + value = args[1] + if schematic is None: self._help('Usage: cpl generate [options]') Console.write_line() diff --git a/src/cpl_cli/configuration/schematic_collection.py b/src/cpl_cli/configuration/schematic_collection.py new file mode 100644 index 00000000..a3469077 --- /dev/null +++ b/src/cpl_cli/configuration/schematic_collection.py @@ -0,0 +1,16 @@ +from cpl_core.utils import String + + +class SchematicCollection: + _schematics: dict = {} + + @classmethod + def register(cls, template: type, schematic: str, aliases: list[str]): + cls._schematics[schematic] = { + "Template": template, + "Aliases": aliases + } + + @classmethod + def get_schematics(cls) -> dict: + return cls._schematics diff --git a/src/cpl_cli/startup_argument_extension.py b/src/cpl_cli/startup_argument_extension.py index 16bd5449..008f47f3 100644 --- a/src/cpl_cli/startup_argument_extension.py +++ b/src/cpl_cli/startup_argument_extension.py @@ -29,16 +29,16 @@ class StartupArgumentExtension(StartupExtensionABC): config.create_console_argument(ArgumentTypeEnum.Executable, '', 'add', ['a', 'A'], AddService, True, validators=[WorkspaceValidator]) \ .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, '', 'pipe', ['p', 'P'], ' ') \ - .add_console_argument(ArgumentTypeEnum.Variable, '', 'service', ['s', 'S'], ' ') \ - .add_console_argument(ArgumentTypeEnum.Variable, '', 'settings', ['st', 'ST'], ' ') \ - .add_console_argument(ArgumentTypeEnum.Variable, '', 'test_case', ['tc', 'TC'], ' ') \ - .add_console_argument(ArgumentTypeEnum.Variable, '', 'thread', ['t', 'T'], ' ') \ - .add_console_argument(ArgumentTypeEnum.Variable, '', 'validator', ['v', 'V'], ' ') + 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, '', 'pipe', ['p', 'P'], ' ') \ + # .add_console_argument(ArgumentTypeEnum.Variable, '', 'service', ['s', 'S'], ' ') \ + # .add_console_argument(ArgumentTypeEnum.Variable, '', 'settings', ['st', 'ST'], ' ') \ + # .add_console_argument(ArgumentTypeEnum.Variable, '', 'test_case', ['tc', 'TC'], ' ') \ + # .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, validators=[ProjectValidator]) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D']) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \ diff --git a/src/cpl_cli/test_enum.py b/src/cpl_cli/test_enum.py new file mode 100644 index 00000000..425ab6c1 --- /dev/null +++ b/src/cpl_cli/test_enum.py @@ -0,0 +1 @@ +# imports diff --git a/src/cpl_cli/test_init.py b/src/cpl_cli/test_init.py new file mode 100644 index 00000000..425ab6c1 --- /dev/null +++ b/src/cpl_cli/test_init.py @@ -0,0 +1 @@ +# imports diff --git a/tests/custom/general/.cpl/custom_schematic.py b/tests/custom/general/.cpl/custom_schematic.py new file mode 100644 index 00000000..dd951a69 --- /dev/null +++ b/tests/custom/general/.cpl/custom_schematic.py @@ -0,0 +1,27 @@ + + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Custom(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + class $Name: + + def __init__(self): + print('hello') + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'custom', + ['cm', 'CM'] + ) diff --git a/tests/custom/general/test/__init__.py b/tests/custom/general/test/__init__.py new file mode 100644 index 00000000..425ab6c1 --- /dev/null +++ b/tests/custom/general/test/__init__.py @@ -0,0 +1 @@ +# imports diff --git a/tests/custom/general/test/custom.py b/tests/custom/general/test/custom.py new file mode 100644 index 00000000..16baa336 --- /dev/null +++ b/tests/custom/general/test/custom.py @@ -0,0 +1,4 @@ +class Custom: + + def __init__(self): + print('hello') diff --git a/unittests/unittests_cli/generate_test_case.py b/unittests/unittests_cli/generate_test_case.py index cba7d8a7..16bb382b 100644 --- a/unittests/unittests_cli/generate_test_case.py +++ b/unittests/unittests_cli/generate_test_case.py @@ -78,8 +78,8 @@ class GenerateTestCase(CommandTestCase): self._test_file_with_project('settings', '_settings', path=self._project) def test_test_case(self): - self._test_file('test_case', '_test_case') - self._test_file_with_project('test_case', '_test_case', path=self._project) + self._test_file('test-case', '_test_case') + self._test_file_with_project('test-case', '_test_case', path=self._project) def test_thread(self): self._test_file('thread', '_thread') -- 2.45.1 From f6cc3a7ddf2d25f0aa739e176a84dc08e56a2e80 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 5 Dec 2022 20:00:32 +0100 Subject: [PATCH 30/63] Removed cpl g arguments #137 --- src/cpl_cli/startup_argument_extension.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/cpl_cli/startup_argument_extension.py b/src/cpl_cli/startup_argument_extension.py index 008f47f3..835a9b67 100644 --- a/src/cpl_cli/startup_argument_extension.py +++ b/src/cpl_cli/startup_argument_extension.py @@ -29,16 +29,7 @@ class StartupArgumentExtension(StartupExtensionABC): config.create_console_argument(ArgumentTypeEnum.Executable, '', 'add', ['a', 'A'], AddService, True, validators=[WorkspaceValidator]) \ .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, '', 'pipe', ['p', 'P'], ' ') \ - # .add_console_argument(ArgumentTypeEnum.Variable, '', 'service', ['s', 'S'], ' ') \ - # .add_console_argument(ArgumentTypeEnum.Variable, '', 'settings', ['st', 'ST'], ' ') \ - # .add_console_argument(ArgumentTypeEnum.Variable, '', 'test_case', ['tc', 'TC'], ' ') \ - # .add_console_argument(ArgumentTypeEnum.Variable, '', 'thread', ['t', 'T'], ' ') \ - # .add_console_argument(ArgumentTypeEnum.Variable, '', 'validator', ['v', 'V'], ' ') + config.create_console_argument(ArgumentTypeEnum.Executable, '', 'generate', ['g', 'G'], GenerateService, True) config.create_console_argument(ArgumentTypeEnum.Executable, '', 'install', ['i', 'I'], InstallService, True, validators=[ProjectValidator]) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D']) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \ -- 2.45.1 From b63bf41294115b9b8ead24d2540b9849c441f590 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 5 Dec 2022 20:24:15 +0100 Subject: [PATCH 31/63] Fixed cpl help #137 --- src/cpl_cli/command/generate_service.py | 105 ++++-------------- src/cpl_cli/command/new_service.py | 27 +---- .../configuration/argument_executable_abc.py | 2 +- src/cpl_core/configuration/configuration.py | 2 +- 4 files changed, 30 insertions(+), 106 deletions(-) diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index 41783b66..975770d7 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -28,51 +28,28 @@ class GenerateService(CommandABC): self._config = configuration self._workspace = workspace - self._schematics = {} - # "abc": { - # "Upper": "ABC", - # "Template": ABCTemplate - # }, - # "class": { - # "Upper": "Class", - # "Template": ClassTemplate - # }, - # "enum": { - # "Upper": "Enum", - # "Template": EnumTemplate - # }, - # "pipe": { - # "Upper": "Pipe", - # "Template": PipeTemplate - # }, - # "service": { - # "Upper": "Service", - # "Template": ServiceTemplate - # }, - # "settings": { - # "Upper": "Settings", - # "Template": ConfigModelTemplate - # }, - # "test_case": { - # "Upper": "TestCase", - # "Template": TestCaseTemplate - # }, - # "thread": { - # "Upper": "Thread", - # "Template": ThreadTemplate - # }, - # "validator": { - # "Upper": "Validator", - # "Template": ValidatorTemplate - # } - # } - self._config = configuration self._env = self._config.environment + self._schematics = {} + + self._read_custom_schematics_from_path(self._env.runtime_directory) + self._read_custom_schematics_from_path(self._env.working_directory) + for schematic in GenerateSchematicABC.__subclasses__(): + schematic.register() + + self._schematics = SchematicCollection.get_schematics() @property def help_message(self) -> str: - return textwrap.dedent("""\ + schematics = [] + for schematic in self._schematics: + aliases = '|'.join(self._schematics[schematic]['Aliases']) + schematic_str = schematic + if len(aliases) > 0: + schematic_str = f'{schematic} ({aliases})' + + schematics.append(schematic_str) + help_msg = textwrap.dedent("""\ Generate a file based on schematic. Usage: cpl generate @@ -80,41 +57,11 @@ class GenerateService(CommandABC): schematic: The schematic to generate. name: The name of the generated file - Schematics: - abc - class - enum - pipe - service - settings - test_case - thread - validator - """) + Schematics:""") - @staticmethod - def _help(message: str): - """ - Internal help output - :param message: - :return: - """ - Console.error(message) - - schematics = [ - 'abc (a|A)', - 'class (c|C)', - 'enum (e|E)', - 'pipe (p|P)', - 'service (s|S)', - 'settings (st|ST)', - 'test-case (tc|TC)', - 'thread (t|T)', - 'validator (v|V)' - ] - Console.write_line('Available Schematics:') - for name in schematics: - Console.write(f'\n\t{name} ') + for schematic in schematics: + help_msg += f'\n {schematic}' + return help_msg @staticmethod def _create_file(file_path: str, value: str): @@ -220,12 +167,6 @@ class GenerateService(CommandABC): :param args: :return: """ - self._read_custom_schematics_from_path(self._env.runtime_directory) - self._read_custom_schematics_from_path(self._env.working_directory) - for schematic in GenerateSchematicABC.__subclasses__(): - schematic.register() - self._schematics = SchematicCollection.get_schematics() - schematic = None value = None for s in self._schematics: @@ -241,8 +182,8 @@ class GenerateService(CommandABC): value = args[1] if schematic is None: - self._help('Usage: cpl generate [options]') - Console.write_line() + Console.error(f'Schematic not found') + Console.write_line(self.help_message) sys.exit() name = value diff --git a/src/cpl_cli/command/new_service.py b/src/cpl_cli/command/new_service.py index 9740a324..5715f5cd 100644 --- a/src/cpl_cli/command/new_service.py +++ b/src/cpl_cli/command/new_service.py @@ -67,29 +67,11 @@ class NewService(CommandABC): name Name of the workspace or the project Types: - console - library - unittest + console (c|C) + library (l|L) + unittest (ut|UT) """) - @staticmethod - def _help(message: str): - """ - Internal help output - :param message: - :return: - """ - Console.error(message) - - schematics = [ - 'console (c|C) ', - 'library (l|L) ', - 'unittest (ut|UT) ', - ] - Console.write_line('Available Schematics:') - for name in schematics: - Console.write(f'\n\t{name} ') - def _create_project_settings(self): self._rel_path = os.path.dirname(self._name) self._project_dict = { @@ -369,5 +351,6 @@ class NewService(CommandABC): self._create_venv() else: - self._help('Usage: cpl new [options]') + Console.error(f'Project type not found') + Console.write_line(self.help_message) return diff --git a/src/cpl_core/configuration/argument_executable_abc.py b/src/cpl_core/configuration/argument_executable_abc.py index 8263b338..d7f3319a 100644 --- a/src/cpl_core/configuration/argument_executable_abc.py +++ b/src/cpl_core/configuration/argument_executable_abc.py @@ -7,4 +7,4 @@ class ArgumentExecutableABC(ABC): def __init__(self): pass @abstractmethod - def execute(self, args: list[str]): pass + def run(self, args: list[str]): pass diff --git a/src/cpl_core/configuration/configuration.py b/src/cpl_core/configuration/configuration.py index dbe2574f..f2b8dd5c 100644 --- a/src/cpl_core/configuration/configuration.py +++ b/src/cpl_core/configuration/configuration.py @@ -341,7 +341,7 @@ class Configuration(ConfigurationABC): continue self._additional_arguments.append(arg) - cmd.execute(self._additional_arguments) + cmd.run(self._additional_arguments) self._handle_pre_or_post_executables(False, exe, services) prevent = exe.prevent_next_executable success = True -- 2.45.1 From 5f10603fe5c36482e2dd544fe4d77c121f7c2b17 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 5 Dec 2022 23:08:52 +0100 Subject: [PATCH 32/63] [WIP] Improved cpl new templating #139 --- src/cpl_cli/.cpl/project_console.py | 42 +++ src/cpl_cli/.cpl/project_file_appsettings.py | 29 ++ .../.cpl/project_file_code_application.py | 49 +++ src/cpl_cli/.cpl/project_file_code_main.py | 93 +++++ src/cpl_cli/.cpl/project_file_code_startup.py | 29 ++ src/cpl_cli/.cpl/project_file_license.py | 11 + src/cpl_cli/.cpl/project_file_readme.py | 11 + .../{abc_schematic.py => schematic_abc.py} | 0 ...{class_schematic.py => schematic_class.py} | 0 ..._schematic.py => schematic_configmodel.py} | 0 .../{enum_schematic.py => schematic_enum.py} | 0 .../{init_schematic.py => schematic_init.py} | 0 .../{pipe_schematic.py => schematic_pipe.py} | 0 ...vice_schematic.py => schematic_service.py} | 0 ...se_schematic.py => schematic_test_case.py} | 0 ...hread_schematic.py => schematic_thread.py} | 0 ...or_schematic.py => schematic_validator.py} | 0 src/cpl_cli/abc/code_file_template_abc.py | 24 ++ src/cpl_cli/abc/file_template_abc.py | 10 +- src/cpl_cli/abc/generate_schematic_abc.py | 8 +- src/cpl_cli/abc/project_type_abc.py | 35 ++ src/cpl_cli/command/generate_service.py | 2 +- src/cpl_cli/command/new_old_service.py | 356 ++++++++++++++++++ src/cpl_cli/command/new_service.py | 94 ++++- .../source_creator/template_builder.py | 45 ++- ...ustom_schematic.py => schematic_custom.py} | 0 26 files changed, 822 insertions(+), 16 deletions(-) create mode 100644 src/cpl_cli/.cpl/project_console.py create mode 100644 src/cpl_cli/.cpl/project_file_appsettings.py create mode 100644 src/cpl_cli/.cpl/project_file_code_application.py create mode 100644 src/cpl_cli/.cpl/project_file_code_main.py create mode 100644 src/cpl_cli/.cpl/project_file_code_startup.py create mode 100644 src/cpl_cli/.cpl/project_file_license.py create mode 100644 src/cpl_cli/.cpl/project_file_readme.py rename src/cpl_cli/.cpl/{abc_schematic.py => schematic_abc.py} (100%) rename src/cpl_cli/.cpl/{class_schematic.py => schematic_class.py} (100%) rename src/cpl_cli/.cpl/{configmodel_schematic.py => schematic_configmodel.py} (100%) rename src/cpl_cli/.cpl/{enum_schematic.py => schematic_enum.py} (100%) rename src/cpl_cli/.cpl/{init_schematic.py => schematic_init.py} (100%) rename src/cpl_cli/.cpl/{pipe_schematic.py => schematic_pipe.py} (100%) rename src/cpl_cli/.cpl/{service_schematic.py => schematic_service.py} (100%) rename src/cpl_cli/.cpl/{test_case_schematic.py => schematic_test_case.py} (100%) rename src/cpl_cli/.cpl/{thread_schematic.py => schematic_thread.py} (100%) rename src/cpl_cli/.cpl/{validator_schematic.py => schematic_validator.py} (100%) create mode 100644 src/cpl_cli/abc/code_file_template_abc.py create mode 100644 src/cpl_cli/abc/project_type_abc.py create mode 100644 src/cpl_cli/command/new_old_service.py rename tests/custom/general/.cpl/{custom_schematic.py => schematic_custom.py} (100%) diff --git a/src/cpl_cli/.cpl/project_console.py b/src/cpl_cli/.cpl/project_console.py new file mode 100644 index 00000000..7028172d --- /dev/null +++ b/src/cpl_cli/.cpl/project_console.py @@ -0,0 +1,42 @@ +import os + +from cpl_cli.abc.project_type_abc import ProjectTypeABC +from cpl_cli.configuration import WorkspaceSettings +from cpl_core.utils import String + + +class Console(ProjectTypeABC): + + def __init__( + self, + base_path: str, + project_name: str, + workspace: WorkspaceSettings, + use_application_api: bool, + use_startup: bool, + use_service_providing: bool, + use_async: bool, + ): + from project_file_license import ProjectFileLicense + from project_file_readme import ProjectFileReadme + from schematic_init import Init + from project_file_code_application import ProjectFileApplication + from project_file_code_main import ProjectFileMain + from project_file_code_startup import ProjectFileStartup + + ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async) + + project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/' + + self.add_template(ProjectFileLicense('')) + self.add_template(ProjectFileReadme('')) + self.add_template(Init('', 'init', f'{base_path}tests/')) + self.add_template(Init('', 'init', project_path)) + + if use_application_api: + self.add_template(ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async)) + + if use_startup: + self.add_template(ProjectFileStartup(project_path, use_application_api, use_startup, use_service_providing, use_async)) + + self.add_template(ProjectFileMain(project_path, use_application_api, use_startup, use_service_providing, use_async)) diff --git a/src/cpl_cli/.cpl/project_file_appsettings.py b/src/cpl_cli/.cpl/project_file_appsettings.py new file mode 100644 index 00000000..e7b0e3ec --- /dev/null +++ b/src/cpl_cli/.cpl/project_file_appsettings.py @@ -0,0 +1,29 @@ +import textwrap + +from cpl_cli.abc.file_template_abc import FileTemplateABC + + +class ProjectFileAppsettings(FileTemplateABC): + + def __init__(self, path: str): + code = textwrap.dedent("""\ + { + "TimeFormatSettings": { + "DateFormat": "%Y-%m-%d", + "TimeFormat": "%H:%M:%S", + "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", + "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" + }, + + "LoggingSettings": { + "Path": "logs/", + "Filename": "log_$start_time.log", + "ConsoleLogLevel": "ERROR", + "FileLogLevel": "WARN" + } + } + """) + FileTemplateABC.__init__(self, 'appsettings.json', path, code) + + def get_code(self) -> str: + return self._code diff --git a/src/cpl_cli/.cpl/project_file_code_application.py b/src/cpl_cli/.cpl/project_file_code_application.py new file mode 100644 index 00000000..59bc447a --- /dev/null +++ b/src/cpl_cli/.cpl/project_file_code_application.py @@ -0,0 +1,49 @@ +from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC + + +class ProjectFileApplication(CodeFileTemplateABC): + + def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool): + CodeFileTemplateABC.__init__(self, 'application', path, '', use_application_api, use_startup, use_service_providing, use_async) + + def get_code(self) -> str: + import textwrap + + if self._use_async: + return textwrap.dedent("""\ + from cpl_core.application import ApplicationABC + from cpl_core.configuration import ConfigurationABC + from cpl_core.console import Console + from cpl_core.dependency_injection import ServiceProviderABC + + + class Application(ApplicationABC): + + def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): + ApplicationABC.__init__(self, config, services) + + async def configure(self): + pass + + async def main(self): + Console.write_line('Hello World') + """) + + return textwrap.dedent("""\ + from cpl_core.application import ApplicationABC + from cpl_core.configuration import ConfigurationABC + from cpl_core.console import Console + from cpl_core.dependency_injection import ServiceProviderABC + + + class Application(ApplicationABC): + + def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): + ApplicationABC.__init__(self, config, services) + + def configure(self): + pass + + def main(self): + Console.write_line('Hello World') + """) diff --git a/src/cpl_cli/.cpl/project_file_code_main.py b/src/cpl_cli/.cpl/project_file_code_main.py new file mode 100644 index 00000000..43b5988f --- /dev/null +++ b/src/cpl_cli/.cpl/project_file_code_main.py @@ -0,0 +1,93 @@ +from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC + + +class ProjectFileMain(CodeFileTemplateABC): + + def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool): + CodeFileTemplateABC.__init__(self, 'main', path, '', use_application_api, use_startup, use_service_providing, use_async) + + import textwrap + + import_pkg = f'{self._name}.' + + self._main_with_application_host_and_startup = textwrap.dedent(f"""\ + {"import asyncio" if self._use_async else ''} + + from cpl_core.application import ApplicationBuilder + + from {import_pkg}application import Application + from {import_pkg}startup import Startup + + + {self._async()}def main(): + app_builder = ApplicationBuilder(Application) + app_builder.use_startup(Startup) + {"app: Application = await app_builder.build_async()" if self._use_async else ""} + {"await app.run_async()" if self._use_async else "app_builder.build().run()"} + + + if __name__ == '__main__': + {"asyncio.run(main())" if self._use_async else "main()"} + """) + self._main_with_application_base = textwrap.dedent(f"""\ + {"import asyncio" if self._use_async else ''} + + from cpl_core.application import ApplicationBuilder + + from {import_pkg}application import Application + + + {self._async()}def main(): + app_builder = ApplicationBuilder(Application) + {"app: Application = await app_builder.build_async()" if self._use_async else ""} + {"await app.run_async()" if self._use_async else "app_builder.build().run()"} + + + if __name__ == '__main__': + {"asyncio.run(main())" if self._use_async else "main()"} + """) + + self._main_with_dependency_injection = textwrap.dedent(f"""\ + {"import asyncio" if self._use_async else ''} + + from cpl_core.application import ApplicationBuilder + + from {import_pkg}application import Application + + + {self._async()}def configure_configuration() -> ConfigurationABC: + config = Configuration() + return config + + + {self._async()}def configure_services(config: ConfigurationABC) -> ServiceProviderABC: + services = ServiceCollection(config) + return services.build_service_provider() + + + {self._async()}def main(): + config = {self._async()}configure_configuration() + provider = {self._async()}configure_services(config) + Console.write_line('Hello World') + + + if __name__ == '__main__': + {"asyncio.run(main())" if self._use_async else "main()"} + """) + + def _async(self) -> str: + if self._use_async: + return 'async ' + return '' + + def get_code(self) -> str: + if self._use_application_api and self._use_startup: + return self._main_with_application_host_and_startup + + if self._use_application_api: + return self._main_with_application_base + + if self._use_service_providing: + return self._main_with_dependency_injection + + return self._main_with_application_base diff --git a/src/cpl_cli/.cpl/project_file_code_startup.py b/src/cpl_cli/.cpl/project_file_code_startup.py new file mode 100644 index 00000000..51ce07c1 --- /dev/null +++ b/src/cpl_cli/.cpl/project_file_code_startup.py @@ -0,0 +1,29 @@ +from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC + + +class ProjectFileStartup(CodeFileTemplateABC): + + def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool): + CodeFileTemplateABC.__init__(self, 'startup', path, '', use_application_api, use_startup, use_service_providing, use_async) + + def get_code(self) -> str: + import textwrap + + return textwrap.dedent("""\ + from cpl_core.application import StartupABC + from cpl_core.configuration import ConfigurationABC + from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC + from cpl_core.environment import ApplicationEnvironment + + + class Startup(StartupABC): + + def __init__(self): + StartupABC.__init__(self) + + def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: + return configuration + + def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: + return services.build_service_provider() + """) diff --git a/src/cpl_cli/.cpl/project_file_license.py b/src/cpl_cli/.cpl/project_file_license.py new file mode 100644 index 00000000..49030517 --- /dev/null +++ b/src/cpl_cli/.cpl/project_file_license.py @@ -0,0 +1,11 @@ +from cpl_cli.abc.file_template_abc import FileTemplateABC + + +class ProjectFileLicense(FileTemplateABC): + + def __init__(self, path: str): + FileTemplateABC.__init__(self, '', path, '') + self._name = 'LICENSE' + + def get_code(self) -> str: + return self._code diff --git a/src/cpl_cli/.cpl/project_file_readme.py b/src/cpl_cli/.cpl/project_file_readme.py new file mode 100644 index 00000000..ff45ab52 --- /dev/null +++ b/src/cpl_cli/.cpl/project_file_readme.py @@ -0,0 +1,11 @@ +from cpl_cli.abc.file_template_abc import FileTemplateABC + + +class ProjectFileReadme(FileTemplateABC): + + def __init__(self, path: str): + FileTemplateABC.__init__(self, '', path, '') + self._name = 'README.md' + + def get_code(self) -> str: + return self._code diff --git a/src/cpl_cli/.cpl/abc_schematic.py b/src/cpl_cli/.cpl/schematic_abc.py similarity index 100% rename from src/cpl_cli/.cpl/abc_schematic.py rename to src/cpl_cli/.cpl/schematic_abc.py diff --git a/src/cpl_cli/.cpl/class_schematic.py b/src/cpl_cli/.cpl/schematic_class.py similarity index 100% rename from src/cpl_cli/.cpl/class_schematic.py rename to src/cpl_cli/.cpl/schematic_class.py diff --git a/src/cpl_cli/.cpl/configmodel_schematic.py b/src/cpl_cli/.cpl/schematic_configmodel.py similarity index 100% rename from src/cpl_cli/.cpl/configmodel_schematic.py rename to src/cpl_cli/.cpl/schematic_configmodel.py diff --git a/src/cpl_cli/.cpl/enum_schematic.py b/src/cpl_cli/.cpl/schematic_enum.py similarity index 100% rename from src/cpl_cli/.cpl/enum_schematic.py rename to src/cpl_cli/.cpl/schematic_enum.py diff --git a/src/cpl_cli/.cpl/init_schematic.py b/src/cpl_cli/.cpl/schematic_init.py similarity index 100% rename from src/cpl_cli/.cpl/init_schematic.py rename to src/cpl_cli/.cpl/schematic_init.py diff --git a/src/cpl_cli/.cpl/pipe_schematic.py b/src/cpl_cli/.cpl/schematic_pipe.py similarity index 100% rename from src/cpl_cli/.cpl/pipe_schematic.py rename to src/cpl_cli/.cpl/schematic_pipe.py diff --git a/src/cpl_cli/.cpl/service_schematic.py b/src/cpl_cli/.cpl/schematic_service.py similarity index 100% rename from src/cpl_cli/.cpl/service_schematic.py rename to src/cpl_cli/.cpl/schematic_service.py diff --git a/src/cpl_cli/.cpl/test_case_schematic.py b/src/cpl_cli/.cpl/schematic_test_case.py similarity index 100% rename from src/cpl_cli/.cpl/test_case_schematic.py rename to src/cpl_cli/.cpl/schematic_test_case.py diff --git a/src/cpl_cli/.cpl/thread_schematic.py b/src/cpl_cli/.cpl/schematic_thread.py similarity index 100% rename from src/cpl_cli/.cpl/thread_schematic.py rename to src/cpl_cli/.cpl/schematic_thread.py diff --git a/src/cpl_cli/.cpl/validator_schematic.py b/src/cpl_cli/.cpl/schematic_validator.py similarity index 100% rename from src/cpl_cli/.cpl/validator_schematic.py rename to src/cpl_cli/.cpl/schematic_validator.py diff --git a/src/cpl_cli/abc/code_file_template_abc.py b/src/cpl_cli/abc/code_file_template_abc.py new file mode 100644 index 00000000..439d8e4f --- /dev/null +++ b/src/cpl_cli/abc/code_file_template_abc.py @@ -0,0 +1,24 @@ +from abc import ABC, abstractmethod + +from cpl_cli.abc.file_template_abc import FileTemplateABC +from cpl_core.utils import String + + +class CodeFileTemplateABC(FileTemplateABC): + + @abstractmethod + def __init__( + self, + name: str, + path: str, + code: str, + use_application_api: bool, + use_startup: bool, + use_service_providing: bool, + use_async: bool, + ): + FileTemplateABC.__init__(self, name, path, code) + self._use_application_api = use_application_api + self._use_startup = use_startup + self._use_service_providing = use_service_providing + self._use_async = use_async diff --git a/src/cpl_cli/abc/file_template_abc.py b/src/cpl_cli/abc/file_template_abc.py index 09e39f23..e86cd436 100644 --- a/src/cpl_cli/abc/file_template_abc.py +++ b/src/cpl_cli/abc/file_template_abc.py @@ -11,6 +11,9 @@ class FileTemplateABC(ABC): self._path = path self._code = code + def __repr__(self): + return f'<{type(self).__name__} {self._path}{self._name}>' + @property def name(self) -> str: return self._name @@ -18,11 +21,14 @@ class FileTemplateABC(ABC): @property def path(self) -> str: return self._path + + @path.setter + def path(self, value: str): + self._path = value @property def value(self) -> str: return self.get_code() @abstractmethod - def get_code(self) -> str: - return self._code + def get_code(self) -> str: pass diff --git a/src/cpl_cli/abc/generate_schematic_abc.py b/src/cpl_cli/abc/generate_schematic_abc.py index 7254e176..5a0b958d 100644 --- a/src/cpl_cli/abc/generate_schematic_abc.py +++ b/src/cpl_cli/abc/generate_schematic_abc.py @@ -15,7 +15,10 @@ class GenerateSchematicABC(FileTemplateABC): if schematic in name.lower(): self._name = f'{String.convert_to_snake_case(name)}.py' - self._class_name = f'{String.first_to_upper(name)}{String.first_to_upper(schematic)}' + self._class_name = name + if name != '': + self._class_name = f'{String.first_to_upper(name)}{String.first_to_upper(schematic)}' + if schematic in name.lower(): self._class_name = f'{String.first_to_upper(name)}' @@ -24,7 +27,8 @@ class GenerateSchematicABC(FileTemplateABC): return self._class_name @abstractmethod - def get_code(self) -> str: pass + def get_code(self) -> str: + pass @classmethod def build_code_str(cls, code: str, **kwargs) -> str: diff --git a/src/cpl_cli/abc/project_type_abc.py b/src/cpl_cli/abc/project_type_abc.py new file mode 100644 index 00000000..7a6d8532 --- /dev/null +++ b/src/cpl_cli/abc/project_type_abc.py @@ -0,0 +1,35 @@ +from abc import ABC, abstractmethod +from typing import Optional + +from cpl_cli.abc.file_template_abc import FileTemplateABC +from cpl_cli.configuration import WorkspaceSettings + + +class ProjectTypeABC(ABC): + + @abstractmethod + def __init__( + self, + base_path: str, + project_name: str, + workspace: Optional[WorkspaceSettings], + use_application_api: bool, + use_startup: bool, + use_service_providing: bool, + use_async: bool, + ): + self._templates: list[FileTemplateABC] = [] + self._base_path = base_path + self._project_name = project_name + self._workspace = workspace + self._use_application_api = use_application_api + self._use_startup = use_startup + self._use_service_providing = use_service_providing + self._use_async = use_async + + @property + def templates(self) -> list[FileTemplateABC]: + return self._templates + + def add_template(self, t: FileTemplateABC): + self._templates.append(t) diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index 975770d7..32f2f061 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -144,7 +144,7 @@ class GenerateService(CommandABC): for r, d, f in os.walk(os.path.join(path, '.cpl')): for file in f: - if not file.endswith('_schematic.py'): + if not file.startswith('schematic_') and not file.endswith('.py'): continue code = '' diff --git a/src/cpl_cli/command/new_old_service.py b/src/cpl_cli/command/new_old_service.py new file mode 100644 index 00000000..5715f5cd --- /dev/null +++ b/src/cpl_cli/command/new_old_service.py @@ -0,0 +1,356 @@ +import os +import sys +import textwrap +from typing import Optional + +from packaging import version + +import cpl_cli +import cpl_core +from cpl_cli.configuration.venv_helper_service import VenvHelper +from cpl_cli.source_creator.unittest_builder import UnittestBuilder + +from cpl_core.configuration.configuration_abc import ConfigurationABC +from cpl_core.console.foreground_color_enum import ForegroundColorEnum +from cpl_core.console.console import Console +from cpl_core.utils.string import String +from cpl_cli.command_abc import CommandABC +from cpl_cli.configuration.build_settings import BuildSettings +from cpl_cli.configuration.build_settings_name_enum import BuildSettingsNameEnum +from cpl_cli.configuration.project_settings import ProjectSettings +from cpl_cli.configuration.project_settings_name_enum import ProjectSettingsNameEnum +from cpl_cli.configuration.project_type_enum import ProjectTypeEnum +from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum +from cpl_cli.configuration.workspace_settings import WorkspaceSettings +from cpl_cli.source_creator.console_builder import ConsoleBuilder +from cpl_cli.source_creator.library_builder import LibraryBuilder + + +class NewService(CommandABC): + + def __init__(self, configuration: ConfigurationABC): + """ + Service for the CLI command new + :param configuration: + """ + CommandABC.__init__(self) + + self._config = configuration + self._env = self._config.environment + + self._workspace: WorkspaceSettings = self._config.get_configuration(WorkspaceSettings) + self._project: ProjectSettings = ProjectSettings() + self._project_dict = {} + self._build: BuildSettings = BuildSettings() + self._build_dict = {} + self._project_json = {} + + self._name: str = '' + self._rel_path: str = '' + self._schematic: ProjectTypeEnum = ProjectTypeEnum.console + self._use_nothing: bool = False + self._use_application_api: bool = False + self._use_startup: bool = False + self._use_service_providing: bool = False + self._use_async: bool = False + self._use_venv: bool = False + self._use_base: bool = False + + @property + def help_message(self) -> str: + return textwrap.dedent("""\ + Generates a workspace and initial project or add a project to workspace. + Usage: cpl new + + Arguments: + type The project type of the initial project + name Name of the workspace or the project + + Types: + console (c|C) + library (l|L) + unittest (ut|UT) + """) + + def _create_project_settings(self): + self._rel_path = os.path.dirname(self._name) + self._project_dict = { + ProjectSettingsNameEnum.name.value: os.path.basename(self._name), + ProjectSettingsNameEnum.version.value: { + VersionSettingsNameEnum.major.value: '0', + VersionSettingsNameEnum.minor.value: '0', + VersionSettingsNameEnum.micro.value: '0' + }, + ProjectSettingsNameEnum.author.value: '', + ProjectSettingsNameEnum.author_email.value: '', + ProjectSettingsNameEnum.description.value: '', + ProjectSettingsNameEnum.long_description.value: '', + ProjectSettingsNameEnum.url.value: '', + ProjectSettingsNameEnum.copyright_date.value: '', + ProjectSettingsNameEnum.copyright_name.value: '', + ProjectSettingsNameEnum.license_name.value: '', + ProjectSettingsNameEnum.license_description.value: '', + ProjectSettingsNameEnum.dependencies.value: [ + f'cpl-core>={version.parse(cpl_core.__version__)}' + ], + ProjectSettingsNameEnum.dev_dependencies.value: [ + f'cpl-cli>={version.parse(cpl_cli.__version__)}' + ], + ProjectSettingsNameEnum.python_version.value: f'>={sys.version.split(" ")[0]}', + ProjectSettingsNameEnum.python_path.value: { + sys.platform: '../../venv/bin/python' if self._use_venv else '' + }, + ProjectSettingsNameEnum.classifiers.value: [] + } + + self._project.from_dict(self._project_dict) + + def _create_build_settings(self): + self._build_dict = { + BuildSettingsNameEnum.project_type.value: self._schematic, + BuildSettingsNameEnum.source_path.value: '', + BuildSettingsNameEnum.output_path.value: '../../dist', + BuildSettingsNameEnum.main.value: f'{String.convert_to_snake_case(self._project.name)}.main', + BuildSettingsNameEnum.entry_point.value: self._project.name, + BuildSettingsNameEnum.include_package_data.value: False, + BuildSettingsNameEnum.included.value: [], + BuildSettingsNameEnum.excluded.value: [ + '*/__pycache__', + '*/logs', + '*/tests' + ], + BuildSettingsNameEnum.package_data.value: {}, + BuildSettingsNameEnum.project_references.value: [] + } + self._build.from_dict(self._build_dict) + + def _create_project_json(self): + """ + Creates cpl.json content + :return: + """ + self._project_json = { + ProjectSettings.__name__: self._project_dict, + BuildSettings.__name__: self._build_dict + } + + def _get_project_path(self) -> Optional[str]: + """ + Gets project path + :return: + """ + if self._workspace is None: + project_path = os.path.join(self._env.working_directory, self._rel_path, self._project.name) + else: + base = '' if self._use_base else 'src' + project_path = os.path.join(self._env.working_directory, base, self._rel_path, String.convert_to_snake_case(self._project.name)) + + if os.path.isdir(project_path) and len(os.listdir(project_path)) > 0: + Console.write_line(project_path) + Console.error('Project path is not empty\n') + return None + + return project_path + + def _get_project_information(self, is_unittest=False): + """ + Gets project information's from user + :return: + """ + if self._use_application_api or self._use_startup or self._use_service_providing or self._use_async or self._use_nothing: + Console.set_foreground_color(ForegroundColorEnum.default) + Console.write_line('Skipping question due to given flags') + return + + if not is_unittest: + self._use_application_api = Console.read('Do you want to use application base? (y/n) ').lower() == 'y' + + if not is_unittest and self._use_application_api: + self._use_startup = Console.read('Do you want to use startup? (y/n) ').lower() == 'y' + + if not is_unittest and not self._use_application_api: + self._use_service_providing = Console.read('Do you want to use service providing? (y/n) ').lower() == 'y' + + if not self._use_async: + self._use_async = Console.read('Do you want to use async? (y/n) ').lower() == 'y' + + Console.set_foreground_color(ForegroundColorEnum.default) + + def _console(self, args: list[str]): + """ + Generates new console project + :param args: + :return: + """ + self._create_project_settings() + self._create_build_settings() + self._create_project_json() + path = self._get_project_path() + if path is None: + return + + self._get_project_information() + project_name = self._project.name + if self._rel_path != '': + project_name = f'{self._rel_path}/{project_name}' + try: + ConsoleBuilder.build( + path, + self._use_application_api, + self._use_startup, + self._use_service_providing, + self._use_async, + project_name, + self._project_json, + self._workspace + ) + except Exception as e: + Console.error('Could not create project', str(e)) + + def _unittest(self, args: list[str]): + """ + Generates new unittest project + :param args: + :return: + """ + self._create_project_settings() + self._create_build_settings() + self._create_project_json() + path = self._get_project_path() + if path is None: + return + + self._get_project_information(is_unittest=True) + project_name = self._project.name + if self._rel_path != '': + project_name = f'{self._rel_path}/{project_name}' + try: + UnittestBuilder.build( + path, + self._use_application_api, + self._use_async, + project_name, + self._project_json, + self._workspace + ) + except Exception as e: + Console.error('Could not create project', str(e)) + + def _library(self, args: list[str]): + """ + Generates new library project + :param args: + :return: + """ + self._create_project_settings() + self._create_build_settings() + self._create_project_json() + path = self._get_project_path() + if path is None: + return + + self._get_project_information() + project_name = self._project.name + if self._rel_path != '': + project_name = f'{self._rel_path}/{project_name}' + try: + LibraryBuilder.build( + path, + self._use_application_api, + self._use_startup, + self._use_service_providing, + self._use_async, + project_name, + self._project_json, + self._workspace + ) + except Exception as e: + Console.error('Could not create project', str(e)) + + def _create_venv(self): + + project = self._project.name + if self._workspace is not None: + project = self._workspace.default_project + + if self._env.working_directory.endswith(project): + project = '' + + if self._workspace is None and self._use_base: + project = f'{self._rel_path}/{project}' + + VenvHelper.init_venv( + False, + self._env, + self._project, + explicit_path=os.path.join(self._env.working_directory, project, self._project.python_executable.replace('../', '')) + ) + + def execute(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ + if 'nothing' in args: + self._use_nothing = True + self._use_async = False + self._use_application_api = False + self._use_startup = False + self._use_service_providing = False + if 'async' in args: + args.remove('async') + if 'application-base' in args: + args.remove('application-base') + if 'startup' in args: + args.remove('startup') + if 'service-providing' in args: + args.remove('service-providing') + + if 'async' in args: + self._use_async = True + args.remove('async') + if 'application-base' in args: + self._use_application_api = True + args.remove('application-base') + if 'startup' in args: + self._use_startup = True + args.remove('startup') + if 'service-providing' in args: + self._use_service_providing = True + args.remove('service-providing') + if 'venv' in args: + self._use_venv = True + args.remove('venv') + if 'base' in args: + self._use_base = True + args.remove('base') + + console = self._config.get_configuration(ProjectTypeEnum.console.value) + library = self._config.get_configuration(ProjectTypeEnum.library.value) + unittest = self._config.get_configuration(ProjectTypeEnum.unittest.value) + if console is not None and library is None and unittest is None: + self._name = console + self._schematic = ProjectTypeEnum.console.value + self._console(args) + if self._use_venv: + self._create_venv() + + elif console is None and library is not None and unittest is None: + self._name = library + self._schematic = ProjectTypeEnum.library.value + self._library(args) + if self._use_venv: + self._create_venv() + + elif console is None and library is None and unittest is not None: + self._name = unittest + self._schematic = ProjectTypeEnum.unittest.value + self._unittest(args) + if self._use_venv: + self._create_venv() + + else: + Console.error(f'Project type not found') + Console.write_line(self.help_message) + return diff --git a/src/cpl_cli/command/new_service.py b/src/cpl_cli/command/new_service.py index 5715f5cd..8b399d58 100644 --- a/src/cpl_cli/command/new_service.py +++ b/src/cpl_cli/command/new_service.py @@ -7,7 +7,9 @@ from packaging import version import cpl_cli import cpl_core +from cpl_cli.abc.project_type_abc import ProjectTypeABC from cpl_cli.configuration.venv_helper_service import VenvHelper +from cpl_cli.source_creator.template_builder import TemplateBuilder from cpl_cli.source_creator.unittest_builder import UnittestBuilder from cpl_core.configuration.configuration_abc import ConfigurationABC @@ -47,7 +49,7 @@ class NewService(CommandABC): self._name: str = '' self._rel_path: str = '' - self._schematic: ProjectTypeEnum = ProjectTypeEnum.console + self._project_type: ProjectTypeEnum = ProjectTypeEnum.console self._use_nothing: bool = False self._use_application_api: bool = False self._use_startup: bool = False @@ -107,7 +109,7 @@ class NewService(CommandABC): def _create_build_settings(self): self._build_dict = { - BuildSettingsNameEnum.project_type.value: self._schematic, + BuildSettingsNameEnum.project_type.value: self._project_type, BuildSettingsNameEnum.source_path.value: '', BuildSettingsNameEnum.output_path.value: '../../dist', BuildSettingsNameEnum.main.value: f'{String.convert_to_snake_case(self._project.name)}.main', @@ -286,6 +288,85 @@ class NewService(CommandABC): explicit_path=os.path.join(self._env.working_directory, project, self._project.python_executable.replace('../', '')) ) + @staticmethod + def _read_custom_project_types_from_path(path: str): + if not os.path.exists(os.path.join(path, '.cpl')): + return + + sys.path.insert(0, os.path.join(path, '.cpl')) + for r, d, f in os.walk(os.path.join(path, '.cpl')): + for file in f: + if not file.startswith('project_') or not file.endswith('.py'): + continue + + code = '' + with open(os.path.join(r, file), 'r') as py_file: + code = py_file.read() + py_file.close() + + exec(code) + + def _create_project(self): + self._read_custom_project_types_from_path(self._env.runtime_directory) + self._read_custom_project_types_from_path(self._env.working_directory) + + self._create_project_settings() + self._create_build_settings() + self._create_project_json() + path = self._get_project_path() + if path is None: + return + + self._get_project_information() + project_name = self._project.name + if self._rel_path != '': + project_name = f'{self._rel_path}/{project_name}' + + project_type = None + for p in ProjectTypeABC.__subclasses__(): + if p.__name__.lower() != self._project_type: + continue + + project_type = p + + base = 'src/' + split_project_name = project_name.split('/') + if self._use_base and len(split_project_name) > 0: + base = f'{split_project_name[0]}/' + + project = project_type( + base if self._workspace is not None else 'src/', + project_name, + self._workspace, + self._use_application_api, + self._use_startup, + self._use_service_providing, + self._use_async, + ) + + if self._workspace is None: + TemplateBuilder.create_workspace( + f'{project_name}/cpl-workspace.json', + project_name.split('/')[-1], + { + project_name: project_name + }, + {} + ) + else: + self._workspace.projects[project_name] = f'{base}{String.convert_to_snake_case(project_name.split("/")[-1])}' + TemplateBuilder.create_workspace('cpl-workspace.json', self._workspace.default_project, self._workspace.projects, self._workspace.scripts) + + for template in project.templates: + Console.spinner( + f'Creating {os.path.join(project_name, template.path, template.name)}', + TemplateBuilder.build, + project_name, + template, + text_foreground_color=ForegroundColorEnum.green, + spinner_foreground_color=ForegroundColorEnum.cyan + ) + def execute(self, args: list[str]): """ Entry point of command @@ -331,21 +412,22 @@ class NewService(CommandABC): unittest = self._config.get_configuration(ProjectTypeEnum.unittest.value) if console is not None and library is None and unittest is None: self._name = console - self._schematic = ProjectTypeEnum.console.value - self._console(args) + self._project_type = ProjectTypeEnum.console.value + self._create_project() + # self._console(args) if self._use_venv: self._create_venv() elif console is None and library is not None and unittest is None: self._name = library - self._schematic = ProjectTypeEnum.library.value + self._project_type = ProjectTypeEnum.library.value self._library(args) if self._use_venv: self._create_venv() elif console is None and library is None and unittest is not None: self._name = unittest - self._schematic = ProjectTypeEnum.unittest.value + self._project_type = ProjectTypeEnum.unittest.value self._unittest(args) if self._use_venv: self._create_venv() diff --git a/src/cpl_cli/source_creator/template_builder.py b/src/cpl_cli/source_creator/template_builder.py index 20939a64..c661cd7a 100644 --- a/src/cpl_cli/source_creator/template_builder.py +++ b/src/cpl_cli/source_creator/template_builder.py @@ -1,12 +1,49 @@ +import json import os +from typing import Union from cpl_cli._templates.template_file_abc import TemplateFileABC +from cpl_cli.abc.file_template_abc import FileTemplateABC +from cpl_cli.configuration import WorkspaceSettings, WorkspaceSettingsNameEnum +from cpl_core.console import Console, ForegroundColorEnum class TemplateBuilder: @staticmethod - def build(project_path: str, template: TemplateFileABC): + def _create_file(file_name: str, content: dict): + if not os.path.isabs(file_name): + file_name = os.path.abspath(file_name) + + path = os.path.dirname(file_name) + if not os.path.isdir(path): + os.makedirs(path) + + with open(file_name, 'w') as project_json: + project_json.write(json.dumps(content, indent=2)) + project_json.close() + + @classmethod + def create_workspace(cls, path: str, project_name, projects: dict, scripts: dict): + ws_dict = { + WorkspaceSettings.__name__: { + WorkspaceSettingsNameEnum.default_project.value: project_name, + WorkspaceSettingsNameEnum.projects.value: projects, + WorkspaceSettingsNameEnum.scripts.value: scripts + } + } + + Console.spinner( + f'Creating {path}', + cls._create_file, + path, + ws_dict, + text_foreground_color=ForegroundColorEnum.green, + spinner_foreground_color=ForegroundColorEnum.cyan + ) + + @staticmethod + def build(project_path: str, template: Union[TemplateFileABC, FileTemplateABC]): """ Creates template :param project_path: @@ -14,10 +51,8 @@ class TemplateBuilder: :return: """ file_path = os.path.join(project_path, template.path, template.name) - file_rel_path = os.path.join(project_path, template.path) - - if not os.path.isdir(file_rel_path): - os.makedirs(file_rel_path) + if not os.path.isdir(os.path.dirname(file_path)): + os.makedirs(os.path.dirname(file_path)) with open(file_path, 'w') as file: file.write(template.value) diff --git a/tests/custom/general/.cpl/custom_schematic.py b/tests/custom/general/.cpl/schematic_custom.py similarity index 100% rename from tests/custom/general/.cpl/custom_schematic.py rename to tests/custom/general/.cpl/schematic_custom.py -- 2.45.1 From e24453555741807dc1684762c80198f1f838752e Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 6 Dec 2022 17:42:55 +0100 Subject: [PATCH 33/63] Improved cpl n custom templating #139 --- src/cpl_cli/.cpl/project_console.py | 23 +- src/cpl_cli/.cpl/project_file.py | 14 + src/cpl_cli/.cpl/project_file_appsettings.py | 22 +- src/cpl_cli/.cpl/project_file_code_main.py | 7 +- .../project_file_code_test_application.py | 59 ++++ .../.cpl/project_file_code_test_case.py | 37 +++ src/cpl_cli/.cpl/project_library.py | 49 ++++ src/cpl_cli/.cpl/project_unittest.py | 42 +++ src/cpl_cli/.cpl/schematic_abc.py | 2 - src/cpl_cli/.cpl/schematic_test_case.py | 3 +- src/cpl_cli/_templates/new/__init__.py | 26 -- .../_templates/new/console/__init__.py | 26 -- .../new/console/appsettings_json.py | 41 --- src/cpl_cli/_templates/new/console/license.py | 23 -- .../_templates/new/console/readme_py.py | 23 -- .../_templates/new/console/source/__init__.py | 26 -- .../new/console/source/name/__init__.py | 26 -- .../new/console/source/name/application.py | 64 ----- .../new/console/source/name/init.py | 27 -- .../new/console/source/name/main.py | 254 ------------------ .../new/console/source/name/startup.py | 43 --- .../new/console/source/tests/__init__.py | 26 -- .../new/console/source/tests/init.py | 27 -- .../_templates/new/library/__init__.py | 26 -- .../new/library/appsettings_json.py | 41 --- src/cpl_cli/_templates/new/library/license.py | 23 -- .../_templates/new/library/readme_py.py | 23 -- .../_templates/new/library/source/__init__.py | 26 -- .../new/library/source/name/__init__.py | 26 -- .../new/library/source/name/application.py | 63 ----- .../new/library/source/name/init.py | 27 -- .../new/library/source/name/main.py | 249 ----------------- .../new/library/source/name/startup.py | 42 --- .../new/library/source/tests/__init__.py | 26 -- .../new/library/source/tests/init.py | 27 -- .../_templates/new/unittest/__init__.py | 26 -- .../_templates/new/unittest/license.py | 23 -- .../_templates/new/unittest/readme_py.py | 23 -- .../new/unittest/source/__init__.py | 26 -- .../new/unittest/source/name/__init__.py | 26 -- .../new/unittest/source/name/application.py | 74 ----- .../new/unittest/source/name/init.py | 27 -- .../new/unittest/source/name/main.py | 62 ----- .../new/unittest/source/name/test_case.py | 52 ---- src/cpl_cli/abc/project_type_abc.py | 2 + src/cpl_cli/command/generate_service.py | 19 +- src/cpl_cli/command/new_service.py | 189 ++++--------- src/cpl_cli/publish/publisher_service.py | 14 +- src/cpl_cli/source_creator/console_builder.py | 182 ------------- src/cpl_cli/source_creator/library_builder.py | 186 ------------- .../source_creator/template_builder.py | 11 +- .../source_creator/unittest_builder.py | 164 ----------- .../unittests_cli/abc/command_test_case.py | 6 +- unittests/unittests_cli/add_test_case.py | 2 +- unittests/unittests_cli/new_test_case.py | 15 +- unittests/unittests_cli/publish_test_case.py | 15 +- 56 files changed, 329 insertions(+), 2304 deletions(-) create mode 100644 src/cpl_cli/.cpl/project_file.py create mode 100644 src/cpl_cli/.cpl/project_file_code_test_application.py create mode 100644 src/cpl_cli/.cpl/project_file_code_test_case.py create mode 100644 src/cpl_cli/.cpl/project_library.py create mode 100644 src/cpl_cli/.cpl/project_unittest.py delete mode 100644 src/cpl_cli/_templates/new/__init__.py delete mode 100644 src/cpl_cli/_templates/new/console/__init__.py delete mode 100644 src/cpl_cli/_templates/new/console/appsettings_json.py delete mode 100644 src/cpl_cli/_templates/new/console/license.py delete mode 100644 src/cpl_cli/_templates/new/console/readme_py.py delete mode 100644 src/cpl_cli/_templates/new/console/source/__init__.py delete mode 100644 src/cpl_cli/_templates/new/console/source/name/__init__.py delete mode 100644 src/cpl_cli/_templates/new/console/source/name/application.py delete mode 100644 src/cpl_cli/_templates/new/console/source/name/init.py delete mode 100644 src/cpl_cli/_templates/new/console/source/name/main.py delete mode 100644 src/cpl_cli/_templates/new/console/source/name/startup.py delete mode 100644 src/cpl_cli/_templates/new/console/source/tests/__init__.py delete mode 100644 src/cpl_cli/_templates/new/console/source/tests/init.py delete mode 100644 src/cpl_cli/_templates/new/library/__init__.py delete mode 100644 src/cpl_cli/_templates/new/library/appsettings_json.py delete mode 100644 src/cpl_cli/_templates/new/library/license.py delete mode 100644 src/cpl_cli/_templates/new/library/readme_py.py delete mode 100644 src/cpl_cli/_templates/new/library/source/__init__.py delete mode 100644 src/cpl_cli/_templates/new/library/source/name/__init__.py delete mode 100644 src/cpl_cli/_templates/new/library/source/name/application.py delete mode 100644 src/cpl_cli/_templates/new/library/source/name/init.py delete mode 100644 src/cpl_cli/_templates/new/library/source/name/main.py delete mode 100644 src/cpl_cli/_templates/new/library/source/name/startup.py delete mode 100644 src/cpl_cli/_templates/new/library/source/tests/__init__.py delete mode 100644 src/cpl_cli/_templates/new/library/source/tests/init.py delete mode 100644 src/cpl_cli/_templates/new/unittest/__init__.py delete mode 100644 src/cpl_cli/_templates/new/unittest/license.py delete mode 100644 src/cpl_cli/_templates/new/unittest/readme_py.py delete mode 100644 src/cpl_cli/_templates/new/unittest/source/__init__.py delete mode 100644 src/cpl_cli/_templates/new/unittest/source/name/__init__.py delete mode 100644 src/cpl_cli/_templates/new/unittest/source/name/application.py delete mode 100644 src/cpl_cli/_templates/new/unittest/source/name/init.py delete mode 100644 src/cpl_cli/_templates/new/unittest/source/name/main.py delete mode 100644 src/cpl_cli/_templates/new/unittest/source/name/test_case.py delete mode 100644 src/cpl_cli/source_creator/console_builder.py delete mode 100644 src/cpl_cli/source_creator/library_builder.py delete mode 100644 src/cpl_cli/source_creator/unittest_builder.py diff --git a/src/cpl_cli/.cpl/project_console.py b/src/cpl_cli/.cpl/project_console.py index 7028172d..cdf2ec62 100644 --- a/src/cpl_cli/.cpl/project_console.py +++ b/src/cpl_cli/.cpl/project_console.py @@ -16,22 +16,29 @@ class Console(ProjectTypeABC): use_startup: bool, use_service_providing: bool, use_async: bool, + project_file_data: dict, ): - from project_file_license import ProjectFileLicense - from project_file_readme import ProjectFileReadme - from schematic_init import Init + from project_file import ProjectFile + from project_file_appsettings import ProjectFileAppsettings from project_file_code_application import ProjectFileApplication from project_file_code_main import ProjectFileMain from project_file_code_startup import ProjectFileStartup + from project_file_readme import ProjectFileReadme + from project_file_license import ProjectFileLicense + from schematic_init import Init - ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async) + ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async, project_file_data) project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/' - self.add_template(ProjectFileLicense('')) - self.add_template(ProjectFileReadme('')) - self.add_template(Init('', 'init', f'{base_path}tests/')) + self.add_template(ProjectFile(project_name.split('/')[-1], project_path, project_file_data)) + if workspace is None: + self.add_template(ProjectFileLicense('')) + self.add_template(ProjectFileReadme('')) + self.add_template(Init('', 'init', f'{base_path}tests/')) + self.add_template(Init('', 'init', project_path)) + self.add_template(ProjectFileAppsettings(project_path)) if use_application_api: self.add_template(ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async)) @@ -39,4 +46,4 @@ class Console(ProjectTypeABC): if use_startup: self.add_template(ProjectFileStartup(project_path, use_application_api, use_startup, use_service_providing, use_async)) - self.add_template(ProjectFileMain(project_path, use_application_api, use_startup, use_service_providing, use_async)) + self.add_template(ProjectFileMain(project_name.split('/')[-1], project_path, use_application_api, use_startup, use_service_providing, use_async)) diff --git a/src/cpl_cli/.cpl/project_file.py b/src/cpl_cli/.cpl/project_file.py new file mode 100644 index 00000000..ecee56ce --- /dev/null +++ b/src/cpl_cli/.cpl/project_file.py @@ -0,0 +1,14 @@ +import json + +from cpl_cli.abc.file_template_abc import FileTemplateABC + + +class ProjectFile(FileTemplateABC): + + def __init__(self, name: str, path: str, code: dict): + FileTemplateABC.__init__(self, '', path, '{}') + self._name = f'{name}.json' + self._code = code + + def get_code(self) -> str: + return json.dumps(self._code, indent=2) diff --git a/src/cpl_cli/.cpl/project_file_appsettings.py b/src/cpl_cli/.cpl/project_file_appsettings.py index e7b0e3ec..c6a62b88 100644 --- a/src/cpl_cli/.cpl/project_file_appsettings.py +++ b/src/cpl_cli/.cpl/project_file_appsettings.py @@ -1,29 +1,11 @@ -import textwrap - from cpl_cli.abc.file_template_abc import FileTemplateABC class ProjectFileAppsettings(FileTemplateABC): def __init__(self, path: str): - code = textwrap.dedent("""\ - { - "TimeFormatSettings": { - "DateFormat": "%Y-%m-%d", - "TimeFormat": "%H:%M:%S", - "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", - "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" - }, - - "LoggingSettings": { - "Path": "logs/", - "Filename": "log_$start_time.log", - "ConsoleLogLevel": "ERROR", - "FileLogLevel": "WARN" - } - } - """) - FileTemplateABC.__init__(self, 'appsettings.json', path, code) + FileTemplateABC.__init__(self, '', path, '{}') + self._name = 'appsettings.json' def get_code(self) -> str: return self._code diff --git a/src/cpl_cli/.cpl/project_file_code_main.py b/src/cpl_cli/.cpl/project_file_code_main.py index 43b5988f..614eb1d2 100644 --- a/src/cpl_cli/.cpl/project_file_code_main.py +++ b/src/cpl_cli/.cpl/project_file_code_main.py @@ -1,14 +1,15 @@ from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC +from cpl_core.utils import String class ProjectFileMain(CodeFileTemplateABC): - def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool): + def __init__(self, name: str, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool): CodeFileTemplateABC.__init__(self, 'main', path, '', use_application_api, use_startup, use_service_providing, use_async) import textwrap - import_pkg = f'{self._name}.' + import_pkg = f'{String.convert_to_snake_case(name)}.' self._main_with_application_host_and_startup = textwrap.dedent(f"""\ {"import asyncio" if self._use_async else ''} @@ -51,8 +52,6 @@ class ProjectFileMain(CodeFileTemplateABC): {"import asyncio" if self._use_async else ''} from cpl_core.application import ApplicationBuilder - - from {import_pkg}application import Application {self._async()}def configure_configuration() -> ConfigurationABC: diff --git a/src/cpl_cli/.cpl/project_file_code_test_application.py b/src/cpl_cli/.cpl/project_file_code_test_application.py new file mode 100644 index 00000000..06221cd6 --- /dev/null +++ b/src/cpl_cli/.cpl/project_file_code_test_application.py @@ -0,0 +1,59 @@ +from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC + + +class ProjectFileTestApplication(CodeFileTemplateABC): + + def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool): + CodeFileTemplateABC.__init__(self, 'application', path, '', use_application_api, use_startup, use_service_providing, use_async) + + def get_code(self) -> str: + import textwrap + + if self._use_async: + return textwrap.dedent("""\ + import unittest + from unittest import TestSuite + + from cpl_core.application import ApplicationABC + from cpl_core.configuration import ConfigurationABC + from cpl_core.dependency_injection import ServiceProviderABC + from unittests.test_case import TestCase + + + class Application(ApplicationABC): + + def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): + ApplicationABC.__init__(self, config, services) + self._suite: TestSuite = unittest.TestSuite() + + async def configure(self): + self._suite.addTest(TestCase('test_equal')) + + async def main(self): + runner = unittest.TextTestRunner() + runner.run(self._suite) + """) + + return textwrap.dedent("""\ + import unittest + from unittest import TestSuite + + from cpl_core.application import ApplicationABC + from cpl_core.configuration import ConfigurationABC + from cpl_core.dependency_injection import ServiceProviderABC + from unittests.test_case import TestCase + + + class Application(ApplicationABC): + + def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): + ApplicationABC.__init__(self, config, services) + self._suite: TestSuite = unittest.TestSuite() + + def configure(self): + self._suite.addTest(TestCase('test_equal')) + + def main(self): + runner = unittest.TextTestRunner() + runner.run(self._suite) + """) diff --git a/src/cpl_cli/.cpl/project_file_code_test_case.py b/src/cpl_cli/.cpl/project_file_code_test_case.py new file mode 100644 index 00000000..731e9b93 --- /dev/null +++ b/src/cpl_cli/.cpl/project_file_code_test_case.py @@ -0,0 +1,37 @@ +from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC + + +class ProjectFileTestCase(CodeFileTemplateABC): + + def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool): + CodeFileTemplateABC.__init__(self, 'test_case', path, '', use_application_api, use_startup, use_service_providing, use_async) + + def get_code(self) -> str: + import textwrap + + if self._use_async: + return textwrap.dedent("""\ + import unittest + + + class TestCase(unittest.TestCase): + + async def setUp(self) -> None: + pass + + async def test_equal(self): + self.assertEqual(True, True) + """) + + return textwrap.dedent("""\ + import unittest + + + class TestCase(unittest.TestCase): + + def setUp(self) -> None: + pass + + def test_equal(self): + self.assertEqual(True, True) + """) diff --git a/src/cpl_cli/.cpl/project_library.py b/src/cpl_cli/.cpl/project_library.py new file mode 100644 index 00000000..91579b10 --- /dev/null +++ b/src/cpl_cli/.cpl/project_library.py @@ -0,0 +1,49 @@ +import os + +from cpl_cli.abc.project_type_abc import ProjectTypeABC +from cpl_cli.configuration import WorkspaceSettings +from cpl_core.utils import String + + +class Library(ProjectTypeABC): + + def __init__( + self, + base_path: str, + project_name: str, + workspace: WorkspaceSettings, + use_application_api: bool, + use_startup: bool, + use_service_providing: bool, + use_async: bool, + project_file_data: dict, + ): + from project_file import ProjectFile + from project_file_appsettings import ProjectFileAppsettings + from project_file_code_application import ProjectFileApplication + from project_file_code_main import ProjectFileMain + from project_file_code_startup import ProjectFileStartup + from project_file_readme import ProjectFileReadme + from project_file_license import ProjectFileLicense + from schematic_init import Init + + ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async, project_file_data) + + project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/' + + self.add_template(ProjectFile(project_name.split('/')[-1], project_path, project_file_data)) + if workspace is None: + self.add_template(ProjectFileLicense('')) + self.add_template(ProjectFileReadme('')) + self.add_template(Init('', 'init', f'{base_path}tests/')) + + self.add_template(Init('', 'init', project_path)) + self.add_template(ProjectFileAppsettings(project_path)) + + if use_application_api: + self.add_template(ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async)) + + if use_startup: + self.add_template(ProjectFileStartup(project_path, use_application_api, use_startup, use_service_providing, use_async)) + + self.add_template(ProjectFileMain(project_name.split('/')[-1], project_path, use_application_api, use_startup, use_service_providing, use_async)) diff --git a/src/cpl_cli/.cpl/project_unittest.py b/src/cpl_cli/.cpl/project_unittest.py new file mode 100644 index 00000000..7b4b4d2b --- /dev/null +++ b/src/cpl_cli/.cpl/project_unittest.py @@ -0,0 +1,42 @@ +import os + +from cpl_cli.abc.project_type_abc import ProjectTypeABC +from cpl_cli.configuration import WorkspaceSettings +from cpl_core.utils import String + + +class Unittest(ProjectTypeABC): + + def __init__( + self, + base_path: str, + project_name: str, + workspace: WorkspaceSettings, + use_application_api: bool, + use_startup: bool, + use_service_providing: bool, + use_async: bool, + project_file_data: dict, + ): + from project_file import ProjectFile + from project_file_code_application import ProjectFileApplication + from project_file_code_main import ProjectFileMain + from project_file_code_test_case import ProjectFileTestCase + from project_file_readme import ProjectFileReadme + from project_file_license import ProjectFileLicense + from schematic_init import Init + + ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async, project_file_data) + + project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/' + + self.add_template(ProjectFile(project_name.split('/')[-1], project_path, project_file_data)) + if workspace is None: + self.add_template(ProjectFileLicense('')) + self.add_template(ProjectFileReadme('')) + self.add_template(Init('', 'init', f'{base_path}tests/')) + + self.add_template(Init('', 'init', project_path)) + self.add_template(ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async)) + self.add_template(ProjectFileMain(project_name.split('/')[-1], project_path, use_application_api, use_startup, use_service_providing, use_async)) + self.add_template(ProjectFileTestCase(project_path, use_application_api, use_startup, use_service_providing, use_async)) diff --git a/src/cpl_cli/.cpl/schematic_abc.py b/src/cpl_cli/.cpl/schematic_abc.py index 917a60a6..aaa74cc3 100644 --- a/src/cpl_cli/.cpl/schematic_abc.py +++ b/src/cpl_cli/.cpl/schematic_abc.py @@ -1,5 +1,3 @@ -import textwrap - from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC diff --git a/src/cpl_cli/.cpl/schematic_test_case.py b/src/cpl_cli/.cpl/schematic_test_case.py index 63ffe56c..d0f2b4bd 100644 --- a/src/cpl_cli/.cpl/schematic_test_case.py +++ b/src/cpl_cli/.cpl/schematic_test_case.py @@ -21,8 +21,7 @@ class TestCase(GenerateSchematicABC): def test_equal(self): pass """ - x = self.build_code_str(code, Name=self._class_name) - return x + return self.build_code_str(code, Name=self._class_name) @classmethod def register(cls): diff --git a/src/cpl_cli/_templates/new/__init__.py b/src/cpl_cli/_templates/new/__init__.py deleted file mode 100644 index 6ab3639e..00000000 --- a/src/cpl_cli/_templates/new/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.new' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/console/__init__.py b/src/cpl_cli/_templates/new/console/__init__.py deleted file mode 100644 index f9bacfd9..00000000 --- a/src/cpl_cli/_templates/new/console/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.new.console' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/console/appsettings_json.py b/src/cpl_cli/_templates/new/console/appsettings_json.py deleted file mode 100644 index 5bd03eaa..00000000 --- a/src/cpl_cli/_templates/new/console/appsettings_json.py +++ /dev/null @@ -1,41 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class AppsettingsTemplate(TemplateFileABC): - - def __init__(self): - TemplateFileABC.__init__(self) - - self._name = 'appsettings.json' - self._path = '' - self._value = textwrap.dedent("""\ - { - "TimeFormatSettings": { - "DateFormat": "%Y-%m-%d", - "TimeFormat": "%H:%M:%S", - "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", - "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" - }, - - "LoggingSettings": { - "Path": "logs/", - "Filename": "log_$start_time.log", - "ConsoleLogLevel": "ERROR", - "FileLogLevel": "WARN" - } - } - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/console/license.py b/src/cpl_cli/_templates/new/console/license.py deleted file mode 100644 index fb586904..00000000 --- a/src/cpl_cli/_templates/new/console/license.py +++ /dev/null @@ -1,23 +0,0 @@ -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class LicenseTemplate(TemplateFileABC): - - def __init__(self): - TemplateFileABC.__init__(self) - - self._name = 'LICENSE' - self._path = '' - self._value = """""" - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/console/readme_py.py b/src/cpl_cli/_templates/new/console/readme_py.py deleted file mode 100644 index a40286a8..00000000 --- a/src/cpl_cli/_templates/new/console/readme_py.py +++ /dev/null @@ -1,23 +0,0 @@ -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class ReadmeTemplate(TemplateFileABC): - - def __init__(self): - TemplateFileABC.__init__(self) - - self._name = 'README.md' - self._path = '' - self._value = """""" - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/console/source/__init__.py b/src/cpl_cli/_templates/new/console/source/__init__.py deleted file mode 100644 index 406a219a..00000000 --- a/src/cpl_cli/_templates/new/console/source/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.new.console.source' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/console/source/name/__init__.py b/src/cpl_cli/_templates/new/console/source/name/__init__.py deleted file mode 100644 index 162a07c3..00000000 --- a/src/cpl_cli/_templates/new/console/source/name/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.new.console.source.name' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/console/source/name/application.py b/src/cpl_cli/_templates/new/console/source/name/application.py deleted file mode 100644 index 56d9990f..00000000 --- a/src/cpl_cli/_templates/new/console/source/name/application.py +++ /dev/null @@ -1,64 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class ApplicationTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - self._name = 'application.py' - self._path = path - self._use_async = use_async - - if self._use_async: - self._value = textwrap.dedent("""\ - from cpl_core.application import ApplicationABC - from cpl_core.configuration import ConfigurationABC - from cpl_core.console import Console - from cpl_core.dependency_injection import ServiceProviderABC - - - class Application(ApplicationABC): - - def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): - ApplicationABC.__init__(self, config, services) - - async def configure(self): - pass - - async def main(self): - Console.write_line('Hello World') - """) - else: - self._value = textwrap.dedent("""\ - from cpl_core.application import ApplicationABC - from cpl_core.configuration import ConfigurationABC - from cpl_core.console import Console - from cpl_core.dependency_injection import ServiceProviderABC - - - class Application(ApplicationABC): - - def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): - ApplicationABC.__init__(self, config, services) - - def configure(self): - pass - - def main(self): - Console.write_line('Hello World') - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/console/source/name/init.py b/src/cpl_cli/_templates/new/console/source/name/init.py deleted file mode 100644 index b3cbdecb..00000000 --- a/src/cpl_cli/_templates/new/console/source/name/init.py +++ /dev/null @@ -1,27 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class MainInitTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str): - TemplateFileABC.__init__(self) - - self._name = '__init__.py' - self._path = path - self._value = textwrap.dedent("""\ - # imports: - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/console/source/name/main.py b/src/cpl_cli/_templates/new/console/source/name/main.py deleted file mode 100644 index 8549c490..00000000 --- a/src/cpl_cli/_templates/new/console/source/name/main.py +++ /dev/null @@ -1,254 +0,0 @@ -import textwrap - -from cpl_core.utils.string import String -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class MainWithApplicationHostAndStartupTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - name = String.convert_to_snake_case(name) - self._name = 'main.py' - self._path = path - - import_pkg = f'{name}.' - - if use_async: - self._value = textwrap.dedent(f"""\ - import asyncio - - from cpl_core.application import ApplicationBuilder - - from {import_pkg}application import Application - from {import_pkg}startup import Startup - - - async def main(): - app_builder = ApplicationBuilder(Application) - app_builder.use_startup(Startup) - app: Application = await app_builder.build_async() - await app.run_async() - - - if __name__ == '__main__': - asyncio.run(main()) - """) - else: - self._value = textwrap.dedent(f"""\ - from cpl_core.application import ApplicationBuilder - - from {import_pkg}application import Application - from {import_pkg}startup import Startup - - - def main(): - app_builder = ApplicationBuilder(Application) - app_builder.use_startup(Startup) - app_builder.build().run() - - - if __name__ == '__main__': - main() - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value - - -class MainWithApplicationBaseTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - name = String.convert_to_snake_case(name) - self._name = 'main.py' - self._path = path - - import_pkg = f'{name}.' - - if use_async: - self._value = textwrap.dedent(f"""\ - import asyncio - - from cpl_core.application import ApplicationBuilder - - from {import_pkg}application import Application - - - async def main(): - app_builder = ApplicationBuilder(Application) - app: Application = await app_builder.build_async() - await app.run_async() - - - if __name__ == '__main__': - asyncio.run(main()) - """) - else: - self._value = textwrap.dedent(f"""\ - from cpl_core.application import ApplicationBuilder - - from {import_pkg}application import Application - - - def main(): - app_builder = ApplicationBuilder(Application) - app_builder.build().run() - - - if __name__ == '__main__': - main() - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value - - -class MainWithoutApplicationBaseTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - name = String.convert_to_snake_case(name) - self._name = 'main.py' - self._path = path - - import_pkg = f'{name}.' - - if use_async: - self._value = textwrap.dedent("""\ - import asyncio - - from cpl_core.console import Console - - - async def main(): - Console.write_line('Hello World') - - - if __name__ == '__main__': - asyncio.run(main()) - """) - else: - self._value = textwrap.dedent("""\ - from cpl_core.console import Console - - - def main(): - Console.write_line('Hello World') - - - if __name__ == '__main__': - main() - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value - - -class MainWithDependencyInjection(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - name = String.convert_to_snake_case(name) - self._name = 'main.py' - self._path = path - - import_pkg = f'{name}.' - - if use_async: - self._value = textwrap.dedent("""\ - import asyncio - - from cpl_core.configuration import Configuration, ConfigurationABC - from cpl_core.console import Console - from cpl_core.dependency_injection import ServiceCollection, ServiceProviderABC - - - async def configure_configuration() -> ConfigurationABC: - config = Configuration() - return config - - - async def configure_services(config: ConfigurationABC) -> ServiceProviderABC: - services = ServiceCollection(config) - return services.build_service_provider() - - - async def main(): - config = await configure_configuration() - provider = await configure_services(config) - Console.write_line('Hello World') - - - if __name__ == '__main__': - asyncio.run(main()) - """) - else: - self._value = textwrap.dedent("""\ - from cpl_core.configuration import Configuration, ConfigurationABC - from cpl_core.console import Console - from cpl_core.dependency_injection import ServiceCollection, ServiceProviderABC - - - def configure_configuration() -> ConfigurationABC: - config = Configuration() - return config - - - def configure_services(config: ConfigurationABC) -> ServiceProviderABC: - services = ServiceCollection(config) - return services.build_service_provider() - - - def main(): - config = configure_configuration() - provider = configure_services(config) - Console.write_line('Hello World') - - - if __name__ == '__main__': - main() - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/console/source/name/startup.py b/src/cpl_cli/_templates/new/console/source/name/startup.py deleted file mode 100644 index 20e14842..00000000 --- a/src/cpl_cli/_templates/new/console/source/name/startup.py +++ /dev/null @@ -1,43 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class StartupTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str): - TemplateFileABC.__init__(self) - - self._name = 'startup.py' - self._path = path - - self._value = textwrap.dedent("""\ - from cpl_core.application import StartupABC - from cpl_core.configuration import ConfigurationABC - from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC - from cpl_core.environment import ApplicationEnvironment - - - class Startup(StartupABC): - - def __init__(self): - StartupABC.__init__(self) - - def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: - return configuration - - def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: - return services.build_service_provider() - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/console/source/tests/__init__.py b/src/cpl_cli/_templates/new/console/source/tests/__init__.py deleted file mode 100644 index 5c376a46..00000000 --- a/src/cpl_cli/_templates/new/console/source/tests/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.new.console.source.tests' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/console/source/tests/init.py b/src/cpl_cli/_templates/new/console/source/tests/init.py deleted file mode 100644 index 338ad115..00000000 --- a/src/cpl_cli/_templates/new/console/source/tests/init.py +++ /dev/null @@ -1,27 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class TestsInitTemplate(TemplateFileABC): - - def __init__(self): - TemplateFileABC.__init__(self) - - self._name = '__init__.py' - self._path = 'src/tests/' - self._value = textwrap.dedent("""\ - # imports: - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/library/__init__.py b/src/cpl_cli/_templates/new/library/__init__.py deleted file mode 100644 index e1cc62fe..00000000 --- a/src/cpl_cli/_templates/new/library/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.new.library' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/library/appsettings_json.py b/src/cpl_cli/_templates/new/library/appsettings_json.py deleted file mode 100644 index 5bd03eaa..00000000 --- a/src/cpl_cli/_templates/new/library/appsettings_json.py +++ /dev/null @@ -1,41 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class AppsettingsTemplate(TemplateFileABC): - - def __init__(self): - TemplateFileABC.__init__(self) - - self._name = 'appsettings.json' - self._path = '' - self._value = textwrap.dedent("""\ - { - "TimeFormatSettings": { - "DateFormat": "%Y-%m-%d", - "TimeFormat": "%H:%M:%S", - "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", - "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" - }, - - "LoggingSettings": { - "Path": "logs/", - "Filename": "log_$start_time.log", - "ConsoleLogLevel": "ERROR", - "FileLogLevel": "WARN" - } - } - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/library/license.py b/src/cpl_cli/_templates/new/library/license.py deleted file mode 100644 index fb586904..00000000 --- a/src/cpl_cli/_templates/new/library/license.py +++ /dev/null @@ -1,23 +0,0 @@ -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class LicenseTemplate(TemplateFileABC): - - def __init__(self): - TemplateFileABC.__init__(self) - - self._name = 'LICENSE' - self._path = '' - self._value = """""" - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/library/readme_py.py b/src/cpl_cli/_templates/new/library/readme_py.py deleted file mode 100644 index a40286a8..00000000 --- a/src/cpl_cli/_templates/new/library/readme_py.py +++ /dev/null @@ -1,23 +0,0 @@ -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class ReadmeTemplate(TemplateFileABC): - - def __init__(self): - TemplateFileABC.__init__(self) - - self._name = 'README.md' - self._path = '' - self._value = """""" - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/library/source/__init__.py b/src/cpl_cli/_templates/new/library/source/__init__.py deleted file mode 100644 index e13d13b4..00000000 --- a/src/cpl_cli/_templates/new/library/source/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.new.library.source' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/library/source/name/__init__.py b/src/cpl_cli/_templates/new/library/source/name/__init__.py deleted file mode 100644 index a688ce5f..00000000 --- a/src/cpl_cli/_templates/new/library/source/name/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.new.library.source.name' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/library/source/name/application.py b/src/cpl_cli/_templates/new/library/source/name/application.py deleted file mode 100644 index 5ca0b146..00000000 --- a/src/cpl_cli/_templates/new/library/source/name/application.py +++ /dev/null @@ -1,63 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class ApplicationTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - self._name = 'application.py' - self._path = path - - if use_async: - self._value = textwrap.dedent("""\ - from cpl_core.application import ApplicationABC - from cpl_core.configuration import ConfigurationABC - from cpl_core.console import Console - from cpl_core.dependency_injection import ServiceProviderABC - - - class Application(ApplicationABC): - - def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): - ApplicationABC.__init__(self, config, services) - - async def configure(self): - pass - - async def main(self): - Console.write_line('Hello World') - """) - else: - self._value = textwrap.dedent("""\ - from cpl_core.application import ApplicationABC - from cpl_core.configuration import ConfigurationABC - from cpl_core.console import Console - from cpl_core.dependency_injection import ServiceProviderABC - - - class Application(ApplicationABC): - - def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): - ApplicationABC.__init__(self, config, services) - - def configure(self): - pass - - def main(self): - Console.write_line('Hello World') - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/library/source/name/init.py b/src/cpl_cli/_templates/new/library/source/name/init.py deleted file mode 100644 index a3b0b8ea..00000000 --- a/src/cpl_cli/_templates/new/library/source/name/init.py +++ /dev/null @@ -1,27 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class NameInitTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str): - TemplateFileABC.__init__(self) - - self._name = '__init__.py' - self._path = path - self._value = textwrap.dedent("""\ - # imports: - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/library/source/name/main.py b/src/cpl_cli/_templates/new/library/source/name/main.py deleted file mode 100644 index c40fef1c..00000000 --- a/src/cpl_cli/_templates/new/library/source/name/main.py +++ /dev/null @@ -1,249 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class MainWithApplicationHostAndStartupTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - self._name = 'main.py' - self._path = path - - import_pkg = f'{name}.' - if name == '': - import_pkg = '' - - if use_async: - self._value = textwrap.dedent(f"""\ - import asyncio - - from cpl_core.application import ApplicationBuilder - - from {import_pkg}application import Application - from {import_pkg}startup import Startup - - - async def main(): - app_builder = ApplicationBuilder(Application) - app_builder.use_startup(Startup) - app: Application = await app_builder.build_async() - await app.run_async() - - - if __name__ == '__main__': - asyncio.run(main()) - """) - else: - self._value = textwrap.dedent(f"""\ - from cpl_core.application import ApplicationBuilder - - from {import_pkg}application import Application - from {import_pkg}startup import Startup - - - def main(): - app_builder = ApplicationBuilder(Application) - app_builder.use_startup(Startup) - app_builder.build().run() - - - if __name__ == '__main__': - main() - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value - - -class MainWithApplicationBaseTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - self._name = 'main.py' - self._path = path - - import_pkg = f'{name}.' - if name == '': - import_pkg = '' - - if use_async: - self._value = textwrap.dedent(f"""\ - import asyncio - - from cpl_core.application import ApplicationBuilder - - from {import_pkg}application import Application - - - async def main(): - app_builder = ApplicationBuilder(Application) - app: Application = await app_builder.build_async() - await app.run_async() - - - if __name__ == '__main__': - asyncio.run(main()) - """) - else: - self._value = textwrap.dedent(f"""\ - from cpl_core.application import ApplicationBuilder - - from {import_pkg}application import Application - - - def main(): - app_builder = ApplicationBuilder(Application) - app_builder.build().run() - - - if __name__ == '__main__': - main() - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value - - -class MainWithoutApplicationBaseTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - self._name = 'main.py' - self._path = path - - if use_async: - self._value = textwrap.dedent("""\ - import asyncio - - from cpl_core.console import Console - - - async def main(): - Console.write_line('Hello World') - - - if __name__ == '__main__': - asyncio.run(main()) - """) - else: - self._value = textwrap.dedent("""\ - from cpl_core.console import Console - - - def main(): - Console.write_line('Hello World') - - - if __name__ == '__main__': - main() - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value - - -class MainWithDependencyInjection(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - self._name = 'main.py' - self._path = path - - if use_async: - self._value = textwrap.dedent("""\ - import asyncio - - from cpl_core.configuration import Configuration, ConfigurationABC - from cpl_core.console import Console - from cpl_core.dependency_injection import ServiceCollection, ServiceProviderABC - - - async def configure_configuration() -> ConfigurationABC: - config = Configuration() - return config - - - async def configure_services(config: ConfigurationABC) -> ServiceProviderABC: - services = ServiceCollection(config) - return services.build_service_provider() - - - async def main(): - config = await configure_configuration() - provider = await configure_services(config) - Console.write_line('Hello World') - - - if __name__ == '__main__': - asyncio.run(main()) - """) - else: - self._value = textwrap.dedent("""\ - from cpl_core.configuration import Configuration, ConfigurationABC - from cpl_core.console import Console - from cpl_core.dependency_injection import ServiceCollection, ServiceProviderABC - - - def configure_configuration() -> ConfigurationABC: - config = Configuration() - return config - - - def configure_services(config: ConfigurationABC) -> ServiceProviderABC: - services = ServiceCollection(config) - return services.build_service_provider() - - - def main(): - config = configure_configuration() - provider = configure_services(config) - Console.write_line('Hello World') - - - if __name__ == '__main__': - main() - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/library/source/name/startup.py b/src/cpl_cli/_templates/new/library/source/name/startup.py deleted file mode 100644 index 959bc0ce..00000000 --- a/src/cpl_cli/_templates/new/library/source/name/startup.py +++ /dev/null @@ -1,42 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class StartupTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str): - TemplateFileABC.__init__(self) - - self._name = 'startup.py' - self._path = path - self._value = textwrap.dedent("""\ - from cpl_core.application import StartupABC - from cpl_core.configuration import ConfigurationABC - from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC - from cpl_core.environment import ApplicationEnvironment - - - class Startup(StartupABC): - - def __init__(self): - StartupABC.__init__(self) - - def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: - return configuration - - def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: - return services.build_service_provider() - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/library/source/tests/__init__.py b/src/cpl_cli/_templates/new/library/source/tests/__init__.py deleted file mode 100644 index c030a958..00000000 --- a/src/cpl_cli/_templates/new/library/source/tests/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.new.library.source.tests' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/library/source/tests/init.py b/src/cpl_cli/_templates/new/library/source/tests/init.py deleted file mode 100644 index 338ad115..00000000 --- a/src/cpl_cli/_templates/new/library/source/tests/init.py +++ /dev/null @@ -1,27 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class TestsInitTemplate(TemplateFileABC): - - def __init__(self): - TemplateFileABC.__init__(self) - - self._name = '__init__.py' - self._path = 'src/tests/' - self._value = textwrap.dedent("""\ - # imports: - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/unittest/__init__.py b/src/cpl_cli/_templates/new/unittest/__init__.py deleted file mode 100644 index 869714c3..00000000 --- a/src/cpl_cli/_templates/new/unittest/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.new.unittest' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/unittest/license.py b/src/cpl_cli/_templates/new/unittest/license.py deleted file mode 100644 index fb586904..00000000 --- a/src/cpl_cli/_templates/new/unittest/license.py +++ /dev/null @@ -1,23 +0,0 @@ -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class LicenseTemplate(TemplateFileABC): - - def __init__(self): - TemplateFileABC.__init__(self) - - self._name = 'LICENSE' - self._path = '' - self._value = """""" - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/unittest/readme_py.py b/src/cpl_cli/_templates/new/unittest/readme_py.py deleted file mode 100644 index a40286a8..00000000 --- a/src/cpl_cli/_templates/new/unittest/readme_py.py +++ /dev/null @@ -1,23 +0,0 @@ -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class ReadmeTemplate(TemplateFileABC): - - def __init__(self): - TemplateFileABC.__init__(self) - - self._name = 'README.md' - self._path = '' - self._value = """""" - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/unittest/source/__init__.py b/src/cpl_cli/_templates/new/unittest/source/__init__.py deleted file mode 100644 index 00b558a0..00000000 --- a/src/cpl_cli/_templates/new/unittest/source/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.new.unittest.source' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/unittest/source/name/__init__.py b/src/cpl_cli/_templates/new/unittest/source/name/__init__.py deleted file mode 100644 index 38c212d0..00000000 --- a/src/cpl_cli/_templates/new/unittest/source/name/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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._templates.new.unittest.source.name' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/_templates/new/unittest/source/name/application.py b/src/cpl_cli/_templates/new/unittest/source/name/application.py deleted file mode 100644 index 6c40e867..00000000 --- a/src/cpl_cli/_templates/new/unittest/source/name/application.py +++ /dev/null @@ -1,74 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class ApplicationTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - self._name = 'application.py' - self._path = path - self._use_async = use_async - - if self._use_async: - self._value = textwrap.dedent("""\ - import unittest - from unittest import TestSuite - - from cpl_core.application import ApplicationABC - from cpl_core.configuration import ConfigurationABC - from cpl_core.dependency_injection import ServiceProviderABC - from unittests.test_case import TestCase - - - class Application(ApplicationABC): - - def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): - ApplicationABC.__init__(self, config, services) - self._suite: TestSuite = unittest.TestSuite() - - async def configure(self): - self._suite.addTest(TestCase('test_equal')) - - async def main(self): - runner = unittest.TextTestRunner() - runner.run(self._suite) - """) - else: - self._value = textwrap.dedent("""\ - import unittest - from unittest import TestSuite - - from cpl_core.application import ApplicationABC - from cpl_core.configuration import ConfigurationABC - from cpl_core.dependency_injection import ServiceProviderABC - from unittests.test_case import TestCase - - - class Application(ApplicationABC): - - def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): - ApplicationABC.__init__(self, config, services) - self._suite: TestSuite = unittest.TestSuite() - - def configure(self): - self._suite.addTest(TestCase('test_equal')) - - def main(self): - runner = unittest.TextTestRunner() - runner.run(self._suite) - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/unittest/source/name/init.py b/src/cpl_cli/_templates/new/unittest/source/name/init.py deleted file mode 100644 index b3cbdecb..00000000 --- a/src/cpl_cli/_templates/new/unittest/source/name/init.py +++ /dev/null @@ -1,27 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class MainInitTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str): - TemplateFileABC.__init__(self) - - self._name = '__init__.py' - self._path = path - self._value = textwrap.dedent("""\ - # imports: - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/unittest/source/name/main.py b/src/cpl_cli/_templates/new/unittest/source/name/main.py deleted file mode 100644 index ba8e3b41..00000000 --- a/src/cpl_cli/_templates/new/unittest/source/name/main.py +++ /dev/null @@ -1,62 +0,0 @@ -import textwrap - -from cpl_core.utils.string import String -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class MainWithApplicationBaseTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - name = String.convert_to_snake_case(name) - self._name = 'main.py' - self._path = path - - import_pkg = f'{name}.' - - if use_async: - self._value = textwrap.dedent(f"""\ - import asyncio - - from cpl_core.application import ApplicationBuilder - - from {import_pkg}application import Application - - - async def main(): - app_builder = ApplicationBuilder(Application) - app: Application = await app_builder.build_async() - await app.run_async() - - - if __name__ == '__main__': - asyncio.run(main()) - """) - else: - self._value = textwrap.dedent(f"""\ - from cpl_core.application import ApplicationBuilder - - from {import_pkg}application import Application - - - def main(): - app_builder = ApplicationBuilder(Application) - app_builder.build().run() - - - if __name__ == '__main__': - main() - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/_templates/new/unittest/source/name/test_case.py b/src/cpl_cli/_templates/new/unittest/source/name/test_case.py deleted file mode 100644 index 096518bd..00000000 --- a/src/cpl_cli/_templates/new/unittest/source/name/test_case.py +++ /dev/null @@ -1,52 +0,0 @@ -import textwrap - -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class TestCaseTemplate(TemplateFileABC): - - def __init__(self, name: str, path: str, use_async: bool): - TemplateFileABC.__init__(self) - - self._name = 'test_case.py' - self._path = path - self._use_async = use_async - - if self._use_async: - self._value = textwrap.dedent("""\ - import unittest - - - class TestCase(unittest.TestCase): - - async def setUp(self) -> None: - pass - - async def test_equal(self): - self.assertEqual(True, True) - """) - else: - self._value = textwrap.dedent("""\ - import unittest - - - class TestCase(unittest.TestCase): - - def setUp(self) -> None: - pass - - def test_equal(self): - self.assertEqual(True, True) - """) - - @property - def name(self) -> str: - return self._name - - @property - def path(self) -> str: - return self._path - - @property - def value(self) -> str: - return self._value diff --git a/src/cpl_cli/abc/project_type_abc.py b/src/cpl_cli/abc/project_type_abc.py index 7a6d8532..68016e49 100644 --- a/src/cpl_cli/abc/project_type_abc.py +++ b/src/cpl_cli/abc/project_type_abc.py @@ -17,6 +17,7 @@ class ProjectTypeABC(ABC): use_startup: bool, use_service_providing: bool, use_async: bool, + project_file_data: dict, ): self._templates: list[FileTemplateABC] = [] self._base_path = base_path @@ -26,6 +27,7 @@ class ProjectTypeABC(ABC): self._use_startup = use_startup self._use_service_providing = use_service_providing self._use_async = use_async + self._project_file_data = project_file_data @property def templates(self) -> list[FileTemplateABC]: diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index 32f2f061..b1ee7967 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -1,6 +1,7 @@ import os import sys import textwrap +import traceback from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC from cpl_cli.command_abc import CommandABC @@ -34,6 +35,10 @@ class GenerateService(CommandABC): self._read_custom_schematics_from_path(self._env.runtime_directory) self._read_custom_schematics_from_path(self._env.working_directory) + + if len(GenerateSchematicABC.__subclasses__()) == 0: + Console.error(f'No schematics found in template directory: .cpl') + sys.exit() for schematic in GenerateSchematicABC.__subclasses__(): schematic.register() @@ -142,17 +147,17 @@ class GenerateService(CommandABC): if not os.path.exists(os.path.join(path, '.cpl')): return + sys.path.insert(0, os.path.join(path, '.cpl')) for r, d, f in os.walk(os.path.join(path, '.cpl')): for file in f: - if not file.startswith('schematic_') and not file.endswith('.py'): + if not file.startswith('schematic_') or not file.endswith('.py'): continue - code = '' - with open(os.path.join(r, file), 'r') as py_file: - code = py_file.read() - py_file.close() - - exec(code) + try: + exec(open(os.path.join(r, file), 'r').read()) + except Exception as e: + Console.error(str(e), traceback.format_exc()) + sys.exit(-1) def _get_schematic_by_alias(self, schematic: str) -> str: for key in self._schematics: diff --git a/src/cpl_cli/command/new_service.py b/src/cpl_cli/command/new_service.py index 8b399d58..32c27def 100644 --- a/src/cpl_cli/command/new_service.py +++ b/src/cpl_cli/command/new_service.py @@ -1,6 +1,7 @@ import os import sys import textwrap +import traceback from typing import Optional from packaging import version @@ -8,24 +9,20 @@ from packaging import version import cpl_cli import cpl_core from cpl_cli.abc.project_type_abc import ProjectTypeABC -from cpl_cli.configuration.venv_helper_service import VenvHelper -from cpl_cli.source_creator.template_builder import TemplateBuilder -from cpl_cli.source_creator.unittest_builder import UnittestBuilder - -from cpl_core.configuration.configuration_abc import ConfigurationABC -from cpl_core.console.foreground_color_enum import ForegroundColorEnum -from cpl_core.console.console import Console -from cpl_core.utils.string import String from cpl_cli.command_abc import CommandABC from cpl_cli.configuration.build_settings import BuildSettings from cpl_cli.configuration.build_settings_name_enum import BuildSettingsNameEnum from cpl_cli.configuration.project_settings import ProjectSettings from cpl_cli.configuration.project_settings_name_enum import ProjectSettingsNameEnum from cpl_cli.configuration.project_type_enum import ProjectTypeEnum +from cpl_cli.configuration.venv_helper_service import VenvHelper from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum from cpl_cli.configuration.workspace_settings import WorkspaceSettings -from cpl_cli.source_creator.console_builder import ConsoleBuilder -from cpl_cli.source_creator.library_builder import LibraryBuilder +from cpl_cli.source_creator.template_builder import TemplateBuilder +from cpl_core.configuration.configuration_abc import ConfigurationABC +from cpl_core.console.console import Console +from cpl_core.console.foreground_color_enum import ForegroundColorEnum +from cpl_core.utils.string import String class NewService(CommandABC): @@ -45,7 +42,6 @@ class NewService(CommandABC): self._project_dict = {} self._build: BuildSettings = BuildSettings() self._build_dict = {} - self._project_json = {} self._name: str = '' self._rel_path: str = '' @@ -107,9 +103,9 @@ class NewService(CommandABC): self._project.from_dict(self._project_dict) - def _create_build_settings(self): + def _create_build_settings(self, project_type: ProjectTypeEnum): self._build_dict = { - BuildSettingsNameEnum.project_type.value: self._project_type, + BuildSettingsNameEnum.project_type.value: project_type.value, BuildSettingsNameEnum.source_path.value: '', BuildSettingsNameEnum.output_path.value: '../../dist', BuildSettingsNameEnum.main.value: f'{String.convert_to_snake_case(self._project.name)}.main', @@ -178,99 +174,7 @@ class NewService(CommandABC): Console.set_foreground_color(ForegroundColorEnum.default) - def _console(self, args: list[str]): - """ - Generates new console project - :param args: - :return: - """ - self._create_project_settings() - self._create_build_settings() - self._create_project_json() - path = self._get_project_path() - if path is None: - return - - self._get_project_information() - project_name = self._project.name - if self._rel_path != '': - project_name = f'{self._rel_path}/{project_name}' - try: - ConsoleBuilder.build( - path, - self._use_application_api, - self._use_startup, - self._use_service_providing, - self._use_async, - project_name, - self._project_json, - self._workspace - ) - except Exception as e: - Console.error('Could not create project', str(e)) - - def _unittest(self, args: list[str]): - """ - Generates new unittest project - :param args: - :return: - """ - self._create_project_settings() - self._create_build_settings() - self._create_project_json() - path = self._get_project_path() - if path is None: - return - - self._get_project_information(is_unittest=True) - project_name = self._project.name - if self._rel_path != '': - project_name = f'{self._rel_path}/{project_name}' - try: - UnittestBuilder.build( - path, - self._use_application_api, - self._use_async, - project_name, - self._project_json, - self._workspace - ) - except Exception as e: - Console.error('Could not create project', str(e)) - - def _library(self, args: list[str]): - """ - Generates new library project - :param args: - :return: - """ - self._create_project_settings() - self._create_build_settings() - self._create_project_json() - path = self._get_project_path() - if path is None: - return - - self._get_project_information() - project_name = self._project.name - if self._rel_path != '': - project_name = f'{self._rel_path}/{project_name}' - try: - LibraryBuilder.build( - path, - self._use_application_api, - self._use_startup, - self._use_service_providing, - self._use_async, - project_name, - self._project_json, - self._workspace - ) - except Exception as e: - Console.error('Could not create project', str(e)) - def _create_venv(self): - project = self._project.name if self._workspace is not None: project = self._workspace.default_project @@ -296,22 +200,25 @@ class NewService(CommandABC): sys.path.insert(0, os.path.join(path, '.cpl')) for r, d, f in os.walk(os.path.join(path, '.cpl')): for file in f: - if not file.startswith('project_') or not file.endswith('.py'): + if file.startswith('project_file_') or not file.startswith('project_') or not file.endswith('.py'): continue - code = '' - with open(os.path.join(r, file), 'r') as py_file: - code = py_file.read() - py_file.close() + try: + exec(open(os.path.join(r, file), 'r').read()) + except Exception as e: + Console.error(str(e), traceback.format_exc()) + sys.exit(-1) - exec(code) - - def _create_project(self): + def _create_project(self, project_type: ProjectTypeEnum): self._read_custom_project_types_from_path(self._env.runtime_directory) self._read_custom_project_types_from_path(self._env.working_directory) + if len(ProjectTypeABC.__subclasses__()) == 0: + Console.error(f'No project types found in template directory: .cpl') + sys.exit() + self._create_project_settings() - self._create_build_settings() + self._create_build_settings(project_type) self._create_project_json() path = self._get_project_path() if path is None: @@ -322,19 +229,23 @@ class NewService(CommandABC): if self._rel_path != '': project_name = f'{self._rel_path}/{project_name}' - project_type = None + project_class = None for p in ProjectTypeABC.__subclasses__(): - if p.__name__.lower() != self._project_type: + if p.__name__.lower() != project_type.value and p.__name__.lower()[0] != project_type.value[0]: continue - project_type = p + project_class = p + + if project_class is None: + Console.error(f'Project type {project_type.value} not found in template directory: .cpl/') + sys.exit() base = 'src/' split_project_name = project_name.split('/') if self._use_base and len(split_project_name) > 0: base = f'{split_project_name[0]}/' - project = project_type( + project = project_class( base if self._workspace is not None else 'src/', project_name, self._workspace, @@ -342,6 +253,7 @@ class NewService(CommandABC): self._use_startup, self._use_service_providing, self._use_async, + self._project_json ) if self._workspace is None: @@ -349,24 +261,41 @@ class NewService(CommandABC): f'{project_name}/cpl-workspace.json', project_name.split('/')[-1], { - project_name: project_name + project_name: f'{base if self._workspace is not None else "src/"}{String.convert_to_snake_case(project_name)}/{project_name}.json' }, {} ) else: - self._workspace.projects[project_name] = f'{base}{String.convert_to_snake_case(project_name.split("/")[-1])}' + self._workspace.projects[project_name] = f'{base if self._workspace is not None else "src/"}{String.convert_to_snake_case(project_name)}/{project_name}.json' TemplateBuilder.create_workspace('cpl-workspace.json', self._workspace.default_project, self._workspace.projects, self._workspace.scripts) for template in project.templates: + rel_base = '/'.join(project_name.split('/')[:-1]) + template_path_base = template.path.split('/')[0] + if not self._use_base and rel_base != '' and template_path_base != '' and template_path_base != rel_base: + template.path = template.path.replace(f'{template_path_base}/', f'{template_path_base}/{rel_base}/') + + if template.name.endswith(f'{project_name.split("/")[-1]}.json'): + pass + + file_path = os.path.join( + project_name if self._workspace is None else '', + template.path, + template.name + ) + Console.spinner( - f'Creating {os.path.join(project_name, template.path, template.name)}', + f'Creating {file_path}', TemplateBuilder.build, - project_name, + file_path, template, text_foreground_color=ForegroundColorEnum.green, spinner_foreground_color=ForegroundColorEnum.cyan ) + if self._use_venv: + self._create_venv() + def execute(self, args: list[str]): """ Entry point of command @@ -412,25 +341,15 @@ class NewService(CommandABC): unittest = self._config.get_configuration(ProjectTypeEnum.unittest.value) if console is not None and library is None and unittest is None: self._name = console - self._project_type = ProjectTypeEnum.console.value - self._create_project() - # self._console(args) - if self._use_venv: - self._create_venv() + self._create_project(ProjectTypeEnum.console) elif console is None and library is not None and unittest is None: self._name = library - self._project_type = ProjectTypeEnum.library.value - self._library(args) - if self._use_venv: - self._create_venv() + self._create_project(ProjectTypeEnum.library) elif console is None and library is None and unittest is not None: self._name = unittest - self._project_type = ProjectTypeEnum.unittest.value - self._unittest(args) - if self._use_venv: - self._create_venv() + self._create_project(ProjectTypeEnum.unittest) else: Console.error(f'Project type not found') diff --git a/src/cpl_cli/publish/publisher_service.py b/src/cpl_cli/publish/publisher_service.py index b1639023..ca1a5382 100644 --- a/src/cpl_cli/publish/publisher_service.py +++ b/src/cpl_cli/publish/publisher_service.py @@ -404,7 +404,7 @@ class PublisherService(PublisherABC): f'--bdist-dir={os.path.join(self._output_path, "bdist")}', f'--dist-dir={os.path.join(self._output_path, "setup")}' ]) - os.remove(setup_py) + # os.remove(setup_py) except Exception as e: Console.error('Executing setup.py failed', str(e)) @@ -492,10 +492,10 @@ class PublisherService(PublisherABC): Console.write_line('Running setup.py:\n') self._run_setup() - Console.spinner( - 'Cleaning dist path:', - self._clean_dist_files, - text_foreground_color=ForegroundColorEnum.green, - spinner_foreground_color=ForegroundColorEnum.blue - ) + # Console.spinner( + # 'Cleaning dist path:', + # self._clean_dist_files, + # text_foreground_color=ForegroundColorEnum.green, + # spinner_foreground_color=ForegroundColorEnum.blue + # ) Console.write_line() diff --git a/src/cpl_cli/source_creator/console_builder.py b/src/cpl_cli/source_creator/console_builder.py deleted file mode 100644 index e8b86f84..00000000 --- a/src/cpl_cli/source_creator/console_builder.py +++ /dev/null @@ -1,182 +0,0 @@ -import json -import os -from typing import Optional - -from cpl_core.console.foreground_color_enum import ForegroundColorEnum -from cpl_core.console.console import Console -from cpl_core.utils.string import String -from cpl_cli.configuration.workspace_settings import WorkspaceSettings -from cpl_cli.configuration.workspace_settings_name_enum import WorkspaceSettingsNameEnum -from cpl_cli.source_creator.template_builder import TemplateBuilder -from cpl_cli._templates.new.console.appsettings_json import AppsettingsTemplate -from cpl_cli._templates.new.console.license import LicenseTemplate -from cpl_cli._templates.new.console.readme_py import ReadmeTemplate -from cpl_cli._templates.new.console.source.name.application import ApplicationTemplate -from cpl_cli._templates.new.console.source.name.init import MainInitTemplate -from cpl_cli._templates.new.console.source.name.main import MainWithApplicationHostAndStartupTemplate, \ - MainWithoutApplicationBaseTemplate, MainWithApplicationBaseTemplate, MainWithDependencyInjection -from cpl_cli._templates.new.console.source.name.startup import StartupTemplate -from cpl_cli._templates.new.console.source.tests.init import TestsInitTemplate -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class ConsoleBuilder: - - def __init__(self): - pass - - @staticmethod - def _create_file(file_name: str, content: dict): - if not os.path.isabs(file_name): - file_name = os.path.abspath(file_name) - - path = os.path.dirname(file_name) - if not os.path.isdir(path): - os.makedirs(path) - - with open(file_name, 'w') as project_json: - project_json.write(json.dumps(content, indent=2)) - project_json.close() - - @classmethod - def _create_workspace(cls, path: str, project_name, projects: dict, scripts: dict): - ws_dict = { - WorkspaceSettings.__name__: { - WorkspaceSettingsNameEnum.default_project.value: project_name, - WorkspaceSettingsNameEnum.projects.value: projects, - WorkspaceSettingsNameEnum.scripts.value: scripts - } - } - - Console.spinner( - f'Creating {path}', - cls._create_file, - path, - ws_dict, - text_foreground_color=ForegroundColorEnum.green, - spinner_foreground_color=ForegroundColorEnum.cyan - ) - - @classmethod - def build(cls, project_path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, - use_async: bool, project_name: str, project_settings: dict, workspace: Optional[WorkspaceSettings]): - """ - Builds the console project files - :param project_path: - :param use_application_api: - :param use_startup: - :param use_service_providing: - :param use_async: - :param project_name: - :param project_settings: - :param workspace: - :return: - """ - pj_name = project_name - if '/' in pj_name: - pj_name = pj_name.split('/')[len(pj_name.split('/')) - 1] - - project_name_snake = String.convert_to_snake_case(pj_name) - - if workspace is None: - templates: list[TemplateFileABC] = [ - LicenseTemplate(), - ReadmeTemplate(), - TestsInitTemplate(), - AppsettingsTemplate(), - MainInitTemplate(project_name, os.path.join('src/', project_name_snake)) - ] - else: - project_path = os.path.join( - os.path.dirname(project_path), - project_name_snake - ) - - templates: list[TemplateFileABC] = [ - AppsettingsTemplate(), - MainInitTemplate('', '') - ] - - if not os.path.isdir(project_path): - os.makedirs(project_path) - - py_src_rel_path = '' - src_name = project_name_snake - if workspace is None: - py_src_rel_path = f'src/{src_name}' - - if use_application_api: - templates.append(ApplicationTemplate(src_name, py_src_rel_path, use_async)) - - if use_startup: - templates.append(StartupTemplate(src_name, py_src_rel_path)) - templates.append(MainWithApplicationHostAndStartupTemplate(src_name, py_src_rel_path, use_async)) - else: - templates.append(MainWithApplicationBaseTemplate(src_name, py_src_rel_path, use_async)) - else: - if use_service_providing: - templates.append(MainWithDependencyInjection(src_name, py_src_rel_path, use_async)) - else: - templates.append(MainWithoutApplicationBaseTemplate(src_name, py_src_rel_path, use_async)) - - src_rel_path = '' - if '/' in project_name: - old_pj_name = project_name - parts = project_name.split('/') - project_name = parts[len(parts) - 1] - src_rel_path = old_pj_name.split(project_name)[0] - - proj_name = project_name - if src_rel_path.endswith('/'): - src_rel_path = src_rel_path[:len(src_rel_path) - 1] - - if src_rel_path != '': - proj_name = f'{src_rel_path}/{project_name}' - if workspace is not None: - proj_name = project_name_snake - - if src_rel_path != '': - project_file_path = f'{src_rel_path}/{project_name_snake}/{project_name}.json' - else: - project_file_path = f'{project_name_snake}/{project_name}.json' - - if workspace is None: - src_path = f'src/{project_name_snake}' - workspace_file_path = f'{proj_name}/cpl-workspace.json' - project_file_rel_path = f'{src_path}/{project_name}.json' - project_file_path = f'{proj_name}/{src_path}/{project_name}.json' - cls._create_workspace( - workspace_file_path, - project_name, - { - project_name: project_file_rel_path - }, - {} - ) - - else: - workspace.projects[project_name] = f'src/{project_file_path}' - cls._create_workspace('cpl-workspace.json', workspace.default_project, workspace.projects, workspace.scripts) - - Console.spinner( - f'Creating {project_file_path}', - cls._create_file, - project_file_path if workspace is None else f'src/{project_file_path}', - project_settings, - text_foreground_color=ForegroundColorEnum.green, - spinner_foreground_color=ForegroundColorEnum.cyan - ) - - for template in templates: - divider = '' - if template.path != '' and not template.path.endswith('/'): - divider = '/' - - Console.spinner( - f'Creating {proj_name}/{template.path}{divider}{template.name}', - TemplateBuilder.build, - project_path, - template, - text_foreground_color=ForegroundColorEnum.green, - spinner_foreground_color=ForegroundColorEnum.cyan - ) diff --git a/src/cpl_cli/source_creator/library_builder.py b/src/cpl_cli/source_creator/library_builder.py deleted file mode 100644 index 702aa449..00000000 --- a/src/cpl_cli/source_creator/library_builder.py +++ /dev/null @@ -1,186 +0,0 @@ -import json -import os -from typing import Optional - -from cpl_core.console.foreground_color_enum import ForegroundColorEnum -from cpl_core.console.console import Console -from cpl_core.utils.string import String -from cpl_cli.configuration.workspace_settings import WorkspaceSettings -from cpl_cli.configuration.workspace_settings_name_enum import WorkspaceSettingsNameEnum -from cpl_cli.source_creator.template_builder import TemplateBuilder -from cpl_cli._templates.new.library.appsettings_json import AppsettingsTemplate -from cpl_cli._templates.new.library.license import LicenseTemplate -from cpl_cli._templates.new.library.readme_py import ReadmeTemplate -from cpl_cli._templates.new.library.source.name.application import ApplicationTemplate -from cpl_cli._templates.new.library.source.name.init import NameInitTemplate -from cpl_cli._templates.new.library.source.name.main import MainWithApplicationHostAndStartupTemplate, \ - MainWithoutApplicationBaseTemplate, MainWithApplicationBaseTemplate, MainWithDependencyInjection -from cpl_cli._templates.new.library.source.name.startup import StartupTemplate -from cpl_cli._templates.new.library.source.tests.init import TestsInitTemplate -from cpl_cli._templates.template_file_abc import TemplateFileABC - - -class LibraryBuilder: - - def __init__(self): - pass - - @staticmethod - def _create_file(file_name: str, content: dict): - if not os.path.isabs(file_name): - file_name = os.path.abspath(file_name) - - path = os.path.dirname(file_name) - if not os.path.isdir(path): - os.makedirs(path) - - with open(file_name, 'w') as project_json: - project_json.write(json.dumps(content, indent=2)) - project_json.close() - - @classmethod - def _create_workspace(cls, path: str, project_name, projects: dict, scripts: dict): - ws_dict = { - WorkspaceSettings.__name__: { - WorkspaceSettingsNameEnum.default_project.value: project_name, - WorkspaceSettingsNameEnum.projects.value: projects, - WorkspaceSettingsNameEnum.scripts.value: scripts, - } - } - - Console.spinner( - f'Creating {path}', - cls._create_file, - path, - ws_dict, - text_foreground_color=ForegroundColorEnum.green, - spinner_foreground_color=ForegroundColorEnum.cyan - ) - - @classmethod - def build(cls, project_path: str, use_application_api: bool, use_startup: bool, - use_async: bool, use_service_providing: bool, project_name: str, project_settings: dict, - workspace: Optional[WorkspaceSettings]): - """ - Builds the library project files - :param project_path: - :param use_application_api: - :param use_startup: - :param use_service_providing: - :param use_async: - :param project_name: - :param project_settings: - :param workspace: - :return: - """ - pj_name = project_name - if '/' in pj_name: - pj_name = pj_name.split('/')[len(pj_name.split('/')) - 1] - - project_name_snake = String.convert_to_snake_case(pj_name) - - if workspace is None: - templates: list[TemplateFileABC] = [ - LicenseTemplate(), - ReadmeTemplate(), - TestsInitTemplate(), - NameInitTemplate(project_name, os.path.join( - 'src/', project_name_snake)), - AppsettingsTemplate() - ] - else: - project_path = os.path.join( - os.path.dirname(project_path), - project_name_snake - ) - - templates: list[TemplateFileABC] = [ - LicenseTemplate(), - ReadmeTemplate(), - NameInitTemplate('', ''), - AppsettingsTemplate() - ] - - if not os.path.isdir(project_path): - os.makedirs(project_path) - - py_src_rel_path = '' - src_name = project_name_snake - if workspace is None: - py_src_rel_path = f'src/{src_name}' - - if use_application_api: - templates.append(ApplicationTemplate(src_name, py_src_rel_path, use_async)) - - if use_startup: - templates.append(StartupTemplate(src_name, py_src_rel_path)) - templates.append(MainWithApplicationHostAndStartupTemplate(src_name, py_src_rel_path, use_async)) - else: - templates.append(MainWithApplicationBaseTemplate(src_name, py_src_rel_path, use_async)) - else: - if use_service_providing: - templates.append(MainWithDependencyInjection(src_name, py_src_rel_path, use_async)) - else: - templates.append(MainWithoutApplicationBaseTemplate(src_name, py_src_rel_path, use_async)) - - src_rel_path = '' - if '/' in project_name: - old_pj_name = project_name - parts = project_name.split('/') - project_name = parts[len(parts) - 1] - src_rel_path = old_pj_name.split(project_name)[0] - - proj_name = project_name - if src_rel_path.endswith('/'): - src_rel_path = src_rel_path[:len(src_rel_path) - 1] - - if src_rel_path != '': - proj_name = f'{src_rel_path}/{project_name}' - if workspace is not None: - proj_name = project_name_snake - - if src_rel_path != '': - project_file_path = f'{src_rel_path}/{project_name_snake}/{project_name}.json' - else: - project_file_path = f'{project_name_snake}/{project_name}.json' - - if workspace is None: - src_path = f'src/{project_name_snake}' - workspace_file_path = f'{proj_name}/cpl-workspace.json' - project_file_rel_path = f'{src_path}/{project_name}.json' - project_file_path = f'{proj_name}/{src_path}/{project_name}.json' - cls._create_workspace( - workspace_file_path, - project_name, - { - project_name: project_file_rel_path - }, - {} - ) - - else: - workspace.projects[project_name] = f'src/{project_file_path}' - cls._create_workspace('cpl-workspace.json', workspace.default_project, workspace.projects, workspace.scripts) - - Console.spinner( - f'Creating {project_file_path}', - cls._create_file, - project_file_path if workspace is None else f'src/{project_file_path}', - project_settings, - text_foreground_color=ForegroundColorEnum.green, - spinner_foreground_color=ForegroundColorEnum.cyan - ) - - for template in templates: - divider = '' - if template.path != '' and not template.path.endswith('/'): - divider = '/' - - Console.spinner( - f'Creating {proj_name}/{template.path}{divider}{template.name}', - TemplateBuilder.build, - project_path, - template, - text_foreground_color=ForegroundColorEnum.green, - spinner_foreground_color=ForegroundColorEnum.cyan - ) diff --git a/src/cpl_cli/source_creator/template_builder.py b/src/cpl_cli/source_creator/template_builder.py index c661cd7a..798b4a9b 100644 --- a/src/cpl_cli/source_creator/template_builder.py +++ b/src/cpl_cli/source_creator/template_builder.py @@ -1,8 +1,6 @@ import json import os -from typing import Union -from cpl_cli._templates.template_file_abc import TemplateFileABC from cpl_cli.abc.file_template_abc import FileTemplateABC from cpl_cli.configuration import WorkspaceSettings, WorkspaceSettingsNameEnum from cpl_core.console import Console, ForegroundColorEnum @@ -11,7 +9,7 @@ from cpl_core.console import Console, ForegroundColorEnum class TemplateBuilder: @staticmethod - def _create_file(file_name: str, content: dict): + def build_cpl_file(file_name: str, content: dict): if not os.path.isabs(file_name): file_name = os.path.abspath(file_name) @@ -35,7 +33,7 @@ class TemplateBuilder: Console.spinner( f'Creating {path}', - cls._create_file, + cls.build_cpl_file, path, ws_dict, text_foreground_color=ForegroundColorEnum.green, @@ -43,14 +41,13 @@ class TemplateBuilder: ) @staticmethod - def build(project_path: str, template: Union[TemplateFileABC, FileTemplateABC]): + def build(file_path: str, template: FileTemplateABC): """ Creates template - :param project_path: + :param file_path: :param template: :return: """ - file_path = os.path.join(project_path, template.path, template.name) if not os.path.isdir(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) diff --git a/src/cpl_cli/source_creator/unittest_builder.py b/src/cpl_cli/source_creator/unittest_builder.py deleted file mode 100644 index 805c6363..00000000 --- a/src/cpl_cli/source_creator/unittest_builder.py +++ /dev/null @@ -1,164 +0,0 @@ -import json -import os -from typing import Optional - -from cpl_cli._templates.new.unittest.license import LicenseTemplate -from cpl_cli._templates.new.unittest.readme_py import ReadmeTemplate -from cpl_cli._templates.new.unittest.source.name.application import ApplicationTemplate -from cpl_cli._templates.new.unittest.source.name.init import MainInitTemplate -from cpl_cli._templates.new.unittest.source.name.main import MainWithApplicationBaseTemplate -from cpl_cli._templates.new.unittest.source.name.test_case import TestCaseTemplate -from cpl_cli._templates.template_file_abc import TemplateFileABC -from cpl_cli.configuration.workspace_settings import WorkspaceSettings -from cpl_cli.configuration.workspace_settings_name_enum import WorkspaceSettingsNameEnum -from cpl_cli.source_creator.template_builder import TemplateBuilder -from cpl_core.console.console import Console -from cpl_core.console.foreground_color_enum import ForegroundColorEnum -from cpl_core.utils.string import String - - -class UnittestBuilder: - - def __init__(self): - pass - - @staticmethod - def _create_file(file_name: str, content: dict): - if not os.path.isabs(file_name): - file_name = os.path.abspath(file_name) - - path = os.path.dirname(file_name) - if not os.path.isdir(path): - os.makedirs(path) - - with open(file_name, 'w') as project_json: - project_json.write(json.dumps(content, indent=2)) - project_json.close() - - @classmethod - def _create_workspace(cls, path: str, project_name, projects: dict, scripts: dict): - ws_dict = { - WorkspaceSettings.__name__: { - WorkspaceSettingsNameEnum.default_project.value: project_name, - WorkspaceSettingsNameEnum.projects.value: projects, - WorkspaceSettingsNameEnum.scripts.value: scripts - } - } - - Console.spinner( - f'Creating {path}', - cls._create_file, - path, - ws_dict, - text_foreground_color=ForegroundColorEnum.green, - spinner_foreground_color=ForegroundColorEnum.cyan - ) - - @classmethod - def build(cls, project_path: str, use_application_api: bool, - use_async: bool, project_name: str, project_settings: dict, workspace: Optional[WorkspaceSettings]): - """ - Builds the console project files - :param project_path: - :param use_application_api: - :param use_async: - :param project_name: - :param project_settings: - :param workspace: - :return: - """ - pj_name = project_name - if '/' in pj_name: - pj_name = pj_name.split('/')[len(pj_name.split('/')) - 1] - - project_name_snake = String.convert_to_snake_case(pj_name) - - if workspace is None: - templates: list[TemplateFileABC] = [ - LicenseTemplate(), - ReadmeTemplate(), - MainInitTemplate(project_name, os.path.join('src/', project_name_snake)) - ] - else: - project_path = os.path.join( - os.path.dirname(project_path), - project_name_snake - ) - - templates: list[TemplateFileABC] = [ - MainInitTemplate('', '') - ] - - if not os.path.isdir(project_path): - os.makedirs(project_path) - - py_src_rel_path = '' - src_name = project_name_snake - if workspace is None: - py_src_rel_path = f'src/{src_name}' - - templates.append(ApplicationTemplate(src_name, py_src_rel_path, use_async)) - templates.append(MainWithApplicationBaseTemplate(src_name, py_src_rel_path, use_async)) - templates.append(TestCaseTemplate(src_name, py_src_rel_path, use_async)) - - src_rel_path = '' - if '/' in project_name: - old_pj_name = project_name - parts = project_name.split('/') - project_name = parts[len(parts) - 1] - src_rel_path = old_pj_name.split(project_name)[0] - - proj_name = project_name - if src_rel_path.endswith('/'): - src_rel_path = src_rel_path[:len(src_rel_path) - 1] - - if src_rel_path != '': - proj_name = f'{src_rel_path}/{project_name}' - if workspace is not None: - proj_name = project_name_snake - - if src_rel_path != '': - project_file_path = f'{src_rel_path}/{project_name_snake}/{project_name}.json' - else: - project_file_path = f'{project_name_snake}/{project_name}.json' - - if workspace is None: - src_path = f'src/{project_name_snake}' - workspace_file_path = f'{proj_name}/cpl-workspace.json' - project_file_rel_path = f'{src_path}/{project_name}.json' - project_file_path = f'{proj_name}/{src_path}/{project_name}.json' - cls._create_workspace( - workspace_file_path, - project_name, - { - project_name: project_file_rel_path - }, - {} - ) - - else: - workspace.projects[project_name] = f'src/{project_file_path}' - cls._create_workspace('cpl-workspace.json', workspace.default_project, workspace.projects, workspace.scripts) - - Console.spinner( - f'Creating {project_file_path}', - cls._create_file, - project_file_path if workspace is None else f'src/{project_file_path}', - project_settings, - text_foreground_color=ForegroundColorEnum.green, - spinner_foreground_color=ForegroundColorEnum.cyan - ) - - for template in templates: - divider = '' - if template.path != '' and not template.path.endswith('/'): - divider = '/' - - Console.spinner( - f'Creating {proj_name}/{template.path}{divider}{template.name}', - TemplateBuilder.build, - project_path, - template, - text_foreground_color=ForegroundColorEnum.green, - spinner_foreground_color=ForegroundColorEnum.cyan - ) diff --git a/unittests/unittests_cli/abc/command_test_case.py b/unittests/unittests_cli/abc/command_test_case.py index 3b609cab..6f216e00 100644 --- a/unittests/unittests_cli/abc/command_test_case.py +++ b/unittests/unittests_cli/abc/command_test_case.py @@ -7,6 +7,7 @@ from unittests_cli.constants import PLAYGROUND_PATH class CommandTestCase(unittest.TestCase): + _skip_tear_down = False def __init__(self, method_name: str): unittest.TestCase.__init__(self, method_name) @@ -18,7 +19,8 @@ class CommandTestCase(unittest.TestCase): if os.path.exists(PLAYGROUND_PATH): shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH))) - os.makedirs(PLAYGROUND_PATH) + if not os.path.exists(PLAYGROUND_PATH): + os.makedirs(PLAYGROUND_PATH) os.chdir(PLAYGROUND_PATH) except Exception as e: print(f'Setup of {__name__} failed: {traceback.format_exc()}') @@ -28,6 +30,8 @@ class CommandTestCase(unittest.TestCase): @classmethod def tearDownClass(cls): + if cls._skip_tear_down: + return try: if os.path.exists(PLAYGROUND_PATH): shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH))) diff --git a/unittests/unittests_cli/add_test_case.py b/unittests/unittests_cli/add_test_case.py index 18efb1bd..e78ade03 100644 --- a/unittests/unittests_cli/add_test_case.py +++ b/unittests/unittests_cli/add_test_case.py @@ -28,7 +28,7 @@ class AddTestCase(CommandTestCase): # create projects CLICommands.new('console', self._source, '--ab', '--s') os.chdir(os.path.join(os.getcwd(), self._source)) - CLICommands.new('console', self._target, '--ab', '--s') + CLICommands.new('library', self._target, '--ab', '--s') def test_add(self): CLICommands.add(self._source, self._target) diff --git a/unittests/unittests_cli/new_test_case.py b/unittests/unittests_cli/new_test_case.py index 21191333..22c830f3 100644 --- a/unittests/unittests_cli/new_test_case.py +++ b/unittests/unittests_cli/new_test_case.py @@ -1,5 +1,6 @@ import json import os +import unittest from cpl_core.utils import String from unittests_cli.abc.command_test_case import CommandTestCase @@ -32,8 +33,8 @@ class NewTestCase(CommandTestCase): project_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, base, name, 'src/', String.convert_to_snake_case(name))) self.assertTrue(os.path.exists(project_path)) - self.assertTrue(os.path.join(project_path, f'{name}.json')) - self.assertTrue(os.path.join(project_path, f'main.py')) + self.assertTrue(os.path.exists(os.path.join(project_path, f'{name}.json'))) + self.assertTrue(os.path.exists(os.path.join(project_path, f'main.py'))) if '--ab' in args: self.assertTrue(os.path.isfile(os.path.join(project_path, f'application.py'))) @@ -110,23 +111,23 @@ class NewTestCase(CommandTestCase): def test_console_without_anything(self): self._test_project('console', 'test-console-without-anything', '--n') - def test_sub_console(self): + def test_console_sub(self): self._test_sub_project('console', 'test-sub-console', 'test-console', '--ab', '--s', '--sp', '--venv', test_venv=True) - def test_sub_console_with_other_base(self): + def test_console_sub_with_other_base(self): self._test_sub_project('console', 'tools/test-sub-console', 'test-console', '--ab', '--s', '--sp', '--venv', '--base', test_venv=True) def test_library(self): self._test_project('library', 'test-library', '--ab', '--s', '--sp') - def test_sub_library(self): + def test_library_sub(self): self._test_sub_project('library', 'test-sub-library', 'test-console', '--ab', '--s', '--sp') - def test_sub_directory_library(self): + def test_library_sub_directory(self): self._test_sub_directory_project('library', 'directory', 'test-sub-library', 'test-console', '--ab', '--s', '--sp') def test_unittest(self): self._test_project('unittest', 'test-unittest', '--ab') - def test_sub_unittest(self): + def test_unittest_sub(self): self._test_sub_project('unittest', 'test-unittest', 'test-console', '--ab', '--s', '--sp') diff --git a/unittests/unittests_cli/publish_test_case.py b/unittests/unittests_cli/publish_test_case.py index 9992626b..c22dfba5 100644 --- a/unittests/unittests_cli/publish_test_case.py +++ b/unittests/unittests_cli/publish_test_case.py @@ -12,6 +12,7 @@ from unittests_shared.cli_commands import CLICommands class PublishTestCase(CommandTestCase): + CommandTestCase._skip_tear_down = True def __init__(self, method_name: str): CommandTestCase.__init__(self, method_name) @@ -26,6 +27,14 @@ class PublishTestCase(CommandTestCase): return project_json + def _get_appsettings(self): + with open(os.path.join(os.getcwd(), os.path.dirname(self._project_file), 'appsettings.json'), 'r', encoding='utf-8') as cfg: + # load json + project_json = json.load(cfg) + cfg.close() + + return project_json + def _save_project_settings(self, settings: dict): with open(os.path.join(os.getcwd(), self._project_file), 'w', encoding='utf-8') as project_file: project_file.write(json.dumps(settings, indent=2)) @@ -34,7 +43,7 @@ class PublishTestCase(CommandTestCase): def setUp(self): if not os.path.exists(PLAYGROUND_PATH): os.makedirs(PLAYGROUND_PATH) - + os.chdir(PLAYGROUND_PATH) # create projects CLICommands.new('console', self._source, '--ab', '--s') @@ -86,4 +95,8 @@ class PublishTestCase(CommandTestCase): with open(f'{full_dist_path}/{self._source}.json', 'w') as file: file.write(json.dumps(self._get_project_settings(), indent=2)) file.close() + + with open(f'{full_dist_path}/appsettings.json', 'w') as file: + file.write(json.dumps(self._get_appsettings(), indent=2)) + file.close() self.assertTrue(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) -- 2.45.1 From 6d2492c1cff293929b29683a249f25cf4bc2a9ca Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 7 Dec 2022 13:06:50 +0100 Subject: [PATCH 34/63] Added generic typing to configuration #141 --- src/cpl_core/configuration/configuration.py | 6 +++--- src/cpl_core/configuration/configuration_abc.py | 8 ++++---- src/cpl_core/typing.py | 3 +++ 3 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 src/cpl_core/typing.py diff --git a/src/cpl_core/configuration/configuration.py b/src/cpl_core/configuration/configuration.py index dbe2574f..b395a826 100644 --- a/src/cpl_core/configuration/configuration.py +++ b/src/cpl_core/configuration/configuration.py @@ -22,6 +22,7 @@ from cpl_core.dependency_injection.service_provider_abc import ServiceProviderAB 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 +from cpl_core.typing import T class Configuration(ConfigurationABC): @@ -267,7 +268,7 @@ class Configuration(ConfigurationABC): configuration.from_dict(value) self.add_configuration(sub, configuration) - def add_configuration(self, key_type: Union[str, type], value: Union[str, ConfigurationModelABC]): + def add_configuration(self, key_type: Union[str, type], value: any): self._config[key_type] = value def create_console_argument(self, arg_type: ArgumentTypeEnum, token: str, name: str, aliases: list[str], @@ -280,8 +281,7 @@ class Configuration(ConfigurationABC): for arg in self._argument_types: call(arg) - def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> \ - Optional[Union[str, ConfigurationModelABC]]: + def get_configuration(self, search_type: Type[T]) -> Optional[T]: if type(search_type) is str: if search_type == ConfigurationVariableNameEnum.environment.value: return self._application_environment.environment_name diff --git a/src/cpl_core/configuration/configuration_abc.py b/src/cpl_core/configuration/configuration_abc.py index caadc15f..4007a1ad 100644 --- a/src/cpl_core/configuration/configuration_abc.py +++ b/src/cpl_core/configuration/configuration_abc.py @@ -6,6 +6,7 @@ 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 +from cpl_core.typing import T class ConfigurationABC(ABC): @@ -75,14 +76,14 @@ class ConfigurationABC(ABC): pass @abstractmethod - def add_configuration(self, key_type: Union[str, type], value: Union[str, ConfigurationModelABC]): + def add_configuration(self, key_type: Union[str, type], value: any): r"""Add configuration object Parameter --------- key_type: Union[:class:`str`, :class:`type`] Type of the value - value: Union[:class:`str`, :class:`cpl_core.configuration.configuration_model_abc.ConfigurationModelABC`] + value: any Object of the value """ pass @@ -125,8 +126,7 @@ class ConfigurationABC(ABC): pass @abstractmethod - def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> Union[ - str, ConfigurationModelABC]: + def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> Optional[T]: r"""Returns value from configuration by given type Parameter diff --git a/src/cpl_core/typing.py b/src/cpl_core/typing.py new file mode 100644 index 00000000..853073b5 --- /dev/null +++ b/src/cpl_core/typing.py @@ -0,0 +1,3 @@ +from typing import TypeVar + +T = TypeVar('T') -- 2.45.1 From 42fb88c35d9a6457b3e545b120bf111d83540bba Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 7 Dec 2022 15:45:10 +0100 Subject: [PATCH 35/63] Removed old new command #139 --- src/cpl_cli/command/new_old_service.py | 356 ------------------------- 1 file changed, 356 deletions(-) delete mode 100644 src/cpl_cli/command/new_old_service.py diff --git a/src/cpl_cli/command/new_old_service.py b/src/cpl_cli/command/new_old_service.py deleted file mode 100644 index 5715f5cd..00000000 --- a/src/cpl_cli/command/new_old_service.py +++ /dev/null @@ -1,356 +0,0 @@ -import os -import sys -import textwrap -from typing import Optional - -from packaging import version - -import cpl_cli -import cpl_core -from cpl_cli.configuration.venv_helper_service import VenvHelper -from cpl_cli.source_creator.unittest_builder import UnittestBuilder - -from cpl_core.configuration.configuration_abc import ConfigurationABC -from cpl_core.console.foreground_color_enum import ForegroundColorEnum -from cpl_core.console.console import Console -from cpl_core.utils.string import String -from cpl_cli.command_abc import CommandABC -from cpl_cli.configuration.build_settings import BuildSettings -from cpl_cli.configuration.build_settings_name_enum import BuildSettingsNameEnum -from cpl_cli.configuration.project_settings import ProjectSettings -from cpl_cli.configuration.project_settings_name_enum import ProjectSettingsNameEnum -from cpl_cli.configuration.project_type_enum import ProjectTypeEnum -from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum -from cpl_cli.configuration.workspace_settings import WorkspaceSettings -from cpl_cli.source_creator.console_builder import ConsoleBuilder -from cpl_cli.source_creator.library_builder import LibraryBuilder - - -class NewService(CommandABC): - - def __init__(self, configuration: ConfigurationABC): - """ - Service for the CLI command new - :param configuration: - """ - CommandABC.__init__(self) - - self._config = configuration - self._env = self._config.environment - - self._workspace: WorkspaceSettings = self._config.get_configuration(WorkspaceSettings) - self._project: ProjectSettings = ProjectSettings() - self._project_dict = {} - self._build: BuildSettings = BuildSettings() - self._build_dict = {} - self._project_json = {} - - self._name: str = '' - self._rel_path: str = '' - self._schematic: ProjectTypeEnum = ProjectTypeEnum.console - self._use_nothing: bool = False - self._use_application_api: bool = False - self._use_startup: bool = False - self._use_service_providing: bool = False - self._use_async: bool = False - self._use_venv: bool = False - self._use_base: bool = False - - @property - def help_message(self) -> str: - return textwrap.dedent("""\ - Generates a workspace and initial project or add a project to workspace. - Usage: cpl new - - Arguments: - type The project type of the initial project - name Name of the workspace or the project - - Types: - console (c|C) - library (l|L) - unittest (ut|UT) - """) - - def _create_project_settings(self): - self._rel_path = os.path.dirname(self._name) - self._project_dict = { - ProjectSettingsNameEnum.name.value: os.path.basename(self._name), - ProjectSettingsNameEnum.version.value: { - VersionSettingsNameEnum.major.value: '0', - VersionSettingsNameEnum.minor.value: '0', - VersionSettingsNameEnum.micro.value: '0' - }, - ProjectSettingsNameEnum.author.value: '', - ProjectSettingsNameEnum.author_email.value: '', - ProjectSettingsNameEnum.description.value: '', - ProjectSettingsNameEnum.long_description.value: '', - ProjectSettingsNameEnum.url.value: '', - ProjectSettingsNameEnum.copyright_date.value: '', - ProjectSettingsNameEnum.copyright_name.value: '', - ProjectSettingsNameEnum.license_name.value: '', - ProjectSettingsNameEnum.license_description.value: '', - ProjectSettingsNameEnum.dependencies.value: [ - f'cpl-core>={version.parse(cpl_core.__version__)}' - ], - ProjectSettingsNameEnum.dev_dependencies.value: [ - f'cpl-cli>={version.parse(cpl_cli.__version__)}' - ], - ProjectSettingsNameEnum.python_version.value: f'>={sys.version.split(" ")[0]}', - ProjectSettingsNameEnum.python_path.value: { - sys.platform: '../../venv/bin/python' if self._use_venv else '' - }, - ProjectSettingsNameEnum.classifiers.value: [] - } - - self._project.from_dict(self._project_dict) - - def _create_build_settings(self): - self._build_dict = { - BuildSettingsNameEnum.project_type.value: self._schematic, - BuildSettingsNameEnum.source_path.value: '', - BuildSettingsNameEnum.output_path.value: '../../dist', - BuildSettingsNameEnum.main.value: f'{String.convert_to_snake_case(self._project.name)}.main', - BuildSettingsNameEnum.entry_point.value: self._project.name, - BuildSettingsNameEnum.include_package_data.value: False, - BuildSettingsNameEnum.included.value: [], - BuildSettingsNameEnum.excluded.value: [ - '*/__pycache__', - '*/logs', - '*/tests' - ], - BuildSettingsNameEnum.package_data.value: {}, - BuildSettingsNameEnum.project_references.value: [] - } - self._build.from_dict(self._build_dict) - - def _create_project_json(self): - """ - Creates cpl.json content - :return: - """ - self._project_json = { - ProjectSettings.__name__: self._project_dict, - BuildSettings.__name__: self._build_dict - } - - def _get_project_path(self) -> Optional[str]: - """ - Gets project path - :return: - """ - if self._workspace is None: - project_path = os.path.join(self._env.working_directory, self._rel_path, self._project.name) - else: - base = '' if self._use_base else 'src' - project_path = os.path.join(self._env.working_directory, base, self._rel_path, String.convert_to_snake_case(self._project.name)) - - if os.path.isdir(project_path) and len(os.listdir(project_path)) > 0: - Console.write_line(project_path) - Console.error('Project path is not empty\n') - return None - - return project_path - - def _get_project_information(self, is_unittest=False): - """ - Gets project information's from user - :return: - """ - if self._use_application_api or self._use_startup or self._use_service_providing or self._use_async or self._use_nothing: - Console.set_foreground_color(ForegroundColorEnum.default) - Console.write_line('Skipping question due to given flags') - return - - if not is_unittest: - self._use_application_api = Console.read('Do you want to use application base? (y/n) ').lower() == 'y' - - if not is_unittest and self._use_application_api: - self._use_startup = Console.read('Do you want to use startup? (y/n) ').lower() == 'y' - - if not is_unittest and not self._use_application_api: - self._use_service_providing = Console.read('Do you want to use service providing? (y/n) ').lower() == 'y' - - if not self._use_async: - self._use_async = Console.read('Do you want to use async? (y/n) ').lower() == 'y' - - Console.set_foreground_color(ForegroundColorEnum.default) - - def _console(self, args: list[str]): - """ - Generates new console project - :param args: - :return: - """ - self._create_project_settings() - self._create_build_settings() - self._create_project_json() - path = self._get_project_path() - if path is None: - return - - self._get_project_information() - project_name = self._project.name - if self._rel_path != '': - project_name = f'{self._rel_path}/{project_name}' - try: - ConsoleBuilder.build( - path, - self._use_application_api, - self._use_startup, - self._use_service_providing, - self._use_async, - project_name, - self._project_json, - self._workspace - ) - except Exception as e: - Console.error('Could not create project', str(e)) - - def _unittest(self, args: list[str]): - """ - Generates new unittest project - :param args: - :return: - """ - self._create_project_settings() - self._create_build_settings() - self._create_project_json() - path = self._get_project_path() - if path is None: - return - - self._get_project_information(is_unittest=True) - project_name = self._project.name - if self._rel_path != '': - project_name = f'{self._rel_path}/{project_name}' - try: - UnittestBuilder.build( - path, - self._use_application_api, - self._use_async, - project_name, - self._project_json, - self._workspace - ) - except Exception as e: - Console.error('Could not create project', str(e)) - - def _library(self, args: list[str]): - """ - Generates new library project - :param args: - :return: - """ - self._create_project_settings() - self._create_build_settings() - self._create_project_json() - path = self._get_project_path() - if path is None: - return - - self._get_project_information() - project_name = self._project.name - if self._rel_path != '': - project_name = f'{self._rel_path}/{project_name}' - try: - LibraryBuilder.build( - path, - self._use_application_api, - self._use_startup, - self._use_service_providing, - self._use_async, - project_name, - self._project_json, - self._workspace - ) - except Exception as e: - Console.error('Could not create project', str(e)) - - def _create_venv(self): - - project = self._project.name - if self._workspace is not None: - project = self._workspace.default_project - - if self._env.working_directory.endswith(project): - project = '' - - if self._workspace is None and self._use_base: - project = f'{self._rel_path}/{project}' - - VenvHelper.init_venv( - False, - self._env, - self._project, - explicit_path=os.path.join(self._env.working_directory, project, self._project.python_executable.replace('../', '')) - ) - - def execute(self, args: list[str]): - """ - Entry point of command - :param args: - :return: - """ - if 'nothing' in args: - self._use_nothing = True - self._use_async = False - self._use_application_api = False - self._use_startup = False - self._use_service_providing = False - if 'async' in args: - args.remove('async') - if 'application-base' in args: - args.remove('application-base') - if 'startup' in args: - args.remove('startup') - if 'service-providing' in args: - args.remove('service-providing') - - if 'async' in args: - self._use_async = True - args.remove('async') - if 'application-base' in args: - self._use_application_api = True - args.remove('application-base') - if 'startup' in args: - self._use_startup = True - args.remove('startup') - if 'service-providing' in args: - self._use_service_providing = True - args.remove('service-providing') - if 'venv' in args: - self._use_venv = True - args.remove('venv') - if 'base' in args: - self._use_base = True - args.remove('base') - - console = self._config.get_configuration(ProjectTypeEnum.console.value) - library = self._config.get_configuration(ProjectTypeEnum.library.value) - unittest = self._config.get_configuration(ProjectTypeEnum.unittest.value) - if console is not None and library is None and unittest is None: - self._name = console - self._schematic = ProjectTypeEnum.console.value - self._console(args) - if self._use_venv: - self._create_venv() - - elif console is None and library is not None and unittest is None: - self._name = library - self._schematic = ProjectTypeEnum.library.value - self._library(args) - if self._use_venv: - self._create_venv() - - elif console is None and library is None and unittest is not None: - self._name = unittest - self._schematic = ProjectTypeEnum.unittest.value - self._unittest(args) - if self._use_venv: - self._create_venv() - - else: - Console.error(f'Project type not found') - Console.write_line(self.help_message) - return -- 2.45.1 From fe8ffb2839fd72e0e7810b6e9d88a9b978b9d9b7 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 7 Dec 2022 15:46:32 +0100 Subject: [PATCH 36/63] Removed comments #139 --- src/cpl_cli/publish/publisher_service.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cpl_cli/publish/publisher_service.py b/src/cpl_cli/publish/publisher_service.py index ca1a5382..b1639023 100644 --- a/src/cpl_cli/publish/publisher_service.py +++ b/src/cpl_cli/publish/publisher_service.py @@ -404,7 +404,7 @@ class PublisherService(PublisherABC): f'--bdist-dir={os.path.join(self._output_path, "bdist")}', f'--dist-dir={os.path.join(self._output_path, "setup")}' ]) - # os.remove(setup_py) + os.remove(setup_py) except Exception as e: Console.error('Executing setup.py failed', str(e)) @@ -492,10 +492,10 @@ class PublisherService(PublisherABC): Console.write_line('Running setup.py:\n') self._run_setup() - # Console.spinner( - # 'Cleaning dist path:', - # self._clean_dist_files, - # text_foreground_color=ForegroundColorEnum.green, - # spinner_foreground_color=ForegroundColorEnum.blue - # ) + Console.spinner( + 'Cleaning dist path:', + self._clean_dist_files, + text_foreground_color=ForegroundColorEnum.green, + spinner_foreground_color=ForegroundColorEnum.blue + ) Console.write_line() -- 2.45.1 From 1ca459e67add989cf351ba428e97377022ee1e74 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 7 Dec 2022 15:48:37 +0100 Subject: [PATCH 37/63] Removed skip test case #139 --- unittests/unittests_cli/publish_test_case.py | 1 - 1 file changed, 1 deletion(-) diff --git a/unittests/unittests_cli/publish_test_case.py b/unittests/unittests_cli/publish_test_case.py index c22dfba5..5d6a8f75 100644 --- a/unittests/unittests_cli/publish_test_case.py +++ b/unittests/unittests_cli/publish_test_case.py @@ -12,7 +12,6 @@ from unittests_shared.cli_commands import CLICommands class PublishTestCase(CommandTestCase): - CommandTestCase._skip_tear_down = True def __init__(self, method_name: str): CommandTestCase.__init__(self, method_name) -- 2.45.1 From 6818fe9a5c239c4c964c11bee5579bbf761c175f Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 7 Dec 2022 20:06:54 +0100 Subject: [PATCH 38/63] Improved cpl new appsettings template --- src/cpl_cli/.cpl/project_file_appsettings.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/cpl_cli/.cpl/project_file_appsettings.py b/src/cpl_cli/.cpl/project_file_appsettings.py index c6a62b88..dabf4a29 100644 --- a/src/cpl_cli/.cpl/project_file_appsettings.py +++ b/src/cpl_cli/.cpl/project_file_appsettings.py @@ -1,3 +1,5 @@ +import textwrap + from cpl_cli.abc.file_template_abc import FileTemplateABC @@ -8,4 +10,20 @@ class ProjectFileAppsettings(FileTemplateABC): self._name = 'appsettings.json' def get_code(self) -> str: - return self._code + return textwrap.dedent("""\ + { + "TimeFormatSettings": { + "DateFormat": "%Y-%m-%d", + "TimeFormat": "%H:%M:%S", + "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", + "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" + }, + + "LoggingSettings": { + "Path": "logs/", + "Filename": "log_$start_time.log", + "ConsoleLogLevel": "ERROR", + "FileLogLevel": "WARN" + } + } + """) -- 2.45.1 From 4fbb3ec838b5f15ed9e70ceea7fba3308708d558 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 7 Dec 2022 20:12:07 +0100 Subject: [PATCH 39/63] Updated readme --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 103a87b2..a6515be0 100644 --- a/README.md +++ b/README.md @@ -87,17 +87,17 @@ Install the CPL package ```sh -pip install sh_cpl --extra-index-url https://pip.sh-edraft.de +pip install cpl --extra-index-url https://pip.sh-edraft.de ``` Install the CPL CLI ```sh -pip install sh_cpl-cli --extra-index-url https://pip.sh-edraft.de +pip install cpl-cli --extra-index-url https://pip.sh-edraft.de ``` Create workspace: ```sh -cpl new +cpl new ``` Run the application: @@ -110,7 +110,7 @@ cpl start ## Roadmap -See the [open issues](https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib/issues) for a list of proposed features (and known issues). +See the [open issues](https://git.sh-edraft.de/sh-edraft.de/sh_cpl/issues) for a list of proposed features (and known issues). @@ -139,7 +139,7 @@ Distributed under the MIT License. See [LICENSE] for more information. Sven Heidemann - sven.heidemann@sh-edraft.de -Project link: [https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib](https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib) +Project link: [https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib](https://git.sh-edraft.de/sh-edraft.de/sh_cpl) [pip_url]: https://pip.sh-edraft.de @@ -147,7 +147,7 @@ Project link: [https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib](https://g [pip]: https://pypi.org/project/pip/ -[project]: https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib -[quickstart]: https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib/wiki/quickstart -[contributing]: https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib/wiki/contributing +[project]: https://git.sh-edraft.de/sh-edraft.de/sh_cpl +[quickstart]: https://git.sh-edraft.de/sh-edraft.de/sh_cpl/wiki/quickstart +[contributing]: https://git.sh-edraft.de/sh-edraft.de/sh_cpl/wiki/contributing [license]: LICENSE -- 2.45.1 From 2f8dc63cdc0ae81410ed94dc8130e393a3f466d2 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 8 Dec 2022 10:36:23 +0100 Subject: [PATCH 40/63] Added discord command & event to cpl g schematics #143 --- src/cpl_cli/.cpl/schematic_abc.py | 8 ++- src/cpl_cli/command/generate_service.py | 7 ++- src/cpl_cli/command/version_service.py | 15 +---- src/cpl_cli/helper/__init__.py | 0 src/cpl_cli/helper/dependencies.py | 22 +++++++ src/cpl_discord/.cpl/__init__.py | 0 src/cpl_discord/.cpl/schematic_command.py | 44 ++++++++++++++ src/cpl_discord/.cpl/schematic_event.py | 63 ++++++++++++++++++++ src/cpl_discord/events/on_group_join_abc.py | 2 +- tests/custom/general/src/general/__init__.py | 1 + 10 files changed, 146 insertions(+), 16 deletions(-) create mode 100644 src/cpl_cli/helper/__init__.py create mode 100644 src/cpl_cli/helper/dependencies.py create mode 100644 src/cpl_discord/.cpl/__init__.py create mode 100644 src/cpl_discord/.cpl/schematic_command.py create mode 100644 src/cpl_discord/.cpl/schematic_event.py create mode 100644 tests/custom/general/src/general/__init__.py diff --git a/src/cpl_cli/.cpl/schematic_abc.py b/src/cpl_cli/.cpl/schematic_abc.py index aaa74cc3..eaaab12e 100644 --- a/src/cpl_cli/.cpl/schematic_abc.py +++ b/src/cpl_cli/.cpl/schematic_abc.py @@ -1,10 +1,14 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC +from cpl_core.utils import String class ABC(GenerateSchematicABC): - def __init__(self, *args): - GenerateSchematicABC.__init__(self, *args) + def __init__(self, name: str, schematic: str, path: str): + GenerateSchematicABC.__init__(self, name, schematic, path) + self._class_name = name + if name != '': + self._class_name = f'{String.first_to_upper(name.replace(schematic, ""))}ABC' def get_code(self) -> str: code = """\ diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index b1ee7967..a615f095 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -1,3 +1,4 @@ +import importlib import os import sys import textwrap @@ -7,6 +8,7 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC from cpl_cli.command_abc import CommandABC from cpl_cli.configuration import WorkspaceSettings from cpl_cli.configuration.schematic_collection import SchematicCollection +from cpl_cli.helper.dependencies import Dependencies from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.console.console import Console from cpl_core.console.foreground_color_enum import ForegroundColorEnum @@ -33,7 +35,10 @@ class GenerateService(CommandABC): self._env = self._config.environment self._schematics = {} - self._read_custom_schematics_from_path(self._env.runtime_directory) + for package_name in Dependencies.get_cpl_packages(): + package = importlib.import_module(String.convert_to_snake_case(package_name[0])) + self._read_custom_schematics_from_path(os.path.dirname(package.__file__)) + self._read_custom_schematics_from_path(self._env.working_directory) if len(GenerateSchematicABC.__subclasses__()) == 0: diff --git a/src/cpl_cli/command/version_service.py b/src/cpl_cli/command/version_service.py index 3f5d705d..03ae7726 100644 --- a/src/cpl_cli/command/version_service.py +++ b/src/cpl_cli/command/version_service.py @@ -5,6 +5,7 @@ import pkg_resources import textwrap import cpl_cli +from cpl_cli.helper.dependencies import Dependencies from cpl_core.console.console import Console from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_cli.command_abc import CommandABC @@ -31,16 +32,6 @@ class VersionService(CommandABC): :param args: :return: """ - packages = [] - cpl_packages = [] - dependencies = dict(tuple(str(ws).split()) for ws in pkg_resources.working_set) - for p in dependencies: - if str(p).startswith('cpl-'): - cpl_packages.append([p, dependencies[p]]) - continue - - packages.append([p, dependencies[p]]) - Console.set_foreground_color(ForegroundColorEnum.yellow) Console.banner('CPL CLI') Console.set_foreground_color(ForegroundColorEnum.default) @@ -52,6 +43,6 @@ class VersionService(CommandABC): Console.write(f'{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}') Console.write_line(f'OS: {platform.system()} {platform.processor()}') Console.write_line('\nCPL packages:') - Console.table(['Name', 'Version'], cpl_packages) + Console.table(['Name', 'Version'], Dependencies.get_cpl_packages()) Console.write_line('\nPython packages:') - Console.table(['Name', 'Version'], packages) + Console.table(['Name', 'Version'], Dependencies.get_packages()) diff --git a/src/cpl_cli/helper/__init__.py b/src/cpl_cli/helper/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_cli/helper/dependencies.py b/src/cpl_cli/helper/dependencies.py new file mode 100644 index 00000000..80d7cf44 --- /dev/null +++ b/src/cpl_cli/helper/dependencies.py @@ -0,0 +1,22 @@ +import pkg_resources + + +class Dependencies: + _packages = [] + _cpl_packages = [] + + _dependencies = dict(tuple(str(ws).split()) for ws in pkg_resources.working_set) + for p in _dependencies: + if str(p).startswith('cpl-'): + _cpl_packages.append([p, _dependencies[p]]) + continue + + _packages.append([p, _dependencies[p]]) + + @classmethod + def get_cpl_packages(cls) -> list[list]: + return cls._cpl_packages + + @classmethod + def get_packages(cls) -> list[list]: + return cls._packages diff --git a/src/cpl_discord/.cpl/__init__.py b/src/cpl_discord/.cpl/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_discord/.cpl/schematic_command.py b/src/cpl_discord/.cpl/schematic_command.py new file mode 100644 index 00000000..e120aa72 --- /dev/null +++ b/src/cpl_discord/.cpl/schematic_command.py @@ -0,0 +1,44 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Command(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + from cpl_core.logging import LoggerABC + from cpl_discord.command import DiscordCommandABC + from cpl_discord.service import DiscordBotServiceABC + from discord.ext import commands + from discord.ext.commands import Context + + + class $Name(DiscordCommandABC): + + def __init__( + self, + logger: LoggerABC, + bot: DiscordBotServiceABC + ): + DiscordCommandABC.__init__(self) + + self._logger = logger + self._bot = bot + + @commands.hybrid_command() + async def ping(self, ctx: Context): + await ctx.send('Pong') + """ + return self.build_code_str(code, Name=self._class_name) + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'command', + [] + ) diff --git a/src/cpl_discord/.cpl/schematic_event.py b/src/cpl_discord/.cpl/schematic_event.py new file mode 100644 index 00000000..28e2aa85 --- /dev/null +++ b/src/cpl_discord/.cpl/schematic_event.py @@ -0,0 +1,63 @@ +import sys +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC +from cpl_core.console import Console +from cpl_core.utils import String + + +class Command(GenerateSchematicABC): + + def __init__(self, name: str, schematic: str, path: str): + GenerateSchematicABC.__init__(self, name, schematic, path) + + event = None + + from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum + for event_type in DiscordEventTypesEnum: + event_name = event_type.value.__name__.replace("ABC", '') + + if event_name in name: + name = name.replace(event_name, "") + event = event_name + break + + if event is None: + Console.error(f'No valid event found in name {name}') + sys.exit() + + self._event_class = f'{event}ABC' + self._name = f'{String.convert_to_snake_case(name)}_{String.convert_to_snake_case(self._event_class.replace("ABC", ""))}_{schematic}.py' + self._class_name = f'{String.first_to_upper(name)}{self._event_class.replace("ABC", "")}{String.first_to_upper(schematic)}' + + def get_code(self) -> str: + code = """\ + from cpl_core.logging import LoggerABC + from cpl_discord.events import $EventClass + from cpl_discord.service import DiscordBotServiceABC + + + class $Name($EventClass): + + def __init__( + self, + logger: LoggerABC, + bot: DiscordBotServiceABC, + ): + OnReadyABC.__init__(self) + + self._logger = logger + self._bot = bot + + async def on_ready(self): + pass + """ + return self.build_code_str(code, Name=self._class_name, EventClass=self._event_class) + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'event', + [] + ) diff --git a/src/cpl_discord/events/on_group_join_abc.py b/src/cpl_discord/events/on_group_join_abc.py index e0b3aaaf..70fffbb7 100644 --- a/src/cpl_discord/events/on_group_join_abc.py +++ b/src/cpl_discord/events/on_group_join_abc.py @@ -9,4 +9,4 @@ class OnGroupJoinABC(ABC): @abstractmethod async def on_group_join( - self, chhanel: discord.GroupChannel, user: discord.User): pass + self, channel: discord.GroupChannel, user: discord.User): pass diff --git a/tests/custom/general/src/general/__init__.py b/tests/custom/general/src/general/__init__.py new file mode 100644 index 00000000..425ab6c1 --- /dev/null +++ b/tests/custom/general/src/general/__init__.py @@ -0,0 +1 @@ +# imports -- 2.45.1 From 604bb8f55c86168fa3352162ac1d4d7f05c33941 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 8 Dec 2022 11:02:54 +0100 Subject: [PATCH 41/63] Updated discord test app #143 --- .../discord/src/discord_bot/__init__.py | 25 +++++++++++++++++++ .../discord/src/discord_bot/discord-bot.json | 8 +++--- tests/custom/discord/src/discord_bot/main.py | 8 +++--- .../custom/discord/src/discord_bot/startup.py | 3 ++- .../src/modules/hello_world/__init__.py | 25 +++++++++++++++++++ .../src/modules/hello_world/hello-world.json | 8 +++--- 6 files changed, 65 insertions(+), 12 deletions(-) diff --git a/tests/custom/discord/src/discord_bot/__init__.py b/tests/custom/discord/src/discord_bot/__init__.py index ad5eca30..b91b4151 100644 --- a/tests/custom/discord/src/discord_bot/__init__.py +++ b/tests/custom/discord/src/discord_bot/__init__.py @@ -1 +1,26 @@ +# -*- coding: utf-8 -*- + +""" +discord-bot +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) +:license: + +""" + +__title__ = 'discord_bot' +__author__ = '' +__license__ = '' +__copyright__ = 'Copyright (c) ' +__version__ = '0.0.0' + +from collections import namedtuple + + # imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='0', micro='0') diff --git a/tests/custom/discord/src/discord_bot/discord-bot.json b/tests/custom/discord/src/discord_bot/discord-bot.json index c543ea19..4a1b4bb2 100644 --- a/tests/custom/discord/src/discord_bot/discord-bot.json +++ b/tests/custom/discord/src/discord_bot/discord-bot.json @@ -16,10 +16,10 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.7.0" + "cpl-core==2022.12.0" ], "DevDependencies": [ - "cpl-cli>=2022.7.0" + "cpl-cli==2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, @@ -39,6 +39,8 @@ "*/tests" ], "PackageData": {}, - "ProjectReferences": [] + "ProjectReferences": [ + "../modules/hello_world/hello-world.json" + ] } } \ No newline at end of file diff --git a/tests/custom/discord/src/discord_bot/main.py b/tests/custom/discord/src/discord_bot/main.py index 669645fe..bb67168b 100644 --- a/tests/custom/discord/src/discord_bot/main.py +++ b/tests/custom/discord/src/discord_bot/main.py @@ -7,7 +7,7 @@ from discord_bot.application import Application from discord_bot.startup import Startup -class Main: +class Program: def __init__(self): self._app: Optional[Application] = None @@ -23,8 +23,8 @@ class Main: if __name__ == '__main__': - main = Main() + program = Program() try: - asyncio.run(main.main()) + asyncio.run(program.main()) except KeyboardInterrupt: - asyncio.run(main.stop()) + asyncio.run(program.stop()) diff --git a/tests/custom/discord/src/discord_bot/startup.py b/tests/custom/discord/src/discord_bot/startup.py index 11599cb2..5108e27c 100644 --- a/tests/custom/discord/src/discord_bot/startup.py +++ b/tests/custom/discord/src/discord_bot/startup.py @@ -1,5 +1,6 @@ from cpl_core.application import StartupABC from cpl_core.configuration import ConfigurationABC +from cpl_core.console import Console from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC from cpl_core.environment import ApplicationEnvironment from cpl_discord import get_discord_collection @@ -16,7 +17,7 @@ class Startup(StartupABC): StartupABC.__init__(self) def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: - configuration.add_json_file('appsettings.json', optional=True) + configuration.add_json_file('appsettings.json', optional=False) configuration.add_environment_variables('CPL_') configuration.add_environment_variables('DISCORD_') diff --git a/tests/custom/discord/src/modules/hello_world/__init__.py b/tests/custom/discord/src/modules/hello_world/__init__.py index ad5eca30..c576f0a0 100644 --- a/tests/custom/discord/src/modules/hello_world/__init__.py +++ b/tests/custom/discord/src/modules/hello_world/__init__.py @@ -1 +1,26 @@ +# -*- coding: utf-8 -*- + +""" +discord-bot +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) +:license: + +""" + +__title__ = 'modules.hello_world' +__author__ = '' +__license__ = '' +__copyright__ = 'Copyright (c) ' +__version__ = '0.0.0' + +from collections import namedtuple + + # imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='0', micro='0') diff --git a/tests/custom/discord/src/modules/hello_world/hello-world.json b/tests/custom/discord/src/modules/hello_world/hello-world.json index f5dd8fcc..459a531b 100644 --- a/tests/custom/discord/src/modules/hello_world/hello-world.json +++ b/tests/custom/discord/src/modules/hello_world/hello-world.json @@ -16,10 +16,10 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.7.0" + "cpl-core==2022.12.0" ], "DevDependencies": [ - "cpl-cli>=2022.7.0.post1" + "cpl-cli==2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, @@ -29,8 +29,8 @@ "ProjectType": "library", "SourcePath": "", "OutputPath": "../../dist", - "Main": "hello_world.main", - "EntryPoint": "hello-world", + "Main": "", + "EntryPoint": "", "IncludePackageData": false, "Included": [], "Excluded": [ -- 2.45.1 From 59920c59e033ccf4cfbfce452944bd354f1fc6d7 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 8 Dec 2022 12:14:58 +0100 Subject: [PATCH 42/63] Added cpl g & n discord support #143 --- src/cpl_cli/command/generate_service.py | 7 +++ src/cpl_cli/command/new_service.py | 62 +++++++++---------- src/cpl_cli/startup_argument_extension.py | 3 - src/cpl_discord/.cpl/project_discord_bot.py | 54 ++++++++++++++++ src/cpl_discord/.cpl/project_file_discord.py | 14 +++++ .../.cpl/project_file_discord_appsettings.py | 34 ++++++++++ .../project_file_discord_code_application.py | 53 ++++++++++++++++ .../.cpl/project_file_discord_code_main.py | 47 ++++++++++++++ .../.cpl/project_file_discord_code_startup.py | 47 ++++++++++++++ .../.cpl/project_file_discord_license.py | 11 ++++ .../.cpl/project_file_discord_readme.py | 11 ++++ ...ommand.py => schematic_discord_command.py} | 0 ...ic_event.py => schematic_discord_event.py} | 12 +++- .../.cpl/schematic_discord_init.py | 24 +++++++ 14 files changed, 342 insertions(+), 37 deletions(-) create mode 100644 src/cpl_discord/.cpl/project_discord_bot.py create mode 100644 src/cpl_discord/.cpl/project_file_discord.py create mode 100644 src/cpl_discord/.cpl/project_file_discord_appsettings.py create mode 100644 src/cpl_discord/.cpl/project_file_discord_code_application.py create mode 100644 src/cpl_discord/.cpl/project_file_discord_code_main.py create mode 100644 src/cpl_discord/.cpl/project_file_discord_code_startup.py create mode 100644 src/cpl_discord/.cpl/project_file_discord_license.py create mode 100644 src/cpl_discord/.cpl/project_file_discord_readme.py rename src/cpl_discord/.cpl/{schematic_command.py => schematic_discord_command.py} (100%) rename src/cpl_discord/.cpl/{schematic_event.py => schematic_discord_event.py} (73%) create mode 100644 src/cpl_discord/.cpl/schematic_discord_init.py diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index a615f095..fa511a58 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -44,7 +44,14 @@ class GenerateService(CommandABC): if len(GenerateSchematicABC.__subclasses__()) == 0: Console.error(f'No schematics found in template directory: .cpl') sys.exit() + + known_schematics = [] for schematic in GenerateSchematicABC.__subclasses__(): + if schematic.__name__ in known_schematics: + Console.error(f'Duplicate of schematic {schematic.__name__} found!') + sys.exit() + + known_schematics.append(schematic.__name__) schematic.register() self._schematics = SchematicCollection.get_schematics() diff --git a/src/cpl_cli/command/new_service.py b/src/cpl_cli/command/new_service.py index 32c27def..eef6e8d4 100644 --- a/src/cpl_cli/command/new_service.py +++ b/src/cpl_cli/command/new_service.py @@ -1,3 +1,4 @@ +import importlib import os import sys import textwrap @@ -18,6 +19,7 @@ from cpl_cli.configuration.project_type_enum import ProjectTypeEnum from cpl_cli.configuration.venv_helper_service import VenvHelper from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum from cpl_cli.configuration.workspace_settings import WorkspaceSettings +from cpl_cli.helper.dependencies import Dependencies from cpl_cli.source_creator.template_builder import TemplateBuilder from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.console.console import Console @@ -103,9 +105,9 @@ class NewService(CommandABC): self._project.from_dict(self._project_dict) - def _create_build_settings(self, project_type: ProjectTypeEnum): + def _create_build_settings(self, project_type: str): self._build_dict = { - BuildSettingsNameEnum.project_type.value: project_type.value, + BuildSettingsNameEnum.project_type.value: project_type, BuildSettingsNameEnum.source_path.value: '', BuildSettingsNameEnum.output_path.value: '../../dist', BuildSettingsNameEnum.main.value: f'{String.convert_to_snake_case(self._project.name)}.main', @@ -209,14 +211,35 @@ class NewService(CommandABC): Console.error(str(e), traceback.format_exc()) sys.exit(-1) - def _create_project(self, project_type: ProjectTypeEnum): - self._read_custom_project_types_from_path(self._env.runtime_directory) + def _create_project(self, project_type: str): + for package_name in Dependencies.get_cpl_packages(): + package = importlib.import_module(String.convert_to_snake_case(package_name[0])) + self._read_custom_project_types_from_path(os.path.dirname(package.__file__)) + self._read_custom_project_types_from_path(self._env.working_directory) if len(ProjectTypeABC.__subclasses__()) == 0: Console.error(f'No project types found in template directory: .cpl') sys.exit() + project_class = None + known_project_types = [] + for p in ProjectTypeABC.__subclasses__(): + if p.__name__ in known_project_types: + Console.error(f'Duplicate of project type {p.__name__} found!') + sys.exit() + + known_project_types.append(p.__name__) + if p.__name__.lower() != project_type and p.__name__.lower()[0] != project_type[0]: + continue + + project_class = p + + if project_class is None: + Console.error(f'Project type {project_type} not found in template directory: .cpl/') + sys.exit() + + project_type = String.convert_to_snake_case(project_class.__name__) self._create_project_settings() self._create_build_settings(project_type) self._create_project_json() @@ -229,17 +252,6 @@ class NewService(CommandABC): if self._rel_path != '': project_name = f'{self._rel_path}/{project_name}' - project_class = None - for p in ProjectTypeABC.__subclasses__(): - if p.__name__.lower() != project_type.value and p.__name__.lower()[0] != project_type.value[0]: - continue - - project_class = p - - if project_class is None: - Console.error(f'Project type {project_type.value} not found in template directory: .cpl/') - sys.exit() - base = 'src/' split_project_name = project_name.split('/') if self._use_base and len(split_project_name) > 0: @@ -336,22 +348,10 @@ class NewService(CommandABC): self._use_base = True args.remove('base') - console = self._config.get_configuration(ProjectTypeEnum.console.value) - library = self._config.get_configuration(ProjectTypeEnum.library.value) - unittest = self._config.get_configuration(ProjectTypeEnum.unittest.value) - if console is not None and library is None and unittest is None: - self._name = console - self._create_project(ProjectTypeEnum.console) - - elif console is None and library is not None and unittest is None: - self._name = library - self._create_project(ProjectTypeEnum.library) - - elif console is None and library is None and unittest is not None: - self._name = unittest - self._create_project(ProjectTypeEnum.unittest) - - else: + if len(args) <= 1: Console.error(f'Project type not found') Console.write_line(self.help_message) return + + self._name = args[1] + self._create_project(args[0]) diff --git a/src/cpl_cli/startup_argument_extension.py b/src/cpl_cli/startup_argument_extension.py index 835a9b67..07de63dd 100644 --- a/src/cpl_cli/startup_argument_extension.py +++ b/src/cpl_cli/startup_argument_extension.py @@ -38,9 +38,6 @@ class StartupArgumentExtension(StartupExtensionABC): .add_console_argument(ArgumentTypeEnum.Flag, '--', 'cpl-exp', ['ce', 'CE']) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'cpl-dev', ['cd', 'CD']) 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'], ' ') \ - .add_console_argument(ArgumentTypeEnum.Variable, '', 'unittest', ['ut', 'UT'], ' ') \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'async', ['a', 'A']) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'application-base', ['ab', 'AB']) \ .add_console_argument(ArgumentTypeEnum.Flag, '--', 'startup', ['s', 'S']) \ diff --git a/src/cpl_discord/.cpl/project_discord_bot.py b/src/cpl_discord/.cpl/project_discord_bot.py new file mode 100644 index 00000000..e78d5d8d --- /dev/null +++ b/src/cpl_discord/.cpl/project_discord_bot.py @@ -0,0 +1,54 @@ +import os + +from cpl_cli.abc.project_type_abc import ProjectTypeABC +from cpl_cli.configuration import WorkspaceSettings +from cpl_core.utils import String + + +class DiscordBot(ProjectTypeABC): + + def __init__( + self, + base_path: str, + project_name: str, + workspace: WorkspaceSettings, + use_application_api: bool, + use_startup: bool, + use_service_providing: bool, + use_async: bool, + project_file_data: dict, + ): + from project_file_discord import DiscordBotProjectFile + from project_file_discord_appsettings import DiscordBotProjectFileAppsettings + from project_file_discord_code_application import DiscordBotProjectFileApplication + from project_file_discord_code_main import DiscordBotProjectFileMain + from project_file_discord_code_startup import DiscordBotProjectFileStartup + from project_file_discord_readme import DiscordBotProjectFileReadme + from project_file_discord_license import DiscordBotProjectFileLicense + from schematic_discord_init import DiscordBotInit + from schematic_discord_event import Event + from schematic_discord_command import Command + + use_application_api, use_startup, use_service_providing, use_async = True, True, True, True + + ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async, project_file_data) + + project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/' + + self.add_template(DiscordBotProjectFile(project_name.split('/')[-1], project_path, project_file_data)) + if workspace is None: + self.add_template(DiscordBotProjectFileLicense('')) + self.add_template(DiscordBotProjectFileReadme('')) + self.add_template(DiscordBotInit('', 'init', f'{base_path}tests/')) + + self.add_template(DiscordBotInit('', 'init', project_path)) + self.add_template(DiscordBotProjectFileAppsettings(project_path)) + + self.add_template(DiscordBotInit('', 'init', f'{project_path}events/')) + self.add_template(Event('OnReady', 'event', f'{project_path}events/')) + self.add_template(DiscordBotInit('', 'init', f'{project_path}commands/')) + self.add_template(Command('Ping', 'command', f'{project_path}commands/')) + + self.add_template(DiscordBotProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async)) + self.add_template(DiscordBotProjectFileStartup(project_name.split('/')[-1], project_path, use_application_api, use_startup, use_service_providing, use_async)) + self.add_template(DiscordBotProjectFileMain(project_name.split('/')[-1], project_path, use_application_api, use_startup, use_service_providing, use_async)) diff --git a/src/cpl_discord/.cpl/project_file_discord.py b/src/cpl_discord/.cpl/project_file_discord.py new file mode 100644 index 00000000..1027c949 --- /dev/null +++ b/src/cpl_discord/.cpl/project_file_discord.py @@ -0,0 +1,14 @@ +import json + +from cpl_cli.abc.file_template_abc import FileTemplateABC + + +class DiscordBotProjectFile(FileTemplateABC): + + def __init__(self, name: str, path: str, code: dict): + FileTemplateABC.__init__(self, '', path, '{}') + self._name = f'{name}.json' + self._code = code + + def get_code(self) -> str: + return json.dumps(self._code, indent=2) diff --git a/src/cpl_discord/.cpl/project_file_discord_appsettings.py b/src/cpl_discord/.cpl/project_file_discord_appsettings.py new file mode 100644 index 00000000..cf0c29ad --- /dev/null +++ b/src/cpl_discord/.cpl/project_file_discord_appsettings.py @@ -0,0 +1,34 @@ +import textwrap + +from cpl_cli.abc.file_template_abc import FileTemplateABC + + +class DiscordBotProjectFileAppsettings(FileTemplateABC): + + def __init__(self, path: str): + FileTemplateABC.__init__(self, '', path, '{}') + self._name = 'appsettings.json' + + def get_code(self) -> str: + return textwrap.dedent("""\ + { + "TimeFormatSettings": { + "DateFormat": "%Y-%m-%d", + "TimeFormat": "%H:%M:%S", + "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", + "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" + }, + + "LoggingSettings": { + "Path": "logs/", + "Filename": "log_$start_time.log", + "ConsoleLogLevel": "ERROR", + "FileLogLevel": "WARN" + }, + + "DiscordBotSettings": { + "Token": "", + "Prefix": "!bot " + } + } + """) diff --git a/src/cpl_discord/.cpl/project_file_discord_code_application.py b/src/cpl_discord/.cpl/project_file_discord_code_application.py new file mode 100644 index 00000000..dbdd4f23 --- /dev/null +++ b/src/cpl_discord/.cpl/project_file_discord_code_application.py @@ -0,0 +1,53 @@ +from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC + + +class DiscordBotProjectFileApplication(CodeFileTemplateABC): + + def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool): + CodeFileTemplateABC.__init__(self, 'application', path, '', use_application_api, use_startup, use_service_providing, use_async) + + def get_code(self) -> str: + import textwrap + + return textwrap.dedent("""\ + from cpl_core.application import ApplicationABC + from cpl_core.configuration import ConfigurationABC + from cpl_core.console import Console + from cpl_core.dependency_injection import ServiceProviderABC + from cpl_core.logging import LoggerABC + from cpl_discord.application.discord_bot_application_abc import DiscordBotApplicationABC + from cpl_discord.configuration.discord_bot_settings import DiscordBotSettings + from cpl_discord.service.discord_bot_service import DiscordBotService + from cpl_discord.service.discord_bot_service_abc import DiscordBotServiceABC + + + class Application(DiscordBotApplicationABC): + + def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): + ApplicationABC.__init__(self, config, services) + + self._bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC) + self._logger: LoggerABC = services.get_service(LoggerABC) + self._bot_settings: DiscordBotSettings = config.get_configuration(DiscordBotSettings) + + async def configure(self): + pass + + async def main(self): + try: + self._logger.debug(__name__, f'Starting...\\n') + self._logger.trace(__name__, f'Try to start {DiscordBotService.__name__}') + await self._bot.start_async() + except Exception as e: + self._logger.error(__name__, 'Start failed', e) + + async def stop_async(self): + try: + self._logger.trace(__name__, f'Try to stop {DiscordBotService.__name__}') + await self._bot.close() + self._logger.trace(__name__, f'Stopped {DiscordBotService.__name__}') + except Exception as e: + self._logger.error(__name__, 'stop failed', e) + + Console.write_line() + """) diff --git a/src/cpl_discord/.cpl/project_file_discord_code_main.py b/src/cpl_discord/.cpl/project_file_discord_code_main.py new file mode 100644 index 00000000..e99183ce --- /dev/null +++ b/src/cpl_discord/.cpl/project_file_discord_code_main.py @@ -0,0 +1,47 @@ +from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC +from cpl_core.utils import String + + +class DiscordBotProjectFileMain(CodeFileTemplateABC): + + def __init__(self, name: str, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool): + CodeFileTemplateABC.__init__(self, 'main', path, '', use_application_api, use_startup, use_service_providing, use_async) + + import textwrap + + import_pkg = f'{String.convert_to_snake_case(name)}.' + + self._main_with_application_host_and_startup = textwrap.dedent(f"""\ + import asyncio + from typing import Optional + + from cpl_core.application import ApplicationBuilder, ApplicationABC + from {import_pkg}application import Application + from {import_pkg}startup import Startup + + + class Program: + + def __init__(self): + self._app: Optional[Application] = None + + async def main(self): + app_builder = ApplicationBuilder(Application) + app_builder.use_startup(Startup) + self._app: ApplicationABC = await app_builder.build_async() + await self._app.run_async() + + async def stop(self): + await self._app.stop_async() + + + if __name__ == '__main__': + program = Program() + try: + asyncio.run(program.main()) + except KeyboardInterrupt: + asyncio.run(program.stop()) + """) + + def get_code(self) -> str: + return self._main_with_application_host_and_startup diff --git a/src/cpl_discord/.cpl/project_file_discord_code_startup.py b/src/cpl_discord/.cpl/project_file_discord_code_startup.py new file mode 100644 index 00000000..885aea67 --- /dev/null +++ b/src/cpl_discord/.cpl/project_file_discord_code_startup.py @@ -0,0 +1,47 @@ +from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC +from cpl_core.utils import String + + +class DiscordBotProjectFileStartup(CodeFileTemplateABC): + + def __init__(self, project_name: str, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool): + CodeFileTemplateABC.__init__(self, 'startup', path, '', use_application_api, use_startup, use_service_providing, use_async) + self._project_name = project_name + + def get_code(self) -> str: + import textwrap + + import_pkg = f'{String.convert_to_snake_case(self._project_name)}.' + + return textwrap.dedent(f"""\ + from cpl_core.application import StartupABC + from cpl_core.configuration import ConfigurationABC + from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC + from cpl_core.environment import ApplicationEnvironment + from cpl_discord import get_discord_collection + from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum + from {import_pkg}commands.ping_command import PingCommand + from {import_pkg}events.on_ready_event import OnReadyEvent + + + class Startup(StartupABC): + + def __init__(self): + StartupABC.__init__(self) + + def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: + configuration.add_json_file('appsettings.json', optional=False) + configuration.add_environment_variables('CPL_') + configuration.add_environment_variables('DISCORD_') + + return configuration + + def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: + services.add_logging() + services.add_discord() + dc_collection = get_discord_collection(services) + dc_collection.add_event(DiscordEventTypesEnum.on_ready.value, OnReadyEvent) + dc_collection.add_command(PingCommand) + + return services.build_service_provider() + """) diff --git a/src/cpl_discord/.cpl/project_file_discord_license.py b/src/cpl_discord/.cpl/project_file_discord_license.py new file mode 100644 index 00000000..4592aba0 --- /dev/null +++ b/src/cpl_discord/.cpl/project_file_discord_license.py @@ -0,0 +1,11 @@ +from cpl_cli.abc.file_template_abc import FileTemplateABC + + +class DiscordBotProjectFileLicense(FileTemplateABC): + + def __init__(self, path: str): + FileTemplateABC.__init__(self, '', path, '') + self._name = 'LICENSE' + + def get_code(self) -> str: + return self._code diff --git a/src/cpl_discord/.cpl/project_file_discord_readme.py b/src/cpl_discord/.cpl/project_file_discord_readme.py new file mode 100644 index 00000000..e3dceea1 --- /dev/null +++ b/src/cpl_discord/.cpl/project_file_discord_readme.py @@ -0,0 +1,11 @@ +from cpl_cli.abc.file_template_abc import FileTemplateABC + + +class DiscordBotProjectFileReadme(FileTemplateABC): + + def __init__(self, path: str): + FileTemplateABC.__init__(self, '', path, '') + self._name = 'README.md' + + def get_code(self) -> str: + return self._code diff --git a/src/cpl_discord/.cpl/schematic_command.py b/src/cpl_discord/.cpl/schematic_discord_command.py similarity index 100% rename from src/cpl_discord/.cpl/schematic_command.py rename to src/cpl_discord/.cpl/schematic_discord_command.py diff --git a/src/cpl_discord/.cpl/schematic_event.py b/src/cpl_discord/.cpl/schematic_discord_event.py similarity index 73% rename from src/cpl_discord/.cpl/schematic_event.py rename to src/cpl_discord/.cpl/schematic_discord_event.py index 28e2aa85..43f08354 100644 --- a/src/cpl_discord/.cpl/schematic_event.py +++ b/src/cpl_discord/.cpl/schematic_discord_event.py @@ -6,7 +6,7 @@ from cpl_core.console import Console from cpl_core.utils import String -class Command(GenerateSchematicABC): +class Event(GenerateSchematicABC): def __init__(self, name: str, schematic: str, path: str): GenerateSchematicABC.__init__(self, name, schematic, path) @@ -24,11 +24,17 @@ class Command(GenerateSchematicABC): if event is None: Console.error(f'No valid event found in name {name}') + Console.write_line('Available events:') + for event_type in DiscordEventTypesEnum: + Console.write_line(f'\t{event_type.value.__name__.replace("ABC", "")}') sys.exit() self._event_class = f'{event}ABC' - self._name = f'{String.convert_to_snake_case(name)}_{String.convert_to_snake_case(self._event_class.replace("ABC", ""))}_{schematic}.py' - self._class_name = f'{String.first_to_upper(name)}{self._event_class.replace("ABC", "")}{String.first_to_upper(schematic)}' + self._name = f'{String.convert_to_snake_case(self._event_class.replace("ABC", ""))}_{schematic}.py' + self._class_name = f'{self._event_class.replace("ABC", "")}{String.first_to_upper(schematic)}' + if name != '': + self._name = f'{String.convert_to_snake_case(name)}_{self._name}' + self._class_name = f'{String.first_to_upper(name)}{self._class_name}' def get_code(self) -> str: code = """\ diff --git a/src/cpl_discord/.cpl/schematic_discord_init.py b/src/cpl_discord/.cpl/schematic_discord_init.py new file mode 100644 index 00000000..8b7ce010 --- /dev/null +++ b/src/cpl_discord/.cpl/schematic_discord_init.py @@ -0,0 +1,24 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class DiscordBotInit(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + self._name = f'__init__.py' + + def get_code(self) -> str: + code = """\ + # imports + """ + return self.build_code_str(code, Name=self._class_name) + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'init', + [] + ) -- 2.45.1 From e46711dc547c65ebf1537b0d831cb5ba0373492e Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 8 Dec 2022 14:23:46 +0100 Subject: [PATCH 43/63] Added unittests #143 --- unittests/unittests_cli/generate_test_case.py | 26 ++++++++++++++----- unittests/unittests_cli/new_test_case.py | 24 +++++++++++++++++ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/unittests/unittests_cli/generate_test_case.py b/unittests/unittests_cli/generate_test_case.py index 16bb382b..64fa4302 100644 --- a/unittests/unittests_cli/generate_test_case.py +++ b/unittests/unittests_cli/generate_test_case.py @@ -9,6 +9,7 @@ from unittests_shared.cli_commands import CLICommands class GenerateTestCase(CommandTestCase): _project = 'test-console' _t_path = 'test' + _skip_tear_down = True @classmethod def setUpClass(cls): @@ -19,29 +20,32 @@ class GenerateTestCase(CommandTestCase): os.chdir(PLAYGROUND_PATH) def _test_file(self, schematic: str, suffix: str, path=None): - file = 'GeneratedFile' - expected_path = f'generated_file{suffix}.py' + file = f'GeneratedFile{"OnReady" if schematic == "event" else ""}' + expected_path = f'generated_file{"_on_ready" if schematic == "event" else ""}{suffix}.py' + if path is not None: file = f'{path}/{file}' expected_path = f'{path}/{expected_path}' + CLICommands.generate(schematic, file) file_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, expected_path)) file_exists = os.path.exists(file_path) self.assertTrue(file_exists) def _test_file_with_project(self, schematic: str, suffix: str, path=None, enter=True): - file = f'GeneratedFile' - excepted_path = f'generated_file{suffix}.py' + file = f'GeneratedFile{"OnReady" if schematic == "event" else ""}' + excepted_path = f'generated_file{"_on_ready" if schematic == "event" else ""}{suffix}.py' if path is not None: - excepted_path = f'{self._project}/src/{String.convert_to_snake_case(self._project)}/{path}/generated_file_in_project{suffix}.py' + excepted_path = f'{self._project}/src/{String.convert_to_snake_case(self._project)}/{path}/generated_file_in_project{"_on_ready" if schematic == "event" else ""}{suffix}.py' if enter: os.chdir(path) - excepted_path = f'{path}/src/{String.convert_to_snake_case(self._project)}/generated_file_in_project{suffix}.py' + excepted_path = f'{path}/src/{String.convert_to_snake_case(self._project)}/generated_file_in_project{"_on_ready" if schematic == "event" else ""}{suffix}.py' - file = f'{path}/GeneratedFileInProject' + file = f'{path}/GeneratedFileInProject{"OnReady" if schematic == "event" else ""}' CLICommands.generate(schematic, file) file_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, excepted_path)) + print(file_path) self.assertTrue(os.path.exists(file_path)) def test_abc(self): @@ -88,3 +92,11 @@ class GenerateTestCase(CommandTestCase): def test_validator(self): self._test_file('validator', '_validator') self._test_file_with_project('validator', '_validator', path=self._project) + + def test_discord_command(self): + self._test_file('command', '_command') + self._test_file_with_project('command', '_command', path=self._project) + + def test_discord_event(self): + self._test_file('event', '_event') + self._test_file_with_project('event', '_event', path=self._project) diff --git a/unittests/unittests_cli/new_test_case.py b/unittests/unittests_cli/new_test_case.py index 22c830f3..80ff154d 100644 --- a/unittests/unittests_cli/new_test_case.py +++ b/unittests/unittests_cli/new_test_case.py @@ -52,6 +52,15 @@ class NewTestCase(CommandTestCase): else: self.assertFalse(os.path.isfile(os.path.join(project_path, f'test_case.py'))) + if project_type == 'discord-bot': + self.assertTrue(os.path.isfile(os.path.join(project_path, f'events/__init__.py'))) + self.assertTrue(os.path.isfile(os.path.join(project_path, f'events/on_ready_event.py'))) + self.assertTrue(os.path.isfile(os.path.join(project_path, f'commands/__init__.py'))) + self.assertTrue(os.path.isfile(os.path.join(project_path, f'commands/ping_command.py'))) + else: + self.assertFalse(os.path.isfile(os.path.join(project_path, f'events/on_ready_event.py'))) + self.assertFalse(os.path.isfile(os.path.join(project_path, f'commands/ping_command.py'))) + def _test_sub_project(self, project_type: str, name: str, workspace_name: str, *args, test_venv=False): os.chdir(os.path.abspath(os.path.join(os.getcwd(), workspace_name))) CLICommands.new(project_type, name, *args) @@ -72,6 +81,15 @@ class NewTestCase(CommandTestCase): self.assertTrue(os.path.exists(project_path)) self.assertTrue(os.path.join(project_path, f'{name}.json')) + if project_type == 'discord-bot': + self.assertTrue(os.path.isfile(os.path.join(project_path, f'events/__init__.py'))) + self.assertTrue(os.path.isfile(os.path.join(project_path, f'events/on_ready_event.py'))) + self.assertTrue(os.path.isfile(os.path.join(project_path, f'commands/__init__.py'))) + self.assertTrue(os.path.isfile(os.path.join(project_path, f'commands/ping_command.py'))) + else: + self.assertFalse(os.path.isfile(os.path.join(project_path, f'events/on_ready_event.py'))) + self.assertFalse(os.path.isfile(os.path.join(project_path, f'commands/ping_command.py'))) + def _test_sub_directory_project(self, project_type: str, directory: str, name: str, workspace_name: str, *args): os.chdir(os.path.abspath(os.path.join(os.getcwd(), workspace_name))) CLICommands.new(project_type, f'{directory}/{name}', *args) @@ -117,6 +135,12 @@ class NewTestCase(CommandTestCase): def test_console_sub_with_other_base(self): self._test_sub_project('console', 'tools/test-sub-console', 'test-console', '--ab', '--s', '--sp', '--venv', '--base', test_venv=True) + def test_discord_bot(self): + self._test_project('discord-bot', 'test-bot', '--ab', '--s', '--venv', test_venv=True) + + def test_discord_bot_sub(self): + self._test_sub_project('discord-bot', 'test-bot-sub', 'test-console', '--ab', '--s', '--venv', test_venv=True) + def test_library(self): self._test_project('library', 'test-library', '--ab', '--s', '--sp') -- 2.45.1 From 6f3099a8db24ae335814542d3c30d8d192a0d41d Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 8 Dec 2022 15:29:48 +0100 Subject: [PATCH 44/63] Updated packages & improved docs #143 --- docs/build/doctrees/cli.generate.doctree | Bin 21443 -> 23619 bytes docs/build/doctrees/cli.new.doctree | Bin 19666 -> 20076 bytes .../doctrees/cpl_core.configuration.doctree | Bin 165504 -> 158508 bytes .../build/doctrees/cpl_discord.events.doctree | Bin 308142 -> 308142 bytes docs/build/doctrees/cpl_query.base.doctree | Bin 208470 -> 179814 bytes .../doctrees/cpl_query.enumerable.doctree | Bin 21864 -> 19690 bytes .../build/doctrees/cpl_query.iterable.doctree | Bin 32376 -> 35914 bytes docs/build/doctrees/environment.pickle | Bin 543750 -> 543088 bytes .../doctrees/tutorials.appsettings.doctree | Bin 3020 -> 3016 bytes .../tutorials.console-arguments.doctree | Bin 3034 -> 3030 bytes docs/build/doctrees/tutorials.console.doctree | Bin 3040 -> 3036 bytes .../doctrees/tutorials.create-startup.doctree | Bin 3015 -> 3011 bytes docs/build/doctrees/tutorials.doctree | Bin 2968 -> 2996 bytes .../tutorials.extend-application.doctree | Bin 3011 -> 3007 bytes .../doctrees/tutorials.extend-startup.doctree | Bin 2991 -> 2987 bytes docs/build/doctrees/tutorials.logging.doctree | Bin 3000 -> 2996 bytes docs/build/doctrees/tutorials.mail.doctree | Bin 2965 -> 2961 bytes .../doctrees/tutorials.templating.doctree | Bin 0 -> 21264 bytes docs/build/html/_sources/cli.generate.md.txt | 26 +- docs/build/html/_sources/cli.new.md.txt | 2 + .../_sources/tutorials.appsettings.md.txt | 2 +- .../tutorials.console-arguments.md.txt | 2 +- .../html/_sources/tutorials.console.md.txt | 2 +- .../_sources/tutorials.create-startup.md.txt | 2 +- .../tutorials.extend-application.md.txt | 2 +- .../_sources/tutorials.extend-startup.md.txt | 2 +- .../html/_sources/tutorials.logging.md.txt | 2 +- .../build/html/_sources/tutorials.mail.md.txt | 2 +- docs/build/html/_sources/tutorials.rst.txt | 3 +- .../html/_sources/tutorials.templating.md.txt | 181 +++++++++++ docs/build/html/cli.generate.html | 9 + docs/build/html/cli.new.html | 1 + docs/build/html/contributing.html | 4 +- docs/build/html/cpl_core.configuration.html | 12 +- docs/build/html/cpl_discord.events.html | 2 +- docs/build/html/cpl_query.base.html | 94 +----- docs/build/html/cpl_query.enumerable.html | 6 - docs/build/html/cpl_query.html | 4 +- docs/build/html/cpl_query.iterable.html | 17 +- docs/build/html/genindex.html | 58 +--- docs/build/html/getting_started.html | 23 +- docs/build/html/modules.html | 27 +- docs/build/html/objects.inv | Bin 7181 -> 7110 bytes docs/build/html/py-modindex.html | 10 - docs/build/html/searchindex.js | 2 +- docs/build/html/tutorials.appsettings.html | 7 +- .../html/tutorials.console-arguments.html | 7 +- docs/build/html/tutorials.console.html | 7 +- docs/build/html/tutorials.create-startup.html | 7 +- .../html/tutorials.extend-application.html | 7 +- docs/build/html/tutorials.extend-startup.html | 7 +- docs/build/html/tutorials.html | 24 +- docs/build/html/tutorials.logging.html | 7 +- docs/build/html/tutorials.mail.html | 11 +- docs/build/html/tutorials.templating.html | 304 ++++++++++++++++++ docs/source/cli.generate.md | 26 +- docs/source/cli.new.md | 2 + docs/source/tutorials.appsettings.md | 2 +- docs/source/tutorials.console-arguments.md | 2 +- docs/source/tutorials.console.md | 2 +- docs/source/tutorials.create-startup.md | 2 +- docs/source/tutorials.extend-application.md | 2 +- docs/source/tutorials.extend-startup.md | 2 +- docs/source/tutorials.logging.md | 2 +- docs/source/tutorials.mail.md | 2 +- docs/source/tutorials.rst | 3 +- docs/source/tutorials.templating.md | 181 +++++++++++ src/cpl_cli/.cpl/project_console.py | 2 - src/cpl_cli/.cpl/schematic_enum.py | 10 +- src/cpl_core/configuration/configuration.py | 2 +- .../configuration/configuration_abc.py | 2 +- src/cpl_core/cpl-core.json | 25 +- src/cpl_core/{typing.py => type.py} | 0 src/cpl_core/utils/pip.py | 2 +- tools/set_pip_urls/set-pip-urls.json | 2 +- tools/set_version/set-version.json | 8 +- 76 files changed, 878 insertions(+), 288 deletions(-) create mode 100644 docs/build/doctrees/tutorials.templating.doctree create mode 100644 docs/build/html/_sources/tutorials.templating.md.txt create mode 100644 docs/build/html/tutorials.templating.html create mode 100644 docs/source/tutorials.templating.md rename src/cpl_core/{typing.py => type.py} (100%) diff --git a/docs/build/doctrees/cli.generate.doctree b/docs/build/doctrees/cli.generate.doctree index bd1c7d8ba4e8a16785ea9460071d10516ebb95e0..f088d0e205813a0370638f9b02601263c0a5a328 100644 GIT binary patch literal 23619 zcmdU1e~cZ+UBC0)y}NfmeR1rNT;cf75miAq!7Lq1c+@i6`EwBop_!VYn~Hj;gPA-Bu%W*oY?B+e4M%;+}Z@6>D^H8+qqh@ z_TqC^WQ0y1qvra?qY#Ds>aocJOb z^0In*>=@`Qn84V@zTTS81i8ENMY6xXau9!g`Ck3CkhAAr95%}w_J=C?qr5^S5w!aPAym6VIJ%ojdEr&j=;YcH?JQ8LrCd<%M>5ah?g* zmbjuML9yAePmpOGXCPbuUwP|c*=s~`82H`XvPI^&MI7X;K_6 zz`&$hz{cSOncPpoIjh&V^~j0xDlS|QC|~4SN@cR5$LlES9>dmkbmfz?dp}5um7#F~ zy)M+_m$GK-hoc!ddJ6W*c?hR55;=D1g{;~$%Bqn@CkSCW9*}7}?s>3V*z0*uM|~al z~GEhebv%r5MkN;$sTL-^n)1Fs04Yw-w0#_&_ z1%niv^hV+Yk;-HRyLA*i)PTKxNSZyJcjdmZ`f+8gM69|W1Q~Y+|NJ!kIZ$wNUyq(^ zc`H{A&nqH4uN1=bv&z=|h{E%a>L_@q;raF$G#kE=LAY^Gz?U($cgY0c_<`T<>io`C zD$Cu)&O=B1E>_`2TDm*rGf4g}Ql3G+QwIooN4=7+&F)<$3CnY~*Ez%YWD(txMcJNA zuh^9-ww5*i&srLz8&*eYy!%3sv<%&EnN|mmT3SXD#X&Dq7EHL^GC~XPBK&R(4h8xi z9P&gh$A@j_OE0~&1)C@MU#k;%rWK|ePTW*oxR-tlM4vn&Z=hhAp7r2>BGf%;sYYG+ zY%xtQWat(O{fyj*xlL?+YUdb3k1Ij9V{^h@c?8~wAJAkW&%-=_K!eWV-DlyH$&iKI zIm#eoN};$w78al?r%t(ha7L9}iEPF_W+{fWC_ko0p7 zO{?(8an=aDsBami%Hj7?FvEDa95c2DJEw8cx{O+^xtD|)V!62jMSM5Pv>A4)hI7=9 zvR4YAZRuti2;8{_`JHQq-VB^8hPTTi*|assPiHuLvI02@5&>V;@l5%?aLo;c1P6RH z>-yM!&Fz)M+?S!K;HS)jn$tcJ-K*MhM@UrLK^9^-INme>Ybyk<%4f0e0nM8Ki0&m; zD?K;FbM+G>UnD!{b3#Q`qkcz7jMu1a3agm*+#5LRnrrVfcoD)*DpqDNWkowM%OSqu zdLSeR&Bo|JT7|_dch?M8loRfJt|R%Dgl{r(Qib*F?}Viaj^XRhgKYZz8zwyJJUZQQ zt-0S416BL82q}xoZG-7#_frA|g^=QKKg9U~Cwv%CcUZ|k}6J_3qg+#TzYRs!^{=G2oWudWxjm1#tF<}+vxniL4LUX9h z+uX!w2t$~cR`OY{!7k;HdQ+fK1MW4(yieAE`wcNrHQYm(_lc6&Xy$$PvJ*ye%knII zn*!cW$o#3!)!g>TE}M$-If7& z&{4d74gRc)Ug+I5b`-Y&dJx{Gjo>#lfzeW=TTa}%6(pXC14A8eLmh&5+_w&*>)lsA z2?O4JTHp}eFqw5rm%u-W+&0dX1v^3JI#%;SNSE0JUAYlV(R-#4(kbskGx3wpQy zP>SQ-S6;{PmVm6K{0zmME6%QDrT=z3N{?hcor?ch3{*`3wW+u+AMRx;{(;c=0CU6l znXt-K{5>(yc%d2T6nW(%ws^3t8qT z7tyAk#6kHE^#b;AYUhE{sZFK`X^IyGV7t3~kxa99PuJK` z)6=Mv%&vDb$)xT61XwKJ8@fMLD%xts0o zRSc&92c0ASMMzZJrN*tgW{%}NqcKxswJZAm2oqNE{SW_-Fj6AxS4)G}Uu716TQroa zIW{AO8M~4L>-<5m{&B{$%^Fyr69ZMp;}D*$m&8W%Y~~Wa9nYD?u4I#UMVG2v+7S}f zx~p-it|?>Tk}FhKFqU(P`?te{Rk&n`fyRr`p>b&*IAr-rubN8JSjEFCy^y2o4Pk!` zpdV#K`i&Yu|C$)68t5TJ`glofG?C`t2L{XQRK7?y{traw3dYmr>5D?5+6pyF)ir7? zl=>^7x`MHsQry$uWWp+x`i2;2yciuSrTR{P$O-E-RtZYc3puL(Ti9O%=yxzm{h$WW z{~-pd26_mk{=Fo&52Zc?1{WxmE0T>r(WtQrqLex&B&w}Yqf}j^#zLug3e^wb=`AL# zLaE2aK;y;e&?vP8%M-pg?HEH?1>Z8#T23r+Er-{20YnYN&oFMiPy_Lgh=HmRAHuDx zC9%=mTDqE=Ez_$|Dnsz|Vh9BYD8p_EiE3Na7*^M`u`uj6h3X2%@|GyB0g{}d?k6J+QfVL0FS%(pO|_oochOoOi`P6>Uw)D^UnRVHMTK)-r*P> zWx^^LEs24u-F;Au4sG7S`%iq}T0Q4XV-;shdLh%~Cx!i0G$~F1?D6qBn`@q_0rXR1 zplYCtL$L$XcbCLQ&o%Scz+ibb&lkzYe^hj?U_4#QUl0=2R;YzbU8BZAsXd{(g0Y-Z z+|w}=R-x3(VxaM2bZC@9xMRp?p_|pDYNVB%R{TfUk-H6ab*)dP_)DTcSp;+J=FX@A+NIZwu8GjOFCw-u?$B ztU|887XytKqeCOt3c!6+_Z(A?gCVa8H$^?CSgu44ve~%<>=PbiESqA&D!5OGfvRyI z!m|GQqIS+@q_rWmLi@gXeJ zOJbv0_TY1nrz!~H9Z`4>l|dl$ZA1$hn%Bh83eZsIy(%QCZB%1kU6aScyw3^M6^!M~ z<8koYOjw0^pB4j+7o$UC9zJ2WATipI+p-y2$63d&mi)`dP!_F=N`y&j+!qsZfLy>%fE?X6=0!!`>v3vwoi?3b@@=#jdl$I;`q^-?s&|1em0qNg--dM0LW9y5s_gyWM;Otv_hhrd$-GD> z6y;t3mP-q70JHaQ`5VBw&M<4_CjXKt*PWbAQqO-dkGUWqUn9734U!8d>c}j~c zlJ*n$edHv(0-c1IZ&DN4B^P-~nq`t?=hkFZ(8z;PcpzUG)paGOD!>e;nAI_S4_*qH>{jH@X>_e4E!w*L^`nD6K!-V0O0LzrQ zOBO?`AB2zv5+*EfuycgW+qx$%XUM9xhq*3eJx(ItXok#~Ry*lJf6JJm5OX;~zn0#E zk|w^)XQ4%q!*JR0`$?=>z7b%?N62)P#GTEjHX{dqKP*>jRu~4MX2Vv_gDt56T^KtRYVD-tA!N3Sv#kP!RrNj%0^78dt(4G z(`#EMQ1~{eU|UuUgB*v{xB3kY5=Ady6O;9lxpaB~K0|0akoFbG5^HH@R2oRDpd^G^3~7fUj3D<+n$vgX7EsCv5i7;yKzy9H7jFTdQlpU2GutTtfKYNlAv z@o5fX_X|+XzaJr!=lS^XOCJ5LVWU@cI%NEW+$W)c9|I3T%>6wWu2SDWMLp0p9WG8E z^I;n0kHHf>EKGlIxF3L~?q&S*&ya4&{WkvDfLGw%Gx%p4_7Cn8_~%({a*_7iM0re9 zLG_|N>{97nD!EIgcB#Z}VxNY*#dH9Bk@jwHrd?wioV0698$-KxaVwILr9Atn#!HYe zmrhm4__PEkS>7&tz_@0)4#L z7ps{d^RNWa0LQg%0Y1v|fEf_YkhOdE5(Yk$zYhL*b?{-B&LG(`OpM^`2nd`GC{_Zg fctI3X&Mi2;;Uy+=zKeOW=S^I!*u0)@oVNZKrOKjh delta 3960 zcmb7`ZEO@p7{{5pw>>Oyy>eX3wf92lL2rA#yVe#96iWmuEgS-h9toPF*kv0*i)SQ( zR5b93M8b1IFhNTyf`}yb#E@uA1gpjmkP?Y8N>Xx83gi zpXdL3X6BhWcLtq1hFq_>-Z-;%*wyBTA1V&uG7M-=+FPO2C=E(T^}@;NyF;__q)Fr@ zMt@Z+4)!hFJt@CYt%DVT1>=2}gdTnl>_=;%BbY&tKzTd@(U>ok)q;1A4ZaF`W>$kQ zm_jPk^b$=J-cEp!Y>A;qbUM)n+ux+?^Nh#u;A? zzlMFN2zSFWzGZ3P7tO#85m4YB7q}sgdvvTLBkI286(o;uK?YYkD5#HvR&vnkaA&rR z$^pev!t+$em}RjFMr*d=76&X2rco0a9D%pek^dFYsV+gTwoJZ~CGQgPynIThlEI0_ zdj@pEy67|l`D`?UcbM{2ambfhp1cvV-wKj=F80Qnk^hkXHLHZPWM35F@3VxT#8%qY$&Kvw)0G#CC&v*Z_#<|zBlsDWAT0I*u=(tFg#Z#Jqjf= zc%>6!?Tw<^U1Ob;+EgzSJVOOxEQ1n^bK?RmF`s3#8#v?6LiDU z!Zppp6+NP0AENAHLl2JiWaJE{{Dd=+O5t*sv13I!=M=cwB;(00<1Bhy7A=c*p!#$z zZgkPMg=MNRO{1+!=fqu>7M3v!59tBLR`Zb2rN%W5=hIE)gfrii#CcPa80UO}CD~%) z?6c$SZ%*R<8t3b}Eis?AsuJfZOA9BMg=2a^!Pz$v&W~Ft=hrPs{Jkm3EY5j}CAnzg zykN&U(wfA7Yn*@RwgjiGs>JDc(e4T<@R@`mc^8j(Ci#sg9Q*Qpi&n;@-awp7RLhn{xOEUO1Q>Hkl9ndoE zFwt(eqwQXr!Gjv@VcnaURa;ew_ESp_XEYC|^@xIY`$TA=a|R(j(K!#_G-a8?Nv~^J zu9`?M+mQ}GJP$i1wu2E2cbhKEwxSYfR5C6tVWC=LjjBon6r7hCr?}${0y%BP{Vq;k zWcaskikIKY$Hl1W7HUj~pGc zjy&>vy<2*o+w|i0=QnMmw^Efx$TD@7DYHzKWr}QGiP14Mfl|hzD@iT%HJYi6CGgTz NG`8w5-dev7{Rgjh75e}H diff --git a/docs/build/doctrees/cli.new.doctree b/docs/build/doctrees/cli.new.doctree index 449ea977000f906d8c53b913daaa063093297031..3dcb91910437eec7c060baa8bb6c5ea8cc903d59 100644 GIT binary patch delta 3884 zcmbuCdu&rx9LIak?Q6u7jMxzNKU>13}gt!O46*bIv`t>s@c?0N%b%(>D_jL)={tep_DLxvG^Ifs-o_LIpruHNgeSH5wLX1U| zd~&cqwug@l^3j1`N!;g>vx@&}f7TffFi2f+duSAb&}5m6k-OA#p_MMrmb$ z=;eGzKnJn0C1@5Z1xJRjR0NwD)96Z5Wk6&LSW&;Z1c|0=&>v>| zVW~iTts4$W7JDHI*Zc2kakj__4@(w@s6}2n209S1qe+)G?=dOrHp*b!BHb-TSBjm5 zJMc~I^bC<{7bTRs5)&utA=*CA1251Cn9nAlluf_{MEy=XJf}!)TrIWs(kH+a`k-_j zyh*&_T+7Pf4Pt9Y2`&#M%C^suJx^gL=!Ahs1;s}AqoNQh{vAM%ZdvMJ1xKVZleC1R zq=g(Qsa&9OC>O}h3Unr$UA;cnD$Ed_C$8vbe{tw)ZjU7<~Nzp$`X|e*-IU^v8I&+^mG9Z4CJnIJljR?O76Dv z=%%9pGyd)H!M_xY3mM}dl<{{3p&$sQf)^Co+_{r2b9FSh>cjUo0WK@ z%$$15A>JJC?@7FTVJ&!?R%sY{d~Uh#4rPa(*6!P6c`w4{=R2L@J%jNm-lWl;67G^;`h4IL=5Uxq*79mt!O!c+at9_d(>bS>&NoZ9 zfS+kPQ<>?Ulhcu9Jf7_!w~XmNrooD3+}h9%?n9q1n&B(H%0R7oqhJP*KCPlt66Zzuokln3jjNI1hg(gGh z#?i@;=Njn7@qR<*s%A8(2zAxUP0($idpL(7b6GPQWSPp%VO;*ajI7~C@q;EK>$jcg zqX4gLx7CbjJ<_%L!J@IYwh92kW1Xwk0`St<@zuX^e0`IAh~m8Xzw#jTnL&eoEh$7_ zw_EwkBmsPgN<~KIKb08hiY8L=q_eLlp2BCsQSk~|(6N}i&I}&uuz|}c)lpyeDK^V# z@B=#EVc##}*Wxa6`5vG0#Ba%EIbNE?7IImO+lSarE)g&Ny5H-mowadssc delta 3463 zcmbuCe@t6d6vw%@Ek6|G*9sf`U16oPr4%eheyr_4$t>$Klj-J$f*bMeIetVSMA0~+ zW=qE6*y$E=gk_N}7;(;EVq(-~B*tXPGF@V_sGB5Hvp6+jQ!{@gdhdPrb?>EpLGceR z+;`tO=X1XO_PocBQ|QtpGVC=R`LyF*Lw^yJuDS@;;sW@_W{2CwM(`L%O-7uNA(+G> z`pYcn1dHGmtg(#YC&dytXKY&TJX?;3fi)#CQ1U!(!|=JS21UVE>Nka@?9Hj!Bd}yP z!;LyW-p&H>R(!a*W!Zoot9^J-3K*aPImrqT4OM41O7%jtcy>_Q6cIF^v59QlV~H0M zm4ZRY6tX%Km0|?WIqdf|4?R23v#zVFD?zV9b#WNoP>+FhB!!f2|PSPt>(VPUe44n>SR|WfAc{v5rl{{iI8+_<;WZz9M zSYt-`&h-u|hY6oAoKN;9uAxIOS%PShOYT&E1;xUYOO<5qAa`=^1bH~iCeI~uzMjvW zH0SjxIYlj-TVTmugSHUp0Df4nbn>Ruy2*)!_OO86dW8cw>6uWeLlyrGl5uY}D>(J|@vbRX&L&?T9KB|XqXB7rj2Zyve2>Ujp_gM$;DLXjCI*@0@ z!PMyVB2vDWswv-V)ph7=6`!5+U6%O1Q1M+#tw0sFz?8oV{m%G)Q}SI>DSS}caeoHs zt_m*KB>h=SYgyNdMpC6)sOU@xF7o5621icY~I@rmN z{f7VL;8q^avZZlwn)83{U@E@5&W(0bYUpY;;4XvG#ht0O@3{E6WYCC#I60d?Njo7D z^2=l3F_um?avIeCX5_6wYLwn!9hxP@eTCe|Yq`=h2Ik`vsvf4bdKjpG6n&EHVL{o$ zH0?pQ^0Cwe+E)G`WFv%MhBlxdl!Pu$_`O7UO+~nvT0m0yRzok!g6{hRNDqHEt&n)TAK_$nlgzg3puEFn4KT{@K!x4lum^O1xbw!;6M% z3EEINgwCkYsyNylLwi$&c1jCvG_oCCU})!+Xs1?&cFy61i_tuScO@D?H&u8Zj`uUe zyP?9nu7!7X{T7^`Mc>A8ZkFO%b)E6a@5;xh8?*T!Z6zCza*jr*)0df}(60Ks3?COTMV0n=b3=En%_@kLUDt_x8|#0S4(m2O`Z7XVGyM8D~*( m77-s79P}PqK*(j;1)r4qDy`(sr@84H56dn3=Swy|g8l*9Ta|GD diff --git a/docs/build/doctrees/cpl_core.configuration.doctree b/docs/build/doctrees/cpl_core.configuration.doctree index ef32c21da33a9288f9358e666e44776708cc366c..d725a0f371a28ae3e5e5dea1cc2df40f7c68e106 100644 GIT binary patch literal 158508 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
  364. SM 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 CFJD9e diff --git a/docs/build/doctrees/cpl_discord.events.doctree b/docs/build/doctrees/cpl_discord.events.doctree index 00bf809b93e88d36e385b81af1f5f4226e29f5e6..a06155489455682155b3bdbed0ee1c66742db9df 100644 GIT binary patch delta 65 zcmZ4YTxi{Mp$+e5Pk(ZsNnrE8*}=?AiFuPh%(j`_KVN*hyZ|G|bR!*R`N``at2cj{ V-~MGjBM>tIG4u8>^I3KY0{|c(A5Z`Q delta 42 wcmZ4YTxi{Mp$+e5Gi4-h{xCa{d2;Ty#m!&lw||+>2*gZ4%)I@}e3o6p0QM3V(*OVf diff --git a/docs/build/doctrees/cpl_query.base.doctree b/docs/build/doctrees/cpl_query.base.doctree index 3d440b8e8a88eb4f170b615dd1b45d34edd78476..2d7ab57a1d7297cfafe9677c17990858aa6d824e 100644 GIT binary patch delta 6106 zcma)=eQ;FO6~Oo1&5~X6tx1GrvrB>o60>mwkzKOcC1GfT2E$kD3}7fp++lr{1Ohu# zs=?3>t<^Z7yKoyB8Fj?gD$vxS8QTQy1hj)ju>)cW+Dx1(RD*S3K)!qLeS7b|bKk3x zKeFteyT9ML=bZaqUOqaV{`s}ZDc!c6mcA5!uTmWg_Le&;mxnh*!|iQhe5?ExrG3oVL;{@Yfe?5sfdrXFJNEO^N`O8dbtQP*<((2vktRV|TeUGbTb zlID0%VcYtLJtVWv&7RhljbYEmM4FzK*0y*{%Npb|V+=-HW{V=w7rC;v2{(+NC}M) z%9BHADH`zMPlr%H8ua15Bd7rP9Y!Vg0kS;e>WRm;9$yyA&YX`sj-a~4l3MzeuaBTH z@s;tnQ3?65Kj$4ZqU5lQ@_9z8*VkYFE_z%+ll`%r*Q!#SYN~(NFj|8O{IU8|rH(0n zqM{$-r-#u>Wb@x93^sqXmF4n-S(% zRj(hf{s0wGRM!U*>L(oafIzu#v)+r=0n`J2Ja`QGioIk}&!mkV(ayGTT&=c|cPS4) z)E2!Z=gXu#nU5U5yjUk92++Gd%{ z+eR}~a_~1D$c?*)k)3znG8bo@M7|I#_~OZig0oq%rI8nQa8$a4oE@nHN(EP!2{qk| zQe#w?O{h+^;s2KD>SaRBcHNd#^XAYMq?ThDqB-rSv|2uON~+}+PJKjB*@k+I zRJsCEZ;WWvqSF%fcbxi?pt4*KCaJtbFU`fxpBOsyOqO|v;@KnztwVH)Nr#Sc^{`O0 z4Si}<4^OCeXa|LeoT^dnfG0<}%+(i#nw^}~8hSzE&7nb3#+n?_oI|6mjIkU4FrIm( z1aFO^GTd!d9Ax6%HGJaP5%K~u4MK9$n2s!`+X%=D1)1f%f{}TX7S`Z>pBb)OowpjA z6myN5>|qlyZ4f55hhG5Gh6zoHo@gd{PtO60^ z-v-nnL1pfjlP`Zb__C8#Xd>!2!M)!^%A4Toe!zM=j^?o?OZMqac- zLYEj137Qh1w@flmc>yp_r2+k|GcPcaRewH=R;f9to?Ao0%J#aLS^4>(K~llM6w#N} z<5~qj%u$TPg;Y*mE2yk5KLb=6gw%8A^i(<57^m(KRF>-tph7zW_`d%d&c)BC8v25_ z7n|iiz%6eG3(Nf|u)Hy$CDDh3Mc&K5xn&Gm&I8L>0Ixf5n6a}3hP{wNI#q8WdC_K! zE-{(0%-Y0^rPYENbJpr-EUgw_zhJO#B6R6DB4+(-(n^<@Sbf}DEv&3>KVViqV>C#n z;bx(jvG*@((=dJ!o>H`i1DgeqwWu8cX^;Td6baz!Z#7`ow-WF-9QZ2;!~jTx1o*N` z0MA|4fEiaL;Ga0~00h1TfHX*eRc-;?a#aI9cU1z8aNx%R$ZB|&0r@@Q<68X5HACkH z+~%EYDkgeuUg#2&&ZPts^P&X7yxbDh&x;bA$g0048Ljf!@NjE6v<85+JczH~H0<>P z*^}9n9xD-hrAtiqdOx==7gko`2Z42Y5bsf}KKje`NyS>^w$Wdao$AZC3w-W$Q~YBb z|ER#TnSBc2A5G%dTE7b~*X;KkzgOT{_J3x0e#U5!4BVnS#K7H5v9gCJm(2>F!#?D| z_XUvU`!4{bK?vMFNdxYmBmu8*;3WZM8QMeoS-KR&=Tf!$&afv7FmtA;Z|MxP`YO}0 zvX4A}ug|mQJEn!ev{nJbw2(0LJHE>xl~`G%Gu#6WD}mvj5Y9}~_Rx@)G&GcnJy_^} zjZZRBouLyNehCbnA-pF&F@@<#!~NyLFlcVrqciM=hSz{$cL-NzYKFC$NkjNfVR(O(Va*~v%Au+A5|_ICd0=>E%%kJU4-gHKdGD%V2S}22RU~DJzZu{I<0e}|^SNxE zkg>C{gvqiJ&+{}$WPbd@WyOs!(e*6}Jqd89V_RgbB=rf0olHpzo0}0SC5MTATg{_HeKF delta 15904 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 UM-_0yFTF#4-zbq!`yp%pe=di{m;e9( diff --git a/docs/build/doctrees/cpl_query.enumerable.doctree b/docs/build/doctrees/cpl_query.enumerable.doctree index db8a26cb658f0aca56a6f09fbeff73f0aa1605c0..4af22b0d00ced14f12e03ae0f48307e1e59b44f6 100644 GIT binary patch delta 625 zcmaE{it*JYk_sLsq_e}n2Z$7!pN@TK&Lo}oHTnX)o4Om4TToBY&Kd9ty!#$*GhlS~P$lm9x)Ocr;pWy)lotSD^^5;^T` z0Fmfrs(}k0bkUrwV8hK6%R2eH%WTfYK+`g0vKE5mb@=B)cymCMT$ae>Ypy9un?W4* z*eO}_m>3u|8>iGx(a2!Uf{A8`^=MC?=%hWl+J&EK2iO+Itw4v$PZkK_oGfR<$;t{e zej`}qfEx?vdYBE954tD`&w^S6qU60nDyPF#a!iG&oCFi#oB$C3I((PA@#H8Q7tuFB zk*q^NXJx$wu?~Y-lQ-L_PQGL$H+j7@+vI)^7qMS(Rlnh?ezR_V=^@L^XtbH#=L@qt z4;xTBCx|!&GUGUiU;%L%fkbH!XI^4%YDr~5YB9+7Ss>MZV3mGgReq%zN+5C0$xZ=5 z9F;)X47r|3lkM!2Cik-&Ox6n&5eAu)brxjoYYpns)yC4 zt&&cC@G($yl*0t))HG%a)xE2d$!IRL|Xk@JsVMHi?37eEyk+zKQHONyp+z z65ijtcVpMU@TpibOWKWiDwQ-Xszt2;y>6birukRNc{Yv`e$=z6`6KJJ1yjwhNdo1} zW=VXJY@B{wELKs9#V(Qm7h{0lEm~DOw1BH1B93XRoOeQ1PG2MVJ9JnxJ#w7_S}-Vu zh2qtqP{j5Gr9(pDb9s8}6o-SOds@PY4A}+#F4W~&Iboa#+h~_7REzOkCfsy+;Y{uJ zG9C@@?bhM*RSx$V+2JVQ z$u%A(8DlgV8#6K~L#&#S7&SJvb!8UyMecR;sz_BT`~>B zuLC<4r<)X6TITtx;7YSDEy11Ue=3&NQ&F9*z=M_%=}`&KF8H9ePkJc${BfIRvY*l0 z%SwY#gPTXFflFQ;wb(5M&ea`)(YC!6E5a;5--at~zsXxvINRZcx%O$a!pYgHg)LfbYkz%DmJzB5|%i}Mr!z%}CYH-FmXEHHCtRW}wo*l70 O6<&IszdXzyJo*GxUG@L~ diff --git a/docs/build/doctrees/cpl_query.iterable.doctree b/docs/build/doctrees/cpl_query.iterable.doctree index 38b30928e5c908af0366cb8cbf775257e88fce5d..56087112b67c9e5b4c4d6795f19ee3494d79d7e4 100644 GIT binary patch delta 3406 zcma)8eQZhY0LFg7WWG){;DbSX5%!RF*r71~lnfDT5dO=A?Qbz0l4AQg$N`#k49Kife; z+CR_N=l<^RoO^!voO}QNFLw6(-28<3d&`o?%&*=LgKG{$#WE)>)Joy%{oSk(dIRNf zq|?nE7P!#)Q=Htx=AqFIh4Wn8Yk`~oTJ{xba0jGeTX8K5p}|kHH@a4^wQ@GlvIyE1 z1o#>Y9B!X!te)?_7p^TR;1y(b!=YJrr*K%NP1DLXljas~V8L%V-DId}Wm=g~E%3_1 zQYi2K!j|ggBO}qF&6UFu5$%gt#)m88TC`GHVsbdpKN@dHY1WM?&6WH=(NCuKrgo=l zG_%-GPRqnoGWd~hms80_vCjfmO6r^#OcMSFL9MmXm>&dGKw| z95}yfIsZp4uZTDD`c7V6kLRL24bQFqI`cvAgFdKSP!FP{9)8@ih*iU(_6j&K-C8WX zR=NL4i&$_bKVpH#h3jA-=!65U)19Y@RM+MhX;TZoZQZAI=!?VX!0$MkgS4g(KUlBSi0|p--q4Gw{*<@d^$5ip2Tpy>PfSV6!C8~ zdEi>N)$m9xJqW2~8wd!Wwp)3t6<&|s=Qx(13slbaD!R~>J3%9<+zBf*gzn+uX!=mc zO~x+4!OpL;3+eNnKE^)6So9kB&?;--wlt7jXh6BRS%H&P_puM*)2?PdTY-apHJIx` zK2ymS03tI&vFkGPc>X=&0_|2m|JP_(5l%#+S|uGz&&HHEV>JXQ-5wnr-VseDv^s4I zR*R07bus~eUH1dEMUk0VMb7JB4`$}9B$SY5xUl}`e3JsN)z5*a7kdk~A{t%~l=DFa z_BNM8tf8LwQ?PDW+EmKN6eucbfd4dDcnArbJkAUmr5R~ZK7*bt8^GM%tfuq`zMGA} zSVZ!DhsZsKejA8F>Sthx=4*uU@pTd^6>L^WLFYt%mf(7Dq3b02(j`1aBPro2g(NhI zvsO6V5wHdHjP>-!;pxy~>{~_tItZ_^n8@;Z=pObGEdTNgWGO&P3L3SlUeD@ybbD`P zAi6vlYRImy>FFQZ9NpPe**_Hb$tF{yz39s{kEEK#8T}{ElI<~?1vhwwlHKI^9VJSN zp3KIuhhmWOYrn`++w&ajiilBkK^5{0@q3g^hl@!TY;gH3eFX9GO%h23!rI}rnBVzcR!K~mtd9wF zq}Rte8p--Nr|R`_8I#=+Nc%VZfw4c!?a`h8feLMp+;V+D5$X-;77Z!;VlJ%jX=f(5 zIPQaA_r&>s^;F>9;WO@zsn+E+vMZ`=WFK$xI&@l@_xIu8U>Q8SYdWmx{pE}ro8cPI zBe@-c!pLsch;Fl2M~w~Mip-x1YU%qXTX6@JdJJ|#=T*5A>9X2}QkTN)&7(>``70A! zXi;HQ{}Z7fx44Q2Vsn4VIQ_#ng&4sGWE7Vew?Rj=g*~3{>@gc$jQR{mB5 z_&FP#*Zk}jN)CvG@|+ZWqVp3&m+nVFLbQgQN(tf6CR= z1#a8qMW@>7qN9Jk-Y@dm_RLLJ4=nxHHn5cI{8j}(a>yB@F`n_WpGx!IL=+-xPZ4QZ~f?DX2~^jdp*VyMW(llJu0ZJ(J| z#b~CFJ}=V??I-kkg#JE^pF~m}>K%;6$48>0^cEC^4ohTMqQVKyL-sy9%-OMq|Hcjj zJ6^6-Vep??(oD?cH`Umv6XyYK6PAXGCG{t-WN>?dSoRF2KtAhsn!B~JO~R;-YXj#Vh0(ld~t hA1rljv=y*qmkNK{U0O|@Vk(E#x#NjNHuv$a{{a=?6#W1I delta 2401 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 GV*dvSA*vk! literal 543750 zcmeFa37BM8br{@QXWz9isHKr$gfv}R00U+d+E7M}Kmyx|N3K*?z3zH%s;f$`s(NOO z6`Obg*@Y3NiAiw0e9mvjTkuAV<7|H%#|seKIJS{7#;k@IA{(1{!9dPAcYXKXx7^oN ztr1*(&{I|K-TTfv=iIa3bHD9^x81UE&I0~7JvbV6;Wp*Ka(!ab$X4YdG9EKHb?Fw8v=_b>ehm`e36wSc@8?^{C%C9-SVydxJ@* z`4E16sNGGYczGO;+TF%#JZ_G_MpEKuWn5D@b?zqFT9gokT1GpupXsp+yPh~-I!i5ipCRqad^L| zKZ*za(Z<7o4~f6iA2GzccV3U@UFEpqj7WCN=H$;5lt`Zj@Nq4 zVU(`5dU5~cs2Kww8`JZi{Px#xOt%fwK@zor5EtJ$SX&$P7hiQ|+=YMckC)R{dS+v~ zqdgd&N#oTn+;in^x7>E?;?YI;=k}Wy5$lVuhyd=jRv%`(5P<3qfJl4ID|;ADnxo0e zN_-k1Y!7-pcq+Zxbk_rECrYEvT`|A`NO=(6_57uDgxrxvqj5TEk0)?_4EWf9D`Wg; z`&uhK*%_R|H(6TiY;=!IrhCWH+OXFeMh3%}rf+r+16x|1-?sL;J+x}Uy| z#;tMOmH=&QvL67Nz0q*8+-#3V&6T(ZvethT8yh0OURK>Jt5Q!ML^DgI~742LGj>cD4td=;(59&^`&{?~h00 zxW9^5Cetf8pEcutH%ehm;rbb;aDBA##_5IYt=@!~_DJ`N?v>N?U}bL{f5S%i8Qp8T z$Kb>C0B5hJ#zYH1LwqN?^Q!LE-B;nA+h7SGt8a84U_-a1Q7>wZBKgAw!11j!^6L)z z+FV&1ZyaYMw)a~7)k$j=-tOE8CL#!S!E3d8Q4`iTVR#$+KH6xp>z6SUHN{w>MZbmX z=#tl^gTeUGrPqmTkG>8#@KHYT;%Wpubb8!u^?HL-&6UYFfAg85n%8B|wBtSdxcZQzl|K?c?j4?4Me#lYW~;W^YC7YEcmgCWBs$9VVI-J2M%>=O&MxeQVh=zX01zUO2V4V$N0 zX`dLBLwH~`84f{?jMSBf`NJ-O_a;IBf1>bf!hI;9;5q@k6NFGR8pgfBs=z1x1YE8C zbdV5*>I7s$bEVh9#lf(%cL+EHF$%<8YsDa|&K&{=6Jze~gGvJgkxtw=ejHh3Kl@FS z`;WpExUd@}><~D6)SRTSaM%pn`|)@fw@;qgc#Lk^%fC0{)&2lh{ljeRMcJQ$kgLFX z{Nja7mI%Tf;-Uq_348**IRr6!>>PSt_a)tzvIp-2vD0nB4a>mJ!2V+N0s1|91du3% z69;vd7y+wI;AZEzH)_JFk5|r!pLXF-ZQ!mHq%9x1a{_9t3GWWpf|zXtI2}JS0k)Kw zKB)cHY!SDEW_aW-kROEZi}dSU4WPO`GTkATH_3-{lNN~P?PMZ=L;^g4Ap+P3p+)*9 zny~ryknmmx0mX#HA*Mc=_7uvK(T?sE;_cp-Z6|AJVR}CP&Ljif!S%*_y6-`XA5_0J zwS_>}cCu^n7?xJ|N_PJ)`i*N~5WjRI15&)-M)w5!nJFH4dM_S7~ z-Z}!U1@H5%`tw0NG+{}@QWRW&5xwVHi~rs{6?bsaEU;1RZAeJM(nXyd_rVN~4FOec&JcHy9QLE}6o5ZN{2yy^8$i*a!gB;f?5KdC`3Nx3Zq z;EbDN|KZHC$|#c^1PX}Z0f+?xZa4k1(po12m;Km%VfSn4YWGFm7qbt~?LLp)zmM(* zVVkzH7`T{C4eGi%8Fs*)1Pw}N20exuWFz3%WiYWpgs|DzAW)`&|3SY67B?}8xO|A_ zWNH9u9k)q#(TwaG>S1N2Z%i-ZZi5g-OE|;E^bi`5V7h@EAEwR0GFk8BO6YH;P4q_g z+Lv`NXE!h#Q)f8>f>UVN11pd5;$!T7b^#5zCUZjgt&@OhfV_d2sk3@4}@*k{Rj3&?5U*Z!AwMlE*1KkrhQHmMHBqU*$PaW zaW?^}Nv_)TYrEs|aP-1PquuE*C8JK%i`Uboel%|MhieUf@5^p)M5E_|?{)g<+FI{u z8v%oxImXB=!5K}dwO2ffi(b^}=bktM*4T*~HzEeU9NdXV;6t7v#eeRJZ^WA(7B|U> zfE&<~;nWagZv!*Z_51DS@4|K9tN~21f;xY{_#J%|lp^B7ZgF9P>hv*o_d)R^`e;p( z5^(=9oahR9Nr|IzD}`Utpkeo1D(>l_oD+@0Y^V<9GUp#)tEAL)>(cQ1Sko@q1r;$GtG_{`+6ni+_!UJ3{TvwTP)i5`ncEa9NsXoVGexDaf&3249Z zMvGR!PWB|GH|UrB>=y_&0o#&T=C<*b>;j4>_Gt~AE6^>y$y%SA+#GJaIDpKFhl6lUUmt5 zW^%khPSMYou%9)xB+MeZyo+6Crf2dt2-NA%Va9=4O>~W;D`Pm&1r7nwunjDQijm(B z0tPI@_DRDpxe_H0yC6(9o&GdfyNBFtkXjH3ic`R+e865c51PNiv$>RNo_TX%a+Za1tfj_RbPJ-@byo&)8_%r~8$?iBb0(S02OsxuIC^-x)#02UA zSf_D+Wq@%FG6%(?b^;4-%r(iM!QkmN5A>r&Kt{BvnZJvJl|>n;-1ABZ@kTw+i9nf= zT-gW31MQW(UtF@5hq&NeiSiW`cBb1!K!kDk#bSa!yl6CT#XVSl6ON+G#Km?xfbfHi zpa|B$`5{cr5ZvyfH96h(>=z&XXV=~IPq~!dL$~y!Q-~3`eEy^l@d+lu579L=8>Jl~ z-C=}_rsiIH#=amOvGX)Wh0|y}mhShyb~ElYAv8*^1w2mZih~%x1g-A6w!htECiKbZ z46KO`k$JieV$G}l7QPUD8ms{9%Yy+Ju-j1U^-zfKKu0R>QhAbe=3y$_479nkd z5P?7d1V6?Q*l%^36uARcOyKWr^S~RtLUa9g;f!6@rYKJnVmU%!@Ef>lytF+WGW*t! z`Ow4=4Q-@86=Ji_` zWwx|V6bChC|;{}Iq-=!18f<1<4Mu;YQQi-GZBK}NkHSOfhIkLSVj znH&-4ug3B)^KmU}+prZaEiJ0=&aT>T)Mq#~2ctC({d}{!v(h^0v#=Z5#v< z_n4k@tGaEkx{dj2asur+CzpXeAufr@iHjVsa8%8=U(E-jC`9I(F^$$Rl9|1JsTxae zPg98R$K({3t6SFMJ{UXcTC)e13@96gAq{~eQ2cBubWg}hG#FV38p1L1;y(2R?j2v@ z7T&J_>Zk>5=;Q^cyW|{A6Oh##AIqo;Q z@njtL)DR7Ia$Yv(fE*((s8NgRL11f>D+>YyvN7N@k3m9!MI-UDADE3Xba9{!qsVk4 z@$vywO2)8DK<=Y%U>z@oRbTS}c2&?4+W`Hq4c@f?KZ`xdoC|(O98l14{ z?pANuZ7oM&&|++eMBk<2RyLm$N-*PEd^&2l3csq1+KBV$m-L1|atwqL+}y=#2+})fMYsLQsUhh;AU62aBIu=mH*g5v_KNXbQQ^lK>18;^L?WY8TU7BIdA{CMN52 z4eTv2*-sf@zVv+L|dvX0b zOUUud_V7*&)ev&{W%L4UcxM1P01Q2&bt$mU-hu@_!3Cfojd(VrhzO^Um_V!a7O*yN zqgYNlfVk%9Tf`lpz~%RE;lVO6BwGv@lgaXQ4-1)4RvaveW9OhVgFzJj3o|Z3OiwQa zR~iMu@$MDVy*xH5eS&ST;&lw7sG_^Qy93jx)9oNeSYGqZz|I$A1|OCOM8!HwC@>)_ zhvE=SJE#Ew6Lbl+6Uamgzf3QeKSLO}g)*K7!NS8L28eLPeK1x*zD)PZ(tstr4OR>b zqJp^#w}AoAZ=q)l;~}Dr3J<89U`Z}z4hsJjR!)@ST8D&?4mn2!D^j3)A$lZX#Wjkt z1~!IGg`qb#(KfoT7jI0jmLni3f-$>(`wTDxMwH3A+linvMnJP2zN8bh&*^8#vGP}^ zst9^7fh2x6xF(=z@NP``tjCCieHc5!0<%}jTk+=+hyyAjU17HENG(JWB1mBuXpi4Sq>1` zpacO*VECJWlALarJc9V#i}n$E+F&11RoJ=UaZdM8auqyiQu+`yK-~y*N8=R&9av5R zIcvc0V<5}nu9HouK8t%zkTqE20b=!y)7?WT13@WFuHF< zYH^w4)7|MxTO0dKF&39Gux=Y-eoJvQUZDvaDO0&0~TZiYjZz3!gZJ^k2pk4P>7H6dr*Ju%%)6F{LGE3lYMx1-Gnu%oGSB>61F z1n#}#10Vg{8~(?y{c7?#`R&)Qx+B?sp1AfK=l*4~Q++%0=H!p%oxgeR_T(grknh4dF{Qg*p>WW_3a)1Bl&ar?S0o=lzdu!>pYPB zo%;4KekwU%&iOxo;!Vk)$!ov;!`qY3t8f4P$C5vi-~K55kI8}@_lbY=UCD*=+h70i zzfC?P@BEuze_`@P`Rz-;`*89>@$H!l|Ikc6CBI#C`?n>3Ex$eE*PlrCi8-Hn85KV2S8 zIVA7={U3UNa)J8x>2FW|M&9`cAGtaC3;FF2pE#KOgZ%b^>)w*=kmEjZ_ZO3G>f7oE zk}s({AG;~}OZDw1Uz;3IcfN0DvPXS;^2d|El6O9F;LnnC<+Ug7`r>2?C3@V@!fZqL z+UYLt6GGw%YhPL65$I7+qvxR(dF#e^Za_UOaUt5T&s|z-!2h6NxgnH$1B9^BdD(Bx z)^Zyp-p2IBj&Yi;)X>x-ND^6}Eyv&C7%$&NGa4IQi-If>6~1zgTOD&0z)o}pm9eX&(gU;A+hv(u82l`f4_Tu%B8Q8cvIC*&ItFuOAQ3UW-Tg2maRUsE zXf+)`LIBq!43bZB@u0T$GkmN4E=gYwX$J0GX3N~wkZ6fcN9_qKbrLM?Vm1x3hW43i znbo`AoWEX_q#DV!^BgxqH8Cr})TK^2MlkH&6k`b^RhQ|em&?>wCf-$wgbd}H>n-r! zF`k6s7KM732+s^`$blKel#k2IBH3~ls>;P^nWr^$?&O|3k@J>Pq=}c50J~l^PXO!O z<`UdlAT!^nBorK_0*jzf{Hk@5yOQ&uwuQe7!TRWYwQ+6!N|ut%r4KaOkSE#jy&fl{ z{wqzXaCrs+)OFKb7(rz4DCD9}V!0}m)}?EtCWywjF=j3w2BAC<++!M4E(C)D)6I9C zF}2Tz6usFkS4hQ=hB1T|Q`rB9brM8`pzk&cts*S5a9c&bTJqTigaP@B1cEIsy&jPz zsMG?_HKb-mQlZyZsoZ@i7xQ3^Pq1Q?czN!M7~^R{5fiS1BGzMEgpzXW zR~p*7VByxUYq4m`x5$%pEK)A#8&4}m{6fczh-76$e1OtYmew=Ok*)Jui((s3krsFP zcmiQI=7Qoc3t8*yGx*Z14n_A-_0L}oiXT&FsQ6t0O1aKJ=JIk1wdB-qwCG%60L_NV zpp^$!q&4O8V)Mp|kjgy6!oh>r)N>(~fC;oXZRXq4$#8InF?kUh=5Gp^U!v#ijRI_m z@xf78?$^ znS?k?BPLj76bvWY+#z#8!Eg$Olk^aTj)#It`5P9oa$_nOPAs(hbT*t^aY5Z_#EsDz z+Ou8M1#!XB(PSxXMc(M?Yp@-0C~Aq`j7$>pvW3AP>E6{0GrL|np!(L5_D6quZ) zwjI`tKh?I~_4&0oP_jIPtqddz>%`8SvA!aQNo@7ye)?BR?9Ekq=q}5`=7iE`& zI?+eN^i}SnR@Ti7^*VE}*Kx)RLbMN~OjT2jXNS>xy<;KLcHaj6mFu-$Q1Gd;ZJp0` zN*A_=5*xQrseZ7Gay zrF~_P6u5d`p=;-Ji)^uA-eUqOBWHqnPhChv$k{3Iidae+qQShUu2#a)3g$iRo-#Kr z%IvBgs| zL&ejkRu?-X!T&N_OfekOpqLEnNh_6Y5os)PLec^%9YN=6Cb9lmv^A@!cQYh3TFZo_h0#=H3%AYBBx!+NCxcfLyc*uoXX}#| zhaHw2?`qzle!nE8$`b~maw$|U^`K>BMRu{f^9A3hFI&2bsJ{%*2Hz+6KICz4c3*<4 z8ZIO5n{cE69R494LR!xS)ySi@F`VMDOt-mw7U|xI580WyOP2{GWDMSHsA>ke9~Y3i z^Mc-RaIBOpQXw%ZjY2gT*5#F@iwc*O(d1{d)nvSDRc0CGJfDutL;^k4$?9)=91oSN_ zp|)-QjbDSC=voLBve8n7nd5tL*3fA1BX*>-M7;)%_8Xkl+~3KXxDhOT9hgHXS1STpucUGZ}EdV%H$&sR9d>aqNX@rVrP0J1wu}-fx zr{uvkzEGH}011in;EJ>3EuLDD zXUjPEc2o=Z$w4_@li7r1iI@xhPJIfuJYmg7$v+}nZahpn1fz85cDSt29w6B^v+x$*6mkA=0 zbomEmZ7xgXie5{rHoJAGetDK_2T@)iNYAMHMQFDsLh51%=E!DCYFwQZB_=n46>t&BCj@Q2y~?!KvA552EY+N~kUc4;S_;EO4DHqPP$G%xTB;R7*)DxmIVSzo z)MZuN9#pN;$hZ2(KOE(f8;meeg5oOOm{I7^rRAkY6d$A|LQ89o`%`pDsl}{ZK;|qe zp)y?xAUh=U?diOSoNJH@ezIr%!Q;s;UI5^d#JUXEK8v0FQsfk}OfrEa#;t9eoU$ro@VT4jb;2>+IwbIqe8ulRwfrCaiAzN^Qy2}&K zja;zMnj?b4JaPOht?Cdsu-jcqK`B0jzyTx}blV4l8f85a-1z{0#*2#260f?nmFA0Q z!-1#AQGW!j<0T8vF>vs=q2fTxM?#ayUJPqukeay9bf*AuPn%kyJT+QP2a|pWs+KZm zG=z$SY8X5VDh`YUL?<3W|I3cPA{+d-=JH_N)K;zJ5tjj!H3@Y8lUoNQ7hGXY z5wD|hp=crE{t@VU!iXys=$6o-Xki)mmga0Bbn&vV5<<}eKRY|KxTP3y`B6IR3Sz*- z!p`wUNnm4Jnk#2mumnWRFcdB1IubcO23*#hPUsMO2(gDY9(0u7J}VS0s9o=&XuP=NC}l?gh)w< zlu)bx5Glz@-w-KTZs#U#G73IKO6C(OdE%>SM~Y#_C=Vb+N-9Q5-gf1}IScro^BhuG zvDWc(p*%#j(mRXFLyYvDS_=JfEAB^W1HvWI>L5LXCn`ce6_#6fd1ZR-r1tr&540GC zJT?YaCvmSs+UaRqe_{as$RtY7G~{{9jb1z&(+if@y=9a!jWNP0MLwavAB!t|&we1r z!!%;4_NKC`4>yiwVmHPv8!@^Y_23M<1}3WDtOsKI5q^X|i_klnUeYt_b7OXIgLsgf zzOfdqE%T{Egh<2;2-B{jFczDfafHaI=eB8t`$;lVFT|7}ZY~y-5g9U;7D)juj?~aT z8zT*4tVn*;tiCa1j7@2|E^|3hI%uJr>T*LXE1z{Y)n}Cn&Qz2eyB4Ffc+`VoHM6B5 zwtq-1DMQPyZhsnkXLb*3zY}j6rNG4Og#~!McqPJy9O?|K(03IVBVp5}I&-_1kl4}A z0tfmlF(@e>E}f;PGBjvdegZay&$M+a zSHy13X+k;Z(?Ap&pw;O}=fbcL#EU7Ut7zms%vUO}n-!CQDK8b z6Hqg438xWJ)J)0jSxKJD24Xz=vN0f|r|8VDeU^~T^`s@w*XcyPNRt9Na!Rqpsc5-7 z7@QoL;={mph~GBw)Oo?zPi_3x$b|@?6j9fr(Fm#@ng%l%B8+%j6a>mtQC_&s5MlO1 zC$Q1h7MGL`~hVdphnmy?0XzhBFlL zPbu|cpdd(5eK>gqJ^QwuZq3B zrGk=kUdDGS73tD>XQEEXk(@+>q9aC*&PcIitO}ADuxhkSrpSzClITW;%w82R2bMR> z=NL96J%@$;tdrz&-T>D!F9#5xXk8niXfuZ%Zje>aO_h}T2F#&1yulpeDE7+g&eDen z!zAj&idl@ayln1*_Ufq21kab=pGG6-%P#LPg^J7cY*ehGhK|98S!LZKEe&m?ZR{6g z!CJ`sfS@&0!YmF7+`813p$Y6aHPwmXbs3haJ$`x8I|-d|oMx@d$kg1lvp28iV=)*A zt2lJhw@pt&2iUld`|B|fFpUnNl-7kkb&t zHu#yPs>dGK8PM4c^c)tOGzW-iXe?4OlVCNdgf1;V@&=&B+3W< z+m~*=#W-*Ys)pC-Xp*Af7v~aLt!#3QA+LyQveALigA@XP*waJyAT@AiOU;ldM};jK zC<^@KuwqD*XV;s)eL+7?CdZx9f@Tm>c#8JWlsX(4OV9{78NpK$K{++H={i)p<;Db^ zgM@m_L7xh1NnchsR1Jedv9gF%k|#wFg+zJAH57OciE=3j9m+Mc^ofm(n2TeK4A<+D zB5ZVWw{j6HR;_d4(iF!`2=Dn$n6bOW5MlO1L!w;PQ7B5VD3l$otQdwbN>jRAYTXeG ziE@X5rYI8<<%Q@m!*Z@t4R3cmB+9X1JtWEj2{I_2lZ(}C{*WkNZA57JH`~1!&*jd9 zNei|)=z9uFeS?rF4~cRS&M5Lv$73)oMuu@{Xad_fG}Vcbr7CrB!kH+Y9cd0r;KHm}T-r(ut=NMF%W+)tN8`N0{SLs7cB zMW#uNEKY%|1shq0P$^EL@P>SW3DH(+LPGcDRCMu!{bV|uHQ!Qcp~d{^MM8qlTwY@m z^6R{lId0P8oy?`;GjiaLG)4V$FO0eE6&>>HA-@h?_q2*Z$(M$y<={&_YZmhB+0dC1 zq(=E!e$YdR)zTQ6R2(6{E_c`&ksd?v5z;j#5Bc@}2s`|TMxsw)Bhk`biy^-b=TzpH zuPVbToRaKjy08(Q?U>i~vP%=qrB!Q=1~Xj_!y63S*YzeDDl=*IwKXg=Vb$lOSK4$= zhu!0prI~De&q*qn;A;+PG5kdVhb=4x$PrZLYw_>7uhff;QxCRYt)2PdEGyc= zpLoWIzu4=HiL$U)-+|5CedlDqX&upXEKaqm=C@bhs0tVK6#|KWFA_mwh=Nu~G59xZ z@8`Qv!uI~Ky+55p)k2PZ7VDN4WfKLzCT@%!d?fkxoghzTO90-*pP`D+bG0&7d2F;=EJhd6LdD|3*M66L>5AuO z`7)GUKn1b0LqUOVruFR{By_V8)s&h_D)Ufwf!hk1<1Tg#8^IcvP}P_`W1k4ThqeZx ztwFkl=eLHk3s}XOE;6D2Kh))dPSKs&r(;`#91Ui=9EMLB$}U3LMLTls1CTbUci1A7 zU1&+PPs@QlhXJ`~C>LfOR@m0cLe-msIgms_K#K_4^6{2J0SlxVPG1c3)UMWYc)G(w4n zmSN8vJbRO)xST~<<6#qeN5Dy+Bh?}I8QHtp%51W;+DY4#w)o2=6^+UmW3wUgu(KQ^ z)NruUQL+iM=K|l5r4Zqe(Q|n)=qXAXRieVmRK-i7hNGd7aVlEw4hAQ!(;E$Jv-Kd0 zYD4Rc-c#5*!|3jySrMIRr8Vh|o4wZBa;HUdD-?W$f{%@<5jrE`dA1aM80k>P&Txuw ziso=bd?02vbh^g*qX@qA+ffsanVUqcHK@V*!gAD3tk0B|%FIxxB#B3Wtd6E8n9fXb zhpKUQtl_3;B!L;CH0m_zr;KZ39K$M9w2D22rXP|S&*thA=gK8_RxU?T=UQn=e9AA$e^FW#{ z^artY4mjwOHPs^Bz^hOi%9Y_dDx5GP$`;C5&nV6_bd8PT&>tl92g!zEY#xytg zQlgiy@CJ=Ms1Qb40N^XRQ03aJ3S}Xa=yW?8Vnr^CUAY2wnP`>jP$iIRBt9HoVP=Bn z+5l99T&rItJw%L_LPg;!^2=OE)iREmJ-sqLB9Y3?opNRJRP`MBXefRO#V?`w#Rzt% zgUPU&>CX4ktjH$WTDak4m=4xs2)vo1K=|fD<*D!m@2N5A>pi~=e@V#nQ2gRLxW>Yz zQH5c&@)RV{#X0}2`PJ2*Box0GWmL)#C9jw)fqSYthJvra9Dvg6wKZr+J8IDR3>8l- zqzST-c%vMHzXqZyOHA1jJ$j0d=}nQbiC z!UiUx_+^l_k+$crJ~Rm1WNmWip{&rfKu9Fs+ApG^j*;#op>v^kQfh zpP@!BBh<^J@j8-0G*KJEv94xOQ4W61UOrm;P)SuIhgt5aZDF?-=gJNBGO`1ly>g9Y zq6l>wor;~~I%gzL7z$2!(OMy3sF$IVJAq$g{Sm^=##vBh<@4 z(Q;_)a<(^iF~m@TwMU$8s3u!#nJIjuzi80zA(^>L)y?ZCiScIZMnG4LrgF;>Br5yhW@tS$jfZLMt-;8DrIJFCGa*oo zh^!bL%4t@6H=mw z@|xo9JJ~wp9Q~)bSX4Yjofu9P4(BEfApGBidJZVEG$K3Bqr;$NZuqhUmpB(Kv>-OwyJ&gqbi;)$(MqMk=E=3Ysbo4dpfE=^2qSB#YaX@6)OsG9e1RW4UqOgBF(!bvB{SMzC1Z2rC&mK;oJ_ zZWH0+P-heBY|_xiMvLo)I-3YHd06`e$-iEY6j@I3t{LoZt+(P{rXtq}wC6?1L!C`H z_Q~i)r+6#0vEgTgxD^(E+`%!knRW?Ao?B}=*QWI?a$ERNo{XjGxP-t0baVd2diN2Z2_RhWn4Szl?L zl?K}7)+NK~EjUOS8ch!&>_@BlhQ?%+0`ov*ztM{`=)fl7sHy0_oL(3OAv_v()|KTL z0&kqQ`lB9eJD`2e>??4kQ9+n$Tie%Ly%?}H$UWtVNDgCY13i@Dg0nrC^kF;kpa+8_ z-#sgz7(B)UBqF>zH?UL->q^!#4jv_2#s>Up>Xvx$gWMjyG6PRr%v!4KRLcNuCq|U(~AL386jxc6113| z-N{90AP2w7_>hV#6!3%so-sx5!#Pyp9IDX>O6i+M({>|NPSQtYtW~?3&?raWPVTa| zLIF>do@t=H9nPUb=Y#KQCo?=W%0cT|^MYVIL6k-v_EW|i!es{kGmk@1wj&)PqX*3l zJ5~5Nru(c&BE7Uwz>~o>6aCJNVSAwUgugCJA{xd{lN*iGxKDkF%^eOJ?L(s+-PLp$ z?JQj>jC~{JDA+qQE}TQ9iHxiTgMuRz@Pq;$%n=)5+=}(maVX${XpkX>m^^n{dt~t# zs@0ZSp@0Ws)1gt0Cbw-Kkzp)X0gn;d)-ntY?Q^y(M`_?J6#ZlZkF=DH4U!siC8D*i zbp}~%qB0a`G7jFtqBw++_snQ*ki=FErtxsH9<-I2**B{FE}aM?dq?A0U%!<&9gQ*m z2o0SF&EDV?q|#+~KUdf#w|0fv6Kgqpt*&wPt)>J=66Fb8T zC8Fk1hgL~w_|pI;50yo{`?QhMu^CV_loT9mWQ@fCE$-2URoNk4%UMk7-cVW8CPW#{ z^Jy6ambCJM%r{m_C51@kk~l#uqf{kjNX=Tc7 zvaN)2$i>godNMTp36(`u4I;!vs4U{uRUj-87bIHC?R?rUma+4Vb1upy)i7mUcce%z zb>PJQ<^FO@S%b!?3|*I@!I-;Z%%waE<*I;|@RL(q7%GcGWl`?t`^;`2BUov)${-%j z`0B9BDO46Uly^v4p7z^I>2ZT2am8Hq<-wq*d~;*vOM3x4U{*}SVi=;4hT$$7l94DC zS_ARyFPO+te}ttty?DgRq+R&RnB~|aMVags4SP{8+tiB`!x3B&3&%V=yArhQY$sZ2 zO?u;IueG+^VTVE*oz?8+Abi>4upCqOqL5mY7|8%_ID!k)!Wr9y+gqWsC{z|{XSRmQ zqK&DcGc@@XDvPAK6Iufqc@m+yaTfuwR4h6`Gyp|XhkL!mX$+F)Is zjUFnCpf@E{f;J)yQK-m-^RQhbKN2d7!Vz3j6Xz&!73JX-3x?-e8o&vaMZ+`W?x27B z(yg}`2W@O&JE2fn)Qh2)Jr=Hn$|9pfLN;X^DvRWf7>W?Fs5SnTqVjNlg9B|_M$Tp# zB~UXt2z~qT(QL@j3Twk*py_xrl<>Gps2JF+E)J@NCc~j#5@%FCXfGNni&P^E153iE zRTLD_SWzDmDvPutV{ToZZbw6uyR2=JQBNgeuqx-!kl6%*RKvn>49O%dLS<3O{=eL; zPG06rCX%GU;aUFjGS#Q*D6u~Yl|`YlC{z~l@&_R@sk(}1xVS;X8VnFYh+ z3^dIkb%0^s3Leumxn2$sdKO_^KU5ZVMh$9HU)V%b8Q5fUhsq*g9m5K?eUWUTlo6%N zDUno&4n2#oP>N%<$&PSgA#_rdhOiUZ??ydvt7$imXt)**9Set!30^KHJpY92U@Kn8gvWNaDQ#i5k{!6H_RPYaBNefu(yU0oHU9Ni}wE!YrEWSEq|Of zam5yOX&s&Ql|>hX)6ha?k@AswHBBR&h8AJOF7zyl`kg3L7D+=_=qFtR@ZTuQuKg}` zfRSvcKnL(vs4RjLXytCI(6b2mqSMIqfee*JA~IPJ9HjF_`1!0ZgH5bhGbkupFonvZ zKA7a%;nRk}EAW?z!GZE|O) zZhcmWXJ+gFk2p3*v-+R)D8+V{s<~*+8-U&nl|@mbu)Kq8)9VZNxv!0f&_;l6GkQMT zj1nq~LS<3LGc9C2!_qevap+kTdKTsB99!~)o<$HMlfASx-q>({cto|oAe;C$1WVyE`WbUKR%xPL+E`JDwINnQs{kTB&G{$ z0{DiZ(EBL#K3b9n0JDXftP+9js#1416JQ7xO0eQWg%Y@E#5~3Z!UAa&DwMDnk<6Cq zZPdc4YT;D1hG<>@Cz#Q(D73tc17D@9Q55{8xMcNUy72$l_GaNh8|T~6x(*deOBl!# zIj@48mBhX)x-}WcJ#Y}y2ujMwajVw^j}cr$cCMfiN?eIWxds#M64;FaR#9vs8)Ur` zCJkpu9D9)5^$;qQbiG1!ktvYS`zRBh9fb-dY&o2xmDPe|DQd%6H+s$3E0T?h!TwxL z=~$f+95Irq!7c4`vOd5jHE@;*)TtU{@5p9lh|eqTS(Y;JS=l+nE1=EH+KQ#n<%Y~7 zQ(EE<=}@7>4-c34e2E*MLKS75gV6hkd+Ip~TrIy)p%f~Vz`GkYpm3Q9)r@Im$R;7h z6#tlZbf{3uxZdNm)gM8|6eDWdXVFqaO1G-(6r6E=qX}13<*DD$`$$GZG^-VDS4o0! zs#+uWq)3x}TFY?I9PHYtc#Hyfx|UmgiEYa>Grta?oB#TXCt`-`XD8D!JqHkcyMF7 zCyj77ShLkT)jBiUc=N`Q-79i+#YYdbpt0k zl6)5Kesp8H;}qmg+k;7eyz%J9k?95ab+mEp!RfZOxIY<3@Ofb}N*v9XAF{6>`w?~-@rEUECe40JUH%LE@+%+J(7MAh`*{kuZN->ELth5_n zPm5{?lxmCyle8UebRU>*Z+D^ZZyNPC9^OcvvmY1cYoN0V+&&ycibk!#F{&H5vg7@cDv%3zR#4+TNKA z)tBW~`(zre;FZaA+qkugmo}2;($uujljp%_20Mo!c_I7);Jz6CneIR+XCP71`QUV&0 zXE<5z#iOnhh9BG{45+zEVAzQ)!otl?5PoWtAfR?E0f9Iqo%Eg0fA=PzkLtJN`6R9A z5N{_0zqUyTP{Wr%um_1S=@+fk_iqvkG$cx(AXZ?ZeiG(l{ zmC3@GcN2s1mQ6x=VL6ohbttiWXcj*EGK1_Tn}m$~(qfbHfP_qh#j>C|t~1!~-z02b zEa$$fEZCNS$o+`gxMaaBzLi1zPc{kh2g@P8+zIg*oebR;niky0VC`-a)=!ng`V0lD zJYHp?8TS(xeqA@8&~9c>uWu6Szb=Pbi5smtCyQM7Eeyi%*d&DeeAYVOjG2W_t#xsk zLH2!{gzOXLxKoejdH+1f#AOEA4{s8(KP`uBAMoM=Q#4fQlLZW~p3tu{xc=QH;X1FJ zmS{k-2jlMaEL6rd2Gf7sBurl}$JJg56NNsqK$#aARKK-JsCJcO>cCy`2n>Zzo>k?z z&S3k%CSm*Aa*SO@+{H66`IZdccB1LJjY0a!O+vc29E&Kr793F283F9yeKLQDc+QUlvPe`FevwL z63UO2LwP6zB`bQ!f{1r05cwSpzGrL_zQ6Z{kL{Ezf{)+9;JbN~@Et7Y$?U4(rCM14 zv#Unj!XSL%CLyF0P_dQ0@6{9N-kK*Ht*Z>KS8Nil50z7v>0R0>v4lG%vPffkSG&sK z`npZR_0e*;E~XX1o{S9$*mjRBba>B+rgaa4v9n1SKT-}O<2wF)al%U$M8)gl`ZA1jhuTJjNiLS7@sW1;l6t# zItg@<0-2B!&iHZGRR-4&Y!a?NDTnK-`yiM$=uF5L#%S8O8(~Ck@vcF8lm)W*RtE7; zZW3b5c$P$Jiowv)+I@fl_3ljqg@+iG0CgS+ku0|87xw&L+vM{x&s*~R%MA8fJQa_- zxslP|+ay4kSuO!+=^@VVlOeHGZ_sY_7Byd+Qaw2xe7E9`Vx4V2v^hf@OA1PWy6hEnOz-I8Au5j2a$=f(qSC;7uorMPK?~QNl>ulqy&_m44l46Xu(Tqf`UtFXNT^T&D-9AV7r>l9m1HHDVyEJ(1QXo}WvemYoKVsj zGrtL?Z!rU#P#P7ppb4ciF&UXqMiEnj3FY-LA(v2A4bxx=<+3pOlu!l?^<(%wp%^*_w-bs`W576}s4oU)6N;{4AT*(9CI%i8iXLL9FQIrH z2G|mcl3`FQp~w`5kP?amVTdN7I17eC5{hSFm?5E90lM-D`Qzv`C*=8}dzz4siEbb( z=R?OUA@2!YorL@qbSM(?3ea#*$ofVTIUze24bgToMWK zHF4(j{4rXDqGpQKJ?&ba!1nYpoSi!yCTYCE%F1@O`t9xjEOkks)f++t2;#x z1~Rg~nWpf^dp{{?P_p_`8dpk`rOI=@rzG4;s4c>3$mV6fW3RV1Ty`O5~@xi)N zsCDoFBZaqdRf6zR75_SK(5vFSM8%)>ez1l1N!=+-wAYYeN(iz=RAUMS#VvJTgbP91 z9kF#nuzaV*FL=L@o2&4}%H-hBdOyozq@STF&Kf!Re(yJ`h`mBN_}ku3wea}fx>Km7 z@SBVjTP_Db?+toYoR`SK&v`%CLi>|-r{V~gMJ%Eu2tj=zSbM^s*Jwt@JKzHV@!pnp6~r!3+d0TJB5k#8p>Mfd!{UE zOrfCo$+`=c>w5~cZ=Jp`-qbkqriz=P@TJOh{m}ba789+}6laaD|32?Gs))TpUH@k9 zr&@TN)}2BvgU1*twp`c0%Nz8nI4{xlKkxlu3+?Z$JH_15UZU$i;0<_Hq!;S?-}ip3 zh4S~;ox((U4V|IX4wG9orch8Mbzg+59m?u%o!Tkg%D(@S*_e;`US*nRkN2}IKH5oB zoHd%K;r&ML1!-ZgQ1jgE{ZtE&H`bj(t%PSXQf#^AdC(j5syHvvJP&w3*h2gLb*Gp+ z+DkOg#2fIcNH5epsrO?oln?4oF?W;~B-GyS4Rlp>=O)zN=KV+u)!$cl3KP{eG_+Fk zOhwd~LP4>u?u&3GPX$|Br{oKJ#r%%FQ&zt8(w77zUvO>x#J_$R&Js3P_X z75rzspK9Up({-m%tKgH26kD#~4_-POlhoqavWl5~-Ve6WzPs)eb4UB0SEU2o`@c9o zGlcGCt_>N_^#;Bwv+q3&r!wNxkFuw8ys60MZQhTzP~WIK#oSR}pyIdsiVWPT*mR5?Msfrp?C@6ltu9W18o*JobouaSXlm zQ>Z2LV~jYnwhH#Xyfup3i@5V_r8jW5J$%16^i}b{?=WnSj@w7&<2mM(g8FUmXIsdB zZ`~;>BfoY@-j&!ejW?S(+H3V!CvZaF;^+)CR5%f!)nPd33swOgEH7a> z%3-nS@;PrnEV?{NQ*5EQ+52FGhdHcAi^JBq>$b%%zHBx|uqCpm`wpl4@kiO?Eu0?o zezt|veRZc$yuO>J$SpsuTYXxV+kd_{rXGCK)EyBmmah>v%uiVuM!QDNF*?prK*|X2jK) zLP7C{y0V>H=hRDh>#XzAzQjM|O&B+4;d_;t;XmO0EQ^o+B~7t~da<~&{XcuZQAO+( zhT?w3`>7Tl-(7bKwG!UNNHJ@pyR@?XBi^7_#d%4t?N7WPY@z*wb*C`VUPFc{F~}BC zjVTlq|Dx`Ta4|?5#J5fimbFH|{PNjYw)k3QQt%S*XIX4?h^9Deq~PJ~_uA!inj%O;O#uN&Q{dHf2 z>v(GY;;rNB#!w269(lt1Rot9}uT-Yr|G@iM77P7e-6<6Dey8pfoOsl&XUm9Ja&F7{ zSIovd!k~jHk$LcGbdeiX6t9uFJo0ZYu}xhD26dOy-a_0QFv!bEiq z`&gOSOhwd~LP7D&x-Y`jJoQi9IyGN*tlX2{ujA$>e62Da{~7ORS#0!anj%-n&pgdr zunzZLIU5Vt!rU}>9q#geq=mrkb*E4(;DWkSsCCH5xT$sc$-2zM*CBN;^v~io4g-vq4T@zPN5dY8yH1q?L6(fCu)r+X#^)P!%-g4(brYG{|nyWS4I8)!z=9h zM^pZM3;jRq{csEYKT~&#%IL2xKrVi0vb+|LM$qAP@!mG1l|12ZWtOd>GIvEyU1wF(IMb70{&Bl(l^yT!53^9%l z0g`;-bBQ+?7D*1(ouV>HY73vs9*oxG=oFnmQcjW=dA~^2^>H~=4Rb(12^Ul31>R6t z6nP#^kt>2`?k-+&N2ilUAmibr7xtoyD^b*0ZnaN3)$IxISFDQYD-T1beGUpRJ>vYR z1jUj^|JWN23)Np&cM8S)57nJQIhKszn{q6fRID+Df`Vzj8dE4-%*hDcednNq%=zG? zmt%W;zc&%8vg979TgHbUP3hql6K;4v*ZJqw>|P7yuq%D^X-S> zs33Z-h3;SSeyD}+U#vTYiS8OpMXfgG!Pb~ULD8*iOz~I*9ecBNv4}mm&q|$#qC0ZQ z9z4>9P9XW5H+9@xg)dhYhT*QQlE8cfuh=c!vMG~EUt(->sp!y8AAPj|!Su_d{?;=4AE zPq*POpi(#R%MSd4=T5P&boXl1hx13r5#6vIZ@>d?>Dw;+7Wd(>tX_|Ppvn5tDRp%? zS%x!oy7a?NygiN9;Q92Oo<=8a(bqkAdD7SCqY;x~M?9V$2%A&T*Mu?Aba&iu_a>ca zB}TCiub5nZHL%H*_~&Z;a}EBv7XKW^KR4i?XW^e4@y|{8=P3SZ;GbLJPc+@W);isZ zhU4zWvGV~vEp~Rv@#*=iy}|OvW77+}aiT8~oXF(UrUeo;v;dS&OYf8j;*eUIx<(sg=U#O-e1s?wgWY4{ZhtI7)_& z4BR@YrC3{EU>UROMk&1hv-i8Xg%`eKneh4*?`K)U>)kX(uJD?De&+_cnl)rDX`dIG zt>tzm95O8(bArY&#rz>}q*Nrp^yb5Ba9B1p&?tKaf`+47rH}r|8!(Gne^_@4<;(mp zM(|ljb#E-g$wHGX;wa6MwshPHIgXL{oM-q-u&U&}r80TNn^+|NQeFCJ=Y`dsV(uhf zs!U?X5-uGq>8!8i8|Fsr=lBxay{5182GCm5*VLV2?gYQqNpOCsvxCNk_v>W6&-<0D zuHhqvWaXf{NqLVqP!=igtUHBC${N;{ax0liuQ7#!;$3xx5O*sVpg1MhrpQgJ)J|XJ z`8gRA?Q5io_Rqb^Ou3CqnQvJ&UTp}| z;6LJxl8Wee7-$)gjTf-A_YZmlX3^>$b*E5k@9m7-^E1#2aN-c^%0Md^rwjLA^F~2c z^4bPk0Z48k|KGfUvq=13>P|6t65mo~-7Yl2iHUj+N>>_wf(_RR{%LQ7R3-THENxyy zaC$E{*+1zGqDA(P)tzGQWPf2bvah$&7~4NCH1SOOg=Pd%_N)-EG|`EsnCJvebb?L9 zMEjm=X5*Y$nsxe8FIEsB5`+vuOWN=BhSlPUZFQ%ZJ5L`q;_NKa1n1roig)2jz8GbdU zP*9wyE48>Gf8o{|@+wup$(&)&0IyA)=n(�jO%3y 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�Ak0vNT!%-x~*|;$5eemlQZ?X2&VVqUzcHK!bZ+X7}831eE>?#k%M5i z#{w0Jxc!2MsB(vP%A@^F^#NSSwA?5Xi0iy6P)!=eUxc1gfJcN~M}mkDCRPcc5Ey7s zlJKa~p#79|jT$|mI4F7*C!P||K9w1uKDs3^XnhXmrtWlYisLI>y0+vwsCdu z7w8~HB|NkTX{2TiD*Yxvq^z-TT%wN&}KSMwNfPS7w-#?Rn z{w;m;Mf&-N^z&o%^V9V6GJ58t^#4DlpBK(LzA8Dp~cSj&|qhK zXs@$9G}qZ4TI*~Njdiw%wmREGQ=RRhrOx)yP-oZ37E9mi40W}c*P0&;J2>&N+?_Y0 zSoVJmsT=FhAFVER`=_&o!3yrk%~sEhmj?Zf^=BWL>%sn)+5UKVX5(Gp0I1&H=fDfr zpJ{wxjDqgB4sUnq3_l+z>h=>Vo(cp#~@s znMi`7>F0-Xs6%Zk2TlpLiV1g7qZfseCaMui8jah-@!G18^U_cb%}=G&h=LApm#+XY z=0DU)rUEHGwDvWb1jU8zE1VrRe&?I>O-MwTlTHRFLb*NyZYVar1@(%;yWbMll`hV%FC)J+VkF>i z3gKx5ir@vSg00|)`AzRusZLr3r~=4lv?>$a9f4NqlwmzYT-?#sN;2*a>+OP5Nxda) zD`bQ(w`>oO!`=lrVUx!bk~0&^*^7gq29@dbPj-icKAo32*&cRrUAr(Q3ELS8qq(vM z!g?c^|6c6Esasx~-JyVnTI-Hs$k$#jlqM^(7v)^EIvlKahT}7Nenj^u)vZcylYFzn z;u@TF0>PqE2Q*>y%8G`gdB(Ia8YL=ha6zKx(P?XDV1w$ERdA~&sd;x%1zeNk3 zRZfZ^GHS72j8KmwJ<*HN(cDJBHX_p4C+sPDp(b2jQlW{U5>{5cIjn@@=mMhVRbwrq zr3c~FP-aq$RP97n)MN1|lrxzs%R}->6z7NJ`%=2HNW~H&^BGO1%dqPEODk+V)&v$yiQ(TEO3aeH zA7-aIkmtbU7SE*qHNde*p47dy3Md&0_n`zosDBIc6+t~MI#kGDlheF98=-dGtW#M# zwK25SZ?C{a0_@loYWg;*rlUz34>6^_j^)Yoeh@k9OZ@ggZ;x$?&}@EfG#uSv^gZu?m`9MuS$P(bEL!WFWPF$effuwz%$K} ziQE9MdJ2jdiXLE3P!fK!3|AVUiNkq(_X&2)y67e&t2shIP;i8^??7E()$j_@%#BjK# zl;gurN7m#&sxl@~7RWdws_~yy5tAru1(p!u5)vWh|5l}lkz-9|!OdMl!mq0mCNamU zCD>OfWc(LZhMT9a?^tI#%gcjPLdb8cLS7UEh+LQ```@4}3khz{(lWEZXG{|ih5tJW z77d@ya)^fSl@Fqn0Q`Rt(9h_vid6)=(A)>$tzSj2MJ@XOMWm{T>2ssoP6eU=uNll> zB;DW-LKwFmU|HDTwpJ#Ho3l!JXFyf^qYz9C-AN@r7~FM(lXIeSe;NW+>$=kqa6S^^ zguRnb$h>%r*Xu7sm}+-|{J+CHJyF5GMnvD8UR&u-c%P`i`P+~goyaP6bVPxkyf1bB zze6b6OY623fk7?Ay&2R9F|Y* zc_G}(W3i((kGIzGmh=KB%{tbodZ?uB$!2_%7b6GJ!$xZq0A;ZHQ%oyS&+#%u^W&jd z8sqLA0{Uwe1o}!1H1tis)rF&zR|62!SU5USA+nuC51@}uUW@#M3d3wT895xCT#fL- z@OTmt!RX`-s)#V*POnA23sN|2rb-FZ;dCkC=;Y0+j7gLgj81M)MNFbBZFF+8DkU79 zq$|rGo!qKQn8Y06=;RJnMmRc2uZ1!?xmy+T${>>Fys3z&grh~z;+{|9B71DYbhk#)F!+^o8;WD{+`D{mycsM^=B>;~hDPa`n z<~1<0_S$%JkFiomMjOgvSfg92m|am&OOH3fcY09OIzNfse5Y1Esk zW)-d+It3T*3H%cpelzZ?gQ4W!*RY#8K5j}|>v!j2(M8aIt0tlueGpMhu#oD<8n%nf zakGZYDuj0m@K{vYnGls6Qs9aHItq#SN~A2}%%SN>iAJ8cp~N6LJTN7xYB2h0Ris;J zOEFATotYM&zDAWetx8(H!m+h^Ju&RvnmO|9`p(sBi zn~E^pQS5puGSLre!j!DFT#J0W1i}6Yz%t9%W>0&NcI0`nvp(B2L1KO!*$W3yT4gnL z#R))?>IXlG5~UxwjVy_N5U-r(4)4`0G)?)@5xg%0 zu6V=SE{oYslJuL?t&3b8AqnpbCAjI>%9`*9LU8W~IOa7q6z?}L^c)sA2>k;{RydD4 zRF%ZlcTFW;kf0BST5%_cno9~@>330(-)ktDEkr}L$wsu6MLp{GH>GBZV|^$T#L|)u z-T(%-3!iCq`*`9M^OF4J4DR&7OW4@~0zAOm`y&8kuEoMe8W>#JIXu~&@4%G02LGqX zSNIl-)=eeQ#^QxJ+_=soA=T$2p@NvtB6}9 z?5{&%``id|B4H!AjJZ=xX^^zP4W%8NmNdE^e(cV&kih@Fc>?J+gf2VZL;^n*3Vd)1 zHKg;g_Wmt+yYk>Wso`5I3;bz;kbrhW({bWo}1pVoR$K+=W))=Jlwy=Wm1B%Cu+7Qnje^^iZlh`Z1Nd zhQZ~+Q09^88dixh&kBX!KV_k6sJUd*1jG4 zvykeIpP`#y)=)v=ozpc=gx09m+8%v>Cp4Rt$o_?IDH5$6&+_A&|dT0nfAb20r+ zRe2@K^7GZiM5$CBbl$(WU?uvvOc3!=5lwjGw!;L@g(iFnlv^q+E|)R zZv&lPtx0qjtdvGkTLrQ8gzE7IKxIzHhNopU5O~(__U3xxyW~kmhRlWMC1$XdVlpKJ zzZsuY22-V$h?6qg{DARM>wcuh<6}a;RK1{ z#}f6?%|#nFEfsyk-6%^YIf;QFDl9)oNd6{d&4jYpglH4BWq8^y4+BEf&QKJaZfGP5 z_iu)E+8qjVn?*_kjn!X}%kKq9=2`B1Wip&^e?N~ufTV?kC8n61vm&I#&klupVpG&9 z2I0BS!MxefY!mDR8p91cIEocMa5NN|7}~0;8S}aaLWzm}T$M!K`5q4Cxf28IlpMdh z4EnX=Iu5HYyvVKB0x;%wZjp)=hyn2%gk~f7b4XS=of~5`7aB z5bK|UBymfcIOlT{h=Uo@P75=uR^OfLA(5T;}Ya4TTGSBb27 zN|Wn`i5$PCT#O*)vcD2#%T!=$l3~--3CITFno_OSZwn>6w0Dv^W`)(b{%%d`G>yzu7KYn@t4Xibt59~Rhg?h&ako|| z_TOn@ADND zN%8T&Xbu)S`Cl~$3%&f~Ay}%?6gU675H0GPp3(w8|73`jYJkwu{~-iRB^G%4KZaQD zz#R8890D(67bv=M^7hXG2J`kC)Zi)0lXt;adl8W@B@y61BPrqgZpUeyQ-GQ6nB9K# z9?=lKjL1P}-3)#9(4hl|1p3pqPY-?Pwj%cyncG z>&b^Tv=<^J(KzCDwRC(y+$)V&Aqbi;L12HzIc}vWHeO-P=R&ASzgz=%$9{eHii6uX z1_|n05M8ES?k>b+Yzl7z_ezbmyU!*Wc@^J~lTVhCI$oy%>p>g?r&Wg=q6oCt0~&KM zxBd|$=x}_`@CQ@G_KnC^xSU%VXfDD!q3Kpcg|0(^L6~+Es}l%C?^GmSuS#@_5fe%b z+QW^iJh#w0fxN)kwyLsTP=q0Pp$*(Mb3E(df26sYL(M5DB>1RqH{!p za^rE0kZP;@H5@mTE5iv%J*0uXrp%GE(Hgz@O4#gC4W?X8w4FzB#m6h4mvR3$ zpY$MA&jSW)m~JITD2J6c?QDk7*!%~9Eg~V&SY6(ii02=^BHS+G%GT@BiB#Yb&iUiR z!W_#Xbi~oD4!mJH5gbS@y2MN+XUBLH?TjV`r(vK*mzbpjs(M@tD_db8g{n6#K=nTz z0=u*+nKE=$?m`m6{i+bxrFzM@y5-*;2)4}0iQ+o|hBcrHzqI)mZ$*c_octgeNo!lPC($+*9%_TK>Bb{x|B=B1?0B^B=b*~h?eTzfocBa z=k}zc_aJxSv2Lw+3bLX;{2eGaNb%jcVj8jokNfU(AT)5o?^A^y(^C-FU74VjX3_{C5Sul5XS)BqY-TZNZ+g&O!JsR4JYfU^|EP34aajv`=C z@m~ol?yjavhm6$s*TVX~!mDq0wFM{d-~#DUSl8c_b#;^NhL~40+kJ4GK?*AQzMztB z{wDz|QoHwuwR@pgI|S!>KQ)FA$ZEMoDMQ7U$qqtcmgZC04+b@HV`;s3g#7P@!F_w7b$(w~!zJE^M_4*LGMGWU8GysOiI)ALpkglDOa+Wo^}|V39rfEM z;LZlMs((^hRj)Ku^)TY8RsHjns#X9-s`}Bes%{P5s1YVrMsN~8wCBfUCH?r!%Voz5 zNMOak399D1MGPiVp-+SrauE|ZvSzfK6+4_Z9>tKO1bh>C?^Ci~Hx^AaT0A=fz&i=j zA0QCoXM$R8YXpk-wRBpByKM|4;Ik;e9~-z1sSa@?gDFV}`hq6NZL(=72nLf{t-hoQ zb3=t%!h*pL>FxZPAkAoKnV7-q0z4L$=Yz>RMR7V!4*V?oq+PE#miRl#5 zk{HUJAR8z6UT0Tgwh8#azg(2^s~M67cr+pqbr+;)El)q+Cg9)Y>Y(%c!6~|#BwWQ8n0oy zzc5&7DF!?iLQ#l@S192{GJL~+mVeip8^9XW>gsZLo~~rzM!$bT3xnN!eoWlg+n zhmpU1FlL7#*dUe!J%;3k6Vc5p(~_0Z)$;ApnSSx^P!ih?bw(}U%AFsqKu@?(=qvxs z^>pb4prVe{6D<%WU|8ME7%@yKgt`}yBhz{ou$u7SDG&qzLDMwF-vOK}b{NWj)uLWH9U__iqKzM6Bi8_s< zWY$63KPHp4I_xZVPutKzg1!m``QwgzCa>0baKgQuktDrclSHd?tWx7PyfbW=K_KZI zhcl#f)n&g^Ebo2@!^yt{AQnz&#;qD6o5?X@wid4cm5^VD+(h7@t9R<7I_BLXKOxfp z3MB-C7Mf>nAm#X4cUj_pql)i^5O~d`s$O3=nMeL#tKgIdHz3cqJCSa_WxDXA#o`T- z1izue)BHdK_Wm2_NW{0PB4{nKfe5?+(t3Wewo7up9p(6~b=GUGsYX6IfIBXAIp3+t zq4{K`I&fnpxs{D8#PoXrfi+UE%PAbumc@5~DJb8MJVd*sS;vq>*dTsL5};9Pq+E7S z(42lW5KMD1r2tub@q|^U(8W(6SkU$p0dX)6BOU?xQz{^BQ>b9L3P;CIcVSAi1O5BT z94rLQ!#k5D`cJFqkx)g7Hwwhuut0~d2DWIRe+BqIr{dEhOga0!SLk+RqxeO{^BV9#FXs5zxB0g#4finP3)##9LKiKx;CT7OvY%@ZVLzBf(YhrN%D7 zejma7c0=RYa-*y)w&fma@|X{))FSyErxv6GA6AhP;zJ*LeudeesCWs!JU9ipXv_1# zKUdLcW}#edn0&(#w+_4)cK|QUEasj_dmmL%>CAH_>PmNQ1+V0Vw*kUp_Z;kVFs~_= z3F6082?DP(5%ht0%cu4uVE#`$hCg^BBpjHO7lonlxJ)(lm*h=un>nqWonjU*y%1hH7Nz z5Lp}U95@N@-}YM96>4oF?kf?g*$QgUSHU9wE5UjL7~L+gHyM+wy+{R&LDN*_wD9xNdGAzYn*&)B|wJ2FQKCP{UZKo)n zg)aIgm3}4A(xB_!;7Im=iwZ>RR%ML5jN~R2CDKp2dYQ#pnIzoO5K74|Z$~KKb0RH; zk-{DAgMQEn-K7$Xj369bkXvq7aU#LM;i!{7vnp04C%8^UcG$aAoJhoTobq>GwrFT5 z8ps|MFydA`DG@090fjZQNC&}-XGdV-N}FE24+)7@7n!Swp+%=vkEm4@D@-mxMbYg{ z0K7wY&}t9om*9k8Yhi6DZWyN)d%r3#lD9O<1?7z{|Y5#cC@NUQ-E2 za%cHIbt-=v%Coo@$(>EX?1*@aI+gz_lrMrA?fg`%L1lA@%!U=ri(vD}O0kcIK;N!b zDl+FGxLIJ?k-tO5i;PiKykO$vYgNd|#FhtH8CTz_f=7~82_6R1Z&1M^Q&AGki=f}6 zB1O7p4+-v|6I-3g&QGX-u>d3-s4Nb@ONEV0a7dmo8Fj+#r6Q8ws-h+7&%Gjpklv#r zMaIsOm+2IgiKg#RF(a9!hABIm??yO3O2s-}VG!FVhI3)xr&5e$nUZ4AW&NOvl@uA& z`O66U&{MU4b&v63m0*!Kbq3-%Gu6XmmGI2EL& zu|JEPMCAAOz}S&+952&yonJs)-vxz5;3BO4c$C4!>)hHhTpE#QW6+y-U?s0TSM-n{ z!3`3>Br7eJp(~NH1O4qFW1kVRgCwvmMI_)?0!2K`$L>vKMCxY^N}_)aMazvbVrkdO zR(4qt!f#6Lh;fZt8Z;7ats%XLtiZ)3e<9MxmrqqxiaW6p@$ELdWg0Odh>apfj^NNh_;EMG}WCx`PKgOpxRM= z>S(5}^fyt1Aw~jz}=^6b^j))uGl%2iiwqWv<2l) zg!L9vo=!yJK%)HL%PNbcP$>(wRo(g1K}AK@T8@O(3;p(=!kR@adVDxoTW#U|e&D*F zm(`1qk^oT0dl2zn0QCL$i$OibE>c&|Qb??@dqCLZyxE`!6REW?0VetfFdgN0@)rOM z%WTACLma}^{1Acqb$=#O6A6yk30ecz)!)z;8n`&rfEej9Ik+*aRjf+}N_dV`f|wR5 zML|6v_BOlZ>8s+hKotk|=uN{&>Boc*LNtPiX3{P*bI?vCi0vfmC{0+yFzWo@=J<&YJRy#s;|@>7QpID z%P;o_8j9tYf|Cd7lz=itt?vtK9m_9CLL|RDBI_N?FFgoLQ_nB&59%JvFRNf({gwRk zp-=;2de~1*a811xNu(Z?YM`^_u|CejDRcqwdJ6S;pbt95KM6iljH{LKkNGCraaoAK zTCA%bhr_kAL!D*pHqcH5zNa1Yw5ZW?6YaQuQeX}0YRBPl?dXwq*g!iK_?~vm)1pRe zHMPU`lm=tB(^5O7QP9J&+BxdBtor%lR|V=hR@M~#haFz=A6 zDUH1jqR@((K!0tZkkZ&&0?X7uk_7d4h8l>>$#!vpG#YomL8>4!hZtah4t5i+9&o=Y zP(ox*HUSvbARZHXc%rTzT;vis@2aB*hf(NZhZZoL`kHDE9=1;dG#Oh`$jiq1+S7fVmpNKJm9gJ-kX!M(o1AKhySKr3NCi zO{_H4owjWHw*Q@=+EIO)EuX+epqaYT--MO^M_5a-0-RSEkrL?!-LsEugrH`?edz>!?v@P8EJXmYp-A~lsV&O)#M9O^Z(J-eP$0Df7jG_gH9 zut1wf)qehIJN-rN#P*ybNmHOHC#w1kq4udmIXGNt?sp8&4m5Qrour12+VPnPy<8gVC9=;=z|1dq;FP=HS3Xy2 zCbADl2a@b(5Z~9%R|MLjcVUE+wRI!}8ltKR9lbErk=R@tF}l$aEj0z2dWqCjBn?vP zQNStsq9rw7X)h0y)=h9Jk9&zQU4QaS9BtLy5^6EB1}Ul?8Jk`y6&M*rN04N7^kM4j z0=-4nAnVBp)TNADUmt2JlDU?~sW(a$MKV_(0(BD)P}c=oiDa&ou%rkUW<`s;KGZ;D zBvZ&S9_vS>8>J2+Bbg9{X<xg@C(L z>SSjm97y5?luus`I@<#EM0PvG2*;#^no=Uoj!<8b-ED>VNR+upsw%R(O+jJ&_3(0U zprOdNfJAVi7$v6c3w09N!wLcy&IBFSL8*yY?qtiF`Y)XEd!xfawIfr>1q+6h*U`QB zllqloVa@2CWhE`>jMi4deVh-RZuqA)Q+B)@Wx1eFtqI9ZyYVwvh8uxPHWb;P|>5)l!cxoYAu9+Tc|g&K4fc}_oZ~tyr!*h zm)a8R86_Cvy6;dm-x;VzcxNqObBR!K@R)4;J&5n0`V?Wao(NDir7c3m-yf=YRx_}o z;!r(s|9u-?xgajUr>gu=C`I&E^(qqHvQI*OG!!Cs^_2+WNeN;71YogAv{b_)PN)`^ zs1W#1A<_6LnhKsOzUDtajbeQN*_~+IXic!ihHmt8q3+d~q_|OBQp}rvF%-6E;%Y^l z>X$-UVzR?G*8E_3xkHn)qM7{)z%YLj$HLgP=&vC+;YX#7%25k(Gn`4z1F<0f zn_>M+Lr|p<8fFL)?+ZnghM-arc%fom4;fA0A4(~8no22VywsXI12?LUWT*LoP?pGl z;ua4A(FXyFInG^We(os$|FvBSkQC(=-iUIzz;bwCB!H+Thm2UULZm!7jL7ZcftHT5 zJF`18%(2cPtkI;f5)Pdx>crcMM>HC9c_bmBLQG;TFSLw`8dM?)kavXXMi^=@Qr$s#JJ>6)lwn)v9 z$VXL3OMBDXTB+tpTBx!Q7A@!C>Ra2jBwO@CN>;zK9=8KH z98Sfa7I>U*m9^bvj<^$x#QcZ_bNw-f60jI7E9EX-)0#eG>CCC@1XL|4Uawr%#9&Gv zX(e{|WieY$H3g`Wb&nT=QCNRYqH< zBEaLYBr!ls)Vvngkf1ko>^HMne;cS(&Z~7{tEa;Af|%5hev;yOC1ksyT8h2#YSp5? zZ}B&{UGgnRuTAUqi4`mHJ7&dES}NdB?D9$^Q#xELHD$yauKe;KB13wTweMi7nq`TnsNb` zs!Y=o0WbZoZ>&%?ruVgmOVfW@YXt0$)y#BAZf8FH6)nJC?eO1MssgIRpQ;rCHbqsz zXXdg->e3Pc2P0cTH&8;01iT~QA})=S(oz9$6m2P&hRJG`fVbgnH zZFbc_@1%U0@^|;0*Fyg#ub9`;GAT(a#XeKvxhX`xN|Ohi%(!HLkiyrsLcp=bJB@;b zzM+Kz`jbau0;#OlDm5P{SA9T5<-Y|yjsR-S2g(i(5k!^o__bI%7Dr{t`yLMI492%t zqO%xAR^im^b=_GONMrOqqN?A~f_{cPkNSY1TX1!Q7V#4=s4L*;vn zZCa{X`{{t_om#|C?7+J|G?~#l_h=nImsoEdZLjZXiRP-}5r%z0>-d?McvrUBe}nC>6?QO>0UKHHCS zF5Tey{*m(v^uDC!`oc?GD)x$2YHk|h9rpcGKS{ZG#~WIzx!&v%1b$2F__?d`?qgoD z;B8u{xn}YX3BRYMn)5x+$ng7GsZT29;^u$TQq4_)-QvU_Xpx$EP}NC7EpMnqa$P+9 zL#@?pD|tkXcWWiKCPBkf9T{SE2_FBmzcpPf`Y)}?Ui@gfo?fBk|7hX9HLy#6*rzp{ zb00hSCWFfV)k@8E3R_8sEkD;<%}tNFmP_>VpmS9wO>;L^wxUZA^AIi8+^sK&iCE@f zE#c>3o%axytAsS2k<8Y<)^G`E4%ZsZU6{S%nj^JPb77-8;myOeUULptE6RDK7W)!D zr@68i%k_pZTRCKHXq$?pJE9TmNyWSP#?@Fj+Y#G5vF4ezh{j_v26q)Rm2~*^h4Sih zX@a23=AyA2>;q0^bMER)Wtqs!a&oe&N3IBVPxHz>V_P^*+QLP(=J;?`8M zla*a5XCnx&t9eh+HK%J)GXh>#o}sm9=U9gpeMIL{)}6_%J6SXjJ2AA>@=FEAyTYY`he$#{8 zah|3;$#+Y@`E!i|n606U4;-|6ut&>xYvu+9k#uAgD`!%(P50kF z)3A=D$?2mGn%0Dk6whprL2NymtpVSm8HAi4ys; zG#AN;`RtE0n{+8pv%z{ODVQxXm-?yZ^IcU4uyFr;0?Fix0OPzo?W#zs7~@mxp96uz zNj>dUIn{Qs3pLY5EDCc~d6BivN)8ZpC?V(-~TWvpZCFgb5csU*+wk~k&^t|g)Sep4F9 zKtpUVssd4%u7+7OVF-*3D@oAawUo>Q%X`Nu;KpD!A;?aNLfF(&kM~HjX(rDl|>vqOmR5< znoi%v^&Qr9J=ZRS!=s7kBUKE?uw9o5*CJqM`55WA<2uGSAACJM5CUYBpEOBH9>FO; zZIY5d>>xYt)s&8#(E1g3^>AGzFT%Q_RR%MMXkwgar5x*GH%8Y)wDrJPIg*^eM;tfJp?t^sM zaHECd%5}zw<4|5j&tf^wx9bVV+WBe`L^(`VmhQ3Yl*)xQl*&eIeVrBdn5{DYqclH7?gQ{!r`Qut zs=!z+KsPqlubsWb;X=+)o_NLskE5s29KZ*Mi_Z%*oSxtcCIRm;&kZozBk>Zu_u(G?OyE-nz z!zn=G@K$=rR*!(Ystf51EE#iD%KQkz>v(9J=`K2+$WV`%i9+(SSf^7|%Ij8#P**OS z4o4FvAV?yoYdZ&*z;O+$!3XKHTn-03 z(4TQ$yYGyamiXfMVtQ(wT!p{RT!?RV5jyltCwh}W$1(H)flg!S;|6WPImJwd?hMWDAc^lXC;MBN`UG$qg%8TyJqk2uR|jrRmPk)cE8+hr!**$f?P z(0^bnv@>+RKvy#KDuW)tbMIv6dVxN|(0dHJ4bR=k&?g1@0z+Rg=q^0>U54%!=w}Qa zvj9%0_!XUd)Y(o;o+Qwz44oy=nG9Vn&;<3@jiE;x^e+d&4%7 zTEx&R1iFf$j|uc~hW^5!v@yaahW<{V&oJ~Qfo@^wn*!a+&>aHZ&d}Wg-Nn$)1o{a> z2Q0O1MK#*b(BT3d0K1u)8O2co9m>$-1bR3_PZH=jhRzh|2@IVp(CG|aBG6MAdZ|EX zF|##a#gnx=^6F`<+2A7AWojXV6Z8;;v@~ z%?K2?^fG9#Kyf!KgMLe(xX+V8ZxSf(cx2GK1d5yd81x~5;>I@y{h2^I2x{!gHo<807j7ud{n zE+*_6bgV!z;nbja3lvid47ypM_$=3;TMTMHxiskO0>!6^2K}o+>3I@99y913gHqTX zpBNc*pFr_>jzP!3Eq8T(MPUPsxEu6Xfnu=Qpl1jaV~7S_E>Miw*l01{KEI_{8h{y# z7%bQb!GLSa)r0v$6c3hKdve+CY!5yp$iso^k4ghmk&ajjk4!2J?v7=u*$X#Zg#4vp z`JQ+pvkIbwoe@YrDvb;~qEkz9*;SPgLFWTIei>wjmlz7vcGnb$$_9H)3HoQ)+3fE1l@G*XD*x7J*&3)VZy6fiXg zzo&cixQc$JE74sp9ZBDMB9J7Q!`*G*U??4dq{-6oh0!H+cy{HdWCry6He9JCn@LA< zE5gt;z2)`L6}r;a=aFDNOrN)(Q9~8(0GpMDL$Wj>`QA(cvqta6qoW|F9THHmW3a1m9BJ2u3|2Y^IiXD(9 zUH}Kf(IojRBp40{;n`3sk;aFcaC9@#q9qbty`XzFj1FWMtWz`{Da6BIs_aS_H)sf2 zR~qR&n(v9g=04)5QE-m}8fA3lr_pQ?njenOn3fpzNMjVv!1#krmHb2IbO6^iro^QL65$4j8>QW@Sp0;!Xz3>4N1F TGn9dnsheny<7fpzM^jVv!1C3&3lb8|EE(iMvH^Yf-;u*Xix5bFU6PG)9Gl;KH+$m)V+ U6El>7(yFmjdO+fv>zKSa0Xk?KdH?_b diff --git a/docs/build/doctrees/tutorials.console-arguments.doctree b/docs/build/doctrees/tutorials.console-arguments.doctree index 81a2d8387cd3c6651bc13851d3c924b2240dd4bc..ea98b3c6779d82f4e0badeebb54261a12d75ab90 100644 GIT binary patch delta 73 zcmca5eodUEfpzNXjVzxS#krmHb2IbO6^iro^QL65$4j8>Q=4VQj;!Xz3>4N1F TGn9dnsLiuOn#gIzW5Zn diff --git a/docs/build/doctrees/tutorials.console.doctree b/docs/build/doctrees/tutorials.console.doctree index af9aea73d06ea682dc275662568d379bc34f800f..c336c5140b45ed9c7475a0c6b9c58e289196f244 100644 GIT binary patch delta 73 zcmaDLen*_8fpzM|jVvD+#krmHb2IbO6^iro^QL65$4j8>Q=4DEh;!Xz3>4N1F TGn9dns7(yFmjdO+fv+nB;Q0Z$wo+5i9m diff --git a/docs/build/doctrees/tutorials.create-startup.doctree b/docs/build/doctrees/tutorials.create-startup.doctree index 9cc71581ec4f6839b60b3fa176ce78e49668dac3..e986753990ed01f9d64e284d70957bbfe6da4e69 100644 GIT binary patch delta 73 zcmX>uepsBPfpzMRjV#X@#krmHb2IbO6^iro^QL65$4j8>QW?@Q{;!Xz3>4N1F TGn9dnsseq5ZTfpzMhjV#X@C3&3lb8|EE(iMvH^Yf-;u*Xix5bFU6PG(|Cl;KH+$m)V+ U6El>7(yFmjdO+fvYnj|Q0X3u>WB>pF diff --git a/docs/build/doctrees/tutorials.doctree b/docs/build/doctrees/tutorials.doctree index f197f99f28676f8d9783e04f0fb28a8a0d7723ef..98870ee6d886c0ba45a9f3d14f806fe4d2d00fff 100644 GIT binary patch delta 90 zcmbOszD1m+fpzN2jVvFT#Ql0iN=i%ei!u{)iuFoTa|?13OEUA)Cx2p6W6B8FEWs?t t%-Fx#ob3a%OlC$}aSvx+Vs2_lWkG83l-em7nSR9?iaszF(ZBfpzMZjV#X@#krmHb2IbO6^iro^QL65$4j8>QW?@Q{;!Xz3>4N1F TGn9dns7(yFmjdO+fvYnhxl0Wv5XQ~&?~ diff --git a/docs/build/doctrees/tutorials.extend-startup.doctree b/docs/build/doctrees/tutorials.extend-startup.doctree index 1e8849257e99fe1c7c26d481ac0c6ce7c160a438..8623dd4f9617f2f76749ab30ca37d22656d0fdba 100644 GIT binary patch delta 73 zcmZ24zFM56fpzMFjV!kr#krmHb2IbO6^iro^QL65$4j8>Q{=t|i#hnb6(*?^V UW+($CRb!|00EIV~GFfo~0LkMTF#rGn delta 77 zcmZ22zFwTAfpzMVjV!krC3&3lb8|EE(iMvH^Yf-;u*Xix5bFU6PX5N2D8rKsk<|su VCT1uDrB!36^nk=S7cyCK0sug)8|wf7 diff --git a/docs/build/doctrees/tutorials.logging.doctree b/docs/build/doctrees/tutorials.logging.doctree index b48d37b53a01740daf207d41c3b7b656c1a73b78..76efdd338bfdc8c4820e2ea5ae696fb593f59d7a 100644 GIT binary patch delta 73 zcmdlXzD1m+fpzN2jVyN<#krmHb2IbO6^iro^QL65$4j8>Q{>hjq#hnb6(*?^V UW+($CRb!|00EIV~F*$Jp0MW4;R{#J2 delta 77 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 | -| ```class``` | Class | `````` | -| ```enum``` | Enum class | `````` | -| ```pipe``` | Pipe class | `````` | -| ```service``` | Service class | `````` | -| ```settings``` | [Configmodel](cpl_core.configuration) | `````` | -| ```test``` | Test class | `````` | -| ```thread``` | Thread class | `````` | -| ```validator``` | Validator class | `````` | +| Schematic | Description | Arguments | +|-----------------|:--------------------------------------:|:------------:| +| ```abc``` | Abstract base class | `````` | +| ```class``` | Class | `````` | +| ```enum``` | Enum class | `````` | +| ```pipe``` | Pipe class | `````` | +| ```service``` | Service class | `````` | +| ```settings``` | [Configmodel](cpl_core.configuration) | `````` | +| ```test``` | Test class | `````` | +| ```thread``` | Thread class | `````` | +| ```validator``` | Validator class | `````` | +| ```command``` | Discord bot command class | `````` | +| ```event``` | Discord bot event class | `````` | diff --git a/docs/build/html/_sources/cli.new.md.txt b/docs/build/html/_sources/cli.new.md.txt index f000dcd6..1301c1ad 100644 --- a/docs/build/html/_sources/cli.new.md.txt +++ b/docs/build/html/_sources/cli.new.md.txt @@ -16,6 +16,8 @@ cpl **N** *<type>* *<name>* Generates a workspace and initial project or add a project to workspace. +You can define custom project types by creating templates in a ```.cpl``` folder. + If the command is running in a CPL workspace, it will add the new project to the workspace. | Argument | Description | Value type | diff --git a/docs/build/html/_sources/tutorials.appsettings.md.txt b/docs/build/html/_sources/tutorials.appsettings.md.txt index ffe26cba..4eabffa2 100644 --- a/docs/build/html/_sources/tutorials.appsettings.md.txt +++ b/docs/build/html/_sources/tutorials.appsettings.md.txt @@ -1,3 +1,3 @@ # Using appsettings.json -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/build/html/_sources/tutorials.console-arguments.md.txt b/docs/build/html/_sources/tutorials.console-arguments.md.txt index a0be2c0f..0a3b5a42 100644 --- a/docs/build/html/_sources/tutorials.console-arguments.md.txt +++ b/docs/build/html/_sources/tutorials.console-arguments.md.txt @@ -1,3 +1,3 @@ # Handle console arguments -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/build/html/_sources/tutorials.console.md.txt b/docs/build/html/_sources/tutorials.console.md.txt index c7d22b99..fcbaaba1 100644 --- a/docs/build/html/_sources/tutorials.console.md.txt +++ b/docs/build/html/_sources/tutorials.console.md.txt @@ -1,3 +1,3 @@ # Use cpl_core.console.Console -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/build/html/_sources/tutorials.create-startup.md.txt b/docs/build/html/_sources/tutorials.create-startup.md.txt index ee443126..028d072c 100644 --- a/docs/build/html/_sources/tutorials.create-startup.md.txt +++ b/docs/build/html/_sources/tutorials.create-startup.md.txt @@ -1,3 +1,3 @@ # Create startup class -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/build/html/_sources/tutorials.extend-application.md.txt b/docs/build/html/_sources/tutorials.extend-application.md.txt index 3697cbc9..1eec6e9e 100644 --- a/docs/build/html/_sources/tutorials.extend-application.md.txt +++ b/docs/build/html/_sources/tutorials.extend-application.md.txt @@ -1,3 +1,3 @@ # Extend application -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/build/html/_sources/tutorials.extend-startup.md.txt b/docs/build/html/_sources/tutorials.extend-startup.md.txt index 66e3e54f..98b90da4 100644 --- a/docs/build/html/_sources/tutorials.extend-startup.md.txt +++ b/docs/build/html/_sources/tutorials.extend-startup.md.txt @@ -1,3 +1,3 @@ # Extend startup -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/build/html/_sources/tutorials.logging.md.txt b/docs/build/html/_sources/tutorials.logging.md.txt index c98020c5..660fbfe1 100644 --- a/docs/build/html/_sources/tutorials.logging.md.txt +++ b/docs/build/html/_sources/tutorials.logging.md.txt @@ -1,3 +1,3 @@ # Use builtin logger -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/build/html/_sources/tutorials.mail.md.txt b/docs/build/html/_sources/tutorials.mail.md.txt index e7a2b778..7b6c9150 100644 --- a/docs/build/html/_sources/tutorials.mail.md.txt +++ b/docs/build/html/_sources/tutorials.mail.md.txt @@ -1,3 +1,3 @@ # Send mails -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/build/html/_sources/tutorials.rst.txt b/docs/build/html/_sources/tutorials.rst.txt index f85e9b8c..b8fd6668 100644 --- a/docs/build/html/_sources/tutorials.rst.txt +++ b/docs/build/html/_sources/tutorials.rst.txt @@ -11,4 +11,5 @@ Tutorials tutorials.console-arguments tutorials.console tutorials.logging - tutorials.mail \ No newline at end of file + tutorials.mail + tutorials.templating \ No newline at end of file diff --git a/docs/build/html/_sources/tutorials.templating.md.txt b/docs/build/html/_sources/tutorials.templating.md.txt new file mode 100644 index 00000000..4530b17c --- /dev/null +++ b/docs/build/html/_sources/tutorials.templating.md.txt @@ -0,0 +1,181 @@ +# Using cpl g & cpl n templating + +## Contents + +- [Prerequisites](#prerequisites) +- [Generate schematics](#cpl-generate-scmatics) +- [Project types](#cpl-new-project-types) + +## Prerequisites + +Create a folder called ```.cpl``` + +## cpl generate schematics + +Create a file which begins with ```schematic_your_schematic.py```. +A schematic template is detected by starting with ```schematic_``` and endswith ```.py```. + +You should replace ```your_schematic``` with an appropriate name of your schematic. For example, we will choose ```Enum```. +Attention: It is important that you do not overwrite templates by creating a file or class with the same name. + +In the template create a class with the name of your schematic. For example: + +```python +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Enum(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + import textwrap + code = textwrap.dedent("""\ + from enum import Enum + + + class $Name(Enum): + + atr = 0 + """) + return self.build_code_str(code, Name=self._class_name) + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'enum', + ['e', 'E'] + ) + +``` + +You can test it by calling ```cpl g --help``` your schematic should be listed as available. + +## cpl new project types + +The project templating is a little more complex and is therefore divided into several files. +First of all, for information, it is very important not to overwrite any existing files or classes! + +Template structure explained by the example of the internal type ```console```: + +``` +- project_console.py +- project_file_license.py +- project_file_appsettings.py +- project_file.py +- project_file_readme.py +- project_file_code_main.py +- project_file_code_startup.py +- project_file_code_application.py +``` + +Here the template ```project_console.py``` defines how a console project has to look like when it is generated. Here is the code to illustrate this: + +```python +from cpl_cli.abc.project_type_abc import ProjectTypeABC +from cpl_cli.configuration import WorkspaceSettings +from cpl_core.utils import String + + +class Console(ProjectTypeABC): + + def __init__( + self, + base_path: str, + project_name: str, + workspace: WorkspaceSettings, + use_application_api: bool, + use_startup: bool, + use_service_providing: bool, + use_async: bool, + project_file_data: dict, + ): + from project_file import ProjectFile + from project_file_appsettings import ProjectFileAppsettings + from project_file_code_application import ProjectFileApplication + from project_file_code_main import ProjectFileMain + from project_file_code_startup import ProjectFileStartup + from project_file_readme import ProjectFileReadme + from project_file_license import ProjectFileLicense + from schematic_init import Init + + ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async, project_file_data) + + project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/' + + self.add_template(ProjectFile(project_name.split('/')[-1], project_path, project_file_data)) + if workspace is None: + self.add_template(ProjectFileLicense('')) + self.add_template(ProjectFileReadme('')) + self.add_template(Init('', 'init', f'{base_path}tests/')) + + self.add_template(Init('', 'init', project_path)) + self.add_template(ProjectFileAppsettings(project_path)) + + if use_application_api: + self.add_template(ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async)) + + if use_startup: + self.add_template(ProjectFileStartup(project_path, use_application_api, use_startup, use_service_providing, use_async)) + + self.add_template(ProjectFileMain(project_name.split('/')[-1], project_path, use_application_api, use_startup, use_service_providing, use_async)) +``` + +The class must be named exactly as the project type should be named. It is also checked on the initial letter of the class as alias. +Now create a class for normal files which inherits from ```FileTemplateABC``` and a class for code files which inherits from ```CodeFileTemplateABC```. + +For example: + +project_file_code_startup.py: +```python +from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC + + +class ProjectFileStartup(CodeFileTemplateABC): + + def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool): + CodeFileTemplateABC.__init__(self, 'startup', path, '', use_application_api, use_startup, use_service_providing, use_async) + + def get_code(self) -> str: + import textwrap + + return textwrap.dedent("""\ + from cpl_core.application import StartupABC + from cpl_core.configuration import ConfigurationABC + from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC + from cpl_core.environment import ApplicationEnvironment + + + class Startup(StartupABC): + + def __init__(self): + StartupABC.__init__(self) + + def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: + return configuration + + def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: + return services.build_service_provider() + """) +``` + +project_file.py: + +```python +import json + +from cpl_cli.abc.file_template_abc import FileTemplateABC + + +class ProjectFile(FileTemplateABC): + + def __init__(self, name: str, path: str, code: dict): + FileTemplateABC.__init__(self, '', path, '{}') + self._name = f'{name}.json' + self._code = code + + def get_code(self) -> str: + return json.dumps(self._code, indent=2) +``` diff --git a/docs/build/html/cli.generate.html b/docs/build/html/cli.generate.html index 7356f273..e0f330eb 100644 --- a/docs/build/html/cli.generate.html +++ b/docs/build/html/cli.generate.html @@ -112,6 +112,7 @@ cpl G <schematic> <name>

    Description

    Generates files based on a schematic.

    +

    You can define custom schematics by creating templates in a .cpl folder.

    Arguments

    @@ -184,6 +185,14 @@ cpl G <schematic> <name>

    Validator class

    <name>

    +

    command

    +

    Discord bot command class

    +

    <name>

    + +

    event

    +

    Discord bot event class

    +

    <name>

    +
    diff --git a/docs/build/html/cli.new.html b/docs/build/html/cli.new.html index ed47b5ca..982eacc3 100644 --- a/docs/build/html/cli.new.html +++ b/docs/build/html/cli.new.html @@ -112,6 +112,7 @@ cpl N <type> <name>

    Description

    Generates a workspace and initial project or add a project to workspace.

    +

    You can define custom project types by creating templates in a .cpl folder.

    If the command is running in a CPL workspace, it will add the new project to the workspace.

    diff --git a/docs/build/html/contributing.html b/docs/build/html/contributing.html index 9ca2df3c..05c75b17 100644 --- a/docs/build/html/contributing.html +++ b/docs/build/html/contributing.html @@ -20,7 +20,7 @@ - + @@ -189,7 +189,7 @@ See - + diff --git a/docs/build/html/cpl_core.configuration.html b/docs/build/html/cpl_core.configuration.html index 4c1c0197..fed12943 100644 --- a/docs/build/html/cpl_core.configuration.html +++ b/docs/build/html/cpl_core.configuration.html @@ -104,13 +104,13 @@

    Bases: ConfigurationABC

    -add_configuration(key_type: Union[str, type], value: Union[str, ConfigurationModelABC])
    +add_configuration(key_type: Union[str, type], value: any)

    Add configuration object

    key_type: Union[str, type]

    Type of the value

    -
    value: Union[str, cpl_core.configuration.configuration_model_abc.ConfigurationModelABC]

    Object of the value

    +
    value: any

    Object of the value

    @@ -217,7 +217,7 @@
    -get_configuration(search_type: Union[str, Type[ConfigurationModelABC]]) Optional[Union[str, ConfigurationModelABC]]
    +get_configuration(search_type: Type[T]) Optional[T]

    Returns value from configuration by given type

    @@ -256,13 +256,13 @@

    Bases: ABC

    -abstract add_configuration(key_type: Union[str, type], value: Union[str, ConfigurationModelABC])
    +abstract add_configuration(key_type: Union[str, type], value: any)

    Add configuration object

    key_type: Union[str, type]

    Type of the value

    -
    value: Union[str, cpl_core.configuration.configuration_model_abc.ConfigurationModelABC]

    Object of the value

    +
    value: any

    Object of the value

    @@ -369,7 +369,7 @@
    -abstract get_configuration(search_type: Union[str, Type[ConfigurationModelABC]]) Union[str, ConfigurationModelABC]
    +abstract get_configuration(search_type: Union[str, Type[ConfigurationModelABC]]) Optional[T]

    Returns value from configuration by given type

    diff --git a/docs/build/html/cpl_discord.events.html b/docs/build/html/cpl_discord.events.html index 7633c306..962c25c9 100644 --- a/docs/build/html/cpl_discord.events.html +++ b/docs/build/html/cpl_discord.events.html @@ -244,7 +244,7 @@

    Bases: ABC

    -abstract async on_group_join(chhanel: GroupChannel, user: User)
    +abstract async on_group_join(channel: GroupChannel, user: User)
    diff --git a/docs/build/html/cpl_query.base.html b/docs/build/html/cpl_query.base.html index 2e00c6d8..c442a914 100644 --- a/docs/build/html/cpl_query.base.html +++ b/docs/build/html/cpl_query.base.html @@ -51,8 +51,8 @@
  365. cpl_query.base.ordered_queryable
  366. cpl_query.base.ordered_queryable_abc
  367. cpl_query.base.queryable_abc
  368. -
  369. cpl_query.base.sequence_abc
  370. -
  371. cpl_query.base.sequence_values
  372. +
  373. cpl_query.base.sequence_abc
  374. +
  375. cpl_query.base.sequence_values
  376. cpl_query.enumerable
  377. @@ -170,7 +170,7 @@
    class cpl_query.base.queryable_abc.QueryableABC(t: Optional[type] = None, values: Optional[list] = None)
    -

    Bases: SequenceABC

    +

    Bases: Sequence

    all(_func: Optional[Callable] = None) bool
    @@ -603,91 +603,11 @@ Exception: when argument is None or found more than one element

    -
    -

    cpl_query.base.sequence_abc

    -
    -
    -class cpl_query.base.sequence_abc.SequenceABC(t: Optional[type] = None, values: Optional[list] = None)
    -

    Bases: ABC

    -
    -
    -copy() SequenceABC
    -

    Creates a copy of sequence

    -
    -

    SequenceABC

    -
    -
    - -
    -
    -classmethod empty() SequenceABC
    -

    Returns an empty sequence

    -
    -

    Sequence object that contains no elements

    -
    -
    - -
    -
    -index(_object: object) int
    -

    Returns the index of given element

    -
    -

    Index of object

    -
    -
    -

    IndexError if object not in sequence

    -
    -
    - -
    -
    -next()
    -
    - -
    -
    -classmethod range(start: int, length: int) SequenceABC
    -
    - -
    -
    -to_list() list
    -

    Converts :class: cpl_query.base.sequence_abc.SequenceABC to :class: list

    -
    -
    -
    class
    -

    list

    -
    -
    -
    -
    - -
    -
    -property type: type
    -
    - -
    - +
    +

    cpl_query.base.sequence_abc

    -
    -

    cpl_query.base.sequence_values

    -
    -
    -class cpl_query.base.sequence_values.SequenceValues(data: list, _t: type)
    -

    Bases: object

    -
    -
    -next()
    -
    - -
    -
    -reset()
    -
    - -
    - +
    +

    cpl_query.base.sequence_values

    diff --git a/docs/build/html/cpl_query.enumerable.html b/docs/build/html/cpl_query.enumerable.html index 36b65ec3..ee7f4347 100644 --- a/docs/build/html/cpl_query.enumerable.html +++ b/docs/build/html/cpl_query.enumerable.html @@ -103,12 +103,6 @@ class cpl_query.enumerable.enumerable_abc.EnumerableABC(t: Optional[type] = None, values: Optional[list] = None)

    Bases: QueryableABC

    ABC to define functions on list

    -
    -
    -set_remove_error_check(_value: bool)
    -

    Set flag to check if element exists before removing

    -
    -
    to_iterable() IterableABC
    diff --git a/docs/build/html/cpl_query.html b/docs/build/html/cpl_query.html index 7c9bdb8d..33dcf0a6 100644 --- a/docs/build/html/cpl_query.html +++ b/docs/build/html/cpl_query.html @@ -88,8 +88,8 @@
  378. cpl_query.base.ordered_queryable
  379. cpl_query.base.ordered_queryable_abc
  380. cpl_query.base.queryable_abc
  381. -
  382. cpl_query.base.sequence_abc
  383. -
  384. cpl_query.base.sequence_values
  385. +
  386. cpl_query.base.sequence_abc
  387. +
  388. cpl_query.base.sequence_values
  389. cpl_query.enumerable
      diff --git a/docs/build/html/cpl_query.iterable.html b/docs/build/html/cpl_query.iterable.html index 98c321c0..c9b0ec82 100644 --- a/docs/build/html/cpl_query.iterable.html +++ b/docs/build/html/cpl_query.iterable.html @@ -119,7 +119,8 @@ Parameter
      append(_object: object)
      -
      +

      Append object to the end of the list.

      +
  390. @@ -149,6 +150,20 @@ Parameter
    +
    +
    +remove_at(_index: int)
    +

    Removes element from list +Parameter +———

    +
    +
    +
    _object: object

    value

    +
    +
    +
    +
    +
    to_enumerable() EnumerableABC
    diff --git a/docs/build/html/genindex.html b/docs/build/html/genindex.html index a0918e35..829e9e55 100644 --- a/docs/build/html/genindex.html +++ b/docs/build/html/genindex.html @@ -388,8 +388,6 @@
  391. convert_to_camel_case() (cpl_core.utils.string.String static method)
  392. convert_to_snake_case() (cpl_core.utils.string.String static method) -
  393. -
  394. copy() (cpl_query.base.sequence_abc.SequenceABC method)
  395. count() (cpl_query.base.queryable_abc.QueryableABC method)
  396. @@ -1275,20 +1273,6 @@ -
  397. - cpl_query.base.sequence_abc - -
  398. -
  399. - cpl_query.base.sequence_values - -
  400. @@ -1527,8 +1511,6 @@
  401. EMailClientSettingsNameEnum (class in cpl_core.mailing.email_client_settings_name_enum)
  402. emojis (cpl_discord.container.guild.Guild attribute) -
  403. -
  404. empty() (cpl_query.base.sequence_abc.SequenceABC class method)
  405. enable() (cpl_core.console.console.Console class method)
  406. @@ -1775,19 +1757,17 @@
  407. implementation (cpl_core.dependency_injection.service_descriptor.ServiceDescriptor property) -
  408. -
  409. index() (cpl_query.base.sequence_abc.SequenceABC method)
  410. INFO (cpl_core.logging.logging_level_enum.LoggingLevelEnum attribute)
  411. - -
    + - - - - - -
  412. cpl_query.enumerable
      diff --git a/docs/build/html/objects.inv b/docs/build/html/objects.inv index afa7006971d814c07399602b775a272afac9eef0..765699ce4345a20428f05c9f2cda119134f887d8 100644 GIT binary patch delta 6413 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 delta 6489 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 diff --git a/docs/build/html/py-modindex.html b/docs/build/html/py-modindex.html index 548a0117..3be92766 100644 --- a/docs/build/html/py-modindex.html +++ b/docs/build/html/py-modindex.html @@ -731,16 +731,6 @@
  413.     cpl_query.base.queryable_abc
        - cpl_query.base.sequence_abc -
        - cpl_query.base.sequence_values -
        diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js index a2b6df51..521b689f 100644 --- a/docs/build/html/searchindex.js +++ b/docs/build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["cli.add", "cli.build", "cli.generate", "cli.help", "cli.install", "cli.new", "cli.overview", "cli.publish", "cli.remove", "cli.run", "cli.start", "cli.uninstall", "cli.update", "cli.version", "contributing", "cpl_cli", "cpl_core", "cpl_core.application", "cpl_core.configuration", "cpl_core.console", "cpl_core.database", "cpl_core.database.connection", "cpl_core.database.context", "cpl_core.dependency_injection", "cpl_core.environment", "cpl_core.logging", "cpl_core.mailing", "cpl_core.pipes", "cpl_core.time", "cpl_core.utils", "cpl_discord", "cpl_discord.application", "cpl_discord.command", "cpl_discord.configuration", "cpl_discord.container", "cpl_discord.events", "cpl_discord.helper", "cpl_discord.service", "cpl_query", "cpl_query.base", "cpl_query.enumerable", "cpl_query.extension", "cpl_query.iterable", "cpl_translation", "getting_started", "index", "introduction", "modules", "quickstart", "setup", "tutorials", "tutorials.appsettings", "tutorials.console", "tutorials.console-arguments", "tutorials.create-startup", "tutorials.extend-application", "tutorials.extend-startup", "tutorials.logging", "tutorials.mail"], "filenames": ["cli.add.md", "cli.build.md", "cli.generate.md", "cli.help.md", "cli.install.md", "cli.new.md", "cli.overview.md", "cli.publish.md", "cli.remove.md", "cli.run.md", "cli.start.md", "cli.uninstall.md", "cli.update.md", "cli.version.md", "contributing.md", "cpl_cli.rst", "cpl_core.rst", "cpl_core.application.rst", "cpl_core.configuration.rst", "cpl_core.console.rst", "cpl_core.database.rst", "cpl_core.database.connection.rst", "cpl_core.database.context.rst", "cpl_core.dependency_injection.rst", "cpl_core.environment.rst", "cpl_core.logging.rst", "cpl_core.mailing.rst", "cpl_core.pipes.rst", "cpl_core.time.rst", "cpl_core.utils.rst", "cpl_discord.rst", "cpl_discord.application.rst", "cpl_discord.command.rst", "cpl_discord.configuration.rst", "cpl_discord.container.rst", "cpl_discord.events.rst", "cpl_discord.helper.rst", "cpl_discord.service.rst", "cpl_query.rst", "cpl_query.base.rst", "cpl_query.enumerable.rst", "cpl_query.extension.rst", "cpl_query.iterable.rst", "cpl_translation.rst", "getting_started.rst", "index.rst", "introduction.md", "modules.rst", "quickstart.md", "setup.md", "tutorials.rst", "tutorials.appsettings.md", "tutorials.console.md", "tutorials.console-arguments.md", "tutorials.create-startup.md", "tutorials.extend-application.md", "tutorials.extend-startup.md", "tutorials.logging.md", "tutorials.mail.md"], "titles": ["cpl add", "cpl build", "cpl generate", "cpl help", "cpl install", "cpl new", "CLI Overview and Command Reference", "cpl publish", "cpl remove", "cpl run", "cpl start", "cpl uninstall", "cpl update", "cpl version", "Contributing to CPL", "CLI reference", "API reference", "cpl_core.application", "cpl_core.configuration", "cpl_core.console", "cpl_core.database", "cpl_core.database.connection", "cpl_core.database.context", "cpl_core.dependency_injection", "cpl_core.environment", "cpl_core.logging", "cpl_core.mailing", "cpl_core.pipes", "cpl_core.time", "cpl_core.utils", "Discord reference", "cpl_discord.application", "cpl_discord.command", "cpl_discord.configuration", "cpl_discord.container", "cpl_discord.events", "cpl_discord.helper", "cpl_discord.service", "Query reference", "cpl_query.base", "cpl_query.enumerable", "cpl_query.extension", "cpl_query.iterable", "Translation reference", "Getting started", "Introduction to the CPL Docs", "Introduction to the CPL Docs", "cpl", "Getting started with CPL", "Setting up the local environment and workspace", "Tutorials", "Using appsettings.json", "Use cpl_core.console.Console", "Handle console arguments", "Create startup class", "Extend application", "Extend startup", "Use builtin logger", "Send mails"], "terms": {"remov": [0, 6, 7, 15, 40, 42, 47], "project": [0, 1, 4, 6, 7, 8, 9, 10, 11, 12, 14, 15, 44, 47, 49], "from": [0, 6, 7, 8, 9, 10, 11, 13, 14, 17, 18, 19, 20, 34, 39, 42, 45, 46, 48], "workspac": [0, 1, 5, 6, 8, 44, 47], "sourc": [0, 1, 7, 9, 10, 14, 29, 48, 49], "target": [0, 1], "A": [0, 5, 14, 34], "refer": [0, 8, 45, 46, 47], "given": [0, 1, 4, 6, 7, 11, 18, 19, 20, 23, 29, 39, 42], "If": [0, 5, 8, 14, 19, 49], "you": [0, 1, 6, 8, 14, 34, 45, 46, 48, 49], "call": [0, 8, 17, 18, 19, 34, 39], "command": [0, 1, 3, 4, 5, 7, 8, 11, 12, 14, 15, 29, 30, 45, 46, 47, 49], "can": [0, 1, 6, 7, 8, 14, 34, 45, 49], "us": [0, 1, 2, 5, 6, 7, 8, 14, 17, 19, 26, 29, 44, 45, 46, 47, 48, 49, 50], "name": [0, 1, 2, 5, 6, 7, 8, 18, 24, 25, 29, 32, 34, 49], "otherwis": [0, 8, 19], "path": [0, 1, 2, 5, 7, 8, 15, 18, 24, 25, 47, 49], "must": [0, 1, 6, 8, 14, 19], "specifi": [0, 4, 5, 6, 8, 9, 11, 12, 18, 19], "valu": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 18, 19, 20, 23, 24, 25, 26, 27, 28, 39, 40, 41, 42, 43], "type": [0, 1, 2, 3, 4, 7, 8, 9, 10, 11, 15, 17, 18, 23, 34, 36, 37, 39, 40, 41, 42, 47], "which": [0, 6, 9, 18, 19, 29, 49], "ha": [0, 19], "ad": [0, 14], "str": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 33, 34, 35, 37, 43, 48], "referenc": 0, "simul": [0, 4, 8, 11, 12], "whether": [0, 4, 5, 8, 11, 12, 18], "copi": [1, 39], "an": [1, 6, 7, 17, 18, 19, 20, 23, 24, 25, 26, 28, 39, 48, 49], "python": [1, 14, 29, 45, 46, 48, 49], "app": [1, 6, 17, 44, 45, 46, 47, 48], "output": [1, 6, 7, 18, 19, 45, 46, 48, 49], "directori": [1, 6, 7, 24, 45, 46, 48], "execut": [1, 6, 7, 18, 29], "within": [1, 6, 14], "b": [1, 6, 14], "The": [1, 2, 4, 5, 6, 7, 8, 11, 14, 23, 26, 29, 34, 37, 45, 46, 48, 49], "consol": [1, 3, 5, 6, 7, 16, 18, 25, 44, 45, 46, 47, 48, 50], "librari": [1, 5, 6, 7, 44, 45, 46, 47], "all": [1, 7, 13, 14, 18, 34, 39], "includ": [1, 14, 49], "file": [1, 2, 6, 7, 8, 10, 14, 18, 45, 49], "run": [1, 5, 10, 17, 18, 19, 22, 29, 39, 45, 46, 48, 49], "directli": [1, 14], "prepar": [1, 6, 7, 14, 17, 45], "publish": [1, 6, 15, 45, 47, 49], "them": 1, "argument": [1, 5, 6, 7, 9, 10, 12, 15, 18, 19, 29, 39, 44, 45, 46, 47, 50], "base": [2, 5, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 36, 37, 38, 40, 41, 42, 43, 45, 46, 47, 48], "g": [2, 5, 6], "first": [2, 5, 6, 14, 27, 29, 34, 39, 45, 46], "element": [2, 5, 19, 22, 34, 39, 40, 42], "src": [2, 5, 48], "For": [2, 5, 14], "exampl": [2, 5], "c": [2, 5, 45], "test": [2, 5, 14, 24, 45, 46, 48], "creat": [2, 5, 6, 7, 14, 17, 18, 19, 23, 25, 26, 29, 39, 44, 45, 46, 47, 50], "would": [2, 5, 14], "abc": [2, 17, 18, 21, 22, 23, 24, 25, 26, 27, 32, 35, 37, 39, 40, 42, 43], "abstract": [2, 17, 18, 21, 22, 23, 24, 25, 26, 27, 31, 35, 37, 39, 43], "class": [2, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 44, 45, 46, 47, 50], "enum": [2, 18, 19, 20, 23, 24, 25, 26, 28], "pipe": [2, 16, 23, 45, 46, 47], "servic": [2, 5, 17, 18, 23, 25, 26, 30, 31, 45, 46, 47, 48], "set": [2, 9, 17, 18, 19, 20, 22, 23, 24, 25, 26, 28, 29, 33, 40, 43, 44, 47, 48], "configmodel": 2, "thread": [2, 19, 30, 47], "valid": [2, 26, 48], "list": [3, 6, 13, 18, 19, 22, 23, 26, 27, 29, 34, 35, 36, 37, 38, 39, 40, 42, 43, 45, 47], "avail": [3, 6, 14], "short": [3, 6], "h": [3, 6], "show": [3, 19], "messag": [3, 19, 25, 35, 37], "thi": [3, 14, 17, 34, 45, 46, 48, 49], "packag": [4, 5, 6, 11, 13, 29, 44, 45, 46, 47, 48], "via": [4, 11, 14, 45, 46], "pip": [4, 11, 13, 16, 45, 46, 47, 48, 49], "i": [4, 6, 48], "without": [4, 6, 14, 39], "deped": 4, "your": [4, 6, 9, 10, 14, 45, 46, 49], "dev": [4, 9, 10, 11], "develop": [4, 6, 11, 14, 24, 45, 46, 48, 49], "mode": [4, 11], "virtual": [4, 11], "gener": [5, 6, 7, 15, 45, 47, 48, 49], "initi": [5, 44, 47], "add": [5, 6, 14, 15, 18, 23, 26, 42, 47, 48], "n": [5, 6, 48, 49], "see": [5, 14, 21, 34, 48, 49], "simpl": [5, 45, 46, 49], "applic": [5, 9, 10, 16, 19, 24, 25, 26, 30, 44, 45, 46, 47, 48, 49, 50], "async": [5, 17, 35, 37], "startup": [5, 17, 44, 45, 46, 47, 50], "provid": [5, 14, 17, 23, 34, 45, 46, 48, 49], "noth": 5, "venv": 5, "instal": [6, 13, 15, 29, 44, 47, 48], "cpl": [6, 15, 23, 44, 49], "To": [6, 9, 10, 14, 48, 49], "build": [6, 7, 9, 10, 15, 17, 29, 45, 47, 48, 49], "serv": 6, "new": [6, 14, 15, 19, 34, 47, 48, 49], "server": [6, 21, 26, 45, 46, 49], "go": [6, 14, 45], "parent": 6, "follow": [6, 14, 48, 49], "my": [6, 14, 49], "cd": [6, 49], "start": [6, 9, 15, 39, 45, 46, 47], "In": [6, 14, 48], "termin": [6, 19, 48, 49], "commandnameoralia": 6, "requiredarg": 6, "optionalsarg": 6, "most": [6, 34, 48, 49], "some": 6, "option": [6, 9, 14, 18, 19, 20, 23, 25, 26, 29, 34, 35, 37, 39, 40, 41, 42, 45, 46, 48], "have": [6, 14, 34, 48, 49], "alias": [6, 18], "ar": [6, 7, 14, 18, 34], "shown": [6, 18, 49], "statement": [6, 22], "each": [6, 18, 39], "prefix": [6, 18, 33], "absolut": 6, "current": [6, 24, 34], "work": [6, 14, 24, 45, 46], "either": 6, "root": 6, "take": [6, 18, 39], "artifact": 6, "addit": [6, 14], "ani": [6, 19, 27, 32, 37, 39, 43], "defin": [6, 18, 19, 40, 42, 49], "its": [6, 14], "own": 6, "suppli": 6, "same": 6, "format": [6, 25, 28, 39], "immedi": 6, "alia": 6, "descript": [6, 9, 10, 12, 15, 34, 47], "dist": [6, 7, 9, 10], "help": [6, 14, 15, 45, 46, 47], "With": 6, "depend": [6, 12, 45, 46, 48], "p": [6, 7], "setup": [6, 7, 46, 49], "py": [6, 7, 29, 45, 48], "r": [6, 8, 9], "s": [6, 10, 14, 34, 44, 47], "restart": [6, 10, 49], "chang": [6, 10, 14, 22, 48], "uninstal": [6, 15, 29, 47], "ui": [6, 11, 34], "updat": [6, 14, 15, 47], "u": [6, 12], "version": [6, 15, 34, 47], "v": [6, 13], "data": [7, 19, 34, 39], "cpl_core": [7, 16, 44, 47, 48, 49, 50], "json": [7, 18, 44, 45, 46, 47, 48, 49, 50], "delet": 8, "onc": 9, "paramet": [9, 42], "default": [9, 19, 34, 49], "after": [9, 10, 35, 37, 39], "cli": [13, 44, 45, 46, 47, 48], "we": [14, 48], "love": 14, "make": [14, 49], "even": 14, "better": 14, "than": [14, 39], "todai": 14, "As": 14, "contributor": 14, "here": [14, 49], "like": [14, 45, 48], "issus": 14, "find": 14, "our": 14, "gitea": 14, "repositori": 14, "fix": 14, "implement": [14, 23, 39, 40, 41], "pleas": 14, "consid": 14, "size": 14, "order": [14, 34, 39], "determin": 14, "right": 14, "step": 14, "proce": 14, "major": 14, "open": [14, 48, 49], "outlin": 14, "propos": 14, "so": [14, 49], "discuss": 14, "process": 14, "allow": 14, "coordin": [14, 19], "effort": 14, "prevent": 14, "duplic": 14, "craft": 14, "successfulli": 14, "accept": 14, "note": [14, 34], "topic": [14, 34], "document": 14, "significantli": 14, "re": 14, "write": [14, 19, 25, 45, 46], "count": [14, 39], "small": 14, "befor": [14, 19, 35, 37, 40], "search": [14, 18, 23], "tracker": 14, "mayb": 14, "problem": 14, "alreadi": [14, 48, 49], "exist": [14, 40], "might": 14, "inform": [14, 25, 49], "workaround": 14, "readili": 14, "want": [14, 48], "soon": [14, 44, 47, 50], "possibl": [14, 18], "need": [14, 34, 48, 49], "reproduc": 14, "confirm": 14, "requir": [14, 34], "minim": 14, "reproduct": 14, "scenario": 14, "give": 14, "wealth": 14, "import": [14, 48], "back": [14, 19], "forth": 14, "question": 14, "quickli": 14, "point": [14, 17, 19], "out": [14, 48, 49], "well": 14, "save": [14, 18, 22], "maintain": 14, "time": [14, 16, 25, 34, 47], "ultim": 14, "abl": 14, "more": [14, 39, 49], "often": 14, "themselv": 14, "while": 14, "understand": [14, 45, 46, 48, 49], "sometim": 14, "hard": 14, "extract": 14, "essenti": [14, 48], "bit": 14, "larger": 14, "codebas": 14, "realli": 14, "isol": 14, "unfortun": 14, "investig": 14, "don": [14, 48], "t": [14, 39, 40, 41, 42, 48], "hear": 14, "close": [14, 19], "doesn": 14, "enough": 14, "info": [14, 25, 45, 46], "pr": 14, "relat": 14, "Be": 14, "sure": 14, "describ": 14, "design": 14, "d": 14, "upfront": 14, "ensur": 14, "readi": [14, 49], "fork": 14, "sh": [14, 49], "edraft": [14, 49], "de": [14, 49], "repo": 14, "git": 14, "branch": 14, "checkout": 14, "master": 14, "patch": 14, "appropri": 14, "case": [14, 27, 29, 48], "commit": 14, "line": [14, 19, 48], "automat": 14, "rm": 14, "edit": 14, "push": 14, "origin": 14, "send": [14, 26, 44, 45, 46, 47, 50], "team": 14, "reserv": 14, "commun": 14, "member": [14, 30, 35, 37, 47], "who": 14, "haven": 14, "been": 14, "good": 14, "citizen": 14, "Such": 14, "behavior": 14, "appli": 14, "outsid": 14, "manag": [14, 34, 45, 46], "channel": [14, 34, 35, 37], "ask": 14, "fixup": 14, "head": 14, "That": 14, "thank": 14, "consist": 14, "throughout": 14, "keep": 14, "mind": 14, "one": [14, 39], "unit": 14, "public": 14, "api": [14, 45, 46, 47], "method": 14, "pep": 14, "8": 14, "style": 14, "guid": 14, "By": 14, "agre": 14, "under": [14, 34], "mit": 14, "overview": [15, 47, 49], "tabl": [15, 19, 29, 44, 45, 46, 47], "content": [15, 44, 47], "basic": [15, 47, 48, 49], "workflow": [15, 47], "languag": [15, 43, 47], "syntax": [15, 47], "rel": [15, 47], "schemat": [15, 47], "flag": [15, 40, 47], "application_abc": [16, 47], "application_build": [16, 47], "application_builder_abc": [16, 47], "startup_abc": [16, 47], "configur": [16, 17, 23, 30, 45, 46, 47], "configuration_abc": [16, 17, 23, 47], "configuration_model_abc": [16, 47], "configuration_variable_name_enum": [16, 47], "console_argu": [16, 47], "background_color_enum": [16, 47], "console_cal": [16, 47], "foreground_color_enum": [16, 47], "spinner_thread": [16, 47], "databas": [16, 23, 47], "connect": [16, 20, 22, 26, 37, 47], "database_connect": [16, 20, 47], "database_connection_abc": [16, 20, 47], "context": [16, 20, 23, 35, 37, 47, 49], "database_context": [16, 20, 47], "database_context_abc": [16, 20, 23, 47], "database_model": [16, 47], "database_set": [16, 21, 22, 47], "database_settings_name_enum": [16, 47], "dependency_inject": [16, 17, 47], "service_collect": [16, 37, 47], "service_collection_abc": [16, 17, 47], "service_descriptor": [16, 47], "service_lifetime_enum": [16, 47], "service_provid": [16, 47], "service_provider_abc": [16, 17, 47], "environ": [16, 17, 18, 25, 26, 44, 45, 46, 47], "application_environ": [16, 47], "application_environment_abc": [16, 17, 25, 26, 47], "environment_name_enum": [16, 47], "log": [16, 26, 45, 46, 47], "logger_abc": [16, 26, 47], "logger_servic": [16, 47], "logging_level_enum": [16, 47], "logging_set": [16, 47], "logging_settings_name_enum": [16, 47], "mail": [16, 44, 45, 46, 47, 50], "email": [16, 47], "email_client_abc": [16, 47], "email_client_servic": [16, 47], "email_client_set": [16, 47], "email_client_settings_name_enum": [16, 47], "bool_pip": [16, 47], "first_char_to_lower_pip": [16, 47], "first_to_upper_pip": [16, 47], "ip_address_pip": [16, 47], "pipe_abc": [16, 47], "to_camel_case_pip": [16, 47], "to_snake_case_pip": [16, 47], "version_pip": [16, 47], "time_format_set": [16, 25, 47], "time_format_settings_names_enum": [16, 47], "util": [16, 45, 46, 47], "credential_manag": [16, 47], "string": [16, 19, 21, 25, 26, 27, 45, 46, 47, 48], "applicationabc": [17, 31], "config": [17, 23, 31, 37], "configurationabc": [17, 18, 23, 31, 37], "serviceproviderabc": [17, 18, 23, 31], "contain": [17, 30, 36, 39, 47], "object": [17, 18, 19, 23, 26, 29, 34, 36, 39, 42, 45, 46], "load": [17, 43], "appset": [17, 44, 47, 48, 50], "instanc": [17, 23], "main": [17, 48], "custom": [17, 18, 24, 45, 46], "entri": [17, 19], "run_async": 17, "applicationbuild": 17, "applicationbuilderabc": 17, "build_async": 17, "use_extens": 17, "extens": [17, 38, 39, 42, 45, 46, 47], "union": [17, 18, 19, 23, 35, 36, 37, 39], "applicationextensionabc": 17, "startupextensionabc": 17, "use_startup": 17, "startupabc": 17, "arg": [17, 18, 19, 22, 27, 29, 32, 35, 37, 43], "configure_configur": 17, "env": [17, 25, 37], "applicationenvironmentabc": [17, 18, 24, 25, 26, 37], "configure_servic": 17, "servicecollectionabc": [17, 23, 37], "add_configur": 18, "key_typ": 18, "configurationmodelabc": [18, 20, 25, 26, 28, 33, 43], "add_console_argu": 18, "argumentabc": 18, "known": 18, "consoleargumentabc": 18, "add_environment_vari": 18, "read": [18, 19, 48], "variabl": [18, 29], "add_json_fil": 18, "bool": [18, 19, 20, 26, 27, 34, 39, 40], "none": [18, 19, 23, 25, 26, 29, 39, 40, 41, 42], "true": 18, "error": [18, 19, 25, 35, 37, 45, 46], "should": [18, 48, 49], "occur": 18, "wa": [18, 49], "found": [18, 39], "place": 18, "store": 18, "properti": [18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 33, 34, 37, 39, 42, 43], "additional_argu": 18, "argument_error_funct": 18, "callabl": [18, 19, 23, 39], "argument_abc": 18, "create_console_argu": 18, "arg_typ": 18, "argumenttypeenum": 18, "token": [18, 33], "kwarg": [18, 19, 32, 35, 37], "begin": 18, "value_token": 18, "were": 18, "is_value_token_opt": 18, "runnabl": 18, "when": [18, 19, 35, 37, 39], "for_each_argu": 18, "iter": [18, 38, 39, 40, 41, 47], "through": [18, 48], "function": [18, 19, 29, 39, 40, 42, 45, 48], "get_configur": 18, "search_typ": 18, "return": [18, 19, 23, 26, 34, 39, 48], "parse_console_argu": 18, "invalid": 18, "from_dict": [18, 20, 25, 26, 28, 33, 43], "dict": [18, 19, 20, 25, 26, 27, 28, 33, 43], "convert": [18, 25, 26, 27, 28, 29, 33, 36, 39, 40, 41, 42, 43, 45, 46], "attribut": [18, 20, 25, 26, 28, 33, 43], "configurationvariablenameenum": 18, "enumer": [18, 19, 20, 23, 24, 25, 26, 28, 38, 41, 42, 47], "static": [18, 26, 29, 36], "to_list": [18, 39], "backgroundcolorenum": 19, "blue": 19, "on_blu": 19, "cyan": 19, "on_cyan": 19, "on_default": 19, "green": 19, "on_green": 19, "grei": 19, "on_grei": 19, "magenta": 19, "on_magenta": 19, "red": 19, "on_r": 19, "white": 19, "on_whit": 19, "yellow": 19, "on_yellow": 19, "handl": [19, 29, 44, 45, 46, 47, 50], "input": [19, 45, 46, 48], "background_color": 19, "bytes_or_buff": 19, "encod": [19, 29], "expos": 19, "buffer": [19, 20], "decod": [19, 29], "handler": 19, "result": [19, 26, 29, 39], "__str__": 19, "repr": 19, "sy": 19, "getdefaultencod": 19, "strict": 19, "classmethod": [19, 29, 39], "banner": [19, 45, 46], "print": [19, 48], "clear": 19, "color_reset": 19, "reset": [19, 29, 39], "color": 19, "disabl": 19, "interact": 19, "enabl": [19, 48], "tb": 19, "traceback": 19, "foreground_color": 19, "read_lin": 19, "next": [19, 39, 44, 47], "reset_cursor_posit": 19, "cursor": [19, 21, 22], "posit": [19, 34], "select": [19, 22, 39, 48], "char": [19, 27, 29], "header_foreground_color": 19, "foregroundcolorenum": 19, "header_background_color": 19, "option_foreground_color": 19, "option_background_color": 19, "cursor_foreground_color": 19, "cursor_background_color": 19, "menu": [19, 44, 45, 46, 47], "charact": 19, "header": [19, 25, 26], "foreground": 19, "background": 19, "set_background_color": 19, "set_cursor_posit": 19, "x": [19, 39], "int": [19, 20, 26, 27, 29, 34, 39, 48], "y": [19, 48], "set_foreground_color": 19, "set_hold_back": 19, "spinner": [19, 45, 46], "text_foreground_color": 19, "spinner_foreground_color": 19, "text_background_color": 19, "spinner_background_color": 19, "end": [19, 25], "stop": 19, "text": [19, 34], "keyword": 19, "activ": [19, 34], "last": [19, 39], "write_at": [19, 45, 46], "write_lin": [19, 45, 46, 48], "write_line_at": [19, 45, 46], "consolecal": 19, "repres": [19, 20, 24, 26], "hold": 19, "spinnerthread": 19, "msg_len": 19, "length": [19, 29, 39, 48], "exit": [19, 48], "stop_spin": 19, "databaseset": [20, 21, 22, 23], "auth_plugin": 20, "charset": 20, "host": [20, 26], "password": [20, 48], "port": [20, 26], "use_unicod": 20, "user": [20, 35, 37, 48], "databasesettingsnameenum": 20, "authplugin": 20, "useunicod": 20, "databaseconnect": 21, "databaseconnectionabc": 21, "represent": [21, 22, 23, 25, 26, 28], "connection_str": 21, "http": [21, 49], "doc": 21, "sqlalchemi": 21, "org": 21, "en": 21, "14": 21, "core": [21, 45, 49], "engin": 21, "html": 21, "mysqlcursorbuff": [21, 22], "mysqlconnectionabstract": 21, "databasecontext": 22, "databasecontextabc": [22, 23], "save_chang": 22, "tupl": [22, 34], "sql": 22, "fetch": 22, "servicecollect": 23, "collect": 23, "add_db_context": 23, "db_context_typ": 23, "db_set": 23, "db_context": 23, "add_log": 23, "intern": 23, "logger": [23, 25, 26, 37, 44, 45, 46, 47, 50], "add_pip": 23, "transient": [23, 45, 46], "add_scop": 23, "service_typ": 23, "scope": [23, 45, 46], "lifetim": [23, 45, 46], "self": 23, "add_singleton": 23, "singleton": [23, 45, 46], "add_transi": 23, "build_service_provid": 23, "add_discord": 23, "discord": [23, 35, 37, 45, 47], "add_transl": 23, "translat": [23, 45, 47], "servicedescriptor": 23, "servicelifetimeenum": 23, "base_typ": 23, "descriptor": 23, "1": [23, 25, 48], "0": [23, 25, 34, 48], "2": [23, 25, 34, 48], "serviceprovid": 23, "build_servic": 23, "instance_typ": 23, "create_scop": 23, "scopeabc": 23, "get_servic": 23, "set_scop": 23, "applicationenviron": 24, "environmentnameenum": 24, "product": [24, 45, 46], "application_nam": 24, "date_time_now": 24, "datetim": [24, 34, 35, 37], "end_tim": 24, "environment_nam": 24, "host_nam": 24, "runtime_directori": 24, "set_runtime_directori": 24, "runtim": [24, 45, 46], "set_working_directori": 24, "working_directori": 24, "start_tim": 24, "stage": [24, 45, 46], "loggerabc": [25, 26, 37], "debug": [25, 45, 46], "ex": 25, "except": [25, 39], "thrown": 25, "fatal": [25, 45, 46], "program": 25, "trace": [25, 45, 46], "warn": [25, 45, 46], "loggingset": [25, 37], "time_format": [25, 28], "timeformatset": [25, 28], "tree": 25, "logfil": 25, "logginglevelenum": 25, "5": [25, 48], "4": 25, "off": 25, "6": 25, "3": 25, "filenam": 25, "level": [25, 45, 46], "loggingsettingsnameenum": 25, "console_level": 25, "consoleloglevel": 25, "file_level": 25, "fileloglevel": 25, "subject": 26, "bodi": 26, "transceiv": 26, "receiv": 26, "e": 26, "add_head": 26, "add_receiv": 26, "check_mail": 26, "address": 26, "check": [26, 39, 40], "get_cont": 26, "header_list": 26, "receiver_list": 26, "emailclientabc": 26, "emailcli": 26, "send_mail": 26, "mail_set": 26, "emailclientset": 26, "login": 26, "credenti": [26, 29, 45, 46], "user_nam": 26, "emailclientsettingsnameenum": 26, "usernam": 26, "boolpip": 27, "pipeabc": [27, 43], "transform": [27, 43], "firstchartolowerpip": 27, "lower": [27, 29, 48], "firsttoupperpip": 27, "upper": [27, 29, 48], "ipaddresspip": 27, "tocamelcasepip": 27, "camel": [27, 29], "camelcas": [27, 29], "tosnakecasepip": 27, "snake": [27, 29], "snake_cas": [27, 29], "versionpip": 27, "date_format": 28, "date_time_format": 28, "date_time_log_format": 28, "timeformatsettingsnamesenum": 28, "dateformat": 28, "datetimeformat": 28, "datetimelogformat": 28, "timeformat": 28, "credentialmanag": 29, "encrypt": [29, 45, 46], "decrypt": 29, "build_str": 29, "replac": 29, "base64": [29, 45, 46], "get_execut": 29, "get_outd": 29, "byte": 29, "get": [29, 45, 46, 47, 49], "outdat": 29, "get_packag": 29, "local": [29, 44, 47], "stdout": 29, "stderr": 29, "extra": [29, 49], "index": [29, 39, 42, 48, 49], "url": [29, 49], "subprocess": [29, 45, 46], "reset_execut": 29, "system": 29, "standard": [29, 45, 46], "set_execut": 29, "convert_to_camel_cas": 29, "convert_to_snake_cas": 29, "first_to_low": 29, "first_to_upp": 29, "random_str": 29, "random": [29, 48], "cpl_discord": [30, 47], "discord_bot_application_abc": [30, 47], "discord_command_abc": [30, 47], "discord_commands_meta": [30, 47], "discord_bot_set": [30, 37, 47], "category_channel": [30, 47], "guild": [30, 35, 37, 47], "role": [30, 35, 37, 47], "text_channel": [30, 47], "voice_channel": [30, 47], "event": [30, 37, 47], "on_bulk_message_delete_abc": [30, 47], "on_command_abc": [30, 47], "on_command_completion_abc": [30, 47], "on_command_error_abc": [30, 47], "on_connect_abc": [30, 47], "on_disconnect_abc": [30, 47], "on_error_abc": [30, 47], "on_group_join_abc": [30, 47], "on_group_remove_abc": [30, 47], "on_guild_available_abc": [30, 47], "on_guild_channel_create_abc": [30, 47], "on_guild_channel_delete_abc": [30, 47], "on_guild_channel_pins_update_abc": [30, 47], "on_guild_channel_update_abc": [30, 47], "on_guild_emojis_update_abc": [30, 47], "on_guild_integrations_update_abc": [30, 47], "on_guild_join_abc": [30, 47], "on_guild_remove_abc": [30, 47], "on_guild_role_create_abc": [30, 47], "on_guild_role_delete_abc": [30, 47], "on_guild_role_update_abc": [30, 47], "on_guild_unavailable_abc": [30, 47], "on_guild_update_abc": [30, 47], "on_invite_create_abc": [30, 47], "on_invite_delete_abc": [30, 47], "on_member_ban_abc": [30, 47], "on_member_join_abc": [30, 47], "on_member_remove_abc": [30, 47], "on_member_unban_abc": [30, 47], "on_member_update_abc": [30, 47], "on_message_abc": [30, 47], "on_message_delete_abc": [30, 47], "on_message_edit_abc": [30, 47], "on_private_channel_create_abc": [30, 47], "on_private_channel_delete_abc": [30, 47], "on_private_channel_pins_update_abc": [30, 47], "on_private_channel_update_abc": [30, 47], "on_raw_reaction_add_abc": [30, 47], "on_raw_reaction_clear_abc": [30, 47], "on_raw_reaction_clear_emoji_abc": [30, 47], "on_raw_reaction_remove_abc": [30, 47], "on_reaction_add_abc": [30, 47], "on_reaction_clear_abc": [30, 47], "on_reaction_clear_emoji_abc": [30, 47], "on_reaction_remove_abc": [30, 47], "on_ready_abc": [30, 47], "on_resume_abc": [30, 47], "on_typing_abc": [30, 47], "on_user_update_abc": [30, 47], "on_voice_state_update_abc": [30, 47], "on_webhooks_update_abc": [30, 47], "helper": [30, 47], "to_containers_convert": [30, 47], "command_error_handler_servic": [30, 47], "discord_bot_servic": [30, 47], "discord_bot_service_abc": [30, 47], "discord_collect": [30, 47], "discord_collection_abc": [30, 47], "discord_servic": [30, 47], "discord_service_abc": [30, 47], "discordbotapplicationabc": 31, "stop_async": [31, 37], "discordcommandabc": [32, 37], "cog": [32, 37], "discordcogmeta": 32, "namespac": 32, "abcmeta": 32, "cogmeta": 32, "discordbotset": [33, 37], "categorychannel": 34, "_t": [34, 36, 37, 39], "category_id": 34, "id": [34, 48], "nsfw": 34, "textchannel": 34, "categori": 34, "voicechannel": 34, "voic": 34, "_o": 34, "afk_channel": 34, "afk_timeout": 34, "approximate_member_count": 34, "approximate_presence_count": 34, "belong": 34, "sort": [34, 39, 45], "top": 34, "bottom": 34, "default_notif": 34, "emoji": [34, 35, 37], "explicit_content_filt": 34, "featur": [34, 49], "max_memb": 34, "max_pres": 34, "max_video_channel_us": 34, "sequenc": [34, 35, 36, 37, 39], "mfa_level": 34, "nsfw_level": 34, "owner_id": 34, "preferred_local": 34, "premium_progress_bar_en": 34, "premium_subscription_count": 34, "premium_ti": 34, "hierarchi": 34, "lowest": [34, 39], "sticker": 34, "permiss": 34, "view": 34, "unavail": 34, "vanity_url_cod": 34, "verification_level": 34, "widget_en": 34, "activitytyp": 34, "joined_at": 34, "nick": 34, "pend": 34, "premium_sinc": 34, "alwai": 34, "everyon": 34, "These": [34, 45], "timed_out_until": 34, "hoist": 34, "mention": 34, "tag": 34, "unicode_emoji": 34, "default_auto_archive_dur": 34, "last_message_id": 34, "slowmode_delai": 34, "archive_timestamp": 34, "archiv": 34, "archiver_id": 34, "auto_archive_dur": 34, "invit": [34, 35, 37], "lock": 34, "me": 34, "member_count": 34, "threadmemb": 34, "intent": 34, "properli": 34, "fill": 34, "howev": 34, "gatewai": 34, "fetch_memb": 34, "message_count": 34, "parent_id": 34, "insid": 34, "onbulkmessagedeleteabc": 35, "on_bulk_message_delet": [35, 37], "oncommandabc": 35, "on_command": [35, 37], "ctx": [35, 37], "oncommandcompletionabc": 35, "on_command_complet": [35, 37], "oncommanderrorabc": [35, 37], "on_command_error": [35, 37], "commanderror": [35, 37], "onconnectabc": 35, "on_connect": [35, 37], "ondisconnectabc": 35, "on_disconnect": [35, 37], "onerrorabc": 35, "on_error": [35, 37], "ongroupjoinabc": 35, "on_group_join": [35, 37], "chhanel": [35, 37], "groupchannel": [35, 37], "ongroupremoveabc": 35, "on_group_remov": [35, 37], "onguildavailableabc": 35, "on_guild_avail": [35, 37], "onguildchannelcreateabc": 35, "on_guild_channel_cr": [35, 37], "guildchannel": [35, 37], "onguildchanneldeleteabc": 35, "on_guild_channel_delet": [35, 37], "onguildchannelpinsupdateabc": 35, "on_guild_channel_pins_upd": [35, 37], "list_pin": [35, 37], "onguildchannelupdateabc": 35, "on_guild_channel_upd": [35, 37], "onguildemojisupdateabc": 35, "on_guild_emojis_upd": [35, 37], "onguildintegrationsupdateabc": 35, "on_guild_integrations_upd": [35, 37], "onguildjoinabc": 35, "on_guild_join": [35, 37], "onguildremoveabc": 35, "on_guild_remov": [35, 37], "onguildrolecreateabc": 35, "on_guild_role_cr": [35, 37], "onguildroledeleteabc": 35, "on_guild_role_delet": [35, 37], "onguildroleupdateabc": 35, "on_guild_role_upd": [35, 37], "onguildunavailableabc": 35, "on_guild_unavail": [35, 37], "onguildupdateabc": 35, "on_guild_upd": [35, 37], "oninvitecreateabc": 35, "on_invite_cr": [35, 37], "oninvitedeleteabc": 35, "on_invite_delet": [35, 37], "onmemberbanabc": 35, "on_member_ban": [35, 37], "onmemberjoinabc": 35, "on_member_join": [35, 37], "onmemberremoveabc": 35, "on_member_remov": [35, 37], "onmemberunbanabc": 35, "on_member_unban": [35, 37], "onmemberupdateabc": 35, "on_member_upd": [35, 37], "onmessageabc": 35, "on_messag": [35, 37], "onmessagedeleteabc": 35, "on_message_delet": [35, 37], "onmessageeditabc": 35, "on_message_edit": [35, 37], "onprivatechannelcreateabc": 35, "on_private_channel_cr": [35, 37], "privatechannel": [35, 37], "onprivatechanneldeleteabc": 35, "on_private_channel_delet": [35, 37], "onprivatechannelpinsupdateabc": 35, "on_private_channel_pins_upd": [35, 37], "onprivatechannelupdateabc": 35, "on_private_channel_upd": [35, 37], "onrawreactionaddabc": 35, "on_raw_reaction_add": [35, 37], "payload": [35, 37], "rawreactionactionev": [35, 37], "onrawreactionclearabc": 35, "on_raw_reaction_clear": [35, 37], "onrawreactionclearemojiabc": 35, "on_raw_reaction_clear_emoji": [35, 37], "onrawreactionremoveabc": 35, "on_raw_reaction_remov": [35, 37], "onreactionaddabc": 35, "on_reaction_add": [35, 37], "reaction": [35, 37], "onreactionclearabc": 35, "on_reaction_clear": [35, 37], "onreactionclearemojiabc": 35, "on_reaction_clear_emoji": [35, 37], "onreactionremoveabc": 35, "on_reaction_remov": [35, 37], "onreadyabc": 35, "on_readi": [35, 37], "onresumeabc": 35, "on_resum": [35, 37], "ontypingabc": 35, "on_typ": [35, 37], "onuserupdateabc": 35, "on_user_upd": [35, 37], "onvoicestateupdateabc": 35, "on_voice_state_upd": [35, 37], "voicest": [35, 37], "onwebhooksupdateabc": 35, "on_webhooks_upd": [35, 37], "tocontainersconvert": 36, "_l": 36, "commanderrorhandlerservic": 37, "discordbotservic": 37, "logging_st": 37, "discordserviceabc": 37, "discordbotserviceabc": 37, "client": 37, "start_async": 37, "bot": 37, "discordcollect": 37, "discordcollectionabc": 37, "add_command": 37, "add_ev": 37, "_t_event": 37, "get_command": 37, "get_events_by_bas": 37, "discordservic": 37, "init": 37, "cpl_queri": [38, 47], "default_lambda": [38, 47], "ordered_query": [38, 47], "ordered_queryable_abc": [38, 47], "queryable_abc": [38, 47], "sequence_abc": [38, 47], "sequence_valu": [38, 47], "enumerable_abc": [38, 41, 42, 47], "iterable_abc": [38, 40, 41, 47], "orderedquery": 39, "_valu": [39, 40], "_func": 39, "orderedqueryableabc": 39, "orderediterableabc": 39, "then_bi": 39, "orderedlist": 39, "ascend": 39, "func": 39, "ordered_iterable_abc": 39, "then_by_descend": 39, "descend": 39, "queryableabc": [39, 40, 42], "sequenceabc": 39, "everi": 39, "equal": 39, "averag": 39, "float": 39, "complex": [39, 45, 46], "distinct": 39, "redund": 39, "element_at": 39, "_index": 39, "element_at_or_default": 39, "first_or_default": 39, "for_each": 39, "group_bi": 39, "group": 39, "last_or_default": 39, "max": 39, "highest": 39, "median": 39, "min": 39, "order_bi": 39, "order_by_descend": 39, "revers": 39, "select_mani": 39, "flatten": 39, "singl": 39, "argumentnoneexcept": 39, "single_or_default": 39, "skip": 39, "skip_last": 39, "sum": 39, "take_last": 39, "where": 39, "empti": 39, "_object": [39, 42], "indexerror": 39, "rang": [39, 48], "sequencevalu": 39, "enumerableabc": [40, 41, 42], "set_remove_error_check": 40, "to_iter": [40, 41], "iterableabc": [40, 41, 42], "to_enumer": [41, 42], "append": 42, "extend": [42, 44, 47, 50], "_iterableabc__iter": 42, "__iter": 42, "translatepip": 43, "translationserviceabc": 43, "translationservic": 43, "lang": 43, "load_by_set": 43, "translationset": 43, "set_default_lang": 43, "set_lang": 43, "kei": [43, 45, 49], "default_languag": 43, "prerequisit": [44, 47], "what": [44, 47], "up": [44, 47], "queri": [44, 45, 46, 47], "tutori": [44, 47, 48, 49], "com": [44, 47, 50], "builtin": [44, 47, 50], "common": [45, 46], "platform": [45, 46], "meant": [45, 46], "effici": [45, 46], "desktop": [45, 46], "learn": [45, 46, 49], "enterpris": [45, 46], "expandl": [45, 46], "builder": [45, 46], "map": [45, 46], "inject": [45, 46, 48], "appnam": [45, 46], "hostnam": [45, 46], "wrapper": [45, 46], "differ": [45, 46], "variant": [45, 46], "to_lower_cas": [45, 46], "to_camel_cas": [45, 46], "code": [45, 48, 49], "connector": 45, "between": 45, "filter": 45, "linq": 45, "xd": 45, "dot": 45, "notat": 45, "page": 45, "great": 45, "detail": 45, "about": [45, 49], "everyth": 45, "do": [45, 48], "contribut": 45, "cpl_translat": 47, "translate_pip": 47, "translation_servic": 47, "translation_service_abc": 47, "translation_set": 47, "welcom": 48, "introduc": 48, "walk": 48, "also": [48, 49], "sampl": 48, "ouput": 48, "look": 48, "licens": 48, "done": 48, "readm": 48, "md": 48, "__init__": 48, "projectmain": 48, "vs": 48, "pycharm": 48, "folder": 48, "hello": [48, 49], "world": [48, 49], "emul": 48, "def": 48, "onli": 48, "__name__": 48, "__main__": 48, "generate_password": 48, "letter": 48, "join": 48, "choic": 48, "ascii_lowercas": 48, "elif": 48, "ascii_uppercas": 48, "ascii_lett": 48, "len": 48, "full": 48, "section": 48, "ve": 48, "continu": 48, "explor": 48, "window": 49, "prompt": 49, "declin": 49, "enter": 49, "press": 49, "lib": 49, "live": 49, "navig": 49, "launch": 49, "watch": 49, "chnage": 49, "those": 49, "success": 49, "similar": 49, "fore": 49, "pyhton": 49}, "objects": {"cpl_core.application": [[17, 0, 0, "-", "application_abc"], [17, 0, 0, "-", "application_builder"], [17, 0, 0, "-", "application_builder_abc"], [17, 0, 0, "-", "startup_abc"]], "cpl_core.application.application_abc": [[17, 1, 1, "", "ApplicationABC"]], "cpl_core.application.application_abc.ApplicationABC": [[17, 2, 1, "", "configure"], [17, 2, 1, "", "main"], [17, 2, 1, "", "run"], [17, 2, 1, "", "run_async"]], "cpl_core.application.application_builder": [[17, 1, 1, "", "ApplicationBuilder"]], "cpl_core.application.application_builder.ApplicationBuilder": [[17, 2, 1, "", "build"], [17, 2, 1, "", "build_async"], [17, 2, 1, "", "use_extension"], [17, 2, 1, "", "use_startup"]], "cpl_core.application.application_builder_abc": [[17, 1, 1, "", "ApplicationBuilderABC"]], "cpl_core.application.application_builder_abc.ApplicationBuilderABC": [[17, 2, 1, "", "build"], [17, 2, 1, "", "build_async"], [17, 2, 1, "", "use_startup"]], "cpl_core.application.startup_abc": [[17, 1, 1, "", "StartupABC"]], "cpl_core.application.startup_abc.StartupABC": [[17, 2, 1, "", "configure_configuration"], [17, 2, 1, "", "configure_services"]], "cpl_core.configuration": [[18, 0, 0, "-", "configuration"], [18, 0, 0, "-", "configuration_abc"], [18, 0, 0, "-", "configuration_model_abc"], [18, 0, 0, "-", "configuration_variable_name_enum"]], "cpl_core.configuration.configuration": [[18, 1, 1, "", "Configuration"]], "cpl_core.configuration.configuration.Configuration": [[18, 2, 1, "", "add_configuration"], [18, 2, 1, "", "add_console_argument"], [18, 2, 1, "", "add_environment_variables"], [18, 2, 1, "", "add_json_file"], [18, 3, 1, "", "additional_arguments"], [18, 3, 1, "", "argument_error_function"], [18, 3, 1, "", "arguments"], [18, 2, 1, "", "create_console_argument"], [18, 3, 1, "", "environment"], [18, 2, 1, "", "for_each_argument"], [18, 2, 1, "", "get_configuration"], [18, 2, 1, "", "parse_console_arguments"]], "cpl_core.configuration.configuration_abc": [[18, 1, 1, "", "ConfigurationABC"]], "cpl_core.configuration.configuration_abc.ConfigurationABC": [[18, 2, 1, "", "add_configuration"], [18, 2, 1, "", "add_console_argument"], [18, 2, 1, "", "add_environment_variables"], [18, 2, 1, "", "add_json_file"], [18, 3, 1, "", "additional_arguments"], [18, 3, 1, "", "argument_error_function"], [18, 3, 1, "", "arguments"], [18, 2, 1, "", "create_console_argument"], [18, 3, 1, "", "environment"], [18, 2, 1, "", "for_each_argument"], [18, 2, 1, "", "get_configuration"], [18, 2, 1, "", "parse_console_arguments"]], "cpl_core.configuration.configuration_model_abc": [[18, 1, 1, "", "ConfigurationModelABC"]], "cpl_core.configuration.configuration_model_abc.ConfigurationModelABC": [[18, 2, 1, "", "from_dict"]], "cpl_core.configuration.configuration_variable_name_enum": [[18, 1, 1, "", "ConfigurationVariableNameEnum"]], "cpl_core.configuration.configuration_variable_name_enum.ConfigurationVariableNameEnum": [[18, 4, 1, "", "customer"], [18, 4, 1, "", "environment"], [18, 4, 1, "", "name"], [18, 2, 1, "", "to_list"]], "cpl_core.console": [[19, 0, 0, "-", "background_color_enum"], [19, 0, 0, "-", "console"], [19, 0, 0, "-", "console_call"], [19, 0, 0, "-", "foreground_color_enum"], [19, 0, 0, "-", "spinner_thread"]], "cpl_core.console.background_color_enum": [[19, 1, 1, "", "BackgroundColorEnum"]], "cpl_core.console.background_color_enum.BackgroundColorEnum": [[19, 4, 1, "", "blue"], [19, 4, 1, "", "cyan"], [19, 4, 1, "", "default"], [19, 4, 1, "", "green"], [19, 4, 1, "", "grey"], [19, 4, 1, "", "magenta"], [19, 4, 1, "", "red"], [19, 4, 1, "", "white"], [19, 4, 1, "", "yellow"]], "cpl_core.console.console": [[19, 1, 1, "", "Console"]], "cpl_core.console.console.Console": [[19, 3, 1, "", "background_color"], [19, 2, 1, "", "banner"], [19, 2, 1, "", "clear"], [19, 2, 1, "", "close"], [19, 2, 1, "", "color_reset"], [19, 2, 1, "", "disable"], [19, 2, 1, "", "enable"], [19, 2, 1, "", "error"], [19, 3, 1, "", "foreground_color"], [19, 2, 1, "", "read"], [19, 2, 1, "", "read_line"], [19, 2, 1, "", "reset_cursor_position"], [19, 2, 1, "", "select"], [19, 2, 1, "", "set_background_color"], [19, 2, 1, "", "set_cursor_position"], [19, 2, 1, "", "set_foreground_color"], [19, 2, 1, "", "set_hold_back"], [19, 2, 1, "", "spinner"], [19, 2, 1, "", "table"], [19, 2, 1, "", "write"], [19, 2, 1, "", "write_at"], [19, 2, 1, "", "write_line"], [19, 2, 1, "", "write_line_at"]], "cpl_core.console.console_call": [[19, 1, 1, "", "ConsoleCall"]], "cpl_core.console.console_call.ConsoleCall": [[19, 3, 1, "", "args"], [19, 3, 1, "", "function"]], "cpl_core.console.foreground_color_enum": [[19, 1, 1, "", "ForegroundColorEnum"]], "cpl_core.console.foreground_color_enum.ForegroundColorEnum": [[19, 4, 1, "", "blue"], [19, 4, 1, "", "cyan"], [19, 4, 1, "", "default"], [19, 4, 1, "", "green"], [19, 4, 1, "", "grey"], [19, 4, 1, "", "magenta"], [19, 4, 1, "", "red"], [19, 4, 1, "", "white"], [19, 4, 1, "", "yellow"]], "cpl_core.console.spinner_thread": [[19, 1, 1, "", "SpinnerThread"]], "cpl_core.console.spinner_thread.SpinnerThread": [[19, 2, 1, "", "exit"], [19, 2, 1, "", "run"], [19, 2, 1, "", "stop_spinning"]], "cpl_core.database.connection": [[21, 0, 0, "-", "database_connection"], [21, 0, 0, "-", "database_connection_abc"]], "cpl_core.database.connection.database_connection": [[21, 1, 1, "", "DatabaseConnection"]], "cpl_core.database.connection.database_connection.DatabaseConnection": [[21, 2, 1, "", "connect"], [21, 3, 1, "", "cursor"], [21, 3, 1, "", "server"]], "cpl_core.database.connection.database_connection_abc": [[21, 1, 1, "", "DatabaseConnectionABC"]], "cpl_core.database.connection.database_connection_abc.DatabaseConnectionABC": [[21, 2, 1, "", "connect"], [21, 3, 1, "", "cursor"], [21, 3, 1, "", "server"]], "cpl_core.database.context": [[22, 0, 0, "-", "database_context"], [22, 0, 0, "-", "database_context_abc"]], "cpl_core.database.context.database_context": [[22, 1, 1, "", "DatabaseContext"]], "cpl_core.database.context.database_context.DatabaseContext": [[22, 2, 1, "", "connect"], [22, 3, 1, "", "cursor"], [22, 2, 1, "", "save_changes"], [22, 2, 1, "", "select"]], "cpl_core.database.context.database_context_abc": [[22, 1, 1, "", "DatabaseContextABC"]], "cpl_core.database.context.database_context_abc.DatabaseContextABC": [[22, 2, 1, "", "connect"], [22, 3, 1, "", "cursor"], [22, 2, 1, "", "save_changes"], [22, 2, 1, "", "select"]], "cpl_core.database": [[20, 0, 0, "-", "database_settings"], [20, 0, 0, "-", "database_settings_name_enum"]], "cpl_core.database.database_settings": [[20, 1, 1, "", "DatabaseSettings"]], "cpl_core.database.database_settings.DatabaseSettings": [[20, 3, 1, "", "auth_plugin"], [20, 3, 1, "", "buffered"], [20, 3, 1, "", "charset"], [20, 3, 1, "", "database"], [20, 2, 1, "", "from_dict"], [20, 3, 1, "", "host"], [20, 3, 1, "", "password"], [20, 3, 1, "", "port"], [20, 3, 1, "", "use_unicode"], [20, 3, 1, "", "user"]], "cpl_core.database.database_settings_name_enum": [[20, 1, 1, "", "DatabaseSettingsNameEnum"]], "cpl_core.database.database_settings_name_enum.DatabaseSettingsNameEnum": [[20, 4, 1, "", "auth_plugin"], [20, 4, 1, "", "buffered"], [20, 4, 1, "", "charset"], [20, 4, 1, "", "database"], [20, 4, 1, "", "host"], [20, 4, 1, "", "password"], [20, 4, 1, "", "port"], [20, 4, 1, "", "use_unicode"], [20, 4, 1, "", "user"]], "cpl_core.dependency_injection": [[23, 0, 0, "-", "service_collection"], [23, 0, 0, "-", "service_collection_abc"], [23, 0, 0, "-", "service_descriptor"], [23, 0, 0, "-", "service_lifetime_enum"], [23, 0, 0, "-", "service_provider"], [23, 0, 0, "-", "service_provider_abc"]], "cpl_core.dependency_injection.service_collection": [[23, 1, 1, "", "ServiceCollection"]], "cpl_core.dependency_injection.service_collection.ServiceCollection": [[23, 2, 1, "", "add_db_context"], [23, 2, 1, "", "add_logging"], [23, 2, 1, "", "add_pipes"], [23, 2, 1, "", "add_scoped"], [23, 2, 1, "", "add_singleton"], [23, 2, 1, "", "add_transient"], [23, 2, 1, "", "build_service_provider"]], "cpl_core.dependency_injection.service_collection_abc": [[23, 1, 1, "", "ServiceCollectionABC"]], "cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC": [[23, 2, 1, "", "add_db_context"], [23, 2, 1, "", "add_discord"], [23, 2, 1, "", "add_logging"], [23, 2, 1, "", "add_pipes"], [23, 2, 1, "", "add_scoped"], [23, 2, 1, "", "add_singleton"], [23, 2, 1, "", "add_transient"], [23, 2, 1, "", "add_translation"], [23, 2, 1, "", "build_service_provider"]], "cpl_core.dependency_injection.service_descriptor": [[23, 1, 1, "", "ServiceDescriptor"]], "cpl_core.dependency_injection.service_descriptor.ServiceDescriptor": [[23, 3, 1, "", "base_type"], [23, 3, 1, "", "implementation"], [23, 3, 1, "", "lifetime"], [23, 3, 1, "", "service_type"]], "cpl_core.dependency_injection.service_lifetime_enum": [[23, 1, 1, "", "ServiceLifetimeEnum"]], "cpl_core.dependency_injection.service_lifetime_enum.ServiceLifetimeEnum": [[23, 4, 1, "", "scoped"], [23, 4, 1, "", "singleton"], [23, 4, 1, "", "transient"]], "cpl_core.dependency_injection.service_provider": [[23, 1, 1, "", "ServiceProvider"]], "cpl_core.dependency_injection.service_provider.ServiceProvider": [[23, 2, 1, "", "build_service"], [23, 2, 1, "", "create_scope"], [23, 2, 1, "", "get_service"], [23, 2, 1, "", "set_scope"]], "cpl_core.dependency_injection.service_provider_abc": [[23, 1, 1, "", "ServiceProviderABC"]], "cpl_core.dependency_injection.service_provider_abc.ServiceProviderABC": [[23, 2, 1, "", "build_service"], [23, 2, 1, "", "create_scope"], [23, 2, 1, "", "get_service"], [23, 2, 1, "", "set_scope"]], "cpl_core.environment": [[24, 0, 0, "-", "application_environment"], [24, 0, 0, "-", "application_environment_abc"], [24, 0, 0, "-", "environment_name_enum"]], "cpl_core.environment.application_environment": [[24, 1, 1, "", "ApplicationEnvironment"]], "cpl_core.environment.application_environment.ApplicationEnvironment": [[24, 3, 1, "", "application_name"], [24, 3, 1, "", "customer"], [24, 3, 1, "", "date_time_now"], [24, 3, 1, "", "end_time"], [24, 3, 1, "", "environment_name"], [24, 3, 1, "", "host_name"], [24, 3, 1, "", "runtime_directory"], [24, 2, 1, "", "set_runtime_directory"], [24, 2, 1, "", "set_working_directory"], [24, 3, 1, "", "start_time"], [24, 3, 1, "", "working_directory"]], "cpl_core.environment.application_environment_abc": [[24, 1, 1, "", "ApplicationEnvironmentABC"]], "cpl_core.environment.application_environment_abc.ApplicationEnvironmentABC": [[24, 3, 1, "", "application_name"], [24, 3, 1, "", "customer"], [24, 3, 1, "", "date_time_now"], [24, 3, 1, "", "end_time"], [24, 3, 1, "", "environment_name"], [24, 3, 1, "", "host_name"], [24, 3, 1, "", "runtime_directory"], [24, 2, 1, "", "set_runtime_directory"], [24, 2, 1, "", "set_working_directory"], [24, 3, 1, "", "start_time"], [24, 3, 1, "", "working_directory"]], "cpl_core.environment.environment_name_enum": [[24, 1, 1, "", "EnvironmentNameEnum"]], "cpl_core.environment.environment_name_enum.EnvironmentNameEnum": [[24, 4, 1, "", "development"], [24, 4, 1, "", "production"], [24, 4, 1, "", "staging"], [24, 4, 1, "", "testing"]], "cpl_core.logging": [[25, 0, 0, "-", "logger_abc"], [25, 0, 0, "-", "logger_service"], [25, 0, 0, "-", "logging_level_enum"], [25, 0, 0, "-", "logging_settings"], [25, 0, 0, "-", "logging_settings_name_enum"]], "cpl_core.logging.logger_abc": [[25, 1, 1, "", "LoggerABC"]], "cpl_core.logging.logger_abc.LoggerABC": [[25, 2, 1, "", "debug"], [25, 2, 1, "", "error"], [25, 2, 1, "", "fatal"], [25, 2, 1, "", "header"], [25, 2, 1, "", "info"], [25, 2, 1, "", "trace"], [25, 2, 1, "", "warn"]], "cpl_core.logging.logger_service": [[25, 1, 1, "", "Logger"]], "cpl_core.logging.logger_service.Logger": [[25, 2, 1, "", "create"], [25, 2, 1, "", "debug"], [25, 2, 1, "", "error"], [25, 2, 1, "", "fatal"], [25, 2, 1, "", "header"], [25, 2, 1, "", "info"], [25, 2, 1, "", "trace"], [25, 2, 1, "", "warn"]], "cpl_core.logging.logging_level_enum": [[25, 1, 1, "", "LoggingLevelEnum"]], "cpl_core.logging.logging_level_enum.LoggingLevelEnum": [[25, 4, 1, "", "DEBUG"], [25, 4, 1, "", "ERROR"], [25, 4, 1, "", "FATAL"], [25, 4, 1, "", "INFO"], [25, 4, 1, "", "OFF"], [25, 4, 1, "", "TRACE"], [25, 4, 1, "", "WARN"]], "cpl_core.logging.logging_settings": [[25, 1, 1, "", "LoggingSettings"]], "cpl_core.logging.logging_settings.LoggingSettings": [[25, 3, 1, "", "console"], [25, 3, 1, "", "filename"], [25, 2, 1, "", "from_dict"], [25, 3, 1, "", "level"], [25, 3, 1, "", "path"]], "cpl_core.logging.logging_settings_name_enum": [[25, 1, 1, "", "LoggingSettingsNameEnum"]], "cpl_core.logging.logging_settings_name_enum.LoggingSettingsNameEnum": [[25, 4, 1, "", "console_level"], [25, 4, 1, "", "file_level"], [25, 4, 1, "", "filename"], [25, 4, 1, "", "path"]], "cpl_core.mailing": [[26, 0, 0, "-", "email"], [26, 0, 0, "-", "email_client_abc"], [26, 0, 0, "-", "email_client_service"], [26, 0, 0, "-", "email_client_settings"], [26, 0, 0, "-", "email_client_settings_name_enum"]], "cpl_core.mailing.email": [[26, 1, 1, "", "EMail"]], "cpl_core.mailing.email.EMail": [[26, 2, 1, "", "add_header"], [26, 2, 1, "", "add_receiver"], [26, 3, 1, "", "body"], [26, 2, 1, "", "check_mail"], [26, 2, 1, "", "get_content"], [26, 3, 1, "", "header"], [26, 3, 1, "", "header_list"], [26, 3, 1, "", "receiver"], [26, 3, 1, "", "receiver_list"], [26, 3, 1, "", "subject"], [26, 3, 1, "", "transceiver"]], "cpl_core.mailing.email_client_abc": [[26, 1, 1, "", "EMailClientABC"]], "cpl_core.mailing.email_client_abc.EMailClientABC": [[26, 2, 1, "", "connect"], [26, 2, 1, "", "send_mail"]], "cpl_core.mailing.email_client_service": [[26, 1, 1, "", "EMailClient"]], "cpl_core.mailing.email_client_service.EMailClient": [[26, 2, 1, "", "connect"], [26, 2, 1, "", "create"], [26, 2, 1, "", "login"], [26, 2, 1, "", "send_mail"]], "cpl_core.mailing.email_client_settings": [[26, 1, 1, "", "EMailClientSettings"]], "cpl_core.mailing.email_client_settings.EMailClientSettings": [[26, 3, 1, "", "credentials"], [26, 2, 1, "", "from_dict"], [26, 3, 1, "", "host"], [26, 3, 1, "", "port"], [26, 3, 1, "", "user_name"]], "cpl_core.mailing.email_client_settings_name_enum": [[26, 1, 1, "", "EMailClientSettingsNameEnum"]], "cpl_core.mailing.email_client_settings_name_enum.EMailClientSettingsNameEnum": [[26, 4, 1, "", "credentials"], [26, 4, 1, "", "host"], [26, 4, 1, "", "port"], [26, 4, 1, "", "user_name"]], "cpl_core.pipes": [[27, 0, 0, "-", "bool_pipe"], [27, 0, 0, "-", "first_char_to_lower_pipe"], [27, 0, 0, "-", "first_to_upper_pipe"], [27, 0, 0, "-", "ip_address_pipe"], [27, 0, 0, "-", "pipe_abc"], [27, 0, 0, "-", "to_camel_case_pipe"], [27, 0, 0, "-", "to_snake_case_pipe"], [27, 0, 0, "-", "version_pipe"]], "cpl_core.pipes.bool_pipe": [[27, 1, 1, "", "BoolPipe"]], "cpl_core.pipes.bool_pipe.BoolPipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.first_char_to_lower_pipe": [[27, 1, 1, "", "FirstCharToLowerPipe"]], "cpl_core.pipes.first_char_to_lower_pipe.FirstCharToLowerPipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.first_to_upper_pipe": [[27, 1, 1, "", "FirstToUpperPipe"]], "cpl_core.pipes.first_to_upper_pipe.FirstToUpperPipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.ip_address_pipe": [[27, 1, 1, "", "IPAddressPipe"]], "cpl_core.pipes.ip_address_pipe.IPAddressPipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.pipe_abc": [[27, 1, 1, "", "PipeABC"]], "cpl_core.pipes.pipe_abc.PipeABC": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.to_camel_case_pipe": [[27, 1, 1, "", "ToCamelCasePipe"]], "cpl_core.pipes.to_camel_case_pipe.ToCamelCasePipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.to_snake_case_pipe": [[27, 1, 1, "", "ToSnakeCasePipe"]], "cpl_core.pipes.to_snake_case_pipe.ToSnakeCasePipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.version_pipe": [[27, 1, 1, "", "VersionPipe"]], "cpl_core.pipes.version_pipe.VersionPipe": [[27, 2, 1, "", "transform"]], "cpl_core.time": [[28, 0, 0, "-", "time_format_settings"], [28, 0, 0, "-", "time_format_settings_names_enum"]], "cpl_core.time.time_format_settings": [[28, 1, 1, "", "TimeFormatSettings"]], "cpl_core.time.time_format_settings.TimeFormatSettings": [[28, 3, 1, "", "date_format"], [28, 3, 1, "", "date_time_format"], [28, 3, 1, "", "date_time_log_format"], [28, 2, 1, "", "from_dict"], [28, 3, 1, "", "time_format"]], "cpl_core.time.time_format_settings_names_enum": [[28, 1, 1, "", "TimeFormatSettingsNamesEnum"]], "cpl_core.time.time_format_settings_names_enum.TimeFormatSettingsNamesEnum": [[28, 4, 1, "", "date_format"], [28, 4, 1, "", "date_time_format"], [28, 4, 1, "", "date_time_log_format"], [28, 4, 1, "", "time_format"]], "cpl_core.utils": [[29, 0, 0, "-", "credential_manager"], [29, 0, 0, "-", "pip"], [29, 0, 0, "-", "string"]], "cpl_core.utils.credential_manager": [[29, 1, 1, "", "CredentialManager"]], "cpl_core.utils.credential_manager.CredentialManager": [[29, 2, 1, "", "build_string"], [29, 2, 1, "", "decrypt"], [29, 2, 1, "", "encrypt"]], "cpl_core.utils.pip": [[29, 1, 1, "", "Pip"]], "cpl_core.utils.pip.Pip": [[29, 2, 1, "", "get_executable"], [29, 2, 1, "", "get_outdated"], [29, 2, 1, "", "get_package"], [29, 2, 1, "", "install"], [29, 2, 1, "", "reset_executable"], [29, 2, 1, "", "set_executable"], [29, 2, 1, "", "uninstall"]], "cpl_core.utils.string": [[29, 1, 1, "", "String"]], "cpl_core.utils.string.String": [[29, 2, 1, "", "convert_to_camel_case"], [29, 2, 1, "", "convert_to_snake_case"], [29, 2, 1, "", "first_to_lower"], [29, 2, 1, "", "first_to_upper"], [29, 2, 1, "", "random_string"]], "cpl_discord.application": [[31, 0, 0, "-", "discord_bot_application_abc"]], "cpl_discord.application.discord_bot_application_abc": [[31, 1, 1, "", "DiscordBotApplicationABC"]], "cpl_discord.application.discord_bot_application_abc.DiscordBotApplicationABC": [[31, 2, 1, "", "stop_async"]], "cpl_discord.command": [[32, 0, 0, "-", "discord_command_abc"], [32, 0, 0, "-", "discord_commands_meta"]], "cpl_discord.command.discord_command_abc": [[32, 1, 1, "", "DiscordCommandABC"]], "cpl_discord.command.discord_commands_meta": [[32, 1, 1, "", "DiscordCogMeta"]], "cpl_discord.configuration": [[33, 0, 0, "-", "discord_bot_settings"]], "cpl_discord.configuration.discord_bot_settings": [[33, 1, 1, "", "DiscordBotSettings"]], "cpl_discord.configuration.discord_bot_settings.DiscordBotSettings": [[33, 2, 1, "", "from_dict"], [33, 3, 1, "", "prefix"], [33, 3, 1, "", "token"]], "cpl_discord.container": [[34, 0, 0, "-", "category_channel"], [34, 0, 0, "-", "container"], [34, 0, 0, "-", "guild"], [34, 0, 0, "-", "member"], [34, 0, 0, "-", "role"], [34, 0, 0, "-", "text_channel"], [34, 0, 0, "-", "thread"], [34, 0, 0, "-", "voice_channel"]], "cpl_discord.container.category_channel": [[34, 1, 1, "", "CategoryChannel"]], "cpl_discord.container.category_channel.CategoryChannel": [[34, 4, 1, "", "category_id"], [34, 4, 1, "", "guild"], [34, 4, 1, "", "id"], [34, 4, 1, "", "name"], [34, 4, 1, "", "nsfw"], [34, 4, 1, "", "position"], [34, 3, 1, "", "text_channels"], [34, 3, 1, "", "voice_channels"]], "cpl_discord.container.container": [[34, 1, 1, "", "Container"]], "cpl_discord.container.guild": [[34, 1, 1, "", "Guild"]], "cpl_discord.container.guild.Guild": [[34, 4, 1, "", "afk_channel"], [34, 4, 1, "", "afk_timeout"], [34, 4, 1, "", "approximate_member_count"], [34, 4, 1, "", "approximate_presence_count"], [34, 3, 1, "", "categories"], [34, 4, 1, "", "default_notifications"], [34, 4, 1, "", "description"], [34, 4, 1, "", "emojis"], [34, 4, 1, "", "explicit_content_filter"], [34, 4, 1, "", "features"], [34, 4, 1, "", "id"], [34, 4, 1, "", "max_members"], [34, 4, 1, "", "max_presences"], [34, 4, 1, "", "max_video_channel_users"], [34, 3, 1, "", "members"], [34, 4, 1, "", "mfa_level"], [34, 4, 1, "", "name"], [34, 4, 1, "", "nsfw_level"], [34, 4, 1, "", "owner_id"], [34, 4, 1, "", "preferred_locale"], [34, 4, 1, "", "premium_progress_bar_enabled"], [34, 4, 1, "", "premium_subscription_count"], [34, 4, 1, "", "premium_tier"], [34, 3, 1, "", "roles"], [34, 4, 1, "", "stickers"], [34, 3, 1, "", "text_channels"], [34, 3, 1, "", "threads"], [34, 4, 1, "", "unavailable"], [34, 4, 1, "", "vanity_url_code"], [34, 4, 1, "", "verification_level"], [34, 3, 1, "", "voice_channels"], [34, 4, 1, "", "widget_enabled"]], "cpl_discord.container.member": [[34, 1, 1, "", "Member"]], "cpl_discord.container.member.Member": [[34, 4, 1, "", "activities"], [34, 4, 1, "", "guild"], [34, 4, 1, "", "joined_at"], [34, 4, 1, "", "nick"], [34, 4, 1, "", "pending"], [34, 4, 1, "", "premium_since"], [34, 3, 1, "", "roles"], [34, 4, 1, "", "timed_out_until"]], "cpl_discord.container.role": [[34, 1, 1, "", "Role"]], "cpl_discord.container.role.Role": [[34, 4, 1, "", "guild"], [34, 4, 1, "", "hoist"], [34, 4, 1, "", "id"], [34, 4, 1, "", "managed"], [34, 3, 1, "", "members"], [34, 4, 1, "", "mentionable"], [34, 4, 1, "", "name"], [34, 4, 1, "", "position"], [34, 4, 1, "", "tags"], [34, 4, 1, "", "unicode_emoji"]], "cpl_discord.container.text_channel": [[34, 1, 1, "", "TextChannel"]], "cpl_discord.container.text_channel.TextChannel": [[34, 4, 1, "", "category_id"], [34, 4, 1, "", "default_auto_archive_duration"], [34, 4, 1, "", "guild"], [34, 4, 1, "", "id"], [34, 4, 1, "", "last_message_id"], [34, 3, 1, "", "members"], [34, 4, 1, "", "name"], [34, 4, 1, "", "nsfw"], [34, 4, 1, "", "position"], [34, 4, 1, "", "slowmode_delay"], [34, 3, 1, "", "threads"], [34, 4, 1, "", "topic"]], "cpl_discord.container.thread": [[34, 1, 1, "", "Thread"]], "cpl_discord.container.thread.Thread": [[34, 4, 1, "", "archive_timestamp"], [34, 4, 1, "", "archived"], [34, 4, 1, "", "archiver_id"], [34, 4, 1, "", "auto_archive_duration"], [34, 4, 1, "", "guild"], [34, 4, 1, "", "id"], [34, 4, 1, "", "invitable"], [34, 4, 1, "", "last_message_id"], [34, 4, 1, "", "locked"], [34, 4, 1, "", "me"], [34, 4, 1, "", "member_count"], [34, 3, 1, "", "members"], [34, 4, 1, "", "message_count"], [34, 4, 1, "", "name"], [34, 4, 1, "", "owner_id"], [34, 4, 1, "", "parent_id"], [34, 4, 1, "", "slowmode_delay"]], "cpl_discord.container.voice_channel": [[34, 1, 1, "", "VoiceChannel"]], "cpl_discord.container.voice_channel.VoiceChannel": [[34, 3, 1, "", "members"]], "cpl_discord.events": [[35, 0, 0, "-", "on_bulk_message_delete_abc"], [35, 0, 0, "-", "on_command_abc"], [35, 0, 0, "-", "on_command_completion_abc"], [35, 0, 0, "-", "on_command_error_abc"], [35, 0, 0, "-", "on_connect_abc"], [35, 0, 0, "-", "on_disconnect_abc"], [35, 0, 0, "-", "on_error_abc"], [35, 0, 0, "-", "on_group_join_abc"], [35, 0, 0, "-", "on_group_remove_abc"], [35, 0, 0, "-", "on_guild_available_abc"], [35, 0, 0, "-", "on_guild_channel_create_abc"], [35, 0, 0, "-", "on_guild_channel_delete_abc"], [35, 0, 0, "-", "on_guild_channel_pins_update_abc"], [35, 0, 0, "-", "on_guild_channel_update_abc"], [35, 0, 0, "-", "on_guild_emojis_update_abc"], [35, 0, 0, "-", "on_guild_integrations_update_abc"], [35, 0, 0, "-", "on_guild_join_abc"], [35, 0, 0, "-", "on_guild_remove_abc"], [35, 0, 0, "-", "on_guild_role_create_abc"], [35, 0, 0, "-", "on_guild_role_delete_abc"], [35, 0, 0, "-", "on_guild_role_update_abc"], [35, 0, 0, "-", "on_guild_unavailable_abc"], [35, 0, 0, "-", "on_guild_update_abc"], [35, 0, 0, "-", "on_invite_create_abc"], [35, 0, 0, "-", "on_invite_delete_abc"], [35, 0, 0, "-", "on_member_ban_abc"], [35, 0, 0, "-", "on_member_join_abc"], [35, 0, 0, "-", "on_member_remove_abc"], [35, 0, 0, "-", "on_member_unban_abc"], [35, 0, 0, "-", "on_member_update_abc"], [35, 0, 0, "-", "on_message_abc"], [35, 0, 0, "-", "on_message_delete_abc"], [35, 0, 0, "-", "on_message_edit_abc"], [35, 0, 0, "-", "on_private_channel_create_abc"], [35, 0, 0, "-", "on_private_channel_delete_abc"], [35, 0, 0, "-", "on_private_channel_pins_update_abc"], [35, 0, 0, "-", "on_private_channel_update_abc"], [35, 0, 0, "-", "on_raw_reaction_add_abc"], [35, 0, 0, "-", "on_raw_reaction_clear_abc"], [35, 0, 0, "-", "on_raw_reaction_clear_emoji_abc"], [35, 0, 0, "-", "on_raw_reaction_remove_abc"], [35, 0, 0, "-", "on_reaction_add_abc"], [35, 0, 0, "-", "on_reaction_clear_abc"], [35, 0, 0, "-", "on_reaction_clear_emoji_abc"], [35, 0, 0, "-", "on_reaction_remove_abc"], [35, 0, 0, "-", "on_ready_abc"], [35, 0, 0, "-", "on_resume_abc"], [35, 0, 0, "-", "on_typing_abc"], [35, 0, 0, "-", "on_user_update_abc"], [35, 0, 0, "-", "on_voice_state_update_abc"], [35, 0, 0, "-", "on_webhooks_update_abc"]], "cpl_discord.events.on_bulk_message_delete_abc": [[35, 1, 1, "", "OnBulkMessageDeleteABC"]], "cpl_discord.events.on_bulk_message_delete_abc.OnBulkMessageDeleteABC": [[35, 2, 1, "", "on_bulk_message_delete"]], "cpl_discord.events.on_command_abc": [[35, 1, 1, "", "OnCommandABC"]], "cpl_discord.events.on_command_abc.OnCommandABC": [[35, 2, 1, "", "on_command"]], "cpl_discord.events.on_command_completion_abc": [[35, 1, 1, "", "OnCommandCompletionABC"]], "cpl_discord.events.on_command_completion_abc.OnCommandCompletionABC": [[35, 2, 1, "", "on_command_completion"]], "cpl_discord.events.on_command_error_abc": [[35, 1, 1, "", "OnCommandErrorABC"]], "cpl_discord.events.on_command_error_abc.OnCommandErrorABC": [[35, 2, 1, "", "on_command_error"]], "cpl_discord.events.on_connect_abc": [[35, 1, 1, "", "OnConnectABC"]], "cpl_discord.events.on_connect_abc.OnConnectABC": [[35, 2, 1, "", "on_connect"]], "cpl_discord.events.on_disconnect_abc": [[35, 1, 1, "", "OnDisconnectABC"]], "cpl_discord.events.on_disconnect_abc.OnDisconnectABC": [[35, 2, 1, "", "on_disconnect"]], "cpl_discord.events.on_error_abc": [[35, 1, 1, "", "OnErrorABC"]], "cpl_discord.events.on_error_abc.OnErrorABC": [[35, 2, 1, "", "on_error"]], "cpl_discord.events.on_group_join_abc": [[35, 1, 1, "", "OnGroupJoinABC"]], "cpl_discord.events.on_group_join_abc.OnGroupJoinABC": [[35, 2, 1, "", "on_group_join"]], "cpl_discord.events.on_group_remove_abc": [[35, 1, 1, "", "OnGroupRemoveABC"]], "cpl_discord.events.on_group_remove_abc.OnGroupRemoveABC": [[35, 2, 1, "", "on_group_remove"]], "cpl_discord.events.on_guild_available_abc": [[35, 1, 1, "", "OnGuildAvailableABC"]], "cpl_discord.events.on_guild_available_abc.OnGuildAvailableABC": [[35, 2, 1, "", "on_guild_available"]], "cpl_discord.events.on_guild_channel_create_abc": [[35, 1, 1, "", "OnGuildChannelCreateABC"]], "cpl_discord.events.on_guild_channel_create_abc.OnGuildChannelCreateABC": [[35, 2, 1, "", "on_guild_channel_create"]], "cpl_discord.events.on_guild_channel_delete_abc": [[35, 1, 1, "", "OnGuildChannelDeleteABC"]], "cpl_discord.events.on_guild_channel_delete_abc.OnGuildChannelDeleteABC": [[35, 2, 1, "", "on_guild_channel_delete"]], "cpl_discord.events.on_guild_channel_pins_update_abc": [[35, 1, 1, "", "OnGuildChannelPinsUpdateABC"]], "cpl_discord.events.on_guild_channel_pins_update_abc.OnGuildChannelPinsUpdateABC": [[35, 2, 1, "", "on_guild_channel_pins_update"]], "cpl_discord.events.on_guild_channel_update_abc": [[35, 1, 1, "", "OnGuildChannelUpdateABC"]], "cpl_discord.events.on_guild_channel_update_abc.OnGuildChannelUpdateABC": [[35, 2, 1, "", "on_guild_channel_update"]], "cpl_discord.events.on_guild_emojis_update_abc": [[35, 1, 1, "", "OnGuildEmojisUpdateABC"]], "cpl_discord.events.on_guild_emojis_update_abc.OnGuildEmojisUpdateABC": [[35, 2, 1, "", "on_guild_emojis_update"]], "cpl_discord.events.on_guild_integrations_update_abc": [[35, 1, 1, "", "OnGuildIntegrationsUpdateABC"]], "cpl_discord.events.on_guild_integrations_update_abc.OnGuildIntegrationsUpdateABC": [[35, 2, 1, "", "on_guild_integrations_update"]], "cpl_discord.events.on_guild_join_abc": [[35, 1, 1, "", "OnGuildJoinABC"]], "cpl_discord.events.on_guild_join_abc.OnGuildJoinABC": [[35, 2, 1, "", "on_guild_join"]], "cpl_discord.events.on_guild_remove_abc": [[35, 1, 1, "", "OnGuildRemoveABC"]], "cpl_discord.events.on_guild_remove_abc.OnGuildRemoveABC": [[35, 2, 1, "", "on_guild_remove"]], "cpl_discord.events.on_guild_role_create_abc": [[35, 1, 1, "", "OnGuildRoleCreateABC"]], "cpl_discord.events.on_guild_role_create_abc.OnGuildRoleCreateABC": [[35, 2, 1, "", "on_guild_role_create"]], "cpl_discord.events.on_guild_role_delete_abc": [[35, 1, 1, "", "OnGuildRoleDeleteABC"]], "cpl_discord.events.on_guild_role_delete_abc.OnGuildRoleDeleteABC": [[35, 2, 1, "", "on_guild_role_delete"]], "cpl_discord.events.on_guild_role_update_abc": [[35, 1, 1, "", "OnGuildRoleUpdateABC"]], "cpl_discord.events.on_guild_role_update_abc.OnGuildRoleUpdateABC": [[35, 2, 1, "", "on_guild_role_update"]], "cpl_discord.events.on_guild_unavailable_abc": [[35, 1, 1, "", "OnGuildUnavailableABC"]], "cpl_discord.events.on_guild_unavailable_abc.OnGuildUnavailableABC": [[35, 2, 1, "", "on_guild_unavailable"]], "cpl_discord.events.on_guild_update_abc": [[35, 1, 1, "", "OnGuildUpdateABC"]], "cpl_discord.events.on_guild_update_abc.OnGuildUpdateABC": [[35, 2, 1, "", "on_guild_update"]], "cpl_discord.events.on_invite_create_abc": [[35, 1, 1, "", "OnInviteCreateABC"]], "cpl_discord.events.on_invite_create_abc.OnInviteCreateABC": [[35, 2, 1, "", "on_invite_create"]], "cpl_discord.events.on_invite_delete_abc": [[35, 1, 1, "", "OnInviteDeleteABC"]], "cpl_discord.events.on_invite_delete_abc.OnInviteDeleteABC": [[35, 2, 1, "", "on_invite_delete"]], "cpl_discord.events.on_member_ban_abc": [[35, 1, 1, "", "OnMemberBanABC"]], "cpl_discord.events.on_member_ban_abc.OnMemberBanABC": [[35, 2, 1, "", "on_member_ban"]], "cpl_discord.events.on_member_join_abc": [[35, 1, 1, "", "OnMemberJoinABC"]], "cpl_discord.events.on_member_join_abc.OnMemberJoinABC": [[35, 2, 1, "", "on_member_join"]], "cpl_discord.events.on_member_remove_abc": [[35, 1, 1, "", "OnMemberRemoveABC"]], "cpl_discord.events.on_member_remove_abc.OnMemberRemoveABC": [[35, 2, 1, "", "on_member_remove"]], "cpl_discord.events.on_member_unban_abc": [[35, 1, 1, "", "OnMemberUnbanABC"]], "cpl_discord.events.on_member_unban_abc.OnMemberUnbanABC": [[35, 2, 1, "", "on_member_unban"]], "cpl_discord.events.on_member_update_abc": [[35, 1, 1, "", "OnMemberUpdateABC"]], "cpl_discord.events.on_member_update_abc.OnMemberUpdateABC": [[35, 2, 1, "", "on_member_update"]], "cpl_discord.events.on_message_abc": [[35, 1, 1, "", "OnMessageABC"]], "cpl_discord.events.on_message_abc.OnMessageABC": [[35, 2, 1, "", "on_message"]], "cpl_discord.events.on_message_delete_abc": [[35, 1, 1, "", "OnMessageDeleteABC"]], "cpl_discord.events.on_message_delete_abc.OnMessageDeleteABC": [[35, 2, 1, "", "on_message_delete"]], "cpl_discord.events.on_message_edit_abc": [[35, 1, 1, "", "OnMessageEditABC"]], "cpl_discord.events.on_message_edit_abc.OnMessageEditABC": [[35, 2, 1, "", "on_message_edit"]], "cpl_discord.events.on_private_channel_create_abc": [[35, 1, 1, "", "OnPrivateChannelCreateABC"]], "cpl_discord.events.on_private_channel_create_abc.OnPrivateChannelCreateABC": [[35, 2, 1, "", "on_private_channel_create"]], "cpl_discord.events.on_private_channel_delete_abc": [[35, 1, 1, "", "OnPrivateChannelDeleteABC"]], "cpl_discord.events.on_private_channel_delete_abc.OnPrivateChannelDeleteABC": [[35, 2, 1, "", "on_private_channel_delete"]], "cpl_discord.events.on_private_channel_pins_update_abc": [[35, 1, 1, "", "OnPrivateChannelPinsUpdateABC"]], "cpl_discord.events.on_private_channel_pins_update_abc.OnPrivateChannelPinsUpdateABC": [[35, 2, 1, "", "on_private_channel_pins_update"]], "cpl_discord.events.on_private_channel_update_abc": [[35, 1, 1, "", "OnPrivateChannelUpdateABC"]], "cpl_discord.events.on_private_channel_update_abc.OnPrivateChannelUpdateABC": [[35, 2, 1, "", "on_private_channel_update"]], "cpl_discord.events.on_raw_reaction_add_abc": [[35, 1, 1, "", "OnRawReactionAddABC"]], "cpl_discord.events.on_raw_reaction_add_abc.OnRawReactionAddABC": [[35, 2, 1, "", "on_raw_reaction_add"]], "cpl_discord.events.on_raw_reaction_clear_abc": [[35, 1, 1, "", "OnRawReactionClearABC"]], "cpl_discord.events.on_raw_reaction_clear_abc.OnRawReactionClearABC": [[35, 2, 1, "", "on_raw_reaction_clear"]], "cpl_discord.events.on_raw_reaction_clear_emoji_abc": [[35, 1, 1, "", "OnRawReactionClearEmojiABC"]], "cpl_discord.events.on_raw_reaction_clear_emoji_abc.OnRawReactionClearEmojiABC": [[35, 2, 1, "", "on_raw_reaction_clear_emoji"]], "cpl_discord.events.on_raw_reaction_remove_abc": [[35, 1, 1, "", "OnRawReactionRemoveABC"]], "cpl_discord.events.on_raw_reaction_remove_abc.OnRawReactionRemoveABC": [[35, 2, 1, "", "on_raw_reaction_remove"]], "cpl_discord.events.on_reaction_add_abc": [[35, 1, 1, "", "OnReactionAddABC"]], "cpl_discord.events.on_reaction_add_abc.OnReactionAddABC": [[35, 2, 1, "", "on_reaction_add"]], "cpl_discord.events.on_reaction_clear_abc": [[35, 1, 1, "", "OnReactionClearABC"]], "cpl_discord.events.on_reaction_clear_abc.OnReactionClearABC": [[35, 2, 1, "", "on_reaction_clear"]], "cpl_discord.events.on_reaction_clear_emoji_abc": [[35, 1, 1, "", "OnReactionClearEmojiABC"]], "cpl_discord.events.on_reaction_clear_emoji_abc.OnReactionClearEmojiABC": [[35, 2, 1, "", "on_reaction_clear_emoji"]], "cpl_discord.events.on_reaction_remove_abc": [[35, 1, 1, "", "OnReactionRemoveABC"]], "cpl_discord.events.on_reaction_remove_abc.OnReactionRemoveABC": [[35, 2, 1, "", "on_reaction_remove"]], "cpl_discord.events.on_ready_abc": [[35, 1, 1, "", "OnReadyABC"]], "cpl_discord.events.on_ready_abc.OnReadyABC": [[35, 2, 1, "", "on_ready"]], "cpl_discord.events.on_resume_abc": [[35, 1, 1, "", "OnResumeABC"]], "cpl_discord.events.on_resume_abc.OnResumeABC": [[35, 2, 1, "", "on_resume"]], "cpl_discord.events.on_typing_abc": [[35, 1, 1, "", "OnTypingABC"]], "cpl_discord.events.on_typing_abc.OnTypingABC": [[35, 2, 1, "", "on_typing"]], "cpl_discord.events.on_user_update_abc": [[35, 1, 1, "", "OnUserUpdateABC"]], "cpl_discord.events.on_user_update_abc.OnUserUpdateABC": [[35, 2, 1, "", "on_user_update"]], "cpl_discord.events.on_voice_state_update_abc": [[35, 1, 1, "", "OnVoiceStateUpdateABC"]], "cpl_discord.events.on_voice_state_update_abc.OnVoiceStateUpdateABC": [[35, 2, 1, "", "on_voice_state_update"]], "cpl_discord.events.on_webhooks_update_abc": [[35, 1, 1, "", "OnWebhooksUpdateABC"]], "cpl_discord.events.on_webhooks_update_abc.OnWebhooksUpdateABC": [[35, 2, 1, "", "on_webhooks_update"]], "cpl_discord.helper": [[36, 0, 0, "-", "to_containers_converter"]], "cpl_discord.helper.to_containers_converter": [[36, 1, 1, "", "ToContainersConverter"]], "cpl_discord.helper.to_containers_converter.ToContainersConverter": [[36, 2, 1, "", "convert"]], "cpl_discord.service": [[37, 0, 0, "-", "command_error_handler_service"], [37, 0, 0, "-", "discord_bot_service"], [37, 0, 0, "-", "discord_bot_service_abc"], [37, 0, 0, "-", "discord_collection"], [37, 0, 0, "-", "discord_collection_abc"], [37, 0, 0, "-", "discord_service"], [37, 0, 0, "-", "discord_service_abc"]], "cpl_discord.service.command_error_handler_service": [[37, 1, 1, "", "CommandErrorHandlerService"]], "cpl_discord.service.command_error_handler_service.CommandErrorHandlerService": [[37, 2, 1, "", "on_command_error"]], "cpl_discord.service.discord_bot_service": [[37, 1, 1, "", "DiscordBotService"]], "cpl_discord.service.discord_bot_service.DiscordBotService": [[37, 3, 1, "", "guilds"], [37, 2, 1, "", "on_ready"], [37, 2, 1, "", "start_async"], [37, 2, 1, "", "stop_async"]], "cpl_discord.service.discord_bot_service_abc": [[37, 1, 1, "", "DiscordBotServiceABC"]], "cpl_discord.service.discord_bot_service_abc.DiscordBotServiceABC": [[37, 3, 1, "", "guilds"], [37, 2, 1, "", "on_ready"], [37, 2, 1, "", "start_async"], [37, 2, 1, "", "stop_async"]], "cpl_discord.service.discord_collection": [[37, 1, 1, "", "DiscordCollection"]], "cpl_discord.service.discord_collection.DiscordCollection": [[37, 2, 1, "", "add_command"], [37, 2, 1, "", "add_event"], [37, 2, 1, "", "get_commands"], [37, 2, 1, "", "get_events_by_base"]], "cpl_discord.service.discord_collection_abc": [[37, 1, 1, "", "DiscordCollectionABC"]], "cpl_discord.service.discord_collection_abc.DiscordCollectionABC": [[37, 2, 1, "", "add_command"], [37, 2, 1, "", "add_event"], [37, 2, 1, "", "get_commands"], [37, 2, 1, "", "get_events_by_base"]], "cpl_discord.service.discord_service": [[37, 1, 1, "", "DiscordService"]], "cpl_discord.service.discord_service.DiscordService": [[37, 2, 1, "", "init"], [37, 2, 1, "", "on_bulk_message_delete"], [37, 2, 1, "", "on_command"], [37, 2, 1, "", "on_command_completion"], [37, 2, 1, "", "on_command_error"], [37, 2, 1, "", "on_connect"], [37, 2, 1, "", "on_disconnect"], [37, 2, 1, "", "on_error"], [37, 2, 1, "", "on_group_join"], [37, 2, 1, "", "on_group_remove"], [37, 2, 1, "", "on_guild_available"], [37, 2, 1, "", "on_guild_channel_create"], [37, 2, 1, "", "on_guild_channel_delete"], [37, 2, 1, "", "on_guild_channel_pins_update"], [37, 2, 1, "", "on_guild_channel_update"], [37, 2, 1, "", "on_guild_emojis_update"], [37, 2, 1, "", "on_guild_integrations_update"], [37, 2, 1, "", "on_guild_join"], [37, 2, 1, "", "on_guild_remove"], [37, 2, 1, "", "on_guild_role_create"], [37, 2, 1, "", "on_guild_role_delete"], [37, 2, 1, "", "on_guild_role_update"], [37, 2, 1, "", "on_guild_unavailable"], [37, 2, 1, "", "on_guild_update"], [37, 2, 1, "", "on_invite_create"], [37, 2, 1, "", "on_invite_delete"], [37, 2, 1, "", "on_member_ban"], [37, 2, 1, "", "on_member_join"], [37, 2, 1, "", "on_member_remove"], [37, 2, 1, "", "on_member_unban"], [37, 2, 1, "", "on_member_update"], [37, 2, 1, "", "on_message"], [37, 2, 1, "", "on_message_delete"], [37, 2, 1, "", "on_message_edit"], [37, 2, 1, "", "on_private_channel_create"], [37, 2, 1, "", "on_private_channel_delete"], [37, 2, 1, "", "on_private_channel_pins_update"], [37, 2, 1, "", "on_private_channel_update"], [37, 2, 1, "", "on_raw_reaction_add"], [37, 2, 1, "", "on_raw_reaction_clear"], [37, 2, 1, "", "on_raw_reaction_clear_emoji"], [37, 2, 1, "", "on_raw_reaction_remove"], [37, 2, 1, "", "on_reaction_add"], [37, 2, 1, "", "on_reaction_clear"], [37, 2, 1, "", "on_reaction_clear_emoji"], [37, 2, 1, "", "on_reaction_remove"], [37, 2, 1, "", "on_ready"], [37, 2, 1, "", "on_resume"], [37, 2, 1, "", "on_typing"], [37, 2, 1, "", "on_user_update"], [37, 2, 1, "", "on_voice_state_update"], [37, 2, 1, "", "on_webhooks_update"]], "cpl_discord.service.discord_service_abc": [[37, 1, 1, "", "DiscordServiceABC"]], "cpl_discord.service.discord_service_abc.DiscordServiceABC": [[37, 2, 1, "", "init"], [37, 2, 1, "", "on_bulk_message_delete"], [37, 2, 1, "", "on_command"], [37, 2, 1, "", "on_command_completion"], [37, 2, 1, "", "on_command_error"], [37, 2, 1, "", "on_connect"], [37, 2, 1, "", "on_disconnect"], [37, 2, 1, "", "on_error"], [37, 2, 1, "", "on_group_join"], [37, 2, 1, "", "on_group_remove"], [37, 2, 1, "", "on_guild_available"], [37, 2, 1, "", "on_guild_channel_create"], [37, 2, 1, "", "on_guild_channel_delete"], [37, 2, 1, "", "on_guild_channel_pins_update"], [37, 2, 1, "", "on_guild_channel_update"], [37, 2, 1, "", "on_guild_emojis_update"], [37, 2, 1, "", "on_guild_integrations_update"], [37, 2, 1, "", "on_guild_join"], [37, 2, 1, "", "on_guild_remove"], [37, 2, 1, "", "on_guild_role_create"], [37, 2, 1, "", "on_guild_role_delete"], [37, 2, 1, "", "on_guild_role_update"], [37, 2, 1, "", "on_guild_unavailable"], [37, 2, 1, "", "on_guild_update"], [37, 2, 1, "", "on_invite_create"], [37, 2, 1, "", "on_invite_delete"], [37, 2, 1, "", "on_member_ban"], [37, 2, 1, "", "on_member_join"], [37, 2, 1, "", "on_member_remove"], [37, 2, 1, "", "on_member_unban"], [37, 2, 1, "", "on_member_update"], [37, 2, 1, "", "on_message"], [37, 2, 1, "", "on_message_delete"], [37, 2, 1, "", "on_message_edit"], [37, 2, 1, "", "on_private_channel_create"], [37, 2, 1, "", "on_private_channel_delete"], [37, 2, 1, "", "on_private_channel_pins_update"], [37, 2, 1, "", "on_private_channel_update"], [37, 2, 1, "", "on_reaction_add"], [37, 2, 1, "", "on_reaction_clear"], [37, 2, 1, "", "on_reaction_clear_emoji"], [37, 2, 1, "", "on_reaction_remove"], [37, 2, 1, "", "on_ready"], [37, 2, 1, "", "on_resume"], [37, 2, 1, "", "on_typing"], [37, 2, 1, "", "on_user_update"], [37, 2, 1, "", "on_voice_state_update"], [37, 2, 1, "", "on_webhooks_update"]], "cpl_query.base": [[39, 0, 0, "-", "default_lambda"], [39, 0, 0, "-", "ordered_queryable"], [39, 0, 0, "-", "ordered_queryable_abc"], [39, 0, 0, "-", "queryable_abc"], [39, 0, 0, "-", "sequence_abc"], [39, 0, 0, "-", "sequence_values"]], "cpl_query.base.default_lambda": [[39, 5, 1, "", "default_lambda"]], "cpl_query.base.ordered_queryable": [[39, 1, 1, "", "OrderedQueryable"]], "cpl_query.base.ordered_queryable.OrderedQueryable": [[39, 2, 1, "", "then_by"], [39, 2, 1, "", "then_by_descending"]], "cpl_query.base.ordered_queryable_abc": [[39, 1, 1, "", "OrderedQueryableABC"]], "cpl_query.base.ordered_queryable_abc.OrderedQueryableABC": [[39, 2, 1, "", "then_by"], [39, 2, 1, "", "then_by_descending"]], "cpl_query.base.queryable_abc": [[39, 1, 1, "", "QueryableABC"]], "cpl_query.base.queryable_abc.QueryableABC": [[39, 2, 1, "", "all"], [39, 2, 1, "", "any"], [39, 2, 1, "", "average"], [39, 2, 1, "", "contains"], [39, 2, 1, "", "count"], [39, 2, 1, "", "distinct"], [39, 2, 1, "", "element_at"], [39, 2, 1, "", "element_at_or_default"], [39, 2, 1, "", "first"], [39, 2, 1, "", "first_or_default"], [39, 2, 1, "", "for_each"], [39, 2, 1, "", "group_by"], [39, 2, 1, "", "last"], [39, 2, 1, "", "last_or_default"], [39, 2, 1, "", "max"], [39, 2, 1, "", "median"], [39, 2, 1, "", "min"], [39, 2, 1, "", "order_by"], [39, 2, 1, "", "order_by_descending"], [39, 2, 1, "", "reverse"], [39, 2, 1, "", "select"], [39, 2, 1, "", "select_many"], [39, 2, 1, "", "single"], [39, 2, 1, "", "single_or_default"], [39, 2, 1, "", "skip"], [39, 2, 1, "", "skip_last"], [39, 2, 1, "", "sum"], [39, 2, 1, "", "take"], [39, 2, 1, "", "take_last"], [39, 2, 1, "", "where"]], "cpl_query.base.sequence_abc": [[39, 1, 1, "", "SequenceABC"]], "cpl_query.base.sequence_abc.SequenceABC": [[39, 2, 1, "", "copy"], [39, 2, 1, "", "empty"], [39, 2, 1, "", "index"], [39, 2, 1, "", "next"], [39, 2, 1, "", "range"], [39, 2, 1, "", "to_list"], [39, 3, 1, "", "type"]], "cpl_query.base.sequence_values": [[39, 1, 1, "", "SequenceValues"]], "cpl_query.base.sequence_values.SequenceValues": [[39, 2, 1, "", "next"], [39, 2, 1, "", "reset"]], "cpl_query.enumerable": [[40, 0, 0, "-", "enumerable"], [40, 0, 0, "-", "enumerable_abc"]], "cpl_query.enumerable.enumerable": [[40, 1, 1, "", "Enumerable"]], "cpl_query.enumerable.enumerable_abc": [[40, 1, 1, "", "EnumerableABC"]], "cpl_query.enumerable.enumerable_abc.EnumerableABC": [[40, 2, 1, "", "set_remove_error_check"], [40, 2, 1, "", "to_iterable"]], "cpl_query.extension": [[41, 0, 0, "-", "list"]], "cpl_query.extension.list": [[41, 1, 1, "", "List"]], "cpl_query.extension.list.List": [[41, 2, 1, "", "to_enumerable"], [41, 2, 1, "", "to_iterable"]], "cpl_query.iterable": [[42, 0, 0, "-", "iterable"], [42, 0, 0, "-", "iterable_abc"]], "cpl_query.iterable.iterable": [[42, 1, 1, "", "Iterable"]], "cpl_query.iterable.iterable_abc": [[42, 1, 1, "", "IterableABC"]], "cpl_query.iterable.iterable_abc.IterableABC": [[42, 2, 1, "", "add"], [42, 2, 1, "", "append"], [42, 2, 1, "", "extend"], [42, 2, 1, "", "remove"], [42, 2, 1, "", "to_enumerable"], [42, 3, 1, "", "type"]], "cpl_translation": [[43, 0, 0, "-", "translate_pipe"], [43, 0, 0, "-", "translation_service"], [43, 0, 0, "-", "translation_service_abc"], [43, 0, 0, "-", "translation_settings"]], "cpl_translation.translate_pipe": [[43, 1, 1, "", "TranslatePipe"]], "cpl_translation.translate_pipe.TranslatePipe": [[43, 2, 1, "", "transform"]], "cpl_translation.translation_service": [[43, 1, 1, "", "TranslationService"]], "cpl_translation.translation_service.TranslationService": [[43, 2, 1, "", "load"], [43, 2, 1, "", "load_by_settings"], [43, 2, 1, "", "set_default_lang"], [43, 2, 1, "", "set_lang"], [43, 2, 1, "", "translate"]], "cpl_translation.translation_service_abc": [[43, 1, 1, "", "TranslationServiceABC"]], "cpl_translation.translation_service_abc.TranslationServiceABC": [[43, 2, 1, "", "load"], [43, 2, 1, "", "load_by_settings"], [43, 2, 1, "", "set_default_lang"], [43, 2, 1, "", "set_lang"], [43, 2, 1, "", "translate"]], "cpl_translation.translation_settings": [[43, 1, 1, "", "TranslationSettings"]], "cpl_translation.translation_settings.TranslationSettings": [[43, 3, 1, "", "default_language"], [43, 2, 1, "", "from_dict"], [43, 3, 1, "", "languages"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:property", "4": "py:attribute", "5": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "property", "Python property"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "function", "Python function"]}, "titleterms": {"cpl": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 45, 46, 47, 48], "add": 0, "content": [0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 48, 49], "descript": [0, 1, 2, 3, 4, 5, 7, 8, 11], "argument": [0, 2, 3, 4, 8, 11, 53], "flag": [0, 4, 5, 8, 11, 12], "build": 1, "gener": 2, "schemat": [2, 6], "help": 3, "instal": [4, 49], "new": 5, "project": [5, 48], "type": 5, "cli": [6, 15, 49], "overview": [6, 46], "command": [6, 32], "refer": [6, 15, 16, 30, 38, 43], "tabl": [6, 48, 49], "basic": 6, "workflow": 6, "languag": 6, "syntax": 6, "rel": 6, "path": 6, "publish": 7, "remov": 8, "run": 9, "start": [10, 44, 48, 49], "uninstal": 11, "updat": 12, "version": 13, "contribut": 14, "found": 14, "bug": 14, "featur": [14, 45, 46], "request": 14, "submiss": 14, "guidelin": 14, "submit": 14, "an": 14, "issu": 14, "pull": 14, "review": 14, "address": 14, "feedback": 14, "code": 14, "rule": 14, "licens": 14, "api": 16, "cpl_core": [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 52], "applic": [17, 31, 55], "application_abc": 17, "application_build": 17, "application_builder_abc": 17, "startup_abc": 17, "configur": [18, 33], "configuration_abc": 18, "configuration_model_abc": 18, "configuration_variable_name_enum": 18, "console_argu": 18, "consol": [19, 49, 52, 53], "background_color_enum": 19, "console_cal": 19, "foreground_color_enum": 19, "spinner_thread": 19, "databas": [20, 21, 22], "database_model": 20, "database_set": 20, "database_settings_name_enum": 20, "connect": 21, "database_connect": 21, "database_connection_abc": 21, "context": 22, "database_context": 22, "database_context_abc": 22, "dependency_inject": 23, "service_collect": 23, "service_collection_abc": 23, "service_descriptor": 23, "service_lifetime_enum": 23, "service_provid": 23, "service_provider_abc": 23, "environ": [24, 49], "application_environ": 24, "application_environment_abc": 24, "environment_name_enum": 24, "log": 25, "logger_abc": 25, "logger_servic": 25, "logging_level_enum": 25, "logging_set": 25, "logging_settings_name_enum": 25, "mail": [26, 58], "email": 26, "email_client_abc": 26, "email_client_servic": 26, "email_client_set": 26, "email_client_settings_name_enum": 26, "pipe": 27, "bool_pip": 27, "first_char_to_lower_pip": 27, "first_to_upper_pip": 27, "ip_address_pip": 27, "pipe_abc": 27, "to_camel_case_pip": 27, "to_snake_case_pip": 27, "version_pip": 27, "time": 28, "time_format_set": 28, "time_format_settings_names_enum": 28, "util": 29, "credential_manag": 29, "pip": 29, "string": 29, "discord": 30, "cpl_discord": [31, 32, 33, 34, 35, 36, 37], "discord_bot_application_abc": 31, "discord_command_abc": 32, "discord_commands_meta": 32, "discord_bot_set": 33, "contain": 34, "category_channel": 34, "guild": 34, "member": 34, "role": 34, "text_channel": 34, "thread": 34, "voice_channel": 34, "event": 35, "on_bulk_message_delete_abc": 35, "on_command_abc": 35, "on_command_completion_abc": 35, "on_command_error_abc": 35, "on_connect_abc": 35, "on_disconnect_abc": 35, "on_error_abc": 35, "on_group_join_abc": 35, "on_group_remove_abc": 35, "on_guild_available_abc": 35, "on_guild_channel_create_abc": 35, "on_guild_channel_delete_abc": 35, "on_guild_channel_pins_update_abc": 35, "on_guild_channel_update_abc": 35, "on_guild_emojis_update_abc": 35, "on_guild_integrations_update_abc": 35, "on_guild_join_abc": 35, "on_guild_remove_abc": 35, "on_guild_role_create_abc": 35, "on_guild_role_delete_abc": 35, "on_guild_role_update_abc": 35, "on_guild_unavailable_abc": 35, "on_guild_update_abc": 35, "on_invite_create_abc": 35, "on_invite_delete_abc": 35, "on_member_ban_abc": 35, "on_member_join_abc": 35, "on_member_remove_abc": 35, "on_member_unban_abc": 35, "on_member_update_abc": 35, "on_message_abc": 35, "on_message_delete_abc": 35, "on_message_edit_abc": 35, "on_private_channel_create_abc": 35, "on_private_channel_delete_abc": 35, "on_private_channel_pins_update_abc": 35, "on_private_channel_update_abc": 35, "on_raw_reaction_add_abc": 35, "on_raw_reaction_clear_abc": 35, "on_raw_reaction_clear_emoji_abc": 35, "on_raw_reaction_remove_abc": 35, "on_reaction_add_abc": 35, "on_reaction_clear_abc": 35, "on_reaction_clear_emoji_abc": 35, "on_reaction_remove_abc": 35, "on_ready_abc": 35, "on_resume_abc": 35, "on_typing_abc": 35, "on_user_update_abc": 35, "on_voice_state_update_abc": 35, "on_webhooks_update_abc": 35, "helper": 36, "to_containers_convert": 36, "servic": 37, "command_error_handler_servic": 37, "discord_bot_servic": 37, "discord_bot_service_abc": 37, "discord_collect": 37, "discord_collection_abc": 37, "discord_servic": 37, "discord_service_abc": 37, "queri": [38, 49], "cpl_queri": [39, 40, 41, 42], "base": 39, "default_lambda": 39, "ordered_query": 39, "ordered_queryable_abc": 39, "queryable_abc": 39, "sequence_abc": 39, "sequence_valu": 39, "enumer": 40, "enumerable_abc": 40, "extens": 41, "list": 41, "iter": 42, "iterable_abc": 42, "translat": 43, "cpl_translat": 43, "translate_pip": 43, "translation_servic": 43, "translation_service_abc": 43, "translation_set": 43, "get": [44, 48], "introduct": [45, 46], "doc": [45, 46], "manual": 45, "explor": 46, "prerequisit": [48, 49], "creat": [48, 49, 54], "menu": 48, "what": [48, 49], "s": [48, 49], "next": [48, 49], "set": 49, "up": 49, "local": 49, "workspac": 49, "packag": 49, "initi": 49, "app": 49, "librari": 49, "tutori": 50, "us": [51, 52, 57], "appset": 51, "json": 51, "com": [51, 52, 53, 54, 55, 56, 57, 58], "soon": [51, 52, 53, 54, 55, 56, 57, 58], "handl": 53, "startup": [54, 56], "class": 54, "extend": [55, 56], "builtin": 57, "logger": 57, "send": 58}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 56}}) \ No newline at end of file +Search.setIndex({"docnames": ["cli.add", "cli.build", "cli.generate", "cli.help", "cli.install", "cli.new", "cli.overview", "cli.publish", "cli.remove", "cli.run", "cli.start", "cli.uninstall", "cli.update", "cli.version", "contributing", "cpl_cli", "cpl_core", "cpl_core.application", "cpl_core.configuration", "cpl_core.console", "cpl_core.database", "cpl_core.database.connection", "cpl_core.database.context", "cpl_core.dependency_injection", "cpl_core.environment", "cpl_core.logging", "cpl_core.mailing", "cpl_core.pipes", "cpl_core.time", "cpl_core.utils", "cpl_discord", "cpl_discord.application", "cpl_discord.command", "cpl_discord.configuration", "cpl_discord.container", "cpl_discord.events", "cpl_discord.helper", "cpl_discord.service", "cpl_query", "cpl_query.base", "cpl_query.enumerable", "cpl_query.extension", "cpl_query.iterable", "cpl_translation", "getting_started", "index", "introduction", "modules", "quickstart", "setup", "tutorials", "tutorials.appsettings", "tutorials.console", "tutorials.console-arguments", "tutorials.create-startup", "tutorials.extend-application", "tutorials.extend-startup", "tutorials.logging", "tutorials.mail", "tutorials.templating"], "filenames": ["cli.add.md", "cli.build.md", "cli.generate.md", "cli.help.md", "cli.install.md", "cli.new.md", "cli.overview.md", "cli.publish.md", "cli.remove.md", "cli.run.md", "cli.start.md", "cli.uninstall.md", "cli.update.md", "cli.version.md", "contributing.md", "cpl_cli.rst", "cpl_core.rst", "cpl_core.application.rst", "cpl_core.configuration.rst", "cpl_core.console.rst", "cpl_core.database.rst", "cpl_core.database.connection.rst", "cpl_core.database.context.rst", "cpl_core.dependency_injection.rst", "cpl_core.environment.rst", "cpl_core.logging.rst", "cpl_core.mailing.rst", "cpl_core.pipes.rst", "cpl_core.time.rst", "cpl_core.utils.rst", "cpl_discord.rst", "cpl_discord.application.rst", "cpl_discord.command.rst", "cpl_discord.configuration.rst", "cpl_discord.container.rst", "cpl_discord.events.rst", "cpl_discord.helper.rst", "cpl_discord.service.rst", "cpl_query.rst", "cpl_query.base.rst", "cpl_query.enumerable.rst", "cpl_query.extension.rst", "cpl_query.iterable.rst", "cpl_translation.rst", "getting_started.rst", "index.rst", "introduction.md", "modules.rst", "quickstart.md", "setup.md", "tutorials.rst", "tutorials.appsettings.md", "tutorials.console.md", "tutorials.console-arguments.md", "tutorials.create-startup.md", "tutorials.extend-application.md", "tutorials.extend-startup.md", "tutorials.logging.md", "tutorials.mail.md", "tutorials.templating.md"], "titles": ["cpl add", "cpl build", "cpl generate", "cpl help", "cpl install", "cpl new", "CLI Overview and Command Reference", "cpl publish", "cpl remove", "cpl run", "cpl start", "cpl uninstall", "cpl update", "cpl version", "Contributing to CPL", "CLI reference", "API reference", "cpl_core.application", "cpl_core.configuration", "cpl_core.console", "cpl_core.database", "cpl_core.database.connection", "cpl_core.database.context", "cpl_core.dependency_injection", "cpl_core.environment", "cpl_core.logging", "cpl_core.mailing", "cpl_core.pipes", "cpl_core.time", "cpl_core.utils", "Discord reference", "cpl_discord.application", "cpl_discord.command", "cpl_discord.configuration", "cpl_discord.container", "cpl_discord.events", "cpl_discord.helper", "cpl_discord.service", "Query reference", "cpl_query.base", "cpl_query.enumerable", "cpl_query.extension", "cpl_query.iterable", "Translation reference", "Getting started", "Introduction to the CPL Docs", "Introduction to the CPL Docs", "cpl", "Getting started with CPL", "Setting up the local environment and workspace", "Tutorials", "Using appsettings.json", "Use cpl_core.console.Console", "Handle console arguments", "Create startup class", "Extend application", "Extend startup", "Use builtin logger", "Send mails", "Using cpl g & cpl n templating"], "terms": {"remov": [0, 6, 7, 15, 42, 47], "project": [0, 1, 4, 6, 7, 8, 9, 10, 11, 12, 14, 15, 44, 47, 49, 50], "from": [0, 6, 7, 8, 9, 10, 11, 13, 14, 17, 18, 19, 20, 34, 39, 42, 45, 46, 48, 59], "workspac": [0, 1, 5, 6, 8, 44, 47, 59], "sourc": [0, 1, 7, 9, 10, 14, 29, 48, 49], "target": [0, 1], "A": [0, 5, 14, 34, 59], "refer": [0, 8, 45, 46, 47], "given": [0, 1, 4, 6, 7, 11, 18, 19, 20, 23, 29, 39, 42], "If": [0, 5, 8, 14, 19, 49], "you": [0, 1, 2, 5, 6, 8, 14, 34, 45, 46, 48, 49, 59], "call": [0, 8, 17, 18, 19, 34, 39, 59], "command": [0, 1, 2, 3, 4, 5, 7, 8, 11, 12, 14, 15, 29, 30, 45, 46, 47, 49], "can": [0, 1, 2, 5, 6, 7, 8, 14, 34, 45, 49, 59], "us": [0, 1, 2, 5, 6, 7, 8, 14, 17, 19, 26, 29, 44, 45, 46, 47, 48, 49, 50], "name": [0, 1, 2, 5, 6, 7, 8, 18, 24, 25, 29, 32, 34, 49, 59], "otherwis": [0, 8, 19], "path": [0, 1, 2, 5, 7, 8, 15, 18, 24, 25, 47, 49, 59], "must": [0, 1, 6, 8, 14, 19, 59], "specifi": [0, 4, 5, 6, 8, 9, 11, 12, 18, 19], "valu": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 18, 19, 20, 23, 24, 25, 26, 27, 28, 39, 40, 41, 42, 43], "type": [0, 1, 2, 3, 4, 7, 8, 9, 10, 11, 15, 17, 18, 23, 34, 36, 37, 39, 40, 41, 42, 44, 47, 50], "which": [0, 6, 9, 18, 19, 29, 49, 59], "ha": [0, 19, 59], "ad": [0, 14], "str": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 33, 34, 35, 37, 43, 48, 59], "referenc": 0, "simul": [0, 4, 8, 11, 12], "whether": [0, 4, 5, 8, 11, 12, 18], "copi": 1, "an": [1, 6, 7, 17, 18, 19, 20, 23, 24, 25, 26, 28, 48, 49, 59], "python": [1, 14, 29, 45, 46, 48, 49], "app": [1, 6, 17, 44, 45, 46, 47, 48], "output": [1, 6, 7, 18, 19, 45, 46, 48, 49], "directori": [1, 6, 7, 24, 45, 46, 48], "execut": [1, 6, 7, 18, 29], "within": [1, 6, 14], "b": [1, 6, 14], "The": [1, 2, 4, 5, 6, 7, 8, 11, 14, 23, 26, 29, 34, 37, 45, 46, 48, 49, 59], "consol": [1, 3, 5, 6, 7, 16, 18, 25, 44, 45, 46, 47, 48, 50, 59], "librari": [1, 5, 6, 7, 44, 45, 46, 47], "all": [1, 7, 13, 14, 18, 34, 39, 59], "includ": [1, 14, 49], "file": [1, 2, 6, 7, 8, 10, 14, 18, 45, 49, 59], "run": [1, 5, 10, 17, 18, 19, 22, 29, 39, 45, 46, 48, 49], "directli": [1, 14], "prepar": [1, 6, 7, 14, 17, 45], "publish": [1, 6, 15, 45, 47, 49], "them": 1, "argument": [1, 5, 6, 7, 9, 10, 12, 15, 18, 19, 29, 39, 44, 45, 46, 47, 50], "base": [2, 5, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 36, 37, 38, 40, 41, 42, 43, 45, 46, 47, 48], "g": [2, 5, 6, 44, 47, 50], "defin": [2, 5, 6, 18, 19, 40, 42, 49, 59], "custom": [2, 5, 17, 18, 24, 45, 46], "creat": [2, 5, 6, 7, 14, 17, 18, 19, 23, 25, 26, 29, 44, 45, 46, 47, 50, 59], "templat": [2, 5, 44, 47, 50], "folder": [2, 5, 48, 59], "first": [2, 5, 6, 14, 27, 29, 34, 39, 45, 46, 59], "element": [2, 5, 19, 22, 34, 39, 42], "src": [2, 5, 48], "For": [2, 5, 14, 59], "exampl": [2, 5, 59], "c": [2, 5, 45], "test": [2, 5, 14, 24, 45, 46, 48, 59], "would": [2, 5, 14], "abc": [2, 17, 18, 21, 22, 23, 24, 25, 26, 27, 32, 35, 37, 40, 42, 43, 59], "abstract": [2, 17, 18, 21, 22, 23, 24, 25, 26, 27, 31, 35, 37, 39, 43], "class": [2, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 44, 45, 46, 47, 50, 59], "enum": [2, 18, 19, 20, 23, 24, 25, 26, 28, 59], "pipe": [2, 16, 23, 45, 46, 47], "servic": [2, 5, 17, 18, 23, 25, 26, 30, 31, 45, 46, 47, 48, 59], "set": [2, 9, 17, 18, 19, 20, 22, 23, 24, 25, 26, 28, 29, 33, 43, 44, 47, 48], "configmodel": 2, "thread": [2, 19, 30, 47], "valid": [2, 26, 48], "discord": [2, 23, 35, 37, 45, 47], "bot": [2, 37], "event": [2, 30, 37, 47], "list": [3, 6, 13, 18, 19, 22, 23, 26, 27, 29, 34, 35, 36, 37, 38, 39, 40, 42, 43, 45, 47, 59], "avail": [3, 6, 14, 59], "short": [3, 6], "h": [3, 6], "show": [3, 19], "messag": [3, 19, 25, 35, 37], "thi": [3, 14, 17, 34, 45, 46, 48, 49, 59], "packag": [4, 5, 6, 11, 13, 29, 44, 45, 46, 47, 48], "via": [4, 11, 14, 45, 46], "pip": [4, 11, 13, 16, 45, 46, 47, 48, 49], "i": [4, 6, 48], "without": [4, 6, 14, 39], "deped": 4, "your": [4, 6, 9, 10, 14, 45, 46, 49, 59], "dev": [4, 9, 10, 11], "develop": [4, 6, 11, 14, 24, 45, 46, 48, 49], "mode": [4, 11], "virtual": [4, 11], "gener": [5, 6, 7, 15, 44, 45, 47, 48, 49, 50], "initi": [5, 44, 47, 59], "add": [5, 6, 14, 15, 18, 23, 26, 42, 47, 48], "n": [5, 6, 44, 47, 48, 49, 50], "see": [5, 14, 21, 34, 48, 49], "simpl": [5, 45, 46, 49], "applic": [5, 9, 10, 16, 19, 24, 25, 26, 30, 44, 45, 46, 47, 48, 49, 50, 59], "async": [5, 17, 35, 37], "startup": [5, 17, 44, 45, 46, 47, 50, 59], "provid": [5, 14, 17, 23, 34, 45, 46, 48, 49], "noth": 5, "venv": 5, "instal": [6, 13, 15, 29, 44, 47, 48], "cpl": [6, 15, 23, 44, 49, 50], "To": [6, 9, 10, 14, 48, 49], "build": [6, 7, 9, 10, 15, 17, 29, 45, 47, 48, 49], "serv": 6, "new": [6, 14, 15, 19, 34, 44, 47, 48, 49, 50], "server": [6, 21, 26, 45, 46, 49], "go": [6, 14, 45], "parent": 6, "follow": [6, 14, 48, 49], "my": [6, 14, 49], "cd": [6, 49], "start": [6, 9, 15, 45, 46, 47, 59], "In": [6, 14, 48, 59], "termin": [6, 19, 48, 49], "commandnameoralia": 6, "requiredarg": 6, "optionalsarg": 6, "most": [6, 34, 48, 49], "some": 6, "option": [6, 9, 14, 18, 19, 20, 23, 25, 26, 29, 34, 35, 37, 39, 40, 41, 42, 45, 46, 48], "have": [6, 14, 34, 48, 49], "alias": [6, 18], "ar": [6, 7, 14, 18, 34], "shown": [6, 18, 49], "statement": [6, 22], "each": [6, 18, 39], "prefix": [6, 18, 33], "absolut": 6, "current": [6, 24, 34], "work": [6, 14, 24, 45, 46], "either": 6, "root": 6, "take": [6, 18, 39], "artifact": 6, "addit": [6, 14], "ani": [6, 18, 19, 27, 32, 37, 39, 43, 59], "its": [6, 14], "own": 6, "suppli": 6, "same": [6, 59], "format": [6, 25, 28, 39], "immedi": 6, "alia": [6, 59], "descript": [6, 9, 10, 12, 15, 34, 47], "dist": [6, 7, 9, 10], "help": [6, 14, 15, 45, 46, 47, 59], "With": 6, "depend": [6, 12, 45, 46, 48], "p": [6, 7], "setup": [6, 7, 46, 49], "py": [6, 7, 29, 45, 48, 59], "r": [6, 8, 9], "s": [6, 10, 14, 34, 44, 47], "restart": [6, 10, 49], "chang": [6, 10, 14, 22, 48], "uninstal": [6, 15, 29, 47], "ui": [6, 11, 34], "updat": [6, 14, 15, 47], "u": [6, 12], "version": [6, 15, 34, 47], "v": [6, 13], "data": [7, 19, 34, 39], "cpl_core": [7, 16, 44, 47, 48, 49, 50, 59], "json": [7, 18, 44, 45, 46, 47, 48, 49, 50, 59], "delet": 8, "onc": 9, "paramet": [9, 42], "default": [9, 19, 34, 49], "after": [9, 10, 35, 37, 39], "cli": [13, 44, 45, 46, 47, 48], "we": [14, 48, 59], "love": 14, "make": [14, 49], "even": 14, "better": 14, "than": [14, 39], "todai": 14, "As": 14, "contributor": 14, "here": [14, 49, 59], "like": [14, 45, 48, 59], "issus": 14, "find": 14, "our": 14, "gitea": 14, "repositori": 14, "fix": 14, "implement": [14, 23, 39, 40, 41], "pleas": 14, "consid": 14, "size": 14, "order": [14, 34, 39], "determin": 14, "right": 14, "step": 14, "proce": 14, "major": 14, "open": [14, 48, 49], "outlin": 14, "propos": 14, "so": [14, 49], "discuss": 14, "process": 14, "allow": 14, "coordin": [14, 19], "effort": 14, "prevent": 14, "duplic": 14, "craft": 14, "successfulli": 14, "accept": 14, "note": [14, 34], "topic": [14, 34], "document": 14, "significantli": 14, "re": 14, "write": [14, 19, 25, 45, 46], "count": [14, 39], "small": 14, "befor": [14, 19, 35, 37], "search": [14, 18, 23], "tracker": 14, "mayb": 14, "problem": 14, "alreadi": [14, 48, 49], "exist": [14, 59], "might": 14, "inform": [14, 25, 49, 59], "workaround": 14, "readili": 14, "want": [14, 48], "soon": [14, 44, 47, 50], "possibl": [14, 18], "need": [14, 34, 48, 49], "reproduc": 14, "confirm": 14, "requir": [14, 34], "minim": 14, "reproduct": 14, "scenario": 14, "give": 14, "wealth": 14, "import": [14, 48, 59], "back": [14, 19], "forth": 14, "question": 14, "quickli": 14, "point": [14, 17, 19], "out": [14, 48, 49], "well": 14, "save": [14, 18, 22], "maintain": 14, "time": [14, 16, 25, 34, 47], "ultim": 14, "abl": 14, "more": [14, 39, 49, 59], "often": 14, "themselv": 14, "while": 14, "understand": [14, 45, 46, 48, 49], "sometim": 14, "hard": 14, "extract": 14, "essenti": [14, 48], "bit": 14, "larger": 14, "codebas": 14, "realli": 14, "isol": 14, "unfortun": 14, "investig": 14, "don": [14, 48], "t": [14, 18, 39, 40, 41, 42, 48], "hear": 14, "close": [14, 19], "doesn": 14, "enough": 14, "info": [14, 25, 45, 46], "pr": 14, "relat": 14, "Be": 14, "sure": 14, "describ": 14, "design": 14, "d": 14, "upfront": 14, "ensur": 14, "readi": [14, 49], "fork": 14, "sh": [14, 49], "edraft": [14, 49], "de": [14, 49], "repo": 14, "git": 14, "branch": 14, "checkout": 14, "master": 14, "patch": 14, "appropri": [14, 59], "case": [14, 27, 29, 48], "commit": 14, "line": [14, 19, 48], "automat": 14, "rm": 14, "edit": 14, "push": 14, "origin": 14, "send": [14, 26, 44, 45, 46, 47, 50], "team": 14, "reserv": 14, "commun": 14, "member": [14, 30, 35, 37, 47], "who": 14, "haven": 14, "been": 14, "good": 14, "citizen": 14, "Such": 14, "behavior": 14, "appli": 14, "outsid": 14, "manag": [14, 34, 45, 46], "channel": [14, 34, 35, 37], "ask": 14, "fixup": 14, "head": 14, "That": 14, "thank": 14, "consist": 14, "throughout": 14, "keep": 14, "mind": 14, "one": [14, 39], "unit": 14, "public": 14, "api": [14, 45, 46, 47], "method": 14, "pep": 14, "8": 14, "style": 14, "guid": 14, "By": 14, "agre": 14, "under": [14, 34], "mit": 14, "overview": [15, 47, 49], "tabl": [15, 19, 29, 44, 45, 46, 47], "content": [15, 44, 47, 50], "basic": [15, 47, 48, 49], "workflow": [15, 47], "languag": [15, 43, 47], "syntax": [15, 47], "rel": [15, 47], "schemat": [15, 44, 47, 50], "flag": [15, 47], "application_abc": [16, 47], "application_build": [16, 47], "application_builder_abc": [16, 47], "startup_abc": [16, 47], "configur": [16, 17, 23, 30, 45, 46, 47, 59], "configuration_abc": [16, 17, 23, 47], "configuration_model_abc": [16, 47], "configuration_variable_name_enum": [16, 47], "console_argu": [16, 47], "background_color_enum": [16, 47], "console_cal": [16, 47], "foreground_color_enum": [16, 47], "spinner_thread": [16, 47], "databas": [16, 23, 47], "connect": [16, 20, 22, 26, 37, 47], "database_connect": [16, 20, 47], "database_connection_abc": [16, 20, 47], "context": [16, 20, 23, 35, 37, 47, 49], "database_context": [16, 20, 47], "database_context_abc": [16, 20, 23, 47], "database_model": [16, 47], "database_set": [16, 21, 22, 47], "database_settings_name_enum": [16, 47], "dependency_inject": [16, 17, 47, 59], "service_collect": [16, 37, 47], "service_collection_abc": [16, 17, 47], "service_descriptor": [16, 47], "service_lifetime_enum": [16, 47], "service_provid": [16, 47], "service_provider_abc": [16, 17, 47], "environ": [16, 17, 18, 25, 26, 44, 45, 46, 47, 59], "application_environ": [16, 47], "application_environment_abc": [16, 17, 25, 26, 47], "environment_name_enum": [16, 47], "log": [16, 26, 45, 46, 47], "logger_abc": [16, 26, 47], "logger_servic": [16, 47], "logging_level_enum": [16, 47], "logging_set": [16, 47], "logging_settings_name_enum": [16, 47], "mail": [16, 44, 45, 46, 47, 50], "email": [16, 47], "email_client_abc": [16, 47], "email_client_servic": [16, 47], "email_client_set": [16, 47], "email_client_settings_name_enum": [16, 47], "bool_pip": [16, 47], "first_char_to_lower_pip": [16, 47], "first_to_upper_pip": [16, 47], "ip_address_pip": [16, 47], "pipe_abc": [16, 47], "to_camel_case_pip": [16, 47], "to_snake_case_pip": [16, 47], "version_pip": [16, 47], "time_format_set": [16, 25, 47], "time_format_settings_names_enum": [16, 47], "util": [16, 45, 46, 47, 59], "credential_manag": [16, 47], "string": [16, 19, 21, 25, 26, 27, 45, 46, 47, 48, 59], "applicationabc": [17, 31], "config": [17, 23, 31, 37], "configurationabc": [17, 18, 23, 31, 37, 59], "serviceproviderabc": [17, 18, 23, 31, 59], "contain": [17, 30, 36, 39, 47], "object": [17, 18, 19, 23, 26, 29, 34, 36, 39, 42, 45, 46], "load": [17, 43], "appset": [17, 44, 47, 48, 50], "instanc": [17, 23], "main": [17, 48], "entri": [17, 19], "run_async": 17, "applicationbuild": 17, "applicationbuilderabc": 17, "build_async": 17, "use_extens": 17, "extens": [17, 38, 39, 42, 45, 46, 47], "union": [17, 18, 19, 23, 35, 36, 37, 39], "applicationextensionabc": 17, "startupextensionabc": 17, "use_startup": [17, 59], "startupabc": [17, 59], "arg": [17, 18, 19, 22, 27, 29, 32, 35, 37, 43, 59], "configure_configur": [17, 59], "env": [17, 25, 37], "applicationenvironmentabc": [17, 18, 24, 25, 26, 37], "configure_servic": [17, 59], "servicecollectionabc": [17, 23, 37, 59], "add_configur": 18, "key_typ": 18, "add_console_argu": 18, "argumentabc": 18, "known": 18, "consoleargumentabc": 18, "add_environment_vari": 18, "read": [18, 19, 48], "variabl": [18, 29], "add_json_fil": 18, "bool": [18, 19, 20, 26, 27, 34, 39, 59], "none": [18, 19, 23, 25, 26, 29, 39, 40, 41, 42, 59], "true": 18, "error": [18, 19, 25, 35, 37, 45, 46], "should": [18, 48, 49, 59], "occur": 18, "wa": [18, 49], "found": [18, 39], "place": 18, "store": 18, "properti": [18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 33, 34, 37, 42, 43], "additional_argu": 18, "argument_error_funct": 18, "callabl": [18, 19, 23, 39], "argument_abc": 18, "create_console_argu": 18, "arg_typ": 18, "argumenttypeenum": 18, "token": [18, 33], "kwarg": [18, 19, 32, 35, 37], "begin": [18, 59], "value_token": 18, "were": 18, "is_value_token_opt": 18, "runnabl": 18, "when": [18, 19, 35, 37, 39, 59], "for_each_argu": 18, "iter": [18, 38, 39, 40, 41, 47], "through": [18, 48], "function": [18, 19, 29, 39, 40, 42, 45, 48], "get_configur": 18, "search_typ": 18, "return": [18, 19, 23, 26, 34, 39, 48, 59], "configurationmodelabc": [18, 20, 25, 26, 28, 33, 43], "parse_console_argu": 18, "invalid": 18, "from_dict": [18, 20, 25, 26, 28, 33, 43], "dict": [18, 19, 20, 25, 26, 27, 28, 33, 43, 59], "convert": [18, 25, 26, 27, 28, 29, 33, 36, 40, 41, 42, 43, 45, 46], "attribut": [18, 20, 25, 26, 28, 33, 43], "configurationvariablenameenum": 18, "enumer": [18, 19, 20, 23, 24, 25, 26, 28, 38, 41, 42, 47], "static": [18, 26, 29, 36], "to_list": 18, "backgroundcolorenum": 19, "blue": 19, "on_blu": 19, "cyan": 19, "on_cyan": 19, "on_default": 19, "green": 19, "on_green": 19, "grei": 19, "on_grei": 19, "magenta": 19, "on_magenta": 19, "red": 19, "on_r": 19, "white": 19, "on_whit": 19, "yellow": 19, "on_yellow": 19, "handl": [19, 29, 44, 45, 46, 47, 50], "input": [19, 45, 46, 48], "background_color": 19, "bytes_or_buff": 19, "encod": [19, 29], "expos": 19, "buffer": [19, 20], "decod": [19, 29], "handler": 19, "result": [19, 26, 29, 39], "__str__": 19, "repr": 19, "sy": 19, "getdefaultencod": 19, "strict": 19, "classmethod": [19, 29, 59], "banner": [19, 45, 46], "print": [19, 48], "clear": 19, "color_reset": 19, "reset": [19, 29], "color": 19, "disabl": 19, "interact": 19, "enabl": [19, 48], "tb": 19, "traceback": 19, "foreground_color": 19, "read_lin": 19, "next": [19, 44, 47], "reset_cursor_posit": 19, "cursor": [19, 21, 22], "posit": [19, 34], "select": [19, 22, 39, 48], "char": [19, 27, 29], "header_foreground_color": 19, "foregroundcolorenum": 19, "header_background_color": 19, "option_foreground_color": 19, "option_background_color": 19, "cursor_foreground_color": 19, "cursor_background_color": 19, "menu": [19, 44, 45, 46, 47], "charact": 19, "header": [19, 25, 26], "foreground": 19, "background": 19, "set_background_color": 19, "set_cursor_posit": 19, "x": [19, 39], "int": [19, 20, 26, 27, 29, 34, 39, 42, 48], "y": [19, 48], "set_foreground_color": 19, "set_hold_back": 19, "spinner": [19, 45, 46], "text_foreground_color": 19, "spinner_foreground_color": 19, "text_background_color": 19, "spinner_background_color": 19, "end": [19, 25, 42], "stop": 19, "text": [19, 34], "keyword": 19, "activ": [19, 34], "last": [19, 39], "write_at": [19, 45, 46], "write_lin": [19, 45, 46, 48], "write_line_at": [19, 45, 46], "consolecal": 19, "repres": [19, 20, 24, 26], "hold": 19, "spinnerthread": 19, "msg_len": 19, "length": [19, 29, 39, 48], "exit": [19, 48], "stop_spin": 19, "databaseset": [20, 21, 22, 23], "auth_plugin": 20, "charset": 20, "host": [20, 26], "password": [20, 48], "port": [20, 26], "use_unicod": 20, "user": [20, 35, 37, 48], "databasesettingsnameenum": 20, "authplugin": 20, "useunicod": 20, "databaseconnect": 21, "databaseconnectionabc": 21, "represent": [21, 22, 23, 25, 26, 28], "connection_str": 21, "http": [21, 49], "doc": 21, "sqlalchemi": 21, "org": 21, "en": 21, "14": 21, "core": [21, 45, 49], "engin": 21, "html": 21, "mysqlcursorbuff": [21, 22], "mysqlconnectionabstract": 21, "databasecontext": 22, "databasecontextabc": [22, 23], "save_chang": 22, "tupl": [22, 34], "sql": 22, "fetch": 22, "servicecollect": 23, "collect": 23, "add_db_context": 23, "db_context_typ": 23, "db_set": 23, "db_context": 23, "add_log": 23, "intern": [23, 59], "logger": [23, 25, 26, 37, 44, 45, 46, 47, 50], "add_pip": 23, "transient": [23, 45, 46], "add_scop": 23, "service_typ": 23, "scope": [23, 45, 46], "lifetim": [23, 45, 46], "self": [23, 59], "add_singleton": 23, "singleton": [23, 45, 46], "add_transi": 23, "build_service_provid": [23, 59], "add_discord": 23, "add_transl": 23, "translat": [23, 45, 47], "servicedescriptor": 23, "servicelifetimeenum": 23, "base_typ": 23, "descriptor": 23, "1": [23, 25, 48, 59], "0": [23, 25, 34, 48, 59], "2": [23, 25, 34, 48, 59], "serviceprovid": 23, "build_servic": 23, "instance_typ": 23, "create_scop": 23, "scopeabc": 23, "get_servic": 23, "set_scop": 23, "applicationenviron": [24, 59], "environmentnameenum": 24, "product": [24, 45, 46], "application_nam": 24, "date_time_now": 24, "datetim": [24, 34, 35, 37], "end_tim": 24, "environment_nam": 24, "host_nam": 24, "runtime_directori": 24, "set_runtime_directori": 24, "runtim": [24, 45, 46], "set_working_directori": 24, "working_directori": 24, "start_tim": 24, "stage": [24, 45, 46], "loggerabc": [25, 26, 37], "debug": [25, 45, 46], "ex": 25, "except": [25, 39], "thrown": 25, "fatal": [25, 45, 46], "program": 25, "trace": [25, 45, 46], "warn": [25, 45, 46], "loggingset": [25, 37], "time_format": [25, 28], "timeformatset": [25, 28], "tree": 25, "logfil": 25, "logginglevelenum": 25, "5": [25, 48], "4": 25, "off": 25, "6": 25, "3": 25, "filenam": 25, "level": [25, 45, 46], "loggingsettingsnameenum": 25, "console_level": 25, "consoleloglevel": 25, "file_level": 25, "fileloglevel": 25, "subject": 26, "bodi": 26, "transceiv": 26, "receiv": 26, "e": [26, 59], "add_head": 26, "add_receiv": 26, "check_mail": 26, "address": 26, "check": [26, 39, 59], "get_cont": 26, "header_list": 26, "receiver_list": 26, "emailclientabc": 26, "emailcli": 26, "send_mail": 26, "mail_set": 26, "emailclientset": 26, "login": 26, "credenti": [26, 29, 45, 46], "user_nam": 26, "emailclientsettingsnameenum": 26, "usernam": 26, "boolpip": 27, "pipeabc": [27, 43], "transform": [27, 43], "firstchartolowerpip": 27, "lower": [27, 29, 48], "firsttoupperpip": 27, "upper": [27, 29, 48], "ipaddresspip": 27, "tocamelcasepip": 27, "camel": [27, 29], "camelcas": [27, 29], "tosnakecasepip": 27, "snake": [27, 29], "snake_cas": [27, 29], "versionpip": 27, "date_format": 28, "date_time_format": 28, "date_time_log_format": 28, "timeformatsettingsnamesenum": 28, "dateformat": 28, "datetimeformat": 28, "datetimelogformat": 28, "timeformat": 28, "credentialmanag": 29, "encrypt": [29, 45, 46], "decrypt": 29, "build_str": 29, "replac": [29, 59], "base64": [29, 45, 46], "get_execut": 29, "get_outd": 29, "byte": 29, "get": [29, 45, 46, 47, 49], "outdat": 29, "get_packag": 29, "local": [29, 44, 47], "stdout": 29, "stderr": 29, "extra": [29, 49], "index": [29, 39, 42, 48, 49], "url": [29, 49], "subprocess": [29, 45, 46], "reset_execut": 29, "system": 29, "standard": [29, 45, 46], "set_execut": 29, "convert_to_camel_cas": 29, "convert_to_snake_cas": [29, 59], "first_to_low": 29, "first_to_upp": 29, "random_str": 29, "random": [29, 48], "cpl_discord": [30, 47], "discord_bot_application_abc": [30, 47], "discord_command_abc": [30, 47], "discord_commands_meta": [30, 47], "discord_bot_set": [30, 37, 47], "category_channel": [30, 47], "guild": [30, 35, 37, 47], "role": [30, 35, 37, 47], "text_channel": [30, 47], "voice_channel": [30, 47], "on_bulk_message_delete_abc": [30, 47], "on_command_abc": [30, 47], "on_command_completion_abc": [30, 47], "on_command_error_abc": [30, 47], "on_connect_abc": [30, 47], "on_disconnect_abc": [30, 47], "on_error_abc": [30, 47], "on_group_join_abc": [30, 47], "on_group_remove_abc": [30, 47], "on_guild_available_abc": [30, 47], "on_guild_channel_create_abc": [30, 47], "on_guild_channel_delete_abc": [30, 47], "on_guild_channel_pins_update_abc": [30, 47], "on_guild_channel_update_abc": [30, 47], "on_guild_emojis_update_abc": [30, 47], "on_guild_integrations_update_abc": [30, 47], "on_guild_join_abc": [30, 47], "on_guild_remove_abc": [30, 47], "on_guild_role_create_abc": [30, 47], "on_guild_role_delete_abc": [30, 47], "on_guild_role_update_abc": [30, 47], "on_guild_unavailable_abc": [30, 47], "on_guild_update_abc": [30, 47], "on_invite_create_abc": [30, 47], "on_invite_delete_abc": [30, 47], "on_member_ban_abc": [30, 47], "on_member_join_abc": [30, 47], "on_member_remove_abc": [30, 47], "on_member_unban_abc": [30, 47], "on_member_update_abc": [30, 47], "on_message_abc": [30, 47], "on_message_delete_abc": [30, 47], "on_message_edit_abc": [30, 47], "on_private_channel_create_abc": [30, 47], "on_private_channel_delete_abc": [30, 47], "on_private_channel_pins_update_abc": [30, 47], "on_private_channel_update_abc": [30, 47], "on_raw_reaction_add_abc": [30, 47], "on_raw_reaction_clear_abc": [30, 47], "on_raw_reaction_clear_emoji_abc": [30, 47], "on_raw_reaction_remove_abc": [30, 47], "on_reaction_add_abc": [30, 47], "on_reaction_clear_abc": [30, 47], "on_reaction_clear_emoji_abc": [30, 47], "on_reaction_remove_abc": [30, 47], "on_ready_abc": [30, 47], "on_resume_abc": [30, 47], "on_typing_abc": [30, 47], "on_user_update_abc": [30, 47], "on_voice_state_update_abc": [30, 47], "on_webhooks_update_abc": [30, 47], "helper": [30, 47], "to_containers_convert": [30, 47], "command_error_handler_servic": [30, 47], "discord_bot_servic": [30, 47], "discord_bot_service_abc": [30, 47], "discord_collect": [30, 47], "discord_collection_abc": [30, 47], "discord_servic": [30, 47], "discord_service_abc": [30, 47], "discordbotapplicationabc": 31, "stop_async": [31, 37], "discordcommandabc": [32, 37], "cog": [32, 37], "discordcogmeta": 32, "namespac": 32, "abcmeta": 32, "cogmeta": 32, "discordbotset": [33, 37], "categorychannel": 34, "_t": [34, 36, 37, 39], "category_id": 34, "id": [34, 48], "nsfw": 34, "textchannel": 34, "categori": 34, "voicechannel": 34, "voic": 34, "_o": 34, "afk_channel": 34, "afk_timeout": 34, "approximate_member_count": 34, "approximate_presence_count": 34, "belong": 34, "sort": [34, 39, 45], "top": 34, "bottom": 34, "default_notif": 34, "emoji": [34, 35, 37], "explicit_content_filt": 34, "featur": [34, 49], "max_memb": 34, "max_pres": 34, "max_video_channel_us": 34, "sequenc": [34, 35, 36, 37, 39], "mfa_level": 34, "nsfw_level": 34, "owner_id": 34, "preferred_local": 34, "premium_progress_bar_en": 34, "premium_subscription_count": 34, "premium_ti": 34, "hierarchi": 34, "lowest": [34, 39], "sticker": 34, "permiss": 34, "view": 34, "unavail": 34, "vanity_url_cod": 34, "verification_level": 34, "widget_en": 34, "activitytyp": 34, "joined_at": 34, "nick": 34, "pend": 34, "premium_sinc": 34, "alwai": 34, "everyon": 34, "These": [34, 45], "timed_out_until": 34, "hoist": 34, "mention": 34, "tag": 34, "unicode_emoji": 34, "default_auto_archive_dur": 34, "last_message_id": 34, "slowmode_delai": 34, "archive_timestamp": 34, "archiv": 34, "archiver_id": 34, "auto_archive_dur": 34, "invit": [34, 35, 37], "lock": 34, "me": 34, "member_count": 34, "threadmemb": 34, "intent": 34, "properli": 34, "fill": 34, "howev": 34, "gatewai": 34, "fetch_memb": 34, "message_count": 34, "parent_id": 34, "insid": 34, "onbulkmessagedeleteabc": 35, "on_bulk_message_delet": [35, 37], "oncommandabc": 35, "on_command": [35, 37], "ctx": [35, 37], "oncommandcompletionabc": 35, "on_command_complet": [35, 37], "oncommanderrorabc": [35, 37], "on_command_error": [35, 37], "commanderror": [35, 37], "onconnectabc": 35, "on_connect": [35, 37], "ondisconnectabc": 35, "on_disconnect": [35, 37], "onerrorabc": 35, "on_error": [35, 37], "ongroupjoinabc": 35, "on_group_join": [35, 37], "groupchannel": [35, 37], "ongroupremoveabc": 35, "on_group_remov": [35, 37], "chhanel": [35, 37], "onguildavailableabc": 35, "on_guild_avail": [35, 37], "onguildchannelcreateabc": 35, "on_guild_channel_cr": [35, 37], "guildchannel": [35, 37], "onguildchanneldeleteabc": 35, "on_guild_channel_delet": [35, 37], "onguildchannelpinsupdateabc": 35, "on_guild_channel_pins_upd": [35, 37], "list_pin": [35, 37], "onguildchannelupdateabc": 35, "on_guild_channel_upd": [35, 37], "onguildemojisupdateabc": 35, "on_guild_emojis_upd": [35, 37], "onguildintegrationsupdateabc": 35, "on_guild_integrations_upd": [35, 37], "onguildjoinabc": 35, "on_guild_join": [35, 37], "onguildremoveabc": 35, "on_guild_remov": [35, 37], "onguildrolecreateabc": 35, "on_guild_role_cr": [35, 37], "onguildroledeleteabc": 35, "on_guild_role_delet": [35, 37], "onguildroleupdateabc": 35, "on_guild_role_upd": [35, 37], "onguildunavailableabc": 35, "on_guild_unavail": [35, 37], "onguildupdateabc": 35, "on_guild_upd": [35, 37], "oninvitecreateabc": 35, "on_invite_cr": [35, 37], "oninvitedeleteabc": 35, "on_invite_delet": [35, 37], "onmemberbanabc": 35, "on_member_ban": [35, 37], "onmemberjoinabc": 35, "on_member_join": [35, 37], "onmemberremoveabc": 35, "on_member_remov": [35, 37], "onmemberunbanabc": 35, "on_member_unban": [35, 37], "onmemberupdateabc": 35, "on_member_upd": [35, 37], "onmessageabc": 35, "on_messag": [35, 37], "onmessagedeleteabc": 35, "on_message_delet": [35, 37], "onmessageeditabc": 35, "on_message_edit": [35, 37], "onprivatechannelcreateabc": 35, "on_private_channel_cr": [35, 37], "privatechannel": [35, 37], "onprivatechanneldeleteabc": 35, "on_private_channel_delet": [35, 37], "onprivatechannelpinsupdateabc": 35, "on_private_channel_pins_upd": [35, 37], "onprivatechannelupdateabc": 35, "on_private_channel_upd": [35, 37], "onrawreactionaddabc": 35, "on_raw_reaction_add": [35, 37], "payload": [35, 37], "rawreactionactionev": [35, 37], "onrawreactionclearabc": 35, "on_raw_reaction_clear": [35, 37], "onrawreactionclearemojiabc": 35, "on_raw_reaction_clear_emoji": [35, 37], "onrawreactionremoveabc": 35, "on_raw_reaction_remov": [35, 37], "onreactionaddabc": 35, "on_reaction_add": [35, 37], "reaction": [35, 37], "onreactionclearabc": 35, "on_reaction_clear": [35, 37], "onreactionclearemojiabc": 35, "on_reaction_clear_emoji": [35, 37], "onreactionremoveabc": 35, "on_reaction_remov": [35, 37], "onreadyabc": 35, "on_readi": [35, 37], "onresumeabc": 35, "on_resum": [35, 37], "ontypingabc": 35, "on_typ": [35, 37], "onuserupdateabc": 35, "on_user_upd": [35, 37], "onvoicestateupdateabc": 35, "on_voice_state_upd": [35, 37], "voicest": [35, 37], "onwebhooksupdateabc": 35, "on_webhooks_upd": [35, 37], "tocontainersconvert": 36, "_l": 36, "commanderrorhandlerservic": 37, "discordbotservic": 37, "logging_st": 37, "discordserviceabc": 37, "discordbotserviceabc": 37, "client": 37, "start_async": 37, "discordcollect": 37, "discordcollectionabc": 37, "add_command": 37, "add_ev": 37, "_t_event": 37, "get_command": 37, "get_events_by_bas": 37, "discordservic": 37, "init": [37, 59], "cpl_queri": [38, 47], "default_lambda": [38, 47], "ordered_query": [38, 47], "ordered_queryable_abc": [38, 47], "queryable_abc": [38, 47], "sequence_abc": [38, 47], "sequence_valu": [38, 47], "enumerable_abc": [38, 41, 42, 47], "iterable_abc": [38, 40, 41, 47], "orderedquery": 39, "_valu": 39, "_func": 39, "orderedqueryableabc": 39, "orderediterableabc": 39, "then_bi": 39, "orderedlist": 39, "ascend": 39, "func": 39, "ordered_iterable_abc": 39, "then_by_descend": 39, "descend": 39, "queryableabc": [39, 40, 42], "everi": 39, "equal": 39, "averag": 39, "float": 39, "complex": [39, 45, 46, 59], "distinct": 39, "redund": 39, "element_at": 39, "_index": [39, 42], "element_at_or_default": 39, "first_or_default": 39, "for_each": 39, "group_bi": 39, "group": 39, "last_or_default": 39, "max": 39, "highest": 39, "median": 39, "min": 39, "order_bi": 39, "order_by_descend": 39, "revers": 39, "select_mani": 39, "flatten": 39, "singl": 39, "argumentnoneexcept": 39, "single_or_default": 39, "skip": 39, "skip_last": 39, "sum": 39, "take_last": 39, "where": 39, "enumerableabc": [40, 41, 42], "to_iter": [40, 41], "iterableabc": [40, 41, 42], "to_enumer": [41, 42], "_object": 42, "append": 42, "extend": [42, 44, 47, 50], "_iterableabc__iter": 42, "__iter": 42, "remove_at": 42, "translatepip": 43, "translationserviceabc": 43, "translationservic": 43, "lang": 43, "load_by_set": 43, "translationset": 43, "set_default_lang": 43, "set_lang": 43, "kei": [43, 45, 49], "default_languag": 43, "prerequisit": [44, 47, 50], "what": [44, 47], "up": [44, 47], "queri": [44, 45, 46, 47], "tutori": [44, 47, 48, 49], "come": [44, 47, 50], "builtin": [44, 47, 50], "common": [45, 46], "platform": [45, 46], "meant": [45, 46], "effici": [45, 46], "desktop": [45, 46], "learn": [45, 46, 49], "enterpris": [45, 46], "expandl": [45, 46], "builder": [45, 46], "map": [45, 46], "inject": [45, 46, 48], "appnam": [45, 46], "hostnam": [45, 46], "wrapper": [45, 46], "differ": [45, 46], "variant": [45, 46], "to_lower_cas": [45, 46], "to_camel_cas": [45, 46], "code": [45, 48, 49, 59], "connector": 45, "between": 45, "filter": 45, "linq": 45, "xd": 45, "dot": 45, "notat": 45, "page": 45, "great": 45, "detail": 45, "about": [45, 49], "everyth": 45, "do": [45, 48, 59], "contribut": 45, "cpl_translat": 47, "translate_pip": 47, "translation_servic": 47, "translation_service_abc": 47, "translation_set": 47, "welcom": 48, "introduc": 48, "walk": 48, "also": [48, 49, 59], "sampl": 48, "ouput": 48, "look": [48, 59], "licens": 48, "done": 48, "readm": 48, "md": 48, "__init__": [48, 59], "projectmain": 48, "vs": 48, "pycharm": 48, "hello": [48, 49], "world": [48, 49], "emul": 48, "def": [48, 59], "onli": 48, "__name__": 48, "__main__": 48, "generate_password": 48, "letter": [48, 59], "join": 48, "choic": 48, "rang": 48, "ascii_lowercas": 48, "elif": 48, "ascii_uppercas": 48, "ascii_lett": 48, "len": 48, "full": 48, "section": 48, "ve": 48, "continu": 48, "explor": 48, "window": 49, "prompt": 49, "declin": 49, "enter": 49, "press": 49, "lib": 49, "live": 49, "navig": 49, "launch": 49, "watch": 49, "chnage": 49, "those": 49, "success": 49, "similar": 49, "fore": 49, "pyhton": 49, "schematic_your_schemat": 59, "detect": 59, "schematic_": 59, "endswith": 59, "your_schemat": 59, "choos": 59, "attent": 59, "It": 59, "overwrit": 59, "cpl_cli": 59, "generate_schematic_abc": 59, "generateschematicabc": 59, "get_cod": 59, "textwrap": 59, "dedent": 59, "atr": 59, "build_code_str": 59, "_class_nam": 59, "regist": 59, "cl": 59, "littl": 59, "therefor": 59, "divid": 59, "sever": 59, "veri": 59, "structur": 59, "explain": 59, "project_consol": 59, "project_file_licens": 59, "project_file_appset": 59, "project_fil": 59, "project_file_readm": 59, "project_file_code_main": 59, "project_file_code_startup": 59, "project_file_code_appl": 59, "how": 59, "illustr": 59, "project_type_abc": 59, "projecttypeabc": 59, "workspaceset": 59, "base_path": 59, "project_nam": 59, "use_application_api": 59, "use_service_provid": 59, "use_async": 59, "project_file_data": 59, "projectfil": 59, "projectfileappset": 59, "projectfileappl": 59, "projectfilemain": 59, "projectfilestartup": 59, "projectfilereadm": 59, "projectfilelicens": 59, "schematic_init": 59, "project_path": 59, "f": 59, "split": 59, "add_templ": 59, "exactli": 59, "now": 59, "normal": 59, "inherit": 59, "filetemplateabc": 59, "codefiletemplateabc": 59, "code_file_template_abc": 59, "file_template_abc": 59, "_name": 59, "_code": 59, "dump": 59, "indent": 59}, "objects": {"cpl_core.application": [[17, 0, 0, "-", "application_abc"], [17, 0, 0, "-", "application_builder"], [17, 0, 0, "-", "application_builder_abc"], [17, 0, 0, "-", "startup_abc"]], "cpl_core.application.application_abc": [[17, 1, 1, "", "ApplicationABC"]], "cpl_core.application.application_abc.ApplicationABC": [[17, 2, 1, "", "configure"], [17, 2, 1, "", "main"], [17, 2, 1, "", "run"], [17, 2, 1, "", "run_async"]], "cpl_core.application.application_builder": [[17, 1, 1, "", "ApplicationBuilder"]], "cpl_core.application.application_builder.ApplicationBuilder": [[17, 2, 1, "", "build"], [17, 2, 1, "", "build_async"], [17, 2, 1, "", "use_extension"], [17, 2, 1, "", "use_startup"]], "cpl_core.application.application_builder_abc": [[17, 1, 1, "", "ApplicationBuilderABC"]], "cpl_core.application.application_builder_abc.ApplicationBuilderABC": [[17, 2, 1, "", "build"], [17, 2, 1, "", "build_async"], [17, 2, 1, "", "use_startup"]], "cpl_core.application.startup_abc": [[17, 1, 1, "", "StartupABC"]], "cpl_core.application.startup_abc.StartupABC": [[17, 2, 1, "", "configure_configuration"], [17, 2, 1, "", "configure_services"]], "cpl_core.configuration": [[18, 0, 0, "-", "configuration"], [18, 0, 0, "-", "configuration_abc"], [18, 0, 0, "-", "configuration_model_abc"], [18, 0, 0, "-", "configuration_variable_name_enum"]], "cpl_core.configuration.configuration": [[18, 1, 1, "", "Configuration"]], "cpl_core.configuration.configuration.Configuration": [[18, 2, 1, "", "add_configuration"], [18, 2, 1, "", "add_console_argument"], [18, 2, 1, "", "add_environment_variables"], [18, 2, 1, "", "add_json_file"], [18, 3, 1, "", "additional_arguments"], [18, 3, 1, "", "argument_error_function"], [18, 3, 1, "", "arguments"], [18, 2, 1, "", "create_console_argument"], [18, 3, 1, "", "environment"], [18, 2, 1, "", "for_each_argument"], [18, 2, 1, "", "get_configuration"], [18, 2, 1, "", "parse_console_arguments"]], "cpl_core.configuration.configuration_abc": [[18, 1, 1, "", "ConfigurationABC"]], "cpl_core.configuration.configuration_abc.ConfigurationABC": [[18, 2, 1, "", "add_configuration"], [18, 2, 1, "", "add_console_argument"], [18, 2, 1, "", "add_environment_variables"], [18, 2, 1, "", "add_json_file"], [18, 3, 1, "", "additional_arguments"], [18, 3, 1, "", "argument_error_function"], [18, 3, 1, "", "arguments"], [18, 2, 1, "", "create_console_argument"], [18, 3, 1, "", "environment"], [18, 2, 1, "", "for_each_argument"], [18, 2, 1, "", "get_configuration"], [18, 2, 1, "", "parse_console_arguments"]], "cpl_core.configuration.configuration_model_abc": [[18, 1, 1, "", "ConfigurationModelABC"]], "cpl_core.configuration.configuration_model_abc.ConfigurationModelABC": [[18, 2, 1, "", "from_dict"]], "cpl_core.configuration.configuration_variable_name_enum": [[18, 1, 1, "", "ConfigurationVariableNameEnum"]], "cpl_core.configuration.configuration_variable_name_enum.ConfigurationVariableNameEnum": [[18, 4, 1, "", "customer"], [18, 4, 1, "", "environment"], [18, 4, 1, "", "name"], [18, 2, 1, "", "to_list"]], "cpl_core.console": [[19, 0, 0, "-", "background_color_enum"], [19, 0, 0, "-", "console"], [19, 0, 0, "-", "console_call"], [19, 0, 0, "-", "foreground_color_enum"], [19, 0, 0, "-", "spinner_thread"]], "cpl_core.console.background_color_enum": [[19, 1, 1, "", "BackgroundColorEnum"]], "cpl_core.console.background_color_enum.BackgroundColorEnum": [[19, 4, 1, "", "blue"], [19, 4, 1, "", "cyan"], [19, 4, 1, "", "default"], [19, 4, 1, "", "green"], [19, 4, 1, "", "grey"], [19, 4, 1, "", "magenta"], [19, 4, 1, "", "red"], [19, 4, 1, "", "white"], [19, 4, 1, "", "yellow"]], "cpl_core.console.console": [[19, 1, 1, "", "Console"]], "cpl_core.console.console.Console": [[19, 3, 1, "", "background_color"], [19, 2, 1, "", "banner"], [19, 2, 1, "", "clear"], [19, 2, 1, "", "close"], [19, 2, 1, "", "color_reset"], [19, 2, 1, "", "disable"], [19, 2, 1, "", "enable"], [19, 2, 1, "", "error"], [19, 3, 1, "", "foreground_color"], [19, 2, 1, "", "read"], [19, 2, 1, "", "read_line"], [19, 2, 1, "", "reset_cursor_position"], [19, 2, 1, "", "select"], [19, 2, 1, "", "set_background_color"], [19, 2, 1, "", "set_cursor_position"], [19, 2, 1, "", "set_foreground_color"], [19, 2, 1, "", "set_hold_back"], [19, 2, 1, "", "spinner"], [19, 2, 1, "", "table"], [19, 2, 1, "", "write"], [19, 2, 1, "", "write_at"], [19, 2, 1, "", "write_line"], [19, 2, 1, "", "write_line_at"]], "cpl_core.console.console_call": [[19, 1, 1, "", "ConsoleCall"]], "cpl_core.console.console_call.ConsoleCall": [[19, 3, 1, "", "args"], [19, 3, 1, "", "function"]], "cpl_core.console.foreground_color_enum": [[19, 1, 1, "", "ForegroundColorEnum"]], "cpl_core.console.foreground_color_enum.ForegroundColorEnum": [[19, 4, 1, "", "blue"], [19, 4, 1, "", "cyan"], [19, 4, 1, "", "default"], [19, 4, 1, "", "green"], [19, 4, 1, "", "grey"], [19, 4, 1, "", "magenta"], [19, 4, 1, "", "red"], [19, 4, 1, "", "white"], [19, 4, 1, "", "yellow"]], "cpl_core.console.spinner_thread": [[19, 1, 1, "", "SpinnerThread"]], "cpl_core.console.spinner_thread.SpinnerThread": [[19, 2, 1, "", "exit"], [19, 2, 1, "", "run"], [19, 2, 1, "", "stop_spinning"]], "cpl_core.database.connection": [[21, 0, 0, "-", "database_connection"], [21, 0, 0, "-", "database_connection_abc"]], "cpl_core.database.connection.database_connection": [[21, 1, 1, "", "DatabaseConnection"]], "cpl_core.database.connection.database_connection.DatabaseConnection": [[21, 2, 1, "", "connect"], [21, 3, 1, "", "cursor"], [21, 3, 1, "", "server"]], "cpl_core.database.connection.database_connection_abc": [[21, 1, 1, "", "DatabaseConnectionABC"]], "cpl_core.database.connection.database_connection_abc.DatabaseConnectionABC": [[21, 2, 1, "", "connect"], [21, 3, 1, "", "cursor"], [21, 3, 1, "", "server"]], "cpl_core.database.context": [[22, 0, 0, "-", "database_context"], [22, 0, 0, "-", "database_context_abc"]], "cpl_core.database.context.database_context": [[22, 1, 1, "", "DatabaseContext"]], "cpl_core.database.context.database_context.DatabaseContext": [[22, 2, 1, "", "connect"], [22, 3, 1, "", "cursor"], [22, 2, 1, "", "save_changes"], [22, 2, 1, "", "select"]], "cpl_core.database.context.database_context_abc": [[22, 1, 1, "", "DatabaseContextABC"]], "cpl_core.database.context.database_context_abc.DatabaseContextABC": [[22, 2, 1, "", "connect"], [22, 3, 1, "", "cursor"], [22, 2, 1, "", "save_changes"], [22, 2, 1, "", "select"]], "cpl_core.database": [[20, 0, 0, "-", "database_settings"], [20, 0, 0, "-", "database_settings_name_enum"]], "cpl_core.database.database_settings": [[20, 1, 1, "", "DatabaseSettings"]], "cpl_core.database.database_settings.DatabaseSettings": [[20, 3, 1, "", "auth_plugin"], [20, 3, 1, "", "buffered"], [20, 3, 1, "", "charset"], [20, 3, 1, "", "database"], [20, 2, 1, "", "from_dict"], [20, 3, 1, "", "host"], [20, 3, 1, "", "password"], [20, 3, 1, "", "port"], [20, 3, 1, "", "use_unicode"], [20, 3, 1, "", "user"]], "cpl_core.database.database_settings_name_enum": [[20, 1, 1, "", "DatabaseSettingsNameEnum"]], "cpl_core.database.database_settings_name_enum.DatabaseSettingsNameEnum": [[20, 4, 1, "", "auth_plugin"], [20, 4, 1, "", "buffered"], [20, 4, 1, "", "charset"], [20, 4, 1, "", "database"], [20, 4, 1, "", "host"], [20, 4, 1, "", "password"], [20, 4, 1, "", "port"], [20, 4, 1, "", "use_unicode"], [20, 4, 1, "", "user"]], "cpl_core.dependency_injection": [[23, 0, 0, "-", "service_collection"], [23, 0, 0, "-", "service_collection_abc"], [23, 0, 0, "-", "service_descriptor"], [23, 0, 0, "-", "service_lifetime_enum"], [23, 0, 0, "-", "service_provider"], [23, 0, 0, "-", "service_provider_abc"]], "cpl_core.dependency_injection.service_collection": [[23, 1, 1, "", "ServiceCollection"]], "cpl_core.dependency_injection.service_collection.ServiceCollection": [[23, 2, 1, "", "add_db_context"], [23, 2, 1, "", "add_logging"], [23, 2, 1, "", "add_pipes"], [23, 2, 1, "", "add_scoped"], [23, 2, 1, "", "add_singleton"], [23, 2, 1, "", "add_transient"], [23, 2, 1, "", "build_service_provider"]], "cpl_core.dependency_injection.service_collection_abc": [[23, 1, 1, "", "ServiceCollectionABC"]], "cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC": [[23, 2, 1, "", "add_db_context"], [23, 2, 1, "", "add_discord"], [23, 2, 1, "", "add_logging"], [23, 2, 1, "", "add_pipes"], [23, 2, 1, "", "add_scoped"], [23, 2, 1, "", "add_singleton"], [23, 2, 1, "", "add_transient"], [23, 2, 1, "", "add_translation"], [23, 2, 1, "", "build_service_provider"]], "cpl_core.dependency_injection.service_descriptor": [[23, 1, 1, "", "ServiceDescriptor"]], "cpl_core.dependency_injection.service_descriptor.ServiceDescriptor": [[23, 3, 1, "", "base_type"], [23, 3, 1, "", "implementation"], [23, 3, 1, "", "lifetime"], [23, 3, 1, "", "service_type"]], "cpl_core.dependency_injection.service_lifetime_enum": [[23, 1, 1, "", "ServiceLifetimeEnum"]], "cpl_core.dependency_injection.service_lifetime_enum.ServiceLifetimeEnum": [[23, 4, 1, "", "scoped"], [23, 4, 1, "", "singleton"], [23, 4, 1, "", "transient"]], "cpl_core.dependency_injection.service_provider": [[23, 1, 1, "", "ServiceProvider"]], "cpl_core.dependency_injection.service_provider.ServiceProvider": [[23, 2, 1, "", "build_service"], [23, 2, 1, "", "create_scope"], [23, 2, 1, "", "get_service"], [23, 2, 1, "", "set_scope"]], "cpl_core.dependency_injection.service_provider_abc": [[23, 1, 1, "", "ServiceProviderABC"]], "cpl_core.dependency_injection.service_provider_abc.ServiceProviderABC": [[23, 2, 1, "", "build_service"], [23, 2, 1, "", "create_scope"], [23, 2, 1, "", "get_service"], [23, 2, 1, "", "set_scope"]], "cpl_core.environment": [[24, 0, 0, "-", "application_environment"], [24, 0, 0, "-", "application_environment_abc"], [24, 0, 0, "-", "environment_name_enum"]], "cpl_core.environment.application_environment": [[24, 1, 1, "", "ApplicationEnvironment"]], "cpl_core.environment.application_environment.ApplicationEnvironment": [[24, 3, 1, "", "application_name"], [24, 3, 1, "", "customer"], [24, 3, 1, "", "date_time_now"], [24, 3, 1, "", "end_time"], [24, 3, 1, "", "environment_name"], [24, 3, 1, "", "host_name"], [24, 3, 1, "", "runtime_directory"], [24, 2, 1, "", "set_runtime_directory"], [24, 2, 1, "", "set_working_directory"], [24, 3, 1, "", "start_time"], [24, 3, 1, "", "working_directory"]], "cpl_core.environment.application_environment_abc": [[24, 1, 1, "", "ApplicationEnvironmentABC"]], "cpl_core.environment.application_environment_abc.ApplicationEnvironmentABC": [[24, 3, 1, "", "application_name"], [24, 3, 1, "", "customer"], [24, 3, 1, "", "date_time_now"], [24, 3, 1, "", "end_time"], [24, 3, 1, "", "environment_name"], [24, 3, 1, "", "host_name"], [24, 3, 1, "", "runtime_directory"], [24, 2, 1, "", "set_runtime_directory"], [24, 2, 1, "", "set_working_directory"], [24, 3, 1, "", "start_time"], [24, 3, 1, "", "working_directory"]], "cpl_core.environment.environment_name_enum": [[24, 1, 1, "", "EnvironmentNameEnum"]], "cpl_core.environment.environment_name_enum.EnvironmentNameEnum": [[24, 4, 1, "", "development"], [24, 4, 1, "", "production"], [24, 4, 1, "", "staging"], [24, 4, 1, "", "testing"]], "cpl_core.logging": [[25, 0, 0, "-", "logger_abc"], [25, 0, 0, "-", "logger_service"], [25, 0, 0, "-", "logging_level_enum"], [25, 0, 0, "-", "logging_settings"], [25, 0, 0, "-", "logging_settings_name_enum"]], "cpl_core.logging.logger_abc": [[25, 1, 1, "", "LoggerABC"]], "cpl_core.logging.logger_abc.LoggerABC": [[25, 2, 1, "", "debug"], [25, 2, 1, "", "error"], [25, 2, 1, "", "fatal"], [25, 2, 1, "", "header"], [25, 2, 1, "", "info"], [25, 2, 1, "", "trace"], [25, 2, 1, "", "warn"]], "cpl_core.logging.logger_service": [[25, 1, 1, "", "Logger"]], "cpl_core.logging.logger_service.Logger": [[25, 2, 1, "", "create"], [25, 2, 1, "", "debug"], [25, 2, 1, "", "error"], [25, 2, 1, "", "fatal"], [25, 2, 1, "", "header"], [25, 2, 1, "", "info"], [25, 2, 1, "", "trace"], [25, 2, 1, "", "warn"]], "cpl_core.logging.logging_level_enum": [[25, 1, 1, "", "LoggingLevelEnum"]], "cpl_core.logging.logging_level_enum.LoggingLevelEnum": [[25, 4, 1, "", "DEBUG"], [25, 4, 1, "", "ERROR"], [25, 4, 1, "", "FATAL"], [25, 4, 1, "", "INFO"], [25, 4, 1, "", "OFF"], [25, 4, 1, "", "TRACE"], [25, 4, 1, "", "WARN"]], "cpl_core.logging.logging_settings": [[25, 1, 1, "", "LoggingSettings"]], "cpl_core.logging.logging_settings.LoggingSettings": [[25, 3, 1, "", "console"], [25, 3, 1, "", "filename"], [25, 2, 1, "", "from_dict"], [25, 3, 1, "", "level"], [25, 3, 1, "", "path"]], "cpl_core.logging.logging_settings_name_enum": [[25, 1, 1, "", "LoggingSettingsNameEnum"]], "cpl_core.logging.logging_settings_name_enum.LoggingSettingsNameEnum": [[25, 4, 1, "", "console_level"], [25, 4, 1, "", "file_level"], [25, 4, 1, "", "filename"], [25, 4, 1, "", "path"]], "cpl_core.mailing": [[26, 0, 0, "-", "email"], [26, 0, 0, "-", "email_client_abc"], [26, 0, 0, "-", "email_client_service"], [26, 0, 0, "-", "email_client_settings"], [26, 0, 0, "-", "email_client_settings_name_enum"]], "cpl_core.mailing.email": [[26, 1, 1, "", "EMail"]], "cpl_core.mailing.email.EMail": [[26, 2, 1, "", "add_header"], [26, 2, 1, "", "add_receiver"], [26, 3, 1, "", "body"], [26, 2, 1, "", "check_mail"], [26, 2, 1, "", "get_content"], [26, 3, 1, "", "header"], [26, 3, 1, "", "header_list"], [26, 3, 1, "", "receiver"], [26, 3, 1, "", "receiver_list"], [26, 3, 1, "", "subject"], [26, 3, 1, "", "transceiver"]], "cpl_core.mailing.email_client_abc": [[26, 1, 1, "", "EMailClientABC"]], "cpl_core.mailing.email_client_abc.EMailClientABC": [[26, 2, 1, "", "connect"], [26, 2, 1, "", "send_mail"]], "cpl_core.mailing.email_client_service": [[26, 1, 1, "", "EMailClient"]], "cpl_core.mailing.email_client_service.EMailClient": [[26, 2, 1, "", "connect"], [26, 2, 1, "", "create"], [26, 2, 1, "", "login"], [26, 2, 1, "", "send_mail"]], "cpl_core.mailing.email_client_settings": [[26, 1, 1, "", "EMailClientSettings"]], "cpl_core.mailing.email_client_settings.EMailClientSettings": [[26, 3, 1, "", "credentials"], [26, 2, 1, "", "from_dict"], [26, 3, 1, "", "host"], [26, 3, 1, "", "port"], [26, 3, 1, "", "user_name"]], "cpl_core.mailing.email_client_settings_name_enum": [[26, 1, 1, "", "EMailClientSettingsNameEnum"]], "cpl_core.mailing.email_client_settings_name_enum.EMailClientSettingsNameEnum": [[26, 4, 1, "", "credentials"], [26, 4, 1, "", "host"], [26, 4, 1, "", "port"], [26, 4, 1, "", "user_name"]], "cpl_core.pipes": [[27, 0, 0, "-", "bool_pipe"], [27, 0, 0, "-", "first_char_to_lower_pipe"], [27, 0, 0, "-", "first_to_upper_pipe"], [27, 0, 0, "-", "ip_address_pipe"], [27, 0, 0, "-", "pipe_abc"], [27, 0, 0, "-", "to_camel_case_pipe"], [27, 0, 0, "-", "to_snake_case_pipe"], [27, 0, 0, "-", "version_pipe"]], "cpl_core.pipes.bool_pipe": [[27, 1, 1, "", "BoolPipe"]], "cpl_core.pipes.bool_pipe.BoolPipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.first_char_to_lower_pipe": [[27, 1, 1, "", "FirstCharToLowerPipe"]], "cpl_core.pipes.first_char_to_lower_pipe.FirstCharToLowerPipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.first_to_upper_pipe": [[27, 1, 1, "", "FirstToUpperPipe"]], "cpl_core.pipes.first_to_upper_pipe.FirstToUpperPipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.ip_address_pipe": [[27, 1, 1, "", "IPAddressPipe"]], "cpl_core.pipes.ip_address_pipe.IPAddressPipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.pipe_abc": [[27, 1, 1, "", "PipeABC"]], "cpl_core.pipes.pipe_abc.PipeABC": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.to_camel_case_pipe": [[27, 1, 1, "", "ToCamelCasePipe"]], "cpl_core.pipes.to_camel_case_pipe.ToCamelCasePipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.to_snake_case_pipe": [[27, 1, 1, "", "ToSnakeCasePipe"]], "cpl_core.pipes.to_snake_case_pipe.ToSnakeCasePipe": [[27, 2, 1, "", "transform"]], "cpl_core.pipes.version_pipe": [[27, 1, 1, "", "VersionPipe"]], "cpl_core.pipes.version_pipe.VersionPipe": [[27, 2, 1, "", "transform"]], "cpl_core.time": [[28, 0, 0, "-", "time_format_settings"], [28, 0, 0, "-", "time_format_settings_names_enum"]], "cpl_core.time.time_format_settings": [[28, 1, 1, "", "TimeFormatSettings"]], "cpl_core.time.time_format_settings.TimeFormatSettings": [[28, 3, 1, "", "date_format"], [28, 3, 1, "", "date_time_format"], [28, 3, 1, "", "date_time_log_format"], [28, 2, 1, "", "from_dict"], [28, 3, 1, "", "time_format"]], "cpl_core.time.time_format_settings_names_enum": [[28, 1, 1, "", "TimeFormatSettingsNamesEnum"]], "cpl_core.time.time_format_settings_names_enum.TimeFormatSettingsNamesEnum": [[28, 4, 1, "", "date_format"], [28, 4, 1, "", "date_time_format"], [28, 4, 1, "", "date_time_log_format"], [28, 4, 1, "", "time_format"]], "cpl_core.utils": [[29, 0, 0, "-", "credential_manager"], [29, 0, 0, "-", "pip"], [29, 0, 0, "-", "string"]], "cpl_core.utils.credential_manager": [[29, 1, 1, "", "CredentialManager"]], "cpl_core.utils.credential_manager.CredentialManager": [[29, 2, 1, "", "build_string"], [29, 2, 1, "", "decrypt"], [29, 2, 1, "", "encrypt"]], "cpl_core.utils.pip": [[29, 1, 1, "", "Pip"]], "cpl_core.utils.pip.Pip": [[29, 2, 1, "", "get_executable"], [29, 2, 1, "", "get_outdated"], [29, 2, 1, "", "get_package"], [29, 2, 1, "", "install"], [29, 2, 1, "", "reset_executable"], [29, 2, 1, "", "set_executable"], [29, 2, 1, "", "uninstall"]], "cpl_core.utils.string": [[29, 1, 1, "", "String"]], "cpl_core.utils.string.String": [[29, 2, 1, "", "convert_to_camel_case"], [29, 2, 1, "", "convert_to_snake_case"], [29, 2, 1, "", "first_to_lower"], [29, 2, 1, "", "first_to_upper"], [29, 2, 1, "", "random_string"]], "cpl_discord.application": [[31, 0, 0, "-", "discord_bot_application_abc"]], "cpl_discord.application.discord_bot_application_abc": [[31, 1, 1, "", "DiscordBotApplicationABC"]], "cpl_discord.application.discord_bot_application_abc.DiscordBotApplicationABC": [[31, 2, 1, "", "stop_async"]], "cpl_discord.command": [[32, 0, 0, "-", "discord_command_abc"], [32, 0, 0, "-", "discord_commands_meta"]], "cpl_discord.command.discord_command_abc": [[32, 1, 1, "", "DiscordCommandABC"]], "cpl_discord.command.discord_commands_meta": [[32, 1, 1, "", "DiscordCogMeta"]], "cpl_discord.configuration": [[33, 0, 0, "-", "discord_bot_settings"]], "cpl_discord.configuration.discord_bot_settings": [[33, 1, 1, "", "DiscordBotSettings"]], "cpl_discord.configuration.discord_bot_settings.DiscordBotSettings": [[33, 2, 1, "", "from_dict"], [33, 3, 1, "", "prefix"], [33, 3, 1, "", "token"]], "cpl_discord.container": [[34, 0, 0, "-", "category_channel"], [34, 0, 0, "-", "container"], [34, 0, 0, "-", "guild"], [34, 0, 0, "-", "member"], [34, 0, 0, "-", "role"], [34, 0, 0, "-", "text_channel"], [34, 0, 0, "-", "thread"], [34, 0, 0, "-", "voice_channel"]], "cpl_discord.container.category_channel": [[34, 1, 1, "", "CategoryChannel"]], "cpl_discord.container.category_channel.CategoryChannel": [[34, 4, 1, "", "category_id"], [34, 4, 1, "", "guild"], [34, 4, 1, "", "id"], [34, 4, 1, "", "name"], [34, 4, 1, "", "nsfw"], [34, 4, 1, "", "position"], [34, 3, 1, "", "text_channels"], [34, 3, 1, "", "voice_channels"]], "cpl_discord.container.container": [[34, 1, 1, "", "Container"]], "cpl_discord.container.guild": [[34, 1, 1, "", "Guild"]], "cpl_discord.container.guild.Guild": [[34, 4, 1, "", "afk_channel"], [34, 4, 1, "", "afk_timeout"], [34, 4, 1, "", "approximate_member_count"], [34, 4, 1, "", "approximate_presence_count"], [34, 3, 1, "", "categories"], [34, 4, 1, "", "default_notifications"], [34, 4, 1, "", "description"], [34, 4, 1, "", "emojis"], [34, 4, 1, "", "explicit_content_filter"], [34, 4, 1, "", "features"], [34, 4, 1, "", "id"], [34, 4, 1, "", "max_members"], [34, 4, 1, "", "max_presences"], [34, 4, 1, "", "max_video_channel_users"], [34, 3, 1, "", "members"], [34, 4, 1, "", "mfa_level"], [34, 4, 1, "", "name"], [34, 4, 1, "", "nsfw_level"], [34, 4, 1, "", "owner_id"], [34, 4, 1, "", "preferred_locale"], [34, 4, 1, "", "premium_progress_bar_enabled"], [34, 4, 1, "", "premium_subscription_count"], [34, 4, 1, "", "premium_tier"], [34, 3, 1, "", "roles"], [34, 4, 1, "", "stickers"], [34, 3, 1, "", "text_channels"], [34, 3, 1, "", "threads"], [34, 4, 1, "", "unavailable"], [34, 4, 1, "", "vanity_url_code"], [34, 4, 1, "", "verification_level"], [34, 3, 1, "", "voice_channels"], [34, 4, 1, "", "widget_enabled"]], "cpl_discord.container.member": [[34, 1, 1, "", "Member"]], "cpl_discord.container.member.Member": [[34, 4, 1, "", "activities"], [34, 4, 1, "", "guild"], [34, 4, 1, "", "joined_at"], [34, 4, 1, "", "nick"], [34, 4, 1, "", "pending"], [34, 4, 1, "", "premium_since"], [34, 3, 1, "", "roles"], [34, 4, 1, "", "timed_out_until"]], "cpl_discord.container.role": [[34, 1, 1, "", "Role"]], "cpl_discord.container.role.Role": [[34, 4, 1, "", "guild"], [34, 4, 1, "", "hoist"], [34, 4, 1, "", "id"], [34, 4, 1, "", "managed"], [34, 3, 1, "", "members"], [34, 4, 1, "", "mentionable"], [34, 4, 1, "", "name"], [34, 4, 1, "", "position"], [34, 4, 1, "", "tags"], [34, 4, 1, "", "unicode_emoji"]], "cpl_discord.container.text_channel": [[34, 1, 1, "", "TextChannel"]], "cpl_discord.container.text_channel.TextChannel": [[34, 4, 1, "", "category_id"], [34, 4, 1, "", "default_auto_archive_duration"], [34, 4, 1, "", "guild"], [34, 4, 1, "", "id"], [34, 4, 1, "", "last_message_id"], [34, 3, 1, "", "members"], [34, 4, 1, "", "name"], [34, 4, 1, "", "nsfw"], [34, 4, 1, "", "position"], [34, 4, 1, "", "slowmode_delay"], [34, 3, 1, "", "threads"], [34, 4, 1, "", "topic"]], "cpl_discord.container.thread": [[34, 1, 1, "", "Thread"]], "cpl_discord.container.thread.Thread": [[34, 4, 1, "", "archive_timestamp"], [34, 4, 1, "", "archived"], [34, 4, 1, "", "archiver_id"], [34, 4, 1, "", "auto_archive_duration"], [34, 4, 1, "", "guild"], [34, 4, 1, "", "id"], [34, 4, 1, "", "invitable"], [34, 4, 1, "", "last_message_id"], [34, 4, 1, "", "locked"], [34, 4, 1, "", "me"], [34, 4, 1, "", "member_count"], [34, 3, 1, "", "members"], [34, 4, 1, "", "message_count"], [34, 4, 1, "", "name"], [34, 4, 1, "", "owner_id"], [34, 4, 1, "", "parent_id"], [34, 4, 1, "", "slowmode_delay"]], "cpl_discord.container.voice_channel": [[34, 1, 1, "", "VoiceChannel"]], "cpl_discord.container.voice_channel.VoiceChannel": [[34, 3, 1, "", "members"]], "cpl_discord.events": [[35, 0, 0, "-", "on_bulk_message_delete_abc"], [35, 0, 0, "-", "on_command_abc"], [35, 0, 0, "-", "on_command_completion_abc"], [35, 0, 0, "-", "on_command_error_abc"], [35, 0, 0, "-", "on_connect_abc"], [35, 0, 0, "-", "on_disconnect_abc"], [35, 0, 0, "-", "on_error_abc"], [35, 0, 0, "-", "on_group_join_abc"], [35, 0, 0, "-", "on_group_remove_abc"], [35, 0, 0, "-", "on_guild_available_abc"], [35, 0, 0, "-", "on_guild_channel_create_abc"], [35, 0, 0, "-", "on_guild_channel_delete_abc"], [35, 0, 0, "-", "on_guild_channel_pins_update_abc"], [35, 0, 0, "-", "on_guild_channel_update_abc"], [35, 0, 0, "-", "on_guild_emojis_update_abc"], [35, 0, 0, "-", "on_guild_integrations_update_abc"], [35, 0, 0, "-", "on_guild_join_abc"], [35, 0, 0, "-", "on_guild_remove_abc"], [35, 0, 0, "-", "on_guild_role_create_abc"], [35, 0, 0, "-", "on_guild_role_delete_abc"], [35, 0, 0, "-", "on_guild_role_update_abc"], [35, 0, 0, "-", "on_guild_unavailable_abc"], [35, 0, 0, "-", "on_guild_update_abc"], [35, 0, 0, "-", "on_invite_create_abc"], [35, 0, 0, "-", "on_invite_delete_abc"], [35, 0, 0, "-", "on_member_ban_abc"], [35, 0, 0, "-", "on_member_join_abc"], [35, 0, 0, "-", "on_member_remove_abc"], [35, 0, 0, "-", "on_member_unban_abc"], [35, 0, 0, "-", "on_member_update_abc"], [35, 0, 0, "-", "on_message_abc"], [35, 0, 0, "-", "on_message_delete_abc"], [35, 0, 0, "-", "on_message_edit_abc"], [35, 0, 0, "-", "on_private_channel_create_abc"], [35, 0, 0, "-", "on_private_channel_delete_abc"], [35, 0, 0, "-", "on_private_channel_pins_update_abc"], [35, 0, 0, "-", "on_private_channel_update_abc"], [35, 0, 0, "-", "on_raw_reaction_add_abc"], [35, 0, 0, "-", "on_raw_reaction_clear_abc"], [35, 0, 0, "-", "on_raw_reaction_clear_emoji_abc"], [35, 0, 0, "-", "on_raw_reaction_remove_abc"], [35, 0, 0, "-", "on_reaction_add_abc"], [35, 0, 0, "-", "on_reaction_clear_abc"], [35, 0, 0, "-", "on_reaction_clear_emoji_abc"], [35, 0, 0, "-", "on_reaction_remove_abc"], [35, 0, 0, "-", "on_ready_abc"], [35, 0, 0, "-", "on_resume_abc"], [35, 0, 0, "-", "on_typing_abc"], [35, 0, 0, "-", "on_user_update_abc"], [35, 0, 0, "-", "on_voice_state_update_abc"], [35, 0, 0, "-", "on_webhooks_update_abc"]], "cpl_discord.events.on_bulk_message_delete_abc": [[35, 1, 1, "", "OnBulkMessageDeleteABC"]], "cpl_discord.events.on_bulk_message_delete_abc.OnBulkMessageDeleteABC": [[35, 2, 1, "", "on_bulk_message_delete"]], "cpl_discord.events.on_command_abc": [[35, 1, 1, "", "OnCommandABC"]], "cpl_discord.events.on_command_abc.OnCommandABC": [[35, 2, 1, "", "on_command"]], "cpl_discord.events.on_command_completion_abc": [[35, 1, 1, "", "OnCommandCompletionABC"]], "cpl_discord.events.on_command_completion_abc.OnCommandCompletionABC": [[35, 2, 1, "", "on_command_completion"]], "cpl_discord.events.on_command_error_abc": [[35, 1, 1, "", "OnCommandErrorABC"]], "cpl_discord.events.on_command_error_abc.OnCommandErrorABC": [[35, 2, 1, "", "on_command_error"]], "cpl_discord.events.on_connect_abc": [[35, 1, 1, "", "OnConnectABC"]], "cpl_discord.events.on_connect_abc.OnConnectABC": [[35, 2, 1, "", "on_connect"]], "cpl_discord.events.on_disconnect_abc": [[35, 1, 1, "", "OnDisconnectABC"]], "cpl_discord.events.on_disconnect_abc.OnDisconnectABC": [[35, 2, 1, "", "on_disconnect"]], "cpl_discord.events.on_error_abc": [[35, 1, 1, "", "OnErrorABC"]], "cpl_discord.events.on_error_abc.OnErrorABC": [[35, 2, 1, "", "on_error"]], "cpl_discord.events.on_group_join_abc": [[35, 1, 1, "", "OnGroupJoinABC"]], "cpl_discord.events.on_group_join_abc.OnGroupJoinABC": [[35, 2, 1, "", "on_group_join"]], "cpl_discord.events.on_group_remove_abc": [[35, 1, 1, "", "OnGroupRemoveABC"]], "cpl_discord.events.on_group_remove_abc.OnGroupRemoveABC": [[35, 2, 1, "", "on_group_remove"]], "cpl_discord.events.on_guild_available_abc": [[35, 1, 1, "", "OnGuildAvailableABC"]], "cpl_discord.events.on_guild_available_abc.OnGuildAvailableABC": [[35, 2, 1, "", "on_guild_available"]], "cpl_discord.events.on_guild_channel_create_abc": [[35, 1, 1, "", "OnGuildChannelCreateABC"]], "cpl_discord.events.on_guild_channel_create_abc.OnGuildChannelCreateABC": [[35, 2, 1, "", "on_guild_channel_create"]], "cpl_discord.events.on_guild_channel_delete_abc": [[35, 1, 1, "", "OnGuildChannelDeleteABC"]], "cpl_discord.events.on_guild_channel_delete_abc.OnGuildChannelDeleteABC": [[35, 2, 1, "", "on_guild_channel_delete"]], "cpl_discord.events.on_guild_channel_pins_update_abc": [[35, 1, 1, "", "OnGuildChannelPinsUpdateABC"]], "cpl_discord.events.on_guild_channel_pins_update_abc.OnGuildChannelPinsUpdateABC": [[35, 2, 1, "", "on_guild_channel_pins_update"]], "cpl_discord.events.on_guild_channel_update_abc": [[35, 1, 1, "", "OnGuildChannelUpdateABC"]], "cpl_discord.events.on_guild_channel_update_abc.OnGuildChannelUpdateABC": [[35, 2, 1, "", "on_guild_channel_update"]], "cpl_discord.events.on_guild_emojis_update_abc": [[35, 1, 1, "", "OnGuildEmojisUpdateABC"]], "cpl_discord.events.on_guild_emojis_update_abc.OnGuildEmojisUpdateABC": [[35, 2, 1, "", "on_guild_emojis_update"]], "cpl_discord.events.on_guild_integrations_update_abc": [[35, 1, 1, "", "OnGuildIntegrationsUpdateABC"]], "cpl_discord.events.on_guild_integrations_update_abc.OnGuildIntegrationsUpdateABC": [[35, 2, 1, "", "on_guild_integrations_update"]], "cpl_discord.events.on_guild_join_abc": [[35, 1, 1, "", "OnGuildJoinABC"]], "cpl_discord.events.on_guild_join_abc.OnGuildJoinABC": [[35, 2, 1, "", "on_guild_join"]], "cpl_discord.events.on_guild_remove_abc": [[35, 1, 1, "", "OnGuildRemoveABC"]], "cpl_discord.events.on_guild_remove_abc.OnGuildRemoveABC": [[35, 2, 1, "", "on_guild_remove"]], "cpl_discord.events.on_guild_role_create_abc": [[35, 1, 1, "", "OnGuildRoleCreateABC"]], "cpl_discord.events.on_guild_role_create_abc.OnGuildRoleCreateABC": [[35, 2, 1, "", "on_guild_role_create"]], "cpl_discord.events.on_guild_role_delete_abc": [[35, 1, 1, "", "OnGuildRoleDeleteABC"]], "cpl_discord.events.on_guild_role_delete_abc.OnGuildRoleDeleteABC": [[35, 2, 1, "", "on_guild_role_delete"]], "cpl_discord.events.on_guild_role_update_abc": [[35, 1, 1, "", "OnGuildRoleUpdateABC"]], "cpl_discord.events.on_guild_role_update_abc.OnGuildRoleUpdateABC": [[35, 2, 1, "", "on_guild_role_update"]], "cpl_discord.events.on_guild_unavailable_abc": [[35, 1, 1, "", "OnGuildUnavailableABC"]], "cpl_discord.events.on_guild_unavailable_abc.OnGuildUnavailableABC": [[35, 2, 1, "", "on_guild_unavailable"]], "cpl_discord.events.on_guild_update_abc": [[35, 1, 1, "", "OnGuildUpdateABC"]], "cpl_discord.events.on_guild_update_abc.OnGuildUpdateABC": [[35, 2, 1, "", "on_guild_update"]], "cpl_discord.events.on_invite_create_abc": [[35, 1, 1, "", "OnInviteCreateABC"]], "cpl_discord.events.on_invite_create_abc.OnInviteCreateABC": [[35, 2, 1, "", "on_invite_create"]], "cpl_discord.events.on_invite_delete_abc": [[35, 1, 1, "", "OnInviteDeleteABC"]], "cpl_discord.events.on_invite_delete_abc.OnInviteDeleteABC": [[35, 2, 1, "", "on_invite_delete"]], "cpl_discord.events.on_member_ban_abc": [[35, 1, 1, "", "OnMemberBanABC"]], "cpl_discord.events.on_member_ban_abc.OnMemberBanABC": [[35, 2, 1, "", "on_member_ban"]], "cpl_discord.events.on_member_join_abc": [[35, 1, 1, "", "OnMemberJoinABC"]], "cpl_discord.events.on_member_join_abc.OnMemberJoinABC": [[35, 2, 1, "", "on_member_join"]], "cpl_discord.events.on_member_remove_abc": [[35, 1, 1, "", "OnMemberRemoveABC"]], "cpl_discord.events.on_member_remove_abc.OnMemberRemoveABC": [[35, 2, 1, "", "on_member_remove"]], "cpl_discord.events.on_member_unban_abc": [[35, 1, 1, "", "OnMemberUnbanABC"]], "cpl_discord.events.on_member_unban_abc.OnMemberUnbanABC": [[35, 2, 1, "", "on_member_unban"]], "cpl_discord.events.on_member_update_abc": [[35, 1, 1, "", "OnMemberUpdateABC"]], "cpl_discord.events.on_member_update_abc.OnMemberUpdateABC": [[35, 2, 1, "", "on_member_update"]], "cpl_discord.events.on_message_abc": [[35, 1, 1, "", "OnMessageABC"]], "cpl_discord.events.on_message_abc.OnMessageABC": [[35, 2, 1, "", "on_message"]], "cpl_discord.events.on_message_delete_abc": [[35, 1, 1, "", "OnMessageDeleteABC"]], "cpl_discord.events.on_message_delete_abc.OnMessageDeleteABC": [[35, 2, 1, "", "on_message_delete"]], "cpl_discord.events.on_message_edit_abc": [[35, 1, 1, "", "OnMessageEditABC"]], "cpl_discord.events.on_message_edit_abc.OnMessageEditABC": [[35, 2, 1, "", "on_message_edit"]], "cpl_discord.events.on_private_channel_create_abc": [[35, 1, 1, "", "OnPrivateChannelCreateABC"]], "cpl_discord.events.on_private_channel_create_abc.OnPrivateChannelCreateABC": [[35, 2, 1, "", "on_private_channel_create"]], "cpl_discord.events.on_private_channel_delete_abc": [[35, 1, 1, "", "OnPrivateChannelDeleteABC"]], "cpl_discord.events.on_private_channel_delete_abc.OnPrivateChannelDeleteABC": [[35, 2, 1, "", "on_private_channel_delete"]], "cpl_discord.events.on_private_channel_pins_update_abc": [[35, 1, 1, "", "OnPrivateChannelPinsUpdateABC"]], "cpl_discord.events.on_private_channel_pins_update_abc.OnPrivateChannelPinsUpdateABC": [[35, 2, 1, "", "on_private_channel_pins_update"]], "cpl_discord.events.on_private_channel_update_abc": [[35, 1, 1, "", "OnPrivateChannelUpdateABC"]], "cpl_discord.events.on_private_channel_update_abc.OnPrivateChannelUpdateABC": [[35, 2, 1, "", "on_private_channel_update"]], "cpl_discord.events.on_raw_reaction_add_abc": [[35, 1, 1, "", "OnRawReactionAddABC"]], "cpl_discord.events.on_raw_reaction_add_abc.OnRawReactionAddABC": [[35, 2, 1, "", "on_raw_reaction_add"]], "cpl_discord.events.on_raw_reaction_clear_abc": [[35, 1, 1, "", "OnRawReactionClearABC"]], "cpl_discord.events.on_raw_reaction_clear_abc.OnRawReactionClearABC": [[35, 2, 1, "", "on_raw_reaction_clear"]], "cpl_discord.events.on_raw_reaction_clear_emoji_abc": [[35, 1, 1, "", "OnRawReactionClearEmojiABC"]], "cpl_discord.events.on_raw_reaction_clear_emoji_abc.OnRawReactionClearEmojiABC": [[35, 2, 1, "", "on_raw_reaction_clear_emoji"]], "cpl_discord.events.on_raw_reaction_remove_abc": [[35, 1, 1, "", "OnRawReactionRemoveABC"]], "cpl_discord.events.on_raw_reaction_remove_abc.OnRawReactionRemoveABC": [[35, 2, 1, "", "on_raw_reaction_remove"]], "cpl_discord.events.on_reaction_add_abc": [[35, 1, 1, "", "OnReactionAddABC"]], "cpl_discord.events.on_reaction_add_abc.OnReactionAddABC": [[35, 2, 1, "", "on_reaction_add"]], "cpl_discord.events.on_reaction_clear_abc": [[35, 1, 1, "", "OnReactionClearABC"]], "cpl_discord.events.on_reaction_clear_abc.OnReactionClearABC": [[35, 2, 1, "", "on_reaction_clear"]], "cpl_discord.events.on_reaction_clear_emoji_abc": [[35, 1, 1, "", "OnReactionClearEmojiABC"]], "cpl_discord.events.on_reaction_clear_emoji_abc.OnReactionClearEmojiABC": [[35, 2, 1, "", "on_reaction_clear_emoji"]], "cpl_discord.events.on_reaction_remove_abc": [[35, 1, 1, "", "OnReactionRemoveABC"]], "cpl_discord.events.on_reaction_remove_abc.OnReactionRemoveABC": [[35, 2, 1, "", "on_reaction_remove"]], "cpl_discord.events.on_ready_abc": [[35, 1, 1, "", "OnReadyABC"]], "cpl_discord.events.on_ready_abc.OnReadyABC": [[35, 2, 1, "", "on_ready"]], "cpl_discord.events.on_resume_abc": [[35, 1, 1, "", "OnResumeABC"]], "cpl_discord.events.on_resume_abc.OnResumeABC": [[35, 2, 1, "", "on_resume"]], "cpl_discord.events.on_typing_abc": [[35, 1, 1, "", "OnTypingABC"]], "cpl_discord.events.on_typing_abc.OnTypingABC": [[35, 2, 1, "", "on_typing"]], "cpl_discord.events.on_user_update_abc": [[35, 1, 1, "", "OnUserUpdateABC"]], "cpl_discord.events.on_user_update_abc.OnUserUpdateABC": [[35, 2, 1, "", "on_user_update"]], "cpl_discord.events.on_voice_state_update_abc": [[35, 1, 1, "", "OnVoiceStateUpdateABC"]], "cpl_discord.events.on_voice_state_update_abc.OnVoiceStateUpdateABC": [[35, 2, 1, "", "on_voice_state_update"]], "cpl_discord.events.on_webhooks_update_abc": [[35, 1, 1, "", "OnWebhooksUpdateABC"]], "cpl_discord.events.on_webhooks_update_abc.OnWebhooksUpdateABC": [[35, 2, 1, "", "on_webhooks_update"]], "cpl_discord.helper": [[36, 0, 0, "-", "to_containers_converter"]], "cpl_discord.helper.to_containers_converter": [[36, 1, 1, "", "ToContainersConverter"]], "cpl_discord.helper.to_containers_converter.ToContainersConverter": [[36, 2, 1, "", "convert"]], "cpl_discord.service": [[37, 0, 0, "-", "command_error_handler_service"], [37, 0, 0, "-", "discord_bot_service"], [37, 0, 0, "-", "discord_bot_service_abc"], [37, 0, 0, "-", "discord_collection"], [37, 0, 0, "-", "discord_collection_abc"], [37, 0, 0, "-", "discord_service"], [37, 0, 0, "-", "discord_service_abc"]], "cpl_discord.service.command_error_handler_service": [[37, 1, 1, "", "CommandErrorHandlerService"]], "cpl_discord.service.command_error_handler_service.CommandErrorHandlerService": [[37, 2, 1, "", "on_command_error"]], "cpl_discord.service.discord_bot_service": [[37, 1, 1, "", "DiscordBotService"]], "cpl_discord.service.discord_bot_service.DiscordBotService": [[37, 3, 1, "", "guilds"], [37, 2, 1, "", "on_ready"], [37, 2, 1, "", "start_async"], [37, 2, 1, "", "stop_async"]], "cpl_discord.service.discord_bot_service_abc": [[37, 1, 1, "", "DiscordBotServiceABC"]], "cpl_discord.service.discord_bot_service_abc.DiscordBotServiceABC": [[37, 3, 1, "", "guilds"], [37, 2, 1, "", "on_ready"], [37, 2, 1, "", "start_async"], [37, 2, 1, "", "stop_async"]], "cpl_discord.service.discord_collection": [[37, 1, 1, "", "DiscordCollection"]], "cpl_discord.service.discord_collection.DiscordCollection": [[37, 2, 1, "", "add_command"], [37, 2, 1, "", "add_event"], [37, 2, 1, "", "get_commands"], [37, 2, 1, "", "get_events_by_base"]], "cpl_discord.service.discord_collection_abc": [[37, 1, 1, "", "DiscordCollectionABC"]], "cpl_discord.service.discord_collection_abc.DiscordCollectionABC": [[37, 2, 1, "", "add_command"], [37, 2, 1, "", "add_event"], [37, 2, 1, "", "get_commands"], [37, 2, 1, "", "get_events_by_base"]], "cpl_discord.service.discord_service": [[37, 1, 1, "", "DiscordService"]], "cpl_discord.service.discord_service.DiscordService": [[37, 2, 1, "", "init"], [37, 2, 1, "", "on_bulk_message_delete"], [37, 2, 1, "", "on_command"], [37, 2, 1, "", "on_command_completion"], [37, 2, 1, "", "on_command_error"], [37, 2, 1, "", "on_connect"], [37, 2, 1, "", "on_disconnect"], [37, 2, 1, "", "on_error"], [37, 2, 1, "", "on_group_join"], [37, 2, 1, "", "on_group_remove"], [37, 2, 1, "", "on_guild_available"], [37, 2, 1, "", "on_guild_channel_create"], [37, 2, 1, "", "on_guild_channel_delete"], [37, 2, 1, "", "on_guild_channel_pins_update"], [37, 2, 1, "", "on_guild_channel_update"], [37, 2, 1, "", "on_guild_emojis_update"], [37, 2, 1, "", "on_guild_integrations_update"], [37, 2, 1, "", "on_guild_join"], [37, 2, 1, "", "on_guild_remove"], [37, 2, 1, "", "on_guild_role_create"], [37, 2, 1, "", "on_guild_role_delete"], [37, 2, 1, "", "on_guild_role_update"], [37, 2, 1, "", "on_guild_unavailable"], [37, 2, 1, "", "on_guild_update"], [37, 2, 1, "", "on_invite_create"], [37, 2, 1, "", "on_invite_delete"], [37, 2, 1, "", "on_member_ban"], [37, 2, 1, "", "on_member_join"], [37, 2, 1, "", "on_member_remove"], [37, 2, 1, "", "on_member_unban"], [37, 2, 1, "", "on_member_update"], [37, 2, 1, "", "on_message"], [37, 2, 1, "", "on_message_delete"], [37, 2, 1, "", "on_message_edit"], [37, 2, 1, "", "on_private_channel_create"], [37, 2, 1, "", "on_private_channel_delete"], [37, 2, 1, "", "on_private_channel_pins_update"], [37, 2, 1, "", "on_private_channel_update"], [37, 2, 1, "", "on_raw_reaction_add"], [37, 2, 1, "", "on_raw_reaction_clear"], [37, 2, 1, "", "on_raw_reaction_clear_emoji"], [37, 2, 1, "", "on_raw_reaction_remove"], [37, 2, 1, "", "on_reaction_add"], [37, 2, 1, "", "on_reaction_clear"], [37, 2, 1, "", "on_reaction_clear_emoji"], [37, 2, 1, "", "on_reaction_remove"], [37, 2, 1, "", "on_ready"], [37, 2, 1, "", "on_resume"], [37, 2, 1, "", "on_typing"], [37, 2, 1, "", "on_user_update"], [37, 2, 1, "", "on_voice_state_update"], [37, 2, 1, "", "on_webhooks_update"]], "cpl_discord.service.discord_service_abc": [[37, 1, 1, "", "DiscordServiceABC"]], "cpl_discord.service.discord_service_abc.DiscordServiceABC": [[37, 2, 1, "", "init"], [37, 2, 1, "", "on_bulk_message_delete"], [37, 2, 1, "", "on_command"], [37, 2, 1, "", "on_command_completion"], [37, 2, 1, "", "on_command_error"], [37, 2, 1, "", "on_connect"], [37, 2, 1, "", "on_disconnect"], [37, 2, 1, "", "on_error"], [37, 2, 1, "", "on_group_join"], [37, 2, 1, "", "on_group_remove"], [37, 2, 1, "", "on_guild_available"], [37, 2, 1, "", "on_guild_channel_create"], [37, 2, 1, "", "on_guild_channel_delete"], [37, 2, 1, "", "on_guild_channel_pins_update"], [37, 2, 1, "", "on_guild_channel_update"], [37, 2, 1, "", "on_guild_emojis_update"], [37, 2, 1, "", "on_guild_integrations_update"], [37, 2, 1, "", "on_guild_join"], [37, 2, 1, "", "on_guild_remove"], [37, 2, 1, "", "on_guild_role_create"], [37, 2, 1, "", "on_guild_role_delete"], [37, 2, 1, "", "on_guild_role_update"], [37, 2, 1, "", "on_guild_unavailable"], [37, 2, 1, "", "on_guild_update"], [37, 2, 1, "", "on_invite_create"], [37, 2, 1, "", "on_invite_delete"], [37, 2, 1, "", "on_member_ban"], [37, 2, 1, "", "on_member_join"], [37, 2, 1, "", "on_member_remove"], [37, 2, 1, "", "on_member_unban"], [37, 2, 1, "", "on_member_update"], [37, 2, 1, "", "on_message"], [37, 2, 1, "", "on_message_delete"], [37, 2, 1, "", "on_message_edit"], [37, 2, 1, "", "on_private_channel_create"], [37, 2, 1, "", "on_private_channel_delete"], [37, 2, 1, "", "on_private_channel_pins_update"], [37, 2, 1, "", "on_private_channel_update"], [37, 2, 1, "", "on_reaction_add"], [37, 2, 1, "", "on_reaction_clear"], [37, 2, 1, "", "on_reaction_clear_emoji"], [37, 2, 1, "", "on_reaction_remove"], [37, 2, 1, "", "on_ready"], [37, 2, 1, "", "on_resume"], [37, 2, 1, "", "on_typing"], [37, 2, 1, "", "on_user_update"], [37, 2, 1, "", "on_voice_state_update"], [37, 2, 1, "", "on_webhooks_update"]], "cpl_query.base": [[39, 0, 0, "-", "default_lambda"], [39, 0, 0, "-", "ordered_queryable"], [39, 0, 0, "-", "ordered_queryable_abc"], [39, 0, 0, "-", "queryable_abc"]], "cpl_query.base.default_lambda": [[39, 5, 1, "", "default_lambda"]], "cpl_query.base.ordered_queryable": [[39, 1, 1, "", "OrderedQueryable"]], "cpl_query.base.ordered_queryable.OrderedQueryable": [[39, 2, 1, "", "then_by"], [39, 2, 1, "", "then_by_descending"]], "cpl_query.base.ordered_queryable_abc": [[39, 1, 1, "", "OrderedQueryableABC"]], "cpl_query.base.ordered_queryable_abc.OrderedQueryableABC": [[39, 2, 1, "", "then_by"], [39, 2, 1, "", "then_by_descending"]], "cpl_query.base.queryable_abc": [[39, 1, 1, "", "QueryableABC"]], "cpl_query.base.queryable_abc.QueryableABC": [[39, 2, 1, "", "all"], [39, 2, 1, "", "any"], [39, 2, 1, "", "average"], [39, 2, 1, "", "contains"], [39, 2, 1, "", "count"], [39, 2, 1, "", "distinct"], [39, 2, 1, "", "element_at"], [39, 2, 1, "", "element_at_or_default"], [39, 2, 1, "", "first"], [39, 2, 1, "", "first_or_default"], [39, 2, 1, "", "for_each"], [39, 2, 1, "", "group_by"], [39, 2, 1, "", "last"], [39, 2, 1, "", "last_or_default"], [39, 2, 1, "", "max"], [39, 2, 1, "", "median"], [39, 2, 1, "", "min"], [39, 2, 1, "", "order_by"], [39, 2, 1, "", "order_by_descending"], [39, 2, 1, "", "reverse"], [39, 2, 1, "", "select"], [39, 2, 1, "", "select_many"], [39, 2, 1, "", "single"], [39, 2, 1, "", "single_or_default"], [39, 2, 1, "", "skip"], [39, 2, 1, "", "skip_last"], [39, 2, 1, "", "sum"], [39, 2, 1, "", "take"], [39, 2, 1, "", "take_last"], [39, 2, 1, "", "where"]], "cpl_query.enumerable": [[40, 0, 0, "-", "enumerable"], [40, 0, 0, "-", "enumerable_abc"]], "cpl_query.enumerable.enumerable": [[40, 1, 1, "", "Enumerable"]], "cpl_query.enumerable.enumerable_abc": [[40, 1, 1, "", "EnumerableABC"]], "cpl_query.enumerable.enumerable_abc.EnumerableABC": [[40, 2, 1, "", "to_iterable"]], "cpl_query.extension": [[41, 0, 0, "-", "list"]], "cpl_query.extension.list": [[41, 1, 1, "", "List"]], "cpl_query.extension.list.List": [[41, 2, 1, "", "to_enumerable"], [41, 2, 1, "", "to_iterable"]], "cpl_query.iterable": [[42, 0, 0, "-", "iterable"], [42, 0, 0, "-", "iterable_abc"]], "cpl_query.iterable.iterable": [[42, 1, 1, "", "Iterable"]], "cpl_query.iterable.iterable_abc": [[42, 1, 1, "", "IterableABC"]], "cpl_query.iterable.iterable_abc.IterableABC": [[42, 2, 1, "", "add"], [42, 2, 1, "", "append"], [42, 2, 1, "", "extend"], [42, 2, 1, "", "remove"], [42, 2, 1, "", "remove_at"], [42, 2, 1, "", "to_enumerable"], [42, 3, 1, "", "type"]], "cpl_translation": [[43, 0, 0, "-", "translate_pipe"], [43, 0, 0, "-", "translation_service"], [43, 0, 0, "-", "translation_service_abc"], [43, 0, 0, "-", "translation_settings"]], "cpl_translation.translate_pipe": [[43, 1, 1, "", "TranslatePipe"]], "cpl_translation.translate_pipe.TranslatePipe": [[43, 2, 1, "", "transform"]], "cpl_translation.translation_service": [[43, 1, 1, "", "TranslationService"]], "cpl_translation.translation_service.TranslationService": [[43, 2, 1, "", "load"], [43, 2, 1, "", "load_by_settings"], [43, 2, 1, "", "set_default_lang"], [43, 2, 1, "", "set_lang"], [43, 2, 1, "", "translate"]], "cpl_translation.translation_service_abc": [[43, 1, 1, "", "TranslationServiceABC"]], "cpl_translation.translation_service_abc.TranslationServiceABC": [[43, 2, 1, "", "load"], [43, 2, 1, "", "load_by_settings"], [43, 2, 1, "", "set_default_lang"], [43, 2, 1, "", "set_lang"], [43, 2, 1, "", "translate"]], "cpl_translation.translation_settings": [[43, 1, 1, "", "TranslationSettings"]], "cpl_translation.translation_settings.TranslationSettings": [[43, 3, 1, "", "default_language"], [43, 2, 1, "", "from_dict"], [43, 3, 1, "", "languages"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:property", "4": "py:attribute", "5": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "property", "Python property"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "function", "Python function"]}, "titleterms": {"cpl": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 45, 46, 47, 48, 59], "add": 0, "content": [0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 48, 49, 59], "descript": [0, 1, 2, 3, 4, 5, 7, 8, 11], "argument": [0, 2, 3, 4, 8, 11, 53], "flag": [0, 4, 5, 8, 11, 12], "build": 1, "gener": [2, 59], "schemat": [2, 6, 59], "help": 3, "instal": [4, 49], "new": [5, 59], "project": [5, 48, 59], "type": [5, 59], "cli": [6, 15, 49], "overview": [6, 46], "command": [6, 32], "refer": [6, 15, 16, 30, 38, 43], "tabl": [6, 48, 49], "basic": 6, "workflow": 6, "languag": 6, "syntax": 6, "rel": 6, "path": 6, "publish": 7, "remov": 8, "run": 9, "start": [10, 44, 48, 49], "uninstal": 11, "updat": 12, "version": 13, "contribut": 14, "found": 14, "bug": 14, "featur": [14, 45, 46], "request": 14, "submiss": 14, "guidelin": 14, "submit": 14, "an": 14, "issu": 14, "pull": 14, "review": 14, "address": 14, "feedback": 14, "code": 14, "rule": 14, "licens": 14, "api": 16, "cpl_core": [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 52], "applic": [17, 31, 55], "application_abc": 17, "application_build": 17, "application_builder_abc": 17, "startup_abc": 17, "configur": [18, 33], "configuration_abc": 18, "configuration_model_abc": 18, "configuration_variable_name_enum": 18, "console_argu": 18, "consol": [19, 49, 52, 53], "background_color_enum": 19, "console_cal": 19, "foreground_color_enum": 19, "spinner_thread": 19, "databas": [20, 21, 22], "database_model": 20, "database_set": 20, "database_settings_name_enum": 20, "connect": 21, "database_connect": 21, "database_connection_abc": 21, "context": 22, "database_context": 22, "database_context_abc": 22, "dependency_inject": 23, "service_collect": 23, "service_collection_abc": 23, "service_descriptor": 23, "service_lifetime_enum": 23, "service_provid": 23, "service_provider_abc": 23, "environ": [24, 49], "application_environ": 24, "application_environment_abc": 24, "environment_name_enum": 24, "log": 25, "logger_abc": 25, "logger_servic": 25, "logging_level_enum": 25, "logging_set": 25, "logging_settings_name_enum": 25, "mail": [26, 58], "email": 26, "email_client_abc": 26, "email_client_servic": 26, "email_client_set": 26, "email_client_settings_name_enum": 26, "pipe": 27, "bool_pip": 27, "first_char_to_lower_pip": 27, "first_to_upper_pip": 27, "ip_address_pip": 27, "pipe_abc": 27, "to_camel_case_pip": 27, "to_snake_case_pip": 27, "version_pip": 27, "time": 28, "time_format_set": 28, "time_format_settings_names_enum": 28, "util": 29, "credential_manag": 29, "pip": 29, "string": 29, "discord": 30, "cpl_discord": [31, 32, 33, 34, 35, 36, 37], "discord_bot_application_abc": 31, "discord_command_abc": 32, "discord_commands_meta": 32, "discord_bot_set": 33, "contain": 34, "category_channel": 34, "guild": 34, "member": 34, "role": 34, "text_channel": 34, "thread": 34, "voice_channel": 34, "event": 35, "on_bulk_message_delete_abc": 35, "on_command_abc": 35, "on_command_completion_abc": 35, "on_command_error_abc": 35, "on_connect_abc": 35, "on_disconnect_abc": 35, "on_error_abc": 35, "on_group_join_abc": 35, "on_group_remove_abc": 35, "on_guild_available_abc": 35, "on_guild_channel_create_abc": 35, "on_guild_channel_delete_abc": 35, "on_guild_channel_pins_update_abc": 35, "on_guild_channel_update_abc": 35, "on_guild_emojis_update_abc": 35, "on_guild_integrations_update_abc": 35, "on_guild_join_abc": 35, "on_guild_remove_abc": 35, "on_guild_role_create_abc": 35, "on_guild_role_delete_abc": 35, "on_guild_role_update_abc": 35, "on_guild_unavailable_abc": 35, "on_guild_update_abc": 35, "on_invite_create_abc": 35, "on_invite_delete_abc": 35, "on_member_ban_abc": 35, "on_member_join_abc": 35, "on_member_remove_abc": 35, "on_member_unban_abc": 35, "on_member_update_abc": 35, "on_message_abc": 35, "on_message_delete_abc": 35, "on_message_edit_abc": 35, "on_private_channel_create_abc": 35, "on_private_channel_delete_abc": 35, "on_private_channel_pins_update_abc": 35, "on_private_channel_update_abc": 35, "on_raw_reaction_add_abc": 35, "on_raw_reaction_clear_abc": 35, "on_raw_reaction_clear_emoji_abc": 35, "on_raw_reaction_remove_abc": 35, "on_reaction_add_abc": 35, "on_reaction_clear_abc": 35, "on_reaction_clear_emoji_abc": 35, "on_reaction_remove_abc": 35, "on_ready_abc": 35, "on_resume_abc": 35, "on_typing_abc": 35, "on_user_update_abc": 35, "on_voice_state_update_abc": 35, "on_webhooks_update_abc": 35, "helper": 36, "to_containers_convert": 36, "servic": 37, "command_error_handler_servic": 37, "discord_bot_servic": 37, "discord_bot_service_abc": 37, "discord_collect": 37, "discord_collection_abc": 37, "discord_servic": 37, "discord_service_abc": 37, "queri": [38, 49], "cpl_queri": [39, 40, 41, 42], "base": 39, "default_lambda": 39, "ordered_query": 39, "ordered_queryable_abc": 39, "queryable_abc": 39, "sequence_abc": 39, "sequence_valu": 39, "enumer": 40, "enumerable_abc": 40, "extens": 41, "list": 41, "iter": 42, "iterable_abc": 42, "translat": 43, "cpl_translat": 43, "translate_pip": 43, "translation_servic": 43, "translation_service_abc": 43, "translation_set": 43, "get": [44, 48], "introduct": [45, 46], "doc": [45, 46], "manual": 45, "explor": 46, "prerequisit": [48, 49, 59], "creat": [48, 49, 54], "menu": 48, "what": [48, 49], "s": [48, 49], "next": [48, 49], "set": 49, "up": 49, "local": 49, "workspac": 49, "packag": 49, "initi": 49, "app": 49, "librari": 49, "tutori": 50, "us": [51, 52, 57, 59], "appset": 51, "json": 51, "come": [51, 52, 53, 54, 55, 56, 57, 58], "soon": [51, 52, 53, 54, 55, 56, 57, 58], "handl": 53, "startup": [54, 56], "class": 54, "extend": [55, 56], "builtin": 57, "logger": 57, "send": 58, "g": 59, "n": 59, "templat": 59}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 56}}) \ No newline at end of file diff --git a/docs/build/html/tutorials.appsettings.html b/docs/build/html/tutorials.appsettings.html index 0b42a876..b3743d8d 100644 --- a/docs/build/html/tutorials.appsettings.html +++ b/docs/build/html/tutorials.appsettings.html @@ -48,13 +48,14 @@
  414. Create startup class
  415. Extend startup
  416. Using appsettings.json
  417. Handle console arguments
  418. Use cpl_core.console.Console
  419. Use builtin logger
  420. Send mails
  421. +
  422. Using cpl g & cpl n templating
  423. @@ -95,8 +96,8 @@

    Using appsettings.json

    -
    -

    Comming soon

    +
    +

    Coming soon

    diff --git a/docs/build/html/tutorials.console-arguments.html b/docs/build/html/tutorials.console-arguments.html index 01cb18f3..515c1c3a 100644 --- a/docs/build/html/tutorials.console-arguments.html +++ b/docs/build/html/tutorials.console-arguments.html @@ -49,12 +49,13 @@
  424. Extend startup
  425. Using appsettings.json
  426. Handle console arguments
  427. Use cpl_core.console.Console
  428. Use builtin logger
  429. Send mails
  430. +
  431. Using cpl g & cpl n templating
  432. @@ -95,8 +96,8 @@

    Handle console arguments

    -
    -

    Comming soon

    +
    +

    Coming soon

    diff --git a/docs/build/html/tutorials.console.html b/docs/build/html/tutorials.console.html index 7b9ef50b..d72ba844 100644 --- a/docs/build/html/tutorials.console.html +++ b/docs/build/html/tutorials.console.html @@ -50,11 +50,12 @@
  433. Using appsettings.json
  434. Handle console arguments
  435. Use cpl_core.console.Console
  436. Use builtin logger
  437. Send mails
  438. +
  439. Using cpl g & cpl n templating
  440. @@ -95,8 +96,8 @@

    Use cpl_core.console.Console

    -
    -

    Comming soon

    +
    +

    Coming soon

    diff --git a/docs/build/html/tutorials.create-startup.html b/docs/build/html/tutorials.create-startup.html index 98beb078..e5ccb0af 100644 --- a/docs/build/html/tutorials.create-startup.html +++ b/docs/build/html/tutorials.create-startup.html @@ -46,7 +46,7 @@
  441. Tutorials
  442. @@ -95,8 +96,8 @@

    Create startup class

    -
    -

    Comming soon

    +
    +

    Coming soon

    diff --git a/docs/build/html/tutorials.extend-application.html b/docs/build/html/tutorials.extend-application.html index 40d36232..6c905a44 100644 --- a/docs/build/html/tutorials.extend-application.html +++ b/docs/build/html/tutorials.extend-application.html @@ -45,7 +45,7 @@
  443. Setting up the local environment and workspace
  444. Tutorials
  445. @@ -95,8 +96,8 @@

    Extend application

    -
    -

    Comming soon

    +
    +

    Coming soon

    diff --git a/docs/build/html/tutorials.extend-startup.html b/docs/build/html/tutorials.extend-startup.html index 660a1afb..4fe21474 100644 --- a/docs/build/html/tutorials.extend-startup.html +++ b/docs/build/html/tutorials.extend-startup.html @@ -47,7 +47,7 @@
  446. Extend application
  447. Create startup class
  448. Extend startup
  449. Using appsettings.json
  450. @@ -55,6 +55,7 @@
  451. Use cpl_core.console.Console
  452. Use builtin logger
  453. Send mails
  454. +
  455. Using cpl g & cpl n templating
  456. @@ -95,8 +96,8 @@

    Extend startup

    -
    -

    Comming soon

    +
    +

    Coming soon

    diff --git a/docs/build/html/tutorials.html b/docs/build/html/tutorials.html index 141e20c5..0f8ed43f 100644 --- a/docs/build/html/tutorials.html +++ b/docs/build/html/tutorials.html @@ -52,6 +52,7 @@
  457. Use cpl_core.console.Console
  458. Use builtin logger
  459. Send mails
  460. +
  461. Using cpl g & cpl n templating
  462. @@ -94,35 +95,42 @@
    diff --git a/docs/build/html/tutorials.logging.html b/docs/build/html/tutorials.logging.html index d88b255f..1a61b350 100644 --- a/docs/build/html/tutorials.logging.html +++ b/docs/build/html/tutorials.logging.html @@ -51,10 +51,11 @@
  463. Handle console arguments
  464. Use cpl_core.console.Console
  465. Use builtin logger
  466. Send mails
  467. +
  468. Using cpl g & cpl n templating
  469. @@ -95,8 +96,8 @@

    Use builtin logger

    -
    -

    Comming soon

    +
    +

    Coming soon

    diff --git a/docs/build/html/tutorials.mail.html b/docs/build/html/tutorials.mail.html index c1c39f37..d61de75d 100644 --- a/docs/build/html/tutorials.mail.html +++ b/docs/build/html/tutorials.mail.html @@ -19,7 +19,7 @@ - + @@ -52,9 +52,10 @@
  470. Use cpl_core.console.Console
  471. Use builtin logger
  472. Send mails
  473. +
  474. Using cpl g & cpl n templating
  475. @@ -95,8 +96,8 @@

    Send mails

    -
    -

    Comming soon

    +
    +

    Coming soon

    @@ -105,7 +106,7 @@

    diff --git a/docs/build/html/tutorials.templating.html b/docs/build/html/tutorials.templating.html new file mode 100644 index 00000000..0efc7173 --- /dev/null +++ b/docs/build/html/tutorials.templating.html @@ -0,0 +1,304 @@ + + + + + + + Using cpl g & cpl n templating — Common Python Library documentation + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Using cpl g & cpl n templating

    +
    +

    Contents

    +
      +
    • Prerequisites

    • +
    • Generate schematics

    • +
    • Project types

    • +
    +
    +
    +

    Prerequisites

    +

    Create a folder called .cpl

    +
    +
    +

    cpl generate schematics

    +

    Create a file which begins with schematic_your_schematic.py. +A schematic template is detected by starting with schematic_ and endswith .py.

    +

    You should replace your_schematic with an appropriate name of your schematic. For example, we will choose Enum. +Attention: It is important that you do not overwrite templates by creating a file or class with the same name.

    +

    In the template create a class with the name of your schematic. For example:

    +
    from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
    +
    +
    +class Enum(GenerateSchematicABC):
    +
    +    def __init__(self, *args: str):
    +        GenerateSchematicABC.__init__(self, *args)
    +
    +    def get_code(self) -> str:
    +        import textwrap
    +        code = textwrap.dedent("""\
    +        from enum import Enum
    +        
    +        
    +        class $Name(Enum):
    +        
    +            atr = 0
    +        """)
    +        return self.build_code_str(code, Name=self._class_name)
    +
    +    @classmethod
    +    def register(cls):
    +        GenerateSchematicABC.register(
    +            cls,
    +            'enum',
    +            ['e', 'E']
    +        )
    +
    +
    +
    +

    You can test it by calling cpl g --help your schematic should be listed as available.

    +
    +
    +

    cpl new project types

    +

    The project templating is a little more complex and is therefore divided into several files. +First of all, for information, it is very important not to overwrite any existing files or classes!

    +

    Template structure explained by the example of the internal type console:

    +
    - project_console.py
    +- project_file_license.py
    +- project_file_appsettings.py
    +- project_file.py
    +- project_file_readme.py
    +- project_file_code_main.py
    +- project_file_code_startup.py
    +- project_file_code_application.py
    +
    +
    +

    Here the template project_console.py defines how a console project has to look like when it is generated. Here is the code to illustrate this:

    +
    from cpl_cli.abc.project_type_abc import ProjectTypeABC
    +from cpl_cli.configuration import WorkspaceSettings
    +from cpl_core.utils import String
    +
    +
    +class Console(ProjectTypeABC):
    +
    +    def __init__(
    +            self,
    +            base_path: str,
    +            project_name: str,
    +            workspace: WorkspaceSettings,
    +            use_application_api: bool,
    +            use_startup: bool,
    +            use_service_providing: bool,
    +            use_async: bool,
    +            project_file_data: dict,
    +    ):
    +        from project_file import ProjectFile
    +        from project_file_appsettings import ProjectFileAppsettings
    +        from project_file_code_application import ProjectFileApplication
    +        from project_file_code_main import ProjectFileMain
    +        from project_file_code_startup import ProjectFileStartup
    +        from project_file_readme import ProjectFileReadme
    +        from project_file_license import ProjectFileLicense
    +        from schematic_init import Init
    +
    +        ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async, project_file_data)
    +
    +        project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/'
    +
    +        self.add_template(ProjectFile(project_name.split('/')[-1], project_path, project_file_data))
    +        if workspace is None:
    +            self.add_template(ProjectFileLicense(''))
    +            self.add_template(ProjectFileReadme(''))
    +            self.add_template(Init('', 'init', f'{base_path}tests/'))
    +
    +        self.add_template(Init('', 'init', project_path))
    +        self.add_template(ProjectFileAppsettings(project_path))
    +
    +        if use_application_api:
    +            self.add_template(ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async))
    +
    +        if use_startup:
    +            self.add_template(ProjectFileStartup(project_path, use_application_api, use_startup, use_service_providing, use_async))
    +
    +        self.add_template(ProjectFileMain(project_name.split('/')[-1], project_path, use_application_api, use_startup, use_service_providing, use_async))
    +
    +
    +

    The class must be named exactly as the project type should be named. It is also checked on the initial letter of the class as alias. +Now create a class for normal files which inherits from FileTemplateABC and a class for code files which inherits from CodeFileTemplateABC.

    +

    For example:

    +

    project_file_code_startup.py:

    +
    from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC
    +
    +
    +class ProjectFileStartup(CodeFileTemplateABC):
    +
    +    def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool):
    +        CodeFileTemplateABC.__init__(self, 'startup', path, '', use_application_api, use_startup, use_service_providing, use_async)
    +
    +    def get_code(self) -> str:
    +        import textwrap
    +
    +        return textwrap.dedent("""\
    +        from cpl_core.application import StartupABC
    +        from cpl_core.configuration import ConfigurationABC
    +        from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC
    +        from cpl_core.environment import ApplicationEnvironment
    +        
    +        
    +        class Startup(StartupABC):
    +        
    +            def __init__(self):
    +                StartupABC.__init__(self)
    +        
    +            def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC:
    +                return configuration
    +        
    +            def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC:
    +                return services.build_service_provider()
    +        """)
    +
    +
    +

    project_file.py:

    +
    import json
    +
    +from cpl_cli.abc.file_template_abc import FileTemplateABC
    +
    +
    +class ProjectFile(FileTemplateABC):
    +
    +    def __init__(self, name: str, path: str, code: dict):
    +        FileTemplateABC.__init__(self, '', path, '{}')
    +        self._name = f'{name}.json'
    +        self._code = code
    +
    +    def get_code(self) -> str:
    +        return json.dumps(self._code, indent=2)
    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/source/cli.generate.md b/docs/source/cli.generate.md index 95a1cb51..6dc285a0 100644 --- a/docs/source/cli.generate.md +++ b/docs/source/cli.generate.md @@ -16,6 +16,8 @@ cpl **G** *<schematic>* *<name>* Generates files based on a schematic. +You can define custom schematics by creating templates in a ```.cpl``` folder. + ## Arguments | Argument | Description | Value type | @@ -26,14 +28,16 @@ Generates files based on a schematic. ## Schematics -| Schematic | Description | Arguments | -|-----------------|:-------------------------------------:|:------------:| -| ```abc``` | Abstract base class | `````` | -| ```class``` | Class | `````` | -| ```enum``` | Enum class | `````` | -| ```pipe``` | Pipe class | `````` | -| ```service``` | Service class | `````` | -| ```settings``` | [Configmodel](cpl_core.configuration) | `````` | -| ```test``` | Test class | `````` | -| ```thread``` | Thread class | `````` | -| ```validator``` | Validator class | `````` | +| Schematic | Description | Arguments | +|-----------------|:--------------------------------------:|:------------:| +| ```abc``` | Abstract base class | `````` | +| ```class``` | Class | `````` | +| ```enum``` | Enum class | `````` | +| ```pipe``` | Pipe class | `````` | +| ```service``` | Service class | `````` | +| ```settings``` | [Configmodel](cpl_core.configuration) | `````` | +| ```test``` | Test class | `````` | +| ```thread``` | Thread class | `````` | +| ```validator``` | Validator class | `````` | +| ```command``` | Discord bot command class | `````` | +| ```event``` | Discord bot event class | `````` | diff --git a/docs/source/cli.new.md b/docs/source/cli.new.md index f000dcd6..1301c1ad 100644 --- a/docs/source/cli.new.md +++ b/docs/source/cli.new.md @@ -16,6 +16,8 @@ cpl **N** *<type>* *<name>* Generates a workspace and initial project or add a project to workspace. +You can define custom project types by creating templates in a ```.cpl``` folder. + If the command is running in a CPL workspace, it will add the new project to the workspace. | Argument | Description | Value type | diff --git a/docs/source/tutorials.appsettings.md b/docs/source/tutorials.appsettings.md index ffe26cba..4eabffa2 100644 --- a/docs/source/tutorials.appsettings.md +++ b/docs/source/tutorials.appsettings.md @@ -1,3 +1,3 @@ # Using appsettings.json -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/source/tutorials.console-arguments.md b/docs/source/tutorials.console-arguments.md index a0be2c0f..0a3b5a42 100644 --- a/docs/source/tutorials.console-arguments.md +++ b/docs/source/tutorials.console-arguments.md @@ -1,3 +1,3 @@ # Handle console arguments -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/source/tutorials.console.md b/docs/source/tutorials.console.md index c7d22b99..fcbaaba1 100644 --- a/docs/source/tutorials.console.md +++ b/docs/source/tutorials.console.md @@ -1,3 +1,3 @@ # Use cpl_core.console.Console -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/source/tutorials.create-startup.md b/docs/source/tutorials.create-startup.md index ee443126..028d072c 100644 --- a/docs/source/tutorials.create-startup.md +++ b/docs/source/tutorials.create-startup.md @@ -1,3 +1,3 @@ # Create startup class -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/source/tutorials.extend-application.md b/docs/source/tutorials.extend-application.md index 3697cbc9..1eec6e9e 100644 --- a/docs/source/tutorials.extend-application.md +++ b/docs/source/tutorials.extend-application.md @@ -1,3 +1,3 @@ # Extend application -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/source/tutorials.extend-startup.md b/docs/source/tutorials.extend-startup.md index 66e3e54f..98b90da4 100644 --- a/docs/source/tutorials.extend-startup.md +++ b/docs/source/tutorials.extend-startup.md @@ -1,3 +1,3 @@ # Extend startup -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/source/tutorials.logging.md b/docs/source/tutorials.logging.md index c98020c5..660fbfe1 100644 --- a/docs/source/tutorials.logging.md +++ b/docs/source/tutorials.logging.md @@ -1,3 +1,3 @@ # Use builtin logger -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/source/tutorials.mail.md b/docs/source/tutorials.mail.md index e7a2b778..7b6c9150 100644 --- a/docs/source/tutorials.mail.md +++ b/docs/source/tutorials.mail.md @@ -1,3 +1,3 @@ # Send mails -## Comming soon \ No newline at end of file +## Coming soon \ No newline at end of file diff --git a/docs/source/tutorials.rst b/docs/source/tutorials.rst index f85e9b8c..b8fd6668 100644 --- a/docs/source/tutorials.rst +++ b/docs/source/tutorials.rst @@ -11,4 +11,5 @@ Tutorials tutorials.console-arguments tutorials.console tutorials.logging - tutorials.mail \ No newline at end of file + tutorials.mail + tutorials.templating \ No newline at end of file diff --git a/docs/source/tutorials.templating.md b/docs/source/tutorials.templating.md new file mode 100644 index 00000000..4530b17c --- /dev/null +++ b/docs/source/tutorials.templating.md @@ -0,0 +1,181 @@ +# Using cpl g & cpl n templating + +## Contents + +- [Prerequisites](#prerequisites) +- [Generate schematics](#cpl-generate-scmatics) +- [Project types](#cpl-new-project-types) + +## Prerequisites + +Create a folder called ```.cpl``` + +## cpl generate schematics + +Create a file which begins with ```schematic_your_schematic.py```. +A schematic template is detected by starting with ```schematic_``` and endswith ```.py```. + +You should replace ```your_schematic``` with an appropriate name of your schematic. For example, we will choose ```Enum```. +Attention: It is important that you do not overwrite templates by creating a file or class with the same name. + +In the template create a class with the name of your schematic. For example: + +```python +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Enum(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + import textwrap + code = textwrap.dedent("""\ + from enum import Enum + + + class $Name(Enum): + + atr = 0 + """) + return self.build_code_str(code, Name=self._class_name) + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'enum', + ['e', 'E'] + ) + +``` + +You can test it by calling ```cpl g --help``` your schematic should be listed as available. + +## cpl new project types + +The project templating is a little more complex and is therefore divided into several files. +First of all, for information, it is very important not to overwrite any existing files or classes! + +Template structure explained by the example of the internal type ```console```: + +``` +- project_console.py +- project_file_license.py +- project_file_appsettings.py +- project_file.py +- project_file_readme.py +- project_file_code_main.py +- project_file_code_startup.py +- project_file_code_application.py +``` + +Here the template ```project_console.py``` defines how a console project has to look like when it is generated. Here is the code to illustrate this: + +```python +from cpl_cli.abc.project_type_abc import ProjectTypeABC +from cpl_cli.configuration import WorkspaceSettings +from cpl_core.utils import String + + +class Console(ProjectTypeABC): + + def __init__( + self, + base_path: str, + project_name: str, + workspace: WorkspaceSettings, + use_application_api: bool, + use_startup: bool, + use_service_providing: bool, + use_async: bool, + project_file_data: dict, + ): + from project_file import ProjectFile + from project_file_appsettings import ProjectFileAppsettings + from project_file_code_application import ProjectFileApplication + from project_file_code_main import ProjectFileMain + from project_file_code_startup import ProjectFileStartup + from project_file_readme import ProjectFileReadme + from project_file_license import ProjectFileLicense + from schematic_init import Init + + ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async, project_file_data) + + project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/' + + self.add_template(ProjectFile(project_name.split('/')[-1], project_path, project_file_data)) + if workspace is None: + self.add_template(ProjectFileLicense('')) + self.add_template(ProjectFileReadme('')) + self.add_template(Init('', 'init', f'{base_path}tests/')) + + self.add_template(Init('', 'init', project_path)) + self.add_template(ProjectFileAppsettings(project_path)) + + if use_application_api: + self.add_template(ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async)) + + if use_startup: + self.add_template(ProjectFileStartup(project_path, use_application_api, use_startup, use_service_providing, use_async)) + + self.add_template(ProjectFileMain(project_name.split('/')[-1], project_path, use_application_api, use_startup, use_service_providing, use_async)) +``` + +The class must be named exactly as the project type should be named. It is also checked on the initial letter of the class as alias. +Now create a class for normal files which inherits from ```FileTemplateABC``` and a class for code files which inherits from ```CodeFileTemplateABC```. + +For example: + +project_file_code_startup.py: +```python +from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC + + +class ProjectFileStartup(CodeFileTemplateABC): + + def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool): + CodeFileTemplateABC.__init__(self, 'startup', path, '', use_application_api, use_startup, use_service_providing, use_async) + + def get_code(self) -> str: + import textwrap + + return textwrap.dedent("""\ + from cpl_core.application import StartupABC + from cpl_core.configuration import ConfigurationABC + from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC + from cpl_core.environment import ApplicationEnvironment + + + class Startup(StartupABC): + + def __init__(self): + StartupABC.__init__(self) + + def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: + return configuration + + def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: + return services.build_service_provider() + """) +``` + +project_file.py: + +```python +import json + +from cpl_cli.abc.file_template_abc import FileTemplateABC + + +class ProjectFile(FileTemplateABC): + + def __init__(self, name: str, path: str, code: dict): + FileTemplateABC.__init__(self, '', path, '{}') + self._name = f'{name}.json' + self._code = code + + def get_code(self) -> str: + return json.dumps(self._code, indent=2) +``` diff --git a/src/cpl_cli/.cpl/project_console.py b/src/cpl_cli/.cpl/project_console.py index cdf2ec62..46179e8b 100644 --- a/src/cpl_cli/.cpl/project_console.py +++ b/src/cpl_cli/.cpl/project_console.py @@ -1,5 +1,3 @@ -import os - from cpl_cli.abc.project_type_abc import ProjectTypeABC from cpl_cli.configuration import WorkspaceSettings from cpl_core.utils import String diff --git a/src/cpl_cli/.cpl/schematic_enum.py b/src/cpl_cli/.cpl/schematic_enum.py index bd838159..93361f65 100644 --- a/src/cpl_cli/.cpl/schematic_enum.py +++ b/src/cpl_cli/.cpl/schematic_enum.py @@ -1,5 +1,3 @@ -import textwrap - from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC @@ -9,16 +7,16 @@ class Enum(GenerateSchematicABC): GenerateSchematicABC.__init__(self, *args) def get_code(self) -> str: - code = """\ + import textwrap + code = textwrap.dedent("""\ from enum import Enum class $Name(Enum): atr = 0 - """ - x = self.build_code_str(code, Name=self._class_name) - return x + """) + return self.build_code_str(code, Name=self._class_name) @classmethod def register(cls): diff --git a/src/cpl_core/configuration/configuration.py b/src/cpl_core/configuration/configuration.py index 7eea05ea..11ddbd32 100644 --- a/src/cpl_core/configuration/configuration.py +++ b/src/cpl_core/configuration/configuration.py @@ -22,7 +22,7 @@ from cpl_core.dependency_injection.service_provider_abc import ServiceProviderAB 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 -from cpl_core.typing import T +from cpl_core.type import T class Configuration(ConfigurationABC): diff --git a/src/cpl_core/configuration/configuration_abc.py b/src/cpl_core/configuration/configuration_abc.py index 4007a1ad..5b748ff1 100644 --- a/src/cpl_core/configuration/configuration_abc.py +++ b/src/cpl_core/configuration/configuration_abc.py @@ -6,7 +6,7 @@ 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 -from cpl_core.typing import T +from cpl_core.type import T class ConfigurationABC(ABC): diff --git a/src/cpl_core/cpl-core.json b/src/cpl_core/cpl-core.json index c4a70de3..b2260ba4 100644 --- a/src/cpl_core/cpl-core.json +++ b/src/cpl_core/cpl-core.json @@ -16,22 +16,23 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "art==5.7", - "colorama==0.4.5", + "art==5.8", + "colorama==0.4.6", "mysql-connector==2.2.9", - "psutil==5.9.2", - "packaging==21.3", + "psutil==5.9.4", + "packaging==22.0", "pynput==1.7.6", - "setuptools==65.3.0", - "tabulate==0.8.10", - "termcolor==1.1.0", - "watchdog==2.1.9", - "wheel==0.37.1" + "setuptools==65.6.3", + "tabulate==0.9.0", + "termcolor==2.1.1", + "watchdog==2.2.0", + "wheel==0.38.4" ], "DevDependencies": [ - "sphinx==5.0.2", - "sphinx_rtd_theme==1.0.0", - "myst_parser==0.18.0" + "Sphinx==5.0.2", + "sphinx-rtd-theme==1.0.0", + "myst-parser==0.18.0", + "twine==4.0.2" ], "PythonVersion": ">=3.10", "PythonPath": {}, diff --git a/src/cpl_core/typing.py b/src/cpl_core/type.py similarity index 100% rename from src/cpl_core/typing.py rename to src/cpl_core/type.py diff --git a/src/cpl_core/utils/pip.py b/src/cpl_core/utils/pip.py index f98a5884..ebf887a1 100644 --- a/src/cpl_core/utils/pip.py +++ b/src/cpl_core/utils/pip.py @@ -65,7 +65,7 @@ class Pip: """ result = None with suppress(Exception): - args = [cls._executable, "-m", "pip", "freeze"] + args = [cls._executable, "-m", "pip", "freeze", "--all"] result = subprocess.check_output( args, diff --git a/tools/set_pip_urls/set-pip-urls.json b/tools/set_pip_urls/set-pip-urls.json index aed7da44..098e63ad 100644 --- a/tools/set_pip_urls/set-pip-urls.json +++ b/tools/set_pip_urls/set-pip-urls.json @@ -16,7 +16,7 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core>=2022.12.0" + "cpl-core==2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, diff --git a/tools/set_version/set-version.json b/tools/set_version/set-version.json index 60132668..22f7d8fb 100644 --- a/tools/set_version/set-version.json +++ b/tools/set_version/set-version.json @@ -16,13 +16,13 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core>=2022.12.0", - "gitpython==3.1.27" + "cpl-core==2022.12.0", + "GitPython==3.1.29" ], + "DevDependencies": [], "PythonVersion": ">=3.10.4", "PythonPath": {}, - "Classifiers": [], - "DevDependencies": [] + "Classifiers": [] }, "BuildSettings": { "ProjectType": "console", -- 2.45.1 From 120c9e68008911fd33bb19f721b4a3467b5e9944 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 8 Dec 2022 16:08:48 +0100 Subject: [PATCH 45/63] Fixed tests #143 --- src/cpl_cli/.cpl/project_file_appsettings.py | 1 - .../unittests_cli/abc/command_test_case.py | 1 - unittests/unittests_cli/generate_test_case.py | 2 -- unittests/unittests_cli/publish_test_case.py | 33 +++---------------- 4 files changed, 4 insertions(+), 33 deletions(-) diff --git a/src/cpl_cli/.cpl/project_file_appsettings.py b/src/cpl_cli/.cpl/project_file_appsettings.py index dabf4a29..c1601d8a 100644 --- a/src/cpl_cli/.cpl/project_file_appsettings.py +++ b/src/cpl_cli/.cpl/project_file_appsettings.py @@ -18,7 +18,6 @@ class ProjectFileAppsettings(FileTemplateABC): "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" }, - "LoggingSettings": { "Path": "logs/", "Filename": "log_$start_time.log", diff --git a/unittests/unittests_cli/abc/command_test_case.py b/unittests/unittests_cli/abc/command_test_case.py index 6f216e00..100b4c89 100644 --- a/unittests/unittests_cli/abc/command_test_case.py +++ b/unittests/unittests_cli/abc/command_test_case.py @@ -14,7 +14,6 @@ class CommandTestCase(unittest.TestCase): @classmethod def setUpClass(cls): - try: if os.path.exists(PLAYGROUND_PATH): shutil.rmtree(os.path.abspath(os.path.join(PLAYGROUND_PATH))) diff --git a/unittests/unittests_cli/generate_test_case.py b/unittests/unittests_cli/generate_test_case.py index 64fa4302..a87f1c7c 100644 --- a/unittests/unittests_cli/generate_test_case.py +++ b/unittests/unittests_cli/generate_test_case.py @@ -9,7 +9,6 @@ from unittests_shared.cli_commands import CLICommands class GenerateTestCase(CommandTestCase): _project = 'test-console' _t_path = 'test' - _skip_tear_down = True @classmethod def setUpClass(cls): @@ -45,7 +44,6 @@ class GenerateTestCase(CommandTestCase): CLICommands.generate(schematic, file) file_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, excepted_path)) - print(file_path) self.assertTrue(os.path.exists(file_path)) def test_abc(self): diff --git a/unittests/unittests_cli/publish_test_case.py b/unittests/unittests_cli/publish_test_case.py index 5d6a8f75..a167fa19 100644 --- a/unittests/unittests_cli/publish_test_case.py +++ b/unittests/unittests_cli/publish_test_case.py @@ -2,43 +2,21 @@ import filecmp import json import os import shutil -import unittest from cpl_core.utils import String from unittests_cli.abc.command_test_case import CommandTestCase - from unittests_cli.constants import PLAYGROUND_PATH from unittests_shared.cli_commands import CLICommands class PublishTestCase(CommandTestCase): + _skip_tear_down = True def __init__(self, method_name: str): CommandTestCase.__init__(self, method_name) self._source = 'publish-test-source' self._project_file = f'src/{String.convert_to_snake_case(self._source)}/{self._source}.json' - def _get_project_settings(self): - with open(os.path.join(os.getcwd(), self._project_file), 'r', encoding='utf-8') as cfg: - # load json - project_json = json.load(cfg) - cfg.close() - - return project_json - - def _get_appsettings(self): - with open(os.path.join(os.getcwd(), os.path.dirname(self._project_file), 'appsettings.json'), 'r', encoding='utf-8') as cfg: - # load json - project_json = json.load(cfg) - cfg.close() - - return project_json - - def _save_project_settings(self, settings: dict): - with open(os.path.join(os.getcwd(), self._project_file), 'w', encoding='utf-8') as project_file: - project_file.write(json.dumps(settings, indent=2)) - project_file.close() - def setUp(self): if not os.path.exists(PLAYGROUND_PATH): os.makedirs(PLAYGROUND_PATH) @@ -91,11 +69,8 @@ class PublishTestCase(CommandTestCase): self.assertTrue(os.path.exists(os.path.join(setup_path, f'{String.convert_to_snake_case(self._source)}-0.0.0-py3-none-any.whl'))) self.assertTrue(os.path.exists(full_dist_path)) self.assertFalse(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) - with open(f'{full_dist_path}/{self._source}.json', 'w') as file: - file.write(json.dumps(self._get_project_settings(), indent=2)) - file.close() - with open(f'{full_dist_path}/appsettings.json', 'w') as file: - file.write(json.dumps(self._get_appsettings(), indent=2)) - file.close() + shutil.copyfile(os.path.join(os.getcwd(), self._project_file), f'{full_dist_path}/{self._source}.json') + shutil.copyfile(os.path.join(os.getcwd(), os.path.dirname(self._project_file), 'appsettings.json'), f'{full_dist_path}/appsettings.json') + self.assertTrue(self._are_dir_trees_equal(f'./src/{String.convert_to_snake_case(self._source)}', full_dist_path)) -- 2.45.1 From ac1cd9bddea3833996f8ea35fd59b536ffd37a0d Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 10 Dec 2022 21:43:46 +0100 Subject: [PATCH 46/63] Added new schematics & fixed run command #145 --- src/cpl_cli/.cpl/__init__.py | 26 ++++++++++ src/cpl_cli/.cpl/schematic_application.py | 39 ++++++++++++++ .../.cpl/schematic_application_extension.py | 35 +++++++++++++ src/cpl_cli/.cpl/schematic_schematic.py | 51 +++++++++++++++++++ src/cpl_cli/.cpl/schematic_startup.py | 39 ++++++++++++++ .../.cpl/schematic_startup_extension.py | 39 ++++++++++++++ src/cpl_cli/abc/__init__.py | 25 +++++++++ src/cpl_cli/command/generate_service.py | 7 ++- src/cpl_cli/command/run_service.py | 13 ++--- src/cpl_cli/configuration/project_settings.py | 2 +- src/cpl_cli/helper/__init__.py | 26 ++++++++++ .../live_server/live_server_service.py | 3 +- src/cpl_cli/live_server/start_executable.py | 8 +-- 13 files changed, 299 insertions(+), 14 deletions(-) create mode 100644 src/cpl_cli/.cpl/schematic_application.py create mode 100644 src/cpl_cli/.cpl/schematic_application_extension.py create mode 100644 src/cpl_cli/.cpl/schematic_schematic.py create mode 100644 src/cpl_cli/.cpl/schematic_startup.py create mode 100644 src/cpl_cli/.cpl/schematic_startup_extension.py diff --git a/src/cpl_cli/.cpl/__init__.py b/src/cpl_cli/.cpl/__init__.py index e69de29b..f96d10fb 100644 --- a/src/cpl_cli/.cpl/__init__.py +++ b/src/cpl_cli/.cpl/__init__.py @@ -0,0 +1,26 @@ +# -*- 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' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' +__version__ = '2022.12.0' + +from collections import namedtuple + + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/.cpl/schematic_application.py b/src/cpl_cli/.cpl/schematic_application.py new file mode 100644 index 00000000..60761fe6 --- /dev/null +++ b/src/cpl_cli/.cpl/schematic_application.py @@ -0,0 +1,39 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Application(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + from cpl_core.application import ApplicationABC + from cpl_core.configuration import ConfigurationABC + from cpl_core.console import Console + from cpl_core.dependency_injection import ServiceProviderABC + + + class $Name(ApplicationABC): + + def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): + ApplicationABC.__init__(self, config, services) + + def configure(self): + pass + + def main(self): + Console.write_line('Hello World') + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'application', + ['app', 'APP'] + ) diff --git a/src/cpl_cli/.cpl/schematic_application_extension.py b/src/cpl_cli/.cpl/schematic_application_extension.py new file mode 100644 index 00000000..82672aee --- /dev/null +++ b/src/cpl_cli/.cpl/schematic_application_extension.py @@ -0,0 +1,35 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class ApplicationExtension(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + from cpl_core.application import ApplicationExtensionABC + from cpl_core.configuration import ConfigurationABC + from cpl_core.dependency_injection import ServiceProviderABC + + + class $Name(ApplicationExtensionABC): + + def __init__(self): + ApplicationExtensionABC.__init__(self) + + def run(self, config: ConfigurationABC, services: ServiceProviderABC): + pass + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'application-extension', + ['appex', 'APPEX'] + ) diff --git a/src/cpl_cli/.cpl/schematic_schematic.py b/src/cpl_cli/.cpl/schematic_schematic.py new file mode 100644 index 00000000..b62d2277 --- /dev/null +++ b/src/cpl_cli/.cpl/schematic_schematic.py @@ -0,0 +1,51 @@ +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC +from cpl_core.utils import String + + +class Schematic(GenerateSchematicABC): + + def __init__(self, name: str, path: str, schematic: str): + GenerateSchematicABC.__init__(self, name, path, schematic) + self._name = f'schematic_{String.convert_to_snake_case(name)}.py' + self._path = '.cpl/' + self._class_name = String.convert_to_camel_case(name) + + def get_code(self) -> str: + code = """\ + from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + + class $Name(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + import textwrap + code = textwrap.dedent(\"\"\"\\ + from enum import Enum + + + class $Name(Enum): + + atr = 0 + \"\"\") + return self.build_code_str(code, Name=self._class_name) + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + '$NameLower', + [] + ) + """ + return self.build_code_str(code, Name=self._class_name) + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'schematic', + ['scheme', 'SCHEME'] + ) diff --git a/src/cpl_cli/.cpl/schematic_startup.py b/src/cpl_cli/.cpl/schematic_startup.py new file mode 100644 index 00000000..4be1b678 --- /dev/null +++ b/src/cpl_cli/.cpl/schematic_startup.py @@ -0,0 +1,39 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Startup(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + from cpl_core.application import StartupABC + from cpl_core.configuration import ConfigurationABC + from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC + from cpl_core.environment import ApplicationEnvironment + + + class $Name(StartupABC): + + def __init__(self): + StartupABC.__init__(self) + + def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: + return configuration + + def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: + return services.build_service_provider() + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'startup', + ['stup', 'STUP'] + ) diff --git a/src/cpl_cli/.cpl/schematic_startup_extension.py b/src/cpl_cli/.cpl/schematic_startup_extension.py new file mode 100644 index 00000000..60debcf8 --- /dev/null +++ b/src/cpl_cli/.cpl/schematic_startup_extension.py @@ -0,0 +1,39 @@ +import textwrap + +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class StartupExtension(GenerateSchematicABC): + + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + code = """\ + from cpl_core.application.startup_extension_abc import StartupExtensionABC + from cpl_core.configuration.configuration_abc import ConfigurationABC + from cpl_core.dependency_injection.service_collection_abc import ServiceCollectionABC + from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC + + + class $Name(StartupExtensionABC): + + def __init__(self): + pass + + def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): + pass + + def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): + pass + """ + x = self.build_code_str(code, Name=self._class_name) + return x + + @classmethod + def register(cls): + GenerateSchematicABC.register( + cls, + 'startup-extension', + ['stupex', 'STUPEX'] + ) diff --git a/src/cpl_cli/abc/__init__.py b/src/cpl_cli/abc/__init__.py index 425ab6c1..aa793603 100644 --- a/src/cpl_cli/abc/__init__.py +++ b/src/cpl_cli/abc/__init__.py @@ -1 +1,26 @@ +# -*- 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.abc' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' +__version__ = '2022.12.0' + +from collections import namedtuple + + # imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index fa511a58..1b686102 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -35,11 +35,14 @@ class GenerateService(CommandABC): self._env = self._config.environment self._schematics = {} - for package_name in Dependencies.get_cpl_packages(): - package = importlib.import_module(String.convert_to_snake_case(package_name[0])) + for package_name, version in Dependencies.get_cpl_packages(): + if package_name == 'cpl-cli': + continue + package = importlib.import_module(String.convert_to_snake_case(package_name)) self._read_custom_schematics_from_path(os.path.dirname(package.__file__)) self._read_custom_schematics_from_path(self._env.working_directory) + self._read_custom_schematics_from_path(self._env.runtime_directory) if len(GenerateSchematicABC.__subclasses__()) == 0: Console.error(f'No schematics found in template directory: .cpl') diff --git a/src/cpl_cli/command/run_service.py b/src/cpl_cli/command/run_service.py index e3740e00..8e2fe2b8 100644 --- a/src/cpl_cli/command/run_service.py +++ b/src/cpl_cli/command/run_service.py @@ -2,18 +2,18 @@ import os import sys import textwrap -from cpl_cli import Error +from cpl_cli.error import Error from cpl_cli.command_abc import CommandABC -from cpl_cli.configuration import WorkspaceSettings +from cpl_cli.configuration.workspace_settings import WorkspaceSettings from cpl_cli.configuration.build_settings import BuildSettings from cpl_cli.configuration.project_settings import ProjectSettings from cpl_cli.live_server.start_executable import StartExecutable -from cpl_cli.publish import PublisherService -from cpl_core.configuration import ConfigurationABC +from cpl_cli.publish.publisher_service import PublisherService +from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.console.console import Console -from cpl_core.dependency_injection import ServiceProviderABC +from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC -from cpl_core.utils import String +from cpl_core.utils.string import String class RunService(CommandABC): @@ -91,6 +91,7 @@ class RunService(CommandABC): self._env.set_working_directory(self._src_dir) self._publisher.build() + self._env.set_working_directory(self._src_dir) self._src_dir = os.path.abspath(os.path.join( self._src_dir, self._build_settings.output_path, diff --git a/src/cpl_cli/configuration/project_settings.py b/src/cpl_cli/configuration/project_settings.py index 8c359cd4..5b90399d 100644 --- a/src/cpl_cli/configuration/project_settings.py +++ b/src/cpl_cli/configuration/project_settings.py @@ -123,7 +123,7 @@ class ProjectSettings(ConfigurationModelABC): self._python_path = settings[ProjectSettingsNameEnum.python_path.value] if ProjectSettingsNameEnum.python_path.value in settings and sys.platform in settings[ProjectSettingsNameEnum.python_path.value]: - path = settings[ProjectSettingsNameEnum.python_path.value][sys.platform] + path = f'{settings[ProjectSettingsNameEnum.python_path.value][sys.platform]}/bin/python' if path == '' or path is None: Error.warn(f'{ProjectSettingsNameEnum.python_path.value} not set') path = sys.executable diff --git a/src/cpl_cli/helper/__init__.py b/src/cpl_cli/helper/__init__.py index e69de29b..9bc349e4 100644 --- a/src/cpl_cli/helper/__init__.py +++ b/src/cpl_cli/helper/__init__.py @@ -0,0 +1,26 @@ +# -*- 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.helper' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' +__version__ = '2022.12.0' + +from collections import namedtuple + + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_cli/live_server/live_server_service.py b/src/cpl_cli/live_server/live_server_service.py index 7eadc8cc..a9f6ffd3 100644 --- a/src/cpl_cli/live_server/live_server_service.py +++ b/src/cpl_cli/live_server/live_server_service.py @@ -103,9 +103,8 @@ class LiveServerService(FileSystemEventHandler): return self._env.set_working_directory(self._src_dir) - Console.disable() self._publisher.build() - Console.enable() + self._env.set_working_directory(self._src_dir) self._wd = os.path.abspath(os.path.join( self._src_dir, self._build_settings.output_path, diff --git a/src/cpl_cli/live_server/start_executable.py b/src/cpl_cli/live_server/start_executable.py index 426f03e7..a72dc402 100644 --- a/src/cpl_cli/live_server/start_executable.py +++ b/src/cpl_cli/live_server/start_executable.py @@ -1,13 +1,12 @@ import os import subprocess import sys -import threading from datetime import datetime from cpl_core.console.console import Console from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC -from cpl_cli.configuration import BuildSettings +from cpl_cli.configuration.build_settings import BuildSettings class StartExecutable: @@ -43,7 +42,10 @@ class StartExecutable: self._env_vars['VIRTUAL_ENV'] = path def run(self, args: list[str], executable: str, path: str, output=True): - self._executable = os.path.abspath(executable) + self._executable = os.path.abspath(os.path.join(self._env.working_directory, executable)) + if not os.path.exists(self._executable): + Console.error(f'Executable not found') + return main = self._build_settings.main if '.' in self._build_settings.main: -- 2.45.1 From 85f75b4677606c2989acc1e0ba1d35372127ecb9 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 11 Dec 2022 08:58:55 +0100 Subject: [PATCH 47/63] Fixed group by --- src/cpl_query/base/queryable_abc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpl_query/base/queryable_abc.py b/src/cpl_query/base/queryable_abc.py index b14f63b2..be201073 100644 --- a/src/cpl_query/base/queryable_abc.py +++ b/src/cpl_query/base/queryable_abc.py @@ -221,7 +221,7 @@ class QueryableABC(Sequence): for v in self: value = _func(v) - if v not in groups: + if value not in groups: groups[value] = [] groups[value].append(v) -- 2.45.1 From 002ba6b4e057e525b1a4fae181d1ae80b5d030f9 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 11 Dec 2022 09:16:38 +0100 Subject: [PATCH 48/63] Added split function --- cpl-workspace.json | 4 ++-- src/cpl_discord/.cpl/__init__.py | 26 ++++++++++++++++++++++ src/cpl_query/__init__.py | 4 ++-- src/cpl_query/base/__init__.py | 4 ++-- src/cpl_query/base/queryable_abc.py | 33 ++++++++++++++++++++++++++++ src/cpl_query/cpl-query.json | 2 +- src/cpl_query/enumerable/__init__.py | 4 ++-- src/cpl_query/extension/__init__.py | 4 ++-- src/cpl_query/iterable/__init__.py | 4 ++-- 9 files changed, 72 insertions(+), 13 deletions(-) diff --git a/cpl-workspace.json b/cpl-workspace.json index 6d34e2bd..0110e201 100644 --- a/cpl-workspace.json +++ b/cpl-workspace.json @@ -20,10 +20,10 @@ "hello-world": "echo 'Hello World'", "sv": "cpl set-version", - "set-version": "cpl run set-version $ARGS; echo '';", + "set-version": "cpl run set-version --dev $ARGS; echo '';", "spu": "cpl set-pip-urls", - "set-pip-urls": "cpl run set-pip-urls $ARGS; echo '';", + "set-pip-urls": "cpl run set-pip-urls --dev $ARGS; echo '';", "docs-build": "echo 'Build Documentation'; cpl db-core; cpl db-discord; cpl db-query; cpl db-translation; cd docs/; make clean; make html; # rm source/cpl_query.tests.rst;", "db-core": "cd docs/; sphinx-apidoc -o source/ ../src/cpl_core; cd ../", diff --git a/src/cpl_discord/.cpl/__init__.py b/src/cpl_discord/.cpl/__init__.py index e69de29b..a25e9f71 100644 --- a/src/cpl_discord/.cpl/__init__.py +++ b/src/cpl_discord/.cpl/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +""" +cpl-discord sh-edraft Common Python library Discord +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Common Python library link between discord.py and CPL + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'cpl_discord' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '2022.12.0' + +from collections import namedtuple + + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='2022', minor='12', micro='0') diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 90568d75..91a385f1 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post1' +__version__ = '2022.12.1.post2' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='1.post2') diff --git a/src/cpl_query/base/__init__.py b/src/cpl_query/base/__init__.py index 6c298ed1..1491112d 100644 --- a/src/cpl_query/base/__init__.py +++ b/src/cpl_query/base/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post1' +__version__ = '2022.12.1.post2' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='1.post2') diff --git a/src/cpl_query/base/queryable_abc.py b/src/cpl_query/base/queryable_abc.py index be201073..c5c8f040 100644 --- a/src/cpl_query/base/queryable_abc.py +++ b/src/cpl_query/base/queryable_abc.py @@ -475,6 +475,39 @@ class QueryableABC(Sequence): return result + def split(self, _func: Callable) -> 'QueryableABC': + r"""Splits the list by given function + + + Parameter + --------- + func: :class:`Callable` + seperator + + Returns + ------- + :class: `cpl_query.base.queryable_abc.QueryableABC` + """ + groups = [] + group = [] + for x in self: + v = _func(x) + if x == v: + groups.append(group) + group = [] + + group.append(x) + + groups.append(group) + + query_groups = [] + for g in groups: + if len(g) == 0: + continue + query_groups.append(type(self)(self._type, g)) + + return type(self)(self._type, query_groups) + def take(self, _index: int) -> 'QueryableABC': r"""Takes all elements from index diff --git a/src/cpl_query/cpl-query.json b/src/cpl_query/cpl-query.json index 198b1699..b06705f3 100644 --- a/src/cpl_query/cpl-query.json +++ b/src/cpl_query/cpl-query.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "1.post1" + "Micro": "0" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index 13ad7c57..7ea6dfcf 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.enumerable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post1' +__version__ = '2022.12.1.post2' from collections import namedtuple @@ -25,4 +25,4 @@ from .enumerable import Enumerable from .enumerable_abc import EnumerableABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='1.post2') diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index 9851b59c..f0ad933a 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post1' +__version__ = '2022.12.1.post2' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .list import List VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='1.post2') diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index 3855dde6..abba389e 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.iterable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post1' +__version__ = '2022.12.1.post2' from collections import namedtuple @@ -25,4 +25,4 @@ from .iterable_abc import IterableABC from .iterable import Iterable VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post1') +version_info = VersionInfo(major='2022', minor='12', micro='1.post2') -- 2.45.1 From cbae40ef4d240da0a07b42885f8dfbb10f8c478c Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 11 Dec 2022 10:44:23 +0100 Subject: [PATCH 49/63] Fixed skip function --- src/cpl_query/__init__.py | 4 ++-- src/cpl_query/base/__init__.py | 4 ++-- src/cpl_query/base/queryable_abc.py | 2 +- src/cpl_query/cpl-query.json | 2 +- src/cpl_query/enumerable/__init__.py | 4 ++-- src/cpl_query/extension/__init__.py | 4 ++-- src/cpl_query/iterable/__init__.py | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 91a385f1..5d622bbe 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post2' +__version__ = '2022.12.1.post3' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post2') +version_info = VersionInfo(major='2022', minor='12', micro='1.post3') diff --git a/src/cpl_query/base/__init__.py b/src/cpl_query/base/__init__.py index 1491112d..6931da1c 100644 --- a/src/cpl_query/base/__init__.py +++ b/src/cpl_query/base/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post2' +__version__ = '2022.12.1.post3' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post2') +version_info = VersionInfo(major='2022', minor='12', micro='1.post3') diff --git a/src/cpl_query/base/queryable_abc.py b/src/cpl_query/base/queryable_abc.py index c5c8f040..2a058959 100644 --- a/src/cpl_query/base/queryable_abc.py +++ b/src/cpl_query/base/queryable_abc.py @@ -431,7 +431,7 @@ class QueryableABC(Sequence): if _index is None: raise ArgumentNoneException(ExceptionArgument.index) - return type(self)(self.type, values=self[_index:]) + return type(self)(self.type, self[_index:]) def skip_last(self, _index: int) -> 'QueryableABC': r"""Skips all elements after index diff --git a/src/cpl_query/cpl-query.json b/src/cpl_query/cpl-query.json index b06705f3..04d3236a 100644 --- a/src/cpl_query/cpl-query.json +++ b/src/cpl_query/cpl-query.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "0" + "Micro": "1.post3" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index 7ea6dfcf..1202a451 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.enumerable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post2' +__version__ = '2022.12.1.post3' from collections import namedtuple @@ -25,4 +25,4 @@ from .enumerable import Enumerable from .enumerable_abc import EnumerableABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post2') +version_info = VersionInfo(major='2022', minor='12', micro='1.post3') diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index f0ad933a..4295e847 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post2' +__version__ = '2022.12.1.post3' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .list import List VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post2') +version_info = VersionInfo(major='2022', minor='12', micro='1.post3') diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index abba389e..8be6be19 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.iterable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post2' +__version__ = '2022.12.1.post3' from collections import namedtuple @@ -25,4 +25,4 @@ from .iterable_abc import IterableABC from .iterable import Iterable VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post2') +version_info = VersionInfo(major='2022', minor='12', micro='1.post3') -- 2.45.1 From 05c33990bb8c39db576631dfeb97de9ebff738bc Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 12 Dec 2022 20:59:04 +0100 Subject: [PATCH 50/63] Performance improvements --- src/cpl_query/base/queryable_abc.py | 79 +++++++++---------- src/cpl_query/base/sequence.py | 35 ++++---- src/cpl_query/cpl-query.json | 2 +- src/cpl_query/extension/list.py | 13 ++- src/cpl_query/iterable/iterable.py | 4 +- src/cpl_query/iterable/iterable_abc.py | 10 +-- .../enumerable_query_test_case.py | 6 +- .../iterable_query_test_case.py | 2 +- 8 files changed, 79 insertions(+), 72 deletions(-) diff --git a/src/cpl_query/base/queryable_abc.py b/src/cpl_query/base/queryable_abc.py index 2a058959..e7d8f5ec 100644 --- a/src/cpl_query/base/queryable_abc.py +++ b/src/cpl_query/base/queryable_abc.py @@ -1,17 +1,17 @@ -from typing import Optional, Callable, Union +from typing import Optional, Callable, Union, Iterable from cpl_query._helper import is_number from cpl_query.base.sequence import Sequence from cpl_query.exceptions import InvalidTypeException, ArgumentNoneException, ExceptionArgument, IndexOutOfRangeException -def _default_lambda(x: object): +def _default_lambda(x: object) -> object: return x class QueryableABC(Sequence): - def __init__(self, t: type = None, values: list = None): + def __init__(self, t: type, values: Iterable = None): Sequence.__init__(self, t, values) def all(self, _func: Callable = None) -> bool: @@ -97,7 +97,7 @@ class QueryableABC(Sequence): if _func is None: return self.__len__() - return self.where(_func).__len__() + return self.where(_func).count() def distinct(self, _func: Callable = None) -> 'QueryableABC': r"""Returns list without redundancies @@ -144,7 +144,7 @@ class QueryableABC(Sequence): if _index < 0 or _index >= self.count(): raise IndexOutOfRangeException - result = self[_index] + result = self._values[_index] if result is None: raise IndexOutOfRangeException @@ -166,7 +166,7 @@ class QueryableABC(Sequence): raise ArgumentNoneException(ExceptionArgument.index) try: - return self[_index] + return self._values[_index] except IndexError: return None @@ -177,10 +177,10 @@ class QueryableABC(Sequence): ------- First element of list: any """ - if len(self) == 0: + if self.count() == 0: raise IndexOutOfRangeException() - return self[0] + return self._values[0] def first_or_default(self) -> any: r"""Returns first element or None @@ -189,10 +189,10 @@ class QueryableABC(Sequence): ------- First element of list: Optional[any] """ - if len(self) == 0: + if self.count() == 0: return None - return self[0] + return self._values[0] def for_each(self, _func: Callable = None): r"""Runs given function for each element of list @@ -221,14 +221,14 @@ class QueryableABC(Sequence): for v in self: value = _func(v) - if value not in groups: + if v not in groups: groups[value] = [] groups[value].append(v) v = [] for g in groups.values(): - v.append(type(self)(None, g)) + v.append(type(self)(object, g)) x = type(self)(type(self), v) return x @@ -239,10 +239,10 @@ class QueryableABC(Sequence): ------- Last element of list: any """ - if len(self) == 0: + if self.count() == 0: raise IndexOutOfRangeException() - return self[len(self) - 1] + return self._values[self.count() - 1] def last_or_default(self) -> any: r"""Returns last element or None @@ -251,12 +251,12 @@ class QueryableABC(Sequence): ------- Last element of list: Optional[any] """ - if len(self) == 0: + if self.count() == 0: return None - return self[len(self) - 1] + return self._values[self.count() - 1] - def max(self, _func: Callable = None) -> Union[int, float, complex]: + def max(self, _func: Callable = None) -> object: r"""Returns the highest value Parameter @@ -266,7 +266,7 @@ class QueryableABC(Sequence): Returns ------- - Union[int, float, complex] + object """ if _func is None and not is_number(self.type): raise InvalidTypeException() @@ -295,7 +295,7 @@ class QueryableABC(Sequence): else (float(result[i - 1]) + float(result[i])) / float(2) ) - def min(self, _func: Callable = None) -> Union[int, float, complex]: + def min(self, _func: Callable = None) -> object: r"""Returns the lowest value Parameter @@ -305,7 +305,7 @@ class QueryableABC(Sequence): Returns ------- - Union[int, float, complex] + object """ if _func is None and not is_number(self.type): raise InvalidTypeException() @@ -358,7 +358,7 @@ class QueryableABC(Sequence): ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - return type(self)(self._type, list(reversed(self))) + return type(self)(self._type, reversed(self._values)) def select(self, _func: Callable) -> 'QueryableABC': r"""Formats each element of list to a given format @@ -370,7 +370,7 @@ class QueryableABC(Sequence): if _func is None: _func = _default_lambda - return type(self)(any, [_func(_o) for _o in self]) + return type(self)(object, [_func(_o) for _o in self]) def select_many(self, _func: Callable) -> 'QueryableABC': r"""Flattens resulting lists to one @@ -381,7 +381,7 @@ class QueryableABC(Sequence): """ # The line below is pain. I don't understand anything of it... # written on 09.11.2022 by Sven Heidemann - return type(self)(any, [_a for _o in self for _a in _func(_o)]) + return type(self)(object, [_a for _o in self for _a in _func(_o)]) def single(self) -> any: r"""Returns one single element of list @@ -395,12 +395,12 @@ class QueryableABC(Sequence): ArgumentNoneException: when argument is None Exception: when argument is None or found more than one element """ - if len(self) > 1: + if self.count() > 1: raise Exception('Found more than one element') - elif len(self) == 0: + elif self.count() == 0: raise Exception('Found no element') - return self[0] + return self._values[0] def single_or_default(self) -> Optional[any]: r"""Returns one single element of list @@ -409,12 +409,12 @@ class QueryableABC(Sequence): ------- Found value: Optional[any] """ - if len(self) > 1: + if self.count() > 1: raise Exception('Index out of range') - elif len(self) == 0: + elif self.count() == 0: return None - return self[0] + return self._values[0] def skip(self, _index: int) -> 'QueryableABC': r"""Skips all elements from index @@ -431,7 +431,7 @@ class QueryableABC(Sequence): if _index is None: raise ArgumentNoneException(ExceptionArgument.index) - return type(self)(self.type, self[_index:]) + return type(self)(self.type, self._values[_index:]) def skip_last(self, _index: int) -> 'QueryableABC': r"""Skips all elements after index @@ -448,8 +448,8 @@ class QueryableABC(Sequence): if _index is None: raise ArgumentNoneException(ExceptionArgument.index) - index = len(self) - _index - return type(self)(self._type, self[:index]) + index = self.count() - _index + return type(self)(self._type, self._values[:index]) def sum(self, _func: Callable = None) -> Union[int, float, complex]: r"""Sum of all values @@ -523,7 +523,7 @@ class QueryableABC(Sequence): if _index is None: raise ArgumentNoneException(ExceptionArgument.index) - return type(self)(self._type, self[:_index]) + return type(self)(self._type, self._values[:_index]) def take_last(self, _index: int) -> 'QueryableABC': r"""Takes all elements after index @@ -537,12 +537,12 @@ class QueryableABC(Sequence): ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - index = len(self) - _index + index = self.count() - _index - if index >= len(self) or index < 0: + if index >= self.count() or index < 0: raise IndexOutOfRangeException() - return type(self)(self._type, self[index:]) + return type(self)(self._type, self._values[index:]) def where(self, _func: Callable = None) -> 'QueryableABC': r"""Select element by function @@ -562,9 +562,4 @@ class QueryableABC(Sequence): if _func is None: _func = _default_lambda - result = [] - for element in self: - if _func(element): - result.append(element) - - return type(self)(self.type, result) + return type(self)(self.type, filter(_func, self)) diff --git a/src/cpl_query/base/sequence.py b/src/cpl_query/base/sequence.py index 15f7fc4a..cb97b1b3 100644 --- a/src/cpl_query/base/sequence.py +++ b/src/cpl_query/base/sequence.py @@ -1,29 +1,36 @@ -from abc import ABC, abstractmethod +from abc import abstractmethod, ABC +from typing import Iterable -class Sequence(list): +class Sequence(ABC): @abstractmethod - def __init__(self, t: type = None, values: list = None): - list.__init__(self) - ABC.__init__(self) - values = [] if values is None else values - list.__init__(self, values) + def __init__(self, t: type, values: Iterable = None): + if values is None: + values = [] - if t is None and len(values) > 0: - t = type(values[0]) + self._values = list(values) if t is None: - t = any + t = object self._type = t + def __iter__(self): + return iter(self._values) + + def __next__(self): + return next(iter(self._values)) + + def __len__(self): + return self.to_list().__len__() + @classmethod def __class_getitem__(cls, _t: type): return _t def __repr__(self): - return f'<{type(self).__name__} {list(self).__repr__()}>' + return f'<{type(self).__name__} {self.to_list().__repr__()}>' @property def type(self) -> type: @@ -43,7 +50,7 @@ class Sequence(list): ------- :class: `list` """ - return [x for x in self] + return [x for x in self._values] def copy(self) -> 'Sequence': r"""Creates a copy of sequence @@ -62,7 +69,7 @@ class Sequence(list): ------- Sequence object that contains no elements """ - return cls() + return cls(object, []) def index_of(self, _object: object) -> int: r"""Returns the index of given element @@ -83,4 +90,4 @@ class Sequence(list): @classmethod def range(cls, start: int, length: int) -> 'Sequence': - return cls(int, list(range(start, length))) + return cls(int, range(start, length)) diff --git a/src/cpl_query/cpl-query.json b/src/cpl_query/cpl-query.json index 04d3236a..48aede0d 100644 --- a/src/cpl_query/cpl-query.json +++ b/src/cpl_query/cpl-query.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "1.post3" + "Micro": "2" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_query/extension/list.py b/src/cpl_query/extension/list.py index 62e0d5b4..30722127 100644 --- a/src/cpl_query/extension/list.py +++ b/src/cpl_query/extension/list.py @@ -1,4 +1,4 @@ -from typing import Iterable as IterableType +from typing import Iterator from cpl_query.iterable.iterable import Iterable @@ -7,9 +7,18 @@ class List(Iterable): r"""Implementation of :class: `cpl_query.extension.iterable.Iterable` """ - def __init__(self, t: type = None, values: IterableType = None): + def __init__(self, t: type = None, values: Iterator = None): Iterable.__init__(self, t, values) + def __getitem__(self, *args): + return self._values.__getitem__(*args) + + def __setitem__(self, *args): + self._values.__setitem__(*args) + + def __delitem__(self, *args): + self._values.__delitem__(*args) + def to_enumerable(self) -> 'EnumerableABC': r"""Converts :class: `cpl_query.iterable.iterable_abc.IterableABC` to :class: `cpl_query.enumerable.enumerable_abc.EnumerableABC` diff --git a/src/cpl_query/iterable/iterable.py b/src/cpl_query/iterable/iterable.py index 38367269..07ec5b8d 100644 --- a/src/cpl_query/iterable/iterable.py +++ b/src/cpl_query/iterable/iterable.py @@ -1,4 +1,4 @@ -from typing import Iterable as IterableType +from typing import Iterable as TIterable from cpl_query.iterable.iterable_abc import IterableABC @@ -9,5 +9,5 @@ def _default_lambda(x: object): class Iterable(IterableABC): - def __init__(self, t: type = None, values: IterableType = None): + def __init__(self, t: type = None, values: TIterable = None): IterableABC.__init__(self, t, values) diff --git a/src/cpl_query/iterable/iterable_abc.py b/src/cpl_query/iterable/iterable_abc.py index 571a61e1..5640230b 100644 --- a/src/cpl_query/iterable/iterable_abc.py +++ b/src/cpl_query/iterable/iterable_abc.py @@ -12,10 +12,6 @@ class IterableABC(QueryableABC): def __init__(self, t: type = None, values: Iterable = None): QueryableABC.__init__(self, t, values) - @property - def type(self) -> type: - return self._type - def __str__(self): return str(self.to_list()) @@ -30,7 +26,7 @@ class IterableABC(QueryableABC): value """ self._check_type(_object) - super().append(_object) + self._values.append(_object) def extend(self, __iterable: Iterable) -> 'IterableABC': r"""Adds elements of given list to list @@ -54,7 +50,7 @@ class IterableABC(QueryableABC): if _object not in self: raise ValueError - super().remove(_object) + self._values.remove(_object) def remove_at(self, _index: int): r"""Removes element from list @@ -63,7 +59,7 @@ class IterableABC(QueryableABC): _object: :class:`object` value """ - self.pop(_index) + self._values.pop(_index) def to_enumerable(self) -> 'EnumerableABC': r"""Converts :class: `cpl_query.iterable.iterable_abc.IterableABC` to :class: `cpl_query.enumerable.enumerable_abc.EnumerableABC` diff --git a/unittests/unittests_query/enumerable_query_test_case.py b/unittests/unittests_query/enumerable_query_test_case.py index ffe71576..89db64d1 100644 --- a/unittests/unittests_query/enumerable_query_test_case.py +++ b/unittests/unittests_query/enumerable_query_test_case.py @@ -183,7 +183,7 @@ class EnumerableQueryTestCase(unittest.TestCase): res = self._tests.max(lambda u: u.address.nr) self.assertEqual(res, self._t_user.address.nr) - tests = Enumerable(values=list(range(0, 100))) + tests = Enumerable(int, list(range(0, 100))) self.assertEqual(99, tests.max()) def invalid(): @@ -196,7 +196,7 @@ class EnumerableQueryTestCase(unittest.TestCase): res = self._tests.min(lambda u: u.address.nr) self.assertEqual(1, res) - tests = Enumerable(values=list(range(0, 100))) + tests = Enumerable(int, list(range(0, 100))) self.assertEqual(0, tests.min()) def invalid(): @@ -319,7 +319,7 @@ class EnumerableQueryTestCase(unittest.TestCase): self.assertEqual(s_res, res) - tests = Enumerable(values=list(range(0, 100))) + tests = Enumerable(int, list(range(0, 100))) self.assertEqual(0, tests.min()) def invalid(): diff --git a/unittests/unittests_query/iterable_query_test_case.py b/unittests/unittests_query/iterable_query_test_case.py index 6dfa36f0..0e64ecbb 100644 --- a/unittests/unittests_query/iterable_query_test_case.py +++ b/unittests/unittests_query/iterable_query_test_case.py @@ -351,7 +351,7 @@ class IterableQueryTestCase(unittest.TestCase): self.assertEqual(s_res, res) - tests = List(values=list(range(0, 100))) + tests = List(int, list(range(0, 100))) self.assertEqual(0, tests.min()) def invalid(): -- 2.45.1 From 086fc75fecd7164e46a4b964cb2fb096de7bb673 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 12 Dec 2022 20:59:43 +0100 Subject: [PATCH 51/63] Build cpl query --- src/cpl_query/__init__.py | 4 ++-- src/cpl_query/base/__init__.py | 4 ++-- src/cpl_query/enumerable/__init__.py | 4 ++-- src/cpl_query/extension/__init__.py | 4 ++-- src/cpl_query/iterable/__init__.py | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 5d622bbe..1924e2c8 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post3' +__version__ = '2022.12.2' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post3') +version_info = VersionInfo(major='2022', minor='12', micro='2') diff --git a/src/cpl_query/base/__init__.py b/src/cpl_query/base/__init__.py index 6931da1c..3b768bbd 100644 --- a/src/cpl_query/base/__init__.py +++ b/src/cpl_query/base/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post3' +__version__ = '2022.12.2' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post3') +version_info = VersionInfo(major='2022', minor='12', micro='2') diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index 1202a451..5009e045 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.enumerable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post3' +__version__ = '2022.12.2' from collections import namedtuple @@ -25,4 +25,4 @@ from .enumerable import Enumerable from .enumerable_abc import EnumerableABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post3') +version_info = VersionInfo(major='2022', minor='12', micro='2') diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index 4295e847..48dbc44c 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post3' +__version__ = '2022.12.2' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .list import List VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post3') +version_info = VersionInfo(major='2022', minor='12', micro='2') diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index 8be6be19..77d1c07f 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.iterable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.1.post3' +__version__ = '2022.12.2' from collections import namedtuple @@ -25,4 +25,4 @@ from .iterable_abc import IterableABC from .iterable import Iterable VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='1.post3') +version_info = VersionInfo(major='2022', minor='12', micro='2') -- 2.45.1 From d5e89d6e2a200037f4de18eb403135db72f3c619 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 18 Dec 2022 12:03:41 +0100 Subject: [PATCH 52/63] Fixed cpl cli build #144 --- src/cpl_cli/.cpl/__init__.py | 4 ++-- src/cpl_cli/__init__.py | 4 ++-- src/cpl_cli/_templates/__init__.py | 4 ++-- src/cpl_cli/_templates/build/__init__.py | 4 ++-- src/cpl_cli/_templates/publish/__init__.py | 4 ++-- src/cpl_cli/abc/__init__.py | 4 ++-- src/cpl_cli/appsettings.json | 2 +- src/cpl_cli/command/__init__.py | 4 ++-- src/cpl_cli/command/generate_service.py | 5 ++--- src/cpl_cli/configuration/__init__.py | 4 ++-- src/cpl_cli/cpl-cli.json | 7 ++++--- src/cpl_cli/helper/__init__.py | 4 ++-- src/cpl_cli/live_server/__init__.py | 4 ++-- src/cpl_cli/main.py | 2 ++ src/cpl_cli/migrations/__init__.py | 4 ++-- src/cpl_cli/migrations/base/__init__.py | 4 ++-- src/cpl_cli/migrations/service/__init__.py | 4 ++-- src/cpl_cli/publish/__init__.py | 4 ++-- src/cpl_cli/source_creator/__init__.py | 4 ++-- src/cpl_cli/validators/__init__.py | 4 ++-- tools/set_version/application.py | 11 ++++++++--- 21 files changed, 49 insertions(+), 42 deletions(-) diff --git a/src/cpl_cli/.cpl/__init__.py b/src/cpl_cli/.cpl/__init__.py index f96d10fb..384e3fa0 100644 --- a/src/cpl_cli/.cpl/__init__.py +++ b/src/cpl_cli/.cpl/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/__init__.py b/src/cpl_cli/__init__.py index a2165c57..d5c71351 100644 --- a/src/cpl_cli/__init__.py +++ b/src/cpl_cli/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -28,4 +28,4 @@ from .main import main from .startup import Startup VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/_templates/__init__.py b/src/cpl_cli/_templates/__init__.py index 46d358eb..506557ff 100644 --- a/src/cpl_cli/_templates/__init__.py +++ b/src/cpl_cli/_templates/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/_templates/build/__init__.py b/src/cpl_cli/_templates/build/__init__.py index 9bc534ca..e006bf80 100644 --- a/src/cpl_cli/_templates/build/__init__.py +++ b/src/cpl_cli/_templates/build/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.build' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/_templates/publish/__init__.py b/src/cpl_cli/_templates/publish/__init__.py index 1778daf8..46a92128 100644 --- a/src/cpl_cli/_templates/publish/__init__.py +++ b/src/cpl_cli/_templates/publish/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/abc/__init__.py b/src/cpl_cli/abc/__init__.py index aa793603..609ba749 100644 --- a/src/cpl_cli/abc/__init__.py +++ b/src/cpl_cli/abc/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.abc' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/appsettings.json b/src/cpl_cli/appsettings.json index f4dbfbf1..eb80fe1d 100644 --- a/src/cpl_cli/appsettings.json +++ b/src/cpl_cli/appsettings.json @@ -1,5 +1,5 @@ { "CLI": { - "PipPath": "https://pip.sh-edraft.de" + "PipPath": "https://pip-dev.sh-edraft.de" } } \ No newline at end of file diff --git a/src/cpl_cli/command/__init__.py b/src/cpl_cli/command/__init__.py index 49b2f0c6..3cb16ed4 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.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -29,4 +29,4 @@ from .publish_service import PublishService from .version_service import VersionService VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index 1b686102..eb42bd04 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -195,9 +195,8 @@ class GenerateService(CommandABC): schematic = s break - schematic_by_alias = self._get_schematic_by_alias(args[0]) - if schematic is None and len(args) >= 1 and (args[0] in self._schematics or schematic_by_alias != args[0]): - schematic = schematic_by_alias + if schematic is None and len(args) >= 1 and (args[0] in self._schematics or self._get_schematic_by_alias(args[0]) != args[0]): + schematic = self._get_schematic_by_alias(args[0]) self._config.add_configuration(schematic, args[1]) value = args[1] diff --git a/src/cpl_cli/configuration/__init__.py b/src/cpl_cli/configuration/__init__.py index 7b7a2e32..cd0a9ef5 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.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -31,4 +31,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='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/cpl-cli.json b/src/cpl_cli/cpl-cli.json index 3c57ece9..04b7fd6b 100644 --- a/src/cpl_cli/cpl-cli.json +++ b/src/cpl_cli/cpl-cli.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "0" + "Micro": "dev144" }, "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.12.0" + "cpl-core>=2022.12.dev144" ], "DevDependencies": [], "PythonVersion": ">=3.10", @@ -42,7 +42,8 @@ ], "PackageData": { "cpl_cli": [ - "*.json" + "*.json", + ".cpl/*.py" ] }, "ProjectReferences": [] diff --git a/src/cpl_cli/helper/__init__.py b/src/cpl_cli/helper/__init__.py index 9bc349e4..0db1862a 100644 --- a/src/cpl_cli/helper/__init__.py +++ b/src/cpl_cli/helper/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.helper' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/live_server/__init__.py b/src/cpl_cli/live_server/__init__.py index de32b9f4..4b74e088 100644 --- a/src/cpl_cli/live_server/__init__.py +++ b/src/cpl_cli/live_server/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.live_server' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/main.py b/src/cpl_cli/main.py index df1c6a9a..4bf4d83d 100644 --- a/src/cpl_cli/main.py +++ b/src/cpl_cli/main.py @@ -9,6 +9,7 @@ from cpl_cli.startup_migration_extension import StartupMigrationExtension from cpl_cli.startup_workspace_extension import StartupWorkspaceExtension from cpl_core.application.application_builder import ApplicationBuilder from cpl_core.application.startup_extension_abc import StartupExtensionABC +from cpl_core.console import Console def get_startup_extensions() -> list[Type[StartupExtensionABC]]: @@ -40,6 +41,7 @@ def main(): app_builder.use_extension(extension) app_builder.build().run() + Console.write_line() if __name__ == '__main__': diff --git a/src/cpl_cli/migrations/__init__.py b/src/cpl_cli/migrations/__init__.py index 83b95050..fca9b7d7 100644 --- a/src/cpl_cli/migrations/__init__.py +++ b/src/cpl_cli/migrations/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.migrations' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/migrations/base/__init__.py b/src/cpl_cli/migrations/base/__init__.py index db9830c8..2872e0a6 100644 --- a/src/cpl_cli/migrations/base/__init__.py +++ b/src/cpl_cli/migrations/base/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.migrations.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/migrations/service/__init__.py b/src/cpl_cli/migrations/service/__init__.py index ad460fb4..6a9679f5 100644 --- a/src/cpl_cli/migrations/service/__init__.py +++ b/src/cpl_cli/migrations/service/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.migrations.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/publish/__init__.py b/src/cpl_cli/publish/__init__.py index 4ddae317..51b16998 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.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -25,4 +25,4 @@ from .publisher_abc import PublisherABC from .publisher_service import PublisherService VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/source_creator/__init__.py b/src/cpl_cli/source_creator/__init__.py index c15325b7..102b512c 100644 --- a/src/cpl_cli/source_creator/__init__.py +++ b/src/cpl_cli/source_creator/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.source_creator' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/src/cpl_cli/validators/__init__.py b/src/cpl_cli/validators/__init__.py index cf262422..f782995b 100644 --- a/src/cpl_cli/validators/__init__.py +++ b/src/cpl_cli/validators/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.validators' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.dev144' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='dev144') diff --git a/tools/set_version/application.py b/tools/set_version/application.py index 6b61c7f1..c4cc9763 100644 --- a/tools/set_version/application.py +++ b/tools/set_version/application.py @@ -56,7 +56,14 @@ class Application(ApplicationABC): return try: - if branch.startswith('#'): + if suffix != '': + self._configuration.add_json_file(self._workspace.projects[self._workspace.default_project], optional=False, output=False) + ps: ProjectSettings = self._configuration.get_configuration(ProjectSettings) + + version[VersionSettingsNameEnum.major.value] = ps.version.major + version[VersionSettingsNameEnum.minor.value] = ps.version.minor + version[VersionSettingsNameEnum.micro.value] = suffix + elif branch.startswith('#'): self._configuration.add_json_file(self._workspace.projects[self._workspace.default_project], optional=False, output=False) ps: ProjectSettings = self._configuration.get_configuration(ProjectSettings) @@ -71,8 +78,6 @@ class Application(ApplicationABC): suffix = '0' version[VersionSettingsNameEnum.micro.value] = f'{suffix}' else: - if not suffix.startswith('.') and suffix != '': - suffix = f'.{suffix}' version[VersionSettingsNameEnum.micro.value] = f'{branch.split(".")[2]}{suffix}' except Exception as e: Console.error(f'Branch {branch} does not contain valid version') -- 2.45.1 From 46fa49a1023b8e2f1aa6adc6600dca9a42ba393c Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 18 Dec 2022 14:27:41 +0100 Subject: [PATCH 53/63] Updated project type library logic & fixed tests #144 --- src/cpl_cli/.cpl/project_library.py | 16 +---- src/cpl_cli/.cpl/schematic_class.py | 4 +- src/cpl_cli/command/generate_service.py | 43 ++++++------ src/cpl_cli/command/new_service.py | 30 ++++---- src/cpl_cli/configuration/project_settings.py | 8 ++- .../configuration/venv_helper_service.py | 4 +- src/cpl_cli/startup_migration_extension.py | 7 -- src/cpl_cli/test_enum.py | 1 - src/cpl_cli/test_init.py | 1 - src/cpl_core/cpl-core.json | 6 +- src/cpl_core/utils/pip.py | 3 +- src/cpl_discord/cpl-discord.json | 6 +- src/cpl_query/cpl-query.json | 5 +- src/cpl_translation/cpl-translation.json | 5 +- unittests/unittests_cli/install_test_case.py | 66 ++++++++++-------- unittests/unittests_cli/new_test_case.py | 69 +++++++++++-------- unittests/unittests_cli/publish_test_case.py | 1 - unittests/unittests_cli/version_test_case.py | 18 +++-- 18 files changed, 161 insertions(+), 132 deletions(-) delete mode 100644 src/cpl_cli/test_enum.py delete mode 100644 src/cpl_cli/test_init.py diff --git a/src/cpl_cli/.cpl/project_library.py b/src/cpl_cli/.cpl/project_library.py index 91579b10..7ade19b6 100644 --- a/src/cpl_cli/.cpl/project_library.py +++ b/src/cpl_cli/.cpl/project_library.py @@ -19,13 +19,10 @@ class Library(ProjectTypeABC): project_file_data: dict, ): from project_file import ProjectFile - from project_file_appsettings import ProjectFileAppsettings - from project_file_code_application import ProjectFileApplication - from project_file_code_main import ProjectFileMain - from project_file_code_startup import ProjectFileStartup from project_file_readme import ProjectFileReadme from project_file_license import ProjectFileLicense from schematic_init import Init + from schematic_class import Class ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async, project_file_data) @@ -35,15 +32,6 @@ class Library(ProjectTypeABC): if workspace is None: self.add_template(ProjectFileLicense('')) self.add_template(ProjectFileReadme('')) - self.add_template(Init('', 'init', f'{base_path}tests/')) self.add_template(Init('', 'init', project_path)) - self.add_template(ProjectFileAppsettings(project_path)) - - if use_application_api: - self.add_template(ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async)) - - if use_startup: - self.add_template(ProjectFileStartup(project_path, use_application_api, use_startup, use_service_providing, use_async)) - - self.add_template(ProjectFileMain(project_name.split('/')[-1], project_path, use_application_api, use_startup, use_service_providing, use_async)) + self.add_template(Class('Class1', 'class', project_path)) diff --git a/src/cpl_cli/.cpl/schematic_class.py b/src/cpl_cli/.cpl/schematic_class.py index f5cdb462..617634de 100644 --- a/src/cpl_cli/.cpl/schematic_class.py +++ b/src/cpl_cli/.cpl/schematic_class.py @@ -4,8 +4,8 @@ from cpl_core.utils import String class Class(GenerateSchematicABC): - def __init__(self, name: str, path: str, schematic: str): - GenerateSchematicABC.__init__(self, name, path, schematic) + def __init__(self, name: str, schematic: str, path: str): + GenerateSchematicABC.__init__(self, name, schematic, path) self._name = f'{String.convert_to_snake_case(name)}.py' self._class_name = f'{String.first_to_upper(name)}' diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index eb42bd04..37946bcb 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -34,6 +34,7 @@ class GenerateService(CommandABC): self._config = configuration self._env = self._config.environment self._schematics = {} + self._schematic_classes = set() for package_name, version in Dependencies.get_cpl_packages(): if package_name == 'cpl-cli': @@ -44,16 +45,12 @@ class GenerateService(CommandABC): self._read_custom_schematics_from_path(self._env.working_directory) self._read_custom_schematics_from_path(self._env.runtime_directory) - if len(GenerateSchematicABC.__subclasses__()) == 0: + if len(self._schematic_classes) == 0: Console.error(f'No schematics found in template directory: .cpl') sys.exit() known_schematics = [] - for schematic in GenerateSchematicABC.__subclasses__(): - if schematic.__name__ in known_schematics: - Console.error(f'Duplicate of schematic {schematic.__name__} found!') - sys.exit() - + for schematic in self._schematic_classes: known_schematics.append(schematic.__name__) schematic.register() @@ -83,6 +80,23 @@ class GenerateService(CommandABC): help_msg += f'\n {schematic}' return help_msg + def _read_custom_schematics_from_path(self, path: str): + if not os.path.exists(os.path.join(path, '.cpl')): + return + + sys.path.insert(0, os.path.join(path, '.cpl')) + for r, d, f in os.walk(os.path.join(path, '.cpl')): + for file in f: + if not file.startswith('schematic_') or not file.endswith('.py'): + continue + + try: + exec(open(os.path.join(r, file), 'r').read()) + self._schematic_classes.update(GenerateSchematicABC.__subclasses__()) + except Exception as e: + Console.error(str(e), traceback.format_exc()) + sys.exit(-1) + @staticmethod def _create_file(file_path: str, value: str): """ @@ -157,23 +171,6 @@ class GenerateService(CommandABC): spinner_foreground_color=ForegroundColorEnum.cyan ) - @staticmethod - def _read_custom_schematics_from_path(path: str): - if not os.path.exists(os.path.join(path, '.cpl')): - return - - sys.path.insert(0, os.path.join(path, '.cpl')) - for r, d, f in os.walk(os.path.join(path, '.cpl')): - for file in f: - if not file.startswith('schematic_') or not file.endswith('.py'): - continue - - try: - exec(open(os.path.join(r, file), 'r').read()) - except Exception as e: - Console.error(str(e), traceback.format_exc()) - sys.exit(-1) - def _get_schematic_by_alias(self, schematic: str) -> str: for key in self._schematics: if schematic in self._schematics[key]['Aliases']: diff --git a/src/cpl_cli/command/new_service.py b/src/cpl_cli/command/new_service.py index eef6e8d4..3c7ada15 100644 --- a/src/cpl_cli/command/new_service.py +++ b/src/cpl_cli/command/new_service.py @@ -45,6 +45,8 @@ class NewService(CommandABC): self._build: BuildSettings = BuildSettings() self._build_dict = {} + self._project_type_classes = set() + self._name: str = '' self._rel_path: str = '' self._project_type: ProjectTypeEnum = ProjectTypeEnum.console @@ -98,7 +100,7 @@ class NewService(CommandABC): ], ProjectSettingsNameEnum.python_version.value: f'>={sys.version.split(" ")[0]}', ProjectSettingsNameEnum.python_path.value: { - sys.platform: '../../venv/bin/python' if self._use_venv else '' + sys.platform: '../../venv/' if self._use_venv else '' }, ProjectSettingsNameEnum.classifiers.value: [] } @@ -152,17 +154,22 @@ class NewService(CommandABC): return project_path - def _get_project_information(self, is_unittest=False): + def _get_project_information(self, project_type: str): """ Gets project information's from user :return: """ + is_unittest = project_type == 'unittest' + is_library = project_type == 'library' + if is_library: + return + if self._use_application_api or self._use_startup or self._use_service_providing or self._use_async or self._use_nothing: Console.set_foreground_color(ForegroundColorEnum.default) Console.write_line('Skipping question due to given flags') return - if not is_unittest: + if not is_unittest and not is_library: self._use_application_api = Console.read('Do you want to use application base? (y/n) ').lower() == 'y' if not is_unittest and self._use_application_api: @@ -194,8 +201,7 @@ class NewService(CommandABC): explicit_path=os.path.join(self._env.working_directory, project, self._project.python_executable.replace('../', '')) ) - @staticmethod - def _read_custom_project_types_from_path(path: str): + def _read_custom_project_types_from_path(self, path: str): if not os.path.exists(os.path.join(path, '.cpl')): return @@ -207,28 +213,28 @@ class NewService(CommandABC): try: exec(open(os.path.join(r, file), 'r').read()) + self._project_type_classes.update(ProjectTypeABC.__subclasses__()) except Exception as e: Console.error(str(e), traceback.format_exc()) sys.exit(-1) def _create_project(self, project_type: str): for package_name in Dependencies.get_cpl_packages(): + if package_name == 'cpl-cli': + continue package = importlib.import_module(String.convert_to_snake_case(package_name[0])) self._read_custom_project_types_from_path(os.path.dirname(package.__file__)) self._read_custom_project_types_from_path(self._env.working_directory) + self._read_custom_project_types_from_path(self._env.runtime_directory) - if len(ProjectTypeABC.__subclasses__()) == 0: + if len(self._project_type_classes) == 0: Console.error(f'No project types found in template directory: .cpl') sys.exit() project_class = None known_project_types = [] - for p in ProjectTypeABC.__subclasses__(): - if p.__name__ in known_project_types: - Console.error(f'Duplicate of project type {p.__name__} found!') - sys.exit() - + for p in self._project_type_classes: known_project_types.append(p.__name__) if p.__name__.lower() != project_type and p.__name__.lower()[0] != project_type[0]: continue @@ -247,7 +253,7 @@ class NewService(CommandABC): if path is None: return - self._get_project_information() + self._get_project_information(project_type) project_name = self._project.name if self._rel_path != '': project_name = f'{self._rel_path}/{project_name}' diff --git a/src/cpl_cli/configuration/project_settings.py b/src/cpl_cli/configuration/project_settings.py index 5b90399d..acdc9963 100644 --- a/src/cpl_cli/configuration/project_settings.py +++ b/src/cpl_cli/configuration/project_settings.py @@ -123,10 +123,16 @@ class ProjectSettings(ConfigurationModelABC): self._python_path = settings[ProjectSettingsNameEnum.python_path.value] if ProjectSettingsNameEnum.python_path.value in settings and sys.platform in settings[ProjectSettingsNameEnum.python_path.value]: - path = f'{settings[ProjectSettingsNameEnum.python_path.value][sys.platform]}/bin/python' + path = f'{settings[ProjectSettingsNameEnum.python_path.value][sys.platform]}' + if path == '' or path is None: Error.warn(f'{ProjectSettingsNameEnum.python_path.value} not set') path = sys.executable + else: + if not path.endswith('bin/python'): + if not path.endswith('/') and len(path) > 0: + path += '/' + path += 'bin/python' else: path = sys.executable diff --git a/src/cpl_cli/configuration/venv_helper_service.py b/src/cpl_cli/configuration/venv_helper_service.py index 28a59171..9cd1d861 100644 --- a/src/cpl_cli/configuration/venv_helper_service.py +++ b/src/cpl_cli/configuration/venv_helper_service.py @@ -17,7 +17,7 @@ class VenvHelper: if is_virtual: return - venv_path = os.path.abspath(os.path.join(env.working_directory, project_settings.python_executable)) + venv_path = os.path.abspath(os.path.join(env.working_directory, project_settings.python_executable, '../../')) if explicit_path is not None: venv_path = os.path.abspath(explicit_path) @@ -31,7 +31,7 @@ class VenvHelper: spinner_foreground_color=ForegroundColorEnum.cyan ) - Pip.set_executable(venv_path) + Pip.set_executable(project_settings.python_executable) @staticmethod def create_venv(path): diff --git a/src/cpl_cli/startup_migration_extension.py b/src/cpl_cli/startup_migration_extension.py index a7a6f5d1..e8d8d4d6 100644 --- a/src/cpl_cli/startup_migration_extension.py +++ b/src/cpl_cli/startup_migration_extension.py @@ -1,18 +1,11 @@ -import os -from typing import Optional - -from cpl_cli.command.custom_script_service import CustomScriptService -from cpl_cli.configuration.workspace_settings import WorkspaceSettings from cpl_cli.migrations.base.migration_abc import MigrationABC from cpl_cli.migrations.base.migration_service_abc import MigrationServiceABC from cpl_cli.migrations.migration_2022_10 import Migration202210 from cpl_cli.migrations.service.migration_service import MigrationService from cpl_core.application.startup_extension_abc 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.application_environment_abc import ApplicationEnvironmentABC -from cpl_core.utils.string import String class StartupMigrationExtension(StartupExtensionABC): diff --git a/src/cpl_cli/test_enum.py b/src/cpl_cli/test_enum.py deleted file mode 100644 index 425ab6c1..00000000 --- a/src/cpl_cli/test_enum.py +++ /dev/null @@ -1 +0,0 @@ -# imports diff --git a/src/cpl_cli/test_init.py b/src/cpl_cli/test_init.py deleted file mode 100644 index 425ab6c1..00000000 --- a/src/cpl_cli/test_init.py +++ /dev/null @@ -1 +0,0 @@ -# imports diff --git a/src/cpl_core/cpl-core.json b/src/cpl_core/cpl-core.json index b2260ba4..931f24d1 100644 --- a/src/cpl_core/cpl-core.json +++ b/src/cpl_core/cpl-core.json @@ -53,7 +53,11 @@ "*/logs", "*/tests" ], - "PackageData": {}, + "PackageData": { + "cpl_core": [ + ".cpl/*.py" + ] + }, "ProjectReferences": [] } } \ No newline at end of file diff --git a/src/cpl_core/utils/pip.py b/src/cpl_core/utils/pip.py index ebf887a1..a75d69a4 100644 --- a/src/cpl_core/utils/pip.py +++ b/src/cpl_core/utils/pip.py @@ -33,7 +33,7 @@ class Pip: return cls._executable = executable - if not os.path.islink(cls._executable): + if not os.path.islink(cls._executable) or not os.path.isfile(executable): return path = os.path.dirname(os.path.dirname(cls._executable)) @@ -119,6 +119,7 @@ class Pip: if source is not None: pip_args.append(f'--extra-index-url') pip_args.append(source) + subprocess.run(pip_args, stdout=stdout, stderr=stderr, env=cls._env) @classmethod diff --git a/src/cpl_discord/cpl-discord.json b/src/cpl_discord/cpl-discord.json index a515bca1..89e2d110 100644 --- a/src/cpl_discord/cpl-discord.json +++ b/src/cpl_discord/cpl-discord.json @@ -40,7 +40,11 @@ "*/logs", "*/tests" ], - "PackageData": {}, + "PackageData": { + "cpl_discord": [ + ".cpl/*.py" + ] + }, "ProjectReferences": [] } } \ No newline at end of file diff --git a/src/cpl_query/cpl-query.json b/src/cpl_query/cpl-query.json index 48aede0d..96e6c188 100644 --- a/src/cpl_query/cpl-query.json +++ b/src/cpl_query/cpl-query.json @@ -34,7 +34,10 @@ "*/logs", "*/tests" ], - "PackageData": {}, + "PackageData": { + "cpl_query": [ + ".cpl/*.py" + ]}, "ProjectReferences": [] } } \ No newline at end of file diff --git a/src/cpl_translation/cpl-translation.json b/src/cpl_translation/cpl-translation.json index 182fa5ed..f3a36a79 100644 --- a/src/cpl_translation/cpl-translation.json +++ b/src/cpl_translation/cpl-translation.json @@ -40,7 +40,10 @@ "*/logs", "*/tests" ], - "PackageData": {}, + "PackageData": { + "cpl_translation": [ + ".cpl/*.py" + ]}, "ProjectReferences": [] } } \ No newline at end of file diff --git a/unittests/unittests_cli/install_test_case.py b/unittests/unittests_cli/install_test_case.py index eaa2a367..6f773886 100644 --- a/unittests/unittests_cli/install_test_case.py +++ b/unittests/unittests_cli/install_test_case.py @@ -34,14 +34,14 @@ class InstallTestCase(CommandTestCase): def setUp(self): if not os.path.exists(PLAYGROUND_PATH): os.makedirs(PLAYGROUND_PATH) - + os.chdir(PLAYGROUND_PATH) # create projects - CLICommands.new('console', self._source, '--ab', '--s') + CLICommands.new('console', self._source, '--ab', '--s', '--venv') os.chdir(os.path.join(os.getcwd(), self._source)) def _get_installed_packages(self) -> dict: - reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze']) + reqs = subprocess.check_output([os.path.join(os.getcwd(), 'venv/bin/python'), '-m', 'pip', 'freeze']) return dict([tuple(r.decode().split('==')) for r in reqs.split()]) def test_install_package(self): @@ -50,16 +50,20 @@ class InstallTestCase(CommandTestCase): package = f'{package_name}=={version}' CLICommands.install(package) settings = self._get_project_settings() - self.assertNotEqual(settings, {}) - self.assertIn('ProjectSettings', settings) - self.assertIn('Dependencies', settings['ProjectSettings']) - self.assertIn( - package, - settings['ProjectSettings']['Dependencies'] - ) - packages = self._get_installed_packages() - self.assertIn(package_name, packages) - self.assertEqual(version, packages[package_name]) + + with self.subTest(msg='Project deps'): + self.assertNotEqual(settings, {}) + self.assertIn('ProjectSettings', settings) + self.assertIn('Dependencies', settings['ProjectSettings']) + self.assertIn( + package, + settings['ProjectSettings']['Dependencies'] + ) + + with self.subTest(msg='PIP'): + packages = self._get_installed_packages() + self.assertIn(package_name, packages) + self.assertEqual(version, packages[package_name]) def test_dev_install_package(self): version = '1.7.3' @@ -67,21 +71,25 @@ class InstallTestCase(CommandTestCase): package = f'{package_name}=={version}' CLICommands.install(package, is_dev=True) settings = self._get_project_settings() - self.assertNotEqual(settings, {}) - self.assertIn('ProjectSettings', settings) - self.assertIn('Dependencies', settings['ProjectSettings']) - self.assertIn('DevDependencies', settings['ProjectSettings']) - self.assertNotIn( - package, - settings['ProjectSettings']['Dependencies'] - ) - self.assertIn( - package, - settings['ProjectSettings']['DevDependencies'] - ) - packages = self._get_installed_packages() - self.assertIn(package_name, packages) - self.assertEqual(version, packages[package_name]) + + with self.subTest(msg='Project deps'): + self.assertNotEqual(settings, {}) + self.assertIn('ProjectSettings', settings) + self.assertIn('Dependencies', settings['ProjectSettings']) + self.assertIn('DevDependencies', settings['ProjectSettings']) + self.assertNotIn( + package, + settings['ProjectSettings']['Dependencies'] + ) + self.assertIn( + package, + settings['ProjectSettings']['DevDependencies'] + ) + + with self.subTest(msg='PIP'): + packages = self._get_installed_packages() + self.assertIn(package_name, packages) + self.assertEqual(version, packages[package_name]) def _test_install_all(self): version = '1.7.3' @@ -120,5 +128,3 @@ class InstallTestCase(CommandTestCase): packages = self._get_installed_packages() self.assertIn(package_name, packages) self.assertEqual(version, packages[package_name]) - - diff --git a/unittests/unittests_cli/new_test_case.py b/unittests/unittests_cli/new_test_case.py index 80ff154d..b744f012 100644 --- a/unittests/unittests_cli/new_test_case.py +++ b/unittests/unittests_cli/new_test_case.py @@ -14,14 +14,15 @@ class NewTestCase(CommandTestCase): CommandTestCase.__init__(self, method_name) def _test_project(self, project_type: str, name: str, *args, test_venv=False, without_ws=False): - CLICommands.new(project_type, name, *args) + CLICommands.new(project_type, name, *args, output=False) workspace_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, name)) self.assertTrue(os.path.exists(workspace_path)) if test_venv: - self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv'))) - self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv/bin'))) - self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv/bin/python'))) - self.assertTrue(os.path.islink(os.path.join(workspace_path, 'venv/bin/python'))) + with self.subTest(msg='Venv exists'): + self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv'))) + self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv/bin'))) + self.assertTrue(os.path.exists(os.path.join(workspace_path, 'venv/bin/python'))) + self.assertTrue(os.path.islink(os.path.join(workspace_path, 'venv/bin/python'))) base = 'src' if '--base' in args and '/' in name: @@ -32,34 +33,46 @@ class NewTestCase(CommandTestCase): if without_ws: project_path = os.path.abspath(os.path.join(PLAYGROUND_PATH, base, name, 'src/', String.convert_to_snake_case(name))) - self.assertTrue(os.path.exists(project_path)) - self.assertTrue(os.path.exists(os.path.join(project_path, f'{name}.json'))) - self.assertTrue(os.path.exists(os.path.join(project_path, f'main.py'))) + with self.subTest(msg='Project json exists'): + self.assertTrue(os.path.exists(project_path)) + self.assertTrue(os.path.exists(os.path.join(project_path, f'{name}.json'))) - if '--ab' in args: - self.assertTrue(os.path.isfile(os.path.join(project_path, f'application.py'))) - else: - self.assertFalse(os.path.isfile(os.path.join(project_path, f'application.py'))) + if project_type == 'library': + with self.subTest(msg='Library class1 exists'): + self.assertTrue(os.path.exists(os.path.join(project_path, f'class1.py'))) + return + + with self.subTest(msg='Project main.py exists'): + self.assertTrue(os.path.exists(os.path.join(project_path, f'main.py'))) + + with self.subTest(msg='Application base'): + if '--ab' in args: + self.assertTrue(os.path.isfile(os.path.join(project_path, f'application.py'))) + else: + self.assertFalse(os.path.isfile(os.path.join(project_path, f'application.py'))) # s depends on ab - if '--ab' in args and '--s' in args: - self.assertTrue(os.path.isfile(os.path.join(project_path, f'startup.py'))) - else: - self.assertFalse(os.path.isfile(os.path.join(project_path, f'startup.py'))) + with self.subTest(msg='Startup'): + if '--ab' in args and '--s' in args: + self.assertTrue(os.path.isfile(os.path.join(project_path, f'startup.py'))) + else: + self.assertFalse(os.path.isfile(os.path.join(project_path, f'startup.py'))) - if project_type == 'unittest': - self.assertTrue(os.path.isfile(os.path.join(project_path, f'test_case.py'))) - else: - self.assertFalse(os.path.isfile(os.path.join(project_path, f'test_case.py'))) + with self.subTest(msg='Unittest'): + if project_type == 'unittest': + self.assertTrue(os.path.isfile(os.path.join(project_path, f'test_case.py'))) + else: + self.assertFalse(os.path.isfile(os.path.join(project_path, f'test_case.py'))) - if project_type == 'discord-bot': - self.assertTrue(os.path.isfile(os.path.join(project_path, f'events/__init__.py'))) - self.assertTrue(os.path.isfile(os.path.join(project_path, f'events/on_ready_event.py'))) - self.assertTrue(os.path.isfile(os.path.join(project_path, f'commands/__init__.py'))) - self.assertTrue(os.path.isfile(os.path.join(project_path, f'commands/ping_command.py'))) - else: - self.assertFalse(os.path.isfile(os.path.join(project_path, f'events/on_ready_event.py'))) - self.assertFalse(os.path.isfile(os.path.join(project_path, f'commands/ping_command.py'))) + with self.subTest(msg='Discord'): + if project_type == 'discord-bot': + self.assertTrue(os.path.isfile(os.path.join(project_path, f'events/__init__.py'))) + self.assertTrue(os.path.isfile(os.path.join(project_path, f'events/on_ready_event.py'))) + self.assertTrue(os.path.isfile(os.path.join(project_path, f'commands/__init__.py'))) + self.assertTrue(os.path.isfile(os.path.join(project_path, f'commands/ping_command.py'))) + else: + self.assertFalse(os.path.isfile(os.path.join(project_path, f'events/on_ready_event.py'))) + self.assertFalse(os.path.isfile(os.path.join(project_path, f'commands/ping_command.py'))) def _test_sub_project(self, project_type: str, name: str, workspace_name: str, *args, test_venv=False): os.chdir(os.path.abspath(os.path.join(os.getcwd(), workspace_name))) diff --git a/unittests/unittests_cli/publish_test_case.py b/unittests/unittests_cli/publish_test_case.py index a167fa19..7877e633 100644 --- a/unittests/unittests_cli/publish_test_case.py +++ b/unittests/unittests_cli/publish_test_case.py @@ -10,7 +10,6 @@ from unittests_shared.cli_commands import CLICommands class PublishTestCase(CommandTestCase): - _skip_tear_down = True def __init__(self, method_name: str): CommandTestCase.__init__(self, method_name) diff --git a/unittests/unittests_cli/version_test_case.py b/unittests/unittests_cli/version_test_case.py index d409db77..3ba980ff 100644 --- a/unittests/unittests_cli/version_test_case.py +++ b/unittests/unittests_cli/version_test_case.py @@ -66,22 +66,30 @@ class VersionTestCase(CommandTestCase): self._get_version_output(version) reference_banner = colored(text2art(self._name), ForegroundColorEnum.yellow.value).split('\n') reference_banner = "\n".join(reference_banner[:len(reference_banner) - 1]) + '\n' - self.assertEqual(reference_banner, self._block_banner) + + with self.subTest(msg='Block banner'): + self.assertEqual(reference_banner, self._block_banner) reference_version = [ colored(f'{colored("Common Python library CLI: ")}{colored(cpl_cli.__version__)}'), colored(f'{colored("Python: ")}{colored(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")}'), colored(f'OS: {colored(f"{platform.system()} {platform.processor()}")}') + '\n' ] - self.assertEqual('\n'.join(reference_version), self._block_version) + with self.subTest(msg='Block version'): + self.assertEqual('\n'.join(reference_version), self._block_version) reference_cpl_packages = [ colored(colored(f'CPL packages:')), colored(f'{tabulate(cpl_packages, headers=["Name", "Version"])}') + '\n' ] - self.assertEqual('\n'.join(reference_cpl_packages), self._block_cpl_packages) + with self.subTest(msg='Block cpl packages'): + self.assertEqual('\n'.join(reference_cpl_packages), self._block_cpl_packages) reference_packages = [ colored(colored(f'Python packages:')), colored(f'{tabulate(packages, headers=["Name", "Version"])}'), - '\x1b[0m\x1b[0m\n\x1b[0m\x1b[0m\n' # fix colored codes + '\x1b[0m\x1b[0m\n\x1b[0m\x1b[0m\n\x1b[0m\x1b[0m\n' # fix colored codes ] - self.assertEqual('\n'.join(reference_packages), self._block_packages) + + self.maxDiff = None + with self.subTest(msg='Block packages'): + ref_packages = '\n'.join(reference_packages) + self.assertEqual(ref_packages, self._block_packages) -- 2.45.1 From b95d90a191bace4787c6cac9d4b81513a7ab610a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 19 Dec 2022 08:36:24 +0100 Subject: [PATCH 54/63] Fixed python path in project settings #144 --- src/cpl_cli/configuration/project_settings.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cpl_cli/configuration/project_settings.py b/src/cpl_cli/configuration/project_settings.py index acdc9963..a06435ad 100644 --- a/src/cpl_cli/configuration/project_settings.py +++ b/src/cpl_cli/configuration/project_settings.py @@ -130,9 +130,7 @@ class ProjectSettings(ConfigurationModelABC): path = sys.executable else: if not path.endswith('bin/python'): - if not path.endswith('/') and len(path) > 0: - path += '/' - path += 'bin/python' + path = os.path.join('bin/python') else: path = sys.executable -- 2.45.1 From 889f51f5c50ce2e8aed7c0295471660657ade3f8 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 20 Dec 2022 14:29:43 +0100 Subject: [PATCH 55/63] Fixed python path in settings --- src/cpl_cli/configuration/project_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpl_cli/configuration/project_settings.py b/src/cpl_cli/configuration/project_settings.py index a06435ad..86e2dbc3 100644 --- a/src/cpl_cli/configuration/project_settings.py +++ b/src/cpl_cli/configuration/project_settings.py @@ -130,7 +130,7 @@ class ProjectSettings(ConfigurationModelABC): path = sys.executable else: if not path.endswith('bin/python'): - path = os.path.join('bin/python') + path = os.path.join(path, 'bin/python') else: path = sys.executable -- 2.45.1 From 2fb515195c93bdc185a57df502f6762856a567fa Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 20 Dec 2022 14:34:55 +0100 Subject: [PATCH 56/63] Improved query performance test --- unittests/unittests_query/performance_test_case.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittests/unittests_query/performance_test_case.py b/unittests/unittests_query/performance_test_case.py index d3f9c205..69c2776a 100644 --- a/unittests/unittests_query/performance_test_case.py +++ b/unittests/unittests_query/performance_test_case.py @@ -28,8 +28,8 @@ class PerformanceTestCase(unittest.TestCase): print(f'i: {iterable}s') print(f'e: {enumerable}s') - self.assertLess(default, enumerable) - self.assertLess(default, iterable) + self.assertAlmostEqual(round(default, 3), round(enumerable, 3)) + self.assertAlmostEqual(round(default, 3), round(iterable, 3)) def test_where_single(self): default = timeit.timeit(lambda: [x for x in list(range(0, VALUES)) if x == 50], number=COUNT) -- 2.45.1 From c09f2f8e83a468f4559244c6aed3fb51d12f76fa Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 20 Dec 2022 14:50:35 +0100 Subject: [PATCH 57/63] Fixed scoped #148 --- .../dependency_injection/service_provider.py | 2 +- tests/custom/di/src/di/application.py | 29 +++++++++---------- tests/custom/di/src/di/di.json | 5 +++- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/cpl_core/dependency_injection/service_provider.py b/src/cpl_core/dependency_injection/service_provider.py index 0819432b..acf3cb95 100644 --- a/src/cpl_core/dependency_injection/service_provider.py +++ b/src/cpl_core/dependency_injection/service_provider.py @@ -93,7 +93,7 @@ class ServiceProvider(ServiceProviderABC): self._scope = scope def create_scope(self) -> ScopeABC: - sb = ScopeBuilder(ServiceProvider(self._service_descriptors, self._configuration, self._database_context)) + sb = ScopeBuilder(ServiceProvider(copy.deepcopy(self._service_descriptors), self._configuration, self._database_context)) return sb.build() def get_service(self, service_type: type) -> Optional[object]: diff --git a/tests/custom/di/src/di/application.py b/tests/custom/di/src/di/application.py index ec91c6ad..bdb0cdfc 100644 --- a/tests/custom/di/src/di/application.py +++ b/tests/custom/di/src/di/application.py @@ -20,26 +20,23 @@ class Application(ApplicationABC): pass def main(self): - Console.write_line('Scope1') - scope1: Scope = self._services.create_scope() - ts: TestService = scope1.service_provider.get_service(TestService) - ts.run() - dit: DITesterService = scope1.service_provider.get_service(DITesterService) - dit.run() - t = scope1 - b = t.service_provider - scope1.dispose() + with self._services.create_scope() as scope: + Console.write_line('Scope1') + ts: TestService = scope.service_provider.get_service(TestService) + ts.run() + dit: DITesterService = scope.service_provider.get_service(DITesterService) + dit.run() #Console.write_line('Disposed:') #ts1: TestService = scope1.service_provider.get_service(TestService) #ts1.run() - - Console.write_line('Scope2') - scope2: Scope = self._services.create_scope() - ts: TestService = scope2.service_provider.get_service(TestService) - ts.run() - dit: DITesterService = scope2.service_provider.get_service(DITesterService) - dit.run() + + with self._services.create_scope() as scope: + Console.write_line('Scope2') + ts: TestService = scope.service_provider.get_service(TestService) + ts.run() + dit: DITesterService = scope.service_provider.get_service(DITesterService) + dit.run() Console.write_line('Global') self._part_of_scoped() diff --git a/tests/custom/di/src/di/di.json b/tests/custom/di/src/di/di.json index 67ca9bd5..8058551d 100644 --- a/tests/custom/di/src/di/di.json +++ b/tests/custom/di/src/di/di.json @@ -16,7 +16,10 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "sh_cpl>=2021.10.0.post1" + "cpl-core==2022.12.0" + ], + "DevDependencies": [ + "cpl-cli==2022.12.0" ], "PythonVersion": ">=3.9.2", "PythonPath": {}, -- 2.45.1 From d600852bec1060df1b6800fc1a2cfa05d6b4265a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 22 Dec 2022 18:52:17 +0100 Subject: [PATCH 58/63] Added logic to support global service provider #148 --- src/cpl_core/configuration/configuration.py | 2 +- .../configuration/configuration_abc.py | 4 +- .../service_collection.py | 13 +++-- .../service_collection_abc.py | 7 +-- .../dependency_injection/service_provider.py | 54 +++++++++++++------ .../service_provider_abc.py | 26 +++++++-- tests/custom/di/src/di/application.py | 20 ++++--- tests/custom/di/src/di/di_tester_service.py | 2 +- tests/custom/di/src/di/startup.py | 4 +- tests/custom/di/src/di/static_test.py | 11 ++++ 10 files changed, 102 insertions(+), 41 deletions(-) create mode 100644 tests/custom/di/src/di/static_test.py diff --git a/src/cpl_core/configuration/configuration.py b/src/cpl_core/configuration/configuration.py index 11ddbd32..84ba9011 100644 --- a/src/cpl_core/configuration/configuration.py +++ b/src/cpl_core/configuration/configuration.py @@ -268,7 +268,7 @@ class Configuration(ConfigurationABC): configuration.from_dict(value) self.add_configuration(sub, configuration) - def add_configuration(self, key_type: Union[str, type], value: any): + def add_configuration(self, key_type: T, value: any): self._config[key_type] = value def create_console_argument(self, arg_type: ArgumentTypeEnum, token: str, name: str, aliases: list[str], diff --git a/src/cpl_core/configuration/configuration_abc.py b/src/cpl_core/configuration/configuration_abc.py index 5b748ff1..fd1ccced 100644 --- a/src/cpl_core/configuration/configuration_abc.py +++ b/src/cpl_core/configuration/configuration_abc.py @@ -76,7 +76,7 @@ class ConfigurationABC(ABC): pass @abstractmethod - def add_configuration(self, key_type: Union[str, type], value: any): + def add_configuration(self, key_type: T, value: any): r"""Add configuration object Parameter @@ -126,7 +126,7 @@ class ConfigurationABC(ABC): pass @abstractmethod - def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> Optional[T]: + def get_configuration(self, search_type: Type[T]) -> Optional[T]: r"""Returns value from configuration by given type Parameter diff --git a/src/cpl_core/dependency_injection/service_collection.py b/src/cpl_core/dependency_injection/service_collection.py index 8be84578..af861881 100644 --- a/src/cpl_core/dependency_injection/service_collection.py +++ b/src/cpl_core/dependency_injection/service_collection.py @@ -11,6 +11,7 @@ from cpl_core.dependency_injection.service_provider_abc import ServiceProviderAB from cpl_core.logging.logger_abc import LoggerABC from cpl_core.logging.logger_service import Logger from cpl_core.pipes.pipe_abc import PipeABC +from cpl_core.type import T class ServiceCollection(ServiceCollectionABC): @@ -53,22 +54,26 @@ class ServiceCollection(ServiceCollectionABC): def add_logging(self): self.add_singleton(LoggerABC, Logger) + return self def add_pipes(self): for pipe in PipeABC.__subclasses__(): self.add_transient(PipeABC, pipe) + return self - def add_singleton(self, service_type: Union[type, object], service: Union[type, object] = None): + def add_singleton(self, service_type: T, service: T = None): self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.singleton, service) return self - def add_scoped(self, service_type: Type, service: Callable = None): + def add_scoped(self, service_type: T, service: Callable = None): self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.scoped, service) return self - def add_transient(self, service_type: type, service: type = None): + def add_transient(self, service_type: T, service: T = None): self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.transient, service) return self def build_service_provider(self) -> ServiceProviderABC: - return ServiceProvider(self._service_descriptors, self._configuration, self._database_context) + sp = ServiceProvider(self._service_descriptors, self._configuration, self._database_context) + ServiceProviderABC.set_global_provider(sp) + return sp diff --git a/src/cpl_core/dependency_injection/service_collection_abc.py b/src/cpl_core/dependency_injection/service_collection_abc.py index a8d5c6a3..7de41dd2 100644 --- a/src/cpl_core/dependency_injection/service_collection_abc.py +++ b/src/cpl_core/dependency_injection/service_collection_abc.py @@ -5,6 +5,7 @@ from typing import Type from cpl_core.database.database_settings import DatabaseSettings from cpl_core.database.context.database_context_abc import DatabaseContextABC from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC +from cpl_core.type import T class ServiceCollectionABC(ABC): @@ -46,7 +47,7 @@ class ServiceCollectionABC(ABC): pass @abstractmethod - def add_transient(self, service_type: Type, service: Callable = None) -> 'ServiceCollectionABC': + def add_transient(self, service_type: T, service: T = None) -> 'ServiceCollectionABC': r"""Adds a service with transient lifetime Parameter @@ -63,7 +64,7 @@ class ServiceCollectionABC(ABC): pass @abstractmethod - def add_scoped(self, service_type: Type, service: Callable = None) -> 'ServiceCollectionABC': + def add_scoped(self, service_type: T, service: T = None) -> 'ServiceCollectionABC': r"""Adds a service with scoped lifetime Parameter @@ -80,7 +81,7 @@ class ServiceCollectionABC(ABC): pass @abstractmethod - def add_singleton(self, service_type: Type, service: Callable = None) -> 'ServiceCollectionABC': + def add_singleton(self, service_type: T, service: T = None) -> 'ServiceCollectionABC': r"""Adds a service with singleton lifetime Parameter diff --git a/src/cpl_core/dependency_injection/service_provider.py b/src/cpl_core/dependency_injection/service_provider.py index acf3cb95..b5438f6d 100644 --- a/src/cpl_core/dependency_injection/service_provider.py +++ b/src/cpl_core/dependency_injection/service_provider.py @@ -1,6 +1,7 @@ import copy -from inspect import signature, Parameter -from typing import Optional +import functools +from inspect import signature, Parameter, Signature +from typing import Optional, Callable from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC @@ -12,6 +13,7 @@ from cpl_core.dependency_injection.service_provider_abc import ServiceProviderAB from cpl_core.dependency_injection.service_descriptor import ServiceDescriptor from cpl_core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC +from cpl_core.type import T class ServiceProvider(ServiceProviderABC): @@ -54,17 +56,9 @@ class ServiceProvider(ServiceProviderABC): return implementation - def build_service(self, service_type: type) -> object: - for descriptor in self._service_descriptors: - if descriptor.service_type == service_type or issubclass(descriptor.service_type, service_type): - if descriptor.implementation is not None: - service_type = type(descriptor.implementation) - else: - service_type = descriptor.service_type + # raise Exception(f'Service {parameter.annotation} not found') - break - - sig = signature(service_type.__init__) + def build_by_signature(self, sig: Signature) -> list[T]: params = [] for param in sig.parameters.items(): parameter = param[1] @@ -87,16 +81,31 @@ class ServiceProvider(ServiceProviderABC): else: params.append(self._get_service(parameter)) + return params + + def build_service(self, service_type: T) -> object: + for descriptor in self._service_descriptors: + if descriptor.service_type == service_type or issubclass(descriptor.service_type, service_type): + if descriptor.implementation is not None: + service_type = type(descriptor.implementation) + else: + service_type = descriptor.service_type + + break + + sig = signature(service_type.__init__) + params = self.build_by_signature(sig) + return service_type(*params) - + def set_scope(self, scope: ScopeABC): self._scope = scope - + def create_scope(self) -> ScopeABC: sb = ScopeBuilder(ServiceProvider(copy.deepcopy(self._service_descriptors), self._configuration, self._database_context)) return sb.build() - def get_service(self, service_type: type) -> Optional[object]: + def get_service(self, service_type: T) -> Optional[T]: result = self._find_service(service_type) if result is None: @@ -110,3 +119,18 @@ class ServiceProvider(ServiceProviderABC): result.implementation = implementation return implementation + + @classmethod + def inject(cls, f=None): + if f is None: + return functools.partial(cls.inject) + + @functools.wraps(f) + def inner(*args, **kwargs): + if cls._provider is None: + raise Exception(f'{cls.__name__} not build!') + + injection = cls._provider.build_by_signature(signature(f)) + return f(*injection, *args, **kwargs) + + return inner diff --git a/src/cpl_core/dependency_injection/service_provider_abc.py b/src/cpl_core/dependency_injection/service_provider_abc.py index 9ed6fd7f..6023aa20 100644 --- a/src/cpl_core/dependency_injection/service_provider_abc.py +++ b/src/cpl_core/dependency_injection/service_provider_abc.py @@ -1,18 +1,29 @@ from abc import abstractmethod, ABC +from inspect import Signature from typing import Type, Optional + from cpl_core.dependency_injection.scope_abc import ScopeABC +from cpl_core.type import T class ServiceProviderABC(ABC): r"""ABC for the class :class:`cpl_core.dependency_injection.service_provider.ServiceProvider`""" - @abstractmethod - def __init__(self): - pass + _provider: Optional['ServiceProviderABC'] = None @abstractmethod - def build_service(self, service_type: Type) -> object: + def __init__(self): pass + + @classmethod + def set_global_provider(cls, provider: 'ServiceProviderABC'): + cls._provider = provider + + @abstractmethod + def build_by_signature(self, sig: Signature) -> list[T]: pass + + @abstractmethod + def build_service(self, service_type: T) -> object: r"""Creates instance of given type Parameter @@ -48,7 +59,7 @@ class ServiceProviderABC(ABC): pass @abstractmethod - def get_service(self, instance_type: Type) -> Optional[object]: + def get_service(self, instance_type: T) -> Optional[T]: r"""Returns instance of given type Parameter @@ -61,3 +72,8 @@ class ServiceProviderABC(ABC): Object of type Optional[Callable[:class:`object`]] """ pass + + # @classmethod + # @abstractmethod + # def inject(cls): + # pass diff --git a/tests/custom/di/src/di/application.py b/tests/custom/di/src/di/application.py index bdb0cdfc..34bdf17e 100644 --- a/tests/custom/di/src/di/application.py +++ b/tests/custom/di/src/di/application.py @@ -3,8 +3,9 @@ from cpl_core.configuration import ConfigurationABC from cpl_core.console.console import Console from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection.scope import Scope -from test_service_service import TestService -from di_tester_service import DITesterService +from di.static_test import StaticTest +from di.test_service_service import TestService +from di.di_tester_service import DITesterService class Application(ApplicationABC): @@ -15,7 +16,7 @@ class Application(ApplicationABC): def _part_of_scoped(self): ts: TestService = self._services.get_service(TestService) ts.run() - + def configure(self): pass @@ -26,10 +27,10 @@ class Application(ApplicationABC): ts.run() dit: DITesterService = scope.service_provider.get_service(DITesterService) dit.run() - - #Console.write_line('Disposed:') - #ts1: TestService = scope1.service_provider.get_service(TestService) - #ts1.run() + + # Console.write_line('Disposed:') + # ts1: TestService = scope1.service_provider.get_service(TestService) + # ts1.run() with self._services.create_scope() as scope: Console.write_line('Scope2') @@ -37,6 +38,9 @@ class Application(ApplicationABC): ts.run() dit: DITesterService = scope.service_provider.get_service(DITesterService) dit.run() - + Console.write_line('Global') self._part_of_scoped() + StaticTest.test() + with self._services.create_scope() as scope: + StaticTest.test() diff --git a/tests/custom/di/src/di/di_tester_service.py b/tests/custom/di/src/di/di_tester_service.py index 27a40b85..db30e4f3 100644 --- a/tests/custom/di/src/di/di_tester_service.py +++ b/tests/custom/di/src/di/di_tester_service.py @@ -1,5 +1,5 @@ from cpl_core.console.console import Console -from test_service_service import TestService +from di.test_service_service import TestService class DITesterService: diff --git a/tests/custom/di/src/di/startup.py b/tests/custom/di/src/di/startup.py index 9f56c8be..e52192ca 100644 --- a/tests/custom/di/src/di/startup.py +++ b/tests/custom/di/src/di/startup.py @@ -2,8 +2,8 @@ from cpl_core.application import StartupABC from cpl_core.configuration import ConfigurationABC from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC from cpl_core.environment import ApplicationEnvironment -from test_service_service import TestService -from di_tester_service import DITesterService +from di.test_service_service import TestService +from di.di_tester_service import DITesterService class Startup(StartupABC): diff --git a/tests/custom/di/src/di/static_test.py b/tests/custom/di/src/di/static_test.py new file mode 100644 index 00000000..ade713dc --- /dev/null +++ b/tests/custom/di/src/di/static_test.py @@ -0,0 +1,11 @@ +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceProvider, ServiceProviderABC +from di.test_service_service import TestService + + +class StaticTest: + + @staticmethod + @ServiceProvider.inject + def test(services: ServiceProviderABC, config: ConfigurationABC, t1: TestService): + t1.run() -- 2.45.1 From 713fa5243c4b398e32973930e986a71642b11ffc Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Fri, 23 Dec 2022 16:09:28 +0100 Subject: [PATCH 59/63] Fixed publisher service --- src/cpl_cli/publish/publisher_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpl_cli/publish/publisher_service.py b/src/cpl_cli/publish/publisher_service.py index b1639023..22ebe291 100644 --- a/src/cpl_cli/publish/publisher_service.py +++ b/src/cpl_cli/publish/publisher_service.py @@ -64,7 +64,7 @@ class PublisherService(PublisherABC): :return: """ if self._src_path_part in file: - file = file.replace(self._src_path_part, '', 1) + file = file.split(self._src_path_part)[1].replace(self._src_path_part, '', 1) dirs = os.path.dirname(file).split(self._path_mark) for d in dirs: -- 2.45.1 From a507ed9f466304648833f80a4426957c0f624707 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Fri, 23 Dec 2022 16:45:14 +0100 Subject: [PATCH 60/63] Fixed publish all script --- cpl-workspace.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpl-workspace.json b/cpl-workspace.json index 0110e201..3c5d5f67 100644 --- a/cpl-workspace.json +++ b/cpl-workspace.json @@ -50,7 +50,7 @@ "pre-publish-all": "cpl sv $ARGS; cpl spu $ARGS;", "publish-all": "cpl publish-cli; cpl publish-core; cpl publish-discord; cpl publish-query; cpl publish-translation;", - "pa": "cpl build-all $ARGS", + "pa": "cpl publish-all $ARGS", "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-discord": "echo 'Publish cpl-discord'; cd ./src/cpl_discord; cpl publish; cd ../../;", -- 2.45.1 From 59263ece6e58defda76eeb971c84de8085f19754 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Fri, 23 Dec 2022 17:28:38 +0100 Subject: [PATCH 61/63] Added multiple instance handling #152 --- .../dependency_injection/service_provider.py | 50 +++++++++------ .../service_provider_abc.py | 63 ++++++++++++++----- tests/custom/di/src/di/application.py | 13 ++-- tests/custom/di/src/di/di_tester_service.py | 2 +- tests/custom/di/src/di/startup.py | 10 ++- tests/custom/di/src/di/static_test.py | 2 +- tests/custom/di/src/di/test1_service.py | 13 ++++ tests/custom/di/src/di/test2_service.py | 13 ++++ tests/custom/di/src/di/test_abc.py | 10 +++ ...est_service_service.py => test_service.py} | 6 +- tests/custom/di/src/di/tester.py | 9 +++ 11 files changed, 146 insertions(+), 45 deletions(-) create mode 100644 tests/custom/di/src/di/test1_service.py create mode 100644 tests/custom/di/src/di/test2_service.py create mode 100644 tests/custom/di/src/di/test_abc.py rename tests/custom/di/src/di/{test_service_service.py => test_service.py} (80%) create mode 100644 tests/custom/di/src/di/tester.py diff --git a/src/cpl_core/dependency_injection/service_provider.py b/src/cpl_core/dependency_injection/service_provider.py index b5438f6d..4e388440 100644 --- a/src/cpl_core/dependency_injection/service_provider.py +++ b/src/cpl_core/dependency_injection/service_provider.py @@ -1,17 +1,16 @@ import copy -import functools +import typing from inspect import signature, Parameter, Signature -from typing import Optional, Callable +from typing import Optional from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console from cpl_core.database.context.database_context_abc import DatabaseContextABC from cpl_core.dependency_injection.scope_abc import ScopeABC from cpl_core.dependency_injection.scope_builder import ScopeBuilder -from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl_core.dependency_injection.service_descriptor import ServiceDescriptor from cpl_core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum +from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC from cpl_core.type import T @@ -44,7 +43,7 @@ class ServiceProvider(ServiceProviderABC): return None - def _get_service(self, parameter: Parameter) -> object: + def _get_service(self, parameter: Parameter) -> Optional[object]: for descriptor in self._service_descriptors: if descriptor.service_type == parameter.annotation or issubclass(descriptor.service_type, parameter.annotation): if descriptor.implementation is not None: @@ -58,12 +57,32 @@ class ServiceProvider(ServiceProviderABC): # raise Exception(f'Service {parameter.annotation} not found') + def _get_services(self, t: type) -> list[Optional[object]]: + implementations = [] + for descriptor in self._service_descriptors: + if descriptor.service_type == t or issubclass(descriptor.service_type, t): + if descriptor.implementation is not None: + implementations.append(descriptor.implementation) + continue + + implementation = self.build_service(descriptor.service_type) + if descriptor.lifetime == ServiceLifetimeEnum.singleton: + descriptor.implementation = implementation + + implementations.append(implementation) + + return implementations + def build_by_signature(self, sig: Signature) -> list[T]: params = [] for param in sig.parameters.items(): parameter = param[1] if parameter.name != 'self' and parameter.annotation != Parameter.empty: - if issubclass(parameter.annotation, ServiceProviderABC): + + if typing.get_origin(parameter.annotation) == list: + params.append(self._get_services(typing.get_args(parameter.annotation)[0])) + + elif issubclass(parameter.annotation, ServiceProviderABC): params.append(self) elif issubclass(parameter.annotation, ApplicationEnvironmentABC): @@ -83,7 +102,7 @@ class ServiceProvider(ServiceProviderABC): return params - def build_service(self, service_type: T) -> object: + def build_service(self, service_type: type) -> object: for descriptor in self._service_descriptors: if descriptor.service_type == service_type or issubclass(descriptor.service_type, service_type): if descriptor.implementation is not None: @@ -120,17 +139,12 @@ class ServiceProvider(ServiceProviderABC): return implementation - @classmethod - def inject(cls, f=None): - if f is None: - return functools.partial(cls.inject) + def get_services(self, service_type: T) -> list[Optional[T]]: + implementations = [] - @functools.wraps(f) - def inner(*args, **kwargs): - if cls._provider is None: - raise Exception(f'{cls.__name__} not build!') + if typing.get_origin(service_type) != list: + raise Exception(f'Invalid type {service_type}! Expected list of type') - injection = cls._provider.build_by_signature(signature(f)) - return f(*injection, *args, **kwargs) + implementations.extend(self._get_services(typing.get_args(service_type)[0])) - return inner + return implementations diff --git a/src/cpl_core/dependency_injection/service_provider_abc.py b/src/cpl_core/dependency_injection/service_provider_abc.py index 6023aa20..a3f7158c 100644 --- a/src/cpl_core/dependency_injection/service_provider_abc.py +++ b/src/cpl_core/dependency_injection/service_provider_abc.py @@ -1,8 +1,8 @@ +import functools from abc import abstractmethod, ABC -from inspect import Signature +from inspect import Signature, signature from typing import Type, Optional - from cpl_core.dependency_injection.scope_abc import ScopeABC from cpl_core.type import T @@ -23,12 +23,12 @@ class ServiceProviderABC(ABC): def build_by_signature(self, sig: Signature) -> list[T]: pass @abstractmethod - def build_service(self, service_type: T) -> object: + def build_service(self, service_type: type) -> object: r"""Creates instance of given type Parameter --------- - instance_type: :class:`Type` + instance_type: :class:`type` The type of the searched instance Returns @@ -36,25 +36,25 @@ class ServiceProviderABC(ABC): Object of the given type """ pass - + @abstractmethod def set_scope(self, scope: ScopeABC): r"""Sets the scope of service provider Parameter --------- - scope :class:`cpl_core.dependency_injection.scope.Scope` + Object of type :class:`cpl_core.dependency_injection.scope_abc.ScopeABC` Service scope """ pass - + @abstractmethod def create_scope(self) -> ScopeABC: r"""Creates a service scope Returns ------- - Object of type :class:`cpl_core.dependency_injection.scope.Scope` + Object of type :class:`cpl_core.dependency_injection.scope_abc.ScopeABC` """ pass @@ -64,16 +64,51 @@ class ServiceProviderABC(ABC): Parameter --------- - instance_type: :class:`Type` + instance_type: :class:`cpl_core.type.T` The type of the searched instance Returns ------- - Object of type Optional[Callable[:class:`object`]] + Object of type Optional[:class:`cpl_core.type.T`] """ pass - # @classmethod - # @abstractmethod - # def inject(cls): - # pass + @abstractmethod + def get_services(self, service_type: T) -> list[Optional[T]]: + r"""Returns instance of given type + + Parameter + --------- + instance_type: :class:`cpl_core.type.T` + The type of the searched instance + + Returns + ------- + Object of type list[Optional[:class:`cpl_core.type.T`] + """ + pass + + @classmethod + def inject(cls, f=None): + r"""Decorator to allow injection into static and class methods + + Parameter + --------- + f: Callable + + Returns + ------- + function + """ + if f is None: + return functools.partial(cls.inject) + + @functools.wraps(f) + def inner(*args, **kwargs): + if cls._provider is None: + raise Exception(f'{cls.__name__} not build!') + + injection = cls._provider.build_by_signature(signature(f)) + return f(*injection, *args, **kwargs) + + return inner diff --git a/tests/custom/di/src/di/application.py b/tests/custom/di/src/di/application.py index 34bdf17e..dd12be54 100644 --- a/tests/custom/di/src/di/application.py +++ b/tests/custom/di/src/di/application.py @@ -4,8 +4,10 @@ from cpl_core.console.console import Console from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection.scope import Scope from di.static_test import StaticTest -from di.test_service_service import TestService +from di.test_abc import TestABC +from di.test_service import TestService from di.di_tester_service import DITesterService +from di.tester import Tester class Application(ApplicationABC): @@ -28,10 +30,6 @@ class Application(ApplicationABC): dit: DITesterService = scope.service_provider.get_service(DITesterService) dit.run() - # Console.write_line('Disposed:') - # ts1: TestService = scope1.service_provider.get_service(TestService) - # ts1.run() - with self._services.create_scope() as scope: Console.write_line('Scope2') ts: TestService = scope.service_provider.get_service(TestService) @@ -42,5 +40,6 @@ class Application(ApplicationABC): Console.write_line('Global') self._part_of_scoped() StaticTest.test() - with self._services.create_scope() as scope: - StaticTest.test() + + self._services.get_service(Tester) + Console.write_line(self._services.get_services(list[TestABC])) diff --git a/tests/custom/di/src/di/di_tester_service.py b/tests/custom/di/src/di/di_tester_service.py index db30e4f3..3c4f9a5d 100644 --- a/tests/custom/di/src/di/di_tester_service.py +++ b/tests/custom/di/src/di/di_tester_service.py @@ -1,5 +1,5 @@ from cpl_core.console.console import Console -from di.test_service_service import TestService +from di.test_service import TestService class DITesterService: diff --git a/tests/custom/di/src/di/startup.py b/tests/custom/di/src/di/startup.py index e52192ca..cff3eac0 100644 --- a/tests/custom/di/src/di/startup.py +++ b/tests/custom/di/src/di/startup.py @@ -2,8 +2,12 @@ from cpl_core.application import StartupABC from cpl_core.configuration import ConfigurationABC from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC from cpl_core.environment import ApplicationEnvironment -from di.test_service_service import TestService +from di.test1_service import Test1Service +from di.test2_service import Test2Service +from di.test_abc import TestABC +from di.test_service import TestService from di.di_tester_service import DITesterService +from di.tester import Tester class Startup(StartupABC): @@ -17,5 +21,9 @@ class Startup(StartupABC): def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: services.add_scoped(TestService) services.add_scoped(DITesterService) + + services.add_singleton(TestABC, Test1Service) + services.add_singleton(TestABC, Test2Service) + services.add_singleton(Tester) return services.build_service_provider() diff --git a/tests/custom/di/src/di/static_test.py b/tests/custom/di/src/di/static_test.py index ade713dc..8e500b0e 100644 --- a/tests/custom/di/src/di/static_test.py +++ b/tests/custom/di/src/di/static_test.py @@ -1,6 +1,6 @@ from cpl_core.configuration import ConfigurationABC from cpl_core.dependency_injection import ServiceProvider, ServiceProviderABC -from di.test_service_service import TestService +from di.test_service import TestService class StaticTest: diff --git a/tests/custom/di/src/di/test1_service.py b/tests/custom/di/src/di/test1_service.py new file mode 100644 index 00000000..93e39d8b --- /dev/null +++ b/tests/custom/di/src/di/test1_service.py @@ -0,0 +1,13 @@ +import string +from cpl_core.console.console import Console +from cpl_core.utils.string import String +from di.test_abc import TestABC + + +class Test1Service(TestABC): + + def __init__(self): + TestABC.__init__(self, String.random_string(string.ascii_lowercase, 8)) + + def run(self): + Console.write_line(f'Im {self._name}') diff --git a/tests/custom/di/src/di/test2_service.py b/tests/custom/di/src/di/test2_service.py new file mode 100644 index 00000000..da27db89 --- /dev/null +++ b/tests/custom/di/src/di/test2_service.py @@ -0,0 +1,13 @@ +import string +from cpl_core.console.console import Console +from cpl_core.utils.string import String +from di.test_abc import TestABC + + +class Test2Service(TestABC): + + def __init__(self): + TestABC.__init__(self, String.random_string(string.ascii_lowercase, 8)) + + def run(self): + Console.write_line(f'Im {self._name}') diff --git a/tests/custom/di/src/di/test_abc.py b/tests/custom/di/src/di/test_abc.py new file mode 100644 index 00000000..92f1aa66 --- /dev/null +++ b/tests/custom/di/src/di/test_abc.py @@ -0,0 +1,10 @@ +from abc import ABC + + +class TestABC(ABC): + + def __init__(self, name: str): + self._name = name + + def __repr__(self): + return f'<{type(self).__name__} {self._name}>' diff --git a/tests/custom/di/src/di/test_service_service.py b/tests/custom/di/src/di/test_service.py similarity index 80% rename from tests/custom/di/src/di/test_service_service.py rename to tests/custom/di/src/di/test_service.py index f99a47a1..895b658f 100644 --- a/tests/custom/di/src/di/test_service_service.py +++ b/tests/custom/di/src/di/test_service.py @@ -1,4 +1,5 @@ import string + from cpl_core.console.console import Console from cpl_core.utils.string import String @@ -7,7 +8,6 @@ class TestService: def __init__(self): self._name = String.random_string(string.ascii_lowercase, 8) - - + def run(self): - Console.write_line(f'Im {self._name}') \ No newline at end of file + Console.write_line(f'Im {self._name}') diff --git a/tests/custom/di/src/di/tester.py b/tests/custom/di/src/di/tester.py new file mode 100644 index 00000000..a43097c0 --- /dev/null +++ b/tests/custom/di/src/di/tester.py @@ -0,0 +1,9 @@ +from cpl_core.console.console import Console +from di.test_abc import TestABC + + +class Tester: + + def __init__(self, t1: TestABC, t2: TestABC, t3: list[TestABC]): + Console.write_line('Tester:') + Console.write_line(t1, t2, t3) -- 2.45.1 From 83f0e8bd424fa188e44c4ebf578af82851e0d985 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 25 Dec 2022 11:25:39 +0100 Subject: [PATCH 62/63] Set version --- src/cpl_cli/cpl-cli.json | 2 +- src/cpl_core/cpl-core.json | 2 +- src/cpl_discord/cpl-discord.json | 2 +- src/cpl_query/cpl-query.json | 2 +- src/cpl_translation/cpl-translation.json | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cpl_cli/cpl-cli.json b/src/cpl_cli/cpl-cli.json index 04b7fd6b..45ae8808 100644 --- a/src/cpl_cli/cpl-cli.json +++ b/src/cpl_cli/cpl-cli.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "dev144" + "Micro": "1" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_core/cpl-core.json b/src/cpl_core/cpl-core.json index 931f24d1..92ec9288 100644 --- a/src/cpl_core/cpl-core.json +++ b/src/cpl_core/cpl-core.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "0" + "Micro": "1" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_discord/cpl-discord.json b/src/cpl_discord/cpl-discord.json index 89e2d110..41dac152 100644 --- a/src/cpl_discord/cpl-discord.json +++ b/src/cpl_discord/cpl-discord.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "0" + "Micro": "1" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_query/cpl-query.json b/src/cpl_query/cpl-query.json index 96e6c188..f87c7b00 100644 --- a/src/cpl_query/cpl-query.json +++ b/src/cpl_query/cpl-query.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "2" + "Micro": "2.post1" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_translation/cpl-translation.json b/src/cpl_translation/cpl-translation.json index f3a36a79..81f775d0 100644 --- a/src/cpl_translation/cpl-translation.json +++ b/src/cpl_translation/cpl-translation.json @@ -3,8 +3,8 @@ "Name": "cpl-translation", "Version": { "Major": "2022", - "Minor": "10", - "Micro": "0.post2" + "Minor": "12", + "Micro": "0" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", -- 2.45.1 From c9bc6a026a75e4e87bcd67ffc34800e9505eca8a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 25 Dec 2022 11:26:51 +0100 Subject: [PATCH 63/63] Build release 2022.12.1 --- src/cpl_cli/.cpl/__init__.py | 4 ++-- src/cpl_cli/__init__.py | 4 ++-- src/cpl_cli/_templates/__init__.py | 4 ++-- src/cpl_cli/_templates/build/__init__.py | 4 ++-- src/cpl_cli/_templates/publish/__init__.py | 4 ++-- src/cpl_cli/abc/__init__.py | 4 ++-- src/cpl_cli/appsettings.json | 2 +- src/cpl_cli/command/__init__.py | 4 ++-- src/cpl_cli/configuration/__init__.py | 4 ++-- src/cpl_cli/helper/__init__.py | 4 ++-- src/cpl_cli/live_server/__init__.py | 4 ++-- src/cpl_cli/migrations/__init__.py | 4 ++-- src/cpl_cli/migrations/base/__init__.py | 4 ++-- src/cpl_cli/migrations/service/__init__.py | 4 ++-- src/cpl_cli/publish/__init__.py | 4 ++-- src/cpl_cli/source_creator/__init__.py | 4 ++-- src/cpl_cli/validators/__init__.py | 4 ++-- src/cpl_core/__init__.py | 4 ++-- src/cpl_core/application/__init__.py | 4 ++-- src/cpl_core/configuration/__init__.py | 4 ++-- src/cpl_core/console/__init__.py | 4 ++-- src/cpl_core/database/__init__.py | 4 ++-- src/cpl_core/database/connection/__init__.py | 4 ++-- src/cpl_core/database/context/__init__.py | 4 ++-- src/cpl_core/dependency_injection/__init__.py | 4 ++-- src/cpl_core/environment/__init__.py | 4 ++-- src/cpl_core/logging/__init__.py | 4 ++-- src/cpl_core/mailing/__init__.py | 4 ++-- src/cpl_core/pipes/__init__.py | 4 ++-- src/cpl_core/time/__init__.py | 4 ++-- src/cpl_core/utils/__init__.py | 4 ++-- src/cpl_discord/.cpl/__init__.py | 4 ++-- src/cpl_discord/__init__.py | 4 ++-- src/cpl_discord/application/__init__.py | 4 ++-- src/cpl_discord/command/__init__.py | 4 ++-- src/cpl_discord/configuration/__init__.py | 4 ++-- src/cpl_discord/container/__init__.py | 4 ++-- src/cpl_discord/events/__init__.py | 4 ++-- src/cpl_discord/helper/__init__.py | 4 ++-- src/cpl_discord/service/__init__.py | 4 ++-- src/cpl_query/__init__.py | 4 ++-- src/cpl_query/base/__init__.py | 4 ++-- src/cpl_query/enumerable/__init__.py | 4 ++-- src/cpl_query/extension/__init__.py | 4 ++-- src/cpl_query/iterable/__init__.py | 4 ++-- src/cpl_translation/__init__.py | 4 ++-- 46 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/cpl_cli/.cpl/__init__.py b/src/cpl_cli/.cpl/__init__.py index 384e3fa0..266c7d74 100644 --- a/src/cpl_cli/.cpl/__init__.py +++ b/src/cpl_cli/.cpl/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/__init__.py b/src/cpl_cli/__init__.py index d5c71351..a9bc3840 100644 --- a/src/cpl_cli/__init__.py +++ b/src/cpl_cli/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -28,4 +28,4 @@ from .main import main from .startup import Startup VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/_templates/__init__.py b/src/cpl_cli/_templates/__init__.py index 506557ff..424946b8 100644 --- a/src/cpl_cli/_templates/__init__.py +++ b/src/cpl_cli/_templates/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/_templates/build/__init__.py b/src/cpl_cli/_templates/build/__init__.py index e006bf80..cc89e736 100644 --- a/src/cpl_cli/_templates/build/__init__.py +++ b/src/cpl_cli/_templates/build/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.build' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/_templates/publish/__init__.py b/src/cpl_cli/_templates/publish/__init__.py index 46a92128..6ab2a7cf 100644 --- a/src/cpl_cli/_templates/publish/__init__.py +++ b/src/cpl_cli/_templates/publish/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli._templates.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/abc/__init__.py b/src/cpl_cli/abc/__init__.py index 609ba749..84ea4829 100644 --- a/src/cpl_cli/abc/__init__.py +++ b/src/cpl_cli/abc/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.abc' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/appsettings.json b/src/cpl_cli/appsettings.json index eb80fe1d..f4dbfbf1 100644 --- a/src/cpl_cli/appsettings.json +++ b/src/cpl_cli/appsettings.json @@ -1,5 +1,5 @@ { "CLI": { - "PipPath": "https://pip-dev.sh-edraft.de" + "PipPath": "https://pip.sh-edraft.de" } } \ No newline at end of file diff --git a/src/cpl_cli/command/__init__.py b/src/cpl_cli/command/__init__.py index 3cb16ed4..3e43a322 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.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -29,4 +29,4 @@ from .publish_service import PublishService from .version_service import VersionService VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/configuration/__init__.py b/src/cpl_cli/configuration/__init__.py index cd0a9ef5..544b8ffa 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.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -31,4 +31,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='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/helper/__init__.py b/src/cpl_cli/helper/__init__.py index 0db1862a..0a3cf183 100644 --- a/src/cpl_cli/helper/__init__.py +++ b/src/cpl_cli/helper/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.helper' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/live_server/__init__.py b/src/cpl_cli/live_server/__init__.py index 4b74e088..dfce0936 100644 --- a/src/cpl_cli/live_server/__init__.py +++ b/src/cpl_cli/live_server/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.live_server' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/migrations/__init__.py b/src/cpl_cli/migrations/__init__.py index fca9b7d7..31de9444 100644 --- a/src/cpl_cli/migrations/__init__.py +++ b/src/cpl_cli/migrations/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.migrations' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/migrations/base/__init__.py b/src/cpl_cli/migrations/base/__init__.py index 2872e0a6..f242e0f8 100644 --- a/src/cpl_cli/migrations/base/__init__.py +++ b/src/cpl_cli/migrations/base/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.migrations.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/migrations/service/__init__.py b/src/cpl_cli/migrations/service/__init__.py index 6a9679f5..a6a73caa 100644 --- a/src/cpl_cli/migrations/service/__init__.py +++ b/src/cpl_cli/migrations/service/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.migrations.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/publish/__init__.py b/src/cpl_cli/publish/__init__.py index 51b16998..5850a382 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.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -25,4 +25,4 @@ from .publisher_abc import PublisherABC from .publisher_service import PublisherService VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/source_creator/__init__.py b/src/cpl_cli/source_creator/__init__.py index 102b512c..32622c31 100644 --- a/src/cpl_cli/source_creator/__init__.py +++ b/src/cpl_cli/source_creator/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.source_creator' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_cli/validators/__init__.py b/src/cpl_cli/validators/__init__.py index f782995b..cd2a3f94 100644 --- a/src/cpl_cli/validators/__init__.py +++ b/src/cpl_cli/validators/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.validators' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.dev144' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='dev144') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/__init__.py b/src/cpl_core/__init__.py index e8905cca..d1080377 100644 --- a/src/cpl_core/__init__.py +++ b/src/cpl_core/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/application/__init__.py b/src/cpl_core/application/__init__.py index 1c504a19..15180c85 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.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -29,4 +29,4 @@ from .startup_abc import StartupABC from .startup_extension_abc import StartupExtensionABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/configuration/__init__.py b/src/cpl_core/configuration/__init__.py index 771be169..aaa2768c 100644 --- a/src/cpl_core/configuration/__init__.py +++ b/src/cpl_core/configuration/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -35,4 +35,4 @@ from .validator_abc import ValidatorABC from .variable_argument import VariableArgument VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/console/__init__.py b/src/cpl_core/console/__init__.py index e4b83bae..03b44671 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.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -28,4 +28,4 @@ from .foreground_color_enum import ForegroundColorEnum from .spinner_thread import SpinnerThread VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/database/__init__.py b/src/cpl_core/database/__init__.py index bbfd6279..d30ad22a 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.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -26,4 +26,4 @@ from .database_settings import DatabaseSettings from .table_abc import TableABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/database/connection/__init__.py b/src/cpl_core/database/connection/__init__.py index 54819c76..335e08ec 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.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -25,4 +25,4 @@ from .database_connection import DatabaseConnection from .database_connection_abc import DatabaseConnectionABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/database/context/__init__.py b/src/cpl_core/database/context/__init__.py index 3667031d..939e0d39 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.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -25,4 +25,4 @@ from .database_context import DatabaseContext from .database_context_abc import DatabaseContextABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/dependency_injection/__init__.py b/src/cpl_core/dependency_injection/__init__.py index ed9acc99..d223a051 100644 --- a/src/cpl_core/dependency_injection/__init__.py +++ b/src/cpl_core/dependency_injection/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.dependency_injection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -31,4 +31,4 @@ from .service_provider import ServiceProvider from .service_provider_abc import ServiceProviderABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/environment/__init__.py b/src/cpl_core/environment/__init__.py index eba19d0c..b3ad91a2 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.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -26,4 +26,4 @@ from .environment_name_enum import EnvironmentNameEnum from .application_environment import ApplicationEnvironment VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/logging/__init__.py b/src/cpl_core/logging/__init__.py index 8aad5906..eb068274 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.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -28,4 +28,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='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/mailing/__init__.py b/src/cpl_core/mailing/__init__.py index 9ce6603f..19343fde 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.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -28,4 +28,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='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/pipes/__init__.py b/src/cpl_core/pipes/__init__.py index ed6ffe40..f5af0359 100644 --- a/src/cpl_core/pipes/__init__.py +++ b/src/cpl_core/pipes/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_core.pipes' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -30,4 +30,4 @@ from .to_camel_case_pipe import ToCamelCasePipe from .to_snake_case_pipe import ToSnakeCasePipe VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/time/__init__.py b/src/cpl_core/time/__init__.py index f3246353..2d1ea1fa 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.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -25,4 +25,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='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_core/utils/__init__.py b/src/cpl_core/utils/__init__.py index ae0c8ac9..dfc4e657 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.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -26,4 +26,4 @@ from .string import String from .pip import Pip VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_discord/.cpl/__init__.py b/src/cpl_discord/.cpl/__init__.py index a25e9f71..884ce6ce 100644 --- a/src/cpl_discord/.cpl/__init__.py +++ b/src/cpl_discord/.cpl/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_discord/__init__.py b/src/cpl_discord/__init__.py index 6a44e988..e0647003 100644 --- a/src/cpl_discord/__init__.py +++ b/src/cpl_discord/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -55,4 +55,4 @@ def get_discord_collection(services: 'ServiceCollectionABC') -> 'DiscordCollecti # build-ignore-end VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_discord/application/__init__.py b/src/cpl_discord/application/__init__.py index 219df343..d74f2402 100644 --- a/src/cpl_discord/application/__init__.py +++ b/src/cpl_discord/application/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.application' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .discord_bot_application_abc import DiscordBotApplicationABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_discord/command/__init__.py b/src/cpl_discord/command/__init__.py index e434da8a..6b77db9c 100644 --- a/src/cpl_discord/command/__init__.py +++ b/src/cpl_discord/command/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.command' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -25,4 +25,4 @@ from .discord_command_abc import DiscordCommandABC from .discord_commands_meta import DiscordCogMeta VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_discord/configuration/__init__.py b/src/cpl_discord/configuration/__init__.py index 94b3d0c0..2b9cd955 100644 --- a/src/cpl_discord/configuration/__init__.py +++ b/src/cpl_discord/configuration/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .discord_bot_settings import DiscordBotSettings VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_discord/container/__init__.py b/src/cpl_discord/container/__init__.py index e8f95ae8..059070a2 100644 --- a/src/cpl_discord/container/__init__.py +++ b/src/cpl_discord/container/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.container' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -31,4 +31,4 @@ from .thread import Thread from .voice_channel import VoiceChannel VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_discord/events/__init__.py b/src/cpl_discord/events/__init__.py index 524123f4..78f8c43f 100644 --- a/src/cpl_discord/events/__init__.py +++ b/src/cpl_discord/events/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.events' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -69,4 +69,4 @@ from .on_voice_state_update_abc import OnVoiceStateUpdateABC from .on_webhooks_update_abc import OnWebhooksUpdateABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_discord/helper/__init__.py b/src/cpl_discord/helper/__init__.py index 7b11a291..31fecbea 100644 --- a/src/cpl_discord/helper/__init__.py +++ b/src/cpl_discord/helper/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.helper' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .to_containers_converter import ToContainersConverter VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_discord/service/__init__.py b/src/cpl_discord/service/__init__.py index 2d370a83..7148f2b8 100644 --- a/src/cpl_discord/service/__init__.py +++ b/src/cpl_discord/service/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_discord.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.0' +__version__ = '2022.12.1' from collections import namedtuple @@ -29,4 +29,4 @@ from .discord_service import DiscordService from .discord_service_abc import DiscordServiceABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='0') +version_info = VersionInfo(major='2022', minor='12', micro='1') diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 1924e2c8..98fa7ddc 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.2' +__version__ = '2022.12.2.post1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='2') +version_info = VersionInfo(major='2022', minor='12', micro='2.post1') diff --git a/src/cpl_query/base/__init__.py b/src/cpl_query/base/__init__.py index 3b768bbd..6051f150 100644 --- a/src/cpl_query/base/__init__.py +++ b/src/cpl_query/base/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.base' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.2' +__version__ = '2022.12.2.post1' from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='2') +version_info = VersionInfo(major='2022', minor='12', micro='2.post1') diff --git a/src/cpl_query/enumerable/__init__.py b/src/cpl_query/enumerable/__init__.py index 5009e045..0f2d45e6 100644 --- a/src/cpl_query/enumerable/__init__.py +++ b/src/cpl_query/enumerable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.enumerable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.2' +__version__ = '2022.12.2.post1' from collections import namedtuple @@ -25,4 +25,4 @@ from .enumerable import Enumerable from .enumerable_abc import EnumerableABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='2') +version_info = VersionInfo(major='2022', minor='12', micro='2.post1') diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index 48dbc44c..dda83ee5 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.2' +__version__ = '2022.12.2.post1' from collections import namedtuple @@ -24,4 +24,4 @@ from collections import namedtuple from .list import List VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='2') +version_info = VersionInfo(major='2022', minor='12', micro='2.post1') diff --git a/src/cpl_query/iterable/__init__.py b/src/cpl_query/iterable/__init__.py index 77d1c07f..9644c909 100644 --- a/src/cpl_query/iterable/__init__.py +++ b/src/cpl_query/iterable/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_query.iterable' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '2022.12.2' +__version__ = '2022.12.2.post1' from collections import namedtuple @@ -25,4 +25,4 @@ from .iterable_abc import IterableABC from .iterable import Iterable VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='12', micro='2') +version_info = VersionInfo(major='2022', minor='12', micro='2.post1') diff --git a/src/cpl_translation/__init__.py b/src/cpl_translation/__init__.py index d789a358..f1d48614 100644 --- a/src/cpl_translation/__init__.py +++ b/src/cpl_translation/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl_translation' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2022 sh-edraft.de' -__version__ = '2022.10.0.post2' +__version__ = '2022.12.0' from collections import namedtuple @@ -51,4 +51,4 @@ init() # build-ignore-end VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2022', minor='10', micro='0.post2') +version_info = VersionInfo(major='2022', minor='12', micro='0') -- 2.45.1
  476. Introduction to the CPL Docs