Merge branch 'release/3.22.0' into master

This commit is contained in:
Roman Mogylatov 2020-07-18 00:45:22 -04:00
commit 3ee629eb5d
56 changed files with 273 additions and 230 deletions

View File

@ -55,10 +55,12 @@ What is ``Dependency Injector``?
Why do I need it? Why do I need it?
================= =================
``Dependency Injector`` helps you improve application structure. ``Dependency Injector`` helps you understand and change the structure of the application.
With the ``Dependency Injector`` you keep **application structure in one place**. With the ``Dependency Injector`` you keep **application structure in one place**.
This place is called **the container**. You use the container to manage all the components of the application. All the component dependencies are defined explicitly. This provides the control on the application structure. It is **easy to understand and change** it. This place is called **the container**. You use the container to manage all the components of the
application. All the component dependencies are defined explicitly. This provides the control on
the application structure. It is **easy to understand and change** it.
.. figure:: https://raw.githubusercontent.com/wiki/ets-labs/python-dependency-injector/img/di-map.svg .. figure:: https://raw.githubusercontent.com/wiki/ets-labs/python-dependency-injector/img/di-map.svg
:target: https://github.com/ets-labs/python-dependency-injector :target: https://github.com/ets-labs/python-dependency-injector
@ -72,6 +74,7 @@ This place is called **the container**. You use the container to manage all the
from dependency_injector import containers, providers from dependency_injector import containers, providers
from dependency_injector.ext import flask from dependency_injector.ext import flask
from flask import Flask from flask import Flask
from flask_bootstrap import Bootstrap
from github import Github from github import Github
from . import views, services from . import views, services
@ -82,6 +85,8 @@ This place is called **the container**. You use the container to manage all the
app = flask.Application(Flask, __name__) app = flask.Application(Flask, __name__)
bootstrap = flask.Extension(Bootstrap)
config = providers.Configuration() config = providers.Configuration()
github_client = providers.Factory( github_client = providers.Factory(
@ -118,6 +123,9 @@ Running such container looks like this:
app = container.app() app = container.app()
app.container = container app.container = container
bootstrap = container.bootstrap()
bootstrap.init_app(app)
app.add_url_rule('/', view_func=container.index_view.as_view()) app.add_url_rule('/', view_func=container.index_view.as_view())
return app return app

1
docs/_static/logo.svg vendored Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -1,5 +1,5 @@
``dependency_injector.containers`` dependency_injector.containers
---------------------------------- ==============================
.. automodule:: dependency_injector.containers .. automodule:: dependency_injector.containers
:members: :members:

View File

@ -1,5 +1,5 @@
``dependency_injector.errors`` dependency_injector.errors
------------------------------ ==========================
.. automodule:: dependency_injector.errors .. automodule:: dependency_injector.errors
:members: :members:

View File

@ -1,5 +1,5 @@
``dependency_injector.ext.flask`` dependency_injector.ext.flask
--------------------------------- =============================
.. automodule:: dependency_injector.ext.flask .. automodule:: dependency_injector.ext.flask
:members: :members:

View File

@ -1,5 +1,5 @@
``dependency_injector.providers`` dependency_injector.providers
--------------------------------- =============================
.. automodule:: dependency_injector.providers .. automodule:: dependency_injector.providers
:members: :members:

View File

@ -1,5 +1,5 @@
``dependency_injector`` dependency_injector
----------------------- ===================
.. automodule:: dependency_injector .. automodule:: dependency_injector
:members: __version__ :members: __version__

View File

@ -15,6 +15,7 @@
import os import os
import re import re
import sys import sys
import alabaster
# If extensions (or modules to document with autodoc) are in another directory, # If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
@ -29,8 +30,11 @@ sys.path.insert(0, os.path.abspath('..'))
# Add any Sphinx extension module names here, as strings. They can be # Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones. # ones.
extensions = ['sphinx.ext.autodoc', extensions = [
'sphinxcontrib.disqus'] 'alabaster',
'sphinx.ext.autodoc',
'sphinxcontrib.disqus',
]
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates'] templates_path = ['_templates']
@ -112,7 +116,8 @@ todo_include_todos = False
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
html_theme = 'sphinx_rtd_theme' # html_theme = 'sphinx_rtd_theme'
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme # Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the # further. For a list of options available for each theme, see the
@ -120,7 +125,7 @@ html_theme = 'sphinx_rtd_theme'
# html_context = {} # html_context = {}
# Add any paths that contain custom themes here, relative to this directory. # Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = ['_themes'] html_theme_path = [alabaster.get_path()]
# The name for this set of Sphinx documents. If None, it defaults to # The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation". # "<project> v<release> documentation".
@ -291,6 +296,13 @@ autodoc_member_order = 'bysource'
disqus_shortname = 'python-dependency-injector' disqus_shortname = 'python-dependency-injector'
html_theme_options = {
def setup(app): 'github_user': 'ets-labs',
app.add_css_file('sphinx_rtd_theme-hotfix.css') 'github_repo': 'python-dependency-injector',
'github_type': 'star',
'github_button': True,
'github_banner': True,
'logo': 'logo.svg',
'description': 'Dependency injection framework for Python',
'code_font_size': '10pt',
}

View File

@ -32,7 +32,6 @@ factories:
.. literalinclude:: ../../examples/containers/declarative.py .. literalinclude:: ../../examples/containers/declarative.py
:language: python :language: python
:linenos:
Example of declarative containers inheritance: Example of declarative containers inheritance:
@ -42,7 +41,6 @@ Example of declarative containers inheritance:
.. literalinclude:: ../../examples/containers/declarative_inheritance.py .. literalinclude:: ../../examples/containers/declarative_inheritance.py
:language: python :language: python
:linenos:
Example of declarative containers's provider injections: Example of declarative containers's provider injections:
@ -52,7 +50,6 @@ Example of declarative containers's provider injections:
.. literalinclude:: ../../examples/containers/declarative_injections.py .. literalinclude:: ../../examples/containers/declarative_injections.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -17,14 +17,12 @@ Here is an simple example of defining dynamic container with several factories:
.. literalinclude:: ../../examples/containers/dynamic.py .. literalinclude:: ../../examples/containers/dynamic.py
:language: python :language: python
:linenos:
Next example demonstrates creation of dynamic container based on some Next example demonstrates creation of dynamic container based on some
configuration: configuration:
.. literalinclude:: ../../examples/containers/dynamic_runtime_creation.py .. literalinclude:: ../../examples/containers/dynamic_runtime_creation.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -18,13 +18,11 @@ method:
.. literalinclude:: ../../examples/containers/override_declarative.py .. literalinclude:: ../../examples/containers/override_declarative.py
:language: python :language: python
:linenos:
Example of overriding container using :py:func:`override` decorator: Example of overriding container using :py:func:`override` decorator:
.. literalinclude:: ../../examples/containers/override_declarative_decorator.py .. literalinclude:: ../../examples/containers/override_declarative_decorator.py
:language: python :language: python
:linenos:
Also there are several useful :py:class:`DeclarativeContainer` methods and Also there are several useful :py:class:`DeclarativeContainer` methods and
properties that help to work with container overridings: properties that help to work with container overridings:

View File

@ -14,14 +14,12 @@ for limitation of its provided type:
.. literalinclude:: ../../examples/containers/declarative_provider_type.py .. literalinclude:: ../../examples/containers/declarative_provider_type.py
:language: python :language: python
:linenos:
Limitation for providers type could be used with :py:class:`DynamicContainer` Limitation for providers type could be used with :py:class:`DynamicContainer`
as well: as well:
.. literalinclude:: ../../examples/containers/dynamic_provider_type.py .. literalinclude:: ../../examples/containers/dynamic_provider_type.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -37,7 +37,6 @@ Listing of ``bundles/users/__init__.py``:
.. literalinclude:: ../../examples/miniapps/bundles/bundles/users/__init__.py .. literalinclude:: ../../examples/miniapps/bundles/bundles/users/__init__.py
:language: python :language: python
:linenos:
.. note:: .. note::
@ -47,7 +46,6 @@ Listing of ``bundles/photos/__init__.py``:
.. literalinclude:: ../../examples/miniapps/bundles/bundles/photos/__init__.py .. literalinclude:: ../../examples/miniapps/bundles/bundles/photos/__init__.py
:language: python :language: python
:linenos:
.. note:: .. note::
@ -65,7 +63,6 @@ Listing of ``run.py``:
.. literalinclude:: ../../examples/miniapps/bundles/run.py .. literalinclude:: ../../examples/miniapps/bundles/run.py
:language: python :language: python
:linenos:
Links Links
~~~~~ ~~~~~

View File

@ -10,14 +10,12 @@ Listing of ``data.py``, demonstrates sample classes structure:
.. literalinclude:: ../../examples/miniapps/factory_patterns/data.py .. literalinclude:: ../../examples/miniapps/factory_patterns/data.py
:language: python :language: python
:linenos:
Listing of ``chained_factories.py``, demonstrates "Chained Factories" Listing of ``chained_factories.py``, demonstrates "Chained Factories"
pattern and provide some explanation: pattern and provide some explanation:
.. literalinclude:: ../../examples/miniapps/factory_patterns/chained_factories.py .. literalinclude:: ../../examples/miniapps/factory_patterns/chained_factories.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -9,14 +9,12 @@ Listing of ``data.py``, demonstrates sample classes structure:
.. literalinclude:: ../../examples/miniapps/factory_patterns/data.py .. literalinclude:: ../../examples/miniapps/factory_patterns/data.py
:language: python :language: python
:linenos:
Listing of ``factory_of_factories.py``, demonstrates "Chained Factories" Listing of ``factory_of_factories.py``, demonstrates "Chained Factories"
pattern and provide some explanation: pattern and provide some explanation:
.. literalinclude:: ../../examples/miniapps/factory_patterns/factory_of_factories.py .. literalinclude:: ../../examples/miniapps/factory_patterns/factory_of_factories.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -70,7 +70,6 @@ Listing of ``movies/__init__.py``:
.. literalinclude:: ../../examples/miniapps/movie_lister/movies/__init__.py .. literalinclude:: ../../examples/miniapps/movie_lister/movies/__init__.py
:language: python :language: python
:linenos:
Example application Example application
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
@ -88,13 +87,11 @@ Listing of ``examples/main.py``:
.. literalinclude:: ../../examples/miniapps/movie_lister/example/main.py .. literalinclude:: ../../examples/miniapps/movie_lister/example/main.py
:language: python :language: python
:linenos:
Listing of ``examples/db.py``: Listing of ``examples/db.py``:
.. literalinclude:: ../../examples/miniapps/movie_lister/example/db.py .. literalinclude:: ../../examples/miniapps/movie_lister/example/db.py
:language: python :language: python
:linenos:
Csv application Csv application
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
@ -103,7 +100,6 @@ Listing of ``app_csv.py``:
.. literalinclude:: ../../examples/miniapps/movie_lister/app_csv.py .. literalinclude:: ../../examples/miniapps/movie_lister/app_csv.py
:language: python :language: python
:linenos:
Database application Database application
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
@ -112,7 +108,6 @@ Listing of ``app_db.py``:
.. literalinclude:: ../../examples/miniapps/movie_lister/app_db.py .. literalinclude:: ../../examples/miniapps/movie_lister/app_db.py
:language: python :language: python
:linenos:
Csv and database application Csv and database application
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -121,7 +116,6 @@ Listing of ``app_db_csv.py``:
.. literalinclude:: ../../examples/miniapps/movie_lister/app_db_csv.py .. literalinclude:: ../../examples/miniapps/movie_lister/app_db_csv.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -14,6 +14,5 @@ Listing of ``example.py``:
.. literalinclude:: ../../examples/miniapps/password_hashing/example.py .. literalinclude:: ../../examples/miniapps/password_hashing/example.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -47,13 +47,11 @@ Listing of ``example/services.py``:
.. literalinclude:: ../../examples/miniapps/services_v1/example/services.py .. literalinclude:: ../../examples/miniapps/services_v1/example/services.py
:language: python :language: python
:linenos:
Listing of ``example/main.py``: Listing of ``example/main.py``:
.. literalinclude:: ../../examples/miniapps/services_v1/example/main.py .. literalinclude:: ../../examples/miniapps/services_v1/example/main.py
:language: python :language: python
:linenos:
IoC containers IoC containers
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
@ -62,7 +60,6 @@ Listing of ``containers.py``:
.. literalinclude:: ../../examples/miniapps/services_v1/containers.py .. literalinclude:: ../../examples/miniapps/services_v1/containers.py
:language: python :language: python
:linenos:
Run application Run application
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
@ -71,7 +68,6 @@ Listing of ``run.py``:
.. literalinclude:: ../../examples/miniapps/services_v1/run.py .. literalinclude:: ../../examples/miniapps/services_v1/run.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -47,13 +47,11 @@ Listing of ``example/services.py``:
.. literalinclude:: ../../examples/miniapps/services_v2/example/services.py .. literalinclude:: ../../examples/miniapps/services_v2/example/services.py
:language: python :language: python
:linenos:
Listing of ``example/main.py``: Listing of ``example/main.py``:
.. literalinclude:: ../../examples/miniapps/services_v2/example/main.py .. literalinclude:: ../../examples/miniapps/services_v2/example/main.py
:language: python :language: python
:linenos:
IoC container IoC container
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
@ -62,7 +60,6 @@ Listing of ``container.py``:
.. literalinclude:: ../../examples/miniapps/services_v2/container.py .. literalinclude:: ../../examples/miniapps/services_v2/container.py
:language: python :language: python
:linenos:
Run application Run application
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
@ -71,7 +68,6 @@ Listing of ``run.py``:
.. literalinclude:: ../../examples/miniapps/services_v2/run.py .. literalinclude:: ../../examples/miniapps/services_v2/run.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -29,7 +29,6 @@ Listing of ``use_cases/containers.py``:
.. literalinclude:: ../../examples/miniapps/use_cases/containers.py .. literalinclude:: ../../examples/miniapps/use_cases/containers.py
:language: python :language: python
:linenos:
Run application Run application
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
@ -38,7 +37,6 @@ Listing of ``run.py``:
.. literalinclude:: ../../examples/miniapps/use_cases/run.py .. literalinclude:: ../../examples/miniapps/use_cases/run.py
:language: python :language: python
:linenos:
Instructions for running: Instructions for running:

View File

@ -17,8 +17,6 @@ Dependency Injector --- Dependency injection framework for Python
.. _index: .. _index:
.. figure:: https://raw.githubusercontent.com/wiki/ets-labs/python-dependency-injector/img/logo.svg
.. image:: https://img.shields.io/pypi/v/dependency_injector.svg .. image:: https://img.shields.io/pypi/v/dependency_injector.svg
:target: https://pypi.org/project/dependency-injector/ :target: https://pypi.org/project/dependency-injector/
:alt: Latest Version :alt: Latest Version
@ -63,27 +61,21 @@ Dependency Injector --- Dependency injection framework for Python
:target: https://coveralls.io/github/ets-labs/python-dependency-injector?branch=master :target: https://coveralls.io/github/ets-labs/python-dependency-injector?branch=master
:alt: Coverage Status :alt: Coverage Status
What is ``Dependency Injector``? ``Dependency Injector`` is a dependency injection framework for Python.
================================
``Dependency Injector`` is a dependency injection microframework for Python. It helps you understand and change the structure of the application.
It was designed to be a unified and developer-friendly tool that helps
implement a dependency injection design pattern in a formal, pretty, and
Pythonic way.
The key features of the *Dependency Injector* framework are: With the ``Dependency Injector`` you keep **application structure in one place**.
This place is called **the container**. You use the container to manage all the components of the
application. All the component dependencies are defined explicitly. This provides the control on
the application structure. It is **easy to understand and change** it.
+ Easy, smart, and pythonic style. .. figure:: https://raw.githubusercontent.com/wiki/ets-labs/python-dependency-injector/img/di-map.svg
+ Obvious and clear structure. :target: https://github.com/ets-labs/python-dependency-injector
+ Extensibility and flexibility.
+ High performance.
+ Memory efficiency.
+ Thread safety.
+ Documented.
+ Semantically versioned.
*Dependency Injector* containers and providers are implemented as C extension *The container is like a map of your application. You always know what depends on what.*
types using Cython.
Explore the documentation to know more about the ``Dependency Injector``.
Contents Contents
-------- --------
@ -93,6 +85,7 @@ Contents
introduction/index introduction/index
main/installation main/installation
tutorials/index
providers/index providers/index
containers/index containers/index
examples/index examples/index

View File

@ -103,19 +103,16 @@ Listing of ``example.engines`` module:
.. literalinclude:: ../../examples/miniapps/engines_cars/example/engines.py .. literalinclude:: ../../examples/miniapps/engines_cars/example/engines.py
:language: python :language: python
:linenos:
Listing of ``example.cars`` module: Listing of ``example.cars`` module:
.. literalinclude:: ../../examples/miniapps/engines_cars/example/cars.py .. literalinclude:: ../../examples/miniapps/engines_cars/example/cars.py
:language: python :language: python
:linenos:
Next example demonstrates creation of several cars with different engines: Next example demonstrates creation of several cars with different engines:
.. literalinclude:: ../../examples/miniapps/engines_cars/example_di.py .. literalinclude:: ../../examples/miniapps/engines_cars/example_di.py
:language: python :language: python
:linenos:
While previous example demonstrates advantages of dependency injection, there While previous example demonstrates advantages of dependency injection, there
is a disadvantage demonstration as well - creation of car requires additional is a disadvantage demonstration as well - creation of car requires additional
@ -128,7 +125,6 @@ using :doc:`Dependency Injector <../index>`:
.. literalinclude:: ../../examples/miniapps/engines_cars/example_ioc_containers.py .. literalinclude:: ../../examples/miniapps/engines_cars/example_ioc_containers.py
:language: python :language: python
:linenos:
Useful links Useful links
~~~~~~~~~~~~ ~~~~~~~~~~~~

View File

@ -1,5 +1,5 @@
Key features of Dependency Injector Key features
----------------------------------- ------------
.. meta:: .. meta::
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control :keywords: Python,DI,Dependency injection,IoC,Inversion of Control
@ -7,13 +7,16 @@ Key features of Dependency Injector
framework. It also provides some cases and recommendations framework. It also provides some cases and recommendations
about usage of "Dependency Injector" framework. about usage of "Dependency Injector" framework.
*Dependency Injector* is a dependency injection framework for Python projects.
It was designed to be unified, developer-friendly tool for managing any kind
of Python objects and their dependencies in formal, pretty way.
*Dependency Injector* framework key features are: ``Dependency Injector`` is a dependency injection framework for Python.
It was designed to be a unified and developer-friendly tool that helps
implement a dependency injection design pattern in a formal, pretty, and
Pythonic way.
+ Easy, smart, and pythonic style. The key features of the ``Dependency Injector`` framework are:
+ Easy, smart, and Pythonic style.
+ Does NOT pollute client code.
+ Obvious and clear structure. + Obvious and clear structure.
+ Extensibility and flexibility. + Extensibility and flexibility.
+ High performance. + High performance.
@ -21,29 +24,28 @@ of Python objects and their dependencies in formal, pretty way.
+ Thread safety. + Thread safety.
+ Documented. + Documented.
+ Semantically versioned. + Semantically versioned.
+ Distributed as pre-compiled wheels.
*Dependency Injector* framework could be used in different application types: ``Dependency Injector`` containers and providers are implemented as C extension
types using ``Cython``.
+ Web applications based on Flask, Django or any other web framework. ``Dependency Injector`` framework can be used in the different application types:
+ Asynchronous applications based on asyncio, Tornado and Twisted.
+ Web applications based on the ``Flask``, ``Django`` or any other web framework.
+ Asynchronous applications ``asyncio``, ``aiohttp``, ``Tornado``, or ``Twisted``.
+ Standalone frameworks and libraries. + Standalone frameworks and libraries.
+ GUI applications. + GUI applications.
*Dependency Injector* framework could be integrated on different project ``Dependency Injector`` framework can be integrated on the different project
stages: stages:
+ It could be used in the beginning of development of new applications. + It can be used in the beginning of the development of a new application.
+ It could be integrated into applications that are in active development + It can be integrated into application that is on its active development stage.
stage. + It can be used for refactoring of legacy application.
+ It could be used for refactoring of legacy applications.
Components of *Dependency Injector* framework could be used: Components of ``Dependency Injector`` framework could be used:
+ In composition with each other. + In composition with each other.
+ Separately between each other. + Independently from each other.
Main idea of *Dependency Injector* framework is to be useful tool for the
right thing.
.. disqus:: .. disqus::

View File

@ -83,14 +83,12 @@ Let's go through the code of ``example.py``:
.. literalinclude:: ../../examples/di_demo/example.py .. literalinclude:: ../../examples/di_demo/example.py
:language: python :language: python
:linenos:
At some point, things defined above mean, that the code from ``example.py``, At some point, things defined above mean, that the code from ``example.py``,
could look different, like in ``example_di.py``: could look different, like in ``example_di.py``:
.. literalinclude:: ../../examples/di_demo/example_di.py .. literalinclude:: ../../examples/di_demo/example_di.py
:language: python :language: python
:linenos:
Best explanation, ever Best explanation, ever
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~

View File

@ -7,6 +7,12 @@ that were made in every particular version.
From version 0.7.6 *Dependency Injector* framework strictly From version 0.7.6 *Dependency Injector* framework strictly
follows `Semantic versioning`_ follows `Semantic versioning`_
3.22.0
------
- Migrate docs to ``alabaster`` theme.
- Add ``Bootstrap`` extension to the ``ghnav-flask`` example.
- Add stubs for the tutorials to the docs.
3.21.2 3.21.2
------ ------
- Hotfix changelog typo. - Hotfix changelog typo.

View File

@ -30,7 +30,6 @@ injections:
.. literalinclude:: ../../examples/providers/callable_args.py .. literalinclude:: ../../examples/providers/callable_args.py
:language: python :language: python
:linenos:
Next one example shows usage of :py:class:`Callable` with keyword argument Next one example shows usage of :py:class:`Callable` with keyword argument
injections: injections:
@ -41,7 +40,6 @@ injections:
.. literalinclude:: ../../examples/providers/callable_kwargs.py .. literalinclude:: ../../examples/providers/callable_kwargs.py
:language: python :language: python
:linenos:
.. _callable_providers_delegation: .. _callable_providers_delegation:

View File

@ -9,7 +9,6 @@ Configuration providers
:language: python :language: python
:emphasize-lines: 4,9-10 :emphasize-lines: 4,9-10
:lines: 4-14 :lines: 4-14
:linenos:
It implements "use first, define later" principle. It implements "use first, define later" principle.
@ -23,13 +22,11 @@ Loading from ``ini`` file
:language: python :language: python
:lines: 3-5,6- :lines: 3-5,6-
:emphasize-lines: 6 :emphasize-lines: 6
:linenos:
where ``examples/providers/configuration/config.ini`` is: where ``examples/providers/configuration/config.ini`` is:
.. literalinclude:: ../../examples/providers/configuration/config.ini .. literalinclude:: ../../examples/providers/configuration/config.ini
:language: ini :language: ini
:linenos:
:py:meth:`Configuration.from_ini` supports environment variables interpolation. Use :py:meth:`Configuration.from_ini` supports environment variables interpolation. Use
``${ENV_NAME}`` format in the configuration file to substitute value of environment ``${ENV_NAME}`` format in the configuration file to substitute value of environment
@ -45,13 +42,11 @@ Loading from ``yaml`` file
:language: python :language: python
:lines: 3-5,6- :lines: 3-5,6-
:emphasize-lines: 6 :emphasize-lines: 6
:linenos:
where ``examples/providers/configuration/config.yml`` is: where ``examples/providers/configuration/config.yml`` is:
.. literalinclude:: ../../examples/providers/configuration/config.yml .. literalinclude:: ../../examples/providers/configuration/config.yml
:language: ini :language: ini
:linenos:
:py:meth:`Configuration.from_yaml` supports environment variables interpolation. Use :py:meth:`Configuration.from_yaml` supports environment variables interpolation. Use
``${ENV_NAME}`` format in the configuration file to substitute value of environment ``${ENV_NAME}`` format in the configuration file to substitute value of environment
@ -73,7 +68,6 @@ Loading from ``dict``
:language: python :language: python
:lines: 3-5,6- :lines: 3-5,6-
:emphasize-lines: 6-13 :emphasize-lines: 6-13
:linenos:
Loading from environment variable Loading from environment variable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -85,7 +79,6 @@ Loading from environment variable
:language: python :language: python
:lines: 5-7,13-21 :lines: 5-7,13-21
:emphasize-lines: 6-8 :emphasize-lines: 6-8
:linenos:
Loading from multiple sources Loading from multiple sources
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -97,12 +90,10 @@ configuration is merged recursively over existing configuration.
:language: python :language: python
:lines: 3-5,6-14 :lines: 3-5,6-14
:emphasize-lines: 6-7 :emphasize-lines: 6-7
:linenos:
where ``examples/providers/configuration/config.local.yml`` is: where ``examples/providers/configuration/config.local.yml`` is:
.. literalinclude:: ../../examples/providers/configuration/config.local.yml .. literalinclude:: ../../examples/providers/configuration/config.local.yml
:language: ini :language: ini
:linenos:
.. disqus:: .. disqus::

View File

@ -18,7 +18,6 @@ coroutine:
.. literalinclude:: ../../examples/providers/coroutine_async_await.py .. literalinclude:: ../../examples/providers/coroutine_async_await.py
:language: python :language: python
:linenos:
Coroutine providers and injections Coroutine providers and injections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -30,7 +30,6 @@ Example:
.. literalinclude:: ../../examples/providers/custom_factory.py .. literalinclude:: ../../examples/providers/custom_factory.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -39,6 +39,5 @@ Example:
.. literalinclude:: ../../examples/providers/dependency.py .. literalinclude:: ../../examples/providers/dependency.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -14,7 +14,6 @@ Nothing could be better than brief example:
.. literalinclude:: ../../examples/providers/factory.py .. literalinclude:: ../../examples/providers/factory.py
:language: python :language: python
:linenos:
Factory providers and __init__ injections Factory providers and __init__ injections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -48,7 +47,6 @@ injectable values are also provided by another factories:
.. literalinclude:: ../../examples/providers/factory_init_injections.py .. literalinclude:: ../../examples/providers/factory_init_injections.py
:language: python :language: python
:linenos:
.. _factory_providers_delegation: .. _factory_providers_delegation:
@ -92,7 +90,6 @@ Example:
.. literalinclude:: ../../examples/providers/factory_delegation.py .. literalinclude:: ../../examples/providers/factory_delegation.py
:language: python :language: python
:linenos:
.. _factory_providers_specialization: .. _factory_providers_specialization:
@ -107,7 +104,6 @@ provided type:
.. literalinclude:: ../../examples/providers/factory_provided_type.py .. literalinclude:: ../../examples/providers/factory_provided_type.py
:language: python :language: python
:linenos:
.. _abstract_factory_providers: .. _abstract_factory_providers:
@ -142,13 +138,11 @@ Listing of ``cache.py``:
.. literalinclude:: ../../examples/providers/abstract_factory/cache.py .. literalinclude:: ../../examples/providers/abstract_factory/cache.py
:language: python :language: python
:linenos:
Listing of ``example.py``: Listing of ``example.py``:
.. literalinclude:: ../../examples/providers/abstract_factory/example.py .. literalinclude:: ../../examples/providers/abstract_factory/example.py
:language: python :language: python
:linenos:
Factory aggregate providers Factory aggregate providers
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -167,7 +161,6 @@ Next prototype might be the best demonstration of
.. literalinclude:: ../../examples/providers/factory_aggregate/prototype.py .. literalinclude:: ../../examples/providers/factory_aggregate/prototype.py
:language: python :language: python
:linenos:
Example below shows one of the :py:class:`FactoryAggregate` use cases, when Example below shows one of the :py:class:`FactoryAggregate` use cases, when
concrete implementation (game) must be selected based on dynamic input (CLI). concrete implementation (game) must be selected based on dynamic input (CLI).
@ -176,12 +169,10 @@ Listing of ``games.py``:
.. literalinclude:: ../../examples/providers/factory_aggregate/games.py .. literalinclude:: ../../examples/providers/factory_aggregate/games.py
:language: python :language: python
:linenos:
Listing of ``example.py``: Listing of ``example.py``:
.. literalinclude:: ../../examples/providers/factory_aggregate/example.py .. literalinclude:: ../../examples/providers/factory_aggregate/example.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -9,7 +9,6 @@ List providers
:language: python :language: python
:emphasize-lines: 6-9 :emphasize-lines: 6-9
:lines: 6-8, 23-29 :lines: 6-8, 23-29
:linenos:
:py:class:`List` provider is needed for injecting a list of dependencies. It handles :py:class:`List` provider is needed for injecting a list of dependencies. It handles
positional argument injections the same way as :py:class:`Factory` provider: positional argument injections the same way as :py:class:`Factory` provider:
@ -27,7 +26,6 @@ Full example:
:language: python :language: python
:emphasize-lines: 23-26 :emphasize-lines: 23-26
:lines: 3- :lines: 3-
:linenos:
.. note:: .. note::

View File

@ -9,7 +9,6 @@ Example:
.. literalinclude:: ../../examples/providers/object.py .. literalinclude:: ../../examples/providers/object.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -33,7 +33,6 @@ Example:
.. literalinclude:: ../../examples/providers/overriding_simple.py .. literalinclude:: ../../examples/providers/overriding_simple.py
:language: python :language: python
:linenos:
Example: Example:
@ -43,7 +42,6 @@ Example:
.. literalinclude:: ../../examples/providers/overriding_users_model.py .. literalinclude:: ../../examples/providers/overriding_users_model.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -9,7 +9,6 @@ Selector providers
:language: python :language: python
:emphasize-lines: 6-10 :emphasize-lines: 6-10
:lines: 3-5,14-20 :lines: 3-5,14-20
:linenos:
:py:class:`Selector` provider has a callable called ``selector`` and a dictionary of providers. :py:class:`Selector` provider has a callable called ``selector`` and a dictionary of providers.
@ -26,6 +25,5 @@ Full example:
:language: python :language: python
:emphasize-lines: 14-18 :emphasize-lines: 14-18
:lines: 3- :lines: 3-
:linenos:
.. disqus:: .. disqus::

View File

@ -14,7 +14,6 @@ Example:
.. literalinclude:: ../../examples/providers/singleton.py .. literalinclude:: ../../examples/providers/singleton.py
:language: python :language: python
:linenos:
Singleton providers resetting Singleton providers resetting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -28,7 +27,6 @@ Example:
.. literalinclude:: ../../examples/providers/singleton_resetting.py .. literalinclude:: ../../examples/providers/singleton_resetting.py
:language: python :language: python
:linenos:
Singleton providers and injections Singleton providers and injections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -108,7 +106,6 @@ Example:
.. literalinclude:: ../../examples/providers/singleton_thread_locals.py .. literalinclude:: ../../examples/providers/singleton_thread_locals.py
:language: python :language: python
:linenos:
.. disqus:: .. disqus::

View File

@ -0,0 +1,4 @@
Aiohttp tutorial
================
Coming soon...

View File

@ -0,0 +1,4 @@
Asyncio tutorial
================
Coming soon...

4
docs/tutorials/flask.rst Normal file
View File

@ -0,0 +1,4 @@
Flask tutorial
==============
Coming soon...

12
docs/tutorials/index.rst Normal file
View File

@ -0,0 +1,12 @@
Tutorials
=========
This section contains tutorials that show how to apply dependency injection for popular Python
frameworks.
.. toctree::
:maxdepth: 2
flask
aiohttp
asyncio

View File

@ -2,16 +2,16 @@
class Service: class Service:
"""Some "Service".""" """The Service."""
class Client: class Client:
"""Some "Client" that uses "Service".""" """The Client that uses the Service."""
def __init__(self): def __init__(self):
"""Initialize instance.""" """Initialize the Client."""
self.service = Service() # Service instance is created inside Client self.service = Service() # The Service is created by the Client
if __name__ == '__main__': if __name__ == '__main__':
client = Client() # Application creates Client's instance client = Client() # Application creates the Client

View File

@ -1,18 +1,18 @@
"""The Code, that demonstrates dependency injection pattern.""" """The Code that demonstrates dependency injection pattern."""
class Service: class Service:
"""Some "Service".""" """The Service."""
class Client: class Client:
"""Some "Client" that uses "Service".""" """The Client that uses the Service."""
def __init__(self, service): # Service instance is injected into Client def __init__(self, service): # The Service is injected into the Client
"""Initialize instance.""" """Initialize the Client."""
self.service = service self.service = service
if __name__ == '__main__': if __name__ == '__main__':
service = Service() # Application creates Service instance service = Service() # Application creates the Service
client = Client(service) # and inject Service instance into the Client client = Client(service) # and inject the Service into the Client

View File

@ -4,8 +4,8 @@
class Engine: class Engine:
"""Example engine base class. """Example engine base class.
Engine is a heart of every car. Engine is a very common term and could be Engine is a heart of every car. Engine is a very common term and
implemented in very different ways. could be implemented in very different ways.
""" """

View File

@ -12,6 +12,9 @@ def create_app():
app = container.app() app = container.app()
app.container = container app.container = container
bootstrap = container.bootstrap()
bootstrap.init_app(app)
app.add_url_rule('/', view_func=container.index_view.as_view()) app.add_url_rule('/', view_func=container.index_view.as_view())
return app return app

View File

@ -3,6 +3,7 @@
from dependency_injector import containers, providers from dependency_injector import containers, providers
from dependency_injector.ext import flask from dependency_injector.ext import flask
from flask import Flask from flask import Flask
from flask_bootstrap import Bootstrap
from github import Github from github import Github
from . import views, services from . import views, services
@ -13,6 +14,8 @@ class ApplicationContainer(containers.DeclarativeContainer):
app = flask.Application(Flask, __name__) app = flask.Application(Flask, __name__)
bootstrap = flask.Extension(Bootstrap)
config = providers.Configuration() config = providers.Configuration()
github_client = providers.Factory( github_client = providers.Factory(

View File

@ -29,7 +29,6 @@ class SearchService:
'url': repository.owner.html_url, 'url': repository.owner.html_url,
'avatar_url': repository.owner.avatar_url, 'avatar_url': repository.owner.avatar_url,
}, },
'created_at': repository.created_at,
'latest_commit': self._format_commit(commits[0]) if commits else {}, 'latest_commit': self._format_commit(commits[0]) if commits else {},
} }

View File

@ -0,0 +1,26 @@
<!doctype html>
<html lang="en">
<head>
{% block head %}
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{% block styles %}
<!-- Bootstrap CSS -->
{{ bootstrap.load_css() }}
{% endblock %}
<title>{% block title %}{% endblock %}</title>
{% endblock %}
</head>
<body>
<!-- Your page content -->
{% block content %}{% endblock %}
{% block scripts %}
<!-- Optional JavaScript -->
{{ bootstrap.load_js() }}
{% endblock %}
</body>
</html>

View File

@ -1,40 +1,55 @@
<!DOCTYPE html> {% extends "base.html" %}
<html>
<head> {% block title %}Github Navigator{% endblock %}
<title>Github Navigator</title>
</head> {% block content %}
<body> <div class="container">
<h1>Github Navigator</h1> <h1 class="mb-4">Github Navigator</h1>
<form method="get">
<form>
<div class="form-group form-row">
<label for="mySearch" class="col-form-label">Search for:</label>
<div class="col-10">
<input class="form-control" type="text" id="mySearch"
placeholder="Type something to search on GitHub"
name="search_term"
value="{{ search_term if search_term }}">
</div>
</div>
</form>
{% if repositories|length == 0 %}
<small>No search results</small>
{% endif %}
<p> <p>
Search term: <input type="text" name="search_term" value="{{ search_term if search_term }}"> <small>Results found: {{ repositories|length }}</small>
Limit: <input type="text" name="limit" value="{{ limit }}">
<input type="submit">
</p> </p>
</form>
<h2>Search results</h2> <table class="table table-striped">
{% if repositories|length == 0 %} <thead>
<small>No search results</small> <tr>
{% endif %} <th>#</th>
{% for repository in repositories %} {{n}} <th>Repository</th>
<p> <th class="text-nowrap">Repository owner</th>
<small>Search result # {{ loop.index }} from {{ repositories|length }}</small> <!-- <th class="text-nowrap">Created at</th>-->
</p> <th class="text-nowrap">Last commit</th>
<p> </tr>
Repository: <a href="{{ repository.url }}">{{ repository.name }}</a> </thead>
</p> <tbody>
<p> {% for repository in repositories %} {{n}}
Repository owner: <tr>
<a href="{{ repository.owner.url }}"><img src="{{ repository.owner.avatar_url }}" alt="avatar" height="24" width="24"/></a> <th>{{ loop.index }}</th>
<td><a href="{{ repository.url }}">{{ repository.name }}</a></td>
<td><a href="{{ repository.owner.url }}"><img src="{{ repository.owner.avatar_url }}" alt="avatar" height="24" width="24"/></a>
<a href="{{ repository.owner.url }}">{{ repository.owner.login }}</a> <a href="{{ repository.owner.url }}">{{ repository.owner.login }}</a>
</p> </td>
<p> <td><a href="{{ repository.latest_commit.url }}">{{ repository.latest_commit.sha }}</a> {{ repository.latest_commit['message'] }} {{ repository.latest_commit.author_name }}</td>
Created at: {{ repository.created_at }} </tr>
</p> {% endfor %}
<p>
LastCommit: <a href="{{ repository.latest_commit.url }}">{{ repository.latest_commit.sha }}</a> {{ repository.latest_commit['message'] }} {{ repository.latest_commit.author_name }} </tbody>
</p> </table>
<hr/> </div>
{% endfor %}
</body> {% endblock %}
</html>

View File

@ -25,7 +25,6 @@ def test_index(client, app):
html_url='owner1-url', html_url='owner1-url',
avatar_url='owner1-avatar-url', avatar_url='owner1-avatar-url',
), ),
created_at='repo1-created-at',
get_commits=mock.Mock(return_value=[mock.Mock()]), get_commits=mock.Mock(return_value=[mock.Mock()]),
), ),
mock.Mock( mock.Mock(
@ -36,7 +35,6 @@ def test_index(client, app):
html_url='owner2-url', html_url='owner2-url',
avatar_url='owner2-avatar-url', avatar_url='owner2-avatar-url',
), ),
created_at='repo2-created-at',
get_commits=mock.Mock(return_value=[mock.Mock()]), get_commits=mock.Mock(return_value=[mock.Mock()]),
), ),
] ]
@ -51,14 +49,12 @@ def test_index(client, app):
assert b'owner1-login' in response.data assert b'owner1-login' in response.data
assert b'owner1-url' in response.data assert b'owner1-url' in response.data
assert b'owner1-avatar-url' in response.data assert b'owner1-avatar-url' in response.data
assert b'repo1-created-at' in response.data
assert b'repo2-url' in response.data assert b'repo2-url' in response.data
assert b'repo2-name' in response.data assert b'repo2-name' in response.data
assert b'owner2-login' in response.data assert b'owner2-login' in response.data
assert b'owner2-url' in response.data assert b'owner2-url' in response.data
assert b'owner2-avatar-url' in response.data assert b'owner2-avatar-url' in response.data
assert b'repo2-created-at' in response.data
def test_index_no_results(client, app): def test_index_no_results(client, app):

View File

@ -10,19 +10,27 @@ cache_client_factory = providers.AbstractFactory(cache.AbstractCacheClient)
if __name__ == '__main__': if __name__ == '__main__':
# Override abstract factory with redis client factory: # Override abstract factory with redis client factory:
cache_client_factory.override(providers.Factory(cache.RedisCacheClient, cache_client_factory.override(
providers.Factory(
cache.RedisCacheClient,
host='localhost', host='localhost',
port=6379, port=6379,
db=0)) db=0,
),
)
redis_cache = cache_client_factory() redis_cache = cache_client_factory()
print(redis_cache) # <cache.RedisCacheClient object at 0x10975bc50> print(redis_cache)
# <cache.RedisCacheClient object at 0x10975bc50>
# Override abstract factory with memcache client factory: # Override abstract factory with memcache client factory:
cache_client_factory.override(providers.Factory(cache.MemcacheCacheClient, cache_client_factory.override(
hosts=['10.0.1.1', providers.Factory(
'10.0.1.2', cache.MemcacheCacheClient,
'10.0.1.3'], hosts=['10.0.1.1', '10.0.1.2', '10.0.1.3'],
port=11211, port=11211,
prefix='my_app')) prefix='my_app',
),
)
memcache_cache = cache_client_factory() memcache_cache = cache_client_factory()
print(memcache_cache) # <cache.MemcacheCacheClient object at 0x10975bc90> print(memcache_cache)
# <cache.MemcacheCacheClient object at 0x10975bc90>

View File

@ -7,9 +7,11 @@ import dependency_injector.providers as providers
from games import Chess, Checkers, Ludo from games import Chess, Checkers, Ludo
game_factory = providers.FactoryAggregate(chess=providers.Factory(Chess), game_factory = providers.FactoryAggregate(
chess=providers.Factory(Chess),
checkers=providers.Factory(Checkers), checkers=providers.Factory(Checkers),
ludo=providers.Factory(Ludo)) ludo=providers.Factory(Ludo),
)
if __name__ == '__main__': if __name__ == '__main__':
game_type = sys.argv[1].lower() game_type = sys.argv[1].lower()

View File

@ -26,27 +26,36 @@ class User:
# Defining User and Photo factories using DelegatedFactory provider: # Defining User and Photo factories using DelegatedFactory provider:
photos_factory = providers.DelegatedFactory(Photo) photos_factory = providers.DelegatedFactory(Photo)
users_factory = providers.DelegatedFactory(User, users_factory = providers.DelegatedFactory(
photos_factory=photos_factory) User,
photos_factory=photos_factory,
)
# or using Delegate(Factory(...)) # or using Delegate(Factory(...))
photos_factory = providers.Factory(Photo) photos_factory = providers.Factory(Photo)
users_factory = providers.Factory(User, users_factory = providers.Factory(
photos_factory=providers.Delegate( User,
photos_factory)) photos_factory=providers.Delegate(photos_factory),
)
# or using Factory(...).delegate() # or using Factory(...).delegate()
photos_factory = providers.Factory(Photo) photos_factory = providers.Factory(Photo)
users_factory = providers.Factory(User, users_factory = providers.Factory(
photos_factory=photos_factory.delegate()) User,
photos_factory=photos_factory.delegate(),
)
# Creating several User objects: # Creating several User objects:
user1 = users_factory() # Same as: user1 = User(photos_factory=photos_factory) user1 = users_factory()
user2 = users_factory() # Same as: user2 = User(photos_factory=photos_factory) user2 = users_factory()
# Same as:
# user1 = User(photos_factory=photos_factory)
# user2 = User(photos_factory=photos_factory)
# Making some asserts: # Making some asserts:
assert isinstance(user1.main_photo, Photo) assert isinstance(user1.main_photo, Photo)
@ -55,13 +64,18 @@ assert isinstance(user2.main_photo, Photo)
# or using Factory(...).provider # or using Factory(...).provider
photos_factory = providers.Factory(Photo) photos_factory = providers.Factory(Photo)
users_factory = providers.Factory(User, users_factory = providers.Factory(
photos_factory=photos_factory.provider) User,
photos_factory=photos_factory.provider,
)
# Creating several User objects: # Creating several User objects:
user1 = users_factory() # Same as: user1 = User(photos_factory=photos_factory) user1 = users_factory()
user2 = users_factory() # Same as: user2 = User(photos_factory=photos_factory) user2 = users_factory()
# Same as:
# user1 = User(photos_factory=photos_factory)
# user2 = User(photos_factory=photos_factory)
# Making some asserts: # Making some asserts:
assert isinstance(user1.main_photo, Photo) assert isinstance(user1.main_photo, Photo)

View File

@ -7,8 +7,8 @@ import dependency_injector.providers as providers
UsersService = collections.namedtuple('UsersService', []) UsersService = collections.namedtuple('UsersService', [])
# Singleton provider creates new instance of specified class on first call and # Singleton provider creates new instance of specified class on first call
# returns same instance on every next call. # and returns same instance on every next call.
users_service_provider = providers.Singleton(UsersService) users_service_provider = providers.Singleton(UsersService)
# Retrieving several UserService objects: # Retrieving several UserService objects:

View File

@ -18,19 +18,22 @@ thread_local_object = providers.ThreadLocalSingleton(object)
queue_factory = providers.ThreadSafeSingleton(queue.Queue) queue_factory = providers.ThreadSafeSingleton(queue.Queue)
# Create callable provider for example(), inject dependencies: # Create callable provider for example(), inject dependencies:
example = providers.DelegatedCallable(example, example = providers.DelegatedCallable(
example,
example_object=thread_local_object, example_object=thread_local_object,
queue_object=queue_factory) queue_object=queue_factory,
)
# Create factory provider for threads that are targeted to execute example(): # Create factory for threads that are targeted to execute example():
thread_factory = providers.Factory(threading.Thread, thread_factory = providers.Factory(threading.Thread, target=example)
target=example)
if __name__ == '__main__': if __name__ == '__main__':
# Create 10 threads for concurrent execution of example(): # Create 10 threads for concurrent execution of example():
threads = [] threads = []
for thread_number in range(10): for thread_number in range(10):
threads.append(thread_factory(name='Thread{0}'.format(thread_number))) threads.append(
thread_factory(name='Thread{0}'.format(thread_number)),
)
# Start execution of all created threads: # Start execution of all created threads:
for thread in threads: for thread in threads:

View File

@ -1,5 +1,5 @@
sphinx sphinx
sphinx_rtd_theme>=0.2.5b2 alabaster>=0.7.12
-e git://github.com/rmk135/sphinxcontrib-disqus.git#egg=sphinxcontrib-disqus -e git://github.com/rmk135/sphinxcontrib-disqus.git#egg=sphinxcontrib-disqus
-r requirements-ext.txt -r requirements-ext.txt

View File

@ -1,6 +1,6 @@
"""Dependency injector top-level package.""" """Dependency injector top-level package."""
__version__ = '3.21.2' __version__ = '3.22.0'
"""Version number that follows semantic versioning. """Version number that follows semantic versioning.
:type: str :type: str