mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 01:47:36 +03:00 
			
		
		
		
	Merge branch 'release/3.30.0' into master
This commit is contained in:
		
						commit
						3ddf131180
					
				| 
						 | 
				
			
			@ -157,6 +157,7 @@ Choose one of the following:
 | 
			
		|||
- `Flask web application tutorial <http://python-dependency-injector.ets-labs.org/tutorials/flask.html>`_
 | 
			
		||||
- `Aiohttp REST API tutorial <http://python-dependency-injector.ets-labs.org/tutorials/aiohttp.html>`_
 | 
			
		||||
- `Asyncio monitoring daemon tutorial <http://python-dependency-injector.ets-labs.org/tutorials/asyncio-daemon.html>`_
 | 
			
		||||
- `CLI application tutorial <http://python-dependency-injector.ets-labs.org/tutorials/cli.html>`_
 | 
			
		||||
 | 
			
		||||
Installation
 | 
			
		||||
============
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,6 @@ and powered by *Dependency Injector* framework.
 | 
			
		|||
..  toctree::
 | 
			
		||||
    :maxdepth: 2
 | 
			
		||||
 | 
			
		||||
    movie_lister
 | 
			
		||||
    services_miniapp_v1
 | 
			
		||||
    services_miniapp_v2
 | 
			
		||||
    bundles_miniapp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,124 +0,0 @@
 | 
			
		|||
Movie lister naive example
 | 
			
		||||
--------------------------
 | 
			
		||||
 | 
			
		||||
.. meta::
 | 
			
		||||
   :description: Movie lister - is a naive example of dependency injection and 
 | 
			
		||||
                 inversion of control containers on Python. Original example 
 | 
			
		||||
                 was taken from Martin Fowler's article about dependency 
 | 
			
		||||
                 injection and inversion of control.
 | 
			
		||||
 | 
			
		||||
This naive example was taken from Martin Fowler's article about dependency 
 | 
			
		||||
injection and inversion of control: http://www.martinfowler.com/articles/injection.html
 | 
			
		||||
 | 
			
		||||
Like Martin says:
 | 
			
		||||
 | 
			
		||||
.. pull-quote::
 | 
			
		||||
 | 
			
		||||
    *Like all of my examples it's one of those super-simple examples; 
 | 
			
		||||
    small enough to be unreal, but hopefully enough for you to visualize 
 | 
			
		||||
    what's going on without falling into the bog of a real example.*
 | 
			
		||||
 | 
			
		||||
While original Martin's MovieLister example was a bit modified here, it 
 | 
			
		||||
makes sense to provide some description. So, the idea of this example is to 
 | 
			
		||||
create ``movies`` library that can be configured to work with different 
 | 
			
		||||
movie databases (csv, sqlite, etc...) and provide 2 main features:
 | 
			
		||||
 | 
			
		||||
1. List all movies that were directed by certain person.
 | 
			
		||||
2. List all movies that were released in certain year.
 | 
			
		||||
 | 
			
		||||
Also this example contains 3 mini applications that are based on ``movies`` 
 | 
			
		||||
library:
 | 
			
		||||
 | 
			
		||||
1. ``app_csv.py`` - list movies by certain criteria from csv file database.
 | 
			
		||||
2. ``app_db.py`` - list movies by certain criteria from sqlite database.
 | 
			
		||||
3. ``app_db_csv.py`` - list movies by certain criteria from csv file and 
 | 
			
		||||
   sqlite databases.
 | 
			
		||||
 | 
			
		||||
Instructions for running:
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
    python app_csv.py
 | 
			
		||||
    python app_db.py
 | 
			
		||||
    python app_db_csv.py
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Full code of example could be found on GitHub_. 
 | 
			
		||||
 | 
			
		||||
Movies library
 | 
			
		||||
~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Classes diagram:
 | 
			
		||||
 | 
			
		||||
.. image:: /images/miniapps/movie_lister/classes.png
 | 
			
		||||
    :width: 100%
 | 
			
		||||
    :align: center
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Movies library structure:
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
    /movies
 | 
			
		||||
        /__init__.py
 | 
			
		||||
        /finders.py
 | 
			
		||||
        /listers.py
 | 
			
		||||
        /models.py
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Listing of ``movies/__init__.py``:
 | 
			
		||||
 | 
			
		||||
.. literalinclude:: ../../examples/miniapps/movie_lister/movies/__init__.py
 | 
			
		||||
   :language: python
 | 
			
		||||
 | 
			
		||||
Example application
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Example application structure:
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
    /example
 | 
			
		||||
        /__init__.py
 | 
			
		||||
        /db.py
 | 
			
		||||
        /main.py
 | 
			
		||||
 | 
			
		||||
Listing of ``examples/main.py``:
 | 
			
		||||
 | 
			
		||||
.. literalinclude:: ../../examples/miniapps/movie_lister/example/main.py
 | 
			
		||||
   :language: python
 | 
			
		||||
 | 
			
		||||
Listing of ``examples/db.py``:
 | 
			
		||||
 | 
			
		||||
.. literalinclude:: ../../examples/miniapps/movie_lister/example/db.py
 | 
			
		||||
   :language: python
 | 
			
		||||
 | 
			
		||||
Csv application
 | 
			
		||||
~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Listing of ``app_csv.py``:
 | 
			
		||||
 | 
			
		||||
.. literalinclude:: ../../examples/miniapps/movie_lister/app_csv.py
 | 
			
		||||
   :language: python
 | 
			
		||||
 | 
			
		||||
Database application
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Listing of ``app_db.py``:
 | 
			
		||||
 | 
			
		||||
.. literalinclude:: ../../examples/miniapps/movie_lister/app_db.py
 | 
			
		||||
   :language: python
 | 
			
		||||
 | 
			
		||||
Csv and database application
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Listing of ``app_db_csv.py``:
 | 
			
		||||
 | 
			
		||||
.. literalinclude:: ../../examples/miniapps/movie_lister/app_db_csv.py
 | 
			
		||||
   :language: python
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.. disqus::
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.. _GitHub: https://github.com/ets-labs/python-dependency-injector/tree/master/examples/miniapps/movie_lister
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 34 KiB  | 
| 
						 | 
				
			
			@ -135,8 +135,9 @@ Choose one of the following as a next step:
 | 
			
		|||
    + :ref:`flask-tutorial`
 | 
			
		||||
    + :ref:`aiohttp-tutorial`
 | 
			
		||||
    + :ref:`asyncio-daemon-tutorial`
 | 
			
		||||
+ Know more about the :ref:`providers`.
 | 
			
		||||
+ Go to the :ref:`contents`.
 | 
			
		||||
    + :ref:`cli-tutorial`
 | 
			
		||||
+ Know more about the :ref:`providers`
 | 
			
		||||
+ Go to the :ref:`contents`
 | 
			
		||||
 | 
			
		||||
Useful links
 | 
			
		||||
~~~~~~~~~~~~
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,13 @@ that were made in every particular version.
 | 
			
		|||
From version 0.7.6 *Dependency Injector* framework strictly 
 | 
			
		||||
follows `Semantic versioning`_
 | 
			
		||||
 | 
			
		||||
3.30.0
 | 
			
		||||
------
 | 
			
		||||
- Rework ``Movie Lister`` example.
 | 
			
		||||
- Add tutorial for building ``Movie Lister``.
 | 
			
		||||
- Make some rewording for the other tutorials.
 | 
			
		||||
- Fix a couple of typos.
 | 
			
		||||
 | 
			
		||||
3.29.0
 | 
			
		||||
------
 | 
			
		||||
- Update README with the more direct message on what is ``Dependency Injector`` and how is it
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
.. _selector-provider:
 | 
			
		||||
 | 
			
		||||
Selector providers
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -922,7 +922,7 @@ We've used the ``Dependency Injector`` as a dependency injection framework.
 | 
			
		|||
 | 
			
		||||
The benefit you get with the ``Dependency Injector`` is the container. It starts to payoff
 | 
			
		||||
when you need to understand or change your application structure. It's easy with the container,
 | 
			
		||||
cause you have everything in one place:
 | 
			
		||||
cause you have everything defined explicitly in one place:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -962,8 +962,8 @@ cause you have everything in one place:
 | 
			
		|||
 | 
			
		||||
What's next?
 | 
			
		||||
 | 
			
		||||
- Look at the other :ref:`tutorials`.
 | 
			
		||||
- Know more about the :ref:`providers`.
 | 
			
		||||
- Go to the :ref:`contents`.
 | 
			
		||||
- Look at the other :ref:`tutorials`
 | 
			
		||||
- Know more about the :ref:`providers`
 | 
			
		||||
- Go to the :ref:`contents`
 | 
			
		||||
 | 
			
		||||
.. disqus::
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1030,7 +1030,7 @@ We've used the ``Dependency Injector`` as a dependency injection framework.
 | 
			
		|||
 | 
			
		||||
The benefit you get with the ``Dependency Injector`` is the container. It starts to payoff
 | 
			
		||||
when you need to understand or change your application structure. It's easy with the container,
 | 
			
		||||
cause you have everything in one place:
 | 
			
		||||
cause you have everything defined explicitly in one place:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1080,8 +1080,8 @@ cause you have everything in one place:
 | 
			
		|||
 | 
			
		||||
What's next?
 | 
			
		||||
 | 
			
		||||
- Look at the other :ref:`tutorials`.
 | 
			
		||||
- Know more about the :ref:`providers`.
 | 
			
		||||
- Go to the :ref:`contents`.
 | 
			
		||||
- Look at the other :ref:`tutorials`
 | 
			
		||||
- Know more about the :ref:`providers`
 | 
			
		||||
- Go to the :ref:`contents`
 | 
			
		||||
 | 
			
		||||
.. disqus::
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										
											BIN
										
									
								
								docs/tutorials/cli-images/classes_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/tutorials/cli-images/classes_01.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 36 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								docs/tutorials/cli-images/classes_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/tutorials/cli-images/classes_02.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 38 KiB  | 
							
								
								
									
										1054
									
								
								docs/tutorials/cli.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1054
									
								
								docs/tutorials/cli.rst
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -1097,7 +1097,7 @@ In this tutorial we've built a ``Flask`` application following the dependency in
 | 
			
		|||
We've used the ``Dependency Injector`` as a dependency injection framework.
 | 
			
		||||
 | 
			
		||||
The main part of this application is the container. It keeps all the application components and
 | 
			
		||||
their dependencies in one place:
 | 
			
		||||
their dependencies defined explicitly in one place:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1141,9 +1141,9 @@ their dependencies in one place:
 | 
			
		|||
 | 
			
		||||
What's next?
 | 
			
		||||
 | 
			
		||||
- Look at the other :ref:`tutorials`.
 | 
			
		||||
- Know more about the :ref:`providers`.
 | 
			
		||||
- Go to the :ref:`contents`.
 | 
			
		||||
- Look at the other :ref:`tutorials`
 | 
			
		||||
- Know more about the :ref:`providers`
 | 
			
		||||
- Go to the :ref:`contents`
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.. disqus::
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,5 +12,6 @@ frameworks.
 | 
			
		|||
    flask
 | 
			
		||||
    aiohttp
 | 
			
		||||
    asyncio-daemon
 | 
			
		||||
    cli
 | 
			
		||||
 | 
			
		||||
.. disqus::
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1,2 @@
 | 
			
		|||
[pydocstyle]
 | 
			
		||||
ignore = D100,D101,D102,D103,D107,D203,D213
 | 
			
		||||
ignore = D100,D101,D102,D103,D105,D107,D203,D213
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										75
									
								
								examples/miniapps/movie-lister/README.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								examples/miniapps/movie-lister/README.rst
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
Movie lister - a naive example of dependency injection in Python
 | 
			
		||||
================================================================
 | 
			
		||||
 | 
			
		||||
This is a Python implementation of the dependency injection example from Martin Fowler's
 | 
			
		||||
article:
 | 
			
		||||
 | 
			
		||||
    http://www.martinfowler.com/articles/injection.html
 | 
			
		||||
 | 
			
		||||
Run
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
Create a virtual environment:
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
   virtualenv venv
 | 
			
		||||
   . venv/bin/activate
 | 
			
		||||
 | 
			
		||||
Install the requirements:
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
    pip install -r requirements.txt
 | 
			
		||||
 | 
			
		||||
To create the fixtures do:
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
   python data/fixtures.py
 | 
			
		||||
 | 
			
		||||
To run the application do:
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
   MOVIE_FINDER_TYPE=csv python -m movies
 | 
			
		||||
   MOVIE_FINDER_TYPE=sqlite python -m movies
 | 
			
		||||
 | 
			
		||||
The output should be something like this for each command:
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
   Francis Lawrence movies: [Movie(title='The Hunger Games: Mockingjay - Part 2', year=2015, director='Francis Lawrence')]
 | 
			
		||||
   2016 movies: [Movie(title='Rogue One: A Star Wars Story', year=2016, director='Gareth Edwards'), Movie(title='The Jungle Book', year=2016, director='Jon Favreau')]
 | 
			
		||||
 | 
			
		||||
Test
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
To run the tests do:
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
   pytest movies/tests.py --cov=movies
 | 
			
		||||
 | 
			
		||||
The output should be something like:
 | 
			
		||||
 | 
			
		||||
.. code-block::
 | 
			
		||||
 | 
			
		||||
   platform darwin -- Python 3.8.3, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
 | 
			
		||||
   plugins: cov-2.10.0
 | 
			
		||||
   collected 2 items
 | 
			
		||||
 | 
			
		||||
   movies/tests.py ..                                              [100%]
 | 
			
		||||
 | 
			
		||||
   ---------- coverage: platform darwin, python 3.8.3-final-0 -----------
 | 
			
		||||
   Name                   Stmts   Miss  Cover
 | 
			
		||||
   ------------------------------------------
 | 
			
		||||
   movies/__init__.py         0      0   100%
 | 
			
		||||
   movies/__main__.py        10     10     0%
 | 
			
		||||
   movies/containers.py       9      0   100%
 | 
			
		||||
   movies/entities.py         7      1    86%
 | 
			
		||||
   movies/finders.py         26     13    50%
 | 
			
		||||
   movies/listers.py          8      0   100%
 | 
			
		||||
   movies/tests.py           24      0   100%
 | 
			
		||||
   ------------------------------------------
 | 
			
		||||
   TOTAL                     84     24    71%
 | 
			
		||||
							
								
								
									
										8
									
								
								examples/miniapps/movie-lister/config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								examples/miniapps/movie-lister/config.yml
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
finder:
 | 
			
		||||
 | 
			
		||||
  csv:
 | 
			
		||||
    path: "data/movies.csv"
 | 
			
		||||
    delimiter: ","
 | 
			
		||||
 | 
			
		||||
  sqlite:
 | 
			
		||||
    path: "data/movies.db"
 | 
			
		||||
							
								
								
									
										6
									
								
								examples/miniapps/movie-lister/data/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								examples/miniapps/movie-lister/data/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
# Everything
 | 
			
		||||
*
 | 
			
		||||
 | 
			
		||||
# Except this file:
 | 
			
		||||
!.gitignore
 | 
			
		||||
!fixtures.py
 | 
			
		||||
							
								
								
									
										44
									
								
								examples/miniapps/movie-lister/data/fixtures.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								examples/miniapps/movie-lister/data/fixtures.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
"""Fixtures module."""
 | 
			
		||||
 | 
			
		||||
import csv
 | 
			
		||||
import sqlite3
 | 
			
		||||
import pathlib
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SAMPLE_DATA = [
 | 
			
		||||
    ('The Hunger Games: Mockingjay - Part 2', 2015, 'Francis Lawrence'),
 | 
			
		||||
    ('Rogue One: A Star Wars Story', 2016, 'Gareth Edwards'),
 | 
			
		||||
    ('The Jungle Book', 2016, 'Jon Favreau'),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
FILE = pathlib.Path(__file__)
 | 
			
		||||
DIR = FILE.parent
 | 
			
		||||
CSV_FILE = DIR / 'movies.csv'
 | 
			
		||||
SQLITE_FILE = DIR / 'movies.db'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_csv(movies_data, path):
 | 
			
		||||
    with open(path, 'w') as opened_file:
 | 
			
		||||
        writer = csv.writer(opened_file)
 | 
			
		||||
        for row in movies_data:
 | 
			
		||||
            writer.writerow(row)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_sqlite(movies_data, path):
 | 
			
		||||
    with sqlite3.connect(path) as db:
 | 
			
		||||
        db.execute(
 | 
			
		||||
            'CREATE TABLE IF NOT EXISTS movies '
 | 
			
		||||
            '(title text, year int, director text)'
 | 
			
		||||
        )
 | 
			
		||||
        db.execute('DELETE FROM movies')
 | 
			
		||||
        db.executemany('INSERT INTO movies VALUES (?,?,?)', movies_data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    create_csv(SAMPLE_DATA, CSV_FILE)
 | 
			
		||||
    create_sqlite(SAMPLE_DATA, SQLITE_FILE)
 | 
			
		||||
    print('OK')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main()
 | 
			
		||||
							
								
								
									
										1
									
								
								examples/miniapps/movie-lister/movies/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								examples/miniapps/movie-lister/movies/__init__.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
"""Top-level package."""
 | 
			
		||||
							
								
								
									
										25
									
								
								examples/miniapps/movie-lister/movies/__main__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								examples/miniapps/movie-lister/movies/__main__.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
"""Main module."""
 | 
			
		||||
 | 
			
		||||
from .containers import ApplicationContainer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    container = ApplicationContainer()
 | 
			
		||||
 | 
			
		||||
    container.config.from_yaml('config.yml')
 | 
			
		||||
    container.config.finder.type.from_env('MOVIE_FINDER_TYPE')
 | 
			
		||||
 | 
			
		||||
    lister = container.lister()
 | 
			
		||||
 | 
			
		||||
    print(
 | 
			
		||||
        'Francis Lawrence movies:',
 | 
			
		||||
        lister.movies_directed_by('Francis Lawrence'),
 | 
			
		||||
    )
 | 
			
		||||
    print(
 | 
			
		||||
        '2016 movies:',
 | 
			
		||||
        lister.movies_released_in(2016),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main()
 | 
			
		||||
							
								
								
									
										36
									
								
								examples/miniapps/movie-lister/movies/containers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								examples/miniapps/movie-lister/movies/containers.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
"""Containers module."""
 | 
			
		||||
 | 
			
		||||
from dependency_injector import containers, providers
 | 
			
		||||
 | 
			
		||||
from . import finders, listers, entities
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ApplicationContainer(containers.DeclarativeContainer):
 | 
			
		||||
 | 
			
		||||
    config = providers.Configuration()
 | 
			
		||||
 | 
			
		||||
    movie = providers.Factory(entities.Movie)
 | 
			
		||||
 | 
			
		||||
    csv_finder = providers.Singleton(
 | 
			
		||||
        finders.CsvMovieFinder,
 | 
			
		||||
        movie_factory=movie.provider,
 | 
			
		||||
        path=config.finder.csv.path,
 | 
			
		||||
        delimiter=config.finder.csv.delimiter,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    sqlite_finder = providers.Singleton(
 | 
			
		||||
        finders.SqliteMovieFinder,
 | 
			
		||||
        movie_factory=movie.provider,
 | 
			
		||||
        path=config.finder.sqlite.path,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    finder = providers.Selector(
 | 
			
		||||
        config.finder.type,
 | 
			
		||||
        csv=csv_finder,
 | 
			
		||||
        sqlite=sqlite_finder,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    lister = providers.Factory(
 | 
			
		||||
        listers.MovieLister,
 | 
			
		||||
        movie_finder=finder,
 | 
			
		||||
    )
 | 
			
		||||
							
								
								
									
										17
									
								
								examples/miniapps/movie-lister/movies/entities.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								examples/miniapps/movie-lister/movies/entities.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
"""Movie entities module."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Movie:
 | 
			
		||||
 | 
			
		||||
    def __init__(self, title: str, year: int, director: str):
 | 
			
		||||
        self.title = str(title)
 | 
			
		||||
        self.year = int(year)
 | 
			
		||||
        self.director = str(director)
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return '{0}(title={1}, year={2}, director={3})'.format(
 | 
			
		||||
            self.__class__.__name__,
 | 
			
		||||
            repr(self.title),
 | 
			
		||||
            repr(self.year),
 | 
			
		||||
            repr(self.director),
 | 
			
		||||
        )
 | 
			
		||||
							
								
								
									
										50
									
								
								examples/miniapps/movie-lister/movies/finders.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								examples/miniapps/movie-lister/movies/finders.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
"""Movie finders module."""
 | 
			
		||||
 | 
			
		||||
import csv
 | 
			
		||||
import sqlite3
 | 
			
		||||
from typing import Callable, List
 | 
			
		||||
 | 
			
		||||
from .entities import Movie
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MovieFinder:
 | 
			
		||||
 | 
			
		||||
    def __init__(self, movie_factory: Callable[..., Movie]) -> None:
 | 
			
		||||
        self._movie_factory = movie_factory
 | 
			
		||||
 | 
			
		||||
    def find_all(self) -> List[Movie]:
 | 
			
		||||
        raise NotImplementedError()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CsvMovieFinder(MovieFinder):
 | 
			
		||||
 | 
			
		||||
    def __init__(
 | 
			
		||||
            self,
 | 
			
		||||
            movie_factory: Callable[..., Movie],
 | 
			
		||||
            path: str,
 | 
			
		||||
            delimiter: str,
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        self._csv_file_path = path
 | 
			
		||||
        self._delimiter = delimiter
 | 
			
		||||
        super().__init__(movie_factory)
 | 
			
		||||
 | 
			
		||||
    def find_all(self) -> List[Movie]:
 | 
			
		||||
        with open(self._csv_file_path) as csv_file:
 | 
			
		||||
            csv_reader = csv.reader(csv_file, delimiter=self._delimiter)
 | 
			
		||||
            return [self._movie_factory(*row) for row in csv_reader]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SqliteMovieFinder(MovieFinder):
 | 
			
		||||
 | 
			
		||||
    def __init__(
 | 
			
		||||
            self,
 | 
			
		||||
            movie_factory: Callable[..., Movie],
 | 
			
		||||
            path: str,
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        self._database = sqlite3.connect(path)
 | 
			
		||||
        super().__init__(movie_factory)
 | 
			
		||||
 | 
			
		||||
    def find_all(self) -> List[Movie]:
 | 
			
		||||
        with self._database as db:
 | 
			
		||||
            rows = db.execute('SELECT title, year, director FROM movies')
 | 
			
		||||
            return [self._movie_factory(*row) for row in rows]
 | 
			
		||||
							
								
								
									
										21
									
								
								examples/miniapps/movie-lister/movies/listers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								examples/miniapps/movie-lister/movies/listers.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
"""Movie listers module."""
 | 
			
		||||
 | 
			
		||||
from .finders import MovieFinder
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MovieLister:
 | 
			
		||||
 | 
			
		||||
    def __init__(self, movie_finder: MovieFinder):
 | 
			
		||||
        self._movie_finder = movie_finder
 | 
			
		||||
 | 
			
		||||
    def movies_directed_by(self, director):
 | 
			
		||||
        return [
 | 
			
		||||
            movie for movie in self._movie_finder.find_all()
 | 
			
		||||
            if movie.director == director
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
    def movies_released_in(self, year):
 | 
			
		||||
        return [
 | 
			
		||||
            movie for movie in self._movie_finder.find_all()
 | 
			
		||||
            if movie.year == year
 | 
			
		||||
        ]
 | 
			
		||||
							
								
								
									
										55
									
								
								examples/miniapps/movie-lister/movies/tests.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								examples/miniapps/movie-lister/movies/tests.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
"""Tests module."""
 | 
			
		||||
 | 
			
		||||
from unittest import mock
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
from .containers import ApplicationContainer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def container():
 | 
			
		||||
    container = ApplicationContainer()
 | 
			
		||||
    container.config.from_dict({
 | 
			
		||||
        'finder': {
 | 
			
		||||
            'type': 'csv',
 | 
			
		||||
            'csv': {
 | 
			
		||||
                'path': '/fake-movies.csv',
 | 
			
		||||
                'delimiter': ',',
 | 
			
		||||
            },
 | 
			
		||||
            'sqlite': {
 | 
			
		||||
                'path': '/fake-movies.db',
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    })
 | 
			
		||||
    return container
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_movies_directed_by(container):
 | 
			
		||||
    finder_mock = mock.Mock()
 | 
			
		||||
    finder_mock.find_all.return_value = [
 | 
			
		||||
        container.movie('The 33', 2015, 'Patricia Riggen'),
 | 
			
		||||
        container.movie('The Jungle Book', 2016, 'Jon Favreau'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    with container.finder.override(finder_mock):
 | 
			
		||||
        lister = container.lister()
 | 
			
		||||
        movies = lister.movies_directed_by('Jon Favreau')
 | 
			
		||||
 | 
			
		||||
    assert len(movies) == 1
 | 
			
		||||
    assert movies[0].title == 'The Jungle Book'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_movies_released_in(container):
 | 
			
		||||
    finder_mock = mock.Mock()
 | 
			
		||||
    finder_mock.find_all.return_value = [
 | 
			
		||||
        container.movie('The 33', 2015, 'Patricia Riggen'),
 | 
			
		||||
        container.movie('The Jungle Book', 2016, 'Jon Favreau'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    with container.finder.override(finder_mock):
 | 
			
		||||
        lister = container.lister()
 | 
			
		||||
        movies = lister.movies_released_in(2015)
 | 
			
		||||
 | 
			
		||||
    assert len(movies) == 1
 | 
			
		||||
    assert movies[0].title == 'The 33'
 | 
			
		||||
							
								
								
									
										4
									
								
								examples/miniapps/movie-lister/requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								examples/miniapps/movie-lister/requirements.txt
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
dependency-injector
 | 
			
		||||
pyyaml
 | 
			
		||||
pytest
 | 
			
		||||
pytest-cov
 | 
			
		||||
| 
						 | 
				
			
			@ -1,16 +0,0 @@
 | 
			
		|||
A naive example of dependency injection in Python
 | 
			
		||||
=================================================
 | 
			
		||||
 | 
			
		||||
Example implementation of dependency injection on Python from Martin Fowler's
 | 
			
		||||
article about dependency injection and inversion of control:
 | 
			
		||||
 | 
			
		||||
http://www.martinfowler.com/articles/injection.html
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Instructions for running:
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
    python app_csv.py
 | 
			
		||||
    python app_db.py
 | 
			
		||||
    python app_db_csv.py
 | 
			
		||||
| 
						 | 
				
			
			@ -1,49 +0,0 @@
 | 
			
		|||
"""A naive example of dependency injection on Python.
 | 
			
		||||
 | 
			
		||||
Example implementation of dependency injection in Python from Martin Fowler's
 | 
			
		||||
article about dependency injection and inversion of control:
 | 
			
		||||
 | 
			
		||||
http://www.martinfowler.com/articles/injection.html
 | 
			
		||||
 | 
			
		||||
This mini application uses ``movies`` library, that is configured to work with
 | 
			
		||||
csv file movies database.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import movies
 | 
			
		||||
import movies.finders
 | 
			
		||||
 | 
			
		||||
import example.db
 | 
			
		||||
import example.main
 | 
			
		||||
 | 
			
		||||
import settings
 | 
			
		||||
import fixtures
 | 
			
		||||
 | 
			
		||||
import dependency_injector.containers as containers
 | 
			
		||||
import dependency_injector.providers as providers
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@containers.override(movies.MoviesModule)
 | 
			
		||||
class MyMoviesModule(containers.DeclarativeContainer):
 | 
			
		||||
    """IoC container for overriding movies module component providers."""
 | 
			
		||||
 | 
			
		||||
    finder = providers.Factory(movies.finders.CsvMovieFinder,
 | 
			
		||||
                               csv_file_path=settings.MOVIES_CSV_PATH,
 | 
			
		||||
                               delimiter=',',
 | 
			
		||||
                               **movies.MoviesModule.finder.kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CsvApplication(containers.DeclarativeContainer):
 | 
			
		||||
    """IoC container of csv application component providers."""
 | 
			
		||||
 | 
			
		||||
    main = providers.Callable(example.main.main,
 | 
			
		||||
                              movie_lister=movies.MoviesModule.lister)
 | 
			
		||||
 | 
			
		||||
    init_db = providers.Callable(example.db.init_csv,
 | 
			
		||||
                                 movies_data=fixtures.MOVIES_SAMPLE_DATA,
 | 
			
		||||
                                 csv_file_path=settings.MOVIES_CSV_PATH,
 | 
			
		||||
                                 delimiter=',')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    CsvApplication.init_db()
 | 
			
		||||
    CsvApplication.main()
 | 
			
		||||
| 
						 | 
				
			
			@ -1,55 +0,0 @@
 | 
			
		|||
"""A naive example of dependency injection on Python.
 | 
			
		||||
 | 
			
		||||
Example implementation of dependency injection in Python from Martin Fowler's
 | 
			
		||||
article about dependency injection and inversion of control:
 | 
			
		||||
 | 
			
		||||
http://www.martinfowler.com/articles/injection.html
 | 
			
		||||
 | 
			
		||||
This mini application uses ``movies`` library, that is configured to work with
 | 
			
		||||
sqlite movies database.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sqlite3
 | 
			
		||||
 | 
			
		||||
import movies
 | 
			
		||||
import movies.finders
 | 
			
		||||
 | 
			
		||||
import example.db
 | 
			
		||||
import example.main
 | 
			
		||||
 | 
			
		||||
import settings
 | 
			
		||||
import fixtures
 | 
			
		||||
 | 
			
		||||
import dependency_injector.containers as containers
 | 
			
		||||
import dependency_injector.providers as providers
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ResourcesModule(containers.DeclarativeContainer):
 | 
			
		||||
    """IoC container of application resource providers."""
 | 
			
		||||
 | 
			
		||||
    database = providers.Singleton(sqlite3.connect, settings.MOVIES_DB_PATH)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@containers.override(movies.MoviesModule)
 | 
			
		||||
class MyMoviesModule(containers.DeclarativeContainer):
 | 
			
		||||
    """IoC container for overriding movies module component providers."""
 | 
			
		||||
 | 
			
		||||
    finder = providers.Factory(movies.finders.SqliteMovieFinder,
 | 
			
		||||
                               database=ResourcesModule.database,
 | 
			
		||||
                               **movies.MoviesModule.finder.kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DbApplication(containers.DeclarativeContainer):
 | 
			
		||||
    """IoC container of database application component providers."""
 | 
			
		||||
 | 
			
		||||
    main = providers.Callable(example.main.main,
 | 
			
		||||
                              movie_lister=movies.MoviesModule.lister)
 | 
			
		||||
 | 
			
		||||
    init_db = providers.Callable(example.db.init_sqlite,
 | 
			
		||||
                                 movies_data=fixtures.MOVIES_SAMPLE_DATA,
 | 
			
		||||
                                 database=ResourcesModule.database)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    DbApplication.init_db()
 | 
			
		||||
    DbApplication.main()
 | 
			
		||||
| 
						 | 
				
			
			@ -1,80 +0,0 @@
 | 
			
		|||
"""A naive example of dependency injection on Python.
 | 
			
		||||
 | 
			
		||||
Example implementation of dependency injection in Python from Martin Fowler's
 | 
			
		||||
article about dependency injection and inversion of control:
 | 
			
		||||
 | 
			
		||||
http://www.martinfowler.com/articles/injection.html
 | 
			
		||||
 | 
			
		||||
This mini application uses ``movies`` library, that is configured to work with
 | 
			
		||||
sqlite movies database and csv file movies database.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sqlite3
 | 
			
		||||
 | 
			
		||||
import movies
 | 
			
		||||
import movies.finders
 | 
			
		||||
 | 
			
		||||
import example.db
 | 
			
		||||
import example.main
 | 
			
		||||
 | 
			
		||||
import settings
 | 
			
		||||
import fixtures
 | 
			
		||||
 | 
			
		||||
import dependency_injector.containers as containers
 | 
			
		||||
import dependency_injector.providers as providers
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ResourcesModule(containers.DeclarativeContainer):
 | 
			
		||||
    """IoC container of application resource providers."""
 | 
			
		||||
 | 
			
		||||
    database = providers.Singleton(sqlite3.connect, settings.MOVIES_DB_PATH)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@containers.copy(movies.MoviesModule)
 | 
			
		||||
class DbMoviesModule(movies.MoviesModule):
 | 
			
		||||
    """IoC container for overriding movies module component providers."""
 | 
			
		||||
 | 
			
		||||
    finder = providers.Factory(movies.finders.SqliteMovieFinder,
 | 
			
		||||
                               database=ResourcesModule.database,
 | 
			
		||||
                               **movies.MoviesModule.finder.kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@containers.copy(movies.MoviesModule)
 | 
			
		||||
class CsvMoviesModule(movies.MoviesModule):
 | 
			
		||||
    """IoC container for overriding movies module component providers."""
 | 
			
		||||
 | 
			
		||||
    finder = providers.Factory(movies.finders.CsvMovieFinder,
 | 
			
		||||
                               csv_file_path=settings.MOVIES_CSV_PATH,
 | 
			
		||||
                               delimiter=',',
 | 
			
		||||
                               **movies.MoviesModule.finder.kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DbApplication(containers.DeclarativeContainer):
 | 
			
		||||
    """IoC container of database application component providers."""
 | 
			
		||||
 | 
			
		||||
    main = providers.Callable(example.main.main,
 | 
			
		||||
                              movie_lister=DbMoviesModule.lister)
 | 
			
		||||
 | 
			
		||||
    init_db = providers.Callable(example.db.init_sqlite,
 | 
			
		||||
                                 movies_data=fixtures.MOVIES_SAMPLE_DATA,
 | 
			
		||||
                                 database=ResourcesModule.database)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CsvApplication(containers.DeclarativeContainer):
 | 
			
		||||
    """IoC container of csv application component providers."""
 | 
			
		||||
 | 
			
		||||
    main = providers.Callable(example.main.main,
 | 
			
		||||
                              movie_lister=CsvMoviesModule.lister)
 | 
			
		||||
 | 
			
		||||
    init_db = providers.Callable(example.db.init_csv,
 | 
			
		||||
                                 movies_data=fixtures.MOVIES_SAMPLE_DATA,
 | 
			
		||||
                                 csv_file_path=settings.MOVIES_CSV_PATH,
 | 
			
		||||
                                 delimiter=',')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    DbApplication.init_db()
 | 
			
		||||
    DbApplication.main()
 | 
			
		||||
 | 
			
		||||
    CsvApplication.init_db()
 | 
			
		||||
    CsvApplication.main()
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +0,0 @@
 | 
			
		|||
# Ignore everything in this directory
 | 
			
		||||
*
 | 
			
		||||
 | 
			
		||||
# Except this file:
 | 
			
		||||
!.gitignore
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +0,0 @@
 | 
			
		|||
The Hunger Games: Mockingjay - Part 2,2015,Francis Lawrence
 | 
			
		||||
The 33,2015,Patricia Riggen
 | 
			
		||||
Star Wars: Episode VII - The Force Awakens,2015,JJ Abrams
 | 
			
		||||
		
		
			
  | 
| 
						 | 
				
			
			@ -1 +0,0 @@
 | 
			
		|||
"""Example top-level package."""
 | 
			
		||||
| 
						 | 
				
			
			@ -1,35 +0,0 @@
 | 
			
		|||
"""Example database module."""
 | 
			
		||||
 | 
			
		||||
import csv
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def init_sqlite(movies_data, database):
 | 
			
		||||
    """Initialize sqlite3 movies database.
 | 
			
		||||
 | 
			
		||||
    :param movies_data: Data about movies
 | 
			
		||||
    :type movies_data: tuple[tuple]
 | 
			
		||||
 | 
			
		||||
    :param database: Connection to sqlite database with movies data
 | 
			
		||||
    :type database: sqlite3.Connection
 | 
			
		||||
    """
 | 
			
		||||
    with database:
 | 
			
		||||
        database.execute('CREATE TABLE IF NOT EXISTS movies '
 | 
			
		||||
                         '(name text, year int, director text)')
 | 
			
		||||
        database.execute('DELETE FROM movies')
 | 
			
		||||
        database.executemany('INSERT INTO movies VALUES (?,?,?)', movies_data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def init_csv(movies_data, csv_file_path, delimiter):
 | 
			
		||||
    """Initialize csv movies database.
 | 
			
		||||
 | 
			
		||||
    :param movies_data: Data about movies
 | 
			
		||||
    :type movies_data: tuple[tuple]
 | 
			
		||||
 | 
			
		||||
    :param csv_file_path: Path to csv file with movies data
 | 
			
		||||
    :type csv_file_path: str
 | 
			
		||||
 | 
			
		||||
    :param delimiter: Csv file's delimiter
 | 
			
		||||
    :type delimiter: str
 | 
			
		||||
    """
 | 
			
		||||
    with open(csv_file_path, 'w') as csv_file:
 | 
			
		||||
        csv.writer(csv_file, delimiter=delimiter).writerows(movies_data)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,17 +0,0 @@
 | 
			
		|||
"""Example main module."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main(movie_lister):
 | 
			
		||||
    """Run application.
 | 
			
		||||
 | 
			
		||||
    This program prints info about all movies that were directed by different
 | 
			
		||||
    persons and then prints all movies that were released in 2015.
 | 
			
		||||
 | 
			
		||||
    :param movie_lister: Movie lister instance
 | 
			
		||||
    :type movie_lister: movies.listers.MovieLister
 | 
			
		||||
    """
 | 
			
		||||
    print(movie_lister.movies_directed_by('Francis Lawrence'))
 | 
			
		||||
    print(movie_lister.movies_directed_by('Patricia Riggen'))
 | 
			
		||||
    print(movie_lister.movies_directed_by('JJ Abrams'))
 | 
			
		||||
 | 
			
		||||
    print(movie_lister.movies_released_in(2015))
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +0,0 @@
 | 
			
		|||
"""Fixtures module."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MOVIES_SAMPLE_DATA = (
 | 
			
		||||
    ('The Hunger Games: Mockingjay - Part 2', 2015, 'Francis Lawrence'),
 | 
			
		||||
    ('The 33', 2015, 'Patricia Riggen'),
 | 
			
		||||
    ('Star Wars: Episode VII - The Force Awakens', 2015, 'JJ Abrams'),
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,32 +0,0 @@
 | 
			
		|||
"""Movies package.
 | 
			
		||||
 | 
			
		||||
Top-level package of movies library. This package contains IoC container of
 | 
			
		||||
movies module component providers - ``MoviesModule``. It is recommended to use
 | 
			
		||||
movies library functionality by fetching required instances from
 | 
			
		||||
``MoviesModule`` providers.
 | 
			
		||||
 | 
			
		||||
``MoviesModule.finder`` is a factory that provides abstract component
 | 
			
		||||
``finders.MovieFinder``. This provider should be overridden by provider of
 | 
			
		||||
concrete finder implementation in terms of library configuration.
 | 
			
		||||
 | 
			
		||||
Each of ``MoviesModule`` providers could be overridden.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import movies.finders
 | 
			
		||||
import movies.listers
 | 
			
		||||
import movies.models
 | 
			
		||||
 | 
			
		||||
import dependency_injector.containers as containers
 | 
			
		||||
import dependency_injector.providers as providers
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MoviesModule(containers.DeclarativeContainer):
 | 
			
		||||
    """IoC container of movies module component providers."""
 | 
			
		||||
 | 
			
		||||
    movie = providers.Factory(movies.models.Movie)
 | 
			
		||||
 | 
			
		||||
    finder = providers.AbstractFactory(movies.finders.MovieFinder,
 | 
			
		||||
                                       movie_model=movie.provider)
 | 
			
		||||
 | 
			
		||||
    lister = providers.Factory(movies.listers.MovieLister,
 | 
			
		||||
                               movie_finder=finder)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,87 +0,0 @@
 | 
			
		|||
"""Movie finders module.
 | 
			
		||||
 | 
			
		||||
This module contains all finder implementations.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import csv
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MovieFinder:
 | 
			
		||||
    """Movie finder component.
 | 
			
		||||
 | 
			
		||||
    Movie finder component is responsible for fetching movies data from
 | 
			
		||||
    various storage.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, movie_model):
 | 
			
		||||
        """Initialize instance.
 | 
			
		||||
 | 
			
		||||
        :param movie_model: Movie model's factory
 | 
			
		||||
        :type movie_model: movies.models.Movie
 | 
			
		||||
        """
 | 
			
		||||
        self._movie_model = movie_model
 | 
			
		||||
 | 
			
		||||
    def find_all(self):
 | 
			
		||||
        """Return all found movies.
 | 
			
		||||
 | 
			
		||||
        :rtype: list[movies.models.Movie]
 | 
			
		||||
        :return: List of movie instances.
 | 
			
		||||
        """
 | 
			
		||||
        raise NotImplementedError()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CsvMovieFinder(MovieFinder):
 | 
			
		||||
    """Movie finder that fetches movies data from csv file."""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, movie_model, csv_file_path, delimiter):
 | 
			
		||||
        """Initialize instance.
 | 
			
		||||
 | 
			
		||||
        :param movie_model: Movie model's factory
 | 
			
		||||
        :type movie_model: movies.models.Movie
 | 
			
		||||
 | 
			
		||||
        :param csv_file_path: Path to csv file with movies data
 | 
			
		||||
        :type csv_file_path: str
 | 
			
		||||
 | 
			
		||||
        :param delimiter: Csv file's delimiter
 | 
			
		||||
        :type delimiter: str
 | 
			
		||||
        """
 | 
			
		||||
        self._csv_file_path = csv_file_path
 | 
			
		||||
        self._delimiter = delimiter
 | 
			
		||||
        super().__init__(movie_model)
 | 
			
		||||
 | 
			
		||||
    def find_all(self):
 | 
			
		||||
        """Return all found movies.
 | 
			
		||||
 | 
			
		||||
        :rtype: list[movies.models.Movie]
 | 
			
		||||
        :return: List of movie instances.
 | 
			
		||||
        """
 | 
			
		||||
        with open(self._csv_file_path) as csv_file:
 | 
			
		||||
            csv_reader = csv.reader(csv_file, delimiter=self._delimiter)
 | 
			
		||||
            return [self._movie_model(*row) for row in csv_reader]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SqliteMovieFinder(MovieFinder):
 | 
			
		||||
    """Movie finder that fetches movies data from sqlite database."""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, movie_model, database):
 | 
			
		||||
        """Initialize instance.
 | 
			
		||||
 | 
			
		||||
        :param movie_model: Movie model's factory
 | 
			
		||||
        :type movie_model: (object) -> movies.models.Movie
 | 
			
		||||
 | 
			
		||||
        :param database: Connection to sqlite database with movies data
 | 
			
		||||
        :type database: sqlite3.Connection
 | 
			
		||||
        """
 | 
			
		||||
        self._database = database
 | 
			
		||||
        super().__init__(movie_model)
 | 
			
		||||
 | 
			
		||||
    def find_all(self):
 | 
			
		||||
        """Return all found movies.
 | 
			
		||||
 | 
			
		||||
        :rtype: list[movies.models.Movie]
 | 
			
		||||
        :return: List of movie instances.
 | 
			
		||||
        """
 | 
			
		||||
        with self._database:
 | 
			
		||||
            rows = self._database.execute('SELECT name, year, director '
 | 
			
		||||
                                          'FROM movies')
 | 
			
		||||
            return [self._movie_model(*row) for row in rows]
 | 
			
		||||
| 
						 | 
				
			
			@ -1,44 +0,0 @@
 | 
			
		|||
"""Movie listers module.
 | 
			
		||||
 | 
			
		||||
This module contains all lister implementations.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MovieLister:
 | 
			
		||||
    """Movie lister component.
 | 
			
		||||
 | 
			
		||||
    Movie lister component provides several methods for filtering movies by
 | 
			
		||||
    specific criteria.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, movie_finder):
 | 
			
		||||
        """Initialize instance.
 | 
			
		||||
 | 
			
		||||
        :param movie_finder: Movie finder instance
 | 
			
		||||
        :type movie_finder: movies.finders.MovieFinder
 | 
			
		||||
        """
 | 
			
		||||
        self._movie_finder = movie_finder
 | 
			
		||||
 | 
			
		||||
    def movies_directed_by(self, director):
 | 
			
		||||
        """Return list of movies that were directed by certain person.
 | 
			
		||||
 | 
			
		||||
        :param director: Director's name
 | 
			
		||||
        :type director: str
 | 
			
		||||
 | 
			
		||||
        :rtype: list[movies.models.Movie]
 | 
			
		||||
        :return: List of movie instances.
 | 
			
		||||
        """
 | 
			
		||||
        return [movie for movie in self._movie_finder.find_all()
 | 
			
		||||
                if movie.director == director]
 | 
			
		||||
 | 
			
		||||
    def movies_released_in(self, year):
 | 
			
		||||
        """Return list of movies that were released in certain year.
 | 
			
		||||
 | 
			
		||||
        :param year: Release year
 | 
			
		||||
        :type year: int
 | 
			
		||||
 | 
			
		||||
        :rtype: list[movies.models.Movie]
 | 
			
		||||
        :return: List of movie instances.
 | 
			
		||||
        """
 | 
			
		||||
        return [movie for movie in self._movie_finder.find_all()
 | 
			
		||||
                if movie.year == year]
 | 
			
		||||
| 
						 | 
				
			
			@ -1,36 +0,0 @@
 | 
			
		|||
"""Movie models module.
 | 
			
		||||
 | 
			
		||||
This module contains all model implementations.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Movie:
 | 
			
		||||
    """Base movie model."""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, name, year, director):
 | 
			
		||||
        """Initialize instance.
 | 
			
		||||
 | 
			
		||||
        :param name: Movie's name
 | 
			
		||||
        :type name: str
 | 
			
		||||
 | 
			
		||||
        :param year: Year, when movie was released
 | 
			
		||||
        :type year: int
 | 
			
		||||
 | 
			
		||||
        :param director: Name of person, that directed the movie
 | 
			
		||||
        :type director: str
 | 
			
		||||
        """
 | 
			
		||||
        self.name = str(name)
 | 
			
		||||
        self.year = int(year)
 | 
			
		||||
        self.director = str(director)
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        """Return string representation of movie instance.
 | 
			
		||||
 | 
			
		||||
        :rtype: str
 | 
			
		||||
        :return: Movie's string representation.
 | 
			
		||||
        """
 | 
			
		||||
        return '{0}(name={1}, year={2}, director={3})'.format(
 | 
			
		||||
            self.__class__.__name__,
 | 
			
		||||
            repr(self.name),
 | 
			
		||||
            repr(self.year),
 | 
			
		||||
            repr(self.director))
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
"""Settings module.
 | 
			
		||||
 | 
			
		||||
This module contains application's settings and constants.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DATA_DIR = os.path.abspath(os.path.dirname(__file__) + '/data')
 | 
			
		||||
MOVIES_CSV_PATH = DATA_DIR + '/movies.csv'
 | 
			
		||||
MOVIES_DB_PATH = DATA_DIR + '/movies.db'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
"""Dependency injector top-level package."""
 | 
			
		||||
 | 
			
		||||
__version__ = '3.29.0'
 | 
			
		||||
__version__ = '3.30.0'
 | 
			
		||||
"""Version number that follows semantic versioning.
 | 
			
		||||
 | 
			
		||||
:type: str
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user