From b31c0dd23cfc4ae65805fec64c144460a02b519a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 22 Nov 2020 00:10:52 +0100 Subject: [PATCH 1/4] Fixed publisher publish relative path error --- src/sh_edraft/__init__.py | 4 ++-- src/sh_edraft/publish/publisher.py | 12 ++++++++++-- src/tests/__init__.py | 25 +++++++++++++++++++++++++ src/{test.py => tests/publisher.py} | 12 ++++++------ 4 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 src/tests/__init__.py rename src/{test.py => tests/publisher.py} (76%) diff --git a/src/sh_edraft/__init__.py b/src/sh_edraft/__init__.py index 58fb4bac..d64c519d 100644 --- a/src/sh_edraft/__init__.py +++ b/src/sh_edraft/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_edraft common python library +sh_edraft ~~~~~~~~~~~~~~~~~~~ -Library to share common classes and models used at sh-edraft.de + :copyright: (c) 2020 sh-edraft.de :license: MIT, see LICENSE for more details. diff --git a/src/sh_edraft/publish/publisher.py b/src/sh_edraft/publish/publisher.py index 75c90ce4..f7e5dc7c 100644 --- a/src/sh_edraft/publish/publisher.py +++ b/src/sh_edraft/publish/publisher.py @@ -153,10 +153,18 @@ class Publisher(PublisherBase): dist_path = dist_path[:len(dist_path) - 1] for file in self._included_files: - if file not in self._excluded_files: + is_file_excluded = False + if file in self._excluded_files: + is_file_excluded = True + else: + for excluded in self._excluded_files: + if file.__contains__(excluded): + is_file_excluded = True + + if not is_file_excluded: output_file = '' if file.startswith('..'): - output_file = file.replace('..', '', 1) + output_file = file.replace('..', '') elif file.startswith('.'): output_file = file.replace('.', '', 1) diff --git a/src/tests/__init__.py b/src/tests/__init__.py new file mode 100644 index 00000000..ce54614e --- /dev/null +++ b/src/tests/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +tests +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) 2020 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'tests' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 sh-edraft.de' +__version__ = '2020.12.0.1' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major=2020, minor=12, micro=0.1) diff --git a/src/test.py b/src/tests/publisher.py similarity index 76% rename from src/test.py rename to src/tests/publisher.py index 6bc8e8d0..b12719fc 100644 --- a/src/test.py +++ b/src/tests/publisher.py @@ -5,7 +5,7 @@ from sh_edraft.publish.model import Template if __name__ == '__main__': templates = [ Template( - '../publish_templates/*_template.txt', + '../../publish_templates/*_template.txt', '*', '', '', @@ -18,7 +18,7 @@ if __name__ == '__main__': Version(2020, 12, 0.1).to_dict() ), Template( - '../publish_templates/*_template.txt', + '../../publish_templates/*_template.txt', 'sh_edraft', 'common python library', 'Library to share common classes and models used at sh-edraft.de', @@ -32,11 +32,11 @@ if __name__ == '__main__': ) ] - publisher = Publisher('./', '../dist', templates) + publisher = Publisher('../', '../../dist', templates) - publisher.exclude('./test.py') - publisher.include('../LICENSE') - publisher.include('../README.md') + publisher.exclude('../tests/') + publisher.include('../../LICENSE') + publisher.include('../../README.md') publisher.create() publisher.publish() From e921338fe6e0395e5595ec7c1f466a0f68dfa6a8 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 22 Nov 2020 00:13:56 +0100 Subject: [PATCH 2/4] Fixed publisher publish template name error --- src/sh_edraft/__init__.py | 4 ++-- src/sh_edraft/publish/publisher.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sh_edraft/__init__.py b/src/sh_edraft/__init__.py index d64c519d..58fb4bac 100644 --- a/src/sh_edraft/__init__.py +++ b/src/sh_edraft/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """ -sh_edraft +sh_edraft common python library ~~~~~~~~~~~~~~~~~~~ - +Library to share common classes and models used at sh-edraft.de :copyright: (c) 2020 sh-edraft.de :license: MIT, see LICENSE for more details. diff --git a/src/sh_edraft/publish/publisher.py b/src/sh_edraft/publish/publisher.py index f7e5dc7c..fb82617a 100644 --- a/src/sh_edraft/publish/publisher.py +++ b/src/sh_edraft/publish/publisher.py @@ -107,11 +107,11 @@ class Publisher(PublisherBase): if name.__contains__('.'): if template.name != name.split('.')[len(name.split('.')) - 1]: - break + continue else: if template.name != name: - break + continue try: module_file_lines: list[str] = [] From bcfe6f2de4468125099da6e2c3292557223fba7a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 22 Nov 2020 14:15:39 +0100 Subject: [PATCH 3/4] Added ServiceProvider --- .../model/configuration_model_base.py | 6 +- src/sh_edraft/publish/base/publisher_base.py | 20 ++---- src/sh_edraft/publish/publisher.py | 26 +++++-- src/sh_edraft/service/__init__.py | 3 +- src/sh_edraft/service/base/__init__.py | 27 ++++++++ src/sh_edraft/service/base/provider_base.py | 30 ++++++++ src/sh_edraft/service/base/service_base.py | 13 ++++ src/sh_edraft/service/model/__init__.py | 25 +++++++ src/sh_edraft/service/model/provide_state.py | 18 +++++ src/sh_edraft/service/service_provider.py | 68 +++++++++++++++++++ 10 files changed, 210 insertions(+), 26 deletions(-) create mode 100644 src/sh_edraft/service/base/__init__.py create mode 100644 src/sh_edraft/service/base/provider_base.py create mode 100644 src/sh_edraft/service/base/service_base.py create mode 100644 src/sh_edraft/service/model/__init__.py create mode 100644 src/sh_edraft/service/model/provide_state.py create mode 100644 src/sh_edraft/service/service_provider.py diff --git a/src/sh_edraft/configuration/model/configuration_model_base.py b/src/sh_edraft/configuration/model/configuration_model_base.py index fe295727..4483a3d3 100644 --- a/src/sh_edraft/configuration/model/configuration_model_base.py +++ b/src/sh_edraft/configuration/model/configuration_model_base.py @@ -4,9 +4,7 @@ from abc import ABC, abstractmethod class ConfigurationModelBase(ABC): @abstractmethod - def from_dict(self, settings: dict): - pass + def from_dict(self, settings: dict): pass @abstractmethod - def to_dict(self) -> dict: - pass + def to_dict(self) -> dict: pass diff --git a/src/sh_edraft/publish/base/publisher_base.py b/src/sh_edraft/publish/base/publisher_base.py index 17274fdf..d8d3fdc2 100644 --- a/src/sh_edraft/publish/base/publisher_base.py +++ b/src/sh_edraft/publish/base/publisher_base.py @@ -1,30 +1,18 @@ from abc import ABC, abstractmethod -from sh_edraft.publish.model.template import Template - class PublisherBase(ABC): @abstractmethod - def __init__(self, source_path: str, dist_path: str, settings: list[Template]): - self._source_path = source_path - self._dist_path = dist_path - self._settings = settings + def __init__(self): pass @property @abstractmethod - def source_path(self) -> str: - pass + def source_path(self) -> str: pass @property @abstractmethod - def dist_path(self): - pass + def dist_path(self) -> str: pass @abstractmethod - def create(self): - pass - - @abstractmethod - def publish(self): - pass + def publish(self) -> str: pass diff --git a/src/sh_edraft/publish/publisher.py b/src/sh_edraft/publish/publisher.py index fb82617a..6241d614 100644 --- a/src/sh_edraft/publish/publisher.py +++ b/src/sh_edraft/publish/publisher.py @@ -1,15 +1,23 @@ import os import shutil from string import Template as stringTemplate +from typing import Optional from sh_edraft.publish.base.publisher_base import PublisherBase from sh_edraft.publish.model.template import Template +from sh_edraft.service.base import ServiceBase -class Publisher(PublisherBase): +class Publisher(ServiceBase, PublisherBase): - def __init__(self, source_path: str, dist_path: str, settings: list[Template]): - super().__init__(source_path, dist_path, settings) + def __init__(self): + ServiceBase.__init__(self) + PublisherBase.__init__(self) + + self._logger: Optional[None] = None + self._source_path: Optional[str] = None + self._dist_path: Optional[str] = None + self._settings: Optional[list[Template]] = None self._included_files: list[str] = [] self._excluded_files: list[str] = [] @@ -24,7 +32,8 @@ class Publisher(PublisherBase): def dist_path(self): return self._dist_path - def _get_template_output(self, t: Template, name: str, imports: str) -> str: + @staticmethod + def _get_template_output(t: Template, name: str, imports: str) -> str: try: if t.file_content == '': raise Exception(f'Template is empty: {t.template_path}') @@ -84,7 +93,8 @@ class Publisher(PublisherBase): print(e) # todo: log error - def _get_template_name_from_dirs(self, file: str) -> str: + @staticmethod + def _get_template_name_from_dirs(file: str) -> str: dirs = os.path.dirname(file).split('/') for d in dirs: if d.__contains__('.'): @@ -194,6 +204,12 @@ class Publisher(PublisherBase): def exclude(self, path: str): self._excluded_files.append(path) + def init(self, args: tuple): + self._logger = args[0] + self._source_path = args[1] + self._dist_path = args[2] + self._settings = args[3] + def create(self): if not self._dist_path.endswith('/'): self._dist_path += '/' diff --git a/src/sh_edraft/service/__init__.py b/src/sh_edraft/service/__init__.py index 070b67c3..50d977b6 100644 --- a/src/sh_edraft/service/__init__.py +++ b/src/sh_edraft/service/__init__.py @@ -19,7 +19,8 @@ __version__ = '2020.12.0.1' from collections import namedtuple - +# imports: +from sh_edraft.service.service_provider import ServiceProvider VersionInfo = namedtuple('VersionInfo', 'major minor micro') version_info = VersionInfo(major=2020, minor=12, micro=0.1) diff --git a/src/sh_edraft/service/base/__init__.py b/src/sh_edraft/service/base/__init__.py new file mode 100644 index 00000000..3af2fd19 --- /dev/null +++ b/src/sh_edraft/service/base/__init__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- + +""" +sh_edraft.service.base +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) 2020 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'sh_edraft.service.base' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 sh-edraft.de' +__version__ = '2020.12.0.1' + +from collections import namedtuple + +# imports: +from sh_edraft.service.base.service_base import ServiceBase +from sh_edraft.service.base.provider_base import ProviderBase + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major=2020, minor=12, micro=0.1) diff --git a/src/sh_edraft/service/base/provider_base.py b/src/sh_edraft/service/base/provider_base.py new file mode 100644 index 00000000..55451908 --- /dev/null +++ b/src/sh_edraft/service/base/provider_base.py @@ -0,0 +1,30 @@ +from abc import ABC, abstractmethod +from collections import Callable +from typing import Type + +from sh_edraft.service.base.service_base import ServiceBase +from sh_edraft.service.model.provide_state import ProvideState + + +class ProviderBase(ABC): + + @abstractmethod + def __init__(self): + self._transient_services: list[ProvideState] = [] + self._scoped_services: list[ProvideState] = [] + self._singleton_services: list[ServiceBase] = [] + + @abstractmethod + def add_transient(self, service: Type[ServiceBase], *args): pass + + @abstractmethod + def add_scoped(self, service: Type[ServiceBase], *args): pass + + @abstractmethod + def add_singleton(self, service: Type[ServiceBase], *args): pass + + @abstractmethod + def get_service(self, instance_type: type) -> Callable[ServiceBase]: pass + + @abstractmethod + def remove_service(self, instance_type: type): pass diff --git a/src/sh_edraft/service/base/service_base.py b/src/sh_edraft/service/base/service_base.py new file mode 100644 index 00000000..2e4a4934 --- /dev/null +++ b/src/sh_edraft/service/base/service_base.py @@ -0,0 +1,13 @@ +from abc import ABC, abstractmethod + + +class ServiceBase(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + def init(self, args: tuple): pass + + @abstractmethod + def create(self): pass diff --git a/src/sh_edraft/service/model/__init__.py b/src/sh_edraft/service/model/__init__.py new file mode 100644 index 00000000..f48cec28 --- /dev/null +++ b/src/sh_edraft/service/model/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +sh_edraft.service.model +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) 2020 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'sh_edraft.service.model' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 sh-edraft.de' +__version__ = '2020.12.0.1' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major=2020, minor=12, micro=0.1) diff --git a/src/sh_edraft/service/model/provide_state.py b/src/sh_edraft/service/model/provide_state.py new file mode 100644 index 00000000..619e0ed5 --- /dev/null +++ b/src/sh_edraft/service/model/provide_state.py @@ -0,0 +1,18 @@ +from typing import Type + +from sh_edraft.service.base import ServiceBase + + +class ProvideState: + + def __init__(self, service: Type[ServiceBase] = None, args: tuple = None): + self._service: Type[ServiceBase] = service + self._args: tuple = args + + @property + def service(self): + return self._service + + @property + def args(self) -> tuple: + return self._args diff --git a/src/sh_edraft/service/service_provider.py b/src/sh_edraft/service/service_provider.py new file mode 100644 index 00000000..b827f83d --- /dev/null +++ b/src/sh_edraft/service/service_provider.py @@ -0,0 +1,68 @@ +from collections import Callable +from typing import Type + +from termcolor import colored + +from sh_edraft.service.base.provider_base import ProviderBase +from sh_edraft.service.base.service_base import ServiceBase +from sh_edraft.service.model.provide_state import ProvideState + + +class ServiceProvider(ProviderBase): + + def __init__(self): + ProviderBase.__init__(self) + + def create(self): + pass + + @staticmethod + def _create_instance(service: type[ServiceBase], args: tuple) -> ServiceBase: + instance = service() + try: + instance.init(args) + return instance + except Exception as e: + print(colored(f'Argument error\n{e}', 'red')) + + def add_transient(self, service: Type[ServiceBase], *args): + self._transient_services.append(ProvideState(service, args)) + + def add_scoped(self, service: Type[ServiceBase], *args): + self._transient_services.append(ProvideState(service, args)) + + def add_singleton(self, service: Type[ServiceBase], *args): + for known_service in self._singleton_services: + if type(known_service) == type(service): + raise Exception(f'Service from type {type(service)} already exists') + + self._singleton_services.append(self._create_instance(service, args)) + + def get_service(self, instance_type: type) -> Callable[ServiceBase]: + for state in self._transient_services: + if state.service == instance_type: + return self._create_instance(state.service, state.args) + + for state in self._scoped_services: + if type(state.service) == instance_type: + return self._create_instance(state.service, state.args) + + for service in self._singleton_services: + if type(service) == instance_type: + return service + + def remove_service(self, instance_type: type): + for state in self._transient_services: + if state.service == instance_type: + self._transient_services.remove(state) + return + + for state in self._scoped_services: + if type(state.service) == instance_type: + self._scoped_services.remove(state) + return + + for service in self._singleton_services: + if type(service) == instance_type: + self._singleton_services.remove(service) + return From c8a7954adb29a6a36491bf10714adb7b39d9ab39 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 22 Nov 2020 14:16:08 +0100 Subject: [PATCH 4/4] Added Tester to create all tests --- src/tests/publisher.py | 84 ++++++++++++++++++++--------------- src/tests/service_provider.py | 23 ++++++++++ src/tests/test.py | 67 ++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+), 35 deletions(-) create mode 100644 src/tests/service_provider.py create mode 100644 src/tests/test.py diff --git a/src/tests/publisher.py b/src/tests/publisher.py index b12719fc..43d350c4 100644 --- a/src/tests/publisher.py +++ b/src/tests/publisher.py @@ -1,42 +1,56 @@ +import os + +from sh_edraft.service import ServiceProvider from sh_edraft.source_code.model import Version from sh_edraft.publish import Publisher from sh_edraft.publish.model import Template -if __name__ == '__main__': - templates = [ - Template( - '../../publish_templates/*_template.txt', - '*', - '', - '', - '2020', - 'sh-edraft.de', - 'MIT', - ', see LICENSE for more details.', - '', - 'Sven Heidemann', - Version(2020, 12, 0.1).to_dict() - ), - Template( - '../../publish_templates/*_template.txt', - 'sh_edraft', - 'common python library', - 'Library to share common classes and models used at sh-edraft.de', - '2020', - 'sh-edraft.de', - 'MIT', - ', see LICENSE for more details.', - '', - 'Sven Heidemann', - Version(2020, 12, 0.1).to_dict() - ) - ] - publisher = Publisher('../', '../../dist', templates) +class PublisherTest: - publisher.exclude('../tests/') - publisher.include('../../LICENSE') - publisher.include('../../README.md') + @staticmethod + def start(services: ServiceProvider): + templates = [ + Template( + '../../publish_templates/*_template.txt', + '*', + '', + '', + '2020', + 'sh-edraft.de', + 'MIT', + ', see LICENSE for more details.', + '', + 'Sven Heidemann', + Version(2020, 12, 0.1).to_dict() + ), + Template( + '../../publish_templates/*_template.txt', + 'sh_edraft', + 'common python library', + 'Library to share common classes and models used at sh-edraft.de', + '2020', + 'sh-edraft.de', + 'MIT', + ', see LICENSE for more details.', + '', + 'Sven Heidemann', + Version(2020, 12, 0.1).to_dict() + ) + ] - publisher.create() - publisher.publish() + source = '../' + dist = '../../dist' + + services.add_singleton(Publisher, None, source, dist, templates) + publisher: Publisher = services.get_service(Publisher) + + publisher.exclude('../tests/') + publisher.include('../../LICENSE') + publisher.include('../../README.md') + + publisher.create() + publisher.publish() + + if not os.path.isdir(dist): + raise Exception(f'{__name__}: Dist path was not created') diff --git a/src/tests/service_provider.py b/src/tests/service_provider.py new file mode 100644 index 00000000..06317e85 --- /dev/null +++ b/src/tests/service_provider.py @@ -0,0 +1,23 @@ +from sh_edraft.publish import Publisher +from sh_edraft.service import ServiceProvider + + +class ServiceProviderTest: + + @staticmethod + def start() -> ServiceProvider: + provider = ServiceProvider() + provider.create() + + provider.add_transient(Publisher, None, '../', '../../dist', []) + + publisher: Publisher = provider.get_service(Publisher) + + if publisher.source_path != '../' or publisher.dist_path != '../../dist': + raise Exception(f'{__name__}: Invalid value in {Publisher.__name__}') + + provider.remove_service(Publisher) + if provider.get_service(Publisher) is not None: + raise Exception(f'{__name__}: Service {Publisher.__name__} was not removed') + + return provider diff --git a/src/tests/test.py b/src/tests/test.py new file mode 100644 index 00000000..91b9bb4f --- /dev/null +++ b/src/tests/test.py @@ -0,0 +1,67 @@ +import os +import sys +from typing import Optional + +from termcolor import colored + +from sh_edraft.service import ServiceProvider +from tests.publisher import PublisherTest +from tests.service_provider import ServiceProviderTest + + +class Test: + + def __init__(self): + self._services: Optional[ServiceProvider] = None + + self._tests = [ + ServiceProviderTest, + PublisherTest + ] + + self._error: bool = False + + @staticmethod + def block_print(): + sys.stdout = open(os.devnull, 'w') + + @staticmethod + def enable_print(): + sys.stdout = sys.__stdout__ + + def success(self, message: str): + self.enable_print() + print(colored(message, 'green')) + self.block_print() + + def failed(self, message: str): + self.enable_print() + print(colored(message, 'red')) + self.block_print() + + def create(self): pass + + def start(self): + self.block_print() + + if not self._error: + try: + self._services = ServiceProviderTest.start() + self.success(f'{ServiceProviderTest.__name__} test succeeded.') + except Exception as e: + self._error = True + self.failed(f'{ServiceProviderTest.__name__} test failed!\n{e}') + + if not self._error: + try: + PublisherTest.start(self._services) + self.success(f'{PublisherTest.__name__} test succeeded.') + except Exception as e: + self._error = True + self.failed(f'{PublisherTest.__name__} test failed!\n{e}') + + +if __name__ == '__main__': + test = Test() + test.create() + test.start()