From 6a64b6e29797b3b7bf2ad6f41922b3759229a388 Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Wed, 20 Dec 2017 12:25:46 +0200 Subject: [PATCH] Add container dependencies concept --- .../miniapps/applications/example/__init__.py | 0 .../applications/example/core/__init__.py | 0 .../applications/example/core/containers.py | 45 +++++++++++++++++++ .../applications/example/core/providers.py | 18 ++++++++ .../miniapps/applications/example/main.py | 30 +++++++++++++ .../applications/example/photos/__init__.py | 20 +++++++++ .../applications/example/photos/entities.py | 2 + .../example/photos/repositories.py | 6 +++ .../applications/example/users/__init__.py | 18 ++++++++ .../applications/example/users/entities.py | 4 ++ .../example/users/repositories.py | 8 ++++ 11 files changed, 151 insertions(+) create mode 100644 examples/miniapps/applications/example/__init__.py create mode 100644 examples/miniapps/applications/example/core/__init__.py create mode 100644 examples/miniapps/applications/example/core/containers.py create mode 100644 examples/miniapps/applications/example/core/providers.py create mode 100644 examples/miniapps/applications/example/main.py create mode 100644 examples/miniapps/applications/example/photos/__init__.py create mode 100644 examples/miniapps/applications/example/photos/entities.py create mode 100644 examples/miniapps/applications/example/photos/repositories.py create mode 100644 examples/miniapps/applications/example/users/__init__.py create mode 100644 examples/miniapps/applications/example/users/entities.py create mode 100644 examples/miniapps/applications/example/users/repositories.py diff --git a/examples/miniapps/applications/example/__init__.py b/examples/miniapps/applications/example/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/examples/miniapps/applications/example/core/__init__.py b/examples/miniapps/applications/example/core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/examples/miniapps/applications/example/core/containers.py b/examples/miniapps/applications/example/core/containers.py new file mode 100644 index 00000000..79dc98ae --- /dev/null +++ b/examples/miniapps/applications/example/core/containers.py @@ -0,0 +1,45 @@ +"""Containers module.""" + +import six + +from dependency_injector import containers + +from core import providers + + +class DeclarativeContainer(containers.DeclarativeContainer): + """Declarative container.""" + + def __new__(cls, **dependencies): + """Constructor. + + :return: Dynamic container with copy of all providers. + :rtype: :py:class:`DynamicContainer` + """ + # Make copy of declarative container providers for container instance + container_providers = providers.deepcopy(cls.providers) + + # Fetch container dependencies + container_dependencies = dict() + for name, provider in six.iteritems(container_providers): + if isinstance(provider, providers.Dependency): + container_dependencies[name] = provider + + # Satisfy container dependencies + for name, dependency in six.iteritems(container_dependencies): + try: + dependency_provider = dependencies[name] + except KeyError: + raise Exception('Dependency {name} of container {container} ' + 'is not satisfied'.format( + name=name, container=cls)) + else: + dependency.provided_by(dependency_provider) + + # Create dynamic container + container = cls.instance_type() + container.provider_type = cls.provider_type + for name, provider in six.iteritems(container_providers): + setattr(container, name, provider) + + return container diff --git a/examples/miniapps/applications/example/core/providers.py b/examples/miniapps/applications/example/core/providers.py new file mode 100644 index 00000000..1010b04a --- /dev/null +++ b/examples/miniapps/applications/example/core/providers.py @@ -0,0 +1,18 @@ +"""Providers module.""" + +from dependency_injector import providers + + +Factory = providers.Factory +Singleton = providers.Singleton + + +deepcopy = providers.deepcopy + + +class Dependency(providers.ExternalDependency): + """Dependency provider.""" + + def __init__(self, type=object): + """Initializer.""" + super(Dependency, self).__init__(type) diff --git a/examples/miniapps/applications/example/main.py b/examples/miniapps/applications/example/main.py new file mode 100644 index 00000000..d2cfb23a --- /dev/null +++ b/examples/miniapps/applications/example/main.py @@ -0,0 +1,30 @@ +"""Example applications.""" + +from core import containers, providers + +from users import Users +from photos import Photos + + +class Core(containers.DeclarativeContainer): + """Core container.""" + + pgsql = providers.Singleton(object) + s3 = providers.Singleton(object) + + +if __name__ == '__main__': + # Initializing containers + core = Core() + users = Users(database=core.pgsql) + photos = Photos(database=core.pgsql, file_storage=core.s3) + + # Fetching few users + user_repository = users.user_repository() + user1 = user_repository.get(id=1) + user2 = user_repository.get(id=2) + + # Making some checks + assert user1.id == 1 + assert user2.id == 2 + assert user_repository.db is core.pgsql() diff --git a/examples/miniapps/applications/example/photos/__init__.py b/examples/miniapps/applications/example/photos/__init__.py new file mode 100644 index 00000000..63bf442a --- /dev/null +++ b/examples/miniapps/applications/example/photos/__init__.py @@ -0,0 +1,20 @@ +"""Photos package.""" + +from core import containers +from core import providers + +from . import entities +from . import repositories + + +class Photos(containers.DeclarativeContainer): + """Photos package container.""" + + database = providers.Dependency() + file_storage = providers.Dependency() + + photo = providers.Factory(entities.Photo) + photo_repository = providers.Singleton(repositories.PhotoRepository, + object_factory=photo.provider, + fs=file_storage, + db=database) diff --git a/examples/miniapps/applications/example/photos/entities.py b/examples/miniapps/applications/example/photos/entities.py new file mode 100644 index 00000000..ac8b0a62 --- /dev/null +++ b/examples/miniapps/applications/example/photos/entities.py @@ -0,0 +1,2 @@ +class Photo(object): + pass diff --git a/examples/miniapps/applications/example/photos/repositories.py b/examples/miniapps/applications/example/photos/repositories.py new file mode 100644 index 00000000..6bd2b51b --- /dev/null +++ b/examples/miniapps/applications/example/photos/repositories.py @@ -0,0 +1,6 @@ +class PhotoRepository(object): + + def __init__(self, object_factory, fs, db): + self.object_factory = object_factory + self.fs = fs + self.db = db diff --git a/examples/miniapps/applications/example/users/__init__.py b/examples/miniapps/applications/example/users/__init__.py new file mode 100644 index 00000000..af0898d8 --- /dev/null +++ b/examples/miniapps/applications/example/users/__init__.py @@ -0,0 +1,18 @@ +"""Users package.""" + +from core import containers +from core import providers + +from . import entities +from . import repositories + + +class Users(containers.DeclarativeContainer): + """Users container.""" + + database = providers.Dependency() + + user = providers.Factory(entities.User) + user_repository = providers.Singleton(repositories.UserRepository, + object_factory=user.provider, + db=database) diff --git a/examples/miniapps/applications/example/users/entities.py b/examples/miniapps/applications/example/users/entities.py new file mode 100644 index 00000000..f83a81fe --- /dev/null +++ b/examples/miniapps/applications/example/users/entities.py @@ -0,0 +1,4 @@ +class User(object): + + def __init__(self, id): + self.id = id diff --git a/examples/miniapps/applications/example/users/repositories.py b/examples/miniapps/applications/example/users/repositories.py new file mode 100644 index 00000000..97e8b392 --- /dev/null +++ b/examples/miniapps/applications/example/users/repositories.py @@ -0,0 +1,8 @@ +class UserRepository(object): + + def __init__(self, object_factory, db): + self.object_factory = object_factory + self.db = db + + def get(self, id): + return self.object_factory(id=id)