mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-25 19:14:00 +03:00
Update examples and docs
This commit is contained in:
parent
bd5ea87ef7
commit
4cf3bdb1fb
273
README.rst
273
README.rst
|
@ -55,259 +55,66 @@ Installation
|
|||
Examples
|
||||
--------
|
||||
|
||||
API client example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
"""Pythonic way for Dependency Injection - API Client."""
|
||||
|
||||
from dependency_injector import providers
|
||||
|
||||
from mock import Mock
|
||||
|
||||
|
||||
class ApiClient(object):
|
||||
"""Some API client."""
|
||||
|
||||
def __init__(self, host, api_key):
|
||||
"""Initializer."""
|
||||
self.host = host
|
||||
self.api_key = api_key
|
||||
|
||||
def call(self, operation, data):
|
||||
"""Make some network operations."""
|
||||
print 'API call [{0}:{1}], method - {2}, data - {3}'.format(
|
||||
self.host, self.api_key, operation, repr(data))
|
||||
|
||||
|
||||
class User(object):
|
||||
"""User model."""
|
||||
|
||||
def __init__(self, id, api_client):
|
||||
"""Initializer."""
|
||||
self.id = id
|
||||
self.api_client = api_client
|
||||
|
||||
def register(self):
|
||||
"""Register user."""
|
||||
self.api_client.call('register', {'id': self.id})
|
||||
|
||||
|
||||
# Creating ApiClient and User providers:
|
||||
api_client = providers.Singleton(ApiClient,
|
||||
host='production.com',
|
||||
api_key='PROD_API_KEY')
|
||||
user_factory = providers.Factory(User,
|
||||
api_client=api_client)
|
||||
|
||||
# Creating several users and register them:
|
||||
user1 = user_factory(1)
|
||||
user1.register()
|
||||
# API call [production.com:PROD_API_KEY], method - register, data - {'id': 1}
|
||||
|
||||
user2 = user_factory(2)
|
||||
user2.register()
|
||||
# API call [production.com:PROD_API_KEY], method - register, data - {'id': 2}
|
||||
|
||||
# Mock ApiClient for testing:
|
||||
with api_client.override(Mock(ApiClient)) as api_client_mock:
|
||||
user = user_factory('test')
|
||||
user.register()
|
||||
api_client_mock().call.assert_called_with('register', {'id': 'test'})
|
||||
|
||||
|
||||
# Overriding of ApiClient on dev environment:
|
||||
api_client.override(providers.Singleton(ApiClient,
|
||||
host='localhost',
|
||||
api_key='DEV_API_KEY'))
|
||||
|
||||
user3 = user_factory(3)
|
||||
user3.register()
|
||||
# API call [localhost:DEV_API_KEY], method - register, data - {'id': 3}
|
||||
|
||||
Auth system example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
"""Pythonic way for Dependency Injection - Auth System."""
|
||||
|
||||
from dependency_injector import providers
|
||||
from dependency_injector import injections
|
||||
|
||||
|
||||
@providers.DelegatedCallable
|
||||
def get_user_info(user_id):
|
||||
"""Return user info."""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@providers.Factory
|
||||
@injections.inject(get_user_info=get_user_info)
|
||||
class AuthComponent(object):
|
||||
"""Some authentication component."""
|
||||
|
||||
def __init__(self, get_user_info):
|
||||
"""Initializer."""
|
||||
self.get_user_info = get_user_info
|
||||
|
||||
def authenticate_user(self, token):
|
||||
"""Authenticate user by token."""
|
||||
user_info = self.get_user_info(user_id=token + '1')
|
||||
return user_info
|
||||
|
||||
|
||||
print AuthComponent
|
||||
print get_user_info
|
||||
|
||||
|
||||
@providers.override(get_user_info)
|
||||
@providers.DelegatedCallable
|
||||
def get_user_info(user_id):
|
||||
"""Return user info."""
|
||||
return {'user_id': user_id}
|
||||
|
||||
|
||||
print AuthComponent().authenticate_user(token='abc')
|
||||
# {'user_id': 'abc1'}
|
||||
|
||||
Service providers catalog example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
"""Pythonic way for Dependency Injection - Service Providers Catalog."""
|
||||
"""Dependency Injector initial example."""
|
||||
|
||||
import sys
|
||||
import sqlite3
|
||||
import boto.s3.connection
|
||||
|
||||
import services
|
||||
|
||||
from dependency_injector import catalogs
|
||||
from dependency_injector import providers
|
||||
from dependency_injector import injections
|
||||
|
||||
|
||||
class UsersService(object):
|
||||
"""Users service, that has dependency on database."""
|
||||
|
||||
def __init__(self, db):
|
||||
"""Initializer."""
|
||||
self.db = db
|
||||
|
||||
|
||||
class AuthService(object):
|
||||
"""Auth service, that has dependencies on users service and database."""
|
||||
|
||||
def __init__(self, db, users_service):
|
||||
"""Initializer."""
|
||||
self.db = db
|
||||
self.users_service = users_service
|
||||
|
||||
|
||||
class Services(catalogs.DeclarativeCatalog):
|
||||
"""Catalog of service providers."""
|
||||
class Platform(catalogs.DeclarativeCatalog):
|
||||
"""Catalog of platform service providers."""
|
||||
|
||||
database = providers.Singleton(sqlite3.connect, ':memory:')
|
||||
|
||||
users = providers.Factory(UsersService,
|
||||
db=database)
|
||||
|
||||
auth = providers.Factory(AuthService,
|
||||
db=database,
|
||||
users_service=users)
|
||||
|
||||
|
||||
# Retrieving catalog providers:
|
||||
users_service = Services.users()
|
||||
auth_service = Services.auth()
|
||||
|
||||
# Making some asserts:
|
||||
assert users_service.db is auth_service.db is Services.database()
|
||||
assert isinstance(auth_service.users_service, UsersService)
|
||||
assert users_service is not Services.users()
|
||||
assert auth_service is not Services.auth()
|
||||
|
||||
|
||||
# Making some "inline" injections:
|
||||
@injections.inject(users_service=Services.users)
|
||||
@injections.inject(auth_service=Services.auth)
|
||||
@injections.inject(database=Services.database)
|
||||
def example(users_service, auth_service, database):
|
||||
"""Example callback."""
|
||||
assert users_service.db is auth_service.db
|
||||
assert auth_service.db is database
|
||||
assert database is Services.database()
|
||||
|
||||
|
||||
# Making a call of decorated callback:
|
||||
example()
|
||||
|
||||
Providing callbacks catalog example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
"""Pythonic way for Dependency Injection - Providing Callbacks Catalog."""
|
||||
|
||||
import sqlite3
|
||||
|
||||
from dependency_injector import catalogs
|
||||
from dependency_injector import providers
|
||||
from dependency_injector import injections
|
||||
|
||||
|
||||
class UsersService(object):
|
||||
"""Users service, that has dependency on database."""
|
||||
|
||||
def __init__(self, db):
|
||||
"""Initializer."""
|
||||
self.db = db
|
||||
|
||||
|
||||
class AuthService(object):
|
||||
"""Auth service, that has dependencies on users service and database."""
|
||||
|
||||
def __init__(self, db, users_service):
|
||||
"""Initializer."""
|
||||
self.db = db
|
||||
self.users_service = users_service
|
||||
s3 = providers.Singleton(boto.s3.connection.S3Connection,
|
||||
aws_access_key_id='KEY',
|
||||
aws_secret_access_key='SECRET')
|
||||
|
||||
|
||||
class Services(catalogs.DeclarativeCatalog):
|
||||
"""Catalog of service providers."""
|
||||
"""Catalog of business service providers."""
|
||||
|
||||
@providers.Singleton
|
||||
def database():
|
||||
"""Provide database connection.
|
||||
users = providers.Factory(services.Users,
|
||||
db=Platform.database)
|
||||
|
||||
:rtype: providers.Provider -> sqlite3.Connection
|
||||
"""
|
||||
return sqlite3.connect(':memory:')
|
||||
photos = providers.Factory(services.Photos,
|
||||
db=Platform.database,
|
||||
s3=Platform.s3)
|
||||
|
||||
@providers.Factory
|
||||
@injections.inject(db=database)
|
||||
def users(**kwargs):
|
||||
"""Provide users service.
|
||||
|
||||
:rtype: providers.Provider -> UsersService
|
||||
"""
|
||||
return UsersService(**kwargs)
|
||||
|
||||
@providers.Factory
|
||||
@injections.inject(db=database)
|
||||
@injections.inject(users_service=users)
|
||||
def auth(**kwargs):
|
||||
"""Provide users service.
|
||||
|
||||
:rtype: providers.Provider -> AuthService
|
||||
"""
|
||||
return AuthService(**kwargs)
|
||||
auth = providers.Factory(services.Auth,
|
||||
db=Platform.database,
|
||||
token_ttl=3600)
|
||||
|
||||
|
||||
# Retrieving catalog providers:
|
||||
users_service = Services.users()
|
||||
auth_service = Services.auth()
|
||||
@injections.inject(users_service=Services.users)
|
||||
@injections.inject(auth_service=Services.auth)
|
||||
def main(argv, users_service, auth_service):
|
||||
"""Main function."""
|
||||
login, password, photo_path = argv[1:]
|
||||
|
||||
# Making some asserts:
|
||||
assert users_service.db is auth_service.db is Services.database()
|
||||
assert isinstance(auth_service.users_service, UsersService)
|
||||
assert users_service is not Services.users()
|
||||
assert auth_service is not Services.auth()
|
||||
user = users_service.get_user(login)
|
||||
auth_service.authenticate(user, password)
|
||||
|
||||
upload_photo(user, photo_path)
|
||||
|
||||
|
||||
@injections.inject(photos_service=Services.photos)
|
||||
def upload_photo(user, photo_path, photos_service):
|
||||
"""Upload photo."""
|
||||
photos_service.upload_photo(user['id'], photo_path)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
|
||||
You can get more *Dependency Injector* examples in ``/examples`` directory on
|
||||
GitHub:
|
||||
|
@ -334,8 +141,8 @@ Your feedback is quite important!
|
|||
|
||||
|
||||
.. _PyPi: https://pypi.python.org/pypi/dependency_injector
|
||||
.. _User's guide: http://dependency_injector.readthedocs.org/en/stable/
|
||||
.. _API docs: http://dependency-injector.readthedocs.org/en/stable/api/
|
||||
.. _User's guide: http://dependency-injector.ets-labs.org/en/stable/
|
||||
.. _API docs: http://dependency-injector.ets-labs.org/en/stable/api/
|
||||
.. _SLOC: http://en.wikipedia.org/wiki/Source_lines_of_code
|
||||
.. _SOLID: http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29
|
||||
.. _IoC: http://en.wikipedia.org/wiki/Inversion_of_control
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
Examples
|
||||
========
|
||||
|
||||
.. meta::
|
||||
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control
|
||||
:description: Current section of documentation is designed to provide
|
||||
several example mini applications that are built on the top
|
||||
of inversion of control principle and powered by
|
||||
"Dependency Injector" framework.
|
||||
|
||||
Current section of documentation is designed to provide several example mini
|
||||
applications that are built on the top of inversion of control principle and
|
||||
powered by *Dependency Injector* framework.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
movie_lister
|
|
@ -0,0 +1,104 @@
|
|||
Movie lister naive example
|
||||
--------------------------
|
||||
|
||||
.. meta::
|
||||
:description: Dependency Injector is a Python dependency injection
|
||||
framework. It was designed to be unified, developer's
|
||||
friendly tool for managing any kind of Python objects and
|
||||
their dependencies in formal, pretty way.
|
||||
|
||||
This naive example was taken from Martin Fowler's article about dependency
|
||||
injection and inversion of control: http://www.martinfowler.com/articles/injection.html
|
||||
|
||||
Like Martin says:
|
||||
|
||||
.. pull-quote::
|
||||
|
||||
*Like all of my examples it's one of those super-simple examples;
|
||||
small enough to be unreal, but hopefully enough for you to visualize
|
||||
what's going on without falling into the bog of a real example.*
|
||||
|
||||
While original Martin's MovieLister example was a bit modified here, it
|
||||
makes sense to provide some description. So, the idea of this example is to
|
||||
create ``movies`` library that can be configurable to work with different
|
||||
movie databases (csv, sqlite) and provide 2 main features:
|
||||
|
||||
1. List all movies that were directed by certain person.
|
||||
2. List all movies that were released in certain year.
|
||||
|
||||
Also this example contains 3 mini applications that are based on ``movies``
|
||||
library :
|
||||
|
||||
1. ``app_csv.py`` - list movies by certain criteria from csv file database.
|
||||
2. ``app_db.py`` - list movies by certain criteria from sqlite database.
|
||||
3. ``app_db_csv.py`` - list movies by certain criteria from csv file and
|
||||
sqlite databases.
|
||||
|
||||
Instructions for running:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python create_db.py
|
||||
|
||||
python app_csv.py
|
||||
python app_db.py
|
||||
python app_db_csv.py
|
||||
|
||||
|
||||
Full code of example could be found on GitHub_.
|
||||
|
||||
Movies library
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Classes diagram:
|
||||
|
||||
.. image:: /images/miniapps/movie_lister/classes.png
|
||||
:width: 100%
|
||||
:align: center
|
||||
|
||||
|
||||
Movies library structure:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
/movies
|
||||
/__init__.py
|
||||
/finders.py
|
||||
/listers.py
|
||||
/models.py
|
||||
|
||||
|
||||
Listing of ``movies/__init__.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/movie_lister/movies/__init__.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
Csv application
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Listing of ``app_csv.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/movie_lister/app_csv.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
Database application
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Listing of ``app_db.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/movie_lister/app_db.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
Csv and database application
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Listing of ``app_db_csv.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/movie_lister/app_db_csv.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
.. _GitHub: https://github.com/ets-labs/dependency_injector/tree/master/examples/miniapps/movie_lister
|
BIN
docs/images/miniapps/movie_lister/classes.png
Normal file
BIN
docs/images/miniapps/movie_lister/classes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
|
@ -2,8 +2,7 @@ Dependency Injector --- Python dependency injection framework
|
|||
=============================================================
|
||||
|
||||
.. meta::
|
||||
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control
|
||||
:google-site-verification: mPdgVBidFHVWRNh0lhxj7q9zi-CpwIU970jINTBKLYQ
|
||||
:google-site-verification: 6it89zX0_wccKEhAqbAiYQooS95f0BA8YfesHk6bsNA
|
||||
:description: Dependency Injector is a Python dependency injection
|
||||
framework. It was designed to be unified, developer's
|
||||
friendly tool for managing any kind of Python objects and
|
||||
|
@ -63,6 +62,7 @@ Contents
|
|||
providers/index
|
||||
catalogs/index
|
||||
advanced_usage/index
|
||||
examples/index
|
||||
api/index
|
||||
main/feedback
|
||||
main/changelog
|
||||
|
|
|
@ -2,7 +2,6 @@ Dependency injection and inversion of control in Python
|
|||
-------------------------------------------------------
|
||||
|
||||
.. meta::
|
||||
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control
|
||||
:description: This article describes benefits of dependency injection and
|
||||
inversion of control for Python applications. Also it
|
||||
contains some Python examples that show how dependency
|
||||
|
|
|
@ -2,7 +2,6 @@ Introduction
|
|||
============
|
||||
|
||||
.. meta::
|
||||
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control
|
||||
:description: Current section of documentation is designed to give some
|
||||
overview about dependency injection pattern, inversion of
|
||||
control principle and "Dependency Injector" framework.
|
||||
|
|
|
@ -2,7 +2,6 @@ Key features of Dependency Injector
|
|||
-----------------------------------
|
||||
|
||||
.. meta::
|
||||
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control
|
||||
:description: This article describes key features of "Dependency Injector"
|
||||
framework. It also provides some cases and recommendations
|
||||
about usage of "Dependency Injector" framework.
|
||||
|
|
|
@ -2,7 +2,6 @@ Structure of Dependency Injector
|
|||
--------------------------------
|
||||
|
||||
.. meta::
|
||||
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control
|
||||
:description: This article describes "Dependency Injector" framework
|
||||
components and their interaction between each other.
|
||||
Catalogs, providers and injections are the former
|
||||
|
|
|
@ -2,7 +2,6 @@ What is dependency injection and inversion of control?
|
|||
------------------------------------------------------
|
||||
|
||||
.. meta::
|
||||
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control
|
||||
:description: This article provides definition of dependency injection,
|
||||
inversion of control and dependency inversion. It contains
|
||||
example code in Python that is refactored to be following
|
||||
|
|
|
@ -11,6 +11,8 @@ Development version
|
|||
-------------------
|
||||
- Add ``@copy`` decorator for copying declarative catalog providers.
|
||||
- Add line numbers for all code samples in documentation.
|
||||
- Move project documentation into organisation's domain
|
||||
(dependency-injector.ets-labs.org).
|
||||
|
||||
1.15.2
|
||||
------
|
||||
|
|
|
@ -24,7 +24,6 @@ class Catalog(catalogs.DeclarativeCatalog):
|
|||
fee=config.FEE,
|
||||
price=config.PRICE,
|
||||
timezone=config.GLOBAL.TIMEZONE)
|
||||
""":type: providers.Provider -> ObjectA"""
|
||||
|
||||
|
||||
# Setting config value and making some tests.
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
"""Pythonic way for Dependency Injection - API Client."""
|
||||
|
||||
from dependency_injector import providers
|
||||
|
||||
from mock import Mock
|
||||
|
||||
|
||||
class ApiClient(object):
|
||||
"""Some API client."""
|
||||
|
||||
def __init__(self, host, api_key):
|
||||
"""Initializer."""
|
||||
self.host = host
|
||||
self.api_key = api_key
|
||||
|
||||
def call(self, operation, data):
|
||||
"""Make some network operations."""
|
||||
print 'API call [{0}:{1}], method - {2}, data - {3}'.format(
|
||||
self.host, self.api_key, operation, repr(data))
|
||||
|
||||
|
||||
class User(object):
|
||||
"""User model."""
|
||||
|
||||
def __init__(self, id, api_client):
|
||||
"""Initializer."""
|
||||
self.id = id
|
||||
self.api_client = api_client
|
||||
|
||||
def register(self):
|
||||
"""Register user."""
|
||||
self.api_client.call('register', {'id': self.id})
|
||||
|
||||
|
||||
# Creating ApiClient and User providers:
|
||||
api_client = providers.Singleton(ApiClient,
|
||||
host='production.com',
|
||||
api_key='PROD_API_KEY')
|
||||
user_factory = providers.Factory(User,
|
||||
api_client=api_client)
|
||||
|
||||
# Creating several users and register them:
|
||||
user1 = user_factory(1)
|
||||
user1.register()
|
||||
# API call [production.com:PROD_API_KEY], method - register, data - {'id': 1}
|
||||
|
||||
user2 = user_factory(2)
|
||||
user2.register()
|
||||
# API call [production.com:PROD_API_KEY], method - register, data - {'id': 2}
|
||||
|
||||
# Mock ApiClient for testing:
|
||||
with api_client.override(Mock(ApiClient)) as api_client_mock:
|
||||
user = user_factory('test')
|
||||
user.register()
|
||||
api_client_mock().call.assert_called_with('register', {'id': 'test'})
|
||||
|
||||
|
||||
# Overriding of ApiClient on dev environment:
|
||||
api_client.override(providers.Singleton(ApiClient,
|
||||
host='localhost',
|
||||
api_key='DEV_API_KEY'))
|
||||
|
||||
user3 = user_factory(3)
|
||||
user3.register()
|
||||
# API call [localhost:DEV_API_KEY], method - register, data - {'id': 3}
|
|
@ -1,63 +0,0 @@
|
|||
"""Pythonic way for Dependency Injection - Service Providers Catalog."""
|
||||
|
||||
import sqlite3
|
||||
|
||||
from dependency_injector import catalogs
|
||||
from dependency_injector import providers
|
||||
from dependency_injector import injections
|
||||
|
||||
|
||||
class UsersService(object):
|
||||
"""Users service, that has dependency on database."""
|
||||
|
||||
def __init__(self, db):
|
||||
"""Initializer."""
|
||||
self.db = db
|
||||
|
||||
|
||||
class AuthService(object):
|
||||
"""Auth service, that has dependencies on users service and database."""
|
||||
|
||||
def __init__(self, db, users_service):
|
||||
"""Initializer."""
|
||||
self.db = db
|
||||
self.users_service = users_service
|
||||
|
||||
|
||||
class Services(catalogs.DeclarativeCatalog):
|
||||
"""Catalog of service providers."""
|
||||
|
||||
database = providers.Singleton(sqlite3.connect, ':memory:')
|
||||
|
||||
users = providers.Factory(UsersService,
|
||||
db=database)
|
||||
|
||||
auth = providers.Factory(AuthService,
|
||||
db=database,
|
||||
users_service=users)
|
||||
|
||||
|
||||
# Retrieving catalog providers:
|
||||
users_service = Services.users()
|
||||
auth_service = Services.auth()
|
||||
|
||||
# Making some asserts:
|
||||
assert users_service.db is auth_service.db is Services.database()
|
||||
assert isinstance(auth_service.users_service, UsersService)
|
||||
assert users_service is not Services.users()
|
||||
assert auth_service is not Services.auth()
|
||||
|
||||
|
||||
# Making some "inline" injections:
|
||||
@injections.inject(users_service=Services.users)
|
||||
@injections.inject(auth_service=Services.auth)
|
||||
@injections.inject(database=Services.database)
|
||||
def example(users_service, auth_service, database):
|
||||
"""Example callback."""
|
||||
assert users_service.db is auth_service.db
|
||||
assert auth_service.db is database
|
||||
assert database is Services.database()
|
||||
|
||||
|
||||
# Making a call of decorated callback:
|
||||
example()
|
|
@ -13,13 +13,10 @@ class Services(catalogs.DeclarativeCatalog):
|
|||
"""Example catalog of service providers."""
|
||||
|
||||
users = providers.Factory(services.Users)
|
||||
""":type: providers.Provider -> services.Users"""
|
||||
|
||||
auth = providers.Factory(services.Auth)
|
||||
""":type: providers.Provider -> services.Auth"""
|
||||
|
||||
photos = providers.Factory(services.Photos)
|
||||
""":type: providers.Provider -> services.Photos"""
|
||||
|
||||
|
||||
# Declaring views catalog:
|
||||
|
@ -29,12 +26,10 @@ class Views(catalogs.DeclarativeCatalog):
|
|||
auth = providers.Factory(views.Auth,
|
||||
services=Services.Bundle(Services.users,
|
||||
Services.auth))
|
||||
""":type: providers.Provider -> views.Auth"""
|
||||
|
||||
photos = providers.Factory(views.Photos,
|
||||
services=Services.Bundle(Services.users,
|
||||
Services.photos))
|
||||
""":type: providers.Provider -> views.Photos"""
|
||||
|
||||
|
||||
# Creating example views:
|
||||
|
|
|
@ -9,10 +9,8 @@ class Catalog(catalogs.DeclarativeCatalog):
|
|||
"""Providers catalog."""
|
||||
|
||||
factory1 = providers.Factory(object)
|
||||
""":type: providers.Provider -> object"""
|
||||
|
||||
factory2 = providers.Factory(object)
|
||||
""":type: providers.Provider -> object"""
|
||||
|
||||
# Creating some objects:
|
||||
object1 = Catalog.factory1()
|
||||
|
|
|
@ -8,14 +8,12 @@ class CatalogA(catalogs.DeclarativeCatalog):
|
|||
"""Example catalog A."""
|
||||
|
||||
provider1 = providers.Factory(object)
|
||||
""":type: providers.Provider -> object"""
|
||||
|
||||
|
||||
class CatalogB(CatalogA):
|
||||
"""Example catalog B."""
|
||||
|
||||
provider2 = providers.Singleton(object)
|
||||
""":type: providers.Provider -> object"""
|
||||
|
||||
|
||||
# Making some asserts for `providers` attribute:
|
||||
|
|
|
@ -27,16 +27,13 @@ class Services(catalogs.DeclarativeCatalog):
|
|||
"""Catalog of service providers."""
|
||||
|
||||
database = providers.Singleton(sqlite3.connect, ':memory:')
|
||||
""":type: providers.Provider -> sqlite3.Connection"""
|
||||
|
||||
users = providers.Factory(UsersService,
|
||||
db=database)
|
||||
""":type: providers.Provider -> UsersService"""
|
||||
|
||||
auth = providers.Factory(AuthService,
|
||||
db=database,
|
||||
users_service=users)
|
||||
""":type: providers.Provider -> AuthService"""
|
||||
|
||||
|
||||
# Retrieving service providers from catalog:
|
||||
|
|
|
@ -31,13 +31,11 @@ class Services(services.Catalog):
|
|||
users = services.Provider(UsersService,
|
||||
config={'option1': '111',
|
||||
'option2': '222'})
|
||||
""":type: services.Provider -> UsersService"""
|
||||
|
||||
auth = services.Provider(AuthService,
|
||||
config={'option3': '333',
|
||||
'option4': '444'},
|
||||
users_service=users)
|
||||
""":type: services.Provider -> AuthService"""
|
||||
|
||||
|
||||
# Creating users & auth services:
|
||||
|
|
|
@ -18,18 +18,15 @@ class Catalog(catalogs.DeclarativeCatalog):
|
|||
object1_factory = providers.Factory(Object1,
|
||||
arg1=1,
|
||||
arg2=2)
|
||||
""":type: providers.Provider -> Object1"""
|
||||
|
||||
object2_factory = providers.Factory(Object2,
|
||||
object1=object1_factory)
|
||||
""":type: providers.Provider -> Object2"""
|
||||
|
||||
|
||||
class AnotherCatalog(catalogs.DeclarativeCatalog):
|
||||
"""Overriding catalog."""
|
||||
|
||||
object2_factory = providers.Factory(ExtendedObject2)
|
||||
""":type: providers.Provider -> ExtendedObject2"""
|
||||
|
||||
|
||||
# Overriding `Catalog` with `AnotherCatalog`:
|
||||
|
|
|
@ -18,11 +18,9 @@ class Catalog(catalogs.DeclarativeCatalog):
|
|||
object1_factory = providers.Factory(Object1,
|
||||
arg1=1,
|
||||
arg2=2)
|
||||
""":type: providers.Provider -> Object1"""
|
||||
|
||||
object2_factory = providers.Factory(Object2,
|
||||
object1=object1_factory)
|
||||
""":type: providers.Provider -> Object2"""
|
||||
|
||||
|
||||
# Overriding `Catalog` with some `DynamicCatalog` instance:
|
||||
|
|
|
@ -17,11 +17,9 @@ class Catalog(catalogs.DeclarativeCatalog):
|
|||
object1_factory = providers.Factory(Object1,
|
||||
arg1=1,
|
||||
arg2=2)
|
||||
""":type: providers.Provider -> Object1"""
|
||||
|
||||
object2_factory = providers.Factory(Object2,
|
||||
object1=object1_factory)
|
||||
""":type: providers.Provider -> Object2"""
|
||||
|
||||
|
||||
# Overriding `Catalog` with `AnotherCatalog`:
|
||||
|
@ -30,7 +28,6 @@ class AnotherCatalog(catalogs.DeclarativeCatalog):
|
|||
"""Overriding catalog."""
|
||||
|
||||
object2_factory = providers.Factory(ExtendedObject2)
|
||||
""":type: providers.Provider -> ExtendedObject2"""
|
||||
|
||||
|
||||
# Creating some objects using overridden catalog:
|
||||
|
|
58
examples/initial.py
Normal file
58
examples/initial.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
"""Dependency Injector initial example."""
|
||||
|
||||
import sys
|
||||
import sqlite3
|
||||
import boto.s3.connection
|
||||
|
||||
import services
|
||||
|
||||
from dependency_injector import catalogs
|
||||
from dependency_injector import providers
|
||||
from dependency_injector import injections
|
||||
|
||||
|
||||
class Platform(catalogs.DeclarativeCatalog):
|
||||
"""Catalog of platform service providers."""
|
||||
|
||||
database = providers.Singleton(sqlite3.connect, ':memory:')
|
||||
|
||||
s3 = providers.Singleton(boto.s3.connection.S3Connection,
|
||||
aws_access_key_id='KEY',
|
||||
aws_secret_access_key='SECRET')
|
||||
|
||||
|
||||
class Services(catalogs.DeclarativeCatalog):
|
||||
"""Catalog of business service providers."""
|
||||
|
||||
users = providers.Factory(services.Users,
|
||||
db=Platform.database)
|
||||
|
||||
photos = providers.Factory(services.Photos,
|
||||
db=Platform.database,
|
||||
s3=Platform.s3)
|
||||
|
||||
auth = providers.Factory(services.Auth,
|
||||
db=Platform.database,
|
||||
token_ttl=3600)
|
||||
|
||||
|
||||
@injections.inject(users_service=Services.users)
|
||||
@injections.inject(auth_service=Services.auth)
|
||||
def main(argv, users_service, auth_service):
|
||||
"""Main function."""
|
||||
login, password, photo_path = argv[1:]
|
||||
|
||||
user = users_service.get_user(login)
|
||||
auth_service.authenticate(user, password)
|
||||
|
||||
upload_photo(user, photo_path)
|
||||
|
||||
|
||||
@injections.inject(photos_service=Services.photos)
|
||||
def upload_photo(user, photo_path, photos_service):
|
||||
"""Upload photo."""
|
||||
photos_service.upload_photo(user['id'], photo_path)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
15
examples/miniapps/api_client/api.py
Normal file
15
examples/miniapps/api_client/api.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
"""asd."""
|
||||
|
||||
|
||||
class ApiClient(object):
|
||||
"""Some API client."""
|
||||
|
||||
def __init__(self, host, api_key):
|
||||
"""Initializer."""
|
||||
self.host = host
|
||||
self.api_key = api_key
|
||||
|
||||
def call(self, operation, data):
|
||||
"""Make some network operations."""
|
||||
print 'API call [{0}:{1}], method - {2}, data - {3}'.format(
|
||||
self.host, self.api_key, operation, repr(data))
|
36
examples/miniapps/api_client/main.py
Normal file
36
examples/miniapps/api_client/main.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
"""asd."""
|
||||
|
||||
from dependency_injector import providers
|
||||
|
||||
import api
|
||||
import models
|
||||
|
||||
|
||||
# Creating ApiClient and User providers:
|
||||
api_client = providers.Singleton(api.ApiClient,
|
||||
host='production.com',
|
||||
api_key='PROD_API_KEY')
|
||||
user_factory = providers.Factory(models.User,
|
||||
api_client=api_client)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Creating several users and register them:
|
||||
user1 = user_factory(1)
|
||||
user1.register()
|
||||
# API call [production.com:PROD_API_KEY], method - register, data -
|
||||
# {'id': 1}
|
||||
|
||||
user2 = user_factory(2)
|
||||
user2.register()
|
||||
# API call [production.com:PROD_API_KEY], method - register, data -
|
||||
# {'id': 2}
|
||||
|
||||
# Overriding of ApiClient on dev environment:
|
||||
api_client.override(providers.Singleton(api.ApiClient,
|
||||
host='localhost',
|
||||
api_key='DEV_API_KEY'))
|
||||
|
||||
user3 = user_factory(3)
|
||||
user3.register()
|
||||
# API call [localhost:DEV_API_KEY], method - register, data - {'id': 3}
|
14
examples/miniapps/api_client/models.py
Normal file
14
examples/miniapps/api_client/models.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
"""asd."""
|
||||
|
||||
|
||||
class User(object):
|
||||
"""User model."""
|
||||
|
||||
def __init__(self, id, api_client):
|
||||
"""Initializer."""
|
||||
self.id = id
|
||||
self.api_client = api_client
|
||||
|
||||
def register(self):
|
||||
"""Register user."""
|
||||
self.api_client.call('register', {'id': self.id})
|
12
examples/miniapps/api_client/tests.py
Normal file
12
examples/miniapps/api_client/tests.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
"""asd."""
|
||||
|
||||
from mock import Mock
|
||||
|
||||
import main
|
||||
import api
|
||||
|
||||
# Mock ApiClient for testing:
|
||||
with main.api_client.override(Mock(api.ApiClient)) as api_client_mock:
|
||||
user = main.user_factory('test')
|
||||
user.register()
|
||||
api_client_mock().call.assert_called_with('register', {'id': 'test'})
|
10
examples/miniapps/flask_services/app.py
Normal file
10
examples/miniapps/flask_services/app.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
"""Flask application."""
|
||||
|
||||
import flask
|
||||
|
||||
|
||||
app = flask.Flask(__name__)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
8
examples/miniapps/flask_services/services/__init__.py
Normal file
8
examples/miniapps/flask_services/services/__init__.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
"""Services package."""
|
||||
|
||||
from dependency_injector import catalogs
|
||||
from dependency_injector import providers
|
||||
|
||||
|
||||
class ServicesModule(catalogs.DeclarativeCatalog):
|
||||
"""Service providers module."""
|
|
@ -5,6 +5,10 @@ module component providers - ``MoviesModule``. It is recommended to use movies
|
|||
library functionality by fetching required instances from ``MoviesModule``
|
||||
providers.
|
||||
|
||||
``MoviesModule.movie_finder`` is a factory that provides abstract component
|
||||
``finders.MovieFinder``. This provider should be overridden by provider of
|
||||
concrete finder implementation in terms of library configuration.
|
||||
|
||||
Each of ``MoviesModule`` providers could be overridden.
|
||||
"""
|
||||
|
||||
|
|
40
examples/services.py
Normal file
40
examples/services.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
"""Services module."""
|
||||
|
||||
|
||||
class Users(object):
|
||||
"""Users service."""
|
||||
|
||||
def __init__(self, db):
|
||||
"""Initializer."""
|
||||
self.db = db
|
||||
|
||||
def get_user(self, login):
|
||||
"""Return user's information by login."""
|
||||
return {'id': 1,
|
||||
'login': login,
|
||||
'password_hash': 'secret_hash'}
|
||||
|
||||
|
||||
class Auth(object):
|
||||
"""Auth service."""
|
||||
|
||||
def __init__(self, db, token_ttl):
|
||||
"""Initializer."""
|
||||
self.db = db
|
||||
self.token_ttl = token_ttl
|
||||
|
||||
def authenticate(self, user, password):
|
||||
"""Authenticate user."""
|
||||
assert user['password_hash'] == '_'.join((password, 'hash'))
|
||||
|
||||
|
||||
class Photos(object):
|
||||
"""Photos service."""
|
||||
|
||||
def __init__(self, db, s3):
|
||||
"""Initializer."""
|
||||
self.db = db
|
||||
self.s3 = s3
|
||||
|
||||
def upload_photo(self, user_id, photo_path):
|
||||
"""Upload user photo."""
|
Loading…
Reference in New Issue
Block a user