diff --git a/examples/stories/movie_lister/app_csv.py b/examples/stories/movie_lister/app_csv.py index b444e105..cf4dd67d 100644 --- a/examples/stories/movie_lister/app_csv.py +++ b/examples/stories/movie_lister/app_csv.py @@ -1,33 +1,45 @@ """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. +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. """ -from movies.module import MoviesModule -from movies.components import CsvMovieFinder +from movies import MoviesModule +from movies import finders from settings import MOVIES_CSV_PATH from dependency_injector import catalogs from dependency_injector import providers +from dependency_injector import injections @catalogs.override(MoviesModule) class MyMoviesModule(catalogs.DeclarativeCatalog): - """Customized catalog of movie module components.""" + """Customized catalog of movies module components.""" - movie_finder = providers.Factory(CsvMovieFinder, + movie_finder = providers.Factory(finders.CsvMovieFinder, + *MoviesModule.movie_finder.injections, csv_file=MOVIES_CSV_PATH, delimeter=',') + """:type: providers.Provider -> finders.CsvMovieFinder""" -def main(): - """Main function.""" - movie_lister = MoviesModule.movie_lister() +@injections.inject(MoviesModule.movie_lister) +def main(movie_lister): + """Main function. + 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: :py:class:`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') diff --git a/examples/stories/movie_lister/app_db.py b/examples/stories/movie_lister/app_db.py index d6f78ada..3635092d 100644 --- a/examples/stories/movie_lister/app_db.py +++ b/examples/stories/movie_lister/app_db.py @@ -1,20 +1,24 @@ """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. +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 -from movies.module import MoviesModule -from movies.components import SqliteMovieFinder +from movies import MoviesModule +from movies import finders from settings import MOVIES_DB_PATH from dependency_injector import catalogs from dependency_injector import providers +from dependency_injector import injections class ApplicationModule(catalogs.DeclarativeCatalog): @@ -22,21 +26,29 @@ class ApplicationModule(catalogs.DeclarativeCatalog): database = providers.Singleton(sqlite3.connect, MOVIES_DB_PATH) - """:type: providers.Provider -> components.MovieFinder""" + """:type: providers.Provider -> sqlite3.Connection""" @catalogs.override(MoviesModule) class MyMoviesModule(catalogs.DeclarativeCatalog): - """Customized catalog of movie module components.""" + """Customized catalog of movies module components.""" - movie_finder = providers.Factory(SqliteMovieFinder, + movie_finder = providers.Factory(finders.SqliteMovieFinder, + *MoviesModule.movie_finder.injections, database=ApplicationModule.database) + """:type: providers.Provider -> finders.SqliteMovieFinder""" -def main(): - """Main function.""" - movie_lister = MoviesModule.movie_lister() +@injections.inject(MoviesModule.movie_lister) +def main(movie_lister): + """Main function. + 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: :py:class:`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') diff --git a/examples/stories/movie_lister/movies/__init__.py b/examples/stories/movie_lister/movies/__init__.py index 29dd5aaa..b1cdbc7b 100644 --- a/examples/stories/movie_lister/movies/__init__.py +++ b/examples/stories/movie_lister/movies/__init__.py @@ -1 +1,23 @@ """Movies package.""" + +from . import finders +from . import listers +from . import models + +from dependency_injector import catalogs +from dependency_injector import providers + + +class MoviesModule(catalogs.DeclarativeCatalog): + """Catalog of movies module components.""" + + movie_model = providers.DelegatedFactory(models.Movie) + """:type: providers.Provider -> models.Movie""" + + movie_finder = providers.Factory(finders.MovieFinder, + movie_model=movie_model) + """:type: providers.Provider -> finders.MovieFinder""" + + movie_lister = providers.Factory(listers.MovieLister, + movie_finder=movie_finder) + """:type: providers.Provider -> listers.MovieLister""" diff --git a/examples/stories/movie_lister/movies/components.py b/examples/stories/movie_lister/movies/components.py deleted file mode 100644 index 14ae4fdd..00000000 --- a/examples/stories/movie_lister/movies/components.py +++ /dev/null @@ -1,100 +0,0 @@ -"""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)) diff --git a/examples/stories/movie_lister/movies/finders.py b/examples/stories/movie_lister/movies/finders.py new file mode 100644 index 00000000..21c9f3c9 --- /dev/null +++ b/examples/stories/movie_lister/movies/finders.py @@ -0,0 +1,59 @@ +"""Movie finders.""" + +import csv + + +class MovieFinder(object): + """Movie finder.""" + + def __init__(self, movie_model): + """Initializer.""" + self.movie_model = movie_model + + 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, movie_model, csv_file, delimeter): + """Initializer.""" + self.csv_file = csv_file + self.delimeter = delimeter + super(CsvMovieFinder, self).__init__(movie_model) + + 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 [self.movie_model(*row) for row in reader] + + +class SqliteMovieFinder(MovieFinder): + """Movie finder that fetches movies info from sqlite database.""" + + def __init__(self, movie_model, database): + """Initializer.""" + self.database = database + super(SqliteMovieFinder, self).__init__(movie_model) + + 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 [self.movie_model(*row) for row in rows] diff --git a/examples/stories/movie_lister/movies/listers.py b/examples/stories/movie_lister/movies/listers.py new file mode 100644 index 00000000..f70aa75f --- /dev/null +++ b/examples/stories/movie_lister/movies/listers.py @@ -0,0 +1,33 @@ +"""Movie listers.""" + + +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] diff --git a/examples/stories/movie_lister/movies/models.py b/examples/stories/movie_lister/movies/models.py new file mode 100644 index 00000000..e1b5a174 --- /dev/null +++ b/examples/stories/movie_lister/movies/models.py @@ -0,0 +1,19 @@ +"""Movie models.""" + + +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 '{0}(name={1}, year={2}, director={3})'.format( + self.__class__.__name__, + repr(self.name), + repr(self.year), + repr(self.director)) diff --git a/examples/stories/movie_lister/movies/module.py b/examples/stories/movie_lister/movies/module.py deleted file mode 100644 index b0e4ad58..00000000 --- a/examples/stories/movie_lister/movies/module.py +++ /dev/null @@ -1,17 +0,0 @@ -"""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"""