+
+ +
+

Using cpl g & cpl n templating

+
+

Contents

+
    +
  • Prerequisites

  • +
  • Generate schematics

  • +
  • Project types

  • +
+
+
+

Prerequisites

+

Create a folder called .cpl

+
+
+

cpl generate schematics

+

Create a file which begins with schematic_your_schematic.py. +A schematic template is detected by starting with schematic_ and endswith .py.

+

You should replace your_schematic with an appropriate name of your schematic. For example, we will choose Enum. +Attention: It is important that you do not overwrite templates by creating a file or class with the same name.

+

In the template create a class with the name of your schematic. For example:

+
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("""\
+        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']
+        )
+
+
+
+

You can test it by calling cpl g --help your schematic should be listed as available.

+
+
+

cpl new project types

+

The project templating is a little more complex and is therefore divided into several files. +First of all, for information, it is very important not to overwrite any existing files or classes!

+

Template structure explained by the example of the internal type console:

+
- project_console.py
+- project_file_license.py
+- project_file_appsettings.py
+- project_file.py
+- project_file_readme.py
+- project_file_code_main.py
+- project_file_code_startup.py
+- project_file_code_application.py
+
+
+

Here the template project_console.py defines how a console project has to look like when it is generated. Here is the code to illustrate this:

+
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,
+            project_file_data: dict,
+    ):
+        from project_file import ProjectFile
+        from project_file_appsettings import ProjectFileAppsettings
+        from project_file_code_application import ProjectFileApplication
+        from project_file_code_main import ProjectFileMain
+        from project_file_code_startup import ProjectFileStartup
+        from project_file_readme import ProjectFileReadme
+        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)
+
+        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))
+        if workspace is None:
+            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(ProjectFileAppsettings(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_name.split('/')[-1], project_path, use_application_api, use_startup, use_service_providing, use_async))
+
+
+

The class must be named exactly as the project type should be named. It is also checked on the initial letter of the class as alias. +Now create a class for normal files which inherits from FileTemplateABC and a class for code files which inherits from CodeFileTemplateABC.

+

For example:

+

project_file_code_startup.py:

+
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()
+        """)
+
+
+

project_file.py:

+
import json
+
+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'
+        self._code = code
+
+    def get_code(self) -> str:
+        return json.dumps(self._code, indent=2)
+
+
+
+
+ + +
+