mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-10-31 07:57:43 +03:00 
			
		
		
		
	Refactor services miniapps (#291)
* Refactor services mini app with single container * Make few little fixes to single container app * Update requirements.txt for single container example * Refactor multiple containers example * Add single container docs page * Create multiple containers page
This commit is contained in:
		
							parent
							
								
									d16e8817db
								
							
						
					
					
						commit
						bf978601ba
					
				
							
								
								
									
										22
									
								
								docs/examples-other/index.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								docs/examples-other/index.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | Other 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 according to the inversion of control principle  | ||||||
|  | and powered by *Dependency Injector* framework. | ||||||
|  | 
 | ||||||
|  | ..  toctree:: | ||||||
|  |     :maxdepth: 2 | ||||||
|  | 
 | ||||||
|  |     bundles_miniapp | ||||||
|  |     use_cases_miniapp | ||||||
|  |     password_hashing_miniapp | ||||||
|  |     chained_factories | ||||||
|  |     factory_of_factories | ||||||
							
								
								
									
										87
									
								
								docs/examples/application-multiple-containers.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								docs/examples/application-multiple-containers.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,87 @@ | ||||||
|  | .. _application-multiple-containers: | ||||||
|  | 
 | ||||||
|  | Application example (multiple containers) | ||||||
|  | ========================================= | ||||||
|  | 
 | ||||||
|  | .. meta:: | ||||||
|  |    :keywords: Python,Dependency Injection,Inversion of Control,Container,Example,Application, | ||||||
|  |               Framework,AWS,boto3,client | ||||||
|  |    :description: This example shows how you can create an application using multiple declarative | ||||||
|  |                  containers. We build an example Python micro application following the dependency | ||||||
|  |                  injection principle. It consists from several services with a domain logic that | ||||||
|  |                  have dependencies on database & AWS S3. | ||||||
|  | 
 | ||||||
|  | This example shows how you can create an application using multiple declarative containers. Using | ||||||
|  | multiple declarative containers is a good choice for a large application. For | ||||||
|  | building a moderate or a small size application refer to :ref:`application-single-container`. | ||||||
|  | 
 | ||||||
|  | We build an example micro application following the dependency injection principle. It consists | ||||||
|  | of several services with a domain logic. The services have dependencies on database & AWS S3. | ||||||
|  | 
 | ||||||
|  | .. image:: images/application.png | ||||||
|  |     :width: 100% | ||||||
|  |     :align: center | ||||||
|  | 
 | ||||||
|  | Start from the scratch or jump to the section: | ||||||
|  | 
 | ||||||
|  | .. contents:: | ||||||
|  |    :local: | ||||||
|  |    :backlinks: none | ||||||
|  | 
 | ||||||
|  | You can find the source code and instructions for running on the `Github <https://github.com/ets-labs/python-dependency-injector/tree/master/examples/miniapps/application-multiple-containers>`_. | ||||||
|  | 
 | ||||||
|  | Application structure | ||||||
|  | --------------------- | ||||||
|  | 
 | ||||||
|  | Application consists of an ``example`` package, a configuration file and a ``requirements.txt`` | ||||||
|  | file. | ||||||
|  | 
 | ||||||
|  | .. code-block:: bash | ||||||
|  | 
 | ||||||
|  |    ./ | ||||||
|  |    ├── example/ | ||||||
|  |    │   ├── __init__.py | ||||||
|  |    │   ├── __main__.py | ||||||
|  |    │   ├── containers.py | ||||||
|  |    │   └── services.py | ||||||
|  |    ├── config.yml | ||||||
|  |    └── requirements.txt | ||||||
|  | 
 | ||||||
|  | Containers | ||||||
|  | ---------- | ||||||
|  | 
 | ||||||
|  | Listing of the ``example/containers.py``: | ||||||
|  | 
 | ||||||
|  | .. literalinclude:: ../../examples/miniapps/application-multiple-containers/example/containers.py | ||||||
|  |    :language: python | ||||||
|  | 
 | ||||||
|  | Main module | ||||||
|  | ----------- | ||||||
|  | 
 | ||||||
|  | Listing of the ``example/__main__.py``: | ||||||
|  | 
 | ||||||
|  | .. literalinclude:: ../../examples/miniapps/application-multiple-containers/example/__main__.py | ||||||
|  |    :language: python | ||||||
|  | 
 | ||||||
|  | Services | ||||||
|  | -------- | ||||||
|  | 
 | ||||||
|  | Listing of the ``example/services.py``: | ||||||
|  | 
 | ||||||
|  | .. literalinclude:: ../../examples/miniapps/application-multiple-containers/example/services.py | ||||||
|  |    :language: python | ||||||
|  | 
 | ||||||
|  | Configuration | ||||||
|  | ------------- | ||||||
|  | 
 | ||||||
|  | Listing of the ``config.yml``: | ||||||
|  | 
 | ||||||
|  | .. literalinclude:: ../../examples/miniapps/application-multiple-containers/config.yml | ||||||
|  |    :language: yaml | ||||||
|  | 
 | ||||||
|  | Run the application | ||||||
|  | ------------------- | ||||||
|  | 
 | ||||||
|  | You can find the source code and instructions for running on the `Github <https://github.com/ets-labs/python-dependency-injector/tree/master/examples/miniapps/application-multiple-containers>`_. | ||||||
|  | 
 | ||||||
|  | .. disqus:: | ||||||
							
								
								
									
										93
									
								
								docs/examples/application-single-container.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								docs/examples/application-single-container.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,93 @@ | ||||||
|  | .. _application-single-container: | ||||||
|  | 
 | ||||||
|  | Application example (single container) | ||||||
|  | ====================================== | ||||||
|  | 
 | ||||||
|  | .. meta:: | ||||||
|  |    :keywords: Python,Dependency Injection,Inversion of Control,Container,Example,Application, | ||||||
|  |               Framework,AWS,boto3,client | ||||||
|  |    :description: This example shows how you can create an application using a single declarative | ||||||
|  |                  container. We build an example Python micro application following the dependency | ||||||
|  |                  injection principle. It consists from several services with a domain logic that | ||||||
|  |                  have dependencies on database & AWS S3. | ||||||
|  | 
 | ||||||
|  | This example shows how you can create an application using a single declarative container. Using | ||||||
|  | a single declarative container is a good choice for small or moderate size application. For | ||||||
|  | building a large application refer to :ref:`application-multiple-containers`. | ||||||
|  | 
 | ||||||
|  | We build an example micro application following the dependency injection principle. It consists | ||||||
|  | of several services with a domain logic. The services have dependencies on database & AWS S3. | ||||||
|  | 
 | ||||||
|  | .. image:: images/application.png | ||||||
|  |     :width: 100% | ||||||
|  |     :align: center | ||||||
|  | 
 | ||||||
|  | Start from the scratch or jump to the section: | ||||||
|  | 
 | ||||||
|  | .. contents:: | ||||||
|  |    :local: | ||||||
|  |    :backlinks: none | ||||||
|  | 
 | ||||||
|  | You can find the source code and instructions for running on the `Github <https://github.com/ets-labs/python-dependency-injector/tree/master/examples/miniapps/application-single-container>`_. | ||||||
|  | 
 | ||||||
|  | Application structure | ||||||
|  | --------------------- | ||||||
|  | 
 | ||||||
|  | Application consists of an ``example`` package, several configuration files and a | ||||||
|  | ``requirements.txt`` file. | ||||||
|  | 
 | ||||||
|  | .. code-block:: bash | ||||||
|  | 
 | ||||||
|  |    ./ | ||||||
|  |    ├── example/ | ||||||
|  |    │   ├── __init__.py | ||||||
|  |    │   ├── __main__.py | ||||||
|  |    │   ├── containers.py | ||||||
|  |    │   └── services.py | ||||||
|  |    ├── config.ini | ||||||
|  |    ├── logging.ini | ||||||
|  |    └── requirements.txt | ||||||
|  | 
 | ||||||
|  | Container | ||||||
|  | --------- | ||||||
|  | 
 | ||||||
|  | Listing of the ``example/containers.py``: | ||||||
|  | 
 | ||||||
|  | .. literalinclude:: ../../examples/miniapps/application-single-container/example/containers.py | ||||||
|  |    :language: python | ||||||
|  | 
 | ||||||
|  | Main module | ||||||
|  | ----------- | ||||||
|  | 
 | ||||||
|  | Listing of the ``example/__main__.py``: | ||||||
|  | 
 | ||||||
|  | .. literalinclude:: ../../examples/miniapps/application-single-container/example/__main__.py | ||||||
|  |    :language: python | ||||||
|  | 
 | ||||||
|  | Services | ||||||
|  | -------- | ||||||
|  | 
 | ||||||
|  | Listing of the ``example/services.py``: | ||||||
|  | 
 | ||||||
|  | .. literalinclude:: ../../examples/miniapps/application-single-container/example/services.py | ||||||
|  |    :language: python | ||||||
|  | 
 | ||||||
|  | Configuration | ||||||
|  | ------------- | ||||||
|  | 
 | ||||||
|  | Listing of the ``config.ini``: | ||||||
|  | 
 | ||||||
|  | .. literalinclude:: ../../examples/miniapps/application-single-container/config.ini | ||||||
|  |    :language: ini | ||||||
|  | 
 | ||||||
|  | Listing of the ``logging.ini``: | ||||||
|  | 
 | ||||||
|  | .. literalinclude:: ../../examples/miniapps/application-single-container/logging.ini | ||||||
|  |    :language: ini | ||||||
|  | 
 | ||||||
|  | Run the application | ||||||
|  | ------------------- | ||||||
|  | 
 | ||||||
|  | You can find the source code and instructions for running on the `Github <https://github.com/ets-labs/python-dependency-injector/tree/master/examples/miniapps/application-single-container>`_. | ||||||
|  | 
 | ||||||
|  | .. disqus:: | ||||||
							
								
								
									
										
											BIN
										
									
								
								docs/examples/images/application.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/examples/images/application.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 66 KiB | 
|  | @ -2,23 +2,15 @@ Examples | ||||||
| ======== | ======== | ||||||
| 
 | 
 | ||||||
| .. meta:: | .. meta:: | ||||||
|    :keywords: Python,DI,Dependency injection,IoC,Inversion of Control |    :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Example | ||||||
|    :description: Current section of documentation is designed to provide  |    :description: Python dependency injection examples. | ||||||
|                  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  | Explore the examples to see the ``Dependency Injector`` in action. | ||||||
| applications that are built according to the inversion of control principle  |  | ||||||
| and powered by *Dependency Injector* framework. |  | ||||||
| 
 | 
 | ||||||
| ..  toctree:: | ..  toctree:: | ||||||
|     :maxdepth: 2 |     :maxdepth: 2 | ||||||
| 
 | 
 | ||||||
|     services_miniapp_v1 |     application-single-container | ||||||
|     services_miniapp_v2 |     application-multiple-containers | ||||||
|     bundles_miniapp | 
 | ||||||
|     use_cases_miniapp | .. disqus:: | ||||||
|     password_hashing_miniapp |  | ||||||
|     chained_factories |  | ||||||
|     factory_of_factories |  | ||||||
|  |  | ||||||
|  | @ -1,73 +0,0 @@ | ||||||
| Services mini application example (v1 - multiple containers) |  | ||||||
| ------------------------------------------------------------ |  | ||||||
| 
 |  | ||||||
| .. 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 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  |  | ||||||
| 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_v1/example/services.py |  | ||||||
|    :language: python |  | ||||||
| 
 |  | ||||||
| Listing of ``example/main.py``: |  | ||||||
| 
 |  | ||||||
| .. literalinclude:: ../../examples/miniapps/services_v1/example/main.py |  | ||||||
|    :language: python |  | ||||||
| 
 |  | ||||||
| IoC containers |  | ||||||
| ~~~~~~~~~~~~~~ |  | ||||||
| 
 |  | ||||||
| Listing of ``containers.py``: |  | ||||||
| 
 |  | ||||||
| .. literalinclude:: ../../examples/miniapps/services_v1/containers.py |  | ||||||
|    :language: python |  | ||||||
| 
 |  | ||||||
| Run application |  | ||||||
| ~~~~~~~~~~~~~~~ |  | ||||||
| 
 |  | ||||||
| Listing of ``run.py``: |  | ||||||
| 
 |  | ||||||
| .. literalinclude:: ../../examples/miniapps/services_v1/run.py |  | ||||||
|    :language: python |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| .. disqus:: |  | ||||||
|  | @ -1,73 +0,0 @@ | ||||||
| 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 |  | ||||||
| 
 |  | ||||||
| Listing of ``example/main.py``: |  | ||||||
| 
 |  | ||||||
| .. literalinclude:: ../../examples/miniapps/services_v2/example/main.py |  | ||||||
|    :language: python |  | ||||||
| 
 |  | ||||||
| IoC container |  | ||||||
| ~~~~~~~~~~~~~ |  | ||||||
| 
 |  | ||||||
| Listing of ``container.py``: |  | ||||||
| 
 |  | ||||||
| .. literalinclude:: ../../examples/miniapps/services_v2/container.py |  | ||||||
|    :language: python |  | ||||||
| 
 |  | ||||||
| Run application |  | ||||||
| ~~~~~~~~~~~~~~~ |  | ||||||
| 
 |  | ||||||
| Listing of ``run.py``: |  | ||||||
| 
 |  | ||||||
| .. literalinclude:: ../../examples/miniapps/services_v2/run.py |  | ||||||
|    :language: python |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| .. disqus:: |  | ||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 49 KiB | 
|  | @ -129,11 +129,11 @@ Contents | ||||||
|     :maxdepth: 2 |     :maxdepth: 2 | ||||||
| 
 | 
 | ||||||
|     introduction/index |     introduction/index | ||||||
|     main/installation |     examples/index | ||||||
|     tutorials/index |     tutorials/index | ||||||
|     providers/index |     providers/index | ||||||
|     containers/index |     containers/index | ||||||
|     examples/index |     examples-other/index | ||||||
|     api/index |     api/index | ||||||
|     main/feedback |     main/feedback | ||||||
|     main/changelog |     main/changelog | ||||||
|  |  | ||||||
|  | @ -131,13 +131,16 @@ What's next? | ||||||
| 
 | 
 | ||||||
| Choose one of the following as a next step: | Choose one of the following as a next step: | ||||||
| 
 | 
 | ||||||
| + Pass one of the dependency injection tutorials: | - Look at application examples: | ||||||
|     + :ref:`flask-tutorial` |     - :ref:`application-single-container` | ||||||
|     + :ref:`aiohttp-tutorial` |     - :ref:`application-multiple-containers` | ||||||
|     + :ref:`asyncio-daemon-tutorial` | - Pass the tutorials: | ||||||
|     + :ref:`cli-tutorial` |     - :ref:`flask-tutorial` | ||||||
| + Know more about the :ref:`providers` |     - :ref:`aiohttp-tutorial` | ||||||
| + Go to the :ref:`contents` |     - :ref:`asyncio-daemon-tutorial` | ||||||
|  |     - :ref:`cli-tutorial` | ||||||
|  | - Know more about the :ref:`providers` | ||||||
|  | - Go to the :ref:`contents` | ||||||
| 
 | 
 | ||||||
| Useful links | Useful links | ||||||
| ~~~~~~~~~~~~ | ~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | @ -17,3 +17,4 @@ dependency injection pattern, inversion of control principle and | ||||||
|     what_is_di |     what_is_di | ||||||
|     di_in_python |     di_in_python | ||||||
|     key_features |     key_features | ||||||
|  |     installation | ||||||
|  |  | ||||||
|  | @ -31,7 +31,7 @@ Verification of currently installed version could be done using | ||||||
| 
 | 
 | ||||||
|     >>> import dependency_injector |     >>> import dependency_injector | ||||||
|     >>> dependency_injector.__version__ |     >>> dependency_injector.__version__ | ||||||
|     '3.15.2' |     '3.38.0' | ||||||
| 
 | 
 | ||||||
| .. _PyPi: https://pypi.org/project/dependency-injector/ | .. _PyPi: https://pypi.org/project/dependency-injector/ | ||||||
| .. _GitHub: https://github.com/ets-labs/python-dependency-injector | .. _GitHub: https://github.com/ets-labs/python-dependency-injector | ||||||
|  | @ -175,13 +175,16 @@ What's next? | ||||||
| 
 | 
 | ||||||
| Choose one of the following as a next step: | Choose one of the following as a next step: | ||||||
| 
 | 
 | ||||||
| + Pass one of the tutorials: | - Look at application examples: | ||||||
|     + :ref:`cli-tutorial` |     - :ref:`application-single-container` | ||||||
|     + :ref:`flask-tutorial` |     - :ref:`application-multiple-containers` | ||||||
|     + :ref:`aiohttp-tutorial` | - Pass the tutorials: | ||||||
|     + :ref:`asyncio-daemon-tutorial` |     - :ref:`flask-tutorial` | ||||||
| + Know more about the :ref:`providers` |     - :ref:`aiohttp-tutorial` | ||||||
| + Go to the :ref:`contents` |     - :ref:`asyncio-daemon-tutorial` | ||||||
|  |     - :ref:`cli-tutorial` | ||||||
|  | - Know more about the :ref:`providers` | ||||||
|  | - Go to the :ref:`contents` | ||||||
| 
 | 
 | ||||||
| .. disqus:: | .. disqus:: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								examples/miniapps/application-multiple-containers/README.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								examples/miniapps/application-multiple-containers/README.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | ||||||
|  | Application example (multiple containers) | ||||||
|  | ========================================= | ||||||
|  | 
 | ||||||
|  | Create virtual env: | ||||||
|  | 
 | ||||||
|  | .. code-block:: bash | ||||||
|  | 
 | ||||||
|  |    python3 -m venv venv | ||||||
|  |    . venv/bin/activate | ||||||
|  | 
 | ||||||
|  | Install requirements: | ||||||
|  | 
 | ||||||
|  | .. code-block:: bash | ||||||
|  | 
 | ||||||
|  |    pip install -r requirements.txt | ||||||
|  | 
 | ||||||
|  | Run: | ||||||
|  | 
 | ||||||
|  | .. code-block:: bash | ||||||
|  | 
 | ||||||
|  |    python -m example user@example.com secret photo.jpg | ||||||
|  | 
 | ||||||
|  | You should see: | ||||||
|  | 
 | ||||||
|  | .. code-block:: bash | ||||||
|  | 
 | ||||||
|  |    [2020-09-04 16:06:00,750] [DEBUG] [example.services.UserService]: User user@example.com has been found in database | ||||||
|  |    [2020-09-04 16:06:00,750] [DEBUG] [example.services.AuthService]: User user@example.com has been successfully authenticated | ||||||
|  |    [2020-09-04 16:06:00,750] [DEBUG] [example.services.PhotoService]: Photo photo.jpg has been successfully uploaded by user user@example.com | ||||||
							
								
								
									
										30
									
								
								examples/miniapps/application-multiple-containers/config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								examples/miniapps/application-multiple-containers/config.yml
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | core: | ||||||
|  | 
 | ||||||
|  |   logging: | ||||||
|  |     version: 1 | ||||||
|  |     formatters: | ||||||
|  |       formatter: | ||||||
|  |         format: "[%(asctime)s] [%(levelname)s] [%(name)s]: %(message)s" | ||||||
|  |     handlers: | ||||||
|  |       console: | ||||||
|  |         class: "logging.StreamHandler" | ||||||
|  |         level: "DEBUG" | ||||||
|  |         formatter: "formatter" | ||||||
|  |         stream: "ext://sys.stderr" | ||||||
|  |     root: | ||||||
|  |       level: "DEBUG" | ||||||
|  |       handlers: ["console"] | ||||||
|  | 
 | ||||||
|  | gateways: | ||||||
|  | 
 | ||||||
|  |   database: | ||||||
|  |     dsn: ":memory:" | ||||||
|  | 
 | ||||||
|  |   aws: | ||||||
|  |     access_key_id: "KEY" | ||||||
|  |     secret_access_key: "SECRET" | ||||||
|  | 
 | ||||||
|  | services: | ||||||
|  | 
 | ||||||
|  |   auth: | ||||||
|  |     token_ttl: 3600 | ||||||
|  | @ -0,0 +1,24 @@ | ||||||
|  | """Main module.""" | ||||||
|  | 
 | ||||||
|  | import sys | ||||||
|  | 
 | ||||||
|  | from .containers import Application | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def main(email: str, password: str, photo: str) -> None: | ||||||
|  |     application = Application() | ||||||
|  | 
 | ||||||
|  |     application.config.from_yaml('config.yml') | ||||||
|  |     application.core.configure_logging() | ||||||
|  | 
 | ||||||
|  |     user_service = application.services.user() | ||||||
|  |     auth_service = application.services.auth() | ||||||
|  |     photo_service = application.services.photo() | ||||||
|  | 
 | ||||||
|  |     user = user_service.get_user(email) | ||||||
|  |     auth_service.authenticate(user, password) | ||||||
|  |     photo_service.upload_photo(user, photo) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == '__main__': | ||||||
|  |     main(*sys.argv[1:]) | ||||||
|  | @ -0,0 +1,80 @@ | ||||||
|  | """Containers module.""" | ||||||
|  | 
 | ||||||
|  | import logging.config | ||||||
|  | import sqlite3 | ||||||
|  | 
 | ||||||
|  | import boto3 | ||||||
|  | from dependency_injector import containers, providers | ||||||
|  | 
 | ||||||
|  | from . import services | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Core(containers.DeclarativeContainer): | ||||||
|  | 
 | ||||||
|  |     config = providers.Configuration() | ||||||
|  | 
 | ||||||
|  |     configure_logging = providers.Callable( | ||||||
|  |         logging.config.dictConfig, | ||||||
|  |         config=config.logging, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Gateways(containers.DeclarativeContainer): | ||||||
|  | 
 | ||||||
|  |     config = providers.Configuration() | ||||||
|  | 
 | ||||||
|  |     database_client = providers.Singleton( | ||||||
|  |         sqlite3.connect, | ||||||
|  |         config.database.dsn, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     s3_client = providers.Singleton( | ||||||
|  |         boto3.client, | ||||||
|  |         service_name='s3', | ||||||
|  |         aws_access_key_id=config.aws.access_key_id, | ||||||
|  |         aws_secret_access_key=config.aws.secret_access_key, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Services(containers.DeclarativeContainer): | ||||||
|  | 
 | ||||||
|  |     config = providers.Configuration() | ||||||
|  |     gateways = providers.DependenciesContainer() | ||||||
|  | 
 | ||||||
|  |     user = providers.Factory( | ||||||
|  |         services.UserService, | ||||||
|  |         db=gateways.database_client, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     auth = providers.Factory( | ||||||
|  |         services.AuthService, | ||||||
|  |         db=gateways.database_client, | ||||||
|  |         token_ttl=config.auth.token_ttl.as_int(), | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     photo = providers.Factory( | ||||||
|  |         services.PhotoService, | ||||||
|  |         db=gateways.database_client, | ||||||
|  |         s3=gateways.s3_client, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Application(containers.DeclarativeContainer): | ||||||
|  | 
 | ||||||
|  |     config = providers.Configuration() | ||||||
|  | 
 | ||||||
|  |     core = providers.Container( | ||||||
|  |         Core, | ||||||
|  |         config=config.core, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     gateways = providers.Container( | ||||||
|  |         Gateways, | ||||||
|  |         config=config.gateways, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     services = providers.Container( | ||||||
|  |         Services, | ||||||
|  |         config=config.services, | ||||||
|  |         gateways=gateways, | ||||||
|  |     ) | ||||||
|  | @ -0,0 +1,56 @@ | ||||||
|  | """Services module.""" | ||||||
|  | 
 | ||||||
|  | import logging | ||||||
|  | import sqlite3 | ||||||
|  | from typing import Dict | ||||||
|  | 
 | ||||||
|  | from mypy_boto3_s3 import S3Client | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class BaseService: | ||||||
|  | 
 | ||||||
|  |     def __init__(self) -> None: | ||||||
|  |         self.logger = logging.getLogger( | ||||||
|  |             f'{__name__}.{self.__class__.__name__}', | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UserService(BaseService): | ||||||
|  | 
 | ||||||
|  |     def __init__(self, db: sqlite3.Connection) -> None: | ||||||
|  |         self.db = db | ||||||
|  |         super().__init__() | ||||||
|  | 
 | ||||||
|  |     def get_user(self, email: str) -> Dict[str, str]: | ||||||
|  |         self.logger.debug('User %s has been found in database', email) | ||||||
|  |         return {'email': email, 'password_hash': '...'} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class AuthService(BaseService): | ||||||
|  | 
 | ||||||
|  |     def __init__(self, db: sqlite3.Connection, token_ttl: int) -> None: | ||||||
|  |         self.db = db | ||||||
|  |         self.token_ttl = token_ttl | ||||||
|  |         super().__init__() | ||||||
|  | 
 | ||||||
|  |     def authenticate(self, user: Dict[str, str], password: str) -> None: | ||||||
|  |         assert password is not None | ||||||
|  |         self.logger.debug( | ||||||
|  |             'User %s has been successfully authenticated', | ||||||
|  |             user['email'], | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PhotoService(BaseService): | ||||||
|  | 
 | ||||||
|  |     def __init__(self, db: sqlite3.Connection, s3: S3Client) -> None: | ||||||
|  |         self.db = db | ||||||
|  |         self.s3 = s3 | ||||||
|  |         super().__init__() | ||||||
|  | 
 | ||||||
|  |     def upload_photo(self, user: Dict[str, str], photo_path: str) -> None: | ||||||
|  |         self.logger.debug( | ||||||
|  |             'Photo %s has been successfully uploaded by user %s', | ||||||
|  |             photo_path, | ||||||
|  |             user['email'], | ||||||
|  |         ) | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | dependency-injector[yaml] | ||||||
|  | boto3 | ||||||
|  | boto3-stubs[s3] | ||||||
							
								
								
									
										29
									
								
								examples/miniapps/application-single-container/README.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								examples/miniapps/application-single-container/README.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | ||||||
|  | Application example (single container) | ||||||
|  | ====================================== | ||||||
|  | 
 | ||||||
|  | Create virtual env: | ||||||
|  | 
 | ||||||
|  | .. code-block:: bash | ||||||
|  | 
 | ||||||
|  |    python3 -m venv venv | ||||||
|  |    . venv/bin/activate | ||||||
|  | 
 | ||||||
|  | Install requirements: | ||||||
|  | 
 | ||||||
|  | .. code-block:: bash | ||||||
|  | 
 | ||||||
|  |    pip install -r requirements.txt | ||||||
|  | 
 | ||||||
|  | Run: | ||||||
|  | 
 | ||||||
|  | .. code-block:: bash | ||||||
|  | 
 | ||||||
|  |    python -m example user@example.com secret photo.jpg | ||||||
|  | 
 | ||||||
|  | You should see: | ||||||
|  | 
 | ||||||
|  | .. code-block:: bash | ||||||
|  | 
 | ||||||
|  |    [2020-09-04 15:27:27,727] [DEBUG] [example.services.UserService]: User user@example.com has been found in database | ||||||
|  |    [2020-09-04 15:27:27,727] [DEBUG] [example.services.AuthService]: User user@example.com has been successfully authenticated | ||||||
|  |    [2020-09-04 15:27:27,727] [DEBUG] [example.services.PhotoService]: Photo photo.jpg has been successfully uploaded by user user@example.com | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | [database] | ||||||
|  | dsn=:memory: | ||||||
|  | 
 | ||||||
|  | [aws] | ||||||
|  | access_key_id=KEY | ||||||
|  | secret_access_key=SECRET | ||||||
|  | 
 | ||||||
|  | [auth] | ||||||
|  | token_ttl=3600 | ||||||
|  | @ -0,0 +1,24 @@ | ||||||
|  | """Main module.""" | ||||||
|  | 
 | ||||||
|  | import sys | ||||||
|  | 
 | ||||||
|  | from .containers import Container | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def main(email: str, password: str, photo: str) -> None: | ||||||
|  |     container = Container() | ||||||
|  | 
 | ||||||
|  |     container.configure_logging() | ||||||
|  |     container.config.from_ini('config.ini') | ||||||
|  | 
 | ||||||
|  |     user_service = container.user_service() | ||||||
|  |     auth_service = container.auth_service() | ||||||
|  |     photo_service = container.photo_service() | ||||||
|  | 
 | ||||||
|  |     user = user_service.get_user(email) | ||||||
|  |     auth_service.authenticate(user, password) | ||||||
|  |     photo_service.upload_photo(user, photo) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == '__main__': | ||||||
|  |     main(*sys.argv[1:]) | ||||||
|  | @ -0,0 +1,52 @@ | ||||||
|  | """Containers module.""" | ||||||
|  | 
 | ||||||
|  | import logging.config | ||||||
|  | import sqlite3 | ||||||
|  | 
 | ||||||
|  | import boto3 | ||||||
|  | from dependency_injector import containers, providers | ||||||
|  | 
 | ||||||
|  | from . import services | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Container(containers.DeclarativeContainer): | ||||||
|  | 
 | ||||||
|  |     config = providers.Configuration() | ||||||
|  | 
 | ||||||
|  |     configure_logging = providers.Callable( | ||||||
|  |         logging.config.fileConfig, | ||||||
|  |         fname='logging.ini', | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     # Gateways | ||||||
|  | 
 | ||||||
|  |     database_client = providers.Singleton( | ||||||
|  |         sqlite3.connect, | ||||||
|  |         config.database.dsn, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     s3_client = providers.Singleton( | ||||||
|  |         boto3.client, | ||||||
|  |         service_name='s3', | ||||||
|  |         aws_access_key_id=config.aws.access_key_id, | ||||||
|  |         aws_secret_access_key=config.aws.secret_access_key, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     # Services | ||||||
|  | 
 | ||||||
|  |     user_service = providers.Factory( | ||||||
|  |         services.UserService, | ||||||
|  |         db=database_client, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     auth_service = providers.Factory( | ||||||
|  |         services.AuthService, | ||||||
|  |         db=database_client, | ||||||
|  |         token_ttl=config.auth.token_ttl.as_int(), | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     photo_service = providers.Factory( | ||||||
|  |         services.PhotoService, | ||||||
|  |         db=database_client, | ||||||
|  |         s3=s3_client, | ||||||
|  |     ) | ||||||
|  | @ -0,0 +1,56 @@ | ||||||
|  | """Services module.""" | ||||||
|  | 
 | ||||||
|  | import logging | ||||||
|  | import sqlite3 | ||||||
|  | from typing import Dict | ||||||
|  | 
 | ||||||
|  | from mypy_boto3_s3 import S3Client | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class BaseService: | ||||||
|  | 
 | ||||||
|  |     def __init__(self) -> None: | ||||||
|  |         self.logger = logging.getLogger( | ||||||
|  |             f'{__name__}.{self.__class__.__name__}', | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UserService(BaseService): | ||||||
|  | 
 | ||||||
|  |     def __init__(self, db: sqlite3.Connection) -> None: | ||||||
|  |         self.db = db | ||||||
|  |         super().__init__() | ||||||
|  | 
 | ||||||
|  |     def get_user(self, email: str) -> Dict[str, str]: | ||||||
|  |         self.logger.debug('User %s has been found in database', email) | ||||||
|  |         return {'email': email, 'password_hash': '...'} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class AuthService(BaseService): | ||||||
|  | 
 | ||||||
|  |     def __init__(self, db: sqlite3.Connection, token_ttl: int) -> None: | ||||||
|  |         self.db = db | ||||||
|  |         self.token_ttl = token_ttl | ||||||
|  |         super().__init__() | ||||||
|  | 
 | ||||||
|  |     def authenticate(self, user: Dict[str, str], password: str) -> None: | ||||||
|  |         assert password is not None | ||||||
|  |         self.logger.debug( | ||||||
|  |             'User %s has been successfully authenticated', | ||||||
|  |             user['email'], | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PhotoService(BaseService): | ||||||
|  | 
 | ||||||
|  |     def __init__(self, db: sqlite3.Connection, s3: S3Client) -> None: | ||||||
|  |         self.db = db | ||||||
|  |         self.s3 = s3 | ||||||
|  |         super().__init__() | ||||||
|  | 
 | ||||||
|  |     def upload_photo(self, user: Dict[str, str], photo_path: str) -> None: | ||||||
|  |         self.logger.debug( | ||||||
|  |             'Photo %s has been successfully uploaded by user %s', | ||||||
|  |             photo_path, | ||||||
|  |             user['email'], | ||||||
|  |         ) | ||||||
							
								
								
									
										21
									
								
								examples/miniapps/application-single-container/logging.ini
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								examples/miniapps/application-single-container/logging.ini
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | ||||||
|  | [loggers] | ||||||
|  | keys=root | ||||||
|  | 
 | ||||||
|  | [handlers] | ||||||
|  | keys=stream_handler | ||||||
|  | 
 | ||||||
|  | [formatters] | ||||||
|  | keys=formatter | ||||||
|  | 
 | ||||||
|  | [logger_root] | ||||||
|  | level=DEBUG | ||||||
|  | handlers=stream_handler | ||||||
|  | 
 | ||||||
|  | [handler_stream_handler] | ||||||
|  | class=StreamHandler | ||||||
|  | level=DEBUG | ||||||
|  | formatter=formatter | ||||||
|  | args=(sys.stderr,) | ||||||
|  | 
 | ||||||
|  | [formatter_formatter] | ||||||
|  | format=[%(asctime)s] [%(levelname)s] [%(name)s]: %(message)s | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | dependency-injector | ||||||
|  | boto3 | ||||||
|  | boto3-stubs[s3] | ||||||
|  | @ -1,8 +0,0 @@ | ||||||
| Dependency Injector IoC containers example |  | ||||||
| ========================================== |  | ||||||
| 
 |  | ||||||
| Instructions for running |  | ||||||
| 
 |  | ||||||
| .. code-block:: bash |  | ||||||
| 
 |  | ||||||
|     python run.py 1 secret photo.jpg |  | ||||||
|  | @ -1,58 +0,0 @@ | ||||||
| """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 Core(containers.DeclarativeContainer): |  | ||||||
|     """IoC container of core component providers.""" |  | ||||||
| 
 |  | ||||||
|     config = providers.Configuration('config') |  | ||||||
| 
 |  | ||||||
|     logger = providers.Singleton(logging.Logger, name='example') |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class Gateways(containers.DeclarativeContainer): |  | ||||||
|     """IoC container of gateway (API clients to remote services) providers.""" |  | ||||||
| 
 |  | ||||||
|     database = providers.Singleton(sqlite3.connect, Core.config.database.dsn) |  | ||||||
| 
 |  | ||||||
|     s3 = 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) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class Services(containers.DeclarativeContainer): |  | ||||||
|     """IoC container of business service providers.""" |  | ||||||
| 
 |  | ||||||
|     users = providers.Factory(example.services.UsersService, |  | ||||||
|                               db=Gateways.database, |  | ||||||
|                               logger=Core.logger) |  | ||||||
| 
 |  | ||||||
|     auth = providers.Factory(example.services.AuthService, |  | ||||||
|                              db=Gateways.database, |  | ||||||
|                              logger=Core.logger, |  | ||||||
|                              token_ttl=Core.config.auth.token_ttl) |  | ||||||
| 
 |  | ||||||
|     photos = providers.Factory(example.services.PhotosService, |  | ||||||
|                                db=Gateways.database, |  | ||||||
|                                s3=Gateways.s3, |  | ||||||
|                                logger=Core.logger) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 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) |  | ||||||
|  | @ -1,8 +0,0 @@ | ||||||
| """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) |  | ||||||
|  | @ -1,50 +0,0 @@ | ||||||
| """Example business services module.""" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class BaseService: |  | ||||||
|     """Service base class.""" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class UsersService(BaseService): |  | ||||||
|     """Users service.""" |  | ||||||
| 
 |  | ||||||
|     def __init__(self, logger, db): |  | ||||||
|         """Initialize instance.""" |  | ||||||
|         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): |  | ||||||
|         """Initialize instance.""" |  | ||||||
|         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): |  | ||||||
|         """Initialize instance.""" |  | ||||||
|         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) |  | ||||||
|  | @ -1,20 +0,0 @@ | ||||||
| """Run example application.""" |  | ||||||
| 
 |  | ||||||
| import sys |  | ||||||
| import logging |  | ||||||
| 
 |  | ||||||
| from containers import Core, Application |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 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)) |  | ||||||
| 
 |  | ||||||
|     # Run application: |  | ||||||
|     Application.main(uid=sys.argv[1], |  | ||||||
|                      password=sys.argv[2], |  | ||||||
|                      photo=sys.argv[3]) |  | ||||||
|  | @ -1,8 +0,0 @@ | ||||||
| Dependency Injector IoC containers example |  | ||||||
| ========================================== |  | ||||||
| 
 |  | ||||||
| Instructions for running |  | ||||||
| 
 |  | ||||||
| .. code-block:: bash |  | ||||||
| 
 |  | ||||||
|     python run.py 1 secret photo.jpg |  | ||||||
|  | @ -1,57 +0,0 @@ | ||||||
| """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,8 +0,0 @@ | ||||||
| """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) |  | ||||||
|  | @ -1,50 +0,0 @@ | ||||||
| """Example business services module.""" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class BaseService: |  | ||||||
|     """Service base class.""" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class UsersService(BaseService): |  | ||||||
|     """Users service.""" |  | ||||||
| 
 |  | ||||||
|     def __init__(self, logger, db): |  | ||||||
|         """Initialize instance.""" |  | ||||||
|         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): |  | ||||||
|         """Initialize instance.""" |  | ||||||
|         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): |  | ||||||
|         """Initialize instance.""" |  | ||||||
|         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) |  | ||||||
|  | @ -1,28 +0,0 @@ | ||||||
| """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:]) |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user