Improved service providing and app hosting

This commit is contained in:
Sven Heidemann 2020-11-26 19:17:05 +01:00
parent c6d1dce577
commit 7d4efe7bda
9 changed files with 97 additions and 19 deletions

View File

@ -3,6 +3,8 @@ from datetime import datetime
from sh_edraft.configuration.configuration import Configuration
from sh_edraft.configuration.base.configuration_base import ConfigurationBase
from sh_edraft.hosting.base.environment_base import EnvironmentBase
from sh_edraft.hosting.hosting_environment import HostingEnvironment
from sh_edraft.hosting.application_runtime import ApplicationRuntime
from sh_edraft.hosting.base.application_host_base import ApplicationHostBase
from sh_edraft.service.service_provider import ServiceProvider
@ -17,7 +19,8 @@ class ApplicationHost(ApplicationHostBase):
self._args: list[str] = sys.argv
self._config = Configuration()
self._app_runtime = ApplicationRuntime(self._config)
self._environment = HostingEnvironment()
self._app_runtime = ApplicationRuntime(self._config, self._environment)
self._services = ServiceProvider(self._app_runtime)
self._start_time: datetime = datetime.now()
@ -27,6 +30,10 @@ class ApplicationHost(ApplicationHostBase):
def name(self) -> str:
return self._name
@property
def environment(self) -> EnvironmentBase:
return self._environment
@property
def configuration(self) -> ConfigurationBase:
return self._config

View File

@ -1,21 +1,27 @@
from datetime import datetime
from sh_edraft.configuration.base import ConfigurationBase
from sh_edraft.configuration.base.configuration_base import ConfigurationBase
from sh_edraft.hosting.base.environment_base import EnvironmentBase
from sh_edraft.hosting.base.application_runtime_base import ApplicationRuntimeBase
class ApplicationRuntime(ApplicationRuntimeBase):
def __init__(self, config: ConfigurationBase):
def __init__(self, config: ConfigurationBase, runtime: EnvironmentBase):
ApplicationRuntimeBase.__init__(self)
self._configuration = config
self._app_runtime = runtime
self._app_configuration = config
self._start_time: datetime = datetime.now()
self._end_time: datetime = datetime.now()
@property
def environment(self) -> EnvironmentBase:
return self._app_runtime
@property
def configuration(self) -> ConfigurationBase:
return self._configuration
return self._app_configuration
@property
def start_time(self) -> datetime:

View File

@ -1,6 +1,7 @@
from abc import ABC, abstractmethod
from sh_edraft.configuration.base.configuration_base import ConfigurationBase
from sh_edraft.hosting.base.environment_base import EnvironmentBase
from sh_edraft.service.base.service_provider_base import ServiceProviderBase
@ -13,6 +14,10 @@ class ApplicationHostBase(ABC):
@abstractmethod
def name(self) -> str: pass
@property
@abstractmethod
def environment(self) -> EnvironmentBase: pass
@property
@abstractmethod
def configuration(self) -> ConfigurationBase: pass

View File

@ -1,7 +1,8 @@
from abc import ABC, abstractmethod
from datetime import datetime
from sh_edraft.configuration.base import ConfigurationBase
from sh_edraft.configuration.base.configuration_base import ConfigurationBase
from sh_edraft.hosting.base.environment_base import EnvironmentBase
class ApplicationRuntimeBase(ABC):
@ -9,6 +10,10 @@ class ApplicationRuntimeBase(ABC):
@abstractmethod
def __init__(self): pass
@property
@abstractmethod
def environment(self) -> EnvironmentBase: pass
@property
@abstractmethod
def configuration(self) -> ConfigurationBase: pass

View File

@ -6,7 +6,7 @@ from sh_edraft.hosting.model.environment_name import EnvironmentName
class HostingEnvironment(EnvironmentBase):
def __init__(self, name: EnvironmentName = None, crp: str = './'):
def __init__(self, name: EnvironmentName = EnvironmentName.production, crp: str = './'):
EnvironmentBase.__init__(self)
self._name: Optional[EnvironmentName] = name

View File

@ -3,7 +3,7 @@ import os
import traceback
from string import Template
from sh_edraft.hosting.base import ApplicationHostBase
from sh_edraft.hosting.base.application_runtime_base import ApplicationRuntimeBase
from sh_edraft.logging.base.logger_base import LoggerBase
from sh_edraft.logging.model import LoggingSettings
from sh_edraft.logging.model.logging_level import LoggingLevel
@ -13,16 +13,16 @@ from sh_edraft.utils.console import Console
class Logger(LoggerBase):
def __init__(self, logging_settings: LoggingSettings, time_format: TimeFormatSettings, app_host: ApplicationHostBase):
def __init__(self, logging_settings: LoggingSettings, time_format: TimeFormatSettings, app_runtime: ApplicationRuntimeBase):
LoggerBase.__init__(self)
self._app_runtime = app_runtime
self._log_settings: LoggingSettings = logging_settings
self._time_format_settings: TimeFormatSettings = time_format
self._app_host = app_host
self._log = Template(self._log_settings.filename).substitute(
date_time_now=self._app_host.date_time_now.strftime(self._time_format_settings.date_time_format),
start_time=self._app_host.start_time.strftime(self._time_format_settings.date_time_log_format)
date_time_now=self._app_runtime.date_time_now.strftime(self._time_format_settings.date_time_format),
start_time=self._app_runtime.start_time.strftime(self._time_format_settings.date_time_log_format)
)
self._path = self._log_settings.path
self._level = self._log_settings.level
@ -47,7 +47,7 @@ class Logger(LoggerBase):
if not os.path.exists(self._path):
os.mkdir(self._path)
except Exception as e:
self.fatal(__name__, 'Cannot create log dir', ex=e)
self._fatal_console(__name__, 'Cannot create log dir', ex=e)
""" create new log file """
try:
@ -57,16 +57,19 @@ class Logger(LoggerBase):
Console.write_line(f'[{__name__}]: Using log file: {path}')
f.close()
except Exception as e:
self.fatal(__name__, 'Cannot open log file', ex=e)
self._fatal_console(__name__, 'Cannot open log file', ex=e)
def _append_log(self, string):
try:
# open log file and append always
if not os.path.isdir(self._path):
self._fatal_console(__name__, 'Log directory not found')
with open(self._path + self._log, "a+", encoding="utf-8") as f:
f.write(string + '\n')
f.close()
except Exception as e:
self.error(__name__, f'Cannot append log file, message: {string}', ex=e)
self._fatal_console(__name__, f'Cannot append log file, message: {string}', ex=e)
def _get_string(self, name: str, level: LoggingLevel, message: str) -> str:
log_level = level.name
@ -156,3 +159,18 @@ class Logger(LoggerBase):
Console.write_line(output, 'red')
exit()
def _fatal_console(self, name: str, message: str, ex: Exception = None):
output = ''
if ex is not None:
tb = traceback.format_exc()
self.error(name, message)
output = self._get_string(name, LoggingLevel.ERROR, f'{ex} -> {tb}')
else:
output = self._get_string(name, LoggingLevel.ERROR, message)
# check if message can be shown in console
if self._console.value >= LoggingLevel.FATAL.value:
Console.write_line(output, 'red')
exit()

View File

@ -18,7 +18,7 @@ class ServiceProviderBase(ServiceBase):
def add_scoped(self, service_type: Type[ServiceBase], service: Type[ServiceBase]): pass
@abstractmethod
def add_singleton(self, service_type: Type[ServiceBase], service: ServiceBase): pass
def add_singleton(self, service_type: Type[ServiceBase], service: Callable[ServiceBase]): pass
@abstractmethod
def get_service(self, instance_type: Type[ServiceBase]) -> Callable[ServiceBase]: pass

View File

@ -43,7 +43,7 @@ class ServiceProvider(ServiceProviderBase):
def add_scoped(self, service_type: Type[ServiceBase], service: Type[ServiceBase]):
self._scoped_services[service_type] = service
def add_singleton(self, service_type: Type[ServiceBase], service: ServiceBase):
def add_singleton(self, service_type: Type[ServiceBase], service: Callable[ServiceBase]):
for known_service in self._singleton_services:
if type(known_service) == type(service_type):
raise Exception(f'Service with type {type(service_type)} already exists')

View File

@ -1,7 +1,14 @@
from typing import Optional
from sh_edraft.configuration.base import ConfigurationBase
from sh_edraft.hosting import ApplicationHost
from sh_edraft.hosting.base import ApplicationBase
from sh_edraft.hosting.model import EnvironmentName
from sh_edraft.logging import Logger
from sh_edraft.logging.base import LoggerBase
from sh_edraft.logging.model import LoggingSettings
from sh_edraft.service.base import ServiceProviderBase
from sh_edraft.time.model import TimeFormatSettings
class Program(ApplicationBase):
@ -11,14 +18,44 @@ class Program(ApplicationBase):
self._app_host: Optional[ApplicationHost] = None
self._services: Optional[ServiceProviderBase] = None
self._configuration: Optional[ConfigurationBase] = None
def create_application_host(self):
self._app_host = ApplicationHost('CPL_DEV_Test')
self._services = self._app_host.services
self._configuration = self._app_host.configuration
self._app_host.environment.name = EnvironmentName.development
def create_configuration(self):
self._app_host.configuration.create()
self._configuration.create()
log_settings = LoggingSettings()
log_settings.from_dict({
"Path": "logs/",
"Filename": "log_$start_time.log",
"ConsoleLogLevel": "TRACE",
"FileLogLevel": "TRACE"
})
time_format_settings = TimeFormatSettings()
time_format_settings.from_dict({
"DateFormat": "%Y-%m-%d",
"TimeFormat": "%H:%M:%S",
"DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
"DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
})
self._configuration.add_config_by_type(LoggingSettings, log_settings)
self._configuration.add_config_by_type(TimeFormatSettings, time_format_settings)
def create_services(self):
self._app_host.services.create()
self._services.create()
self._services.add_singleton(LoggerBase, Logger)
logger: Logger = self._services.get_service(LoggerBase)
logger.create()
logger.header(self._app_host.name)
def main(self):
print('RUN')