mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-22 09:36:48 +03:00
Merge branch 'release/3.44.0' into master
This commit is contained in:
commit
53b7ad0275
149
README.rst
149
README.rst
|
@ -54,103 +54,23 @@ What is ``Dependency Injector``?
|
||||||
|
|
||||||
It helps implementing the dependency injection principle.
|
It helps implementing the dependency injection principle.
|
||||||
|
|
||||||
What is dependency injection?
|
Key features of the ``Dependency Injector``:
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
Dependency injection is a principle that helps to decrease coupling and increase cohesion.
|
- **Providers**. Provides ``Factory``, ``Singleton``, ``Callable``, ``Coroutine``, ``Object``,
|
||||||
|
``List``, ``Configuration``, ``Dependency`` and ``Selector`` providers that help assembling your
|
||||||
What is coupling and cohesion?
|
objects. See `Providers <http://python-dependency-injector.ets-labs.org/providers/index.html>`_.
|
||||||
|
- **Overriding**. Can override any provider by another provider on the fly. This helps in testing
|
||||||
Coupling and cohesion are about how tough the components are tied.
|
and configuring dev / stage environment to replace API clients with stubs etc. See
|
||||||
|
`Provider overriding <http://python-dependency-injector.ets-labs.org/providers/overriding.html>`_.
|
||||||
- **High coupling**. If the coupling is high it's like using a superglue or welding. No easy way
|
- **Configuration**. Read configuration from ``yaml`` & ``ini`` files, environment variables
|
||||||
to disassemble.
|
and dictionaries.
|
||||||
- **High cohesion**. High cohesion is like using the screws. Very easy to disassemble and
|
See `Configuration provider <http://python-dependency-injector.ets-labs.org/providers/configuration.html>`_.
|
||||||
assemble back or assemble a different way. It is an opposite to high coupling.
|
- **Containers**. Provides declarative and dynamic containers.
|
||||||
|
See `Containers <http://python-dependency-injector.ets-labs.org/containers/index.html>`_.
|
||||||
When the cohesion is high the coupling is low.
|
- **Performance**. Fast. Written in ``Cython``.
|
||||||
|
- **Typing**. Provides typing stubs, ``mypy``-friendly.
|
||||||
Low coupling brings a flexibility. Your code becomes easier to change and test.
|
See `Typing and mypy <http://python-dependency-injector.ets-labs.org/providers/typing_mypy.html>`_.
|
||||||
|
- **Maturity**. Mature and production-ready. Well-tested, documented and supported.
|
||||||
How to implement dependency injection?
|
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
Objects do not create each other anymore. They provide a way to inject the dependencies instead.
|
|
||||||
|
|
||||||
Before:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
class ApiClient:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.api_key = os.getenv('API_KEY') # <-- the dependency
|
|
||||||
self.timeout = os.getenv('TIMEOUT') # <-- the dependency
|
|
||||||
|
|
||||||
|
|
||||||
class Service:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.api_client = ApiClient() # <-- the dependency
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
service = Service()
|
|
||||||
|
|
||||||
|
|
||||||
After:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
class ApiClient:
|
|
||||||
|
|
||||||
def __init__(self, api_key: str, timeout: int):
|
|
||||||
self.api_key = api_key # <-- the dependency is injected
|
|
||||||
self.timeout = timeout # <-- the dependency is injected
|
|
||||||
|
|
||||||
|
|
||||||
class Service:
|
|
||||||
|
|
||||||
def __init__(self, api_client: ApiClient):
|
|
||||||
self.api_client = api_client # <-- the dependency is injected
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
service = Service(ApiClient(os.getenv('API_KEY'), os.getenv('TIMEOUT')))
|
|
||||||
|
|
||||||
``ApiClient`` is decoupled from knowing where the options come from. You can read a key and a
|
|
||||||
timeout from a configuration file or even get them from a database.
|
|
||||||
|
|
||||||
``Service`` is decoupled from the ``ApiClient``. It does not create it anymore. You can provide a
|
|
||||||
stub or other compatible object.
|
|
||||||
|
|
||||||
Flexibility comes with a price.
|
|
||||||
|
|
||||||
Now you need to assemble the objects like this::
|
|
||||||
|
|
||||||
service = Service(ApiClient(os.getenv('API_KEY'), os.getenv('TIMEOUT')))
|
|
||||||
|
|
||||||
The assembly code might get duplicated and it'll become harder to change the application structure.
|
|
||||||
|
|
||||||
Here comes the ``Dependency Injector``.
|
|
||||||
|
|
||||||
What does the Dependency Injector do?
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
With the dependency injection pattern objects loose the responsibility of assembling the
|
|
||||||
dependencies. The ``Dependency Injector`` absorbs that responsibility.
|
|
||||||
|
|
||||||
``Dependency Injector`` helps to assemble the objects.
|
|
||||||
|
|
||||||
It provides a container and providers that help you with the objects assembly. When you
|
|
||||||
need an object you get it from the container. The rest of the assembly work is done by the
|
|
||||||
framework:
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -180,28 +100,18 @@ framework:
|
||||||
|
|
||||||
service = container.service()
|
service = container.service()
|
||||||
|
|
||||||
Retrieving of the ``Service`` instance now is done like this::
|
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.
|
||||||
|
|
||||||
service = container.service()
|
.. figure:: https://raw.githubusercontent.com/wiki/ets-labs/python-dependency-injector/img/di-map.svg
|
||||||
|
:target: https://github.com/ets-labs/python-dependency-injector
|
||||||
|
|
||||||
Objects assembling is consolidated in the container. When you need to make a change you do it in
|
*The container is like a map of your application. You always know what depends on what.*
|
||||||
one place.
|
|
||||||
|
|
||||||
When doing a testing you call the ``container.api_client.override()`` to replace the real API
|
Visit the docs to know more about the
|
||||||
client with a mock:
|
`Dependency injection and inversion of control in Python <http://python-dependency-injector.ets-labs.org/introduction/di_in_python.html>`_.
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
|
|
||||||
with container.api_client.override(mock.Mock()):
|
|
||||||
service = container.service()
|
|
||||||
|
|
||||||
You can override any provider with another provider.
|
|
||||||
|
|
||||||
It also helps you in configuring project for the different environments: replace an API client
|
|
||||||
with a stub on the dev or stage.
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
@ -215,6 +125,15 @@ Documentation
|
||||||
|
|
||||||
The documentation is available on the `Read The Docs <http://python-dependency-injector.ets-labs.org/>`_
|
The documentation is available on the `Read The Docs <http://python-dependency-injector.ets-labs.org/>`_
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
Choose one of the following:
|
||||||
|
|
||||||
|
- `Application example (single container) <http://python-dependency-injector.ets-labs.org/examples/application-single-container.html>`_
|
||||||
|
- `Application example (multiple containers) <http://python-dependency-injector.ets-labs.org/examples/application-multiple-containers.html>`_
|
||||||
|
- `Decoupled packages example (multiple containers) <http://python-dependency-injector.ets-labs.org/examples/decoupled-packages.html>`_
|
||||||
|
|
||||||
Tutorials
|
Tutorials
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ Key features of the ``Dependency Injector``:
|
||||||
and dictionaries. See :ref:`configuration-provider`.
|
and dictionaries. See :ref:`configuration-provider`.
|
||||||
- **Containers**. Provides declarative and dynamic containers. See :ref:`containers`.
|
- **Containers**. Provides declarative and dynamic containers. See :ref:`containers`.
|
||||||
- **Performance**. Fast. Written in ``Cython``.
|
- **Performance**. Fast. Written in ``Cython``.
|
||||||
- **Typing**. Provides typing stubs, ``mypy``-friendly.
|
- **Typing**. Provides typing stubs, ``mypy``-friendly. See :ref:`provider-typing`.
|
||||||
- **Maturity**. Mature and production-ready. Well-tested, documented and supported.
|
- **Maturity**. Mature and production-ready. Well-tested, documented and supported.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
|
@ -20,7 +20,7 @@ Key features of the ``Dependency Injector``:
|
||||||
and dictionaries. See :ref:`configuration-provider`.
|
and dictionaries. See :ref:`configuration-provider`.
|
||||||
- **Containers**. Provides declarative and dynamic containers. See :ref:`containers`.
|
- **Containers**. Provides declarative and dynamic containers. See :ref:`containers`.
|
||||||
- **Performance**. Fast. Written in ``Cython``.
|
- **Performance**. Fast. Written in ``Cython``.
|
||||||
- **Typing**. Provides typing stubs, ``mypy``-friendly.
|
- **Typing**. Provides typing stubs, ``mypy``-friendly. See :ref:`provider-typing`.
|
||||||
- **Maturity**. Mature and production-ready. Well-tested, documented and supported.
|
- **Maturity**. Mature and production-ready. Well-tested, documented and supported.
|
||||||
|
|
||||||
The framework stands on two principles:
|
The framework stands on two principles:
|
||||||
|
|
|
@ -7,6 +7,13 @@ 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.44.0
|
||||||
|
------
|
||||||
|
- Add native support of the generics to the providers: ``some_provider = providers.Provider[SomeClass]``.
|
||||||
|
- Deprecate module ``types``.
|
||||||
|
- Add documentation page on providers typing and ``mypy`` support.
|
||||||
|
- Update README.
|
||||||
|
|
||||||
3.43.1
|
3.43.1
|
||||||
------
|
------
|
||||||
- Fix a typo in README.
|
- Fix a typo in README.
|
||||||
|
|
|
@ -49,3 +49,4 @@ Providers module API docs - :py:mod:`dependency_injector.providers`
|
||||||
overriding
|
overriding
|
||||||
provided_instance
|
provided_instance
|
||||||
custom
|
custom
|
||||||
|
typing_mypy
|
||||||
|
|
58
docs/providers/typing_mypy.rst
Normal file
58
docs/providers/typing_mypy.rst
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
.. _provider-typing:
|
||||||
|
|
||||||
|
Typing and mypy
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. meta::
|
||||||
|
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Providers,Typing,Mypy,
|
||||||
|
Pattern,Example
|
||||||
|
:description: Dependency Injector providers are mypy-friendly. Providers module goes with the
|
||||||
|
typing stubs to provide the typing information to ``mypy``, IDEs and editors.
|
||||||
|
|
||||||
|
Providers are ``mypy``-friendly.
|
||||||
|
|
||||||
|
Providers module goes with the typing stubs. It provides typing information to ``mypy`` and your
|
||||||
|
IDE.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from dependency_injector import providers
|
||||||
|
|
||||||
|
|
||||||
|
class Animal:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Cat(Animal)
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
provider = providers.Factory(Cat)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
animal = provider() # mypy knows that animal is of type "Cat"
|
||||||
|
|
||||||
|
|
||||||
|
You can use ``Provider`` as a generic type. This helps when a provider is an argument of a
|
||||||
|
function or method.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 12
|
||||||
|
|
||||||
|
from dependency_injector import providers
|
||||||
|
|
||||||
|
|
||||||
|
class Animal:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Cat(Animal)
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
provider: providers.Provider[Animal] = providers.Factory(Cat)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
animal = provider() # mypy knows that animal is of type "Animal"
|
|
@ -1,6 +1,6 @@
|
||||||
"""Top-level package."""
|
"""Top-level package."""
|
||||||
|
|
||||||
__version__ = '3.43.1'
|
__version__ = '3.44.0'
|
||||||
"""Version number.
|
"""Version number.
|
||||||
|
|
||||||
:type: str
|
:type: str
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Generated by Cython 0.29.20 */
|
/* Generated by Cython 0.29.21 */
|
||||||
|
|
||||||
#define PY_SSIZE_T_CLEAN
|
#define PY_SSIZE_T_CLEAN
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
@ -7,8 +7,8 @@
|
||||||
#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000)
|
#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000)
|
||||||
#error Cython requires Python 2.6+ or Python 3.3+.
|
#error Cython requires Python 2.6+ or Python 3.3+.
|
||||||
#else
|
#else
|
||||||
#define CYTHON_ABI "0_29_20"
|
#define CYTHON_ABI "0_29_21"
|
||||||
#define CYTHON_HEX_VERSION 0x001D14F0
|
#define CYTHON_HEX_VERSION 0x001D15F0
|
||||||
#define CYTHON_FUTURE_DIVISION 0
|
#define CYTHON_FUTURE_DIVISION 0
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#ifndef offsetof
|
#ifndef offsetof
|
||||||
|
@ -435,7 +435,11 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
|
||||||
#define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u)
|
#define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u)
|
||||||
#define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i)
|
#define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i)
|
||||||
#define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch)
|
#define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch)
|
||||||
|
#if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE)
|
||||||
#define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u)))
|
#define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u)))
|
||||||
|
#else
|
||||||
|
#define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u))
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define CYTHON_PEP393_ENABLED 0
|
#define CYTHON_PEP393_ENABLED 0
|
||||||
#define PyUnicode_1BYTE_KIND 1
|
#define PyUnicode_1BYTE_KIND 1
|
||||||
|
@ -544,7 +548,7 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
|
||||||
#define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t
|
#define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t
|
||||||
#endif
|
#endif
|
||||||
#if PY_MAJOR_VERSION >= 3
|
#if PY_MAJOR_VERSION >= 3
|
||||||
#define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : (Py_INCREF(func), func))
|
#define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func))
|
||||||
#else
|
#else
|
||||||
#define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass)
|
#define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass)
|
||||||
#endif
|
#endif
|
||||||
|
@ -12437,8 +12441,9 @@ static int __Pyx_modinit_variable_import_code(void) {
|
||||||
__Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0);
|
__Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0);
|
||||||
/*--- Variable import code ---*/
|
/*--- Variable import code ---*/
|
||||||
__pyx_t_1 = PyImport_ImportModule("dependency_injector.providers"); if (!__pyx_t_1) __PYX_ERR(0, 1, __pyx_L1_error)
|
__pyx_t_1 = PyImport_ImportModule("dependency_injector.providers"); if (!__pyx_t_1) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||||
|
__Pyx_GOTREF(__pyx_t_1);
|
||||||
if (__Pyx_ImportVoidPtr(__pyx_t_1, "CLASS_TYPES", (void **)&__pyx_vp_19dependency_injector_9providers_CLASS_TYPES, "PyObject *") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
if (__Pyx_ImportVoidPtr(__pyx_t_1, "CLASS_TYPES", (void **)&__pyx_vp_19dependency_injector_9providers_CLASS_TYPES, "PyObject *") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||||
Py_DECREF(__pyx_t_1); __pyx_t_1 = 0;
|
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
|
||||||
__Pyx_RefNannyFinishContext();
|
__Pyx_RefNannyFinishContext();
|
||||||
return 0;
|
return 0;
|
||||||
__pyx_L1_error:;
|
__pyx_L1_error:;
|
||||||
|
@ -12456,8 +12461,9 @@ static int __Pyx_modinit_function_import_code(void) {
|
||||||
__Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0);
|
__Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0);
|
||||||
/*--- Function import code ---*/
|
/*--- Function import code ---*/
|
||||||
__pyx_t_1 = PyImport_ImportModule("dependency_injector.providers"); if (!__pyx_t_1) __PYX_ERR(0, 1, __pyx_L1_error)
|
__pyx_t_1 = PyImport_ImportModule("dependency_injector.providers"); if (!__pyx_t_1) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||||
|
__Pyx_GOTREF(__pyx_t_1);
|
||||||
if (__Pyx_ImportFunction(__pyx_t_1, "deepcopy", (void (**)(void))&__pyx_f_19dependency_injector_9providers_deepcopy, "PyObject *(PyObject *, int __pyx_skip_dispatch, struct __pyx_opt_args_19dependency_injector_9providers_deepcopy *__pyx_optional_args)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
if (__Pyx_ImportFunction(__pyx_t_1, "deepcopy", (void (**)(void))&__pyx_f_19dependency_injector_9providers_deepcopy, "PyObject *(PyObject *, int __pyx_skip_dispatch, struct __pyx_opt_args_19dependency_injector_9providers_deepcopy *__pyx_optional_args)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
|
||||||
Py_DECREF(__pyx_t_1); __pyx_t_1 = 0;
|
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
|
||||||
__Pyx_RefNannyFinishContext();
|
__Pyx_RefNannyFinishContext();
|
||||||
return 0;
|
return 0;
|
||||||
__pyx_L1_error:;
|
__pyx_L1_error:;
|
||||||
|
@ -14667,6 +14673,7 @@ static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit,
|
||||||
}
|
}
|
||||||
static PyObject *__Pyx_CyFunction_descr_get(PyObject *func, PyObject *obj, PyObject *type)
|
static PyObject *__Pyx_CyFunction_descr_get(PyObject *func, PyObject *obj, PyObject *type)
|
||||||
{
|
{
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
__pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
|
__pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
|
||||||
if (m->flags & __Pyx_CYFUNCTION_STATICMETHOD) {
|
if (m->flags & __Pyx_CYFUNCTION_STATICMETHOD) {
|
||||||
Py_INCREF(func);
|
Py_INCREF(func);
|
||||||
|
@ -14679,6 +14686,7 @@ static PyObject *__Pyx_CyFunction_descr_get(PyObject *func, PyObject *obj, PyObj
|
||||||
}
|
}
|
||||||
if (obj == Py_None)
|
if (obj == Py_None)
|
||||||
obj = NULL;
|
obj = NULL;
|
||||||
|
#endif
|
||||||
return __Pyx_PyMethod_New(func, obj, type);
|
return __Pyx_PyMethod_New(func, obj, type);
|
||||||
}
|
}
|
||||||
static PyObject*
|
static PyObject*
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,8 +14,6 @@ from typing import (
|
||||||
Coroutine as _Coroutine,
|
Coroutine as _Coroutine,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .types import Provider as _Provider
|
|
||||||
|
|
||||||
|
|
||||||
Injection = Any
|
Injection = Any
|
||||||
T = TypeVar('T')
|
T = TypeVar('T')
|
||||||
|
@ -27,10 +25,10 @@ class OverridingContext:
|
||||||
def __exit__(self, *_: Any) -> None: ...
|
def __exit__(self, *_: Any) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
class Provider(_Provider):
|
class Provider(Generic[T]):
|
||||||
def __init__(self) -> None: ...
|
def __init__(self) -> None: ...
|
||||||
def __call__(self, *args: Injection, **kwargs: Injection) -> Any: ...
|
def __call__(self, *args: Injection, **kwargs: Injection) -> T: ...
|
||||||
def __deepcopy__(self, memo: Optional[Dict[str, Any]]) -> Provider: ...
|
def __deepcopy__(self, memo: Optional[Dict[Any, Any]]) -> Provider: ...
|
||||||
def __str__(self) -> str: ...
|
def __str__(self) -> str: ...
|
||||||
def __repr__(self) -> str: ...
|
def __repr__(self) -> str: ...
|
||||||
@property
|
@property
|
||||||
|
@ -43,7 +41,7 @@ class Provider(_Provider):
|
||||||
def delegate(self) -> Provider: ...
|
def delegate(self) -> Provider: ...
|
||||||
@property
|
@property
|
||||||
def provider(self) -> Provider: ...
|
def provider(self) -> Provider: ...
|
||||||
def _copy_overridings(self, copied: Provider, memo: Optional[Dict[str, Any]]) -> None: ...
|
def _copy_overridings(self, copied: Provider, memo: Optional[Dict[Any, Any]]) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
class Object(Provider, Generic[T]):
|
class Object(Provider, Generic[T]):
|
||||||
|
@ -316,7 +314,7 @@ def is_delegated(instance: Any) -> bool: ...
|
||||||
def represent_provider(provider: Provider, provides: Any) -> str: ...
|
def represent_provider(provider: Provider, provides: Any) -> str: ...
|
||||||
|
|
||||||
|
|
||||||
def deepcopy(instance: Any, memo: Optional[Dict[str, Any]]): Any: ...
|
def deepcopy(instance: Any, memo: Optional[Dict[Any, Any]]): Any: ...
|
||||||
|
|
||||||
|
|
||||||
def merge_dicts(dict1: Dict[Any, Any], dict2: Dict[Any, Any]) -> Dict[Any, Any]: ...
|
def merge_dicts(dict1: Dict[Any, Any], dict2: Dict[Any, Any]) -> Dict[Any, Any]: ...
|
||||||
|
|
|
@ -169,6 +169,10 @@ cdef class Provider(object):
|
||||||
|
|
||||||
return copied
|
return copied
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __class_getitem__(cls, item):
|
||||||
|
return cls
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""Return string representation of provider.
|
"""Return string representation of provider.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
from typing import TypeVar, Generic, Any
|
from typing import TypeVar, Generic, Any
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
'Types module is deprecated since version 3.44.0. Use "providers" module instead: '
|
||||||
|
'providers.Provider[SomeClass]',
|
||||||
|
category=DeprecationWarning,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
Injection = Any
|
Injection = Any
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from typing import Tuple, Any, Dict
|
from typing import Tuple, Any, Dict
|
||||||
|
|
||||||
from dependency_injector import providers, types
|
from dependency_injector import providers
|
||||||
|
|
||||||
|
|
||||||
class Animal:
|
class Animal:
|
||||||
|
@ -64,5 +64,5 @@ factory_b_9: providers.Factory = provider9.b
|
||||||
val9: Any = provider9('a')
|
val9: Any = provider9('a')
|
||||||
|
|
||||||
# Test 10: to check the explicit typing
|
# Test 10: to check the explicit typing
|
||||||
factory10: types.Provider[Animal] = providers.Factory(Cat)
|
factory10: providers.Provider[Animal] = providers.Factory(Cat)
|
||||||
animal10: Animal = factory10()
|
animal10: Animal = factory10()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from dependency_injector import providers, types
|
from dependency_injector import providers
|
||||||
|
|
||||||
|
|
||||||
class SomeClass:
|
class SomeClass:
|
||||||
|
@ -10,6 +10,6 @@ class SomeClass:
|
||||||
class TypesTest(unittest.TestCase):
|
class TypesTest(unittest.TestCase):
|
||||||
|
|
||||||
def test_provider(self):
|
def test_provider(self):
|
||||||
provider: types.Provider[SomeClass] = providers.Factory(SomeClass)
|
provider: providers.Provider[SomeClass] = providers.Factory(SomeClass)
|
||||||
some_object = provider()
|
some_object = provider()
|
||||||
self.assertIsInstance(some_object, SomeClass)
|
self.assertIsInstance(some_object, SomeClass)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user