From 079d3f5ea74927801a681bd46427574ccd464a36 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Fri, 11 Nov 2016 23:08:47 +0200 Subject: [PATCH] Add services mini app example to docs --- docs/api/utils.rst | 5 -- docs/examples/index.rst | 1 + docs/examples/services_miniapp.rst | 73 ++++++++++++++++ docs/images/miniapps/services/classes.png | Bin 0 -> 49929 bytes docs/main/changelog.rst | 5 ++ examples/miniapps/services/example/main.py | 21 ++++- .../miniapps/services/example/services.py | 80 +++++++++++++++--- src/dependency_injector/__init__.py | 2 +- 8 files changed, 168 insertions(+), 19 deletions(-) delete mode 100644 docs/api/utils.rst create mode 100644 docs/examples/services_miniapp.rst create mode 100644 docs/images/miniapps/services/classes.png diff --git a/docs/api/utils.rst b/docs/api/utils.rst deleted file mode 100644 index 38ea3b70..00000000 --- a/docs/api/utils.rst +++ /dev/null @@ -1,5 +0,0 @@ -``dependency_injector.utils`` ------------------------------ - -.. automodule:: dependency_injector.utils - :members: diff --git a/docs/examples/index.rst b/docs/examples/index.rst index 89d623fb..3d57076e 100644 --- a/docs/examples/index.rst +++ b/docs/examples/index.rst @@ -16,3 +16,4 @@ and powered by *Dependency Injector* framework. :maxdepth: 2 movie_lister + services_miniapp diff --git a/docs/examples/services_miniapp.rst b/docs/examples/services_miniapp.rst new file mode 100644 index 00000000..33ea11ac --- /dev/null +++ b/docs/examples/services_miniapp.rst @@ -0,0 +1,73 @@ +Services mini application example +--------------------------------- + +.. 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 several IoC containers. + +"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 several IoC containers. + +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/example/services.py + :language: python + :linenos: + +Listing of ``example/main.py``: + +.. literalinclude:: ../../examples/miniapps/services/example/main.py + :language: python + :linenos: + +IoC containers +~~~~~~~~~~~~~~ + +Listing of ``containers.py``: + +.. literalinclude:: ../../examples/miniapps/services/containers.py + :language: python + :linenos: + +Run application +~~~~~~~~~~~~~~~ + +Listing of ``run.py``: + +.. literalinclude:: ../../examples/miniapps/services/run.py + :language: python + :linenos: diff --git a/docs/images/miniapps/services/classes.png b/docs/images/miniapps/services/classes.png new file mode 100644 index 0000000000000000000000000000000000000000..8e9d29f7d97114cc16de01fdd3bc420d766ac546 GIT binary patch literal 49929 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 Qg@fqoY8z-#Z(G0oFB0h7X#fBK literal 0 HcmV?d00001 diff --git a/docs/main/changelog.rst b/docs/main/changelog.rst index 27289641..a7da69e6 100644 --- a/docs/main/changelog.rst +++ b/docs/main/changelog.rst @@ -11,6 +11,11 @@ Development version ------------------- - No features. +3.1.0 +----- +- Add "Services mini application" example. +- Fix minor error in ``Factory`` provider API doc. + 3.0.1 ----- - Add ``*.c`` source files under version control. diff --git a/examples/miniapps/services/example/main.py b/examples/miniapps/services/example/main.py index d3399ff7..f1386c1a 100644 --- a/examples/miniapps/services/example/main.py +++ b/examples/miniapps/services/example/main.py @@ -2,7 +2,26 @@ def main(uid, password, photo, users_service, auth_service, photos_service): - """Example main function.""" + """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) diff --git a/examples/miniapps/services/example/services.py b/examples/miniapps/services/example/services.py index e907c1ca..4344e003 100644 --- a/examples/miniapps/services/example/services.py +++ b/examples/miniapps/services/example/services.py @@ -1,47 +1,103 @@ """Example business services module.""" -class UsersService(object): +class BaseService(object): + """Service base class.""" + + +class UsersService(BaseService): """Users service.""" def __init__(self, logger, db): - """Initializer.""" + """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 information by login.""" + """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 {'uid': uid, - 'password_hash': 'secret_hash'} + return dict(uid=uid, password_hash='secret_hash') -class AuthService(object): - """Auth service.""" +class AuthService(BaseService): + """Authentication service.""" def __init__(self, logger, db, token_ttl): - """Initializer.""" + """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.""" + """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(object): +class PhotosService(BaseService): """Photos service.""" def __init__(self, logger, db, s3): - """Initializer.""" + """Initializer. + + :param logger: Logger instance. + :type logger: logging.Logger + + :param db: Database connection. + :type db: sqlite3.Connection + + :param s3: AWS S3 client. + :type s3: boto.s3.connection.S3Connection + """ self.logger = logger self.db = db self.s3 = s3 def upload_photo(self, uid, photo_path): - """Upload user photo.""" + """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) diff --git a/src/dependency_injector/__init__.py b/src/dependency_injector/__init__.py index 169c3ea7..a344b9bf 100644 --- a/src/dependency_injector/__init__.py +++ b/src/dependency_injector/__init__.py @@ -1,6 +1,6 @@ """Dependency injector top-level package.""" -VERSION = '3.0.1' +VERSION = '3.1.0' """Version number that follows semantic versioning. :type: str