diff --git a/.gitignore b/.gitignore index d9c65a9f..66c1e7ab 100644 --- a/.gitignore +++ b/.gitignore @@ -110,6 +110,9 @@ ENV/ env.bak/ venv.bak/ +# Custom Environments +cpl-env/ + # Spyder project settings .spyderproject .spyproject diff --git a/README.md b/README.md index ac07ceb2..58eb7203 100644 --- a/README.md +++ b/README.md @@ -38,11 +38,16 @@ ### Installation -Install the cpl package +Install the CPL package ```sh pip install sh_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 +``` + Create workspace: ```sh cpl new diff --git a/cpl-workspace.json b/cpl-workspace.json new file mode 100644 index 00000000..28077a0b --- /dev/null +++ b/cpl-workspace.json @@ -0,0 +1,9 @@ +{ + "WorkspaceSettings": { + "DefaultProject": "cpl_cli", + "Projects": { + "cpl": "src/cpl/cpl.json", + "cpl_cli": "src/cpl_cli/cpl_cli.json" + } + } +} \ No newline at end of file diff --git a/docs/cli.txt b/docs/cli.txt deleted file mode 100644 index 2c396d12..00000000 --- a/docs/cli.txt +++ /dev/null @@ -1,19 +0,0 @@ -prefix: cpl -commands: - build - - generate: - abc | a - class | c - configmodel | cm - enum | e - service | s - - help - new - console - - start - publish - update - version \ No newline at end of file diff --git a/docs/install.txt b/docs/install.txt deleted file mode 100644 index 54c105b4..00000000 --- a/docs/install.txt +++ /dev/null @@ -1,2 +0,0 @@ -python setup.py install # for install -python setup.py sdist bdist_wheel # for build \ No newline at end of file diff --git a/docs/pip.txt b/docs/pip.txt index 90a20272..76c38047 100644 --- a/docs/pip.txt +++ b/docs/pip.txt @@ -1,11 +1,39 @@ upload: prod: - twine upload --repository-url https://pip.sh-edraft.de dist/publish/setup/* - twine upload -r pip.sh-edraft.de dist/publish/setup/* + cpl: + twine upload --repository-url https://pip.sh-edraft.de dist/sh_cpl/publish/setup/* + twine upload -r pip.sh-edraft.de dist/sh_cpl-cli/publish/setup/* + cli: + twine upload --repository-url https://pip.sh-edraft.de dist/sh_cpl-cli/publish/setup/* + twine upload -r pip.sh-edraft.de dist/sh_cpl-cli/publish/setup/* + + exp: + cpl: + twine upload --repository-url https://pip-exp.sh-edraft.de dist/sh_cpl/publish/setup/* + twine upload -r pip-exp.sh-edraft.de dist/sh_cpl/publish/setup/* + + cli: + twine upload --repository-url https://pip-exp.sh-edraft.de dist/sh_cpl-cli/publish/setup/* + twine upload -r pip-exp.sh-edraft.de dist/sh_cpl-cli/publish/setup/* dev: - twine upload --repository-url https://pip-dev.sh-edraft.de dist/publish/setup/* - twine upload -r pip-dev.sh-edraft.de dist/publish/setup/* + cpl: + twine upload --repository-url https://pip-dev.sh-edraft.de dist/sh_cpl/publish/setup/* + twine upload -r pip-dev.sh-edraft.de dist/sh_cpl/publish/setup/* + + cli: + twine upload --repository-url https://pip-dev.sh-edraft.de dist/sh_cpl-cli/publish/setup/* + twine upload -r pip-dev.sh-edraft.de dist/sh_cpl-cli/publish/setup/* install: - pip install --extra-index-url https://pip.sh-edraft.de/ sh_cpl + prod: + pip install --extra-index-url https://pip.sh-edraft.de/ sh_cpl + pip install --extra-index-url https://pip.sh-edraft.de/ sh_cpl-cli + + exp: + pip install --extra-index-url https://pip-exp.sh-edraft.de/ sh_cpl + pip install --extra-index-url https://pip-exp.sh-edraft.de/ sh_cpl-cli + + dev: + pip install --extra-index-url https://pip-dev.sh-edraft.de/ sh_cpl + pip install --extra-index-url https://pip-dev.sh-edraft.de/ sh_cpl-cli diff --git a/src/cpl/__init__.py b/src/cpl/__init__.py index 2d0005b2..bae0963e 100644 --- a/src/cpl/__init__.py +++ b/src/cpl/__init__.py @@ -11,15 +11,15 @@ sh-edraft Common Python library """ -__title__ = 'sh_cpl.cpl' +__title__ = 'cpl' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/application/__init__.py b/src/cpl/application/__init__.py index 58595598..cb6f8940 100644 --- a/src/cpl/application/__init__.py +++ b/src/cpl/application/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl.application' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple @@ -26,4 +26,4 @@ from .application_builder_abc import ApplicationBuilderABC from .startup_abc import StartupABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/configuration/__init__.py b/src/cpl/configuration/__init__.py index 73693042..ef980856 100644 --- a/src/cpl/configuration/__init__.py +++ b/src/cpl/configuration/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple @@ -27,4 +27,4 @@ from .configuration_variable_name_enum import ConfigurationVariableNameEnum from .console_argument import ConsoleArgument VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/configuration/configuration.py b/src/cpl/configuration/configuration.py index 55e35a4f..72959a94 100644 --- a/src/cpl/configuration/configuration.py +++ b/src/cpl/configuration/configuration.py @@ -85,7 +85,7 @@ class Configuration(ConfigurationABC): Console.write_line(f'[{name}] {message}') Console.set_foreground_color(ForegroundColorEnum.default) - def _set_variable(self, name: str, value: str): + def _set_variable(self, name: str, value: any): """ Sets variable to given value :param name: @@ -120,6 +120,9 @@ class Configuration(ConfigurationABC): if found and child_argument_type.name not in self._additional_arguments: self._additional_arguments.append(child_argument_type.name) + if found: + break + if not found: raise Exception(f'Invalid argument: {argument}') @@ -157,10 +160,16 @@ class Configuration(ConfigurationABC): if argument_type.token != '' and argument.startswith(argument_type.token): # --new=value + if len(argument.split(argument_type.token)[1].split(argument_type.value_token)) == 0: + raise Exception(f'Expected argument for command: {argument}') + argument_name = argument.split(argument_type.token)[1].split(argument_type.value_token)[0] else: # new=value - argument_name = argument.split(argument_type.token)[1] + argument_name = argument.split(argument_type.value_token)[1] + + if argument_name == '': + raise Exception(f'Expected argument for command: {argument_type.name}') result = True @@ -191,7 +200,7 @@ class Configuration(ConfigurationABC): # ?new value found = False for alias in argument_type.aliases: - if alias in argument: + if alias == argument or f' {alias} ' == argument: found = True if argument_type.name not in argument and not found: @@ -199,12 +208,13 @@ class Configuration(ConfigurationABC): if (next_arguments is None or len(next_arguments) == 0) and \ argument_type.is_value_token_optional is not True: - raise Exception(f'Invalid argument: {argument}') + raise Exception(f'Expected argument for command: {argument_type.name}') if (next_arguments is None or len(next_arguments) == 0) and argument_type.is_value_token_optional is True: value = '' else: value = next_arguments[0] + next_arguments.remove(value) self._handled_args.append(value) if argument_type.token != '' and argument.startswith(argument_type.token): @@ -277,6 +287,7 @@ class Configuration(ConfigurationABC): if not found and error_message == '' and error is not False: error_message = f'Invalid argument: {argument}' + if error_message != '': if self._argument_error_function is not None: self._argument_error_function(error_message) else: @@ -284,15 +295,25 @@ class Configuration(ConfigurationABC): exit() - def add_json_file(self, name: str, optional: bool = None, output: bool = True, path: str = None): - path_root = self._application_environment.content_root_path - if path is not None: - path_root = path + add_args = [] + for next_arg in next_arguments: + if next_arg not in self._handled_args and next_arg not in self._additional_arguments: + add_args.append(next_arg) - if str(path_root).endswith('/') and not name.startswith('/'): - file_path = f'{path_root}{name}' + self._set_variable(f'{argument}AdditionalArguments', add_args) + + def add_json_file(self, name: str, optional: bool = None, output: bool = True, path: str = None): + if os.path.isabs(name): + file_path = name else: - file_path = f'{path_root}/{name}' + path_root = self._application_environment.working_directory + if path is not None: + path_root = path + + if str(path_root).endswith('/') and not name.startswith('/'): + file_path = f'{path_root}{name}' + else: + file_path = f'{path_root}/{name}' if not os.path.isfile(file_path): if optional is not True: @@ -334,7 +355,7 @@ class Configuration(ConfigurationABC): self._print_error(__name__, f'Cannot load config file: {file}! -> {e}') return {} - def add_configuration(self, key_type: type, value: ConfigurationModelABC): + def add_configuration(self, key_type: Union[str, type], value: ConfigurationModelABC): self._config[key_type] = value def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> Union[ diff --git a/src/cpl/configuration/configuration_abc.py b/src/cpl/configuration/configuration_abc.py index 2fc03bb5..0d0e7ed7 100644 --- a/src/cpl/configuration/configuration_abc.py +++ b/src/cpl/configuration/configuration_abc.py @@ -72,7 +72,7 @@ class ConfigurationABC(ABC): pass @abstractmethod - def add_configuration(self, key_type: type, value: object): + def add_configuration(self, key_type: Union[str, type], value: object): """ Add configuration object :param key_type: diff --git a/src/cpl/console/__init__.py b/src/cpl/console/__init__.py index b43b7224..c39bfcd4 100644 --- a/src/cpl/console/__init__.py +++ b/src/cpl/console/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl.console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple @@ -27,4 +27,4 @@ from .foreground_color_enum import ForegroundColorEnum from .spinner_thread import SpinnerThread VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/console/console.py b/src/cpl/console/console.py index b1536b60..c4336634 100644 --- a/src/cpl/console/console.py +++ b/src/cpl/console/console.py @@ -446,6 +446,8 @@ class Console: for call in cls._hold_back_calls: call.function(*call.args) + cls._hold_back_calls = [] + time.sleep(0.1) return return_value diff --git a/cpl.json b/src/cpl/cpl.json similarity index 79% rename from cpl.json rename to src/cpl/cpl.json index 6fc6ba4b..429043da 100644 --- a/cpl.json +++ b/src/cpl/cpl.json @@ -3,8 +3,8 @@ "Name": "sh_cpl", "Version": { "Major": "2021", - "Minor": "04", - "Micro": "0" + "Minor": "4", + "Micro": "post1" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", @@ -22,8 +22,8 @@ "packaging==20.9", "pyfiglet==0.8.post1", "pynput==1.7.3", - "SQLAlchemy==1.4.3", - "setuptools==54.2.0", + "SQLAlchemy==1.4.7", + "setuptools==56.0.0", "tabulate==0.8.9", "termcolor==1.1.0", "watchdog==2.0.2", @@ -35,10 +35,10 @@ }, "BuildSettings": { "ProjectType": "library", - "SourcePath": "src", - "OutputPath": "dist", - "Main": "cpl_cli.main", - "EntryPoint": "cpl", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "", + "EntryPoint": "", "IncludePackageData": true, "Included": [ "*/templates" @@ -48,10 +48,7 @@ "*/logs", "*/tests" ], - "PackageData": { - "cpl_cli": [ - "*.json" - ] - } + "PackageData": {}, + "ProjectReferences": [] } } \ No newline at end of file diff --git a/src/cpl/database/__init__.py b/src/cpl/database/__init__.py index 307c43a4..50754371 100644 --- a/src/cpl/database/__init__.py +++ b/src/cpl/database/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl.database' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple @@ -25,4 +25,4 @@ from .database_settings import DatabaseSettings from .database_settings_name_enum import DatabaseSettingsNameEnum VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/database/connection/__init__.py b/src/cpl/database/connection/__init__.py index 959b5143..d244382e 100644 --- a/src/cpl/database/connection/__init__.py +++ b/src/cpl/database/connection/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl.database.connection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple @@ -24,4 +24,4 @@ from .database_connection import DatabaseConnection from .database_connection_abc import DatabaseConnectionABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/database/context/__init__.py b/src/cpl/database/context/__init__.py index 5e9e9607..9615dec2 100644 --- a/src/cpl/database/context/__init__.py +++ b/src/cpl/database/context/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl.database.context' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple @@ -24,4 +24,4 @@ from .database_context import DatabaseContext from .database_context_abc import DatabaseContextABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/dependency_injection/__init__.py b/src/cpl/dependency_injection/__init__.py index eecee040..8df606c9 100644 --- a/src/cpl/dependency_injection/__init__.py +++ b/src/cpl/dependency_injection/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl.dependency_injection' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple @@ -28,4 +28,4 @@ from .service_provider import ServiceProvider from .service_provider_abc import ServiceProviderABC VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/environment/__init__.py b/src/cpl/environment/__init__.py index 078ab0bc..0437731e 100644 --- a/src/cpl/environment/__init__.py +++ b/src/cpl/environment/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl.environment' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple @@ -25,4 +25,4 @@ from .environment_name_enum import EnvironmentNameEnum from .application_environment import ApplicationEnvironment VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/environment/application_environment.py b/src/cpl/environment/application_environment.py index 7bb76f13..e28e6c6a 100644 --- a/src/cpl/environment/application_environment.py +++ b/src/cpl/environment/application_environment.py @@ -1,4 +1,4 @@ -import pathlib +import os from datetime import datetime from socket import gethostname from typing import Optional @@ -9,23 +9,21 @@ from cpl.environment.environment_name_enum import EnvironmentNameEnum class ApplicationEnvironment(ApplicationEnvironmentABC): - def __init__(self, name: EnvironmentNameEnum = EnvironmentNameEnum.production, crp: str = './'): + def __init__(self, name: EnvironmentNameEnum = EnvironmentNameEnum.production): """ Represents environment of the application :param name: - :param crp: """ ApplicationEnvironmentABC.__init__(self) self._environment_name: Optional[EnvironmentNameEnum] = name self._app_name: Optional[str] = None self._customer: Optional[str] = None - self._content_root_path: Optional[str] = crp self._start_time: datetime = datetime.now() self._end_time: datetime = datetime.now() - self._working_directory = pathlib.Path().absolute() - self._runtime_directory = pathlib.Path(__file__).parent.absolute() + self._runtime_directory = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + self._working_directory = os.getcwd() @property def environment_name(self) -> str: @@ -51,14 +49,6 @@ class ApplicationEnvironment(ApplicationEnvironmentABC): def customer(self, customer: str): self._customer = customer - @property - def content_root_path(self) -> str: - return self._content_root_path - - @content_root_path.setter - def content_root_path(self, content_root_path: str): - self._content_root_path = content_root_path - @property def host_name(self): return gethostname() @@ -81,18 +71,24 @@ class ApplicationEnvironment(ApplicationEnvironmentABC): @property def working_directory(self) -> str: - return self._working_directory - - def set_working_directory(self, path: str = ''): - if path != '': - self._working_directory = path - return - - self._working_directory = pathlib.Path().absolute() + return str(self._working_directory) @property def runtime_directory(self) -> str: - return self._runtime_directory + return str(self._runtime_directory) - def set_runtime_directory(self, file: str): - self._runtime_directory = pathlib.Path(file).parent.absolute() + def set_runtime_directory(self, runtime_directory: str): + if runtime_directory != '': + self._runtime_directory = runtime_directory + return + + self._runtime_directory = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + def set_working_directory(self, working_directory: str): + if working_directory != '': + self._working_directory = working_directory + os.chdir(self._working_directory) + return + + self._working_directory = os.path.abspath('./') + os.chdir(self._working_directory) diff --git a/src/cpl/environment/application_environment_abc.py b/src/cpl/environment/application_environment_abc.py index c306f53f..fef45a17 100644 --- a/src/cpl/environment/application_environment_abc.py +++ b/src/cpl/environment/application_environment_abc.py @@ -35,14 +35,6 @@ class ApplicationEnvironmentABC(ABC): @abstractmethod def customer(self, customer: str): pass - @property - @abstractmethod - def content_root_path(self) -> str: pass - - @content_root_path.setter - @abstractmethod - def content_root_path(self, content_root_path: str): pass - @property @abstractmethod def host_name(self) -> str: pass @@ -83,3 +75,12 @@ class ApplicationEnvironmentABC(ABC): :return: """ pass + + @abstractmethod + def set_working_directory(self, working_directory: str): + """ + Sets the current working directory + :param working_directory: + :return: + """ + pass diff --git a/src/cpl/logging/__init__.py b/src/cpl/logging/__init__.py index d2fbfadf..f7ef863b 100644 --- a/src/cpl/logging/__init__.py +++ b/src/cpl/logging/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl.logging' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple @@ -27,4 +27,4 @@ from .logging_settings import LoggingSettings from .logging_settings_name_enum import LoggingSettingsNameEnum VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/mailing/__init__.py b/src/cpl/mailing/__init__.py index bbce7c2f..d37d49d8 100644 --- a/src/cpl/mailing/__init__.py +++ b/src/cpl/mailing/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl.mailing' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple @@ -27,4 +27,4 @@ from .email_client_settings import EMailClientSettings from .email_client_settings_name_enum import EMailClientSettingsNameEnum VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/time/__init__.py b/src/cpl/time/__init__.py index e6e22b6a..c67c3290 100644 --- a/src/cpl/time/__init__.py +++ b/src/cpl/time/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl.time' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple @@ -24,4 +24,4 @@ from .time_format_settings import TimeFormatSettings from .time_format_settings_names_enum import TimeFormatSettingsNamesEnum VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/utils/__init__.py b/src/cpl/utils/__init__.py index e3b9690b..204211b1 100644 --- a/src/cpl/utils/__init__.py +++ b/src/cpl/utils/__init__.py @@ -15,7 +15,7 @@ __title__ = 'cpl.utils' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4.post1' from collections import namedtuple @@ -25,4 +25,4 @@ from .string import String from .pip import Pip VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='post1') diff --git a/src/cpl/utils/pip.py b/src/cpl/utils/pip.py index b0035a0c..5ed0f617 100644 --- a/src/cpl/utils/pip.py +++ b/src/cpl/utils/pip.py @@ -1,6 +1,9 @@ +import os import subprocess import sys +import shlex from contextlib import suppress +from textwrap import dedent from typing import Optional @@ -9,6 +12,8 @@ class Pip: Executes pip commands """ _executable = sys.executable + _env = os.environ + _is_venv = False """ Getter @@ -29,8 +34,17 @@ class Pip: :param executable: :return: """ - if executable is not None: + if executable is not None and executable != sys.executable: cls._executable = executable + if os.path.islink(cls._executable): + cls._is_venv = True + path = os.path.dirname(os.path.dirname(cls._executable)) + cls._env = os.environ + if sys.platform == 'win32': + cls._env['PATH'] = f'{path}\\bin' + os.pathsep + os.environ.get('PATH', '') + else: + cls._env['PATH'] = f'{path}/bin' + os.pathsep + os.environ.get('PATH', '') + cls._env['VIRTUAL_ENV'] = path @classmethod def reset_executable(cls): @@ -39,6 +53,7 @@ class Pip: :return: """ cls._executable = sys.executable + cls._is_venv = False """ Public utils functions @@ -53,7 +68,14 @@ class Pip: """ result = None with suppress(Exception): - result = subprocess.check_output([cls._executable, "-m", "pip", "show", package], stderr=subprocess.DEVNULL) + args = [cls._executable, "-m", "pip", "show", package] + if cls._is_venv: + args = ["pip", "show", package] + + result = subprocess.check_output( + args, + stderr=subprocess.DEVNULL, env=cls._env + ) if result is None: return None @@ -76,7 +98,11 @@ class Pip: Gets table of outdated packages :return: """ - return subprocess.check_output([cls._executable, "-m", "pip", "list", "--outdated"]) + args = [cls._executable, "-m", "pip", "list", "--outdated"] + if cls._is_venv: + args = ["pip", "list", "--outdated"] + + return subprocess.check_output(args, env=cls._env) @classmethod def install(cls, package: str, *args, source: str = None, stdout=None, stderr=None): @@ -90,6 +116,8 @@ class Pip: :return: """ pip_args = [cls._executable, "-m", "pip", "install"] + if cls._is_venv: + pip_args = ["pip", "install"] for arg in args: pip_args.append(arg) @@ -99,7 +127,7 @@ class Pip: pip_args.append(source) pip_args.append(package) - subprocess.run(pip_args, stdout=stdout, stderr=stderr) + subprocess.run(pip_args, stdout=stdout, stderr=stderr, env=cls._env) @classmethod def uninstall(cls, package: str, stdout=None, stderr=None): @@ -110,4 +138,11 @@ class Pip: :param stderr: :return: """ - subprocess.run([cls._executable, "-m", "pip", "uninstall", "--yes", package], stdout=stdout, stderr=stderr) + args = [cls._executable, "-m", "pip", "uninstall", "--yes", package] + if cls._is_venv: + args = ["pip", "uninstall", "--yes", package] + + subprocess.run( + args, + stdout=stdout, stderr=stderr, env=cls._env + ) diff --git a/src/cpl/utils/string.py b/src/cpl/utils/string.py index 29d2da95..ebca8382 100644 --- a/src/cpl/utils/string.py +++ b/src/cpl/utils/string.py @@ -1,4 +1,6 @@ import re +import string +import random class String: @@ -7,31 +9,58 @@ class String: """ @staticmethod - def convert_to_snake_case(name: str) -> str: + def convert_to_camel_case(chars: str) -> str: """ - Converts string to snake case - :param name: + Converts string to camel case + :param chars: :return: """ + converted_name = chars + char_set = string.punctuation + ' ' + for char in char_set: + if char in converted_name: + converted_name = ''.join(word.title() for word in converted_name.split(char)) + + return converted_name + + @staticmethod + def convert_to_snake_case(chars: str) -> str: + """ + Converts string to snake case + :param chars: + :return: + """ + # convert to train-case to CamelCase + if '-' in chars: + chars = ''.join(word.title() for word in chars.split('-')) + pattern1 = re.compile(r'(.)([A-Z][a-z]+)') pattern2 = re.compile(r'([a-z0-9])([A-Z])') - file_name = re.sub(pattern1, r'\1_\2', name) + file_name = re.sub(pattern1, r'\1_\2', chars) return re.sub(pattern2, r'\1_\2', file_name).lower() @staticmethod - def first_to_upper(string: str) -> str: + def first_to_upper(chars: str) -> str: """ Converts first char to upper - :param string: + :param chars: :return: """ - return f'{string[0].upper()}{string[1:]}' + return f'{chars[0].upper()}{chars[1:]}' @staticmethod - def first_to_lower(string: str) -> str: + def first_to_lower(chars: str) -> str: """ Converts first char to lower - :param string: + :param chars: :return: """ - return f'{string[0].lower()}{string[1:]}' + return f'{chars[0].lower()}{chars[1:]}' + + @staticmethod + def random_string(chars: str, length: int) -> str: + """ + Creates random string by given chars and length + """ + + return ''.join(random.choice(chars) for _ in range(length)) diff --git a/src/cpl_cli/__init__.py b/src/cpl_cli/__init__.py index c5052acc..8061ef90 100644 --- a/src/cpl_cli/__init__.py +++ b/src/cpl_cli/__init__.py @@ -1,21 +1,21 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. """ -__title__ = 'sh_cpl.cpl_cli' +__title__ = 'cpl_cli' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple @@ -29,4 +29,4 @@ from .main import main from .startup import Startup VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/cli.py b/src/cpl_cli/cli.py index 8547844e..145abc12 100644 --- a/src/cpl_cli/cli.py +++ b/src/cpl_cli/cli.py @@ -4,11 +4,13 @@ from cpl.application.application_abc import ApplicationABC from cpl.configuration.configuration_abc import ConfigurationABC from cpl.console.console import Console from cpl.dependency_injection import ServiceProviderABC +from cpl_cli.command.add_service import AddService from cpl_cli.command.build_service import BuildService from cpl_cli.command.generate_service import GenerateService from cpl_cli.command.install_service import InstallService from cpl_cli.command.new_service import NewService from cpl_cli.command.publish_service import PublishService +from cpl_cli.command.remove_service import RemoveService from cpl_cli.command.start_service import StartService from cpl_cli.command.uninstall_service import UninstallService from cpl_cli.command.update_service import UpdateService @@ -32,16 +34,18 @@ class CLI(ApplicationABC): def configure(self): self._command_handler: CommandHandler = self._services.get_service(CommandHandler) - self._command_handler.add_command(CommandModel('build', ['h', 'B'], BuildService, True)) - self._command_handler.add_command(CommandModel('generate', ['g', 'G'], GenerateService, True)) - self._command_handler.add_command(CommandModel('help', ['h', 'H'], HelpService, False)) - self._command_handler.add_command(CommandModel('install', ['i', 'I'], InstallService, True)) - self._command_handler.add_command(CommandModel('new', ['n', 'N'], NewService, False)) - self._command_handler.add_command(CommandModel('publish', ['p', 'P'], PublishService, True)) - self._command_handler.add_command(CommandModel('start', ['s', 'S'], StartService, True)) - self._command_handler.add_command(CommandModel('uninstall', ['ui', 'UI'], UninstallService, True)) - self._command_handler.add_command(CommandModel('update', ['u', 'U'], UpdateService, True)) - self._command_handler.add_command(CommandModel('version', ['v', 'V'], VersionService, False)) + self._command_handler.add_command(CommandModel('add', ['a', 'a'], AddService, False, False, False)) + self._command_handler.add_command(CommandModel('build', ['b', 'B'], BuildService, False, True, True)) + self._command_handler.add_command(CommandModel('generate', ['g', 'G'], GenerateService, False, True, False)) + self._command_handler.add_command(CommandModel('help', ['h', 'H'], HelpService, False, False, False)) + self._command_handler.add_command(CommandModel('install', ['i', 'I'], InstallService, False, True, True)) + self._command_handler.add_command(CommandModel('new', ['n', 'N'], NewService, False, False, True)) + self._command_handler.add_command(CommandModel('publish', ['p', 'P'], PublishService, False, True, True)) + self._command_handler.add_command(CommandModel('remove', ['r', 'R'], RemoveService, True, True, False)) + self._command_handler.add_command(CommandModel('start', ['s', 'S'], StartService, False, True, True)) + self._command_handler.add_command(CommandModel('uninstall', ['ui', 'UI'], UninstallService, False, True, True)) + self._command_handler.add_command(CommandModel('update', ['u', 'U'], UpdateService, False, True, True)) + self._command_handler.add_command(CommandModel('version', ['v', 'V'], VersionService, False, False, False)) def main(self): """ @@ -58,10 +62,14 @@ class CLI(ApplicationABC): else: for cmd in self._command_handler.commands: result = self._configuration.get_configuration(cmd.name) + result_args = self._configuration.get_configuration(f'{cmd.name}AdditionalArguments') if result is not None: command = cmd.name args.append(result) + for arg in result_args: + args.append(arg) + if command is None: Error.error(f'Expected command') return diff --git a/src/cpl_cli/command/__init__.py b/src/cpl_cli/command/__init__.py index b316c90b..652af826 100644 --- a/src/cpl_cli/command/__init__.py +++ b/src/cpl_cli/command/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.command' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple @@ -28,4 +28,4 @@ from .publish_service import PublishService from .version_service import VersionService VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/command/add_service.py b/src/cpl_cli/command/add_service.py new file mode 100644 index 00000000..ea4c8738 --- /dev/null +++ b/src/cpl_cli/command/add_service.py @@ -0,0 +1,114 @@ +import json +import os.path +from typing import Optional + +from cpl.configuration.configuration_abc import ConfigurationABC +from cpl.console.console import Console +from cpl.console.foreground_color_enum import ForegroundColorEnum +from cpl_cli.command_abc import CommandABC +from cpl_cli.configuration.build_settings import BuildSettings +from cpl_cli.configuration.project_settings import ProjectSettings +from cpl_cli.configuration.settings_helper import SettingsHelper +from cpl_cli.configuration.workspace_settings import WorkspaceSettings + + +class AddService(CommandABC): + + def __init__(self, config: ConfigurationABC, workspace: WorkspaceSettings): + """ + Service for CLI command add + """ + CommandABC.__init__(self) + + self._config = config + + self._workspace = workspace + + @staticmethod + def _edit_project_file(source: str, project_settings: ProjectSettings, build_settings: BuildSettings): + with open(source, 'w') as file: + file.write(json.dumps({ + ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(project_settings), + BuildSettings.__name__: SettingsHelper.get_build_settings_dict(build_settings) + }, indent=2)) + file.close() + + def run(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ + if len(args) == 0: + Console.error('Expected source and target project') + return + + elif len(args) == 1: + Console.error('Expected target project') + return + + elif len(args) > 2: + Console.error(f'Unexpected argument: {" ".join(args[2:])}') + return + + # file names + source = args[0] + target = args[1] + # validation flags + is_invalid_source = False + is_invalid_target = source == target + + if not is_invalid_target: + if self._workspace is None: + is_invalid_source = not os.path.isfile(source) + is_invalid_target = not os.path.isfile(target) + + else: + if source not in self._workspace.projects: + is_invalid_source = True + + else: + source = self._workspace.projects[source] + + if target not in self._workspace.projects: + is_invalid_target = True + + else: + target = self._workspace.projects[target] + + # load project-name.json + self._config.add_json_file(source, optional=True, output=False) + project_settings: Optional[ProjectSettings] = self._config.get_configuration(ProjectSettings) + build_settings: Optional[BuildSettings] = self._config.get_configuration(BuildSettings) + + if project_settings is None or build_settings is None: + is_invalid_source = True + + if is_invalid_source: + Console.error(f'Invalid source: {source}') + return + + if is_invalid_target or source == target or not os.path.isfile(target): + Console.error(f'Invalid target: {target}') + return + + if target in build_settings.project_references: + Console.error(f'Project reference already exists.') + return + + if self._workspace is None: + target = f'../{target}' + else: + target = target.replace('src', '..') + + build_settings.project_references.append(target) + + Console.spinner( + f'Editing {source}', + self._edit_project_file, + source, + project_settings, + build_settings, + text_foreground_color=ForegroundColorEnum.green, + spinner_foreground_color=ForegroundColorEnum.cyan + ) diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index e7e32652..3358d681 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -102,7 +102,7 @@ class GenerateService(CommandABC): rel_path = '/'.join(parts[:-1]) class_name = parts[len(parts) - 1] - if 'src' not in name: + if 'src' not in rel_path: rel_path = f'src/{rel_path}' template = template(class_name, schematic, self._schematics[schematic]["Upper"], rel_path) diff --git a/src/cpl_cli/command/help_service.py b/src/cpl_cli/command/help_service.py index 5088b379..fb96a419 100644 --- a/src/cpl_cli/command/help_service.py +++ b/src/cpl_cli/command/help_service.py @@ -19,13 +19,15 @@ class HelpService(CommandABC): """ Console.write_line('Available Commands:') commands = [ + ['add (a|a)', 'Adds a project reference to given project.'], ['build (b|B)', 'Prepares files for publish into an output directory named dist/ at the given output path. Must be executed from within a workspace directory.'], ['generate (g|G)', 'Generate a new file.'], ['help (h|H)', 'Lists available command and their short descriptions.'], ['install (i|I)', 'With argument installs packages to project, without argument installs project dependencies.'], ['new (n|N)', 'Creates new CPL project.'], ['publish (p|P)', 'Prepares files for publish into an output directory named dist/ at the given output path and executes setup.py. Must be executed from within a library workspace directory.'], - ['start (s|S)', 'Starts CPL project, restarting on file changes'], + ['remove (r|R)', 'Removes a project from workspace.'], + ['start (s|S)', 'Starts CPL project, restarting on file changes.'], ['uninstall (ui|UI)', 'Uninstalls packages from project.'], ['update (u|u)', 'Update CPL and project dependencies.'], ['version (v|V)', 'Outputs CPL CLI version.'] diff --git a/src/cpl_cli/command/install_service.py b/src/cpl_cli/command/install_service.py index 494bb823..2178e735 100644 --- a/src/cpl_cli/command/install_service.py +++ b/src/cpl_cli/command/install_service.py @@ -4,6 +4,7 @@ import subprocess from packaging import version +from cpl.configuration.configuration_abc import ConfigurationABC from cpl.console.console import Console from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.environment.application_environment_abc import ApplicationEnvironmentABC @@ -18,10 +19,11 @@ from cpl_cli.error import Error class InstallService(CommandABC): - def __init__(self, env: ApplicationEnvironmentABC, build_settings: BuildSettings, project_settings: ProjectSettings, - cli_settings: CLISettings): + def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC, build_settings: BuildSettings, + project_settings: ProjectSettings, cli_settings: CLISettings): """ Service for the CLI command install + :param config: :param env: :param build_settings: :param project_settings: @@ -29,11 +31,14 @@ class InstallService(CommandABC): """ CommandABC.__init__(self) + self._config = config self._env = env self._build_settings = build_settings self._project_settings = project_settings self._cli_settings = cli_settings + self._project_file = f'{self._config.get_configuration("ProjectName")}.json' + def _install_project(self): """ Installs dependencies of CPl project @@ -45,7 +50,7 @@ class InstallService(CommandABC): return if self._project_settings.dependencies is None: - Error.error('Found invalid dependencies in cpl.json.') + Error.error(f'Found invalid dependencies in {self._project_file}.') return Pip.set_executable(self._project_settings.python_executable) @@ -76,7 +81,7 @@ class InstallService(CommandABC): return if self._project_settings.dependencies is None: - Error.error('Found invalid dependencies in cpl.json.') + Error.error(f'Found invalid dependencies in {self._project_file}.') return package_version = '' @@ -121,6 +126,7 @@ class InstallService(CommandABC): spinner_foreground_color=ForegroundColorEnum.cyan ) new_package = Pip.get_package(name) + Console.write_line(new_package) if new_package is None \ or '==' in package and \ version.parse(package.split('==')[1]) != version.parse(new_package.split('==')[1]): @@ -147,7 +153,7 @@ class InstallService(CommandABC): BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings) } - with open(os.path.join(self._env.working_directory, 'cpl.json'), 'w') as project_file: + with open(os.path.join(self._env.working_directory, self._project_file), 'w') as project_file: project_file.write(json.dumps(config, indent=2)) project_file.close() diff --git a/src/cpl_cli/command/new_service.py b/src/cpl_cli/command/new_service.py index 7b945c25..20c3bb22 100644 --- a/src/cpl_cli/command/new_service.py +++ b/src/cpl_cli/command/new_service.py @@ -1,4 +1,3 @@ -import json import os import sys from typing import Optional @@ -18,6 +17,7 @@ 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 @@ -34,6 +34,7 @@ class NewService(CommandABC): self._config = configuration self._env = self._config.environment + self._workspace = self._config.get_configuration(WorkspaceSettings) self._project: ProjectSettings = ProjectSettings() self._project_dict = {} self._build: BuildSettings = BuildSettings() @@ -93,12 +94,12 @@ class NewService(CommandABC): def _create_build_settings(self): main = f'{String.convert_to_snake_case(self._project.name)}.main' if self._command == ProjectTypeEnum.library.value: - main = f'{String.convert_to_snake_case(self._project.name)}_cli.main' + main = f'{String.convert_to_snake_case(self._project.name)}.main' self._build_dict = { BuildSettingsNameEnum.project_type.value: self._command, - BuildSettingsNameEnum.source_path.value: 'src', - BuildSettingsNameEnum.output_path.value: 'dist', + BuildSettingsNameEnum.source_path.value: '', + BuildSettingsNameEnum.output_path.value: '../../dist', BuildSettingsNameEnum.main.value: main, BuildSettingsNameEnum.entry_point.value: self._project.name, BuildSettingsNameEnum.include_package_data.value: False, @@ -108,7 +109,8 @@ class NewService(CommandABC): '*/logs', '*/tests' ], - BuildSettingsNameEnum.package_data.value: {} + BuildSettingsNameEnum.package_data.value: {}, + BuildSettingsNameEnum.project_references.value: [] } self._build.from_dict(self._build_dict) @@ -127,7 +129,15 @@ class NewService(CommandABC): Gets project path :return: """ - project_path = os.path.join(self._env.working_directory, self._project.name) + if self._workspace is None: + project_path = os.path.join(self._env.working_directory, self._project.name) + else: + project_path = os.path.join( + self._env.working_directory, + 'src', + String.convert_to_snake_case(self._project.name) + ) + if os.path.isdir(project_path) and len(os.listdir(project_path)) > 0: Console.error('Project path is not empty\n') return None @@ -176,7 +186,8 @@ class NewService(CommandABC): self._use_startup, self._use_service_providing, self._project.name, - self._project_json + self._project_json, + self._workspace ) except Exception as e: Console.error('Could not create project', str(e)) @@ -204,7 +215,8 @@ class NewService(CommandABC): self._use_startup, self._use_service_providing, self._project.name, - self._project_json + self._project_json, + self._workspace ) except Exception as e: Console.error('Could not create project', str(e)) diff --git a/src/cpl_cli/command/publish_service.py b/src/cpl_cli/command/publish_service.py index 7f459ea9..b46474cb 100644 --- a/src/cpl_cli/command/publish_service.py +++ b/src/cpl_cli/command/publish_service.py @@ -1,4 +1,3 @@ -from cpl.console.console import Console from cpl_cli.command_abc import CommandABC from cpl_cli.publish.publisher_abc import PublisherABC diff --git a/src/cpl_cli/command/remove_service.py b/src/cpl_cli/command/remove_service.py new file mode 100644 index 00000000..89457e57 --- /dev/null +++ b/src/cpl_cli/command/remove_service.py @@ -0,0 +1,88 @@ +import os +import shutil +import json + +from cpl.configuration.configuration_abc import ConfigurationABC +from cpl.console.console import Console +from cpl.console.foreground_color_enum import ForegroundColorEnum +from cpl.environment.application_environment_abc import ApplicationEnvironmentABC +from cpl_cli.command_abc import CommandABC +from cpl_cli.configuration import WorkspaceSettings, WorkspaceSettingsNameEnum + + +class RemoveService(CommandABC): + + def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): + """ + Service for CLI command remove + :param config: + :param env: + """ + CommandABC.__init__(self) + + self._config = config + self._env = env + + self._workspace: WorkspaceSettings = self._config.get_configuration(WorkspaceSettings) + + @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() + + @staticmethod + def _remove_sources(path: str): + shutil.rmtree(path) + + def _create_workspace(self, path: str): + ws_dict = { + WorkspaceSettings.__name__: { + WorkspaceSettingsNameEnum.default_project.value: self._workspace.default_project, + WorkspaceSettingsNameEnum.projects.value: self._workspace.projects + } + } + + self._create_file(path, ws_dict) + + def run(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ + + project_name = args[0] + if project_name not in self._workspace.projects: + Console.error(f'Project {project_name} not found in workspace.') + return + + if project_name == self._workspace.default_project: + Console.error(f'Project {project_name} is the default project.') + return + + src_path = os.path.abspath(os.path.dirname(self._workspace.projects[project_name])) + Console.spinner( + f'Removing {src_path}', + self._remove_sources, + src_path, + text_foreground_color=ForegroundColorEnum.green, + spinner_foreground_color=ForegroundColorEnum.cyan + ) + + del self._workspace.projects[project_name] + path = 'cpl-workspace.json' + Console.spinner( + f'Changing {path}', + self._create_workspace, + path, + text_foreground_color=ForegroundColorEnum.green, + spinner_foreground_color=ForegroundColorEnum.cyan + ) diff --git a/src/cpl_cli/command/start_service.py b/src/cpl_cli/command/start_service.py index 7dae7086..388846f1 100644 --- a/src/cpl_cli/command/start_service.py +++ b/src/cpl_cli/command/start_service.py @@ -19,4 +19,4 @@ class StartService(CommandABC): :param args: :return: """ - self._live_server.start() + self._live_server.start(args) diff --git a/src/cpl_cli/command/uninstall_service.py b/src/cpl_cli/command/uninstall_service.py index da7ea3ca..8e091766 100644 --- a/src/cpl_cli/command/uninstall_service.py +++ b/src/cpl_cli/command/uninstall_service.py @@ -2,6 +2,7 @@ import json import os import subprocess +from cpl.configuration.configuration_abc import ConfigurationABC from cpl.console.console import Console from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.environment.application_environment_abc import ApplicationEnvironmentABC @@ -14,18 +15,19 @@ from cpl_cli.configuration.settings_helper import SettingsHelper class UninstallService(CommandABC): - def __init__(self, env: ApplicationEnvironmentABC, build_settings: BuildSettings, + def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC, build_settings: BuildSettings, project_settings: ProjectSettings): """ Service for the CLI command uninstall + :param config: :param env: :param build_settings: :param project_settings: """ CommandABC.__init__(self) + self._config = config self._env = env - self._build_settings = build_settings self._project_settings = project_settings @@ -74,7 +76,7 @@ class UninstallService(CommandABC): ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings), BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings) } - with open(os.path.join(self._env.working_directory, 'cpl.json'), 'w') as project_file: + with open(os.path.join(self._env.working_directory, f'{self._config.get_configuration("ProjectName")}.json'), 'w') as project_file: project_file.write(json.dumps(config, indent=2)) project_file.close() diff --git a/src/cpl_cli/command/update_service.py b/src/cpl_cli/command/update_service.py index c45679bd..eef18f80 100644 --- a/src/cpl_cli/command/update_service.py +++ b/src/cpl_cli/command/update_service.py @@ -2,6 +2,7 @@ import json import os import subprocess +from cpl.configuration.configuration_abc import ConfigurationABC from cpl.console.console import Console from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.environment.application_environment_abc import ApplicationEnvironmentABC @@ -16,12 +17,14 @@ from cpl_cli.configuration.settings_helper import SettingsHelper class UpdateService(CommandABC): def __init__(self, + config: ConfigurationABC, env: ApplicationEnvironmentABC, build_settings: BuildSettings, project_settings: ProjectSettings, cli_settings: CLISettings): """ Service for the CLI command update + :param config: :param env: :param build_settings: :param project_settings: @@ -29,6 +32,7 @@ class UpdateService(CommandABC): """ CommandABC.__init__(self) + self._config = config self._env = env self._build_settings = build_settings self._project_settings = project_settings @@ -115,7 +119,7 @@ class UpdateService(CommandABC): def _project_json_update_dependency(self, old_package: str, new_package: str): """ - Writes new package version to cpl.json + Writes new package version to project.json :param old_package: :param new_package: :return: @@ -135,7 +139,8 @@ class UpdateService(CommandABC): BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings) } - with open(os.path.join(self._env.working_directory, 'cpl.json'), 'w') as project: + with open(os.path.join(self._env.working_directory, f'{self._config.get_configuration("ProjectName")}.json'), + 'w') as project: project.write(json.dumps(config, indent=2)) project.close() diff --git a/src/cpl_cli/command_handler_service.py b/src/cpl_cli/command_handler_service.py index 75bcdced..62d0c73c 100644 --- a/src/cpl_cli/command_handler_service.py +++ b/src/cpl_cli/command_handler_service.py @@ -1,9 +1,12 @@ import os from abc import ABC +from typing import Optional from cpl.configuration.configuration_abc import ConfigurationABC from cpl.console.console import Console from cpl.dependency_injection.service_provider_abc import ServiceProviderABC +from cpl.utils.string import String +from cpl_cli.configuration.workspace_settings import WorkspaceSettings from cpl_cli.error import Error from cpl_cli.command_model import CommandModel @@ -28,6 +31,12 @@ class CommandHandler(ABC): def commands(self) -> list[CommandModel]: return self._commands + @staticmethod + def _project_not_found(): + Error.error( + 'The command requires to be run in an CPL project, but a project could not be found.' + ) + def add_command(self, cmd: CommandModel): self._commands.append(cmd) @@ -43,12 +52,63 @@ class CommandHandler(ABC): """ for command in self._commands: if cmd == command.name or cmd in command.aliases: - if command.is_project_needed and not os.path.isfile(os.path.join(self._env.working_directory, 'cpl.json')): - Error.error('The command requires to be run in an CPL project, but a project could not be found.') - return + error = None + project_name: Optional[str] = None + workspace: Optional[WorkspaceSettings] = None + + if os.path.isfile(os.path.join(self._env.working_directory, 'cpl-workspace.json')): + self._config.add_json_file('cpl-workspace.json', optional=True, output=False) + workspace = self._config.get_configuration(WorkspaceSettings) if command.is_project_needed: - self._config.add_json_file('cpl.json', optional=True, output=False) + name = os.path.basename(self._env.working_directory) + for r, d, f in os.walk(self._env.working_directory): + for file in f: + if file.endswith('.json'): + f_name = file.split('.json')[0] + if f_name == name or \ + String.convert_to_camel_case(f_name) == String.convert_to_camel_case(name): + project_name = f_name + break + + if not command.is_workspace_needed and project_name is None and workspace is None: + self._project_not_found() + return + + elif command.is_workspace_needed or project_name is None: + if workspace is None: + Error.error( + 'The command requires to be run in an CPL workspace or project, ' + 'but a workspace or project could not be found.' + ) + return + + if project_name is None: + project_name = workspace.default_project + + self._config.add_configuration('ProjectName', project_name) + project_json = f'{project_name}.json' + + if workspace is not None: + if project_name not in workspace.projects: + Error.error( + f'Project {project_name} not found.' + ) + return + project_json = workspace.projects[project_name] + + if not os.path.isfile(os.path.join(self._env.working_directory, project_json)): + self._project_not_found() + return + + project_json = os.path.join(self._env.working_directory, project_json) + + if command.change_cwd: + self._env.set_working_directory( + os.path.join(self._env.working_directory, os.path.dirname(project_json)) + ) + + self._config.add_json_file(project_json, optional=True, output=False) self._services.get_service(command.command).run(args) Console.write('\n') diff --git a/src/cpl_cli/command_model.py b/src/cpl_cli/command_model.py index 85afe007..5fabea2a 100644 --- a/src/cpl_cli/command_model.py +++ b/src/cpl_cli/command_model.py @@ -5,11 +5,14 @@ from cpl_cli.command_abc import CommandABC class CommandModel: - def __init__(self, name: str, aliases: list[str], command: Callable[CommandABC], is_project_needed: bool): + def __init__(self, name: str, aliases: list[str], command: Callable[CommandABC], is_workspace_needed: bool, + is_project_needed: bool, change_cwd: bool): self._name = name self._aliases = aliases self._command = command + self._is_workspace_needed = is_workspace_needed self._is_project_needed = is_project_needed + self._change_cwd = change_cwd @property def name(self) -> str: @@ -18,11 +21,19 @@ class CommandModel: @property def aliases(self) -> list[str]: return self._aliases - + @property def command(self) -> Callable[CommandABC]: return self._command + @property + def is_workspace_needed(self) -> bool: + return self._is_workspace_needed + @property def is_project_needed(self) -> bool: return self._is_project_needed + + @property + def change_cwd(self) -> bool: + return self._change_cwd diff --git a/src/cpl_cli/configuration/__init__.py b/src/cpl_cli/configuration/__init__.py index 4144b72d..d6a9ffa1 100644 --- a/src/cpl_cli/configuration/__init__.py +++ b/src/cpl_cli/configuration/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple @@ -26,6 +26,8 @@ from .project_settings import ProjectSettings from .project_settings_name_enum import ProjectSettingsNameEnum from .version_settings import VersionSettings from .version_settings_name_enum import VersionSettingsNameEnum +from .workspace_settings import WorkspaceSettings +from .workspace_settings_name_enum import WorkspaceSettingsNameEnum VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/configuration/build_settings.py b/src/cpl_cli/configuration/build_settings.py index f24be025..167db345 100644 --- a/src/cpl_cli/configuration/build_settings.py +++ b/src/cpl_cli/configuration/build_settings.py @@ -23,6 +23,7 @@ class BuildSettings(ConfigurationModelABC): self._included: Optional[list[str]] = None self._excluded: Optional[list[str]] = None self._package_data: Optional[dict[str, list[str]]] = None + self._project_references: Optional[list[str]] = None @property def project_type(self): @@ -60,6 +61,10 @@ class BuildSettings(ConfigurationModelABC): def package_data(self) -> dict[str, list[str]]: return self._package_data + @property + def project_references(self) -> list[str]: + return self._project_references + def from_dict(self, settings: dict): try: self._project_type = settings[BuildSettingsNameEnum.project_type.value] @@ -71,6 +76,7 @@ class BuildSettings(ConfigurationModelABC): self._included = settings[BuildSettingsNameEnum.included.value] self._excluded = settings[BuildSettingsNameEnum.excluded.value] self._package_data = settings[BuildSettingsNameEnum.package_data.value] + self._project_references = settings[BuildSettingsNameEnum.project_references.value] if sys.platform == 'win32': self._source_path = str(self._source_path).replace('/', '\\') diff --git a/src/cpl_cli/configuration/build_settings_name_enum.py b/src/cpl_cli/configuration/build_settings_name_enum.py index 18d78749..5c0dee28 100644 --- a/src/cpl_cli/configuration/build_settings_name_enum.py +++ b/src/cpl_cli/configuration/build_settings_name_enum.py @@ -12,3 +12,4 @@ class BuildSettingsNameEnum(Enum): included = 'Included' excluded = 'Excluded' package_data = 'PackageData' + project_references = 'ProjectReferences' diff --git a/src/cpl_cli/configuration/settings_helper.py b/src/cpl_cli/configuration/settings_helper.py index e4229445..8a7c47ad 100644 --- a/src/cpl_cli/configuration/settings_helper.py +++ b/src/cpl_cli/configuration/settings_helper.py @@ -42,5 +42,6 @@ class SettingsHelper: BuildSettingsNameEnum.include_package_data.value: build.include_package_data, BuildSettingsNameEnum.included.value: build.included, BuildSettingsNameEnum.excluded.value: build.excluded, - BuildSettingsNameEnum.package_data.value: build.package_data + BuildSettingsNameEnum.package_data.value: build.package_data, + BuildSettingsNameEnum.project_references.value: build.project_references } diff --git a/src/cpl_cli/configuration/version_settings.py b/src/cpl_cli/configuration/version_settings.py index 3d64d71e..86fac84c 100644 --- a/src/cpl_cli/configuration/version_settings.py +++ b/src/cpl_cli/configuration/version_settings.py @@ -31,16 +31,25 @@ class VersionSettings(ConfigurationModelABC): return self._micro def to_str(self) -> str: - return f'{self._major}.{self._minor}.{self._micro}' + if self._micro is None: + return f'{self._major}.{self._minor}' + else: + return f'{self._major}.{self._minor}.{self._micro}' def from_dict(self, settings: dict): self._major = settings[VersionSettingsNameEnum.major.value] self._minor = settings[VersionSettingsNameEnum.minor.value] - self._micro = settings[VersionSettingsNameEnum.micro.value] + micro = settings[VersionSettingsNameEnum.micro.value] + if micro != '': + self._micro = micro def to_dict(self) -> dict: - return { + version = { VersionSettingsNameEnum.major.value: self._major, VersionSettingsNameEnum.minor.value: self._minor, - VersionSettingsNameEnum.micro.value: self._micro } + + if self._micro is not None: + version[VersionSettingsNameEnum.micro.value] = self._micro + + return version diff --git a/src/cpl_cli/configuration/workspace_settings.py b/src/cpl_cli/configuration/workspace_settings.py new file mode 100644 index 00000000..ff40999a --- /dev/null +++ b/src/cpl_cli/configuration/workspace_settings.py @@ -0,0 +1,31 @@ +import traceback +from typing import Optional + +from cpl.configuration.configuration_model_abc import ConfigurationModelABC +from cpl.console import Console +from cpl_cli.configuration.workspace_settings_name_enum import WorkspaceSettingsNameEnum + + +class WorkspaceSettings(ConfigurationModelABC): + + def __init__(self): + ConfigurationModelABC.__init__(self) + + self._default_project: Optional[str] = None + self._projects: dict[str, str] = {} + + @property + def default_project(self) -> str: + return self._default_project + + @property + def projects(self) -> dict[str, str]: + return self._projects + + def from_dict(self, settings: dict): + try: + self._default_project = settings[WorkspaceSettingsNameEnum.default_project.value] + self._projects = settings[WorkspaceSettingsNameEnum.projects.value] + except Exception as e: + Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings') + Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') diff --git a/src/cpl_cli/configuration/workspace_settings_name_enum.py b/src/cpl_cli/configuration/workspace_settings_name_enum.py new file mode 100644 index 00000000..57bbdd20 --- /dev/null +++ b/src/cpl_cli/configuration/workspace_settings_name_enum.py @@ -0,0 +1,7 @@ +from enum import Enum + + +class WorkspaceSettingsNameEnum(Enum): + + default_project = 'DefaultProject' + projects = 'Projects' diff --git a/src/cpl_cli/cpl_cli.json b/src/cpl_cli/cpl_cli.json new file mode 100644 index 00000000..af832920 --- /dev/null +++ b/src/cpl_cli/cpl_cli.json @@ -0,0 +1,47 @@ +{ + "ProjectSettings": { + "Name": "sh_cpl-cli", + "Version": { + "Major": "2021", + "Minor": "4", + "Micro": "" + }, + "Author": "Sven Heidemann", + "AuthorEmail": "sven.heidemann@sh-edraft.de", + "Description": "sh-edraft Common Python library CLI", + "LongDescription": "sh-edraft Common Python library Command Line Interface", + "URL": "https://www.sh-edraft.de", + "CopyrightDate": "2020 - 2021", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": "MIT, see LICENSE for more details.", + "Dependencies": [ + "sh_cpl==2021.4.post1" + ], + "PythonVersion": ">=3.8", + "PythonPath": {}, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "console", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "cpl_cli.main", + "EntryPoint": "cpl", + "IncludePackageData": true, + "Included": [ + "*/templates" + ], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": { + "cpl_cli": [ + "*.json" + ] + }, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/src/cpl_cli/live_server/__init__.py b/src/cpl_cli/live_server/__init__.py index aeb9ebfb..d181e4e0 100644 --- a/src/cpl_cli/live_server/__init__.py +++ b/src/cpl_cli/live_server/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. @@ -15,11 +15,11 @@ __title__ = 'cpl_cli.live_server' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/live_server/live_server_service.py b/src/cpl_cli/live_server/live_server_service.py index 9005ae50..d837f4e3 100644 --- a/src/cpl_cli/live_server/live_server_service.py +++ b/src/cpl_cli/live_server/live_server_service.py @@ -9,26 +9,32 @@ from watchdog.observers import Observer from cpl.console.console import Console from cpl.environment.application_environment_abc import ApplicationEnvironmentABC 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 class LiveServerService(FileSystemEventHandler): - def __init__(self, env: ApplicationEnvironmentABC, build_settings: BuildSettings): + def __init__(self, env: ApplicationEnvironmentABC, project_settings: ProjectSettings, + build_settings: BuildSettings): """ Service for the live development server :param env: + :param project_settings: :param build_settings: """ FileSystemEventHandler.__init__(self) self._env = env + self._project_settings = project_settings self._build_settings = build_settings 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] = [] + def _start_observer(self): """ Starts the file changes observer @@ -70,15 +76,27 @@ class LiveServerService(FileSystemEventHandler): def _start(self): self._start_observer() - self._ls_thread = LiveServerThread(self._src_dir, self._build_settings) + self._ls_thread = LiveServerThread( + self._project_settings.python_executable, + self._src_dir, + self._args, + self._env, + self._build_settings + ) self._ls_thread.start() self._ls_thread.join() Console.close() - def start(self): + def start(self, args: list[str]): """ Starts the CPL live development server + :param args: :return: """ + if self._build_settings.main == '': + Console.error('Project has no entry point.') + return + + self._args = args Console.write_line('** CPL live development server is running **') self._start() diff --git a/src/cpl_cli/live_server/live_server_thread.py b/src/cpl_cli/live_server/live_server_thread.py index 172d4e0d..183d8703 100644 --- a/src/cpl_cli/live_server/live_server_thread.py +++ b/src/cpl_cli/live_server/live_server_thread.py @@ -6,23 +6,36 @@ from datetime import datetime from cpl.console.console import Console from cpl.console.foreground_color_enum import ForegroundColorEnum +from cpl.environment.application_environment_abc import ApplicationEnvironmentABC from cpl_cli.configuration import BuildSettings class LiveServerThread(threading.Thread): - def __init__(self, path: str, build_settings: BuildSettings): + def __init__(self, executable: str, path: str, args: list[str], env: ApplicationEnvironmentABC, + build_settings: BuildSettings): """ Thread to start the CPL project for the live development server + :param executable: :param path: + :param args: + :param env: + :param build_settings: """ threading.Thread.__init__(self) + self._executable = os.path.abspath(executable) + self._path = path + self._args = args + self._env = env self._build_settings = build_settings self._main = '' self._command = [] + self._env_vars = os.environ + + self._set_venv() @property def command(self) -> list[str]: @@ -32,17 +45,38 @@ class LiveServerThread(threading.Thread): def main(self) -> str: return self._main + def _set_venv(self): + if self._executable != sys.executable: + path = os.path.abspath(os.path.dirname(os.path.dirname(self._executable))) + if sys.platform == 'win32': + self._env_vars['PATH'] = f'{path}\\bin' + os.pathsep + os.environ.get('PATH', '') + else: + self._env_vars['PATH'] = f'{path}/bin' + os.pathsep + os.environ.get('PATH', '') + + self._env_vars['VIRTUAL_ENV'] = path + def run(self): """ Starts the CPL project :return: """ - main = self._build_settings.main.replace('.', '/') + main = self._build_settings.main + if '.' in self._build_settings.main: + length = len(self._build_settings.main.split('.')) - 1 + main = self._build_settings.main.split('.')[length] + self._main = os.path.join(self._path, f'{main}.py') if not os.path.isfile(self._main): Console.error('Entry point main.py not found') return + if sys.platform == 'win32': + self._env_vars['PYTHONPATH'] = f'{self._env.working_directory};' \ + f'{os.path.join(self._env.working_directory, self._build_settings.source_path)}' + else: + self._env_vars['PYTHONPATH'] = f'{self._env.working_directory}:' \ + f'{os.path.join(self._env.working_directory, self._build_settings.source_path)}' + Console.set_foreground_color(ForegroundColorEnum.green) Console.write_line('Read successfully') Console.set_foreground_color(ForegroundColorEnum.cyan) @@ -50,13 +84,6 @@ class LiveServerThread(threading.Thread): Console.write_line(f'Started at {now.strftime("%Y-%m-%d %H:%M:%S")}\n\n') Console.set_foreground_color(ForegroundColorEnum.default) - env_vars = os.environ - if sys.platform == 'win32': - env_vars['PYTHONPATH'] = f'{os.path.dirname(self._path)};' \ - f'{os.path.join(os.path.dirname(self._path), self._build_settings.source_path)}' - else: - env_vars['PYTHONPATH'] = f'{os.path.dirname(self._path)}:' \ - f'{os.path.join(os.path.dirname(self._path), self._build_settings.source_path)}' - - self._command = [sys.executable, self._main, ''.join(sys.argv[2:])] - subprocess.run(self._command, env=env_vars) + os.chdir(self._env.working_directory) + self._command = [self._executable, self._main, ''.join(self._args)] + subprocess.run(self._command, env=self._env_vars) diff --git a/src/cpl_cli/publish/__init__.py b/src/cpl_cli/publish/__init__.py index bd94bec5..0fed38ce 100644 --- a/src/cpl_cli/publish/__init__.py +++ b/src/cpl_cli/publish/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. @@ -15,7 +15,7 @@ __title__ = 'cpl_cli.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple @@ -24,4 +24,4 @@ from .publisher_abc import PublisherABC from .publisher_service import PublisherService VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/publish/publisher_service.py b/src/cpl_cli/publish/publisher_service.py index 95f8e0cc..1c61243a 100644 --- a/src/cpl_cli/publish/publisher_service.py +++ b/src/cpl_cli/publish/publisher_service.py @@ -7,6 +7,7 @@ import setuptools from packaging import version from setuptools import sandbox +from cpl.configuration.configuration_abc import ConfigurationABC from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.console.console import Console from cpl.environment.application_environment_abc import ApplicationEnvironmentABC @@ -19,15 +20,18 @@ from cpl_cli.templates.publish.setup_template import SetupTemplate class PublisherService(PublisherABC): - def __init__(self, env: ApplicationEnvironmentABC, project: ProjectSettings, build: BuildSettings): + def __init__(self, config: ConfigurationABC, + env: ApplicationEnvironmentABC, project: ProjectSettings, build: BuildSettings): """ Service to build or publish files for distribution + :param config: :param env: :param project: :param build: """ PublisherABC.__init__(self) + self._config = config self._env = env self._project_settings = project self._build_settings = build @@ -130,6 +134,43 @@ class PublisherService(PublisherABC): return False + def _is_file_excluded(self, file: str) -> bool: + """ + Checks if the file is excluded + :param file: + :return: + """ + for excluded in self._build_settings.excluded: + if excluded.startswith('*'): + excluded = excluded.replace('*', '') + + if excluded in file and not self._is_path_included(file): + return True + + return False + + def _read_sources_from_path(self, path: str): + """ + Reads all source files from given path + :param path: + :return: + """ + for r, d, f in os.walk(path): + for file in f: + relative_path = os.path.relpath(r) + file_path = os.path.join(relative_path, os.path.relpath(file)) + if self._is_file_excluded(file_path): + continue + + if len(d) > 0: + for directory in d: + empty_dir = os.path.join(os.path.dirname(file_path), directory) + if len(os.listdir(empty_dir)) == 0: + self._included_dirs.append(empty_dir) + + if not self._is_path_excluded(relative_path): + self._included_files.append(os.path.relpath(file_path)) + def _read_sources(self): """ Reads all source files and save included files @@ -148,21 +189,16 @@ class PublisherService(PublisherABC): elif os.path.isfile(rel_path): self._included_files.append(rel_path) - for r, d, f in os.walk(self._build_settings.source_path): - for file in f: - relative_path = os.path.relpath(r) - file_path = os.path.join(relative_path, os.path.relpath(file)) - if self._is_path_excluded(relative_path): - break + self._read_sources_from_path(self._source_path) - if len(d) > 0: - for directory in d: - empty_dir = os.path.join(os.path.dirname(file_path), directory) - if len(os.listdir(empty_dir)) == 0: - self._included_dirs.append(empty_dir) + for project in self._build_settings.project_references: + project = os.path.abspath(os.path.join(self._source_path, project)) + if not os.path.isfile(os.path.abspath(project)): + Console.error(f'Cannot import project: {project}') + return - if not self._is_path_excluded(relative_path): - self._included_files.append(os.path.relpath(file_path)) + self.exclude(f'*/{os.path.basename(project)}') + self._read_sources_from_path(os.path.dirname(project)) def _create_packages(self): """ @@ -177,8 +213,6 @@ class PublisherService(PublisherABC): title = self._get_module_name_from_dirs(file) if title == '': title = self._project_settings.name - elif not title.__contains__('.'): - title = f'{self._project_settings.name}.{title}' module_py_lines: list[str] = [] imports = '' @@ -289,31 +323,39 @@ class PublisherService(PublisherABC): if os.path.isfile(setup_file): os.remove(setup_file) - main = None - try: - main_name = self._build_settings.main + entry_points = {} + if self._build_settings.main != "": + main = None + try: + main_name = self._build_settings.main - if '.' in self._build_settings.main: - length = len(self._build_settings.main.split('.')) - main_name = self._build_settings.main.split('.')[length - 1] + if '.' in self._build_settings.main: + length = len(self._build_settings.main.split('.')) + main_name = self._build_settings.main.split('.')[length - 1] - sys.path.insert(0, self._source_path) - main_mod = __import__(self._build_settings.main) - main = getattr(main_mod, main_name) - except Exception as e: - Console.error('Could not find entry point', str(e)) - return + sys.path.insert(0, self._source_path) + main_mod = __import__(self._build_settings.main) + main = getattr(main_mod, main_name) + except Exception as e: + Console.error('Could not find entry point', str(e)) + return - if main is None or not callable(main) and not hasattr(main, 'main'): - Console.error('Could not find entry point') - return + if main is None or not callable(main) and not hasattr(main, 'main'): + Console.error('Could not find entry point') + return - if callable(main): - mod_name = main.__module__ - func_name = main.__name__ - else: - mod_name = main.__name__ - func_name = main.main.__name__ + if callable(main): + mod_name = main.__module__ + func_name = main.__name__ + else: + mod_name = main.__name__ + func_name = main.main.__name__ + + entry_points = { + 'console_scripts': [ + f'{self._build_settings.entry_point} = {mod_name}:{func_name}' + ] + } with open(setup_file, 'w+') as setup_py: setup_string = stringTemplate(SetupTemplate.get_setup_py()).substitute( @@ -328,11 +370,7 @@ class PublisherService(PublisherABC): Description=self._project_settings.description, PyRequires=self._project_settings.python_version, Dependencies=self._project_settings.dependencies, - EntryPoints={ - 'console_scripts': [ - f'{self._build_settings.entry_point} = {mod_name}:{func_name}' - ] - }, + EntryPoints=entry_points, PackageData=self._build_settings.package_data ) setup_py.write(setup_string) @@ -385,7 +423,9 @@ class PublisherService(PublisherABC): 3. Copies all included source files to dist_path/build :return: """ - self._output_path = os.path.join(self._output_path, 'build') + self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) + self.exclude(f'*/{self._config.get_configuration("ProjectName")}.json') + self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, 'build')) Console.spinner('Reading source files:', self._read_sources, text_foreground_color=ForegroundColorEnum.green, spinner_foreground_color=ForegroundColorEnum.blue) @@ -405,7 +445,9 @@ class PublisherService(PublisherABC): 4. Remove all included source from dist_path/publish :return: """ - self._output_path = os.path.join(self._output_path, 'publish') + self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) + self.exclude(f'*/{self._config.get_configuration("ProjectName")}.json') + self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, 'publish')) Console.write_line('Build:') Console.spinner( diff --git a/src/cpl_cli/source_creator/__init__.py b/src/cpl_cli/source_creator/__init__.py index 2b9b45a1..59f35b1b 100644 --- a/src/cpl_cli/source_creator/__init__.py +++ b/src/cpl_cli/source_creator/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. @@ -15,11 +15,11 @@ __title__ = 'cpl_cli.source_creator' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/source_creator/console_builder.py b/src/cpl_cli/source_creator/console_builder.py index 8d6ad878..5ca10f50 100644 --- a/src/cpl_cli/source_creator/console_builder.py +++ b/src/cpl_cli/source_creator/console_builder.py @@ -1,17 +1,22 @@ import json import os +from typing import Optional + from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.console.console import Console +from cpl.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.src.name.application import ApplicationTemplate -from cpl_cli.templates.new.console.src.name.init import MainInitTemplate -from cpl_cli.templates.new.console.src.name.main import MainWithApplicationHostAndStartupTemplate, \ +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.src.name.startup import StartupTemplate -from cpl_cli.templates.new.console.src.tests.init import TestsInitTemplate +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 @@ -21,8 +26,39 @@ class ConsoleBuilder: pass @staticmethod - def build(project_path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, - project_name: str, project_settings: dict): + 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): + ws_dict = { + WorkspaceSettings.__name__: { + WorkspaceSettingsNameEnum.default_project.value: project_name, + WorkspaceSettingsNameEnum.projects.value: projects + } + } + + 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, + project_name: str, project_settings: dict, workspace: Optional[WorkspaceSettings]): """ Builds the console project files :param project_path: @@ -31,40 +67,88 @@ class ConsoleBuilder: :param use_service_providing: :param project_name: :param project_settings: + :param workspace: :return: """ + project_name_snake = String.convert_to_snake_case(project_name) + + if workspace is None: + templates: list[TemplateFileABC] = [ + LicenseTemplate(), + ReadmeTemplate(), + TestsInitTemplate(), + AppsettingsTemplate(), + MainInitTemplate(project_name, 'src') + ] + else: + project_path = os.path.join( + os.path.dirname(project_path), + project_name_snake + ) + + templates: list[TemplateFileABC] = [ + LicenseTemplate(), + ReadmeTemplate(), + AppsettingsTemplate(), + MainInitTemplate('', '') + ] + if not os.path.isdir(project_path): os.makedirs(project_path) - with open(os.path.join(project_path, 'cpl.json'), 'w') as project_json: - project_json.write(json.dumps(project_settings, indent=2)) - project_json.close() - - templates: list[TemplateFileABC] = [ - LicenseTemplate(), - ReadmeTemplate(), - TestsInitTemplate(), - AppsettingsTemplate(), - MainInitTemplate(project_name) - ] + src_rel_path = '' + src_name = '' + if workspace is None: + src_rel_path = 'src/' + src_name = project_name_snake if use_application_api: - templates.append(ApplicationTemplate(project_name)) + templates.append(ApplicationTemplate(src_name, src_rel_path)) if use_startup: - templates.append(StartupTemplate(project_name)) - templates.append(MainWithApplicationHostAndStartupTemplate(project_name)) + templates.append(StartupTemplate(src_name, src_rel_path)) + templates.append(MainWithApplicationHostAndStartupTemplate(src_name, src_rel_path)) else: - templates.append(MainWithApplicationBaseTemplate(project_name)) + templates.append(MainWithApplicationBaseTemplate(src_name, src_rel_path)) else: if use_service_providing: - templates.append(MainWithDependencyInjection(project_name)) + templates.append(MainWithDependencyInjection(src_name, src_rel_path)) else: - templates.append(MainWithoutApplicationBaseTemplate(project_name)) + templates.append(MainWithoutApplicationBaseTemplate(src_name, src_rel_path)) + + proj_name = project_name + if workspace is not None: + proj_name = project_name_snake + + project_file_path = f'{project_name_snake}/{project_name}.json' + if workspace is None: + src_path = f'{proj_name}/src/{project_name_snake}' + workspace_file_path = f'{proj_name}/cpl-workspace.json' + project_file_path = f'{src_path}/{project_name}.json' + cls._create_workspace(workspace_file_path, project_name, { + project_name: project_file_path + }) + + else: + workspace.projects[project_name] = f'src/{project_file_path}' + cls._create_workspace('cpl-workspace.json', workspace.default_project, workspace.projects) + + 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 {project_name}/{template.path}{template.name}', + f'Creating {proj_name}/{template.path}{divider}{template.name}', TemplateBuilder.build, project_path, template, diff --git a/src/cpl_cli/source_creator/library_builder.py b/src/cpl_cli/source_creator/library_builder.py index bc22ccc4..bb233e6a 100644 --- a/src/cpl_cli/source_creator/library_builder.py +++ b/src/cpl_cli/source_creator/library_builder.py @@ -1,17 +1,22 @@ import json import os +from typing import Optional + from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.console.console import Console +from cpl.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.src.cli.application import ApplicationTemplate -from cpl_cli.templates.new.library.src.cli.init import CLIInitTemplate -from cpl_cli.templates.new.library.src.cli.main import MainWithApplicationHostAndStartupTemplate, \ +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.src.cli.startup import StartupTemplate -from cpl_cli.templates.new.library.src.tests.init import TestsInitTemplate +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 @@ -21,8 +26,40 @@ class LibraryBuilder: pass @staticmethod - def build(project_path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, - project_name: str, project_settings: dict): + 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): + ws_dict = { + WorkspaceSettings.__name__: { + WorkspaceSettingsNameEnum.default_project.value: project_name, + WorkspaceSettingsNameEnum.projects.value: projects + } + } + + 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, project_name: str, project_settings: dict, + workspace: Optional[WorkspaceSettings]): """ Builds the library project files :param project_path: @@ -31,40 +68,88 @@ class LibraryBuilder: :param use_service_providing: :param project_name: :param project_settings: + :param workspace: :return: """ + project_name_snake = String.convert_to_snake_case(project_name) + + if workspace is None: + templates: list[TemplateFileABC] = [ + LicenseTemplate(), + ReadmeTemplate(), + TestsInitTemplate(), + NameInitTemplate(project_name, 'src/'), + 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) - with open(os.path.join(project_path, 'cpl.json'), 'w') as project_json: - project_json.write(json.dumps(project_settings, indent=2)) - project_json.close() - - templates: list[TemplateFileABC] = [ - LicenseTemplate(), - ReadmeTemplate(), - TestsInitTemplate(), - CLIInitTemplate(project_name), - AppsettingsTemplate() - ] + src_rel_path = '' + src_name = '' + if workspace is None: + src_rel_path = 'src/' + src_name = project_name_snake if use_application_api: - templates.append(ApplicationTemplate(project_name)) + templates.append(ApplicationTemplate(src_name, src_rel_path)) if use_startup: - templates.append(StartupTemplate(project_name)) - templates.append(MainWithApplicationHostAndStartupTemplate(project_name)) + templates.append(StartupTemplate(src_name, src_rel_path)) + templates.append(MainWithApplicationHostAndStartupTemplate(src_name, src_rel_path)) else: - templates.append(MainWithApplicationBaseTemplate()) + templates.append(MainWithApplicationBaseTemplate(src_name, src_rel_path)) else: if use_service_providing: - templates.append(MainWithDependencyInjection()) + templates.append(MainWithDependencyInjection(src_name, src_rel_path)) else: - templates.append(MainWithoutApplicationBaseTemplate()) + templates.append(MainWithoutApplicationBaseTemplate(src_name, src_rel_path)) + + proj_name = project_name + if workspace is not None: + proj_name = project_name_snake + + project_file_path = f'{project_name_snake}/{project_name}.json' + if workspace is None: + src_path = f'{proj_name}/src/{project_name_snake}' + workspace_file_path = f'{proj_name}/cpl-workspace.json' + project_file_path = f'{src_path}/{project_name}.json' + cls._create_workspace(workspace_file_path, project_name, { + project_name: project_file_path + }) + + else: + workspace.projects[project_name] = f'src/{project_file_path}' + cls._create_workspace('cpl-workspace.json', workspace.default_project, workspace.projects) + + 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 {project_name}/{template.path}{template.name}', + f'Creating {proj_name}/{template.path}{divider}{template.name}', TemplateBuilder.build, project_path, template, diff --git a/src/cpl_cli/startup.py b/src/cpl_cli/startup.py index f05fe10a..84e77c8d 100644 --- a/src/cpl_cli/startup.py +++ b/src/cpl_cli/startup.py @@ -1,13 +1,17 @@ +import os + from cpl.application.startup_abc import StartupABC from cpl.configuration.console_argument import ConsoleArgument from cpl.configuration.configuration_abc import ConfigurationABC from cpl.dependency_injection.service_collection_abc import ServiceCollectionABC from cpl.dependency_injection.service_provider_abc import ServiceProviderABC +from cpl_cli.command.add_service import AddService from cpl_cli.command.build_service import BuildService from cpl_cli.command.generate_service import GenerateService from cpl_cli.command.install_service import InstallService from cpl_cli.command.new_service import NewService from cpl_cli.command.publish_service import PublishService +from cpl_cli.command.remove_service import RemoveService from cpl_cli.command.start_service import StartService from cpl_cli.command.uninstall_service import UninstallService from cpl_cli.command.update_service import UpdateService @@ -29,7 +33,7 @@ class Startup(StartupABC): self._env = self._configuration.environment self._services = services - self._env.set_runtime_directory(__file__) + self._env.set_runtime_directory(os.path.dirname(__file__)) def configure_configuration(self) -> ConfigurationABC: self._configuration.argument_error_function = Error.error @@ -38,6 +42,8 @@ class Startup(StartupABC): self._configuration.add_environment_variables('CPL_') self._configuration.add_json_file('appsettings.json', path=self._env.runtime_directory, optional=False, output=False) + + self._configuration.add_console_argument(ConsoleArgument('', 'add', ['a', 'a'], ' ')) self._configuration.add_console_argument(ConsoleArgument('', 'build', ['b', 'B'], '')) self._configuration.add_console_argument(ConsoleArgument('', 'generate', ['g', 'G'], '', console_arguments=[ ConsoleArgument('', 'abc', ['a', 'A'], ' '), @@ -56,6 +62,7 @@ class Startup(StartupABC): ConsoleArgument('', 'library', ['l', 'L'], ' ') ])) self._configuration.add_console_argument(ConsoleArgument('', 'publish', ['p', 'P'], '')) + self._configuration.add_console_argument(ConsoleArgument('', 'remove', ['r', 'R'], ' ')) self._configuration.add_console_argument(ConsoleArgument('', 'start', ['s', 'S'], '')) self._configuration.add_console_argument(ConsoleArgument('', 'uninstall', ['ui', 'UI'], ' ')) self._configuration.add_console_argument(ConsoleArgument('', 'update', ['u', 'U'], '')) @@ -70,12 +77,14 @@ class Startup(StartupABC): self._services.add_transient(PublisherABC, PublisherService) self._services.add_transient(LiveServerService) + self._services.add_transient(AddService) self._services.add_transient(BuildService) self._services.add_transient(GenerateService) self._services.add_transient(HelpService) self._services.add_transient(InstallService) self._services.add_transient(NewService) self._services.add_transient(PublishService) + self._services.add_transient(RemoveService) self._services.add_transient(StartService) self._services.add_transient(UninstallService) self._services.add_transient(UpdateService) diff --git a/src/cpl_cli/templates/__init__.py b/src/cpl_cli/templates/__init__.py index 978cc953..2d7ccb56 100644 --- a/src/cpl_cli/templates/__init__.py +++ b/src/cpl_cli/templates/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. @@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/templates/build/__init__.py b/src/cpl_cli/templates/build/__init__.py index 46603a05..bd74cfa4 100644 --- a/src/cpl_cli/templates/build/__init__.py +++ b/src/cpl_cli/templates/build/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. @@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates.build' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/templates/generate/__init__.py b/src/cpl_cli/templates/generate/__init__.py index 0d30d1c0..b881ddd1 100644 --- a/src/cpl_cli/templates/generate/__init__.py +++ b/src/cpl_cli/templates/generate/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. @@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates.generate' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/templates/new/__init__.py b/src/cpl_cli/templates/new/__init__.py index 62c8d6be..cda737ac 100644 --- a/src/cpl_cli/templates/new/__init__.py +++ b/src/cpl_cli/templates/new/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. @@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates.new' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/templates/new/console/__init__.py b/src/cpl_cli/templates/new/console/__init__.py index b1a8e76d..1ddf7033 100644 --- a/src/cpl_cli/templates/new/console/__init__.py +++ b/src/cpl_cli/templates/new/console/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. @@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates.new.console' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/templates/new/console/src/name/__init__.py b/src/cpl_cli/templates/new/console/source/__init__.py similarity index 59% rename from src/cpl_cli/templates/new/console/src/name/__init__.py rename to src/cpl_cli/templates/new/console/source/__init__.py index 6f728248..c844cefa 100644 --- a/src/cpl_cli/templates/new/console/src/name/__init__.py +++ b/src/cpl_cli/templates/new/console/source/__init__.py @@ -1,25 +1,25 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. """ -__title__ = 'cpl_cli.templates.new.console.src.name' +__title__ = 'cpl_cli.templates.new.console.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/templates/new/console/src/tests/__init__.py b/src/cpl_cli/templates/new/console/source/name/__init__.py similarity index 59% rename from src/cpl_cli/templates/new/console/src/tests/__init__.py rename to src/cpl_cli/templates/new/console/source/name/__init__.py index 365d5174..7dfac621 100644 --- a/src/cpl_cli/templates/new/console/src/tests/__init__.py +++ b/src/cpl_cli/templates/new/console/source/name/__init__.py @@ -1,25 +1,25 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. """ -__title__ = 'cpl_cli.templates.new.console.src.tests' +__title__ = 'cpl_cli.templates.new.console.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/templates/new/library/src/cli/application.py b/src/cpl_cli/templates/new/console/source/name/application.py similarity index 91% rename from src/cpl_cli/templates/new/library/src/cli/application.py rename to src/cpl_cli/templates/new/console/source/name/application.py index 0d92c2cc..a18686ee 100644 --- a/src/cpl_cli/templates/new/library/src/cli/application.py +++ b/src/cpl_cli/templates/new/console/source/name/application.py @@ -1,3 +1,4 @@ +import os.path import textwrap from cpl.utils.string import String @@ -6,12 +7,12 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC class ApplicationTemplate(TemplateFileABC): - def __init__(self, name: str): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) name = String.convert_to_snake_case(name) self._name = 'application.py' - self._path = f'src/{name}_cli/' + self._path = os.path.join(path, name) self._value = textwrap.dedent("""\ from cpl.application import ApplicationABC from cpl.configuration import ConfigurationABC diff --git a/src/cpl_cli/templates/new/console/src/name/init.py b/src/cpl_cli/templates/new/console/source/name/init.py similarity index 84% rename from src/cpl_cli/templates/new/console/src/name/init.py rename to src/cpl_cli/templates/new/console/source/name/init.py index 9cdd21ad..9f20cefb 100644 --- a/src/cpl_cli/templates/new/console/src/name/init.py +++ b/src/cpl_cli/templates/new/console/source/name/init.py @@ -1,3 +1,4 @@ +import os.path import textwrap from cpl.utils.string import String @@ -6,12 +7,12 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC class MainInitTemplate(TemplateFileABC): - def __init__(self, name: str): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) name = String.convert_to_snake_case(name) self._name = '__init__.py' - self._path = f'src/{name}/' + self._path = os.path.join(path, name) self._value = textwrap.dedent("""\ # imports: """) diff --git a/src/cpl_cli/templates/new/console/src/name/main.py b/src/cpl_cli/templates/new/console/source/name/main.py similarity index 80% rename from src/cpl_cli/templates/new/console/src/name/main.py rename to src/cpl_cli/templates/new/console/source/name/main.py index 7a3cb7ac..fa4a8cf6 100644 --- a/src/cpl_cli/templates/new/console/src/name/main.py +++ b/src/cpl_cli/templates/new/console/source/name/main.py @@ -1,3 +1,4 @@ +import os.path import textwrap from cpl.utils.string import String @@ -6,17 +7,22 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC class MainWithApplicationHostAndStartupTemplate(TemplateFileABC): - def __init__(self, name: str): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) name = String.convert_to_snake_case(name) self._name = 'main.py' - self._path = f'src/{name}/' + self._path = os.path.join(path, name) + + import_pkg = f'{name}.' + if name == '': + import_pkg = '' + self._value = textwrap.dedent(f"""\ from cpl.application import ApplicationBuilder - from {name}.application import Application - from {name}.startup import Startup + from {import_pkg}application import Application + from {import_pkg}startup import Startup def main(): @@ -44,16 +50,21 @@ class MainWithApplicationHostAndStartupTemplate(TemplateFileABC): class MainWithApplicationBaseTemplate(TemplateFileABC): - def __init__(self, name: str): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) name = String.convert_to_snake_case(name) self._name = 'main.py' - self._path = f'src/{name}' + self._path = os.path.join(path, name) + + import_pkg = f'{name}.' + if name == '': + import_pkg = '' + self._value = textwrap.dedent(f"""\ from cpl.application import ApplicationBuilder - from {name}.application import Application + from {import_pkg}application import Application def main(): @@ -80,12 +91,17 @@ class MainWithApplicationBaseTemplate(TemplateFileABC): class MainWithoutApplicationBaseTemplate(TemplateFileABC): - def __init__(self, name: str): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) name = String.convert_to_snake_case(name) self._name = 'main.py' - self._path = f'src/{name}' + self._path = os.path.join(path, name) + + import_pkg = f'{name}.' + if name == '': + import_pkg = '' + self._value = textwrap.dedent("""\ from cpl.console import Console @@ -113,12 +129,17 @@ class MainWithoutApplicationBaseTemplate(TemplateFileABC): class MainWithDependencyInjection(TemplateFileABC): - def __init__(self, name: str): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) name = String.convert_to_snake_case(name) self._name = 'main.py' - self._path = f'src/{name}' + self._path = os.path.join(path, name) + + import_pkg = f'{name}.' + if name == '': + import_pkg = '' + self._value = textwrap.dedent("""\ from cpl.configuration import Configuration, ConfigurationABC from cpl.console import Console diff --git a/src/cpl_cli/templates/new/library/src/cli/startup.py b/src/cpl_cli/templates/new/console/source/name/startup.py similarity index 93% rename from src/cpl_cli/templates/new/library/src/cli/startup.py rename to src/cpl_cli/templates/new/console/source/name/startup.py index 0e33e643..e30ad000 100644 --- a/src/cpl_cli/templates/new/library/src/cli/startup.py +++ b/src/cpl_cli/templates/new/console/source/name/startup.py @@ -1,3 +1,4 @@ +import os.path import textwrap from cpl.utils.string import String @@ -6,12 +7,12 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC class StartupTemplate(TemplateFileABC): - def __init__(self, name: str): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) name = String.convert_to_snake_case(name) self._name = 'startup.py' - self._path = f'src/{name}_cli/' + self._path = os.path.join(path, name) self._value = textwrap.dedent("""\ from cpl.application import StartupABC from cpl.configuration import ConfigurationABC diff --git a/src/cpl_cli/templates/new/console/source/tests/__init__.py b/src/cpl_cli/templates/new/console/source/tests/__init__.py new file mode 100644 index 00000000..e9ec5a2f --- /dev/null +++ b/src/cpl_cli/templates/new/console/source/tests/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +sh_cpl-cli sh-edraft Common Python library CLI +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Common Python library Command Line Interface + +:copyright: (c) 2020 - 2021 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 - 2021 sh-edraft.de' +__version__ = '2021.4' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/templates/new/console/src/tests/init.py b/src/cpl_cli/templates/new/console/source/tests/init.py similarity index 100% rename from src/cpl_cli/templates/new/console/src/tests/init.py rename to src/cpl_cli/templates/new/console/source/tests/init.py diff --git a/src/cpl_cli/templates/new/library/__init__.py b/src/cpl_cli/templates/new/library/__init__.py index 43584a93..b4c7abd9 100644 --- a/src/cpl_cli/templates/new/library/__init__.py +++ b/src/cpl_cli/templates/new/library/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. @@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates.new.library' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/templates/new/library/src/__init__.py b/src/cpl_cli/templates/new/library/source/__init__.py similarity index 59% rename from src/cpl_cli/templates/new/library/src/__init__.py rename to src/cpl_cli/templates/new/library/source/__init__.py index d21498c7..ba73726c 100644 --- a/src/cpl_cli/templates/new/library/src/__init__.py +++ b/src/cpl_cli/templates/new/library/source/__init__.py @@ -1,25 +1,25 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. """ -__title__ = 'cpl_cli.templates.new.library.src' +__title__ = 'cpl_cli.templates.new.library.source' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/templates/new/console/src/__init__.py b/src/cpl_cli/templates/new/library/source/name/__init__.py similarity index 59% rename from src/cpl_cli/templates/new/console/src/__init__.py rename to src/cpl_cli/templates/new/library/source/name/__init__.py index b666bf0d..813c312a 100644 --- a/src/cpl_cli/templates/new/console/src/__init__.py +++ b/src/cpl_cli/templates/new/library/source/name/__init__.py @@ -1,25 +1,25 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. """ -__title__ = 'cpl_cli.templates.new.console.src' +__title__ = 'cpl_cli.templates.new.library.source.name' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/templates/new/console/src/name/application.py b/src/cpl_cli/templates/new/library/source/name/application.py similarity index 92% rename from src/cpl_cli/templates/new/console/src/name/application.py rename to src/cpl_cli/templates/new/library/source/name/application.py index 516c77aa..995b0566 100644 --- a/src/cpl_cli/templates/new/console/src/name/application.py +++ b/src/cpl_cli/templates/new/library/source/name/application.py @@ -1,3 +1,4 @@ +import os import textwrap from cpl.utils.string import String @@ -6,12 +7,12 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC class ApplicationTemplate(TemplateFileABC): - def __init__(self, name: str): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) name = String.convert_to_snake_case(name) self._name = 'application.py' - self._path = f'src/{name}/' + self._path = os.path.join(path, name) self._value = textwrap.dedent("""\ from cpl.application import ApplicationABC from cpl.configuration import ConfigurationABC diff --git a/src/cpl_cli/templates/new/library/src/cli/init.py b/src/cpl_cli/templates/new/library/source/name/init.py similarity index 78% rename from src/cpl_cli/templates/new/library/src/cli/init.py rename to src/cpl_cli/templates/new/library/source/name/init.py index 28634bf3..82e76950 100644 --- a/src/cpl_cli/templates/new/library/src/cli/init.py +++ b/src/cpl_cli/templates/new/library/source/name/init.py @@ -1,17 +1,18 @@ +import os import textwrap from cpl.utils.string import String from cpl_cli.templates.template_file_abc import TemplateFileABC -class CLIInitTemplate(TemplateFileABC): +class NameInitTemplate(TemplateFileABC): - def __init__(self, name: str): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) name = String.convert_to_snake_case(name) self._name = '__init__.py' - self._path = f'src/{name}_cli/' + self._path = os.path.join(path, name) self._value = textwrap.dedent("""\ # imports: """) diff --git a/src/cpl_cli/templates/new/library/src/cli/main.py b/src/cpl_cli/templates/new/library/source/name/main.py similarity index 78% rename from src/cpl_cli/templates/new/library/src/cli/main.py rename to src/cpl_cli/templates/new/library/source/name/main.py index 248cdb3e..e9686271 100644 --- a/src/cpl_cli/templates/new/library/src/cli/main.py +++ b/src/cpl_cli/templates/new/library/source/name/main.py @@ -1,3 +1,4 @@ +import os.path import textwrap from cpl.utils.string import String @@ -6,17 +7,22 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC class MainWithApplicationHostAndStartupTemplate(TemplateFileABC): - def __init__(self, name: str): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) name = String.convert_to_snake_case(name) self._name = 'main.py' - self._path = f'src/{name}_cli/' + self._path = os.path.join(path, name) + + import_pkg = f'{name}.' + if name == '': + import_pkg = '' + self._value = textwrap.dedent(f"""\ from cpl.application import ApplicationBuilder - from {name}_cli.application import Application - from {name}_cli.startup import Startup + from {import_pkg}application import Application + from {import_pkg}startup import Startup def main(): @@ -44,15 +50,21 @@ class MainWithApplicationHostAndStartupTemplate(TemplateFileABC): class MainWithApplicationBaseTemplate(TemplateFileABC): - def __init__(self): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) + name = String.convert_to_snake_case(name) self._name = 'main.py' - self._path = 'src/' + self._path = os.path.join(path, name) + + import_pkg = f'{name}.' + if name == '': + import_pkg = '' + self._value = textwrap.dedent(f"""\ from cpl.application import ApplicationBuilder - from {name}_cli.application import Application + from {import_pkg}application import Application def main(): @@ -79,11 +91,16 @@ class MainWithApplicationBaseTemplate(TemplateFileABC): class MainWithoutApplicationBaseTemplate(TemplateFileABC): - def __init__(self): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) self._name = 'main.py' - self._path = 'src/' + self._path = os.path.join(path, name) + + import_pkg = f'{name}.' + if name == '': + import_pkg = '' + self._value = textwrap.dedent("""\ from cpl.console import Console @@ -111,11 +128,16 @@ class MainWithoutApplicationBaseTemplate(TemplateFileABC): class MainWithDependencyInjection(TemplateFileABC): - def __init__(self): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) self._name = 'main.py' - self._path = 'src/' + self._path = os.path.join(path, name) + + import_pkg = f'{name}.' + if name == '': + import_pkg = '' + self._value = textwrap.dedent("""\ from cpl.configuration import Configuration, ConfigurationABC from cpl.console import Console diff --git a/src/cpl_cli/templates/new/console/src/name/startup.py b/src/cpl_cli/templates/new/library/source/name/startup.py similarity index 93% rename from src/cpl_cli/templates/new/console/src/name/startup.py rename to src/cpl_cli/templates/new/library/source/name/startup.py index 90881b96..fe37fdf4 100644 --- a/src/cpl_cli/templates/new/console/src/name/startup.py +++ b/src/cpl_cli/templates/new/library/source/name/startup.py @@ -1,3 +1,4 @@ +import os import textwrap from cpl.utils.string import String @@ -6,12 +7,12 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC class StartupTemplate(TemplateFileABC): - def __init__(self, name: str): + def __init__(self, name: str, path: str): TemplateFileABC.__init__(self) name = String.convert_to_snake_case(name) self._name = 'startup.py' - self._path = f'src/{name}/' + self._path = os.path.join(path, name) self._value = textwrap.dedent("""\ from cpl.application import StartupABC from cpl.configuration import ConfigurationABC diff --git a/src/cpl_cli/templates/new/library/source/tests/__init__.py b/src/cpl_cli/templates/new/library/source/tests/__init__.py new file mode 100644 index 00000000..b787bf81 --- /dev/null +++ b/src/cpl_cli/templates/new/library/source/tests/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +sh_cpl-cli sh-edraft Common Python library CLI +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Common Python library Command Line Interface + +:copyright: (c) 2020 - 2021 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 - 2021 sh-edraft.de' +__version__ = '2021.4' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/cpl_cli/templates/new/library/src/tests/init.py b/src/cpl_cli/templates/new/library/source/tests/init.py similarity index 100% rename from src/cpl_cli/templates/new/library/src/tests/init.py rename to src/cpl_cli/templates/new/library/source/tests/init.py diff --git a/src/cpl_cli/templates/new/library/src/cli/__init__.py b/src/cpl_cli/templates/new/library/src/cli/__init__.py deleted file mode 100644 index 5f59f690..00000000 --- a/src/cpl_cli/templates/new/library/src/cli/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -sh_cpl 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__ = 'cpl_cli.templates.new.library.src.cli' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' - -from collections import namedtuple - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') diff --git a/src/cpl_cli/templates/new/library/src/name/__init__.py b/src/cpl_cli/templates/new/library/src/name/__init__.py deleted file mode 100644 index 2421f687..00000000 --- a/src/cpl_cli/templates/new/library/src/name/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -sh_cpl 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__ = 'cpl_cli.templates.new.library.src.name' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' - -from collections import namedtuple - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') diff --git a/src/cpl_cli/templates/new/library/src/name/init.py b/src/cpl_cli/templates/new/library/src/name/init.py deleted file mode 100644 index ebb078a7..00000000 --- a/src/cpl_cli/templates/new/library/src/name/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, name: str): - TemplateFileABC.__init__(self) - - self._name = '__init__.py' - self._path = f'src/{name}/' - 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/src/tests/__init__.py b/src/cpl_cli/templates/new/library/src/tests/__init__.py deleted file mode 100644 index 33fba570..00000000 --- a/src/cpl_cli/templates/new/library/src/tests/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -sh_cpl 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__ = 'cpl_cli.templates.new.library.src.tests' -__author__ = 'Sven Heidemann' -__license__ = 'MIT' -__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' - -from collections import namedtuple - -# imports: - -VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') diff --git a/src/cpl_cli/templates/publish/__init__.py b/src/cpl_cli/templates/publish/__init__.py index 1c84a56d..10ad6cb8 100644 --- a/src/cpl_cli/templates/publish/__init__.py +++ b/src/cpl_cli/templates/publish/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_cpl sh-edraft Common Python library +sh_cpl-cli sh-edraft Common Python library CLI ~~~~~~~~~~~~~~~~~~~ -sh-edraft Common Python library +sh-edraft Common Python library Command Line Interface :copyright: (c) 2020 - 2021 sh-edraft.de :license: MIT, see LICENSE for more details. @@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates.publish' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.4.0' +__version__ = '2021.4' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='04', micro='0') +version_info = VersionInfo(major='2021', minor='4', micro='None') diff --git a/src/tests/custom/console/__init__.py b/src/tests/custom/console/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/tests/custom/general/__init__.py b/src/tests/custom/general/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/tests/custom/general/cpl-workspace.json b/src/tests/custom/general/cpl-workspace.json new file mode 100644 index 00000000..3b5ae16f --- /dev/null +++ b/src/tests/custom/general/cpl-workspace.json @@ -0,0 +1,8 @@ +{ + "Workspace": { + "DefaultProject": "general", + "Projects": { + "general": "src/general/general.json" + } + } +} \ No newline at end of file diff --git a/src/tests/custom/__init__.py b/src/tests/custom/general/src/general/__init__.py similarity index 100% rename from src/tests/custom/__init__.py rename to src/tests/custom/general/src/general/__init__.py diff --git a/src/tests/custom/general/application.py b/src/tests/custom/general/src/general/application.py similarity index 97% rename from src/tests/custom/general/application.py rename to src/tests/custom/general/src/general/application.py index f7af31b0..96bcb086 100644 --- a/src/tests/custom/general/application.py +++ b/src/tests/custom/general/src/general/application.py @@ -8,7 +8,7 @@ from cpl.dependency_injection.service_provider_abc import ServiceProviderABC from cpl.logging.logger_abc import LoggerABC from cpl.mailing.email import EMail from cpl.mailing.email_client_abc import EMailClientABC -from tests.custom.general.test_service import TestService +from test_service import TestService class Application(ApplicationABC): diff --git a/src/tests/custom/general/appsettings.development.json b/src/tests/custom/general/src/general/appsettings.development.json similarity index 100% rename from src/tests/custom/general/appsettings.development.json rename to src/tests/custom/general/src/general/appsettings.development.json diff --git a/src/tests/custom/general/appsettings.edrafts-lapi.json b/src/tests/custom/general/src/general/appsettings.edrafts-lapi.json similarity index 100% rename from src/tests/custom/general/appsettings.edrafts-lapi.json rename to src/tests/custom/general/src/general/appsettings.edrafts-lapi.json diff --git a/src/tests/custom/general/appsettings.edrafts-pc.json b/src/tests/custom/general/src/general/appsettings.edrafts-pc.json similarity index 100% rename from src/tests/custom/general/appsettings.edrafts-pc.json rename to src/tests/custom/general/src/general/appsettings.edrafts-pc.json diff --git a/src/tests/custom/general/appsettings.json b/src/tests/custom/general/src/general/appsettings.json similarity index 100% rename from src/tests/custom/general/appsettings.json rename to src/tests/custom/general/src/general/appsettings.json diff --git a/src/tests/custom/general/db/__init__.py b/src/tests/custom/general/src/general/db/__init__.py similarity index 100% rename from src/tests/custom/general/db/__init__.py rename to src/tests/custom/general/src/general/db/__init__.py diff --git a/src/tests/custom/general/cpl.json b/src/tests/custom/general/src/general/general.json similarity index 85% rename from src/tests/custom/general/cpl.json rename to src/tests/custom/general/src/general/general.json index b57adb29..8c2aee2a 100644 --- a/src/tests/custom/general/cpl.json +++ b/src/tests/custom/general/src/general/general.json @@ -1,6 +1,6 @@ { "ProjectSettings": { - "Name": "sh_cpl.tests", + "Name": "general", "Version": { "Major": "2021", "Minor": "04", @@ -16,12 +16,11 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "sh_cpl==2021.4.1.post13", - "discord.py==1.6.0" + "sh_cpl==2021.4.dev1" ], "PythonVersion": ">=3.8", "PythonPath": { - "linux": "../../../../cpl-env/bin/python3.9", + "linux": "../../../../../../cpl-env/bin/python3.9", "win32": "" }, "Classifiers": [] @@ -31,7 +30,7 @@ "SourcePath": "", "OutputPath": "dist", "Main": "main", - "EntryPoint": "cpl", + "EntryPoint": "", "IncludePackageData": true, "Included": [ "*/templates" diff --git a/src/tests/custom/general/main.py b/src/tests/custom/general/src/general/main.py similarity index 69% rename from src/tests/custom/general/main.py rename to src/tests/custom/general/src/general/main.py index a9fd514f..a2e8cbd0 100644 --- a/src/tests/custom/general/main.py +++ b/src/tests/custom/general/src/general/main.py @@ -1,6 +1,6 @@ from cpl.application.application_builder import ApplicationBuilder -from tests.custom.general.application import Application -from tests.custom.general.startup import Startup +from application import Application +from startup import Startup def main(): diff --git a/src/tests/custom/general/startup.py b/src/tests/custom/general/src/general/startup.py similarity index 93% rename from src/tests/custom/general/startup.py rename to src/tests/custom/general/src/general/startup.py index d0370bff..102ae67b 100644 --- a/src/tests/custom/general/startup.py +++ b/src/tests/custom/general/src/general/startup.py @@ -6,7 +6,7 @@ from cpl.logging.logger_service import Logger from cpl.logging.logger_abc import LoggerABC from cpl.mailing.email_client_service import EMailClient from cpl.mailing.email_client_abc import EMailClientABC -from tests.custom.general.test_service import TestService +from test_service import TestService class Startup(StartupABC): @@ -20,7 +20,6 @@ class Startup(StartupABC): def configure_configuration(self) -> ConfigurationABC: self._configuration.add_environment_variables('PYTHON_') self._configuration.add_environment_variables('CPL_') - self._configuration.add_console_arguments() self._configuration.add_json_file(f'appsettings.json') self._configuration.add_json_file(f'appsettings.{self._configuration.environment.environment_name}.json') self._configuration.add_json_file(f'appsettings.{self._configuration.environment.host_name}.json', optional=True) diff --git a/src/tests/custom/general/test_service.py b/src/tests/custom/general/src/general/test_service.py similarity index 100% rename from src/tests/custom/general/test_service.py rename to src/tests/custom/general/src/general/test_service.py