Refactor example miniapps - services_v1, services_v2

This commit is contained in:
Roman Mogylatov 2018-06-27 19:06:56 +03:00
parent 32a8052715
commit 96b44004b1
19 changed files with 203 additions and 268 deletions

View File

@ -16,6 +16,7 @@ and powered by *Dependency Injector* framework.
:maxdepth: 2 :maxdepth: 2
movie_lister movie_lister
services_miniapp services_miniapp_v1
services_miniapp_v2
bundles_miniapp bundles_miniapp
use_cases_miniapp use_cases_miniapp

View File

@ -1,5 +1,5 @@
Services mini application example Services mini application example (v1 - multiple containers)
--------------------------------- ------------------------------------------------------------
.. meta:: .. meta::
:description: "Services miniapp" is an example mini application that :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, some standard and 3rd-party libraries for logging,
interaction with database and remote service via API. interaction with database and remote service via API.
"Services miniapp" example demonstrates usage of "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 miniapp" is an example mini application that consists from several
services that have dependencies on some standard and 3rd-party libraries for services that have dependencies on some standard and 3rd-party libraries for
@ -44,13 +45,13 @@ Example application structure:
Listing of ``example/services.py``: Listing of ``example/services.py``:
.. literalinclude:: ../../examples/miniapps/services/example/services.py .. literalinclude:: ../../examples/miniapps/services_v1/example/services.py
:language: python :language: python
:linenos: :linenos:
Listing of ``example/main.py``: Listing of ``example/main.py``:
.. literalinclude:: ../../examples/miniapps/services/example/main.py .. literalinclude:: ../../examples/miniapps/services_v1/example/main.py
:language: python :language: python
:linenos: :linenos:
@ -59,7 +60,7 @@ IoC containers
Listing of ``containers.py``: Listing of ``containers.py``:
.. literalinclude:: ../../examples/miniapps/services/containers.py .. literalinclude:: ../../examples/miniapps/services_v1/containers.py
:language: python :language: python
:linenos: :linenos:
@ -68,7 +69,7 @@ Run application
Listing of ``run.py``: Listing of ``run.py``:
.. literalinclude:: ../../examples/miniapps/services/run.py .. literalinclude:: ../../examples/miniapps/services_v1/run.py
:language: python :language: python
:linenos: :linenos:

View 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::

View File

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

View File

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

View File

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

View File

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

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

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

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

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