Add draft version of MovieLister example

This commit is contained in:
Roman Mogilatov 2016-03-18 18:47:44 +02:00
parent 40f7e6ed26
commit 59615bc88b
8 changed files with 253 additions and 0 deletions

View File

@ -0,0 +1,33 @@
"""Small script for initializing movies data."""
import os
import csv
import sqlite3
import shutil
from settings import DATA_DIR
from settings import MOVIES_CSV_PATH
from settings import MOVIES_DB_PATH
MOVIES = (('The Hunger Games: Mockingjay - Part 2', 2015, 'Francis Lawrence'),
('The 33', 2015, 'Patricia Riggen'),
('Star Wars: Episode VII - The Force Awakens', 2015, 'JJ Abrams'))
if __name__ == '__main__':
# (Re)create data directory:
if os.path.exists(DATA_DIR):
shutil.rmtree(DATA_DIR)
os.makedirs(DATA_DIR)
# Initialize sqlite database:
connection = sqlite3.connect(MOVIES_DB_PATH)
with connection:
connection.execute('CREATE TABLE movies '
'(name text, year int, director text)')
connection.executemany('INSERT INTO movies VALUES (?,?,?)', MOVIES)
# Initialize csv database:
with open(MOVIES_CSV_PATH, 'w') as csv_file:
csv.writer(csv_file).writerows(MOVIES)

View File

@ -0,0 +1,39 @@
"""A naive example of dependency injection in 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
"""
from movies.module import MoviesModule
from movies.components import CsvMovieFinder
from settings import MOVIES_CSV_PATH
from dependency_injector import catalogs
from dependency_injector import providers
@catalogs.override(MoviesModule)
class MyMoviesModule(catalogs.DeclarativeCatalog):
"""Customized catalog of movie module components."""
movie_finder = providers.Factory(CsvMovieFinder,
csv_file=MOVIES_CSV_PATH,
delimeter=',')
def main():
"""Main function."""
movie_lister = MoviesModule.movie_lister()
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)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,48 @@
"""A naive example of dependency injection in 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
"""
import sqlite3
from movies.module import MoviesModule
from movies.components import SqliteMovieFinder
from settings import MOVIES_DB_PATH
from dependency_injector import catalogs
from dependency_injector import providers
class ApplicationModule(catalogs.DeclarativeCatalog):
"""Catalog of application components."""
database = providers.Singleton(sqlite3.connect,
MOVIES_DB_PATH)
""":type: providers.Provider -> components.MovieFinder"""
@catalogs.override(MoviesModule)
class MyMoviesModule(catalogs.DeclarativeCatalog):
"""Customized catalog of movie module components."""
movie_finder = providers.Factory(SqliteMovieFinder,
database=ApplicationModule.database)
def main():
"""Main function."""
movie_lister = MoviesModule.movie_lister()
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)
if __name__ == '__main__':
main()

View File

@ -0,0 +1 @@
movies.*

View File

@ -0,0 +1 @@
"""Movies package."""

View File

@ -0,0 +1,100 @@
"""Movies package components."""
import csv
class MovieLister(object):
"""Movie lister."""
def __init__(self, movie_finder):
"""Initializer."""
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[:py:class:`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[:py:class:`Movie`]
:return: List of movie instances.
"""
return [movie for movie in self.movie_finder.find_all()
if movie.year == year]
class MovieFinder(object):
"""Movie finder."""
def find_all(self):
"""Return all found movies.
:rtype: list[:py:class:`Movie`]
:return: List of movie instances.
"""
raise NotImplementedError()
class CsvMovieFinder(MovieFinder):
"""Movie finder that fetches movies info from csv file."""
def __init__(self, csv_file, delimeter):
"""Initializer."""
self.csv_file = csv_file
self.delimeter = delimeter
def find_all(self):
"""Return all found movies.
:rtype: list[:py:class:`Movie`]
:return: List of movie instances.
"""
with open(self.csv_file) as csv_file:
reader = csv.reader(csv_file, delimiter=self.delimeter)
return [Movie(*row) for row in reader]
class SqliteMovieFinder(MovieFinder):
"""Movie finder that fetches movies info from sqlite database."""
def __init__(self, database):
"""Initializer."""
self.database = database
def find_all(self):
"""Return all found movies.
:rtype: list[:py:class:`Movie`]
:return: List of movie instances.
"""
with self.database:
rows = self.database.execute('SELECT name, year, director '
'FROM movies')
return [Movie(*row) for row in rows]
class Movie(object):
"""Movie model."""
def __init__(self, name, year, director):
"""Initializer."""
self.name = str(name)
self.year = int(year)
self.director = str(director)
def __repr__(self):
"""Return string representation of movie instance."""
return 'Movie(name={0}, year={1}, director={2})'.format(
repr(self.name), repr(self.year), repr(self.director))

View File

@ -0,0 +1,17 @@
"""Movies package dependency injection module."""
from . import components
from dependency_injector import catalogs
from dependency_injector import providers
class MoviesModule(catalogs.DeclarativeCatalog):
"""Catalog of movie module components."""
movie_finder = providers.Factory(components.MovieFinder)
""":type: providers.Provider -> components.MovieFinder"""
movie_lister = providers.Factory(components.MovieLister,
movie_finder=movie_finder)
""":type: providers.Provider -> components.MovieLister"""

View File

@ -0,0 +1,14 @@
"""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_CSV_DELIMETER = ','
MOVIES_DB_PATH = DATA_DIR + '/movies.db'