From 56740fbc591edec7fe3028982e9d85b66e3f82ad Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Fri, 23 Oct 2020 13:48:31 -0400 Subject: [PATCH] Draft resources docs --- README.rst | 9 +- docs/index.rst | 8 +- docs/introduction/key_features.rst | 8 +- docs/providers/index.rst | 1 + docs/providers/resource.rst | 206 +++++++++++++++++++++++++++++ 5 files changed, 223 insertions(+), 9 deletions(-) create mode 100644 docs/providers/resource.rst diff --git a/README.rst b/README.rst index 2ca89d7b..cd22aac0 100644 --- a/README.rst +++ b/README.rst @@ -57,17 +57,20 @@ It helps implementing the dependency injection principle. Key features of the ``Dependency Injector``: - **Providers**. Provides ``Factory``, ``Singleton``, ``Callable``, ``Coroutine``, ``Object``, - ``List``, ``Dict``, ``Configuration``, ``Dependency`` and ``Selector`` providers that help - assembling your objects. + ``List``, ``Dict``, ``Configuration``, ``Resource``, ``Dependency`` and ``Selector`` providers + that help assembling your objects. See `Providers `_. - **Overriding**. Can override any provider by another provider on the fly. This helps in testing and configuring dev / stage environment to replace API clients with stubs etc. See `Provider overriding `_. -- **Configuration**. Read configuration from ``yaml`` & ``ini`` files, environment variables +- **Configuration**. Reads configuration from ``yaml`` & ``ini`` files, environment variables and dictionaries. See `Configuration provider `_. - **Containers**. Provides declarative and dynamic containers. See `Containers `_. +- **Resources**. Helps with initialization and configuring of logging, event loop, thread + or process pool, etc. + See `Resource provider `_. - **Wiring**. Injects dependencies into functions and methods. Helps integrating with other frameworks: Django, Flask, Aiohttp, etc. See `Wiring `_. diff --git a/docs/index.rst b/docs/index.rst index 6a86da16..aeb81224 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -69,13 +69,15 @@ It helps implementing the dependency injection principle. Key features of the ``Dependency Injector``: - **Providers**. Provides ``Factory``, ``Singleton``, ``Callable``, ``Coroutine``, ``Object``, - ``List``, ``Dict``, ``Configuration``, ``Dependency`` and ``Selector`` providers that help - assembling your objects. See :ref:`providers`. + ``List``, ``Dict``, ``Configuration``, ``Resource``, ``Dependency`` and ``Selector`` providers + that help assembling your objects. See :ref:`providers`. - **Overriding**. Can override any provider by another provider on the fly. This helps in testing and configuring dev / stage environment to replace API clients with stubs etc. See :ref:`provider-overriding`. -- **Configuration**. Read configuration from ``yaml`` & ``ini`` files, environment variables +- **Configuration**. Reads configuration from ``yaml`` & ``ini`` files, environment variables and dictionaries. See :ref:`configuration-provider`. +- **Resources**. Helps with initialization and configuring of logging, event loop, thread + or process pool, etc. See :ref:`resource-provider`. - **Containers**. Provides declarative and dynamic containers. See :ref:`containers`. - **Wiring**. Injects dependencies into functions and methods. Helps integrating with other frameworks: Django, Flask, Aiohttp, etc. See :ref:`wiring`. diff --git a/docs/introduction/key_features.rst b/docs/introduction/key_features.rst index 63d2c24b..26dfa6b9 100644 --- a/docs/introduction/key_features.rst +++ b/docs/introduction/key_features.rst @@ -11,13 +11,15 @@ Key features Key features of the ``Dependency Injector``: - **Providers**. Provides ``Factory``, ``Singleton``, ``Callable``, ``Coroutine``, ``Object``, - ``List``, ``Dict``, ``Configuration``, ``Dependency`` and ``Selector`` providers that help - assembling your objects. See :ref:`providers`. + ``List``, ``Dict``, ``Configuration``, ``Resource``, ``Dependency`` and ``Selector`` providers + that help assembling your objects. See :ref:`providers`. - **Overriding**. Can override any provider by another provider on the fly. This helps in testing and configuring dev / stage environment to replace API clients with stubs etc. See :ref:`provider-overriding`. -- **Configuration**. Read configuration from ``yaml`` & ``ini`` files, environment variables +- **Configuration**. Reads configuration from ``yaml`` & ``ini`` files, environment variables and dictionaries. See :ref:`configuration-provider`. +- **Resources**. Helps with initialization and configuring of logging, event loop, thread + or process pool, etc. See :ref:`resource-provider`. - **Containers**. Provides declarative and dynamic containers. See :ref:`containers`. - **Wiring**. Injects dependencies into functions and methods. Helps integrating with other frameworks: Django, Flask, Aiohttp, etc. See :ref:`wiring`. diff --git a/docs/providers/index.rst b/docs/providers/index.rst index ca36a11e..0e328048 100644 --- a/docs/providers/index.rst +++ b/docs/providers/index.rst @@ -45,6 +45,7 @@ Providers module API docs - :py:mod:`dependency_injector.providers` list dict configuration + resource selector dependency overriding diff --git a/docs/providers/resource.rst b/docs/providers/resource.rst new file mode 100644 index 00000000..616730a9 --- /dev/null +++ b/docs/providers/resource.rst @@ -0,0 +1,206 @@ +.. _resource-provider: + +Resource provider +================= + +.. meta:: + :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Resource,Injection, + Logging,Event Loop,Thread Pool + :description: Resource provider provides a component with initialization and shutdown. It works + well for configuring logging, event loop, thread or process pool, etc. + This page demonstrates how to use resource provider. + +.. currentmodule:: dependency_injector.providers + +:py:class:`Resource` provider provides a component with initialization and shutdown. + +.. literalinclude:: ../../examples/providers/resource.py + :language: python + :lines: 3- + +Resource providers help to initialize and configure logging, event loop, thread or process pool, etc. + +Resource provider is similar to ``Singleton``. Resource initialization happens only once. +You can do injections and use provided instance the same way like you do with any other provider. + +.. code-block:: python + :emphasize-lines: 12 + + class Container(containers.DeclarativeContainer): + + config = providers.Configuration() + + thread_pool = providers.Resource( + init_threat_pool, + max_workers=config.max_workers, + ) + + dispatcher = providers.Factory( + TaskDispatcher, + executor=thread_pool, + ) + +Container has an interface to initialize and shutdown all resources: + +.. code-block:: python + + container = Container() + container.init_resources() + container.shutdown_resources() + +You also can initialize and shutdown resources using ``init()`` and ``shutdown()`` +methods of the provider: + +.. code-block:: python + + container = Container() + container.thread_pool.init() + container.thread_pool.shutdown() + +Resource provider supports 3 types of resource initializers: + +- Function +- Generator +- Subclass of ``resources.Resource`` + +Function initializer +-------------------- + +Function is the most common way to specify resource initialization: + +.. code-block:: python + + def init_resource(argument1=..., argument2=...): + return SomeResource() + + + class Container(containers.DeclarativeContainer): + + resource = providers.Resource( + init_resource, + argument1=..., + argument2=..., + ) + +Function initializer should not necessarily return a value. This often happens when +you configure global resource: + +.. code-block:: python + + import logging.config + + + class Container(containers.DeclarativeContainer): + + configure_logging = providers.Resource( + logging.config.fileConfig, + fname='logging.ini', + ) + +Function initializer does not support shutdown. + +Generator initializer +--------------------- + +Resource provider can use 2-step generators: + +- First step of generator is an initialization phase +- The second is step is a shutdown phase + +.. code-block:: python + + def init_resource(argument1=..., argument2=...): + resource = SomeResource() # initialization + + yield resource + + # shutdown + ... + + + class Container(containers.DeclarativeContainer): + + resource = providers.Resource( + init_resource, + argument1=..., + argument2=..., + ) + +Generator initialization phase ends on the first ``yield`` statement. You can return a +resource object using ``yield resource`` like in the example above. Returning of the +object is not mandatory. You can leave ``yield`` statement empty: + +.. code-block:: python + + def init_resource(argument1=..., argument2=...): + # initialization + ... + + yield + + # shutdown + ... + + + class Container(containers.DeclarativeContainer): + + resource = providers.Resource( + init_resource, + argument1=..., + argument2=..., + ) + +Subclass initializer +-------------------- + +You can provide resource initializer by implementing a subclass of ``resources.Resource``: + +.. code-block:: python + + from dependency_injector import resources + + + class MyResource(resources.Resource): + + def init(self, argument1=..., argument2=...) -> SomeResource: + return SomeResource() + + def shutdown(self, resource: SomeResource) -> None: + # shutdown + ... + + + class Container(containers.DeclarativeContainer): + + resource = providers.Resource( + MyResource, + argument1=..., + argument2=..., + ) + +Subclass must implement two methods: ``.init()`` and ``.shutdown()``. + +Method ``.init()`` receives arguments specified in resource provider. +It performs initialization and returns resource object. Returning of the object +is not mandatory. + +Method ``.shutdown()`` receives resource object returned from ``.init()``. If ``.init()`` +didn't return an object ``.shutdown()`` method will be called anyway with ``None`` as a +first argument. + +.. code-block:: python + + from dependency_injector import resources + + + class MyResource(resources.Resource): + + def init(self, argument1=..., argument2=...) -> None: + # initialization + ... + + def shutdown(self, _: None) -> None: + # shutdown + ... + +.. disqus::