Merge pull request '2021.4.6' (#25) from 2021.4.6 into 2021.4.post1

Reviewed-on: #25
This commit is contained in:
Sven Heidemann 2021-04-11 15:54:37 +02:00
commit cce4b6b191
100 changed files with 1285 additions and 501 deletions

3
.gitignore vendored
View File

@ -110,6 +110,9 @@ ENV/
env.bak/ env.bak/
venv.bak/ venv.bak/
# Custom Environments
cpl-env/
# Spyder project settings # Spyder project settings
.spyderproject .spyderproject
.spyproject .spyproject

View File

@ -38,11 +38,16 @@
### Installation ### Installation
Install the cpl package Install the CPL package
```sh ```sh
pip install sh_cpl --extra-index-url https://pip.sh-edraft.de 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: Create workspace:
```sh ```sh
cpl new <console|library> <PROJECT NAME> cpl new <console|library> <PROJECT NAME>

9
cpl-workspace.json Normal file
View File

@ -0,0 +1,9 @@
{
"WorkspaceSettings": {
"DefaultProject": "cpl_cli",
"Projects": {
"cpl": "src/cpl/cpl.json",
"cpl_cli": "src/cpl_cli/cpl_cli.json"
}
}
}

View File

@ -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

View File

@ -1,2 +0,0 @@
python setup.py install # for install
python setup.py sdist bdist_wheel # for build

View File

@ -1,11 +1,39 @@
upload: upload:
prod: prod:
twine upload --repository-url https://pip.sh-edraft.de dist/publish/setup/* cpl:
twine upload -r pip.sh-edraft.de dist/publish/setup/* 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: dev:
twine upload --repository-url https://pip-dev.sh-edraft.de dist/publish/setup/* cpl:
twine upload -r pip-dev.sh-edraft.de dist/publish/setup/* 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: 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

View File

@ -11,15 +11,15 @@ sh-edraft Common Python library
""" """
__title__ = 'sh_cpl.cpl' __title__ = 'cpl'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -15,7 +15,7 @@ __title__ = 'cpl.application'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
@ -26,4 +26,4 @@ from .application_builder_abc import ApplicationBuilderABC
from .startup_abc import StartupABC from .startup_abc import StartupABC
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -15,7 +15,7 @@ __title__ = 'cpl.configuration'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
@ -27,4 +27,4 @@ from .configuration_variable_name_enum import ConfigurationVariableNameEnum
from .console_argument import ConsoleArgument from .console_argument import ConsoleArgument
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -85,7 +85,7 @@ class Configuration(ConfigurationABC):
Console.write_line(f'[{name}] {message}') Console.write_line(f'[{name}] {message}')
Console.set_foreground_color(ForegroundColorEnum.default) 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 Sets variable to given value
:param name: :param name:
@ -120,6 +120,9 @@ class Configuration(ConfigurationABC):
if found and child_argument_type.name not in self._additional_arguments: if found and child_argument_type.name not in self._additional_arguments:
self._additional_arguments.append(child_argument_type.name) self._additional_arguments.append(child_argument_type.name)
if found:
break
if not found: if not found:
raise Exception(f'Invalid argument: {argument}') raise Exception(f'Invalid argument: {argument}')
@ -157,10 +160,16 @@ class Configuration(ConfigurationABC):
if argument_type.token != '' and argument.startswith(argument_type.token): if argument_type.token != '' and argument.startswith(argument_type.token):
# --new=value # --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] argument_name = argument.split(argument_type.token)[1].split(argument_type.value_token)[0]
else: else:
# new=value # 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 result = True
@ -191,7 +200,7 @@ class Configuration(ConfigurationABC):
# ?new value # ?new value
found = False found = False
for alias in argument_type.aliases: for alias in argument_type.aliases:
if alias in argument: if alias == argument or f' {alias} ' == argument:
found = True found = True
if argument_type.name not in argument and not found: 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 \ if (next_arguments is None or len(next_arguments) == 0) and \
argument_type.is_value_token_optional is not True: 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: if (next_arguments is None or len(next_arguments) == 0) and argument_type.is_value_token_optional is True:
value = '' value = ''
else: else:
value = next_arguments[0] value = next_arguments[0]
next_arguments.remove(value)
self._handled_args.append(value) self._handled_args.append(value)
if argument_type.token != '' and argument.startswith(argument_type.token): 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: if not found and error_message == '' and error is not False:
error_message = f'Invalid argument: {argument}' error_message = f'Invalid argument: {argument}'
if error_message != '':
if self._argument_error_function is not None: if self._argument_error_function is not None:
self._argument_error_function(error_message) self._argument_error_function(error_message)
else: else:
@ -284,15 +295,25 @@ class Configuration(ConfigurationABC):
exit() exit()
def add_json_file(self, name: str, optional: bool = None, output: bool = True, path: str = None): add_args = []
path_root = self._application_environment.content_root_path for next_arg in next_arguments:
if path is not None: if next_arg not in self._handled_args and next_arg not in self._additional_arguments:
path_root = path add_args.append(next_arg)
if str(path_root).endswith('/') and not name.startswith('/'): self._set_variable(f'{argument}AdditionalArguments', add_args)
file_path = f'{path_root}{name}'
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: 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 not os.path.isfile(file_path):
if optional is not True: if optional is not True:
@ -334,7 +355,7 @@ class Configuration(ConfigurationABC):
self._print_error(__name__, f'Cannot load config file: {file}! -> {e}') self._print_error(__name__, f'Cannot load config file: {file}! -> {e}')
return {} 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 self._config[key_type] = value
def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> Union[ def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> Union[

View File

@ -72,7 +72,7 @@ class ConfigurationABC(ABC):
pass pass
@abstractmethod @abstractmethod
def add_configuration(self, key_type: type, value: object): def add_configuration(self, key_type: Union[str, type], value: object):
""" """
Add configuration object Add configuration object
:param key_type: :param key_type:

View File

@ -15,7 +15,7 @@ __title__ = 'cpl.console'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
@ -27,4 +27,4 @@ from .foreground_color_enum import ForegroundColorEnum
from .spinner_thread import SpinnerThread from .spinner_thread import SpinnerThread
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -446,6 +446,8 @@ class Console:
for call in cls._hold_back_calls: for call in cls._hold_back_calls:
call.function(*call.args) call.function(*call.args)
cls._hold_back_calls = []
time.sleep(0.1) time.sleep(0.1)
return return_value return return_value

View File

@ -3,8 +3,8 @@
"Name": "sh_cpl", "Name": "sh_cpl",
"Version": { "Version": {
"Major": "2021", "Major": "2021",
"Minor": "04", "Minor": "4",
"Micro": "0" "Micro": "post1"
}, },
"Author": "Sven Heidemann", "Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de", "AuthorEmail": "sven.heidemann@sh-edraft.de",
@ -22,8 +22,8 @@
"packaging==20.9", "packaging==20.9",
"pyfiglet==0.8.post1", "pyfiglet==0.8.post1",
"pynput==1.7.3", "pynput==1.7.3",
"SQLAlchemy==1.4.3", "SQLAlchemy==1.4.7",
"setuptools==54.2.0", "setuptools==56.0.0",
"tabulate==0.8.9", "tabulate==0.8.9",
"termcolor==1.1.0", "termcolor==1.1.0",
"watchdog==2.0.2", "watchdog==2.0.2",
@ -35,10 +35,10 @@
}, },
"BuildSettings": { "BuildSettings": {
"ProjectType": "library", "ProjectType": "library",
"SourcePath": "src", "SourcePath": "",
"OutputPath": "dist", "OutputPath": "../../dist",
"Main": "cpl_cli.main", "Main": "",
"EntryPoint": "cpl", "EntryPoint": "",
"IncludePackageData": true, "IncludePackageData": true,
"Included": [ "Included": [
"*/templates" "*/templates"
@ -48,10 +48,7 @@
"*/logs", "*/logs",
"*/tests" "*/tests"
], ],
"PackageData": { "PackageData": {},
"cpl_cli": [ "ProjectReferences": []
"*.json"
]
}
} }
} }

View File

@ -15,7 +15,7 @@ __title__ = 'cpl.database'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
@ -25,4 +25,4 @@ from .database_settings import DatabaseSettings
from .database_settings_name_enum import DatabaseSettingsNameEnum from .database_settings_name_enum import DatabaseSettingsNameEnum
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -15,7 +15,7 @@ __title__ = 'cpl.database.connection'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
@ -24,4 +24,4 @@ from .database_connection import DatabaseConnection
from .database_connection_abc import DatabaseConnectionABC from .database_connection_abc import DatabaseConnectionABC
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -15,7 +15,7 @@ __title__ = 'cpl.database.context'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
@ -24,4 +24,4 @@ from .database_context import DatabaseContext
from .database_context_abc import DatabaseContextABC from .database_context_abc import DatabaseContextABC
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -15,7 +15,7 @@ __title__ = 'cpl.dependency_injection'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
@ -28,4 +28,4 @@ from .service_provider import ServiceProvider
from .service_provider_abc import ServiceProviderABC from .service_provider_abc import ServiceProviderABC
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -15,7 +15,7 @@ __title__ = 'cpl.environment'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
@ -25,4 +25,4 @@ from .environment_name_enum import EnvironmentNameEnum
from .application_environment import ApplicationEnvironment from .application_environment import ApplicationEnvironment
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -1,4 +1,4 @@
import pathlib import os
from datetime import datetime from datetime import datetime
from socket import gethostname from socket import gethostname
from typing import Optional from typing import Optional
@ -9,23 +9,21 @@ from cpl.environment.environment_name_enum import EnvironmentNameEnum
class ApplicationEnvironment(ApplicationEnvironmentABC): class ApplicationEnvironment(ApplicationEnvironmentABC):
def __init__(self, name: EnvironmentNameEnum = EnvironmentNameEnum.production, crp: str = './'): def __init__(self, name: EnvironmentNameEnum = EnvironmentNameEnum.production):
""" """
Represents environment of the application Represents environment of the application
:param name: :param name:
:param crp:
""" """
ApplicationEnvironmentABC.__init__(self) ApplicationEnvironmentABC.__init__(self)
self._environment_name: Optional[EnvironmentNameEnum] = name self._environment_name: Optional[EnvironmentNameEnum] = name
self._app_name: Optional[str] = None self._app_name: Optional[str] = None
self._customer: Optional[str] = None self._customer: Optional[str] = None
self._content_root_path: Optional[str] = crp
self._start_time: datetime = datetime.now() self._start_time: datetime = datetime.now()
self._end_time: datetime = datetime.now() self._end_time: datetime = datetime.now()
self._working_directory = pathlib.Path().absolute() self._runtime_directory = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
self._runtime_directory = pathlib.Path(__file__).parent.absolute() self._working_directory = os.getcwd()
@property @property
def environment_name(self) -> str: def environment_name(self) -> str:
@ -51,14 +49,6 @@ class ApplicationEnvironment(ApplicationEnvironmentABC):
def customer(self, customer: str): def customer(self, customer: str):
self._customer = customer 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 @property
def host_name(self): def host_name(self):
return gethostname() return gethostname()
@ -81,18 +71,24 @@ class ApplicationEnvironment(ApplicationEnvironmentABC):
@property @property
def working_directory(self) -> str: def working_directory(self) -> str:
return self._working_directory return str(self._working_directory)
def set_working_directory(self, path: str = ''):
if path != '':
self._working_directory = path
return
self._working_directory = pathlib.Path().absolute()
@property @property
def runtime_directory(self) -> str: def runtime_directory(self) -> str:
return self._runtime_directory return str(self._runtime_directory)
def set_runtime_directory(self, file: str): def set_runtime_directory(self, runtime_directory: str):
self._runtime_directory = pathlib.Path(file).parent.absolute() 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)

View File

@ -35,14 +35,6 @@ class ApplicationEnvironmentABC(ABC):
@abstractmethod @abstractmethod
def customer(self, customer: str): pass 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 @property
@abstractmethod @abstractmethod
def host_name(self) -> str: pass def host_name(self) -> str: pass
@ -83,3 +75,12 @@ class ApplicationEnvironmentABC(ABC):
:return: :return:
""" """
pass pass
@abstractmethod
def set_working_directory(self, working_directory: str):
"""
Sets the current working directory
:param working_directory:
:return:
"""
pass

View File

@ -15,7 +15,7 @@ __title__ = 'cpl.logging'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
@ -27,4 +27,4 @@ from .logging_settings import LoggingSettings
from .logging_settings_name_enum import LoggingSettingsNameEnum from .logging_settings_name_enum import LoggingSettingsNameEnum
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -15,7 +15,7 @@ __title__ = 'cpl.mailing'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
@ -27,4 +27,4 @@ from .email_client_settings import EMailClientSettings
from .email_client_settings_name_enum import EMailClientSettingsNameEnum from .email_client_settings_name_enum import EMailClientSettingsNameEnum
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -15,7 +15,7 @@ __title__ = 'cpl.time'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
@ -24,4 +24,4 @@ from .time_format_settings import TimeFormatSettings
from .time_format_settings_names_enum import TimeFormatSettingsNamesEnum from .time_format_settings_names_enum import TimeFormatSettingsNamesEnum
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -15,7 +15,7 @@ __title__ = 'cpl.utils'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4.post1'
from collections import namedtuple from collections import namedtuple
@ -25,4 +25,4 @@ from .string import String
from .pip import Pip from .pip import Pip
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='post1')

View File

@ -1,6 +1,9 @@
import os
import subprocess import subprocess
import sys import sys
import shlex
from contextlib import suppress from contextlib import suppress
from textwrap import dedent
from typing import Optional from typing import Optional
@ -9,6 +12,8 @@ class Pip:
Executes pip commands Executes pip commands
""" """
_executable = sys.executable _executable = sys.executable
_env = os.environ
_is_venv = False
""" """
Getter Getter
@ -29,8 +34,17 @@ class Pip:
:param executable: :param executable:
:return: :return:
""" """
if executable is not None: if executable is not None and executable != sys.executable:
cls._executable = 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 @classmethod
def reset_executable(cls): def reset_executable(cls):
@ -39,6 +53,7 @@ class Pip:
:return: :return:
""" """
cls._executable = sys.executable cls._executable = sys.executable
cls._is_venv = False
""" """
Public utils functions Public utils functions
@ -53,7 +68,14 @@ class Pip:
""" """
result = None result = None
with suppress(Exception): 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: if result is None:
return None return None
@ -76,7 +98,11 @@ class Pip:
Gets table of outdated packages Gets table of outdated packages
:return: :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 @classmethod
def install(cls, package: str, *args, source: str = None, stdout=None, stderr=None): def install(cls, package: str, *args, source: str = None, stdout=None, stderr=None):
@ -90,6 +116,8 @@ class Pip:
:return: :return:
""" """
pip_args = [cls._executable, "-m", "pip", "install"] pip_args = [cls._executable, "-m", "pip", "install"]
if cls._is_venv:
pip_args = ["pip", "install"]
for arg in args: for arg in args:
pip_args.append(arg) pip_args.append(arg)
@ -99,7 +127,7 @@ class Pip:
pip_args.append(source) pip_args.append(source)
pip_args.append(package) pip_args.append(package)
subprocess.run(pip_args, stdout=stdout, stderr=stderr) subprocess.run(pip_args, stdout=stdout, stderr=stderr, env=cls._env)
@classmethod @classmethod
def uninstall(cls, package: str, stdout=None, stderr=None): def uninstall(cls, package: str, stdout=None, stderr=None):
@ -110,4 +138,11 @@ class Pip:
:param stderr: :param stderr:
:return: :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
)

View File

@ -1,4 +1,6 @@
import re import re
import string
import random
class String: class String:
@ -7,31 +9,58 @@ class String:
""" """
@staticmethod @staticmethod
def convert_to_snake_case(name: str) -> str: def convert_to_camel_case(chars: str) -> str:
""" """
Converts string to snake case Converts string to camel case
:param name: :param chars:
:return: :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]+)') pattern1 = re.compile(r'(.)([A-Z][a-z]+)')
pattern2 = re.compile(r'([a-z0-9])([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() return re.sub(pattern2, r'\1_\2', file_name).lower()
@staticmethod @staticmethod
def first_to_upper(string: str) -> str: def first_to_upper(chars: str) -> str:
""" """
Converts first char to upper Converts first char to upper
:param string: :param chars:
:return: :return:
""" """
return f'{string[0].upper()}{string[1:]}' return f'{chars[0].upper()}{chars[1:]}'
@staticmethod @staticmethod
def first_to_lower(string: str) -> str: def first_to_lower(chars: str) -> str:
""" """
Converts first char to lower Converts first char to lower
:param string: :param chars:
:return: :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))

View File

@ -1,21 +1,21 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
""" """
__title__ = 'sh_cpl.cpl_cli' __title__ = 'cpl_cli'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
@ -29,4 +29,4 @@ from .main import main
from .startup import Startup from .startup import Startup
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -4,11 +4,13 @@ from cpl.application.application_abc import ApplicationABC
from cpl.configuration.configuration_abc import ConfigurationABC from cpl.configuration.configuration_abc import ConfigurationABC
from cpl.console.console import Console from cpl.console.console import Console
from cpl.dependency_injection import ServiceProviderABC 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.build_service import BuildService
from cpl_cli.command.generate_service import GenerateService from cpl_cli.command.generate_service import GenerateService
from cpl_cli.command.install_service import InstallService from cpl_cli.command.install_service import InstallService
from cpl_cli.command.new_service import NewService from cpl_cli.command.new_service import NewService
from cpl_cli.command.publish_service import PublishService 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.start_service import StartService
from cpl_cli.command.uninstall_service import UninstallService from cpl_cli.command.uninstall_service import UninstallService
from cpl_cli.command.update_service import UpdateService from cpl_cli.command.update_service import UpdateService
@ -32,16 +34,18 @@ class CLI(ApplicationABC):
def configure(self): def configure(self):
self._command_handler: CommandHandler = self._services.get_service(CommandHandler) 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('add', ['a', 'a'], AddService, False, False, False))
self._command_handler.add_command(CommandModel('generate', ['g', 'G'], GenerateService, True)) self._command_handler.add_command(CommandModel('build', ['b', 'B'], BuildService, False, True, True))
self._command_handler.add_command(CommandModel('help', ['h', 'H'], HelpService, False)) self._command_handler.add_command(CommandModel('generate', ['g', 'G'], GenerateService, False, True, False))
self._command_handler.add_command(CommandModel('install', ['i', 'I'], InstallService, True)) self._command_handler.add_command(CommandModel('help', ['h', 'H'], HelpService, False, False, False))
self._command_handler.add_command(CommandModel('new', ['n', 'N'], NewService, False)) self._command_handler.add_command(CommandModel('install', ['i', 'I'], InstallService, False, True, True))
self._command_handler.add_command(CommandModel('publish', ['p', 'P'], PublishService, True)) self._command_handler.add_command(CommandModel('new', ['n', 'N'], NewService, False, False, True))
self._command_handler.add_command(CommandModel('start', ['s', 'S'], StartService, True)) self._command_handler.add_command(CommandModel('publish', ['p', 'P'], PublishService, False, True, True))
self._command_handler.add_command(CommandModel('uninstall', ['ui', 'UI'], UninstallService, True)) self._command_handler.add_command(CommandModel('remove', ['r', 'R'], RemoveService, True, True, False))
self._command_handler.add_command(CommandModel('update', ['u', 'U'], UpdateService, True)) self._command_handler.add_command(CommandModel('start', ['s', 'S'], StartService, False, True, True))
self._command_handler.add_command(CommandModel('version', ['v', 'V'], VersionService, False)) 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): def main(self):
""" """
@ -58,10 +62,14 @@ class CLI(ApplicationABC):
else: else:
for cmd in self._command_handler.commands: for cmd in self._command_handler.commands:
result = self._configuration.get_configuration(cmd.name) result = self._configuration.get_configuration(cmd.name)
result_args = self._configuration.get_configuration(f'{cmd.name}AdditionalArguments')
if result is not None: if result is not None:
command = cmd.name command = cmd.name
args.append(result) args.append(result)
for arg in result_args:
args.append(arg)
if command is None: if command is None:
Error.error(f'Expected command') Error.error(f'Expected command')
return return

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
@ -15,7 +15,7 @@ __title__ = 'cpl_cli.command'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
@ -28,4 +28,4 @@ from .publish_service import PublishService
from .version_service import VersionService from .version_service import VersionService
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -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
)

View File

@ -102,7 +102,7 @@ class GenerateService(CommandABC):
rel_path = '/'.join(parts[:-1]) rel_path = '/'.join(parts[:-1])
class_name = parts[len(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}' rel_path = f'src/{rel_path}'
template = template(class_name, schematic, self._schematics[schematic]["Upper"], rel_path) template = template(class_name, schematic, self._schematics[schematic]["Upper"], rel_path)

View File

@ -19,13 +19,15 @@ class HelpService(CommandABC):
""" """
Console.write_line('Available Commands:') Console.write_line('Available Commands:')
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.'], ['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.'], ['generate (g|G)', 'Generate a new file.'],
['help (h|H)', 'Lists available command and their short descriptions.'], ['help (h|H)', 'Lists available command and their short descriptions.'],
['install (i|I)', 'With argument installs packages to project, without argument installs project dependencies.'], ['install (i|I)', 'With argument installs packages to project, without argument installs project dependencies.'],
['new (n|N)', 'Creates new CPL project.'], ['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.'], ['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.'], ['uninstall (ui|UI)', 'Uninstalls packages from project.'],
['update (u|u)', 'Update CPL and project dependencies.'], ['update (u|u)', 'Update CPL and project dependencies.'],
['version (v|V)', 'Outputs CPL CLI version.'] ['version (v|V)', 'Outputs CPL CLI version.']

View File

@ -4,6 +4,7 @@ import subprocess
from packaging import version from packaging import version
from cpl.configuration.configuration_abc import ConfigurationABC
from cpl.console.console import Console from cpl.console.console import Console
from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.console.foreground_color_enum import ForegroundColorEnum
from cpl.environment.application_environment_abc import ApplicationEnvironmentABC from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
@ -18,10 +19,11 @@ from cpl_cli.error import Error
class InstallService(CommandABC): class InstallService(CommandABC):
def __init__(self, env: ApplicationEnvironmentABC, build_settings: BuildSettings, project_settings: ProjectSettings, def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC, build_settings: BuildSettings,
cli_settings: CLISettings): project_settings: ProjectSettings, cli_settings: CLISettings):
""" """
Service for the CLI command install Service for the CLI command install
:param config:
:param env: :param env:
:param build_settings: :param build_settings:
:param project_settings: :param project_settings:
@ -29,11 +31,14 @@ class InstallService(CommandABC):
""" """
CommandABC.__init__(self) CommandABC.__init__(self)
self._config = config
self._env = env self._env = env
self._build_settings = build_settings self._build_settings = build_settings
self._project_settings = project_settings self._project_settings = project_settings
self._cli_settings = cli_settings self._cli_settings = cli_settings
self._project_file = f'{self._config.get_configuration("ProjectName")}.json'
def _install_project(self): def _install_project(self):
""" """
Installs dependencies of CPl project Installs dependencies of CPl project
@ -45,7 +50,7 @@ class InstallService(CommandABC):
return return
if self._project_settings.dependencies is None: 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 return
Pip.set_executable(self._project_settings.python_executable) Pip.set_executable(self._project_settings.python_executable)
@ -76,7 +81,7 @@ class InstallService(CommandABC):
return return
if self._project_settings.dependencies is None: 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 return
package_version = '' package_version = ''
@ -121,6 +126,7 @@ class InstallService(CommandABC):
spinner_foreground_color=ForegroundColorEnum.cyan spinner_foreground_color=ForegroundColorEnum.cyan
) )
new_package = Pip.get_package(name) new_package = Pip.get_package(name)
Console.write_line(new_package)
if new_package is None \ if new_package is None \
or '==' in package and \ or '==' in package and \
version.parse(package.split('==')[1]) != version.parse(new_package.split('==')[1]): 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) 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.write(json.dumps(config, indent=2))
project_file.close() project_file.close()

View File

@ -1,4 +1,3 @@
import json
import os import os
import sys import sys
from typing import Optional 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_settings_name_enum import ProjectSettingsNameEnum
from cpl_cli.configuration.project_type_enum import ProjectTypeEnum from cpl_cli.configuration.project_type_enum import ProjectTypeEnum
from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum 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.console_builder import ConsoleBuilder
from cpl_cli.source_creator.library_builder import LibraryBuilder from cpl_cli.source_creator.library_builder import LibraryBuilder
@ -34,6 +34,7 @@ class NewService(CommandABC):
self._config = configuration self._config = configuration
self._env = self._config.environment self._env = self._config.environment
self._workspace = self._config.get_configuration(WorkspaceSettings)
self._project: ProjectSettings = ProjectSettings() self._project: ProjectSettings = ProjectSettings()
self._project_dict = {} self._project_dict = {}
self._build: BuildSettings = BuildSettings() self._build: BuildSettings = BuildSettings()
@ -93,12 +94,12 @@ class NewService(CommandABC):
def _create_build_settings(self): def _create_build_settings(self):
main = f'{String.convert_to_snake_case(self._project.name)}.main' main = f'{String.convert_to_snake_case(self._project.name)}.main'
if self._command == ProjectTypeEnum.library.value: 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 = { self._build_dict = {
BuildSettingsNameEnum.project_type.value: self._command, BuildSettingsNameEnum.project_type.value: self._command,
BuildSettingsNameEnum.source_path.value: 'src', BuildSettingsNameEnum.source_path.value: '',
BuildSettingsNameEnum.output_path.value: 'dist', BuildSettingsNameEnum.output_path.value: '../../dist',
BuildSettingsNameEnum.main.value: main, BuildSettingsNameEnum.main.value: main,
BuildSettingsNameEnum.entry_point.value: self._project.name, BuildSettingsNameEnum.entry_point.value: self._project.name,
BuildSettingsNameEnum.include_package_data.value: False, BuildSettingsNameEnum.include_package_data.value: False,
@ -108,7 +109,8 @@ class NewService(CommandABC):
'*/logs', '*/logs',
'*/tests' '*/tests'
], ],
BuildSettingsNameEnum.package_data.value: {} BuildSettingsNameEnum.package_data.value: {},
BuildSettingsNameEnum.project_references.value: []
} }
self._build.from_dict(self._build_dict) self._build.from_dict(self._build_dict)
@ -127,7 +129,15 @@ class NewService(CommandABC):
Gets project path Gets project path
:return: :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: if os.path.isdir(project_path) and len(os.listdir(project_path)) > 0:
Console.error('Project path is not empty\n') Console.error('Project path is not empty\n')
return None return None
@ -176,7 +186,8 @@ class NewService(CommandABC):
self._use_startup, self._use_startup,
self._use_service_providing, self._use_service_providing,
self._project.name, self._project.name,
self._project_json self._project_json,
self._workspace
) )
except Exception as e: except Exception as e:
Console.error('Could not create project', str(e)) Console.error('Could not create project', str(e))
@ -204,7 +215,8 @@ class NewService(CommandABC):
self._use_startup, self._use_startup,
self._use_service_providing, self._use_service_providing,
self._project.name, self._project.name,
self._project_json self._project_json,
self._workspace
) )
except Exception as e: except Exception as e:
Console.error('Could not create project', str(e)) Console.error('Could not create project', str(e))

View File

@ -1,4 +1,3 @@
from cpl.console.console import Console
from cpl_cli.command_abc import CommandABC from cpl_cli.command_abc import CommandABC
from cpl_cli.publish.publisher_abc import PublisherABC from cpl_cli.publish.publisher_abc import PublisherABC

View File

@ -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
)

View File

@ -19,4 +19,4 @@ class StartService(CommandABC):
:param args: :param args:
:return: :return:
""" """
self._live_server.start() self._live_server.start(args)

View File

@ -2,6 +2,7 @@ import json
import os import os
import subprocess import subprocess
from cpl.configuration.configuration_abc import ConfigurationABC
from cpl.console.console import Console from cpl.console.console import Console
from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.console.foreground_color_enum import ForegroundColorEnum
from cpl.environment.application_environment_abc import ApplicationEnvironmentABC from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
@ -14,18 +15,19 @@ from cpl_cli.configuration.settings_helper import SettingsHelper
class UninstallService(CommandABC): class UninstallService(CommandABC):
def __init__(self, env: ApplicationEnvironmentABC, build_settings: BuildSettings, def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC, build_settings: BuildSettings,
project_settings: ProjectSettings): project_settings: ProjectSettings):
""" """
Service for the CLI command uninstall Service for the CLI command uninstall
:param config:
:param env: :param env:
:param build_settings: :param build_settings:
:param project_settings: :param project_settings:
""" """
CommandABC.__init__(self) CommandABC.__init__(self)
self._config = config
self._env = env self._env = env
self._build_settings = build_settings self._build_settings = build_settings
self._project_settings = project_settings self._project_settings = project_settings
@ -74,7 +76,7 @@ class UninstallService(CommandABC):
ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings), ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings),
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_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.write(json.dumps(config, indent=2))
project_file.close() project_file.close()

View File

@ -2,6 +2,7 @@ import json
import os import os
import subprocess import subprocess
from cpl.configuration.configuration_abc import ConfigurationABC
from cpl.console.console import Console from cpl.console.console import Console
from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.console.foreground_color_enum import ForegroundColorEnum
from cpl.environment.application_environment_abc import ApplicationEnvironmentABC from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
@ -16,12 +17,14 @@ from cpl_cli.configuration.settings_helper import SettingsHelper
class UpdateService(CommandABC): class UpdateService(CommandABC):
def __init__(self, def __init__(self,
config: ConfigurationABC,
env: ApplicationEnvironmentABC, env: ApplicationEnvironmentABC,
build_settings: BuildSettings, build_settings: BuildSettings,
project_settings: ProjectSettings, project_settings: ProjectSettings,
cli_settings: CLISettings): cli_settings: CLISettings):
""" """
Service for the CLI command update Service for the CLI command update
:param config:
:param env: :param env:
:param build_settings: :param build_settings:
:param project_settings: :param project_settings:
@ -29,6 +32,7 @@ class UpdateService(CommandABC):
""" """
CommandABC.__init__(self) CommandABC.__init__(self)
self._config = config
self._env = env self._env = env
self._build_settings = build_settings self._build_settings = build_settings
self._project_settings = project_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): 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 old_package:
:param new_package: :param new_package:
:return: :return:
@ -135,7 +139,8 @@ class UpdateService(CommandABC):
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_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: 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.write(json.dumps(config, indent=2))
project.close() project.close()

View File

@ -1,9 +1,12 @@
import os import os
from abc import ABC from abc import ABC
from typing import Optional
from cpl.configuration.configuration_abc import ConfigurationABC from cpl.configuration.configuration_abc import ConfigurationABC
from cpl.console.console import Console from cpl.console.console import Console
from cpl.dependency_injection.service_provider_abc import ServiceProviderABC 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.error import Error
from cpl_cli.command_model import CommandModel from cpl_cli.command_model import CommandModel
@ -28,6 +31,12 @@ class CommandHandler(ABC):
def commands(self) -> list[CommandModel]: def commands(self) -> list[CommandModel]:
return self._commands 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): def add_command(self, cmd: CommandModel):
self._commands.append(cmd) self._commands.append(cmd)
@ -43,12 +52,63 @@ class CommandHandler(ABC):
""" """
for command in self._commands: for command in self._commands:
if cmd == command.name or cmd in command.aliases: 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 = None
Error.error('The command requires to be run in an CPL project, but a project could not be found.') project_name: Optional[str] = None
return 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: 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) self._services.get_service(command.command).run(args)
Console.write('\n') Console.write('\n')

View File

@ -5,11 +5,14 @@ from cpl_cli.command_abc import CommandABC
class CommandModel: 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._name = name
self._aliases = aliases self._aliases = aliases
self._command = command self._command = command
self._is_workspace_needed = is_workspace_needed
self._is_project_needed = is_project_needed self._is_project_needed = is_project_needed
self._change_cwd = change_cwd
@property @property
def name(self) -> str: def name(self) -> str:
@ -18,11 +21,19 @@ class CommandModel:
@property @property
def aliases(self) -> list[str]: def aliases(self) -> list[str]:
return self._aliases return self._aliases
@property @property
def command(self) -> Callable[CommandABC]: def command(self) -> Callable[CommandABC]:
return self._command return self._command
@property
def is_workspace_needed(self) -> bool:
return self._is_workspace_needed
@property @property
def is_project_needed(self) -> bool: def is_project_needed(self) -> bool:
return self._is_project_needed return self._is_project_needed
@property
def change_cwd(self) -> bool:
return self._change_cwd

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
@ -15,7 +15,7 @@ __title__ = 'cpl_cli.configuration'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
@ -26,6 +26,8 @@ from .project_settings import ProjectSettings
from .project_settings_name_enum import ProjectSettingsNameEnum from .project_settings_name_enum import ProjectSettingsNameEnum
from .version_settings import VersionSettings from .version_settings import VersionSettings
from .version_settings_name_enum import VersionSettingsNameEnum 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') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -23,6 +23,7 @@ class BuildSettings(ConfigurationModelABC):
self._included: Optional[list[str]] = None self._included: Optional[list[str]] = None
self._excluded: Optional[list[str]] = None self._excluded: Optional[list[str]] = None
self._package_data: Optional[dict[str, list[str]]] = None self._package_data: Optional[dict[str, list[str]]] = None
self._project_references: Optional[list[str]] = None
@property @property
def project_type(self): def project_type(self):
@ -60,6 +61,10 @@ class BuildSettings(ConfigurationModelABC):
def package_data(self) -> dict[str, list[str]]: def package_data(self) -> dict[str, list[str]]:
return self._package_data return self._package_data
@property
def project_references(self) -> list[str]:
return self._project_references
def from_dict(self, settings: dict): def from_dict(self, settings: dict):
try: try:
self._project_type = settings[BuildSettingsNameEnum.project_type.value] self._project_type = settings[BuildSettingsNameEnum.project_type.value]
@ -71,6 +76,7 @@ class BuildSettings(ConfigurationModelABC):
self._included = settings[BuildSettingsNameEnum.included.value] self._included = settings[BuildSettingsNameEnum.included.value]
self._excluded = settings[BuildSettingsNameEnum.excluded.value] self._excluded = settings[BuildSettingsNameEnum.excluded.value]
self._package_data = settings[BuildSettingsNameEnum.package_data.value] self._package_data = settings[BuildSettingsNameEnum.package_data.value]
self._project_references = settings[BuildSettingsNameEnum.project_references.value]
if sys.platform == 'win32': if sys.platform == 'win32':
self._source_path = str(self._source_path).replace('/', '\\') self._source_path = str(self._source_path).replace('/', '\\')

View File

@ -12,3 +12,4 @@ class BuildSettingsNameEnum(Enum):
included = 'Included' included = 'Included'
excluded = 'Excluded' excluded = 'Excluded'
package_data = 'PackageData' package_data = 'PackageData'
project_references = 'ProjectReferences'

View File

@ -42,5 +42,6 @@ class SettingsHelper:
BuildSettingsNameEnum.include_package_data.value: build.include_package_data, BuildSettingsNameEnum.include_package_data.value: build.include_package_data,
BuildSettingsNameEnum.included.value: build.included, BuildSettingsNameEnum.included.value: build.included,
BuildSettingsNameEnum.excluded.value: build.excluded, 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
} }

View File

@ -31,16 +31,25 @@ class VersionSettings(ConfigurationModelABC):
return self._micro return self._micro
def to_str(self) -> str: 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): def from_dict(self, settings: dict):
self._major = settings[VersionSettingsNameEnum.major.value] self._major = settings[VersionSettingsNameEnum.major.value]
self._minor = settings[VersionSettingsNameEnum.minor.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: def to_dict(self) -> dict:
return { version = {
VersionSettingsNameEnum.major.value: self._major, VersionSettingsNameEnum.major.value: self._major,
VersionSettingsNameEnum.minor.value: self._minor, VersionSettingsNameEnum.minor.value: self._minor,
VersionSettingsNameEnum.micro.value: self._micro
} }
if self._micro is not None:
version[VersionSettingsNameEnum.micro.value] = self._micro
return version

View File

@ -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()}')

View File

@ -0,0 +1,7 @@
from enum import Enum
class WorkspaceSettingsNameEnum(Enum):
default_project = 'DefaultProject'
projects = 'Projects'

47
src/cpl_cli/cpl_cli.json Normal file
View File

@ -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": []
}
}

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
@ -15,11 +15,11 @@ __title__ = 'cpl_cli.live_server'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -9,26 +9,32 @@ from watchdog.observers import Observer
from cpl.console.console import Console from cpl.console.console import Console
from cpl.environment.application_environment_abc import ApplicationEnvironmentABC from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl_cli.configuration.build_settings import BuildSettings from cpl_cli.configuration.build_settings import BuildSettings
from cpl_cli.configuration.project_settings import ProjectSettings
from cpl_cli.live_server.live_server_thread import LiveServerThread from cpl_cli.live_server.live_server_thread import LiveServerThread
class LiveServerService(FileSystemEventHandler): 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 Service for the live development server
:param env: :param env:
:param project_settings:
:param build_settings: :param build_settings:
""" """
FileSystemEventHandler.__init__(self) FileSystemEventHandler.__init__(self)
self._env = env self._env = env
self._project_settings = project_settings
self._build_settings = build_settings self._build_settings = build_settings
self._src_dir = os.path.join(self._env.working_directory, self._build_settings.source_path) self._src_dir = os.path.join(self._env.working_directory, self._build_settings.source_path)
self._ls_thread = None self._ls_thread = None
self._observer = None self._observer = None
self._args: list[str] = []
def _start_observer(self): def _start_observer(self):
""" """
Starts the file changes observer Starts the file changes observer
@ -70,15 +76,27 @@ class LiveServerService(FileSystemEventHandler):
def _start(self): def _start(self):
self._start_observer() 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.start()
self._ls_thread.join() self._ls_thread.join()
Console.close() Console.close()
def start(self): def start(self, args: list[str]):
""" """
Starts the CPL live development server Starts the CPL live development server
:param args:
:return: :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 **') Console.write_line('** CPL live development server is running **')
self._start() self._start()

View File

@ -6,23 +6,36 @@ from datetime import datetime
from cpl.console.console import Console from cpl.console.console import Console
from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.console.foreground_color_enum import ForegroundColorEnum
from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl_cli.configuration import BuildSettings from cpl_cli.configuration import BuildSettings
class LiveServerThread(threading.Thread): 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 Thread to start the CPL project for the live development server
:param executable:
:param path: :param path:
:param args:
:param env:
:param build_settings:
""" """
threading.Thread.__init__(self) threading.Thread.__init__(self)
self._executable = os.path.abspath(executable)
self._path = path self._path = path
self._args = args
self._env = env
self._build_settings = build_settings self._build_settings = build_settings
self._main = '' self._main = ''
self._command = [] self._command = []
self._env_vars = os.environ
self._set_venv()
@property @property
def command(self) -> list[str]: def command(self) -> list[str]:
@ -32,17 +45,38 @@ class LiveServerThread(threading.Thread):
def main(self) -> str: def main(self) -> str:
return self._main 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): def run(self):
""" """
Starts the CPL project Starts the CPL project
:return: :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') self._main = os.path.join(self._path, f'{main}.py')
if not os.path.isfile(self._main): if not os.path.isfile(self._main):
Console.error('Entry point main.py not found') Console.error('Entry point main.py not found')
return 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.set_foreground_color(ForegroundColorEnum.green)
Console.write_line('Read successfully') Console.write_line('Read successfully')
Console.set_foreground_color(ForegroundColorEnum.cyan) 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.write_line(f'Started at {now.strftime("%Y-%m-%d %H:%M:%S")}\n\n')
Console.set_foreground_color(ForegroundColorEnum.default) Console.set_foreground_color(ForegroundColorEnum.default)
env_vars = os.environ os.chdir(self._env.working_directory)
if sys.platform == 'win32': self._command = [self._executable, self._main, ''.join(self._args)]
env_vars['PYTHONPATH'] = f'{os.path.dirname(self._path)};' \ subprocess.run(self._command, env=self._env_vars)
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)

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
@ -15,7 +15,7 @@ __title__ = 'cpl_cli.publish'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
@ -24,4 +24,4 @@ from .publisher_abc import PublisherABC
from .publisher_service import PublisherService from .publisher_service import PublisherService
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -7,6 +7,7 @@ import setuptools
from packaging import version from packaging import version
from setuptools import sandbox from setuptools import sandbox
from cpl.configuration.configuration_abc import ConfigurationABC
from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.console.foreground_color_enum import ForegroundColorEnum
from cpl.console.console import Console from cpl.console.console import Console
from cpl.environment.application_environment_abc import ApplicationEnvironmentABC from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
@ -19,15 +20,18 @@ from cpl_cli.templates.publish.setup_template import SetupTemplate
class PublisherService(PublisherABC): 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 Service to build or publish files for distribution
:param config:
:param env: :param env:
:param project: :param project:
:param build: :param build:
""" """
PublisherABC.__init__(self) PublisherABC.__init__(self)
self._config = config
self._env = env self._env = env
self._project_settings = project self._project_settings = project
self._build_settings = build self._build_settings = build
@ -130,6 +134,43 @@ class PublisherService(PublisherABC):
return False 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): def _read_sources(self):
""" """
Reads all source files and save included files Reads all source files and save included files
@ -148,21 +189,16 @@ class PublisherService(PublisherABC):
elif os.path.isfile(rel_path): elif os.path.isfile(rel_path):
self._included_files.append(rel_path) self._included_files.append(rel_path)
for r, d, f in os.walk(self._build_settings.source_path): self._read_sources_from_path(self._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
if len(d) > 0: for project in self._build_settings.project_references:
for directory in d: project = os.path.abspath(os.path.join(self._source_path, project))
empty_dir = os.path.join(os.path.dirname(file_path), directory) if not os.path.isfile(os.path.abspath(project)):
if len(os.listdir(empty_dir)) == 0: Console.error(f'Cannot import project: {project}')
self._included_dirs.append(empty_dir) return
if not self._is_path_excluded(relative_path): self.exclude(f'*/{os.path.basename(project)}')
self._included_files.append(os.path.relpath(file_path)) self._read_sources_from_path(os.path.dirname(project))
def _create_packages(self): def _create_packages(self):
""" """
@ -177,8 +213,6 @@ class PublisherService(PublisherABC):
title = self._get_module_name_from_dirs(file) title = self._get_module_name_from_dirs(file)
if title == '': if title == '':
title = self._project_settings.name title = self._project_settings.name
elif not title.__contains__('.'):
title = f'{self._project_settings.name}.{title}'
module_py_lines: list[str] = [] module_py_lines: list[str] = []
imports = '' imports = ''
@ -289,31 +323,39 @@ class PublisherService(PublisherABC):
if os.path.isfile(setup_file): if os.path.isfile(setup_file):
os.remove(setup_file) os.remove(setup_file)
main = None entry_points = {}
try: if self._build_settings.main != "":
main_name = self._build_settings.main main = None
try:
main_name = self._build_settings.main
if '.' in self._build_settings.main: if '.' in self._build_settings.main:
length = len(self._build_settings.main.split('.')) length = len(self._build_settings.main.split('.'))
main_name = self._build_settings.main.split('.')[length - 1] main_name = self._build_settings.main.split('.')[length - 1]
sys.path.insert(0, self._source_path) sys.path.insert(0, self._source_path)
main_mod = __import__(self._build_settings.main) main_mod = __import__(self._build_settings.main)
main = getattr(main_mod, main_name) main = getattr(main_mod, main_name)
except Exception as e: except Exception as e:
Console.error('Could not find entry point', str(e)) Console.error('Could not find entry point', str(e))
return return
if main is None or not callable(main) and not hasattr(main, 'main'): if main is None or not callable(main) and not hasattr(main, 'main'):
Console.error('Could not find entry point') Console.error('Could not find entry point')
return return
if callable(main): if callable(main):
mod_name = main.__module__ mod_name = main.__module__
func_name = main.__name__ func_name = main.__name__
else: else:
mod_name = main.__name__ mod_name = main.__name__
func_name = main.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: with open(setup_file, 'w+') as setup_py:
setup_string = stringTemplate(SetupTemplate.get_setup_py()).substitute( setup_string = stringTemplate(SetupTemplate.get_setup_py()).substitute(
@ -328,11 +370,7 @@ class PublisherService(PublisherABC):
Description=self._project_settings.description, Description=self._project_settings.description,
PyRequires=self._project_settings.python_version, PyRequires=self._project_settings.python_version,
Dependencies=self._project_settings.dependencies, Dependencies=self._project_settings.dependencies,
EntryPoints={ EntryPoints=entry_points,
'console_scripts': [
f'{self._build_settings.entry_point} = {mod_name}:{func_name}'
]
},
PackageData=self._build_settings.package_data PackageData=self._build_settings.package_data
) )
setup_py.write(setup_string) setup_py.write(setup_string)
@ -385,7 +423,9 @@ class PublisherService(PublisherABC):
3. Copies all included source files to dist_path/build 3. Copies all included source files to dist_path/build
:return: :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, Console.spinner('Reading source files:', self._read_sources, text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.blue) spinner_foreground_color=ForegroundColorEnum.blue)
@ -405,7 +445,9 @@ class PublisherService(PublisherABC):
4. Remove all included source from dist_path/publish 4. Remove all included source from dist_path/publish
:return: :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.write_line('Build:')
Console.spinner( Console.spinner(

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
@ -15,11 +15,11 @@ __title__ = 'cpl_cli.source_creator'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -1,17 +1,22 @@
import json import json
import os import os
from typing import Optional
from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.console.foreground_color_enum import ForegroundColorEnum
from cpl.console.console import Console 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.source_creator.template_builder import TemplateBuilder
from cpl_cli.templates.new.console.appsettings_json import AppsettingsTemplate 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.license import LicenseTemplate
from cpl_cli.templates.new.console.readme_py import ReadmeTemplate 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.source.name.application import ApplicationTemplate
from cpl_cli.templates.new.console.src.name.init import MainInitTemplate from cpl_cli.templates.new.console.source.name.init import MainInitTemplate
from cpl_cli.templates.new.console.src.name.main import MainWithApplicationHostAndStartupTemplate, \ from cpl_cli.templates.new.console.source.name.main import MainWithApplicationHostAndStartupTemplate, \
MainWithoutApplicationBaseTemplate, MainWithApplicationBaseTemplate, MainWithDependencyInjection MainWithoutApplicationBaseTemplate, MainWithApplicationBaseTemplate, MainWithDependencyInjection
from cpl_cli.templates.new.console.src.name.startup import StartupTemplate from cpl_cli.templates.new.console.source.name.startup import StartupTemplate
from cpl_cli.templates.new.console.src.tests.init import TestsInitTemplate from cpl_cli.templates.new.console.source.tests.init import TestsInitTemplate
from cpl_cli.templates.template_file_abc import TemplateFileABC from cpl_cli.templates.template_file_abc import TemplateFileABC
@ -21,8 +26,39 @@ class ConsoleBuilder:
pass pass
@staticmethod @staticmethod
def build(project_path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, def _create_file(file_name: str, content: dict):
project_name: str, project_settings: 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 Builds the console project files
:param project_path: :param project_path:
@ -31,40 +67,88 @@ class ConsoleBuilder:
:param use_service_providing: :param use_service_providing:
:param project_name: :param project_name:
:param project_settings: :param project_settings:
:param workspace:
:return: :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): if not os.path.isdir(project_path):
os.makedirs(project_path) os.makedirs(project_path)
with open(os.path.join(project_path, 'cpl.json'), 'w') as project_json: src_rel_path = ''
project_json.write(json.dumps(project_settings, indent=2)) src_name = ''
project_json.close() if workspace is None:
src_rel_path = 'src/'
templates: list[TemplateFileABC] = [ src_name = project_name_snake
LicenseTemplate(),
ReadmeTemplate(),
TestsInitTemplate(),
AppsettingsTemplate(),
MainInitTemplate(project_name)
]
if use_application_api: if use_application_api:
templates.append(ApplicationTemplate(project_name)) templates.append(ApplicationTemplate(src_name, src_rel_path))
if use_startup: if use_startup:
templates.append(StartupTemplate(project_name)) templates.append(StartupTemplate(src_name, src_rel_path))
templates.append(MainWithApplicationHostAndStartupTemplate(project_name)) templates.append(MainWithApplicationHostAndStartupTemplate(src_name, src_rel_path))
else: else:
templates.append(MainWithApplicationBaseTemplate(project_name)) templates.append(MainWithApplicationBaseTemplate(src_name, src_rel_path))
else: else:
if use_service_providing: if use_service_providing:
templates.append(MainWithDependencyInjection(project_name)) templates.append(MainWithDependencyInjection(src_name, src_rel_path))
else: 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: for template in templates:
divider = ''
if template.path != '' and not template.path.endswith('/'):
divider = '/'
Console.spinner( Console.spinner(
f'Creating {project_name}/{template.path}{template.name}', f'Creating {proj_name}/{template.path}{divider}{template.name}',
TemplateBuilder.build, TemplateBuilder.build,
project_path, project_path,
template, template,

View File

@ -1,17 +1,22 @@
import json import json
import os import os
from typing import Optional
from cpl.console.foreground_color_enum import ForegroundColorEnum from cpl.console.foreground_color_enum import ForegroundColorEnum
from cpl.console.console import Console 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.source_creator.template_builder import TemplateBuilder
from cpl_cli.templates.new.library.appsettings_json import AppsettingsTemplate 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.license import LicenseTemplate
from cpl_cli.templates.new.library.readme_py import ReadmeTemplate 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.source.name.application import ApplicationTemplate
from cpl_cli.templates.new.library.src.cli.init import CLIInitTemplate from cpl_cli.templates.new.library.source.name.init import NameInitTemplate
from cpl_cli.templates.new.library.src.cli.main import MainWithApplicationHostAndStartupTemplate, \ from cpl_cli.templates.new.library.source.name.main import MainWithApplicationHostAndStartupTemplate, \
MainWithoutApplicationBaseTemplate, MainWithApplicationBaseTemplate, MainWithDependencyInjection MainWithoutApplicationBaseTemplate, MainWithApplicationBaseTemplate, MainWithDependencyInjection
from cpl_cli.templates.new.library.src.cli.startup import StartupTemplate from cpl_cli.templates.new.library.source.name.startup import StartupTemplate
from cpl_cli.templates.new.library.src.tests.init import TestsInitTemplate from cpl_cli.templates.new.library.source.tests.init import TestsInitTemplate
from cpl_cli.templates.template_file_abc import TemplateFileABC from cpl_cli.templates.template_file_abc import TemplateFileABC
@ -21,8 +26,40 @@ class LibraryBuilder:
pass pass
@staticmethod @staticmethod
def build(project_path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, def _create_file(file_name: str, content: dict):
project_name: str, project_settings: 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 Builds the library project files
:param project_path: :param project_path:
@ -31,40 +68,88 @@ class LibraryBuilder:
:param use_service_providing: :param use_service_providing:
:param project_name: :param project_name:
:param project_settings: :param project_settings:
:param workspace:
:return: :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): if not os.path.isdir(project_path):
os.makedirs(project_path) os.makedirs(project_path)
with open(os.path.join(project_path, 'cpl.json'), 'w') as project_json: src_rel_path = ''
project_json.write(json.dumps(project_settings, indent=2)) src_name = ''
project_json.close() if workspace is None:
src_rel_path = 'src/'
templates: list[TemplateFileABC] = [ src_name = project_name_snake
LicenseTemplate(),
ReadmeTemplate(),
TestsInitTemplate(),
CLIInitTemplate(project_name),
AppsettingsTemplate()
]
if use_application_api: if use_application_api:
templates.append(ApplicationTemplate(project_name)) templates.append(ApplicationTemplate(src_name, src_rel_path))
if use_startup: if use_startup:
templates.append(StartupTemplate(project_name)) templates.append(StartupTemplate(src_name, src_rel_path))
templates.append(MainWithApplicationHostAndStartupTemplate(project_name)) templates.append(MainWithApplicationHostAndStartupTemplate(src_name, src_rel_path))
else: else:
templates.append(MainWithApplicationBaseTemplate()) templates.append(MainWithApplicationBaseTemplate(src_name, src_rel_path))
else: else:
if use_service_providing: if use_service_providing:
templates.append(MainWithDependencyInjection()) templates.append(MainWithDependencyInjection(src_name, src_rel_path))
else: 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: for template in templates:
divider = ''
if template.path != '' and not template.path.endswith('/'):
divider = '/'
Console.spinner( Console.spinner(
f'Creating {project_name}/{template.path}{template.name}', f'Creating {proj_name}/{template.path}{divider}{template.name}',
TemplateBuilder.build, TemplateBuilder.build,
project_path, project_path,
template, template,

View File

@ -1,13 +1,17 @@
import os
from cpl.application.startup_abc import StartupABC from cpl.application.startup_abc import StartupABC
from cpl.configuration.console_argument import ConsoleArgument from cpl.configuration.console_argument import ConsoleArgument
from cpl.configuration.configuration_abc import ConfigurationABC from cpl.configuration.configuration_abc import ConfigurationABC
from cpl.dependency_injection.service_collection_abc import ServiceCollectionABC from cpl.dependency_injection.service_collection_abc import ServiceCollectionABC
from cpl.dependency_injection.service_provider_abc import ServiceProviderABC 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.build_service import BuildService
from cpl_cli.command.generate_service import GenerateService from cpl_cli.command.generate_service import GenerateService
from cpl_cli.command.install_service import InstallService from cpl_cli.command.install_service import InstallService
from cpl_cli.command.new_service import NewService from cpl_cli.command.new_service import NewService
from cpl_cli.command.publish_service import PublishService 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.start_service import StartService
from cpl_cli.command.uninstall_service import UninstallService from cpl_cli.command.uninstall_service import UninstallService
from cpl_cli.command.update_service import UpdateService from cpl_cli.command.update_service import UpdateService
@ -29,7 +33,7 @@ class Startup(StartupABC):
self._env = self._configuration.environment self._env = self._configuration.environment
self._services = services self._services = services
self._env.set_runtime_directory(__file__) self._env.set_runtime_directory(os.path.dirname(__file__))
def configure_configuration(self) -> ConfigurationABC: def configure_configuration(self) -> ConfigurationABC:
self._configuration.argument_error_function = Error.error self._configuration.argument_error_function = Error.error
@ -38,6 +42,8 @@ class Startup(StartupABC):
self._configuration.add_environment_variables('CPL_') self._configuration.add_environment_variables('CPL_')
self._configuration.add_json_file('appsettings.json', path=self._env.runtime_directory, self._configuration.add_json_file('appsettings.json', path=self._env.runtime_directory,
optional=False, output=False) 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('', 'build', ['b', 'B'], ''))
self._configuration.add_console_argument(ConsoleArgument('', 'generate', ['g', 'G'], '', console_arguments=[ self._configuration.add_console_argument(ConsoleArgument('', 'generate', ['g', 'G'], '', console_arguments=[
ConsoleArgument('', 'abc', ['a', 'A'], ' '), ConsoleArgument('', 'abc', ['a', 'A'], ' '),
@ -56,6 +62,7 @@ class Startup(StartupABC):
ConsoleArgument('', 'library', ['l', 'L'], ' ') ConsoleArgument('', 'library', ['l', 'L'], ' ')
])) ]))
self._configuration.add_console_argument(ConsoleArgument('', 'publish', ['p', 'P'], '')) 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('', 'start', ['s', 'S'], ''))
self._configuration.add_console_argument(ConsoleArgument('', 'uninstall', ['ui', 'UI'], ' ')) self._configuration.add_console_argument(ConsoleArgument('', 'uninstall', ['ui', 'UI'], ' '))
self._configuration.add_console_argument(ConsoleArgument('', 'update', ['u', 'U'], '')) 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(PublisherABC, PublisherService)
self._services.add_transient(LiveServerService) self._services.add_transient(LiveServerService)
self._services.add_transient(AddService)
self._services.add_transient(BuildService) self._services.add_transient(BuildService)
self._services.add_transient(GenerateService) self._services.add_transient(GenerateService)
self._services.add_transient(HelpService) self._services.add_transient(HelpService)
self._services.add_transient(InstallService) self._services.add_transient(InstallService)
self._services.add_transient(NewService) self._services.add_transient(NewService)
self._services.add_transient(PublishService) self._services.add_transient(PublishService)
self._services.add_transient(RemoveService)
self._services.add_transient(StartService) self._services.add_transient(StartService)
self._services.add_transient(UninstallService) self._services.add_transient(UninstallService)
self._services.add_transient(UpdateService) self._services.add_transient(UpdateService)

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates.build'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates.generate'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates.new'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates.new.console'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -1,25 +1,25 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :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' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -1,25 +1,25 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :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' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -1,3 +1,4 @@
import os.path
import textwrap import textwrap
from cpl.utils.string import String from cpl.utils.string import String
@ -6,12 +7,12 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC
class ApplicationTemplate(TemplateFileABC): class ApplicationTemplate(TemplateFileABC):
def __init__(self, name: str): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name) name = String.convert_to_snake_case(name)
self._name = 'application.py' self._name = 'application.py'
self._path = f'src/{name}_cli/' self._path = os.path.join(path, name)
self._value = textwrap.dedent("""\ self._value = textwrap.dedent("""\
from cpl.application import ApplicationABC from cpl.application import ApplicationABC
from cpl.configuration import ConfigurationABC from cpl.configuration import ConfigurationABC

View File

@ -1,3 +1,4 @@
import os.path
import textwrap import textwrap
from cpl.utils.string import String from cpl.utils.string import String
@ -6,12 +7,12 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC
class MainInitTemplate(TemplateFileABC): class MainInitTemplate(TemplateFileABC):
def __init__(self, name: str): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name) name = String.convert_to_snake_case(name)
self._name = '__init__.py' self._name = '__init__.py'
self._path = f'src/{name}/' self._path = os.path.join(path, name)
self._value = textwrap.dedent("""\ self._value = textwrap.dedent("""\
# imports: # imports:
""") """)

View File

@ -1,3 +1,4 @@
import os.path
import textwrap import textwrap
from cpl.utils.string import String from cpl.utils.string import String
@ -6,17 +7,22 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC
class MainWithApplicationHostAndStartupTemplate(TemplateFileABC): class MainWithApplicationHostAndStartupTemplate(TemplateFileABC):
def __init__(self, name: str): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name) name = String.convert_to_snake_case(name)
self._name = 'main.py' 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"""\ self._value = textwrap.dedent(f"""\
from cpl.application import ApplicationBuilder from cpl.application import ApplicationBuilder
from {name}.application import Application from {import_pkg}application import Application
from {name}.startup import Startup from {import_pkg}startup import Startup
def main(): def main():
@ -44,16 +50,21 @@ class MainWithApplicationHostAndStartupTemplate(TemplateFileABC):
class MainWithApplicationBaseTemplate(TemplateFileABC): class MainWithApplicationBaseTemplate(TemplateFileABC):
def __init__(self, name: str): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name) name = String.convert_to_snake_case(name)
self._name = 'main.py' 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"""\ self._value = textwrap.dedent(f"""\
from cpl.application import ApplicationBuilder from cpl.application import ApplicationBuilder
from {name}.application import Application from {import_pkg}application import Application
def main(): def main():
@ -80,12 +91,17 @@ class MainWithApplicationBaseTemplate(TemplateFileABC):
class MainWithoutApplicationBaseTemplate(TemplateFileABC): class MainWithoutApplicationBaseTemplate(TemplateFileABC):
def __init__(self, name: str): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name) name = String.convert_to_snake_case(name)
self._name = 'main.py' 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("""\ self._value = textwrap.dedent("""\
from cpl.console import Console from cpl.console import Console
@ -113,12 +129,17 @@ class MainWithoutApplicationBaseTemplate(TemplateFileABC):
class MainWithDependencyInjection(TemplateFileABC): class MainWithDependencyInjection(TemplateFileABC):
def __init__(self, name: str): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name) name = String.convert_to_snake_case(name)
self._name = 'main.py' 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("""\ self._value = textwrap.dedent("""\
from cpl.configuration import Configuration, ConfigurationABC from cpl.configuration import Configuration, ConfigurationABC
from cpl.console import Console from cpl.console import Console

View File

@ -1,3 +1,4 @@
import os.path
import textwrap import textwrap
from cpl.utils.string import String from cpl.utils.string import String
@ -6,12 +7,12 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC
class StartupTemplate(TemplateFileABC): class StartupTemplate(TemplateFileABC):
def __init__(self, name: str): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name) name = String.convert_to_snake_case(name)
self._name = 'startup.py' self._name = 'startup.py'
self._path = f'src/{name}_cli/' self._path = os.path.join(path, name)
self._value = textwrap.dedent("""\ self._value = textwrap.dedent("""\
from cpl.application import StartupABC from cpl.application import StartupABC
from cpl.configuration import ConfigurationABC from cpl.configuration import ConfigurationABC

View File

@ -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')

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates.new.library'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -1,25 +1,25 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
""" """
__title__ = 'cpl_cli.templates.new.library.src' __title__ = 'cpl_cli.templates.new.library.source'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -1,25 +1,25 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :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' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -1,3 +1,4 @@
import os
import textwrap import textwrap
from cpl.utils.string import String from cpl.utils.string import String
@ -6,12 +7,12 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC
class ApplicationTemplate(TemplateFileABC): class ApplicationTemplate(TemplateFileABC):
def __init__(self, name: str): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name) name = String.convert_to_snake_case(name)
self._name = 'application.py' self._name = 'application.py'
self._path = f'src/{name}/' self._path = os.path.join(path, name)
self._value = textwrap.dedent("""\ self._value = textwrap.dedent("""\
from cpl.application import ApplicationABC from cpl.application import ApplicationABC
from cpl.configuration import ConfigurationABC from cpl.configuration import ConfigurationABC

View File

@ -1,17 +1,18 @@
import os
import textwrap import textwrap
from cpl.utils.string import String from cpl.utils.string import String
from cpl_cli.templates.template_file_abc import TemplateFileABC 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) TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name) name = String.convert_to_snake_case(name)
self._name = '__init__.py' self._name = '__init__.py'
self._path = f'src/{name}_cli/' self._path = os.path.join(path, name)
self._value = textwrap.dedent("""\ self._value = textwrap.dedent("""\
# imports: # imports:
""") """)

View File

@ -1,3 +1,4 @@
import os.path
import textwrap import textwrap
from cpl.utils.string import String from cpl.utils.string import String
@ -6,17 +7,22 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC
class MainWithApplicationHostAndStartupTemplate(TemplateFileABC): class MainWithApplicationHostAndStartupTemplate(TemplateFileABC):
def __init__(self, name: str): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name) name = String.convert_to_snake_case(name)
self._name = 'main.py' 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"""\ self._value = textwrap.dedent(f"""\
from cpl.application import ApplicationBuilder from cpl.application import ApplicationBuilder
from {name}_cli.application import Application from {import_pkg}application import Application
from {name}_cli.startup import Startup from {import_pkg}startup import Startup
def main(): def main():
@ -44,15 +50,21 @@ class MainWithApplicationHostAndStartupTemplate(TemplateFileABC):
class MainWithApplicationBaseTemplate(TemplateFileABC): class MainWithApplicationBaseTemplate(TemplateFileABC):
def __init__(self): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name)
self._name = 'main.py' 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"""\ self._value = textwrap.dedent(f"""\
from cpl.application import ApplicationBuilder from cpl.application import ApplicationBuilder
from {name}_cli.application import Application from {import_pkg}application import Application
def main(): def main():
@ -79,11 +91,16 @@ class MainWithApplicationBaseTemplate(TemplateFileABC):
class MainWithoutApplicationBaseTemplate(TemplateFileABC): class MainWithoutApplicationBaseTemplate(TemplateFileABC):
def __init__(self): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
self._name = 'main.py' 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("""\ self._value = textwrap.dedent("""\
from cpl.console import Console from cpl.console import Console
@ -111,11 +128,16 @@ class MainWithoutApplicationBaseTemplate(TemplateFileABC):
class MainWithDependencyInjection(TemplateFileABC): class MainWithDependencyInjection(TemplateFileABC):
def __init__(self): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
self._name = 'main.py' 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("""\ self._value = textwrap.dedent("""\
from cpl.configuration import Configuration, ConfigurationABC from cpl.configuration import Configuration, ConfigurationABC
from cpl.console import Console from cpl.console import Console

View File

@ -1,3 +1,4 @@
import os
import textwrap import textwrap
from cpl.utils.string import String from cpl.utils.string import String
@ -6,12 +7,12 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC
class StartupTemplate(TemplateFileABC): class StartupTemplate(TemplateFileABC):
def __init__(self, name: str): def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self) TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name) name = String.convert_to_snake_case(name)
self._name = 'startup.py' self._name = 'startup.py'
self._path = f'src/{name}/' self._path = os.path.join(path, name)
self._value = textwrap.dedent("""\ self._value = textwrap.dedent("""\
from cpl.application import StartupABC from cpl.application import StartupABC
from cpl.configuration import ConfigurationABC from cpl.configuration import ConfigurationABC

View File

@ -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')

View File

@ -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')

View File

@ -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')

View File

@ -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

View File

@ -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')

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- 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 :copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
@ -15,11 +15,11 @@ __title__ = 'cpl_cli.templates.publish'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.4.0' __version__ = '2021.4'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='04', micro='0') version_info = VersionInfo(major='2021', minor='4', micro='None')

View File

@ -0,0 +1,8 @@
{
"Workspace": {
"DefaultProject": "general",
"Projects": {
"general": "src/general/general.json"
}
}
}

View File

@ -8,7 +8,7 @@ from cpl.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl.logging.logger_abc import LoggerABC from cpl.logging.logger_abc import LoggerABC
from cpl.mailing.email import EMail from cpl.mailing.email import EMail
from cpl.mailing.email_client_abc import EMailClientABC from cpl.mailing.email_client_abc import EMailClientABC
from tests.custom.general.test_service import TestService from test_service import TestService
class Application(ApplicationABC): class Application(ApplicationABC):

View File

@ -1,6 +1,6 @@
{ {
"ProjectSettings": { "ProjectSettings": {
"Name": "sh_cpl.tests", "Name": "general",
"Version": { "Version": {
"Major": "2021", "Major": "2021",
"Minor": "04", "Minor": "04",
@ -16,12 +16,11 @@
"LicenseName": "MIT", "LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"sh_cpl==2021.4.1.post13", "sh_cpl==2021.4.dev1"
"discord.py==1.6.0"
], ],
"PythonVersion": ">=3.8", "PythonVersion": ">=3.8",
"PythonPath": { "PythonPath": {
"linux": "../../../../cpl-env/bin/python3.9", "linux": "../../../../../../cpl-env/bin/python3.9",
"win32": "" "win32": ""
}, },
"Classifiers": [] "Classifiers": []
@ -31,7 +30,7 @@
"SourcePath": "", "SourcePath": "",
"OutputPath": "dist", "OutputPath": "dist",
"Main": "main", "Main": "main",
"EntryPoint": "cpl", "EntryPoint": "",
"IncludePackageData": true, "IncludePackageData": true,
"Included": [ "Included": [
"*/templates" "*/templates"

View File

@ -1,6 +1,6 @@
from cpl.application.application_builder import ApplicationBuilder from cpl.application.application_builder import ApplicationBuilder
from tests.custom.general.application import Application from application import Application
from tests.custom.general.startup import Startup from startup import Startup
def main(): def main():

View File

@ -6,7 +6,7 @@ from cpl.logging.logger_service import Logger
from cpl.logging.logger_abc import LoggerABC from cpl.logging.logger_abc import LoggerABC
from cpl.mailing.email_client_service import EMailClient from cpl.mailing.email_client_service import EMailClient
from cpl.mailing.email_client_abc import EMailClientABC from cpl.mailing.email_client_abc import EMailClientABC
from tests.custom.general.test_service import TestService from test_service import TestService
class Startup(StartupABC): class Startup(StartupABC):
@ -20,7 +20,6 @@ class Startup(StartupABC):
def configure_configuration(self) -> ConfigurationABC: def configure_configuration(self) -> ConfigurationABC:
self._configuration.add_environment_variables('PYTHON_') self._configuration.add_environment_variables('PYTHON_')
self._configuration.add_environment_variables('CPL_') 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.json')
self._configuration.add_json_file(f'appsettings.{self._configuration.environment.environment_name}.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) self._configuration.add_json_file(f'appsettings.{self._configuration.environment.host_name}.json', optional=True)