mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-29 21:14:00 +03:00
Merge branch 'release/3.12.1' into master
This commit is contained in:
commit
83053ad49e
|
@ -1,6 +1,7 @@
|
|||
sudo: false
|
||||
install:
|
||||
- pip install tox
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == 3.3 ]]; then pip install virtualenv==15.2.0; fi
|
||||
script:
|
||||
- tox
|
||||
language:
|
||||
|
|
107
README.rst
107
README.rst
|
@ -270,9 +270,9 @@ Dependency Injector in action
|
|||
-----------------------------
|
||||
|
||||
Brief example below is a simplified version of inversion of control
|
||||
containters from one of the real-life applications. This example demonstrates
|
||||
usage of *Dependency Injector* inversion of control containers & providers
|
||||
for specifying all application components and their dependencies beetween
|
||||
container from one of the real-life applications. This example demonstrates
|
||||
usage of *Dependency Injector* inversion of control container & providers
|
||||
for specifying all application components and their dependencies between
|
||||
each other in one module. Besides other listed above advantages, it gives a
|
||||
great opportunity to control & manage application's structure in one place.
|
||||
|
||||
|
@ -285,82 +285,89 @@ great opportunity to control & manage application's structure in one place.
|
|||
|
||||
import boto3
|
||||
|
||||
import example.main
|
||||
import example.services
|
||||
|
||||
import dependency_injector.containers as containers
|
||||
import dependency_injector.providers as providers
|
||||
from dependency_injector import containers, providers
|
||||
from example import services, main
|
||||
|
||||
|
||||
class Core(containers.DeclarativeContainer):
|
||||
"""IoC container of core component providers."""
|
||||
class IocContainer(containers.DeclarativeContainer):
|
||||
"""Application IoC container."""
|
||||
|
||||
config = providers.Configuration('config')
|
||||
|
||||
logger = providers.Singleton(logging.Logger, name='example')
|
||||
|
||||
# Gateways
|
||||
|
||||
class Gateways(containers.DeclarativeContainer):
|
||||
"""IoC container of gateway (API clients to remote services) providers."""
|
||||
database_client = providers.Singleton(sqlite3.connect, config.database.dsn)
|
||||
|
||||
database = providers.Singleton(sqlite3.connect, Core.config.database.dsn)
|
||||
|
||||
s3 = providers.Singleton(
|
||||
s3_client = providers.Singleton(
|
||||
boto3.client, 's3',
|
||||
aws_access_key_id=Core.config.aws.access_key_id,
|
||||
aws_secret_access_key=Core.config.aws.secret_access_key)
|
||||
aws_access_key_id=config.aws.access_key_id,
|
||||
aws_secret_access_key=config.aws.secret_access_key
|
||||
)
|
||||
|
||||
# Services
|
||||
|
||||
class Services(containers.DeclarativeContainer):
|
||||
"""IoC container of business service providers."""
|
||||
users_service = providers.Factory(
|
||||
services.UsersService,
|
||||
db=database_client,
|
||||
logger=logger
|
||||
)
|
||||
|
||||
users = providers.Factory(example.services.UsersService,
|
||||
db=Gateways.database,
|
||||
logger=Core.logger)
|
||||
auth_service = providers.Factory(
|
||||
services.AuthService,
|
||||
token_ttl=config.auth.token_ttl,
|
||||
db=database_client,
|
||||
logger=logger
|
||||
)
|
||||
|
||||
auth = providers.Factory(example.services.AuthService,
|
||||
db=Gateways.database,
|
||||
logger=Core.logger,
|
||||
token_ttl=Core.config.auth.token_ttl)
|
||||
photos_service = providers.Factory(
|
||||
services.PhotosService,
|
||||
db=database_client,
|
||||
s3=s3_client,
|
||||
logger=logger
|
||||
)
|
||||
|
||||
photos = providers.Factory(example.services.PhotosService,
|
||||
db=Gateways.database,
|
||||
s3=Gateways.s3,
|
||||
logger=Core.logger)
|
||||
# Misc
|
||||
|
||||
|
||||
class Application(containers.DeclarativeContainer):
|
||||
"""IoC container of application component providers."""
|
||||
|
||||
main = providers.Callable(example.main.main,
|
||||
users_service=Services.users,
|
||||
auth_service=Services.auth,
|
||||
photos_service=Services.photos)
|
||||
main = providers.Callable(
|
||||
main.main,
|
||||
users_service=users_service,
|
||||
auth_service=auth_service,
|
||||
photos_service=photos_service
|
||||
)
|
||||
|
||||
Next example demonstrates run of example application defined above:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
"""Run example application."""
|
||||
"""Run example of dependency injection in Python."""
|
||||
|
||||
import sys
|
||||
import logging
|
||||
|
||||
from containers import Core, Application
|
||||
from container import IocContainer
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Configure platform:
|
||||
Core.config.override({'database': {'dsn': ':memory:'},
|
||||
'aws': {'access_key_id': 'KEY',
|
||||
'secret_access_key': 'SECRET'},
|
||||
'auth': {'token_ttl': 3600}})
|
||||
Core.logger().addHandler(logging.StreamHandler(sys.stdout))
|
||||
# Configure container:
|
||||
container = IocContainer(
|
||||
config={
|
||||
'database': {
|
||||
'dsn': ':memory:'
|
||||
},
|
||||
'aws': {
|
||||
'access_key_id': 'KEY',
|
||||
'secret_access_key': 'SECRET'
|
||||
},
|
||||
'auth': {
|
||||
'token_ttl': 3600
|
||||
}
|
||||
}
|
||||
)
|
||||
container.logger().addHandler(logging.StreamHandler(sys.stdout))
|
||||
|
||||
# Run application:
|
||||
Application.main(uid=sys.argv[1],
|
||||
password=sys.argv[2],
|
||||
photo=sys.argv[3])
|
||||
container.main(*sys.argv[1:])
|
||||
|
||||
You can get more *Dependency Injector* examples in ``/examples`` directory on
|
||||
GitHub:
|
||||
|
|
|
@ -16,6 +16,8 @@ and powered by *Dependency Injector* framework.
|
|||
:maxdepth: 2
|
||||
|
||||
movie_lister
|
||||
services_miniapp
|
||||
services_miniapp_v1
|
||||
services_miniapp_v2
|
||||
bundles_miniapp
|
||||
use_cases_miniapp
|
||||
password_hashing_miniapp
|
||||
|
|
19
docs/examples/password_hashing_miniapp.rst
Normal file
19
docs/examples/password_hashing_miniapp.rst
Normal file
|
@ -0,0 +1,19 @@
|
|||
Dependency injection and password hashing in Python
|
||||
===================================================
|
||||
|
||||
Small example that demonstrates using of dependency injection for user
|
||||
password hashing.
|
||||
|
||||
Instructions for running:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python example.py
|
||||
|
||||
Listing of ``example.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/password_hashing/example.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
.. disqus::
|
|
@ -1,5 +1,5 @@
|
|||
Services mini application example
|
||||
---------------------------------
|
||||
Services mini application example (v1 - multiple containers)
|
||||
------------------------------------------------------------
|
||||
|
||||
.. meta::
|
||||
:description: "Services miniapp" is an example mini application that
|
||||
|
@ -7,7 +7,8 @@ Services mini application example
|
|||
some standard and 3rd-party libraries for logging,
|
||||
interaction with database and remote service via API.
|
||||
"Services miniapp" example demonstrates usage of
|
||||
Dependency Injector for creating several IoC containers.
|
||||
Dependency Injector for creating several inversion of control /
|
||||
dependency injection containers.
|
||||
|
||||
"Services miniapp" is an example mini application that consists from several
|
||||
services that have dependencies on some standard and 3rd-party libraries for
|
||||
|
@ -44,13 +45,13 @@ Example application structure:
|
|||
|
||||
Listing of ``example/services.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/services/example/services.py
|
||||
.. literalinclude:: ../../examples/miniapps/services_v1/example/services.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
Listing of ``example/main.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/services/example/main.py
|
||||
.. literalinclude:: ../../examples/miniapps/services_v1/example/main.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
|
@ -59,7 +60,7 @@ IoC containers
|
|||
|
||||
Listing of ``containers.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/services/containers.py
|
||||
.. literalinclude:: ../../examples/miniapps/services_v1/containers.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
|
@ -68,7 +69,7 @@ Run application
|
|||
|
||||
Listing of ``run.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/services/run.py
|
||||
.. literalinclude:: ../../examples/miniapps/services_v1/run.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
77
docs/examples/services_miniapp_v2.rst
Normal file
77
docs/examples/services_miniapp_v2.rst
Normal file
|
@ -0,0 +1,77 @@
|
|||
Services mini application example (v2 - single container)
|
||||
---------------------------------------------------------
|
||||
|
||||
.. meta::
|
||||
:description: "Services miniapp" is an example mini application that
|
||||
consists from several services that have dependencies on
|
||||
some standard and 3rd-party libraries for logging,
|
||||
interaction with database and remote service via API.
|
||||
"Services miniapp" example demonstrates usage of
|
||||
Dependency Injector for creating inversion of control /
|
||||
dependency injection container.
|
||||
|
||||
"Services miniapp" is an example mini application that consists from several
|
||||
services that have dependencies on some standard and 3rd-party libraries for
|
||||
logging, interaction with database and remote service calls via API.
|
||||
|
||||
"Services miniapp" example demonstrates usage of
|
||||
:doc:`Dependency Injector <../index>` for creating IoC container.
|
||||
|
||||
Instructions for running:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python run.py 1 secret photo.jpg
|
||||
|
||||
Example application
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Classes diagram:
|
||||
|
||||
.. image:: /images/miniapps/services/classes.png
|
||||
:width: 100%
|
||||
:align: center
|
||||
|
||||
|
||||
Example application structure:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
/example
|
||||
/__init__.py
|
||||
/main.py
|
||||
/services.py
|
||||
|
||||
|
||||
Listing of ``example/services.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/services_v2/example/services.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
Listing of ``example/main.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/services_v2/example/main.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
IoC container
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Listing of ``container.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/services_v2/container.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
Run application
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Listing of ``run.py``:
|
||||
|
||||
.. literalinclude:: ../../examples/miniapps/services_v2/run.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
|
||||
.. disqus::
|
|
@ -7,6 +7,18 @@ that were made in every particular version.
|
|||
From version 0.7.6 *Dependency Injector* framework strictly
|
||||
follows `Semantic versioning`_
|
||||
|
||||
3.12.1
|
||||
------
|
||||
- Update main page example from "services_v1" to "services_v2".
|
||||
- Fix few typos on main page.
|
||||
- Add new example miniapp "password_hashing".
|
||||
- Add new example miniapp "services_v2".
|
||||
- Rename example miniapp "services" to "services_v1".
|
||||
- Fix incompatibility issue between Python 3.3, pip 10.0.0 and virtualenv
|
||||
16.0.0 (`details <https://github.com/awslabs/base64io-python/issues/4>`_)
|
||||
that caused failures of Python 3.3 tests on Travis.
|
||||
- Regenerate C sources using Cython 0.28.3.
|
||||
|
||||
3.12.0
|
||||
------
|
||||
- Regenerate C sources using Cython 0.28.2.
|
||||
|
|
12
examples/miniapps/password_hashing/README.rst
Normal file
12
examples/miniapps/password_hashing/README.rst
Normal file
|
@ -0,0 +1,12 @@
|
|||
Dependency injection and password hashing in Python
|
||||
===================================================
|
||||
|
||||
Small example that demonstrates using of dependency injection for user
|
||||
password hashing.
|
||||
|
||||
|
||||
instructions for running:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python example.py
|
42
examples/miniapps/password_hashing/example.py
Normal file
42
examples/miniapps/password_hashing/example.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
"""Example of dependency injection and password hashing in Python."""
|
||||
|
||||
import passlib.hash
|
||||
|
||||
import dependency_injector.containers as containers
|
||||
import dependency_injector.providers as providers
|
||||
|
||||
|
||||
class UsersService(object):
|
||||
"""Users service."""
|
||||
|
||||
def __init__(self, password_hasher):
|
||||
"""Initializer."""
|
||||
self._password_hasher = password_hasher
|
||||
|
||||
def create_user(self, name, password):
|
||||
"""Create user with hashed password."""
|
||||
hashed_password = self._password_hasher(password)
|
||||
return dict(name=name, password=hashed_password)
|
||||
|
||||
|
||||
class Container(containers.DeclarativeContainer):
|
||||
"""Inversion of control container."""
|
||||
|
||||
password_hasher = providers.Callable(
|
||||
passlib.hash.sha256_crypt.encrypt,
|
||||
salt_size=16,
|
||||
rounds=10000)
|
||||
|
||||
users_service = providers.Factory(
|
||||
UsersService,
|
||||
password_hasher=password_hasher.provider)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
container = Container()
|
||||
users_service = container.users_service()
|
||||
|
||||
user1 = users_service.create_user(name='Roman', password='secret1')
|
||||
user2 = users_service.create_user(name='Vitaly', password='secret2')
|
||||
|
||||
print(user1, user2)
|
|
@ -1,27 +0,0 @@
|
|||
"""Example main module."""
|
||||
|
||||
|
||||
def main(uid, password, photo, users_service, auth_service, photos_service):
|
||||
"""Authenticate user and upload photo.
|
||||
|
||||
:param uid: User identifier.
|
||||
:type uid: int
|
||||
|
||||
:param password: User's password for verification.
|
||||
:type password: str
|
||||
|
||||
:param photo_path: Path to photo for uploading.
|
||||
:type photo_path: str
|
||||
|
||||
:param users_service: Users service.
|
||||
:type users_service: example.services.UsersService
|
||||
|
||||
:param auth_service: Authentication service.
|
||||
:type auth_service: example.services.AuthService
|
||||
|
||||
:param photo_service: Photo service.
|
||||
:type photo_service: example.services.PhotoService
|
||||
"""
|
||||
user = users_service.get_user_by_id(uid)
|
||||
auth_service.authenticate(user, password)
|
||||
photos_service.upload_photo(user['uid'], photo)
|
|
@ -1,103 +0,0 @@
|
|||
"""Example business services module."""
|
||||
|
||||
|
||||
class BaseService(object):
|
||||
"""Service base class."""
|
||||
|
||||
|
||||
class UsersService(BaseService):
|
||||
"""Users service."""
|
||||
|
||||
def __init__(self, logger, db):
|
||||
"""Initializer.
|
||||
|
||||
:param logger: Logger instance.
|
||||
:type logger: logging.Logger
|
||||
|
||||
:param db: Database connection.
|
||||
:type db: sqlite3.Connection
|
||||
"""
|
||||
self.logger = logger
|
||||
self.db = db
|
||||
|
||||
def get_user_by_id(self, uid):
|
||||
"""Return user's data by identifier.
|
||||
|
||||
:param uid: User identifier.
|
||||
:type uid: int
|
||||
|
||||
:rtype: dict
|
||||
"""
|
||||
self.logger.debug('User %s has been found in database', uid)
|
||||
return dict(uid=uid, password_hash='secret_hash')
|
||||
|
||||
|
||||
class AuthService(BaseService):
|
||||
"""Authentication service."""
|
||||
|
||||
def __init__(self, logger, db, token_ttl):
|
||||
"""Initializer.
|
||||
|
||||
:param logger: Logger instance.
|
||||
:type logger: logging.Logger
|
||||
|
||||
:param db: Database connection.
|
||||
:type db: sqlite3.Connection
|
||||
|
||||
:param token_ttl: Token lifetime in seconds.
|
||||
:type token_ttl: int
|
||||
"""
|
||||
self.logger = logger
|
||||
self.db = db
|
||||
self.token_ttl = token_ttl
|
||||
|
||||
def authenticate(self, user, password):
|
||||
"""Authenticate user.
|
||||
|
||||
:param user: User's data.
|
||||
:type user: dict
|
||||
|
||||
:param password: User's password for verification.
|
||||
:type password: str
|
||||
|
||||
:raises: AssertionError when password is wrong
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
assert user['password_hash'] == '_'.join((password, 'hash'))
|
||||
self.logger.debug('User %s has been successfully authenticated',
|
||||
user['uid'])
|
||||
|
||||
|
||||
class PhotosService(BaseService):
|
||||
"""Photos service."""
|
||||
|
||||
def __init__(self, logger, db, s3):
|
||||
"""Initializer.
|
||||
|
||||
:param logger: Logger instance.
|
||||
:type logger: logging.Logger
|
||||
|
||||
:param db: Database connection.
|
||||
:type db: sqlite3.Connection
|
||||
|
||||
:param s3: AWS S3 client.
|
||||
:type s3: botocore.client.S3
|
||||
"""
|
||||
self.logger = logger
|
||||
self.db = db
|
||||
self.s3 = s3
|
||||
|
||||
def upload_photo(self, uid, photo_path):
|
||||
"""Upload user photo.
|
||||
|
||||
:param uid: User identifier.
|
||||
:type uid: int
|
||||
|
||||
:param photo_path: Path to photo for uploading.
|
||||
:type photo_path: str
|
||||
|
||||
:rtpe: None
|
||||
"""
|
||||
self.logger.debug('Photo %s has been successfully uploaded by user %s',
|
||||
photo_path, uid)
|
8
examples/miniapps/services_v1/example/main.py
Normal file
8
examples/miniapps/services_v1/example/main.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
"""Example main module."""
|
||||
|
||||
|
||||
def main(uid, password, photo, users_service, auth_service, photos_service):
|
||||
"""Authenticate user and upload photo."""
|
||||
user = users_service.get_user_by_id(uid)
|
||||
auth_service.authenticate(user, password)
|
||||
photos_service.upload_photo(user['uid'], photo)
|
50
examples/miniapps/services_v1/example/services.py
Normal file
50
examples/miniapps/services_v1/example/services.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
"""Example business services module."""
|
||||
|
||||
|
||||
class BaseService(object):
|
||||
"""Service base class."""
|
||||
|
||||
|
||||
class UsersService(BaseService):
|
||||
"""Users service."""
|
||||
|
||||
def __init__(self, logger, db):
|
||||
"""Initializer."""
|
||||
self.logger = logger
|
||||
self.db = db
|
||||
|
||||
def get_user_by_id(self, uid):
|
||||
"""Return user's data by identifier."""
|
||||
self.logger.debug('User %s has been found in database', uid)
|
||||
return dict(uid=uid, password_hash='secret_hash')
|
||||
|
||||
|
||||
class AuthService(BaseService):
|
||||
"""Authentication service."""
|
||||
|
||||
def __init__(self, logger, db, token_ttl):
|
||||
"""Initializer."""
|
||||
self.logger = logger
|
||||
self.db = db
|
||||
self.token_ttl = token_ttl
|
||||
|
||||
def authenticate(self, user, password):
|
||||
"""Authenticate user."""
|
||||
assert user['password_hash'] == '_'.join((password, 'hash'))
|
||||
self.logger.debug('User %s has been successfully authenticated',
|
||||
user['uid'])
|
||||
|
||||
|
||||
class PhotosService(BaseService):
|
||||
"""Photos service."""
|
||||
|
||||
def __init__(self, logger, db, s3):
|
||||
"""Initializer."""
|
||||
self.logger = logger
|
||||
self.db = db
|
||||
self.s3 = s3
|
||||
|
||||
def upload_photo(self, uid, photo_path):
|
||||
"""Upload user photo."""
|
||||
self.logger.debug('Photo %s has been successfully uploaded by user %s',
|
||||
photo_path, uid)
|
8
examples/miniapps/services_v2/README.rst
Normal file
8
examples/miniapps/services_v2/README.rst
Normal file
|
@ -0,0 +1,8 @@
|
|||
Dependency Injector IoC containers example
|
||||
==========================================
|
||||
|
||||
Instructions for running
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python run.py 1 secret photo.jpg
|
57
examples/miniapps/services_v2/container.py
Normal file
57
examples/miniapps/services_v2/container.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
"""Example of dependency injection in Python."""
|
||||
|
||||
import logging
|
||||
import sqlite3
|
||||
|
||||
import boto3
|
||||
|
||||
from dependency_injector import containers, providers
|
||||
from example import services, main
|
||||
|
||||
|
||||
class IocContainer(containers.DeclarativeContainer):
|
||||
"""Application IoC container."""
|
||||
|
||||
config = providers.Configuration('config')
|
||||
logger = providers.Singleton(logging.Logger, name='example')
|
||||
|
||||
# Gateways
|
||||
|
||||
database_client = providers.Singleton(sqlite3.connect, config.database.dsn)
|
||||
|
||||
s3_client = providers.Singleton(
|
||||
boto3.client, 's3',
|
||||
aws_access_key_id=config.aws.access_key_id,
|
||||
aws_secret_access_key=config.aws.secret_access_key
|
||||
)
|
||||
|
||||
# Services
|
||||
|
||||
users_service = providers.Factory(
|
||||
services.UsersService,
|
||||
db=database_client,
|
||||
logger=logger
|
||||
)
|
||||
|
||||
auth_service = providers.Factory(
|
||||
services.AuthService,
|
||||
token_ttl=config.auth.token_ttl,
|
||||
db=database_client,
|
||||
logger=logger
|
||||
)
|
||||
|
||||
photos_service = providers.Factory(
|
||||
services.PhotosService,
|
||||
db=database_client,
|
||||
s3=s3_client,
|
||||
logger=logger
|
||||
)
|
||||
|
||||
# Misc
|
||||
|
||||
main = providers.Callable(
|
||||
main.main,
|
||||
users_service=users_service,
|
||||
auth_service=auth_service,
|
||||
photos_service=photos_service
|
||||
)
|
1
examples/miniapps/services_v2/example/__init__.py
Normal file
1
examples/miniapps/services_v2/example/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
"""Example top-level package."""
|
8
examples/miniapps/services_v2/example/main.py
Normal file
8
examples/miniapps/services_v2/example/main.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
"""Example main module."""
|
||||
|
||||
|
||||
def main(uid, password, photo, users_service, auth_service, photos_service):
|
||||
"""Authenticate user and upload photo."""
|
||||
user = users_service.get_user_by_id(uid)
|
||||
auth_service.authenticate(user, password)
|
||||
photos_service.upload_photo(user['uid'], photo)
|
50
examples/miniapps/services_v2/example/services.py
Normal file
50
examples/miniapps/services_v2/example/services.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
"""Example business services module."""
|
||||
|
||||
|
||||
class BaseService(object):
|
||||
"""Service base class."""
|
||||
|
||||
|
||||
class UsersService(BaseService):
|
||||
"""Users service."""
|
||||
|
||||
def __init__(self, logger, db):
|
||||
"""Initializer."""
|
||||
self.logger = logger
|
||||
self.db = db
|
||||
|
||||
def get_user_by_id(self, uid):
|
||||
"""Return user's data by identifier."""
|
||||
self.logger.debug('User %s has been found in database', uid)
|
||||
return dict(uid=uid, password_hash='secret_hash')
|
||||
|
||||
|
||||
class AuthService(BaseService):
|
||||
"""Authentication service."""
|
||||
|
||||
def __init__(self, logger, db, token_ttl):
|
||||
"""Initializer."""
|
||||
self.logger = logger
|
||||
self.db = db
|
||||
self.token_ttl = token_ttl
|
||||
|
||||
def authenticate(self, user, password):
|
||||
"""Authenticate user."""
|
||||
assert user['password_hash'] == '_'.join((password, 'hash'))
|
||||
self.logger.debug('User %s has been successfully authenticated',
|
||||
user['uid'])
|
||||
|
||||
|
||||
class PhotosService(BaseService):
|
||||
"""Photos service."""
|
||||
|
||||
def __init__(self, logger, db, s3):
|
||||
"""Initializer."""
|
||||
self.logger = logger
|
||||
self.db = db
|
||||
self.s3 = s3
|
||||
|
||||
def upload_photo(self, uid, photo_path):
|
||||
"""Upload user photo."""
|
||||
self.logger.debug('Photo %s has been successfully uploaded by user %s',
|
||||
photo_path, uid)
|
28
examples/miniapps/services_v2/run.py
Normal file
28
examples/miniapps/services_v2/run.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
"""Run example of dependency injection in Python."""
|
||||
|
||||
import sys
|
||||
import logging
|
||||
|
||||
from container import IocContainer
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Configure container:
|
||||
container = IocContainer(
|
||||
config={
|
||||
'database': {
|
||||
'dsn': ':memory:'
|
||||
},
|
||||
'aws': {
|
||||
'access_key_id': 'KEY',
|
||||
'secret_access_key': 'SECRET'
|
||||
},
|
||||
'auth': {
|
||||
'token_ttl': 3600
|
||||
}
|
||||
}
|
||||
)
|
||||
container.logger().addHandler(logging.StreamHandler(sys.stdout))
|
||||
|
||||
# Run application:
|
||||
container.main(*sys.argv[1:])
|
|
@ -1,4 +1,4 @@
|
|||
cython==0.27.3
|
||||
cython==0.28.3
|
||||
tox
|
||||
unittest2
|
||||
coverage
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""Dependency injector top-level package."""
|
||||
|
||||
__version__ = '3.12.0'
|
||||
__version__ = '3.12.1'
|
||||
"""Version number that follows semantic versioning.
|
||||
|
||||
:type: str
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Generated by Cython 0.28.2 */
|
||||
/* Generated by Cython 0.28.3 */
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include "Python.h"
|
||||
|
@ -7,7 +7,7 @@
|
|||
#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000)
|
||||
#error Cython requires Python 2.6+ or Python 3.3+.
|
||||
#else
|
||||
#define CYTHON_ABI "0_28_2"
|
||||
#define CYTHON_ABI "0_28_3"
|
||||
#define CYTHON_FUTURE_DIVISION 0
|
||||
#include <stddef.h>
|
||||
#ifndef offsetof
|
||||
|
@ -453,6 +453,7 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
|
|||
#define PyString_Type PyUnicode_Type
|
||||
#define PyString_Check PyUnicode_Check
|
||||
#define PyString_CheckExact PyUnicode_CheckExact
|
||||
#define PyObject_Unicode PyObject_Str
|
||||
#endif
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
#define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj)
|
||||
|
@ -645,7 +646,7 @@ static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) {
|
|||
#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode
|
||||
#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj)
|
||||
#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None)
|
||||
#define __Pyx_PyBool_FromLong(b) ((b) ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False))
|
||||
static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b);
|
||||
static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
|
||||
static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x);
|
||||
#define __Pyx_PySequence_Tuple(obj)\
|
||||
|
@ -753,7 +754,7 @@ static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; }
|
|||
static PyObject *__pyx_m = NULL;
|
||||
static PyObject *__pyx_d;
|
||||
static PyObject *__pyx_b;
|
||||
static PyObject *__pyx_cython_runtime;
|
||||
static PyObject *__pyx_cython_runtime = NULL;
|
||||
static PyObject *__pyx_empty_tuple;
|
||||
static PyObject *__pyx_empty_bytes;
|
||||
static PyObject *__pyx_empty_unicode;
|
||||
|
@ -11455,7 +11456,7 @@ static int __Pyx_modinit_function_import_code(void) {
|
|||
#ifndef CYTHON_SMALL_CODE
|
||||
#if defined(__clang__)
|
||||
#define CYTHON_SMALL_CODE
|
||||
#elif defined(__GNUC__)
|
||||
#elif defined(__GNUC__) && (!(defined(__cplusplus)) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4)))
|
||||
#define CYTHON_SMALL_CODE __attribute__((optimize("Os")))
|
||||
#else
|
||||
#define CYTHON_SMALL_CODE
|
||||
|
@ -14131,6 +14132,9 @@ static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_li
|
|||
#if CYTHON_COMPILING_IN_CPYTHON
|
||||
PyObject **cython_runtime_dict;
|
||||
#endif
|
||||
if (unlikely(!__pyx_cython_runtime)) {
|
||||
return c_line;
|
||||
}
|
||||
__Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback);
|
||||
#if CYTHON_COMPILING_IN_CPYTHON
|
||||
cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime);
|
||||
|
@ -16325,6 +16329,9 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
|
|||
Py_DECREF(x);
|
||||
return ival;
|
||||
}
|
||||
static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) {
|
||||
return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False);
|
||||
}
|
||||
static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
|
||||
return PyInt_FromSize_t(ival);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Generated by Cython 0.28.2 */
|
||||
/* Generated by Cython 0.28.3 */
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include "Python.h"
|
||||
|
@ -7,7 +7,7 @@
|
|||
#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000)
|
||||
#error Cython requires Python 2.6+ or Python 3.3+.
|
||||
#else
|
||||
#define CYTHON_ABI "0_28_2"
|
||||
#define CYTHON_ABI "0_28_3"
|
||||
#define CYTHON_FUTURE_DIVISION 0
|
||||
#include <stddef.h>
|
||||
#ifndef offsetof
|
||||
|
@ -453,6 +453,7 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
|
|||
#define PyString_Type PyUnicode_Type
|
||||
#define PyString_Check PyUnicode_Check
|
||||
#define PyString_CheckExact PyUnicode_CheckExact
|
||||
#define PyObject_Unicode PyObject_Str
|
||||
#endif
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
#define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj)
|
||||
|
@ -645,7 +646,7 @@ static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) {
|
|||
#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode
|
||||
#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj)
|
||||
#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None)
|
||||
#define __Pyx_PyBool_FromLong(b) ((b) ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False))
|
||||
static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b);
|
||||
static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
|
||||
static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x);
|
||||
#define __Pyx_PySequence_Tuple(obj)\
|
||||
|
@ -753,7 +754,7 @@ static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; }
|
|||
static PyObject *__pyx_m = NULL;
|
||||
static PyObject *__pyx_d;
|
||||
static PyObject *__pyx_b;
|
||||
static PyObject *__pyx_cython_runtime;
|
||||
static PyObject *__pyx_cython_runtime = NULL;
|
||||
static PyObject *__pyx_empty_tuple;
|
||||
static PyObject *__pyx_empty_bytes;
|
||||
static PyObject *__pyx_empty_unicode;
|
||||
|
@ -56515,7 +56516,7 @@ static int __Pyx_modinit_function_import_code(void) {
|
|||
#ifndef CYTHON_SMALL_CODE
|
||||
#if defined(__clang__)
|
||||
#define CYTHON_SMALL_CODE
|
||||
#elif defined(__GNUC__)
|
||||
#elif defined(__GNUC__) && (!(defined(__cplusplus)) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4)))
|
||||
#define CYTHON_SMALL_CODE __attribute__((optimize("Os")))
|
||||
#else
|
||||
#define CYTHON_SMALL_CODE
|
||||
|
@ -59958,6 +59959,9 @@ static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_li
|
|||
#if CYTHON_COMPILING_IN_CPYTHON
|
||||
PyObject **cython_runtime_dict;
|
||||
#endif
|
||||
if (unlikely(!__pyx_cython_runtime)) {
|
||||
return c_line;
|
||||
}
|
||||
__Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback);
|
||||
#if CYTHON_COMPILING_IN_CPYTHON
|
||||
cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime);
|
||||
|
@ -60939,6 +60943,9 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
|
|||
Py_DECREF(x);
|
||||
return ival;
|
||||
}
|
||||
static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) {
|
||||
return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False);
|
||||
}
|
||||
static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
|
||||
return PyInt_FromSize_t(ival);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user