[WIP] Improved cpl new templating #139
This commit is contained in:
parent
6b8491eea2
commit
5f10603fe5
42
src/cpl_cli/.cpl/project_console.py
Normal file
42
src/cpl_cli/.cpl/project_console.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from cpl_cli.abc.project_type_abc import ProjectTypeABC
|
||||||
|
from cpl_cli.configuration import WorkspaceSettings
|
||||||
|
from cpl_core.utils import String
|
||||||
|
|
||||||
|
|
||||||
|
class Console(ProjectTypeABC):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
base_path: str,
|
||||||
|
project_name: str,
|
||||||
|
workspace: WorkspaceSettings,
|
||||||
|
use_application_api: bool,
|
||||||
|
use_startup: bool,
|
||||||
|
use_service_providing: bool,
|
||||||
|
use_async: bool,
|
||||||
|
):
|
||||||
|
from project_file_license import ProjectFileLicense
|
||||||
|
from project_file_readme import ProjectFileReadme
|
||||||
|
from schematic_init import Init
|
||||||
|
from project_file_code_application import ProjectFileApplication
|
||||||
|
from project_file_code_main import ProjectFileMain
|
||||||
|
from project_file_code_startup import ProjectFileStartup
|
||||||
|
|
||||||
|
ProjectTypeABC.__init__(self, base_path, project_name, workspace, use_application_api, use_startup, use_service_providing, use_async)
|
||||||
|
|
||||||
|
project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/'
|
||||||
|
|
||||||
|
self.add_template(ProjectFileLicense(''))
|
||||||
|
self.add_template(ProjectFileReadme(''))
|
||||||
|
self.add_template(Init('', 'init', f'{base_path}tests/'))
|
||||||
|
self.add_template(Init('', 'init', project_path))
|
||||||
|
|
||||||
|
if use_application_api:
|
||||||
|
self.add_template(ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async))
|
||||||
|
|
||||||
|
if use_startup:
|
||||||
|
self.add_template(ProjectFileStartup(project_path, use_application_api, use_startup, use_service_providing, use_async))
|
||||||
|
|
||||||
|
self.add_template(ProjectFileMain(project_path, use_application_api, use_startup, use_service_providing, use_async))
|
29
src/cpl_cli/.cpl/project_file_appsettings.py
Normal file
29
src/cpl_cli/.cpl/project_file_appsettings.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import textwrap
|
||||||
|
|
||||||
|
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectFileAppsettings(FileTemplateABC):
|
||||||
|
|
||||||
|
def __init__(self, path: str):
|
||||||
|
code = textwrap.dedent("""\
|
||||||
|
{
|
||||||
|
"TimeFormatSettings": {
|
||||||
|
"DateFormat": "%Y-%m-%d",
|
||||||
|
"TimeFormat": "%H:%M:%S",
|
||||||
|
"DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
|
||||||
|
"DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
|
||||||
|
},
|
||||||
|
|
||||||
|
"LoggingSettings": {
|
||||||
|
"Path": "logs/",
|
||||||
|
"Filename": "log_$start_time.log",
|
||||||
|
"ConsoleLogLevel": "ERROR",
|
||||||
|
"FileLogLevel": "WARN"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
FileTemplateABC.__init__(self, 'appsettings.json', path, code)
|
||||||
|
|
||||||
|
def get_code(self) -> str:
|
||||||
|
return self._code
|
49
src/cpl_cli/.cpl/project_file_code_application.py
Normal file
49
src/cpl_cli/.cpl/project_file_code_application.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectFileApplication(CodeFileTemplateABC):
|
||||||
|
|
||||||
|
def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool):
|
||||||
|
CodeFileTemplateABC.__init__(self, 'application', path, '', use_application_api, use_startup, use_service_providing, use_async)
|
||||||
|
|
||||||
|
def get_code(self) -> str:
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
if self._use_async:
|
||||||
|
return textwrap.dedent("""\
|
||||||
|
from cpl_core.application import ApplicationABC
|
||||||
|
from cpl_core.configuration import ConfigurationABC
|
||||||
|
from cpl_core.console import Console
|
||||||
|
from cpl_core.dependency_injection import ServiceProviderABC
|
||||||
|
|
||||||
|
|
||||||
|
class Application(ApplicationABC):
|
||||||
|
|
||||||
|
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||||
|
ApplicationABC.__init__(self, config, services)
|
||||||
|
|
||||||
|
async def configure(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def main(self):
|
||||||
|
Console.write_line('Hello World')
|
||||||
|
""")
|
||||||
|
|
||||||
|
return textwrap.dedent("""\
|
||||||
|
from cpl_core.application import ApplicationABC
|
||||||
|
from cpl_core.configuration import ConfigurationABC
|
||||||
|
from cpl_core.console import Console
|
||||||
|
from cpl_core.dependency_injection import ServiceProviderABC
|
||||||
|
|
||||||
|
|
||||||
|
class Application(ApplicationABC):
|
||||||
|
|
||||||
|
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||||
|
ApplicationABC.__init__(self, config, services)
|
||||||
|
|
||||||
|
def configure(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def main(self):
|
||||||
|
Console.write_line('Hello World')
|
||||||
|
""")
|
93
src/cpl_cli/.cpl/project_file_code_main.py
Normal file
93
src/cpl_cli/.cpl/project_file_code_main.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectFileMain(CodeFileTemplateABC):
|
||||||
|
|
||||||
|
def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool):
|
||||||
|
CodeFileTemplateABC.__init__(self, 'main', path, '', use_application_api, use_startup, use_service_providing, use_async)
|
||||||
|
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
import_pkg = f'{self._name}.'
|
||||||
|
|
||||||
|
self._main_with_application_host_and_startup = textwrap.dedent(f"""\
|
||||||
|
{"import asyncio" if self._use_async else ''}
|
||||||
|
|
||||||
|
from cpl_core.application import ApplicationBuilder
|
||||||
|
|
||||||
|
from {import_pkg}application import Application
|
||||||
|
from {import_pkg}startup import Startup
|
||||||
|
|
||||||
|
|
||||||
|
{self._async()}def main():
|
||||||
|
app_builder = ApplicationBuilder(Application)
|
||||||
|
app_builder.use_startup(Startup)
|
||||||
|
{"app: Application = await app_builder.build_async()" if self._use_async else ""}
|
||||||
|
{"await app.run_async()" if self._use_async else "app_builder.build().run()"}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
{"asyncio.run(main())" if self._use_async else "main()"}
|
||||||
|
""")
|
||||||
|
self._main_with_application_base = textwrap.dedent(f"""\
|
||||||
|
{"import asyncio" if self._use_async else ''}
|
||||||
|
|
||||||
|
from cpl_core.application import ApplicationBuilder
|
||||||
|
|
||||||
|
from {import_pkg}application import Application
|
||||||
|
|
||||||
|
|
||||||
|
{self._async()}def main():
|
||||||
|
app_builder = ApplicationBuilder(Application)
|
||||||
|
{"app: Application = await app_builder.build_async()" if self._use_async else ""}
|
||||||
|
{"await app.run_async()" if self._use_async else "app_builder.build().run()"}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
{"asyncio.run(main())" if self._use_async else "main()"}
|
||||||
|
""")
|
||||||
|
|
||||||
|
self._main_with_dependency_injection = textwrap.dedent(f"""\
|
||||||
|
{"import asyncio" if self._use_async else ''}
|
||||||
|
|
||||||
|
from cpl_core.application import ApplicationBuilder
|
||||||
|
|
||||||
|
from {import_pkg}application import Application
|
||||||
|
|
||||||
|
|
||||||
|
{self._async()}def configure_configuration() -> ConfigurationABC:
|
||||||
|
config = Configuration()
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
{self._async()}def configure_services(config: ConfigurationABC) -> ServiceProviderABC:
|
||||||
|
services = ServiceCollection(config)
|
||||||
|
return services.build_service_provider()
|
||||||
|
|
||||||
|
|
||||||
|
{self._async()}def main():
|
||||||
|
config = {self._async()}configure_configuration()
|
||||||
|
provider = {self._async()}configure_services(config)
|
||||||
|
Console.write_line('Hello World')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
{"asyncio.run(main())" if self._use_async else "main()"}
|
||||||
|
""")
|
||||||
|
|
||||||
|
def _async(self) -> str:
|
||||||
|
if self._use_async:
|
||||||
|
return 'async '
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def get_code(self) -> str:
|
||||||
|
if self._use_application_api and self._use_startup:
|
||||||
|
return self._main_with_application_host_and_startup
|
||||||
|
|
||||||
|
if self._use_application_api:
|
||||||
|
return self._main_with_application_base
|
||||||
|
|
||||||
|
if self._use_service_providing:
|
||||||
|
return self._main_with_dependency_injection
|
||||||
|
|
||||||
|
return self._main_with_application_base
|
29
src/cpl_cli/.cpl/project_file_code_startup.py
Normal file
29
src/cpl_cli/.cpl/project_file_code_startup.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectFileStartup(CodeFileTemplateABC):
|
||||||
|
|
||||||
|
def __init__(self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool):
|
||||||
|
CodeFileTemplateABC.__init__(self, 'startup', path, '', use_application_api, use_startup, use_service_providing, use_async)
|
||||||
|
|
||||||
|
def get_code(self) -> str:
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
return textwrap.dedent("""\
|
||||||
|
from cpl_core.application import StartupABC
|
||||||
|
from cpl_core.configuration import ConfigurationABC
|
||||||
|
from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC
|
||||||
|
from cpl_core.environment import ApplicationEnvironment
|
||||||
|
|
||||||
|
|
||||||
|
class Startup(StartupABC):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
StartupABC.__init__(self)
|
||||||
|
|
||||||
|
def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC:
|
||||||
|
return configuration
|
||||||
|
|
||||||
|
def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC:
|
||||||
|
return services.build_service_provider()
|
||||||
|
""")
|
11
src/cpl_cli/.cpl/project_file_license.py
Normal file
11
src/cpl_cli/.cpl/project_file_license.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectFileLicense(FileTemplateABC):
|
||||||
|
|
||||||
|
def __init__(self, path: str):
|
||||||
|
FileTemplateABC.__init__(self, '', path, '')
|
||||||
|
self._name = 'LICENSE'
|
||||||
|
|
||||||
|
def get_code(self) -> str:
|
||||||
|
return self._code
|
11
src/cpl_cli/.cpl/project_file_readme.py
Normal file
11
src/cpl_cli/.cpl/project_file_readme.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectFileReadme(FileTemplateABC):
|
||||||
|
|
||||||
|
def __init__(self, path: str):
|
||||||
|
FileTemplateABC.__init__(self, '', path, '')
|
||||||
|
self._name = 'README.md'
|
||||||
|
|
||||||
|
def get_code(self) -> str:
|
||||||
|
return self._code
|
24
src/cpl_cli/abc/code_file_template_abc.py
Normal file
24
src/cpl_cli/abc/code_file_template_abc.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
||||||
|
from cpl_core.utils import String
|
||||||
|
|
||||||
|
|
||||||
|
class CodeFileTemplateABC(FileTemplateABC):
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: str,
|
||||||
|
path: str,
|
||||||
|
code: str,
|
||||||
|
use_application_api: bool,
|
||||||
|
use_startup: bool,
|
||||||
|
use_service_providing: bool,
|
||||||
|
use_async: bool,
|
||||||
|
):
|
||||||
|
FileTemplateABC.__init__(self, name, path, code)
|
||||||
|
self._use_application_api = use_application_api
|
||||||
|
self._use_startup = use_startup
|
||||||
|
self._use_service_providing = use_service_providing
|
||||||
|
self._use_async = use_async
|
@ -11,6 +11,9 @@ class FileTemplateABC(ABC):
|
|||||||
self._path = path
|
self._path = path
|
||||||
self._code = code
|
self._code = code
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'<{type(self).__name__} {self._path}{self._name}>'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
return self._name
|
return self._name
|
||||||
@ -19,10 +22,13 @@ class FileTemplateABC(ABC):
|
|||||||
def path(self) -> str:
|
def path(self) -> str:
|
||||||
return self._path
|
return self._path
|
||||||
|
|
||||||
|
@path.setter
|
||||||
|
def path(self, value: str):
|
||||||
|
self._path = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> str:
|
def value(self) -> str:
|
||||||
return self.get_code()
|
return self.get_code()
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_code(self) -> str:
|
def get_code(self) -> str: pass
|
||||||
return self._code
|
|
||||||
|
@ -15,7 +15,10 @@ class GenerateSchematicABC(FileTemplateABC):
|
|||||||
if schematic in name.lower():
|
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 = f'{String.first_to_upper(name)}{String.first_to_upper(schematic)}'
|
self._class_name = name
|
||||||
|
if name != '':
|
||||||
|
self._class_name = f'{String.first_to_upper(name)}{String.first_to_upper(schematic)}'
|
||||||
|
|
||||||
if schematic in name.lower():
|
if schematic in name.lower():
|
||||||
self._class_name = f'{String.first_to_upper(name)}'
|
self._class_name = f'{String.first_to_upper(name)}'
|
||||||
|
|
||||||
@ -24,7 +27,8 @@ class GenerateSchematicABC(FileTemplateABC):
|
|||||||
return self._class_name
|
return self._class_name
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_code(self) -> str: pass
|
def get_code(self) -> str:
|
||||||
|
pass
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def build_code_str(cls, code: str, **kwargs) -> str:
|
def build_code_str(cls, code: str, **kwargs) -> str:
|
||||||
|
35
src/cpl_cli/abc/project_type_abc.py
Normal file
35
src/cpl_cli/abc/project_type_abc.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
||||||
|
from cpl_cli.configuration import WorkspaceSettings
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTypeABC(ABC):
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
base_path: str,
|
||||||
|
project_name: str,
|
||||||
|
workspace: Optional[WorkspaceSettings],
|
||||||
|
use_application_api: bool,
|
||||||
|
use_startup: bool,
|
||||||
|
use_service_providing: bool,
|
||||||
|
use_async: bool,
|
||||||
|
):
|
||||||
|
self._templates: list[FileTemplateABC] = []
|
||||||
|
self._base_path = base_path
|
||||||
|
self._project_name = project_name
|
||||||
|
self._workspace = workspace
|
||||||
|
self._use_application_api = use_application_api
|
||||||
|
self._use_startup = use_startup
|
||||||
|
self._use_service_providing = use_service_providing
|
||||||
|
self._use_async = use_async
|
||||||
|
|
||||||
|
@property
|
||||||
|
def templates(self) -> list[FileTemplateABC]:
|
||||||
|
return self._templates
|
||||||
|
|
||||||
|
def add_template(self, t: FileTemplateABC):
|
||||||
|
self._templates.append(t)
|
@ -144,7 +144,7 @@ class GenerateService(CommandABC):
|
|||||||
|
|
||||||
for r, d, f in os.walk(os.path.join(path, '.cpl')):
|
for r, d, f in os.walk(os.path.join(path, '.cpl')):
|
||||||
for file in f:
|
for file in f:
|
||||||
if not file.endswith('_schematic.py'):
|
if not file.startswith('schematic_') and not file.endswith('.py'):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
code = ''
|
code = ''
|
||||||
|
356
src/cpl_cli/command/new_old_service.py
Normal file
356
src/cpl_cli/command/new_old_service.py
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import textwrap
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from packaging import version
|
||||||
|
|
||||||
|
import cpl_cli
|
||||||
|
import cpl_core
|
||||||
|
from cpl_cli.configuration.venv_helper_service import VenvHelper
|
||||||
|
from cpl_cli.source_creator.unittest_builder import UnittestBuilder
|
||||||
|
|
||||||
|
from cpl_core.configuration.configuration_abc import ConfigurationABC
|
||||||
|
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
|
||||||
|
from cpl_core.console.console import Console
|
||||||
|
from cpl_core.utils.string import String
|
||||||
|
from cpl_cli.command_abc import CommandABC
|
||||||
|
from cpl_cli.configuration.build_settings import BuildSettings
|
||||||
|
from cpl_cli.configuration.build_settings_name_enum import BuildSettingsNameEnum
|
||||||
|
from cpl_cli.configuration.project_settings import ProjectSettings
|
||||||
|
from cpl_cli.configuration.project_settings_name_enum import ProjectSettingsNameEnum
|
||||||
|
from cpl_cli.configuration.project_type_enum import ProjectTypeEnum
|
||||||
|
from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum
|
||||||
|
from cpl_cli.configuration.workspace_settings import WorkspaceSettings
|
||||||
|
from cpl_cli.source_creator.console_builder import ConsoleBuilder
|
||||||
|
from cpl_cli.source_creator.library_builder import LibraryBuilder
|
||||||
|
|
||||||
|
|
||||||
|
class NewService(CommandABC):
|
||||||
|
|
||||||
|
def __init__(self, configuration: ConfigurationABC):
|
||||||
|
"""
|
||||||
|
Service for the CLI command new
|
||||||
|
:param configuration:
|
||||||
|
"""
|
||||||
|
CommandABC.__init__(self)
|
||||||
|
|
||||||
|
self._config = configuration
|
||||||
|
self._env = self._config.environment
|
||||||
|
|
||||||
|
self._workspace: WorkspaceSettings = self._config.get_configuration(WorkspaceSettings)
|
||||||
|
self._project: ProjectSettings = ProjectSettings()
|
||||||
|
self._project_dict = {}
|
||||||
|
self._build: BuildSettings = BuildSettings()
|
||||||
|
self._build_dict = {}
|
||||||
|
self._project_json = {}
|
||||||
|
|
||||||
|
self._name: str = ''
|
||||||
|
self._rel_path: str = ''
|
||||||
|
self._schematic: ProjectTypeEnum = ProjectTypeEnum.console
|
||||||
|
self._use_nothing: bool = False
|
||||||
|
self._use_application_api: bool = False
|
||||||
|
self._use_startup: bool = False
|
||||||
|
self._use_service_providing: bool = False
|
||||||
|
self._use_async: bool = False
|
||||||
|
self._use_venv: bool = False
|
||||||
|
self._use_base: bool = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def help_message(self) -> str:
|
||||||
|
return textwrap.dedent("""\
|
||||||
|
Generates a workspace and initial project or add a project to workspace.
|
||||||
|
Usage: cpl new <type> <name>
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
type The project type of the initial project
|
||||||
|
name Name of the workspace or the project
|
||||||
|
|
||||||
|
Types:
|
||||||
|
console (c|C)
|
||||||
|
library (l|L)
|
||||||
|
unittest (ut|UT)
|
||||||
|
""")
|
||||||
|
|
||||||
|
def _create_project_settings(self):
|
||||||
|
self._rel_path = os.path.dirname(self._name)
|
||||||
|
self._project_dict = {
|
||||||
|
ProjectSettingsNameEnum.name.value: os.path.basename(self._name),
|
||||||
|
ProjectSettingsNameEnum.version.value: {
|
||||||
|
VersionSettingsNameEnum.major.value: '0',
|
||||||
|
VersionSettingsNameEnum.minor.value: '0',
|
||||||
|
VersionSettingsNameEnum.micro.value: '0'
|
||||||
|
},
|
||||||
|
ProjectSettingsNameEnum.author.value: '',
|
||||||
|
ProjectSettingsNameEnum.author_email.value: '',
|
||||||
|
ProjectSettingsNameEnum.description.value: '',
|
||||||
|
ProjectSettingsNameEnum.long_description.value: '',
|
||||||
|
ProjectSettingsNameEnum.url.value: '',
|
||||||
|
ProjectSettingsNameEnum.copyright_date.value: '',
|
||||||
|
ProjectSettingsNameEnum.copyright_name.value: '',
|
||||||
|
ProjectSettingsNameEnum.license_name.value: '',
|
||||||
|
ProjectSettingsNameEnum.license_description.value: '',
|
||||||
|
ProjectSettingsNameEnum.dependencies.value: [
|
||||||
|
f'cpl-core>={version.parse(cpl_core.__version__)}'
|
||||||
|
],
|
||||||
|
ProjectSettingsNameEnum.dev_dependencies.value: [
|
||||||
|
f'cpl-cli>={version.parse(cpl_cli.__version__)}'
|
||||||
|
],
|
||||||
|
ProjectSettingsNameEnum.python_version.value: f'>={sys.version.split(" ")[0]}',
|
||||||
|
ProjectSettingsNameEnum.python_path.value: {
|
||||||
|
sys.platform: '../../venv/bin/python' if self._use_venv else ''
|
||||||
|
},
|
||||||
|
ProjectSettingsNameEnum.classifiers.value: []
|
||||||
|
}
|
||||||
|
|
||||||
|
self._project.from_dict(self._project_dict)
|
||||||
|
|
||||||
|
def _create_build_settings(self):
|
||||||
|
self._build_dict = {
|
||||||
|
BuildSettingsNameEnum.project_type.value: self._schematic,
|
||||||
|
BuildSettingsNameEnum.source_path.value: '',
|
||||||
|
BuildSettingsNameEnum.output_path.value: '../../dist',
|
||||||
|
BuildSettingsNameEnum.main.value: f'{String.convert_to_snake_case(self._project.name)}.main',
|
||||||
|
BuildSettingsNameEnum.entry_point.value: self._project.name,
|
||||||
|
BuildSettingsNameEnum.include_package_data.value: False,
|
||||||
|
BuildSettingsNameEnum.included.value: [],
|
||||||
|
BuildSettingsNameEnum.excluded.value: [
|
||||||
|
'*/__pycache__',
|
||||||
|
'*/logs',
|
||||||
|
'*/tests'
|
||||||
|
],
|
||||||
|
BuildSettingsNameEnum.package_data.value: {},
|
||||||
|
BuildSettingsNameEnum.project_references.value: []
|
||||||
|
}
|
||||||
|
self._build.from_dict(self._build_dict)
|
||||||
|
|
||||||
|
def _create_project_json(self):
|
||||||
|
"""
|
||||||
|
Creates cpl.json content
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
self._project_json = {
|
||||||
|
ProjectSettings.__name__: self._project_dict,
|
||||||
|
BuildSettings.__name__: self._build_dict
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get_project_path(self) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
Gets project path
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if self._workspace is None:
|
||||||
|
project_path = os.path.join(self._env.working_directory, self._rel_path, self._project.name)
|
||||||
|
else:
|
||||||
|
base = '' if self._use_base else 'src'
|
||||||
|
project_path = os.path.join(self._env.working_directory, base, self._rel_path, String.convert_to_snake_case(self._project.name))
|
||||||
|
|
||||||
|
if os.path.isdir(project_path) and len(os.listdir(project_path)) > 0:
|
||||||
|
Console.write_line(project_path)
|
||||||
|
Console.error('Project path is not empty\n')
|
||||||
|
return None
|
||||||
|
|
||||||
|
return project_path
|
||||||
|
|
||||||
|
def _get_project_information(self, is_unittest=False):
|
||||||
|
"""
|
||||||
|
Gets project information's from user
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if self._use_application_api or self._use_startup or self._use_service_providing or self._use_async or self._use_nothing:
|
||||||
|
Console.set_foreground_color(ForegroundColorEnum.default)
|
||||||
|
Console.write_line('Skipping question due to given flags')
|
||||||
|
return
|
||||||
|
|
||||||
|
if not is_unittest:
|
||||||
|
self._use_application_api = Console.read('Do you want to use application base? (y/n) ').lower() == 'y'
|
||||||
|
|
||||||
|
if not is_unittest and self._use_application_api:
|
||||||
|
self._use_startup = Console.read('Do you want to use startup? (y/n) ').lower() == 'y'
|
||||||
|
|
||||||
|
if not is_unittest and not self._use_application_api:
|
||||||
|
self._use_service_providing = Console.read('Do you want to use service providing? (y/n) ').lower() == 'y'
|
||||||
|
|
||||||
|
if not self._use_async:
|
||||||
|
self._use_async = Console.read('Do you want to use async? (y/n) ').lower() == 'y'
|
||||||
|
|
||||||
|
Console.set_foreground_color(ForegroundColorEnum.default)
|
||||||
|
|
||||||
|
def _console(self, args: list[str]):
|
||||||
|
"""
|
||||||
|
Generates new console project
|
||||||
|
:param args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
self._create_project_settings()
|
||||||
|
self._create_build_settings()
|
||||||
|
self._create_project_json()
|
||||||
|
path = self._get_project_path()
|
||||||
|
if path is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._get_project_information()
|
||||||
|
project_name = self._project.name
|
||||||
|
if self._rel_path != '':
|
||||||
|
project_name = f'{self._rel_path}/{project_name}'
|
||||||
|
try:
|
||||||
|
ConsoleBuilder.build(
|
||||||
|
path,
|
||||||
|
self._use_application_api,
|
||||||
|
self._use_startup,
|
||||||
|
self._use_service_providing,
|
||||||
|
self._use_async,
|
||||||
|
project_name,
|
||||||
|
self._project_json,
|
||||||
|
self._workspace
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
Console.error('Could not create project', str(e))
|
||||||
|
|
||||||
|
def _unittest(self, args: list[str]):
|
||||||
|
"""
|
||||||
|
Generates new unittest project
|
||||||
|
:param args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
self._create_project_settings()
|
||||||
|
self._create_build_settings()
|
||||||
|
self._create_project_json()
|
||||||
|
path = self._get_project_path()
|
||||||
|
if path is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._get_project_information(is_unittest=True)
|
||||||
|
project_name = self._project.name
|
||||||
|
if self._rel_path != '':
|
||||||
|
project_name = f'{self._rel_path}/{project_name}'
|
||||||
|
try:
|
||||||
|
UnittestBuilder.build(
|
||||||
|
path,
|
||||||
|
self._use_application_api,
|
||||||
|
self._use_async,
|
||||||
|
project_name,
|
||||||
|
self._project_json,
|
||||||
|
self._workspace
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
Console.error('Could not create project', str(e))
|
||||||
|
|
||||||
|
def _library(self, args: list[str]):
|
||||||
|
"""
|
||||||
|
Generates new library project
|
||||||
|
:param args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
self._create_project_settings()
|
||||||
|
self._create_build_settings()
|
||||||
|
self._create_project_json()
|
||||||
|
path = self._get_project_path()
|
||||||
|
if path is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._get_project_information()
|
||||||
|
project_name = self._project.name
|
||||||
|
if self._rel_path != '':
|
||||||
|
project_name = f'{self._rel_path}/{project_name}'
|
||||||
|
try:
|
||||||
|
LibraryBuilder.build(
|
||||||
|
path,
|
||||||
|
self._use_application_api,
|
||||||
|
self._use_startup,
|
||||||
|
self._use_service_providing,
|
||||||
|
self._use_async,
|
||||||
|
project_name,
|
||||||
|
self._project_json,
|
||||||
|
self._workspace
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
Console.error('Could not create project', str(e))
|
||||||
|
|
||||||
|
def _create_venv(self):
|
||||||
|
|
||||||
|
project = self._project.name
|
||||||
|
if self._workspace is not None:
|
||||||
|
project = self._workspace.default_project
|
||||||
|
|
||||||
|
if self._env.working_directory.endswith(project):
|
||||||
|
project = ''
|
||||||
|
|
||||||
|
if self._workspace is None and self._use_base:
|
||||||
|
project = f'{self._rel_path}/{project}'
|
||||||
|
|
||||||
|
VenvHelper.init_venv(
|
||||||
|
False,
|
||||||
|
self._env,
|
||||||
|
self._project,
|
||||||
|
explicit_path=os.path.join(self._env.working_directory, project, self._project.python_executable.replace('../', ''))
|
||||||
|
)
|
||||||
|
|
||||||
|
def execute(self, args: list[str]):
|
||||||
|
"""
|
||||||
|
Entry point of command
|
||||||
|
:param args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if 'nothing' in args:
|
||||||
|
self._use_nothing = True
|
||||||
|
self._use_async = False
|
||||||
|
self._use_application_api = False
|
||||||
|
self._use_startup = False
|
||||||
|
self._use_service_providing = False
|
||||||
|
if 'async' in args:
|
||||||
|
args.remove('async')
|
||||||
|
if 'application-base' in args:
|
||||||
|
args.remove('application-base')
|
||||||
|
if 'startup' in args:
|
||||||
|
args.remove('startup')
|
||||||
|
if 'service-providing' in args:
|
||||||
|
args.remove('service-providing')
|
||||||
|
|
||||||
|
if 'async' in args:
|
||||||
|
self._use_async = True
|
||||||
|
args.remove('async')
|
||||||
|
if 'application-base' in args:
|
||||||
|
self._use_application_api = True
|
||||||
|
args.remove('application-base')
|
||||||
|
if 'startup' in args:
|
||||||
|
self._use_startup = True
|
||||||
|
args.remove('startup')
|
||||||
|
if 'service-providing' in args:
|
||||||
|
self._use_service_providing = True
|
||||||
|
args.remove('service-providing')
|
||||||
|
if 'venv' in args:
|
||||||
|
self._use_venv = True
|
||||||
|
args.remove('venv')
|
||||||
|
if 'base' in args:
|
||||||
|
self._use_base = True
|
||||||
|
args.remove('base')
|
||||||
|
|
||||||
|
console = self._config.get_configuration(ProjectTypeEnum.console.value)
|
||||||
|
library = self._config.get_configuration(ProjectTypeEnum.library.value)
|
||||||
|
unittest = self._config.get_configuration(ProjectTypeEnum.unittest.value)
|
||||||
|
if console is not None and library is None and unittest is None:
|
||||||
|
self._name = console
|
||||||
|
self._schematic = ProjectTypeEnum.console.value
|
||||||
|
self._console(args)
|
||||||
|
if self._use_venv:
|
||||||
|
self._create_venv()
|
||||||
|
|
||||||
|
elif console is None and library is not None and unittest is None:
|
||||||
|
self._name = library
|
||||||
|
self._schematic = ProjectTypeEnum.library.value
|
||||||
|
self._library(args)
|
||||||
|
if self._use_venv:
|
||||||
|
self._create_venv()
|
||||||
|
|
||||||
|
elif console is None and library is None and unittest is not None:
|
||||||
|
self._name = unittest
|
||||||
|
self._schematic = ProjectTypeEnum.unittest.value
|
||||||
|
self._unittest(args)
|
||||||
|
if self._use_venv:
|
||||||
|
self._create_venv()
|
||||||
|
|
||||||
|
else:
|
||||||
|
Console.error(f'Project type not found')
|
||||||
|
Console.write_line(self.help_message)
|
||||||
|
return
|
@ -7,7 +7,9 @@ from packaging import version
|
|||||||
|
|
||||||
import cpl_cli
|
import cpl_cli
|
||||||
import cpl_core
|
import cpl_core
|
||||||
|
from cpl_cli.abc.project_type_abc import ProjectTypeABC
|
||||||
from cpl_cli.configuration.venv_helper_service import VenvHelper
|
from cpl_cli.configuration.venv_helper_service import VenvHelper
|
||||||
|
from cpl_cli.source_creator.template_builder import TemplateBuilder
|
||||||
from cpl_cli.source_creator.unittest_builder import UnittestBuilder
|
from cpl_cli.source_creator.unittest_builder import UnittestBuilder
|
||||||
|
|
||||||
from cpl_core.configuration.configuration_abc import ConfigurationABC
|
from cpl_core.configuration.configuration_abc import ConfigurationABC
|
||||||
@ -47,7 +49,7 @@ class NewService(CommandABC):
|
|||||||
|
|
||||||
self._name: str = ''
|
self._name: str = ''
|
||||||
self._rel_path: str = ''
|
self._rel_path: str = ''
|
||||||
self._schematic: ProjectTypeEnum = ProjectTypeEnum.console
|
self._project_type: ProjectTypeEnum = ProjectTypeEnum.console
|
||||||
self._use_nothing: bool = False
|
self._use_nothing: bool = False
|
||||||
self._use_application_api: bool = False
|
self._use_application_api: bool = False
|
||||||
self._use_startup: bool = False
|
self._use_startup: bool = False
|
||||||
@ -107,7 +109,7 @@ class NewService(CommandABC):
|
|||||||
|
|
||||||
def _create_build_settings(self):
|
def _create_build_settings(self):
|
||||||
self._build_dict = {
|
self._build_dict = {
|
||||||
BuildSettingsNameEnum.project_type.value: self._schematic,
|
BuildSettingsNameEnum.project_type.value: self._project_type,
|
||||||
BuildSettingsNameEnum.source_path.value: '',
|
BuildSettingsNameEnum.source_path.value: '',
|
||||||
BuildSettingsNameEnum.output_path.value: '../../dist',
|
BuildSettingsNameEnum.output_path.value: '../../dist',
|
||||||
BuildSettingsNameEnum.main.value: f'{String.convert_to_snake_case(self._project.name)}.main',
|
BuildSettingsNameEnum.main.value: f'{String.convert_to_snake_case(self._project.name)}.main',
|
||||||
@ -286,6 +288,85 @@ class NewService(CommandABC):
|
|||||||
explicit_path=os.path.join(self._env.working_directory, project, self._project.python_executable.replace('../', ''))
|
explicit_path=os.path.join(self._env.working_directory, project, self._project.python_executable.replace('../', ''))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _read_custom_project_types_from_path(path: str):
|
||||||
|
if not os.path.exists(os.path.join(path, '.cpl')):
|
||||||
|
return
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.join(path, '.cpl'))
|
||||||
|
for r, d, f in os.walk(os.path.join(path, '.cpl')):
|
||||||
|
for file in f:
|
||||||
|
if not file.startswith('project_') or not file.endswith('.py'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
code = ''
|
||||||
|
with open(os.path.join(r, file), 'r') as py_file:
|
||||||
|
code = py_file.read()
|
||||||
|
py_file.close()
|
||||||
|
|
||||||
|
exec(code)
|
||||||
|
|
||||||
|
def _create_project(self):
|
||||||
|
self._read_custom_project_types_from_path(self._env.runtime_directory)
|
||||||
|
self._read_custom_project_types_from_path(self._env.working_directory)
|
||||||
|
|
||||||
|
self._create_project_settings()
|
||||||
|
self._create_build_settings()
|
||||||
|
self._create_project_json()
|
||||||
|
path = self._get_project_path()
|
||||||
|
if path is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._get_project_information()
|
||||||
|
project_name = self._project.name
|
||||||
|
if self._rel_path != '':
|
||||||
|
project_name = f'{self._rel_path}/{project_name}'
|
||||||
|
|
||||||
|
project_type = None
|
||||||
|
for p in ProjectTypeABC.__subclasses__():
|
||||||
|
if p.__name__.lower() != self._project_type:
|
||||||
|
continue
|
||||||
|
|
||||||
|
project_type = p
|
||||||
|
|
||||||
|
base = 'src/'
|
||||||
|
split_project_name = project_name.split('/')
|
||||||
|
if self._use_base and len(split_project_name) > 0:
|
||||||
|
base = f'{split_project_name[0]}/'
|
||||||
|
|
||||||
|
project = project_type(
|
||||||
|
base if self._workspace is not None else 'src/',
|
||||||
|
project_name,
|
||||||
|
self._workspace,
|
||||||
|
self._use_application_api,
|
||||||
|
self._use_startup,
|
||||||
|
self._use_service_providing,
|
||||||
|
self._use_async,
|
||||||
|
)
|
||||||
|
|
||||||
|
if self._workspace is None:
|
||||||
|
TemplateBuilder.create_workspace(
|
||||||
|
f'{project_name}/cpl-workspace.json',
|
||||||
|
project_name.split('/')[-1],
|
||||||
|
{
|
||||||
|
project_name: project_name
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._workspace.projects[project_name] = f'{base}{String.convert_to_snake_case(project_name.split("/")[-1])}'
|
||||||
|
TemplateBuilder.create_workspace('cpl-workspace.json', self._workspace.default_project, self._workspace.projects, self._workspace.scripts)
|
||||||
|
|
||||||
|
for template in project.templates:
|
||||||
|
Console.spinner(
|
||||||
|
f'Creating {os.path.join(project_name, template.path, template.name)}',
|
||||||
|
TemplateBuilder.build,
|
||||||
|
project_name,
|
||||||
|
template,
|
||||||
|
text_foreground_color=ForegroundColorEnum.green,
|
||||||
|
spinner_foreground_color=ForegroundColorEnum.cyan
|
||||||
|
)
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
def execute(self, args: list[str]):
|
||||||
"""
|
"""
|
||||||
Entry point of command
|
Entry point of command
|
||||||
@ -331,21 +412,22 @@ class NewService(CommandABC):
|
|||||||
unittest = self._config.get_configuration(ProjectTypeEnum.unittest.value)
|
unittest = self._config.get_configuration(ProjectTypeEnum.unittest.value)
|
||||||
if console is not None and library is None and unittest is None:
|
if console is not None and library is None and unittest is None:
|
||||||
self._name = console
|
self._name = console
|
||||||
self._schematic = ProjectTypeEnum.console.value
|
self._project_type = ProjectTypeEnum.console.value
|
||||||
self._console(args)
|
self._create_project()
|
||||||
|
# self._console(args)
|
||||||
if self._use_venv:
|
if self._use_venv:
|
||||||
self._create_venv()
|
self._create_venv()
|
||||||
|
|
||||||
elif console is None and library is not None and unittest is None:
|
elif console is None and library is not None and unittest is None:
|
||||||
self._name = library
|
self._name = library
|
||||||
self._schematic = ProjectTypeEnum.library.value
|
self._project_type = ProjectTypeEnum.library.value
|
||||||
self._library(args)
|
self._library(args)
|
||||||
if self._use_venv:
|
if self._use_venv:
|
||||||
self._create_venv()
|
self._create_venv()
|
||||||
|
|
||||||
elif console is None and library is None and unittest is not None:
|
elif console is None and library is None and unittest is not None:
|
||||||
self._name = unittest
|
self._name = unittest
|
||||||
self._schematic = ProjectTypeEnum.unittest.value
|
self._project_type = ProjectTypeEnum.unittest.value
|
||||||
self._unittest(args)
|
self._unittest(args)
|
||||||
if self._use_venv:
|
if self._use_venv:
|
||||||
self._create_venv()
|
self._create_venv()
|
||||||
|
@ -1,12 +1,49 @@
|
|||||||
|
import json
|
||||||
import os
|
import os
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
from cpl_cli._templates.template_file_abc import TemplateFileABC
|
from cpl_cli._templates.template_file_abc import TemplateFileABC
|
||||||
|
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
||||||
|
from cpl_cli.configuration import WorkspaceSettings, WorkspaceSettingsNameEnum
|
||||||
|
from cpl_core.console import Console, ForegroundColorEnum
|
||||||
|
|
||||||
|
|
||||||
class TemplateBuilder:
|
class TemplateBuilder:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def build(project_path: str, template: TemplateFileABC):
|
def _create_file(file_name: str, content: dict):
|
||||||
|
if not os.path.isabs(file_name):
|
||||||
|
file_name = os.path.abspath(file_name)
|
||||||
|
|
||||||
|
path = os.path.dirname(file_name)
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
os.makedirs(path)
|
||||||
|
|
||||||
|
with open(file_name, 'w') as project_json:
|
||||||
|
project_json.write(json.dumps(content, indent=2))
|
||||||
|
project_json.close()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_workspace(cls, path: str, project_name, projects: dict, scripts: dict):
|
||||||
|
ws_dict = {
|
||||||
|
WorkspaceSettings.__name__: {
|
||||||
|
WorkspaceSettingsNameEnum.default_project.value: project_name,
|
||||||
|
WorkspaceSettingsNameEnum.projects.value: projects,
|
||||||
|
WorkspaceSettingsNameEnum.scripts.value: scripts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.spinner(
|
||||||
|
f'Creating {path}',
|
||||||
|
cls._create_file,
|
||||||
|
path,
|
||||||
|
ws_dict,
|
||||||
|
text_foreground_color=ForegroundColorEnum.green,
|
||||||
|
spinner_foreground_color=ForegroundColorEnum.cyan
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def build(project_path: str, template: Union[TemplateFileABC, FileTemplateABC]):
|
||||||
"""
|
"""
|
||||||
Creates template
|
Creates template
|
||||||
:param project_path:
|
:param project_path:
|
||||||
@ -14,10 +51,8 @@ class TemplateBuilder:
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
file_path = os.path.join(project_path, template.path, template.name)
|
file_path = os.path.join(project_path, template.path, template.name)
|
||||||
file_rel_path = os.path.join(project_path, template.path)
|
if not os.path.isdir(os.path.dirname(file_path)):
|
||||||
|
os.makedirs(os.path.dirname(file_path))
|
||||||
if not os.path.isdir(file_rel_path):
|
|
||||||
os.makedirs(file_rel_path)
|
|
||||||
|
|
||||||
with open(file_path, 'w') as file:
|
with open(file_path, 'w') as file:
|
||||||
file.write(template.value)
|
file.write(template.value)
|
||||||
|
Loading…
Reference in New Issue
Block a user