From bcfe6f2de4468125099da6e2c3292557223fba7a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 22 Nov 2020 14:15:39 +0100 Subject: [PATCH] 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