Merge branch 'concept/declarative-container-dependencies' into develop

This commit is contained in:
Roman Mogylatov 2017-12-21 22:06:22 +02:00
commit dec490291b
12 changed files with 160 additions and 0 deletions

View File

@ -0,0 +1,8 @@
Dependency Injector Bundles example
===================================
Instructions for running
.. code-block:: bash
python run.py

View File

@ -0,0 +1 @@
"""Bundles package."""

View File

@ -0,0 +1,20 @@
"""Photos bundle."""
from core import containers
from core import providers
from . import entities
from . import repositories
class Photos(containers.DeclarativeContainer):
"""Photos bundle 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)

View File

@ -0,0 +1,2 @@
class Photo(object):
pass

View File

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

View File

@ -0,0 +1,18 @@
"""Users bundle."""
from core import containers
from core import providers
from . import entities
from . import repositories
class Users(containers.DeclarativeContainer):
"""Users bundle container."""
database = providers.Dependency()
user = providers.Factory(entities.User)
user_repository = providers.Singleton(repositories.UserRepository,
object_factory=user.provider,
db=database)

View File

@ -0,0 +1,4 @@
class User(object):
def __init__(self, id):
self.id = id

View File

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

View File

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

View File

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

View File

@ -0,0 +1,30 @@
"""Example application - Bundles."""
from core import containers, providers
from bundles.users import Users
from bundles.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()