Merge pull request '2020.12.4' (#1) from 2020.12.4 into 2020.12

Reviewed-on: http://git.sh-edraft.de/sh-edraft.de/sh_common_py_lib/pulls/1
This commit is contained in:
Sven Heidemann 2020-11-22 14:17:46 +01:00
commit d75735798f
15 changed files with 393 additions and 72 deletions

View File

@ -4,9 +4,7 @@ from abc import ABC, abstractmethod
class ConfigurationModelBase(ABC): class ConfigurationModelBase(ABC):
@abstractmethod @abstractmethod
def from_dict(self, settings: dict): def from_dict(self, settings: dict): pass
pass
@abstractmethod @abstractmethod
def to_dict(self) -> dict: def to_dict(self) -> dict: pass
pass

View File

@ -1,30 +1,18 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from sh_edraft.publish.model.template import Template
class PublisherBase(ABC): class PublisherBase(ABC):
@abstractmethod @abstractmethod
def __init__(self, source_path: str, dist_path: str, settings: list[Template]): def __init__(self): pass
self._source_path = source_path
self._dist_path = dist_path
self._settings = settings
@property @property
@abstractmethod @abstractmethod
def source_path(self) -> str: def source_path(self) -> str: pass
pass
@property @property
@abstractmethod @abstractmethod
def dist_path(self): def dist_path(self) -> str: pass
pass
@abstractmethod @abstractmethod
def create(self): def publish(self) -> str: pass
pass
@abstractmethod
def publish(self):
pass

View File

@ -1,15 +1,23 @@
import os import os
import shutil import shutil
from string import Template as stringTemplate from string import Template as stringTemplate
from typing import Optional
from sh_edraft.publish.base.publisher_base import PublisherBase from sh_edraft.publish.base.publisher_base import PublisherBase
from sh_edraft.publish.model.template import Template 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]): def __init__(self):
super().__init__(source_path, dist_path, settings) 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._included_files: list[str] = []
self._excluded_files: list[str] = [] self._excluded_files: list[str] = []
@ -24,7 +32,8 @@ class Publisher(PublisherBase):
def dist_path(self): def dist_path(self):
return self._dist_path 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: try:
if t.file_content == '': if t.file_content == '':
raise Exception(f'Template is empty: {t.template_path}') raise Exception(f'Template is empty: {t.template_path}')
@ -84,7 +93,8 @@ class Publisher(PublisherBase):
print(e) print(e)
# todo: log error # 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('/') dirs = os.path.dirname(file).split('/')
for d in dirs: for d in dirs:
if d.__contains__('.'): if d.__contains__('.'):
@ -107,11 +117,11 @@ class Publisher(PublisherBase):
if name.__contains__('.'): if name.__contains__('.'):
if template.name != name.split('.')[len(name.split('.')) - 1]: if template.name != name.split('.')[len(name.split('.')) - 1]:
break continue
else: else:
if template.name != name: if template.name != name:
break continue
try: try:
module_file_lines: list[str] = [] module_file_lines: list[str] = []
@ -153,10 +163,18 @@ class Publisher(PublisherBase):
dist_path = dist_path[:len(dist_path) - 1] dist_path = dist_path[:len(dist_path) - 1]
for file in self._included_files: 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 = '' output_file = ''
if file.startswith('..'): if file.startswith('..'):
output_file = file.replace('..', '', 1) output_file = file.replace('..', '')
elif file.startswith('.'): elif file.startswith('.'):
output_file = file.replace('.', '', 1) output_file = file.replace('.', '', 1)
@ -186,6 +204,12 @@ class Publisher(PublisherBase):
def exclude(self, path: str): def exclude(self, path: str):
self._excluded_files.append(path) 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): def create(self):
if not self._dist_path.endswith('/'): if not self._dist_path.endswith('/'):
self._dist_path += '/' self._dist_path += '/'

View File

@ -19,7 +19,8 @@ __version__ = '2020.12.0.1'
from collections import namedtuple from collections import namedtuple
# imports:
from sh_edraft.service.service_provider import ServiceProvider
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major=2020, minor=12, micro=0.1) version_info = VersionInfo(major=2020, minor=12, micro=0.1)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -1,42 +0,0 @@
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)
publisher.exclude('./test.py')
publisher.include('../LICENSE')
publisher.include('../README.md')
publisher.create()
publisher.publish()

25
src/tests/__init__.py Normal file
View File

@ -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)

56
src/tests/publisher.py Normal file
View File

@ -0,0 +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
class PublisherTest:
@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()
)
]
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')

View File

@ -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

67
src/tests/test.py Normal file
View File

@ -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()