From 59bb38623ad3b58fb9ce5c6718b85b6c54869faa Mon Sep 17 00:00:00 2001 From: miragecentury Date: Thu, 8 Aug 2024 21:13:02 +0200 Subject: [PATCH] refactor(example): :recycle: implementation done --- .../core/app/abstracts/__init__.py | 25 +++++++++++++++++-- .../core/app/abstracts/config.py | 2 -- src/python_factory/example/app/app.py | 23 +++++++++++------ src/python_factory/example/app/config.py | 1 - src/python_factory/example/application.yaml | 8 ++++++ 5 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/python_factory/core/app/abstracts/__init__.py b/src/python_factory/core/app/abstracts/__init__.py index b910291..7b895fc 100644 --- a/src/python_factory/core/app/abstracts/__init__.py +++ b/src/python_factory/core/app/abstracts/__init__.py @@ -2,19 +2,31 @@ Provides the abstract class for the application. """ -from abc import ABC -from typing import cast +from typing import Generic, TypeVar, cast, get_args + +import injector from .config import AppConfigAbstract from .fastapi_abstract import FastAPIAbstract +APP_T = TypeVar("APP_T", bound="AppBase") # pylint: disable=invalid-name +CONFIG_T = TypeVar("CONFIG_T", bound=AppConfigAbstract) # pylint: disable=invalid-name + class AppBase(FastAPIAbstract): """ Application abstract class. """ + PACKAGE_NAME: str = "" + def __init__(self, config: AppConfigAbstract) -> None: + + if self.PACKAGE_NAME == "": + raise ValueError( + "The package name must be set in the concrete application class." + ) + self._config: AppConfigAbstract = config FastAPIAbstract.__init__(self=cast(FastAPIAbstract, self), config=self._config) @@ -23,3 +35,12 @@ def get_config(self) -> AppConfigAbstract: Get the application configuration. """ return self._config + + +class GenericAppModule(Generic[APP_T, CONFIG_T], injector.Module): + + def configure(self, binder: injector.Binder) -> None: + app_concrete_class, _ = get_args( + self.__orig_bases__[0] # type: ignore[attr-defined] + ) + binder.bind(interface=app_concrete_class, to=app_concrete_class) diff --git a/src/python_factory/core/app/abstracts/config.py b/src/python_factory/core/app/abstracts/config.py index f8c5e02..ab32ec6 100644 --- a/src/python_factory/core/app/abstracts/config.py +++ b/src/python_factory/core/app/abstracts/config.py @@ -7,6 +7,4 @@ class AppConfigAbstract(FastAPIConfigAbstract): - - package_name: str environment: EnvironmentEnum diff --git a/src/python_factory/example/app/app.py b/src/python_factory/example/app/app.py index b76c148..fe6b205 100644 --- a/src/python_factory/example/app/app.py +++ b/src/python_factory/example/app/app.py @@ -4,7 +4,10 @@ import injector -from python_factory.core.app import AppBase, EnvironmentEnum +from python_factory.core.app import AppBase +from python_factory.core.app.abstracts import GenericAppModule +from python_factory.core.utils.importlib import get_path_file_in_package +from python_factory.core.utils.yaml_reader import YamlFileReader from .config import AppConfig @@ -14,19 +17,25 @@ class App(AppBase): Concrete application class. """ + PACKAGE_NAME: str = "python_factory.example" + def __init__(self, config: injector.Inject[AppConfig]) -> None: super().__init__(config=config) -class AppInjectorModule(injector.Module): - def configure(self, binder: injector.Binder) -> None: - binder.bind(App, to=App) +class AppModule(GenericAppModule[App, AppConfig]): @injector.singleton @injector.provider - def app_config_provider(self) -> AppConfig: + def provider_for_app_config(self) -> AppConfig: return AppConfig( - environment=EnvironmentEnum.DEVELOPMENT, + **YamlFileReader( + file_path=get_path_file_in_package( + filename="application.yaml", package=App.PACKAGE_NAME + ), + yaml_base_key="application", + use_environment_injection=True, + ).read() ) @@ -34,4 +43,4 @@ def app_factory() -> App: """ Provides the application factory. """ - return injector.Injector(modules=[AppInjectorModule]).get(interface=App) + return injector.Injector(modules=[AppModule]).get(interface=App) diff --git a/src/python_factory/example/app/config.py b/src/python_factory/example/app/config.py index 668847e..5ca62e2 100644 --- a/src/python_factory/example/app/config.py +++ b/src/python_factory/example/app/config.py @@ -6,6 +6,5 @@ class AppConfig(AppConfigAbstract): - package_name: str = "python_factory.example" title: str = "Python Factory Example" description: str = "An example application for Python Factory." diff --git a/src/python_factory/example/application.yaml b/src/python_factory/example/application.yaml index e69de29..ea1cdf7 100644 --- a/src/python_factory/example/application.yaml +++ b/src/python_factory/example/application.yaml @@ -0,0 +1,8 @@ +--- +application: + title: Python Factory Example + description: An example application for Python Factory + version: 0.1.0 + environment: ${ENVIRONMENT:development} + debug: ${DEBUG:false} + reload: ${RELOAD:false}