Updated docs

This commit is contained in:
2023-02-20 15:55:20 +01:00
parent 48d0daabf5
commit 9e28dce5ce
632 changed files with 10917 additions and 6775 deletions

View File

@@ -1,26 +1,26 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -4,17 +4,16 @@ from cpl_core.utils import String
class Console(ProjectTypeABC):
def __init__(
self,
base_path: str,
project_name: str,
workspace: WorkspaceSettings,
use_application_api: bool,
use_startup: bool,
use_service_providing: bool,
use_async: bool,
project_file_data: dict,
self,
base_path: str,
project_name: str,
workspace: WorkspaceSettings,
use_application_api: bool,
use_startup: bool,
use_service_providing: bool,
use_async: bool,
project_file_data: dict,
):
from project_file import ProjectFile
from project_file_appsettings import ProjectFileAppsettings
@@ -25,23 +24,46 @@ class Console(ProjectTypeABC):
from project_file_license import ProjectFileLicense
from schematic_init import Init
ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async, project_file_data)
ProjectTypeABC.__init__(
self,
base_path,
project_name,
workspace,
use_application_api,
use_startup,
use_service_providing,
use_async,
project_file_data,
)
project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/'
self.add_template(ProjectFile(project_name.split('/')[-1], project_path, project_file_data))
self.add_template(ProjectFile(project_name.split("/")[-1], project_path, project_file_data))
if workspace is None:
self.add_template(ProjectFileLicense(''))
self.add_template(ProjectFileReadme(''))
self.add_template(Init('', 'init', f'{base_path}tests/'))
self.add_template(ProjectFileLicense(""))
self.add_template(ProjectFileReadme(""))
self.add_template(Init("", "init", f"{base_path}tests/"))
self.add_template(Init('', 'init', project_path))
self.add_template(Init("", "init", project_path))
self.add_template(ProjectFileAppsettings(project_path))
if use_application_api:
self.add_template(ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async))
self.add_template(
ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async)
)
if use_startup:
self.add_template(ProjectFileStartup(project_path, use_application_api, use_startup, use_service_providing, use_async))
self.add_template(
ProjectFileStartup(project_path, use_application_api, use_startup, use_service_providing, use_async)
)
self.add_template(ProjectFileMain(project_name.split('/')[-1], project_path, use_application_api, use_startup, use_service_providing, use_async))
self.add_template(
ProjectFileMain(
project_name.split("/")[-1],
project_path,
use_application_api,
use_startup,
use_service_providing,
use_async,
)
)

View File

@@ -4,10 +4,9 @@ from cpl_cli.abc.file_template_abc import FileTemplateABC
class ProjectFile(FileTemplateABC):
def __init__(self, name: str, path: str, code: dict):
FileTemplateABC.__init__(self, '', path, '{}')
self._name = f'{name}.json'
FileTemplateABC.__init__(self, "", path, "{}")
self._name = f"{name}.json"
self._code = code
def get_code(self) -> str:

View File

@@ -4,13 +4,13 @@ from cpl_cli.abc.file_template_abc import FileTemplateABC
class ProjectFileAppsettings(FileTemplateABC):
def __init__(self, path: str):
FileTemplateABC.__init__(self, '', path, '{}')
self._name = 'appsettings.json'
FileTemplateABC.__init__(self, "", path, "{}")
self._name = "appsettings.json"
def get_code(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
{
"TimeFormatSettings": {
"DateFormat": "%Y-%m-%d",
@@ -25,4 +25,5 @@ class ProjectFileAppsettings(FileTemplateABC):
"FileLogLevel": "WARN"
}
}
""")
"""
)

View File

@@ -2,15 +2,19 @@ from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC
class ProjectFileApplication(CodeFileTemplateABC):
def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool):
CodeFileTemplateABC.__init__(self, 'application', path, '', use_application_api, use_startup, use_service_providing, use_async)
def __init__(
self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool
):
CodeFileTemplateABC.__init__(
self, "application", path, "", use_application_api, use_startup, use_service_providing, use_async
)
def get_code(self) -> str:
import textwrap
if self._use_async:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
from cpl_core.application import ApplicationABC
from cpl_core.configuration import ConfigurationABC
from cpl_core.console import Console
@@ -27,9 +31,11 @@ class ProjectFileApplication(CodeFileTemplateABC):
async def main(self):
Console.write_line('Hello World')
""")
"""
)
return textwrap.dedent("""\
return textwrap.dedent(
"""\
from cpl_core.application import ApplicationABC
from cpl_core.configuration import ConfigurationABC
from cpl_core.console import Console
@@ -46,4 +52,5 @@ class ProjectFileApplication(CodeFileTemplateABC):
def main(self):
Console.write_line('Hello World')
""")
"""
)

View File

@@ -3,15 +3,25 @@ from cpl_core.utils import String
class ProjectFileMain(CodeFileTemplateABC):
def __init__(self, name: str, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool):
CodeFileTemplateABC.__init__(self, 'main', path, '', use_application_api, use_startup, use_service_providing, use_async)
def __init__(
self,
name: str,
path: str,
use_application_api: bool,
use_startup: bool,
use_service_providing: bool,
use_async: bool,
):
CodeFileTemplateABC.__init__(
self, "main", path, "", use_application_api, use_startup, use_service_providing, use_async
)
import textwrap
import_pkg = f'{String.convert_to_snake_case(name)}.'
import_pkg = f"{String.convert_to_snake_case(name)}."
self._main_with_application_host_and_startup = textwrap.dedent(f"""\
self._main_with_application_host_and_startup = textwrap.dedent(
f"""\
{"import asyncio" if self._use_async else ''}
from cpl_core.application import ApplicationBuilder
@@ -29,8 +39,10 @@ class ProjectFileMain(CodeFileTemplateABC):
if __name__ == '__main__':
{"asyncio.run(main())" if self._use_async else "main()"}
""")
self._main_with_application_base = textwrap.dedent(f"""\
"""
)
self._main_with_application_base = textwrap.dedent(
f"""\
{"import asyncio" if self._use_async else ''}
from cpl_core.application import ApplicationBuilder
@@ -46,9 +58,11 @@ class ProjectFileMain(CodeFileTemplateABC):
if __name__ == '__main__':
{"asyncio.run(main())" if self._use_async else "main()"}
""")
"""
)
self._main_with_dependency_injection = textwrap.dedent(f"""\
self._main_with_dependency_injection = textwrap.dedent(
f"""\
{"import asyncio" if self._use_async else ''}
from cpl_core.application import ApplicationBuilder
@@ -72,12 +86,13 @@ class ProjectFileMain(CodeFileTemplateABC):
if __name__ == '__main__':
{"asyncio.run(main())" if self._use_async else "main()"}
""")
"""
)
def _async(self) -> str:
if self._use_async:
return 'async '
return ''
return "async "
return ""
def get_code(self) -> str:
if self._use_application_api and self._use_startup:

View File

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

View File

@@ -2,15 +2,19 @@ from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC
class ProjectFileTestApplication(CodeFileTemplateABC):
def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool):
CodeFileTemplateABC.__init__(self, 'application', path, '', use_application_api, use_startup, use_service_providing, use_async)
def __init__(
self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool
):
CodeFileTemplateABC.__init__(
self, "application", path, "", use_application_api, use_startup, use_service_providing, use_async
)
def get_code(self) -> str:
import textwrap
if self._use_async:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
import unittest
from unittest import TestSuite
@@ -32,9 +36,11 @@ class ProjectFileTestApplication(CodeFileTemplateABC):
async def main(self):
runner = unittest.TextTestRunner()
runner.run(self._suite)
""")
"""
)
return textwrap.dedent("""\
return textwrap.dedent(
"""\
import unittest
from unittest import TestSuite
@@ -56,4 +62,5 @@ class ProjectFileTestApplication(CodeFileTemplateABC):
def main(self):
runner = unittest.TextTestRunner()
runner.run(self._suite)
""")
"""
)

View File

@@ -2,15 +2,19 @@ from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC
class ProjectFileTestCase(CodeFileTemplateABC):
def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool):
CodeFileTemplateABC.__init__(self, 'test_case', path, '', use_application_api, use_startup, use_service_providing, use_async)
def __init__(
self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool
):
CodeFileTemplateABC.__init__(
self, "test_case", path, "", use_application_api, use_startup, use_service_providing, use_async
)
def get_code(self) -> str:
import textwrap
if self._use_async:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
import unittest
@@ -21,9 +25,11 @@ class ProjectFileTestCase(CodeFileTemplateABC):
async def test_equal(self):
self.assertEqual(True, True)
""")
"""
)
return textwrap.dedent("""\
return textwrap.dedent(
"""\
import unittest
@@ -34,4 +40,5 @@ class ProjectFileTestCase(CodeFileTemplateABC):
def test_equal(self):
self.assertEqual(True, True)
""")
"""
)

View File

@@ -2,10 +2,9 @@ from cpl_cli.abc.file_template_abc import FileTemplateABC
class ProjectFileLicense(FileTemplateABC):
def __init__(self, path: str):
FileTemplateABC.__init__(self, '', path, '')
self._name = 'LICENSE'
FileTemplateABC.__init__(self, "", path, "")
self._name = "LICENSE"
def get_code(self) -> str:
return self._code

View File

@@ -2,10 +2,9 @@ from cpl_cli.abc.file_template_abc import FileTemplateABC
class ProjectFileReadme(FileTemplateABC):
def __init__(self, path: str):
FileTemplateABC.__init__(self, '', path, '')
self._name = 'README.md'
FileTemplateABC.__init__(self, "", path, "")
self._name = "README.md"
def get_code(self) -> str:
return self._code

View File

@@ -6,17 +6,16 @@ from cpl_core.utils import String
class Library(ProjectTypeABC):
def __init__(
self,
base_path: str,
project_name: str,
workspace: WorkspaceSettings,
use_application_api: bool,
use_startup: bool,
use_service_providing: bool,
use_async: bool,
project_file_data: dict,
self,
base_path: str,
project_name: str,
workspace: WorkspaceSettings,
use_application_api: bool,
use_startup: bool,
use_service_providing: bool,
use_async: bool,
project_file_data: dict,
):
from project_file import ProjectFile
from project_file_readme import ProjectFileReadme
@@ -24,14 +23,24 @@ class Library(ProjectTypeABC):
from schematic_init import Init
from schematic_class import Class
ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async, project_file_data)
ProjectTypeABC.__init__(
self,
base_path,
project_name,
workspace,
use_application_api,
use_startup,
use_service_providing,
use_async,
project_file_data,
)
project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/'
self.add_template(ProjectFile(project_name.split('/')[-1], project_path, project_file_data))
self.add_template(ProjectFile(project_name.split("/")[-1], project_path, project_file_data))
if workspace is None:
self.add_template(ProjectFileLicense(''))
self.add_template(ProjectFileReadme(''))
self.add_template(ProjectFileLicense(""))
self.add_template(ProjectFileReadme(""))
self.add_template(Init('', 'init', project_path))
self.add_template(Class('Class1', 'class', project_path))
self.add_template(Init("", "init", project_path))
self.add_template(Class("Class1", "class", project_path))

View File

@@ -6,17 +6,16 @@ from cpl_core.utils import String
class Unittest(ProjectTypeABC):
def __init__(
self,
base_path: str,
project_name: str,
workspace: WorkspaceSettings,
use_application_api: bool,
use_startup: bool,
use_service_providing: bool,
use_async: bool,
project_file_data: dict,
self,
base_path: str,
project_name: str,
workspace: WorkspaceSettings,
use_application_api: bool,
use_startup: bool,
use_service_providing: bool,
use_async: bool,
project_file_data: dict,
):
from project_file import ProjectFile
from project_file_code_application import ProjectFileApplication
@@ -26,17 +25,40 @@ class Unittest(ProjectTypeABC):
from project_file_license import ProjectFileLicense
from schematic_init import Init
ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async, project_file_data)
ProjectTypeABC.__init__(
self,
base_path,
project_name,
workspace,
use_application_api,
use_startup,
use_service_providing,
use_async,
project_file_data,
)
project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/'
self.add_template(ProjectFile(project_name.split('/')[-1], project_path, project_file_data))
self.add_template(ProjectFile(project_name.split("/")[-1], project_path, project_file_data))
if workspace is None:
self.add_template(ProjectFileLicense(''))
self.add_template(ProjectFileReadme(''))
self.add_template(Init('', 'init', f'{base_path}tests/'))
self.add_template(ProjectFileLicense(""))
self.add_template(ProjectFileReadme(""))
self.add_template(Init("", "init", f"{base_path}tests/"))
self.add_template(Init('', 'init', project_path))
self.add_template(ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async))
self.add_template(ProjectFileMain(project_name.split('/')[-1], project_path, use_application_api, use_startup, use_service_providing, use_async))
self.add_template(ProjectFileTestCase(project_path, use_application_api, use_startup, use_service_providing, use_async))
self.add_template(Init("", "init", project_path))
self.add_template(
ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async)
)
self.add_template(
ProjectFileMain(
project_name.split("/")[-1],
project_path,
use_application_api,
use_startup,
use_service_providing,
use_async,
)
)
self.add_template(
ProjectFileTestCase(project_path, use_application_api, use_startup, use_service_providing, use_async)
)

View File

@@ -3,11 +3,10 @@ from cpl_core.utils import String
class ABC(GenerateSchematicABC):
def __init__(self, name: str, schematic: str, path: str):
GenerateSchematicABC.__init__(self, name, schematic, path)
self._class_name = name
if name != '':
if name != "":
self._class_name = f'{String.first_to_upper(name.replace(schematic, ""))}ABC'
def get_code(self) -> str:
@@ -25,8 +24,4 @@ class ABC(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'abc',
['a', 'A']
)
GenerateSchematicABC.register(cls, "abc", ["a", "A"])

View File

@@ -4,7 +4,6 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class Application(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
@@ -32,8 +31,4 @@ class Application(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'application',
['app', 'APP']
)
GenerateSchematicABC.register(cls, "application", ["app", "APP"])

View File

@@ -4,7 +4,6 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class ApplicationExtension(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
@@ -28,8 +27,4 @@ class ApplicationExtension(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'application-extension',
['appex', 'APPEX']
)
GenerateSchematicABC.register(cls, "application-extension", ["appex", "APPEX"])

View File

@@ -3,11 +3,10 @@ from cpl_core.utils import String
class Class(GenerateSchematicABC):
def __init__(self, name: str, schematic: str, path: str):
GenerateSchematicABC.__init__(self, name, schematic, path)
self._name = f'{String.convert_to_snake_case(name)}.py'
self._class_name = f'{String.first_to_upper(name)}'
self._name = f"{String.convert_to_snake_case(name)}.py"
self._class_name = f"{String.first_to_upper(name)}"
def get_code(self) -> str:
code = """\
@@ -21,8 +20,4 @@ class Class(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'class',
['c', 'C']
)
GenerateSchematicABC.register(cls, "class", ["c", "C"])

View File

@@ -4,7 +4,6 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class ConfigModel(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
@@ -39,8 +38,4 @@ class ConfigModel(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'settings',
['st', 'ST']
)
GenerateSchematicABC.register(cls, "settings", ["st", "ST"])

View File

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

View File

@@ -4,10 +4,9 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class Init(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
self._name = f'__init__.py'
self._name = f"__init__.py"
def get_code(self) -> str:
code = """\
@@ -18,8 +17,4 @@ class Init(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'init',
[]
)
GenerateSchematicABC.register(cls, "init", [])

View File

@@ -4,7 +4,6 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class Pipe(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
@@ -25,8 +24,4 @@ class Pipe(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'pipe',
['p', 'P']
)
GenerateSchematicABC.register(cls, "pipe", ["p", "P"])

View File

@@ -3,11 +3,10 @@ from cpl_core.utils import String
class Schematic(GenerateSchematicABC):
def __init__(self, name: str, path: str, schematic: str):
GenerateSchematicABC.__init__(self, name, path, schematic)
self._name = f'schematic_{String.convert_to_snake_case(name)}.py'
self._path = '.cpl/'
self._name = f"schematic_{String.convert_to_snake_case(name)}.py"
self._path = ".cpl/"
self._class_name = String.convert_to_camel_case(name)
def get_code(self) -> str:
@@ -44,8 +43,4 @@ class Schematic(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'schematic',
['scheme', 'SCHEME']
)
GenerateSchematicABC.register(cls, "schematic", ["scheme", "SCHEME"])

View File

@@ -4,7 +4,6 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class Service(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
@@ -20,8 +19,4 @@ class Service(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'service',
['s', 'S']
)
GenerateSchematicABC.register(cls, "service", ["s", "S"])

View File

@@ -4,7 +4,6 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class Startup(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
@@ -32,8 +31,4 @@ class Startup(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'startup',
['stup', 'STUP']
)
GenerateSchematicABC.register(cls, "startup", ["stup", "STUP"])

View File

@@ -4,7 +4,6 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class StartupExtension(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
@@ -32,8 +31,4 @@ class StartupExtension(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'startup-extension',
['stupex', 'STUPEX']
)
GenerateSchematicABC.register(cls, "startup-extension", ["stupex", "STUPEX"])

View File

@@ -4,7 +4,6 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class TestCase(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
@@ -25,8 +24,4 @@ class TestCase(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'test-case',
['tc', 'TC']
)
GenerateSchematicABC.register(cls, "test-case", ["tc", "TC"])

View File

@@ -4,7 +4,6 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class Thread(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
@@ -26,8 +25,4 @@ class Thread(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'thread',
['t', 'T']
)
GenerateSchematicABC.register(cls, "thread", ["t", "T"])

View File

@@ -4,7 +4,6 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class Validator(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
@@ -26,8 +25,4 @@ class Validator(GenerateSchematicABC):
@classmethod
def register(cls):
GenerateSchematicABC.register(
cls,
'validator',
['v', 'V']
)
GenerateSchematicABC.register(cls, "validator", ["v", "V"])

View File

@@ -1,21 +1,21 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
@@ -27,5 +27,5 @@ from .error import Error
from .main import main
from .startup import Startup
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -1,26 +1,26 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli._templates'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli._templates"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -1,26 +1,26 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli._templates.build'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli._templates.build"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -2,10 +2,10 @@ import textwrap
class InitTemplate:
@staticmethod
def get_init_py() -> str:
string = textwrap.dedent("""\
string = textwrap.dedent(
"""\
# -*- coding: utf-8 -*-
\"\"\"
@@ -32,6 +32,7 @@ class InitTemplate:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='$Major', minor='$Minor', micro='$Micro')
""")
"""
)
return string

View File

@@ -1,26 +1,26 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli._templates.publish'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli._templates.publish"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -2,10 +2,10 @@ import textwrap
class SetupTemplate:
@staticmethod
def get_setup_py() -> str:
string = textwrap.dedent("""\
string = textwrap.dedent(
"""\
\"\"\"
This file is generated by CPL CLI
\"\"\"
@@ -27,6 +27,7 @@ class SetupTemplate:
entry_points=$EntryPoints,
package_data=$PackageData
)
""")
"""
)
return string

View File

@@ -2,18 +2,21 @@ from abc import ABC, abstractmethod
class TemplateFileABC(ABC):
@abstractmethod
def __init__(self): pass
def __init__(self):
pass
@property
@abstractmethod
def name(self) -> str: pass
def name(self) -> str:
pass
@property
@abstractmethod
def path(self) -> str: pass
def path(self) -> str:
pass
@property
@abstractmethod
def value(self) -> str: pass
def value(self) -> str:
pass

View File

@@ -1,26 +1,26 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli.abc'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli.abc"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
# imports
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -5,17 +5,16 @@ from cpl_core.utils import String
class CodeFileTemplateABC(FileTemplateABC):
@abstractmethod
def __init__(
self,
name: str,
path: str,
code: str,
use_application_api: bool,
use_startup: bool,
use_service_providing: bool,
use_async: bool,
self,
name: str,
path: str,
code: str,
use_application_api: bool,
use_startup: bool,
use_service_providing: bool,
use_async: bool,
):
FileTemplateABC.__init__(self, name, path, code)
self._use_application_api = use_application_api

View File

@@ -4,15 +4,14 @@ from cpl_core.utils import String
class FileTemplateABC(ABC):
@abstractmethod
def __init__(self, name: str, path: str, code: str):
self._name = f'{String.convert_to_snake_case(name)}.py'
self._name = f"{String.convert_to_snake_case(name)}.py"
self._path = path
self._code = code
def __repr__(self):
return f'<{type(self).__name__} {self._path}{self._name}>'
return f"<{type(self).__name__} {self._path}{self._name}>"
@property
def name(self) -> str:
@@ -21,7 +20,7 @@ class FileTemplateABC(ABC):
@property
def path(self) -> str:
return self._path
@path.setter
def path(self, value: str):
self._path = value
@@ -31,4 +30,5 @@ class FileTemplateABC(ABC):
return self.get_code()
@abstractmethod
def get_code(self) -> str: pass
def get_code(self) -> str:
pass

View File

@@ -8,19 +8,18 @@ from cpl_core.utils import String
class GenerateSchematicABC(FileTemplateABC):
def __init__(self, name: str, schematic: str, path: str):
FileTemplateABC.__init__(self, name, path, '')
self._name = f'{String.convert_to_snake_case(name)}_{schematic}.py'
FileTemplateABC.__init__(self, name, path, "")
self._name = f"{String.convert_to_snake_case(name)}_{schematic}.py"
if schematic in name.lower():
self._name = f'{String.convert_to_snake_case(name)}.py'
self._name = f"{String.convert_to_snake_case(name)}.py"
self._class_name = name
if name != '':
self._class_name = f'{String.first_to_upper(name)}{String.first_to_upper(schematic)}'
if name != "":
self._class_name = f"{String.first_to_upper(name)}{String.first_to_upper(schematic)}"
if schematic in name.lower():
self._class_name = f'{String.first_to_upper(name)}'
self._class_name = f"{String.first_to_upper(name)}"
@property
def class_name(self) -> str:

View File

@@ -6,18 +6,17 @@ from cpl_cli.configuration import WorkspaceSettings
class ProjectTypeABC(ABC):
@abstractmethod
def __init__(
self,
base_path: str,
project_name: str,
workspace: Optional[WorkspaceSettings],
use_application_api: bool,
use_startup: bool,
use_service_providing: bool,
use_async: bool,
project_file_data: dict,
self,
base_path: str,
project_name: str,
workspace: Optional[WorkspaceSettings],
use_application_api: bool,
use_startup: bool,
use_service_providing: bool,
use_async: bool,
project_file_data: dict,
):
self._templates: list[FileTemplateABC] = []
self._base_path = base_path

View File

@@ -9,7 +9,6 @@ from cpl_core.dependency_injection.service_provider_abc import ServiceProviderAB
class CLI(ApplicationABC):
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
"""
CPL CLI
@@ -33,11 +32,11 @@ class CLI(ApplicationABC):
return
if len(self._configuration.additional_arguments) == 0:
Error.error('Expected command')
Error.error("Expected command")
return
unexpected_arguments = ', '.join(self._configuration.additional_arguments)
Error.error(f'Unexpected argument(s): {unexpected_arguments}')
unexpected_arguments = ", ".join(self._configuration.additional_arguments)
Error.error(f"Unexpected argument(s): {unexpected_arguments}")
Console.write_line()
except KeyboardInterrupt:
Console.write_line()

View File

@@ -7,7 +7,6 @@ from cpl_cli.cli_settings_name_enum import CLISettingsNameEnum
class CLISettings(ConfigurationModelABC):
def __init__(self):
ConfigurationModelABC.__init__(self)
@@ -21,5 +20,5 @@ class CLISettings(ConfigurationModelABC):
try:
self._pip_path = settings[CLISettingsNameEnum.pip_path.value]
except Exception as e:
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings')
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")

View File

@@ -2,5 +2,4 @@ from enum import Enum
class CLISettingsNameEnum(Enum):
pip_path = 'PipPath'
pip_path = "PipPath"

View File

@@ -1,21 +1,21 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli.command'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli.command"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
@@ -28,5 +28,5 @@ 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='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -14,7 +14,6 @@ from cpl_cli.configuration.workspace_settings import WorkspaceSettings
class AddService(CommandABC):
def __init__(self, config: ConfigurationABC, workspace: WorkspaceSettings):
"""
Service for CLI command add
@@ -27,23 +26,30 @@ class AddService(CommandABC):
@property
def help_message(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
Adds a project reference to given project.
Usage: cpl add <source-project> <target-project>
Arguments:
source-project: Name of the project to which the reference has to be
target-project: Name of the project to be referenced
""")
"""
)
def _edit_project_file(self, source: str, project_settings: ProjectSettings, build_settings: BuildSettings):
if self._is_simulation:
return
with open(source, 'w') as file:
file.write(json.dumps({
ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(project_settings),
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(build_settings)
}, indent=2))
with open(source, "w") as file:
file.write(
json.dumps(
{
ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(project_settings),
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(build_settings),
},
indent=2,
)
)
file.close()
def execute(self, args: list[str]):
@@ -52,17 +58,17 @@ class AddService(CommandABC):
:param args:
:return:
"""
if 'simulate' in args:
args.remove('simulate')
Console.write_line('Running in simulation mode:')
if "simulate" in args:
args.remove("simulate")
Console.write_line("Running in simulation mode:")
self._is_simulation = True
if len(args) == 0:
Console.error('Expected source and target project')
Console.error("Expected source and target project")
return
elif len(args) == 1:
Console.error('Expected target project')
Console.error("Expected target project")
return
elif len(args) > 2:
@@ -103,30 +109,30 @@ class AddService(CommandABC):
is_invalid_source = True
if is_invalid_source:
Console.error(f'Invalid source: {source}')
Console.error(f"Invalid source: {source}")
return
if is_invalid_target or source == target or not os.path.isfile(target):
Console.error(f'Invalid target: {target}')
Console.error(f"Invalid target: {target}")
return
if self._workspace is None:
target = f'../{target}'
target = f"../{target}"
else:
target = target.replace('src', '..')
target = target.replace("src", "..")
if target in build_settings.project_references:
Console.error(f'Project reference already exists.')
Console.error(f"Project reference already exists.")
return
build_settings.project_references.append(target)
Console.spinner(
f'Editing {source}',
f"Editing {source}",
self._edit_project_file,
source,
project_settings,
build_settings,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)

View File

@@ -5,7 +5,6 @@ from cpl_cli.publish.publisher_abc import PublisherABC
class BuildService(CommandABC):
def __init__(self, publisher: PublisherABC):
"""
Service for the CLI command build
@@ -17,10 +16,12 @@ class BuildService(CommandABC):
@property
def help_message(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
Copies an python app into an output directory named build/ at the given output path. Must be executed within a CPL workspace or project directory
Usage: cpl build
""")
"""
)
def execute(self, args: list[str]):
"""

View File

@@ -10,7 +10,6 @@ from cpl_cli.configuration.workspace_settings import WorkspaceSettings
class CustomScriptService(CommandABC):
def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC, ws: WorkspaceSettings):
"""
Service for CLI scripts
@@ -23,11 +22,11 @@ class CustomScriptService(CommandABC):
@property
def help_message(self) -> str:
return ''
return ""
def execute(self, args: list[str]):
cmd = self._config.get_configuration('ACTIVE_EXECUTABLE')
wd = self._config.get_configuration('PATH_WORKSPACE')
cmd = self._config.get_configuration("ACTIVE_EXECUTABLE")
wd = self._config.get_configuration("PATH_WORKSPACE")
if wd is not None:
self._env.set_working_directory(wd)
@@ -35,16 +34,16 @@ class CustomScriptService(CommandABC):
if script != cmd:
continue
command = ''
external_args = self._config.get_configuration('ARGS')
command = ""
external_args = self._config.get_configuration("ARGS")
if external_args is not None:
command += f'ARGS="{external_args}";'
command += self._workspace.scripts[script]
env_vars = os.environ
env_vars['CPL_ARGS'] = " ".join(args)
env_vars["CPL_ARGS"] = " ".join(args)
try:
subprocess.run(command, shell=True if os.name == 'posix' else None)
subprocess.run(command, shell=True if os.name == "posix" else None)
except Exception as e:
Console.error(str(e))

View File

@@ -16,11 +16,10 @@ from cpl_core.utils.string import String
class GenerateService(CommandABC):
def __init__(
self,
configuration: ConfigurationABC,
workspace: WorkspaceSettings,
self,
configuration: ConfigurationABC,
workspace: WorkspaceSettings,
):
"""
Service for the CLI command generate
@@ -37,7 +36,7 @@ class GenerateService(CommandABC):
self._schematic_classes = set()
for package_name, version in Dependencies.get_cpl_packages():
if package_name == 'cpl-cli':
if package_name == "cpl-cli":
continue
package = importlib.import_module(String.convert_to_snake_case(package_name))
self._read_custom_schematics_from_path(os.path.dirname(package.__file__))
@@ -46,7 +45,7 @@ class GenerateService(CommandABC):
self._read_custom_schematics_from_path(self._env.runtime_directory)
if len(self._schematic_classes) == 0:
Console.error(f'No schematics found in template directory: .cpl')
Console.error(f"No schematics found in template directory: .cpl")
sys.exit()
known_schematics = []
@@ -60,13 +59,14 @@ class GenerateService(CommandABC):
def help_message(self) -> str:
schematics = []
for schematic in self._schematics:
aliases = '|'.join(self._schematics[schematic]['Aliases'])
aliases = "|".join(self._schematics[schematic]["Aliases"])
schematic_str = schematic
if len(aliases) > 0:
schematic_str = f'{schematic} ({aliases})'
schematic_str = f"{schematic} ({aliases})"
schematics.append(schematic_str)
help_msg = textwrap.dedent("""\
help_msg = textwrap.dedent(
"""\
Generate a file based on schematic.
Usage: cpl generate <schematic> <name>
@@ -74,24 +74,25 @@ class GenerateService(CommandABC):
schematic: The schematic to generate.
name: The name of the generated file
Schematics:""")
Schematics:"""
)
for schematic in schematics:
help_msg += f'\n {schematic}'
help_msg += f"\n {schematic}"
return help_msg
def _read_custom_schematics_from_path(self, path: str):
if not os.path.exists(os.path.join(path, '.cpl')):
if not os.path.exists(os.path.join(path, ".cpl")):
return
sys.path.insert(0, os.path.join(path, '.cpl'))
for r, d, f in os.walk(os.path.join(path, '.cpl')):
sys.path.insert(0, os.path.join(path, ".cpl"))
for r, d, f in os.walk(os.path.join(path, ".cpl")):
for file in f:
if not file.startswith('schematic_') or not file.endswith('.py'):
if not file.startswith("schematic_") or not file.endswith(".py"):
continue
try:
exec(open(os.path.join(r, file), 'r').read())
exec(open(os.path.join(r, file), "r").read())
self._schematic_classes.update(GenerateSchematicABC.__subclasses__())
except Exception as e:
Console.error(str(e), traceback.format_exc())
@@ -105,30 +106,32 @@ class GenerateService(CommandABC):
:param value:
:return:
"""
with open(file_path, 'w') as template:
with open(file_path, "w") as template:
template.write(value)
template.close()
def _create_init_files(self, file_path: str, template: GenerateSchematicABC, class_name: str, schematic: str, rel_path: str):
def _create_init_files(
self, file_path: str, template: GenerateSchematicABC, class_name: str, schematic: str, rel_path: str
):
if not os.path.isdir(os.path.dirname(file_path)):
os.makedirs(os.path.dirname(file_path))
directory = ''
for subdir in template.path.split('/'):
directory = ""
for subdir in template.path.split("/"):
directory = os.path.join(directory, subdir)
if subdir == 'src':
if subdir == "src":
continue
file = self._schematics['init']['Template'](class_name, 'init', rel_path)
file = self._schematics["init"]["Template"](class_name, "init", rel_path)
if os.path.exists(os.path.join(os.path.abspath(directory), file.name)):
continue
Console.spinner(
f'Creating {os.path.abspath(directory)}/{file.name}',
f"Creating {os.path.abspath(directory)}/{file.name}",
self._create_file,
os.path.join(os.path.abspath(directory), file.name),
file.get_code(),
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
def _generate(self, schematic: str, name: str, template: type):
@@ -140,10 +143,10 @@ class GenerateService(CommandABC):
:return:
"""
class_name = name
rel_path = ''
if '/' in name:
parts = name.split('/')
rel_path = '/'.join(parts[:-1])
rel_path = ""
if "/" in name:
parts = name.split("/")
rel_path = "/".join(parts[:-1])
class_name = parts[len(parts) - 1]
if self._workspace is not None and parts[0] in self._workspace.projects:
@@ -155,12 +158,12 @@ class GenerateService(CommandABC):
self._create_init_files(file_path, template, class_name, schematic, rel_path)
if os.path.isfile(file_path):
Console.error(f'{String.first_to_upper(schematic)} already exists!\n')
Console.error(f"{String.first_to_upper(schematic)} already exists!\n")
sys.exit()
message = f'Creating {self._env.working_directory}/{template.path}/{template.name}'
if template.path == '':
message = f'Creating {self._env.working_directory}/{template.name}'
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,
@@ -168,12 +171,12 @@ class GenerateService(CommandABC):
file_path,
template.get_code(),
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
def _get_schematic_by_alias(self, schematic: str) -> str:
for key in self._schematics:
if schematic in self._schematics[key]['Aliases']:
if schematic in self._schematics[key]["Aliases"]:
return key
return schematic
@@ -192,25 +195,29 @@ class GenerateService(CommandABC):
schematic = s
break
if schematic is None and len(args) >= 1 and (args[0] in self._schematics or self._get_schematic_by_alias(args[0]) != args[0]):
if (
schematic is None
and len(args) >= 1
and (args[0] in self._schematics or self._get_schematic_by_alias(args[0]) != args[0])
):
schematic = self._get_schematic_by_alias(args[0])
self._config.add_configuration(schematic, args[1])
value = args[1]
if schematic is None:
Console.error(f'Schematic not found')
Console.error(f"Schematic not found")
Console.write_line(self.help_message)
sys.exit()
name = value
if name is None:
name = Console.read(f'Name for the {args[0]}: ')
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 <schematic> [options]')
self._help("Usage: cpl generate <schematic> [options]")
Console.write_line()
sys.exit()

View File

@@ -8,7 +8,6 @@ from cpl_cli.command_abc import CommandABC
class HelpService(CommandABC):
def __init__(self, services: ServiceProviderABC):
"""
Service for CLI command help
@@ -19,10 +18,12 @@ class HelpService(CommandABC):
@property
def help_message(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
Lists available command and their short descriptions.
Usage: cpl help
""")
"""
)
def execute(self, args: list[str]):
"""
@@ -34,24 +35,33 @@ class HelpService(CommandABC):
Console.error(f'Unexpected argument(s): {", ".join(args)}')
sys.exit()
Console.write_line('Available Commands:')
Console.write_line("Available Commands:")
commands = [
['add (a|a)', 'Adds a project reference to given project.'],
['build (b|B)', 'Prepares files for publish into an output directory named dist/ at the given output path. Must be executed from within a workspace directory.'],
['generate (g|G)', 'Generate a new file.'],
['help (h|H)', 'Lists available command and their short descriptions.'],
['install (i|I)', 'With argument installs packages to project, without argument installs project dependencies.'],
['new (n|N)', 'Creates new CPL project.'],
['publish (p|P)', 'Prepares files for publish into an output directory named dist/ at the given output path and executes setup.py. Must be executed from within a library workspace directory.'],
['remove (r|R)', 'Removes a project from workspace.'],
['start (s|S)', 'Starts CPL project, restarting on file changes.'],
['uninstall (ui|UI)', 'Uninstalls packages from project.'],
['update (u|u)', 'Update CPL and project dependencies.'],
['version (v|V)', 'Outputs CPL CLI version.']
["add (a|a)", "Adds a project reference to given project."],
[
"build (b|B)",
"Prepares files for publish into an output directory named dist/ at the given output path. Must be executed from within a workspace directory.",
],
["generate (g|G)", "Generate a new file."],
["help (h|H)", "Lists available command and their short descriptions."],
[
"install (i|I)",
"With argument installs packages to project, without argument installs project dependencies.",
],
["new (n|N)", "Creates new CPL project."],
[
"publish (p|P)",
"Prepares files for publish into an output directory named dist/ at the given output path and executes setup.py. Must be executed from within a library workspace directory.",
],
["remove (r|R)", "Removes a project from workspace."],
["start (s|S)", "Starts CPL project, restarting on file changes."],
["uninstall (ui|UI)", "Uninstalls packages from project."],
["update (u|u)", "Update CPL and project dependencies."],
["version (v|V)", "Outputs CPL CLI version."],
]
for name, description in commands:
Console.set_foreground_color(ForegroundColorEnum.blue)
Console.write(f'\n\t{name} ')
Console.write(f"\n\t{name} ")
Console.set_foreground_color(ForegroundColorEnum.default)
Console.write(f'{description}')
Console.write_line('\nRun \'cpl <command> --help\' for command specific information\'s\n')
Console.write(f"{description}")
Console.write_line("\nRun 'cpl <command> --help' for command specific information's\n")

View File

@@ -21,9 +21,14 @@ from cpl_core.utils.pip import Pip
class InstallService(CommandABC):
def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC, build_settings: BuildSettings,
project_settings: ProjectSettings, cli_settings: CLISettings):
def __init__(
self,
config: ConfigurationABC,
env: ApplicationEnvironmentABC,
build_settings: BuildSettings,
project_settings: ProjectSettings,
cli_settings: CLISettings,
):
"""
Service for the CLI command install
:param config:
@@ -44,17 +49,19 @@ class InstallService(CommandABC):
self._is_virtual = False
self._is_dev = False
self._project_file = f'{self._project_settings.name}.json'
self._project_file = f"{self._project_settings.name}.json"
@property
def help_message(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
Installs given package via pip
Usage: cpl install <package>
Arguments:
package The package to install
""")
"""
)
def _wait(self, t: int, *args, source: str = None, stdout=None, stderr=None):
time.sleep(t)
@@ -65,43 +72,45 @@ class InstallService(CommandABC):
: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.')
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(f'Found invalid dependencies in {self._project_file}.')
Error.error(f"Found invalid dependencies in {self._project_file}.")
return
for dependency in self._project_settings.dependencies:
Console.spinner(
f'Installing: {dependency}',
Pip.install if not self._is_virtual else self._wait, dependency if not self._is_virtual else 2,
'--upgrade',
f"Installing: {dependency}",
Pip.install if not self._is_virtual else self._wait,
dependency if not self._is_virtual else 2,
"--upgrade",
source=self._cli_settings.pip_path,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
local_package = Pip.get_package(dependency)
if local_package is None:
Error.warn(f'Installation of package {dependency} failed!')
Error.warn(f"Installation of package {dependency} failed!")
return
for dependency in self._project_settings.dev_dependencies:
Console.spinner(
f'Installing dev: {dependency}',
Pip.install if not self._is_virtual else self._wait, dependency if not self._is_virtual else 2,
'--upgrade',
f"Installing dev: {dependency}",
Pip.install if not self._is_virtual else self._wait,
dependency if not self._is_virtual else 2,
"--upgrade",
source=self._cli_settings.pip_path,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
local_package = Pip.get_package(dependency)
if local_package is None:
Error.warn(f'Installation of package {dependency} failed!')
Error.warn(f"Installation of package {dependency} failed!")
return
if not self._is_virtual:
@@ -115,18 +124,18 @@ class InstallService(CommandABC):
"""
is_already_in_project = False
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.')
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(f'Found invalid dependencies in {self._project_file}.')
Error.error(f"Found invalid dependencies in {self._project_file}.")
return
package_version = ''
package_version = ""
name = package
if '==' in package:
name = package.split('==')[0]
package_version = package.split('==')[1]
if "==" in package:
name = package.split("==")[0]
package_version = package.split("==")[1]
to_remove_list = []
deps = self._project_settings.dependencies
@@ -134,13 +143,13 @@ class InstallService(CommandABC):
deps = self._project_settings.dev_dependencies
for dependency in deps:
dependency_version = ''
dependency_version = ""
if '==' in dependency:
dependency_version = dependency.split('==')[1]
if "==" in dependency:
dependency_version = dependency.split("==")[1]
if name in dependency:
if package_version != '' and version.parse(package_version) != version.parse(dependency_version):
if package_version != "" and version.parse(package_version) != version.parse(dependency_version):
to_remove_list.append(dependency)
break
else:
@@ -154,45 +163,48 @@ class InstallService(CommandABC):
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.')
Error.warn(f"Package {local_package} is already installed.")
return
elif is_already_in_project:
Error.warn(f'Package {package} is already installed.')
Error.warn(f"Package {package} is already installed.")
return
Console.spinner(
f'Installing: {package}' if not self._is_dev else f'Installing dev: {package}',
Pip.install if not self._is_virtual else self._wait, package if not self._is_virtual else 2,
f"Installing: {package}" if not self._is_dev else f"Installing dev: {package}",
Pip.install if not self._is_virtual else self._wait,
package if not self._is_virtual else 2,
source=self._cli_settings.pip_path,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
if self._is_virtual:
new_package = name
else:
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')
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:
if "==" in new_package:
new_name = new_package
elif '==' in name:
elif "==" in name:
new_name = name
if '/' in new_name:
new_name = new_name.split('/')[0]
if "/" in new_name:
new_name = new_name.split("/")[0]
if '\r' in new_name:
new_name = new_name.replace('\r', '')
if "\r" in new_name:
new_name = new_name.replace("\r", "")
if self._is_dev:
self._project_settings.dev_dependencies.append(new_name)
@@ -202,10 +214,10 @@ class InstallService(CommandABC):
if not self._is_simulation:
config = {
ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings),
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings)
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings),
}
with open(os.path.join(self._env.working_directory, self._project_file), 'w') as project_file:
with open(os.path.join(self._env.working_directory, self._project_file), "w") as project_file:
project_file.write(json.dumps(config, indent=2))
project_file.close()
@@ -217,31 +229,31 @@ class InstallService(CommandABC):
:param args:
:return:
"""
if 'dev' in args:
if "dev" in args:
self._is_dev = True
args.remove('dev')
args.remove("dev")
if 'virtual' in args:
if "virtual" in args:
self._is_virtual = True
args.remove('virtual')
Console.write_line('Running in virtual mode:')
args.remove("virtual")
Console.write_line("Running in virtual mode:")
if 'simulate' in args:
if "simulate" in args:
self._is_simulation = True
args.remove('simulate')
Console.write_line('Running in simulation mode:')
args.remove("simulate")
Console.write_line("Running in simulation mode:")
if 'cpl-prod' in args:
args.remove('cpl-prod')
self._cli_settings.from_dict({'PipPath': 'https://pip.sh-edraft.de'})
if "cpl-prod" in args:
args.remove("cpl-prod")
self._cli_settings.from_dict({"PipPath": "https://pip.sh-edraft.de"})
if 'cpl-exp' in args:
args.remove('cpl-exp')
self._cli_settings.from_dict({'PipPath': 'https://pip-exp.sh-edraft.de'})
if "cpl-exp" in args:
args.remove("cpl-exp")
self._cli_settings.from_dict({"PipPath": "https://pip-exp.sh-edraft.de"})
if 'cpl-dev' in args:
args.remove('cpl-dev')
self._cli_settings.from_dict({'PipPath': 'https://pip-dev.sh-edraft.de'})
if "cpl-dev" in args:
args.remove("cpl-dev")
self._cli_settings.from_dict({"PipPath": "https://pip-dev.sh-edraft.de"})
VenvHelper.init_venv(self._is_virtual, self._env, self._project_settings)

View File

@@ -28,7 +28,6 @@ from cpl_core.utils.string import String
class NewService(CommandABC):
def __init__(self, configuration: ConfigurationABC):
"""
Service for the CLI command new
@@ -47,8 +46,8 @@ class NewService(CommandABC):
self._project_type_classes = set()
self._name: str = ''
self._rel_path: str = ''
self._name: str = ""
self._rel_path: str = ""
self._project_type: ProjectTypeEnum = ProjectTypeEnum.console
self._use_nothing: bool = False
self._use_application_api: bool = False
@@ -60,7 +59,8 @@ class NewService(CommandABC):
@property
def help_message(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
Generates a workspace and initial project or add a project to workspace.
Usage: cpl new <type> <name>
@@ -72,37 +72,32 @@ class NewService(CommandABC):
console (c|C)
library (l|L)
unittest (ut|UT)
""")
"""
)
def _create_project_settings(self):
self._rel_path = os.path.dirname(self._name)
self._project_dict = {
ProjectSettingsNameEnum.name.value: os.path.basename(self._name),
ProjectSettingsNameEnum.version.value: {
VersionSettingsNameEnum.major.value: '0',
VersionSettingsNameEnum.minor.value: '0',
VersionSettingsNameEnum.micro.value: '0'
VersionSettingsNameEnum.major.value: "0",
VersionSettingsNameEnum.minor.value: "0",
VersionSettingsNameEnum.micro.value: "0",
},
ProjectSettingsNameEnum.author.value: '',
ProjectSettingsNameEnum.author_email.value: '',
ProjectSettingsNameEnum.description.value: '',
ProjectSettingsNameEnum.long_description.value: '',
ProjectSettingsNameEnum.url.value: '',
ProjectSettingsNameEnum.copyright_date.value: '',
ProjectSettingsNameEnum.copyright_name.value: '',
ProjectSettingsNameEnum.license_name.value: '',
ProjectSettingsNameEnum.license_description.value: '',
ProjectSettingsNameEnum.dependencies.value: [
f'cpl-core>={version.parse(cpl_core.__version__)}'
],
ProjectSettingsNameEnum.dev_dependencies.value: [
f'cpl-cli>={version.parse(cpl_cli.__version__)}'
],
ProjectSettingsNameEnum.author.value: "",
ProjectSettingsNameEnum.author_email.value: "",
ProjectSettingsNameEnum.description.value: "",
ProjectSettingsNameEnum.long_description.value: "",
ProjectSettingsNameEnum.url.value: "",
ProjectSettingsNameEnum.copyright_date.value: "",
ProjectSettingsNameEnum.copyright_name.value: "",
ProjectSettingsNameEnum.license_name.value: "",
ProjectSettingsNameEnum.license_description.value: "",
ProjectSettingsNameEnum.dependencies.value: [f"cpl-core>={version.parse(cpl_core.__version__)}"],
ProjectSettingsNameEnum.dev_dependencies.value: [f"cpl-cli>={version.parse(cpl_cli.__version__)}"],
ProjectSettingsNameEnum.python_version.value: f'>={sys.version.split(" ")[0]}',
ProjectSettingsNameEnum.python_path.value: {
sys.platform: '../../venv/' if self._use_venv else ''
},
ProjectSettingsNameEnum.classifiers.value: []
ProjectSettingsNameEnum.python_path.value: {sys.platform: "../../venv/" if self._use_venv else ""},
ProjectSettingsNameEnum.classifiers.value: [],
}
self._project.from_dict(self._project_dict)
@@ -110,19 +105,15 @@ class NewService(CommandABC):
def _create_build_settings(self, project_type: str):
self._build_dict = {
BuildSettingsNameEnum.project_type.value: project_type,
BuildSettingsNameEnum.source_path.value: '',
BuildSettingsNameEnum.output_path.value: '../../dist',
BuildSettingsNameEnum.main.value: f'{String.convert_to_snake_case(self._project.name)}.main',
BuildSettingsNameEnum.source_path.value: "",
BuildSettingsNameEnum.output_path.value: "../../dist",
BuildSettingsNameEnum.main.value: f"{String.convert_to_snake_case(self._project.name)}.main",
BuildSettingsNameEnum.entry_point.value: self._project.name,
BuildSettingsNameEnum.include_package_data.value: False,
BuildSettingsNameEnum.included.value: [],
BuildSettingsNameEnum.excluded.value: [
'*/__pycache__',
'*/logs',
'*/tests'
],
BuildSettingsNameEnum.excluded.value: ["*/__pycache__", "*/logs", "*/tests"],
BuildSettingsNameEnum.package_data.value: {},
BuildSettingsNameEnum.project_references.value: []
BuildSettingsNameEnum.project_references.value: [],
}
self._build.from_dict(self._build_dict)
@@ -131,10 +122,7 @@ class NewService(CommandABC):
Creates cpl.json content
:return:
"""
self._project_json = {
ProjectSettings.__name__: self._project_dict,
BuildSettings.__name__: self._build_dict
}
self._project_json = {ProjectSettings.__name__: self._project_dict, BuildSettings.__name__: self._build_dict}
def _get_project_path(self) -> Optional[str]:
"""
@@ -144,12 +132,14 @@ class NewService(CommandABC):
if self._workspace is None:
project_path = os.path.join(self._env.working_directory, self._rel_path, self._project.name)
else:
base = '' if self._use_base else 'src'
project_path = os.path.join(self._env.working_directory, base, self._rel_path, String.convert_to_snake_case(self._project.name))
base = "" if self._use_base else "src"
project_path = os.path.join(
self._env.working_directory, base, self._rel_path, String.convert_to_snake_case(self._project.name)
)
if os.path.isdir(project_path) and len(os.listdir(project_path)) > 0:
Console.write_line(project_path)
Console.error('Project path is not empty\n')
Console.error("Project path is not empty\n")
return None
return project_path
@@ -159,27 +149,33 @@ class NewService(CommandABC):
Gets project information's from user
:return:
"""
is_unittest = project_type == 'unittest'
is_library = project_type == 'library'
is_unittest = project_type == "unittest"
is_library = project_type == "library"
if is_library:
return
if self._use_application_api or self._use_startup or self._use_service_providing or self._use_async or self._use_nothing:
if (
self._use_application_api
or self._use_startup
or self._use_service_providing
or self._use_async
or self._use_nothing
):
Console.set_foreground_color(ForegroundColorEnum.default)
Console.write_line('Skipping question due to given flags')
Console.write_line("Skipping question due to given flags")
return
if not is_unittest and not is_library:
self._use_application_api = Console.read('Do you want to use application base? (y/n) ').lower() == 'y'
self._use_application_api = Console.read("Do you want to use application base? (y/n) ").lower() == "y"
if not is_unittest and self._use_application_api:
self._use_startup = Console.read('Do you want to use startup? (y/n) ').lower() == 'y'
self._use_startup = Console.read("Do you want to use startup? (y/n) ").lower() == "y"
if not is_unittest and not self._use_application_api:
self._use_service_providing = Console.read('Do you want to use service providing? (y/n) ').lower() == 'y'
self._use_service_providing = Console.read("Do you want to use service providing? (y/n) ").lower() == "y"
if not self._use_async:
self._use_async = Console.read('Do you want to use async? (y/n) ').lower() == 'y'
self._use_async = Console.read("Do you want to use async? (y/n) ").lower() == "y"
Console.set_foreground_color(ForegroundColorEnum.default)
@@ -189,30 +185,32 @@ class NewService(CommandABC):
project = self._workspace.default_project
if self._env.working_directory.endswith(project):
project = ''
project = ""
if self._workspace is None and self._use_base:
project = f'{self._rel_path}/{project}'
project = f"{self._rel_path}/{project}"
VenvHelper.init_venv(
False,
self._env,
self._project,
explicit_path=os.path.join(self._env.working_directory, project, self._project.python_executable.replace('../', ''))
explicit_path=os.path.join(
self._env.working_directory, project, self._project.python_executable.replace("../", "")
),
)
def _read_custom_project_types_from_path(self, path: str):
if not os.path.exists(os.path.join(path, '.cpl')):
if not os.path.exists(os.path.join(path, ".cpl")):
return
sys.path.insert(0, os.path.join(path, '.cpl'))
for r, d, f in os.walk(os.path.join(path, '.cpl')):
sys.path.insert(0, os.path.join(path, ".cpl"))
for r, d, f in os.walk(os.path.join(path, ".cpl")):
for file in f:
if file.startswith('project_file_') or not file.startswith('project_') or not file.endswith('.py'):
if file.startswith("project_file_") or not file.startswith("project_") or not file.endswith(".py"):
continue
try:
exec(open(os.path.join(r, file), 'r').read())
exec(open(os.path.join(r, file), "r").read())
self._project_type_classes.update(ProjectTypeABC.__subclasses__())
except Exception as e:
Console.error(str(e), traceback.format_exc())
@@ -220,7 +218,7 @@ class NewService(CommandABC):
def _create_project(self, project_type: str):
for package_name in Dependencies.get_cpl_packages():
if package_name == 'cpl-cli':
if package_name == "cpl-cli":
continue
package = importlib.import_module(String.convert_to_snake_case(package_name[0]))
self._read_custom_project_types_from_path(os.path.dirname(package.__file__))
@@ -229,7 +227,7 @@ class NewService(CommandABC):
self._read_custom_project_types_from_path(self._env.runtime_directory)
if len(self._project_type_classes) == 0:
Console.error(f'No project types found in template directory: .cpl')
Console.error(f"No project types found in template directory: .cpl")
sys.exit()
project_class = None
@@ -242,7 +240,7 @@ class NewService(CommandABC):
project_class = p
if project_class is None:
Console.error(f'Project type {project_type} not found in template directory: .cpl/')
Console.error(f"Project type {project_type} not found in template directory: .cpl/")
sys.exit()
project_type = String.convert_to_snake_case(project_class.__name__)
@@ -255,60 +253,60 @@ class NewService(CommandABC):
self._get_project_information(project_type)
project_name = self._project.name
if self._rel_path != '':
project_name = f'{self._rel_path}/{project_name}'
if self._rel_path != "":
project_name = f"{self._rel_path}/{project_name}"
base = 'src/'
split_project_name = project_name.split('/')
base = "src/"
split_project_name = project_name.split("/")
if self._use_base and len(split_project_name) > 0:
base = f'{split_project_name[0]}/'
base = f"{split_project_name[0]}/"
project = project_class(
base if self._workspace is not None else 'src/',
base if self._workspace is not None else "src/",
project_name,
self._workspace,
self._use_application_api,
self._use_startup,
self._use_service_providing,
self._use_async,
self._project_json
self._project_json,
)
if self._workspace is None:
TemplateBuilder.create_workspace(
f'{project_name}/cpl-workspace.json',
project_name.split('/')[-1],
f"{project_name}/cpl-workspace.json",
project_name.split("/")[-1],
{
project_name: f'{base if self._workspace is not None else "src/"}{String.convert_to_snake_case(project_name)}/{project_name}.json'
},
{}
{},
)
else:
self._workspace.projects[project_name] = f'{base if self._workspace is not None else "src/"}{String.convert_to_snake_case(project_name)}/{project_name}.json'
TemplateBuilder.create_workspace('cpl-workspace.json', self._workspace.default_project, self._workspace.projects, self._workspace.scripts)
self._workspace.projects[
project_name
] = f'{base if self._workspace is not None else "src/"}{String.convert_to_snake_case(project_name)}/{project_name}.json'
TemplateBuilder.create_workspace(
"cpl-workspace.json", self._workspace.default_project, self._workspace.projects, self._workspace.scripts
)
for template in project.templates:
rel_base = '/'.join(project_name.split('/')[:-1])
template_path_base = template.path.split('/')[0]
if not self._use_base and rel_base != '' and template_path_base != '' and template_path_base != rel_base:
template.path = template.path.replace(f'{template_path_base}/', f'{template_path_base}/{rel_base}/')
rel_base = "/".join(project_name.split("/")[:-1])
template_path_base = template.path.split("/")[0]
if not self._use_base and rel_base != "" and template_path_base != "" and template_path_base != rel_base:
template.path = template.path.replace(f"{template_path_base}/", f"{template_path_base}/{rel_base}/")
if template.name.endswith(f'{project_name.split("/")[-1]}.json'):
pass
file_path = os.path.join(
project_name if self._workspace is None else '',
template.path,
template.name
)
file_path = os.path.join(project_name if self._workspace is None else "", template.path, template.name)
Console.spinner(
f'Creating {file_path}',
f"Creating {file_path}",
TemplateBuilder.build,
file_path,
template,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
if self._use_venv:
@@ -320,42 +318,42 @@ class NewService(CommandABC):
:param args:
:return:
"""
if 'nothing' in args:
if "nothing" in args:
self._use_nothing = True
self._use_async = False
self._use_application_api = False
self._use_startup = False
self._use_service_providing = False
if 'async' in args:
args.remove('async')
if 'application-base' in args:
args.remove('application-base')
if 'startup' in args:
args.remove('startup')
if 'service-providing' in args:
args.remove('service-providing')
if "async" in args:
args.remove("async")
if "application-base" in args:
args.remove("application-base")
if "startup" in args:
args.remove("startup")
if "service-providing" in args:
args.remove("service-providing")
if 'async' in args:
if "async" in args:
self._use_async = True
args.remove('async')
if 'application-base' in args:
args.remove("async")
if "application-base" in args:
self._use_application_api = True
args.remove('application-base')
if 'startup' in args:
args.remove("application-base")
if "startup" in args:
self._use_startup = True
args.remove('startup')
if 'service-providing' in args:
args.remove("startup")
if "service-providing" in args:
self._use_service_providing = True
args.remove('service-providing')
if 'venv' in args:
args.remove("service-providing")
if "venv" in args:
self._use_venv = True
args.remove('venv')
if 'base' in args:
args.remove("venv")
if "base" in args:
self._use_base = True
args.remove('base')
args.remove("base")
if len(args) <= 1:
Console.error(f'Project type not found')
Console.error(f"Project type not found")
Console.write_line(self.help_message)
return

View File

@@ -5,7 +5,6 @@ from cpl_cli.publish.publisher_abc import PublisherABC
class PublishService(CommandABC):
def __init__(self, publisher: PublisherABC):
"""
Service for the CLI command publish
@@ -17,10 +16,12 @@ class PublishService(CommandABC):
@property
def help_message(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
Prepares files for publish into an output directory named dist/ at the given output path and executes setup.py.
Usage: cpl publish
""")
"""
)
def execute(self, args: list[str]):
"""

View File

@@ -10,11 +10,16 @@ from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl_cli.command_abc import CommandABC
from cpl_cli.configuration import WorkspaceSettings, WorkspaceSettingsNameEnum, BuildSettingsNameEnum, ProjectSettings, BuildSettings
from cpl_cli.configuration import (
WorkspaceSettings,
WorkspaceSettingsNameEnum,
BuildSettingsNameEnum,
ProjectSettings,
BuildSettings,
)
class RemoveService(CommandABC):
def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
"""
Service for CLI command remove
@@ -31,13 +36,15 @@ class RemoveService(CommandABC):
@property
def help_message(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
Removes a project from workspace.
Usage: cpl remove <project>
Arguments:
project The name of the project to delete
""")
"""
)
def _create_file(self, file_name: str, content: dict):
if self._is_simulation:
@@ -50,7 +57,7 @@ class RemoveService(CommandABC):
if not os.path.isdir(path):
os.makedirs(path)
with open(file_name, 'w') as project_json:
with open(file_name, "w") as project_json:
project_json.write(json.dumps(content, indent=2))
project_json.close()
@@ -64,14 +71,14 @@ class RemoveService(CommandABC):
WorkspaceSettings.__name__: {
WorkspaceSettingsNameEnum.default_project.value: self._workspace.default_project,
WorkspaceSettingsNameEnum.projects.value: self._workspace.projects,
WorkspaceSettingsNameEnum.scripts.value: self._workspace.scripts
WorkspaceSettingsNameEnum.scripts.value: self._workspace.scripts,
}
}
self._create_file(path, ws_dict)
def _get_project_settings(self, project: str) -> dict:
with open(os.path.join(os.getcwd(), self._workspace.projects[project]), 'r', encoding='utf-8') as cfg:
with open(os.path.join(os.getcwd(), self._workspace.projects[project]), "r", encoding="utf-8") as cfg:
# load json
project_json = json.load(cfg)
cfg.close()
@@ -79,11 +86,12 @@ class RemoveService(CommandABC):
return project_json
def _write_project_settings(self, project: str, project_settings: dict, build_settings: dict):
with open(os.path.join(os.getcwd(), self._workspace.projects[project]), 'w', encoding='utf-8') as file:
file.write(json.dumps({
ProjectSettings.__name__: project_settings,
BuildSettings.__name__: build_settings
}, indent=2))
with open(os.path.join(os.getcwd(), self._workspace.projects[project]), "w", encoding="utf-8") as file:
file.write(
json.dumps(
{ProjectSettings.__name__: project_settings, BuildSettings.__name__: build_settings}, indent=2
)
)
file.close()
def _find_deps_in_projects(self, project_name: str, rel_path: str):
@@ -92,26 +100,34 @@ class RemoveService(CommandABC):
continue
project_settings = self._get_project_settings(project)
if BuildSettings.__name__ not in project_settings or BuildSettingsNameEnum.project_references.value not in project_settings[BuildSettings.__name__]:
if (
BuildSettings.__name__ not in project_settings
or BuildSettingsNameEnum.project_references.value not in project_settings[BuildSettings.__name__]
):
continue
ref_to_delete = ''
ref_to_delete = ""
for ref in project_settings[BuildSettings.__name__][BuildSettingsNameEnum.project_references.value]:
if os.path.basename(ref) == f'{project_name}.json':
if os.path.basename(ref) == f"{project_name}.json":
ref_to_delete = ref
if ref_to_delete not in project_settings[BuildSettings.__name__][BuildSettingsNameEnum.project_references.value]:
if (
ref_to_delete
not in project_settings[BuildSettings.__name__][BuildSettingsNameEnum.project_references.value]
):
continue
project_settings[BuildSettings.__name__][BuildSettingsNameEnum.project_references.value].remove(ref_to_delete)
project_settings[BuildSettings.__name__][BuildSettingsNameEnum.project_references.value].remove(
ref_to_delete
)
Console.spinner(
f'Removing {project_name} from {project}',
f"Removing {project_name} from {project}",
self._write_project_settings,
project,
project_settings[ProjectSettings.__name__],
project_settings[BuildSettings.__name__],
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
def execute(self, args: list[str]):
@@ -120,37 +136,37 @@ class RemoveService(CommandABC):
:param args:
:return:
"""
if 'simulate' in args:
args.remove('simulate')
Console.write_line('Running in simulation mode:')
if "simulate" in args:
args.remove("simulate")
Console.write_line("Running in simulation mode:")
self._is_simulation = True
project_name = args[0]
if project_name not in self._workspace.projects:
Console.error(f'Project {project_name} not found in workspace.')
Console.error(f"Project {project_name} not found in workspace.")
return
if project_name == self._workspace.default_project:
Console.error(f'Project {project_name} is the default project.')
Console.error(f"Project {project_name} is the default project.")
return
src_path = os.path.dirname(self._workspace.projects[project_name])
Console.spinner(
f'Removing {src_path}',
f"Removing {src_path}",
self._remove_sources,
os.path.abspath(src_path),
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
self._find_deps_in_projects(project_name, src_path)
del self._workspace.projects[project_name]
path = 'cpl-workspace.json'
path = "cpl-workspace.json"
Console.spinner(
f'Changing {path}',
f"Changing {path}",
self._create_workspace,
path,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)

View File

@@ -17,16 +17,16 @@ from cpl_core.utils.string import String
class RunService(CommandABC):
def __init__(self,
config: ConfigurationABC,
env: ApplicationEnvironmentABC,
services: ServiceProviderABC,
project_settings: ProjectSettings,
build_settings: BuildSettings,
workspace: WorkspaceSettings,
publisher: PublisherService,
):
def __init__(
self,
config: ConfigurationABC,
env: ApplicationEnvironmentABC,
services: ServiceProviderABC,
project_settings: ProjectSettings,
build_settings: BuildSettings,
workspace: WorkspaceSettings,
publisher: PublisherService,
):
"""
Service for the CLI command start
:param config:
@@ -51,18 +51,20 @@ class RunService(CommandABC):
@property
def help_message(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
Starts your application.
Usage: cpl run
""")
"""
)
def _set_project_by_args(self, name: str):
if self._workspace is None:
Error.error('The command requires to be run in an CPL workspace, but a workspace could not be found.')
Error.error("The command requires to be run in an CPL workspace, but a workspace could not be found.")
sys.exit()
if name not in self._workspace.projects:
Error.error(f'Project {name} not found in workspace')
Error.error(f"Project {name} not found in workspace")
sys.exit()
project_path = self._workspace.projects[name]
@@ -70,7 +72,7 @@ class RunService(CommandABC):
self._config.add_configuration(ProjectSettings, None)
self._config.add_configuration(BuildSettings, None)
working_directory = self._config.get_configuration('PATH_WORKSPACE')
working_directory = self._config.get_configuration("PATH_WORKSPACE")
if working_directory is not None:
self._env.set_working_directory(working_directory)
@@ -80,7 +82,7 @@ class RunService(CommandABC):
self._build_settings: BuildSettings = self._config.get_configuration(BuildSettings)
if self._project_settings is None or self._build_settings is None:
Error.error(f'Project {name} not found')
Error.error(f"Project {name} not found")
sys.exit()
self._src_dir = os.path.dirname(json_file)
@@ -92,13 +94,15 @@ class RunService(CommandABC):
self._env.set_working_directory(self._src_dir)
self._publisher.build()
self._env.set_working_directory(self._src_dir)
self._src_dir = os.path.abspath(os.path.join(
self._src_dir,
self._build_settings.output_path,
self._project_settings.name,
'build',
String.convert_to_snake_case(self._project_settings.name)
))
self._src_dir = os.path.abspath(
os.path.join(
self._src_dir,
self._build_settings.output_path,
self._project_settings.name,
"build",
String.convert_to_snake_case(self._project_settings.name),
)
)
def execute(self, args: list[str]):
"""
@@ -106,9 +110,9 @@ class RunService(CommandABC):
:param args:
:return:
"""
if 'dev' in args:
if "dev" in args:
self._is_dev = True
args.remove('dev')
args.remove("dev")
if len(args) >= 1:
self._set_project_by_args(args[0])

View File

@@ -5,7 +5,6 @@ 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
@@ -17,10 +16,12 @@ class StartService(CommandABC):
@property
def help_message(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
Starts your application, restarting on file changes.
Usage: cpl start
""")
"""
)
def execute(self, args: list[str]):
"""

View File

@@ -17,9 +17,13 @@ from cpl_cli.configuration.settings_helper import SettingsHelper
class UninstallService(CommandABC):
def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC, build_settings: BuildSettings,
project_settings: ProjectSettings):
def __init__(
self,
config: ConfigurationABC,
env: ApplicationEnvironmentABC,
build_settings: BuildSettings,
project_settings: ProjectSettings,
):
"""
Service for the CLI command uninstall
:param config:
@@ -33,23 +37,25 @@ class UninstallService(CommandABC):
self._env = env
self._build_settings = build_settings
self._project_settings = project_settings
self._is_simulating = False
self._is_virtual = False
self._is_dev = False
self._project_file = f'{self._project_settings.name}.json'
self._project_file = f"{self._project_settings.name}.json"
@property
def help_message(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
Uninstalls given package via pip
Usage: cpl uninstall <package>
Arguments:
package The package to uninstall
""")
"""
)
def _wait(self, t: int, *args, source: str = None, stdout=None, stderr=None):
time.sleep(t)
@@ -60,23 +66,23 @@ class UninstallService(CommandABC):
:return:
"""
if len(args) == 0:
Console.error(f'Expected package')
Console.error(f'Usage: cpl uninstall <package>')
Console.error(f"Expected package")
Console.error(f"Usage: cpl uninstall <package>")
return
if 'dev' in args:
if "dev" in args:
self._is_dev = True
args.remove('dev')
args.remove("dev")
if '--virtual' in args:
if "--virtual" in args:
self._is_virtual = True
args.remove('--virtual')
Console.write_line('Running in virtual mode:')
if '--simulate' in args:
args.remove("--virtual")
Console.write_line("Running in virtual mode:")
if "--simulate" in args:
self._is_virtual = True
args.remove('--simulate')
Console.write_line('Running in simulation mode:')
args.remove("--simulate")
Console.write_line("Running in simulation mode:")
VenvHelper.init_venv(self._is_virtual, self._env, self._project_settings)
@@ -98,19 +104,20 @@ class UninstallService(CommandABC):
package = dependency
if not is_in_dependencies and pip_package is None:
Console.error(f'Package {package} not found')
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}' if not self._is_dev else f'Uninstalling dev: {package}',
Pip.uninstall if not self._is_virtual else self._wait, package if not self._is_virtual else 2,
f"Uninstalling: {package}" if not self._is_dev else f"Uninstalling dev: {package}",
Pip.uninstall if not self._is_virtual else self._wait,
package if not self._is_virtual else 2,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
deps = self._project_settings.dependencies
@@ -122,12 +129,12 @@ class UninstallService(CommandABC):
if not self._is_simulating:
config = {
ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings),
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings)
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings),
}
with open(os.path.join(self._env.working_directory, self._project_file), 'w') as project_file:
with open(os.path.join(self._env.working_directory, self._project_file), "w") as project_file:
project_file.write(json.dumps(config, indent=2))
project_file.close()
Console.write_line(f'Removed {package}')
Console.write_line(f"Removed {package}")
if not self._is_virtual:
Pip.reset_executable()

View File

@@ -18,14 +18,15 @@ from cpl_cli.configuration.settings_helper import SettingsHelper
class UpdateService(CommandABC):
def __init__(self,
config: ConfigurationABC,
env: ApplicationEnvironmentABC,
build_settings: BuildSettings,
project_settings: ProjectSettings,
cli_settings: CLISettings,
migrations: MigrationServiceABC):
def __init__(
self,
config: ConfigurationABC,
env: ApplicationEnvironmentABC,
build_settings: BuildSettings,
project_settings: ProjectSettings,
cli_settings: CLISettings,
migrations: MigrationServiceABC,
):
"""
Service for the CLI command update
:param config:
@@ -44,14 +45,16 @@ class UpdateService(CommandABC):
self._migrations = migrations
self._is_simulation = False
self._project_file = f'{self._project_settings.name}.json'
self._project_file = f"{self._project_settings.name}.json"
@property
def help_message(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
Updates the CPL and project dependencies.
Usage: cpl update
""")
"""
)
def _collect_project_dependencies(self) -> list[tuple]:
"""
@@ -61,8 +64,8 @@ class UpdateService(CommandABC):
dependencies = []
for package in [*self._project_settings.dependencies, *self._project_settings.dev_dependencies]:
name = package
if '==' in package:
name = package.split('==')[0]
if "==" in package:
name = package.split("==")[0]
dependencies.append((package, name))
@@ -76,17 +79,17 @@ class UpdateService(CommandABC):
for package, name in dependencies:
Pip.install(
name,
'--upgrade',
'--upgrade-strategy',
'eager',
"--upgrade",
"--upgrade-strategy",
"eager",
source=self._cli_settings.pip_path,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
stderr=subprocess.DEVNULL,
)
new_package = Pip.get_package(name)
if new_package is None:
Console.error(f'Update for package {package} failed')
Console.error(f"Update for package {package} failed")
continue
self._project_json_update_dependency(package, new_package)
@@ -97,27 +100,32 @@ class UpdateService(CommandABC):
:return:
"""
dependencies = Console.spinner(
'Collecting installed dependencies', self._collect_project_dependencies,
"Collecting installed dependencies",
self._collect_project_dependencies,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
Console.spinner(
'Updating installed dependencies', self._update_project_dependencies, dependencies,
"Updating installed dependencies",
self._update_project_dependencies,
dependencies,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
if 'cpl-cli' in [y for x, y in dependencies]:
if "cpl-cli" in [y for x, y in dependencies]:
import cpl_cli
Console.spinner(
'Running migrations', self._migrations.migrate_from, cpl_cli.__version__,
"Running migrations",
self._migrations.migrate_from,
cpl_cli.__version__,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
Console.write_line(f'Found {len(self._project_settings.dependencies)} dependencies.')
Console.write_line(f"Found {len(self._project_settings.dependencies)} dependencies.")
@staticmethod
def _check_outdated():
@@ -126,19 +134,20 @@ class UpdateService(CommandABC):
:return:
"""
table_str: bytes = Console.spinner(
'Analyzing for available package updates', Pip.get_outdated,
"Analyzing for available package updates",
Pip.get_outdated,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
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:')
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.write_line(f"\t{row}")
Console.set_foreground_color(ForegroundColorEnum.yellow)
Console.write_line(f'\tUpdate with {Pip.get_executable()} -m pip install --upgrade <package>')
Console.write_line(f"\tUpdate with {Pip.get_executable()} -m pip install --upgrade <package>")
Console.set_foreground_color(ForegroundColorEnum.default)
def _project_json_update_dependency(self, old_package: str, new_package: str):
@@ -153,20 +162,20 @@ class UpdateService(CommandABC):
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 "/" in new_package:
new_package = new_package.split("/")[0]
if '\r' in new_package:
new_package = new_package.replace('\r', '')
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)
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings),
}
with open(os.path.join(self._env.working_directory, self._project_file), 'w') as project:
with open(os.path.join(self._env.working_directory, self._project_file), "w") as project:
project.write(json.dumps(config, indent=2))
project.close()
@@ -176,22 +185,22 @@ class UpdateService(CommandABC):
:param args:
:return:
"""
if 'simulate' in args:
args.remove('simulate')
Console.write_line('Running in simulation mode:')
if "simulate" in args:
args.remove("simulate")
Console.write_line("Running in simulation mode:")
self._is_simulation = True
if 'cpl-prod' in args:
args.remove('cpl-prod')
self._cli_settings.from_dict({'PipPath': 'https://pip.sh-edraft.de'})
if "cpl-prod" in args:
args.remove("cpl-prod")
self._cli_settings.from_dict({"PipPath": "https://pip.sh-edraft.de"})
if 'cpl-exp' in args:
args.remove('cpl-exp')
self._cli_settings.from_dict({'PipPath': 'https://pip-exp.sh-edraft.de'})
if "cpl-exp" in args:
args.remove("cpl-exp")
self._cli_settings.from_dict({"PipPath": "https://pip-exp.sh-edraft.de"})
if 'cpl-dev' in args:
args.remove('cpl-dev')
self._cli_settings.from_dict({'PipPath': 'https://pip-dev.sh-edraft.de'})
if "cpl-dev" in args:
args.remove("cpl-dev")
self._cli_settings.from_dict({"PipPath": "https://pip-dev.sh-edraft.de"})
VenvHelper.init_venv(False, self._env, self._project_settings)

View File

@@ -12,7 +12,6 @@ from cpl_cli.command_abc import CommandABC
class VersionService(CommandABC):
def __init__(self):
"""
Service for the CLI command version
@@ -21,10 +20,12 @@ class VersionService(CommandABC):
@property
def help_message(self) -> str:
return textwrap.dedent("""\
return textwrap.dedent(
"""\
Lists the version of CPL, CPL CLI and all installed packages from pip.
Usage: cpl version
""")
"""
)
def execute(self, args: list[str]):
"""
@@ -33,16 +34,16 @@ class VersionService(CommandABC):
:return:
"""
Console.set_foreground_color(ForegroundColorEnum.yellow)
Console.banner('CPL CLI')
Console.banner("CPL CLI")
Console.set_foreground_color(ForegroundColorEnum.default)
if '__version__' in dir(cpl_cli):
Console.write_line(f'Common Python library CLI: ')
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:')
Console.table(['Name', 'Version'], Dependencies.get_cpl_packages())
Console.write_line('\nPython packages:')
Console.table(['Name', 'Version'], Dependencies.get_packages())
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:")
Console.table(["Name", "Version"], Dependencies.get_cpl_packages())
Console.write_line("\nPython packages:")
Console.table(["Name", "Version"], Dependencies.get_packages())

View File

@@ -5,20 +5,21 @@ from cpl_core.console import Console
class CommandABC(ArgumentExecutableABC):
@abstractmethod
def __init__(self):
ABC.__init__(self)
@property
@abstractmethod
def help_message(self) -> str: pass
def help_message(self) -> str:
pass
@abstractmethod
def execute(self, args: list[str]): pass
def execute(self, args: list[str]):
pass
def run(self, args: list[str]):
if 'help' in args:
if "help" in args:
Console.write_line(self.help_message)
return

View File

@@ -1,21 +1,21 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli.configuration'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli.configuration"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
@@ -30,5 +30,5 @@ from .version_settings_name_enum import VersionSettingsNameEnum
from .workspace_settings import WorkspaceSettings
from .workspace_settings_name_enum import WorkspaceSettingsNameEnum
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -10,7 +10,6 @@ from cpl_cli.configuration.project_type_enum import ProjectTypeEnum
class BuildSettings(ConfigurationModelABC):
def __init__(self):
ConfigurationModelABC.__init__(self)
@@ -82,27 +81,26 @@ class BuildSettings(ConfigurationModelABC):
else:
self._project_references = []
if sys.platform == 'win32':
self._source_path = str(self._source_path).replace('/', '\\')
self._output_path = str(self._output_path).replace('/', '\\')
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('/', '\\'))
excluded.append(str(ex).replace("/", "\\"))
self._excluded = excluded
# windows paths for included files
included = []
for inc in self._included:
included.append(str(inc).replace('/', '\\'))
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.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)

View File

@@ -2,14 +2,13 @@ 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'
project_references = 'ProjectReferences'
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"
project_references = "ProjectReferences"

View File

@@ -12,7 +12,6 @@ from cpl_core.console.foreground_color_enum import ForegroundColorEnum
class ProjectSettings(ConfigurationModelABC):
def __init__(self):
ConfigurationModelABC.__init__(self)
@@ -122,15 +121,18 @@ class ProjectSettings(ConfigurationModelABC):
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 = f'{settings[ProjectSettingsNameEnum.python_path.value][sys.platform]}'
if (
ProjectSettingsNameEnum.python_path.value in settings
and sys.platform in settings[ProjectSettingsNameEnum.python_path.value]
):
path = f"{settings[ProjectSettingsNameEnum.python_path.value][sys.platform]}"
if path == '' or path is None:
Error.warn(f'{ProjectSettingsNameEnum.python_path.value} not set')
if path == "" or path is None:
Error.warn(f"{ProjectSettingsNameEnum.python_path.value} not set")
path = sys.executable
else:
if not path.endswith('bin/python'):
path = os.path.join(path, 'bin/python')
if not path.endswith("bin/python"):
path = os.path.join(path, "bin/python")
else:
path = sys.executable
@@ -143,6 +145,6 @@ class ProjectSettings(ConfigurationModelABC):
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.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)

View File

@@ -2,19 +2,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'
dev_dependencies = 'DevDependencies'
python_version = 'PythonVersion'
python_path = 'PythonPath'
classifiers = 'Classifiers'
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"
dev_dependencies = "DevDependencies"
python_version = "PythonVersion"
python_path = "PythonPath"
classifiers = "Classifiers"

View File

@@ -2,7 +2,6 @@ from enum import Enum
class ProjectTypeEnum(Enum):
console = 'console'
library = 'library'
unittest = 'unittest'
console = "console"
library = "library"
unittest = "unittest"

View File

@@ -6,10 +6,7 @@ class SchematicCollection:
@classmethod
def register(cls, template: type, schematic: str, aliases: list[str]):
cls._schematics[schematic] = {
"Template": template,
"Aliases": aliases
}
cls._schematics[schematic] = {"Template": template, "Aliases": aliases}
@classmethod
def get_schematics(cls) -> dict:

View File

@@ -6,7 +6,6 @@ from cpl_cli.configuration.project_settings_name_enum import ProjectSettingsName
class SettingsHelper:
@staticmethod
def get_project_settings_dict(project: ProjectSettings) -> dict:
return {
@@ -14,7 +13,7 @@ class SettingsHelper:
ProjectSettingsNameEnum.version.value: {
VersionSettingsNameEnum.major.value: project.version.major,
VersionSettingsNameEnum.minor.value: project.version.minor,
VersionSettingsNameEnum.micro.value: project.version.micro
VersionSettingsNameEnum.micro.value: project.version.micro,
},
ProjectSettingsNameEnum.author.value: project.author,
ProjectSettingsNameEnum.author_email.value: project.author_email,
@@ -29,7 +28,7 @@ class SettingsHelper:
ProjectSettingsNameEnum.dev_dependencies.value: project.dev_dependencies,
ProjectSettingsNameEnum.python_version.value: project.python_version,
ProjectSettingsNameEnum.python_path.value: project.python_path,
ProjectSettingsNameEnum.classifiers.value: project.classifiers
ProjectSettingsNameEnum.classifiers.value: project.classifiers,
}
@staticmethod
@@ -44,5 +43,5 @@ class SettingsHelper:
BuildSettingsNameEnum.included.value: build.included,
BuildSettingsNameEnum.excluded.value: build.excluded,
BuildSettingsNameEnum.package_data.value: build.package_data,
BuildSettingsNameEnum.project_references.value: build.project_references
BuildSettingsNameEnum.project_references.value: build.project_references,
}

View File

@@ -11,24 +11,25 @@ from cpl_core.console import Console, ForegroundColorEnum
class VenvHelper:
@staticmethod
def init_venv(is_virtual: bool, env: ApplicationEnvironmentABC, project_settings: ProjectSettings, explicit_path=None):
def init_venv(
is_virtual: bool, env: ApplicationEnvironmentABC, project_settings: ProjectSettings, explicit_path=None
):
if is_virtual:
return
venv_path = os.path.abspath(os.path.join(env.working_directory, project_settings.python_executable, '../../'))
venv_path = os.path.abspath(os.path.join(env.working_directory, project_settings.python_executable, "../../"))
if explicit_path is not None:
venv_path = os.path.abspath(explicit_path)
if not os.path.exists(venv_path):
Console.spinner(
f'Creating venv: {venv_path}',
f"Creating venv: {venv_path}",
VenvHelper.create_venv,
venv_path,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
Pip.set_executable(project_settings.python_executable)
@@ -36,8 +37,8 @@ class VenvHelper:
@staticmethod
def create_venv(path):
subprocess.run(
[sys.executable, '-m', 'venv', os.path.abspath(os.path.join(path, '../../'))],
[sys.executable, "-m", "venv", os.path.abspath(os.path.join(path, "../../"))],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
stdin=subprocess.DEVNULL
stdin=subprocess.DEVNULL,
)

View File

@@ -5,13 +5,7 @@ from cpl_cli.configuration.version_settings_name_enum import VersionSettingsName
class VersionSettings(ConfigurationModelABC):
def __init__(
self,
major: str = None,
minor: str = None,
micro: str = None
):
def __init__(self, major: str = None, minor: str = None, micro: str = None):
ConfigurationModelABC.__init__(self)
self._major: Optional[str] = major
@@ -32,15 +26,15 @@ class VersionSettings(ConfigurationModelABC):
def to_str(self) -> str:
if self._micro is None:
return f'{self._major}.{self._minor}'
return f"{self._major}.{self._minor}"
else:
return f'{self._major}.{self._minor}.{self._micro}'
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]
micro = settings[VersionSettingsNameEnum.micro.value]
if micro != '':
if micro != "":
self._micro = micro
def to_dict(self) -> dict:

View File

@@ -2,7 +2,6 @@ from enum import Enum
class VersionSettingsNameEnum(Enum):
major = 'Major'
minor = 'Minor'
micro = 'Micro'
major = "Major"
minor = "Minor"
micro = "Micro"

View File

@@ -7,14 +7,13 @@ from cpl_cli.configuration.workspace_settings_name_enum import WorkspaceSettings
class WorkspaceSettings(ConfigurationModelABC):
def __init__(self):
ConfigurationModelABC.__init__(self)
self._default_project: Optional[str] = None
self._projects: dict[str, str] = {}
self._scripts: dict[str, str] = {}
@property
def default_project(self) -> str:
return self._default_project
@@ -37,5 +36,5 @@ class WorkspaceSettings(ConfigurationModelABC):
else:
self._scripts = {}
except Exception as e:
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings')
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")

View File

@@ -2,7 +2,6 @@ from enum import Enum
class WorkspaceSettingsNameEnum(Enum):
default_project = 'DefaultProject'
projects = 'Projects'
scripts = 'Scripts'
default_project = "DefaultProject"
projects = "Projects"
scripts = "Scripts"

View File

@@ -2,21 +2,21 @@
"ProjectSettings": {
"Name": "cpl-cli",
"Version": {
"Major": "2022",
"Minor": "12",
"Micro": "1"
"Major": "2023",
"Minor": "2",
"Micro": "0"
},
"Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de",
"Description": "sh-edraft Common Python library CLI",
"LongDescription": "sh-edraft Common Python library Command Line Interface",
"Description": "CPL CLI",
"LongDescription": "CPL Command Line Interface",
"URL": "https://www.sh-edraft.de",
"CopyrightDate": "2020 - 2023",
"CopyrightName": "sh-edraft.de",
"LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [
"cpl-core>=2022.12.1"
"cpl-core>=2023.2.0"
],
"DevDependencies": [],
"PythonVersion": ">=3.10",

View File

@@ -3,15 +3,13 @@ from cpl_core.console.console import Console
class Error:
@staticmethod
def error(message: str):
Console.error(message)
Console.error('Run \'cpl help\'\n')
Console.error("Run 'cpl help'\n")
@staticmethod
def warn(message: str):
Console.set_foreground_color(ForegroundColorEnum.yellow)
Console.write_line(message, '\n')
Console.write_line(message, "\n")
Console.set_foreground_color(ForegroundColorEnum.default)

View File

@@ -1,26 +1,26 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli.helper'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli.helper"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -7,7 +7,7 @@ class Dependencies:
_dependencies = dict(tuple(str(ws).split()) for ws in pkg_resources.working_set)
for p in _dependencies:
if str(p).startswith('cpl-'):
if str(p).startswith("cpl-"):
_cpl_packages.append([p, _dependencies[p]])
continue

View File

@@ -1,26 +1,26 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli.live_server'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli.live_server"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -16,13 +16,12 @@ from cpl_core.utils import String
class LiveServerService(FileSystemEventHandler):
def __init__(
self,
env: ApplicationEnvironmentABC,
project_settings: ProjectSettings,
build_settings: BuildSettings,
publisher: PublisherService,
self,
env: ApplicationEnvironmentABC,
project_settings: ProjectSettings,
build_settings: BuildSettings,
publisher: PublisherService,
):
"""
Service for the live development server
@@ -51,7 +50,7 @@ class LiveServerService(FileSystemEventHandler):
:return:
"""
self._observer = Observer()
self._observer.schedule(self, path=os.path.abspath(os.path.join(self._src_dir, '../')), recursive=True)
self._observer.schedule(self, path=os.path.abspath(os.path.join(self._src_dir, "../")), recursive=True)
self._observer.start()
def _restart(self):
@@ -64,7 +63,7 @@ class LiveServerService(FileSystemEventHandler):
if proc.cmdline() == self._ls_thread.command:
proc.kill()
Console.write_line('Restart\n')
Console.write_line("Restart\n")
while self._ls_thread.is_alive():
time.sleep(1)
@@ -80,7 +79,7 @@ class LiveServerService(FileSystemEventHandler):
return None
# Event is modified, you can process it now
if str(event.src_path).endswith('.py'):
if str(event.src_path).endswith(".py"):
self._observer.stop()
self._restart()
@@ -88,11 +87,7 @@ class LiveServerService(FileSystemEventHandler):
self._build()
self._start_observer()
self._ls_thread = LiveServerThread(
self._project_settings.python_executable,
self._wd,
self._args,
self._env,
self._build_settings
self._project_settings.python_executable, self._wd, self._args, self._env, self._build_settings
)
self._ls_thread.start()
self._ls_thread.join()
@@ -105,13 +100,15 @@ class LiveServerService(FileSystemEventHandler):
self._env.set_working_directory(self._src_dir)
self._publisher.build()
self._env.set_working_directory(self._src_dir)
self._wd = os.path.abspath(os.path.join(
self._src_dir,
self._build_settings.output_path,
self._project_settings.name,
'build',
String.convert_to_snake_case(self._project_settings.name)
))
self._wd = os.path.abspath(
os.path.join(
self._src_dir,
self._build_settings.output_path,
self._project_settings.name,
"build",
String.convert_to_snake_case(self._project_settings.name),
)
)
def start(self, args: list[str]):
"""
@@ -119,14 +116,14 @@ class LiveServerService(FileSystemEventHandler):
:param args:
:return:
"""
if self._build_settings.main == '':
Console.error('Project has no entry point.')
if self._build_settings.main == "":
Console.error("Project has no entry point.")
return
if 'dev' in args:
if "dev" in args:
self._is_dev = True
args.remove('dev')
args.remove("dev")
self._args = args
Console.write_line('** CPL live development server is running **')
Console.write_line("** CPL live development server is running **")
self._start()

View File

@@ -11,9 +11,9 @@ from cpl_cli.configuration import BuildSettings
class LiveServerThread(threading.Thread):
def __init__(self, executable: str, path: str, args: list[str], env: ApplicationEnvironmentABC,
build_settings: BuildSettings):
def __init__(
self, executable: str, path: str, args: list[str], env: ApplicationEnvironmentABC, build_settings: BuildSettings
):
"""
Thread to start the CPL project for the live development server
:param executable:
@@ -31,7 +31,7 @@ class LiveServerThread(threading.Thread):
self._env = env
self._build_settings = build_settings
self._main = ''
self._main = ""
self._command = []
self._env_vars = os.environ
@@ -49,27 +49,29 @@ class LiveServerThread(threading.Thread):
:return:
"""
main = self._build_settings.main
if '.' in self._build_settings.main:
length = len(self._build_settings.main.split('.')) - 1
main = self._build_settings.main.split('.')[length]
if "." in self._build_settings.main:
length = len(self._build_settings.main.split(".")) - 1
main = self._build_settings.main.split(".")[length]
self._main = os.path.join(self._path, f'{main}.py')
self._main = os.path.join(self._path, f"{main}.py")
if not os.path.isfile(self._main):
Console.error('Entry point main.py not found')
Console.error("Entry point main.py not found")
return
# set cwd to src/
self._env.set_working_directory(os.path.abspath(os.path.join(self._path)))
src_cwd = os.path.abspath(os.path.join(self._path, '../'))
if sys.platform == 'win32':
self._env_vars['PYTHONPATH'] = f'{src_cwd};' \
f'{os.path.join(self._env.working_directory, self._build_settings.source_path)}'
src_cwd = os.path.abspath(os.path.join(self._path, "../"))
if sys.platform == "win32":
self._env_vars["PYTHONPATH"] = (
f"{src_cwd};" f"{os.path.join(self._env.working_directory, self._build_settings.source_path)}"
)
else:
self._env_vars['PYTHONPATH'] = f'{src_cwd}:' \
f'{os.path.join(self._env.working_directory, self._build_settings.source_path)}'
self._env_vars["PYTHONPATH"] = (
f"{src_cwd}:" f"{os.path.join(self._env.working_directory, self._build_settings.source_path)}"
)
Console.set_foreground_color(ForegroundColorEnum.green)
Console.write_line('Read successfully')
Console.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')

View File

@@ -10,7 +10,6 @@ from cpl_cli.configuration.build_settings import BuildSettings
class StartExecutable:
def __init__(self, env: ApplicationEnvironmentABC, build_settings: BuildSettings):
"""
Service to start the CPL project for the live development server
@@ -23,7 +22,7 @@ class StartExecutable:
self._env = env
self._build_settings = build_settings
self._main = ''
self._main = ""
self._command = []
self._env_vars = os.environ
@@ -34,42 +33,44 @@ class StartExecutable:
return
path = os.path.abspath(os.path.dirname(os.path.dirname(self._executable)))
if sys.platform == 'win32':
self._env_vars['PATH'] = f'{path}\\bin' + os.pathsep + os.environ.get('PATH', '')
if sys.platform == "win32":
self._env_vars["PATH"] = f"{path}\\bin" + os.pathsep + os.environ.get("PATH", "")
else:
self._env_vars['PATH'] = f'{path}/bin' + os.pathsep + os.environ.get('PATH', '')
self._env_vars["PATH"] = f"{path}/bin" + os.pathsep + os.environ.get("PATH", "")
self._env_vars['VIRTUAL_ENV'] = path
self._env_vars["VIRTUAL_ENV"] = path
def run(self, args: list[str], executable: str, path: str, output=True):
self._executable = os.path.abspath(os.path.join(self._env.working_directory, executable))
if not os.path.exists(self._executable):
Console.error(f'Executable not found')
Console.error(f"Executable not found")
return
main = self._build_settings.main
if '.' in self._build_settings.main:
length = len(self._build_settings.main.split('.')) - 1
main = self._build_settings.main.split('.')[length]
if "." in self._build_settings.main:
length = len(self._build_settings.main.split(".")) - 1
main = self._build_settings.main.split(".")[length]
self._main = os.path.join(path, f'{main}.py')
self._main = os.path.join(path, f"{main}.py")
if not os.path.isfile(self._main):
Console.error('Entry point main.py not found')
Console.error("Entry point main.py not found")
return
# set cwd to src/
self._env.set_working_directory(os.path.abspath(os.path.join(path)))
src_cwd = os.path.abspath(os.path.join(path, '../'))
if sys.platform == 'win32':
self._env_vars['PYTHONPATH'] = f'{src_cwd};' \
f'{os.path.join(self._env.working_directory, self._build_settings.source_path)}'
src_cwd = os.path.abspath(os.path.join(path, "../"))
if sys.platform == "win32":
self._env_vars["PYTHONPATH"] = (
f"{src_cwd};" f"{os.path.join(self._env.working_directory, self._build_settings.source_path)}"
)
else:
self._env_vars['PYTHONPATH'] = f'{src_cwd}:' \
f'{os.path.join(self._env.working_directory, self._build_settings.source_path)}'
self._env_vars["PYTHONPATH"] = (
f"{src_cwd}:" f"{os.path.join(self._env.working_directory, self._build_settings.source_path)}"
)
if output:
Console.set_foreground_color(ForegroundColorEnum.green)
Console.write_line('Read successfully')
Console.write_line("Read successfully")
Console.set_foreground_color(ForegroundColorEnum.cyan)
Console.write_line(f'Started at {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}\n\n')
Console.set_foreground_color(ForegroundColorEnum.default)

View File

@@ -13,18 +13,18 @@ from cpl_core.console import Console
def get_startup_extensions() -> list[Type[StartupExtensionABC]]:
blacklisted_packages = ['cpl-cli']
blacklisted_packages = ["cpl-cli"]
startup_extensions = []
installed_packages = pkg_resources.working_set
for p in installed_packages:
package = str(p).split(' ')[0]
if not package.startswith('cpl-') or package in blacklisted_packages:
package = str(p).split(" ")[0]
if not package.startswith("cpl-") or package in blacklisted_packages:
continue
package = package.replace('-', '_')
package = package.replace("-", "_")
loaded_package = __import__(package)
if '__cli_startup_extension__' not in dir(loaded_package):
if "__cli_startup_extension__" not in dir(loaded_package):
continue
startup_extensions.append(loaded_package.__cli_startup_extension__)
@@ -44,7 +44,7 @@ def main():
Console.write_line()
if __name__ == '__main__':
if __name__ == "__main__":
main()
# ((

View File

@@ -1,26 +1,26 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli.migrations'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli.migrations"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
# imports
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -1,26 +1,26 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli.migrations.base'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli.migrations.base"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -2,7 +2,6 @@ from abc import ABC, abstractmethod
class MigrationABC(ABC):
@abstractmethod
def __init__(self, version: str):
self._version = version
@@ -12,4 +11,5 @@ class MigrationABC(ABC):
return self._version
@abstractmethod
def migrate(self): pass
def migrate(self):
pass

View File

@@ -2,9 +2,10 @@ from abc import ABC, abstractmethod
class MigrationServiceABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
def __init__(self): pass
@abstractmethod
def migrate_from(self, version: str): pass
def migrate_from(self, version: str):
pass

View File

@@ -2,9 +2,8 @@ from cpl_cli.migrations.base.migration_abc import MigrationABC
class Migration202210(MigrationABC):
def __init__(self):
MigrationABC.__init__(self, '2022.10')
MigrationABC.__init__(self, "2022.10")
def migrate(self):
# This migration could be deleted, but stays as an example.

View File

@@ -1,26 +1,26 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli.migrations.service'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli.migrations.service"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -6,7 +6,6 @@ from cpl_core.dependency_injection import ServiceProviderABC
class MigrationService(MigrationServiceABC):
def __init__(self, services: ServiceProviderABC):
MigrationServiceABC.__init__(self)

View File

@@ -1,21 +1,21 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli.publish'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli.publish"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
@@ -24,5 +24,5 @@ from collections import namedtuple
from .publisher_abc import PublisherABC
from .publisher_service import PublisherService
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -2,27 +2,32 @@ from abc import abstractmethod, ABC
class PublisherABC(ABC):
@abstractmethod
def __init__(self):
ABC.__init__(self)
@property
@abstractmethod
def source_path(self) -> str: pass
def source_path(self) -> str:
pass
@property
@abstractmethod
def dist_path(self) -> str: pass
def dist_path(self) -> str:
pass
@abstractmethod
def include(self, path: str): pass
def include(self, path: str):
pass
@abstractmethod
def exclude(self, path: str): pass
def exclude(self, path: str):
pass
@abstractmethod
def build(self): pass
def build(self):
pass
@abstractmethod
def publish(self): pass
def publish(self):
pass

View File

@@ -19,9 +19,9 @@ from cpl_cli._templates.publish.setup_template import SetupTemplate
class PublisherService(PublisherABC):
def __init__(self, config: ConfigurationABC,
env: ApplicationEnvironmentABC, project: ProjectSettings, build: BuildSettings):
def __init__(
self, config: ConfigurationABC, env: ApplicationEnvironmentABC, project: ProjectSettings, build: BuildSettings
):
"""
Service to build or publish files for distribution
:param config:
@@ -43,11 +43,11 @@ class PublisherService(PublisherABC):
self._included_dirs: list[str] = []
self._distributed_files: list[str] = []
self._path_mark = '/'
if sys.platform == 'win32':
self._path_mark = '\\'
self._path_mark = "/"
if sys.platform == "win32":
self._path_mark = "\\"
self._src_path_part = f'src{self._path_mark}'
self._src_path_part = f"src{self._path_mark}"
@property
def source_path(self) -> str:
@@ -64,17 +64,17 @@ class PublisherService(PublisherABC):
:return:
"""
if self._src_path_part in file:
file = file.split(self._src_path_part)[1].replace(self._src_path_part, '', 1)
file = file.split(self._src_path_part)[1].replace(self._src_path_part, "", 1)
dirs = os.path.dirname(file).split(self._path_mark)
for d in dirs:
if d.__contains__('.'):
if d.__contains__("."):
dirs.remove(d)
if len(dirs) == 0:
return os.path.basename(file)
else:
return '.'.join(dirs)
return ".".join(dirs)
@staticmethod
def _delete_path(path: str):
@@ -87,7 +87,7 @@ class PublisherService(PublisherABC):
try:
shutil.rmtree(path)
except Exception as e:
Console.error(f'{e}')
Console.error(f"{e}")
sys.exit()
@staticmethod
@@ -101,7 +101,7 @@ class PublisherService(PublisherABC):
try:
os.makedirs(path)
except Exception as e:
Console.error(f'{e}')
Console.error(f"{e}")
sys.exit()
def _is_path_included(self, path: str) -> bool:
@@ -111,8 +111,8 @@ class PublisherService(PublisherABC):
:return:
"""
for included in self._build_settings.included:
if included.startswith('*'):
included = included.replace('*', '')
if included.startswith("*"):
included = included.replace("*", "")
if included in path and path not in self._build_settings.excluded:
return True
@@ -126,8 +126,8 @@ class PublisherService(PublisherABC):
:return:
"""
for excluded in self._build_settings.excluded:
if excluded.startswith('*'):
excluded = excluded.replace('*', '')
if excluded.startswith("*"):
excluded = excluded.replace("*", "")
if excluded in path and not self._is_path_included(path):
return True
@@ -141,8 +141,8 @@ class PublisherService(PublisherABC):
:return:
"""
for excluded in self._build_settings.excluded:
if excluded.startswith('*'):
excluded = excluded.replace('*', '')
if excluded.startswith("*"):
excluded = excluded.replace("*", "")
if excluded in file and not self._is_path_included(file):
return True
@@ -194,10 +194,10 @@ class PublisherService(PublisherABC):
for project in self._build_settings.project_references:
project = os.path.abspath(os.path.join(self._source_path, project))
if not os.path.isfile(os.path.abspath(project)):
Console.error(f'Cannot import project: {project}')
Console.error(f"Cannot import project: {project}")
return
self.exclude(f'*/{os.path.basename(project)}')
self.exclude(f"*/{os.path.basename(project)}")
self._read_sources_from_path(os.path.dirname(project))
def _create_packages(self):
@@ -206,44 +206,48 @@ class PublisherService(PublisherABC):
:return:
"""
for file in self._included_files:
if not file.endswith('__init__.py'):
if not file.endswith("__init__.py"):
continue
template_content = ''
template_content = ""
module_file_lines: list[str] = []
title = self._get_module_name_from_dirs(file)
if title == '':
if title == "":
title = self._project_settings.name
module_py_lines: list[str] = []
imports = ''
imports = ""
with open(file, 'r') as py_file:
with open(file, "r") as py_file:
module_file_lines = py_file.readlines()
py_file.close()
if len(module_file_lines) == 0:
imports = '# imports:'
imports = "# imports:"
else:
is_started = False
build_ignore = False
for line in module_file_lines:
if line.__contains__('# imports'):
if line.__contains__("# imports"):
is_started = True
if line.__contains__('# build-ignore'):
if line.__contains__("# build-ignore"):
build_ignore = True
if line.__contains__('# build-ignore-end') and is_started:
module_py_lines.append('# build-ignore-end'.replace('\n', ''))
if line.__contains__("# build-ignore-end") and is_started:
module_py_lines.append("# build-ignore-end".replace("\n", ""))
build_ignore = False
if ((line.__contains__('from') or line.__contains__('import')) and is_started) or line.startswith('__cli_startup_extension__') or build_ignore:
module_py_lines.append(line.replace('\n', ''))
if (
((line.__contains__("from") or line.__contains__("import")) and is_started)
or line.startswith("__cli_startup_extension__")
or build_ignore
):
module_py_lines.append(line.replace("\n", ""))
if len(module_py_lines) > 0:
imports = '\n'.join(module_py_lines)
imports = "\n".join(module_py_lines)
template_content = stringTemplate(InitTemplate.get_init_py()).substitute(
Name=self._project_settings.name,
@@ -253,16 +257,16 @@ class PublisherService(PublisherABC):
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,
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
Imports=imports,
)
with open(file, 'w+') as py_file:
with open(file, "w+") as py_file:
py_file.write(template_content)
py_file.close()
@@ -278,7 +282,7 @@ class PublisherService(PublisherABC):
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)
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)
@@ -287,20 +291,20 @@ class PublisherService(PublisherABC):
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}')
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}')
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)
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):
@@ -329,7 +333,7 @@ class PublisherService(PublisherABC):
Dependencies: ProjectSettings, BuildSettings
:return:
"""
setup_file = os.path.join(self._output_path, 'setup.py')
setup_file = os.path.join(self._output_path, "setup.py")
if os.path.isfile(setup_file):
os.remove(setup_file)
@@ -339,19 +343,19 @@ class PublisherService(PublisherABC):
try:
main_name = self._build_settings.main
if '.' in self._build_settings.main:
length = len(self._build_settings.main.split('.'))
main_name = self._build_settings.main.split('.')[length - 1]
if "." in self._build_settings.main:
length = len(self._build_settings.main.split("."))
main_name = self._build_settings.main.split(".")[length - 1]
sys.path.insert(0, os.path.join(self._source_path, '../'))
sys.path.insert(0, os.path.join(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))
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')
if main is None or not callable(main) and not hasattr(main, "main"):
Console.error("Could not find entry point")
return
if callable(main):
@@ -361,13 +365,9 @@ class PublisherService(PublisherABC):
mod_name = main.__name__
func_name = main.main.__name__
entry_points = {
'console_scripts': [
f'{self._build_settings.entry_point} = {mod_name}:{func_name}'
]
}
entry_points = {"console_scripts": [f"{self._build_settings.entry_point} = {mod_name}:{func_name}"]}
with open(setup_file, 'w+') as setup_py:
with open(setup_file, "w+") as setup_py:
setup_string = stringTemplate(SetupTemplate.get_setup_py()).substitute(
Name=self._project_settings.name,
Version=self._project_settings.version.to_str(),
@@ -381,7 +381,7 @@ class PublisherService(PublisherABC):
PyRequires=self._project_settings.python_version,
Dependencies=self._project_settings.dependencies,
EntryPoints=entry_points,
PackageData=self._build_settings.package_data
PackageData=self._build_settings.package_data,
)
setup_py.write(setup_string)
setup_py.close()
@@ -391,22 +391,25 @@ class PublisherService(PublisherABC):
Starts setup.py
:return:
"""
setup_py = os.path.join(self._output_path, 'setup.py')
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}')
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")}'
])
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))
Console.error("Executing setup.py failed", str(e))
def include(self, path: str):
"""
@@ -433,17 +436,30 @@ class PublisherService(PublisherABC):
3. Copies all included source files to dist_path/build
:return:
"""
self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) # probably causing some errors (#125)
self.exclude(f'*/{self._project_settings.name}.json')
self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, 'build'))
self._env.set_working_directory(
os.path.join(self._env.working_directory, "../")
) # probably causing some errors (#125)
self.exclude(f"*/{self._project_settings.name}.json")
self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, "build"))
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.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()
def publish(self):
@@ -456,46 +472,48 @@ class PublisherService(PublisherABC):
4. Remove all included source from dist_path/publish
:return:
"""
self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) # probably causing some errors (#125)
self.exclude(f'*/{self._project_settings.name}.json')
self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, 'publish'))
self._env.set_working_directory(
os.path.join(self._env.working_directory, "../")
) # probably causing some errors (#125)
self.exclude(f"*/{self._project_settings.name}.json")
self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, "publish"))
Console.write_line('Build:')
Console.write_line("Build:")
Console.spinner(
'Reading source files:',
"Reading source files:",
self._read_sources,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.blue
spinner_foreground_color=ForegroundColorEnum.blue,
)
Console.spinner(
'Creating internal packages:',
"Creating internal packages:",
self._create_packages,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.blue
spinner_foreground_color=ForegroundColorEnum.blue,
)
Console.spinner(
'Building application:',
"Building application:",
self._dist_files,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.blue
spinner_foreground_color=ForegroundColorEnum.blue,
)
Console.write_line('\nPublish:')
Console.write_line("\nPublish:")
Console.spinner(
'Generating setup.py:',
"Generating setup.py:",
self._create_setup,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.blue
spinner_foreground_color=ForegroundColorEnum.blue,
)
Console.write_line('Running setup.py:\n')
Console.write_line("Running setup.py:\n")
self._run_setup()
Console.spinner(
'Cleaning dist path:',
"Cleaning dist path:",
self._clean_dist_files,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.blue
spinner_foreground_color=ForegroundColorEnum.blue,
)
Console.write_line()

View File

@@ -1,26 +1,26 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli.source_creator'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli.source_creator"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -7,7 +7,6 @@ from cpl_core.console import Console, ForegroundColorEnum
class TemplateBuilder:
@staticmethod
def build_cpl_file(file_name: str, content: dict):
if not os.path.isabs(file_name):
@@ -17,7 +16,7 @@ class TemplateBuilder:
if not os.path.isdir(path):
os.makedirs(path)
with open(file_name, 'w') as project_json:
with open(file_name, "w") as project_json:
project_json.write(json.dumps(content, indent=2))
project_json.close()
@@ -27,17 +26,17 @@ class TemplateBuilder:
WorkspaceSettings.__name__: {
WorkspaceSettingsNameEnum.default_project.value: project_name,
WorkspaceSettingsNameEnum.projects.value: projects,
WorkspaceSettingsNameEnum.scripts.value: scripts
WorkspaceSettingsNameEnum.scripts.value: scripts,
}
}
Console.spinner(
f'Creating {path}',
f"Creating {path}",
cls.build_cpl_file,
path,
ws_dict,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
spinner_foreground_color=ForegroundColorEnum.cyan,
)
@staticmethod
@@ -51,6 +50,6 @@ class TemplateBuilder:
if not os.path.isdir(os.path.dirname(file_path)):
os.makedirs(os.path.dirname(file_path))
with open(file_path, 'w') as file:
with open(file_path, "w") as file:
file.write(template.value)
file.close()

View File

@@ -32,26 +32,31 @@ from cpl_core.environment.application_environment_abc import ApplicationEnvironm
class Startup(StartupABC):
def __init__(self):
StartupABC.__init__(self)
def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironmentABC) -> ConfigurationABC:
def configure_configuration(
self, configuration: ConfigurationABC, environment: ApplicationEnvironmentABC
) -> ConfigurationABC:
environment.set_runtime_directory(os.path.dirname(__file__))
configuration.argument_error_function = Error.error
configuration.add_environment_variables('PYTHON_')
configuration.add_environment_variables('CPL_')
configuration.add_environment_variables("PYTHON_")
configuration.add_environment_variables("CPL_")
is_unittest = configuration.get_configuration('IS_UNITTEST')
if is_unittest == 'YES':
is_unittest = configuration.get_configuration("IS_UNITTEST")
if is_unittest == "YES":
Console.disable()
configuration.add_json_file('appsettings.json', path=environment.runtime_directory, optional=False, output=False)
configuration.add_json_file(
"appsettings.json", path=environment.runtime_directory, optional=False, output=False
)
return configuration
def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironmentABC) -> ServiceProviderABC:
def configure_services(
self, services: ServiceCollectionABC, environment: ApplicationEnvironmentABC
) -> ServiceProviderABC:
services.add_transient(PublisherABC, PublisherService)
services.add_transient(LiveServerService)

View File

@@ -21,50 +21,83 @@ from cpl_core.environment.application_environment_abc import ApplicationEnvironm
class StartupArgumentExtension(StartupExtensionABC):
def __init__(self):
pass
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'add', ['a', 'A'], AddService, True, validators=[WorkspaceValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'build', ['b', 'B'], BuildService, True, validators=[ProjectValidator])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'generate', ['g', 'G'], GenerateService, True)
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'install', ['i', 'I'], InstallService, True, validators=[ProjectValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'cpl-prod', ['cp', 'CP']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'cpl-exp', ['ce', 'CE']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'cpl-dev', ['cd', 'CD'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'new', ['n', 'N'], NewService, True) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'async', ['a', 'A']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'application-base', ['ab', 'AB']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'startup', ['s', 'S']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'service-providing', ['sp', 'SP']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'nothing', ['n', 'N']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'venv', ['v', 'V']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'base', ['b', 'B'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'publish', ['p', 'P'], PublishService, True, validators=[ProjectValidator])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'remove', ['r', 'R'], RemoveService, True, validators=[WorkspaceValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'run', [], RunService, True, validators=[ProjectValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'start', ['s', 'S'], StartService, True, validators=[ProjectValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'uninstall', ['ui', 'UI'], UninstallService, True, validators=[ProjectValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'update', ['u', 'U'], UpdateService, True, validators=[ProjectValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'cpl-prod', ['cp', 'CP']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'cpl-exp', ['ce', 'CE']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'cpl-dev', ['cd', 'CD'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'version', ['v', 'V'], VersionService, True)
config.create_console_argument(
ArgumentTypeEnum.Executable, "", "add", ["a", "A"], AddService, True, validators=[WorkspaceValidator]
).add_console_argument(ArgumentTypeEnum.Flag, "--", "simulate", ["s", "S"])
config.create_console_argument(
ArgumentTypeEnum.Executable, "", "build", ["b", "B"], BuildService, True, validators=[ProjectValidator]
)
config.create_console_argument(ArgumentTypeEnum.Executable, "", "generate", ["g", "G"], GenerateService, True)
config.create_console_argument(
ArgumentTypeEnum.Executable, "", "install", ["i", "I"], InstallService, True, validators=[ProjectValidator]
).add_console_argument(ArgumentTypeEnum.Flag, "--", "dev", ["d", "D"]).add_console_argument(
ArgumentTypeEnum.Flag, "--", "virtual", ["v", "V"]
).add_console_argument(
ArgumentTypeEnum.Flag, "--", "simulate", ["s", "S"]
).add_console_argument(
ArgumentTypeEnum.Flag, "--", "cpl-prod", ["cp", "CP"]
).add_console_argument(
ArgumentTypeEnum.Flag, "--", "cpl-exp", ["ce", "CE"]
).add_console_argument(
ArgumentTypeEnum.Flag, "--", "cpl-dev", ["cd", "CD"]
)
config.create_console_argument(
ArgumentTypeEnum.Executable, "", "new", ["n", "N"], NewService, True
).add_console_argument(ArgumentTypeEnum.Flag, "--", "async", ["a", "A"]).add_console_argument(
ArgumentTypeEnum.Flag, "--", "application-base", ["ab", "AB"]
).add_console_argument(
ArgumentTypeEnum.Flag, "--", "startup", ["s", "S"]
).add_console_argument(
ArgumentTypeEnum.Flag, "--", "service-providing", ["sp", "SP"]
).add_console_argument(
ArgumentTypeEnum.Flag, "--", "nothing", ["n", "N"]
).add_console_argument(
ArgumentTypeEnum.Flag, "--", "venv", ["v", "V"]
).add_console_argument(
ArgumentTypeEnum.Flag, "--", "base", ["b", "B"]
)
config.create_console_argument(
ArgumentTypeEnum.Executable, "", "publish", ["p", "P"], PublishService, True, validators=[ProjectValidator]
)
config.create_console_argument(
ArgumentTypeEnum.Executable, "", "remove", ["r", "R"], RemoveService, True, validators=[WorkspaceValidator]
).add_console_argument(ArgumentTypeEnum.Flag, "--", "simulate", ["s", "S"])
config.create_console_argument(
ArgumentTypeEnum.Executable, "", "run", [], RunService, True, validators=[ProjectValidator]
).add_console_argument(ArgumentTypeEnum.Flag, "--", "dev", ["d", "D"])
config.create_console_argument(
ArgumentTypeEnum.Executable, "", "start", ["s", "S"], StartService, True, validators=[ProjectValidator]
).add_console_argument(ArgumentTypeEnum.Flag, "--", "dev", ["d", "D"])
config.create_console_argument(
ArgumentTypeEnum.Executable,
"",
"uninstall",
["ui", "UI"],
UninstallService,
True,
validators=[ProjectValidator],
).add_console_argument(ArgumentTypeEnum.Flag, "--", "dev", ["d", "D"]).add_console_argument(
ArgumentTypeEnum.Flag, "--", "virtual", ["v", "V"]
).add_console_argument(
ArgumentTypeEnum.Flag, "--", "simulate", ["s", "S"]
)
config.create_console_argument(
ArgumentTypeEnum.Executable, "", "update", ["u", "U"], UpdateService, True, validators=[ProjectValidator]
).add_console_argument(ArgumentTypeEnum.Flag, "--", "simulate", ["s", "S"]).add_console_argument(
ArgumentTypeEnum.Flag, "--", "cpl-prod", ["cp", "CP"]
).add_console_argument(
ArgumentTypeEnum.Flag, "--", "cpl-exp", ["ce", "CE"]
).add_console_argument(
ArgumentTypeEnum.Flag, "--", "cpl-dev", ["cd", "CD"]
)
config.create_console_argument(ArgumentTypeEnum.Executable, "", "version", ["v", "V"], VersionService, True)
config.for_each_argument(lambda a: a.add_console_argument(ArgumentTypeEnum.Flag, '--', 'help', ['h', 'H']))
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'help', ['h', 'H'], HelpService)
config.for_each_argument(lambda a: a.add_console_argument(ArgumentTypeEnum.Flag, "--", "help", ["h", "H"]))
config.create_console_argument(ArgumentTypeEnum.Executable, "", "help", ["h", "H"], HelpService)
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
pass

View File

@@ -9,7 +9,6 @@ from cpl_core.environment.application_environment_abc import ApplicationEnvironm
class StartupMigrationExtension(StartupExtensionABC):
def __init__(self):
pass

View File

@@ -12,7 +12,6 @@ from cpl_core.utils.string import String
class StartupWorkspaceExtension(StartupExtensionABC):
def __init__(self):
pass
@@ -22,9 +21,12 @@ class StartupWorkspaceExtension(StartupExtensionABC):
name = os.path.basename(working_directory)
for r, d, f in os.walk(working_directory):
for file in f:
if file.endswith('.json'):
f_name = file.split('.json')[0]
if f_name == name or String.convert_to_camel_case(f_name).lower() == String.convert_to_camel_case(name).lower():
if file.endswith(".json"):
f_name = file.split(".json")[0]
if (
f_name == name
or String.convert_to_camel_case(f_name).lower() == String.convert_to_camel_case(name).lower()
):
project_name = f_name
break
@@ -32,15 +34,15 @@ class StartupWorkspaceExtension(StartupExtensionABC):
def _read_cpl_environment(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
workspace: Optional[WorkspaceSettings] = config.get_configuration(WorkspaceSettings)
config.add_configuration('PATH_WORKSPACE', env.working_directory)
config.add_configuration("PATH_WORKSPACE", env.working_directory)
if workspace is not None:
for script in workspace.scripts:
config.create_console_argument(ArgumentTypeEnum.Executable, '', script, [], CustomScriptService)
config.create_console_argument(ArgumentTypeEnum.Executable, "", script, [], CustomScriptService)
return
project = self._search_project_json(env.working_directory)
if project is not None:
project = f'{project}.json'
project = f"{project}.json"
if project is None:
return
@@ -48,7 +50,7 @@ class StartupWorkspaceExtension(StartupExtensionABC):
config.add_json_file(project, optional=True, output=False)
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
config.add_json_file('cpl-workspace.json', path=env.working_directory, optional=True, output=False)
config.add_json_file("cpl-workspace.json", path=env.working_directory, optional=True, output=False)
self._read_cpl_environment(config, env)
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):

View File

@@ -1,26 +1,26 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
cpl-cli CPL CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
CPL Command Line Interface
:copyright: (c) 2020 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli.validators'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2023 sh-edraft.de'
__version__ = '2022.12.1'
__title__ = "cpl_cli.validators"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2023 sh-edraft.de"
__version__ = "2023.2.0"
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='12', micro='1')
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2023", minor="2", micro="0")

View File

@@ -8,8 +8,13 @@ from cpl_core.environment import ApplicationEnvironmentABC
class ProjectValidator(ValidatorABC):
def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC, workspace: WorkspaceSettings, project: ProjectSettings):
def __init__(
self,
config: ConfigurationABC,
env: ApplicationEnvironmentABC,
workspace: WorkspaceSettings,
project: ProjectSettings,
):
self._config: ConfigurationABC = config
self._env: ApplicationEnvironmentABC = env
self._workspace: WorkspaceSettings = workspace
@@ -26,5 +31,5 @@ class ProjectValidator(ValidatorABC):
result = self._project is not None or self._workspace is not None
if not result:
Error.error('The command requires to be run in an CPL project, but a project could not be found.')
Error.error("The command requires to be run in an CPL project, but a project could not be found.")
return result

View File

@@ -4,7 +4,6 @@ from cpl_core.configuration.validator_abc import ValidatorABC
class WorkspaceValidator(ValidatorABC):
def __init__(self, workspace: WorkspaceSettings):
self._workspace = workspace
@@ -13,5 +12,5 @@ class WorkspaceValidator(ValidatorABC):
def validate(self) -> bool:
result = self._workspace is not None
if not result:
Error.error('The command requires to be run in an CPL workspace, but a workspace could not be found.')
Error.error("The command requires to be run in an CPL workspace, but a workspace could not be found.")
return result