From 20339af52bfeb45a03054a364df2992979479fc7 Mon Sep 17 00:00:00 2001 From: qingsong Date: Sun, 10 Dec 2023 13:25:16 +0800 Subject: [PATCH] update decoupled-example with abstraction layer --- docs/examples/decoupled-packages.rst | 31 +++++++++++++++++++ .../decoupled-packages/example/__main__.py | 15 +++++---- .../example/abstraction/__init__.py | 1 + .../example/abstraction/analytics/__init__.py | 1 + .../example/abstraction/analytics/services.py | 19 ++++++++++++ .../example/abstraction/photo/__init__.py | 1 + .../example/abstraction/photo/repositories.py | 11 +++++++ .../example/abstraction/user/__init__.py | 1 + .../example/abstraction/user/repositories.py | 12 +++++++ .../example/analytics/containers.py | 7 +++-- .../example/analytics/services.py | 18 ++++++++--- .../example/photo/repositories.py | 5 ++- .../example/user/repositories.py | 4 ++- 13 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 examples/miniapps/decoupled-packages/example/abstraction/__init__.py create mode 100644 examples/miniapps/decoupled-packages/example/abstraction/analytics/__init__.py create mode 100644 examples/miniapps/decoupled-packages/example/abstraction/analytics/services.py create mode 100644 examples/miniapps/decoupled-packages/example/abstraction/photo/__init__.py create mode 100644 examples/miniapps/decoupled-packages/example/abstraction/photo/repositories.py create mode 100644 examples/miniapps/decoupled-packages/example/abstraction/user/__init__.py create mode 100644 examples/miniapps/decoupled-packages/example/abstraction/user/repositories.py diff --git a/docs/examples/decoupled-packages.rst b/docs/examples/decoupled-packages.rst index abb4c6ab..998b888e 100644 --- a/docs/examples/decoupled-packages.rst +++ b/docs/examples/decoupled-packages.rst @@ -55,6 +55,17 @@ file. ./ ├── example/ + │ ├── abstraction + │ │ ├── __init__.py + │ │ ├── analytics + │ │ │ ├── __init__.py + │ │ │ └── services.py + │ │ ├── photo + │ │ │ ├── __init__.py + │ │ │ └── repositories.py + │ │ └── user + │ │ ├── __init__.py + │ │ └── repositories.py │ ├── analytics/ │ │ ├── __init__.py │ │ ├── containers.py @@ -75,6 +86,26 @@ file. ├── config.ini └── requirements.txt + +Abstraction +------------------ + +Listing of the ``example/abstraction/user/repositories.py``: + +.. literalinclude:: ../../examples/miniapps/decoupled-packages/example/abstraction/user/repositories.py + :language: python + +Listing of the ``example/abstraction/photo/repositories.py``: + +.. literalinclude:: ../../examples/miniapps/decoupled-packages/example/abstraction/photo/repositories.py + :language: python + +Listing of the ``example/abstraction/analytics/services.py``: + +.. literalinclude:: ../../examples/miniapps/decoupled-packages/example/abstraction/analytics/services.py + :language: python + + Package containers ------------------ diff --git a/examples/miniapps/decoupled-packages/example/__main__.py b/examples/miniapps/decoupled-packages/example/__main__.py index 11bf4202..506faa71 100644 --- a/examples/miniapps/decoupled-packages/example/__main__.py +++ b/examples/miniapps/decoupled-packages/example/__main__.py @@ -2,21 +2,22 @@ from dependency_injector.wiring import Provide, inject -from .user.repositories import UserRepository -from .photo.repositories import PhotoRepository -from .analytics.services import AggregationService +from .abstraction.user.repositories import UserRepositoryMeta +from .abstraction.photo.repositories import PhotoRepositoryMeta +from .abstraction.analytics.services import AggregationServiceMeta + from .containers import ApplicationContainer @inject def main( - user_repository: UserRepository = Provide[ + user_repository: UserRepositoryMeta = Provide[ ApplicationContainer.user_package.user_repository ], - photo_repository: PhotoRepository = Provide[ + photo_repository: PhotoRepositoryMeta = Provide[ ApplicationContainer.photo_package.photo_repository ], - aggregation_service: AggregationService = Provide[ + aggregation_service: AggregationServiceMeta = Provide[ ApplicationContainer.analytics_package.aggregation_service ], ) -> None: @@ -32,6 +33,8 @@ def main( assert aggregation_service.photo_repository is photo_repository print("Aggregate analytics from user and photo packages") + aggregation_service.call_user_photo() + if __name__ == "__main__": application = ApplicationContainer() diff --git a/examples/miniapps/decoupled-packages/example/abstraction/__init__.py b/examples/miniapps/decoupled-packages/example/abstraction/__init__.py new file mode 100644 index 00000000..75edeb00 --- /dev/null +++ b/examples/miniapps/decoupled-packages/example/abstraction/__init__.py @@ -0,0 +1 @@ +"""abstraction package.""" diff --git a/examples/miniapps/decoupled-packages/example/abstraction/analytics/__init__.py b/examples/miniapps/decoupled-packages/example/abstraction/analytics/__init__.py new file mode 100644 index 00000000..b4d87a9a --- /dev/null +++ b/examples/miniapps/decoupled-packages/example/abstraction/analytics/__init__.py @@ -0,0 +1 @@ +"""abstraction analytics package.""" diff --git a/examples/miniapps/decoupled-packages/example/abstraction/analytics/services.py b/examples/miniapps/decoupled-packages/example/abstraction/analytics/services.py new file mode 100644 index 00000000..5ddcd2e5 --- /dev/null +++ b/examples/miniapps/decoupled-packages/example/abstraction/analytics/services.py @@ -0,0 +1,19 @@ +"""Analytics services module.""" + +import abc + + +from ..photo.repositories import PhotoRepositoryMeta +from ..user.repositories import UserRepositoryMeta + + +class AggregationServiceMeta(metaclass=abc.ABCMeta): + + def __init__(self, user_repository: UserRepositoryMeta, photo_repository: PhotoRepositoryMeta): + self.user_repository: UserRepositoryMeta = user_repository + self.photo_repository: PhotoRepositoryMeta = photo_repository + + @abc.abstractmethod + def call_user_photo(self): + """Must be implemented in order to instantiate.""" + pass diff --git a/examples/miniapps/decoupled-packages/example/abstraction/photo/__init__.py b/examples/miniapps/decoupled-packages/example/abstraction/photo/__init__.py new file mode 100644 index 00000000..4034762c --- /dev/null +++ b/examples/miniapps/decoupled-packages/example/abstraction/photo/__init__.py @@ -0,0 +1 @@ +"""abstraction photo package.""" diff --git a/examples/miniapps/decoupled-packages/example/abstraction/photo/repositories.py b/examples/miniapps/decoupled-packages/example/abstraction/photo/repositories.py new file mode 100644 index 00000000..e2286e53 --- /dev/null +++ b/examples/miniapps/decoupled-packages/example/abstraction/photo/repositories.py @@ -0,0 +1,11 @@ +"""Photo repositories Meta module.""" + +import abc + + +class PhotoRepositoryMeta(metaclass=abc.ABCMeta): + + @abc.abstractmethod + def get_photos(self, user_id): + """Must be implemented in order to instantiate.""" + pass diff --git a/examples/miniapps/decoupled-packages/example/abstraction/user/__init__.py b/examples/miniapps/decoupled-packages/example/abstraction/user/__init__.py new file mode 100644 index 00000000..eb66704c --- /dev/null +++ b/examples/miniapps/decoupled-packages/example/abstraction/user/__init__.py @@ -0,0 +1 @@ +"""abstraction user package.""" diff --git a/examples/miniapps/decoupled-packages/example/abstraction/user/repositories.py b/examples/miniapps/decoupled-packages/example/abstraction/user/repositories.py new file mode 100644 index 00000000..fc5e1dc0 --- /dev/null +++ b/examples/miniapps/decoupled-packages/example/abstraction/user/repositories.py @@ -0,0 +1,12 @@ +"""User repositories meta module.""" + + +import abc + + +class UserRepositoryMeta(metaclass=abc.ABCMeta): + + @abc.abstractmethod + def get(self, id): + """Must be implemented in order to instantiate.""" + pass diff --git a/examples/miniapps/decoupled-packages/example/analytics/containers.py b/examples/miniapps/decoupled-packages/example/analytics/containers.py index c4b5abba..455c79de 100644 --- a/examples/miniapps/decoupled-packages/example/analytics/containers.py +++ b/examples/miniapps/decoupled-packages/example/analytics/containers.py @@ -4,11 +4,14 @@ from dependency_injector import containers, providers from . import services +from ..abstraction.photo.repositories import PhotoRepositoryMeta +from ..abstraction.user.repositories import UserRepositoryMeta + class AnalyticsContainer(containers.DeclarativeContainer): - user_repository = providers.Dependency() - photo_repository = providers.Dependency() + user_repository: UserRepositoryMeta = providers.Dependency() + photo_repository: PhotoRepositoryMeta = providers.Dependency() aggregation_service = providers.Singleton( services.AggregationService, diff --git a/examples/miniapps/decoupled-packages/example/analytics/services.py b/examples/miniapps/decoupled-packages/example/analytics/services.py index 46b42ae8..36bb764d 100644 --- a/examples/miniapps/decoupled-packages/example/analytics/services.py +++ b/examples/miniapps/decoupled-packages/example/analytics/services.py @@ -1,8 +1,18 @@ """Analytics services module.""" -class AggregationService: +from ..abstraction.analytics.services import AggregationServiceMeta +from ..abstraction.photo.repositories import PhotoRepositoryMeta +from ..abstraction.user.repositories import UserRepositoryMeta - def __init__(self, user_repository, photo_repository): - self.user_repository = user_repository - self.photo_repository = photo_repository + +class AggregationService(AggregationServiceMeta): + + def __init__(self, user_repository: UserRepositoryMeta, photo_repository: PhotoRepositoryMeta): + self.user_repository: UserRepositoryMeta = user_repository + self.photo_repository: PhotoRepositoryMeta = photo_repository + + def call_user_photo(self): + user1 = self.user_repository.get(id=1) + user1_photos = self.photo_repository.get_photos(user1.id) + print(f"Retrieve user id={user1.id}, photos count={len(user1_photos)} from aggregation service.") diff --git a/examples/miniapps/decoupled-packages/example/photo/repositories.py b/examples/miniapps/decoupled-packages/example/photo/repositories.py index b3c3d3b4..fd76b7df 100644 --- a/examples/miniapps/decoupled-packages/example/photo/repositories.py +++ b/examples/miniapps/decoupled-packages/example/photo/repositories.py @@ -1,7 +1,10 @@ """Photo repositories module.""" -class PhotoRepository: +from ..abstraction.photo.repositories import PhotoRepositoryMeta + + +class PhotoRepository(PhotoRepositoryMeta): def __init__(self, entity_factory, fs, db): self.entity_factory = entity_factory diff --git a/examples/miniapps/decoupled-packages/example/user/repositories.py b/examples/miniapps/decoupled-packages/example/user/repositories.py index 75392433..bfa47065 100644 --- a/examples/miniapps/decoupled-packages/example/user/repositories.py +++ b/examples/miniapps/decoupled-packages/example/user/repositories.py @@ -1,7 +1,9 @@ """User repositories module.""" +from ..abstraction.user.repositories import UserRepositoryMeta -class UserRepository: + +class UserRepository(UserRepositoryMeta): def __init__(self, entity_factory, db): self.entity_factory = entity_factory