diff --git a/.gitignore b/.gitignore
index a2f9a4d3..d9c65a9f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,7 +37,7 @@ MANIFEST
pip-log.txt
pip-delete-this-directory.txt
-# Unit test / coverage reports
+# Unit model / coverage reports
htmlcov/
.tox/
.nox/
@@ -130,4 +130,4 @@ dmypy.json
# IDE
.vscode/
-
+.idea/
diff --git a/.idea/dictionaries/sven.xml b/.idea/dictionaries/sven.xml
deleted file mode 100644
index 6b8908ae..00000000
--- a/.idea/dictionaries/sven.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index f9ea47c4..00000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
deleted file mode 100644
index 105ce2da..00000000
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 74c32a17..00000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 3430c667..00000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/sh_common_py_lib.iml b/.idea/sh_common_py_lib.iml
deleted file mode 100644
index 7f4b6244..00000000
--- a/.idea/sh_common_py_lib.iml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/shelf/Uncommitted_changes_before_Update_at_26_11_2020_10_36_[Default_Changelist]/shelved.patch b/.idea/shelf/Uncommitted_changes_before_Update_at_26_11_2020_10_36_[Default_Changelist]/shelved.patch
deleted file mode 100644
index bb3b0e06..00000000
--- a/.idea/shelf/Uncommitted_changes_before_Update_at_26_11_2020_10_36_[Default_Changelist]/shelved.patch
+++ /dev/null
@@ -1,61 +0,0 @@
-Index: src/tests/publishing/publisher.py
-IDEA additional info:
-Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP
-<+>import os\r\nimport shutil\r\nimport unittest\r\n\r\nfrom sh_edraft.configuration import ApplicationHost\r\nfrom sh_edraft.logging import Logger\r\nfrom sh_edraft.logging.base import LoggerBase\r\nfrom sh_edraft.logging.model import LoggingSettings\r\nfrom sh_edraft.publishing import Publisher\r\nfrom sh_edraft.publishing.base import PublisherBase\r\nfrom sh_edraft.publishing.model import Template\r\nfrom sh_edraft.publishing.model.publish_settings_model import PublishSettingsModel\r\nfrom sh_edraft.source_code.model import Version\r\nfrom sh_edraft.time.model import TimeFormatSettings\r\n\r\n\r\nclass PublisherTest(unittest.TestCase):\r\n\r\n def _config(self):\r\n self._log_settings = LoggingSettings()\r\n self._log_settings.from_dict({\r\n \"Path\": \"logs/\",\r\n \"Filename\": \"log_$start_time.log\",\r\n \"ConsoleLogLevel\": \"TRACE\",\r\n \"FileLogLevel\": \"TRACE\"\r\n })\r\n\r\n self._time_format_settings = TimeFormatSettings()\r\n self._time_format_settings.from_dict({\r\n \"DateFormat\": \"%Y-%m-%d\",\r\n \"TimeFormat\": \"%H:%M:%S\",\r\n \"DateTimeFormat\": \"%Y-%m-%d %H:%M:%S.%f\",\r\n \"DateTimeLogFormat\": \"%Y-%m-%d_%H-%M-%S\"\r\n })\r\n\r\n self._version = Version(2020, 12, 5).to_dict()\r\n templates = [\r\n Template(\r\n '../../publish_templates/*_template.txt',\r\n '*',\r\n '',\r\n '',\r\n '2020',\r\n 'sh-edraft.de',\r\n 'MIT',\r\n ', see LICENSE for more details.',\r\n '',\r\n 'Sven Heidemann',\r\n self._version\r\n ),\r\n Template(\r\n '../../publish_templates/*_template.txt',\r\n 'sh_edraft',\r\n 'common python library',\r\n 'Library to share common classes and models used at sh-edraft.de',\r\n '2020',\r\n 'sh-edraft.de',\r\n 'MIT',\r\n ', see LICENSE for more details.',\r\n '',\r\n 'Sven Heidemann',\r\n self._version\r\n )\r\n ]\r\n\r\n self._source_path = '../'\r\n self._dist_path = '../../dist'\r\n\r\n self._publish_settings_model = PublishSettingsModel()\r\n self._publish_settings_model.from_dict({\r\n \"SourcePath\": self._source_path,\r\n \"DistPath\": self._dist_path,\r\n \"Templates\": templates,\r\n \"IncludedFiles\": [],\r\n \"ExcludedFiles\": [],\r\n \"TemplateEnding\": \"_template.txt\",\r\n })\r\n\r\n def setUp(self):\r\n self._config()\r\n\r\n self._app_host = ApplicationHost()\r\n self._logger = Logger(self._log_settings, self._time_format_settings, self._app_host)\r\n self._logger.create()\r\n\r\n def tearDown(self):\r\n if os.path.isdir(self._log_settings.path):\r\n shutil.rmtree(self._log_settings.path)\r\n\r\n def test_create(self):\r\n publisher: Publisher = Publisher(self._logger, self._publish_settings_model)\r\n self.assertIsNotNone(publisher)\r\n\r\n publisher.create()\r\n self.assertTrue(os.path.isdir(self._dist_path))\r\n
-Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
-<+>UTF-8
-===================================================================
---- src/tests/publishing/publisher.py (revision 9dbad20e9714ffa1546bb2d1b2f8b5ea8e854369)
-+++ src/tests/publishing/publisher.py (date 1606383223452)
-@@ -36,8 +36,8 @@
- self._version = Version(2020, 12, 5).to_dict()
- templates = [
- Template(
-- '../../publish_templates/*_template.txt',
-- '*',
-+ '../../publish_templates/all_template.txt',
-+ 'all',
- '',
- '',
- '2020',
-@@ -49,7 +49,7 @@
- self._version
- ),
- Template(
-- '../../publish_templates/*_template.txt',
-+ '../../publish_templates/all_template.txt',
- 'sh_edraft',
- 'common python library',
- 'Library to share common classes and models used at sh-edraft.de',
-Index: src/sh_edraft/publishing/publisher.py
-IDEA additional info:
-Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP
-<+>import os\r\nimport shutil\r\nfrom string import Template as stringTemplate\r\n\r\nfrom sh_edraft.logging.base.logger_base import LoggerBase\r\nfrom sh_edraft.publishing.base.publisher_base import PublisherBase\r\nfrom sh_edraft.publishing.model.publish_settings_model import PublishSettingsModel\r\nfrom sh_edraft.publishing.model.template import Template\r\n\r\n\r\nclass Publisher(PublisherBase):\r\n\r\n def __init__(self, logger: LoggerBase, publish_settings: PublishSettingsModel):\r\n super().__init__(logger, publish_settings)\r\n\r\n @property\r\n def source_path(self) -> str:\r\n return self._publish_settings.source_path\r\n\r\n @property\r\n def dist_path(self):\r\n return self._publish_settings.dist_path\r\n\r\n def _get_template_output(self, t: Template, name: str, imports: str) -> str:\r\n self._logger.trace(__name__, f'Started {__name__}._get_template_output')\r\n try:\r\n if t.file_content == '':\r\n raise Exception(f'Template is empty: {t.template_path}')\r\n\r\n self._logger.trace(__name__, f'Stopped {__name__}._get_template_output')\r\n return stringTemplate(t.file_content).substitute(\r\n Name=name,\r\n Description=t.description,\r\n LongDescription=t.long_description,\r\n CopyrightDate=t.copyright_date,\r\n CopyrightName=t.copyright_name,\r\n LicenseName=t.license_name,\r\n LicenseDescription=t.license_description,\r\n Title=t.title if t.title is not None and t.title != '' else name,\r\n Author=t.author,\r\n Version=t.version.to_str(),\r\n Major=t.version.major,\r\n Minor=t.version.minor,\r\n Micro=t.version.micro,\r\n Imports=imports\r\n )\r\n except Exception as e:\r\n self._logger.fatal(__name__, f'Cannot read Template: {t.template_path}', e)\r\n self._logger.trace(__name__, f'Stopped {__name__}._get_template_output')\r\n\r\n def _read_source_path(self):\r\n self._logger.trace(__name__, f'Started {__name__}._read_source_path')\r\n for r, d, f in os.walk(self._publish_settings.source_path):\r\n for file in f:\r\n if file.endswith('.py') or file in self._publish_settings.included_files:\r\n self._publish_settings.included_files.append(os.path.join(r, file))\r\n\r\n self._logger.trace(__name__, f'Stopped {__name__}._read_source_path')\r\n\r\n def _read_templates(self):\r\n self._logger.trace(__name__, f'Started {__name__}._read_templates')\r\n for t in self._publish_settings.templates:\r\n output_template: str = ''\r\n if not os.path.isfile(t.template_path):\r\n self._logger.fatal(__name__, f'Template not found: {t.template_path}')\r\n\r\n with open(t.template_path) as template:\r\n t.file_content = template.read()\r\n template.close()\r\n if t.file_content == '':\r\n self._logger.fatal(__name__, f'Template is empty: {t.template_path}')\r\n\r\n self._logger.trace(__name__, f'Stopped {__name__}._read_templates')\r\n\r\n def _create_dist_path(self):\r\n self._logger.trace(__name__, f'Started {__name__}._create_dist_path')\r\n if os.path.isdir(self._publish_settings.dist_path):\r\n try:\r\n shutil.rmtree(self._publish_settings.dist_path)\r\n self._logger.info(__name__, f'Deleted {self._publish_settings.dist_path}')\r\n except Exception as e:\r\n self._logger.fatal(__name__, f'Cannot delete old dist directory', e)\r\n\r\n if not os.path.isdir(self._publish_settings.dist_path):\r\n try:\r\n os.makedirs(self._publish_settings.dist_path)\r\n self._logger.debug(__name__, f'Created directories: {self._publish_settings.dist_path}')\r\n self._logger.info(__name__, f'Created dist directory')\r\n except Exception as e:\r\n self._logger.fatal(__name__, f'Cannot create dist directory', e)\r\n\r\n self._logger.trace(__name__, f'Stopped {__name__}._create_dist_path')\r\n\r\n @staticmethod\r\n def _get_template_name_from_dirs(file: str) -> str:\r\n dirs = os.path.dirname(file).split('/')\r\n for d in dirs:\r\n if d.__contains__('.'):\r\n dirs.remove(d)\r\n\r\n if len(dirs) == 0:\r\n return os.path.basename(file)\r\n else:\r\n return '.'.join(dirs)\r\n\r\n def _write_templates(self):\r\n self._logger.trace(__name__, f'Started {__name__}._write_templates')\r\n for template in self._publish_settings.templates:\r\n for file in self._publish_settings.included_files:\r\n if os.path.basename(file) == '__init__.py' and file not in self._publish_settings.excluded_files:\r\n template_name = template.name\r\n if template.name == '*' or template.name == '':\r\n template_name = self._get_template_name_from_dirs(file)\r\n else:\r\n name = self._get_template_name_from_dirs(file)\r\n\r\n if name.__contains__('.'):\r\n if template.name != name.split('.')[len(name.split('.')) - 1]:\r\n continue\r\n\r\n else:\r\n if template.name != name:\r\n continue\r\n\r\n try:\r\n module_file_lines: list[str] = []\r\n module_py_lines: list[str] = []\r\n imports = ''\r\n with open(file, 'r') as py_file:\r\n module_file_lines = py_file.readlines()\r\n py_file.close()\r\n\r\n if len(module_file_lines) == 0:\r\n with open(file, 'w+') as py_file:\r\n py_file.write(self._get_template_output(template, template_name, '# imports:'))\r\n py_file.close()\r\n self._logger.debug(__name__, f'Written to {file}')\r\n else:\r\n is_started = False\r\n for line in module_file_lines:\r\n if line.__contains__('# imports'):\r\n is_started = True\r\n\r\n if (line.__contains__('from') or line.__contains__('import')) and is_started:\r\n module_py_lines.append(line.replace('\\n', ''))\r\n\r\n if len(module_py_lines) > 0:\r\n imports = '\\n'.join(module_py_lines)\r\n\r\n with open(file, 'w+') as py_file:\r\n py_file.write(self._get_template_output(template, template_name, imports))\r\n py_file.close()\r\n self._logger.debug(__name__, f'Written to {file}')\r\n\r\n except Exception as e:\r\n self._logger.error(__name__, f'Cannot write to file: {file}', e)\r\n\r\n self._logger.info(__name__, f'Written to all included modules')\r\n self._logger.trace(__name__, f'Stopped {__name__}._write_templates')\r\n\r\n def _copy_all_included_files(self):\r\n self._logger.trace(__name__, f'Started {__name__}._copy_all_included_files')\r\n dist_path = self._publish_settings.dist_path\r\n if self._publish_settings.dist_path.endswith('/'):\r\n dist_path = dist_path[:len(dist_path) - 1]\r\n\r\n for file in self._publish_settings.included_files:\r\n is_file_excluded = False\r\n if file in self._publish_settings.excluded_files:\r\n is_file_excluded = True\r\n else:\r\n for excluded in self._publish_settings.excluded_files:\r\n if file.__contains__(excluded):\r\n is_file_excluded = True\r\n\r\n if not is_file_excluded:\r\n output_file = ''\r\n\r\n if file.startswith('..'):\r\n output_file = file.replace('..', '')\r\n elif file.startswith('.'):\r\n output_file = file.replace('.', '', 1)\r\n\r\n output_file = f'{dist_path}{output_file}'\r\n output_path = os.path.dirname(output_file)\r\n\r\n try:\r\n if not os.path.isdir(output_path):\r\n os.makedirs(output_path)\r\n except Exception as e:\r\n self._logger.error(__name__, f'Cannot create directories: {output_path}', e)\r\n\r\n try:\r\n shutil.copy(file, output_file)\r\n except Exception as e:\r\n self._logger.error(__name__, f'Cannot copy file: {file} to {output_path}', e)\r\n\r\n self._logger.debug(__name__, f'Copied {file} to {output_path}')\r\n\r\n self._logger.info(__name__, f'Copied all included files')\r\n self._logger.trace(__name__, f'Stopped {__name__}._copy_all_included_files')\r\n\r\n def include(self, path: str):\r\n self._logger.trace(__name__, f'Started {__name__}.include')\r\n self._publish_settings.included_files.append(path)\r\n self._logger.trace(__name__, f'Stopped {__name__}.include')\r\n\r\n def exclude(self, path: str):\r\n self._logger.trace(__name__, f'Started {__name__}.exclude')\r\n self._publish_settings.excluded_files.append(path)\r\n self._logger.trace(__name__, f'Stopped {__name__}.exclude')\r\n\r\n def create(self):\r\n self._logger.trace(__name__, f'Started {__name__}.create')\r\n if not self._publish_settings.dist_path.endswith('/'):\r\n self._publish_settings.dist_path += '/'\r\n\r\n self._read_source_path()\r\n self._read_templates()\r\n self._create_dist_path()\r\n self._logger.trace(__name__, f'Stopped {__name__}.create')\r\n\r\n def publish(self):\r\n self._logger.trace(__name__, f'Started {__name__}.publish')\r\n self._write_templates()\r\n self._copy_all_included_files()\r\n self._logger.trace(__name__, f'Stopped {__name__}.publish')\r\n
-Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
-<+>UTF-8
-===================================================================
---- src/sh_edraft/publishing/publisher.py (revision 9dbad20e9714ffa1546bb2d1b2f8b5ea8e854369)
-+++ src/sh_edraft/publishing/publisher.py (date 1606383234093)
-@@ -109,7 +109,7 @@
- for file in self._publish_settings.included_files:
- if os.path.basename(file) == '__init__.py' and file not in self._publish_settings.excluded_files:
- template_name = template.name
-- if template.name == '*' or template.name == '':
-+ if template.name == 'all' or template.name == '':
- template_name = self._get_template_name_from_dirs(file)
- else:
- name = self._get_template_name_from_dirs(file)
-Index: publish_templates/*_template.txt
-IDEA additional info:
-Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP
-<+># -*- coding: utf-8 -*-\r\n\r\n\"\"\"\r\n$Name $Description\r\n~~~~~~~~~~~~~~~~~~~\r\n\r\n$LongDescription\r\n\r\n:copyright: (c) $CopyrightDate $CopyrightName\r\n:license: $LicenseName$LicenseDescription\r\n\r\n\"\"\"\r\n\r\n__title__ = '$Title'\r\n__author__ = '$Author'\r\n__license__ = '$LicenseName'\r\n__copyright__ = 'Copyright (c) $CopyrightDate $CopyrightName'\r\n__version__ = '$Version'\r\n\r\nfrom collections import namedtuple\r\n\r\n$Imports\r\n\r\nVersionInfo = namedtuple('VersionInfo', 'major minor micro')\r\nversion_info = VersionInfo(major=$Major, minor=$Minor, micro=$Micro)\r\n
-===================================================================
---- publish_templates/*_template.txt (revision 9dbad20e9714ffa1546bb2d1b2f8b5ea8e854369)
-+++ publish_templates/all_template.txt (date 1606383191684)
-@@ -22,4 +22,4 @@
- $Imports
-
- VersionInfo = namedtuple('VersionInfo', 'major minor micro')
--version_info = VersionInfo(major=$Major, minor=$Minor, micro=$Micro)
-+version_info = VersionInfo(major=$Major, minor=$Minor, micro=$Micro)
-\ No newline at end of file
diff --git a/.idea/shelf/Uncommitted_changes_before_Update_at_26_11_2020_10_36__Default_Changelist_.xml b/.idea/shelf/Uncommitted_changes_before_Update_at_26_11_2020_10_36__Default_Changelist_.xml
deleted file mode 100644
index 49edc74a..00000000
--- a/.idea/shelf/Uncommitted_changes_before_Update_at_26_11_2020_10_36__Default_Changelist_.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7f..00000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
deleted file mode 100644
index 8106a0a5..00000000
--- a/.idea/workspace.xml
+++ /dev/null
@@ -1,868 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1605881914521
-
-
- 1605881914521
-
-
- 1607285697331
-
-
-
- 1607285697331
-
-
- 1607620265254
-
-
-
- 1607620265254
-
-
- 1607712129507
-
-
-
- 1607712129507
-
-
- 1607971885250
-
-
-
- 1607971885250
-
-
- 1607976456889
-
-
-
- 1607976456889
-
-
- 1607976626173
-
-
-
- 1607976626173
-
-
- 1608037411172
-
-
-
- 1608037411172
-
-
- 1608047595029
-
-
-
- 1608047595029
-
-
- 1608047655667
-
-
-
- 1608047655667
-
-
- 1608048544558
-
-
-
- 1608048544558
-
-
- 1608049672925
-
-
-
- 1608049672925
-
-
- 1608049772153
-
-
-
- 1608049772153
-
-
- 1608059323858
-
-
-
- 1608059323858
-
-
- 1608059501153
-
-
-
- 1608059501153
-
-
- 1608066984496
-
-
-
- 1608066984496
-
-
- 1608070231599
-
-
-
- 1608070231599
-
-
- 1608122289003
-
-
-
- 1608122289003
-
-
- 1608125743068
-
-
-
- 1608125743068
-
-
- 1608127752645
-
-
-
- 1608127752645
-
-
- 1608127998033
-
-
-
- 1608127998034
-
-
- 1608128026922
-
-
-
- 1608128026922
-
-
- 1608133651981
-
-
-
- 1608133651982
-
-
- 1608136663213
-
-
-
- 1608136663213
-
-
- 1608137669182
-
-
-
- 1608137669182
-
-
- 1608138851088
-
-
-
- 1608138851088
-
-
- 1608138986801
-
-
-
- 1608138986801
-
-
- 1608139067953
-
-
-
- 1608139067953
-
-
- 1608139239527
-
-
-
- 1608139239527
-
-
- 1608139414722
-
-
-
- 1608139414722
-
-
- 1608139502304
-
-
-
- 1608139502304
-
-
- 1608139612476
-
-
-
- 1608139612476
-
-
- 1608383809354
-
-
-
- 1608383809355
-
-
- 1608383870849
-
-
-
- 1608383870849
-
-
- 1608472168532
-
-
-
- 1608472168532
-
-
- 1608472183294
-
-
-
- 1608472183294
-
-
- 1608474022759
-
-
-
- 1608474022759
-
-
- 1608474032244
-
-
-
- 1608474032244
-
-
- 1608474289859
-
-
-
- 1608474289859
-
-
- 1608813096023
-
-
-
- 1608813096023
-
-
- 1608813152266
-
-
-
- 1608813152266
-
-
- 1608822597300
-
-
-
- 1608822597311
-
-
- 1608823061488
-
-
-
- 1608823061489
-
-
- 1608894745271
-
-
-
- 1608894745274
-
-
- 1608896199033
-
-
-
- 1608896199034
-
-
- 1608896235005
-
-
-
- 1608896235006
-
-
- 1608901608928
-
-
-
- 1608901608930
-
-
- 1608921175852
-
-
-
- 1608921175853
-
-
- 1608986131753
-
-
-
- 1608986131755
-
-
- 1611431001647
-
-
-
- 1611431001649
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- file://$PROJECT_DIR$/src/tests/publish_test/publisher_test.py
- 50
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index dec1870d..ac07ceb2 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,101 @@
-# sh_common_py_lib
+
CPL - Common python library
+
+
+
+
+
+ CPL is a development platform for python server applications
+
using Python.
+
+
+
+## Table of Contents
+
+
+ -
+ Getting Started
+
+
+ - Roadmap
+ - Contributing
+ - License
+ - Contact
+
+
+
+
+## Getting Started
+
+[Get started with CPL][quickstart].
+
+### Prerequisites
+
+- Install [python] which includes [Pip installs packages][pip]
+
+### Installation
+
+Install the cpl package
+```sh
+pip install sh_cpl --extra-index-url https://pip.sh-edraft.de
+```
+
+Create workspace:
+```sh
+cpl new
+```
+
+Run the application:
+```sh
+cd
+cpl start
+```
+
+
+
+## Roadmap
+
+See the [open issues](https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib/issues) for a list of proposed features (and known issues).
+
+
+
+
+## Contributing
+
+### Contributing Guidelines
+
+Read through our [contributing guidelines][contributing] to learn about our submission process, coding rules and more.
+
+### Want to Help?
+
+Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our guidelines for [contributing][contributing].
+
+
+
+
+## License
+
+Distributed under the MIT License. See [LICENSE] for more information.
+
+
+
+
+## Contact
+
+Sven Heidemann - sven.heidemann@sh-edraft.de
+
+Project link: [https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib](https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib)
+
+
+[pip_url]: https://pip.sh-edraft.de
+[python]: https://www.python.org/
+[pip]: https://pypi.org/project/pip/
+
+
+[project]: https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib
+[quickstart]: https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib/wiki/quickstart
+[contributing]: https://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib/wiki/contributing
+[license]: LICENSE
diff --git a/cpl.json b/cpl.json
new file mode 100644
index 00000000..6fc6ba4b
--- /dev/null
+++ b/cpl.json
@@ -0,0 +1,57 @@
+{
+ "ProjectSettings": {
+ "Name": "sh_cpl",
+ "Version": {
+ "Major": "2021",
+ "Minor": "04",
+ "Micro": "0"
+ },
+ "Author": "Sven Heidemann",
+ "AuthorEmail": "sven.heidemann@sh-edraft.de",
+ "Description": "sh-edraft Common Python library",
+ "LongDescription": "sh-edraft Common Python library",
+ "URL": "https://www.sh-edraft.de",
+ "CopyrightDate": "2020 - 2021",
+ "CopyrightName": "sh-edraft.de",
+ "LicenseName": "MIT",
+ "LicenseDescription": "MIT, see LICENSE for more details.",
+ "Dependencies": [
+ "colorama==0.4.4",
+ "mysql-connector==2.2.9",
+ "psutil==5.8.0",
+ "packaging==20.9",
+ "pyfiglet==0.8.post1",
+ "pynput==1.7.3",
+ "SQLAlchemy==1.4.3",
+ "setuptools==54.2.0",
+ "tabulate==0.8.9",
+ "termcolor==1.1.0",
+ "watchdog==2.0.2",
+ "wheel==0.36.2"
+ ],
+ "PythonVersion": ">=3.8",
+ "PythonPath": {},
+ "Classifiers": []
+ },
+ "BuildSettings": {
+ "ProjectType": "library",
+ "SourcePath": "src",
+ "OutputPath": "dist",
+ "Main": "cpl_cli.main",
+ "EntryPoint": "cpl",
+ "IncludePackageData": true,
+ "Included": [
+ "*/templates"
+ ],
+ "Excluded": [
+ "*/__pycache__",
+ "*/logs",
+ "*/tests"
+ ],
+ "PackageData": {
+ "cpl_cli": [
+ "*.json"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/cli.md b/docs/cli.md
deleted file mode 100644
index f2f2291e..00000000
--- a/docs/cli.md
+++ /dev/null
@@ -1,9 +0,0 @@
-prefix: cpl
-commands:
- new:
- app
- base
- class
- configmodel
- enum
- service
\ No newline at end of file
diff --git a/docs/cli.txt b/docs/cli.txt
new file mode 100644
index 00000000..2c396d12
--- /dev/null
+++ b/docs/cli.txt
@@ -0,0 +1,19 @@
+prefix: cpl
+commands:
+ build
+
+ generate:
+ abc | a
+ class | c
+ configmodel | cm
+ enum | e
+ service | s
+
+ help
+ new
+ console
+
+ start
+ publish
+ update
+ version
\ No newline at end of file
diff --git a/docs/install.md b/docs/install.txt
similarity index 100%
rename from docs/install.md
rename to docs/install.txt
diff --git a/docs/pip.txt b/docs/pip.txt
new file mode 100644
index 00000000..90a20272
--- /dev/null
+++ b/docs/pip.txt
@@ -0,0 +1,11 @@
+upload:
+ prod:
+ twine upload --repository-url https://pip.sh-edraft.de dist/publish/setup/*
+ twine upload -r pip.sh-edraft.de dist/publish/setup/*
+
+ dev:
+ twine upload --repository-url https://pip-dev.sh-edraft.de dist/publish/setup/*
+ twine upload -r pip-dev.sh-edraft.de dist/publish/setup/*
+
+install:
+ pip install --extra-index-url https://pip.sh-edraft.de/ sh_cpl
diff --git a/docs/structure.md b/docs/structure.md
deleted file mode 100644
index 71f2f0ea..00000000
--- a/docs/structure.md
+++ /dev/null
@@ -1,10 +0,0 @@
-- sh_edraft
- - common # Contains Interfaces and models for the hole library
- - interface
- - model
- - configuration # Contains classes for app configuration by JSON, ENV vars and arguments
- - discord # Contains classes for better use of discord.py
- - logging # Contains classes for logging
- - mailing # Contains classes for mailing
- - messenger # Contains classes for sh_messenger_server client
- - service # Contains classes to provide and use the services defined in this library
\ No newline at end of file
diff --git a/docs/todo.md b/docs/todo.md
deleted file mode 100644
index 5d5a99b8..00000000
--- a/docs/todo.md
+++ /dev/null
@@ -1,2 +0,0 @@
-- create logger
-- use logger in publisher
\ No newline at end of file
diff --git a/src/tests/publish_test/__init__.py b/docs/todo.txt
similarity index 100%
rename from src/tests/publish_test/__init__.py
rename to docs/todo.txt
diff --git a/publish_templates/all_template.txt b/publish_templates/all_template.txt
deleted file mode 100644
index 3b24f44f..00000000
--- a/publish_templates/all_template.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-$Name $Description
-~~~~~~~~~~~~~~~~~~~
-
-$LongDescription
-
-:copyright: (c) $CopyrightDate $CopyrightName
-:license: $LicenseName$LicenseDescription
-
-"""
-
-__title__ = '$Title'
-__author__ = '$Author'
-__license__ = '$LicenseName'
-__copyright__ = 'Copyright (c) $CopyrightDate $CopyrightName'
-__version__ = '$Version'
-
-from collections import namedtuple
-
-$Imports
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=$Major, minor=$Minor, micro=$Micro)
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index afb24683..00000000
--- a/requirements.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-aiohttp==3.6.3
-async-timeout==3.0.1
-attrs==20.3.0
-certifi==2020.11.8
-chardet==3.0.4
-click==7.1.2
-dateutils==0.6.12
-discord==1.0.1
-discord.py==1.5.1
-Flask==1.1.2
-idna==2.10
-itsdangerous==1.1.0
-Jinja2==2.11.2
-keyboard==0.13.5
-MarkupSafe==1.1.1
-multidict==4.7.6
-mysql-connector==2.2.9
-overloading==0.5.0
-python-dateutil==2.8.1
-pytz==2020.4
-six==1.15.0
-SQLAlchemy==1.3.20
-termcolor==1.1.0
-urllib3==1.26.2
-Werkzeug==1.0.1
-yarl==1.5.1
-setuptools~=49.2.1
-pyfiglet~=0.8.post1
-tabulate~=0.8.7
\ No newline at end of file
diff --git a/src/MANIFEST.in b/src/MANIFEST.in
deleted file mode 100644
index cb32f474..00000000
--- a/src/MANIFEST.in
+++ /dev/null
@@ -1,2 +0,0 @@
-include ../ README
-recursive-include sh_edraft *.txt
\ No newline at end of file
diff --git a/src/build.json b/src/build.json
deleted file mode 100644
index 68883b77..00000000
--- a/src/build.json
+++ /dev/null
@@ -1,66 +0,0 @@
-{
- "TimeFormatSettings": {
- "DateFormat": "%Y-%m-%d",
- "TimeFormat": "%H:%M:%S",
- "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
- "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
- },
- "LoggingSettings": {
- "Path": "../build/logs/",
- "Filename": "log_$start_time.log",
- "ConsoleLogLevel": "INFO",
- "FileLogLevel": "TRACE"
- },
- "PublishSettings": {
- "SourcePath": "./",
- "DistPath": "../build/dist",
- "Templates": [
- {
- "TemplatePath": "../publish_templates/all_template.txt",
- "Name": "all",
- "Description": "",
- "LongDescription": "",
- "CopyrightDate": "2020",
- "CopyrightName": "sh-edraft.de",
- "LicenseName": "MIT",
- "LicenseDescription": ", see LICENSE for more details.",
- "Title": "",
- "Author": "Sven Heidemann",
- "Version": {
- "Major": 2020,
- "Minor": 12,
- "Micro": 10
- }
- },
- {
- "TemplatePath": "../publish_templates/all_template.txt",
- "Name": "sh_edraft",
- "Description": "common python library",
- "LongDescription": "Library to share common classes and models used at sh-edraft.de",
- "CopyrightDate": "2020",
- "CopyrightName": "sh-edraft.de",
- "LicenseName": "MIT",
- "LicenseDescription": ", see LICENSE for more details.",
- "Title": "",
- "Author": "Sven Heidemann",
- "Version": {
- "Major": 2020,
- "Minor": 12,
- "Micro": 10
- }
- }
- ],
- "IncludedFiles": [
- "./MANIFEST.in",
- "../LICENSE",
- "../README.md",
- "../requirements.txt",
- "sh_edraft/cli/cpl_cli/templates"
- ],
- "ExcludedFiles": [
- "./tests",
- "./tests_dev"
- ],
- "TemplateEnding": "_template.txt"
- }
-}
diff --git a/src/cpl/__init__.py b/src/cpl/__init__.py
new file mode 100644
index 00000000..2d0005b2
--- /dev/null
+++ b/src/cpl/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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__ = 'sh_cpl.cpl'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl/application/__init__.py b/src/cpl/application/__init__.py
new file mode 100644
index 00000000..58595598
--- /dev/null
+++ b/src/cpl/application/__init__.py
@@ -0,0 +1,29 @@
+# -*- 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.application'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .application_abc import ApplicationABC
+from .application_builder import ApplicationBuilder
+from .application_builder_abc import ApplicationBuilderABC
+from .startup_abc import StartupABC
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl/application/application_abc.py b/src/cpl/application/application_abc.py
new file mode 100644
index 00000000..4c0e07d8
--- /dev/null
+++ b/src/cpl/application/application_abc.py
@@ -0,0 +1,46 @@
+from abc import ABC, abstractmethod
+from typing import Optional
+
+from cpl.configuration.configuration_abc import ConfigurationABC
+from cpl.console.console import Console
+from cpl.dependency_injection.service_provider_abc import ServiceProviderABC
+from cpl.environment import ApplicationEnvironmentABC
+
+
+class ApplicationABC(ABC):
+
+ @abstractmethod
+ def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
+ """
+ ABC of application
+ """
+ self._configuration: Optional[ConfigurationABC] = config
+ self._environment: Optional[ApplicationEnvironmentABC] = self._configuration.environment
+ self._services: Optional[ServiceProviderABC] = services
+
+ def run(self):
+ """
+ Entry point
+ :return:
+ """
+ try:
+ self.configure()
+ self.main()
+ except KeyboardInterrupt:
+ Console.close()
+
+ @abstractmethod
+ def configure(self):
+ """
+ Prepare the application
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def main(self):
+ """
+ Custom entry point
+ :return:
+ """
+ pass
diff --git a/src/cpl/application/application_builder.py b/src/cpl/application/application_builder.py
new file mode 100644
index 00000000..1dd7355d
--- /dev/null
+++ b/src/cpl/application/application_builder.py
@@ -0,0 +1,41 @@
+from typing import Type, Optional
+
+from cpl.application.application_abc import ApplicationABC
+from cpl.application.application_builder_abc import ApplicationBuilderABC
+from cpl.application.startup_abc import StartupABC
+from cpl.configuration.configuration import Configuration
+from cpl.dependency_injection.service_collection import ServiceCollection
+
+
+class ApplicationBuilder(ApplicationBuilderABC):
+
+ def __init__(self, app: Type[ApplicationABC]):
+ """
+ Builder class for application
+ """
+ ApplicationBuilderABC.__init__(self)
+ self._app = app
+ self._startup: Optional[StartupABC] = None
+
+ self._configuration = Configuration()
+ self._environment = self._configuration.environment
+ self._services = ServiceCollection(self._configuration)
+
+ def use_startup(self, startup: Type[StartupABC]):
+ """
+ Sets the used startup class
+ :param startup:
+ :return:
+ """
+ self._startup = startup(self._configuration, self._services)
+
+ def build(self) -> ApplicationABC:
+ """
+ Creates application host and runtime
+ :return:
+ """
+ if self._startup is not None:
+ self._startup.configure_configuration()
+ self._startup.configure_services()
+
+ return self._app(self._configuration, self._services.build_service_provider())
diff --git a/src/cpl/application/application_builder_abc.py b/src/cpl/application/application_builder_abc.py
new file mode 100644
index 00000000..b4e7d0d4
--- /dev/null
+++ b/src/cpl/application/application_builder_abc.py
@@ -0,0 +1,30 @@
+from abc import ABC, abstractmethod
+from typing import Type
+
+from cpl.application.application_abc import ApplicationABC
+from cpl.application.startup_abc import StartupABC
+
+
+class ApplicationBuilderABC(ABC):
+
+ def __init__(self, *args):
+ """
+ ABC of application builder
+ """
+
+ @abstractmethod
+ def use_startup(self, startup: Type[StartupABC]):
+ """
+ Sets the used startup class
+ :param startup:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def build(self) -> ApplicationABC:
+ """
+ Creates application host and runtime
+ :return:
+ """
+ pass
diff --git a/src/cpl/application/startup_abc.py b/src/cpl/application/startup_abc.py
new file mode 100644
index 00000000..203adebf
--- /dev/null
+++ b/src/cpl/application/startup_abc.py
@@ -0,0 +1,29 @@
+from abc import ABC, abstractmethod
+
+from cpl.configuration.configuration_abc import ConfigurationABC
+from cpl.dependency_injection.service_provider_abc import ServiceProviderABC
+
+
+class StartupABC(ABC):
+
+ @abstractmethod
+ def __init__(self, *args):
+ """
+ ABC for a startup class
+ """
+
+ @abstractmethod
+ def configure_configuration(self) -> ConfigurationABC:
+ """
+ Creates configuration of application
+ :return: configuration
+ """
+ pass
+
+ @abstractmethod
+ def configure_services(self) -> ServiceProviderABC:
+ """
+ Creates service provider
+ :return: service provider
+ """
+ pass
diff --git a/src/cpl/configuration/__init__.py b/src/cpl/configuration/__init__.py
new file mode 100644
index 00000000..73693042
--- /dev/null
+++ b/src/cpl/configuration/__init__.py
@@ -0,0 +1,30 @@
+# -*- 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.configuration'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .configuration import Configuration
+from .configuration_abc import ConfigurationABC
+from .configuration_model_abc import ConfigurationModelABC
+from .configuration_variable_name_enum import ConfigurationVariableNameEnum
+from .console_argument import ConsoleArgument
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl/configuration/configuration.py b/src/cpl/configuration/configuration.py
new file mode 100644
index 00000000..55e35a4f
--- /dev/null
+++ b/src/cpl/configuration/configuration.py
@@ -0,0 +1,357 @@
+import json
+import os
+import sys
+from collections import Callable
+from typing import Union, Type, Optional
+
+from cpl.configuration.configuration_abc import ConfigurationABC
+from cpl.configuration.configuration_model_abc import ConfigurationModelABC
+from cpl.configuration.configuration_variable_name_enum import ConfigurationVariableNameEnum
+from cpl.configuration.console_argument import ConsoleArgument
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.environment.application_environment import ApplicationEnvironment
+from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
+from cpl.environment.environment_name_enum import EnvironmentNameEnum
+
+
+class Configuration(ConfigurationABC):
+
+ def __init__(self):
+ """
+ Representation of configuration
+ """
+ ConfigurationABC.__init__(self)
+
+ self._application_environment = ApplicationEnvironment()
+ self._config: dict[Union[type, str], Union[ConfigurationModelABC, str]] = {}
+
+ self._argument_types: list[ConsoleArgument] = []
+ self._additional_arguments: list[str] = []
+
+ self._argument_error_function: Optional[Callable] = None
+
+ self._handled_args = []
+
+ @property
+ def environment(self) -> ApplicationEnvironmentABC:
+ return self._application_environment
+
+ @property
+ def additional_arguments(self) -> list[str]:
+ return self._additional_arguments
+
+ @property
+ def argument_error_function(self) -> Optional[Callable]:
+ return self._argument_error_function
+
+ @argument_error_function.setter
+ def argument_error_function(self, argument_error_function: Callable):
+ self._argument_error_function = argument_error_function
+
+ @staticmethod
+ def _print_info(name: str, message: str):
+ """
+ Prints an info message
+ :param name:
+ :param message:
+ :return:
+ """
+ Console.set_foreground_color(ForegroundColorEnum.green)
+ Console.write_line(f'[{name}] {message}')
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ @staticmethod
+ def _print_warn(name: str, message: str):
+ """
+ Prints a warning
+ :param name:
+ :param message:
+ :return:
+ """
+ Console.set_foreground_color(ForegroundColorEnum.yellow)
+ Console.write_line(f'[{name}] {message}')
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ @staticmethod
+ def _print_error(name: str, message: str):
+ """
+ Prints an error
+ :param name:
+ :param message:
+ :return:
+ """
+ Console.set_foreground_color(ForegroundColorEnum.red)
+ Console.write_line(f'[{name}] {message}')
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ def _set_variable(self, name: str, value: str):
+ """
+ Sets variable to given value
+ :param name:
+ :param value:
+ :return:
+ """
+ if name == ConfigurationVariableNameEnum.environment.value:
+ self._application_environment.environment_name = EnvironmentNameEnum(value)
+
+ elif name == ConfigurationVariableNameEnum.name.value:
+ self._application_environment.application_name = value
+
+ elif name == ConfigurationVariableNameEnum.customer.value:
+ self._application_environment.customer = value
+
+ else:
+ self._config[name] = value
+
+ def _validate_argument_child(self, argument: str, argument_type: ConsoleArgument,
+ next_arguments: Optional[list[str]]) -> bool:
+ """
+ Validates the child arguments of argument
+ :param argument:
+ :param argument_type:
+ :param next_arguments:
+ :return:
+ """
+ if argument_type.console_arguments is not None and len(argument_type.console_arguments) > 0:
+ found = False
+ for child_argument_type in argument_type.console_arguments:
+ found = self._validate_argument_by_argument_type(argument, child_argument_type, next_arguments)
+ if found and child_argument_type.name not in self._additional_arguments:
+ self._additional_arguments.append(child_argument_type.name)
+
+ if not found:
+ raise Exception(f'Invalid argument: {argument}')
+
+ return found
+
+ return True
+
+ def _validate_argument_by_argument_type(self, argument: str, argument_type: ConsoleArgument,
+ next_arguments: list[str] = None) -> bool:
+ """
+ Validate argument by argument type
+ :param argument:
+ :param argument_type:
+ :param next_arguments:
+ :return:
+ """
+ argument_name = ''
+ value = ''
+ result = False
+
+ if argument_type.value_token != '' and argument_type.value_token in argument:
+ # ?new=value
+ found = False
+ for alias in argument_type.aliases:
+ if alias in argument:
+ found = True
+
+ if argument_type.name not in argument_name and not found:
+ return False
+
+ if argument_type.is_value_token_optional is not None and argument_type.is_value_token_optional:
+ if argument_type.name not in self._additional_arguments:
+ self._additional_arguments.append(argument_type.name)
+ result = True
+
+ if argument_type.token != '' and argument.startswith(argument_type.token):
+ # --new=value
+ argument_name = argument.split(argument_type.token)[1].split(argument_type.value_token)[0]
+ else:
+ # new=value
+ argument_name = argument.split(argument_type.token)[1]
+
+ result = True
+
+ if argument_type.is_value_token_optional is True:
+ is_valid = False
+
+ name_list = argument.split(argument_type.token)
+ if len(name_list) > 1:
+ value_list = name_list[1].split(argument_type.value_token)
+ if len(value_list) > 1:
+ is_valid = True
+ value = argument.split(argument_type.token)[1].split(argument_type.value_token)[1]
+
+ if not is_valid:
+ if argument_type.name not in self._additional_arguments:
+ self._additional_arguments.append(argument_type.name)
+ result = True
+ else:
+ value = argument.split(argument_type.token)[1].split(argument_type.value_token)[1]
+
+ if argument_name != argument_type.name and argument_name not in argument_type.aliases:
+ return False
+
+ self._set_variable(argument_type.name, value)
+ result = True
+
+ elif argument_type.value_token == ' ':
+ # ?new value
+ found = False
+ for alias in argument_type.aliases:
+ if alias in argument:
+ found = True
+
+ if argument_type.name not in argument and not found:
+ return False
+
+ if (next_arguments is None or len(next_arguments) == 0) and \
+ argument_type.is_value_token_optional is not True:
+ raise Exception(f'Invalid argument: {argument}')
+
+ if (next_arguments is None or len(next_arguments) == 0) and argument_type.is_value_token_optional is True:
+ value = ''
+ else:
+ value = next_arguments[0]
+ self._handled_args.append(value)
+
+ if argument_type.token != '' and argument.startswith(argument_type.token):
+ # --new value
+ argument_name = argument.split(argument_type.token)[1]
+ else:
+ # new value
+ argument_name = argument
+
+ if argument_name != argument_type.name and argument_name not in argument_type.aliases:
+ return False
+
+ if value == '':
+ if argument_type.name not in self._additional_arguments:
+ self._additional_arguments.append(argument_type.name)
+ else:
+ self._set_variable(argument_type.name, value)
+
+ result = True
+
+ elif argument_type.name == argument or argument in argument_type.aliases:
+ # new
+ self._additional_arguments.append(argument_type.name)
+ result = True
+
+ if result:
+ self._handled_args.append(argument)
+ if next_arguments is not None and len(next_arguments) > 0:
+ next_args = []
+ if len(next_arguments) > 1:
+ next_args = next_arguments[1:]
+ result = self._validate_argument_child(next_arguments[0], argument_type, next_args)
+
+ return result
+
+ def add_environment_variables(self, prefix: str):
+ for variable in ConfigurationVariableNameEnum.to_list():
+ var_name = f'{prefix}{variable}'
+ if var_name in [key.upper() for key in os.environ.keys()]:
+ self._set_variable(variable, os.environ[var_name])
+
+ def add_console_argument(self, argument: ConsoleArgument):
+ self._argument_types.append(argument)
+
+ def add_console_arguments(self, error: bool = None):
+ for arg_name in ConfigurationVariableNameEnum.to_list():
+ self.add_console_argument(ConsoleArgument('--', str(arg_name).upper(), [str(arg_name).lower()], '='))
+
+ arg_list = sys.argv[1:]
+ for i in range(0, len(arg_list)):
+ argument = arg_list[i]
+ next_arguments = []
+ error_message = ''
+
+ if argument in self._handled_args:
+ break
+
+ if i + 1 < len(arg_list):
+ next_arguments = arg_list[i + 1:]
+
+ found = False
+ for argument_type in self._argument_types:
+ try:
+ found = self._validate_argument_by_argument_type(argument, argument_type, next_arguments)
+ if found:
+ break
+ except Exception as e:
+ error_message = e
+
+ if not found and error_message == '' and error is not False:
+ error_message = f'Invalid argument: {argument}'
+
+ if self._argument_error_function is not None:
+ self._argument_error_function(error_message)
+ else:
+ self._print_error(__name__, error_message)
+
+ exit()
+
+ def add_json_file(self, name: str, optional: bool = None, output: bool = True, path: str = None):
+ path_root = self._application_environment.content_root_path
+ if path is not None:
+ path_root = path
+
+ if str(path_root).endswith('/') and not name.startswith('/'):
+ file_path = f'{path_root}{name}'
+ else:
+ file_path = f'{path_root}/{name}'
+
+ if not os.path.isfile(file_path):
+ if optional is not True:
+ if output:
+ self._print_error(__name__, f'File not found: {file_path}')
+
+ exit()
+
+ if output:
+ self._print_warn(__name__, f'Not Loaded config file: {file_path}')
+
+ return None
+
+ config_from_file = self._load_json_file(file_path, output)
+ for sub in ConfigurationModelABC.__subclasses__():
+ for key, value in config_from_file.items():
+ if sub.__name__ == key or sub.__name__.replace('Settings', '') == key:
+ configuration = sub()
+ configuration.from_dict(value)
+ self.add_configuration(sub, configuration)
+
+ def _load_json_file(self, file: str, output: bool) -> dict:
+ """
+ Reads the json file
+ :param file:
+ :param output:
+ :return:
+ """
+ try:
+ # open config file, create if not exists
+ with open(file, encoding='utf-8') as cfg:
+ # load json
+ json_cfg = json.load(cfg)
+ if output:
+ self._print_info(__name__, f'Loaded config file: {file}')
+
+ return json_cfg
+ except Exception as e:
+ self._print_error(__name__, f'Cannot load config file: {file}! -> {e}')
+ return {}
+
+ def add_configuration(self, key_type: type, value: ConfigurationModelABC):
+ self._config[key_type] = value
+
+ def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> Union[
+ str, Callable[ConfigurationModelABC]]:
+ if type(search_type) is str:
+ if search_type == ConfigurationVariableNameEnum.environment.value:
+ return self._application_environment.environment_name
+
+ elif search_type == ConfigurationVariableNameEnum.name.value:
+ return self._application_environment.application_name
+
+ elif search_type == ConfigurationVariableNameEnum.customer.value:
+ return self._application_environment.customer
+
+ if search_type not in self._config:
+ return None
+
+ for config_model in self._config:
+ if config_model == search_type:
+ return self._config[config_model]
diff --git a/src/cpl/configuration/configuration_abc.py b/src/cpl/configuration/configuration_abc.py
new file mode 100644
index 00000000..2fc03bb5
--- /dev/null
+++ b/src/cpl/configuration/configuration_abc.py
@@ -0,0 +1,91 @@
+from abc import abstractmethod, ABC
+from collections import Callable
+from typing import Type, Union, Optional
+
+from cpl.configuration.console_argument import ConsoleArgument
+from cpl.configuration.configuration_model_abc import ConfigurationModelABC
+from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
+
+
+class ConfigurationABC(ABC):
+
+ @abstractmethod
+ def __init__(self):
+ """
+ ABC of configuration
+ """
+ pass
+
+ @property
+ @abstractmethod
+ def environment(self) -> ApplicationEnvironmentABC: pass
+
+ @property
+ @abstractmethod
+ def additional_arguments(self) -> list[str]: pass
+
+ @property
+ @abstractmethod
+ def argument_error_function(self) -> Optional[Callable]: pass
+
+ @argument_error_function.setter
+ @abstractmethod
+ def argument_error_function(self, argument_error_function: Callable): pass
+
+ @abstractmethod
+ def add_environment_variables(self, prefix: str):
+ """
+ Reads the environment variables
+ :param prefix:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def add_console_argument(self, argument: ConsoleArgument):
+ """
+ Adds console argument to known console arguments
+ :param argument:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def add_console_arguments(self, error: bool = None):
+ """
+ Reads the console arguments
+ :param error: defines is invalid argument error will be shown or not
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def add_json_file(self, name: str, optional: bool = None, output: bool = True, path: str = None):
+ """
+ Reads and saves settings from given json file
+ :param name:
+ :param optional:
+ :param output:
+ :param path:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def add_configuration(self, key_type: type, value: object):
+ """
+ Add configuration object
+ :param key_type:
+ :param value:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def get_configuration(self, search_type: Union[str, Type[ConfigurationModelABC]]) -> Union[str, Callable[ConfigurationModelABC]]:
+ """
+ Returns value in configuration by given type
+ :param search_type:
+ :return:
+ """
+ pass
diff --git a/src/cpl/configuration/configuration_model_abc.py b/src/cpl/configuration/configuration_model_abc.py
new file mode 100644
index 00000000..bcc6ab37
--- /dev/null
+++ b/src/cpl/configuration/configuration_model_abc.py
@@ -0,0 +1,20 @@
+from abc import ABC, abstractmethod
+
+
+class ConfigurationModelABC(ABC):
+
+ @abstractmethod
+ def __init__(self):
+ """
+ ABC for settings representation
+ """
+ pass
+
+ @abstractmethod
+ def from_dict(self, settings: dict):
+ """
+ Converts attributes to dict
+ :param settings:
+ :return:
+ """
+ pass
diff --git a/src/sh_edraft/configuration/model/configuration_variable_name.py b/src/cpl/configuration/configuration_variable_name_enum.py
similarity index 55%
rename from src/sh_edraft/configuration/model/configuration_variable_name.py
rename to src/cpl/configuration/configuration_variable_name_enum.py
index c89deb88..7db3688d 100644
--- a/src/sh_edraft/configuration/model/configuration_variable_name.py
+++ b/src/cpl/configuration/configuration_variable_name_enum.py
@@ -1,7 +1,7 @@
from enum import Enum
-class ConfigurationVariableName(Enum):
+class ConfigurationVariableNameEnum(Enum):
environment = 'ENVIRONMENT'
name = 'NAME'
@@ -9,4 +9,4 @@ class ConfigurationVariableName(Enum):
@staticmethod
def to_list():
- return [var.value for var in ConfigurationVariableName]
+ return [var.value for var in ConfigurationVariableNameEnum]
diff --git a/src/cpl/configuration/console_argument.py b/src/cpl/configuration/console_argument.py
new file mode 100644
index 00000000..bc8a4e13
--- /dev/null
+++ b/src/cpl/configuration/console_argument.py
@@ -0,0 +1,49 @@
+class ConsoleArgument:
+
+ def __init__(self,
+ token: str,
+ name: str,
+ aliases: list[str],
+ value_token: str,
+ is_value_token_optional: bool = None,
+ console_arguments: list['ConsoleArgument'] = None
+ ):
+ """
+ Representation of an console argument
+ :param token:
+ :param name:
+ :param aliases:
+ :param value_token:
+ :param is_value_token_optional:
+ :param console_arguments:
+ """
+ self._token = token
+ self._name = name
+ self._aliases = aliases
+ self._value_token = value_token
+ self._is_value_token_optional = is_value_token_optional
+ self._console_arguments = console_arguments
+
+ @property
+ def token(self) -> str:
+ return self._token
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def aliases(self) -> list[str]:
+ return self._aliases
+
+ @property
+ def value_token(self) -> str:
+ return self._value_token
+
+ @property
+ def is_value_token_optional(self) -> bool:
+ return self._is_value_token_optional
+
+ @property
+ def console_arguments(self) -> list['ConsoleArgument']:
+ return self._console_arguments
diff --git a/src/cpl/console/__init__.py b/src/cpl/console/__init__.py
new file mode 100644
index 00000000..b43b7224
--- /dev/null
+++ b/src/cpl/console/__init__.py
@@ -0,0 +1,30 @@
+# -*- 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.console'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .background_color_enum import BackgroundColorEnum
+from .console import Console
+from .console_call import ConsoleCall
+from .foreground_color_enum import ForegroundColorEnum
+from .spinner_thread import SpinnerThread
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/sh_edraft/console/model/background_color.py b/src/cpl/console/background_color_enum.py
similarity index 87%
rename from src/sh_edraft/console/model/background_color.py
rename to src/cpl/console/background_color_enum.py
index f4947e30..64258332 100644
--- a/src/sh_edraft/console/model/background_color.py
+++ b/src/cpl/console/background_color_enum.py
@@ -1,7 +1,7 @@
from enum import Enum
-class BackgroundColor(Enum):
+class BackgroundColorEnum(Enum):
default = 'on_default'
grey = 'on_grey'
diff --git a/src/cpl/console/console.py b/src/cpl/console/console.py
new file mode 100644
index 00000000..b1536b60
--- /dev/null
+++ b/src/cpl/console/console.py
@@ -0,0 +1,528 @@
+import os
+import sys
+import time
+from collections import Callable
+from typing import Union, Optional
+
+import colorama
+import pyfiglet
+from pynput import keyboard
+from pynput.keyboard import Key
+from tabulate import tabulate
+from termcolor import colored
+
+from cpl.console.background_color_enum import BackgroundColorEnum
+from cpl.console.console_call import ConsoleCall
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.console.spinner_thread import SpinnerThread
+
+
+class Console:
+ """
+ Useful functions for handling with input and output
+ """
+ colorama.init()
+ _is_first_write = True
+
+ _background_color: BackgroundColorEnum = BackgroundColorEnum.default
+ _foreground_color: ForegroundColorEnum = ForegroundColorEnum.default
+ _x: Optional[int] = None
+ _y: Optional[int] = None
+ _disabled: bool = False
+
+ _hold_back = False
+ _hold_back_calls: list[ConsoleCall] = []
+
+ _select_menu_items: list[str] = []
+ _is_first_select_menu_output = True
+ _selected_menu_item_index: int = 0
+ _selected_menu_item_char: str = ''
+ _selected_menu_option_foreground_color: ForegroundColorEnum = ForegroundColorEnum.default
+ _selected_menu_option_background_color: BackgroundColorEnum = BackgroundColorEnum.default
+ _selected_menu_cursor_foreground_color: ForegroundColorEnum = ForegroundColorEnum.default
+ _selected_menu_cursor_background_color: BackgroundColorEnum = BackgroundColorEnum.default
+
+ """
+ Properties
+ """
+
+ @classmethod
+ @property
+ def background_color(cls) -> str:
+ return str(cls._background_color.value)
+
+ @classmethod
+ @property
+ def foreground_color(cls) -> str:
+ return str(cls._foreground_color.value)
+
+ """
+ Settings
+ """
+
+ @classmethod
+ def set_hold_back(cls, value: bool):
+ cls._hold_back = value
+
+ @classmethod
+ def set_background_color(cls, color: Union[BackgroundColorEnum, str]):
+ """
+ Sets the background color
+ :param color:
+ :return:
+ """
+ if type(color) is str:
+ cls._background_color = BackgroundColorEnum[color]
+ else:
+ cls._background_color = color
+
+ @classmethod
+ def set_foreground_color(cls, color: Union[ForegroundColorEnum, str]):
+ """
+ Sets the foreground color
+ :param color:
+ :return:
+ """
+ if type(color) is str:
+ cls._foreground_color = ForegroundColorEnum[color]
+ else:
+ cls._foreground_color = color
+
+ @classmethod
+ def reset_cursor_position(cls):
+ """
+ Resets cursor position
+ :return:
+ """
+ cls._x = None
+ cls._y = None
+
+ @classmethod
+ def set_cursor_position(cls, x: int, y: int):
+ """
+ Sets cursor position
+ :param x:
+ :param y:
+ :return:
+ """
+ cls._x = x
+ cls._y = y
+
+ """
+ Useful protected methods
+ """
+
+ @classmethod
+ def _output(cls, string: str, x: int = None, y: int = None, end: str = None):
+ """
+ Prints given output with given format
+ :param string:
+ :param x:
+ :param y:
+ :param end:
+ :return:
+ """
+ if cls._is_first_write:
+ cls._is_first_write = False
+
+ if end is None:
+ end = '\n'
+
+ args = []
+ colored_args = []
+ if x is not None and y is not None:
+ args.append(f'\033[{y};{x}H')
+ elif cls._x is not None and cls._y is not None:
+ args.append(f'\033[{cls._y};{cls._x}H')
+
+ colored_args.append(string)
+ if cls._foreground_color != ForegroundColorEnum.default and cls._background_color == BackgroundColorEnum.default:
+ colored_args.append(cls._foreground_color.value)
+ elif cls._foreground_color == ForegroundColorEnum.default and cls._background_color != BackgroundColorEnum.default:
+ colored_args.append(cls._background_color.value)
+ elif cls._foreground_color != ForegroundColorEnum.default and cls._background_color != BackgroundColorEnum.default:
+ colored_args.append(cls._foreground_color.value)
+ colored_args.append(cls._background_color.value)
+
+ args.append(colored(*colored_args))
+ print(*args, end=end)
+
+ @classmethod
+ def _show_select_menu(cls):
+ """
+ Shows the select menu
+ :return:
+ """
+ if not cls._is_first_select_menu_output:
+ for _ in range(0, len(cls._select_menu_items) + 1):
+ sys.stdout.write('\x1b[1A\x1b[2K')
+ else:
+ cls._is_first_select_menu_output = False
+
+ for i in range(0, len(cls._select_menu_items)):
+ Console.set_foreground_color(cls._selected_menu_cursor_foreground_color)
+ Console.set_background_color(cls._selected_menu_cursor_background_color)
+ placeholder = ''
+ for _ in cls._selected_menu_item_char:
+ placeholder += ' '
+
+ Console.write_line(
+ f'{cls._selected_menu_item_char if cls._selected_menu_item_index == i else placeholder} ')
+ Console.set_foreground_color(cls._selected_menu_option_foreground_color)
+ Console.set_background_color(cls._selected_menu_option_background_color)
+ Console.write(f'{cls._select_menu_items[i]}')
+
+ Console.write_line()
+
+ @classmethod
+ def _select_menu_key_press(cls, key: Key):
+ """
+ Event function when key press is detected
+ :param key:
+ :return:
+ """
+ if key == Key.down:
+ if cls._selected_menu_item_index == len(cls._select_menu_items) - 1:
+ return
+ cls._selected_menu_item_index += 1
+ cls._show_select_menu()
+
+ elif key == Key.up:
+ if cls._selected_menu_item_index == 0:
+ return
+ cls._selected_menu_item_index -= 1
+ cls._show_select_menu()
+
+ elif key == Key.enter:
+ return False
+
+ """
+ Useful public methods
+ """
+
+ @classmethod
+ def banner(cls, string: str):
+ """
+ Prints the string as a banner
+ :param string:
+ :return:
+ """
+ if cls._disabled:
+ return
+
+ if cls._hold_back:
+ cls._hold_back_calls.append(ConsoleCall(cls.banner, string))
+ return
+
+ ascii_banner = pyfiglet.figlet_format(string)
+ cls.write_line(ascii_banner)
+
+ @classmethod
+ def color_reset(cls):
+ """
+ Resets color
+ :return:
+ """
+ cls._background_color = BackgroundColorEnum.default
+ cls._foreground_color = ForegroundColorEnum.default
+
+ @classmethod
+ def clear(cls):
+ """
+ Clears the console
+ :return:
+ """
+ if cls._hold_back:
+ cls._hold_back_calls.append(ConsoleCall(cls.clear))
+ return
+
+ os.system('cls' if os.name == 'nt' else 'clear')
+
+ @classmethod
+ def close(cls):
+ """
+ Close the application
+ :return:
+ """
+ if cls._disabled:
+ return
+
+ if cls._hold_back:
+ cls._hold_back_calls.append(ConsoleCall(cls.close))
+ return
+
+ Console.color_reset()
+ Console.write('\n\n\nPress any key to continue...')
+ Console.read()
+ exit()
+
+ @classmethod
+ def disable(cls):
+ """
+ Disable console interaction
+ :return:
+ """
+ cls._disabled = True
+
+ @classmethod
+ def error(cls, string: str, tb: str = None):
+ """
+ Prints an error with traceback
+ :param string:
+ :param tb:
+ :return:
+ """
+ if cls._disabled:
+ return
+
+ if cls._hold_back:
+ cls._hold_back_calls.append(ConsoleCall(cls.error, string, tb))
+ return
+
+ cls.set_foreground_color('red')
+ if tb is not None:
+ cls.write_line(f'{string} -> {tb}')
+ else:
+ cls.write_line(string)
+ cls.set_foreground_color('default')
+
+ @classmethod
+ def enable(cls):
+ """
+ Enable console interaction
+ :return:
+ """
+ cls._disabled = False
+
+ @classmethod
+ def read(cls, output: str = None) -> str:
+ """
+ Read in line
+ :param output:
+ :return:
+ """
+ if output is not None and not cls._hold_back:
+ cls.write_line(output)
+
+ return input()
+
+ @classmethod
+ def read_line(cls, output: str = None) -> str:
+ """
+ Reads in next line
+ :param output:
+ :return:
+ """
+ if cls._disabled and not cls._hold_back:
+ return ''
+
+ if output is not None:
+ cls.write_line(output)
+
+ cls._output('\n', end='')
+
+ return input()
+
+ @classmethod
+ def table(cls, header: list[str], values: list[list[str]]):
+ """
+ Prints a table with header and values
+ :param header:
+ :param values:
+ :return:
+ """
+ if cls._disabled:
+ return
+
+ if cls._hold_back:
+ cls._hold_back_calls.append(ConsoleCall(cls.table, header, values))
+ return
+
+ table = tabulate(values, headers=header)
+
+ Console.write_line(table)
+ Console.write('\n')
+
+ @classmethod
+ def select(cls, char: str, message: str, options: list[str],
+ header_foreground_color: Union[str, ForegroundColorEnum] = ForegroundColorEnum.default,
+ header_background_color: Union[str, BackgroundColorEnum] = BackgroundColorEnum.default,
+ option_foreground_color: Union[str, ForegroundColorEnum] = ForegroundColorEnum.default,
+ option_background_color: Union[str, BackgroundColorEnum] = BackgroundColorEnum.default,
+ cursor_foreground_color: Union[str, ForegroundColorEnum] = ForegroundColorEnum.default,
+ cursor_background_color: Union[str, BackgroundColorEnum] = BackgroundColorEnum.default
+ ) -> str:
+ """
+ Prints select menu
+ :param char:
+ :param message:
+ :param options:
+ :param header_foreground_color:
+ :param header_background_color:
+ :param option_foreground_color:
+ :param option_background_color:
+ :param cursor_foreground_color:
+ :param cursor_background_color:
+ :return: Selected option as str
+ """
+ cls._selected_menu_item_char = char
+ cls.options = options
+ cls._select_menu_items = cls.options
+
+ if option_foreground_color is not None:
+ cls._selected_menu_option_foreground_color = option_foreground_color
+ if option_background_color is not None:
+ cls._selected_menu_option_background_color = option_background_color
+
+ if cursor_foreground_color is not None:
+ cls._selected_menu_cursor_foreground_color = cursor_foreground_color
+ if cursor_background_color is not None:
+ cls._selected_menu_cursor_background_color = cursor_background_color
+
+ Console.set_foreground_color(header_foreground_color)
+ Console.set_background_color(header_background_color)
+ Console.write_line(message, '\n')
+ cls._show_select_menu()
+
+ with keyboard.Listener(
+ on_press=cls._select_menu_key_press, suppress=True) as listener:
+ listener.join()
+
+ Console.color_reset()
+ return cls._select_menu_items[cls._selected_menu_item_index]
+
+ @classmethod
+ def spinner(cls, message: str, call: Callable, *args, text_foreground_color: Union[str, ForegroundColorEnum] = None,
+ spinner_foreground_color: Union[str, ForegroundColorEnum] = None,
+ text_background_color: Union[str, BackgroundColorEnum] = None,
+ spinner_background_color: Union[str, BackgroundColorEnum] = None, **kwargs) -> any:
+ """
+ Shows spinner and calls given function
+ When function has ended the spinner stops
+ :param message:
+ :param call:
+ :param args:
+ :param text_foreground_color:
+ :param spinner_foreground_color:
+ :param text_background_color:
+ :param spinner_background_color:
+ :param kwargs:
+ :return: Return value of call
+ """
+ if cls._hold_back:
+ cls._hold_back_calls.append(ConsoleCall(cls.spinner, message, call, *args))
+ return
+
+ if text_foreground_color is not None:
+ cls.set_foreground_color(text_foreground_color)
+
+ if text_background_color is not None:
+ cls.set_background_color(text_background_color)
+
+ if type(spinner_foreground_color) is str:
+ spinner_foreground_color = ForegroundColorEnum[spinner_foreground_color]
+
+ if type(spinner_background_color) is str:
+ spinner_background_color = BackgroundColorEnum[spinner_background_color]
+
+ cls.write_line(message)
+ cls.set_hold_back(True)
+ spinner = SpinnerThread(len(message), spinner_foreground_color, spinner_background_color)
+ spinner.start()
+
+ return_value = None
+ try:
+ return_value = call(*args, **kwargs)
+ except KeyboardInterrupt:
+ spinner.exit()
+ cls.close()
+
+ spinner.stop_spinning()
+ cls.set_hold_back(False)
+
+ cls.set_foreground_color(ForegroundColorEnum.default)
+ cls.set_background_color(BackgroundColorEnum.default)
+
+ for call in cls._hold_back_calls:
+ call.function(*call.args)
+
+ time.sleep(0.1)
+
+ return return_value
+
+ @classmethod
+ def write(cls, *args, end=''):
+ """
+ Prints in active line
+ :param args:
+ :param end:
+ :return:
+ """
+ if cls._disabled:
+ return
+
+ if cls._hold_back:
+ cls._hold_back_calls.append(ConsoleCall(cls.write, args))
+ return
+
+ string = ' '.join(map(str, args))
+ cls._output(string, end=end)
+
+ @classmethod
+ def write_at(cls, x: int, y: int, *args):
+ """
+ Prints at given position
+ :param x:
+ :param y:
+ :param args:
+ :return:
+ """
+ if cls._disabled:
+ return
+
+ if cls._hold_back:
+ cls._hold_back_calls.append(ConsoleCall(cls.write_at, x, y, args))
+ return
+
+ string = ' '.join(map(str, args))
+ cls._output(string, x, y, end='')
+
+ @classmethod
+ def write_line(cls, *args):
+ """
+ Prints to new line
+ :param args:
+ :return:
+ """
+ if cls._disabled:
+ return
+
+ if cls._hold_back:
+ cls._hold_back_calls.append(ConsoleCall(cls.write_line, args))
+ return
+
+ string = ' '.join(map(str, args))
+ if not cls._is_first_write:
+ cls._output('')
+ cls._output(string, end='')
+
+ @classmethod
+ def write_line_at(cls, x: int, y: int, *args):
+ """
+ Prints new line at given position
+ :param x:
+ :param y:
+ :param args:
+ :return:
+ """
+ if cls._disabled:
+ return
+
+ if cls._hold_back:
+ cls._hold_back_calls.append(ConsoleCall(cls.write_line_at, x, y, args))
+ return
+
+ string = ' '.join(map(str, args))
+ if not cls._is_first_write:
+ cls._output('', end='')
+ cls._output(string, x, y, end='')
diff --git a/src/cpl/console/console_call.py b/src/cpl/console/console_call.py
new file mode 100644
index 00000000..1a8c10f8
--- /dev/null
+++ b/src/cpl/console/console_call.py
@@ -0,0 +1,21 @@
+from collections import Callable
+
+
+class ConsoleCall:
+
+ def __init__(self, function: Callable, *args):
+ """
+ Represents a console call, for hold back when spinner is active
+ :param function:
+ :param args:
+ """
+ self._func = function
+ self._args = args
+
+ @property
+ def function(self):
+ return self._func
+
+ @property
+ def args(self):
+ return self._args
diff --git a/src/sh_edraft/console/model/foreground_color.py b/src/cpl/console/foreground_color_enum.py
similarity index 86%
rename from src/sh_edraft/console/model/foreground_color.py
rename to src/cpl/console/foreground_color_enum.py
index 463d4ae7..7ee02c30 100644
--- a/src/sh_edraft/console/model/foreground_color.py
+++ b/src/cpl/console/foreground_color_enum.py
@@ -1,7 +1,7 @@
from enum import Enum
-class ForegroundColor(Enum):
+class ForegroundColorEnum(Enum):
default = 'default'
grey = 'grey'
diff --git a/src/cpl/console/spinner_thread.py b/src/cpl/console/spinner_thread.py
new file mode 100644
index 00000000..7b13d963
--- /dev/null
+++ b/src/cpl/console/spinner_thread.py
@@ -0,0 +1,107 @@
+import os
+import sys
+import threading
+import time
+
+from termcolor import colored
+
+from cpl.console.background_color_enum import BackgroundColorEnum
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+
+
+class SpinnerThread(threading.Thread):
+
+ def __init__(self, msg_len: int, foreground_color: ForegroundColorEnum, background_color: BackgroundColorEnum):
+ """
+ Thread to show spinner in terminal
+ :param msg_len:
+ :param foreground_color:
+ :param background_color:
+ """
+ threading.Thread.__init__(self)
+
+ self._msg_len = msg_len
+ self._foreground_color = foreground_color
+ self._background_color = background_color
+
+ self._is_spinning = True
+ self._exit = False
+
+ @staticmethod
+ def _spinner():
+ """
+ Selects active spinner char
+ :return:
+ """
+ while True:
+ for cursor in '|/-\\':
+ yield cursor
+
+ def _get_color_args(self) -> list[str]:
+ """
+ Creates color arguments
+ :return:
+ """
+ color_args = []
+ if self._foreground_color is not None:
+ color_args.append(str(self._foreground_color.value))
+
+ if self._background_color is not None:
+ color_args.append(str(self._background_color.value))
+
+ return color_args
+
+ def run(self) -> None:
+ """
+ Entry point of thread, shows the spinner
+ :return:
+ """
+ columns = 0
+ if sys.platform == 'win32':
+ columns = os.get_terminal_size().columns
+ else:
+ term_rows, term_columns = os.popen('stty size', 'r').read().split()
+ columns = int(term_columns)
+
+ end_msg = 'done'
+ end_msg_pos = columns - self._msg_len - len(end_msg)
+ if end_msg_pos > 0:
+ print(f'{"" : >{end_msg_pos}}', end='')
+ else:
+ print('', end='')
+
+ first = True
+ spinner = self._spinner()
+ while self._is_spinning:
+ if first:
+ first = False
+ print(colored(f'{next(spinner): >{len(end_msg) - 1}}', *self._get_color_args()), end='')
+ else:
+ print(colored(f'{next(spinner): >{len(end_msg)}}', *self._get_color_args()), end='')
+ time.sleep(0.1)
+ back = ''
+ for i in range(0, len(end_msg)):
+ back += '\b'
+
+ print(back, end='')
+ sys.stdout.flush()
+
+ if not self._exit:
+ print(colored(end_msg, *self._get_color_args()), end='')
+
+ def stop_spinning(self):
+ """
+ Stops the spinner
+ :return:
+ """
+ self._is_spinning = False
+ time.sleep(0.1)
+
+ def exit(self):
+ """
+ Stops the spinner
+ :return:
+ """
+ self._is_spinning = False
+ self._exit = True
+ time.sleep(0.1)
diff --git a/src/cpl/database/__init__.py b/src/cpl/database/__init__.py
new file mode 100644
index 00000000..307c43a4
--- /dev/null
+++ b/src/cpl/database/__init__.py
@@ -0,0 +1,28 @@
+# -*- 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.database'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .database_model import DatabaseModel
+from .database_settings import DatabaseSettings
+from .database_settings_name_enum import DatabaseSettingsNameEnum
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl/database/connection/__init__.py b/src/cpl/database/connection/__init__.py
new file mode 100644
index 00000000..959b5143
--- /dev/null
+++ b/src/cpl/database/connection/__init__.py
@@ -0,0 +1,27 @@
+# -*- 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.database.connection'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .database_connection import DatabaseConnection
+from .database_connection_abc import DatabaseConnectionABC
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/sh_edraft/database/connection/database_connection.py b/src/cpl/database/connection/database_connection.py
similarity index 60%
rename from src/sh_edraft/database/connection/database_connection.py
rename to src/cpl/database/connection/database_connection.py
index b3397113..87f77758 100644
--- a/src/sh_edraft/database/connection/database_connection.py
+++ b/src/cpl/database/connection/database_connection.py
@@ -3,16 +3,20 @@ from typing import Optional
from sqlalchemy import engine, create_engine
from sqlalchemy.orm import Session, sessionmaker
-from sh_edraft.database.connection.base.database_connection_base import DatabaseConnectionBase
-from sh_edraft.database.model.database_settings import DatabaseSettings
-from sh_edraft.console.console import Console
-from sh_edraft.console.model.foreground_color import ForegroundColor
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.database.connection.database_connection_abc import DatabaseConnectionABC
+from cpl.database.database_settings import DatabaseSettings
-class DatabaseConnection(DatabaseConnectionBase):
+class DatabaseConnection(DatabaseConnectionABC):
def __init__(self, database_settings: DatabaseSettings):
- DatabaseConnectionBase.__init__(self)
+ """
+ Represents an connection to a database
+ :param database_settings:
+ """
+ DatabaseConnectionABC.__init__(self)
self._db_settings = database_settings
@@ -32,6 +36,9 @@ class DatabaseConnection(DatabaseConnectionBase):
try:
self._engine = create_engine(connection_string)
+ if self._db_settings.auth_plugin is not None:
+ self._engine = create_engine(connection_string, connect_args={'auth_plugin': self._db_settings.auth_plugin})
+
if self._db_settings.encoding is not None:
self._engine.encoding = self._db_settings.encoding
@@ -45,12 +52,11 @@ class DatabaseConnection(DatabaseConnectionBase):
db_session = sessionmaker(bind=self._engine)
self._session = db_session()
- Console.set_foreground_color(ForegroundColor.green)
+ Console.set_foreground_color(ForegroundColorEnum.green)
Console.write_line(f'[{__name__}] Connected to database')
- Console.set_foreground_color(ForegroundColor.default)
+ Console.set_foreground_color(ForegroundColorEnum.default)
except Exception as e:
- Console.set_foreground_color(ForegroundColor.red)
+ Console.set_foreground_color(ForegroundColorEnum.red)
Console.write_line(f'[{__name__}] Database connection failed -> {e}')
- Console.set_foreground_color(ForegroundColor.default)
+ Console.set_foreground_color(ForegroundColorEnum.default)
exit()
-
diff --git a/src/sh_edraft/database/connection/base/database_connection_base.py b/src/cpl/database/connection/database_connection_abc.py
similarity index 59%
rename from src/sh_edraft/database/connection/base/database_connection_base.py
rename to src/cpl/database/connection/database_connection_abc.py
index 9bc31427..139e9214 100644
--- a/src/sh_edraft/database/connection/base/database_connection_base.py
+++ b/src/cpl/database/connection/database_connection_abc.py
@@ -4,7 +4,7 @@ from sqlalchemy import engine
from sqlalchemy.orm import Session
-class DatabaseConnectionBase(ABC):
+class DatabaseConnectionABC(ABC):
@abstractmethod
def __init__(self): pass
@@ -18,4 +18,10 @@ class DatabaseConnectionBase(ABC):
def session(self) -> Session: pass
@abstractmethod
- def connect(self, connection_string: str): pass
+ def connect(self, connection_string: str):
+ """
+ Connects to a database by connection string
+ :param connection_string:
+ :return:
+ """
+ pass
diff --git a/src/cpl/database/context/__init__.py b/src/cpl/database/context/__init__.py
new file mode 100644
index 00000000..5e9e9607
--- /dev/null
+++ b/src/cpl/database/context/__init__.py
@@ -0,0 +1,27 @@
+# -*- 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.database.context'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .database_context import DatabaseContext
+from .database_context_abc import DatabaseContextABC
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl/database/context/database_context.py b/src/cpl/database/context/database_context.py
new file mode 100644
index 00000000..c07f1acd
--- /dev/null
+++ b/src/cpl/database/context/database_context.py
@@ -0,0 +1,50 @@
+from sqlalchemy import engine, Table
+from sqlalchemy.orm import Session
+
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.database.connection.database_connection import DatabaseConnection
+from cpl.database.connection.database_connection_abc import DatabaseConnectionABC
+from cpl.database.context.database_context_abc import DatabaseContextABC
+from cpl.database.database_settings import DatabaseSettings
+from cpl.database.database_model import DatabaseModel
+
+
+class DatabaseContext(DatabaseContextABC):
+
+ def __init__(self, database_settings: DatabaseSettings):
+ DatabaseContextABC.__init__(self)
+
+ self._db: DatabaseConnectionABC = DatabaseConnection(database_settings)
+ self._tables: list[Table] = []
+
+ @property
+ def engine(self) -> engine:
+ return self._db.engine
+
+ @property
+ def session(self) -> Session:
+ return self._db.session
+
+ def connect(self, connection_string: str):
+ self._db.connect(connection_string)
+ self._create_tables()
+
+ def save_changes(self):
+ self._db.session.commit()
+
+ def _create_tables(self):
+ try:
+ for subclass in DatabaseModel.__subclasses__():
+ self._tables.append(subclass.__table__)
+
+ DatabaseModel.metadata.drop_all(self._db.engine, self._tables)
+ DatabaseModel.metadata.create_all(self._db.engine, self._tables, checkfirst=True)
+ Console.set_foreground_color(ForegroundColorEnum.green)
+ Console.write_line(f'[{__name__}] Created tables')
+ Console.set_foreground_color(ForegroundColorEnum.default)
+ except Exception as e:
+ Console.set_foreground_color(ForegroundColorEnum.red)
+ Console.write_line(f'[{__name__}] Creating tables failed -> {e}')
+ Console.set_foreground_color(ForegroundColorEnum.default)
+ exit()
diff --git a/src/cpl/database/context/database_context_abc.py b/src/cpl/database/context/database_context_abc.py
new file mode 100644
index 00000000..d27d6da0
--- /dev/null
+++ b/src/cpl/database/context/database_context_abc.py
@@ -0,0 +1,42 @@
+from abc import abstractmethod, ABC
+
+from sqlalchemy import engine
+from sqlalchemy.orm import Session
+
+
+class DatabaseContextABC(ABC):
+
+ @abstractmethod
+ def __init__(self, *args):
+ pass
+
+ @property
+ @abstractmethod
+ def engine(self) -> engine: pass
+
+ @property
+ @abstractmethod
+ def session(self) -> Session: pass
+
+ @abstractmethod
+ def connect(self, connection_string: str):
+ """
+ Connects to a database with connection string
+ :param connection_string:
+ :return:
+ """
+ pass
+
+ def save_changes(self):
+ """
+ Saves changes of the database
+ """
+ pass
+
+ @abstractmethod
+ def _create_tables(self):
+ """
+ Create all tables for application from database model
+ :return:
+ """
+ pass
diff --git a/src/sh_edraft/database/model/dbmodel.py b/src/cpl/database/database_model.py
similarity index 51%
rename from src/sh_edraft/database/model/dbmodel.py
rename to src/cpl/database/database_model.py
index 145da02b..7c2a8228 100644
--- a/src/sh_edraft/database/model/dbmodel.py
+++ b/src/cpl/database/database_model.py
@@ -1,3 +1,3 @@
from sqlalchemy.ext.declarative import declarative_base
-DBModel: declarative_base = declarative_base()
+DatabaseModel: declarative_base = declarative_base()
diff --git a/src/sh_edraft/database/model/database_settings.py b/src/cpl/database/database_settings.py
similarity index 54%
rename from src/sh_edraft/database/model/database_settings.py
rename to src/cpl/database/database_settings.py
index aed39e5f..130fc78c 100644
--- a/src/sh_edraft/database/model/database_settings.py
+++ b/src/cpl/database/database_settings.py
@@ -1,35 +1,44 @@
import traceback
from typing import Optional
-from sh_edraft.configuration.base.configuration_model_base import ConfigurationModelBase
-from sh_edraft.database.model.database_settings_name import DatabaseSettingsName
-from sh_edraft.console.console import Console
-from sh_edraft.console.model.foreground_color import ForegroundColor
+from cpl.configuration.configuration_model_abc import ConfigurationModelABC
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.database.database_settings_name_enum import DatabaseSettingsNameEnum
-class DatabaseSettings(ConfigurationModelBase):
+class DatabaseSettings(ConfigurationModelABC):
def __init__(self):
- ConfigurationModelBase.__init__(self)
+ ConfigurationModelABC.__init__(self)
+ self._auth_plugin: Optional[str] = None
self._connection_string: Optional[str] = None
self._credentials: Optional[str] = None
self._encoding: Optional[str] = None
self._case_sensitive: Optional[bool] = None
self._echo: Optional[bool] = None
-
+
+ @property
+ def auth_plugin(self) -> str:
+ return self._auth_plugin
+
+ @auth_plugin.setter
+ def auth_plugin(self, auth_plugin: str):
+ self._auth_plugin = auth_plugin
+
@property
def connection_string(self) -> str:
return self._connection_string
-
+
@connection_string.setter
def connection_string(self, connection_string: str):
self._connection_string = connection_string
-
+
@property
def credentials(self) -> str:
return self._credentials
-
+
@credentials.setter
def credentials(self, credentials: str):
self._credentials = credentials
@@ -60,19 +69,22 @@ class DatabaseSettings(ConfigurationModelBase):
def from_dict(self, settings: dict):
try:
- self._connection_string = settings[DatabaseSettingsName.connection_string.value]
- self._credentials = settings[DatabaseSettingsName.credentials.value]
+ self._connection_string = settings[DatabaseSettingsNameEnum.connection_string.value]
+ self._credentials = settings[DatabaseSettingsNameEnum.credentials.value]
- if DatabaseSettingsName.encoding.value in settings:
- self._encoding = settings[DatabaseSettingsName.encoding.value]
+ if DatabaseSettingsNameEnum.auth_plugin.value in settings:
+ self._auth_plugin = settings[DatabaseSettingsNameEnum.auth_plugin.value]
- if DatabaseSettingsName.case_sensitive.value in settings:
- self._case_sensitive = bool(settings[DatabaseSettingsName.case_sensitive.value])
+ if DatabaseSettingsNameEnum.encoding.value in settings:
+ self._encoding = settings[DatabaseSettingsNameEnum.encoding.value]
- if DatabaseSettingsName.echo.value in settings:
- self._echo = bool(settings[DatabaseSettingsName.echo.value])
+ if DatabaseSettingsNameEnum.case_sensitive.value in settings:
+ self._case_sensitive = bool(settings[DatabaseSettingsNameEnum.case_sensitive.value])
+
+ if DatabaseSettingsNameEnum.echo.value in settings:
+ self._echo = bool(settings[DatabaseSettingsNameEnum.echo.value])
except Exception as e:
- Console.set_foreground_color(ForegroundColor.red)
+ Console.set_foreground_color(ForegroundColorEnum.red)
Console.write_line(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings')
Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
- Console.set_foreground_color(ForegroundColor.default)
+ Console.set_foreground_color(ForegroundColorEnum.default)
diff --git a/src/sh_edraft/database/model/database_settings_name.py b/src/cpl/database/database_settings_name_enum.py
similarity index 72%
rename from src/sh_edraft/database/model/database_settings_name.py
rename to src/cpl/database/database_settings_name_enum.py
index 57ece941..5b532ba8 100644
--- a/src/sh_edraft/database/model/database_settings_name.py
+++ b/src/cpl/database/database_settings_name_enum.py
@@ -1,10 +1,11 @@
from enum import Enum
-class DatabaseSettingsName(Enum):
+class DatabaseSettingsNameEnum(Enum):
connection_string = 'ConnectionString'
credentials = 'Credentials'
encoding = 'Encoding'
case_sensitive = 'CaseSensitive'
echo = 'Echo'
+ auth_plugin = 'AuthPlugin'
diff --git a/src/cpl/dependency_injection/__init__.py b/src/cpl/dependency_injection/__init__.py
new file mode 100644
index 00000000..eecee040
--- /dev/null
+++ b/src/cpl/dependency_injection/__init__.py
@@ -0,0 +1,31 @@
+# -*- 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.dependency_injection'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .service_collection import ServiceCollection
+from .service_collection_abc import ServiceCollectionABC
+from .service_descriptor import ServiceDescriptor
+from .service_lifetime_enum import ServiceLifetimeEnum
+from .service_provider import ServiceProvider
+from .service_provider_abc import ServiceProviderABC
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl/dependency_injection/service_collection.py b/src/cpl/dependency_injection/service_collection.py
new file mode 100644
index 00000000..157a012c
--- /dev/null
+++ b/src/cpl/dependency_injection/service_collection.py
@@ -0,0 +1,70 @@
+from typing import Union, Type, Callable, Optional
+
+from cpl.configuration.configuration_abc import ConfigurationABC
+from cpl.database.database_settings import DatabaseSettings
+from cpl.database.context.database_context_abc import DatabaseContextABC
+from cpl.dependency_injection.service_provider_abc import ServiceProviderABC
+from cpl.dependency_injection.service_collection_abc import ServiceCollectionABC
+from cpl.dependency_injection.service_descriptor import ServiceDescriptor
+from cpl.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum
+from cpl.dependency_injection.service_provider import ServiceProvider
+from cpl.logging.logger_service import Logger
+from cpl.logging.logger_abc import LoggerABC
+from cpl.utils.credential_manager import CredentialManager
+
+
+class ServiceCollection(ServiceCollectionABC):
+
+ def __init__(self, config: ConfigurationABC):
+ ServiceCollectionABC.__init__(self)
+ self._configuration: ConfigurationABC = config
+
+ self._database_context: Optional[DatabaseContextABC] = None
+ self._service_descriptors: list[ServiceDescriptor] = []
+
+ def _add_descriptor(self, service: Union[type, object], lifetime: ServiceLifetimeEnum):
+ found = False
+ for descriptor in self._service_descriptors:
+ if isinstance(service, descriptor.service_type):
+ found = True
+
+ if found:
+ service_type = service
+ if not isinstance(service, type):
+ service_type = type(service)
+
+ raise Exception(f'Service of type {service_type} already exists')
+
+ self._service_descriptors.append(ServiceDescriptor(service, lifetime))
+
+ def add_db_context(self, db_context_type: Type[DatabaseContextABC], db_settings: DatabaseSettings):
+ self._database_context = db_context_type(db_settings)
+ self._database_context.connect(CredentialManager.build_string(db_settings.connection_string, db_settings.credentials))
+
+ def add_logging(self):
+ self.add_singleton(LoggerABC, Logger)
+
+ def add_singleton(self, service_type: Union[type, object], service: Union[type, object] = None):
+ impl = None
+ if service is not None:
+ if isinstance(service, type):
+ impl = self.build_service_provider().build_service(service)
+
+ self._add_descriptor(impl, ServiceLifetimeEnum.singleton)
+ else:
+ if isinstance(service_type, type):
+ impl = self.build_service_provider().build_service(service_type)
+
+ self._add_descriptor(impl, ServiceLifetimeEnum.singleton)
+
+ def add_scoped(self, service_type: Type, service: Callable = None):
+ raise Exception('Not implemented')
+
+ def add_transient(self, service_type: Union[type], service: Union[type] = None):
+ if service is not None:
+ self._add_descriptor(service, ServiceLifetimeEnum.transient)
+ else:
+ self._add_descriptor(service_type, ServiceLifetimeEnum.transient)
+
+ def build_service_provider(self) -> ServiceProviderABC:
+ return ServiceProvider(self._service_descriptors, self._configuration, self._database_context)
diff --git a/src/cpl/dependency_injection/service_collection_abc.py b/src/cpl/dependency_injection/service_collection_abc.py
new file mode 100644
index 00000000..c77ac6b6
--- /dev/null
+++ b/src/cpl/dependency_injection/service_collection_abc.py
@@ -0,0 +1,71 @@
+from abc import abstractmethod, ABC
+from collections import Callable
+from typing import Type
+
+from cpl.database.database_settings import DatabaseSettings
+from cpl.database.context.database_context_abc import DatabaseContextABC
+from cpl.dependency_injection.service_provider_abc import ServiceProviderABC
+
+
+class ServiceCollectionABC(ABC):
+
+ @abstractmethod
+ def __init__(self):
+ """
+ ABC for service providing
+ """
+ pass
+
+ @abstractmethod
+ def add_db_context(self, db_context: Type[DatabaseContextABC], db_settings: DatabaseSettings):
+ """
+ Adds database context
+ :param db_context:
+ :param db_settings:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def add_logging(self):
+ """
+ Adds the CPL internal logger
+ """
+ pass
+
+ @abstractmethod
+ def add_transient(self, service_type: Type, service: Callable = None):
+ """
+ Adds a service with transient lifetime
+ :param service_type:
+ :param service:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def add_scoped(self, service_type: Type, service: Callable = None):
+ """
+ Adds a service with scoped lifetime
+ :param service_type:
+ :param service:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def add_singleton(self, service_type: Type, service: Callable = None):
+ """
+ Adds a service with singleton lifetime
+ :param service_type:
+ :param service:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def build_service_provider(self) -> ServiceProviderABC:
+ """
+ Creates instance of the service provider
+ """
+ pass
diff --git a/src/cpl/dependency_injection/service_descriptor.py b/src/cpl/dependency_injection/service_descriptor.py
new file mode 100644
index 00000000..845089ac
--- /dev/null
+++ b/src/cpl/dependency_injection/service_descriptor.py
@@ -0,0 +1,33 @@
+from typing import Union, Optional
+
+from cpl.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum
+
+
+class ServiceDescriptor:
+
+ def __init__(self, implementation: Union[type, Optional[object]], lifetime: ServiceLifetimeEnum):
+
+ self._service_type = implementation
+ self._implementation = implementation
+ self._lifetime = lifetime
+
+ if not isinstance(implementation, type):
+ self._service_type = type(implementation)
+ else:
+ self._implementation = None
+
+ @property
+ def service_type(self) -> type:
+ return self._service_type
+
+ @property
+ def implementation(self) -> Union[type, Optional[object]]:
+ return self._implementation
+
+ @implementation.setter
+ def implementation(self, implementation: Union[type, Optional[object]]):
+ self._implementation = implementation
+
+ @property
+ def lifetime(self) -> ServiceLifetimeEnum:
+ return self._lifetime
diff --git a/src/cpl/dependency_injection/service_lifetime_enum.py b/src/cpl/dependency_injection/service_lifetime_enum.py
new file mode 100644
index 00000000..c2057ba8
--- /dev/null
+++ b/src/cpl/dependency_injection/service_lifetime_enum.py
@@ -0,0 +1,8 @@
+from enum import Enum
+
+
+class ServiceLifetimeEnum(Enum):
+
+ singleton = 0
+ scoped = 1 # not supported yet
+ transient = 2
diff --git a/src/cpl/dependency_injection/service_provider.py b/src/cpl/dependency_injection/service_provider.py
new file mode 100644
index 00000000..c4c8b2df
--- /dev/null
+++ b/src/cpl/dependency_injection/service_provider.py
@@ -0,0 +1,90 @@
+from collections import Callable
+from inspect import signature, Parameter
+from typing import Optional
+
+from cpl.configuration.configuration_abc import ConfigurationABC
+from cpl.configuration.configuration_model_abc import ConfigurationModelABC
+from cpl.database.context.database_context_abc import DatabaseContextABC
+from cpl.dependency_injection.service_provider_abc import ServiceProviderABC
+from cpl.dependency_injection.service_descriptor import ServiceDescriptor
+from cpl.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum
+from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
+
+
+class ServiceProvider(ServiceProviderABC):
+
+ def __init__(self, service_descriptors: list[ServiceDescriptor], config: ConfigurationABC, db_context: Optional[DatabaseContextABC]):
+ ServiceProviderABC.__init__(self)
+
+ self._service_descriptors: list[ServiceDescriptor] = service_descriptors
+ self._configuration: ConfigurationABC = config
+ self._database_context = db_context
+
+ def _find_service(self, service_type: type) -> [ServiceDescriptor]:
+ for descriptor in self._service_descriptors:
+ if descriptor.service_type == service_type or issubclass(descriptor.service_type, service_type):
+ return descriptor
+
+ return None
+
+ def _get_service(self, parameter: Parameter) -> object:
+ for descriptor in self._service_descriptors:
+ if descriptor.service_type == parameter.annotation or issubclass(descriptor.service_type, parameter.annotation):
+ if descriptor.implementation is not None:
+ return descriptor.implementation
+
+ implementation = self.build_service(descriptor.service_type)
+ if descriptor.lifetime == ServiceLifetimeEnum.singleton:
+ descriptor.implementation = implementation
+
+ return implementation
+
+ def build_service(self, service_type: type) -> object:
+ for descriptor in self._service_descriptors:
+ if descriptor.service_type == service_type or issubclass(descriptor.service_type, service_type):
+ if descriptor.implementation is not None:
+ service_type = type(descriptor.implementation)
+ else:
+ service_type = descriptor.service_type
+
+ break
+
+ sig = signature(service_type.__init__)
+ params = []
+ for param in sig.parameters.items():
+ parameter = param[1]
+ if parameter.name != 'self' and parameter.annotation != Parameter.empty:
+ if issubclass(parameter.annotation, ServiceProviderABC):
+ params.append(self)
+
+ elif issubclass(parameter.annotation, ApplicationEnvironmentABC):
+ params.append(self._configuration.environment)
+
+ elif issubclass(parameter.annotation, DatabaseContextABC):
+ params.append(self._database_context)
+
+ elif issubclass(parameter.annotation, ConfigurationModelABC):
+ params.append(self._configuration.get_configuration(parameter.annotation))
+
+ elif issubclass(parameter.annotation, ConfigurationABC):
+ params.append(self._configuration)
+
+ else:
+ params.append(self._get_service(parameter))
+
+ return service_type(*params)
+
+ def get_service(self, service_type: type) -> Optional[Callable[object]]:
+ result = self._find_service(service_type)
+
+ if result is None:
+ return None
+
+ if result.implementation is not None:
+ return result.implementation
+
+ implementation = self.build_service(service_type)
+ if result.lifetime == ServiceLifetimeEnum.singleton:
+ result.implementation = implementation
+
+ return implementation
diff --git a/src/cpl/dependency_injection/service_provider_abc.py b/src/cpl/dependency_injection/service_provider_abc.py
new file mode 100644
index 00000000..042b0355
--- /dev/null
+++ b/src/cpl/dependency_injection/service_provider_abc.py
@@ -0,0 +1,31 @@
+from abc import abstractmethod, ABC
+from collections import Callable
+from typing import Type, Optional
+
+
+class ServiceProviderABC(ABC):
+
+ @abstractmethod
+ def __init__(self):
+ """
+ ABC for service providing
+ """
+ pass
+
+ @abstractmethod
+ def build_service(self, service_type: type) -> object:
+ """
+ Creates instance of given type
+ :param service_type:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def get_service(self, instance_type: Type) -> Optional[Callable[object]]:
+ """
+ Returns instance of given type
+ :param instance_type:
+ :return:
+ """
+ pass
diff --git a/src/cpl/environment/__init__.py b/src/cpl/environment/__init__.py
new file mode 100644
index 00000000..078ab0bc
--- /dev/null
+++ b/src/cpl/environment/__init__.py
@@ -0,0 +1,28 @@
+# -*- 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.environment'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .application_environment_abc import ApplicationEnvironmentABC
+from .environment_name_enum import EnvironmentNameEnum
+from .application_environment import ApplicationEnvironment
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl/environment/application_environment.py b/src/cpl/environment/application_environment.py
new file mode 100644
index 00000000..7bb76f13
--- /dev/null
+++ b/src/cpl/environment/application_environment.py
@@ -0,0 +1,98 @@
+import pathlib
+from datetime import datetime
+from socket import gethostname
+from typing import Optional
+
+from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
+from cpl.environment.environment_name_enum import EnvironmentNameEnum
+
+
+class ApplicationEnvironment(ApplicationEnvironmentABC):
+
+ def __init__(self, name: EnvironmentNameEnum = EnvironmentNameEnum.production, crp: str = './'):
+ """
+ Represents environment of the application
+ :param name:
+ :param crp:
+ """
+ ApplicationEnvironmentABC.__init__(self)
+
+ self._environment_name: Optional[EnvironmentNameEnum] = name
+ self._app_name: Optional[str] = None
+ self._customer: Optional[str] = None
+ self._content_root_path: Optional[str] = crp
+
+ self._start_time: datetime = datetime.now()
+ self._end_time: datetime = datetime.now()
+ self._working_directory = pathlib.Path().absolute()
+ self._runtime_directory = pathlib.Path(__file__).parent.absolute()
+
+ @property
+ def environment_name(self) -> str:
+ return str(self._environment_name.value)
+
+ @environment_name.setter
+ def environment_name(self, environment_name: str):
+ self._environment_name = EnvironmentNameEnum(environment_name)
+
+ @property
+ def application_name(self) -> str:
+ return self._app_name if self._app_name is not None else ''
+
+ @application_name.setter
+ def application_name(self, application_name: str):
+ self._app_name = application_name
+
+ @property
+ def customer(self) -> str:
+ return self._customer if self._customer is not None else ''
+
+ @customer.setter
+ def customer(self, customer: str):
+ self._customer = customer
+
+ @property
+ def content_root_path(self) -> str:
+ return self._content_root_path
+
+ @content_root_path.setter
+ def content_root_path(self, content_root_path: str):
+ self._content_root_path = content_root_path
+
+ @property
+ def host_name(self):
+ return gethostname()
+
+ @property
+ def start_time(self) -> datetime:
+ return self._start_time
+
+ @property
+ def end_time(self) -> datetime:
+ return self._end_time
+
+ @end_time.setter
+ def end_time(self, end_time: datetime):
+ self._end_time = end_time
+
+ @property
+ def date_time_now(self) -> datetime:
+ return datetime.now()
+
+ @property
+ def working_directory(self) -> str:
+ return self._working_directory
+
+ def set_working_directory(self, path: str = ''):
+ if path != '':
+ self._working_directory = path
+ return
+
+ self._working_directory = pathlib.Path().absolute()
+
+ @property
+ def runtime_directory(self) -> str:
+ return self._runtime_directory
+
+ def set_runtime_directory(self, file: str):
+ self._runtime_directory = pathlib.Path(file).parent.absolute()
diff --git a/src/cpl/environment/application_environment_abc.py b/src/cpl/environment/application_environment_abc.py
new file mode 100644
index 00000000..c306f53f
--- /dev/null
+++ b/src/cpl/environment/application_environment_abc.py
@@ -0,0 +1,85 @@
+from abc import ABC, abstractmethod
+from datetime import datetime
+
+
+class ApplicationEnvironmentABC(ABC):
+
+ @abstractmethod
+ def __init__(self):
+ """
+ ABC of application environment
+ """
+ pass
+
+ @property
+ @abstractmethod
+ def environment_name(self) -> str: pass
+
+ @environment_name.setter
+ @abstractmethod
+ def environment_name(self, environment_name: str): pass
+
+ @property
+ @abstractmethod
+ def application_name(self) -> str: pass
+
+ @application_name.setter
+ @abstractmethod
+ def application_name(self, application_name: str): pass
+
+ @property
+ @abstractmethod
+ def customer(self) -> str: pass
+
+ @customer.setter
+ @abstractmethod
+ def customer(self, customer: str): pass
+
+ @property
+ @abstractmethod
+ def content_root_path(self) -> str: pass
+
+ @content_root_path.setter
+ @abstractmethod
+ def content_root_path(self, content_root_path: str): pass
+
+ @property
+ @abstractmethod
+ def host_name(self) -> str: pass
+
+ @property
+ @abstractmethod
+ def start_time(self) -> datetime: pass
+
+ @start_time.setter
+ @abstractmethod
+ def start_time(self, start_time: datetime): pass
+
+ @property
+ @abstractmethod
+ def end_time(self): pass
+
+ @end_time.setter
+ @abstractmethod
+ def end_time(self, end_time: datetime): pass
+
+ @property
+ @abstractmethod
+ def date_time_now(self) -> datetime: pass
+
+ @property
+ @abstractmethod
+ def working_directory(self) -> str: pass
+
+ @property
+ @abstractmethod
+ def runtime_directory(self) -> str: pass
+
+ @abstractmethod
+ def set_runtime_directory(self, runtime_directory: str):
+ """
+ Sets the current runtime directory
+ :param runtime_directory:
+ :return:
+ """
+ pass
diff --git a/src/sh_edraft/environment/model/environment_name.py b/src/cpl/environment/environment_name_enum.py
similarity index 80%
rename from src/sh_edraft/environment/model/environment_name.py
rename to src/cpl/environment/environment_name_enum.py
index 18abcbb5..8ff90237 100644
--- a/src/sh_edraft/environment/model/environment_name.py
+++ b/src/cpl/environment/environment_name_enum.py
@@ -1,7 +1,7 @@
from enum import Enum
-class EnvironmentName(Enum):
+class EnvironmentNameEnum(Enum):
production = 'production'
staging = 'staging'
diff --git a/src/cpl/logging/__init__.py b/src/cpl/logging/__init__.py
new file mode 100644
index 00000000..d2fbfadf
--- /dev/null
+++ b/src/cpl/logging/__init__.py
@@ -0,0 +1,30 @@
+# -*- 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.logging'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .logger_service import Logger
+from .logger_abc import LoggerABC
+from .logging_level_enum import LoggingLevelEnum
+from .logging_settings import LoggingSettings
+from .logging_settings_name_enum import LoggingSettingsNameEnum
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl/logging/logger_abc.py b/src/cpl/logging/logger_abc.py
new file mode 100644
index 00000000..98ef4eb9
--- /dev/null
+++ b/src/cpl/logging/logger_abc.py
@@ -0,0 +1,82 @@
+from abc import abstractmethod, ABC
+
+
+class LoggerABC(ABC):
+
+ @abstractmethod
+ def __init__(self):
+ """
+ ABC for logging
+ """
+ ABC.__init__(self)
+
+ @abstractmethod
+ def header(self, string: str):
+ """
+ Writes a header message
+ :param string:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def trace(self, name: str, message: str):
+ """
+ Writes a trace message
+ :param name:
+ :param message:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def debug(self, name: str, message: str):
+ """
+ Writes a debug message
+ :param name:
+ :param message:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def info(self, name: str, message: str):
+ """
+ Writes an information
+ :param name:
+ :param message:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def warn(self, name: str, message: str):
+ """
+ Writes an warning
+ :param name:
+ :param message:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def error(self, name: str, message: str, ex: Exception = None):
+ """
+ Writes an error
+ :param name:
+ :param message:
+ :param ex:
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def fatal(self, name: str, message: str, ex: Exception = None):
+ """
+ Writes an error and exits
+ :param name:
+ :param message:
+ :param ex:
+ :return:
+ """
+ pass
diff --git a/src/cpl/logging/logger_service.py b/src/cpl/logging/logger_service.py
new file mode 100644
index 00000000..4c04a5d2
--- /dev/null
+++ b/src/cpl/logging/logger_service.py
@@ -0,0 +1,233 @@
+import datetime
+import os
+import traceback
+from string import Template
+
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
+from cpl.logging.logger_abc import LoggerABC
+from cpl.logging.logging_level_enum import LoggingLevelEnum
+from cpl.logging.logging_settings import LoggingSettings
+from cpl.time.time_format_settings import TimeFormatSettings
+
+
+class Logger(LoggerABC):
+
+ def __init__(self, logging_settings: LoggingSettings, time_format: TimeFormatSettings, env: ApplicationEnvironmentABC):
+ """
+ Service for logging
+ :param logging_settings:
+ :param time_format:
+ :param app_runtime:
+ """
+ LoggerABC.__init__(self)
+
+ self._env = env
+ self._log_settings: LoggingSettings = logging_settings
+ self._time_format_settings: TimeFormatSettings = time_format
+
+ self._log = Template(self._log_settings.filename).substitute(
+ date_time_now=self._env.date_time_now.strftime(self._time_format_settings.date_time_format),
+ start_time=self._env.start_time.strftime(self._time_format_settings.date_time_log_format)
+ )
+ self._path = self._log_settings.path
+ self._level = self._log_settings.level
+ self._console = self._log_settings.console
+
+ self.create()
+
+ def _get_datetime_now(self) -> str:
+ """
+ Returns the date and time by given format
+ :return:
+ """
+ try:
+ return datetime.datetime.now().strftime(self._time_format_settings.date_time_format)
+ except Exception as e:
+ self.error(__name__, 'Cannot get time', ex=e)
+
+ def _get_date(self) -> str:
+ """
+ Returns the date by given format
+ :return:
+ """
+ try:
+ return datetime.datetime.now().strftime(self._time_format_settings.date_format)
+ except Exception as e:
+ self.error(__name__, 'Cannot get date', ex=e)
+
+ def create(self) -> None:
+ """
+ Creates path tree and logfile
+ :return:
+ """
+
+ """ path """
+ try:
+ # check if log file path exists
+ if not os.path.exists(self._path):
+ os.makedirs(self._path)
+ except Exception as e:
+ self._fatal_console(__name__, 'Cannot create log dir', ex=e)
+
+ """ create new log file """
+ try:
+ # open log file, create if not exists
+ path = f'{self._path}{self._log}'
+ f = open(path, "w+")
+ Console.write_line(f'[{__name__}]: Using log file: {path}')
+ f.close()
+ except Exception as e:
+ self._fatal_console(__name__, 'Cannot open log file', ex=e)
+
+ def _append_log(self, string):
+ """
+ Writes to logfile
+ :param string:
+ :return:
+ """
+ try:
+ # open log file and append always
+ if not os.path.isdir(self._path):
+ self._fatal_console(__name__, 'Log directory not found')
+
+ with open(self._path + self._log, "a+", encoding="utf-8") as f:
+ f.write(string + '\n')
+ f.close()
+ except Exception as e:
+ self._fatal_console(__name__, f'Cannot append log file, message: {string}', ex=e)
+
+ def _get_string(self, name: str, level: LoggingLevelEnum, message: str) -> str:
+ """
+ Returns input as log entry format
+ :param name:
+ :param level:
+ :param message:
+ :return:
+ """
+ log_level = level.name
+ return f'<{self._get_datetime_now()}> [ {log_level} ] [ {name} ]: {message}'
+
+ def header(self, string: str):
+ # append log and print message
+ self._append_log(string)
+ Console.set_foreground_color(ForegroundColorEnum.default)
+ Console.write_line(string)
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ def trace(self, name: str, message: str):
+ output = self._get_string(name, LoggingLevelEnum.TRACE, message)
+
+ # check if message can be written to log
+ if self._level.value >= LoggingLevelEnum.TRACE.value:
+ self._append_log(output)
+
+ # check if message can be shown in console_old
+ if self._console.value >= LoggingLevelEnum.TRACE.value:
+ Console.set_foreground_color(ForegroundColorEnum.green)
+ Console.write_line(output)
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ def debug(self, name: str, message: str):
+ output = self._get_string(name, LoggingLevelEnum.DEBUG, message)
+
+ # check if message can be written to log
+ if self._level.value >= LoggingLevelEnum.DEBUG.value:
+ self._append_log(output)
+
+ # check if message can be shown in console_old
+ if self._console.value >= LoggingLevelEnum.DEBUG.value:
+ Console.set_foreground_color(ForegroundColorEnum.green)
+ Console.write_line(output)
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ def info(self, name: str, message: str):
+ output = self._get_string(name, LoggingLevelEnum.INFO, message)
+
+ # check if message can be written to log
+ if self._level.value >= LoggingLevelEnum.INFO.value:
+ self._append_log(output)
+
+ # check if message can be shown in console_old
+ if self._console.value >= LoggingLevelEnum.INFO.value:
+ Console.set_foreground_color(ForegroundColorEnum.green)
+ Console.write_line(output)
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ def warn(self, name: str, message: str):
+ output = self._get_string(name, LoggingLevelEnum.WARN, message)
+
+ # check if message can be written to log
+ if self._level.value >= LoggingLevelEnum.WARN.value:
+ self._append_log(output)
+
+ # check if message can be shown in console_old
+ if self._console.value >= LoggingLevelEnum.WARN.value:
+ Console.set_foreground_color(ForegroundColorEnum.yellow)
+ Console.write_line(output)
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ def error(self, name: str, message: str, ex: Exception = None):
+ output = ''
+ if ex is not None:
+ tb = traceback.format_exc()
+ self.error(name, message)
+ output = self._get_string(name, LoggingLevelEnum.ERROR, f'{ex} -> {tb}')
+ else:
+ output = self._get_string(name, LoggingLevelEnum.ERROR, message)
+
+ # check if message can be written to log
+ if self._level.value >= LoggingLevelEnum.ERROR.value:
+ self._append_log(output)
+
+ # check if message can be shown in console_old
+ if self._console.value >= LoggingLevelEnum.ERROR.value:
+ Console.set_foreground_color(ForegroundColorEnum.red)
+ Console.write_line(output)
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ def fatal(self, name: str, message: str, ex: Exception = None):
+ output = ''
+ if ex is not None:
+ tb = traceback.format_exc()
+ self.error(name, message)
+ output = self._get_string(name, LoggingLevelEnum.FATAL, f'{ex} -> {tb}')
+ else:
+ output = self._get_string(name, LoggingLevelEnum.FATAL, message)
+
+ # check if message can be written to log
+ if self._level.value >= LoggingLevelEnum.FATAL.value:
+ self._append_log(output)
+
+ # check if message can be shown in console_old
+ if self._console.value >= LoggingLevelEnum.FATAL.value:
+ Console.set_foreground_color(ForegroundColorEnum.red)
+ Console.write_line(output)
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ exit()
+
+ def _fatal_console(self, name: str, message: str, ex: Exception = None):
+ """
+ Writes an error to console only
+ :param name:
+ :param message:
+ :param ex:
+ :return:
+ """
+ output = ''
+ if ex is not None:
+ tb = traceback.format_exc()
+ self.error(name, message)
+ output = self._get_string(name, LoggingLevelEnum.ERROR, f'{ex} -> {tb}')
+ else:
+ output = self._get_string(name, LoggingLevelEnum.ERROR, message)
+
+ # check if message can be shown in console_old
+ if self._console.value >= LoggingLevelEnum.FATAL.value:
+ Console.set_foreground_color(ForegroundColorEnum.red)
+ Console.write_line(output)
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ exit()
diff --git a/src/sh_edraft/logging/model/logging_level.py b/src/cpl/logging/logging_level_enum.py
similarity index 91%
rename from src/sh_edraft/logging/model/logging_level.py
rename to src/cpl/logging/logging_level_enum.py
index ceb7b4c7..f9b6259b 100644
--- a/src/sh_edraft/logging/model/logging_level.py
+++ b/src/cpl/logging/logging_level_enum.py
@@ -1,7 +1,7 @@
from enum import Enum
-class LoggingLevel(Enum):
+class LoggingLevelEnum(Enum):
OFF = 0 # Nothing
FATAL = 1 # Error that cause exit
diff --git a/src/cpl/logging/logging_settings.py b/src/cpl/logging/logging_settings.py
new file mode 100644
index 00000000..20f87650
--- /dev/null
+++ b/src/cpl/logging/logging_settings.py
@@ -0,0 +1,62 @@
+import traceback
+from typing import Optional
+
+from cpl.configuration.configuration_model_abc import ConfigurationModelABC
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.logging.logging_level_enum import LoggingLevelEnum
+from cpl.logging.logging_settings_name_enum import LoggingSettingsNameEnum
+
+
+class LoggingSettings(ConfigurationModelABC):
+
+ def __init__(self):
+ ConfigurationModelABC.__init__(self)
+ self._path: Optional[str] = None
+ self._filename: Optional[str] = None
+ self._console: Optional[LoggingLevelEnum] = None
+ self._level: Optional[LoggingLevelEnum] = None
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @path.setter
+ def path(self, path: str) -> None:
+ self._path = path
+
+ @property
+ def filename(self) -> str:
+ return self._filename
+
+ @filename.setter
+ def filename(self, filename: str) -> None:
+ self._filename = filename
+
+ @property
+ def console(self) -> LoggingLevelEnum:
+ return self._console
+
+ @console.setter
+ def console(self, console: LoggingLevelEnum) -> None:
+ self._console = console
+
+ @property
+ def level(self) -> LoggingLevelEnum:
+ return self._level
+
+ @level.setter
+ def level(self, level: LoggingLevelEnum) -> None:
+ self._level = level
+
+ def from_dict(self, settings: dict):
+ try:
+ self._path = settings[LoggingSettingsNameEnum.path.value]
+ self._filename = settings[LoggingSettingsNameEnum.filename.value]
+ self._console = LoggingLevelEnum[settings[LoggingSettingsNameEnum.console_level.value]]
+ self._level = LoggingLevelEnum[settings[LoggingSettingsNameEnum.file_level.value]]
+ except Exception as e:
+ Console.set_foreground_color(ForegroundColorEnum.red)
+ Console.write_line(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings')
+ Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
+ Console.set_foreground_color(ForegroundColorEnum.default)
diff --git a/src/sh_edraft/logging/model/logging_settings_name.py b/src/cpl/logging/logging_settings_name_enum.py
similarity index 78%
rename from src/sh_edraft/logging/model/logging_settings_name.py
rename to src/cpl/logging/logging_settings_name_enum.py
index 323e5735..3b682428 100644
--- a/src/sh_edraft/logging/model/logging_settings_name.py
+++ b/src/cpl/logging/logging_settings_name_enum.py
@@ -1,7 +1,7 @@
from enum import Enum
-class LoggingSettingsName(Enum):
+class LoggingSettingsNameEnum(Enum):
path = 'Path'
filename = 'Filename'
diff --git a/src/cpl/mailing/__init__.py b/src/cpl/mailing/__init__.py
new file mode 100644
index 00000000..bbce7c2f
--- /dev/null
+++ b/src/cpl/mailing/__init__.py
@@ -0,0 +1,30 @@
+# -*- 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.mailing'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .email import EMail
+from .email_client_service import EMailClient
+from .email_client_abc import EMailClientABC
+from .email_client_settings import EMailClientSettings
+from .email_client_settings_name_enum import EMailClientSettingsNameEnum
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/sh_edraft/mailing/model/email.py b/src/cpl/mailing/email.py
similarity index 80%
rename from src/sh_edraft/mailing/model/email.py
rename to src/cpl/mailing/email.py
index de49639d..d204c070 100644
--- a/src/sh_edraft/mailing/model/email.py
+++ b/src/cpl/mailing/email.py
@@ -4,6 +4,14 @@ import re
class EMail:
def __init__(self, header: list[str] = None, subject: str = None, body: str = None, transceiver: str = None, receiver: list[str] = None):
+ """
+ Represents an email
+ :param header:
+ :param subject:
+ :param body:
+ :param transceiver:
+ :param receiver:
+ """
self._header: list[str] = header
self._subject: str = subject
@@ -65,15 +73,30 @@ class EMail:
@staticmethod
def check_mail(address: str) -> bool:
+ """
+ Checks if an email is valid
+ :param address:
+ :return:
+ """
return bool(re.search('^\\w+([.-]?\\w+)*@\\w+([.-]?\\w+)*(.\\w{2,3})+$', address))
def add_header(self, header: str):
+ """
+ Adds header
+ :param header:
+ :return:
+ """
if self._header is None:
self._header = []
self._header.append(header)
def add_receiver(self, receiver: str):
+ """
+ Adds receiver
+ :param receiver:
+ :return:
+ """
if self._receiver is None:
self._receiver = []
@@ -83,4 +106,9 @@ class EMail:
raise Exception(f'Invalid email: {receiver}')
def get_content(self, transceiver: str):
+ """
+ Returns the mail as string
+ :param transceiver:
+ :return:
+ """
return str(f'From: {transceiver}\r\nTo: {self.receiver}\r\n{self.header}\r\nSubject: {self.subject}\r\n{self.body}').encode('utf-8')
diff --git a/src/cpl/mailing/email_client_abc.py b/src/cpl/mailing/email_client_abc.py
new file mode 100644
index 00000000..29690394
--- /dev/null
+++ b/src/cpl/mailing/email_client_abc.py
@@ -0,0 +1,30 @@
+from abc import abstractmethod, ABC
+
+from cpl.mailing.email import EMail
+
+
+class EMailClientABC(ABC):
+
+ @abstractmethod
+ def __init__(self):
+ """
+ ABC to send emails
+ """
+ ABC.__init__(self)
+
+ @abstractmethod
+ def connect(self):
+ """
+ Connects to server
+ :return:
+ """
+ pass
+
+ @abstractmethod
+ def send_mail(self, email: EMail):
+ """
+ Sends email
+ :param email:
+ :return:
+ """
+ pass
diff --git a/src/sh_edraft/mailing/email_client.py b/src/cpl/mailing/email_client_service.py
similarity index 77%
rename from src/sh_edraft/mailing/email_client.py
rename to src/cpl/mailing/email_client_service.py
index cc6296ee..170489ff 100644
--- a/src/sh_edraft/mailing/email_client.py
+++ b/src/cpl/mailing/email_client_service.py
@@ -2,19 +2,24 @@ import ssl
from smtplib import SMTP
from typing import Optional
-from sh_edraft.environment.base.environment_base import EnvironmentBase
-from sh_edraft.logging.base.logger_base import LoggerBase
-from sh_edraft.mailing.base.email_client_base import EMailClientBase
-from sh_edraft.mailing.model.email import EMail
-from sh_edraft.mailing.model.email_client_settings import EMailClientSettings
-from sh_edraft.service.base.service_base import ServiceBase
-from sh_edraft.utils.credential_manager import CredentialManager
+from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
+from cpl.logging.logger_abc import LoggerABC
+from cpl.mailing.email import EMail
+from cpl.mailing.email_client_abc import EMailClientABC
+from cpl.mailing.email_client_settings import EMailClientSettings
+from cpl.utils.credential_manager import CredentialManager
-class EMailClient(EMailClientBase):
+class EMailClient(EMailClientABC):
- def __init__(self, environment: EnvironmentBase, logger: LoggerBase, mail_settings: EMailClientSettings):
- ServiceBase.__init__(self)
+ def __init__(self, environment: ApplicationEnvironmentABC, logger: LoggerABC, mail_settings: EMailClientSettings):
+ """
+ Service to send emails
+ :param environment:
+ :param logger:
+ :param mail_settings:
+ """
+ EMailClientABC.__init__(self)
self._environment = environment
self._mail_settings = mail_settings
@@ -25,6 +30,10 @@ class EMailClient(EMailClientBase):
self.create()
def create(self):
+ """
+ Creates connection
+ :return:
+ """
self._logger.trace(__name__, f'Started {__name__}.create')
self.connect()
self._logger.trace(__name__, f'Stopped {__name__}.create')
@@ -45,6 +54,10 @@ class EMailClient(EMailClientBase):
self._logger.trace(__name__, f'Stopped {__name__}.connect')
def login(self):
+ """
+ Login to server
+ :return:
+ """
self._logger.trace(__name__, f'Started {__name__}.login')
try:
self._logger.debug(__name__, f'Try to login {self._mail_settings.user_name}@{self._mail_settings.host}:{self._mail_settings.port}')
diff --git a/src/sh_edraft/mailing/model/email_client_settings.py b/src/cpl/mailing/email_client_settings.py
similarity index 68%
rename from src/sh_edraft/mailing/model/email_client_settings.py
rename to src/cpl/mailing/email_client_settings.py
index d9755919..3c75f1e8 100644
--- a/src/sh_edraft/mailing/model/email_client_settings.py
+++ b/src/cpl/mailing/email_client_settings.py
@@ -1,14 +1,14 @@
import traceback
-from sh_edraft.configuration.base.configuration_model_base import ConfigurationModelBase
-from sh_edraft.console.console import Console
-from sh_edraft.mailing.model.email_client_settings_name import EMailClientSettingsName
+from cpl.configuration.configuration_model_abc import ConfigurationModelABC
+from cpl.console.console import Console
+from cpl.mailing.email_client_settings_name_enum import EMailClientSettingsNameEnum
-class EMailClientSettings(ConfigurationModelBase):
+class EMailClientSettings(ConfigurationModelABC):
def __init__(self):
- ConfigurationModelBase.__init__(self)
+ ConfigurationModelABC.__init__(self)
self._host: str = ''
self._port: int = 0
@@ -49,10 +49,10 @@ class EMailClientSettings(ConfigurationModelBase):
def from_dict(self, settings: dict):
try:
- self._host = settings[EMailClientSettingsName.host.value]
- self._port = settings[EMailClientSettingsName.port.value]
- self._user_name = settings[EMailClientSettingsName.user_name.value]
- self._credentials = settings[EMailClientSettingsName.credentials.value]
+ self._host = settings[EMailClientSettingsNameEnum.host.value]
+ self._port = settings[EMailClientSettingsNameEnum.port.value]
+ self._user_name = settings[EMailClientSettingsNameEnum.user_name.value]
+ self._credentials = settings[EMailClientSettingsNameEnum.credentials.value]
except Exception as e:
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings')
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
diff --git a/src/sh_edraft/mailing/model/email_client_settings_name.py b/src/cpl/mailing/email_client_settings_name_enum.py
similarity index 74%
rename from src/sh_edraft/mailing/model/email_client_settings_name.py
rename to src/cpl/mailing/email_client_settings_name_enum.py
index 665c64b6..782abdd2 100644
--- a/src/sh_edraft/mailing/model/email_client_settings_name.py
+++ b/src/cpl/mailing/email_client_settings_name_enum.py
@@ -1,7 +1,7 @@
from enum import Enum
-class EMailClientSettingsName(Enum):
+class EMailClientSettingsNameEnum(Enum):
host = 'Host'
port = 'Port'
diff --git a/src/cpl/time/__init__.py b/src/cpl/time/__init__.py
new file mode 100644
index 00000000..e6e22b6a
--- /dev/null
+++ b/src/cpl/time/__init__.py
@@ -0,0 +1,27 @@
+# -*- 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.time'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .time_format_settings import TimeFormatSettings
+from .time_format_settings_names_enum import TimeFormatSettingsNamesEnum
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/sh_edraft/time/model/time_format_settings.py b/src/cpl/time/time_format_settings.py
similarity index 73%
rename from src/sh_edraft/time/model/time_format_settings.py
rename to src/cpl/time/time_format_settings.py
index e4be7511..f3f2d9d2 100644
--- a/src/sh_edraft/time/model/time_format_settings.py
+++ b/src/cpl/time/time_format_settings.py
@@ -1,16 +1,16 @@
import traceback
from typing import Optional
-from sh_edraft.configuration.base.configuration_model_base import ConfigurationModelBase
-from sh_edraft.time.model.time_format_settings_names import TimeFormatSettingsNames
-from sh_edraft.console.console import Console
-from sh_edraft.console.model.foreground_color import ForegroundColor
+from cpl.configuration.configuration_model_abc import ConfigurationModelABC
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.time.time_format_settings_names_enum import TimeFormatSettingsNamesEnum
-class TimeFormatSettings(ConfigurationModelBase):
+class TimeFormatSettings(ConfigurationModelABC):
def __init__(self):
- ConfigurationModelBase.__init__(self)
+ ConfigurationModelABC.__init__(self)
self._date_format: Optional[str] = None
self._time_format: Optional[str] = None
self._date_time_format: Optional[str] = None
@@ -50,12 +50,12 @@ class TimeFormatSettings(ConfigurationModelBase):
def from_dict(self, settings: dict):
try:
- self._date_format = settings[TimeFormatSettingsNames.date_format.value]
- self._time_format = settings[TimeFormatSettingsNames.time_format.value]
- self._date_time_format = settings[TimeFormatSettingsNames.date_time_format.value]
- self._date_time_log_format = settings[TimeFormatSettingsNames.date_time_log_format.value]
+ self._date_format = settings[TimeFormatSettingsNamesEnum.date_format.value]
+ self._time_format = settings[TimeFormatSettingsNamesEnum.time_format.value]
+ self._date_time_format = settings[TimeFormatSettingsNamesEnum.date_time_format.value]
+ self._date_time_log_format = settings[TimeFormatSettingsNamesEnum.date_time_log_format.value]
except Exception as e:
- Console.set_foreground_color(ForegroundColor.red)
+ Console.set_foreground_color(ForegroundColorEnum.red)
Console.write_line(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings')
Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
- Console.set_foreground_color(ForegroundColor.default)
+ Console.set_foreground_color(ForegroundColorEnum.default)
diff --git a/src/sh_edraft/time/model/time_format_settings_names.py b/src/cpl/time/time_format_settings_names_enum.py
similarity index 80%
rename from src/sh_edraft/time/model/time_format_settings_names.py
rename to src/cpl/time/time_format_settings_names_enum.py
index 3858de10..63bf373d 100644
--- a/src/sh_edraft/time/model/time_format_settings_names.py
+++ b/src/cpl/time/time_format_settings_names_enum.py
@@ -1,7 +1,7 @@
from enum import Enum
-class TimeFormatSettingsNames(Enum):
+class TimeFormatSettingsNamesEnum(Enum):
date_format = 'DateFormat'
time_format = 'TimeFormat'
diff --git a/src/cpl/utils/__init__.py b/src/cpl/utils/__init__.py
new file mode 100644
index 00000000..e3b9690b
--- /dev/null
+++ b/src/cpl/utils/__init__.py
@@ -0,0 +1,28 @@
+# -*- 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.utils'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .credential_manager import CredentialManager
+from .string import String
+from .pip import Pip
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/sh_edraft/utils/credential_manager.py b/src/cpl/utils/credential_manager.py
similarity index 55%
rename from src/sh_edraft/utils/credential_manager.py
rename to src/cpl/utils/credential_manager.py
index 7f9977d1..8a40e8dc 100644
--- a/src/sh_edraft/utils/credential_manager.py
+++ b/src/cpl/utils/credential_manager.py
@@ -2,16 +2,35 @@ import base64
class CredentialManager:
+ """
+ Handles credentials
+ """
@staticmethod
def encrypt(string: str) -> str:
+ """
+ Encode with base64
+ :param string:
+ :return:
+ """
return base64.b64encode(string.encode('utf-8')).decode('utf-8')
@staticmethod
def decrypt(string: str) -> str:
+ """
+ Decode with base64
+ :param string:
+ :return:
+ """
return base64.b64decode(string).decode('utf-8')
@staticmethod
def build_string(string: str, credentials: str):
+ """
+ Builds string with credentials in it
+ :param string:
+ :param credentials:
+ :return:
+ """
return string.replace('$credentials', CredentialManager.decrypt(credentials))
diff --git a/src/cpl/utils/pip.py b/src/cpl/utils/pip.py
new file mode 100644
index 00000000..b0035a0c
--- /dev/null
+++ b/src/cpl/utils/pip.py
@@ -0,0 +1,113 @@
+import subprocess
+import sys
+from contextlib import suppress
+from typing import Optional
+
+
+class Pip:
+ """
+ Executes pip commands
+ """
+ _executable = sys.executable
+
+ """
+ Getter
+ """
+
+ @classmethod
+ def get_executable(cls) -> str:
+ return cls._executable
+
+ """
+ Setter
+ """
+
+ @classmethod
+ def set_executable(cls, executable: str):
+ """
+ Sets the executable
+ :param executable:
+ :return:
+ """
+ if executable is not None:
+ cls._executable = executable
+
+ @classmethod
+ def reset_executable(cls):
+ """
+ Resets the executable to system standard
+ :return:
+ """
+ cls._executable = sys.executable
+
+ """
+ Public utils functions
+ """
+
+ @classmethod
+ def get_package(cls, package: str) -> Optional[str]:
+ """
+ Gets given package py local pip list
+ :param package:
+ :return:
+ """
+ result = None
+ with suppress(Exception):
+ result = subprocess.check_output([cls._executable, "-m", "pip", "show", package], stderr=subprocess.DEVNULL)
+
+ if result is None:
+ return None
+
+ new_package: list[str] = str(result, 'utf-8').lower().split('\n')
+ new_version = ''
+
+ for atr in new_package:
+ if 'version' in atr:
+ new_version = atr.split(': ')[1]
+
+ if new_version != '':
+ return f'{package}=={new_version}'
+
+ return package
+
+ @classmethod
+ def get_outdated(cls) -> bytes:
+ """
+ Gets table of outdated packages
+ :return:
+ """
+ return subprocess.check_output([cls._executable, "-m", "pip", "list", "--outdated"])
+
+ @classmethod
+ def install(cls, package: str, *args, source: str = None, stdout=None, stderr=None):
+ """
+ Installs given package
+ :param package:
+ :param args:
+ :param source:
+ :param stdout:
+ :param stderr:
+ :return:
+ """
+ pip_args = [cls._executable, "-m", "pip", "install"]
+
+ for arg in args:
+ pip_args.append(arg)
+
+ if source is not None:
+ pip_args.append(f'--extra-index-url')
+ pip_args.append(source)
+
+ pip_args.append(package)
+ subprocess.run(pip_args, stdout=stdout, stderr=stderr)
+
+ @classmethod
+ def uninstall(cls, package: str, stdout=None, stderr=None):
+ """
+ Uninstalls given package
+ :param package:
+ :param stdout:
+ :param stderr:
+ :return:
+ """
+ subprocess.run([cls._executable, "-m", "pip", "uninstall", "--yes", package], stdout=stdout, stderr=stderr)
diff --git a/src/cpl/utils/string.py b/src/cpl/utils/string.py
new file mode 100644
index 00000000..29d2da95
--- /dev/null
+++ b/src/cpl/utils/string.py
@@ -0,0 +1,37 @@
+import re
+
+
+class String:
+ """
+ Useful functions for strings
+ """
+
+ @staticmethod
+ def convert_to_snake_case(name: str) -> str:
+ """
+ Converts string to snake case
+ :param name:
+ :return:
+ """
+ pattern1 = re.compile(r'(.)([A-Z][a-z]+)')
+ pattern2 = re.compile(r'([a-z0-9])([A-Z])')
+ file_name = re.sub(pattern1, r'\1_\2', name)
+ return re.sub(pattern2, r'\1_\2', file_name).lower()
+
+ @staticmethod
+ def first_to_upper(string: str) -> str:
+ """
+ Converts first char to upper
+ :param string:
+ :return:
+ """
+ return f'{string[0].upper()}{string[1:]}'
+
+ @staticmethod
+ def first_to_lower(string: str) -> str:
+ """
+ Converts first char to lower
+ :param string:
+ :return:
+ """
+ return f'{string[0].lower()}{string[1:]}'
diff --git a/src/cpl_cli/__init__.py b/src/cpl_cli/__init__.py
new file mode 100644
index 00000000..c5052acc
--- /dev/null
+++ b/src/cpl_cli/__init__.py
@@ -0,0 +1,32 @@
+# -*- 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__ = 'sh_cpl.cpl_cli'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .cli import CLI
+from .command_abc import CommandABC
+from .command_handler_service import CommandHandler
+from .command_model import CommandModel
+from .error import Error
+from .main import main
+from .startup import Startup
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/appsettings.json b/src/cpl_cli/appsettings.json
new file mode 100644
index 00000000..f4dbfbf1
--- /dev/null
+++ b/src/cpl_cli/appsettings.json
@@ -0,0 +1,5 @@
+{
+ "CLI": {
+ "PipPath": "https://pip.sh-edraft.de"
+ }
+}
\ No newline at end of file
diff --git a/src/cpl_cli/cli.py b/src/cpl_cli/cli.py
new file mode 100644
index 00000000..8547844e
--- /dev/null
+++ b/src/cpl_cli/cli.py
@@ -0,0 +1,72 @@
+from typing import Optional
+
+from cpl.application.application_abc import ApplicationABC
+from cpl.configuration.configuration_abc import ConfigurationABC
+from cpl.console.console import Console
+from cpl.dependency_injection import ServiceProviderABC
+from cpl_cli.command.build_service import BuildService
+from cpl_cli.command.generate_service import GenerateService
+from cpl_cli.command.install_service import InstallService
+from cpl_cli.command.new_service import NewService
+from cpl_cli.command.publish_service import PublishService
+from cpl_cli.command.start_service import StartService
+from cpl_cli.command.uninstall_service import UninstallService
+from cpl_cli.command.update_service import UpdateService
+from cpl_cli.command_handler_service import CommandHandler
+from cpl_cli.command_model import CommandModel
+from cpl_cli.error import Error
+from cpl_cli.command.help_service import HelpService
+from cpl_cli.command.version_service import VersionService
+
+
+class CLI(ApplicationABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
+ """
+ CPL CLI
+ """
+ ApplicationABC.__init__(self, config, services)
+
+ self._command_handler: Optional[CommandHandler] = None
+
+ def configure(self):
+ self._command_handler: CommandHandler = self._services.get_service(CommandHandler)
+
+ self._command_handler.add_command(CommandModel('build', ['h', 'B'], BuildService, True))
+ self._command_handler.add_command(CommandModel('generate', ['g', 'G'], GenerateService, True))
+ self._command_handler.add_command(CommandModel('help', ['h', 'H'], HelpService, False))
+ self._command_handler.add_command(CommandModel('install', ['i', 'I'], InstallService, True))
+ self._command_handler.add_command(CommandModel('new', ['n', 'N'], NewService, False))
+ self._command_handler.add_command(CommandModel('publish', ['p', 'P'], PublishService, True))
+ self._command_handler.add_command(CommandModel('start', ['s', 'S'], StartService, True))
+ self._command_handler.add_command(CommandModel('uninstall', ['ui', 'UI'], UninstallService, True))
+ self._command_handler.add_command(CommandModel('update', ['u', 'U'], UpdateService, True))
+ self._command_handler.add_command(CommandModel('version', ['v', 'V'], VersionService, False))
+
+ def main(self):
+ """
+ Entry point of the CPL CLI
+ :return:
+ """
+ try:
+ command = None
+ args = []
+ if len(self._configuration.additional_arguments) > 0:
+ command = self._configuration.additional_arguments[0]
+ if len(self._configuration.additional_arguments) > 1:
+ args = self._configuration.additional_arguments[1:]
+ else:
+ for cmd in self._command_handler.commands:
+ result = self._configuration.get_configuration(cmd.name)
+ if result is not None:
+ command = cmd.name
+ args.append(result)
+
+ if command is None:
+ Error.error(f'Expected command')
+ return
+
+ self._command_handler.handle(command, args)
+ except KeyboardInterrupt:
+ Console.write_line()
+ exit()
diff --git a/src/cpl_cli/cli_settings.py b/src/cpl_cli/cli_settings.py
new file mode 100644
index 00000000..2adb1228
--- /dev/null
+++ b/src/cpl_cli/cli_settings.py
@@ -0,0 +1,25 @@
+import traceback
+from typing import Optional
+
+from cpl.configuration.configuration_model_abc import ConfigurationModelABC
+from cpl.console.console import Console
+from cpl_cli.cli_settings_name_enum import CLISettingsNameEnum
+
+
+class CLISettings(ConfigurationModelABC):
+
+ def __init__(self):
+ ConfigurationModelABC.__init__(self)
+
+ self._pip_path: Optional[str] = None
+
+ @property
+ def pip_path(self) -> str:
+ return self._pip_path
+
+ def from_dict(self, settings: dict):
+ try:
+ self._pip_path = settings[CLISettingsNameEnum.pip_path.value]
+ except Exception as e:
+ Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings')
+ Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
diff --git a/src/cpl_cli/cli_settings_name_enum.py b/src/cpl_cli/cli_settings_name_enum.py
new file mode 100644
index 00000000..f7dc8889
--- /dev/null
+++ b/src/cpl_cli/cli_settings_name_enum.py
@@ -0,0 +1,6 @@
+from enum import Enum
+
+
+class CLISettingsNameEnum(Enum):
+
+ pip_path = 'PipPath'
diff --git a/src/cpl_cli/command/__init__.py b/src/cpl_cli/command/__init__.py
new file mode 100644
index 00000000..b316c90b
--- /dev/null
+++ b/src/cpl_cli/command/__init__.py
@@ -0,0 +1,31 @@
+# -*- 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.command'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .build_service import BuildService
+from .generate_service import GenerateService
+from .help_service import HelpService
+from .new_service import NewService
+from .publish_service import PublishService
+from .version_service import VersionService
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/command/build_service.py b/src/cpl_cli/command/build_service.py
new file mode 100644
index 00000000..18ce4dbd
--- /dev/null
+++ b/src/cpl_cli/command/build_service.py
@@ -0,0 +1,22 @@
+from cpl_cli.command_abc import CommandABC
+from cpl_cli.publish.publisher_abc import PublisherABC
+
+
+class BuildService(CommandABC):
+
+ def __init__(self, publisher: PublisherABC):
+ """
+ Service for the CLI command build
+ :param publisher:
+ """
+ CommandABC.__init__(self)
+
+ self._publisher = publisher
+
+ def run(self, args: list[str]):
+ """
+ Entry point of command
+ :param args:
+ :return:
+ """
+ self._publisher.build()
diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py
new file mode 100644
index 00000000..7a084e6e
--- /dev/null
+++ b/src/cpl_cli/command/generate_service.py
@@ -0,0 +1,162 @@
+import os
+from collections import Callable
+
+from cpl.configuration.configuration_abc import ConfigurationABC
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.console.console import Console
+from cpl.utils.string import String
+from cpl_cli.command_abc import CommandABC
+from cpl_cli.templates.generate.init_template import InitTemplate
+from cpl_cli.templates.generate.abc_template import ABCTemplate
+from cpl_cli.templates.generate.class_template import ClassTemplate
+from cpl_cli.templates.generate.configmodel_template import ConfigModelTemplate
+from cpl_cli.templates.generate.enum_template import EnumTemplate
+from cpl_cli.templates.generate.service_template import ServiceTemplate
+from cpl_cli.templates.generate.thread_template import ThreadTemplate
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class GenerateService(CommandABC):
+
+ def __init__(self, configuration: ConfigurationABC):
+ """
+ Service for the CLI command generate
+ :param configuration:
+ """
+ CommandABC.__init__(self)
+
+ self._schematics = {
+ "abc": {
+ "Upper": "ABC",
+ "Template": ABCTemplate
+ },
+ "class": {
+ "Upper": "",
+ "Template": ClassTemplate
+ },
+ "enum": {
+ "Upper": "Enum",
+ "Template": EnumTemplate
+ },
+ "service": {
+ "Upper": "Service",
+ "Template": ServiceTemplate
+ },
+ "settings": {
+ "Upper": "Settings",
+ "Template": ConfigModelTemplate
+ },
+ "thread": {
+ "Upper": "Thread",
+ "Template": ThreadTemplate
+ }
+ }
+
+ self._config = configuration
+ self._env = self._config.environment
+
+ @staticmethod
+ def _help(message: str):
+ """
+ Internal help output
+ :param message:
+ :return:
+ """
+ Console.error(message)
+
+ schematics = [
+ 'abc (a|A)',
+ 'class (c|C)',
+ 'enum (e|E)',
+ 'service (s|S)',
+ 'settings (st|ST)'
+ ]
+ Console.write_line('Available Schematics:')
+ for name in schematics:
+ Console.write(f'\n\t{name} ')
+
+ @staticmethod
+ def _create_file(file_path: str, value: str):
+ """
+ Creates the given file with content
+ :param file_path:
+ :param value:
+ :return:
+ """
+ with open(file_path, 'w') as template:
+ template.write(value)
+ template.close()
+
+ def _generate(self, schematic: str, name: str, template: Callable[TemplateFileABC]):
+ """
+ Generates files by given schematic, name and template
+ :param schematic:
+ :param name:
+ :param template:
+ :return:
+ """
+ class_name = name
+ rel_path = ''
+ if '/' in name:
+ parts = name.split('/')
+ rel_path = '/'.join(parts[:-1])
+ class_name = parts[len(parts) - 1]
+
+ template = template(class_name, schematic, self._schematics[schematic]["Upper"], rel_path)
+
+ file_path = os.path.join(self._env.working_directory, template.path, template.name)
+ if not os.path.isdir(os.path.dirname(file_path)):
+ os.makedirs(os.path.dirname(file_path))
+ directory = ''
+ for subdir in template.path.split('/'):
+ directory = os.path.join(directory, subdir)
+ if subdir != 'src':
+ file = InitTemplate(class_name, schematic, self._schematics[schematic]["Upper"], rel_path)
+ Console.spinner(
+ f'Creating {os.path.abspath(directory)}/{file.name}',
+ self._create_file,
+ os.path.join(os.path.abspath(directory), file.name),
+ file.value,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.cyan
+ )
+
+ if os.path.isfile(file_path):
+ Console.error(f'{String.first_to_upper(schematic)} already exists!')
+ exit()
+
+ message = f'Creating {self._env.working_directory}/{template.path}/{template.name}'
+ if template.path == '':
+ message = f'Creating {self._env.working_directory}/{template.name}'
+
+ Console.spinner(
+ message,
+ self._create_file,
+ file_path,
+ template.value,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.cyan
+ )
+
+ def run(self, args: list[str]):
+ """
+ Entry point of command
+ :param args:
+ :return:
+ """
+ if len(args) == 0:
+ self._help('Usage: cpl generate [options]')
+ exit()
+
+ schematic = args[0]
+ name = self._config.get_configuration(schematic)
+ if name is None:
+ name = Console.read(f'Name for the {args[0]}: ')
+
+ if schematic in self._schematics:
+ s = self._schematics[schematic]
+ self._generate(schematic, name, s["Template"])
+
+ else:
+ self._help('Usage: cpl generate [options]')
+ exit()
diff --git a/src/cpl_cli/command/help_service.py b/src/cpl_cli/command/help_service.py
new file mode 100644
index 00000000..5088b379
--- /dev/null
+++ b/src/cpl_cli/command/help_service.py
@@ -0,0 +1,37 @@
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl_cli.command_abc import CommandABC
+
+
+class HelpService(CommandABC):
+
+ def __init__(self):
+ """
+ Service for CLI command help
+ """
+ CommandABC.__init__(self)
+
+ def run(self, args: list[str]):
+ """
+ Entry point of command
+ :param args:
+ :return:
+ """
+ Console.write_line('Available Commands:')
+ commands = [
+ ['build (b|B)', 'Prepares files for publish into an output directory named dist/ at the given output path. Must be executed from within a workspace directory.'],
+ ['generate (g|G)', 'Generate a new file.'],
+ ['help (h|H)', 'Lists available command and their short descriptions.'],
+ ['install (i|I)', 'With argument installs packages to project, without argument installs project dependencies.'],
+ ['new (n|N)', 'Creates new CPL project.'],
+ ['publish (p|P)', 'Prepares files for publish into an output directory named dist/ at the given output path and executes setup.py. Must be executed from within a library workspace directory.'],
+ ['start (s|S)', 'Starts CPL project, restarting on file changes'],
+ ['uninstall (ui|UI)', 'Uninstalls packages from project.'],
+ ['update (u|u)', 'Update CPL and project dependencies.'],
+ ['version (v|V)', 'Outputs CPL CLI version.']
+ ]
+ for name, description in commands:
+ Console.set_foreground_color(ForegroundColorEnum.blue)
+ Console.write(f'\n\t{name} ')
+ Console.set_foreground_color(ForegroundColorEnum.default)
+ Console.write(f'{description}')
diff --git a/src/cpl_cli/command/install_service.py b/src/cpl_cli/command/install_service.py
new file mode 100644
index 00000000..494bb823
--- /dev/null
+++ b/src/cpl_cli/command/install_service.py
@@ -0,0 +1,165 @@
+import json
+import os
+import subprocess
+
+from packaging import version
+
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
+from cpl.utils.pip import Pip
+from cpl_cli.cli_settings import CLISettings
+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.error import Error
+
+
+class InstallService(CommandABC):
+
+ def __init__(self, env: ApplicationEnvironmentABC, build_settings: BuildSettings, project_settings: ProjectSettings,
+ cli_settings: CLISettings):
+ """
+ Service for the CLI command install
+ :param env:
+ :param build_settings:
+ :param project_settings:
+ :param cli_settings:
+ """
+ CommandABC.__init__(self)
+
+ self._env = env
+ self._build_settings = build_settings
+ self._project_settings = project_settings
+ self._cli_settings = cli_settings
+
+ def _install_project(self):
+ """
+ Installs dependencies of CPl project
+ :return:
+ """
+
+ if self._project_settings is None or self._build_settings is None:
+ Error.error('The command requires to be run in an CPL project, but a project could not be found.')
+ return
+
+ if self._project_settings.dependencies is None:
+ Error.error('Found invalid dependencies in cpl.json.')
+ return
+
+ Pip.set_executable(self._project_settings.python_executable)
+ for dependency in self._project_settings.dependencies:
+ Console.spinner(
+ f'Installing: {dependency}',
+ Pip.install, dependency,
+ source=self._cli_settings.pip_path if 'sh_cpl' in dependency else None,
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.cyan
+ )
+
+ Pip.reset_executable()
+
+ def _install_package(self, package: str):
+ """
+ Installs given package
+ :param package:
+ :return:
+ """
+ is_already_in_project = False
+ Pip.set_executable(self._project_settings.python_executable)
+
+ if self._project_settings is None or self._build_settings is None:
+ Error.error('The command requires to be run in an CPL project, but a project could not be found.')
+ return
+
+ if self._project_settings.dependencies is None:
+ Error.error('Found invalid dependencies in cpl.json.')
+ return
+
+ package_version = ''
+ name = package
+ if '==' in package:
+ name = package.split('==')[0]
+ package_version = package.split('==')[1]
+
+ to_remove_list = []
+ for dependency in self._project_settings.dependencies:
+ dependency_version = ''
+
+ if '==' in dependency:
+ dependency_version = dependency.split('==')[1]
+
+ if name in dependency:
+ if package_version != '' and version.parse(package_version) != version.parse(dependency_version):
+ to_remove_list.append(dependency)
+ break
+ else:
+ is_already_in_project = True
+
+ for to_remove in to_remove_list:
+ self._project_settings.dependencies.remove(to_remove)
+
+ local_package = Pip.get_package(package)
+ if local_package is not None and local_package in self._project_settings.dependencies:
+ Error.warn(f'Package {local_package} is already installed.')
+ return
+
+ elif is_already_in_project:
+ Error.warn(f'Package {package} is already installed.')
+ return
+
+ Console.spinner(
+ f'Installing: {package}',
+ Pip.install, package,
+ source=self._cli_settings.pip_path if 'sh_cpl' in package else None,
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.cyan
+ )
+ new_package = Pip.get_package(name)
+ if new_package is None \
+ or '==' in package and \
+ version.parse(package.split('==')[1]) != version.parse(new_package.split('==')[1]):
+ Console.error(f'Installation of package {package} failed')
+ return
+
+ if not is_already_in_project:
+ new_name = package
+ if '==' in new_package:
+ new_name = new_package
+ elif '==' in name:
+ new_name = name
+
+ if '/' in new_name:
+ new_name = new_name.split('/')[0]
+
+ if '\r' in new_name:
+ new_name = new_name.replace('\r', '')
+
+ self._project_settings.dependencies.append(new_name)
+
+ config = {
+ ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings),
+ BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings)
+ }
+
+ with open(os.path.join(self._env.working_directory, 'cpl.json'), 'w') as project_file:
+ project_file.write(json.dumps(config, indent=2))
+ project_file.close()
+
+ Pip.reset_executable()
+
+ def run(self, args: list[str]):
+ """
+ Entry point of command
+ :param args:
+ :return:
+ """
+ if len(args) == 0:
+ self._install_project()
+ else:
+ self._install_package(args[0])
diff --git a/src/cpl_cli/command/new_service.py b/src/cpl_cli/command/new_service.py
new file mode 100644
index 00000000..7b945c25
--- /dev/null
+++ b/src/cpl_cli/command/new_service.py
@@ -0,0 +1,231 @@
+import json
+import os
+import sys
+from typing import Optional
+
+from packaging import version
+
+import cpl
+
+from cpl.configuration.configuration_abc import ConfigurationABC
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.console.console import Console
+from cpl.utils.string import String
+from cpl_cli.command_abc import CommandABC
+from cpl_cli.configuration.build_settings import BuildSettings
+from cpl_cli.configuration.build_settings_name_enum import BuildSettingsNameEnum
+from cpl_cli.configuration.project_settings import ProjectSettings
+from cpl_cli.configuration.project_settings_name_enum import ProjectSettingsNameEnum
+from cpl_cli.configuration.project_type_enum import ProjectTypeEnum
+from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum
+from cpl_cli.source_creator.console_builder import ConsoleBuilder
+from cpl_cli.source_creator.library_builder import LibraryBuilder
+
+
+class NewService(CommandABC):
+
+ def __init__(self, configuration: ConfigurationABC):
+ """
+ Service for the CLI command new
+ :param configuration:
+ """
+ CommandABC.__init__(self)
+
+ self._config = configuration
+ self._env = self._config.environment
+
+ self._project: ProjectSettings = ProjectSettings()
+ self._project_dict = {}
+ self._build: BuildSettings = BuildSettings()
+ self._build_dict = {}
+ self._project_json = {}
+
+ self._command: str = ''
+ self._use_application_api: bool = False
+ self._use_startup: bool = False
+ self._use_service_providing: bool = False
+
+ @staticmethod
+ def _help(message: str):
+ """
+ Internal help output
+ :param message:
+ :return:
+ """
+ Console.error(message)
+
+ schematics = [
+ 'console (c|C) ',
+ ]
+ Console.write_line('Available Schematics:')
+ for name in schematics:
+ Console.write(f'\n\t{name} ')
+
+ def _create_project_settings(self, name: str):
+ self._project_dict = {
+ ProjectSettingsNameEnum.name.value: name,
+ ProjectSettingsNameEnum.version.value: {
+ VersionSettingsNameEnum.major.value: '0',
+ VersionSettingsNameEnum.minor.value: '0',
+ VersionSettingsNameEnum.micro.value: '0'
+ },
+ ProjectSettingsNameEnum.author.value: '',
+ ProjectSettingsNameEnum.author_email.value: '',
+ ProjectSettingsNameEnum.description.value: '',
+ ProjectSettingsNameEnum.long_description.value: '',
+ ProjectSettingsNameEnum.url.value: '',
+ ProjectSettingsNameEnum.copyright_date.value: '',
+ ProjectSettingsNameEnum.copyright_name.value: '',
+ ProjectSettingsNameEnum.license_name.value: '',
+ ProjectSettingsNameEnum.license_description.value: '',
+ ProjectSettingsNameEnum.dependencies.value: [
+ f'sh_cpl=={version.parse(cpl.__version__)}'
+ ],
+ ProjectSettingsNameEnum.python_version.value: f'>={sys.version.split(" ")[0]}',
+ ProjectSettingsNameEnum.python_path.value: {
+ sys.platform: ''
+ },
+ ProjectSettingsNameEnum.classifiers.value: []
+ }
+
+ self._project.from_dict(self._project_dict)
+
+ def _create_build_settings(self):
+ main = f'{String.convert_to_snake_case(self._project.name)}.main'
+ if self._command == ProjectTypeEnum.library.value:
+ main = f'{String.convert_to_snake_case(self._project.name)}_cli.main'
+
+ self._build_dict = {
+ BuildSettingsNameEnum.project_type.value: self._command,
+ BuildSettingsNameEnum.source_path.value: 'src',
+ BuildSettingsNameEnum.output_path.value: 'dist',
+ BuildSettingsNameEnum.main.value: main,
+ BuildSettingsNameEnum.entry_point.value: self._project.name,
+ BuildSettingsNameEnum.include_package_data.value: False,
+ BuildSettingsNameEnum.included.value: [],
+ BuildSettingsNameEnum.excluded.value: [
+ '*/__pycache__',
+ '*/logs',
+ '*/tests'
+ ],
+ BuildSettingsNameEnum.package_data.value: {}
+ }
+ self._build.from_dict(self._build_dict)
+
+ def _create_project_json(self):
+ """
+ Creates cpl.json content
+ :return:
+ """
+ self._project_json = {
+ ProjectSettings.__name__: self._project_dict,
+ BuildSettings.__name__: self._build_dict
+ }
+
+ def _get_project_path(self) -> Optional[str]:
+ """
+ Gets project path
+ :return:
+ """
+ project_path = os.path.join(self._env.working_directory, self._project.name)
+ if os.path.isdir(project_path) and len(os.listdir(project_path)) > 0:
+ Console.error('Project path is not empty\n')
+ return None
+
+ return project_path
+
+ def _get_project_information(self):
+ """
+ Gets project information's from user
+ :return:
+ """
+ result = Console.read('Do you want to use application base? (y/n) ')
+ if result.lower() == 'y':
+ self._use_application_api = True
+
+ result = Console.read('Do you want to use startup? (y/n) ')
+ if result.lower() == 'y':
+ self._use_startup = True
+ else:
+ result = Console.read('Do you want to use service providing? (y/n) ')
+ if result.lower() == 'y':
+ self._use_service_providing = True
+
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ def _console(self, args: list[str]):
+ """
+ Generates new console project
+ :param args:
+ :return:
+ """
+ name = self._config.get_configuration(self._command)
+
+ self._create_project_settings(name)
+ self._create_build_settings()
+ self._create_project_json()
+ path = self._get_project_path()
+ if path is None:
+ return
+
+ self._get_project_information()
+ try:
+ ConsoleBuilder.build(
+ path,
+ self._use_application_api,
+ self._use_startup,
+ self._use_service_providing,
+ self._project.name,
+ self._project_json
+ )
+ except Exception as e:
+ Console.error('Could not create project', str(e))
+
+ def _library(self, args: list[str]):
+ """
+ Generates new library project
+ :param args:
+ :return:
+ """
+ name = self._config.get_configuration(self._command)
+
+ self._create_project_settings(name)
+ self._create_build_settings()
+ self._create_project_json()
+ path = self._get_project_path()
+ if path is None:
+ return
+
+ self._get_project_information()
+ try:
+ LibraryBuilder.build(
+ path,
+ self._use_application_api,
+ self._use_startup,
+ self._use_service_providing,
+ self._project.name,
+ self._project_json
+ )
+ except Exception as e:
+ Console.error('Could not create project', str(e))
+
+ def run(self, args: list[str]):
+ """
+ Entry point of command
+ :param args:
+ :return:
+ """
+ if len(args) == 0:
+ self._help('Usage: cpl new [options]')
+ return
+
+ self._command = str(args[0]).lower()
+ if self._command == ProjectTypeEnum.console.value:
+ self._console(args)
+
+ elif self._command == ProjectTypeEnum.library.value:
+ self._library(args)
+
+ else:
+ self._help('Usage: cpl new [options]')
+ return
diff --git a/src/cpl_cli/command/publish_service.py b/src/cpl_cli/command/publish_service.py
new file mode 100644
index 00000000..7f459ea9
--- /dev/null
+++ b/src/cpl_cli/command/publish_service.py
@@ -0,0 +1,23 @@
+from cpl.console.console import Console
+from cpl_cli.command_abc import CommandABC
+from cpl_cli.publish.publisher_abc import PublisherABC
+
+
+class PublishService(CommandABC):
+
+ def __init__(self, publisher: PublisherABC):
+ """
+ Service for the CLI command publish
+ :param publisher:
+ """
+ CommandABC.__init__(self)
+
+ self._publisher = publisher
+
+ def run(self, args: list[str]):
+ """
+ Entry point of command
+ :param args:
+ :return:
+ """
+ self._publisher.publish()
diff --git a/src/cpl_cli/command/start_service.py b/src/cpl_cli/command/start_service.py
new file mode 100644
index 00000000..7dae7086
--- /dev/null
+++ b/src/cpl_cli/command/start_service.py
@@ -0,0 +1,22 @@
+from cpl_cli.command_abc import CommandABC
+from cpl_cli.live_server.live_server_service import LiveServerService
+
+
+class StartService(CommandABC):
+
+ def __init__(self, live_server: LiveServerService):
+ """
+ Service for the CLI command start
+ :param live_server:
+ """
+ CommandABC.__init__(self)
+
+ self._live_server = live_server
+
+ def run(self, args: list[str]):
+ """
+ Entry point of command
+ :param args:
+ :return:
+ """
+ self._live_server.start()
diff --git a/src/cpl_cli/command/uninstall_service.py b/src/cpl_cli/command/uninstall_service.py
new file mode 100644
index 00000000..da7ea3ca
--- /dev/null
+++ b/src/cpl_cli/command/uninstall_service.py
@@ -0,0 +1,82 @@
+import json
+import os
+import subprocess
+
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
+from cpl.utils.pip import Pip
+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
+
+
+class UninstallService(CommandABC):
+
+ def __init__(self, env: ApplicationEnvironmentABC, build_settings: BuildSettings,
+ project_settings: ProjectSettings):
+ """
+ Service for the CLI command uninstall
+ :param env:
+ :param build_settings:
+ :param project_settings:
+ """
+ CommandABC.__init__(self)
+
+ self._env = env
+
+ self._build_settings = build_settings
+ self._project_settings = project_settings
+
+ def run(self, args: list[str]):
+ """
+ Entry point of command
+ :param args:
+ :return:
+ """
+ if len(args) == 0:
+ Console.error(f'Expected package')
+ Console.error(f'Usage: cpl uninstall ')
+ return
+
+ Pip.set_executable(self._project_settings.python_executable)
+
+ package = args[0]
+ is_in_dependencies = False
+
+ pip_package = Pip.get_package(package)
+
+ for dependency in self._project_settings.dependencies:
+ if package in dependency:
+ is_in_dependencies = True
+ package = dependency
+
+ if not is_in_dependencies and pip_package is None:
+ Console.error(f'Package {package} not found')
+ return
+
+ elif not is_in_dependencies and pip_package is not None:
+ package = pip_package
+
+ Console.spinner(
+ f'Uninstalling: {package}',
+ Pip.uninstall, package,
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.cyan
+ )
+
+ if package in self._project_settings.dependencies:
+ self._project_settings.dependencies.remove(package)
+ config = {
+ ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings),
+ BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings)
+ }
+ with open(os.path.join(self._env.working_directory, 'cpl.json'), 'w') as project_file:
+ project_file.write(json.dumps(config, indent=2))
+ project_file.close()
+
+ Console.write_line(f'Removed {package}')
+ Pip.reset_executable()
diff --git a/src/cpl_cli/command/update_service.py b/src/cpl_cli/command/update_service.py
new file mode 100644
index 00000000..c45679bd
--- /dev/null
+++ b/src/cpl_cli/command/update_service.py
@@ -0,0 +1,151 @@
+import json
+import os
+import subprocess
+
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
+from cpl.utils.pip import Pip
+from cpl_cli.cli_settings import CLISettings
+from cpl_cli.command_abc import CommandABC
+from cpl_cli.configuration import BuildSettings
+from cpl_cli.configuration.project_settings import ProjectSettings
+from cpl_cli.configuration.settings_helper import SettingsHelper
+
+
+class UpdateService(CommandABC):
+
+ def __init__(self,
+ env: ApplicationEnvironmentABC,
+ build_settings: BuildSettings,
+ project_settings: ProjectSettings,
+ cli_settings: CLISettings):
+ """
+ Service for the CLI command update
+ :param env:
+ :param build_settings:
+ :param project_settings:
+ :param cli_settings:
+ """
+ CommandABC.__init__(self)
+
+ self._env = env
+ self._build_settings = build_settings
+ self._project_settings = project_settings
+ self._cli_settings = cli_settings
+
+ def _collect_project_dependencies(self) -> list[tuple]:
+ """
+ Collects project dependencies
+ :return:
+ """
+ dependencies = []
+ for package in self._project_settings.dependencies:
+ name = package
+ if '==' in package:
+ name = package.split('==')[0]
+
+ dependencies.append((package, name))
+
+ return dependencies
+
+ def _update_project_dependencies(self, dependencies):
+ """
+ Updates project dependencies
+ :return:
+ """
+ for package, name in dependencies:
+ Pip.install(
+ name,
+ '--upgrade',
+ '--upgrade-strategy',
+ 'eager',
+ source=self._cli_settings.pip_path if 'sh_cpl' in name else None,
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL
+ )
+
+ new_package = Pip.get_package(name)
+ if new_package is None:
+ Console.error(f'Update for package {package} failed')
+ return
+
+ self._project_json_update_dependency(package, new_package)
+
+ def _check_project_dependencies(self):
+ """
+ Checks project dependencies for updates
+ :return:
+ """
+ dependencies = Console.spinner(
+ 'Collecting installed dependencies', self._collect_project_dependencies,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.cyan
+ )
+
+ Console.spinner(
+ 'Updating installed dependencies', self._update_project_dependencies, dependencies,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.cyan
+ )
+
+ Console.write_line(f'Found {len(self._project_settings.dependencies)} dependencies.')
+
+ @staticmethod
+ def _check_outdated():
+ """
+ Checks for outdated packages in project
+ :return:
+ """
+ table_str: bytes = Console.spinner(
+ 'Analyzing for available package updates', Pip.get_outdated,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.cyan
+ )
+
+ table = str(table_str, 'utf-8').split('\n')
+ if len(table) > 1 and table[0] != '':
+ Console.write_line('\tAvailable updates for packages:')
+ for row in table:
+ Console.write_line(f'\t{row}')
+
+ Console.set_foreground_color(ForegroundColorEnum.yellow)
+ Console.write_line(f'\tUpdate with {Pip.get_executable()} -m pip install --upgrade ')
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ def _project_json_update_dependency(self, old_package: str, new_package: str):
+ """
+ Writes new package version to cpl.json
+ :param old_package:
+ :param new_package:
+ :return:
+ """
+ if old_package in self._project_settings.dependencies:
+ index = self._project_settings.dependencies.index(old_package)
+ if '/' in new_package:
+ new_package = new_package.split('/')[0]
+
+ if '\r' in new_package:
+ new_package = new_package.replace('\r', '')
+
+ self._project_settings.dependencies[index] = new_package
+
+ config = {
+ ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings),
+ BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings)
+ }
+
+ with open(os.path.join(self._env.working_directory, 'cpl.json'), 'w') as project:
+ project.write(json.dumps(config, indent=2))
+ project.close()
+
+ def run(self, args: list[str]):
+ """
+ Entry point of command
+ :param args:
+ :return:
+ """
+ Pip.set_executable(self._project_settings.python_executable)
+ self._check_project_dependencies()
+ self._check_outdated()
+ Pip.reset_executable()
diff --git a/src/cpl_cli/command/version_service.py b/src/cpl_cli/command/version_service.py
new file mode 100644
index 00000000..0046a3f9
--- /dev/null
+++ b/src/cpl_cli/command/version_service.py
@@ -0,0 +1,54 @@
+import pkgutil
+import sys
+import platform
+import pkg_resources
+
+import cpl
+import cpl_cli
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl_cli.command_abc import CommandABC
+
+
+class VersionService(CommandABC):
+
+ def __init__(self):
+ """
+ Service for the CLI command version
+ """
+ CommandABC.__init__(self)
+
+ def run(self, args: list[str]):
+ """
+ Entry point of command
+ :param args:
+ :return:
+ """
+ Console.set_foreground_color(ForegroundColorEnum.yellow)
+ Console.banner('CPL CLI')
+ Console.set_foreground_color(ForegroundColorEnum.default)
+ if '__version__' in dir(cpl_cli):
+ Console.write_line(f'Common Python library CLI: ')
+ Console.write(cpl_cli.__version__)
+
+ Console.write_line(f'Python: ')
+ Console.write(f'{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}')
+
+ Console.write_line(f'OS: {platform.system()} {platform.processor()}')
+
+ Console.write_line('\nCPL packages:')
+ packages = []
+ for importer, modname, is_pkg in pkgutil.iter_modules(cpl.__path__):
+ module = importer.find_module(modname).load_module(modname)
+ if '__version__' in dir(module):
+ packages.append([f'{modname}', module.__version__])
+
+ Console.table(['Name', 'Version'], packages)
+
+ Console.write_line('\nPython packages:')
+ packages = []
+ dependencies = dict(tuple(str(ws).split()) for ws in pkg_resources.working_set)
+ for p in dependencies:
+ packages.append([p, dependencies[p]])
+
+ Console.table(['Name', 'Version'], packages)
diff --git a/src/cpl_cli/command_abc.py b/src/cpl_cli/command_abc.py
new file mode 100644
index 00000000..6ac6376f
--- /dev/null
+++ b/src/cpl_cli/command_abc.py
@@ -0,0 +1,11 @@
+from abc import abstractmethod, ABC
+
+
+class CommandABC(ABC):
+
+ @abstractmethod
+ def __init__(self):
+ ABC.__init__(self)
+
+ @abstractmethod
+ def run(self, args: list[str]): pass
diff --git a/src/cpl_cli/command_handler_service.py b/src/cpl_cli/command_handler_service.py
new file mode 100644
index 00000000..75bcdced
--- /dev/null
+++ b/src/cpl_cli/command_handler_service.py
@@ -0,0 +1,54 @@
+import os
+from abc import ABC
+
+from cpl.configuration.configuration_abc import ConfigurationABC
+from cpl.console.console import Console
+from cpl.dependency_injection.service_provider_abc import ServiceProviderABC
+from cpl_cli.error import Error
+from cpl_cli.command_model import CommandModel
+
+
+class CommandHandler(ABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
+ """
+ Service to handle incoming commands and args
+ :param config:
+ :param services:
+ """
+ ABC.__init__(self)
+
+ self._config = config
+ self._env = self._config.environment
+ self._services = services
+
+ self._commands: list[CommandModel] = []
+
+ @property
+ def commands(self) -> list[CommandModel]:
+ return self._commands
+
+ def add_command(self, cmd: CommandModel):
+ self._commands.append(cmd)
+
+ def remove_command(self, cmd: CommandModel):
+ self._commands.remove(cmd)
+
+ def handle(self, cmd: str, args: list[str]):
+ """
+ Handles incoming commands and args
+ :param cmd:
+ :param args:
+ :return:
+ """
+ for command in self._commands:
+ if cmd == command.name or cmd in command.aliases:
+ if command.is_project_needed and not os.path.isfile(os.path.join(self._env.working_directory, 'cpl.json')):
+ Error.error('The command requires to be run in an CPL project, but a project could not be found.')
+ return
+
+ if command.is_project_needed:
+ self._config.add_json_file('cpl.json', optional=True, output=False)
+
+ self._services.get_service(command.command).run(args)
+ Console.write('\n')
diff --git a/src/cpl_cli/command_model.py b/src/cpl_cli/command_model.py
new file mode 100644
index 00000000..85afe007
--- /dev/null
+++ b/src/cpl_cli/command_model.py
@@ -0,0 +1,28 @@
+from collections import Callable
+
+from cpl_cli.command_abc import CommandABC
+
+
+class CommandModel:
+
+ def __init__(self, name: str, aliases: list[str], command: Callable[CommandABC], is_project_needed: bool):
+ self._name = name
+ self._aliases = aliases
+ self._command = command
+ self._is_project_needed = is_project_needed
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def aliases(self) -> list[str]:
+ return self._aliases
+
+ @property
+ def command(self) -> Callable[CommandABC]:
+ return self._command
+
+ @property
+ def is_project_needed(self) -> bool:
+ return self._is_project_needed
diff --git a/src/cpl_cli/configuration/__init__.py b/src/cpl_cli/configuration/__init__.py
new file mode 100644
index 00000000..4144b72d
--- /dev/null
+++ b/src/cpl_cli/configuration/__init__.py
@@ -0,0 +1,31 @@
+# -*- 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.configuration'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .build_settings import BuildSettings
+from .build_settings_name_enum import BuildSettingsNameEnum
+from .project_settings import ProjectSettings
+from .project_settings_name_enum import ProjectSettingsNameEnum
+from .version_settings import VersionSettings
+from .version_settings_name_enum import VersionSettingsNameEnum
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/configuration/build_settings.py b/src/cpl_cli/configuration/build_settings.py
new file mode 100644
index 00000000..f24be025
--- /dev/null
+++ b/src/cpl_cli/configuration/build_settings.py
@@ -0,0 +1,98 @@
+import sys
+import traceback
+from typing import Optional
+
+from cpl.configuration.configuration_model_abc import ConfigurationModelABC
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl_cli.configuration.build_settings_name_enum import BuildSettingsNameEnum
+from cpl_cli.configuration.project_type_enum import ProjectTypeEnum
+
+
+class BuildSettings(ConfigurationModelABC):
+
+ def __init__(self):
+ ConfigurationModelABC.__init__(self)
+
+ self._project_type: Optional[ProjectTypeEnum] = None
+ self._source_path: Optional[str] = None
+ self._output_path: Optional[str] = None
+ self._main: Optional[str] = None
+ self._entry_point: Optional[str] = None
+ self._include_package_data: Optional[bool] = None
+ self._included: Optional[list[str]] = None
+ self._excluded: Optional[list[str]] = None
+ self._package_data: Optional[dict[str, list[str]]] = None
+
+ @property
+ def project_type(self):
+ return self._project_type
+
+ @property
+ def source_path(self) -> str:
+ return self._source_path
+
+ @property
+ def output_path(self) -> str:
+ return self._output_path
+
+ @property
+ def main(self) -> str:
+ return self._main
+
+ @property
+ def entry_point(self) -> str:
+ return self._entry_point
+
+ @property
+ def include_package_data(self) -> bool:
+ return self._include_package_data
+
+ @property
+ def included(self) -> list[str]:
+ return self._included
+
+ @property
+ def excluded(self) -> list[str]:
+ return self._excluded
+
+ @property
+ def package_data(self) -> dict[str, list[str]]:
+ return self._package_data
+
+ def from_dict(self, settings: dict):
+ try:
+ self._project_type = settings[BuildSettingsNameEnum.project_type.value]
+ self._source_path = settings[BuildSettingsNameEnum.source_path.value]
+ self._output_path = settings[BuildSettingsNameEnum.output_path.value]
+ self._include_package_data = bool(settings[BuildSettingsNameEnum.include_package_data.value])
+ self._main = settings[BuildSettingsNameEnum.main.value]
+ self._entry_point = settings[BuildSettingsNameEnum.entry_point.value]
+ self._included = settings[BuildSettingsNameEnum.included.value]
+ self._excluded = settings[BuildSettingsNameEnum.excluded.value]
+ self._package_data = settings[BuildSettingsNameEnum.package_data.value]
+
+ if sys.platform == 'win32':
+ self._source_path = str(self._source_path).replace('/', '\\')
+ self._output_path = str(self._output_path).replace('/', '\\')
+
+ # windows paths for excluded files
+ excluded = []
+ for ex in self._excluded:
+ excluded.append(str(ex).replace('/', '\\'))
+
+ self._excluded = excluded
+
+ # windows paths for included files
+ included = []
+ for inc in self._included:
+ included.append(str(inc).replace('/', '\\'))
+
+ self._included = included
+
+ except Exception as e:
+ Console.set_foreground_color(ForegroundColorEnum.red)
+ Console.write_line(
+ f'[ ERROR ] [ {__name__} ]: Reading error in {BuildSettings.__name__} settings')
+ Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
+ Console.set_foreground_color(ForegroundColorEnum.default)
diff --git a/src/cpl_cli/configuration/build_settings_name_enum.py b/src/cpl_cli/configuration/build_settings_name_enum.py
new file mode 100644
index 00000000..18d78749
--- /dev/null
+++ b/src/cpl_cli/configuration/build_settings_name_enum.py
@@ -0,0 +1,14 @@
+from enum import Enum
+
+
+class BuildSettingsNameEnum(Enum):
+
+ project_type = 'ProjectType'
+ source_path = 'SourcePath'
+ output_path = 'OutputPath'
+ main = 'Main'
+ entry_point = 'EntryPoint'
+ include_package_data = 'IncludePackageData'
+ included = 'Included'
+ excluded = 'Excluded'
+ package_data = 'PackageData'
diff --git a/src/cpl_cli/configuration/project_settings.py b/src/cpl_cli/configuration/project_settings.py
new file mode 100644
index 00000000..d9e8413b
--- /dev/null
+++ b/src/cpl_cli/configuration/project_settings.py
@@ -0,0 +1,136 @@
+import os
+import sys
+import traceback
+from typing import Optional
+
+from cpl.configuration.configuration_model_abc import ConfigurationModelABC
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl_cli.configuration.version_settings import VersionSettings
+from cpl_cli.configuration.project_settings_name_enum import ProjectSettingsNameEnum
+from cpl_cli.error import Error
+
+
+class ProjectSettings(ConfigurationModelABC):
+
+ def __init__(self):
+ ConfigurationModelABC.__init__(self)
+
+ self._name: Optional[str] = None
+ self._version: Optional[VersionSettings] = VersionSettings()
+ self._author: Optional[str] = None
+ self._author_email: Optional[str] = None
+ self._description: Optional[str] = None
+ self._long_description: Optional[str] = None
+ self._url: Optional[str] = None
+ self._copyright_date: Optional[str] = None
+ self._copyright_name: Optional[str] = None
+ self._license_name: Optional[str] = None
+ self._license_description: Optional[str] = None
+ self._dependencies: Optional[list[str]] = None
+ self._python_version: Optional[str] = None
+ self._python_path: Optional[str] = None
+ self._python_executable: Optional[str] = None
+ self._classifiers: Optional[list[str]] = None
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def version(self) -> VersionSettings:
+ return self._version
+
+ @property
+ def author(self) -> str:
+ return self._author
+
+ @property
+ def author_email(self) -> str:
+ return self._author_email
+
+ @property
+ def description(self) -> str:
+ return self._description
+
+ @property
+ def long_description(self) -> str:
+ return self._long_description
+
+ @property
+ def url(self) -> str:
+ return self._url
+
+ @property
+ def copyright_date(self) -> str:
+ return self._copyright_date
+
+ @property
+ def copyright_name(self) -> str:
+ return self._copyright_name
+
+ @property
+ def license_name(self) -> str:
+ return self._license_name
+
+ @property
+ def license_description(self) -> str:
+ return self._license_description
+
+ @property
+ def dependencies(self) -> list[str]:
+ return self._dependencies
+
+ @property
+ def python_version(self) -> str:
+ return self._python_version
+
+ @property
+ def python_path(self) -> str:
+ return self._python_path
+
+ @property
+ def python_executable(self) -> str:
+ return self._python_executable
+
+ @property
+ def classifiers(self) -> list[str]:
+ return self._classifiers
+
+ def from_dict(self, settings: dict):
+ try:
+ self._name = settings[ProjectSettingsNameEnum.name.value]
+ self._version.from_dict(settings[ProjectSettingsNameEnum.version.value])
+ self._author = settings[ProjectSettingsNameEnum.author.value]
+ self._author_email = settings[ProjectSettingsNameEnum.author_email.value]
+ self._description = settings[ProjectSettingsNameEnum.description.value]
+ self._long_description = settings[ProjectSettingsNameEnum.long_description.value]
+ self._url = settings[ProjectSettingsNameEnum.url.value]
+ self._copyright_date = settings[ProjectSettingsNameEnum.copyright_date.value]
+ self._copyright_name = settings[ProjectSettingsNameEnum.copyright_name.value]
+ self._license_name = settings[ProjectSettingsNameEnum.license_name.value]
+ self._license_description = settings[ProjectSettingsNameEnum.license_description.value]
+ self._dependencies = settings[ProjectSettingsNameEnum.dependencies.value]
+ self._python_version = settings[ProjectSettingsNameEnum.python_version.value]
+ self._python_path = settings[ProjectSettingsNameEnum.python_path.value]
+
+ if ProjectSettingsNameEnum.python_path.value in settings and \
+ sys.platform in settings[ProjectSettingsNameEnum.python_path.value]:
+ path = settings[ProjectSettingsNameEnum.python_path.value][sys.platform]
+ if not os.path.isfile(path) and not os.path.islink(path):
+ if path != '' and path is not None:
+ Error.warn(f'{ProjectSettingsNameEnum.python_path.value} not found')
+
+ path = sys.executable
+ else:
+ path = sys.executable
+
+ self._python_executable = path
+
+ self._classifiers = settings[ProjectSettingsNameEnum.classifiers.value]
+ except Exception as e:
+ Console.set_foreground_color(ForegroundColorEnum.red)
+ Console.write_line(
+ f'[ ERROR ] [ {__name__} ]: Reading error in {ProjectSettings.__name__} settings')
+ Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
+ Console.set_foreground_color(ForegroundColorEnum.default)
diff --git a/src/cpl_cli/configuration/project_settings_name_enum.py b/src/cpl_cli/configuration/project_settings_name_enum.py
new file mode 100644
index 00000000..7b4b6557
--- /dev/null
+++ b/src/cpl_cli/configuration/project_settings_name_enum.py
@@ -0,0 +1,19 @@
+from enum import Enum
+
+
+class ProjectSettingsNameEnum(Enum):
+ name = 'Name'
+ version = 'Version'
+ author = 'Author'
+ author_email = 'AuthorEmail'
+ description = 'Description'
+ long_description = 'LongDescription'
+ url = 'URL'
+ copyright_date = 'CopyrightDate'
+ copyright_name = 'CopyrightName'
+ license_name = 'LicenseName'
+ license_description = 'LicenseDescription'
+ dependencies = 'Dependencies'
+ python_version = 'PythonVersion'
+ python_path = 'PythonPath'
+ classifiers = 'Classifiers'
diff --git a/src/cpl_cli/configuration/project_type_enum.py b/src/cpl_cli/configuration/project_type_enum.py
new file mode 100644
index 00000000..9471c59c
--- /dev/null
+++ b/src/cpl_cli/configuration/project_type_enum.py
@@ -0,0 +1,7 @@
+from enum import Enum
+
+
+class ProjectTypeEnum(Enum):
+
+ console = 'console'
+ library = 'library'
diff --git a/src/cpl_cli/configuration/settings_helper.py b/src/cpl_cli/configuration/settings_helper.py
new file mode 100644
index 00000000..e4229445
--- /dev/null
+++ b/src/cpl_cli/configuration/settings_helper.py
@@ -0,0 +1,46 @@
+from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum
+from cpl_cli.configuration.build_settings import BuildSettings
+from cpl_cli.configuration.build_settings_name_enum import BuildSettingsNameEnum
+from cpl_cli.configuration.project_settings import ProjectSettings
+from cpl_cli.configuration.project_settings_name_enum import ProjectSettingsNameEnum
+
+
+class SettingsHelper:
+
+ @staticmethod
+ def get_project_settings_dict(project: ProjectSettings) -> dict:
+ return {
+ ProjectSettingsNameEnum.name.value: project.name,
+ ProjectSettingsNameEnum.version.value: {
+ VersionSettingsNameEnum.major.value: project.version.major,
+ VersionSettingsNameEnum.minor.value: project.version.minor,
+ VersionSettingsNameEnum.micro.value: project.version.micro
+ },
+ ProjectSettingsNameEnum.author.value: project.author,
+ ProjectSettingsNameEnum.author_email.value: project.author_email,
+ ProjectSettingsNameEnum.description.value: project.description,
+ ProjectSettingsNameEnum.long_description.value: project.long_description,
+ ProjectSettingsNameEnum.url.value: project.url,
+ ProjectSettingsNameEnum.copyright_date.value: project.copyright_date,
+ ProjectSettingsNameEnum.copyright_name.value: project.copyright_name,
+ ProjectSettingsNameEnum.license_name.value: project.license_name,
+ ProjectSettingsNameEnum.license_description.value: project.license_description,
+ ProjectSettingsNameEnum.dependencies.value: project.dependencies,
+ ProjectSettingsNameEnum.python_version.value: project.python_version,
+ ProjectSettingsNameEnum.python_path.value: project.python_path,
+ ProjectSettingsNameEnum.classifiers.value: project.classifiers
+ }
+
+ @staticmethod
+ def get_build_settings_dict(build: BuildSettings) -> dict:
+ return {
+ BuildSettingsNameEnum.project_type.value: build.project_type,
+ BuildSettingsNameEnum.source_path.value: build.source_path,
+ BuildSettingsNameEnum.output_path.value: build.output_path,
+ BuildSettingsNameEnum.main.value: build.main,
+ BuildSettingsNameEnum.entry_point.value: build.entry_point,
+ BuildSettingsNameEnum.include_package_data.value: build.include_package_data,
+ BuildSettingsNameEnum.included.value: build.included,
+ BuildSettingsNameEnum.excluded.value: build.excluded,
+ BuildSettingsNameEnum.package_data.value: build.package_data
+ }
diff --git a/src/cpl_cli/configuration/version_settings.py b/src/cpl_cli/configuration/version_settings.py
new file mode 100644
index 00000000..3d64d71e
--- /dev/null
+++ b/src/cpl_cli/configuration/version_settings.py
@@ -0,0 +1,46 @@
+from typing import Optional
+
+from cpl.configuration.configuration_model_abc import ConfigurationModelABC
+from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum
+
+
+class VersionSettings(ConfigurationModelABC):
+
+ def __init__(
+ self,
+ major: str = None,
+ minor: str = None,
+ micro: str = None
+ ):
+ ConfigurationModelABC.__init__(self)
+
+ self._major: Optional[str] = major
+ self._minor: Optional[str] = minor
+ self._micro: Optional[str] = micro
+
+ @property
+ def major(self) -> str:
+ return self._major
+
+ @property
+ def minor(self) -> str:
+ return self._minor
+
+ @property
+ def micro(self) -> str:
+ return self._micro
+
+ def to_str(self) -> str:
+ return f'{self._major}.{self._minor}.{self._micro}'
+
+ def from_dict(self, settings: dict):
+ self._major = settings[VersionSettingsNameEnum.major.value]
+ self._minor = settings[VersionSettingsNameEnum.minor.value]
+ self._micro = settings[VersionSettingsNameEnum.micro.value]
+
+ def to_dict(self) -> dict:
+ return {
+ VersionSettingsNameEnum.major.value: self._major,
+ VersionSettingsNameEnum.minor.value: self._minor,
+ VersionSettingsNameEnum.micro.value: self._micro
+ }
diff --git a/src/cpl_cli/configuration/version_settings_name_enum.py b/src/cpl_cli/configuration/version_settings_name_enum.py
new file mode 100644
index 00000000..23eab9e1
--- /dev/null
+++ b/src/cpl_cli/configuration/version_settings_name_enum.py
@@ -0,0 +1,8 @@
+from enum import Enum
+
+
+class VersionSettingsNameEnum(Enum):
+
+ major = 'Major'
+ minor = 'Minor'
+ micro = 'Micro'
diff --git a/src/cpl_cli/error.py b/src/cpl_cli/error.py
new file mode 100644
index 00000000..e4bd7225
--- /dev/null
+++ b/src/cpl_cli/error.py
@@ -0,0 +1,17 @@
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.console.console import Console
+
+
+class Error:
+
+ @staticmethod
+ def error(message: str):
+ Console.error(message)
+ Console.error('Run \'cpl help\'\n')
+
+ @staticmethod
+ def warn(message: str):
+ Console.set_foreground_color(ForegroundColorEnum.yellow)
+ Console.write_line(message)
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
diff --git a/src/cpl_cli/live_server/__init__.py b/src/cpl_cli/live_server/__init__.py
new file mode 100644
index 00000000..aeb9ebfb
--- /dev/null
+++ b/src/cpl_cli/live_server/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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.live_server'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/live_server/live_server_service.py b/src/cpl_cli/live_server/live_server_service.py
new file mode 100644
index 00000000..9005ae50
--- /dev/null
+++ b/src/cpl_cli/live_server/live_server_service.py
@@ -0,0 +1,84 @@
+import os
+import time
+from contextlib import suppress
+
+import psutil as psutil
+from watchdog.events import FileSystemEventHandler
+from watchdog.observers import Observer
+
+from cpl.console.console import Console
+from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
+from cpl_cli.configuration.build_settings import BuildSettings
+from cpl_cli.live_server.live_server_thread import LiveServerThread
+
+
+class LiveServerService(FileSystemEventHandler):
+
+ def __init__(self, env: ApplicationEnvironmentABC, build_settings: BuildSettings):
+ """
+ Service for the live development server
+ :param env:
+ :param build_settings:
+ """
+ FileSystemEventHandler.__init__(self)
+
+ self._env = env
+ self._build_settings = build_settings
+
+ self._src_dir = os.path.join(self._env.working_directory, self._build_settings.source_path)
+ self._ls_thread = None
+ self._observer = None
+
+ def _start_observer(self):
+ """
+ Starts the file changes observer
+ :return:
+ """
+ self._observer = Observer()
+ self._observer.schedule(self, path=self._src_dir, recursive=True)
+ self._observer.start()
+
+ def _restart(self):
+ """
+ Restarts the CPL project
+ :return:
+ """
+ for proc in psutil.process_iter():
+ with suppress(Exception):
+ if proc.cmdline() == self._ls_thread.command:
+ proc.kill()
+
+ Console.write_line('Restart\n')
+ while self._ls_thread.is_alive():
+ time.sleep(1)
+
+ self._start()
+
+ def on_modified(self, event):
+ """
+ Triggers when source file is modified
+ :param event:
+ :return:
+ """
+ if event.is_directory:
+ return None
+
+ # Event is modified, you can process it now
+ if str(event.src_path).endswith('.py'):
+ self._observer.stop()
+ self._restart()
+
+ def _start(self):
+ self._start_observer()
+ self._ls_thread = LiveServerThread(self._src_dir, self._build_settings)
+ self._ls_thread.start()
+ self._ls_thread.join()
+ Console.close()
+
+ def start(self):
+ """
+ Starts the CPL live development server
+ :return:
+ """
+ Console.write_line('** CPL live development server is running **')
+ self._start()
diff --git a/src/cpl_cli/live_server/live_server_thread.py b/src/cpl_cli/live_server/live_server_thread.py
new file mode 100644
index 00000000..172d4e0d
--- /dev/null
+++ b/src/cpl_cli/live_server/live_server_thread.py
@@ -0,0 +1,62 @@
+import os
+import subprocess
+import sys
+import threading
+from datetime import datetime
+
+from cpl.console.console import Console
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl_cli.configuration import BuildSettings
+
+
+class LiveServerThread(threading.Thread):
+
+ def __init__(self, path: str, build_settings: BuildSettings):
+ """
+ Thread to start the CPL project for the live development server
+ :param path:
+ """
+ threading.Thread.__init__(self)
+
+ self._path = path
+ self._build_settings = build_settings
+
+ self._main = ''
+ self._command = []
+
+ @property
+ def command(self) -> list[str]:
+ return self._command
+
+ @property
+ def main(self) -> str:
+ return self._main
+
+ def run(self):
+ """
+ Starts the CPL project
+ :return:
+ """
+ main = self._build_settings.main.replace('.', '/')
+ self._main = os.path.join(self._path, f'{main}.py')
+ if not os.path.isfile(self._main):
+ Console.error('Entry point main.py not found')
+ return
+
+ Console.set_foreground_color(ForegroundColorEnum.green)
+ Console.write_line('Read successfully')
+ Console.set_foreground_color(ForegroundColorEnum.cyan)
+ now = datetime.now()
+ Console.write_line(f'Started at {now.strftime("%Y-%m-%d %H:%M:%S")}\n\n')
+ Console.set_foreground_color(ForegroundColorEnum.default)
+
+ env_vars = os.environ
+ if sys.platform == 'win32':
+ env_vars['PYTHONPATH'] = f'{os.path.dirname(self._path)};' \
+ f'{os.path.join(os.path.dirname(self._path), self._build_settings.source_path)}'
+ else:
+ env_vars['PYTHONPATH'] = f'{os.path.dirname(self._path)}:' \
+ f'{os.path.join(os.path.dirname(self._path), self._build_settings.source_path)}'
+
+ self._command = [sys.executable, self._main, ''.join(sys.argv[2:])]
+ subprocess.run(self._command, env=env_vars)
diff --git a/src/cpl_cli/main.py b/src/cpl_cli/main.py
new file mode 100644
index 00000000..71024452
--- /dev/null
+++ b/src/cpl_cli/main.py
@@ -0,0 +1,13 @@
+from cpl.application.application_builder import ApplicationBuilder
+from cpl_cli.cli import CLI
+from cpl_cli.startup import Startup
+
+
+def main():
+ app_builder = ApplicationBuilder(CLI)
+ app_builder.use_startup(Startup)
+ app_builder.build().run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/cpl_cli/publish/__init__.py b/src/cpl_cli/publish/__init__.py
new file mode 100644
index 00000000..bd94bec5
--- /dev/null
+++ b/src/cpl_cli/publish/__init__.py
@@ -0,0 +1,27 @@
+# -*- 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.publish'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+from .publisher_abc import PublisherABC
+from .publisher_service import PublisherService
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/sh_edraft/publish/base/publisher_base.py b/src/cpl_cli/publish/publisher_abc.py
similarity index 71%
rename from src/sh_edraft/publish/base/publisher_base.py
rename to src/cpl_cli/publish/publisher_abc.py
index 092dec3d..c33ed644 100644
--- a/src/sh_edraft/publish/base/publisher_base.py
+++ b/src/cpl_cli/publish/publisher_abc.py
@@ -1,13 +1,11 @@
-from abc import abstractmethod
-
-from sh_edraft.service.base.service_base import ServiceBase
+from abc import abstractmethod, ABC
-class PublisherBase(ServiceBase):
+class PublisherABC(ABC):
@abstractmethod
def __init__(self):
- ServiceBase.__init__(self)
+ ABC.__init__(self)
@property
@abstractmethod
diff --git a/src/cpl_cli/publish/publisher_service.py b/src/cpl_cli/publish/publisher_service.py
new file mode 100644
index 00000000..95f8e0cc
--- /dev/null
+++ b/src/cpl_cli/publish/publisher_service.py
@@ -0,0 +1,447 @@
+import os
+import shutil
+import sys
+from string import Template as stringTemplate
+
+import setuptools
+from packaging import version
+from setuptools import sandbox
+
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.console.console import Console
+from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
+from cpl_cli.configuration.build_settings import BuildSettings
+from cpl_cli.configuration.project_settings import ProjectSettings
+from cpl_cli.publish.publisher_abc import PublisherABC
+from cpl_cli.templates.build.init_template import InitTemplate
+from cpl_cli.templates.publish.setup_template import SetupTemplate
+
+
+class PublisherService(PublisherABC):
+
+ def __init__(self, env: ApplicationEnvironmentABC, project: ProjectSettings, build: BuildSettings):
+ """
+ Service to build or publish files for distribution
+ :param env:
+ :param project:
+ :param build:
+ """
+ PublisherABC.__init__(self)
+
+ self._env = env
+ self._project_settings = project
+ self._build_settings = build
+
+ self._source_path = os.path.join(self._env.working_directory, self._build_settings.source_path)
+ self._output_path = os.path.join(self._env.working_directory, self._build_settings.output_path)
+
+ self._included_files: list[str] = []
+ self._included_dirs: list[str] = []
+ self._distributed_files: list[str] = []
+
+ self._path_mark = '/'
+ if sys.platform == 'win32':
+ self._path_mark = '\\'
+
+ self._src_path_part = f'src{self._path_mark}'
+
+ @property
+ def source_path(self) -> str:
+ return self._source_path
+
+ @property
+ def dist_path(self) -> str:
+ return self._output_path
+
+ def _get_module_name_from_dirs(self, file: str) -> str:
+ """
+ Extracts module name from directories
+ :param file:
+ :return:
+ """
+ if self._src_path_part in file:
+ file = file.replace(self._src_path_part, '', 1)
+
+ dirs = os.path.dirname(file).split(self._path_mark)
+ for d in dirs:
+ if d.__contains__('.'):
+ dirs.remove(d)
+
+ if len(dirs) == 0:
+ return os.path.basename(file)
+ else:
+ return '.'.join(dirs)
+
+ @staticmethod
+ def _delete_path(path: str):
+ """
+ Deletes full path tree
+ :param path:
+ :return:
+ """
+ if os.path.isdir(path):
+ try:
+ shutil.rmtree(path)
+ except Exception as e:
+ Console.error(f'{e}')
+ exit()
+
+ @staticmethod
+ def _create_path(path: str):
+ """
+ Creates full path tree
+ :param path:
+ :return:
+ """
+ if not os.path.isdir(path):
+ try:
+ os.makedirs(path)
+ except Exception as e:
+ Console.error(f'{e}')
+ exit()
+
+ def _is_path_included(self, path: str) -> bool:
+ """
+ Checks if the path is included
+ :param path:
+ :return:
+ """
+ for included in self._build_settings.included:
+ if included.startswith('*'):
+ included = included.replace('*', '')
+
+ if included in path and path not in self._build_settings.excluded:
+ return True
+
+ return False
+
+ def _is_path_excluded(self, path: str) -> bool:
+ """
+ Checks if the path is excluded
+ :param path:
+ :return:
+ """
+ for excluded in self._build_settings.excluded:
+ if excluded.startswith('*'):
+ excluded = excluded.replace('*', '')
+
+ if excluded in path and not self._is_path_included(path):
+ return True
+
+ return False
+
+ def _read_sources(self):
+ """
+ Reads all source files and save included files
+ :return:
+ """
+ for file in self._build_settings.included:
+ rel_path = os.path.relpath(file)
+ if os.path.isdir(rel_path):
+ for r, d, f in os.walk(rel_path):
+ for sub_file in f:
+ relative_path = os.path.relpath(r)
+ file_path = os.path.join(relative_path, os.path.relpath(sub_file))
+
+ self._included_files.append(os.path.relpath(file_path))
+
+ elif os.path.isfile(rel_path):
+ self._included_files.append(rel_path)
+
+ for r, d, f in os.walk(self._build_settings.source_path):
+ for file in f:
+ relative_path = os.path.relpath(r)
+ file_path = os.path.join(relative_path, os.path.relpath(file))
+ if self._is_path_excluded(relative_path):
+ break
+
+ 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 _create_packages(self):
+ """
+ Writes information from template to all included __init__.py
+ :return:
+ """
+ for file in self._included_files:
+ if file.endswith('__init__.py'):
+ template_content = ''
+ module_file_lines: list[str] = []
+
+ title = self._get_module_name_from_dirs(file)
+ if title == '':
+ title = self._project_settings.name
+ elif not title.__contains__('.'):
+ title = f'{self._project_settings.name}.{title}'
+
+ module_py_lines: list[str] = []
+ imports = ''
+
+ with open(file, 'r') as py_file:
+ module_file_lines = py_file.readlines()
+ py_file.close()
+
+ if len(module_file_lines) == 0:
+ imports = '# imports:'
+ else:
+ is_started = False
+ for line in module_file_lines:
+ if line.__contains__('# imports'):
+ is_started = True
+
+ if (line.__contains__('from') or line.__contains__('import')) and is_started:
+ module_py_lines.append(line.replace('\n', ''))
+
+ if len(module_py_lines) > 0:
+ imports = '\n'.join(module_py_lines)
+
+ template_content = stringTemplate(InitTemplate.get_init_py()).substitute(
+ Name=self._project_settings.name,
+ Description=self._project_settings.description,
+ LongDescription=self._project_settings.long_description,
+ CopyrightDate=self._project_settings.copyright_date,
+ CopyrightName=self._project_settings.copyright_name,
+ LicenseName=self._project_settings.license_name,
+ LicenseDescription=self._project_settings.license_description,
+ Title=title if title is not None and title != '' else self._project_settings.name,
+ Author=self._project_settings.author,
+ Version=version.parse(self._project_settings.version.to_str()),
+ Major=self._project_settings.version.major,
+ Minor=self._project_settings.version.minor,
+ Micro=self._project_settings.version.micro,
+ Imports=imports
+ )
+
+ with open(file, 'w+') as py_file:
+ py_file.write(template_content)
+ py_file.close()
+
+ def _dist_files(self):
+ """
+ Copies all included source files to dist_path
+ :return:
+ """
+ build_path = os.path.join(self._output_path)
+ self._delete_path(build_path)
+ self._create_path(build_path)
+
+ for file in self._included_files:
+ dist_file = file
+ if self._src_path_part in dist_file:
+ dist_file = dist_file.replace(self._src_path_part, '', 1)
+
+ output_path = os.path.join(build_path, os.path.dirname(dist_file))
+ output_file = os.path.join(build_path, dist_file)
+
+ try:
+ if not os.path.isdir(output_path):
+ os.makedirs(output_path, exist_ok=True)
+ except Exception as e:
+ Console.error(__name__, f'Cannot create directories: {output_path} -> {e}')
+ return
+
+ try:
+ self._distributed_files.append(output_file)
+ shutil.copy(os.path.abspath(file), output_file)
+ except Exception as e:
+ Console.error(__name__, f'Cannot copy file: {file} to {output_path} -> {e}')
+ return
+
+ for empty_dir in self._included_dirs:
+ dist_dir = empty_dir
+ if self._src_path_part in dist_dir:
+ dist_dir = dist_dir.replace(self._src_path_part, '', 1)
+
+ output_path = os.path.join(build_path, dist_dir)
+ if not os.path.isdir(output_path):
+ os.makedirs(output_path)
+
+ def _clean_dist_files(self):
+ """
+ Deletes all included source files from dist_path
+ :return:
+ """
+ paths: list[str] = []
+ for file in self._distributed_files:
+ paths.append(os.path.dirname(file))
+
+ if os.path.isfile(file):
+ os.remove(file)
+
+ for path in paths:
+ if path != self._output_path and os.path.isdir(path):
+ shutil.rmtree(path)
+
+ def _create_setup(self):
+ """
+ Generates setup.py
+
+ Dependencies: ProjectSettings, BuildSettings
+ :return:
+ """
+ setup_file = os.path.join(self._output_path, 'setup.py')
+ if os.path.isfile(setup_file):
+ os.remove(setup_file)
+
+ main = None
+ try:
+ main_name = self._build_settings.main
+
+ if '.' in self._build_settings.main:
+ length = len(self._build_settings.main.split('.'))
+ main_name = self._build_settings.main.split('.')[length - 1]
+
+ sys.path.insert(0, self._source_path)
+ main_mod = __import__(self._build_settings.main)
+ main = getattr(main_mod, main_name)
+ except Exception as e:
+ Console.error('Could not find entry point', str(e))
+ return
+
+ if main is None or not callable(main) and not hasattr(main, 'main'):
+ Console.error('Could not find entry point')
+ return
+
+ if callable(main):
+ mod_name = main.__module__
+ func_name = main.__name__
+ else:
+ mod_name = main.__name__
+ func_name = main.main.__name__
+
+ with open(setup_file, 'w+') as setup_py:
+ setup_string = stringTemplate(SetupTemplate.get_setup_py()).substitute(
+ Name=self._project_settings.name,
+ Version=self._project_settings.version.to_str(),
+ Packages=setuptools.find_packages(where=self._output_path, exclude=self._build_settings.excluded),
+ URL=self._project_settings.url,
+ LicenseName=self._project_settings.license_name,
+ Author=self._project_settings.author,
+ AuthorMail=self._project_settings.author_email,
+ IncludePackageData=self._build_settings.include_package_data,
+ Description=self._project_settings.description,
+ PyRequires=self._project_settings.python_version,
+ Dependencies=self._project_settings.dependencies,
+ EntryPoints={
+ 'console_scripts': [
+ f'{self._build_settings.entry_point} = {mod_name}:{func_name}'
+ ]
+ },
+ PackageData=self._build_settings.package_data
+ )
+ setup_py.write(setup_string)
+ setup_py.close()
+
+ def _run_setup(self):
+ """
+ Starts setup.py
+ :return:
+ """
+ setup_py = os.path.join(self._output_path, 'setup.py')
+ if not os.path.isfile(setup_py):
+ Console.error(__name__, f'setup.py not found in {self._output_path}')
+ return
+
+ try:
+ sandbox.run_setup(os.path.abspath(setup_py), [
+ 'sdist',
+ f'--dist-dir={os.path.join(self._output_path, "setup")}',
+ 'bdist_wheel',
+ f'--bdist-dir={os.path.join(self._output_path, "bdist")}',
+ f'--dist-dir={os.path.join(self._output_path, "setup")}'
+ ])
+ os.remove(setup_py)
+ except Exception as e:
+ Console.error('Executing setup.py failed', str(e))
+
+ def include(self, path: str):
+ """
+ Includes given path from sources
+ :param path:
+ :return:
+ """
+ self._build_settings.included.append(path)
+
+ def exclude(self, path: str):
+ """
+ Excludes given path from sources
+ :param path:
+ :return:
+ """
+ self._build_settings.excluded.append(path)
+
+ def build(self):
+ """
+ Build the CPL project to dist_path/build
+
+ 1. Reads all included source files
+ 2. Writes informations from template to all included __init__.py
+ 3. Copies all included source files to dist_path/build
+ :return:
+ """
+ self._output_path = os.path.join(self._output_path, 'build')
+
+ Console.spinner('Reading source files:', self._read_sources, text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.blue)
+ Console.spinner('Creating internal packages:', self._create_packages,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.blue)
+ Console.spinner('Building application:', self._dist_files, text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.blue)
+
+ def publish(self):
+ """
+ Publishes the CPL project to dist_path/publish
+
+ 1. Builds the project
+ 2. Generates setup.py
+ 3. Start setup.py
+ 4. Remove all included source from dist_path/publish
+ :return:
+ """
+ self._output_path = os.path.join(self._output_path, 'publish')
+
+ Console.write_line('Build:')
+ Console.spinner(
+ 'Reading source files:',
+ self._read_sources,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.blue
+ )
+
+ Console.spinner(
+ 'Creating internal packages:',
+ self._create_packages,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.blue
+ )
+
+ Console.spinner(
+ 'Building application:',
+ self._dist_files,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.blue
+ )
+
+ Console.write_line('\nPublish:')
+ Console.spinner(
+ 'Generating setup.py:',
+ self._create_setup,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.blue
+ )
+
+ Console.write_line('Running setup.py:\n')
+ self._run_setup()
+ Console.spinner(
+ 'Cleaning dist path:',
+ self._clean_dist_files,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.blue
+ )
diff --git a/src/cpl_cli/source_creator/__init__.py b/src/cpl_cli/source_creator/__init__.py
new file mode 100644
index 00000000..2b9b45a1
--- /dev/null
+++ b/src/cpl_cli/source_creator/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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.source_creator'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/source_creator/console_builder.py b/src/cpl_cli/source_creator/console_builder.py
new file mode 100644
index 00000000..8d6ad878
--- /dev/null
+++ b/src/cpl_cli/source_creator/console_builder.py
@@ -0,0 +1,73 @@
+import json
+import os
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.console.console import Console
+from cpl_cli.source_creator.template_builder import TemplateBuilder
+from cpl_cli.templates.new.console.appsettings_json import AppsettingsTemplate
+from cpl_cli.templates.new.console.license import LicenseTemplate
+from cpl_cli.templates.new.console.readme_py import ReadmeTemplate
+from cpl_cli.templates.new.console.src.name.application import ApplicationTemplate
+from cpl_cli.templates.new.console.src.name.init import MainInitTemplate
+from cpl_cli.templates.new.console.src.name.main import MainWithApplicationHostAndStartupTemplate, \
+ MainWithoutApplicationBaseTemplate, MainWithApplicationBaseTemplate, MainWithDependencyInjection
+from cpl_cli.templates.new.console.src.name.startup import StartupTemplate
+from cpl_cli.templates.new.console.src.tests.init import TestsInitTemplate
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class ConsoleBuilder:
+
+ def __init__(self):
+ pass
+
+ @staticmethod
+ def build(project_path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool,
+ project_name: str, project_settings: dict):
+ """
+ Builds the console project files
+ :param project_path:
+ :param use_application_api:
+ :param use_startup:
+ :param use_service_providing:
+ :param project_name:
+ :param project_settings:
+ :return:
+ """
+ if not os.path.isdir(project_path):
+ os.makedirs(project_path)
+
+ with open(os.path.join(project_path, 'cpl.json'), 'w') as project_json:
+ project_json.write(json.dumps(project_settings, indent=2))
+ project_json.close()
+
+ templates: list[TemplateFileABC] = [
+ LicenseTemplate(),
+ ReadmeTemplate(),
+ TestsInitTemplate(),
+ AppsettingsTemplate(),
+ MainInitTemplate(project_name)
+ ]
+
+ if use_application_api:
+ templates.append(ApplicationTemplate(project_name))
+
+ if use_startup:
+ templates.append(StartupTemplate(project_name))
+ templates.append(MainWithApplicationHostAndStartupTemplate(project_name))
+ else:
+ templates.append(MainWithApplicationBaseTemplate(project_name))
+ else:
+ if use_service_providing:
+ templates.append(MainWithDependencyInjection(project_name))
+ else:
+ templates.append(MainWithoutApplicationBaseTemplate(project_name))
+
+ for template in templates:
+ Console.spinner(
+ f'Creating {project_name}/{template.path}{template.name}',
+ TemplateBuilder.build,
+ project_path,
+ template,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.cyan
+ )
diff --git a/src/cpl_cli/source_creator/library_builder.py b/src/cpl_cli/source_creator/library_builder.py
new file mode 100644
index 00000000..bc22ccc4
--- /dev/null
+++ b/src/cpl_cli/source_creator/library_builder.py
@@ -0,0 +1,73 @@
+import json
+import os
+from cpl.console.foreground_color_enum import ForegroundColorEnum
+from cpl.console.console import Console
+from cpl_cli.source_creator.template_builder import TemplateBuilder
+from cpl_cli.templates.new.library.appsettings_json import AppsettingsTemplate
+from cpl_cli.templates.new.library.license import LicenseTemplate
+from cpl_cli.templates.new.library.readme_py import ReadmeTemplate
+from cpl_cli.templates.new.library.src.cli.application import ApplicationTemplate
+from cpl_cli.templates.new.library.src.cli.init import CLIInitTemplate
+from cpl_cli.templates.new.library.src.cli.main import MainWithApplicationHostAndStartupTemplate, \
+ MainWithoutApplicationBaseTemplate, MainWithApplicationBaseTemplate, MainWithDependencyInjection
+from cpl_cli.templates.new.library.src.cli.startup import StartupTemplate
+from cpl_cli.templates.new.library.src.tests.init import TestsInitTemplate
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class LibraryBuilder:
+
+ def __init__(self):
+ pass
+
+ @staticmethod
+ def build(project_path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool,
+ project_name: str, project_settings: dict):
+ """
+ Builds the library project files
+ :param project_path:
+ :param use_application_api:
+ :param use_startup:
+ :param use_service_providing:
+ :param project_name:
+ :param project_settings:
+ :return:
+ """
+ if not os.path.isdir(project_path):
+ os.makedirs(project_path)
+
+ with open(os.path.join(project_path, 'cpl.json'), 'w') as project_json:
+ project_json.write(json.dumps(project_settings, indent=2))
+ project_json.close()
+
+ templates: list[TemplateFileABC] = [
+ LicenseTemplate(),
+ ReadmeTemplate(),
+ TestsInitTemplate(),
+ CLIInitTemplate(project_name),
+ AppsettingsTemplate()
+ ]
+
+ if use_application_api:
+ templates.append(ApplicationTemplate(project_name))
+
+ if use_startup:
+ templates.append(StartupTemplate(project_name))
+ templates.append(MainWithApplicationHostAndStartupTemplate(project_name))
+ else:
+ templates.append(MainWithApplicationBaseTemplate())
+ else:
+ if use_service_providing:
+ templates.append(MainWithDependencyInjection())
+ else:
+ templates.append(MainWithoutApplicationBaseTemplate())
+
+ for template in templates:
+ Console.spinner(
+ f'Creating {project_name}/{template.path}{template.name}',
+ TemplateBuilder.build,
+ project_path,
+ template,
+ text_foreground_color=ForegroundColorEnum.green,
+ spinner_foreground_color=ForegroundColorEnum.cyan
+ )
diff --git a/src/cpl_cli/source_creator/template_builder.py b/src/cpl_cli/source_creator/template_builder.py
new file mode 100644
index 00000000..1ccfbce0
--- /dev/null
+++ b/src/cpl_cli/source_creator/template_builder.py
@@ -0,0 +1,24 @@
+import os
+
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class TemplateBuilder:
+
+ @staticmethod
+ def build(project_path: str, template: TemplateFileABC):
+ """
+ Creates template
+ :param project_path:
+ :param template:
+ :return:
+ """
+ file_path = os.path.join(project_path, template.path, template.name)
+ file_rel_path = os.path.join(project_path, template.path)
+
+ if not os.path.isdir(file_rel_path):
+ os.makedirs(file_rel_path)
+
+ with open(file_path, 'w') as license_file:
+ license_file.write(template.value)
+ license_file.close()
diff --git a/src/cpl_cli/startup.py b/src/cpl_cli/startup.py
new file mode 100644
index 00000000..f05fe10a
--- /dev/null
+++ b/src/cpl_cli/startup.py
@@ -0,0 +1,84 @@
+from cpl.application.startup_abc import StartupABC
+from cpl.configuration.console_argument import ConsoleArgument
+from cpl.configuration.configuration_abc import ConfigurationABC
+from cpl.dependency_injection.service_collection_abc import ServiceCollectionABC
+from cpl.dependency_injection.service_provider_abc import ServiceProviderABC
+from cpl_cli.command.build_service import BuildService
+from cpl_cli.command.generate_service import GenerateService
+from cpl_cli.command.install_service import InstallService
+from cpl_cli.command.new_service import NewService
+from cpl_cli.command.publish_service import PublishService
+from cpl_cli.command.start_service import StartService
+from cpl_cli.command.uninstall_service import UninstallService
+from cpl_cli.command.update_service import UpdateService
+from cpl_cli.command_handler_service import CommandHandler
+from cpl_cli.command.help_service import HelpService
+from cpl_cli.command.version_service import VersionService
+from cpl_cli.error import Error
+from cpl_cli.live_server.live_server_service import LiveServerService
+from cpl_cli.publish.publisher_service import PublisherService
+from cpl_cli.publish.publisher_abc import PublisherABC
+
+
+class Startup(StartupABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceCollectionABC):
+ StartupABC.__init__(self)
+
+ self._configuration = config
+ self._env = self._configuration.environment
+ self._services = services
+
+ self._env.set_runtime_directory(__file__)
+
+ def configure_configuration(self) -> ConfigurationABC:
+ self._configuration.argument_error_function = Error.error
+
+ self._configuration.add_environment_variables('PYTHON_')
+ self._configuration.add_environment_variables('CPL_')
+ self._configuration.add_json_file('appsettings.json', path=self._env.runtime_directory,
+ optional=False, output=False)
+ self._configuration.add_console_argument(ConsoleArgument('', 'build', ['b', 'B'], ''))
+ self._configuration.add_console_argument(ConsoleArgument('', 'generate', ['g', 'G'], '', console_arguments=[
+ ConsoleArgument('', 'abc', ['a', 'A'], ' '),
+ ConsoleArgument('', 'class', ['c', 'C'], ' '),
+ ConsoleArgument('', 'enum', ['e', 'E'], ' '),
+ ConsoleArgument('', 'service', ['s', 'S'], ' '),
+ ConsoleArgument('', 'settings', ['st', 'ST'], ' '),
+ ConsoleArgument('', 'thread', ['t', 't'], ' ')
+ ]))
+ self._configuration.add_console_argument(ConsoleArgument('', 'help', ['h', 'H'], ''))
+ self._configuration.add_console_argument(
+ ConsoleArgument('', 'install', ['i', 'I'], ' ', is_value_token_optional=True)
+ )
+ self._configuration.add_console_argument(ConsoleArgument('', 'new', ['n', 'N'], '', console_arguments=[
+ ConsoleArgument('', 'console', ['c', 'C'], ' '),
+ ConsoleArgument('', 'library', ['l', 'L'], ' ')
+ ]))
+ self._configuration.add_console_argument(ConsoleArgument('', 'publish', ['p', 'P'], ''))
+ self._configuration.add_console_argument(ConsoleArgument('', 'start', ['s', 'S'], ''))
+ self._configuration.add_console_argument(ConsoleArgument('', 'uninstall', ['ui', 'UI'], ' '))
+ self._configuration.add_console_argument(ConsoleArgument('', 'update', ['u', 'U'], ''))
+ self._configuration.add_console_argument(ConsoleArgument('', 'version', ['v', 'V'], ''))
+ self._configuration.add_console_arguments(error=False)
+
+ return self._configuration
+
+ def configure_services(self) -> ServiceProviderABC:
+ self._services.add_singleton(CommandHandler)
+
+ self._services.add_transient(PublisherABC, PublisherService)
+ self._services.add_transient(LiveServerService)
+
+ self._services.add_transient(BuildService)
+ self._services.add_transient(GenerateService)
+ self._services.add_transient(HelpService)
+ self._services.add_transient(InstallService)
+ self._services.add_transient(NewService)
+ self._services.add_transient(PublishService)
+ self._services.add_transient(StartService)
+ self._services.add_transient(UninstallService)
+ self._services.add_transient(UpdateService)
+ self._services.add_transient(VersionService)
+
+ return self._services.build_service_provider()
diff --git a/src/cpl_cli/templates/__init__.py b/src/cpl_cli/templates/__init__.py
new file mode 100644
index 00000000..978cc953
--- /dev/null
+++ b/src/cpl_cli/templates/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/build/__init__.py b/src/cpl_cli/templates/build/__init__.py
new file mode 100644
index 00000000..46603a05
--- /dev/null
+++ b/src/cpl_cli/templates/build/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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.build'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/build/init_template.py b/src/cpl_cli/templates/build/init_template.py
new file mode 100644
index 00000000..b6947e22
--- /dev/null
+++ b/src/cpl_cli/templates/build/init_template.py
@@ -0,0 +1,36 @@
+import textwrap
+
+
+class InitTemplate:
+
+ @staticmethod
+ def get_init_py() -> str:
+ string = textwrap.dedent("""\
+ # -*- coding: utf-8 -*-
+
+ \"\"\"
+ $Name $Description
+ ~~~~~~~~~~~~~~~~~~~
+
+ $LongDescription
+
+ :copyright: (c) $CopyrightDate $CopyrightName
+ :license: $LicenseDescription
+
+ \"\"\"
+
+ __title__ = '$Title'
+ __author__ = '$Author'
+ __license__ = '$LicenseName'
+ __copyright__ = 'Copyright (c) $CopyrightDate $CopyrightName'
+ __version__ = '$Version'
+
+ from collections import namedtuple
+
+ $Imports
+
+ VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+ version_info = VersionInfo(major='$Major', minor='$Minor', micro='$Micro')
+ """)
+
+ return string
diff --git a/src/cpl_cli/templates/generate/__init__.py b/src/cpl_cli/templates/generate/__init__.py
new file mode 100644
index 00000000..0d30d1c0
--- /dev/null
+++ b/src/cpl_cli/templates/generate/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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.generate'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/generate/abc_template.py b/src/cpl_cli/templates/generate/abc_template.py
new file mode 100644
index 00000000..cb6474a7
--- /dev/null
+++ b/src/cpl_cli/templates/generate/abc_template.py
@@ -0,0 +1,38 @@
+import textwrap
+from string import Template
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class ABCTemplate(TemplateFileABC):
+
+ def __init__(self, name: str, schematic: str, schematic_upper: str, path: str):
+ TemplateFileABC.__init__(self)
+
+ self._name = f'{String.convert_to_snake_case(name)}_{schematic}.py'
+ self._class_name = f'{String.first_to_upper(name)}{schematic_upper}'
+ self._path = path
+ self._value = textwrap.dedent("""\
+ from abc import ABC, abstractmethod
+
+
+ class $Name(ABC):
+
+ @abstractmethod
+ def __init__(self): pass
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return Template(self._value).substitute(
+ Name=self._class_name
+ )
diff --git a/src/cpl_cli/templates/generate/class_template.py b/src/cpl_cli/templates/generate/class_template.py
new file mode 100644
index 00000000..2c754027
--- /dev/null
+++ b/src/cpl_cli/templates/generate/class_template.py
@@ -0,0 +1,35 @@
+import textwrap
+from string import Template
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class ClassTemplate(TemplateFileABC):
+
+ def __init__(self, name: str, schematic: str, schematic_upper: str, path: str):
+ TemplateFileABC.__init__(self)
+
+ self._name = f'{String.convert_to_snake_case(name)}.py'
+ self._class_name = f'{String.first_to_upper(name)}'
+ self._path = path
+ self._value = textwrap.dedent("""\
+ class $Name:
+
+ def __init__(self):
+ pass
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return Template(self._value).substitute(
+ Name=self._class_name
+ )
diff --git a/src/cpl_cli/templates/generate/configmodel_template.py b/src/cpl_cli/templates/generate/configmodel_template.py
new file mode 100644
index 00000000..2c9461e1
--- /dev/null
+++ b/src/cpl_cli/templates/generate/configmodel_template.py
@@ -0,0 +1,54 @@
+import textwrap
+from string import Template
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class ConfigModelTemplate(TemplateFileABC):
+
+ def __init__(self, name: str, schematic: str, schematic_upper: str, path: str):
+ TemplateFileABC.__init__(self)
+
+ self._name = f'{String.convert_to_snake_case(name)}_{schematic}.py'
+ self._class_name = f'{String.first_to_upper(name)}{schematic_upper}'
+ self._path = path
+ self._value = textwrap.dedent("""\
+ import traceback
+
+ from cpl.configuration.configuration_model_abc import ConfigurationModelABC
+ from cpl.console import Console
+
+
+ class $Name(ConfigurationModelABC):
+
+ def __init__(self):
+ ConfigurationModelABC.__init__(self)
+
+ self._atr = ''
+
+ @property
+ def atr(self) -> str:
+ return self._atr
+
+ def from_dict(self, settings: dict):
+ try:
+ self._atr = settings['atr']
+ except Exception as e:
+ Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings')
+ Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return Template(self._value).substitute(
+ Name=self._class_name
+ )
diff --git a/src/cpl_cli/templates/generate/enum_template.py b/src/cpl_cli/templates/generate/enum_template.py
new file mode 100644
index 00000000..9cf20ab9
--- /dev/null
+++ b/src/cpl_cli/templates/generate/enum_template.py
@@ -0,0 +1,37 @@
+import textwrap
+from string import Template
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class EnumTemplate(TemplateFileABC):
+
+ def __init__(self, name: str, schematic: str, schematic_upper: str, path: str):
+ TemplateFileABC.__init__(self)
+
+ self._name = f'{String.convert_to_snake_case(name)}_{schematic}.py'
+ self._class_name = f'{String.first_to_upper(name)}{schematic_upper}'
+ self._path = path
+ self._value = textwrap.dedent("""\
+ from enum import Enum
+
+
+ class $Name(Enum):
+
+ atr = 0
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return Template(self._value).substitute(
+ Name=self._class_name
+ )
diff --git a/src/cpl_cli/templates/generate/init_template.py b/src/cpl_cli/templates/generate/init_template.py
new file mode 100644
index 00000000..59c0f0fa
--- /dev/null
+++ b/src/cpl_cli/templates/generate/init_template.py
@@ -0,0 +1,32 @@
+import textwrap
+from string import Template
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class InitTemplate(TemplateFileABC):
+
+ def __init__(self, name: str, schematic: str, schematic_upper: str, path: str):
+ TemplateFileABC.__init__(self)
+
+ self._name = f'__init__.py'
+ self._class_name = f'{String.first_to_upper(name)}{schematic_upper}'
+ self._path = path
+ self._value = textwrap.dedent("""\
+ # imports
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return Template(self._value).substitute(
+ Name=self._class_name
+ )
diff --git a/src/cpl_cli/templates/generate/service_template.py b/src/cpl_cli/templates/generate/service_template.py
new file mode 100644
index 00000000..98e5466d
--- /dev/null
+++ b/src/cpl_cli/templates/generate/service_template.py
@@ -0,0 +1,35 @@
+import textwrap
+from string import Template
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class ServiceTemplate(TemplateFileABC):
+
+ def __init__(self, name: str, schematic: str, schematic_upper: str, path: str):
+ TemplateFileABC.__init__(self)
+
+ self._name = f'{String.convert_to_snake_case(name)}_{schematic}.py'
+ self._class_name = f'{String.first_to_upper(name)}{schematic_upper}'
+ self._path = path
+ self._value = textwrap.dedent("""\
+ class $Name:
+
+ def __init__(self):
+ pass
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return Template(self._value).substitute(
+ Name=self._class_name
+ )
diff --git a/src/cpl_cli/templates/generate/thread_template.py b/src/cpl_cli/templates/generate/thread_template.py
new file mode 100644
index 00000000..78c68372
--- /dev/null
+++ b/src/cpl_cli/templates/generate/thread_template.py
@@ -0,0 +1,41 @@
+import textwrap
+from string import Template
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class ThreadTemplate(TemplateFileABC):
+
+ def __init__(self, name: str, schematic: str, schematic_upper: str, path: str):
+ TemplateFileABC.__init__(self)
+
+ self._name = f'{String.convert_to_snake_case(name)}_{schematic}.py'
+ self._class_name = f'{String.first_to_upper(name)}{schematic_upper}'
+ self._path = path
+ self._value = textwrap.dedent("""\
+ import threading
+
+
+ class $Name(threading.Thread):
+
+ def __init__(self):
+ threading.Thread.__init__(self)
+
+ def run(self) -> None:
+ pass
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return Template(self._value).substitute(
+ Name=self._class_name
+ )
diff --git a/src/cpl_cli/templates/new/__init__.py b/src/cpl_cli/templates/new/__init__.py
new file mode 100644
index 00000000..62c8d6be
--- /dev/null
+++ b/src/cpl_cli/templates/new/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/new/console/__init__.py b/src/cpl_cli/templates/new/console/__init__.py
new file mode 100644
index 00000000..b1a8e76d
--- /dev/null
+++ b/src/cpl_cli/templates/new/console/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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.console'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/new/console/appsettings_json.py b/src/cpl_cli/templates/new/console/appsettings_json.py
new file mode 100644
index 00000000..04c1a239
--- /dev/null
+++ b/src/cpl_cli/templates/new/console/appsettings_json.py
@@ -0,0 +1,41 @@
+import textwrap
+
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class AppsettingsTemplate(TemplateFileABC):
+
+ def __init__(self):
+ TemplateFileABC.__init__(self)
+
+ self._name = 'appsettings.json'
+ self._path = ''
+ self._value = textwrap.dedent("""\
+ {
+ "TimeFormatSettings": {
+ "DateFormat": "%Y-%m-%d",
+ "TimeFormat": "%H:%M:%S",
+ "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
+ "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
+ },
+
+ "LoggingSettings": {
+ "Path": "logs/",
+ "Filename": "log_$start_time.log",
+ "ConsoleLogLevel": "ERROR",
+ "FileLogLevel": "WARN"
+ }
+ }
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/console/license.py b/src/cpl_cli/templates/new/console/license.py
new file mode 100644
index 00000000..d9bcdda7
--- /dev/null
+++ b/src/cpl_cli/templates/new/console/license.py
@@ -0,0 +1,23 @@
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class LicenseTemplate(TemplateFileABC):
+
+ def __init__(self):
+ TemplateFileABC.__init__(self)
+
+ self._name = 'LICENSE'
+ self._path = ''
+ self._value = """"""
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/console/readme_py.py b/src/cpl_cli/templates/new/console/readme_py.py
new file mode 100644
index 00000000..7af465a4
--- /dev/null
+++ b/src/cpl_cli/templates/new/console/readme_py.py
@@ -0,0 +1,23 @@
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class ReadmeTemplate(TemplateFileABC):
+
+ def __init__(self):
+ TemplateFileABC.__init__(self)
+
+ self._name = 'README.md'
+ self._path = ''
+ self._value = """"""
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/console/src/__init__.py b/src/cpl_cli/templates/new/console/src/__init__.py
new file mode 100644
index 00000000..b666bf0d
--- /dev/null
+++ b/src/cpl_cli/templates/new/console/src/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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.console.src'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/new/console/src/name/__init__.py b/src/cpl_cli/templates/new/console/src/name/__init__.py
new file mode 100644
index 00000000..6f728248
--- /dev/null
+++ b/src/cpl_cli/templates/new/console/src/name/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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.console.src.name'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/new/console/src/name/application.py b/src/cpl_cli/templates/new/console/src/name/application.py
new file mode 100644
index 00000000..516c77aa
--- /dev/null
+++ b/src/cpl_cli/templates/new/console/src/name/application.py
@@ -0,0 +1,44 @@
+import textwrap
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class ApplicationTemplate(TemplateFileABC):
+
+ def __init__(self, name: str):
+ TemplateFileABC.__init__(self)
+
+ name = String.convert_to_snake_case(name)
+ self._name = 'application.py'
+ self._path = f'src/{name}/'
+ self._value = textwrap.dedent("""\
+ from cpl.application import ApplicationABC
+ from cpl.configuration import ConfigurationABC
+ from cpl.console import Console
+ from cpl.dependency_injection import ServiceProviderABC
+
+
+ class Application(ApplicationABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
+ ApplicationABC.__init__(self, config, services)
+
+ def configure(self):
+ pass
+
+ def main(self):
+ Console.write_line('Hello World')
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/console/src/name/init.py b/src/cpl_cli/templates/new/console/src/name/init.py
new file mode 100644
index 00000000..9cdd21ad
--- /dev/null
+++ b/src/cpl_cli/templates/new/console/src/name/init.py
@@ -0,0 +1,29 @@
+import textwrap
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class MainInitTemplate(TemplateFileABC):
+
+ def __init__(self, name: str):
+ TemplateFileABC.__init__(self)
+
+ name = String.convert_to_snake_case(name)
+ self._name = '__init__.py'
+ self._path = f'src/{name}/'
+ self._value = textwrap.dedent("""\
+ # imports:
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/console/src/name/main.py b/src/cpl_cli/templates/new/console/src/name/main.py
new file mode 100644
index 00000000..7a3cb7ac
--- /dev/null
+++ b/src/cpl_cli/templates/new/console/src/name/main.py
@@ -0,0 +1,158 @@
+import textwrap
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class MainWithApplicationHostAndStartupTemplate(TemplateFileABC):
+
+ def __init__(self, name: str):
+ TemplateFileABC.__init__(self)
+
+ name = String.convert_to_snake_case(name)
+ self._name = 'main.py'
+ self._path = f'src/{name}/'
+ self._value = textwrap.dedent(f"""\
+ from cpl.application import ApplicationBuilder
+
+ from {name}.application import Application
+ from {name}.startup import Startup
+
+
+ def main():
+ app_builder = ApplicationBuilder(Application)
+ app_builder.use_startup(Startup)
+ app_builder.build().run()
+
+
+ if __name__ == '__main__':
+ main()
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
+
+
+class MainWithApplicationBaseTemplate(TemplateFileABC):
+
+ def __init__(self, name: str):
+ TemplateFileABC.__init__(self)
+
+ name = String.convert_to_snake_case(name)
+ self._name = 'main.py'
+ self._path = f'src/{name}'
+ self._value = textwrap.dedent(f"""\
+ from cpl.application import ApplicationBuilder
+
+ from {name}.application import Application
+
+
+ def main():
+ app_builder = ApplicationBuilder(Application)
+ app_builder.build().run()
+
+
+ if __name__ == '__main__':
+ main()
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
+
+
+class MainWithoutApplicationBaseTemplate(TemplateFileABC):
+
+ def __init__(self, name: str):
+ TemplateFileABC.__init__(self)
+
+ name = String.convert_to_snake_case(name)
+ self._name = 'main.py'
+ self._path = f'src/{name}'
+ self._value = textwrap.dedent("""\
+ from cpl.console import Console
+
+
+ def main():
+ Console.write_line('Hello World')
+
+
+ if __name__ == '__main__':
+ main()
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
+
+
+class MainWithDependencyInjection(TemplateFileABC):
+
+ def __init__(self, name: str):
+ TemplateFileABC.__init__(self)
+
+ name = String.convert_to_snake_case(name)
+ self._name = 'main.py'
+ self._path = f'src/{name}'
+ self._value = textwrap.dedent("""\
+ from cpl.configuration import Configuration, ConfigurationABC
+ from cpl.console import Console
+ from cpl.dependency_injection import ServiceCollection, ServiceProviderABC
+
+
+ def configure_configuration() -> ConfigurationABC:
+ config = Configuration()
+ return config
+
+
+ def configure_services(config: ConfigurationABC) -> ServiceProviderABC:
+ services = ServiceCollection(config)
+ return services.build_service_provider()
+
+
+ def main():
+ config = configure_configuration()
+ provider = configure_services(config)
+ Console.write_line('Hello World')
+
+
+ if __name__ == '__main__':
+ main()
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/console/src/name/startup.py b/src/cpl_cli/templates/new/console/src/name/startup.py
new file mode 100644
index 00000000..90881b96
--- /dev/null
+++ b/src/cpl_cli/templates/new/console/src/name/startup.py
@@ -0,0 +1,47 @@
+import textwrap
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class StartupTemplate(TemplateFileABC):
+
+ def __init__(self, name: str):
+ TemplateFileABC.__init__(self)
+
+ name = String.convert_to_snake_case(name)
+ self._name = 'startup.py'
+ self._path = f'src/{name}/'
+ self._value = textwrap.dedent("""\
+ from cpl.application import StartupABC
+ from cpl.configuration import ConfigurationABC
+ from cpl.dependency_injection import ServiceProviderABC, ServiceCollectionABC
+
+
+ class Startup(StartupABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceCollectionABC):
+ StartupABC.__init__(self)
+
+ self._configuration = config
+ self._environment = self._configuration.environment
+ self._services = services
+
+ def configure_configuration(self) -> ConfigurationABC:
+ return self._configuration
+
+ def configure_services(self) -> ServiceProviderABC:
+ return self._services.build_service_provider()
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/console/src/tests/__init__.py b/src/cpl_cli/templates/new/console/src/tests/__init__.py
new file mode 100644
index 00000000..365d5174
--- /dev/null
+++ b/src/cpl_cli/templates/new/console/src/tests/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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.console.src.tests'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/new/console/src/tests/init.py b/src/cpl_cli/templates/new/console/src/tests/init.py
new file mode 100644
index 00000000..3358c6f6
--- /dev/null
+++ b/src/cpl_cli/templates/new/console/src/tests/init.py
@@ -0,0 +1,27 @@
+import textwrap
+
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class TestsInitTemplate(TemplateFileABC):
+
+ def __init__(self):
+ TemplateFileABC.__init__(self)
+
+ self._name = '__init__.py'
+ self._path = 'src/tests/'
+ self._value = textwrap.dedent("""\
+ # imports:
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/library/__init__.py b/src/cpl_cli/templates/new/library/__init__.py
new file mode 100644
index 00000000..43584a93
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/new/library/appsettings_json.py b/src/cpl_cli/templates/new/library/appsettings_json.py
new file mode 100644
index 00000000..04c1a239
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/appsettings_json.py
@@ -0,0 +1,41 @@
+import textwrap
+
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class AppsettingsTemplate(TemplateFileABC):
+
+ def __init__(self):
+ TemplateFileABC.__init__(self)
+
+ self._name = 'appsettings.json'
+ self._path = ''
+ self._value = textwrap.dedent("""\
+ {
+ "TimeFormatSettings": {
+ "DateFormat": "%Y-%m-%d",
+ "TimeFormat": "%H:%M:%S",
+ "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
+ "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
+ },
+
+ "LoggingSettings": {
+ "Path": "logs/",
+ "Filename": "log_$start_time.log",
+ "ConsoleLogLevel": "ERROR",
+ "FileLogLevel": "WARN"
+ }
+ }
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/library/license.py b/src/cpl_cli/templates/new/library/license.py
new file mode 100644
index 00000000..d9bcdda7
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/license.py
@@ -0,0 +1,23 @@
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class LicenseTemplate(TemplateFileABC):
+
+ def __init__(self):
+ TemplateFileABC.__init__(self)
+
+ self._name = 'LICENSE'
+ self._path = ''
+ self._value = """"""
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/library/readme_py.py b/src/cpl_cli/templates/new/library/readme_py.py
new file mode 100644
index 00000000..7af465a4
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/readme_py.py
@@ -0,0 +1,23 @@
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class ReadmeTemplate(TemplateFileABC):
+
+ def __init__(self):
+ TemplateFileABC.__init__(self)
+
+ self._name = 'README.md'
+ self._path = ''
+ self._value = """"""
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/library/src/__init__.py b/src/cpl_cli/templates/new/library/src/__init__.py
new file mode 100644
index 00000000..d21498c7
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/src/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/new/library/src/cli/__init__.py b/src/cpl_cli/templates/new/library/src/cli/__init__.py
new file mode 100644
index 00000000..5f59f690
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/src/cli/__init__.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+"""
+sh_cpl sh-edraft Common Python library
+~~~~~~~~~~~~~~~~~~~
+
+sh-edraft Common Python library
+
+:copyright: (c) 2020 - 2021 sh-edraft.de
+:license: MIT, see LICENSE for more details.
+
+"""
+
+__title__ = 'cpl_cli.templates.new.library.src.cli'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/new/library/src/cli/application.py b/src/cpl_cli/templates/new/library/src/cli/application.py
new file mode 100644
index 00000000..0d92c2cc
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/src/cli/application.py
@@ -0,0 +1,44 @@
+import textwrap
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class ApplicationTemplate(TemplateFileABC):
+
+ def __init__(self, name: str):
+ TemplateFileABC.__init__(self)
+
+ name = String.convert_to_snake_case(name)
+ self._name = 'application.py'
+ self._path = f'src/{name}_cli/'
+ self._value = textwrap.dedent("""\
+ from cpl.application import ApplicationABC
+ from cpl.configuration import ConfigurationABC
+ from cpl.console import Console
+ from cpl.dependency_injection import ServiceProviderABC
+
+
+ class Application(ApplicationABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
+ ApplicationABC.__init__(self, config, services)
+
+ def configure(self):
+ pass
+
+ def main(self):
+ Console.write_line('Hello World')
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/library/src/cli/init.py b/src/cpl_cli/templates/new/library/src/cli/init.py
new file mode 100644
index 00000000..28634bf3
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/src/cli/init.py
@@ -0,0 +1,29 @@
+import textwrap
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class CLIInitTemplate(TemplateFileABC):
+
+ def __init__(self, name: str):
+ TemplateFileABC.__init__(self)
+
+ name = String.convert_to_snake_case(name)
+ self._name = '__init__.py'
+ self._path = f'src/{name}_cli/'
+ self._value = textwrap.dedent("""\
+ # imports:
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/library/src/cli/main.py b/src/cpl_cli/templates/new/library/src/cli/main.py
new file mode 100644
index 00000000..248cdb3e
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/src/cli/main.py
@@ -0,0 +1,155 @@
+import textwrap
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class MainWithApplicationHostAndStartupTemplate(TemplateFileABC):
+
+ def __init__(self, name: str):
+ TemplateFileABC.__init__(self)
+
+ name = String.convert_to_snake_case(name)
+ self._name = 'main.py'
+ self._path = f'src/{name}_cli/'
+ self._value = textwrap.dedent(f"""\
+ from cpl.application import ApplicationBuilder
+
+ from {name}_cli.application import Application
+ from {name}_cli.startup import Startup
+
+
+ def main():
+ app_builder = ApplicationBuilder(Application)
+ app_builder.use_startup(Startup)
+ app_builder.build().run()
+
+
+ if __name__ == '__main__':
+ main()
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
+
+
+class MainWithApplicationBaseTemplate(TemplateFileABC):
+
+ def __init__(self):
+ TemplateFileABC.__init__(self)
+
+ self._name = 'main.py'
+ self._path = 'src/'
+ self._value = textwrap.dedent(f"""\
+ from cpl.application import ApplicationBuilder
+
+ from {name}_cli.application import Application
+
+
+ def main():
+ app_builder = ApplicationBuilder(Application)
+ app_builder.build().run()
+
+
+ if __name__ == '__main__':
+ main()
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
+
+
+class MainWithoutApplicationBaseTemplate(TemplateFileABC):
+
+ def __init__(self):
+ TemplateFileABC.__init__(self)
+
+ self._name = 'main.py'
+ self._path = 'src/'
+ self._value = textwrap.dedent("""\
+ from cpl.console import Console
+
+
+ def main():
+ Console.write_line('Hello World')
+
+
+ if __name__ == '__main__':
+ main()
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
+
+
+class MainWithDependencyInjection(TemplateFileABC):
+
+ def __init__(self):
+ TemplateFileABC.__init__(self)
+
+ self._name = 'main.py'
+ self._path = 'src/'
+ self._value = textwrap.dedent("""\
+ from cpl.configuration import Configuration, ConfigurationABC
+ from cpl.console import Console
+ from cpl.dependency_injection import ServiceCollection, ServiceProviderABC
+
+
+ def configure_configuration() -> ConfigurationABC:
+ config = Configuration()
+ return config
+
+
+ def configure_services(config: ConfigurationABC) -> ServiceProviderABC:
+ services = ServiceCollection(config)
+ return services.build_service_provider()
+
+
+ def main():
+ config = configure_configuration()
+ provider = configure_services(config)
+ Console.write_line('Hello World')
+
+
+ if __name__ == '__main__':
+ main()
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/library/src/cli/startup.py b/src/cpl_cli/templates/new/library/src/cli/startup.py
new file mode 100644
index 00000000..0e33e643
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/src/cli/startup.py
@@ -0,0 +1,47 @@
+import textwrap
+
+from cpl.utils.string import String
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class StartupTemplate(TemplateFileABC):
+
+ def __init__(self, name: str):
+ TemplateFileABC.__init__(self)
+
+ name = String.convert_to_snake_case(name)
+ self._name = 'startup.py'
+ self._path = f'src/{name}_cli/'
+ self._value = textwrap.dedent("""\
+ from cpl.application import StartupABC
+ from cpl.configuration import ConfigurationABC
+ from cpl.dependency_injection import ServiceProviderABC, ServiceCollectionABC
+
+
+ class Startup(StartupABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceCollectionABC):
+ StartupABC.__init__(self)
+
+ self._configuration = config
+ self._environment = self._configuration.environment
+ self._services = services
+
+ def configure_configuration(self) -> ConfigurationABC:
+ return self._configuration
+
+ def configure_services(self) -> ServiceProviderABC:
+ return self._services.build_service_provider()
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/library/src/name/__init__.py b/src/cpl_cli/templates/new/library/src/name/__init__.py
new file mode 100644
index 00000000..2421f687
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/src/name/__init__.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+"""
+sh_cpl sh-edraft Common Python library
+~~~~~~~~~~~~~~~~~~~
+
+sh-edraft Common Python library
+
+:copyright: (c) 2020 - 2021 sh-edraft.de
+:license: MIT, see LICENSE for more details.
+
+"""
+
+__title__ = 'cpl_cli.templates.new.library.src.name'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/new/library/src/name/init.py b/src/cpl_cli/templates/new/library/src/name/init.py
new file mode 100644
index 00000000..ebb078a7
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/src/name/init.py
@@ -0,0 +1,27 @@
+import textwrap
+
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class TestsInitTemplate(TemplateFileABC):
+
+ def __init__(self, name: str):
+ TemplateFileABC.__init__(self)
+
+ self._name = '__init__.py'
+ self._path = f'src/{name}/'
+ self._value = textwrap.dedent("""\
+ # imports:
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/new/library/src/tests/__init__.py b/src/cpl_cli/templates/new/library/src/tests/__init__.py
new file mode 100644
index 00000000..33fba570
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/src/tests/__init__.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+"""
+sh_cpl sh-edraft Common Python library
+~~~~~~~~~~~~~~~~~~~
+
+sh-edraft Common Python library
+
+:copyright: (c) 2020 - 2021 sh-edraft.de
+:license: MIT, see LICENSE for more details.
+
+"""
+
+__title__ = 'cpl_cli.templates.new.library.src.tests'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/new/library/src/tests/init.py b/src/cpl_cli/templates/new/library/src/tests/init.py
new file mode 100644
index 00000000..3358c6f6
--- /dev/null
+++ b/src/cpl_cli/templates/new/library/src/tests/init.py
@@ -0,0 +1,27 @@
+import textwrap
+
+from cpl_cli.templates.template_file_abc import TemplateFileABC
+
+
+class TestsInitTemplate(TemplateFileABC):
+
+ def __init__(self):
+ TemplateFileABC.__init__(self)
+
+ self._name = '__init__.py'
+ self._path = 'src/tests/'
+ self._value = textwrap.dedent("""\
+ # imports:
+ """)
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def path(self) -> str:
+ return self._path
+
+ @property
+ def value(self) -> str:
+ return self._value
diff --git a/src/cpl_cli/templates/publish/__init__.py b/src/cpl_cli/templates/publish/__init__.py
new file mode 100644
index 00000000..1c84a56d
--- /dev/null
+++ b/src/cpl_cli/templates/publish/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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.publish'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.0'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major='2021', minor='04', micro='0')
diff --git a/src/cpl_cli/templates/publish/setup_template.py b/src/cpl_cli/templates/publish/setup_template.py
new file mode 100644
index 00000000..abae3251
--- /dev/null
+++ b/src/cpl_cli/templates/publish/setup_template.py
@@ -0,0 +1,32 @@
+import textwrap
+
+
+class SetupTemplate:
+
+ @staticmethod
+ def get_setup_py() -> str:
+ string = textwrap.dedent("""\
+ \"\"\"
+ This file is generated by CPL CLI
+ \"\"\"
+
+ import setuptools
+
+ setuptools.setup(
+ name='$Name',
+ version='$Version',
+ packages=$Packages,
+ url='$URL',
+ license='$LicenseName',
+ author='$Author',
+ author_email='$AuthorMail',
+ include_package_data=$IncludePackageData,
+ description='$Description',
+ python_requires='$PyRequires',
+ install_requires=$Dependencies,
+ entry_points=$EntryPoints,
+ package_data=$PackageData
+ )
+ """)
+
+ return string
diff --git a/src/cpl_cli/templates/template_file_abc.py b/src/cpl_cli/templates/template_file_abc.py
new file mode 100644
index 00000000..bbe2f2e3
--- /dev/null
+++ b/src/cpl_cli/templates/template_file_abc.py
@@ -0,0 +1,19 @@
+from abc import ABC, abstractmethod
+
+
+class TemplateFileABC(ABC):
+
+ @abstractmethod
+ def __init__(self): pass
+
+ @property
+ @abstractmethod
+ def name(self) -> str: pass
+
+ @property
+ @abstractmethod
+ def path(self) -> str: pass
+
+ @property
+ @abstractmethod
+ def value(self) -> str: pass
diff --git a/src/setup.py b/src/setup.py
deleted file mode 100644
index a2e40b12..00000000
--- a/src/setup.py
+++ /dev/null
@@ -1,29 +0,0 @@
-import setuptools
-
-setuptools.setup(
- name='sh_edraft',
- version='2020.0.1',
- packages=setuptools.find_packages(exclude=["tests*"]),
- url='https://www.sh-edraft.de',
- license='MIT',
- author='Sven Heidemann',
- author_email='edraft.sh@gmail.com',
- include_package_data=True,
- description='sh-edraft python common lib',
- python_requires='>=3.8',
- install_requires=[
- 'discord.py',
- 'flask',
- 'mysql-connector',
- 'SQLAlchemy',
- 'termcolor',
- 'pyfiglet',
- 'tabulate',
- 'smtplib'
- ],
- entry_points={
- 'console_scripts': [
- 'cpl = sh_edraft.cli.cpl_cli.cli:main'
- ]
- }
-)
diff --git a/src/sh_edraft/__init__.py b/src/sh_edraft/__init__.py
deleted file mode 100644
index a74b7597..00000000
--- a/src/sh_edraft/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft common python library
-~~~~~~~~~~~~~~~~~~~
-
-Library to share common classes and models used at sh-edraft.de
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/cli/__init__.py b/src/sh_edraft/cli/__init__.py
deleted file mode 100644
index d604c174..00000000
--- a/src/sh_edraft/cli/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.cli
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.cli'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/cli/command/__init__.py b/src/sh_edraft/cli/command/__init__.py
deleted file mode 100644
index 5d5abc0b..00000000
--- a/src/sh_edraft/cli/command/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.cli.command
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.cli.command'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/cli/command/base/__init__.py b/src/sh_edraft/cli/command/base/__init__.py
deleted file mode 100644
index bf79046d..00000000
--- a/src/sh_edraft/cli/command/base/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.cli.command.base
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.cli.command.base'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .command_base import CommandBase
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/cli/command/base/command_base.py b/src/sh_edraft/cli/command/base/command_base.py
deleted file mode 100644
index 76319ba7..00000000
--- a/src/sh_edraft/cli/command/base/command_base.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from abc import ABC, abstractmethod
-
-
-class CommandBase(ABC):
-
- @abstractmethod
- def __init__(self):
- self._aliases: list[str] = []
-
- @property
- def aliases(self):
- return self._aliases
-
- @abstractmethod
- def run(self, args: list[str]): pass
diff --git a/src/sh_edraft/cli/cpl_cli/__init__.py b/src/sh_edraft/cli/cpl_cli/__init__.py
deleted file mode 100644
index d2709a11..00000000
--- a/src/sh_edraft/cli/cpl_cli/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.cli.cpl_cli
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.cli.cpl_cli'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .cli import CLI
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/cli/cpl_cli/cli.py b/src/sh_edraft/cli/cpl_cli/cli.py
deleted file mode 100644
index f0728d13..00000000
--- a/src/sh_edraft/cli/cpl_cli/cli.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import sys
-import traceback
-
-from sh_edraft.cli.cpl_cli.commands.build.build import Build
-from sh_edraft.cli.cpl_cli.commands.help import Help
-from sh_edraft.cli.cpl_cli.commands.new import New
-from sh_edraft.cli.cpl_cli.commands.publish.publish import Publish
-from sh_edraft.cli.cpl_cli.commands.version import Version
-from sh_edraft.cli.interpreter.interpreter import Interpreter
-from sh_edraft.console.console import Console
-
-
-class CLI:
-
- def __init__(self):
- self._interpreter = Interpreter()
-
- def setup(self):
- self._interpreter.add_command(Build())
- self._interpreter.add_command(Help())
- self._interpreter.add_command(New())
- self._interpreter.add_command(Publish())
- self._interpreter.add_command(Version())
-
- def main(self):
- string = ' '.join(sys.argv[1:])
- try:
- self._interpreter.interpret(string)
- except Exception as e:
- tb = traceback.format_exc()
- Console.error(str(e), tb)
- Console.error('Run \'cpl help\'')
-
-
-def main():
- cli = CLI()
- cli.setup()
- cli.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/sh_edraft/cli/cpl_cli/commands/__init__.py b/src/sh_edraft/cli/cpl_cli/commands/__init__.py
deleted file mode 100644
index a1d5ec40..00000000
--- a/src/sh_edraft/cli/cpl_cli/commands/__init__.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.cli.cpl_cli.commands
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.cli.cpl_cli.commands'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .version import Version
-from .help import Help
-from .new import New
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/cli/cpl_cli/commands/build/__init__.py b/src/sh_edraft/cli/cpl_cli/commands/build/__init__.py
deleted file mode 100644
index 6a057cac..00000000
--- a/src/sh_edraft/cli/cpl_cli/commands/build/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.cli.cpl_cli.commands.build
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.cli.cpl_cli.commands.build'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .app import BuildApp
-from .build import Build
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/cli/cpl_cli/commands/build/app.py b/src/sh_edraft/cli/cpl_cli/commands/build/app.py
deleted file mode 100644
index 4c0b9833..00000000
--- a/src/sh_edraft/cli/cpl_cli/commands/build/app.py
+++ /dev/null
@@ -1,47 +0,0 @@
-from typing import Optional
-
-from sh_edraft.configuration.base.configuration_base import ConfigurationBase
-from sh_edraft.hosting.application_host import ApplicationHost
-from sh_edraft.hosting.base.application_base import ApplicationBase
-from sh_edraft.logging.logger import Logger
-from sh_edraft.logging.base.logger_base import LoggerBase
-from sh_edraft.publish.publisher import Publisher
-from sh_edraft.publish.base.publisher_base import PublisherBase
-from sh_edraft.service.providing.base.service_provider_base import ServiceProviderBase
-
-
-class BuildApp(ApplicationBase):
-
- def __init__(self):
- ApplicationBase.__init__(self)
-
- self._app_host: Optional[ApplicationHost] = None
- self._services: Optional[ServiceProviderBase] = None
- self._configuration: Optional[ConfigurationBase] = None
- self._logger: Optional[LoggerBase] = None
- self._publisher: Optional[PublisherBase] = None
-
- def create_application_host(self):
- self._app_host = ApplicationHost()
- self._configuration = self._app_host.configuration
- self._services = self._app_host.services
-
- def create_configuration(self):
- self._configuration.add_json_file(f'build.json')
-
- def create_services(self):
- # Add and create logger
- self._services.add_singleton(LoggerBase, Logger)
- self._logger = self._services.get_service(LoggerBase)
-
- # Add and create publisher
- self._services.add_singleton(PublisherBase, Publisher)
- self._publisher: Publisher = self._services.get_service(PublisherBase)
-
- def main(self):
- self._logger.header(f'{self._configuration.environment.application_name}:')
- self._logger.debug(__name__, f'Host: {self._configuration.environment.host_name}')
- self._logger.debug(__name__, f'Environment: {self._configuration.environment.environment_name}')
- self._logger.debug(__name__, f'Customer: {self._configuration.environment.customer}')
- self._publisher.create()
- self._publisher.build()
diff --git a/src/sh_edraft/cli/cpl_cli/commands/build/build.py b/src/sh_edraft/cli/cpl_cli/commands/build/build.py
deleted file mode 100644
index f22eb436..00000000
--- a/src/sh_edraft/cli/cpl_cli/commands/build/build.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from sh_edraft.cli.command.base.command_base import CommandBase
-from sh_edraft.cli.cpl_cli.commands.build.app import BuildApp
-from sh_edraft.console.console import Console
-
-
-class Build(CommandBase):
-
- def __init__(self):
- CommandBase.__init__(self)
- self._app = BuildApp()
-
- self._aliases.append('-b')
- self._aliases.append('-B')
-
- def run(self, args: list[str]):
- if len(args) > 0:
- Console.error(f'Invalid arguments {args}')
- Console.error('Run \'cpl help\'')
-
- self._app.create_application_host()
- self._app.create_configuration()
- self._app.create_services()
- self._app.main()
diff --git a/src/sh_edraft/cli/cpl_cli/commands/help.py b/src/sh_edraft/cli/cpl_cli/commands/help.py
deleted file mode 100644
index 6ea89066..00000000
--- a/src/sh_edraft/cli/cpl_cli/commands/help.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from sh_edraft.cli.command.base.command_base import CommandBase
-from sh_edraft.console.console import Console
-
-
-class Help(CommandBase):
-
- def __init__(self):
- CommandBase.__init__(self)
- self._aliases.append('-h')
- self._aliases.append('-H')
-
- def run(self, args: list[str]):
- Console.write_line('Available Commands:')
- commands = [
- ['build (-b|-B)', 'Prepares files for publishing into an output directory named dist/ at the given output path. Must be executed from within a workspace directory.'],
- ['help (-h|-H)', 'Lists available commands and their short descriptions.'],
- ['new', 'Creates a new file or package.'],
- ['publish (-p|-P)', 'Prepares files for publishing into an output directory named dist/ at the given output path and executes setup.py. Must be executed from within a workspace directory.'],
- ['version (-v|-V)', 'Outputs CPL CLI version.']
- ]
- for name, description in commands:
- Console.set_foreground_color('blue')
- Console.write(f'\n\t{name} ')
- Console.set_foreground_color('default')
- Console.write(f'{description}')
-
- Console.write('\n')
diff --git a/src/sh_edraft/cli/cpl_cli/commands/new.py b/src/sh_edraft/cli/cpl_cli/commands/new.py
deleted file mode 100644
index 90ebb690..00000000
--- a/src/sh_edraft/cli/cpl_cli/commands/new.py
+++ /dev/null
@@ -1,97 +0,0 @@
-import os
-
-from sh_edraft.cli.command.base.command_base import CommandBase
-from sh_edraft.console.console import Console
-
-
-class New(CommandBase):
-
- def __init__(self):
- CommandBase.__init__(self)
-
- def run(self, args: list[str]):
- rel_path = f'{os.path.dirname(__file__)}/../'
- if len(args) == 0:
- Console.error(f'Expected arguments {args}')
- Console.error('Run \'cpl help\'')
- return
-
- elif len(args) != 2:
- Console.error(f'Invalid arguments {args}')
- Console.error('Run \'cpl help\'')
- return
-
- if not os.path.isdir(f'{rel_path}/templates/{args[0]}'):
- Console.error(f'Unexpected argument {args[0]}')
- Console.error('Run \'cpl help\'')
-
- sub_args = args[1:]
-
- if len(sub_args) != 1:
- Console.error(f'Unexpected argument {sub_args[1]}')
- Console.error('Run \'cpl help\'')
-
- if not (sub_args[0].startswith('.') or sub_args[0].startswith('/')):
- full_path = f'./{sub_args[0]}'
- else:
- full_path = sub_args[0]
-
- name = os.path.basename(full_path)
- path = os.path.dirname(full_path)
-
- if args[0] in ['base', 'class', 'configmodel', 'enum', 'service']:
- if not os.path.isdir(path):
- os.makedirs(path)
- else:
- if not os.path.isdir(full_path):
- os.makedirs(full_path)
-
- for r, d, f in os.walk(f'{rel_path}/templates/{args[0]}'):
- for file in f:
- template_content = ''
- with open(f'{r}/{file}') as template:
- template_content = template.read()
- template.close()
-
- file = file.replace('txt', 'py')
- if args[0] in ['base', 'class', 'configmodel', 'enum', 'service']:
- suffix = None
-
- if args[0] == 'base':
- suffix = 'base'
-
- elif args[0] == 'configmodel':
- suffix = 'settings'
-
- elif args[0] == 'service':
- suffix = 'service'
-
- if suffix is not None:
- file_path = f'{path}/{name}_{suffix}.py'
- else:
- file_path = f'{path}/{name}.py'
- else:
- file_path = f'{full_path}/{file}'
-
- with open(file_path, 'w+') as pyfile:
- if name[0].islower():
- name = f'{name[0].upper()}{name[1:]}'
-
- if args[0] == 'base':
- template_content = template_content.replace('$Name', f'{name}Base')
- pyfile.write(template_content)
-
- elif args[0] == 'configmodel':
- template_content = template_content.replace('$Name', f'{name}Settings')
- pyfile.write(template_content)
-
- elif args[0] == 'service':
- template_content = template_content.replace('$Name', f'{name}Service')
- template_content = template_content.replace('$Base', f'{name}Base')
- pyfile.write(template_content)
-
- else:
- template_content = template_content.replace('$Name', name)
- pyfile.write(template_content)
-
- pyfile.close()
diff --git a/src/sh_edraft/cli/cpl_cli/commands/publish/__init__.py b/src/sh_edraft/cli/cpl_cli/commands/publish/__init__.py
deleted file mode 100644
index d367c84a..00000000
--- a/src/sh_edraft/cli/cpl_cli/commands/publish/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.cli.cpl_cli.commands.publish
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.cli.cpl_cli.commands.publish'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .app import PublishApp
-from .publish import Publish
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/cli/cpl_cli/commands/publish/app.py b/src/sh_edraft/cli/cpl_cli/commands/publish/app.py
deleted file mode 100644
index 2a0f6cec..00000000
--- a/src/sh_edraft/cli/cpl_cli/commands/publish/app.py
+++ /dev/null
@@ -1,48 +0,0 @@
-from typing import Optional
-
-from sh_edraft.configuration.base.configuration_base import ConfigurationBase
-from sh_edraft.hosting.application_host import ApplicationHost
-from sh_edraft.hosting.base.application_base import ApplicationBase
-from sh_edraft.logging.logger import Logger
-from sh_edraft.logging.base.logger_base import LoggerBase
-from sh_edraft.publish.publisher import Publisher
-from sh_edraft.publish.base.publisher_base import PublisherBase
-from sh_edraft.service.providing.base.service_provider_base import ServiceProviderBase
-
-
-class PublishApp(ApplicationBase):
-
- def __init__(self):
- ApplicationBase.__init__(self)
-
- self._app_host: Optional[ApplicationHost] = None
- self._services: Optional[ServiceProviderBase] = None
- self._configuration: Optional[ConfigurationBase] = None
- self._logger: Optional[LoggerBase] = None
- self._publisher: Optional[PublisherBase] = None
-
- def create_application_host(self):
- self._app_host = ApplicationHost()
- self._configuration = self._app_host.configuration
- self._services = self._app_host.services
-
- def create_configuration(self):
- self._configuration.add_json_file(f'build.json')
-
- def create_services(self):
- # Add and create logger
- self._services.add_singleton(LoggerBase, Logger)
- self._logger = self._services.get_service(LoggerBase)
-
- # Add and create publisher
- self._services.add_singleton(PublisherBase, Publisher)
- self._publisher: Publisher = self._services.get_service(PublisherBase)
-
- def main(self):
- self._logger.header(f'{self._configuration.environment.application_name}:')
- self._logger.debug(__name__, f'Host: {self._configuration.environment.host_name}')
- self._logger.debug(__name__, f'Environment: {self._configuration.environment.environment_name}')
- self._logger.debug(__name__, f'Customer: {self._configuration.environment.customer}')
- self._publisher.create()
- self._publisher.build()
- self._publisher.publish()
diff --git a/src/sh_edraft/cli/cpl_cli/commands/publish/publish.py b/src/sh_edraft/cli/cpl_cli/commands/publish/publish.py
deleted file mode 100644
index 7e72ae3a..00000000
--- a/src/sh_edraft/cli/cpl_cli/commands/publish/publish.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from sh_edraft.cli.command.base.command_base import CommandBase
-from sh_edraft.cli.cpl_cli.commands.publish.app import PublishApp
-from sh_edraft.console.console import Console
-
-
-class Publish(CommandBase):
-
- def __init__(self):
- CommandBase.__init__(self)
- self._app = PublishApp()
-
- self._aliases.append('-p')
- self._aliases.append('-P')
-
- def run(self, args: list[str]):
- if len(args) > 0:
- Console.error(f'Invalid arguments {args}')
- Console.error('Run \'cpl help\'')
-
- self._app.create_application_host()
- self._app.create_configuration()
- self._app.create_services()
- self._app.main()
diff --git a/src/sh_edraft/cli/cpl_cli/commands/version.py b/src/sh_edraft/cli/cpl_cli/commands/version.py
deleted file mode 100644
index 737a69c7..00000000
--- a/src/sh_edraft/cli/cpl_cli/commands/version.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import pkgutil
-import sys
-import platform
-
-import pkg_resources
-
-import sh_edraft
-from sh_edraft import cli
-from sh_edraft.cli.command.base.command_base import CommandBase
-from sh_edraft.console.console import Console
-
-
-class Version(CommandBase):
-
- def __init__(self):
- CommandBase.__init__(self)
- self._aliases.append('-v')
- self._aliases.append('-V')
-
- def run(self, args: list[str]):
- Console.set_foreground_color('yellow')
- Console.banner('CPL CLI')
- Console.set_foreground_color('default')
- Console.write_line(f'Common Python Library CLI: {cli.__version__}')
- Console.write_line(f'Python: {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}')
- Console.write_line(f'OS: {platform.system()} {platform.processor()}')
-
- Console.write_line('CPL:')
- packages = []
- for importer, modname, is_pkg in pkgutil.iter_modules(sh_edraft.__path__):
- module = importer.find_module(modname).load_module(modname)
- packages.append([f'{modname}', module.__version__])
-
- Console.table(['Name', 'Version'], packages)
-
- Console.write_line('\nPython Packages:')
- packages = []
- deps = dict(tuple(str(ws).split()) for ws in pkg_resources.working_set)
- for p in deps:
- packages.append([p, deps[p]])
-
- Console.table(['Name', 'Version'], packages)
diff --git a/src/sh_edraft/cli/cpl_cli/templates/app/__init__.txt b/src/sh_edraft/cli/cpl_cli/templates/app/__init__.txt
deleted file mode 100644
index 2e12875a..00000000
--- a/src/sh_edraft/cli/cpl_cli/templates/app/__init__.txt
+++ /dev/null
@@ -1 +0,0 @@
-# imports:
\ No newline at end of file
diff --git a/src/sh_edraft/cli/cpl_cli/templates/app/build.json b/src/sh_edraft/cli/cpl_cli/templates/app/build.json
deleted file mode 100644
index c6ea10bc..00000000
--- a/src/sh_edraft/cli/cpl_cli/templates/app/build.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "TimeFormatSettings": {
- "DateFormat": "%Y-%m-%d",
- "TimeFormat": "%H:%M:%S",
- "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
- "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
- },
- "LoggingSettings": {
- "Path": "build/logs/",
- "Filename": "log_$start_time.log",
- "ConsoleLogLevel": "INFO",
- "FileLogLevel": "INFO"
- },
- "PublishSettings": {
- "SourcePath": "./",
- "DistPath": "build/dist",
- "Templates": [],
- "IncludedFiles": [],
- "ExcludedFiles": [],
- "TemplateEnding": "_template.txt"
- }
-}
diff --git a/src/sh_edraft/cli/cpl_cli/templates/app/main.txt b/src/sh_edraft/cli/cpl_cli/templates/app/main.txt
deleted file mode 100644
index 081d79dd..00000000
--- a/src/sh_edraft/cli/cpl_cli/templates/app/main.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-from program import Program
-
-if __name__ == '__main__':
- program = Program()
- program.create_application_host()
- program.create_configuration()
- program.create_services()
- program.main()
diff --git a/src/sh_edraft/cli/cpl_cli/templates/app/program.txt b/src/sh_edraft/cli/cpl_cli/templates/app/program.txt
deleted file mode 100644
index 890c6b73..00000000
--- a/src/sh_edraft/cli/cpl_cli/templates/app/program.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-from typing import Optional
-
-from sh_edraft.configuration.base import ConfigurationBase
-from sh_edraft.hosting import ApplicationHost
-from sh_edraft.hosting.base import ApplicationBase
-from sh_edraft.logging import Logger
-from sh_edraft.logging.base import LoggerBase
-from sh_edraft.service.providing.base import ServiceProviderBase
-
-
-class Program(ApplicationBase):
-
- def __init__(self):
- ApplicationBase.__init__(self)
-
- self._app_host: Optional[ApplicationHost] = None
- self._services: Optional[ServiceProviderBase] = None
- self._configuration: Optional[ConfigurationBase] = None
- self._logger: Optional[LoggerBase] = None
-
- def create_application_host(self):
- self._app_host = ApplicationHost()
- self._configuration = self._app_host.configuration
- self._services = self._app_host.services
-
- def create_configuration(self):
- self._configuration.add_environment_variables('PYTHON_')
- self._configuration.add_environment_variables('CPL_')
- self._configuration.add_argument_variables()
- self._configuration.add_json_file(f'appsettings.json')
- self._configuration.add_json_file(f'appsettings.{self._configuration.environment.environment_name}.json', optional=True)
- self._configuration.add_json_file(f'appsettings.{self._configuration.environment.host_name}.json', optional=True)
-
- def create_services(self):
- # Add and create logger
- self._services.add_singleton(LoggerBase, Logger)
- self._logger = self._services.get_service(LoggerBase)
-
- def main(self):
- self._logger.header(f'{self._configuration.environment.application_name}:')
- self._logger.debug(__name__, f'Host: {self._configuration.environment.host_name}')
- self._logger.debug(__name__, f'Environment: {self._configuration.environment.environment_name}')
- self._logger.debug(__name__, f'Customer: {self._configuration.environment.customer}')
diff --git a/src/sh_edraft/cli/cpl_cli/templates/base/base.txt b/src/sh_edraft/cli/cpl_cli/templates/base/base.txt
deleted file mode 100644
index 1940e8ab..00000000
--- a/src/sh_edraft/cli/cpl_cli/templates/base/base.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-from abc import ABC, abstractmethod
-
-
-class $Name(ABC):
-
- @abstractmethod
- def __init__(self): pass
-
- @abstractmethod
- def create(self): pass
diff --git a/src/sh_edraft/cli/cpl_cli/templates/class/class.txt b/src/sh_edraft/cli/cpl_cli/templates/class/class.txt
deleted file mode 100644
index d22b7581..00000000
--- a/src/sh_edraft/cli/cpl_cli/templates/class/class.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-class $Name:
-
- def __init__(self):
- pass
diff --git a/src/sh_edraft/cli/cpl_cli/templates/configmodel/model.txt b/src/sh_edraft/cli/cpl_cli/templates/configmodel/model.txt
deleted file mode 100644
index ca37a816..00000000
--- a/src/sh_edraft/cli/cpl_cli/templates/configmodel/model.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-import traceback
-
-from sh_edraft.configuration.base import ConfigurationModelBase
-from sh_edraft.console import Console
-from sh_edraft.console.model import ForegroundColor
-
-
-class $Name(ConfigurationModelBase):
-
- def __init__(self):
- ConfigurationModelBase.__init__(self)
-
- def from_dict(self, settings: dict):
- try:
- pass
- except Exception as e:
- Console.set_foreground_color(ForegroundColor.red)
- Console.write_line(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings')
- Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
- Console.set_foreground_color(ForegroundColor.default)
diff --git a/src/sh_edraft/cli/cpl_cli/templates/enum/enum.txt b/src/sh_edraft/cli/cpl_cli/templates/enum/enum.txt
deleted file mode 100644
index a7aef900..00000000
--- a/src/sh_edraft/cli/cpl_cli/templates/enum/enum.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-from enum import Enum
-
-
-class $Name(Enum):
-
- pass
diff --git a/src/sh_edraft/cli/cpl_cli/templates/service/service.txt b/src/sh_edraft/cli/cpl_cli/templates/service/service.txt
deleted file mode 100644
index d2add199..00000000
--- a/src/sh_edraft/cli/cpl_cli/templates/service/service.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-class $Name($Base):
-
- def __init__(self):
- TestBase.__init__(self)
-
- self.create()
diff --git a/src/sh_edraft/cli/interpreter/__init__.py b/src/sh_edraft/cli/interpreter/__init__.py
deleted file mode 100644
index 7f342630..00000000
--- a/src/sh_edraft/cli/interpreter/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.cli.interpreter
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.cli.interpreter'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .interpreter import Interpreter
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/cli/interpreter/interpreter.py b/src/sh_edraft/cli/interpreter/interpreter.py
deleted file mode 100644
index d3e580e4..00000000
--- a/src/sh_edraft/cli/interpreter/interpreter.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from sh_edraft.cli.command.base.command_base import CommandBase
-from sh_edraft.console.console import Console
-
-
-class Interpreter:
-
- def __init__(self):
- self._commands: list[CommandBase] = []
-
- def add_command(self, command: CommandBase):
- self._commands.append(command)
-
- def remove_command(self, command: CommandBase):
- self._commands.remove(command)
-
- def interpret(self, input_string: str):
- input_list = input_string.split(' ')
- command = input_list[0]
- if command is None or command == '':
- Console.error(f'Expected command')
- Console.error('Run \'cpl help\'')
- return
-
- args = input_list[1:] if len(input_list) > 1 else []
-
- cmd = next(
- (cmd for cmd in self._commands if type(cmd).__name__.lower() == command or command in cmd.aliases),
- None)
- if cmd is not None:
- cmd.run(args)
- else:
- Console.error(f'Unexpected command {command}')
- Console.error('Run \'cpl help\'')
diff --git a/src/sh_edraft/coding/__init__.py b/src/sh_edraft/coding/__init__.py
deleted file mode 100644
index 74fd8f6b..00000000
--- a/src/sh_edraft/coding/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.coding
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.coding'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/coding/model/__init__.py b/src/sh_edraft/coding/model/__init__.py
deleted file mode 100644
index ccdd0f5a..00000000
--- a/src/sh_edraft/coding/model/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.coding.model
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.coding.model'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .version import Version
-from .version_enum import VersionEnum
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/coding/model/version.py b/src/sh_edraft/coding/model/version.py
deleted file mode 100644
index be2d5a3d..00000000
--- a/src/sh_edraft/coding/model/version.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from typing import Optional
-
-from sh_edraft.coding.model.version_enum import VersionEnum
-from sh_edraft.configuration.base.configuration_model_base import ConfigurationModelBase
-
-
-class Version(ConfigurationModelBase):
-
- def __init__(
- self,
- major: int = None,
- minor: int = None,
- micro: float = None
- ):
- ConfigurationModelBase.__init__(self)
-
- self._major: Optional[int] = major
- self._minor: Optional[int] = minor
- self._micro: Optional[int] = micro
-
- @property
- def major(self) -> int:
- return self._major
-
- @property
- def minor(self) -> int:
- return self._minor
-
- @property
- def micro(self) -> float:
- return self._micro
-
- def to_str(self) -> str:
- return f'{self._major}.{self._minor}.{self._micro}'
-
- def from_dict(self, settings: dict):
- self._major = int(settings[VersionEnum.Major.value])
- self._minor = int(settings[VersionEnum.Minor.value])
- self._micro = int(settings[VersionEnum.Micro.value])
-
- def to_dict(self) -> dict:
- return {
- VersionEnum.Major.value: self._major,
- VersionEnum.Minor.value: self._minor,
- VersionEnum.Micro.value: self._micro
- }
diff --git a/src/sh_edraft/coding/model/version_enum.py b/src/sh_edraft/coding/model/version_enum.py
deleted file mode 100644
index 8c294c1e..00000000
--- a/src/sh_edraft/coding/model/version_enum.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from enum import Enum
-
-
-class VersionEnum(Enum):
-
- Major = 'Major'
- Minor = 'Minor'
- Micro = 'Micro'
diff --git a/src/sh_edraft/configuration/__init__.py b/src/sh_edraft/configuration/__init__.py
deleted file mode 100644
index 21979d7f..00000000
--- a/src/sh_edraft/configuration/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.configuration
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.configuration'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .configuration import Configuration
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/configuration/base/__init__.py b/src/sh_edraft/configuration/base/__init__.py
deleted file mode 100644
index 28444895..00000000
--- a/src/sh_edraft/configuration/base/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.configuration.base
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.configuration.base'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .configuration_base import ConfigurationBase
-from .configuration_model_base import ConfigurationModelBase
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/configuration/base/configuration_base.py b/src/sh_edraft/configuration/base/configuration_base.py
deleted file mode 100644
index bf44a8c1..00000000
--- a/src/sh_edraft/configuration/base/configuration_base.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from abc import abstractmethod, ABC
-from collections import Callable
-from typing import Type
-
-from sh_edraft.configuration.base.configuration_model_base import ConfigurationModelBase
-from sh_edraft.environment.base.environment_base import EnvironmentBase
-
-
-class ConfigurationBase(ABC):
-
- @abstractmethod
- def __init__(self): pass
-
- @property
- @abstractmethod
- def environment(self) -> EnvironmentBase: pass
-
- @abstractmethod
- def add_environment_variables(self, prefix: str): pass
-
- @abstractmethod
- def add_argument_variables(self): pass
-
- @abstractmethod
- def add_json_file(self, name: str, optional: bool = None): pass
-
- @abstractmethod
- def add_configuration(self, key_type: type, value: object): pass
-
- @abstractmethod
- def get_configuration(self, search_type: Type[ConfigurationModelBase]) -> Callable[ConfigurationModelBase]: pass
-
- @abstractmethod
- def create(self): pass
diff --git a/src/sh_edraft/configuration/base/configuration_model_base.py b/src/sh_edraft/configuration/base/configuration_model_base.py
deleted file mode 100644
index 9772a648..00000000
--- a/src/sh_edraft/configuration/base/configuration_model_base.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from abc import ABC, abstractmethod
-
-
-class ConfigurationModelBase(ABC):
-
- @abstractmethod
- def __init__(self): pass
-
- @abstractmethod
- def from_dict(self, settings: dict): pass
diff --git a/src/sh_edraft/configuration/configuration.py b/src/sh_edraft/configuration/configuration.py
deleted file mode 100644
index f4007ada..00000000
--- a/src/sh_edraft/configuration/configuration.py
+++ /dev/null
@@ -1,121 +0,0 @@
-import json
-import os
-import sys
-
-from sh_edraft.configuration.base.configuration_model_base import ConfigurationModelBase
-from sh_edraft.configuration.base.configuration_base import ConfigurationBase
-from sh_edraft.configuration.model.configuration_variable_name import ConfigurationVariableName
-from sh_edraft.environment.base.environment_base import EnvironmentBase
-from sh_edraft.environment.hosting_environment import HostingEnvironment
-from sh_edraft.environment.model.environment_name import EnvironmentName
-from sh_edraft.console.console import Console
-from sh_edraft.console.model import ForegroundColor
-
-
-class Configuration(ConfigurationBase):
-
- def __init__(self):
- ConfigurationBase.__init__(self)
-
- self._hosting_environment = HostingEnvironment()
- self._config: dict[type, ConfigurationModelBase] = {}
-
- @property
- def environment(self) -> EnvironmentBase:
- return self._hosting_environment
-
- @staticmethod
- def _print_info(name: str, message: str):
- Console.set_foreground_color(ForegroundColor.green)
- Console.write_line(f'[{name}] {message}')
- Console.set_foreground_color(ForegroundColor.default)
-
- @staticmethod
- def _print_warn(name: str, message: str):
- Console.set_foreground_color(ForegroundColor.yellow)
- Console.write_line(f'[{name}] {message}')
- Console.set_foreground_color(ForegroundColor.default)
-
- @staticmethod
- def _print_error(name: str, message: str):
- Console.set_foreground_color(ForegroundColor.red)
- Console.write_line(f'[{name}] {message}')
- Console.set_foreground_color(ForegroundColor.default)
-
- def _set_variable(self, name: str, value: str):
- if name == ConfigurationVariableName.environment.value:
- self._hosting_environment.environment_name = EnvironmentName(value)
-
- elif name == ConfigurationVariableName.name.value:
- self._hosting_environment.application_name = value
-
- elif name == ConfigurationVariableName.customer.value:
- self._hosting_environment.customer = value
-
- def add_environment_variables(self, prefix: str):
- for variable in ConfigurationVariableName.to_list():
- var_name = f'{prefix}{variable}'
- if var_name in [key.upper() for key in os.environ.keys()]:
- self._set_variable(variable, os.environ[var_name])
-
- def add_argument_variables(self):
- for arg in sys.argv[1:]:
- try:
- argument = arg.split('--')[1].split('=')[0].upper()
- value = arg.split('=')[1]
-
- if argument not in ConfigurationVariableName.to_list():
- raise Exception(f'Invalid argument name: {argument}')
-
- self._set_variable(argument, value)
- except Exception as e:
- self._print_error(__name__, f'Invalid argument: {arg} -> {e}')
- exit()
-
- def add_json_file(self, name: str, optional: bool = None):
- if self._hosting_environment.content_root_path.endswith('/') and not name.startswith('/'):
- file_path = f'{self._hosting_environment.content_root_path}{name}'
- else:
- file_path = f'{self._hosting_environment.content_root_path}/{name}'
-
- if not os.path.isfile(file_path):
- if not optional:
- self._print_error(__name__, f'File not found: {file_path}')
- exit()
-
- self._print_warn(__name__, f'Not Loaded config file: {file_path}')
- return None
-
- config_from_file = self._load_json_file(file_path)
- for sub in ConfigurationModelBase.__subclasses__():
- for key, value in config_from_file.items():
- if sub.__name__ == key:
- configuration = sub()
- configuration.from_dict(value)
- self.add_configuration(sub, configuration)
-
- def _load_json_file(self, file: str) -> dict:
- try:
- # open config file, create if not exists
- with open(file, encoding='utf-8') as cfg:
- # load json
- json_cfg = json.load(cfg)
- self._print_info(__name__, f'Loaded config file: {file}')
- return json_cfg
- except Exception as e:
- self._print_error(__name__, f'Cannot load config file: {file}! -> {e}')
- return {}
-
- def add_configuration(self, key_type: type, value: ConfigurationModelBase):
- self._config[key_type] = value
-
- def get_configuration(self, search_type: type) -> ConfigurationModelBase:
- if search_type not in self._config:
- raise Exception(f'Config model by type {search_type} not found')
-
- for config_model in self._config:
- if config_model == search_type:
- return self._config[config_model]
-
- def create(self):
- pass
diff --git a/src/sh_edraft/configuration/model/__init__.py b/src/sh_edraft/configuration/model/__init__.py
deleted file mode 100644
index ae7cc417..00000000
--- a/src/sh_edraft/configuration/model/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.configuration.model
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.configuration.model'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .configuration_variable_name import ConfigurationVariableName
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/console/__init__.py b/src/sh_edraft/console/__init__.py
deleted file mode 100644
index 632019e8..00000000
--- a/src/sh_edraft/console/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.console
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.console'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .console import Console
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/console/console.py b/src/sh_edraft/console/console.py
deleted file mode 100644
index 14964866..00000000
--- a/src/sh_edraft/console/console.py
+++ /dev/null
@@ -1,205 +0,0 @@
-import os
-from typing import Union, Optional
-
-import pyfiglet
-from tabulate import tabulate
-from termcolor import colored
-
-from sh_edraft.console.model.background_color import BackgroundColor
-from sh_edraft.console.model.foreground_color import ForegroundColor
-
-
-class Console:
- _is_first_write = True
-
- _background_color: BackgroundColor = BackgroundColor.default
- _foreground_color: ForegroundColor = ForegroundColor.default
- _x: Optional[int] = None
- _y: Optional[int] = None
- _disabled: bool = False
-
- """
- Properties
- """
-
- @classmethod
- @property
- def background_color(cls) -> str:
- return str(cls._background_color.value)
-
- @classmethod
- @property
- def foreground_color(cls) -> str:
- return str(cls._foreground_color.value)
-
- """
- Settings
- """
-
- @classmethod
- def set_background_color(cls, color: Union[BackgroundColor, str]):
- if type(color) is str:
- cls._background_color = BackgroundColor[color]
- else:
- cls._background_color = color
-
- @classmethod
- def set_foreground_color(cls, color: Union[ForegroundColor, str]):
-
- if type(color) is str:
- cls._foreground_color = ForegroundColor[color]
- else:
- cls._foreground_color = color
-
- @classmethod
- def reset_cursor_position(cls):
- cls._x = None
- cls._y = None
-
- @classmethod
- def set_cursor_position(cls, x: int, y: int):
- cls._x = x
- cls._y = y
-
- """
- Useful protected methods
- """
-
- @classmethod
- def _output(cls, string: str, x: int = None, y: int = None, end='\n'):
- if cls._is_first_write:
- cls._is_first_write = False
-
- args = []
- colored_args = []
-
- if x is not None and y is not None:
- args.append(f'\033[{x};{y}H')
- elif cls._x is not None and cls._y is not None:
- args.append(f'\033[{cls._x};{cls._y}H')
-
- colored_args.append(string)
- if cls._foreground_color != ForegroundColor.default and cls._background_color == BackgroundColor.default:
- colored_args.append(cls._foreground_color.value)
- elif cls._foreground_color == ForegroundColor.default and cls._background_color != BackgroundColor.default:
- colored_args.append(cls._background_color.value)
- elif cls._foreground_color != ForegroundColor.default and cls._background_color != BackgroundColor.default:
- colored_args.append(cls._foreground_color.value)
- colored_args.append(cls._background_color.value)
-
- args.append(colored(*colored_args))
- print(*args, end=end)
-
- """
- Useful public methods
- """
-
- @classmethod
- def banner(cls, string: str):
- if cls._disabled:
- return
-
- ascii_banner = pyfiglet.figlet_format(string)
- cls.write_line(ascii_banner)
-
- @classmethod
- def clear(cls):
- os.system('cls' if os.name == 'nt' else 'clear')
-
- @classmethod
- def close(cls):
- if cls._disabled:
- return
-
- Console.reset()
- Console.write('\n\n\nPress any key to continue...')
- Console.read_line()
- exit()
-
- @classmethod
- def disable(cls):
- cls._disabled = True
-
- @classmethod
- def error(cls, string: str, tb: str = None):
- if cls._disabled:
- return
-
- cls.set_foreground_color('red')
- if tb is not None:
- cls.write_line(f'{string} -> {tb}')
- else:
- cls.write_line(string)
- cls.set_foreground_color('default')
-
- @classmethod
- def enable(cls):
- cls._disabled = False
-
- @classmethod
- def read(cls, output: str = None) -> str:
- if output is not None:
- cls.write(output)
-
- return input()[0]
-
- @classmethod
- def read_line(cls, output: str = None) -> str:
- if cls._disabled:
- return ''
-
- if output is not None:
- cls.write(output)
-
- return input()
-
- @classmethod
- def reset(cls):
- cls._background_color = BackgroundColor.default
- cls._foreground_color = ForegroundColor.default
-
- @classmethod
- def table(cls, header: list[str], values: list[list[str]]):
- if cls._disabled:
- return
-
- table = tabulate(values, headers=header)
-
- Console.write_line(table)
- Console.write('\n')
-
- @classmethod
- def write(cls, *args):
- if cls._disabled:
- return
-
- string = ' '.join(map(str, args))
- cls._output(string, end='')
-
- @classmethod
- def write_at(cls, x: int, y: int, *args):
- if cls._disabled:
- return
-
- string = ' '.join(map(str, args))
- cls._output(string, x, y, end='')
-
- @classmethod
- def write_line(cls, *args):
- if cls._disabled:
- return
-
- string = ' '.join(map(str, args))
- if not cls._is_first_write:
- cls._output('')
- cls._output(string, end='')
-
- @classmethod
- def write_line_at(cls, x: int, y: int, *args):
- if cls._disabled:
- return
-
- string = ' '.join(map(str, args))
- if not cls._is_first_write:
- cls._output('', end='')
- cls._output(string, x, y, end='')
diff --git a/src/sh_edraft/console/model/__init__.py b/src/sh_edraft/console/model/__init__.py
deleted file mode 100644
index 3df50dae..00000000
--- a/src/sh_edraft/console/model/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.console.model
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.console.model'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .background_color import BackgroundColor
-from .foreground_color import ForegroundColor
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/database/__init__.py b/src/sh_edraft/database/__init__.py
deleted file mode 100644
index 7bb526a4..00000000
--- a/src/sh_edraft/database/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.database
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.database'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/database/connection/__init__.py b/src/sh_edraft/database/connection/__init__.py
deleted file mode 100644
index 5f3406df..00000000
--- a/src/sh_edraft/database/connection/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.database.connection
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.database.connection'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .database_connection import DatabaseConnection
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/database/connection/base/__init__.py b/src/sh_edraft/database/connection/base/__init__.py
deleted file mode 100644
index 492da1d6..00000000
--- a/src/sh_edraft/database/connection/base/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.database.connection.base
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.database.connection.base'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .database_connection_base import DatabaseConnectionBase
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/database/context/__init__.py b/src/sh_edraft/database/context/__init__.py
deleted file mode 100644
index 1f5bc196..00000000
--- a/src/sh_edraft/database/context/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.database.context
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.database.context'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .database_context import DatabaseContext
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/database/context/base/__init__.py b/src/sh_edraft/database/context/base/__init__.py
deleted file mode 100644
index 63d9bb64..00000000
--- a/src/sh_edraft/database/context/base/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.database.context.base
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.database.context.base'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .database_context_base import DatabaseContextBase
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/database/context/base/database_context_base.py b/src/sh_edraft/database/context/base/database_context_base.py
deleted file mode 100644
index b8294e64..00000000
--- a/src/sh_edraft/database/context/base/database_context_base.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from abc import abstractmethod
-
-from sqlalchemy import engine
-from sqlalchemy.orm import Session
-
-from sh_edraft.service.base.service_base import ServiceBase
-
-
-class DatabaseContextBase(ServiceBase):
-
- @abstractmethod
- def __init__(self):
- ServiceBase.__init__(self)
-
- @property
- @abstractmethod
- def engine(self) -> engine: pass
-
- @property
- @abstractmethod
- def session(self) -> Session: pass
-
- @abstractmethod
- def connect(self, connection_string: str): pass
-
- @abstractmethod
- def _create_tables(self): pass
diff --git a/src/sh_edraft/database/context/database_context.py b/src/sh_edraft/database/context/database_context.py
deleted file mode 100644
index 436ed53e..00000000
--- a/src/sh_edraft/database/context/database_context.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from sqlalchemy import engine, Table
-from sqlalchemy.orm import Session
-
-from sh_edraft.database.connection.database_connection import DatabaseConnection
-from sh_edraft.database.connection.base.database_connection_base import DatabaseConnectionBase
-from sh_edraft.database.context.base.database_context_base import DatabaseContextBase
-from sh_edraft.database.model.dbmodel import DBModel
-from sh_edraft.database.model.database_settings import DatabaseSettings
-from sh_edraft.console.console import Console
-from sh_edraft.console.model.foreground_color import ForegroundColor
-
-
-class DatabaseContext(DatabaseContextBase):
-
- def __init__(self, database_settings: DatabaseSettings):
- DatabaseContextBase.__init__(self)
-
- self._db: DatabaseConnectionBase = DatabaseConnection(database_settings)
- self._tables: list[Table] = []
-
- @property
- def engine(self) -> engine:
- return self._db.engine
-
- @property
- def session(self) -> Session:
- return self._db.session
-
- def create(self):
- pass
-
- def connect(self, connection_string: str):
- self._db.connect(connection_string)
- self._create_tables()
-
- def _create_tables(self):
- try:
- for subclass in DBModel.__subclasses__():
- self._tables.append(subclass.__table__)
-
- DBModel.metadata.drop_all(self._db.engine, self._tables)
- DBModel.metadata.create_all(self._db.engine, self._tables, checkfirst=True)
- Console.set_foreground_color(ForegroundColor.green)
- Console.write_line(f'[{__name__}] Created tables')
- Console.set_foreground_color(ForegroundColor.default)
- except Exception as e:
- Console.set_foreground_color(ForegroundColor.red)
- Console.write_line(f'[{__name__}] Creating tables failed -> {e}')
- Console.set_foreground_color(ForegroundColor.default)
- exit()
diff --git a/src/sh_edraft/database/model/__init__.py b/src/sh_edraft/database/model/__init__.py
deleted file mode 100644
index de87e001..00000000
--- a/src/sh_edraft/database/model/__init__.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.database.model
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.database.model'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .database_settings import DatabaseSettings
-from .database_settings_name import DatabaseSettingsName
-from .dbmodel import DBModel
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/environment/__init__.py b/src/sh_edraft/environment/__init__.py
deleted file mode 100644
index ac993870..00000000
--- a/src/sh_edraft/environment/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.environment
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.environment'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .hosting_environment import HostingEnvironment
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/environment/base/__init__.py b/src/sh_edraft/environment/base/__init__.py
deleted file mode 100644
index 36b8b351..00000000
--- a/src/sh_edraft/environment/base/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.environment.base
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.environment.base'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .environment_base import EnvironmentBase
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/environment/base/environment_base.py b/src/sh_edraft/environment/base/environment_base.py
deleted file mode 100644
index f5dc9266..00000000
--- a/src/sh_edraft/environment/base/environment_base.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from abc import ABC, abstractmethod
-
-
-class EnvironmentBase(ABC):
-
- @abstractmethod
- def __init__(self): pass
-
- @property
- @abstractmethod
- def environment_name(self) -> str: pass
-
- @environment_name.setter
- @abstractmethod
- def environment_name(self, environment_name: str): pass
-
- @property
- @abstractmethod
- def application_name(self) -> str: pass
-
- @application_name.setter
- @abstractmethod
- def application_name(self, application_name: str): pass
-
- @property
- @abstractmethod
- def customer(self) -> str: pass
-
- @customer.setter
- @abstractmethod
- def customer(self, customer: str): pass
-
- @property
- @abstractmethod
- def content_root_path(self) -> str: pass
-
- @content_root_path.setter
- @abstractmethod
- def content_root_path(self, content_root_path: str): pass
-
- @property
- @abstractmethod
- def host_name(self) -> str: pass
diff --git a/src/sh_edraft/environment/hosting_environment.py b/src/sh_edraft/environment/hosting_environment.py
deleted file mode 100644
index 2f2021ff..00000000
--- a/src/sh_edraft/environment/hosting_environment.py
+++ /dev/null
@@ -1,52 +0,0 @@
-from socket import gethostname
-from typing import Optional
-
-from sh_edraft.environment.base.environment_base import EnvironmentBase
-from sh_edraft.environment.model.environment_name import EnvironmentName
-
-
-class HostingEnvironment(EnvironmentBase):
-
- def __init__(self, name: EnvironmentName = EnvironmentName.production, crp: str = './'):
- EnvironmentBase.__init__(self)
-
- self._environment_name: Optional[EnvironmentName] = name
- self._app_name: Optional[str] = None
- self._customer: Optional[str] = None
- self._content_root_path: Optional[str] = crp
-
- @property
- def environment_name(self) -> str:
- return str(self._environment_name.value)
-
- @environment_name.setter
- def environment_name(self, environment_name: str):
- self._environment_name = EnvironmentName(environment_name)
-
- @property
- def application_name(self) -> str:
- return self._app_name if self._app_name is not None else ''
-
- @application_name.setter
- def application_name(self, application_name: str):
- self._app_name = application_name
-
- @property
- def customer(self) -> str:
- return self._customer if self._customer is not None else ''
-
- @customer.setter
- def customer(self, customer: str):
- self._customer = customer
-
- @property
- def content_root_path(self) -> str:
- return self._content_root_path
-
- @content_root_path.setter
- def content_root_path(self, content_root_path: str):
- self._content_root_path = content_root_path
-
- @property
- def host_name(self):
- return gethostname()
diff --git a/src/sh_edraft/environment/model/__init__.py b/src/sh_edraft/environment/model/__init__.py
deleted file mode 100644
index 59266f74..00000000
--- a/src/sh_edraft/environment/model/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.environment.model
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.environment.model'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .environment_name import EnvironmentName
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/hosting/__init__.py b/src/sh_edraft/hosting/__init__.py
deleted file mode 100644
index d650f7e0..00000000
--- a/src/sh_edraft/hosting/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.hosting
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.hosting'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .application_host import ApplicationHost
-from .application_runtime import ApplicationRuntime
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/hosting/application_host.py b/src/sh_edraft/hosting/application_host.py
deleted file mode 100644
index 1c5ed011..00000000
--- a/src/sh_edraft/hosting/application_host.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import atexit
-from datetime import datetime
-
-from sh_edraft.configuration.configuration import Configuration
-from sh_edraft.configuration.base.configuration_base import ConfigurationBase
-from sh_edraft.hosting.base.application_runtime_base import ApplicationRuntimeBase
-from sh_edraft.hosting.application_runtime import ApplicationRuntime
-from sh_edraft.hosting.base.application_host_base import ApplicationHostBase
-from sh_edraft.service.providing.service_provider import ServiceProvider
-from sh_edraft.service.providing.base.service_provider_base import ServiceProviderBase
-from sh_edraft.console.console import Console
-
-
-class ApplicationHost(ApplicationHostBase):
-
- def __init__(self):
- ApplicationHostBase.__init__(self)
-
- # Init
- self._config = Configuration()
- self._app_runtime = ApplicationRuntime(self._config)
- self._services = ServiceProvider(self._app_runtime)
-
- # Create
- self._config.create()
- self._services.create()
-
- # Set vars
- self._start_time: datetime = datetime.now()
- self._end_time: datetime = datetime.now()
-
- atexit.register(Console.close)
-
- @property
- def configuration(self) -> ConfigurationBase:
- return self._config
-
- @property
- def application_runtime(self) -> ApplicationRuntimeBase:
- return self._app_runtime
-
- @property
- def services(self) -> ServiceProviderBase:
- return self._services
-
- def create(self): pass
diff --git a/src/sh_edraft/hosting/application_runtime.py b/src/sh_edraft/hosting/application_runtime.py
deleted file mode 100644
index 5e903bb5..00000000
--- a/src/sh_edraft/hosting/application_runtime.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from datetime import datetime
-
-from sh_edraft.configuration.base.configuration_base import ConfigurationBase
-from sh_edraft.hosting.base.application_runtime_base import ApplicationRuntimeBase
-
-
-class ApplicationRuntime(ApplicationRuntimeBase):
-
- def __init__(self, config: ConfigurationBase):
- ApplicationRuntimeBase.__init__(self)
-
- self._app_configuration = config
- self._start_time: datetime = datetime.now()
- self._end_time: datetime = datetime.now()
-
- @property
- def configuration(self) -> ConfigurationBase:
- return self._app_configuration
-
- @property
- def start_time(self) -> datetime:
- return self._start_time
-
- @start_time.setter
- def start_time(self, start_time: datetime):
- self._start_time = start_time
-
- @property
- def end_time(self) -> datetime:
- return self._end_time
-
- @end_time.setter
- def end_time(self, end_time: datetime):
- self._end_time = end_time
-
- @property
- def date_time_now(self) -> datetime:
- return datetime.now()
diff --git a/src/sh_edraft/hosting/base/__init__.py b/src/sh_edraft/hosting/base/__init__.py
deleted file mode 100644
index 47f46211..00000000
--- a/src/sh_edraft/hosting/base/__init__.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.hosting.base
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.hosting.base'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .application_base import ApplicationBase
-from .application_host_base import ApplicationHostBase
-from .application_runtime_base import ApplicationRuntimeBase
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/hosting/base/application_base.py b/src/sh_edraft/hosting/base/application_base.py
deleted file mode 100644
index 00f72997..00000000
--- a/src/sh_edraft/hosting/base/application_base.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from abc import ABC, abstractmethod
-
-
-class ApplicationBase(ABC):
-
- @abstractmethod
- def __init__(self): pass
-
- @abstractmethod
- def create_application_host(self): pass
-
- @abstractmethod
- def create_configuration(self): pass
-
- @abstractmethod
- def create_services(self): pass
-
- @abstractmethod
- def main(self): pass
diff --git a/src/sh_edraft/hosting/base/application_host_base.py b/src/sh_edraft/hosting/base/application_host_base.py
deleted file mode 100644
index fb816ccb..00000000
--- a/src/sh_edraft/hosting/base/application_host_base.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from abc import ABC, abstractmethod
-
-from sh_edraft.configuration.base.configuration_base import ConfigurationBase
-from sh_edraft.hosting.base.application_runtime_base import ApplicationRuntimeBase
-from sh_edraft.service.providing.base.service_provider_base import ServiceProviderBase
-
-
-class ApplicationHostBase(ABC):
-
- @abstractmethod
- def __init__(self): pass
-
- @property
- @abstractmethod
- def configuration(self) -> ConfigurationBase: pass
-
- @property
- @abstractmethod
- def application_runtime(self) -> ApplicationRuntimeBase: pass
-
- @property
- @abstractmethod
- def services(self) -> ServiceProviderBase: pass
-
- @abstractmethod
- def create(self): pass
diff --git a/src/sh_edraft/hosting/base/application_runtime_base.py b/src/sh_edraft/hosting/base/application_runtime_base.py
deleted file mode 100644
index fd644270..00000000
--- a/src/sh_edraft/hosting/base/application_runtime_base.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from abc import ABC, abstractmethod
-from datetime import datetime
-
-from sh_edraft.configuration.base.configuration_base import ConfigurationBase
-
-
-class ApplicationRuntimeBase(ABC):
-
- @abstractmethod
- def __init__(self): pass
-
- @property
- @abstractmethod
- def configuration(self) -> ConfigurationBase: pass
-
- @property
- @abstractmethod
- def start_time(self) -> datetime: pass
-
- @start_time.setter
- @abstractmethod
- def start_time(self, start_time: datetime): pass
-
- @property
- @abstractmethod
- def end_time(self): pass
-
- @end_time.setter
- @abstractmethod
- def end_time(self, end_time: datetime): pass
-
- @property
- @abstractmethod
- def date_time_now(self) -> datetime: pass
diff --git a/src/sh_edraft/hosting/model/__init__.py b/src/sh_edraft/hosting/model/__init__.py
deleted file mode 100644
index 2ff0878e..00000000
--- a/src/sh_edraft/hosting/model/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.hosting.model
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.hosting.model'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/logging/__init__.py b/src/sh_edraft/logging/__init__.py
deleted file mode 100644
index 80fdec21..00000000
--- a/src/sh_edraft/logging/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.logging
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.logging'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .logger import Logger
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/logging/base/__init__.py b/src/sh_edraft/logging/base/__init__.py
deleted file mode 100644
index 83da99e0..00000000
--- a/src/sh_edraft/logging/base/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.logging.base
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.logging.base'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .logger_base import LoggerBase
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/logging/base/logger_base.py b/src/sh_edraft/logging/base/logger_base.py
deleted file mode 100644
index 2dc5de50..00000000
--- a/src/sh_edraft/logging/base/logger_base.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from abc import abstractmethod
-
-from sh_edraft.service.base.service_base import ServiceBase
-
-
-class LoggerBase(ServiceBase):
-
- @abstractmethod
- def __init__(self):
- ServiceBase.__init__(self)
-
- @abstractmethod
- def header(self, string: str): pass
-
- @abstractmethod
- def trace(self, name: str, message: str): pass
-
- @abstractmethod
- def debug(self, name: str, message: str): pass
-
- @abstractmethod
- def info(self, name: str, message: str): pass
-
- @abstractmethod
- def warn(self, name: str, message: str): pass
-
- @abstractmethod
- def error(self, name: str, message: str, ex: Exception = None): pass
-
- @abstractmethod
- def fatal(self, name: str, message: str, ex: Exception = None): pass
diff --git a/src/sh_edraft/logging/logger.py b/src/sh_edraft/logging/logger.py
deleted file mode 100644
index 6668132e..00000000
--- a/src/sh_edraft/logging/logger.py
+++ /dev/null
@@ -1,195 +0,0 @@
-import datetime
-import os
-import traceback
-from string import Template
-
-from sh_edraft.hosting.base.application_runtime_base import ApplicationRuntimeBase
-from sh_edraft.logging.base.logger_base import LoggerBase
-from sh_edraft.logging.model.logging_settings import LoggingSettings
-from sh_edraft.logging.model.logging_level import LoggingLevel
-from sh_edraft.time.model.time_format_settings import TimeFormatSettings
-from sh_edraft.console.console import Console
-from sh_edraft.console.model.foreground_color import ForegroundColor
-
-
-class Logger(LoggerBase):
-
- def __init__(self, logging_settings: LoggingSettings, time_format: TimeFormatSettings, app_runtime: ApplicationRuntimeBase):
- LoggerBase.__init__(self)
-
- self._app_runtime = app_runtime
- self._log_settings: LoggingSettings = logging_settings
- self._time_format_settings: TimeFormatSettings = time_format
-
- self._log = Template(self._log_settings.filename).substitute(
- date_time_now=self._app_runtime.date_time_now.strftime(self._time_format_settings.date_time_format),
- start_time=self._app_runtime.start_time.strftime(self._time_format_settings.date_time_log_format)
- )
- self._path = self._log_settings.path
- self._level = self._log_settings.level
- self._console = self._log_settings.console
-
- self.create()
-
- def _get_datetime_now(self) -> str:
- try:
- return datetime.datetime.now().strftime(self._time_format_settings.date_time_format)
- except Exception as e:
- self.error(__name__, 'Cannot get time', ex=e)
-
- def _get_date(self) -> str:
- try:
- return datetime.datetime.now().strftime(self._time_format_settings.date_format)
- except Exception as e:
- self.error(__name__, 'Cannot get date', ex=e)
-
- def create(self) -> None:
- """ path """
- try:
- # check if log file path exists
- if not os.path.exists(self._path):
- os.makedirs(self._path)
- except Exception as e:
- self._fatal_console(__name__, 'Cannot create log dir', ex=e)
-
- """ create new log file """
- try:
- # open log file, create if not exists
- path = f'{self._path}{self._log}'
- f = open(path, "w+")
- Console.write_line(f'[{__name__}]: Using log file: {path}')
- f.close()
- except Exception as e:
- self._fatal_console(__name__, 'Cannot open log file', ex=e)
-
- def _append_log(self, string):
- try:
- # open log file and append always
- if not os.path.isdir(self._path):
- self._fatal_console(__name__, 'Log directory not found')
-
- with open(self._path + self._log, "a+", encoding="utf-8") as f:
- f.write(string + '\n')
- f.close()
- except Exception as e:
- self._fatal_console(__name__, f'Cannot append log file, message: {string}', ex=e)
-
- def _get_string(self, name: str, level: LoggingLevel, message: str) -> str:
- log_level = level.name
- return f'<{self._get_datetime_now()}> [ {log_level} ] [ {name} ]: {message}'
-
- def header(self, string: str):
- # append log and print message
- self._append_log(string)
- Console.set_foreground_color(ForegroundColor.default)
- Console.write_line(string)
- Console.set_foreground_color(ForegroundColor.default)
-
- def trace(self, name: str, message: str):
- output = self._get_string(name, LoggingLevel.TRACE, message)
-
- # check if message can be written to log
- if self._level.value >= LoggingLevel.TRACE.value:
- self._append_log(output)
-
- # check if message can be shown in console
- if self._console.value >= LoggingLevel.TRACE.value:
- Console.set_foreground_color(ForegroundColor.green)
- Console.write_line(output)
- Console.set_foreground_color(ForegroundColor.default)
-
- def debug(self, name: str, message: str):
- output = self._get_string(name, LoggingLevel.DEBUG, message)
-
- # check if message can be written to log
- if self._level.value >= LoggingLevel.DEBUG.value:
- self._append_log(output)
-
- # check if message can be shown in console
- if self._console.value >= LoggingLevel.DEBUG.value:
- Console.set_foreground_color(ForegroundColor.green)
- Console.write_line(output)
- Console.set_foreground_color(ForegroundColor.default)
-
- def info(self, name: str, message: str):
- output = self._get_string(name, LoggingLevel.INFO, message)
-
- # check if message can be written to log
- if self._level.value >= LoggingLevel.INFO.value:
- self._append_log(output)
-
- # check if message can be shown in console
- if self._console.value >= LoggingLevel.INFO.value:
- Console.set_foreground_color(ForegroundColor.green)
- Console.write_line(output)
- Console.set_foreground_color(ForegroundColor.default)
-
- def warn(self, name: str, message: str):
- output = self._get_string(name, LoggingLevel.WARN, message)
-
- # check if message can be written to log
- if self._level.value >= LoggingLevel.WARN.value:
- self._append_log(output)
-
- # check if message can be shown in console
- if self._console.value >= LoggingLevel.WARN.value:
- Console.set_foreground_color(ForegroundColor.yellow)
- Console.write_line(output)
- Console.set_foreground_color(ForegroundColor.default)
-
- def error(self, name: str, message: str, ex: Exception = None):
- output = ''
- if ex is not None:
- tb = traceback.format_exc()
- self.error(name, message)
- output = self._get_string(name, LoggingLevel.ERROR, f'{ex} -> {tb}')
- else:
- output = self._get_string(name, LoggingLevel.ERROR, message)
-
- # check if message can be written to log
- if self._level.value >= LoggingLevel.ERROR.value:
- self._append_log(output)
-
- # check if message can be shown in console
- if self._console.value >= LoggingLevel.ERROR.value:
- Console.set_foreground_color(ForegroundColor.red)
- Console.write_line(output)
- Console.set_foreground_color(ForegroundColor.default)
-
- def fatal(self, name: str, message: str, ex: Exception = None):
- output = ''
- if ex is not None:
- tb = traceback.format_exc()
- self.error(name, message)
- output = self._get_string(name, LoggingLevel.FATAL, f'{ex} -> {tb}')
- else:
- output = self._get_string(name, LoggingLevel.FATAL, message)
-
- # check if message can be written to log
- if self._level.value >= LoggingLevel.FATAL.value:
- self._append_log(output)
-
- # check if message can be shown in console
- if self._console.value >= LoggingLevel.FATAL.value:
- Console.set_foreground_color(ForegroundColor.red)
- Console.write_line(output)
- Console.set_foreground_color(ForegroundColor.default)
-
- exit()
-
- def _fatal_console(self, name: str, message: str, ex: Exception = None):
- output = ''
- if ex is not None:
- tb = traceback.format_exc()
- self.error(name, message)
- output = self._get_string(name, LoggingLevel.ERROR, f'{ex} -> {tb}')
- else:
- output = self._get_string(name, LoggingLevel.ERROR, message)
-
- # check if message can be shown in console
- if self._console.value >= LoggingLevel.FATAL.value:
- Console.set_foreground_color(ForegroundColor.red)
- Console.write_line(output)
- Console.set_foreground_color(ForegroundColor.default)
-
- exit()
diff --git a/src/sh_edraft/logging/model/__init__.py b/src/sh_edraft/logging/model/__init__.py
deleted file mode 100644
index e7bcd608..00000000
--- a/src/sh_edraft/logging/model/__init__.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.logging.model
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.logging.model'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .logging_level import LoggingLevel
-from .logging_settings import LoggingSettings
-from .logging_settings_name import LoggingSettingsName
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/logging/model/logging_settings.py b/src/sh_edraft/logging/model/logging_settings.py
deleted file mode 100644
index 563369cc..00000000
--- a/src/sh_edraft/logging/model/logging_settings.py
+++ /dev/null
@@ -1,62 +0,0 @@
-import traceback
-from typing import Optional
-
-from sh_edraft.configuration.base.configuration_model_base import ConfigurationModelBase
-from sh_edraft.logging.model.logging_settings_name import LoggingSettingsName
-from sh_edraft.logging.model.logging_level import LoggingLevel
-from sh_edraft.console.console import Console
-from sh_edraft.console.model.foreground_color import ForegroundColor
-
-
-class LoggingSettings(ConfigurationModelBase):
-
- def __init__(self):
- ConfigurationModelBase.__init__(self)
- self._path: Optional[str] = None
- self._filename: Optional[str] = None
- self._console: Optional[LoggingLevel] = None
- self._level: Optional[LoggingLevel] = None
-
- @property
- def path(self) -> str:
- return self._path
-
- @path.setter
- def path(self, path: str) -> None:
- self._path = path
-
- @property
- def filename(self) -> str:
- return self._filename
-
- @filename.setter
- def filename(self, filename: str) -> None:
- self._filename = filename
-
- @property
- def console(self) -> LoggingLevel:
- return self._console
-
- @console.setter
- def console(self, console: LoggingLevel) -> None:
- self._console = console
-
- @property
- def level(self) -> LoggingLevel:
- return self._level
-
- @level.setter
- def level(self, level: LoggingLevel) -> None:
- self._level = level
-
- def from_dict(self, settings: dict):
- try:
- self._path = settings[LoggingSettingsName.path.value]
- self._filename = settings[LoggingSettingsName.filename.value]
- self._console = LoggingLevel[settings[LoggingSettingsName.console_level.value]]
- self._level = LoggingLevel[settings[LoggingSettingsName.file_level.value]]
- except Exception as e:
- Console.set_foreground_color(ForegroundColor.red)
- Console.write_line(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings')
- Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
- Console.set_foreground_color(ForegroundColor.default)
diff --git a/src/sh_edraft/mailing/__init__.py b/src/sh_edraft/mailing/__init__.py
deleted file mode 100644
index db3f827b..00000000
--- a/src/sh_edraft/mailing/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.mailing
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.mailing'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .email_client import EMailClient
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/mailing/base/__init__.py b/src/sh_edraft/mailing/base/__init__.py
deleted file mode 100644
index 587aab2c..00000000
--- a/src/sh_edraft/mailing/base/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.mailing.base
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.mailing.base'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .email_client_base import EMailClientBase
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/mailing/base/email_client_base.py b/src/sh_edraft/mailing/base/email_client_base.py
deleted file mode 100644
index bbb98879..00000000
--- a/src/sh_edraft/mailing/base/email_client_base.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from abc import abstractmethod
-
-from sh_edraft.mailing.model.email import EMail
-from sh_edraft.service.base.service_base import ServiceBase
-
-
-class EMailClientBase(ServiceBase):
-
- @abstractmethod
- def __init__(self):
- ServiceBase.__init__(self)
-
- @abstractmethod
- def connect(self): pass
-
- @abstractmethod
- def send_mail(self, email: EMail): pass
diff --git a/src/sh_edraft/mailing/model/__init__.py b/src/sh_edraft/mailing/model/__init__.py
deleted file mode 100644
index ee1b8eb3..00000000
--- a/src/sh_edraft/mailing/model/__init__.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.mailing.model
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.mailing.model'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .email import EMail
-from .email_client_settings_name import EMailClientSettingsName
-from .email_client_settings import EMailClientSettings
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/publish/model/publish_settings_model.py b/src/sh_edraft/publish/model/publish_settings_model.py
deleted file mode 100644
index 3a1f8ce5..00000000
--- a/src/sh_edraft/publish/model/publish_settings_model.py
+++ /dev/null
@@ -1,90 +0,0 @@
-import traceback
-from typing import Optional
-
-from sh_edraft.configuration.base.configuration_model_base import ConfigurationModelBase
-from sh_edraft.publish.model.template import Template
-from sh_edraft.publish.model.publish_settings_name import PublishSettingsName
-from sh_edraft.console.console import Console
-from sh_edraft.console.model.foreground_color import ForegroundColor
-
-
-class PublishSettings(ConfigurationModelBase):
-
- def __init__(self):
- ConfigurationModelBase.__init__(self)
-
- self._source_path: Optional[str] = None
- self._dist_path: Optional[str] = None
- self._templates: list[Template] = []
-
- self._included_files: list[str] = []
- self._excluded_files: list[str] = []
-
- self._template_ending: Optional[str] = None
-
- @property
- def source_path(self) -> str:
- return self._source_path
-
- @source_path.setter
- def source_path(self, source_path: str):
- self._source_path = source_path
-
- @property
- def dist_path(self) -> str:
- return self._dist_path
-
- @dist_path.setter
- def dist_path(self, dist_path: str):
- self._dist_path = dist_path
-
- @property
- def templates(self) -> list[Template]:
- return self._templates
-
- @templates.setter
- def templates(self, templates: list[Template]):
- self._templates = templates
-
- @property
- def included_files(self) -> list[str]:
- return self._included_files
-
- @included_files.setter
- def included_files(self, included_files: list[str]):
- self._included_files = included_files
-
- @property
- def excluded_files(self) -> list[str]:
- return self._excluded_files
-
- @excluded_files.setter
- def excluded_files(self, excluded_files: list[str]):
- self._excluded_files = excluded_files
-
- @property
- def template_ending(self) -> str:
- return self._template_ending
-
- @template_ending.setter
- def template_ending(self, template_ending: str):
- self._template_ending = template_ending
-
- def from_dict(self, settings: dict):
- try:
- self._source_path = settings[PublishSettingsName.source_path.value]
- self._dist_path = settings[PublishSettingsName.dist_path.value]
- for template in settings[PublishSettingsName.templates.value]:
- temp = Template()
- temp.from_dict(template)
- self._templates.append(temp)
-
- self._included_files = settings[PublishSettingsName.included_files.value]
- self._excluded_files = settings[PublishSettingsName.excluded_files.value]
- self._template_ending = settings[PublishSettingsName.template_ending.value]
- except Exception as e:
- Console.set_foreground_color(ForegroundColor.red)
- Console.write_line(
- f'[ ERROR ] [ {__name__} ]: Reading error in {PublishSettingsName.publish.value} settings')
- Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
- Console.set_foreground_color(ForegroundColor.default)
diff --git a/src/sh_edraft/publish/model/publish_settings_name.py b/src/sh_edraft/publish/model/publish_settings_name.py
deleted file mode 100644
index 80033c68..00000000
--- a/src/sh_edraft/publish/model/publish_settings_name.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from enum import Enum
-
-
-class PublishSettingsName(Enum):
-
- publish = 'Publish'
- source_path = 'SourcePath'
- dist_path = 'DistPath'
- templates = 'Templates'
- included_files = 'IncludedFiles'
- excluded_files = 'ExcludedFiles'
- template_ending = 'TemplateEnding'
diff --git a/src/sh_edraft/publish/model/template.py b/src/sh_edraft/publish/model/template.py
deleted file mode 100644
index b98a4738..00000000
--- a/src/sh_edraft/publish/model/template.py
+++ /dev/null
@@ -1,122 +0,0 @@
-from typing import Optional
-
-from sh_edraft.coding.model.version import Version
-from sh_edraft.configuration.base.configuration_model_base import ConfigurationModelBase
-from sh_edraft.publish.model.template_enum import TemplateEnum
-
-
-class Template(ConfigurationModelBase):
-
- def __init__(
- self,
- template_path: Optional[str] = None,
- name: Optional[str] = None,
- description: Optional[str] = None,
- long_description: Optional[str] = None,
- copyright_date: Optional[str] = None,
- copyright_name: Optional[str] = None,
- license_name: Optional[str] = None,
- license_description: Optional[str] = None,
- title: Optional[str] = None,
- author: Optional[str] = None,
- version: Optional[Version] = Version()
- ):
- ConfigurationModelBase.__init__(self)
- self._template_path: Optional[str] = template_path
- self._name: Optional[str] = name
- self._description: Optional[str] = description
- self._long_description: Optional[str] = long_description
- self._copyright_date: Optional[str] = copyright_date
- self._copyright_name: Optional[str] = copyright_name
- self._license_name: Optional[str] = license_name
- self._license_description: Optional[str] = license_description
- self._title: Optional[str] = title
- self._author: Optional[str] = author
-
- self._version: Optional[Version] = version
-
- self._file_content: Optional[str] = None
-
- @property
- def template_path(self) -> Optional[str]:
- return self._template_path
-
- @property
- def name(self) -> Optional[str]:
- return self._name
-
- @property
- def description(self) -> Optional[str]:
- return self._description
-
- @property
- def long_description(self) -> Optional[str]:
- return self._long_description
-
- @property
- def copyright_date(self) -> Optional[str]:
- return self._copyright_date
-
- @property
- def copyright_name(self) -> Optional[str]:
- return self._copyright_name
-
- @property
- def license_name(self) -> Optional[str]:
- return self._license_name
-
- @property
- def license_description(self) -> Optional[str]:
- return self._license_description
-
- @property
- def title(self) -> Optional[str]:
- return self._title
-
- @property
- def author(self) -> Optional[str]:
- return self._author
-
- @property
- def version(self) -> Optional[Version]:
- return self._version
-
- @property
- def file_content(self) -> Optional[str]:
- return self._file_content
-
- @file_content.setter
- def file_content(self, file_content: Optional[str]):
- self._file_content = file_content
-
- def from_dict(self, settings: dict):
- self._template_path = settings[TemplateEnum.TemplatePath.value]
- self._name = settings[TemplateEnum.Name.value]
- self._description = settings[TemplateEnum.Description.value]
- self._long_description = settings[TemplateEnum.LongDescription.value]
- self._copyright_date = settings[TemplateEnum.CopyrightDate.value]
- self._copyright_name = settings[TemplateEnum.CopyrightName.value]
- self._license_name = settings[TemplateEnum.LicenseName.value]
- self._license_description = settings[TemplateEnum.LicenseDescription.value]
- self._title = settings[TemplateEnum.Title.value]
- self._author = settings[TemplateEnum.Author.value]
- self._version.from_dict(settings[TemplateEnum.Version.value])
-
- def to_dict(self) -> dict:
- version: Optional[dict] = None
- if self._version is not None:
- version = self._version.to_dict()
-
- return {
- TemplateEnum.TemplatePath.value: self._template_path,
- TemplateEnum.Name.value: self._name,
- TemplateEnum.Description.value: self._description,
- TemplateEnum.LongDescription.value: self._long_description,
- TemplateEnum.CopyrightDate.value: self._copyright_date,
- TemplateEnum.CopyrightName.value: self._copyright_name,
- TemplateEnum.LicenseName.value: self._license_name,
- TemplateEnum.LicenseDescription.value: self._license_description,
- TemplateEnum.Title.value: self._title,
- TemplateEnum.Author.value: self._author,
- TemplateEnum.Version.value: version
- }
diff --git a/src/sh_edraft/publish/model/template_enum.py b/src/sh_edraft/publish/model/template_enum.py
deleted file mode 100644
index f628c4ce..00000000
--- a/src/sh_edraft/publish/model/template_enum.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from enum import Enum
-
-
-class TemplateEnum(Enum):
-
- TemplatePath = 'TemplatePath'
- Name = 'Name'
- Description = 'Description'
- LongDescription = 'LongDescription'
- CopyrightDate = 'CopyrightDate'
- CopyrightName = 'CopyrightName'
- LicenseName = 'LicenseName'
- LicenseDescription = 'LicenseDescription'
- Title = 'Title'
- Author = 'Author'
- Version = 'Version'
diff --git a/src/sh_edraft/publish/publisher.py b/src/sh_edraft/publish/publisher.py
deleted file mode 100644
index 2ddd2b15..00000000
--- a/src/sh_edraft/publish/publisher.py
+++ /dev/null
@@ -1,279 +0,0 @@
-import os
-import shutil
-from string import Template as stringTemplate
-
-from setuptools import sandbox
-
-from sh_edraft.logging.base.logger_base import LoggerBase
-from sh_edraft.publish.base.publisher_base import PublisherBase
-from sh_edraft.publish.model.publish_settings_model import PublishSettings
-from sh_edraft.publish.model.template import Template
-
-
-class Publisher(PublisherBase):
-
- def __init__(self, logger: LoggerBase, publish_settings: PublishSettings):
- PublisherBase.__init__(self)
-
- self._logger: LoggerBase = logger
- self._publish_settings: PublishSettings = publish_settings
-
- self._included_files: list[str] = []
-
- @property
- def source_path(self) -> str:
- return self._publish_settings.source_path
-
- @property
- def dist_path(self):
- return self._publish_settings.dist_path
-
- def _get_template_output(self, t: Template, name: str, imports: str) -> str:
- self._logger.trace(__name__, f'Started {__name__}._get_template_output')
- try:
- if t.file_content == '':
- raise Exception(f'Template is empty: {t.template_path}')
-
- self._logger.trace(__name__, f'Stopped {__name__}._get_template_output')
- return stringTemplate(t.file_content).substitute(
- Name=name,
- Description=t.description,
- LongDescription=t.long_description,
- CopyrightDate=t.copyright_date,
- CopyrightName=t.copyright_name,
- LicenseName=t.license_name,
- LicenseDescription=t.license_description,
- Title=t.title if t.title is not None and t.title != '' else name,
- Author=t.author,
- Version=t.version.to_str(),
- Major=t.version.major,
- Minor=t.version.minor,
- Micro=t.version.micro,
- Imports=imports
- )
- except Exception as e:
- self._logger.fatal(__name__, f'Cannot read Template: {t.template_path}', e)
- self._logger.trace(__name__, f'Stopped {__name__}._get_template_output')
-
- def _read_source_path(self):
- self._logger.trace(__name__, f'Started {__name__}._read_source_path')
- included_files = self._publish_settings.included_files
- for included in included_files:
- if os.path.isdir(included):
- self._publish_settings.included_files.remove(included)
-
- for r, d, f in os.walk(included):
- for file in f:
- rel_path = os.path.relpath(r)
- if not rel_path.startswith('.'):
- rel_path = f'./{rel_path}'
-
- file_path = os.path.join(self._publish_settings.source_path, r, file)
- if os.path.isfile(file_path):
- self._included_files.append(file_path)
- elif os.path.isfile(os.path.join(rel_path, file)):
- self._included_files.append(os.path.join(rel_path, file))
- else:
- self._logger.fatal(__name__, f'File not found: {file}')
-
- elif os.path.isfile(included):
- self._included_files.append(included)
- else:
- self._logger.fatal(__name__, f'File not found: {included}')
-
- for r, d, f in os.walk(self._publish_settings.source_path):
- for file in f:
- is_file_excluded = False
- if os.path.join(r, file) in self._publish_settings.excluded_files:
- is_file_excluded = True
- else:
- for excluded in self._publish_settings.excluded_files:
- if os.path.join(r, file).__contains__(excluded):
- is_file_excluded = True
-
- if not is_file_excluded and file.endswith('.py') or file in self._publish_settings.included_files:
- self._included_files.append(os.path.join(r, file))
-
- self._logger.trace(__name__, f'Stopped {__name__}._read_source_path')
-
- def _read_templates(self):
- self._logger.trace(__name__, f'Started {__name__}._read_templates')
- for t in self._publish_settings.templates:
- output_template: str = ''
- if not os.path.isfile(t.template_path):
- self._logger.fatal(__name__, f'Template not found: {t.template_path}')
-
- with open(t.template_path) as template:
- t.file_content = template.read()
- template.close()
- if t.file_content == '':
- self._logger.fatal(__name__, f'Template is empty: {t.template_path}')
-
- self._logger.trace(__name__, f'Stopped {__name__}._read_templates')
-
- def _create_dist_path(self):
- self._logger.trace(__name__, f'Started {__name__}._create_dist_path')
- if os.path.isdir(self._publish_settings.dist_path):
- try:
- shutil.rmtree(self._publish_settings.dist_path)
- self._logger.info(__name__, f'Deleted {self._publish_settings.dist_path}')
- except Exception as e:
- self._logger.fatal(__name__, f'Cannot delete old dist directory', e)
-
- if not os.path.isdir(self._publish_settings.dist_path):
- try:
- os.makedirs(self._publish_settings.dist_path)
- self._logger.debug(__name__, f'Created directories: {self._publish_settings.dist_path}')
- self._logger.info(__name__, f'Created dist directory')
- except Exception as e:
- self._logger.fatal(__name__, f'Cannot create dist directory', e)
-
- self._logger.trace(__name__, f'Stopped {__name__}._create_dist_path')
-
- @staticmethod
- def _get_template_name_from_dirs(file: str) -> str:
- dirs = os.path.dirname(file).split('/')
- for d in dirs:
- if d.__contains__('.'):
- dirs.remove(d)
-
- if len(dirs) == 0:
- return os.path.basename(file)
- else:
- return '.'.join(dirs)
-
- def _write_templates(self):
- self._logger.trace(__name__, f'Started {__name__}._write_templates')
- for template in self._publish_settings.templates:
- for file in self._included_files:
- if os.path.basename(file) == '__init__.py' and file not in self._publish_settings.excluded_files:
- template_name = template.name
- if template.name == 'all' or template.name == '':
- template_name = self._get_template_name_from_dirs(file)
- else:
- name = self._get_template_name_from_dirs(file)
-
- if name.__contains__('.'):
- if template.name != name.split('.')[len(name.split('.')) - 1]:
- continue
-
- else:
- if template.name != name:
- continue
-
- try:
- module_file_lines: list[str] = []
- module_py_lines: list[str] = []
- imports = ''
- with open(file, 'r') as py_file:
- module_file_lines = py_file.readlines()
- py_file.close()
-
- if len(module_file_lines) == 0:
- with open(file, 'w+') as py_file:
- py_file.write(self._get_template_output(template, template_name, '# imports:'))
- py_file.close()
- self._logger.debug(__name__, f'Written to {file}')
- else:
- is_started = False
- for line in module_file_lines:
- if line.__contains__('# imports'):
- is_started = True
-
- if (line.__contains__('from') or line.__contains__('import')) and is_started:
- module_py_lines.append(line.replace('\n', ''))
-
- if len(module_py_lines) > 0:
- imports = '\n'.join(module_py_lines)
-
- with open(file, 'w+') as py_file:
- py_file.write(self._get_template_output(template, template_name, imports))
- py_file.close()
- self._logger.debug(__name__, f'Written to {file}')
-
- except Exception as e:
- self._logger.error(__name__, f'Cannot write to file: {file}', e)
-
- self._logger.info(__name__, f'Written to all included modules')
- self._logger.trace(__name__, f'Stopped {__name__}._write_templates')
-
- def _copy_all_included_files(self):
- self._logger.trace(__name__, f'Started {__name__}._copy_all_included_files')
- dist_path = self._publish_settings.dist_path
- if self._publish_settings.dist_path.endswith('/'):
- dist_path = dist_path[:len(dist_path) - 1]
-
- for file in self._included_files:
- is_file_excluded = False
- if file in self._publish_settings.excluded_files:
- is_file_excluded = True
- else:
- for excluded in self._publish_settings.excluded_files:
- if file.__contains__(excluded):
- is_file_excluded = True
-
- if not is_file_excluded:
- output_file = ''
-
- if file.startswith('..'):
- output_file = file.replace('..', '')
- elif file.startswith('.'):
- output_file = file.replace('.', '', 1)
-
- if output_file.__contains__('..'):
- output_file = os.path.join(dist_path, os.path.basename(file))
- else:
- output_file = f'{dist_path}{output_file}'
-
- output_path = os.path.dirname(output_file)
-
- try:
- if not os.path.isdir(output_path):
- os.makedirs(output_path, exist_ok=True)
- except Exception as e:
- self._logger.error(__name__, f'Cannot create directories: {output_path}', e)
-
- try:
- shutil.copy(file, output_file)
- except Exception as e:
- self._logger.error(__name__, f'Cannot copy file: {file} to {output_path}', e)
-
- self._logger.debug(__name__, f'Copied {file} to {output_path}')
-
- self._logger.info(__name__, f'Copied all included files')
- self._logger.trace(__name__, f'Stopped {__name__}._copy_all_included_files')
-
- def include(self, path: str):
- self._logger.trace(__name__, f'Started {__name__}.include')
- self._publish_settings.included_files.append(path)
- self._logger.trace(__name__, f'Stopped {__name__}.include')
-
- def exclude(self, path: str):
- self._logger.trace(__name__, f'Started {__name__}.exclude')
- self._publish_settings.excluded_files.append(path)
- self._logger.trace(__name__, f'Stopped {__name__}.exclude')
-
- def create(self):
- self._logger.trace(__name__, f'Started {__name__}.create')
- if not self._publish_settings.dist_path.endswith('/'):
- self._publish_settings.dist_path += '/'
-
- self._read_source_path()
- self._read_templates()
- self._create_dist_path()
- self._logger.trace(__name__, f'Stopped {__name__}.create')
-
- def build(self):
- self._logger.trace(__name__, f'Started {__name__}.build')
- self._write_templates()
- self._copy_all_included_files()
- self._logger.trace(__name__, f'Stopped {__name__}.build')
-
- def publish(self):
- self._logger.trace(__name__, f'Started {__name__}.publish')
- setup_py = os.path.join(self._publish_settings.dist_path, 'setup.py')
- if not os.path.isfile(setup_py):
- self._logger.fatal(__name__, f'setup.py not found in {self._publish_settings.dist_path}')
-
- sandbox.run_setup(os.path.abspath(setup_py), ['sdist', 'bdist_wheel'])
- self._logger.trace(__name__, f'Stopped {__name__}.publish')
diff --git a/src/sh_edraft/publishing/__init__.py b/src/sh_edraft/publishing/__init__.py
deleted file mode 100644
index 62c88c4e..00000000
--- a/src/sh_edraft/publishing/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.publishing
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.publishing'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .publisher import Publisher
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/publishing/base/__init__.py b/src/sh_edraft/publishing/base/__init__.py
deleted file mode 100644
index a462ce7c..00000000
--- a/src/sh_edraft/publishing/base/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.publishing.base
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.publishing.base'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .publisher_base import PublisherBase
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/publishing/model/__init__.py b/src/sh_edraft/publishing/model/__init__.py
deleted file mode 100644
index 54283917..00000000
--- a/src/sh_edraft/publishing/model/__init__.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.publishing.model
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.publishing.model'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .template import Template
-from .template_enum import TemplateEnum
-from .publish_settings_model import PublishSettings
-from .publish_settings_name import PublishSettingsName
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/service/__init__.py b/src/sh_edraft/service/__init__.py
deleted file mode 100644
index 7d487f52..00000000
--- a/src/sh_edraft/service/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.service
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.service'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/service/base/__init__.py b/src/sh_edraft/service/base/__init__.py
deleted file mode 100644
index 73148fb0..00000000
--- a/src/sh_edraft/service/base/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.service.base
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.service.base'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .service_base import ServiceBase
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/service/providing/__init__.py b/src/sh_edraft/service/providing/__init__.py
deleted file mode 100644
index a532dc9d..00000000
--- a/src/sh_edraft/service/providing/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.service.providing
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.service.providing'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.10'
-
-from collections import namedtuple
-
-# imports:
-from .service_provider import ServiceProvider
-from .service_provider import ServiceProviderBase
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=10)
diff --git a/src/sh_edraft/service/providing/base/__init__.py b/src/sh_edraft/service/providing/base/__init__.py
deleted file mode 100644
index 740e8631..00000000
--- a/src/sh_edraft/service/providing/base/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.service.providing.base
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.service.providing.base'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .service_provider_base import ServiceProviderBase
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/service/providing/base/service_provider_base.py b/src/sh_edraft/service/providing/base/service_provider_base.py
deleted file mode 100644
index 28c986f0..00000000
--- a/src/sh_edraft/service/providing/base/service_provider_base.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from abc import abstractmethod, ABC
-from collections import Callable
-from typing import Type
-
-from sh_edraft.database.context.base.database_context_base import DatabaseContextBase
-from sh_edraft.service.base.service_base import ServiceBase
-
-
-class ServiceProviderBase(ABC):
-
- @abstractmethod
- def __init__(self): pass
-
- @abstractmethod
- def add_db_context(self, db_context: Type[DatabaseContextBase]): pass
-
- @abstractmethod
- def get_db_context(self) -> Callable[DatabaseContextBase]: pass
-
- @abstractmethod
- def add_transient(self, service_type: Type[ServiceBase], service: Type[ServiceBase]): pass
-
- @abstractmethod
- def add_scoped(self, service_type: Type[ServiceBase], service: Type[ServiceBase]): pass
-
- @abstractmethod
- def add_singleton(self, service_type: Type[ServiceBase], service: Callable[ServiceBase]): pass
-
- @abstractmethod
- def get_service(self, instance_type: Type[ServiceBase]) -> Callable[ServiceBase]: pass
-
- @abstractmethod
- def remove_service(self, instance_type: type): pass
diff --git a/src/sh_edraft/service/providing/model/__init__.py b/src/sh_edraft/service/providing/model/__init__.py
deleted file mode 100644
index 779edb8d..00000000
--- a/src/sh_edraft/service/providing/model/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.service.providing.model
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.service.providing.model'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .provide_state import ProvideState
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/service/providing/model/provide_state.py b/src/sh_edraft/service/providing/model/provide_state.py
deleted file mode 100644
index 52d0af05..00000000
--- a/src/sh_edraft/service/providing/model/provide_state.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from typing import Type
-
-from sh_edraft.service.base.service_base import ServiceBase
-
-
-class ProvideState:
-
- def __init__(self, service: Type[ServiceBase] = None, args: tuple = None):
- self._service: Type[ServiceBase] = service
- self._args: tuple = args
-
- @property
- def service(self):
- return self._service
-
- @property
- def args(self) -> tuple:
- return self._args
diff --git a/src/sh_edraft/service/providing/service_provider.py b/src/sh_edraft/service/providing/service_provider.py
deleted file mode 100644
index 2ba39e4c..00000000
--- a/src/sh_edraft/service/providing/service_provider.py
+++ /dev/null
@@ -1,95 +0,0 @@
-from collections import Callable
-from inspect import signature, Parameter
-from typing import Type, Optional
-
-from sh_edraft.configuration.base.configuration_model_base import ConfigurationModelBase
-from sh_edraft.database.context.base.database_context_base import DatabaseContextBase
-from sh_edraft.environment.base import EnvironmentBase
-from sh_edraft.hosting.base.application_runtime_base import ApplicationRuntimeBase
-from sh_edraft.service.providing.base.service_provider_base import ServiceProviderBase
-from sh_edraft.service.base.service_base import ServiceBase
-
-
-class ServiceProvider(ServiceProviderBase):
-
- def __init__(self, app_runtime: ApplicationRuntimeBase):
- ServiceProviderBase.__init__(self)
- self._app_runtime: ApplicationRuntimeBase = app_runtime
- self._database_context: Optional[DatabaseContextBase] = None
-
- self._transient_services: dict[Type[ServiceBase], Type[ServiceBase]] = {}
- self._scoped_services: dict[Type[ServiceBase], Type[ServiceBase]] = {}
- self._singleton_services: dict[Type[ServiceBase], ServiceBase] = {}
-
- def create(self): pass
-
- def _create_instance(self, service: Callable[ServiceBase]) -> ServiceBase:
- sig = signature(service.__init__)
- params = []
- for param in sig.parameters.items():
- parameter = param[1]
- if parameter.name != 'self' and parameter.annotation != Parameter.empty:
- if issubclass(parameter.annotation, ApplicationRuntimeBase):
- params.append(self._app_runtime)
-
- elif issubclass(parameter.annotation, EnvironmentBase):
- params.append(self._app_runtime.configuration.environment)
-
- elif issubclass(parameter.annotation, DatabaseContextBase):
- params.append(self._database_context)
-
- elif issubclass(parameter.annotation, ServiceBase):
- params.append(self.get_service(parameter.annotation))
-
- elif issubclass(parameter.annotation, ConfigurationModelBase):
- params.append(self._app_runtime.configuration.get_configuration(parameter.annotation))
-
- return service(*params)
-
- def add_db_context(self, db_context: Type[DatabaseContextBase]):
- self._database_context = self._create_instance(db_context)
-
- def get_db_context(self) -> Callable[DatabaseContextBase]:
- return self._database_context
-
- def add_transient(self, service_type: Type[ServiceBase], service: Type[ServiceBase]):
- self._transient_services[service_type] = service
-
- def add_scoped(self, service_type: Type[ServiceBase], service: Type[ServiceBase]):
- self._scoped_services[service_type] = service
-
- def add_singleton(self, service_type: Type[ServiceBase], service: Callable[ServiceBase]):
- for known_service in self._singleton_services:
- if type(known_service) == service_type:
- raise Exception(f'Service with type {service_type} already exists')
-
- self._singleton_services[service_type] = self._create_instance(service)
-
- def get_service(self, instance_type: Type[ServiceBase]) -> Callable[ServiceBase]:
- for service in self._transient_services:
- if service == instance_type and isinstance(self._transient_services[service], type(instance_type)):
- return self._create_instance(self._transient_services[service])
-
- for service in self._scoped_services:
- if service == instance_type and isinstance(self._scoped_services[service], type(instance_type)):
- return self._create_instance(self._scoped_services[service])
-
- for service in self._singleton_services:
- if service == instance_type and isinstance(self._singleton_services[service], instance_type):
- return self._singleton_services[service]
-
- def remove_service(self, instance_type: Type[ServiceBase]):
- for service in self._transient_services:
- if service == instance_type and isinstance(self._transient_services[service], type(instance_type)):
- del self._transient_services[service]
- return
-
- for service in self._scoped_services:
- if service == instance_type and isinstance(self._scoped_services[service], type(instance_type)):
- del self._scoped_services[service]
- return
-
- for service in self._singleton_services:
- if service == instance_type and isinstance(self._singleton_services[service], instance_type):
- del self._singleton_services[service]
- return
diff --git a/src/sh_edraft/time/__init__.py b/src/sh_edraft/time/__init__.py
deleted file mode 100644
index d8460af8..00000000
--- a/src/sh_edraft/time/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.time
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.time'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/time/model/__init__.py b/src/sh_edraft/time/model/__init__.py
deleted file mode 100644
index 1056120c..00000000
--- a/src/sh_edraft/time/model/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.time.model
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.time.model'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .time_format_settings import TimeFormatSettings
-from .time_format_settings_names import TimeFormatSettingsNames
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/sh_edraft/utils/__init__.py b/src/sh_edraft/utils/__init__.py
deleted file mode 100644
index ab011b6e..00000000
--- a/src/sh_edraft/utils/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-sh_edraft.utils
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'sh_edraft.utils'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-from .credential_manager import CredentialManager
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/tests/__init__.py b/src/tests/__init__.py
index 924bb32a..71ee2167 100644
--- a/src/tests/__init__.py
+++ b/src/tests/__init__.py
@@ -1,25 +1,25 @@
# -*- coding: utf-8 -*-
"""
-tests
+sh_cpl sh-edraft Common Python library
~~~~~~~~~~~~~~~~~~~
+sh-edraft Common Python library
-
-:copyright: (c) 2020 sh-edraft.de
+:copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
-__title__ = 'tests'
+__title__ = 'sh_cpl.tests'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.1'
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
+version_info = VersionInfo(major=2021, minor=4, micro=1)
diff --git a/src/tests/appsettings.edrafts-lapi.json b/src/tests/appsettings.edrafts-lapi.json
deleted file mode 100644
index 9af6f6c0..00000000
--- a/src/tests/appsettings.edrafts-lapi.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "TimeFormatSettings": {
- "DateFormat": "%Y-%m-%d",
- "TimeFormat": "%H:%M:%S",
- "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
- "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
- },
- "LoggingSettings": {
- "Path": "logs/",
- "Filename": "log_$start_time.log",
- "ConsoleLogLevel": "TRACE",
- "FileLogLevel": "TRACE"
- },
- "EMailClientSettings": {
- "Host": "mail.sh-edraft.de",
- "Port": "587",
- "UserName": "dev-srv@sh-edraft.de",
- "Credentials": "RmBOQX1eNFYiYjgsSid3fV1nelc2WA=="
- }
-}
\ No newline at end of file
diff --git a/src/tests/build.json b/src/tests/build.json
deleted file mode 100644
index 3921c95f..00000000
--- a/src/tests/build.json
+++ /dev/null
@@ -1,59 +0,0 @@
-{
- "TimeFormatSettings": {
- "DateFormat": "%Y-%m-%d",
- "TimeFormat": "%H:%M:%S",
- "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
- "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
- },
- "LoggingSettings": {
- "Path": "../../build_test/logs/",
- "Filename": "log_$start_time.log",
- "ConsoleLogLevel": "INFO",
- "FileLogLevel": "TRACE"
- },
- "PublishSettings": {
- "SourcePath": "./",
- "DistPath": "../../build_test/dist",
- "Templates": [
- {
- "TemplatePath": "../../publish_templates/all_template.txt",
- "Name": "all",
- "Description": "",
- "LongDescription": "",
- "CopyrightDate": "2020",
- "CopyrightName": "sh-edraft.de",
- "LicenseName": "MIT",
- "LicenseDescription": ", see LICENSE for more details.",
- "Title": "",
- "Author": "Sven Heidemann",
- "Version": {
- "Major": 2020,
- "Minor": 12,
- "Micro": 10
- }
- },
- {
- "TemplatePath": "../../publish_templates/all_template.txt",
- "Name": "sh_edraft",
- "Description": "common python library",
- "LongDescription": "Library to share common classes and models used at sh-edraft.de",
- "CopyrightDate": "2020",
- "CopyrightName": "sh-edraft.de",
- "LicenseName": "MIT",
- "LicenseDescription": ", see LICENSE for more details.",
- "Title": "",
- "Author": "Sven Heidemann",
- "Version": {
- "Major": 2020,
- "Minor": 12,
- "Micro": 10
- }
- }
- ],
- "IncludedFiles": [
- ],
- "ExcludedFiles": [
- ],
- "TemplateEnding": "_template.txt"
- }
-}
diff --git a/src/tests/service_test/__init__.py b/src/tests/custom/__init__.py
similarity index 100%
rename from src/tests/service_test/__init__.py
rename to src/tests/custom/__init__.py
diff --git a/src/tests/time_test/__init__.py b/src/tests/custom/console/__init__.py
similarity index 100%
rename from src/tests/time_test/__init__.py
rename to src/tests/custom/console/__init__.py
diff --git a/src/tests/custom/console/main.py b/src/tests/custom/console/main.py
new file mode 100644
index 00000000..6dfe9a9c
--- /dev/null
+++ b/src/tests/custom/console/main.py
@@ -0,0 +1,39 @@
+import time
+from cpl.console import Console, ForegroundColorEnum
+
+
+def test_spinner():
+ time.sleep(2)
+
+
+def test_console():
+ Console.write_line('Hello World')
+ Console.write('\nName: ')
+ Console.write_line(' Hello', Console.read_line())
+ Console.clear()
+ Console.write_at(5, 5, 'at 5, 5')
+ Console.write_at(10, 10, 'at 10, 10')
+
+
+if __name__ == '__main__':
+ Console.write_line('Hello World\n')
+ Console.spinner('Test:', test_spinner, spinner_foreground_color=ForegroundColorEnum.cyan,
+ text_foreground_color='green')
+ # opts = [
+ # 'Option 1',
+ # 'Option 2',
+ # 'Option 3',
+ # 'Option 4'
+ # ]
+ # selected = Console.select(
+ # '>',
+ # 'Select item:',
+ # opts,
+ # header_foreground_color=ForegroundColorEnum.blue,
+ # option_foreground_color=ForegroundColorEnum.green,
+ # cursor_foreground_color=ForegroundColorEnum.red
+ # )
+ # Console.write_line(f'You selected: {selected}')
+ # test_console()
+
+ Console.write_line()
diff --git a/src/tests/utils_test/__init__.py b/src/tests/custom/database/LICENSE
similarity index 100%
rename from src/tests/utils_test/__init__.py
rename to src/tests/custom/database/LICENSE
diff --git a/src/tests/custom/database/README.md b/src/tests/custom/database/README.md
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tests/custom/database/appsettings.development.json b/src/tests/custom/database/appsettings.development.json
new file mode 100644
index 00000000..62ec6c61
--- /dev/null
+++ b/src/tests/custom/database/appsettings.development.json
@@ -0,0 +1,8 @@
+{
+ "LoggingSettings": {
+ "Path": "logs/",
+ "Filename": "log_$start_time.log",
+ "ConsoleLogLevel": "TRACE",
+ "FileLogLevel": "TRACE"
+ }
+}
\ No newline at end of file
diff --git a/src/tests_dev/appsettings.development.json b/src/tests/custom/database/appsettings.edrafts-lapi.json
similarity index 60%
rename from src/tests_dev/appsettings.development.json
rename to src/tests/custom/database/appsettings.edrafts-lapi.json
index d134912e..c78e3458 100644
--- a/src/tests_dev/appsettings.development.json
+++ b/src/tests/custom/database/appsettings.edrafts-lapi.json
@@ -1,4 +1,11 @@
{
+ "TimeFormatSettings": {
+ "DateFormat": "%Y-%m-%d",
+ "TimeFormat": "%H:%M:%S",
+ "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
+ "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
+ },
+
"LoggingSettings": {
"Path": "logs/",
"Filename": "log_$start_time.log",
@@ -7,6 +14,7 @@
},
"DatabaseSettings": {
+ "AuthPlugin": "mysql_native_password",
"ConnectionString": "mysql+mysqlconnector://sh_cpl:$credentials@localhost/sh_cpl",
"Credentials": "MHZhc0Y2bjhKc1VUMWV0Qw==",
"Encoding": "utf8mb4"
diff --git a/src/tests/appsettings.testing.json b/src/tests/custom/database/appsettings.edrafts-pc.json
similarity index 60%
rename from src/tests/appsettings.testing.json
rename to src/tests/custom/database/appsettings.edrafts-pc.json
index d134912e..c78e3458 100644
--- a/src/tests/appsettings.testing.json
+++ b/src/tests/custom/database/appsettings.edrafts-pc.json
@@ -1,4 +1,11 @@
{
+ "TimeFormatSettings": {
+ "DateFormat": "%Y-%m-%d",
+ "TimeFormat": "%H:%M:%S",
+ "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
+ "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
+ },
+
"LoggingSettings": {
"Path": "logs/",
"Filename": "log_$start_time.log",
@@ -7,6 +14,7 @@
},
"DatabaseSettings": {
+ "AuthPlugin": "mysql_native_password",
"ConnectionString": "mysql+mysqlconnector://sh_cpl:$credentials@localhost/sh_cpl",
"Credentials": "MHZhc0Y2bjhKc1VUMWV0Qw==",
"Encoding": "utf8mb4"
diff --git a/src/tests/appsettings.json b/src/tests/custom/database/appsettings.json
similarity index 100%
rename from src/tests/appsettings.json
rename to src/tests/custom/database/appsettings.json
diff --git a/src/tests/custom/database/cpl.json b/src/tests/custom/database/cpl.json
new file mode 100644
index 00000000..e964c144
--- /dev/null
+++ b/src/tests/custom/database/cpl.json
@@ -0,0 +1,42 @@
+{
+ "ProjectSettings": {
+ "Name": "database",
+ "Version": {
+ "Major": "0",
+ "Minor": "0",
+ "Micro": "0"
+ },
+ "Author": "",
+ "AuthorEmail": "",
+ "Description": "",
+ "LongDescription": "",
+ "URL": "",
+ "CopyrightDate": "",
+ "CopyrightName": "",
+ "LicenseName": "",
+ "LicenseDescription": "",
+ "Dependencies": [
+ "sh_cpl==2021.4.2.dev1"
+ ],
+ "PythonVersion": ">=3.9.2",
+ "PythonPath": {
+ "linux": ""
+ },
+ "Classifiers": []
+ },
+ "BuildSettings": {
+ "ProjectType": "console",
+ "SourcePath": "src",
+ "OutputPath": "dist",
+ "Main": "main",
+ "EntryPoint": "database",
+ "IncludePackageData": false,
+ "Included": [],
+ "Excluded": [
+ "*/__pycache__",
+ "*/logs",
+ "*/tests"
+ ],
+ "PackageData": {}
+ }
+}
\ No newline at end of file
diff --git a/src/tests/custom/database/src/application.py b/src/tests/custom/database/src/application.py
new file mode 100644
index 00000000..4ac5352c
--- /dev/null
+++ b/src/tests/custom/database/src/application.py
@@ -0,0 +1,36 @@
+from typing import Optional
+
+from cpl.application import ApplicationABC
+from cpl.configuration import ConfigurationABC
+from cpl.console import Console
+from cpl.dependency_injection import ServiceProviderABC
+from cpl.logging import LoggerABC
+from model.user_repo_abc import UserRepoABC
+from model.user_repo import UserRepo
+
+
+class Application(ApplicationABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
+ ApplicationABC.__init__(self, config, services)
+
+ self._logger: Optional[LoggerABC] = None
+
+ def configure(self):
+ self._logger = self._services.get_service(LoggerABC)
+
+ def main(self):
+ self._logger.header(f'{self._configuration.environment.application_name}:')
+ self._logger.debug(__name__, f'Host: {self._configuration.environment.host_name}')
+ self._logger.debug(__name__, f'Environment: {self._configuration.environment.environment_name}')
+ self._logger.debug(__name__, f'Customer: {self._configuration.environment.customer}')
+
+ user_repo: UserRepo = self._services.get_service(UserRepoABC)
+ user_repo.add_test_user()
+ Console.write_line('Users:')
+ for user in user_repo.get_users():
+ Console.write_line(user.Id, user.Name, user.City_Id, user.City.Id, user.City.Name, user.City.ZIP)
+
+ Console.write_line('Cities:')
+ for city in user_repo.get_cities():
+ Console.write_line(city.Id, city.Name, city.ZIP)
diff --git a/src/tests/custom/database/src/main.py b/src/tests/custom/database/src/main.py
new file mode 100644
index 00000000..6e678925
--- /dev/null
+++ b/src/tests/custom/database/src/main.py
@@ -0,0 +1,14 @@
+from cpl.application import ApplicationBuilder
+
+from application import Application
+from startup import Startup
+
+
+def main():
+ app_builder = ApplicationBuilder(Application)
+ app_builder.use_startup(Startup)
+ app_builder.build().run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/tests/custom/database/src/model/__init__.py b/src/tests/custom/database/src/model/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tests_dev/db/city.py b/src/tests/custom/database/src/model/city_model.py
similarity index 83%
rename from src/tests_dev/db/city.py
rename to src/tests/custom/database/src/model/city_model.py
index baf07ded..98523169 100644
--- a/src/tests_dev/db/city.py
+++ b/src/tests/custom/database/src/model/city_model.py
@@ -1,9 +1,9 @@
from sqlalchemy import Column, Integer, String
-from sh_edraft.database.model import DBModel
+from cpl.database import DatabaseModel
-class City(DBModel):
+class CityModel(DatabaseModel):
__tablename__ = 'Cities'
Id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
Name = Column(String(64), nullable=False)
diff --git a/src/tests/custom/database/src/model/db_context.py b/src/tests/custom/database/src/model/db_context.py
new file mode 100644
index 00000000..160ed8b4
--- /dev/null
+++ b/src/tests/custom/database/src/model/db_context.py
@@ -0,0 +1,8 @@
+from cpl.database import DatabaseSettings
+from cpl.database.context import DatabaseContext
+
+
+class DBContext(DatabaseContext):
+
+ def __init__(self, db_settings: DatabaseSettings):
+ DatabaseContext.__init__(self, db_settings)
diff --git a/src/tests_dev/db/user.py b/src/tests/custom/database/src/model/user_model.py
similarity index 75%
rename from src/tests_dev/db/user.py
rename to src/tests/custom/database/src/model/user_model.py
index e840df86..bce0ed69 100644
--- a/src/tests_dev/db/user.py
+++ b/src/tests/custom/database/src/model/user_model.py
@@ -1,16 +1,16 @@
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
-from sh_edraft.database.model import DBModel
-from tests_dev.db.city import City as CityModel
+from cpl.database import DatabaseModel
+from .city_model import CityModel
-class User(DBModel):
+class UserModel(DatabaseModel):
__tablename__ = 'Users'
Id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
Name = Column(String(64), nullable=False)
City_Id = Column(Integer, ForeignKey('Cities.Id'), nullable=False)
- City = relationship("City")
+ City = relationship("CityModel")
def __init__(self, name: str, city: CityModel):
self.Name = name
diff --git a/src/tests/custom/database/src/model/user_repo.py b/src/tests/custom/database/src/model/user_repo.py
new file mode 100644
index 00000000..111605b3
--- /dev/null
+++ b/src/tests/custom/database/src/model/user_repo.py
@@ -0,0 +1,29 @@
+from cpl.database.context import DatabaseContextABC
+from .city_model import CityModel
+from .user_model import UserModel
+from .user_repo_abc import UserRepoABC
+
+
+class UserRepo(UserRepoABC):
+
+ def __init__(self, db_context: DatabaseContextABC):
+ UserRepoABC.__init__(self)
+
+ self._session = db_context.session
+ self._user_query = db_context.session.query(UserModel)
+
+ def create(self): pass
+
+ def add_test_user(self):
+ city = CityModel('Haren', '49733')
+ city2 = CityModel('Meppen', '49716')
+ self._session.add(city2)
+ user = UserModel('TestUser', city)
+ self._session.add(user)
+ self._session.commit()
+
+ def get_users(self) -> list[UserModel]:
+ return self._session.query(UserModel).all()
+
+ def get_cities(self) -> list[CityModel]:
+ return self._session.query(CityModel).all()
diff --git a/src/sh_edraft/service/base/service_base.py b/src/tests/custom/database/src/model/user_repo_abc.py
similarity index 50%
rename from src/sh_edraft/service/base/service_base.py
rename to src/tests/custom/database/src/model/user_repo_abc.py
index e135c2a9..f19a2a3e 100644
--- a/src/sh_edraft/service/base/service_base.py
+++ b/src/tests/custom/database/src/model/user_repo_abc.py
@@ -1,10 +1,12 @@
from abc import ABC, abstractmethod
+from .user_model import UserModel
-class ServiceBase(ABC):
+
+class UserRepoABC(ABC):
@abstractmethod
def __init__(self): pass
@abstractmethod
- def create(self): pass
+ def get_users(self) -> list[UserModel]: pass
diff --git a/src/tests/custom/database/src/startup.py b/src/tests/custom/database/src/startup.py
new file mode 100644
index 00000000..27417a3b
--- /dev/null
+++ b/src/tests/custom/database/src/startup.py
@@ -0,0 +1,39 @@
+from cpl.application import StartupABC
+from cpl.configuration import ConfigurationABC
+from cpl.database import DatabaseSettings
+from cpl.dependency_injection import ServiceProviderABC, ServiceCollectionABC
+from cpl.logging import LoggerABC, Logger
+from model.db_context import DBContext
+from model.user_repo import UserRepo
+from model.user_repo_abc import UserRepoABC
+
+
+class Startup(StartupABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceCollectionABC):
+ StartupABC.__init__(self)
+
+ self._configuration = config
+ self._environment = self._configuration.environment
+ self._services = services
+
+ def configure_configuration(self) -> ConfigurationABC:
+ self._configuration.add_environment_variables('PYTHON_')
+ self._configuration.add_environment_variables('CPL_')
+ self._configuration.add_console_arguments()
+ self._configuration.add_json_file(f'appsettings.json')
+ self._configuration.add_json_file(f'appsettings.{self._configuration.environment.environment_name}.json')
+ self._configuration.add_json_file(f'appsettings.{self._configuration.environment.host_name}.json', optional=True)
+
+ return self._configuration
+
+ def configure_services(self) -> ServiceProviderABC:
+ # Create and connect to database
+ db_settings: DatabaseSettings = self._configuration.get_configuration(DatabaseSettings)
+ self._services.add_db_context(DBContext, db_settings)
+
+ self._services.add_singleton(UserRepoABC, UserRepo)
+
+ self._services.add_singleton(LoggerABC, Logger)
+ return self._services.build_service_provider()
+
diff --git a/src/tests/custom/database/src/tests/__init__.py b/src/tests/custom/database/src/tests/__init__.py
new file mode 100644
index 00000000..ad5eca30
--- /dev/null
+++ b/src/tests/custom/database/src/tests/__init__.py
@@ -0,0 +1 @@
+# imports:
diff --git a/src/tests/custom/general/__init__.py b/src/tests/custom/general/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tests/custom/general/application.py b/src/tests/custom/general/application.py
new file mode 100644
index 00000000..f7af31b0
--- /dev/null
+++ b/src/tests/custom/general/application.py
@@ -0,0 +1,47 @@
+import time
+from typing import Optional
+
+from cpl.application.application_abc import ApplicationABC
+from cpl.configuration.configuration_abc import ConfigurationABC
+from cpl.console.console import Console
+from cpl.dependency_injection.service_provider_abc import ServiceProviderABC
+from cpl.logging.logger_abc import LoggerABC
+from cpl.mailing.email import EMail
+from cpl.mailing.email_client_abc import EMailClientABC
+from tests.custom.general.test_service import TestService
+
+
+class Application(ApplicationABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
+ ApplicationABC.__init__(self, config, services)
+ self._logger: Optional[LoggerABC] = None
+ self._mailer: Optional[EMailClientABC] = None
+
+ def test_send_mail(self):
+ mail = EMail()
+ mail.add_header('Mime-Version: 1.0')
+ mail.add_header('Content-Type: text/plain; charset=utf-8')
+ mail.add_header('Content-Transfer-Encoding: quoted-printable')
+ mail.add_receiver('sven.heidemann@sh-edraft.de')
+ mail.subject = f'Test - {self._configuration.environment.host_name}'
+ mail.body = 'Dies ist ein Test :D'
+ self._mailer.send_mail(mail)
+
+ @staticmethod
+ def _wait(time_ms: int):
+ time.sleep(time_ms)
+
+ def configure(self):
+ self._logger = self._services.get_service(LoggerABC)
+ self._mailer = self._services.get_service(EMailClientABC)
+
+ def main(self):
+ self._logger.header(f'{self._configuration.environment.application_name}:')
+ self._logger.debug(__name__, f'Host: {self._configuration.environment.host_name}')
+ self._logger.debug(__name__, f'Environment: {self._configuration.environment.environment_name}')
+ self._logger.debug(__name__, f'Customer: {self._configuration.environment.customer}')
+ Console.spinner('Test', self._wait, 2, spinner_foreground_color='red')
+ test: TestService = self._services.get_service(TestService)
+ test.run()
+ # self.test_send_mail()
diff --git a/src/tests/custom/general/appsettings.development.json b/src/tests/custom/general/appsettings.development.json
new file mode 100644
index 00000000..62ec6c61
--- /dev/null
+++ b/src/tests/custom/general/appsettings.development.json
@@ -0,0 +1,8 @@
+{
+ "LoggingSettings": {
+ "Path": "logs/",
+ "Filename": "log_$start_time.log",
+ "ConsoleLogLevel": "TRACE",
+ "FileLogLevel": "TRACE"
+ }
+}
\ No newline at end of file
diff --git a/src/tests_dev/appsettings.edrafts-lapi.json b/src/tests/custom/general/appsettings.edrafts-lapi.json
similarity index 100%
rename from src/tests_dev/appsettings.edrafts-lapi.json
rename to src/tests/custom/general/appsettings.edrafts-lapi.json
diff --git a/src/tests/appsettings.edrafts-pc.json b/src/tests/custom/general/appsettings.edrafts-pc.json
similarity index 68%
rename from src/tests/appsettings.edrafts-pc.json
rename to src/tests/custom/general/appsettings.edrafts-pc.json
index 9af6f6c0..afae3437 100644
--- a/src/tests/appsettings.edrafts-pc.json
+++ b/src/tests/custom/general/appsettings.edrafts-pc.json
@@ -5,16 +5,25 @@
"DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
"DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
},
+
"LoggingSettings": {
"Path": "logs/",
"Filename": "log_$start_time.log",
"ConsoleLogLevel": "TRACE",
"FileLogLevel": "TRACE"
},
+
"EMailClientSettings": {
"Host": "mail.sh-edraft.de",
"Port": "587",
"UserName": "dev-srv@sh-edraft.de",
"Credentials": "RmBOQX1eNFYiYjgsSid3fV1nelc2WA=="
+ },
+
+ "DatabaseSettings": {
+ "AuthPlugin": "mysql_native_password",
+ "ConnectionString": "mysql+mysqlconnector://sh_cpl:$credentials@localhost/sh_cpl",
+ "Credentials": "MHZhc0Y2bjhKc1VUMWV0Qw==",
+ "Encoding": "utf8mb4"
}
}
\ No newline at end of file
diff --git a/src/tests_dev/appsettings.json b/src/tests/custom/general/appsettings.json
similarity index 100%
rename from src/tests_dev/appsettings.json
rename to src/tests/custom/general/appsettings.json
diff --git a/src/tests/custom/general/cpl.json b/src/tests/custom/general/cpl.json
new file mode 100644
index 00000000..b57adb29
--- /dev/null
+++ b/src/tests/custom/general/cpl.json
@@ -0,0 +1,46 @@
+{
+ "ProjectSettings": {
+ "Name": "sh_cpl.tests",
+ "Version": {
+ "Major": "2021",
+ "Minor": "04",
+ "Micro": "01"
+ },
+ "Author": "Sven Heidemann",
+ "AuthorEmail": "sven.heidemann@sh-edraft.de",
+ "Description": "sh-edraft Common Python library",
+ "LongDescription": "sh-edraft Common Python library",
+ "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.1.post13",
+ "discord.py==1.6.0"
+ ],
+ "PythonVersion": ">=3.8",
+ "PythonPath": {
+ "linux": "../../../../cpl-env/bin/python3.9",
+ "win32": ""
+ },
+ "Classifiers": []
+ },
+ "BuildSettings": {
+ "ProjectType": "console",
+ "SourcePath": "",
+ "OutputPath": "dist",
+ "Main": "main",
+ "EntryPoint": "cpl",
+ "IncludePackageData": true,
+ "Included": [
+ "*/templates"
+ ],
+ "Excluded": [
+ "*/__pycache__",
+ "*/logs",
+ "*/tests"
+ ],
+ "PackageData": {}
+ }
+}
\ No newline at end of file
diff --git a/src/tests/custom/general/db/__init__.py b/src/tests/custom/general/db/__init__.py
new file mode 100644
index 00000000..746ca0b0
--- /dev/null
+++ b/src/tests/custom/general/db/__init__.py
@@ -0,0 +1,25 @@
+# -*- 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__ = 'tests.db'
+__author__ = 'Sven Heidemann'
+__license__ = 'MIT'
+__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
+__version__ = '2021.4.1'
+
+from collections import namedtuple
+
+# imports:
+
+VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+version_info = VersionInfo(major=2021, minor=4, micro=1)
diff --git a/src/tests/custom/general/main.py b/src/tests/custom/general/main.py
new file mode 100644
index 00000000..a9fd514f
--- /dev/null
+++ b/src/tests/custom/general/main.py
@@ -0,0 +1,13 @@
+from cpl.application.application_builder import ApplicationBuilder
+from tests.custom.general.application import Application
+from tests.custom.general.startup import Startup
+
+
+def main():
+ app_builder = ApplicationBuilder(Application)
+ app_builder.use_startup(Startup)
+ app_builder.build().run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/tests/custom/general/startup.py b/src/tests/custom/general/startup.py
new file mode 100644
index 00000000..d0370bff
--- /dev/null
+++ b/src/tests/custom/general/startup.py
@@ -0,0 +1,35 @@
+from cpl.application.startup_abc import StartupABC
+from cpl.configuration.configuration_abc import ConfigurationABC
+from cpl.dependency_injection.service_collection_abc import ServiceCollectionABC
+from cpl.dependency_injection.service_provider_abc import ServiceProviderABC
+from cpl.logging.logger_service import Logger
+from cpl.logging.logger_abc import LoggerABC
+from cpl.mailing.email_client_service import EMailClient
+from cpl.mailing.email_client_abc import EMailClientABC
+from tests.custom.general.test_service import TestService
+
+
+class Startup(StartupABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceCollectionABC):
+ StartupABC.__init__(self)
+
+ self._configuration = config
+ self._services = services
+
+ def configure_configuration(self) -> ConfigurationABC:
+ self._configuration.add_environment_variables('PYTHON_')
+ self._configuration.add_environment_variables('CPL_')
+ self._configuration.add_console_arguments()
+ self._configuration.add_json_file(f'appsettings.json')
+ self._configuration.add_json_file(f'appsettings.{self._configuration.environment.environment_name}.json')
+ self._configuration.add_json_file(f'appsettings.{self._configuration.environment.host_name}.json', optional=True)
+
+ return self._configuration
+
+ def configure_services(self) -> ServiceProviderABC:
+ self._services.add_singleton(LoggerABC, Logger)
+ self._services.add_singleton(EMailClientABC, EMailClient)
+ self._services.add_singleton(TestService)
+
+ return self._services.build_service_provider()
diff --git a/src/tests/custom/general/test_service.py b/src/tests/custom/general/test_service.py
new file mode 100644
index 00000000..376707c1
--- /dev/null
+++ b/src/tests/custom/general/test_service.py
@@ -0,0 +1,15 @@
+from abc import ABC
+
+from cpl.console.console import Console
+from cpl.dependency_injection import ServiceProviderABC
+
+
+class TestService(ABC):
+
+ def __init__(self, provider: ServiceProviderABC):
+ ABC.__init__(self)
+
+ self._provider = provider
+
+ def run(self):
+ Console.write_line('Hello World!', self._provider)
diff --git a/src/tests/generated/simple-app/LICENSE b/src/tests/generated/simple-app/LICENSE
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tests/generated/simple-app/README.md b/src/tests/generated/simple-app/README.md
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tests/generated/simple-app/cpl.json b/src/tests/generated/simple-app/cpl.json
new file mode 100644
index 00000000..f223da45
--- /dev/null
+++ b/src/tests/generated/simple-app/cpl.json
@@ -0,0 +1,42 @@
+{
+ "ProjectSettings": {
+ "Name": "simple-app",
+ "Version": {
+ "Major": "0",
+ "Minor": "0",
+ "Micro": "0"
+ },
+ "Author": "",
+ "AuthorEmail": "",
+ "Description": "",
+ "LongDescription": "",
+ "URL": "",
+ "CopyrightDate": "",
+ "CopyrightName": "",
+ "LicenseName": "",
+ "LicenseDescription": "",
+ "Dependencies": [
+ "sh_cpl==2021.4.2"
+ ],
+ "PythonVersion": ">=3.9.2",
+ "PythonPath": {
+ "linux": ""
+ },
+ "Classifiers": []
+ },
+ "BuildSettings": {
+ "ProjectType": "console",
+ "SourcePath": "src",
+ "OutputPath": "dist",
+ "Main": "main",
+ "EntryPoint": "simple-app",
+ "IncludePackageData": false,
+ "Included": [],
+ "Excluded": [
+ "*/__pycache__",
+ "*/logs",
+ "*/tests"
+ ],
+ "PackageData": {}
+ }
+}
\ No newline at end of file
diff --git a/src/tests/generated/simple-app/src/application.py b/src/tests/generated/simple-app/src/application.py
new file mode 100644
index 00000000..0a98353b
--- /dev/null
+++ b/src/tests/generated/simple-app/src/application.py
@@ -0,0 +1,16 @@
+from cpl.application import ApplicationABC
+from cpl.configuration import ConfigurationABC
+from cpl.console import Console
+from cpl.dependency_injection import ServiceProviderABC
+
+
+class Application(ApplicationABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
+ ApplicationABC.__init__(self, config, services)
+
+ def configure(self):
+ pass
+
+ def main(self):
+ Console.write_line('Hello World')
diff --git a/src/tests/generated/simple-app/src/main.py b/src/tests/generated/simple-app/src/main.py
new file mode 100644
index 00000000..3d3e7eba
--- /dev/null
+++ b/src/tests/generated/simple-app/src/main.py
@@ -0,0 +1,12 @@
+from cpl.application import ApplicationBuilder
+
+from application import Application
+
+
+def main():
+ app_builder = ApplicationBuilder(Application)
+ app_builder.build().run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/tests/generated/simple-app/src/tests/__init__.py b/src/tests/generated/simple-app/src/tests/__init__.py
new file mode 100644
index 00000000..ad5eca30
--- /dev/null
+++ b/src/tests/generated/simple-app/src/tests/__init__.py
@@ -0,0 +1 @@
+# imports:
diff --git a/src/tests/generated/simple-console/LICENSE b/src/tests/generated/simple-console/LICENSE
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tests/generated/simple-console/README.md b/src/tests/generated/simple-console/README.md
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tests/generated/simple-console/cpl.json b/src/tests/generated/simple-console/cpl.json
new file mode 100644
index 00000000..63fe1a4d
--- /dev/null
+++ b/src/tests/generated/simple-console/cpl.json
@@ -0,0 +1,42 @@
+{
+ "ProjectSettings": {
+ "Name": "simple-console",
+ "Version": {
+ "Major": "0",
+ "Minor": "0",
+ "Micro": "0"
+ },
+ "Author": "",
+ "AuthorEmail": "",
+ "Description": "",
+ "LongDescription": "",
+ "URL": "",
+ "CopyrightDate": "",
+ "CopyrightName": "",
+ "LicenseName": "",
+ "LicenseDescription": "",
+ "Dependencies": [
+ "sh_cpl==2021.4.2"
+ ],
+ "PythonVersion": ">=3.9.2",
+ "PythonPath": {
+ "linux": ""
+ },
+ "Classifiers": []
+ },
+ "BuildSettings": {
+ "ProjectType": "console",
+ "SourcePath": "src",
+ "OutputPath": "dist",
+ "Main": "main",
+ "EntryPoint": "simple-console",
+ "IncludePackageData": false,
+ "Included": [],
+ "Excluded": [
+ "*/__pycache__",
+ "*/logs",
+ "*/tests"
+ ],
+ "PackageData": {}
+ }
+}
\ No newline at end of file
diff --git a/src/tests/generated/simple-console/src/main.py b/src/tests/generated/simple-console/src/main.py
new file mode 100644
index 00000000..42e34771
--- /dev/null
+++ b/src/tests/generated/simple-console/src/main.py
@@ -0,0 +1,9 @@
+from cpl.console import Console
+
+
+def main():
+ Console.write_line('Hello World')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/tests/generated/simple-console/src/tests/__init__.py b/src/tests/generated/simple-console/src/tests/__init__.py
new file mode 100644
index 00000000..ad5eca30
--- /dev/null
+++ b/src/tests/generated/simple-console/src/tests/__init__.py
@@ -0,0 +1 @@
+# imports:
diff --git a/src/tests/generated/simple-di/LICENSE b/src/tests/generated/simple-di/LICENSE
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tests/generated/simple-di/README.md b/src/tests/generated/simple-di/README.md
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tests/generated/simple-di/cpl.json b/src/tests/generated/simple-di/cpl.json
new file mode 100644
index 00000000..8804958a
--- /dev/null
+++ b/src/tests/generated/simple-di/cpl.json
@@ -0,0 +1,42 @@
+{
+ "ProjectSettings": {
+ "Name": "simple-di",
+ "Version": {
+ "Major": "0",
+ "Minor": "0",
+ "Micro": "0"
+ },
+ "Author": "",
+ "AuthorEmail": "",
+ "Description": "",
+ "LongDescription": "",
+ "URL": "",
+ "CopyrightDate": "",
+ "CopyrightName": "",
+ "LicenseName": "",
+ "LicenseDescription": "",
+ "Dependencies": [
+ "sh_cpl==2021.4.2.dev1"
+ ],
+ "PythonVersion": ">=3.9.2",
+ "PythonPath": {
+ "linux": ""
+ },
+ "Classifiers": []
+ },
+ "BuildSettings": {
+ "ProjectType": "console",
+ "SourcePath": "src",
+ "OutputPath": "dist",
+ "Main": "main",
+ "EntryPoint": "simple-di",
+ "IncludePackageData": false,
+ "Included": [],
+ "Excluded": [
+ "*/__pycache__",
+ "*/logs",
+ "*/tests"
+ ],
+ "PackageData": {}
+ }
+}
\ No newline at end of file
diff --git a/src/tests/generated/simple-di/src/main.py b/src/tests/generated/simple-di/src/main.py
new file mode 100644
index 00000000..a6bd96ec
--- /dev/null
+++ b/src/tests/generated/simple-di/src/main.py
@@ -0,0 +1,23 @@
+from cpl.configuration import Configuration, ConfigurationABC
+from cpl.console import Console
+from cpl.dependency_injection import ServiceCollection, ServiceProviderABC
+
+
+def configure_configuration() -> ConfigurationABC:
+ config = Configuration()
+ return config
+
+
+def configure_services(config: ConfigurationABC) -> ServiceProviderABC:
+ services = ServiceCollection(config)
+ return services.build_service_provider()
+
+
+def main():
+ config = configure_configuration()
+ provider = configure_services(config)
+ Console.write_line('Hello World')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/tests/generated/simple-di/src/tests/__init__.py b/src/tests/generated/simple-di/src/tests/__init__.py
new file mode 100644
index 00000000..ad5eca30
--- /dev/null
+++ b/src/tests/generated/simple-di/src/tests/__init__.py
@@ -0,0 +1 @@
+# imports:
diff --git a/src/tests/generated/startup-app/LICENSE b/src/tests/generated/startup-app/LICENSE
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tests/generated/startup-app/README.md b/src/tests/generated/startup-app/README.md
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tests/generated/startup-app/cpl.json b/src/tests/generated/startup-app/cpl.json
new file mode 100644
index 00000000..086c70ae
--- /dev/null
+++ b/src/tests/generated/startup-app/cpl.json
@@ -0,0 +1,42 @@
+{
+ "ProjectSettings": {
+ "Name": "startup-app",
+ "Version": {
+ "Major": "0",
+ "Minor": "0",
+ "Micro": "0"
+ },
+ "Author": "",
+ "AuthorEmail": "",
+ "Description": "",
+ "LongDescription": "",
+ "URL": "",
+ "CopyrightDate": "",
+ "CopyrightName": "",
+ "LicenseName": "",
+ "LicenseDescription": "",
+ "Dependencies": [
+ "sh_cpl==2021.4.2"
+ ],
+ "PythonVersion": ">=3.9.2",
+ "PythonPath": {
+ "linux": ""
+ },
+ "Classifiers": []
+ },
+ "BuildSettings": {
+ "ProjectType": "console",
+ "SourcePath": "src",
+ "OutputPath": "dist",
+ "Main": "main",
+ "EntryPoint": "startup-app",
+ "IncludePackageData": false,
+ "Included": [],
+ "Excluded": [
+ "*/__pycache__",
+ "*/logs",
+ "*/tests"
+ ],
+ "PackageData": {}
+ }
+}
\ No newline at end of file
diff --git a/src/tests/generated/startup-app/src/application.py b/src/tests/generated/startup-app/src/application.py
new file mode 100644
index 00000000..0a98353b
--- /dev/null
+++ b/src/tests/generated/startup-app/src/application.py
@@ -0,0 +1,16 @@
+from cpl.application import ApplicationABC
+from cpl.configuration import ConfigurationABC
+from cpl.console import Console
+from cpl.dependency_injection import ServiceProviderABC
+
+
+class Application(ApplicationABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
+ ApplicationABC.__init__(self, config, services)
+
+ def configure(self):
+ pass
+
+ def main(self):
+ Console.write_line('Hello World')
diff --git a/src/tests/generated/startup-app/src/main.py b/src/tests/generated/startup-app/src/main.py
new file mode 100644
index 00000000..6e678925
--- /dev/null
+++ b/src/tests/generated/startup-app/src/main.py
@@ -0,0 +1,14 @@
+from cpl.application import ApplicationBuilder
+
+from application import Application
+from startup import Startup
+
+
+def main():
+ app_builder = ApplicationBuilder(Application)
+ app_builder.use_startup(Startup)
+ app_builder.build().run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/tests/generated/startup-app/src/startup.py b/src/tests/generated/startup-app/src/startup.py
new file mode 100644
index 00000000..07f5dece
--- /dev/null
+++ b/src/tests/generated/startup-app/src/startup.py
@@ -0,0 +1,20 @@
+from cpl.application import StartupABC
+from cpl.configuration import ConfigurationABC
+from cpl.dependency_injection import ServiceProviderABC, ServiceCollectionABC
+
+
+class Startup(StartupABC):
+
+ def __init__(self, config: ConfigurationABC, services: ServiceCollectionABC):
+ StartupABC.__init__(self)
+
+ self._configuration = config
+ self._environment = self._configuration.environment
+ self._services = services
+
+ def configure_configuration(self) -> ConfigurationABC:
+ return self._configuration
+
+ def configure_services(self) -> ServiceProviderABC:
+ return self._services.build_service_provider()
+
diff --git a/src/tests/generated/startup-app/src/tests/__init__.py b/src/tests/generated/startup-app/src/tests/__init__.py
new file mode 100644
index 00000000..ad5eca30
--- /dev/null
+++ b/src/tests/generated/startup-app/src/tests/__init__.py
@@ -0,0 +1 @@
+# imports:
diff --git a/src/tests/publish_test/publisher_test.py b/src/tests/publish_test/publisher_test.py
deleted file mode 100644
index 06f95519..00000000
--- a/src/tests/publish_test/publisher_test.py
+++ /dev/null
@@ -1,52 +0,0 @@
-import os
-import unittest
-
-from sh_edraft.console import Console
-from sh_edraft.hosting import ApplicationHost
-from sh_edraft.logging import Logger
-from sh_edraft.logging.base import LoggerBase
-from sh_edraft.publish import Publisher
-from sh_edraft.publish.base import PublisherBase
-from sh_edraft.publish.model import PublishSettings
-
-
-class PublisherTest(unittest.TestCase):
-
- def setUp(self):
- Console.disable()
- self._app_host = ApplicationHost()
- self._configuration = self._app_host.configuration
- self._services = self._app_host.services
-
- self._configuration.add_environment_variables('CPL_')
- self._configuration.add_argument_variables()
- self._configuration.add_json_file(f'build.json')
-
- self._services.add_singleton(LoggerBase, Logger)
- self._services.add_singleton(PublisherBase, Publisher)
- self._publisher: Publisher = self._services.get_service(PublisherBase)
-
- def test_include(self):
- value = './test.py'
- self._publisher.include(value)
- self.assertTrue(value in self._publisher._publish_settings.included_files)
-
- def test_exclude(self):
- value = './test.py'
- self._publisher.exclude(value)
- self.assertTrue(value in self._publisher._publish_settings.excluded_files)
-
- def test_create(self):
- self._publisher.create()
- self.assertTrue(os.path.isdir(self._configuration.get_configuration(PublishSettings).dist_path))
-
- def test_build(self):
- self._publisher.create()
- self._publisher.build()
- self.assertTrue(os.path.isdir(self._configuration.get_configuration(PublishSettings).dist_path))
-
- def test_publish(self):
- self._publisher.create()
- self._publisher.build()
- self._publisher.publish()
- self.assertTrue(os.path.isdir(self._configuration.get_configuration(PublishSettings).dist_path))
diff --git a/src/tests/service_test/provider_test.py b/src/tests/service_test/provider_test.py
deleted file mode 100644
index 96fef8eb..00000000
--- a/src/tests/service_test/provider_test.py
+++ /dev/null
@@ -1,79 +0,0 @@
-import unittest
-
-from sh_edraft.console import Console
-from sh_edraft.database.context import DatabaseContext
-from sh_edraft.hosting import ApplicationHost
-from sh_edraft.logging import Logger
-from sh_edraft.logging.base import LoggerBase
-
-
-class ProviderTest(unittest.TestCase):
-
- def setUp(self):
- Console.disable()
- self._app_host = ApplicationHost()
- self._configuration = self._app_host.configuration
- self._services = self._app_host.services
-
- self._configuration.add_environment_variables('CPL_')
- self._configuration.add_argument_variables()
- self._configuration.add_json_file(f'appsettings.json')
- self._configuration.add_json_file(f'appsettings.{self._configuration.environment.environment_name}.json')
- self._configuration.add_json_file(f'appsettings.{self._configuration.environment.host_name}.json', optional=True)
-
- def test_get_db_context(self):
- self._services.add_db_context(DatabaseContext)
- db: DatabaseContext = self._services.get_db_context()
-
- self.assertIsNotNone(db)
-
- def test_get_service_singleton(self):
- self._services.add_singleton(LoggerBase, Logger)
- logger = self._services.get_service(LoggerBase)
-
- self.assertIsNotNone(logger)
-
- def test_get_service_scoped(self):
- self._services.add_scoped(LoggerBase, Logger)
- logger = self._services.get_service(LoggerBase)
-
- self.assertIsNotNone(logger)
-
- def test_get_service_transient(self):
- self._services.add_transient(LoggerBase, Logger)
- logger = self._services.get_service(LoggerBase)
-
- self.assertIsNotNone(logger)
-
- def test_remove_service_singleton(self):
- self._services.add_singleton(LoggerBase, Logger)
- logger = self._services.get_service(LoggerBase)
-
- self.assertIsNotNone(logger)
-
- self._services.remove_service(LoggerBase)
- logger = self._services.get_service(LoggerBase)
-
- self.assertIsNone(logger)
-
- def test_remove_service_scoped(self):
- self._services.add_scoped(LoggerBase, Logger)
- logger = self._services.get_service(LoggerBase)
-
- self.assertIsNotNone(logger)
-
- self._services.remove_service(LoggerBase)
- logger = self._services.get_service(LoggerBase)
-
- self.assertIsNone(logger)
-
- def test_remove_service_transient(self):
- self._services.add_transient(LoggerBase, Logger)
- logger = self._services.get_service(LoggerBase)
-
- self.assertIsNotNone(logger)
-
- self._services.remove_service(LoggerBase)
- logger = self._services.get_service(LoggerBase)
-
- self.assertIsNone(logger)
diff --git a/src/tests/setup.py b/src/tests/setup.py
deleted file mode 100644
index b9da5bf5..00000000
--- a/src/tests/setup.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import setuptools
-
-setuptools.setup(
- name='sh_edraft_unittests',
- version='2020.0.1',
- packages=setuptools.find_packages(exclude=["tests*"]),
- url='https://www.sh-edraft.de',
- license='MIT',
- author='Sven Heidemann',
- author_email='edraft.sh@gmail.com',
- include_package_data=True,
- description='sh-edraft python common lib unittest',
- python_requires='>=3.8',
- install_requires=[
- 'discord.py',
- 'flask',
- 'mysql-connector',
- 'SQLAlchemy',
- 'termcolor',
- 'pyfiglet',
- 'tabulate',
- 'smtplib'
- ]
-)
diff --git a/src/tests/time_test/time_format_settings_test.py b/src/tests/time_test/time_format_settings_test.py
deleted file mode 100644
index 9bc5347a..00000000
--- a/src/tests/time_test/time_format_settings_test.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import unittest
-
-from sh_edraft.time.model import TimeFormatSettingsNames, TimeFormatSettings
-
-
-class TimeFormatSettingsTest(unittest.TestCase):
-
- def setUp(self): pass
-
- def test_from_dict(self):
- test_dict = {
- TimeFormatSettingsNames.date_format.value: '%H:%M:%S',
- TimeFormatSettingsNames.time_format.value: '%Y-%m-%d',
- TimeFormatSettingsNames.date_time_format.value: '%Y-%m-%d %H:%M:%S.%f',
- TimeFormatSettingsNames.date_time_log_format.value: '%Y-%m-%d_%H-%M-%S'
- }
-
- settings = TimeFormatSettings()
- settings.from_dict(test_dict)
-
- self.assertIsNotNone(settings)
-
- self.assertEqual(test_dict[TimeFormatSettingsNames.date_format.value], settings.date_format)
- self.assertEqual(test_dict[TimeFormatSettingsNames.time_format.value], settings.time_format)
- self.assertEqual(test_dict[TimeFormatSettingsNames.date_time_format.value], settings.date_time_format)
- self.assertEqual(test_dict[TimeFormatSettingsNames.date_time_log_format.value], settings.date_time_log_format)
diff --git a/src/tests/utils_test/credential_manager_test.py b/src/tests/utils_test/credential_manager_test.py
deleted file mode 100644
index 204f1283..00000000
--- a/src/tests/utils_test/credential_manager_test.py
+++ /dev/null
@@ -1,37 +0,0 @@
-import base64
-import unittest
-
-from sh_edraft.utils import CredentialManager
-
-
-class CredentialManagerTest(unittest.TestCase):
-
- def setUp(self): pass
-
- def test_encode(self):
- test_string = 'Hello World'
- expected_test_result = base64.b64encode(test_string.encode('utf-8')).decode('utf-8')
-
- test_result = CredentialManager.encrypt(test_string)
-
- self.assertIsNotNone(test_result)
- self.assertEqual(expected_test_result, test_result)
-
- def test_decode(self):
- test_string = 'SGVsbG8gV29ybGQ='
- expected_test_result = base64.b64decode(test_string).decode('utf-8')
-
- test_result = CredentialManager.decrypt(test_string)
-
- self.assertIsNotNone(test_result)
- self.assertEqual(expected_test_result, test_result)
-
- def test_build_string(self):
- test_string = 'String is $credentials'
- test_credentials = 'SGVsbG8gV29ybGQ='
- expected_test_result = test_string.replace('$credentials', base64.b64decode(test_credentials).decode('utf-8'))
-
- test_result = CredentialManager.build_string(test_string, test_credentials)
-
- self.assertIsNotNone(test_result)
- self.assertEqual(expected_test_result, test_result)
diff --git a/src/tests_dev/__init__.py b/src/tests_dev/__init__.py
deleted file mode 100644
index caf789c0..00000000
--- a/src/tests_dev/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-tests_dev
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'tests_dev'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/tests_dev/appsettings.edrafts-pc.json b/src/tests_dev/appsettings.edrafts-pc.json
deleted file mode 100644
index 0b2e194a..00000000
--- a/src/tests_dev/appsettings.edrafts-pc.json
+++ /dev/null
@@ -1,63 +0,0 @@
-{
- "TimeFormatSettings": {
- "DateFormat": "%Y-%m-%d",
- "TimeFormat": "%H:%M:%S",
- "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
- "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
- },
- "LoggingSettings": {
- "Path": "logs/",
- "Filename": "log_$start_time.log",
- "ConsoleLogLevel": "TRACE",
- "FileLogLevel": "TRACE"
- },
- "EMailClientSettings": {
- "Host": "mail.sh-edraft.de",
- "Port": "587",
- "UserName": "dev-srv@sh-edraft.de",
- "Credentials": "RmBOQX1eNFYiYjgsSid3fV1nelc2WA=="
- },
- "PublishSettings": {
- "SourcePath": "../",
- "DistPath": "../../dist",
- "Templates": [
- {
- "TemplatePath": "../../publish_templates/all_template.txt",
- "Name": "all",
- "Description": "",
- "LongDescription": "",
- "CopyrightDate": "2020",
- "CopyrightName": "sh-edraft.de",
- "LicenseName": "MIT",
- "LicenseDescription": ", see LICENSE for more details.",
- "Title": "",
- "Author": "Sven Heidemann",
- "Version": {
- "Major": 2020,
- "Minor": 12,
- "Micro": 9
- }
- },
- {
- "TemplatePath": "../../publish_templates/all_template.txt",
- "Name": "sh_edraft",
- "Description": "common python library",
- "LongDescription": "Library to share common classes and models used at sh-edraft.de",
- "CopyrightDate": "2020",
- "CopyrightName": "sh-edraft.de",
- "LicenseName": "MIT",
- "LicenseDescription": ", see LICENSE for more details.",
- "Title": "",
- "Author": "Sven Heidemann",
- "Version": {
- "Major": 2020,
- "Minor": 12,
- "Micro": 9
- }
- }
- ],
- "IncludedFiles": [],
- "ExcludedFiles": [],
- "TemplateEnding": "_template.txt"
- }
-}
\ No newline at end of file
diff --git a/src/tests_dev/db/__init__.py b/src/tests_dev/db/__init__.py
deleted file mode 100644
index 44b89a68..00000000
--- a/src/tests_dev/db/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-tests_dev.db
-~~~~~~~~~~~~~~~~~~~
-
-
-
-:copyright: (c) 2020 sh-edraft.de
-:license: MIT, see LICENSE for more details.
-
-"""
-
-__title__ = 'tests_dev.db'
-__author__ = 'Sven Heidemann'
-__license__ = 'MIT'
-__copyright__ = 'Copyright (c) 2020 sh-edraft.de'
-__version__ = '2020.12.9'
-
-from collections import namedtuple
-
-# imports:
-
-VersionInfo = namedtuple('VersionInfo', 'major minor micro')
-version_info = VersionInfo(major=2020, minor=12, micro=9)
diff --git a/src/tests_dev/db/user_repo.py b/src/tests_dev/db/user_repo.py
deleted file mode 100644
index a1b3cffc..00000000
--- a/src/tests_dev/db/user_repo.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from sh_edraft.database.context.base import DatabaseContextBase
-from tests_dev.db.city import City
-from tests_dev.db.user import User
-from tests_dev.db.user_repo_base import UserRepoBase
-
-
-class UserRepo(UserRepoBase):
-
- def __init__(self, db_context: DatabaseContextBase):
- UserRepoBase.__init__(self)
-
- self._session = db_context.session
- self._user_query = db_context.session.query(User)
-
- def create(self): pass
-
- def add_test_user(self):
- city = City('Haren', '49733')
- city2 = City('Meppen', '49716')
- self._session.add(city2)
- user = User('TestUser', city)
- self._session.add(user)
- self._session.commit()
diff --git a/src/tests_dev/db/user_repo_base.py b/src/tests_dev/db/user_repo_base.py
deleted file mode 100644
index c48be0b2..00000000
--- a/src/tests_dev/db/user_repo_base.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from abc import abstractmethod
-
-from sh_edraft.service.base import ServiceBase
-
-
-class UserRepoBase(ServiceBase):
-
- @abstractmethod
- def __init__(self):
- ServiceBase.__init__(self)
diff --git a/src/tests_dev/main.py b/src/tests_dev/main.py
deleted file mode 100644
index cfb45c60..00000000
--- a/src/tests_dev/main.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from tests_dev.program import Program
-
-if __name__ == '__main__':
- program = Program()
- program.create_application_host()
- program.create_configuration()
- program.create_services()
- program.main()
diff --git a/src/tests_dev/program.py b/src/tests_dev/program.py
deleted file mode 100644
index e08eadbe..00000000
--- a/src/tests_dev/program.py
+++ /dev/null
@@ -1,87 +0,0 @@
-from typing import Optional
-
-from sh_edraft.configuration.base import ConfigurationBase
-from sh_edraft.console import Console
-from sh_edraft.database.context import DatabaseContext
-from sh_edraft.database.model import DatabaseSettings
-from sh_edraft.hosting import ApplicationHost
-from sh_edraft.hosting.base import ApplicationBase
-from sh_edraft.logging import Logger
-from sh_edraft.logging.base import LoggerBase
-from sh_edraft.mailing.base import EMailClientBase
-from sh_edraft.mailing import EMailClient
-from sh_edraft.mailing.model import EMail
-from sh_edraft.service.providing.base import ServiceProviderBase
-from sh_edraft.utils import CredentialManager
-
-from tests_dev.db.user_repo import UserRepo
-from tests_dev.db.user_repo_base import UserRepoBase
-
-
-class Program(ApplicationBase):
-
- def __init__(self):
- ApplicationBase.__init__(self)
-
- self._app_host: Optional[ApplicationHost] = None
- self._services: Optional[ServiceProviderBase] = None
- self._configuration: Optional[ConfigurationBase] = None
- self._logger: Optional[LoggerBase] = None
- self._mailer: Optional[EMailClientBase] = None
-
- def create_application_host(self):
- self._app_host = ApplicationHost()
- self._configuration = self._app_host.configuration
- self._services = self._app_host.services
-
- def create_configuration(self):
- self._configuration.add_environment_variables('PYTHON_')
- self._configuration.add_environment_variables('CPL_')
- self._configuration.add_argument_variables()
- self._configuration.add_json_file(f'appsettings.json')
- self._configuration.add_json_file(f'appsettings.{self._configuration.environment.environment_name}.json')
- self._configuration.add_json_file(f'appsettings.{self._configuration.environment.host_name}.json', optional=True)
-
- def create_services(self):
- # Create and connect to database
- db_settings: DatabaseSettings = self._configuration.get_configuration(DatabaseSettings)
- self._services.add_db_context(DatabaseContext)
- db: DatabaseContext = self._services.get_db_context()
- db.connect(CredentialManager.build_string(db_settings.connection_string, db_settings.credentials))
-
- self._services.add_scoped(UserRepoBase, UserRepo)
-
- # Add and create logger
- self._services.add_singleton(LoggerBase, Logger)
- self._logger = self._services.get_service(LoggerBase)
-
- self._services.add_singleton(EMailClientBase, EMailClient)
- self._mailer = self._services.get_service(EMailClientBase)
-
- def test_send_mail(self):
- mail = EMail()
- mail.add_header('Mime-Version: 1.0')
- mail.add_header('Content-Type: text/plain; charset=utf-8')
- mail.add_header('Content-Transfer-Encoding: quoted-printable')
- mail.add_receiver('edraft.sh@gmail.com')
- mail.add_receiver('edraft@sh-edraft.de')
- mail.subject = f'Test - {self._configuration.environment.host_name}'
- mail.body = 'Dies ist ein Test :D'
- self._mailer.send_mail(mail)
-
- def test_console(self):
- self._logger.debug(__name__, 'Started console test')
- Console.write_line('Hello World')
- Console.write('\nName: ')
- Console.write_line('Hello', Console.read_line())
- Console.clear()
- Console.write_at(5, 5, 'at 5, 5')
- Console.write_at(10, 10, 'at 10, 10')
-
- def main(self):
- self._logger.header(f'{self._configuration.environment.application_name}:')
- self._logger.debug(__name__, f'Host: {self._configuration.environment.host_name}')
- self._logger.debug(__name__, f'Environment: {self._configuration.environment.environment_name}')
- self._logger.debug(__name__, f'Customer: {self._configuration.environment.customer}')
- self._services.get_service(UserRepoBase).add_test_user()
- self.test_console()