diff --git a/docs/cli.md b/docs/cli.md new file mode 100644 index 00000000..f2f2291e --- /dev/null +++ b/docs/cli.md @@ -0,0 +1,9 @@ +prefix: cpl +commands: + new: + app + base + class + configmodel + enum + service \ No newline at end of file diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 00000000..54c105b4 --- /dev/null +++ b/docs/install.md @@ -0,0 +1,2 @@ +python setup.py install # for install +python setup.py sdist bdist_wheel # for build \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..afb24683 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,29 @@ +aiohttp==3.6.3 +async-timeout==3.0.1 +attrs==20.3.0 +certifi==2020.11.8 +chardet==3.0.4 +click==7.1.2 +dateutils==0.6.12 +discord==1.0.1 +discord.py==1.5.1 +Flask==1.1.2 +idna==2.10 +itsdangerous==1.1.0 +Jinja2==2.11.2 +keyboard==0.13.5 +MarkupSafe==1.1.1 +multidict==4.7.6 +mysql-connector==2.2.9 +overloading==0.5.0 +python-dateutil==2.8.1 +pytz==2020.4 +six==1.15.0 +SQLAlchemy==1.3.20 +termcolor==1.1.0 +urllib3==1.26.2 +Werkzeug==1.0.1 +yarl==1.5.1 +setuptools~=49.2.1 +pyfiglet~=0.8.post1 +tabulate~=0.8.7 \ No newline at end of file diff --git a/src/MANIFEST.in b/src/MANIFEST.in new file mode 100644 index 00000000..cb32f474 --- /dev/null +++ b/src/MANIFEST.in @@ -0,0 +1,2 @@ +include ../ README +recursive-include sh_edraft *.txt \ No newline at end of file diff --git a/src/build.json b/src/build.json new file mode 100644 index 00000000..d2ca1def --- /dev/null +++ b/src/build.json @@ -0,0 +1,66 @@ +{ + "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": "../build/logs/", + "Filename": "log_$start_time.log", + "ConsoleLogLevel": "INFO", + "FileLogLevel": "TRACE" + }, + "PublishSettings": { + "SourcePath": "./", + "DistPath": "../build/dist", + "Templates": [ + { + "TemplatePath": "../publish_templates/all_template.txt", + "Name": "all", + "Description": "", + "LongDescription": "", + "CopyrightDate": "2020", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": ", see LICENSE for more details.", + "Title": "", + "Author": "Sven Heidemann", + "Version": { + "Major": 2020, + "Minor": 12, + "Micro": 9 + } + }, + { + "TemplatePath": "../publish_templates/all_template.txt", + "Name": "sh_edraft", + "Description": "common python library", + "LongDescription": "Library to share common classes and models used at sh-edraft.de", + "CopyrightDate": "2020", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": ", see LICENSE for more details.", + "Title": "", + "Author": "Sven Heidemann", + "Version": { + "Major": 2020, + "Minor": 12, + "Micro": 9 + } + } + ], + "IncludedFiles": [ + "./MANIFEST.in", + "../LICENSE", + "../README.md", + "../requirements.txt", + "sh_edraft/cli/cpl_cli/templates" + ], + "ExcludedFiles": [ + "./tests", + "./tests_dev" + ], + "TemplateEnding": "_template.txt" + } +} diff --git a/src/setup.py b/src/setup.py index 4f86d310..748df92d 100644 --- a/src/setup.py +++ b/src/setup.py @@ -3,10 +3,26 @@ import setuptools setuptools.setup( name='sh_edraft', version='2020.0.1', - packages=setuptools.find_packages(), + packages=setuptools.find_packages(exclude=["tests*"]), url='https://www.sh-edraft.de', license='MIT', author='Sven Heidemann', author_email='edraft.sh@gmail.com', - description='sh-edraft python common lib' + include_package_data=True, + description='sh-edraft python common lib', + python_requires='>=3.8', + install_requires=[ + 'discord.py', + 'flask', + 'mysql-connector', + 'SQLAlchemy', + 'termcolor', + 'pyfiglet', + 'tabulate' + ], + entry_points={ + 'console_scripts': [ + 'cpl = sh_edraft.cli.cpl_cli.cli:main' + ] + } ) diff --git a/src/sh_edraft/cli/__init__.py b/src/sh_edraft/cli/__init__.py new file mode 100644 index 00000000..89b6ae33 --- /dev/null +++ b/src/sh_edraft/cli/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +sh_edraft.cli +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) 2020 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'sh_edraft.cli' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 sh-edraft.de' +__version__ = '2020.12.9' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major=2020, minor=12, micro=9) diff --git a/src/sh_edraft/cli/command/__init__.py b/src/sh_edraft/cli/command/__init__.py new file mode 100644 index 00000000..336d4a17 --- /dev/null +++ b/src/sh_edraft/cli/command/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +sh_edraft.cli.command +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) 2020 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'sh_edraft.cli.command' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 sh-edraft.de' +__version__ = '2020.12.9' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major=2020, minor=12, micro=9) diff --git a/src/sh_edraft/cli/command/base/__init__.py b/src/sh_edraft/cli/command/base/__init__.py new file mode 100644 index 00000000..13a5ebca --- /dev/null +++ b/src/sh_edraft/cli/command/base/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +""" +sh_edraft.cli.command.base +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) 2020 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'sh_edraft.cli.command.base' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 sh-edraft.de' +__version__ = '2020.12.9' + +from collections import namedtuple + +# imports: +from .command_base import CommandBase + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major=2020, minor=12, micro=9) diff --git a/src/sh_edraft/cli/command/base/command_base.py b/src/sh_edraft/cli/command/base/command_base.py new file mode 100644 index 00000000..76319ba7 --- /dev/null +++ b/src/sh_edraft/cli/command/base/command_base.py @@ -0,0 +1,15 @@ +from abc import ABC, abstractmethod + + +class CommandBase(ABC): + + @abstractmethod + def __init__(self): + self._aliases: list[str] = [] + + @property + def aliases(self): + return self._aliases + + @abstractmethod + def run(self, args: list[str]): pass diff --git a/src/sh_edraft/cli/cpl_cli/__init__.py b/src/sh_edraft/cli/cpl_cli/__init__.py new file mode 100644 index 00000000..9130756c --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +""" +sh_edraft.cli.cpl_cli +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) 2020 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'sh_edraft.cli.cpl_cli' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 sh-edraft.de' +__version__ = '2020.12.9' + +from collections import namedtuple + +# imports: +from .cli import CLI + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major=2020, minor=12, micro=9) diff --git a/src/sh_edraft/cli/cpl_cli/cli.py b/src/sh_edraft/cli/cpl_cli/cli.py new file mode 100644 index 00000000..f0728d13 --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/cli.py @@ -0,0 +1,42 @@ +import sys +import traceback + +from sh_edraft.cli.cpl_cli.commands.build.build import Build +from sh_edraft.cli.cpl_cli.commands.help import Help +from sh_edraft.cli.cpl_cli.commands.new import New +from sh_edraft.cli.cpl_cli.commands.publish.publish import Publish +from sh_edraft.cli.cpl_cli.commands.version import Version +from sh_edraft.cli.interpreter.interpreter import Interpreter +from sh_edraft.console.console import Console + + +class CLI: + + def __init__(self): + self._interpreter = Interpreter() + + def setup(self): + self._interpreter.add_command(Build()) + self._interpreter.add_command(Help()) + self._interpreter.add_command(New()) + self._interpreter.add_command(Publish()) + self._interpreter.add_command(Version()) + + def main(self): + string = ' '.join(sys.argv[1:]) + try: + self._interpreter.interpret(string) + except Exception as e: + tb = traceback.format_exc() + Console.error(str(e), tb) + Console.error('Run \'cpl help\'') + + +def main(): + cli = CLI() + cli.setup() + cli.main() + + +if __name__ == '__main__': + main() diff --git a/src/sh_edraft/cli/cpl_cli/commands/__init__.py b/src/sh_edraft/cli/cpl_cli/commands/__init__.py new file mode 100644 index 00000000..27f75a8b --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/commands/__init__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +""" +sh_edraft.cli.cpl_cli.commands +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) 2020 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'sh_edraft.cli.cpl_cli.commands' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 sh-edraft.de' +__version__ = '2020.12.9' + +from collections import namedtuple + +# imports: +from .version import Version +from .help import Help +from .new import New + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major=2020, minor=12, micro=9) diff --git a/src/sh_edraft/cli/cpl_cli/commands/help.py b/src/sh_edraft/cli/cpl_cli/commands/help.py new file mode 100644 index 00000000..6ea89066 --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/commands/help.py @@ -0,0 +1,27 @@ +from sh_edraft.cli.command.base.command_base import CommandBase +from sh_edraft.console.console import Console + + +class Help(CommandBase): + + def __init__(self): + CommandBase.__init__(self) + self._aliases.append('-h') + self._aliases.append('-H') + + 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.'], + ['help (-h|-H)', 'Lists available commands and their short descriptions.'], + ['new', 'Creates a new file or package.'], + ['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.'], + ['version (-v|-V)', 'Outputs CPL CLI version.'] + ] + for name, description in commands: + Console.set_foreground_color('blue') + Console.write(f'\n\t{name} ') + Console.set_foreground_color('default') + Console.write(f'{description}') + + Console.write('\n') diff --git a/src/sh_edraft/cli/cpl_cli/commands/new.py b/src/sh_edraft/cli/cpl_cli/commands/new.py new file mode 100644 index 00000000..90ebb690 --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/commands/new.py @@ -0,0 +1,97 @@ +import os + +from sh_edraft.cli.command.base.command_base import CommandBase +from sh_edraft.console.console import Console + + +class New(CommandBase): + + def __init__(self): + CommandBase.__init__(self) + + def run(self, args: list[str]): + rel_path = f'{os.path.dirname(__file__)}/../' + if len(args) == 0: + Console.error(f'Expected arguments {args}') + Console.error('Run \'cpl help\'') + return + + elif len(args) != 2: + Console.error(f'Invalid arguments {args}') + Console.error('Run \'cpl help\'') + return + + if not os.path.isdir(f'{rel_path}/templates/{args[0]}'): + Console.error(f'Unexpected argument {args[0]}') + Console.error('Run \'cpl help\'') + + sub_args = args[1:] + + if len(sub_args) != 1: + Console.error(f'Unexpected argument {sub_args[1]}') + Console.error('Run \'cpl help\'') + + if not (sub_args[0].startswith('.') or sub_args[0].startswith('/')): + full_path = f'./{sub_args[0]}' + else: + full_path = sub_args[0] + + name = os.path.basename(full_path) + path = os.path.dirname(full_path) + + if args[0] in ['base', 'class', 'configmodel', 'enum', 'service']: + if not os.path.isdir(path): + os.makedirs(path) + else: + if not os.path.isdir(full_path): + os.makedirs(full_path) + + for r, d, f in os.walk(f'{rel_path}/templates/{args[0]}'): + for file in f: + template_content = '' + with open(f'{r}/{file}') as template: + template_content = template.read() + template.close() + + file = file.replace('txt', 'py') + if args[0] in ['base', 'class', 'configmodel', 'enum', 'service']: + suffix = None + + if args[0] == 'base': + suffix = 'base' + + elif args[0] == 'configmodel': + suffix = 'settings' + + elif args[0] == 'service': + suffix = 'service' + + if suffix is not None: + file_path = f'{path}/{name}_{suffix}.py' + else: + file_path = f'{path}/{name}.py' + else: + file_path = f'{full_path}/{file}' + + with open(file_path, 'w+') as pyfile: + if name[0].islower(): + name = f'{name[0].upper()}{name[1:]}' + + if args[0] == 'base': + template_content = template_content.replace('$Name', f'{name}Base') + pyfile.write(template_content) + + elif args[0] == 'configmodel': + template_content = template_content.replace('$Name', f'{name}Settings') + pyfile.write(template_content) + + elif args[0] == 'service': + template_content = template_content.replace('$Name', f'{name}Service') + template_content = template_content.replace('$Base', f'{name}Base') + pyfile.write(template_content) + + else: + template_content = template_content.replace('$Name', name) + pyfile.write(template_content) + + pyfile.close() diff --git a/src/sh_edraft/cli/cpl_cli/commands/publish/__init__.py b/src/sh_edraft/cli/cpl_cli/commands/publish/__init__.py new file mode 100644 index 00000000..f4af0e65 --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/commands/publish/__init__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- + +""" +sh_edraft.cli.cpl_cli.commands.publish +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) 2020 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'sh_edraft.cli.cpl_cli.commands.publish' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 sh-edraft.de' +__version__ = '2020.12.9' + +from collections import namedtuple + +# imports: +from .app import PublishApp +from .publish import Publish + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major=2020, minor=12, micro=9) diff --git a/src/sh_edraft/cli/cpl_cli/commands/publish/app.py b/src/sh_edraft/cli/cpl_cli/commands/publish/app.py new file mode 100644 index 00000000..c7ce661a --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/commands/publish/app.py @@ -0,0 +1,48 @@ +from typing import Optional + +from sh_edraft.configuration.base.configuration_base import ConfigurationBase +from sh_edraft.hosting.application_host import ApplicationHost +from sh_edraft.hosting.base.application_base import ApplicationBase +from sh_edraft.logging.logger import Logger +from sh_edraft.logging.base.logger_base import LoggerBase +from sh_edraft.publishing.publisher import Publisher +from sh_edraft.publishing.base.publisher_base import PublisherBase +from sh_edraft.service.providing.base.service_provider_base import ServiceProviderBase + + +class PublishApp(ApplicationBase): + + def __init__(self): + ApplicationBase.__init__(self) + + self._app_host: Optional[ApplicationHost] = None + self._services: Optional[ServiceProviderBase] = None + self._configuration: Optional[ConfigurationBase] = None + self._logger: Optional[LoggerBase] = None + self._publisher: Optional[PublisherBase] = None + + def create_application_host(self): + self._app_host = ApplicationHost() + self._configuration = self._app_host.configuration + self._services = self._app_host.services + + def create_configuration(self): + self._configuration.add_json_file(f'build.json') + + def create_services(self): + # Add and create logger + self._services.add_singleton(LoggerBase, Logger) + self._logger = self._services.get_service(LoggerBase) + + # Add and create publisher + self._services.add_singleton(PublisherBase, Publisher) + self._publisher: Publisher = self._services.get_service(PublisherBase) + + def main(self): + self._logger.header(f'{self._configuration.environment.application_name}:') + self._logger.debug(__name__, f'Host: {self._configuration.environment.host_name}') + self._logger.debug(__name__, f'Environment: {self._configuration.environment.environment_name}') + self._logger.debug(__name__, f'Customer: {self._configuration.environment.customer}') + self._publisher.create() + self._publisher.build() + self._publisher.publish() diff --git a/src/sh_edraft/cli/cpl_cli/commands/publish/publish.py b/src/sh_edraft/cli/cpl_cli/commands/publish/publish.py new file mode 100644 index 00000000..7e72ae3a --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/commands/publish/publish.py @@ -0,0 +1,23 @@ +from sh_edraft.cli.command.base.command_base import CommandBase +from sh_edraft.cli.cpl_cli.commands.publish.app import PublishApp +from sh_edraft.console.console import Console + + +class Publish(CommandBase): + + def __init__(self): + CommandBase.__init__(self) + self._app = PublishApp() + + self._aliases.append('-p') + self._aliases.append('-P') + + def run(self, args: list[str]): + if len(args) > 0: + Console.error(f'Invalid arguments {args}') + Console.error('Run \'cpl help\'') + + self._app.create_application_host() + self._app.create_configuration() + self._app.create_services() + self._app.main() diff --git a/src/sh_edraft/cli/cpl_cli/commands/version.py b/src/sh_edraft/cli/cpl_cli/commands/version.py new file mode 100644 index 00000000..737a69c7 --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/commands/version.py @@ -0,0 +1,42 @@ +import pkgutil +import sys +import platform + +import pkg_resources + +import sh_edraft +from sh_edraft import cli +from sh_edraft.cli.command.base.command_base import CommandBase +from sh_edraft.console.console import Console + + +class Version(CommandBase): + + def __init__(self): + CommandBase.__init__(self) + self._aliases.append('-v') + self._aliases.append('-V') + + def run(self, args: list[str]): + Console.set_foreground_color('yellow') + Console.banner('CPL CLI') + Console.set_foreground_color('default') + Console.write_line(f'Common Python Library CLI: {cli.__version__}') + Console.write_line(f'Python: {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}') + Console.write_line(f'OS: {platform.system()} {platform.processor()}') + + Console.write_line('CPL:') + packages = [] + for importer, modname, is_pkg in pkgutil.iter_modules(sh_edraft.__path__): + module = importer.find_module(modname).load_module(modname) + packages.append([f'{modname}', module.__version__]) + + Console.table(['Name', 'Version'], packages) + + Console.write_line('\nPython Packages:') + packages = [] + deps = dict(tuple(str(ws).split()) for ws in pkg_resources.working_set) + for p in deps: + packages.append([p, deps[p]]) + + Console.table(['Name', 'Version'], packages) diff --git a/src/sh_edraft/cli/cpl_cli/templates/app/__init__.txt b/src/sh_edraft/cli/cpl_cli/templates/app/__init__.txt new file mode 100644 index 00000000..2e12875a --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/templates/app/__init__.txt @@ -0,0 +1 @@ +# imports: \ No newline at end of file diff --git a/src/sh_edraft/cli/cpl_cli/templates/app/build.json b/src/sh_edraft/cli/cpl_cli/templates/app/build.json new file mode 100644 index 00000000..c6ea10bc --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/templates/app/build.json @@ -0,0 +1,22 @@ +{ + "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": "build/logs/", + "Filename": "log_$start_time.log", + "ConsoleLogLevel": "INFO", + "FileLogLevel": "INFO" + }, + "PublishSettings": { + "SourcePath": "./", + "DistPath": "build/dist", + "Templates": [], + "IncludedFiles": [], + "ExcludedFiles": [], + "TemplateEnding": "_template.txt" + } +} diff --git a/src/sh_edraft/cli/cpl_cli/templates/app/main.txt b/src/sh_edraft/cli/cpl_cli/templates/app/main.txt new file mode 100644 index 00000000..081d79dd --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/templates/app/main.txt @@ -0,0 +1,8 @@ +from program import Program + +if __name__ == '__main__': + program = Program() + program.create_application_host() + program.create_configuration() + program.create_services() + program.main() diff --git a/src/tests_dev/publisher.py b/src/sh_edraft/cli/cpl_cli/templates/app/program.txt similarity index 71% rename from src/tests_dev/publisher.py rename to src/sh_edraft/cli/cpl_cli/templates/app/program.txt index f07de2f0..890c6b73 100644 --- a/src/tests_dev/publisher.py +++ b/src/sh_edraft/cli/cpl_cli/templates/app/program.txt @@ -1,13 +1,10 @@ from typing import Optional from sh_edraft.configuration.base import ConfigurationBase -from sh_edraft.console import Console from sh_edraft.hosting import ApplicationHost from sh_edraft.hosting.base import ApplicationBase from sh_edraft.logging import Logger from sh_edraft.logging.base import LoggerBase -from sh_edraft.publishing import Publisher -from sh_edraft.publishing.base import PublisherBase from sh_edraft.service.providing.base import ServiceProviderBase @@ -20,7 +17,6 @@ class Program(ApplicationBase): self._services: Optional[ServiceProviderBase] = None self._configuration: Optional[ConfigurationBase] = None self._logger: Optional[LoggerBase] = None - self._publisher: Optional[PublisherBase] = None def create_application_host(self): self._app_host = ApplicationHost() @@ -32,7 +28,7 @@ class Program(ApplicationBase): self._configuration.add_environment_variables('CPL_') self._configuration.add_argument_variables() self._configuration.add_json_file(f'appsettings.json') - self._configuration.add_json_file(f'appsettings.{self._configuration.environment.environment_name}.json') + self._configuration.add_json_file(f'appsettings.{self._configuration.environment.environment_name}.json', optional=True) self._configuration.add_json_file(f'appsettings.{self._configuration.environment.host_name}.json', optional=True) def create_services(self): @@ -40,24 +36,8 @@ class Program(ApplicationBase): self._services.add_singleton(LoggerBase, Logger) self._logger = self._services.get_service(LoggerBase) - # Add and create publisher - self._services.add_singleton(PublisherBase, Publisher) - self._publisher: Publisher = self._services.get_service(PublisherBase) - def main(self): self._logger.header(f'{self._configuration.environment.application_name}:') self._logger.debug(__name__, f'Host: {self._configuration.environment.host_name}') self._logger.debug(__name__, f'Environment: {self._configuration.environment.environment_name}') self._logger.debug(__name__, f'Customer: {self._configuration.environment.customer}') - self._publisher.exclude('../tests') - self._publisher.exclude('../tests_dev') - self._publisher.create() - self._publisher.publish() - - -if __name__ == '__main__': - program = Program() - program.create_application_host() - program.create_configuration() - program.create_services() - program.main() diff --git a/src/sh_edraft/cli/cpl_cli/templates/base/base.txt b/src/sh_edraft/cli/cpl_cli/templates/base/base.txt new file mode 100644 index 00000000..1940e8ab --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/templates/base/base.txt @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod + + +class $Name(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + def create(self): pass diff --git a/src/sh_edraft/cli/cpl_cli/templates/class/class.txt b/src/sh_edraft/cli/cpl_cli/templates/class/class.txt new file mode 100644 index 00000000..d22b7581 --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/templates/class/class.txt @@ -0,0 +1,4 @@ +class $Name: + + def __init__(self): + pass diff --git a/src/sh_edraft/cli/cpl_cli/templates/configmodel/model.txt b/src/sh_edraft/cli/cpl_cli/templates/configmodel/model.txt new file mode 100644 index 00000000..ca37a816 --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/templates/configmodel/model.txt @@ -0,0 +1,20 @@ +import traceback + +from sh_edraft.configuration.base import ConfigurationModelBase +from sh_edraft.console import Console +from sh_edraft.console.model import ForegroundColor + + +class $Name(ConfigurationModelBase): + + def __init__(self): + ConfigurationModelBase.__init__(self) + + def from_dict(self, settings: dict): + try: + pass + except Exception as e: + Console.set_foreground_color(ForegroundColor.red) + Console.write_line(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings') + Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') + Console.set_foreground_color(ForegroundColor.default) diff --git a/src/sh_edraft/cli/cpl_cli/templates/enum/enum.txt b/src/sh_edraft/cli/cpl_cli/templates/enum/enum.txt new file mode 100644 index 00000000..a7aef900 --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/templates/enum/enum.txt @@ -0,0 +1,6 @@ +from enum import Enum + + +class $Name(Enum): + + pass diff --git a/src/sh_edraft/cli/cpl_cli/templates/service/service.txt b/src/sh_edraft/cli/cpl_cli/templates/service/service.txt new file mode 100644 index 00000000..d2add199 --- /dev/null +++ b/src/sh_edraft/cli/cpl_cli/templates/service/service.txt @@ -0,0 +1,6 @@ +class $Name($Base): + + def __init__(self): + TestBase.__init__(self) + + self.create() diff --git a/src/sh_edraft/cli/interpreter/__init__.py b/src/sh_edraft/cli/interpreter/__init__.py new file mode 100644 index 00000000..ccd63b96 --- /dev/null +++ b/src/sh_edraft/cli/interpreter/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +""" +sh_edraft.cli.interpreter +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) 2020 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'sh_edraft.cli.interpreter' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 sh-edraft.de' +__version__ = '2020.12.9' + +from collections import namedtuple + +# imports: +from .interpreter import Interpreter + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major=2020, minor=12, micro=9) diff --git a/src/sh_edraft/cli/interpreter/interpreter.py b/src/sh_edraft/cli/interpreter/interpreter.py new file mode 100644 index 00000000..d3e580e4 --- /dev/null +++ b/src/sh_edraft/cli/interpreter/interpreter.py @@ -0,0 +1,33 @@ +from sh_edraft.cli.command.base.command_base import CommandBase +from sh_edraft.console.console import Console + + +class Interpreter: + + def __init__(self): + self._commands: list[CommandBase] = [] + + def add_command(self, command: CommandBase): + self._commands.append(command) + + def remove_command(self, command: CommandBase): + self._commands.remove(command) + + def interpret(self, input_string: str): + input_list = input_string.split(' ') + command = input_list[0] + if command is None or command == '': + Console.error(f'Expected command') + Console.error('Run \'cpl help\'') + return + + args = input_list[1:] if len(input_list) > 1 else [] + + cmd = next( + (cmd for cmd in self._commands if type(cmd).__name__.lower() == command or command in cmd.aliases), + None) + if cmd is not None: + cmd.run(args) + else: + Console.error(f'Unexpected command {command}') + Console.error('Run \'cpl help\'') diff --git a/src/sh_edraft/console/console.py b/src/sh_edraft/console/console.py index 2418cf8a..c454eb81 100644 --- a/src/sh_edraft/console/console.py +++ b/src/sh_edraft/console/console.py @@ -1,5 +1,8 @@ import os from typing import Union, Optional + +import pyfiglet +from tabulate import tabulate from termcolor import colored from sh_edraft.console.model.background_color import BackgroundColor @@ -7,6 +10,8 @@ from sh_edraft.console.model.foreground_color import ForegroundColor class Console: + _is_first_write = True + _background_color: BackgroundColor = BackgroundColor.default _foreground_color: ForegroundColor = ForegroundColor.default _x: Optional[int] = None @@ -64,6 +69,9 @@ class Console: if cls._disabled: return + if cls._is_first_write: + cls._is_first_write = False + args = [] colored_args = [] @@ -88,6 +96,11 @@ class Console: Useful public methods """ + @classmethod + def banner(cls, string: str): + ascii_banner = pyfiglet.figlet_format(string) + cls.write_line(ascii_banner) + @staticmethod def clear(): os.system('cls' if os.name == 'nt' else 'clear') @@ -103,6 +116,15 @@ class Console: def disable(cls): cls._disabled = True + @classmethod + def error(cls, string: str, tb: str = None): + cls.set_foreground_color('red') + if tb is not None: + cls.write_line(f'{string} -> {tb}') + else: + cls.write_line(string) + cls.set_foreground_color('default') + @classmethod def enable(cls): cls._disabled = False @@ -126,6 +148,13 @@ class Console: cls._background_color = BackgroundColor.default cls._foreground_color = ForegroundColor.default + @classmethod + def table(cls, header: list[str], values: list[list[str]]): + table = tabulate(values, headers=header) + + Console.write_line(table) + Console.write('\n') + @classmethod def write(cls, *args): string = ' '.join(map(str, args)) @@ -139,11 +168,13 @@ class Console: @classmethod def write_line(cls, *args): string = ' '.join(map(str, args)) - cls._output('') + if not cls._is_first_write: + cls._output('') cls._output(string, end='') @classmethod def write_line_at(cls, x: int, y: int, *args): string = ' '.join(map(str, args)) - cls._output('', end='') + if not cls._is_first_write: + cls._output('', end='') cls._output(string, x, y, end='') diff --git a/src/sh_edraft/logging/logger.py b/src/sh_edraft/logging/logger.py index ec96469e..6668132e 100644 --- a/src/sh_edraft/logging/logger.py +++ b/src/sh_edraft/logging/logger.py @@ -48,7 +48,7 @@ class Logger(LoggerBase): try: # check if log file path exists if not os.path.exists(self._path): - os.mkdir(self._path) + os.makedirs(self._path) except Exception as e: self._fatal_console(__name__, 'Cannot create log dir', ex=e) diff --git a/src/sh_edraft/publishing/base/publisher_base.py b/src/sh_edraft/publishing/base/publisher_base.py index f3f899ca..092dec3d 100644 --- a/src/sh_edraft/publishing/base/publisher_base.py +++ b/src/sh_edraft/publishing/base/publisher_base.py @@ -24,4 +24,7 @@ class PublisherBase(ServiceBase): def exclude(self, path: str): pass @abstractmethod - def publish(self) -> str: pass + def build(self): pass + + @abstractmethod + def publish(self): pass diff --git a/src/sh_edraft/publishing/publisher.py b/src/sh_edraft/publishing/publisher.py index 2e922f36..9a9a1518 100644 --- a/src/sh_edraft/publishing/publisher.py +++ b/src/sh_edraft/publishing/publisher.py @@ -2,6 +2,8 @@ import os import shutil from string import Template as stringTemplate +from setuptools import sandbox + from sh_edraft.logging.base.logger_base import LoggerBase from sh_edraft.publishing.base.publisher_base import PublisherBase from sh_edraft.publishing.model.publish_settings_model import PublishSettings @@ -16,6 +18,8 @@ class Publisher(PublisherBase): self._logger: LoggerBase = logger self._publish_settings: PublishSettings = publish_settings + self._included_files: list[str] = [] + @property def source_path(self) -> str: return self._publish_settings.source_path @@ -53,10 +57,36 @@ class Publisher(PublisherBase): def _read_source_path(self): self._logger.trace(__name__, f'Started {__name__}._read_source_path') + included_files = self._publish_settings.included_files + for included in included_files: + if os.path.isdir(included): + self._publish_settings.included_files.remove(included) + + for r, d, f in os.walk(included): + for file in f: + file_path = os.path.join(self._publish_settings.source_path, r, file) + if os.path.isfile(file_path): + self._included_files.append(file_path) + else: + self._logger.fatal(__name__, f'File not found: {file}') + + elif os.path.isfile(included): + self._included_files.append(os.path.join(self._publish_settings.source_path, included)) + else: + self._logger.fatal(__name__, f'File not found: {included}') + for r, d, f in os.walk(self._publish_settings.source_path): for file in f: - if file.endswith('.py') or file in self._publish_settings.included_files: - self._publish_settings.included_files.append(os.path.join(r, file)) + is_file_excluded = False + if os.path.join(r, file) in self._publish_settings.excluded_files: + is_file_excluded = True + else: + for excluded in self._publish_settings.excluded_files: + if os.path.join(r, file).__contains__(excluded): + is_file_excluded = True + + if not is_file_excluded and file.endswith('.py') or file in self._publish_settings.included_files: + self._included_files.append(os.path.join(r, file)) self._logger.trace(__name__, f'Stopped {__name__}._read_source_path') @@ -109,7 +139,7 @@ class Publisher(PublisherBase): def _write_templates(self): self._logger.trace(__name__, f'Started {__name__}._write_templates') for template in self._publish_settings.templates: - for file in self._publish_settings.included_files: + for file in self._included_files: if os.path.basename(file) == '__init__.py' and file not in self._publish_settings.excluded_files: template_name = template.name if template.name == 'all' or template.name == '': @@ -167,7 +197,7 @@ class Publisher(PublisherBase): if self._publish_settings.dist_path.endswith('/'): dist_path = dist_path[:len(dist_path) - 1] - for file in self._publish_settings.included_files: + for file in self._included_files: is_file_excluded = False if file in self._publish_settings.excluded_files: is_file_excluded = True @@ -184,7 +214,11 @@ class Publisher(PublisherBase): elif file.startswith('.'): output_file = file.replace('.', '', 1) - output_file = f'{dist_path}{output_file}' + if output_file.__contains__('..'): + output_file = os.path.join(dist_path, os.path.basename(file)) + else: + output_file = f'{dist_path}{output_file}' + output_path = os.path.dirname(output_file) try: @@ -223,8 +257,17 @@ class Publisher(PublisherBase): self._create_dist_path() self._logger.trace(__name__, f'Stopped {__name__}.create') - def publish(self): - self._logger.trace(__name__, f'Started {__name__}.publish') + def build(self): + self._logger.trace(__name__, f'Started {__name__}.build') self._write_templates() self._copy_all_included_files() + self._logger.trace(__name__, f'Stopped {__name__}.build') + + def publish(self): + self._logger.trace(__name__, f'Started {__name__}.publish') + setup_py = os.path.join(self._publish_settings.dist_path, 'setup.py') + if not os.path.isfile(setup_py): + self._logger.fatal(__name__, f'setup.py not found in {self._publish_settings.dist_path}') + + sandbox.run_setup(os.path.abspath(setup_py), ['sdist', 'bdist_wheel']) self._logger.trace(__name__, f'Stopped {__name__}.publish')