From 700bf9c937daa815d176f4ae3c2bbc5100c18f9e Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 4 Mar 2021 19:06:53 +0100 Subject: [PATCH] Improved command handling --- src/cpl_cli/cli.py | 14 +++-- src/cpl_cli/command/__init__.py | 0 src/cpl_cli/command/build.py | 13 ++++ src/cpl_cli/command/generate.py | 0 src/cpl_cli/{commands => command}/help.py | 6 +- src/cpl_cli/command/new.py | 0 src/cpl_cli/command/publish.py | 0 src/cpl_cli/command/start.py | 0 src/cpl_cli/command/update.py | 0 src/cpl_cli/{commands => command}/version.py | 0 src/cpl_cli/command_handler.py | 14 +++-- src/cpl_cli/publish/__init__.py | 0 src/cpl_cli/publish/project_settings.py | 46 ++++++++++++++ src/cpl_cli/publish/project_settings_name.py | 9 +++ src/cpl_cli/publish/publisher.py | 65 ++++++++++++++++++++ src/cpl_cli/publish/publisher_abc.py | 30 +++++++++ src/cpl_cli/startup.py | 19 ++++-- 17 files changed, 197 insertions(+), 19 deletions(-) create mode 100644 src/cpl_cli/command/__init__.py create mode 100644 src/cpl_cli/command/build.py create mode 100644 src/cpl_cli/command/generate.py rename src/cpl_cli/{commands => command}/help.py (65%) create mode 100644 src/cpl_cli/command/new.py create mode 100644 src/cpl_cli/command/publish.py create mode 100644 src/cpl_cli/command/start.py create mode 100644 src/cpl_cli/command/update.py rename src/cpl_cli/{commands => command}/version.py (100%) create mode 100644 src/cpl_cli/publish/__init__.py create mode 100644 src/cpl_cli/publish/project_settings.py create mode 100644 src/cpl_cli/publish/project_settings_name.py create mode 100644 src/cpl_cli/publish/publisher.py create mode 100644 src/cpl_cli/publish/publisher_abc.py diff --git a/src/cpl_cli/cli.py b/src/cpl_cli/cli.py index 580e39ec..15edf618 100644 --- a/src/cpl_cli/cli.py +++ b/src/cpl_cli/cli.py @@ -1,11 +1,14 @@ from typing import Optional from cpl.application.application_abc import ApplicationABC -from cpl_cli.command import Command +from cpl.console.console import Console +from cpl_cli.command.build import Build from cpl_cli.command_handler import CommandHandler +from cpl_cli.command_model import CommandModel from cpl_cli.error import Error -from cpl_cli.commands.help import Help -from cpl_cli.commands.version import Version +from cpl_cli.command.help import Help +from cpl_cli.command.version import Version +from cpl_cli.publish.project_settings import ProjectSettings class CLI(ApplicationABC): @@ -18,8 +21,9 @@ class CLI(ApplicationABC): def configure(self): self._command_handler: CommandHandler = self._services.get_service(CommandHandler) - self._command_handler.add_command(Command('help', ['h', 'H'], self._services.get_service(Help))) - self._command_handler.add_command(Command('version', ['v', 'V'], self._services.get_service(Version))) + self._command_handler.add_command(CommandModel('build', ['h', 'B'], Build)) + self._command_handler.add_command(CommandModel('help', ['h', 'H'], Help)) + self._command_handler.add_command(CommandModel('version', ['v', 'V'], Version)) def main(self): if len(self._configuration.additional_arguments) < 1: diff --git a/src/cpl_cli/command/__init__.py b/src/cpl_cli/command/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_cli/command/build.py b/src/cpl_cli/command/build.py new file mode 100644 index 00000000..8226ea31 --- /dev/null +++ b/src/cpl_cli/command/build.py @@ -0,0 +1,13 @@ +from cpl_cli.command_abc import CommandABC +from cpl_cli.publish.publisher_abc import PublisherABC + + +class Build(CommandABC): + + def __init__(self, publisher: PublisherABC): + CommandABC.__init__(self) + + self._publisher = publisher + + def run(self, args: list[str]): + self._publisher.build() diff --git a/src/cpl_cli/command/generate.py b/src/cpl_cli/command/generate.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_cli/commands/help.py b/src/cpl_cli/command/help.py similarity index 65% rename from src/cpl_cli/commands/help.py rename to src/cpl_cli/command/help.py index 004d9280..cace0549 100644 --- a/src/cpl_cli/commands/help.py +++ b/src/cpl_cli/command/help.py @@ -10,12 +10,12 @@ class Help(CommandABC): def run(self, args: list[str]): Console.write_line('Available Commands:') commands = [ - ['build (-b|-B)', 'Prepares files for publishing into an output directory named dist/ at the given output path. Must be executed from within a workspace directory.'], + ['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 commands and their short descriptions.'], + ['help (-h|-H)', 'Lists available command and their short descriptions.'], ['new (-n|-N)', 'Creates new CPL project.'], ['start (-s|-S)', 'Starts CPL project, restarting on file changes'], - ['publish (-p|-P)', 'Prepares files for publishing into an output directory named dist/ at the given output path and executes setup.py. Must be executed from within a workspace directory.'], + ['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 workspace directory.'], ['update (-u|-u)', 'Update CPL and project dependencies.'], ['version (-v|-V)', 'Outputs CPL CLI version.'] ] diff --git a/src/cpl_cli/command/new.py b/src/cpl_cli/command/new.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_cli/command/publish.py b/src/cpl_cli/command/publish.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_cli/command/start.py b/src/cpl_cli/command/start.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_cli/command/update.py b/src/cpl_cli/command/update.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_cli/commands/version.py b/src/cpl_cli/command/version.py similarity index 100% rename from src/cpl_cli/commands/version.py rename to src/cpl_cli/command/version.py diff --git a/src/cpl_cli/command_handler.py b/src/cpl_cli/command_handler.py index d3eaa9b6..850807eb 100644 --- a/src/cpl_cli/command_handler.py +++ b/src/cpl_cli/command_handler.py @@ -1,24 +1,26 @@ from cpl.application.application_runtime_abc import ApplicationRuntimeABC from cpl.dependency_injection.service_abc import ServiceABC -from cpl_cli.command import Command +from cpl.dependency_injection.service_provider_base import ServiceProviderABC +from cpl_cli.command_model import CommandModel class CommandHandler(ServiceABC): - def __init__(self, runtime: ApplicationRuntimeABC): + def __init__(self, runtime: ApplicationRuntimeABC, services: ServiceProviderABC): ServiceABC.__init__(self) self._runtime = runtime + self._services = services - self._commands: list[Command] = [] + self._commands: list[CommandModel] = [] - def add_command(self, cmd: Command): + def add_command(self, cmd: CommandModel): self._commands.append(cmd) - def remove_command(self, cmd: Command): + def remove_command(self, cmd: CommandModel): self._commands.remove(cmd) def handle(self, cmd: str, args: list[str]): for command in self._commands: if cmd == command.name or cmd in command.aliases: - command.command.run(args) + self._services.get_service(command.command).run(args) diff --git a/src/cpl_cli/publish/__init__.py b/src/cpl_cli/publish/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_cli/publish/project_settings.py b/src/cpl_cli/publish/project_settings.py new file mode 100644 index 00000000..79e9fefa --- /dev/null +++ b/src/cpl_cli/publish/project_settings.py @@ -0,0 +1,46 @@ +import traceback +from typing import Optional + +from cpl.configuration.configuration_model_abc import ConfigurationModelABC +from cpl.console.console import Console +from cpl.console.foreground_color import ForegroundColor +from cpl.version.version import Version +from cpl_cli.publish.project_settings_name import ProjectSettingsName + + +class ProjectSettings(ConfigurationModelABC): + + def __init__(self): + ConfigurationModelABC.__init__(self) + + self._dist_path: Optional[str] = None + self._excluded_files: list[str] = [] + self._version: Optional[Version] = None + + @property + def excluded_files(self) -> list[str]: + return self._excluded_files + + @property + def dist_path(self) -> str: + return self._dist_path + + @dist_path.setter + def dist_path(self, dist_path: str): + self._dist_path = dist_path + + @property + def version(self) -> Version: + return self._version + + def from_dict(self, settings: dict): + try: + self._dist_path = settings[ProjectSettingsName.dist_path.value] + self._excluded_files = settings[ProjectSettingsName.excluded_files.value] + self._version = settings[ProjectSettingsName.version.value] + except Exception as e: + Console.set_foreground_color(ForegroundColor.red) + Console.write_line( + f'[ ERROR ] [ {__name__} ]: Reading error in {ProjectSettingsName.project.value} settings') + Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') + Console.set_foreground_color(ForegroundColor.default) diff --git a/src/cpl_cli/publish/project_settings_name.py b/src/cpl_cli/publish/project_settings_name.py new file mode 100644 index 00000000..2285c913 --- /dev/null +++ b/src/cpl_cli/publish/project_settings_name.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class ProjectSettingsName(Enum): + + dist_path = 'DistPath' + excluded_files = 'ExcludedFiles' + version = 'Version' + project = 'Project' diff --git a/src/cpl_cli/publish/publisher.py b/src/cpl_cli/publish/publisher.py new file mode 100644 index 00000000..eb8eecff --- /dev/null +++ b/src/cpl_cli/publish/publisher.py @@ -0,0 +1,65 @@ +import os +import shutil + +from cpl.application.application_runtime_abc import ApplicationRuntimeABC +from cpl.console.console import Console +from cpl_cli.publish.project_settings import ProjectSettings +from cpl_cli.publish.publisher_abc import PublisherABC + + +class Publisher(PublisherABC): + + def __init__(self, runtime: ApplicationRuntimeABC, project: ProjectSettings): + PublisherABC.__init__(self) + + self._runtime = runtime + + self._project = project + + @property + def source_path(self) -> str: + return '' + + @property + def dist_path(self) -> str: + return '' + + def _create_dist_path(self): + self._project.dist_path = os.path.join(self._runtime.working_directory, self._project.dist_path) + + Console.write_line('DIST:', self._project.dist_path) + + if os.path.isdir(self._project.dist_path): + try: + shutil.rmtree(self._project.dist_path) + except Exception as e: + Console.error(f'{e}') + exit() + + if not os.path.isdir(self._project.dist_path): + try: + os.makedirs(self._project.dist_path) + except Exception as e: + Console.error(f'{e}') + exit() + + def _create_packages(self): + pass + + def _dist_files(self): + pass + + def include(self, path: str): + pass + + def exclude(self, path: str): + pass + + def build(self): + Console.write_line('Creating internal packages:') + self._create_packages() + Console.write_line('Building application:') + self._dist_files() + + def publish(self): + pass diff --git a/src/cpl_cli/publish/publisher_abc.py b/src/cpl_cli/publish/publisher_abc.py new file mode 100644 index 00000000..48aaaaa1 --- /dev/null +++ b/src/cpl_cli/publish/publisher_abc.py @@ -0,0 +1,30 @@ +from abc import abstractmethod + +from cpl.dependency_injection.service_abc import ServiceABC + + +class PublisherABC(ServiceABC): + + @abstractmethod + def __init__(self): + ServiceABC.__init__(self) + + @property + @abstractmethod + def source_path(self) -> str: pass + + @property + @abstractmethod + def dist_path(self) -> str: pass + + @abstractmethod + def include(self, path: str): pass + + @abstractmethod + def exclude(self, path: str): pass + + @abstractmethod + def build(self): pass + + @abstractmethod + def publish(self): pass diff --git a/src/cpl_cli/startup.py b/src/cpl_cli/startup.py index 9ec776c7..332f8935 100644 --- a/src/cpl_cli/startup.py +++ b/src/cpl_cli/startup.py @@ -4,11 +4,15 @@ from cpl.application.application_host import ApplicationHost from cpl.application.application_host_abc import ApplicationHostABC from cpl.application.startup_abc import StartupABC from cpl.configuration.configuration_abc import ConfigurationABC +from cpl.console.console import Console from cpl.dependency_injection.service_provider_base import ServiceProviderABC +from cpl_cli.command.build import Build from cpl_cli.command_handler import CommandHandler -from cpl_cli.commands.help import Help -from cpl_cli.commands.version import Version +from cpl_cli.command.help import Help +from cpl_cli.command.version import Version from cpl_cli.error import Error +from cpl_cli.publish.publisher import Publisher +from cpl_cli.publish.publisher_abc import PublisherABC class Startup(StartupABC): @@ -34,6 +38,8 @@ class Startup(StartupABC): def create_configuration(self) -> ConfigurationABC: self._configuration.add_environment_variables('PYTHON_') self._configuration.add_environment_variables('CPL_') + self._configuration.add_json_file('cpl.json', optional=True, output=False) + self._configuration.add_console_argument('', 'build', ['-b', '-B'], '') self._configuration.add_console_argument('', 'help', ['-h', '-H'], '') self._configuration.add_console_argument('', 'version', ['-v', '-V'], '') self._configuration.add_console_arguments() @@ -41,9 +47,12 @@ class Startup(StartupABC): return self._configuration def create_services(self) -> ServiceProviderABC: - self._services.add_singleton(CommandHandler, CommandHandler) + self._services.add_singleton(CommandHandler) - self._services.add_scoped(Help, Help) - self._services.add_scoped(Version, Version) + self._services.add_transient(PublisherABC, Publisher) + + self._services.add_transient(Build) + self._services.add_transient(Help) + self._services.add_transient(Version) return self._services