From cbf333564c11f982cb7ca9360bafd7a8972a2606 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 14 Mar 2021 16:01:15 +0100 Subject: [PATCH] Added comments --- src/cpl_cli/cli.py | 7 ++ src/cpl_cli/command/build_service.py | 9 ++ src/cpl_cli/command/generate_service.py | 28 ++++++ src/cpl_cli/command/help_service.py | 8 ++ src/cpl_cli/command/install_service.py | 19 ++++ src/cpl_cli/command/new_service.py | 39 +++++++- src/cpl_cli/command/publish_service.py | 9 ++ src/cpl_cli/command/start_service.py | 9 ++ src/cpl_cli/command/uninstall_service.py | 11 +++ src/cpl_cli/command/update_service.py | 51 +++++++--- src/cpl_cli/command/version_service.py | 9 +- src/cpl_cli/command_handler_service.py | 11 +++ .../live_server/live_server_service.py | 22 +++++ src/cpl_cli/live_server/live_server_thread.py | 8 ++ src/cpl_cli/publish/publisher_service.py | 92 +++++++++++++++++-- 15 files changed, 308 insertions(+), 24 deletions(-) diff --git a/src/cpl_cli/cli.py b/src/cpl_cli/cli.py index ef6c7c27..6f191807 100644 --- a/src/cpl_cli/cli.py +++ b/src/cpl_cli/cli.py @@ -19,6 +19,9 @@ from cpl_cli.command.version_service import VersionService class CLI(ApplicationABC): def __init__(self): + """ + CPL CLI + """ ApplicationABC.__init__(self) self._command_handler: Optional[CommandHandler] = None @@ -38,6 +41,10 @@ class CLI(ApplicationABC): self._command_handler.add_command(CommandModel('version', ['v', 'V'], VersionService, False)) def main(self): + """ + Entry point of the CPL CLI + :return: + """ command = None args = [] if len(self._configuration.additional_arguments) > 0: diff --git a/src/cpl_cli/command/build_service.py b/src/cpl_cli/command/build_service.py index 16cac950..dd8899d4 100644 --- a/src/cpl_cli/command/build_service.py +++ b/src/cpl_cli/command/build_service.py @@ -6,10 +6,19 @@ from cpl_cli.publish.publisher_abc import PublisherABC class BuildService(CommandABC): def __init__(self, publisher: PublisherABC): + """ + Service for the CLI command build + :param publisher: + """ CommandABC.__init__(self) self._publisher = publisher def run(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ self._publisher.build() Console.write('\n') diff --git a/src/cpl_cli/command/generate_service.py b/src/cpl_cli/command/generate_service.py index 98ea2411..b8ef2d11 100644 --- a/src/cpl_cli/command/generate_service.py +++ b/src/cpl_cli/command/generate_service.py @@ -19,6 +19,11 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC class GenerateService(CommandABC): def __init__(self, configuration: ConfigurationABC, runtime: ApplicationRuntimeABC): + """ + Service for the CLI command generate + :param configuration: + :param runtime: + """ CommandABC.__init__(self) self._schematics = { @@ -53,6 +58,11 @@ class GenerateService(CommandABC): @staticmethod def _help(message: str): + """ + Internal help output + :param message: + :return: + """ Console.error(message) schematics = [ @@ -68,11 +78,24 @@ class GenerateService(CommandABC): @staticmethod def _create_file(file_path: str, value: str): + """ + Creates the given file with content + :param file_path: + :param value: + :return: + """ with open(file_path, 'w') as template: template.write(value) template.close() def _generate(self, schematic: str, name: str, template: Callable[TemplateFileABC]): + """ + Generates files by given schematic, name and template + :param schematic: + :param name: + :param template: + :return: + """ class_name = name rel_path = '' if '/' in name: @@ -104,6 +127,11 @@ class GenerateService(CommandABC): ) def run(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ if len(args) == 0: self._help('Usage: cpl generate [options]') exit() diff --git a/src/cpl_cli/command/help_service.py b/src/cpl_cli/command/help_service.py index 387bfaf6..6c101838 100644 --- a/src/cpl_cli/command/help_service.py +++ b/src/cpl_cli/command/help_service.py @@ -6,9 +6,17 @@ from cpl_cli.command_abc import CommandABC class HelpService(CommandABC): def __init__(self): + """ + Service for CLI command help + """ CommandABC.__init__(self) def run(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ Console.write_line('Available Commands:') commands = [ ['build (b|B)', 'Prepares files for publish into an output directory named dist/ at the given output path. Must be executed from within a workspace directory.'], diff --git a/src/cpl_cli/command/install_service.py b/src/cpl_cli/command/install_service.py index 46cc3ba7..f0e18ba7 100644 --- a/src/cpl_cli/command/install_service.py +++ b/src/cpl_cli/command/install_service.py @@ -19,12 +19,21 @@ from cpl_cli.error import Error class InstallService(CommandABC): def __init__(self, runtime: ApplicationRuntimeABC, configuration: ConfigurationABC): + """ + Service for the CLI command install + :param runtime: + :param configuration: + """ CommandABC.__init__(self) self._runtime = runtime self._config = configuration def _install_project(self): + """ + Installs dependencies of CPl project + :return: + """ project: ProjectSettings = self._config.get_configuration(ProjectSettings) build: BuildSettings = self._config.get_configuration(BuildSettings) @@ -88,6 +97,11 @@ class InstallService(CommandABC): } def _install_package(self, package: str): + """ + Installs given package + :param package: + :return: + """ is_already_in_project = False project: ProjectSettings = self._config.get_configuration(ProjectSettings) build: BuildSettings = self._config.get_configuration(BuildSettings) @@ -165,6 +179,11 @@ class InstallService(CommandABC): Pip.reset_executable() def run(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ if len(args) == 0: self._install_project() else: diff --git a/src/cpl_cli/command/new_service.py b/src/cpl_cli/command/new_service.py index 33728f8a..5711e687 100644 --- a/src/cpl_cli/command/new_service.py +++ b/src/cpl_cli/command/new_service.py @@ -1,7 +1,6 @@ import json import os import sys -import time from typing import Optional from packaging import version @@ -30,6 +29,11 @@ from cpl_cli.templates.template_file_abc import TemplateFileABC class NewService(CommandABC): def __init__(self, configuration: ConfigurationABC, runtime: ApplicationRuntimeABC): + """ + Service for the CLI command new + :param configuration: + :param runtime: + """ CommandABC.__init__(self) self._config = configuration @@ -90,12 +94,20 @@ class NewService(CommandABC): self._build.from_dict(self._build_dict) def _create_project_json(self): + """ + Creates cpl.json content + :return: + """ self._project_json = { ProjectSettings.__name__: self._project_dict, BuildSettings.__name__: self._build_dict } def _get_project_path(self) -> Optional[str]: + """ + Gets project path + :return: + """ project_path = os.path.join(self._runtime.working_directory, self._project.name) if os.path.isdir(project_path) and len(os.listdir(project_path)) > 0: Console.error('Project path is not empty\n') @@ -104,6 +116,10 @@ class NewService(CommandABC): return project_path def _get_project_informations(self): + """ + Gets project informations from user + :return: + """ result = Console.read('Do you want to use application host? (y/n) ') if result.lower() == 'y': self._use_application_api = True @@ -121,6 +137,11 @@ class NewService(CommandABC): # self._use_service_providing = True def _build_project_dir(self, project_path: str): + """ + Builds the project files + :param project_path: + :return: + """ if not os.path.isdir(project_path): os.makedirs(project_path) @@ -155,6 +176,12 @@ class NewService(CommandABC): @staticmethod def _create_template(project_path: str, template: TemplateFileABC): + """ + Creates template + :param project_path: + :param template: + :return: + """ file_path = os.path.join(project_path, template.path, template.name) file_rel_path = os.path.join(project_path, template.path) @@ -166,6 +193,11 @@ class NewService(CommandABC): license_file.close() def _console(self, args: list[str]): + """ + Generates new console project + :param args: + :return: + """ name = self._config.get_configuration(self._command) self._create_project_settings(name) @@ -182,6 +214,11 @@ class NewService(CommandABC): Console.error('Could not create project', str(e)) def run(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ self._command = args[0] if self._command == 'console': self._console(args) diff --git a/src/cpl_cli/command/publish_service.py b/src/cpl_cli/command/publish_service.py index b455a451..4975a7e1 100644 --- a/src/cpl_cli/command/publish_service.py +++ b/src/cpl_cli/command/publish_service.py @@ -6,10 +6,19 @@ from cpl_cli.publish.publisher_abc import PublisherABC class PublishService(CommandABC): def __init__(self, publisher: PublisherABC): + """ + Service for the CLI command publish + :param publisher: + """ CommandABC.__init__(self) self._publisher = publisher def run(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ self._publisher.publish() Console.write('\n') diff --git a/src/cpl_cli/command/start_service.py b/src/cpl_cli/command/start_service.py index a81a8523..7dae7086 100644 --- a/src/cpl_cli/command/start_service.py +++ b/src/cpl_cli/command/start_service.py @@ -5,9 +5,18 @@ from cpl_cli.live_server.live_server_service import LiveServerService class StartService(CommandABC): def __init__(self, live_server: LiveServerService): + """ + Service for the CLI command start + :param live_server: + """ CommandABC.__init__(self) self._live_server = live_server def run(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ self._live_server.start() diff --git a/src/cpl_cli/command/uninstall_service.py b/src/cpl_cli/command/uninstall_service.py index 67afe747..865bf87b 100644 --- a/src/cpl_cli/command/uninstall_service.py +++ b/src/cpl_cli/command/uninstall_service.py @@ -16,6 +16,12 @@ class UninstallService(CommandABC): def __init__(self, runtime: ApplicationRuntimeABC, build_settings: BuildSettings, project_settings: ProjectSettings): + """ + Service for the CLI command uninstall + :param runtime: + :param build_settings: + :param project_settings: + """ CommandABC.__init__(self) self._runtime = runtime @@ -59,6 +65,11 @@ class UninstallService(CommandABC): } def run(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ if len(args) == 0: Console.error(f'Expected package') Console.error(f'Usage: cpl uninstall ') diff --git a/src/cpl_cli/command/update_service.py b/src/cpl_cli/command/update_service.py index b92e5965..419c36a7 100644 --- a/src/cpl_cli/command/update_service.py +++ b/src/cpl_cli/command/update_service.py @@ -1,7 +1,6 @@ import json import os import subprocess -import sys from cpl.application import ApplicationRuntimeABC from cpl.console import ForegroundColorEnum @@ -14,30 +13,35 @@ from cpl_cli.configuration.project_settings import ProjectSettings class UpdateService(CommandABC): def __init__(self, runtime: ApplicationRuntimeABC, project_settings: ProjectSettings): + """ + Service for the CLI command update + :param runtime: + :param project_settings: + """ CommandABC.__init__(self) self._runtime = runtime self._project_settings = project_settings - @staticmethod - def _install_package(name: str): - Pip.install( - name, - '--upgrade', - '--upgrade-strategy', - 'eager', - source='https://pip.sh-edraft.de' if 'sh_cpl' in name else None, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL - ) - def _update_project_dependencies(self): + """ + Updates project dependencies + :return: + """ for package in self._project_settings.dependencies: name = package if '==' in package: name = package.split('==')[0] - self._install_package(name) + Pip.install( + name, + '--upgrade', + '--upgrade-strategy', + 'eager', + source='https://pip.sh-edraft.de' if 'sh_cpl' in name else None, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL + ) new_package = Pip.get_package(name) if new_package is None: @@ -47,6 +51,10 @@ class UpdateService(CommandABC): self._project_json_update_dependency(package, new_package) def _check_project_dependencies(self): + """ + Checks project dependencies for updates + :return: + """ Console.spinner( 'Collecting installed dependencies', self._update_project_dependencies, text_foreground_color=ForegroundColorEnum.green, @@ -56,6 +64,10 @@ class UpdateService(CommandABC): @staticmethod def _check_outdated(): + """ + Checks for outdated packages in project + :return: + """ table_str: bytes = Console.spinner( 'Analyzing for available package updates', Pip.get_outdated, text_foreground_color=ForegroundColorEnum.green, @@ -73,6 +85,12 @@ class UpdateService(CommandABC): Console.set_foreground_color(ForegroundColorEnum.default) def _project_json_update_dependency(self, old_package: str, new_package: str): + """ + Writes new package version to cpl.json + :param old_package: + :param new_package: + :return: + """ content = '' with open(os.path.join(self._runtime.working_directory, 'cpl.json'), 'r') as project: content = project.read() @@ -89,6 +107,11 @@ class UpdateService(CommandABC): project.close() def run(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ Pip.set_executable(self._project_settings.python_path) self._check_project_dependencies() self._check_outdated() diff --git a/src/cpl_cli/command/version_service.py b/src/cpl_cli/command/version_service.py index f66e8e51..0046a3f9 100644 --- a/src/cpl_cli/command/version_service.py +++ b/src/cpl_cli/command/version_service.py @@ -1,4 +1,3 @@ -import os import pkgutil import sys import platform @@ -14,9 +13,17 @@ from cpl_cli.command_abc import CommandABC class VersionService(CommandABC): def __init__(self): + """ + Service for the CLI command version + """ CommandABC.__init__(self) def run(self, args: list[str]): + """ + Entry point of command + :param args: + :return: + """ Console.set_foreground_color(ForegroundColorEnum.yellow) Console.banner('CPL CLI') Console.set_foreground_color(ForegroundColorEnum.default) diff --git a/src/cpl_cli/command_handler_service.py b/src/cpl_cli/command_handler_service.py index 8c1781d8..c4a4da50 100644 --- a/src/cpl_cli/command_handler_service.py +++ b/src/cpl_cli/command_handler_service.py @@ -10,6 +10,11 @@ from cpl_cli.command_model import CommandModel class CommandHandler(ServiceABC): def __init__(self, runtime: ApplicationRuntimeABC, services: ServiceProviderABC): + """ + Service to handle incoming commands and args + :param runtime: + :param services: + """ ServiceABC.__init__(self) self._runtime = runtime @@ -28,6 +33,12 @@ class CommandHandler(ServiceABC): self._commands.remove(cmd) def handle(self, cmd: str, args: list[str]): + """ + Handles incoming commands and args + :param cmd: + :param args: + :return: + """ for command in self._commands: if cmd == command.name or cmd in command.aliases: if command.is_project_needed and not os.path.isfile(os.path.join(self._runtime.working_directory, 'cpl.json')): diff --git a/src/cpl_cli/live_server/live_server_service.py b/src/cpl_cli/live_server/live_server_service.py index 3c3fa9c2..c09a36fc 100644 --- a/src/cpl_cli/live_server/live_server_service.py +++ b/src/cpl_cli/live_server/live_server_service.py @@ -16,6 +16,11 @@ from cpl_cli.live_server.live_server_thread import LiveServerThread class LiveServerService(ServiceABC, FileSystemEventHandler): def __init__(self, runtime: ApplicationRuntimeABC, build_settings: BuildSettings): + """ + Service for the live development server + :param runtime: + :param build_settings: + """ ServiceABC.__init__(self) FileSystemEventHandler.__init__(self) @@ -27,11 +32,19 @@ class LiveServerService(ServiceABC, FileSystemEventHandler): self._observer = None def _start_observer(self): + """ + Starts the file changes observer + :return: + """ self._observer = Observer() self._observer.schedule(self, path=self._src_dir, recursive=True) self._observer.start() def _restart(self): + """ + Restarts the CPL project + :return: + """ for proc in psutil.process_iter(): with suppress(Exception): if proc.cmdline() == self._ls_thread.command: @@ -47,6 +60,11 @@ class LiveServerService(ServiceABC, FileSystemEventHandler): self._start_observer() def on_modified(self, event): + """ + Triggers when source file is modified + :param event: + :return: + """ if event.is_directory: return None @@ -56,6 +74,10 @@ class LiveServerService(ServiceABC, FileSystemEventHandler): self._restart() def start(self): + """ + Starts the CPL live development server + :return: + """ Console.write_line('** CPL live development server is running **') self._start_observer() self._ls_thread.start() diff --git a/src/cpl_cli/live_server/live_server_thread.py b/src/cpl_cli/live_server/live_server_thread.py index 920859ca..caf3c85e 100644 --- a/src/cpl_cli/live_server/live_server_thread.py +++ b/src/cpl_cli/live_server/live_server_thread.py @@ -10,6 +10,10 @@ from cpl.console import Console class LiveServerThread(threading.Thread): def __init__(self, path: str): + """ + Thread to start the CPL project for the live development server + :param path: + """ threading.Thread.__init__(self) self._path = path @@ -25,6 +29,10 @@ class LiveServerThread(threading.Thread): return self._main def run(self): + """ + Starts the CPL project + :return: + """ self._main = os.path.join(self._path, 'main.py') if not os.path.isfile(self._main): Console.error('Entry point main.py not found') diff --git a/src/cpl_cli/publish/publisher_service.py b/src/cpl_cli/publish/publisher_service.py index f7420e95..255cb054 100644 --- a/src/cpl_cli/publish/publisher_service.py +++ b/src/cpl_cli/publish/publisher_service.py @@ -20,6 +20,12 @@ from cpl_cli.templates.publish.setup_template import SetupTemplate class PublisherService(PublisherABC): def __init__(self, runtime: ApplicationRuntimeABC, project: ProjectSettings, build: BuildSettings): + """ + Service to build or publish files for distribution + :param runtime: + :param project: + :param build: + """ PublisherABC.__init__(self) self._runtime = runtime @@ -43,6 +49,11 @@ class PublisherService(PublisherABC): @staticmethod def _get_module_name_from_dirs(file: str) -> str: + """ + Extracts module name from directories + :param file: + :return: + """ if 'src/' in file: file = file.replace('src/', '', 1) @@ -58,6 +69,11 @@ class PublisherService(PublisherABC): @staticmethod def _delete_path(path: str): + """ + Deletes full path tree + :param path: + :return: + """ if os.path.isdir(path): try: shutil.rmtree(path) @@ -67,6 +83,11 @@ class PublisherService(PublisherABC): @staticmethod def _create_path(path: str): + """ + Creates full path tree + :param path: + :return: + """ if not os.path.isdir(path): try: os.makedirs(path) @@ -75,6 +96,11 @@ class PublisherService(PublisherABC): exit() def _is_path_included(self, path: str) -> bool: + """ + Checks if the path is included + :param path: + :return: + """ for included in self._build_settings.included: if included.startswith('*'): included = included.replace('*', '') @@ -85,6 +111,11 @@ class PublisherService(PublisherABC): return False def _is_path_excluded(self, path: str) -> bool: + """ + Checks if the path is excluded + :param path: + :return: + """ for excluded in self._build_settings.excluded: if excluded.startswith('*'): excluded = excluded.replace('*', '') @@ -95,6 +126,10 @@ class PublisherService(PublisherABC): return False def _read_sources(self): + """ + Reads all source files and save included files + :return: + """ for file in self._build_settings.included: rel_path = os.path.relpath(file) if os.path.isdir(rel_path): @@ -127,6 +162,10 @@ class PublisherService(PublisherABC): self._included_files.append(os.path.relpath(file_path)) def _create_packages(self): + """ + Writes information from template to all included __init__.py + :return: + """ for file in self._included_files: if file.endswith('__init__.py'): template_content = '' @@ -181,6 +220,10 @@ class PublisherService(PublisherABC): py_file.close() def _dist_files(self): + """ + Copies all included source files to dist_path + :return: + """ build_path = os.path.join(self._output_path) self._delete_path(build_path) self._create_path(build_path) @@ -217,6 +260,10 @@ class PublisherService(PublisherABC): os.makedirs(output_path) def _clean_dist_files(self): + """ + Deletes all included source files from dist_path + :return: + """ paths: list[str] = [] for file in self._distributed_files: paths.append(os.path.dirname(file)) @@ -228,15 +275,13 @@ class PublisherService(PublisherABC): if os.path.isdir(path): shutil.rmtree(path) - @staticmethod - def _package_files(directory): - paths = [] - for (path, directories, filenames) in os.walk(directory): - for filename in filenames: - paths.append(os.path.join('..', path, filename)) - return paths - def _create_setup(self): + """ + Generates setup.py + + Dependencies: ProjectSettings, BuildSettings + :return: + """ setup_file = os.path.join(self._output_path, 'setup.py') if os.path.isfile(setup_file): os.remove(setup_file) @@ -275,6 +320,10 @@ class PublisherService(PublisherABC): setup_py.close() def _run_setup(self): + """ + Starts setup.py + :return: + """ setup_py = os.path.join(self._output_path, 'setup.py') if not os.path.isfile(setup_py): Console.error(__name__, f'setup.py not found in {self._output_path}') @@ -293,12 +342,30 @@ class PublisherService(PublisherABC): Console.error('Executing setup.py failed', str(e)) def include(self, path: str): + """ + Includes given path from sources + :param path: + :return: + """ self._build_settings.included.append(path) def exclude(self, path: str): + """ + Excludes given path from sources + :param path: + :return: + """ self._build_settings.excluded.append(path) def build(self): + """ + Build the CPL project to dist_path/build + + 1. Reads all included source files + 2. Writes informations from template to all included __init__.py + 3. Copies all included source files to dist_path/build + :return: + """ self._output_path = os.path.join(self._output_path, 'build') Console.spinner('Reading source files:', self._read_sources, text_foreground_color=ForegroundColorEnum.green, spinner_foreground_color=ForegroundColorEnum.blue) @@ -306,6 +373,15 @@ class PublisherService(PublisherABC): Console.spinner('Building application:', self._dist_files, text_foreground_color=ForegroundColorEnum.green, spinner_foreground_color=ForegroundColorEnum.blue) def publish(self): + """ + Publishes the CPL project to dist_path/publish + + 1. Builds the project + 2. Generates setup.py + 3. Start setup.py + 4. Remove all included source from dist_path/publish + :return: + """ self._output_path = os.path.join(self._output_path, 'publish') Console.write_line('Build:')