From 50af2508e856f7297d2597b45b81fcafeb40658b Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Thu, 16 Aug 2018 23:52:29 +0300 Subject: [PATCH 1/9] Add factory patterns --- .../factory_patterns/chained_factories.py | 59 ++++++++++++++++ examples/miniapps/factory_patterns/data.py | 41 +++++++++++ .../factory_patterns/factory_of_factories.py | 69 +++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 examples/miniapps/factory_patterns/chained_factories.py create mode 100644 examples/miniapps/factory_patterns/data.py create mode 100644 examples/miniapps/factory_patterns/factory_of_factories.py diff --git a/examples/miniapps/factory_patterns/chained_factories.py b/examples/miniapps/factory_patterns/chained_factories.py new file mode 100644 index 00000000..993d1fa2 --- /dev/null +++ b/examples/miniapps/factory_patterns/chained_factories.py @@ -0,0 +1,59 @@ +"""`Chained Factories` pattern.""" + +from dependency_injector import providers + +from data import ( + id_generator, + session, + SqlAlchemyDatabaseService, + TokensService, + Token, + UsersService, + User, +) + + +# "Chained Factories" pattern + +database = providers.Factory(SqlAlchemyDatabaseService, session=session) + +tokens = providers.Factory( + TokensService, + id_generator=id_generator, + database=providers.Factory(database, base_class=Token), +) + +users = providers.Factory( + UsersService, + id_generator=id_generator, + database=providers.Factory(database, base_class=User), +) + +tokens_service = tokens() +assert tokens_service.database.base_class is Token + +users_service = users() +assert users_service.database.base_class is User + +# Explanation & some more examples + +# 1. Keyword arguments of upper level factory are added to lower level factory +chained_dict_factory = providers.Factory( + providers.Factory(dict, arg1=1), + arg2=2, +) +print(chained_dict_factory()) # prints: {'arg1': 1, 'arg2': 2} + +# 2. Keyword arguments of upper level factory have priority +chained_dict_factory = providers.Factory( + providers.Factory(dict, arg1=1), + arg1=2, +) +print(chained_dict_factory()) # prints: {'arg1': 2} + +# 3. Keyword arguments provided from context have most priority +chained_dict_factory = providers.Factory( + providers.Factory(dict, arg1=1), + arg1=2, +) +print(chained_dict_factory(arg1=3)) # prints: {'arg1': 3} diff --git a/examples/miniapps/factory_patterns/data.py b/examples/miniapps/factory_patterns/data.py new file mode 100644 index 00000000..80fdd20f --- /dev/null +++ b/examples/miniapps/factory_patterns/data.py @@ -0,0 +1,41 @@ +"""Sample data classes.""" + + +class SqlAlchemyDatabaseService: + """Database service of an entity.""" + + def __init__(self, session, base_class): + """Initialize object.""" + self.session = session + self.base_class = base_class + + +class TokensService: + """Tokens service.""" + + def __init__(self, id_generator, database): + """Initialize object.""" + self.id_generator = id_generator + self.database = database + + +class Token: + """Token entity.""" + + +class UsersService: + """Users service.""" + + def __init__(self, id_generator, database): + """Initialize object.""" + self.id_generator = id_generator + self.database = database + + +class User: + """User entity.""" + + +# Sample objects +session = object() +id_generator = object() diff --git a/examples/miniapps/factory_patterns/factory_of_factories.py b/examples/miniapps/factory_patterns/factory_of_factories.py new file mode 100644 index 00000000..7a6a5fc1 --- /dev/null +++ b/examples/miniapps/factory_patterns/factory_of_factories.py @@ -0,0 +1,69 @@ +"""`Factory of Factories` pattern.""" + +from dependency_injector import providers + +from data import ( + id_generator, + session, + SqlAlchemyDatabaseService, + TokensService, + Token, + UsersService, + User, +) + + +# "Factory of Factories" pattern + +database_factory = providers.Factory( + providers.Factory, + SqlAlchemyDatabaseService, + session=session, +) + +tokens = providers.Factory( + TokensService, + id_generator=id_generator, + database=database_factory(base_class=Token), +) + +users = providers.Factory( + UsersService, + id_generator=id_generator, + database=database_factory(base_class=User), +) + +tokens_service = tokens() +assert tokens_service.database.base_class is Token + +users_service = users() +assert users_service.database.base_class is User + +# Explanation & some more examples + +# 1. Keyword arguments of upper level factory are added to lower level factory +factory_of_dict_factories = providers.Factory( + providers.Factory, + dict, + arg1=1, +) +dict_factory = factory_of_dict_factories(arg2=2) +print(dict_factory()) # prints: {'arg1': 1, 'arg2': 2} + +# 2. Keyword arguments of upper level factory have priority +factory_of_dict_factories = providers.Factory( + providers.Factory, + dict, + arg1=1, +) +dict_factory = factory_of_dict_factories(arg1=2) +print(dict_factory()) # prints: {'arg1': 2} + +# 3. Keyword arguments provided from context have most priority +factory_of_dict_factories = providers.Factory( + providers.Factory, + dict, + arg1=1, +) +dict_factory = factory_of_dict_factories(arg1=2) +print(dict_factory(arg1=3)) # prints: {'arg1': 3} From 2a051ffd70be90a4e64a4f583dc8d55c9294d0e6 Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Thu, 16 Aug 2018 23:52:56 +0300 Subject: [PATCH 2/9] Add factory patterns to docs --- docs/examples/chained_factories.rst | 22 ++++++++++++++++++++++ docs/examples/factory_of_factories.rst | 22 ++++++++++++++++++++++ docs/examples/index.rst | 2 ++ 3 files changed, 46 insertions(+) create mode 100644 docs/examples/chained_factories.rst create mode 100644 docs/examples/factory_of_factories.rst diff --git a/docs/examples/chained_factories.rst b/docs/examples/chained_factories.rst new file mode 100644 index 00000000..9233af7c --- /dev/null +++ b/docs/examples/chained_factories.rst @@ -0,0 +1,22 @@ +Chained Factories pattern +========================= + +This example demonstrate implementation of "Chained Factories" pattern. +Main idea of this pattern is about wrapping `Factory` into other `Factory` +that mix additional arguments or keyword arguments to a wrapped one. + +Listing of ``data.py``, demonstrates sample classes structure: + +.. literalinclude:: ../../examples/miniapps/factory_patterns/data.py + :language: python + :linenos: + +Listing of ``chained_factories.py``, demonstrates "Chained Factories" +pattern and provide some explanation: + +.. literalinclude:: ../../examples/miniapps/factory_patterns/chained_factories.py + :language: python + :linenos: + + +.. disqus:: diff --git a/docs/examples/factory_of_factories.rst b/docs/examples/factory_of_factories.rst new file mode 100644 index 00000000..adabd042 --- /dev/null +++ b/docs/examples/factory_of_factories.rst @@ -0,0 +1,22 @@ +Factory of Factories pattern +============================ + +This example demonstrate implementation of "Factory of Factories" pattern. +Main idea of this pattern is about creation of a :py:class:`Factory` that +creates another :py:class:`Factory` and mix additional arguments to it. + +Listing of ``data.py``, demonstrates sample classes structure: + +.. literalinclude:: ../../examples/miniapps/factory_patterns/data.py + :language: python + :linenos: + +Listing of ``factory_of_factories.py``, demonstrates "Chained Factories" +pattern and provide some explanation: + +.. literalinclude:: ../../examples/miniapps/factory_patterns/factory_of_factories.py + :language: python + :linenos: + + +.. disqus:: diff --git a/docs/examples/index.rst b/docs/examples/index.rst index 977a35a2..c61c4009 100644 --- a/docs/examples/index.rst +++ b/docs/examples/index.rst @@ -21,3 +21,5 @@ and powered by *Dependency Injector* framework. bundles_miniapp use_cases_miniapp password_hashing_miniapp + chained_factories + factory_of_factories From 7aa07449b2b7226367e85be8e113393c917c9215 Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Thu, 16 Aug 2018 23:53:22 +0300 Subject: [PATCH 3/9] Bump version to 3.12.5 --- docs/main/changelog.rst | 5 +++++ src/dependency_injector/__init__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/main/changelog.rst b/docs/main/changelog.rst index 16d3679b..838befe3 100644 --- a/docs/main/changelog.rst +++ b/docs/main/changelog.rst @@ -7,6 +7,11 @@ that were made in every particular version. From version 0.7.6 *Dependency Injector* framework strictly follows `Semantic versioning`_ +3.12.5 +------ +- Add example of "Chained Factories" pattern. +- Add example of "Factory of Factories" pattern. + 3.12.4 ------ - Fix bug `#200 `_. diff --git a/src/dependency_injector/__init__.py b/src/dependency_injector/__init__.py index 80683df0..ba56ac14 100644 --- a/src/dependency_injector/__init__.py +++ b/src/dependency_injector/__init__.py @@ -1,6 +1,6 @@ """Dependency injector top-level package.""" -__version__ = '3.12.4' +__version__ = '3.12.5' """Version number that follows semantic versioning. :type: str From e13d3b4271f646905041b6f4a9cef59fa0a707a1 Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Fri, 17 Aug 2018 00:01:26 +0300 Subject: [PATCH 4/9] Try remove py3 - virtualenv16 incompatibility fix --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 42d594fc..cd8d8425 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ sudo: false install: - pip install tox - - if [[ $TRAVIS_PYTHON_VERSION == 3.3 ]]; then pip install virtualenv==15.2.0; fi script: - tox language: From 4cdc5bce56790c1ee7ca920c321ba601feb3bf78 Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Fri, 17 Aug 2018 00:06:20 +0300 Subject: [PATCH 5/9] Drop python 2.6 and 3.3 support --- .travis.yml | 4 ---- setup.py | 2 -- 2 files changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index cd8d8425..1f478402 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,12 +19,8 @@ matrix: env: TOXENV=flake8 - python: 2.7 env: TOXENV=pydocstyle - - python: 2.6 - env: TOXENV=py26 - python: 2.7 env: TOXENV=py27 - - python: 3.3 - env: TOXENV=py33 - python: 3.4 env: TOXENV=py34 - python: 3.5 diff --git a/setup.py b/setup.py index 768eae5c..1a3858d8 100644 --- a/setup.py +++ b/setup.py @@ -78,10 +78,8 @@ setup(name='dependency-injector', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', From d90b7945684029b784468b7d27362086828e5122 Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Fri, 17 Aug 2018 00:13:41 +0300 Subject: [PATCH 6/9] Add python 3.7 support --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1f478402..51fc4f0c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,10 @@ matrix: env: TOXENV=py35 - python: 3.6 env: TOXENV=py36 + - python: 3.7 + env: TOXENV=py37 + sudo: required + dist: xenial - python: pypy env: TOXENV=pypy notifications: From 7daf23eb2bbfafb4b4c5f3a52e7b09cdcd7b4ba3 Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Fri, 17 Aug 2018 00:17:47 +0300 Subject: [PATCH 7/9] Add python 3.7 to the list of classifiers --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 1a3858d8..47eb0b78 100644 --- a/setup.py +++ b/setup.py @@ -83,6 +83,7 @@ setup(name='dependency-injector', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Software Development', From 0757f492a5a7add836888c462270a1624015680a Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Fri, 17 Aug 2018 00:17:57 +0300 Subject: [PATCH 8/9] Update changelog --- docs/main/changelog.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/main/changelog.rst b/docs/main/changelog.rst index 838befe3..f63ebaa2 100644 --- a/docs/main/changelog.rst +++ b/docs/main/changelog.rst @@ -7,8 +7,11 @@ that were made in every particular version. From version 0.7.6 *Dependency Injector* framework strictly follows `Semantic versioning`_ -3.12.5 +3.13.0 ------ +- Add Python 3.7 support. +- Drop Python 3.3 support. +- Drop Python 2.6 support. - Add example of "Chained Factories" pattern. - Add example of "Factory of Factories" pattern. From bd43d62f98e2feeb7af01fee9b8e3760408af362 Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Fri, 17 Aug 2018 00:18:35 +0300 Subject: [PATCH 9/9] Bump version to 3.13.0 --- src/dependency_injector/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dependency_injector/__init__.py b/src/dependency_injector/__init__.py index ba56ac14..546bedd9 100644 --- a/src/dependency_injector/__init__.py +++ b/src/dependency_injector/__init__.py @@ -1,6 +1,6 @@ """Dependency injector top-level package.""" -__version__ = '3.12.5' +__version__ = '3.13.0' """Version number that follows semantic versioning. :type: str