Add ioc_container example

This commit is contained in:
Roman Mogylatov 2018-06-22 09:52:58 +03:00
parent cdc3a7b51d
commit 431dee80d8
7 changed files with 219 additions and 0 deletions

View File

@ -7,6 +7,10 @@ that were made in every particular version.
From version 0.7.6 *Dependency Injector* framework strictly From version 0.7.6 *Dependency Injector* framework strictly
follows `Semantic versioning`_ follows `Semantic versioning`_
Development version
-------------------
- Add new example miniapp "ioc_container".
3.12.0 3.12.0
------ ------
- Regenerate C sources using Cython 0.28.2. - Regenerate C sources using Cython 0.28.2.

View File

@ -0,0 +1,8 @@
Dependency Injector IoC containers example
==========================================
Instructions for running
.. code-block:: bash
python run.py 1 secret photo.jpg

View File

@ -0,0 +1,55 @@
"""Example of dependency injection in Python."""
import logging
import sqlite3
import boto3
import example.main
import example.services
import dependency_injector.containers as containers
import dependency_injector.providers as providers
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(
example.services.UsersService,
db=database_client,
logger=logger)
auth_service = providers.Factory(
example.services.AuthService,
token_ttl=config.auth.token_ttl,
db=database_client,
logger=logger)
photos_service = providers.Factory(
example.services.PhotosService,
db=database_client,
s3=s3_client,
logger=logger)
# Misc
main = providers.Callable(
example.main.main,
users_service=users_service,
auth_service=auth_service,
photos_service=photos_service)

View File

@ -0,0 +1 @@
"""Example top-level package."""

View File

@ -0,0 +1,27 @@
"""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)

View File

@ -0,0 +1,103 @@
"""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)

View File

@ -0,0 +1,21 @@
"""Run example of dependency injection in Python."""
import sys
import logging
from container import IocContainer
if __name__ == '__main__':
# Configure platform:
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(uid=sys.argv[1],
password=sys.argv[2],
photo=sys.argv[3])