mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-05-01 22:43:46 +03:00
Merge branch 'release/4.38.0' into master
This commit is contained in:
commit
c26b260c73
|
@ -90,7 +90,7 @@ Key features of the ``Dependency Injector``:
|
||||||
api_client = providers.Singleton(
|
api_client = providers.Singleton(
|
||||||
ApiClient,
|
ApiClient,
|
||||||
api_key=config.api_key,
|
api_key=config.api_key,
|
||||||
timeout=config.timeout.as_int(),
|
timeout=config.timeout,
|
||||||
)
|
)
|
||||||
|
|
||||||
service = providers.Factory(
|
service = providers.Factory(
|
||||||
|
@ -106,8 +106,8 @@ Key features of the ``Dependency Injector``:
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
container = Container()
|
container = Container()
|
||||||
container.config.api_key.from_env("API_KEY")
|
container.config.api_key.from_env("API_KEY", required=True)
|
||||||
container.config.timeout.from_env("TIMEOUT")
|
container.config.timeout.from_env("TIMEOUT", as_=int, default=5)
|
||||||
container.wire(modules=[__name__])
|
container.wire(modules=[__name__])
|
||||||
|
|
||||||
main() # <-- dependency is injected automatically
|
main() # <-- dependency is injected automatically
|
||||||
|
|
2
docs/_static/logo.svg
vendored
2
docs/_static/logo.svg
vendored
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.8 KiB |
|
@ -96,7 +96,7 @@ Key features of the ``Dependency Injector``:
|
||||||
api_client = providers.Singleton(
|
api_client = providers.Singleton(
|
||||||
ApiClient,
|
ApiClient,
|
||||||
api_key=config.api_key,
|
api_key=config.api_key,
|
||||||
timeout=config.timeout.as_int(),
|
timeout=config.timeout,
|
||||||
)
|
)
|
||||||
|
|
||||||
service = providers.Factory(
|
service = providers.Factory(
|
||||||
|
@ -112,8 +112,8 @@ Key features of the ``Dependency Injector``:
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
container = Container()
|
container = Container()
|
||||||
container.config.api_key.from_env("API_KEY")
|
container.config.api_key.from_env("API_KEY", required=True)
|
||||||
container.config.timeout.from_env("TIMEOUT")
|
container.config.timeout.from_env("TIMEOUT", as_=int, default=5)
|
||||||
container.wire(modules=[__name__])
|
container.wire(modules=[__name__])
|
||||||
|
|
||||||
main() # <-- dependency is injected automatically
|
main() # <-- dependency is injected automatically
|
||||||
|
|
|
@ -150,7 +150,7 @@ What does the Dependency Injector do?
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
With the dependency injection pattern objects loose the responsibility of assembling
|
With the dependency injection pattern objects loose the responsibility of assembling
|
||||||
the dependencies. The ``Dependency Injector`` absorbs that responsibilities.
|
the dependencies. The ``Dependency Injector`` absorbs that responsibility.
|
||||||
|
|
||||||
``Dependency Injector`` helps to assemble and inject the dependencies.
|
``Dependency Injector`` helps to assemble and inject the dependencies.
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ the dependency.
|
||||||
api_client = providers.Singleton(
|
api_client = providers.Singleton(
|
||||||
ApiClient,
|
ApiClient,
|
||||||
api_key=config.api_key,
|
api_key=config.api_key,
|
||||||
timeout=config.timeout.as_int(),
|
timeout=config.timeout,
|
||||||
)
|
)
|
||||||
|
|
||||||
service = providers.Factory(
|
service = providers.Factory(
|
||||||
|
@ -188,8 +188,8 @@ the dependency.
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
container = Container()
|
container = Container()
|
||||||
container.config.api_key.from_env("API_KEY")
|
container.config.api_key.from_env("API_KEY", required=True)
|
||||||
container.config.timeout.from_env("TIMEOUT")
|
container.config.timeout.from_env("TIMEOUT", as_=int, default=5)
|
||||||
container.wire(modules=[__name__])
|
container.wire(modules=[__name__])
|
||||||
|
|
||||||
main() # <-- dependency is injected automatically
|
main() # <-- dependency is injected automatically
|
||||||
|
|
|
@ -7,6 +7,31 @@ 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`_
|
||||||
|
|
||||||
|
4.38.0
|
||||||
|
------
|
||||||
|
- Add new provider ``Aggregate``. It is a generalized version of ``FactoryAggregate`` that
|
||||||
|
can contain providers of any type, not only ``Factory``. See issue
|
||||||
|
`#530 <https://github.com/ets-labs/python-dependency-injector/issues/530>`_. Thanks to
|
||||||
|
`@zerlok (Danil Troshnev) <https://github.com/zerlok>`_ for suggesting the feature.
|
||||||
|
- Add argument ``as_`` to the ``config.from_env()`` method for the explicit type casting
|
||||||
|
of an environment variable value, e.g.: ``config.timeout.from_env("TIMEOUT", as_=int)``.
|
||||||
|
See issue `#533 <https://github.com/ets-labs/python-dependency-injector/issues/533>`_. Thanks to
|
||||||
|
`@gtors (Andrey Torsunov) <https://github.com/gtors>`_ for suggesting the feature.
|
||||||
|
- Add ``.providers`` attribute to the ``FactoryAggregate`` provider. It is an alias for
|
||||||
|
``FactoryAggregate.factories`` attribute.
|
||||||
|
- Add ``.set_providers()`` method to the ``FactoryAggregate`` provider. It is an alias for
|
||||||
|
``FactoryAggregate.set_factories()`` method.
|
||||||
|
- Add string imports for ``Factory``, ``Singleton``, ``Callable``, ``Resource``, and ``Coroutine``
|
||||||
|
providers, e.g. ``Factory("module.Class")``.
|
||||||
|
See issue `#531 <https://github.com/ets-labs/python-dependency-injector/issues/531>`_.
|
||||||
|
Thanks to `@al-stefanitsky-mozdor <https://github.com/al-stefanitsky-mozdor>`_ for suggesting the feature.
|
||||||
|
- Fix ``Dependency`` provider to don't raise "Dependency is not defined" error when the ``default``
|
||||||
|
is a falsy value of proper type.
|
||||||
|
See issue `#550 <https://github.com/ets-labs/python-dependency-injector/issues/550>`_. Thanks to
|
||||||
|
`@approxit <https://github.com/approxit>`_ for reporting the issue.
|
||||||
|
- Refactor ``FactoryAggregate`` provider internals.
|
||||||
|
- Update logo on Github and in docs to support dark themes and remove some imperfections.
|
||||||
|
|
||||||
4.37.0
|
4.37.0
|
||||||
------
|
------
|
||||||
- Add support of Python 3.10.
|
- Add support of Python 3.10.
|
||||||
|
|
72
docs/providers/aggregate.rst
Normal file
72
docs/providers/aggregate.rst
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
.. _aggregate-provider:
|
||||||
|
|
||||||
|
Aggregate provider
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. meta::
|
||||||
|
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Configuration,Injection,
|
||||||
|
Aggregate,Polymorphism,Environment Variable,Flexibility
|
||||||
|
:description: Aggregate provider aggregates other providers.
|
||||||
|
This page demonstrates how to implement the polymorphism and increase the
|
||||||
|
flexibility of your application using the Aggregate provider.
|
||||||
|
|
||||||
|
:py:class:`Aggregate` provider aggregates a group of other providers.
|
||||||
|
|
||||||
|
.. currentmodule:: dependency_injector.providers
|
||||||
|
|
||||||
|
.. literalinclude:: ../../examples/providers/aggregate.py
|
||||||
|
:language: python
|
||||||
|
:lines: 3-
|
||||||
|
:emphasize-lines: 24-27
|
||||||
|
|
||||||
|
Each provider in the ``Aggregate`` is associated with a key. You can call aggregated providers by providing
|
||||||
|
their key as a first argument. All positional and keyword arguments following the key will be forwarded to
|
||||||
|
the called provider:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
yaml_reader = container.config_readers("yaml", "./config.yml", foo=...)
|
||||||
|
|
||||||
|
You can also retrieve an aggregated provider by providing its key as an attribute name:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
yaml_reader = container.config_readers.yaml("./config.yml", foo=...)
|
||||||
|
|
||||||
|
To retrieve a dictionary of aggregated providers, use ``.providers`` attribute:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
container.config_readers.providers == {
|
||||||
|
"yaml": <YAML provider>,
|
||||||
|
"json": <JSON provider>,
|
||||||
|
}
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
You can not override the ``Aggregate`` provider.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
When you inject the ``Aggregate`` provider, it is passed "as is".
|
||||||
|
|
||||||
|
To use non-string keys or string keys with ``.`` and ``-``, provide a dictionary as a positional argument:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
aggregate = providers.Aggregate({
|
||||||
|
SomeClass: providers.Factory(...),
|
||||||
|
"key.with.periods": providers.Factory(...),
|
||||||
|
"key-with-dashes": providers.Factory(...),
|
||||||
|
})
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
:ref:`selector-provider` to make injections based on a configuration value, environment variable, or a result of a callable.
|
||||||
|
|
||||||
|
``Aggregate`` provider is different from the :ref:`selector-provider`. ``Aggregate`` provider doesn't select which provider
|
||||||
|
to inject and doesn't have a selector. It is a group of providers and is always injected "as is". The rest of the interface
|
||||||
|
of both providers is similar.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
``Aggregate`` provider is a successor of :ref:`factory-aggregate-provider` provider. ``Aggregate`` provider doesn't have
|
||||||
|
a restriction on the provider type, while ``FactoryAggregate`` aggregates only ``Factory`` providers.
|
||||||
|
|
||||||
|
.. disqus::
|
|
@ -205,6 +205,24 @@ Loading from an environment variable
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
:emphasize-lines: 18-20
|
:emphasize-lines: 18-20
|
||||||
|
|
||||||
|
You can use ``as_`` argument for the type casting of an environment variable value:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 2,6,10
|
||||||
|
|
||||||
|
# API_KEY=secret
|
||||||
|
container.config.api_key.from_env("API_KEY", as_=str, required=True)
|
||||||
|
assert container.config.api_key() == "secret"
|
||||||
|
|
||||||
|
# SAMPLING_RATIO=0.5
|
||||||
|
container.config.sampling.from_env("SAMPLING_RATIO", as_=float, required=True)
|
||||||
|
assert container.config.sampling() == 0.5
|
||||||
|
|
||||||
|
# TIMEOUT undefined, default is used
|
||||||
|
container.config.timeout.from_env("TIMEOUT", as_=int, default=5)
|
||||||
|
assert container.config.timeout() == 5
|
||||||
|
|
||||||
|
|
||||||
Loading a value
|
Loading a value
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,45 @@ attribute of the provider that you're going to inject.
|
||||||
|
|
||||||
.. note:: Any provider has a ``.provider`` attribute.
|
.. note:: Any provider has a ``.provider`` attribute.
|
||||||
|
|
||||||
|
.. _factory-string-imports:
|
||||||
|
|
||||||
|
String imports
|
||||||
|
--------------
|
||||||
|
|
||||||
|
``Factory`` provider can handle string imports:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
service = providers.Factory("myapp.mypackage.mymodule.Service")
|
||||||
|
|
||||||
|
You can also make a relative import:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# in myapp/container.py
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
service = providers.Factory(".mypackage.mymodule.Service")
|
||||||
|
|
||||||
|
or import a member of the current module just specifying its name:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class Service:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
service = providers.Factory("Service")
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
``Singleton``, ``Callable``, ``Resource``, and ``Coroutine`` providers handle string imports
|
||||||
|
the same way as a ``Factory`` provider.
|
||||||
|
|
||||||
.. _factory-specialize-provided-type:
|
.. _factory-specialize-provided-type:
|
||||||
|
|
||||||
Specializing the provided type
|
Specializing the provided type
|
||||||
|
@ -145,11 +184,17 @@ provider with two peculiarities:
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
:emphasize-lines: 34
|
:emphasize-lines: 34
|
||||||
|
|
||||||
|
.. _factory-aggregate-provider:
|
||||||
|
|
||||||
Factory aggregate
|
Factory aggregate
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
:py:class:`FactoryAggregate` provider aggregates multiple factories.
|
:py:class:`FactoryAggregate` provider aggregates multiple factories.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
:ref:`aggregate-provider` – it's a successor of ``FactoryAggregate`` provider that can aggregate
|
||||||
|
any type of provider, not only ``Factory``.
|
||||||
|
|
||||||
The aggregated factories are associated with the string keys. When you call the
|
The aggregated factories are associated with the string keys. When you call the
|
||||||
``FactoryAggregate`` you have to provide one of the these keys as a first argument.
|
``FactoryAggregate`` you have to provide one of the these keys as a first argument.
|
||||||
``FactoryAggregate`` looks for the factory with a matching key and calls it with the rest of the arguments.
|
``FactoryAggregate`` looks for the factory with a matching key and calls it with the rest of the arguments.
|
||||||
|
@ -163,9 +208,9 @@ The aggregated factories are associated with the string keys. When you call the
|
||||||
:lines: 3-
|
:lines: 3-
|
||||||
:emphasize-lines: 33-37,47
|
:emphasize-lines: 33-37,47
|
||||||
|
|
||||||
You can get a dictionary of the aggregated factories using the ``.factories`` attribute.
|
You can get a dictionary of the aggregated providers using ``.providers`` attribute.
|
||||||
To get a game factories dictionary from the previous example you can use
|
To get a game provider dictionary from the previous example you can use
|
||||||
``game_factory.factories`` attribute.
|
``game_factory.providers`` attribute.
|
||||||
|
|
||||||
You can also access an aggregated factory as an attribute. To create the ``Chess`` object from the
|
You can also access an aggregated factory as an attribute. To create the ``Chess`` object from the
|
||||||
previous example you can do ``chess = game_factory.chess("John", "Jane")``.
|
previous example you can do ``chess = game_factory.chess("John", "Jane")``.
|
||||||
|
@ -176,7 +221,7 @@ previous example you can do ``chess = game_factory.chess("John", "Jane")``.
|
||||||
.. note::
|
.. note::
|
||||||
When you inject the ``FactoryAggregate`` provider it is passed "as is".
|
When you inject the ``FactoryAggregate`` provider it is passed "as is".
|
||||||
|
|
||||||
To use non-string keys or keys with ``.`` and ``-`` you can provide a dictionary as a positional argument:
|
To use non-string keys or string keys with ``.`` and ``-``, you can provide a dictionary as a positional argument:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ Providers module API docs - :py:mod:`dependency_injector.providers`
|
||||||
dict
|
dict
|
||||||
configuration
|
configuration
|
||||||
resource
|
resource
|
||||||
|
aggregate
|
||||||
selector
|
selector
|
||||||
dependency
|
dependency
|
||||||
overriding
|
overriding
|
||||||
|
|
|
@ -30,4 +30,7 @@ When a ``Selector`` provider is called, it gets a ``selector`` value and delegat
|
||||||
the provider with a matching name. The ``selector`` callable works as a switch: when the returned
|
the provider with a matching name. The ``selector`` callable works as a switch: when the returned
|
||||||
value is changed the ``Selector`` provider will delegate the work to another provider.
|
value is changed the ``Selector`` provider will delegate the work to another provider.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
:ref:`aggregate-provider` to inject a group of providers.
|
||||||
|
|
||||||
.. disqus::
|
.. disqus::
|
||||||
|
|
|
@ -13,7 +13,7 @@ class Container(containers.DeclarativeContainer):
|
||||||
api_client = providers.Singleton(
|
api_client = providers.Singleton(
|
||||||
ApiClient,
|
ApiClient,
|
||||||
api_key=config.api_key,
|
api_key=config.api_key,
|
||||||
timeout=config.timeout.as_int(),
|
timeout=config.timeout,
|
||||||
)
|
)
|
||||||
|
|
||||||
service = providers.Factory(
|
service = providers.Factory(
|
||||||
|
@ -29,8 +29,8 @@ def main(service: Service = Provide[Container.service]):
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
container = Container()
|
container = Container()
|
||||||
container.config.api_key.from_env("API_KEY")
|
container.config.api_key.from_env("API_KEY", required=True)
|
||||||
container.config.timeout.from_env("TIMEOUT")
|
container.config.timeout.from_env("TIMEOUT", as_=int, default=5)
|
||||||
container.wire(modules=[__name__])
|
container.wire(modules=[__name__])
|
||||||
|
|
||||||
main() # <-- dependency is injected automatically
|
main() # <-- dependency is injected automatically
|
||||||
|
|
39
examples/providers/aggregate.py
Normal file
39
examples/providers/aggregate.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
"""`Aggregate` provider example."""
|
||||||
|
|
||||||
|
from dependency_injector import containers, providers
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigReader:
|
||||||
|
|
||||||
|
def __init__(self, path):
|
||||||
|
self._path = path
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
print(f"Parsing {self._path} with {self.__class__.__name__}")
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class YamlReader(ConfigReader):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class JsonReader(ConfigReader):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Container(containers.DeclarativeContainer):
|
||||||
|
|
||||||
|
config_readers = providers.Aggregate(
|
||||||
|
yaml=providers.Factory(YamlReader),
|
||||||
|
json=providers.Factory(JsonReader),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
container = Container()
|
||||||
|
|
||||||
|
yaml_reader = container.config_readers("yaml", "./config.yml")
|
||||||
|
yaml_reader.read() # Parsing ./config.yml with YamlReader
|
||||||
|
|
||||||
|
json_reader = container.config_readers("json", "./config.json")
|
||||||
|
json_reader.read() # Parsing ./config.json with JsonReader
|
|
@ -1,6 +1,6 @@
|
||||||
"""Top-level package."""
|
"""Top-level package."""
|
||||||
|
|
||||||
__version__ = "4.37.0"
|
__version__ = "4.38.0"
|
||||||
"""Version number.
|
"""Version number.
|
||||||
|
|
||||||
:type: str
|
:type: str
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,11 +20,11 @@ from typing import (
|
||||||
from .providers import Provider, Self, ProviderParent
|
from .providers import Provider, Self, ProviderParent
|
||||||
|
|
||||||
|
|
||||||
C_Base = TypeVar('C_Base', bound='Container')
|
C_Base = TypeVar("C_Base", bound="Container")
|
||||||
C = TypeVar('C', bound='DeclarativeContainer')
|
C = TypeVar("C", bound="DeclarativeContainer")
|
||||||
C_Overriding = TypeVar('C_Overriding', bound='DeclarativeContainer')
|
C_Overriding = TypeVar("C_Overriding", bound="DeclarativeContainer")
|
||||||
T = TypeVar('T')
|
T = TypeVar("T")
|
||||||
TT = TypeVar('TT')
|
TT = TypeVar("TT")
|
||||||
|
|
||||||
|
|
||||||
class WiringConfiguration:
|
class WiringConfiguration:
|
||||||
|
|
|
@ -28,10 +28,10 @@ if sys.version_info[:2] >= (3, 6):
|
||||||
from .wiring import wire, unwire
|
from .wiring import wire, unwire
|
||||||
else:
|
else:
|
||||||
def wire(*args, **kwargs):
|
def wire(*args, **kwargs):
|
||||||
raise NotImplementedError('Wiring requires Python 3.6 or above')
|
raise NotImplementedError("Wiring requires Python 3.6 or above")
|
||||||
|
|
||||||
def unwire(*args, **kwargs):
|
def unwire(*args, **kwargs):
|
||||||
raise NotImplementedError('Wiring requires Python 3.6 or above')
|
raise NotImplementedError("Wiring requires Python 3.6 or above")
|
||||||
|
|
||||||
if sys.version_info[:2] == (3, 5):
|
if sys.version_info[:2] == (3, 5):
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
|
@ -137,17 +137,17 @@ class DynamicContainer(Container):
|
||||||
If value of attribute is provider, it will be added into providers
|
If value of attribute is provider, it will be added into providers
|
||||||
dictionary.
|
dictionary.
|
||||||
|
|
||||||
:param name: Attribute's name
|
:param name: Attribute name
|
||||||
:type name: object
|
:type name: object
|
||||||
|
|
||||||
:param value: Attribute's value
|
:param value: Attribute value
|
||||||
:type value: object
|
:type value: object
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if isinstance(value, providers.Provider) \
|
if isinstance(value, providers.Provider) \
|
||||||
and not isinstance(value, providers.Self) \
|
and not isinstance(value, providers.Self) \
|
||||||
and name != 'parent':
|
and name != "parent":
|
||||||
_check_provider_type(self, value)
|
_check_provider_type(self, value)
|
||||||
|
|
||||||
self.providers[name] = value
|
self.providers[name] = value
|
||||||
|
@ -163,7 +163,7 @@ class DynamicContainer(Container):
|
||||||
If value of attribute is provider, it will be deleted from providers
|
If value of attribute is provider, it will be deleted from providers
|
||||||
dictionary.
|
dictionary.
|
||||||
|
|
||||||
:param name: Attribute's name
|
:param name: Attribute name
|
||||||
:type name: object
|
:type name: object
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
|
@ -229,8 +229,8 @@ class DynamicContainer(Container):
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if overriding is self:
|
if overriding is self:
|
||||||
raise errors.Error('Container {0} could not be overridden '
|
raise errors.Error("Container {0} could not be overridden "
|
||||||
'with itself'.format(self))
|
"with itself".format(self))
|
||||||
|
|
||||||
self.overridden += (overriding,)
|
self.overridden += (overriding,)
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ class DynamicContainer(Container):
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if not self.overridden:
|
if not self.overridden:
|
||||||
raise errors.Error('Container {0} is not overridden'.format(self))
|
raise errors.Error("Container {0} is not overridden".format(self))
|
||||||
|
|
||||||
self.overridden = self.overridden[:-1]
|
self.overridden = self.overridden[:-1]
|
||||||
|
|
||||||
|
@ -364,7 +364,7 @@ class DynamicContainer(Container):
|
||||||
while any(resource.initialized for resource in resources):
|
while any(resource.initialized for resource in resources):
|
||||||
resources_to_shutdown = list(_independent_resources(resources))
|
resources_to_shutdown = list(_independent_resources(resources))
|
||||||
if not resources_to_shutdown:
|
if not resources_to_shutdown:
|
||||||
raise RuntimeError('Unable to resolve resources shutdown order')
|
raise RuntimeError("Unable to resolve resources shutdown order")
|
||||||
futures = []
|
futures = []
|
||||||
for resource in resources_to_shutdown:
|
for resource in resources_to_shutdown:
|
||||||
result = resource.shutdown()
|
result = resource.shutdown()
|
||||||
|
@ -376,7 +376,7 @@ class DynamicContainer(Container):
|
||||||
while any(resource.initialized for resource in resources):
|
while any(resource.initialized for resource in resources):
|
||||||
resources_to_shutdown = list(_independent_resources(resources))
|
resources_to_shutdown = list(_independent_resources(resources))
|
||||||
if not resources_to_shutdown:
|
if not resources_to_shutdown:
|
||||||
raise RuntimeError('Unable to resolve resources shutdown order')
|
raise RuntimeError("Unable to resolve resources shutdown order")
|
||||||
for resource in resources_to_shutdown:
|
for resource in resources_to_shutdown:
|
||||||
resource.shutdown()
|
resource.shutdown()
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ class DynamicContainer(Container):
|
||||||
config.load()
|
config.load()
|
||||||
|
|
||||||
def apply_container_providers_overridings(self):
|
def apply_container_providers_overridings(self):
|
||||||
"""Apply container providers' overridings."""
|
"""Apply container providers overridings."""
|
||||||
for provider in self.traverse(types=[providers.Container]):
|
for provider in self.traverse(types=[providers.Container]):
|
||||||
provider.apply_overridings()
|
provider.apply_overridings()
|
||||||
|
|
||||||
|
@ -419,12 +419,12 @@ class DynamicContainer(Container):
|
||||||
|
|
||||||
container_name = self.parent_name if self.parent_name else self.__class__.__name__
|
container_name = self.parent_name if self.parent_name else self.__class__.__name__
|
||||||
undefined_names = [
|
undefined_names = [
|
||||||
f'"{dependency.parent_name if dependency.parent_name else dependency}"'
|
f"\"{dependency.parent_name if dependency.parent_name else dependency}\""
|
||||||
for dependency in undefined
|
for dependency in undefined
|
||||||
]
|
]
|
||||||
raise errors.Error(
|
raise errors.Error(
|
||||||
f'Container "{container_name}" has undefined dependencies: '
|
f"Container \"{container_name}\" has undefined dependencies: "
|
||||||
f'{", ".join(undefined_names)}',
|
f"{', '.join(undefined_names)}",
|
||||||
)
|
)
|
||||||
|
|
||||||
def from_schema(self, schema):
|
def from_schema(self, schema):
|
||||||
|
@ -441,9 +441,9 @@ class DynamicContainer(Container):
|
||||||
"""
|
"""
|
||||||
if yaml is None:
|
if yaml is None:
|
||||||
raise errors.Error(
|
raise errors.Error(
|
||||||
'Unable to load yaml schema - PyYAML is not installed. '
|
"Unable to load yaml schema - PyYAML is not installed. "
|
||||||
'Install PyYAML or install Dependency Injector with yaml extras: '
|
"Install PyYAML or install Dependency Injector with yaml extras: "
|
||||||
'"pip install dependency-injector[yaml]"'
|
"\"pip install dependency-injector[yaml]\""
|
||||||
)
|
)
|
||||||
|
|
||||||
if loader is None:
|
if loader is None:
|
||||||
|
@ -466,7 +466,7 @@ class DynamicContainer(Container):
|
||||||
if container_provider is provider:
|
if container_provider is provider:
|
||||||
return provider_name
|
return provider_name
|
||||||
else:
|
else:
|
||||||
raise errors.Error(f'Can not resolve name for provider "{provider}"')
|
raise errors.Error(f"Can not resolve name for provider \"{provider}\"")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parent_name(self):
|
def parent_name(self):
|
||||||
|
@ -525,11 +525,11 @@ class DeclarativeContainerMetaClass(type):
|
||||||
"instead got {0}".format(wiring_config)
|
"instead got {0}".format(wiring_config)
|
||||||
)
|
)
|
||||||
|
|
||||||
attributes['containers'] = containers
|
attributes["containers"] = containers
|
||||||
attributes['inherited_providers'] = inherited_providers
|
attributes["inherited_providers"] = inherited_providers
|
||||||
attributes['cls_providers'] = cls_providers
|
attributes["cls_providers"] = cls_providers
|
||||||
attributes['providers'] = all_providers
|
attributes["providers"] = all_providers
|
||||||
attributes['wiring_config'] = wiring_config
|
attributes["wiring_config"] = wiring_config
|
||||||
|
|
||||||
cls = <type>type.__new__(mcs, class_name, bases, attributes)
|
cls = <type>type.__new__(mcs, class_name, bases, attributes)
|
||||||
|
|
||||||
|
@ -551,15 +551,15 @@ class DeclarativeContainerMetaClass(type):
|
||||||
If value of attribute is provider, it will be added into providers
|
If value of attribute is provider, it will be added into providers
|
||||||
dictionary.
|
dictionary.
|
||||||
|
|
||||||
:param name: Attribute's name
|
:param name: Attribute name
|
||||||
:type name: object
|
:type name: object
|
||||||
|
|
||||||
:param value: Attribute's value
|
:param value: Attribute value
|
||||||
:type value: object
|
:type value: object
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if isinstance(value, providers.Provider) and name != '__self__':
|
if isinstance(value, providers.Provider) and name != "__self__":
|
||||||
_check_provider_type(cls, value)
|
_check_provider_type(cls, value)
|
||||||
|
|
||||||
if isinstance(value, providers.CHILD_PROVIDERS):
|
if isinstance(value, providers.CHILD_PROVIDERS):
|
||||||
|
@ -575,7 +575,7 @@ class DeclarativeContainerMetaClass(type):
|
||||||
If value of attribute is provider, it will be deleted from providers
|
If value of attribute is provider, it will be deleted from providers
|
||||||
dictionary.
|
dictionary.
|
||||||
|
|
||||||
:param name: Attribute's name
|
:param name: Attribute name
|
||||||
:type name: object
|
:type name: object
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
|
@ -611,7 +611,7 @@ class DeclarativeContainerMetaClass(type):
|
||||||
if container_provider is provider:
|
if container_provider is provider:
|
||||||
return provider_name
|
return provider_name
|
||||||
else:
|
else:
|
||||||
raise errors.Error(f'Can not resolve name for provider "{provider}"')
|
raise errors.Error(f"Can not resolve name for provider \"{provider}\"")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parent_name(cls):
|
def parent_name(cls):
|
||||||
|
@ -628,9 +628,9 @@ class DeclarativeContainerMetaClass(type):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if self is not None and value is not self:
|
if self is not None and value is not self:
|
||||||
raise errors.Error('Container can have only one "Self" provider')
|
raise errors.Error("Container can have only one \"Self\" provider")
|
||||||
|
|
||||||
if name != '__self__':
|
if name != "__self__":
|
||||||
alt_names.append(name)
|
alt_names.append(name)
|
||||||
|
|
||||||
self = value
|
self = value
|
||||||
|
@ -727,8 +727,8 @@ class DeclarativeContainer(Container):
|
||||||
container.wiring_config = copy_module.deepcopy(cls.wiring_config)
|
container.wiring_config = copy_module.deepcopy(cls.wiring_config)
|
||||||
container.declarative_parent = cls
|
container.declarative_parent = cls
|
||||||
|
|
||||||
copied_providers = providers.deepcopy({ **cls.providers, **{'@@self@@': cls.__self__}})
|
copied_providers = providers.deepcopy({ **cls.providers, **{"@@self@@": cls.__self__}})
|
||||||
copied_self = copied_providers.pop('@@self@@')
|
copied_self = copied_providers.pop("@@self@@")
|
||||||
copied_self.set_container(container)
|
copied_self.set_container(container)
|
||||||
|
|
||||||
container.__self__ = copied_self
|
container.__self__ = copied_self
|
||||||
|
@ -762,8 +762,8 @@ class DeclarativeContainer(Container):
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if issubclass(cls, overriding):
|
if issubclass(cls, overriding):
|
||||||
raise errors.Error('Container {0} could not be overridden '
|
raise errors.Error("Container {0} could not be overridden "
|
||||||
'with itself or its subclasses'.format(cls))
|
"with itself or its subclasses".format(cls))
|
||||||
|
|
||||||
cls.overridden += (overriding,)
|
cls.overridden += (overriding,)
|
||||||
|
|
||||||
|
@ -780,7 +780,7 @@ class DeclarativeContainer(Container):
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if not cls.overridden:
|
if not cls.overridden:
|
||||||
raise errors.Error('Container {0} is not overridden'.format(cls))
|
raise errors.Error("Container {0} is not overridden".format(cls))
|
||||||
|
|
||||||
cls.overridden = cls.overridden[:-1]
|
cls.overridden = cls.overridden[:-1]
|
||||||
|
|
||||||
|
@ -833,7 +833,7 @@ def override(object container):
|
||||||
container.
|
container.
|
||||||
:type container: :py:class:`DeclarativeContainer`
|
:type container: :py:class:`DeclarativeContainer`
|
||||||
|
|
||||||
:return: Declarative container's overriding decorator.
|
:return: Declarative container overriding decorator.
|
||||||
:rtype: callable(:py:class:`DeclarativeContainer`)
|
:rtype: callable(:py:class:`DeclarativeContainer`)
|
||||||
"""
|
"""
|
||||||
def _decorator(object overriding_container):
|
def _decorator(object overriding_container):
|
||||||
|
@ -853,7 +853,7 @@ def copy(object base_container):
|
||||||
:param base_container: Container that should be copied by decorated container.
|
:param base_container: Container that should be copied by decorated container.
|
||||||
:type base_container: :py:class:`DeclarativeContainer`
|
:type base_container: :py:class:`DeclarativeContainer`
|
||||||
|
|
||||||
:return: Declarative container's copying decorator.
|
:return: Declarative container copying decorator.
|
||||||
:rtype: callable(:py:class:`DeclarativeContainer`)
|
:rtype: callable(:py:class:`DeclarativeContainer`)
|
||||||
"""
|
"""
|
||||||
def _get_memo_for_matching_names(new_providers, base_providers):
|
def _get_memo_for_matching_names(new_providers, base_providers):
|
||||||
|
@ -864,7 +864,7 @@ def copy(object base_container):
|
||||||
source_provider = base_providers[new_provider_name]
|
source_provider = base_providers[new_provider_name]
|
||||||
memo[id(source_provider)] = new_provider
|
memo[id(source_provider)] = new_provider
|
||||||
|
|
||||||
if hasattr(new_provider, 'providers') and hasattr(source_provider, 'providers'):
|
if hasattr(new_provider, "providers") and hasattr(source_provider, "providers"):
|
||||||
sub_memo = _get_memo_for_matching_names(new_provider.providers, source_provider.providers)
|
sub_memo = _get_memo_for_matching_names(new_provider.providers, source_provider.providers)
|
||||||
memo.update(sub_memo)
|
memo.update(sub_memo)
|
||||||
return memo
|
return memo
|
||||||
|
@ -892,13 +892,13 @@ cpdef bint is_container(object instance):
|
||||||
|
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
return getattr(instance, '__IS_CONTAINER__', False) is True
|
return getattr(instance, "__IS_CONTAINER__", False) is True
|
||||||
|
|
||||||
|
|
||||||
cpdef object _check_provider_type(object container, object provider):
|
cpdef object _check_provider_type(object container, object provider):
|
||||||
if not isinstance(provider, container.provider_type):
|
if not isinstance(provider, container.provider_type):
|
||||||
raise errors.Error('{0} can contain only {1} '
|
raise errors.Error("{0} can contain only {1} "
|
||||||
'instances'.format(container, container.provider_type))
|
"instances".format(container, container.provider_type))
|
||||||
|
|
||||||
|
|
||||||
cpdef bint _any_relative_string_imports_in(object modules):
|
cpdef bint _any_relative_string_imports_in(object modules):
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -38,6 +38,12 @@ cdef class Delegate(Provider):
|
||||||
cpdef object _provide(self, tuple args, dict kwargs)
|
cpdef object _provide(self, tuple args, dict kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
cdef class Aggregate(Provider):
|
||||||
|
cdef dict __providers
|
||||||
|
|
||||||
|
cdef Provider __get_provider(self, object provider_name)
|
||||||
|
|
||||||
|
|
||||||
cdef class Dependency(Provider):
|
cdef class Dependency(Provider):
|
||||||
cdef object __instance_of
|
cdef object __instance_of
|
||||||
cdef object __default
|
cdef object __default
|
||||||
|
@ -142,10 +148,8 @@ cdef class FactoryDelegate(Delegate):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
cdef class FactoryAggregate(Provider):
|
cdef class FactoryAggregate(Aggregate):
|
||||||
cdef dict __factories
|
pass
|
||||||
|
|
||||||
cdef Factory __get_factory(self, object factory_name)
|
|
||||||
|
|
||||||
|
|
||||||
# Singleton providers
|
# Singleton providers
|
||||||
|
@ -359,11 +363,11 @@ cdef inline tuple __separate_prefixed_kwargs(dict kwargs):
|
||||||
cdef dict prefixed_kwargs = {}
|
cdef dict prefixed_kwargs = {}
|
||||||
|
|
||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
if '__' not in key:
|
if "__" not in key:
|
||||||
plain_kwargs[key] = value
|
plain_kwargs[key] = value
|
||||||
continue
|
continue
|
||||||
|
|
||||||
index = key.index('__')
|
index = key.index("__")
|
||||||
prefix, name = key[:index], key[index+2:]
|
prefix, name = key[:index], key[index+2:]
|
||||||
|
|
||||||
if prefix not in prefixed_kwargs:
|
if prefix not in prefixed_kwargs:
|
||||||
|
|
|
@ -35,11 +35,11 @@ from . import resources
|
||||||
|
|
||||||
|
|
||||||
Injection = Any
|
Injection = Any
|
||||||
ProviderParent = Union['Provider', Any]
|
ProviderParent = Union["Provider", Any]
|
||||||
T = TypeVar('T')
|
T = TypeVar("T")
|
||||||
TT = TypeVar('TT')
|
TT = TypeVar("TT")
|
||||||
P = TypeVar('P', bound='Provider')
|
P = TypeVar("P", bound="Provider")
|
||||||
BS = TypeVar('BS', bound='BaseSingleton')
|
BS = TypeVar("BS", bound="BaseSingleton")
|
||||||
|
|
||||||
|
|
||||||
class Provider(Generic[T]):
|
class Provider(Generic[T]):
|
||||||
|
@ -104,6 +104,21 @@ class Delegate(Provider[Provider]):
|
||||||
def set_provides(self, provides: Optional[Provider]) -> Delegate: ...
|
def set_provides(self, provides: Optional[Provider]) -> Delegate: ...
|
||||||
|
|
||||||
|
|
||||||
|
class Aggregate(Provider[T]):
|
||||||
|
def __init__(self, provider_dict: Optional[_Dict[Any, Provider[T]]] = None, **provider_kwargs: Provider[T]): ...
|
||||||
|
def __getattr__(self, provider_name: Any) -> Provider[T]: ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def __call__(self, provider_name: Optional[Any] = None, *args: Injection, **kwargs: Injection) -> T: ...
|
||||||
|
@overload
|
||||||
|
def __call__(self, provider_name: Optional[Any] = None, *args: Injection, **kwargs: Injection) -> Awaitable[T]: ...
|
||||||
|
def async_(self, provider_name: Optional[Any] = None, *args: Injection, **kwargs: Injection) -> Awaitable[T]: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def providers(self) -> _Dict[Any, Provider[T]]: ...
|
||||||
|
def set_providers(self, provider_dict: Optional[_Dict[Any, Provider[T]]] = None, **provider_kwargs: Provider[T]) -> Aggregate[T]: ...
|
||||||
|
|
||||||
|
|
||||||
class Dependency(Provider[T]):
|
class Dependency(Provider[T]):
|
||||||
def __init__(self, instance_of: Type[T] = object, default: Optional[Union[Provider, Any]] = None) -> None: ...
|
def __init__(self, instance_of: Type[T] = object, default: Optional[Union[Provider, Any]] = None) -> None: ...
|
||||||
def __getattr__(self, name: str) -> Any: ...
|
def __getattr__(self, name: str) -> Any: ...
|
||||||
|
@ -143,10 +158,10 @@ class DependenciesContainer(Object):
|
||||||
|
|
||||||
|
|
||||||
class Callable(Provider[T]):
|
class Callable(Provider[T]):
|
||||||
def __init__(self, provides: Optional[_Callable[..., T]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
def __init__(self, provides: Optional[Union[_Callable[..., T], str]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
||||||
@property
|
@property
|
||||||
def provides(self) -> Optional[_Callable[..., T]]: ...
|
def provides(self) -> Optional[_Callable[..., T]]: ...
|
||||||
def set_provides(self, provides: Optional[_Callable[..., T]]) -> Callable[T]: ...
|
def set_provides(self, provides: Optional[Union[_Callable[..., T], str]]) -> Callable[T]: ...
|
||||||
@property
|
@property
|
||||||
def args(self) -> Tuple[Injection]: ...
|
def args(self) -> Tuple[Injection]: ...
|
||||||
def add_args(self, *args: Injection) -> Callable[T]: ...
|
def add_args(self, *args: Injection) -> Callable[T]: ...
|
||||||
|
@ -205,7 +220,7 @@ class ConfigurationOption(Provider[Any]):
|
||||||
def from_yaml(self, filepath: Union[Path, str], required: bool = False, loader: Optional[Any] = None, envs_required: bool = False) -> None: ...
|
def from_yaml(self, filepath: Union[Path, str], required: bool = False, loader: Optional[Any] = None, envs_required: bool = False) -> None: ...
|
||||||
def from_pydantic(self, settings: PydanticSettings, required: bool = False, **kwargs: Any) -> None: ...
|
def from_pydantic(self, settings: PydanticSettings, required: bool = False, **kwargs: Any) -> None: ...
|
||||||
def from_dict(self, options: _Dict[str, Any], required: bool = False) -> None: ...
|
def from_dict(self, options: _Dict[str, Any], required: bool = False) -> None: ...
|
||||||
def from_env(self, name: str, default: Optional[Any] = None, required: bool = False) -> None: ...
|
def from_env(self, name: str, default: Optional[Any] = None, required: bool = False, as_: Optional[_Callable[..., Any]] = None) -> None: ...
|
||||||
def from_value(self, value: Any) -> None: ...
|
def from_value(self, value: Any) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
|
@ -215,7 +230,7 @@ class TypedConfigurationOption(Callable[T]):
|
||||||
|
|
||||||
|
|
||||||
class Configuration(Object[Any]):
|
class Configuration(Object[Any]):
|
||||||
DEFAULT_NAME: str = 'config'
|
DEFAULT_NAME: str = "config"
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: str = DEFAULT_NAME,
|
name: str = DEFAULT_NAME,
|
||||||
|
@ -262,18 +277,18 @@ class Configuration(Object[Any]):
|
||||||
def from_yaml(self, filepath: Union[Path, str], required: bool = False, loader: Optional[Any] = None, envs_required: bool = False) -> None: ...
|
def from_yaml(self, filepath: Union[Path, str], required: bool = False, loader: Optional[Any] = None, envs_required: bool = False) -> None: ...
|
||||||
def from_pydantic(self, settings: PydanticSettings, required: bool = False, **kwargs: Any) -> None: ...
|
def from_pydantic(self, settings: PydanticSettings, required: bool = False, **kwargs: Any) -> None: ...
|
||||||
def from_dict(self, options: _Dict[str, Any], required: bool = False) -> None: ...
|
def from_dict(self, options: _Dict[str, Any], required: bool = False) -> None: ...
|
||||||
def from_env(self, name: str, default: Optional[Any] = None, required: bool = False) -> None: ...
|
def from_env(self, name: str, default: Optional[Any] = None, required: bool = False, as_: Optional[_Callable[..., Any]] = None) -> None: ...
|
||||||
def from_value(self, value: Any) -> None: ...
|
def from_value(self, value: Any) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
class Factory(Provider[T]):
|
class Factory(Provider[T]):
|
||||||
provided_type: Optional[Type]
|
provided_type: Optional[Type]
|
||||||
def __init__(self, provides: Optional[_Callable[..., T]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
def __init__(self, provides: Optional[Union[_Callable[..., T], str]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
||||||
@property
|
@property
|
||||||
def cls(self) -> Type[T]: ...
|
def cls(self) -> Type[T]: ...
|
||||||
@property
|
@property
|
||||||
def provides(self) -> Optional[_Callable[..., T]]: ...
|
def provides(self) -> Optional[_Callable[..., T]]: ...
|
||||||
def set_provides(self, provides: Optional[_Callable[..., T]]) -> Factory[T]: ...
|
def set_provides(self, provides: Optional[Union[_Callable[..., T], str]]) -> Factory[T]: ...
|
||||||
@property
|
@property
|
||||||
def args(self) -> Tuple[Injection]: ...
|
def args(self) -> Tuple[Injection]: ...
|
||||||
def add_args(self, *args: Injection) -> Factory[T]: ...
|
def add_args(self, *args: Injection) -> Factory[T]: ...
|
||||||
|
@ -302,29 +317,21 @@ class FactoryDelegate(Delegate):
|
||||||
def __init__(self, factory: Factory): ...
|
def __init__(self, factory: Factory): ...
|
||||||
|
|
||||||
|
|
||||||
class FactoryAggregate(Provider[T]):
|
class FactoryAggregate(Aggregate[T]):
|
||||||
def __init__(self, dict_: Optional[_Dict[Any, Factory[T]]] = None, **factories: Factory[T]): ...
|
def __getattr__(self, provider_name: Any) -> Factory[T]: ...
|
||||||
def __getattr__(self, factory_name: Any) -> Factory[T]: ...
|
|
||||||
|
|
||||||
@overload
|
|
||||||
def __call__(self, factory_name: Any, *args: Injection, **kwargs: Injection) -> T: ...
|
|
||||||
@overload
|
|
||||||
def __call__(self, factory_name: Any, *args: Injection, **kwargs: Injection) -> Awaitable[T]: ...
|
|
||||||
def async_(self, factory_name: Any, *args: Injection, **kwargs: Injection) -> Awaitable[T]: ...
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def factories(self) -> _Dict[Any, Factory[T]]: ...
|
def factories(self) -> _Dict[Any, Factory[T]]: ...
|
||||||
def set_factories(self, dict_: Optional[_Dict[Any, Factory[T]]] = None, **factories: Factory[T]) -> FactoryAggregate[T]: ...
|
def set_factories(self, provider_dict: Optional[_Dict[Any, Factory[T]]] = None, **provider_kwargs: Factory[T]) -> FactoryAggregate[T]: ...
|
||||||
|
|
||||||
|
|
||||||
class BaseSingleton(Provider[T]):
|
class BaseSingleton(Provider[T]):
|
||||||
provided_type = Optional[Type]
|
provided_type = Optional[Type]
|
||||||
def __init__(self, provides: Optional[_Callable[..., T]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
def __init__(self, provides: Optional[Union[_Callable[..., T], str]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
||||||
@property
|
@property
|
||||||
def cls(self) -> Type[T]: ...
|
def cls(self) -> Type[T]: ...
|
||||||
@property
|
@property
|
||||||
def provides(self) -> Optional[_Callable[..., T]]: ...
|
def provides(self) -> Optional[_Callable[..., T]]: ...
|
||||||
def set_provides(self, provides: Optional[_Callable[..., T]]) -> BaseSingleton[T]: ...
|
def set_provides(self, provides: Optional[Union[_Callable[..., T], str]]) -> BaseSingleton[T]: ...
|
||||||
@property
|
@property
|
||||||
def args(self) -> Tuple[Injection]: ...
|
def args(self) -> Tuple[Injection]: ...
|
||||||
def add_args(self, *args: Injection) -> BaseSingleton[T]: ...
|
def add_args(self, *args: Injection) -> BaseSingleton[T]: ...
|
||||||
|
@ -370,7 +377,7 @@ class AbstractSingleton(BaseSingleton[T]):
|
||||||
|
|
||||||
|
|
||||||
class SingletonDelegate(Delegate):
|
class SingletonDelegate(Delegate):
|
||||||
def __init__(self, factory: BaseSingleton): ...
|
def __init__(self, singleton: BaseSingleton): ...
|
||||||
|
|
||||||
|
|
||||||
class List(Provider[_List]):
|
class List(Provider[_List]):
|
||||||
|
@ -403,7 +410,7 @@ class Resource(Provider[T]):
|
||||||
@overload
|
@overload
|
||||||
def __init__(self, provides: Optional[_Callable[..., _Coroutine[Injection, Injection, T]]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
def __init__(self, provides: Optional[_Callable[..., _Coroutine[Injection, Injection, T]]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
||||||
@overload
|
@overload
|
||||||
def __init__(self, provides: Optional[_Callable[..., T]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
def __init__(self, provides: Optional[Union[_Callable[..., T], str]] = None, *args: Injection, **kwargs: Injection) -> None: ...
|
||||||
@property
|
@property
|
||||||
def provides(self) -> Optional[_Callable[..., Any]]: ...
|
def provides(self) -> Optional[_Callable[..., Any]]: ...
|
||||||
def set_provides(self, provides: Optional[Any]) -> Resource[T]: ...
|
def set_provides(self, provides: Optional[Any]) -> Resource[T]: ...
|
||||||
|
@ -483,7 +490,9 @@ class MethodCaller(Provider, ProvidedInstanceFluentInterface):
|
||||||
class OverridingContext(Generic[T]):
|
class OverridingContext(Generic[T]):
|
||||||
def __init__(self, overridden: Provider, overriding: Provider): ...
|
def __init__(self, overridden: Provider, overriding: Provider): ...
|
||||||
def __enter__(self) -> T: ...
|
def __enter__(self) -> T: ...
|
||||||
def __exit__(self, *_: Any) -> None: ...
|
def __exit__(self, *_: Any) -> None:
|
||||||
|
pass
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
class BaseSingletonResetContext(Generic[T]):
|
class BaseSingletonResetContext(Generic[T]):
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,7 +4,7 @@ import abc
|
||||||
from typing import TypeVar, Generic, Optional
|
from typing import TypeVar, Generic, Optional
|
||||||
|
|
||||||
|
|
||||||
T = TypeVar('T')
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
class Resource(Generic[T], metaclass=abc.ABCMeta):
|
class Resource(Generic[T], metaclass=abc.ABCMeta):
|
||||||
|
|
|
@ -19,8 +19,8 @@ class SchemaProcessorV1:
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
"""Process schema."""
|
"""Process schema."""
|
||||||
self._create_providers(self._schema['container'])
|
self._create_providers(self._schema["container"])
|
||||||
self._setup_injections(self._schema['container'])
|
self._setup_injections(self._schema["container"])
|
||||||
|
|
||||||
def get_providers(self):
|
def get_providers(self):
|
||||||
"""Return providers."""
|
"""Return providers."""
|
||||||
|
@ -36,11 +36,11 @@ class SchemaProcessorV1:
|
||||||
for provider_name, data in provider_schema.items():
|
for provider_name, data in provider_schema.items():
|
||||||
provider = None
|
provider = None
|
||||||
|
|
||||||
if 'provider' in data:
|
if "provider" in data:
|
||||||
provider_type = _get_provider_cls(data['provider'])
|
provider_type = _get_provider_cls(data["provider"])
|
||||||
args = []
|
args = []
|
||||||
|
|
||||||
# provides = data.get('provides')
|
# provides = data.get("provides")
|
||||||
# if provides:
|
# if provides:
|
||||||
# provides = _import_string(provides)
|
# provides = _import_string(provides)
|
||||||
# if provides:
|
# if provides:
|
||||||
|
@ -69,38 +69,38 @@ class SchemaProcessorV1:
|
||||||
args = []
|
args = []
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
|
|
||||||
provides = data.get('provides')
|
provides = data.get("provides")
|
||||||
if provides:
|
if provides:
|
||||||
if isinstance(provides, str) and provides.startswith('container.'):
|
if isinstance(provides, str) and provides.startswith("container."):
|
||||||
provides = self._resolve_provider(provides[len('container.'):])
|
provides = self._resolve_provider(provides[len("container."):])
|
||||||
else:
|
else:
|
||||||
provides = _import_string(provides)
|
provides = _import_string(provides)
|
||||||
provider.set_provides(provides)
|
provider.set_provides(provides)
|
||||||
|
|
||||||
arg_injections = data.get('args')
|
arg_injections = data.get("args")
|
||||||
if arg_injections:
|
if arg_injections:
|
||||||
for arg in arg_injections:
|
for arg in arg_injections:
|
||||||
injection = None
|
injection = None
|
||||||
|
|
||||||
if isinstance(arg, str) and arg.startswith('container.'):
|
if isinstance(arg, str) and arg.startswith("container."):
|
||||||
injection = self._resolve_provider(arg[len('container.'):])
|
injection = self._resolve_provider(arg[len("container."):])
|
||||||
|
|
||||||
# TODO: refactoring
|
# TODO: refactoring
|
||||||
if isinstance(arg, dict):
|
if isinstance(arg, dict):
|
||||||
provider_args = []
|
provider_args = []
|
||||||
provider_type = _get_provider_cls(arg.get('provider'))
|
provider_type = _get_provider_cls(arg.get("provider"))
|
||||||
provides = arg.get('provides')
|
provides = arg.get("provides")
|
||||||
if provides:
|
if provides:
|
||||||
if isinstance(provides, str) and provides.startswith('container.'):
|
if isinstance(provides, str) and provides.startswith("container."):
|
||||||
provides = self._resolve_provider(provides[len('container.'):])
|
provides = self._resolve_provider(provides[len("container."):])
|
||||||
else:
|
else:
|
||||||
provides = _import_string(provides)
|
provides = _import_string(provides)
|
||||||
provider_args.append(provides)
|
provider_args.append(provides)
|
||||||
for provider_arg in arg.get('args', []):
|
for provider_arg in arg.get("args", []):
|
||||||
if isinstance(provider_arg, str) \
|
if isinstance(provider_arg, str) \
|
||||||
and provider_arg.startswith('container.'):
|
and provider_arg.startswith("container."):
|
||||||
provider_args.append(
|
provider_args.append(
|
||||||
self._resolve_provider(provider_arg[len('container.'):]),
|
self._resolve_provider(provider_arg[len("container."):]),
|
||||||
)
|
)
|
||||||
injection = provider_type(*provider_args)
|
injection = provider_type(*provider_args)
|
||||||
|
|
||||||
|
@ -111,30 +111,30 @@ class SchemaProcessorV1:
|
||||||
if args:
|
if args:
|
||||||
provider.add_args(*args)
|
provider.add_args(*args)
|
||||||
|
|
||||||
kwarg_injections = data.get('kwargs')
|
kwarg_injections = data.get("kwargs")
|
||||||
if kwarg_injections:
|
if kwarg_injections:
|
||||||
for name, arg in kwarg_injections.items():
|
for name, arg in kwarg_injections.items():
|
||||||
injection = None
|
injection = None
|
||||||
|
|
||||||
if isinstance(arg, str) and arg.startswith('container.'):
|
if isinstance(arg, str) and arg.startswith("container."):
|
||||||
injection = self._resolve_provider(arg[len('container.'):])
|
injection = self._resolve_provider(arg[len("container."):])
|
||||||
|
|
||||||
# TODO: refactoring
|
# TODO: refactoring
|
||||||
if isinstance(arg, dict):
|
if isinstance(arg, dict):
|
||||||
provider_args = []
|
provider_args = []
|
||||||
provider_type = _get_provider_cls(arg.get('provider'))
|
provider_type = _get_provider_cls(arg.get("provider"))
|
||||||
provides = arg.get('provides')
|
provides = arg.get("provides")
|
||||||
if provides:
|
if provides:
|
||||||
if isinstance(provides, str) and provides.startswith('container.'):
|
if isinstance(provides, str) and provides.startswith("container."):
|
||||||
provides = self._resolve_provider(provides[len('container.'):])
|
provides = self._resolve_provider(provides[len("container."):])
|
||||||
else:
|
else:
|
||||||
provides = _import_string(provides)
|
provides = _import_string(provides)
|
||||||
provider_args.append(provides)
|
provider_args.append(provides)
|
||||||
for provider_arg in arg.get('args', []):
|
for provider_arg in arg.get("args", []):
|
||||||
if isinstance(provider_arg, str) \
|
if isinstance(provider_arg, str) \
|
||||||
and provider_arg.startswith('container.'):
|
and provider_arg.startswith("container."):
|
||||||
provider_args.append(
|
provider_args.append(
|
||||||
self._resolve_provider(provider_arg[len('container.'):]),
|
self._resolve_provider(provider_arg[len("container."):]),
|
||||||
)
|
)
|
||||||
injection = provider_type(*provider_args)
|
injection = provider_type(*provider_args)
|
||||||
|
|
||||||
|
@ -149,17 +149,17 @@ class SchemaProcessorV1:
|
||||||
self._setup_injections(provider_schema=data, container=provider)
|
self._setup_injections(provider_schema=data, container=provider)
|
||||||
|
|
||||||
def _resolve_provider(self, name: str) -> Optional[providers.Provider]:
|
def _resolve_provider(self, name: str) -> Optional[providers.Provider]:
|
||||||
segments = name.split('.')
|
segments = name.split(".")
|
||||||
try:
|
try:
|
||||||
provider = getattr(self._container, segments[0])
|
provider = getattr(self._container, segments[0])
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for segment in segments[1:]:
|
for segment in segments[1:]:
|
||||||
parentheses = ''
|
parentheses = ""
|
||||||
if '(' in segment and ')' in segment:
|
if "(" in segment and ")" in segment:
|
||||||
parentheses = segment[segment.find('('):segment.rfind(')')+1]
|
parentheses = segment[segment.find("("):segment.rfind(")")+1]
|
||||||
segment = segment.replace(parentheses, '')
|
segment = segment.replace(parentheses, "")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
provider = getattr(provider, segment)
|
provider = getattr(provider, segment)
|
||||||
|
@ -190,7 +190,7 @@ def _get_provider_cls(provider_cls_name: str) -> Type[providers.Provider]:
|
||||||
if custom_provider_type:
|
if custom_provider_type:
|
||||||
return custom_provider_type
|
return custom_provider_type
|
||||||
|
|
||||||
raise SchemaError(f'Undefined provider class "{provider_cls_name}"')
|
raise SchemaError(f"Undefined provider class \"{provider_cls_name}\"")
|
||||||
|
|
||||||
|
|
||||||
def _fetch_provider_cls_from_std(provider_cls_name: str) -> Optional[Type[providers.Provider]]:
|
def _fetch_provider_cls_from_std(provider_cls_name: str) -> Optional[Type[providers.Provider]]:
|
||||||
|
@ -201,24 +201,24 @@ def _import_provider_cls(provider_cls_name: str) -> Optional[Type[providers.Prov
|
||||||
try:
|
try:
|
||||||
cls = _import_string(provider_cls_name)
|
cls = _import_string(provider_cls_name)
|
||||||
except (ImportError, ValueError) as exception:
|
except (ImportError, ValueError) as exception:
|
||||||
raise SchemaError(f'Can not import provider "{provider_cls_name}"') from exception
|
raise SchemaError(f"Can not import provider \"{provider_cls_name}\"") from exception
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
if isinstance(cls, type) and not issubclass(cls, providers.Provider):
|
if isinstance(cls, type) and not issubclass(cls, providers.Provider):
|
||||||
raise SchemaError(f'Provider class "{cls}" is not a subclass of providers base class')
|
raise SchemaError(f"Provider class \"{cls}\" is not a subclass of providers base class")
|
||||||
return cls
|
return cls
|
||||||
|
|
||||||
|
|
||||||
def _import_string(string_name: str) -> Optional[object]:
|
def _import_string(string_name: str) -> Optional[object]:
|
||||||
segments = string_name.split('.')
|
segments = string_name.split(".")
|
||||||
|
|
||||||
if len(segments) == 1:
|
if len(segments) == 1:
|
||||||
member = getattr(builtins, segments[0], None)
|
member = getattr(builtins, segments[0], None)
|
||||||
if member:
|
if member:
|
||||||
return member
|
return member
|
||||||
|
|
||||||
module_name = '.'.join(segments[:-1])
|
module_name = ".".join(segments[:-1])
|
||||||
if not module_name:
|
if not module_name:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -68,27 +68,27 @@ if sys.version_info[:2] == (3, 5):
|
||||||
)
|
)
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'wire',
|
"wire",
|
||||||
'unwire',
|
"unwire",
|
||||||
'inject',
|
"inject",
|
||||||
'as_int',
|
"as_int",
|
||||||
'as_float',
|
"as_float",
|
||||||
'as_',
|
"as_",
|
||||||
'required',
|
"required",
|
||||||
'invariant',
|
"invariant",
|
||||||
'provided',
|
"provided",
|
||||||
'Provide',
|
"Provide",
|
||||||
'Provider',
|
"Provider",
|
||||||
'Closing',
|
"Closing",
|
||||||
'register_loader_containers',
|
"register_loader_containers",
|
||||||
'unregister_loader_containers',
|
"unregister_loader_containers",
|
||||||
'install_loader',
|
"install_loader",
|
||||||
'uninstall_loader',
|
"uninstall_loader",
|
||||||
'is_loader_installed',
|
"is_loader_installed",
|
||||||
)
|
)
|
||||||
|
|
||||||
T = TypeVar('T')
|
T = TypeVar("T")
|
||||||
F = TypeVar('F', bound=Callable[..., Any])
|
F = TypeVar("F", bound=Callable[..., Any])
|
||||||
Container = Any
|
Container = Any
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,10 +107,10 @@ class PatchedRegistry:
|
||||||
continue
|
continue
|
||||||
yield patched
|
yield patched
|
||||||
|
|
||||||
def add_attribute(self, patched: 'PatchedAttribute'):
|
def add_attribute(self, patched: "PatchedAttribute"):
|
||||||
self._attributes.add(patched)
|
self._attributes.add(patched)
|
||||||
|
|
||||||
def get_attributes_from_module(self, module: ModuleType) -> Iterator['PatchedAttribute']:
|
def get_attributes_from_module(self, module: ModuleType) -> Iterator["PatchedAttribute"]:
|
||||||
for attribute in self._attributes:
|
for attribute in self._attributes:
|
||||||
if not attribute.is_in_module(module):
|
if not attribute.is_in_module(module):
|
||||||
continue
|
continue
|
||||||
|
@ -125,7 +125,7 @@ class PatchedRegistry:
|
||||||
|
|
||||||
class PatchedAttribute:
|
class PatchedAttribute:
|
||||||
|
|
||||||
def __init__(self, member: Any, name: str, marker: '_Marker'):
|
def __init__(self, member: Any, name: str, marker: "_Marker"):
|
||||||
self.member = member
|
self.member = member
|
||||||
self.name = name
|
self.name = name
|
||||||
self.marker = marker
|
self.marker = marker
|
||||||
|
@ -143,7 +143,7 @@ class PatchedAttribute:
|
||||||
|
|
||||||
class ProvidersMap:
|
class ProvidersMap:
|
||||||
|
|
||||||
CONTAINER_STRING_ID = '<container>'
|
CONTAINER_STRING_ID = "<container>"
|
||||||
|
|
||||||
def __init__(self, container):
|
def __init__(self, container):
|
||||||
self._container = container
|
self._container = container
|
||||||
|
@ -159,7 +159,7 @@ class ProvidersMap:
|
||||||
def resolve_provider(
|
def resolve_provider(
|
||||||
self,
|
self,
|
||||||
provider: Union[providers.Provider, str],
|
provider: Union[providers.Provider, str],
|
||||||
modifier: Optional['Modifier'] = None,
|
modifier: Optional["Modifier"] = None,
|
||||||
) -> Optional[providers.Provider]:
|
) -> Optional[providers.Provider]:
|
||||||
if isinstance(provider, providers.Delegate):
|
if isinstance(provider, providers.Delegate):
|
||||||
return self._resolve_delegate(provider)
|
return self._resolve_delegate(provider)
|
||||||
|
@ -182,13 +182,13 @@ class ProvidersMap:
|
||||||
def _resolve_string_id(
|
def _resolve_string_id(
|
||||||
self,
|
self,
|
||||||
id: str,
|
id: str,
|
||||||
modifier: Optional['Modifier'] = None,
|
modifier: Optional["Modifier"] = None,
|
||||||
) -> Optional[providers.Provider]:
|
) -> Optional[providers.Provider]:
|
||||||
if id == self.CONTAINER_STRING_ID:
|
if id == self.CONTAINER_STRING_ID:
|
||||||
return self._container.__self__
|
return self._container.__self__
|
||||||
|
|
||||||
provider = self._container
|
provider = self._container
|
||||||
for segment in id.split('.'):
|
for segment in id.split("."):
|
||||||
try:
|
try:
|
||||||
provider = getattr(provider, segment)
|
provider = getattr(provider, segment)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
@ -282,10 +282,10 @@ class ProvidersMap:
|
||||||
original_container: Container,
|
original_container: Container,
|
||||||
) -> Dict[providers.Provider, providers.Provider]:
|
) -> Dict[providers.Provider, providers.Provider]:
|
||||||
current_providers = current_container.providers
|
current_providers = current_container.providers
|
||||||
current_providers['__self__'] = current_container.__self__
|
current_providers["__self__"] = current_container.__self__
|
||||||
|
|
||||||
original_providers = original_container.providers
|
original_providers = original_container.providers
|
||||||
original_providers['__self__'] = original_container.__self__
|
original_providers["__self__"] = original_container.__self__
|
||||||
|
|
||||||
providers_map = {}
|
providers_map = {}
|
||||||
for provider_name, current_provider in current_providers.items():
|
for provider_name, current_provider in current_providers.items():
|
||||||
|
@ -429,7 +429,7 @@ def _patch_method(
|
||||||
method: Callable[..., Any],
|
method: Callable[..., Any],
|
||||||
providers_map: ProvidersMap,
|
providers_map: ProvidersMap,
|
||||||
) -> None:
|
) -> None:
|
||||||
if hasattr(cls, '__dict__') \
|
if hasattr(cls, "__dict__") \
|
||||||
and name in cls.__dict__ \
|
and name in cls.__dict__ \
|
||||||
and isinstance(cls.__dict__[name], (classmethod, staticmethod)):
|
and isinstance(cls.__dict__[name], (classmethod, staticmethod)):
|
||||||
method = cls.__dict__[name]
|
method = cls.__dict__[name]
|
||||||
|
@ -457,7 +457,7 @@ def _unpatch(
|
||||||
name: str,
|
name: str,
|
||||||
fn: Callable[..., Any],
|
fn: Callable[..., Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
if hasattr(module, '__dict__') \
|
if hasattr(module, "__dict__") \
|
||||||
and name in module.__dict__ \
|
and name in module.__dict__ \
|
||||||
and isinstance(module.__dict__[name], (classmethod, staticmethod)):
|
and isinstance(module.__dict__[name], (classmethod, staticmethod)):
|
||||||
method = module.__dict__[name]
|
method = module.__dict__[name]
|
||||||
|
@ -472,7 +472,7 @@ def _unpatch(
|
||||||
def _patch_attribute(
|
def _patch_attribute(
|
||||||
member: Any,
|
member: Any,
|
||||||
name: str,
|
name: str,
|
||||||
marker: '_Marker',
|
marker: "_Marker",
|
||||||
providers_map: ProvidersMap,
|
providers_map: ProvidersMap,
|
||||||
) -> None:
|
) -> None:
|
||||||
provider = providers_map.resolve_provider(marker.provider, marker.modifier)
|
provider = providers_map.resolve_provider(marker.provider, marker.modifier)
|
||||||
|
@ -487,7 +487,7 @@ def _patch_attribute(
|
||||||
elif isinstance(marker, Provider):
|
elif isinstance(marker, Provider):
|
||||||
setattr(member, name, provider)
|
setattr(member, name, provider)
|
||||||
else:
|
else:
|
||||||
raise Exception(f'Unknown type of marker {marker}')
|
raise Exception(f"Unknown type of marker {marker}")
|
||||||
|
|
||||||
|
|
||||||
def _unpatch_attribute(patched: PatchedAttribute) -> None:
|
def _unpatch_attribute(patched: PatchedAttribute) -> None:
|
||||||
|
@ -502,16 +502,16 @@ def _fetch_reference_injections( # noqa: C901
|
||||||
# - https://github.com/ets-labs/python-dependency-injector/issues/398
|
# - https://github.com/ets-labs/python-dependency-injector/issues/398
|
||||||
if GenericAlias and any((
|
if GenericAlias and any((
|
||||||
fn is GenericAlias,
|
fn is GenericAlias,
|
||||||
getattr(fn, '__func__', None) is GenericAlias
|
getattr(fn, "__func__", None) is GenericAlias
|
||||||
)):
|
)):
|
||||||
fn = fn.__init__
|
fn = fn.__init__
|
||||||
|
|
||||||
try:
|
try:
|
||||||
signature = inspect.signature(fn)
|
signature = inspect.signature(fn)
|
||||||
except ValueError as exception:
|
except ValueError as exception:
|
||||||
if 'no signature found' in str(exception):
|
if "no signature found" in str(exception):
|
||||||
return {}, {}
|
return {}, {}
|
||||||
elif 'not supported by signature' in str(exception):
|
elif "not supported by signature" in str(exception):
|
||||||
return {}, {}
|
return {}, {}
|
||||||
else:
|
else:
|
||||||
raise exception
|
raise exception
|
||||||
|
@ -565,11 +565,11 @@ def _unbind_injections(fn: Callable[..., Any]) -> None:
|
||||||
|
|
||||||
def _fetch_modules(package):
|
def _fetch_modules(package):
|
||||||
modules = [package]
|
modules = [package]
|
||||||
if not hasattr(package, '__path__') or not hasattr(package, '__name__'):
|
if not hasattr(package, "__path__") or not hasattr(package, "__name__"):
|
||||||
return modules
|
return modules
|
||||||
for module_info in pkgutil.walk_packages(
|
for module_info in pkgutil.walk_packages(
|
||||||
path=package.__path__,
|
path=package.__path__,
|
||||||
prefix=package.__name__ + '.',
|
prefix=package.__name__ + ".",
|
||||||
):
|
):
|
||||||
module = importlib.import_module(module_info.name)
|
module = importlib.import_module(module_info.name)
|
||||||
modules.append(module)
|
modules.append(module)
|
||||||
|
@ -670,13 +670,13 @@ def _is_fastapi_depends(param: Any) -> bool:
|
||||||
|
|
||||||
|
|
||||||
def _is_patched(fn):
|
def _is_patched(fn):
|
||||||
return getattr(fn, '__wired__', False) is True
|
return getattr(fn, "__wired__", False) is True
|
||||||
|
|
||||||
|
|
||||||
def _is_declarative_container(instance: Any) -> bool:
|
def _is_declarative_container(instance: Any) -> bool:
|
||||||
return (isinstance(instance, type)
|
return (isinstance(instance, type)
|
||||||
and getattr(instance, '__IS_CONTAINER__', False) is True
|
and getattr(instance, "__IS_CONTAINER__", False) is True
|
||||||
and getattr(instance, 'declarative_parent', None) is None)
|
and getattr(instance, "declarative_parent", None) is None)
|
||||||
|
|
||||||
|
|
||||||
class Modifier:
|
class Modifier:
|
||||||
|
@ -722,15 +722,15 @@ class RequiredModifier(Modifier):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.type_modifier = None
|
self.type_modifier = None
|
||||||
|
|
||||||
def as_int(self) -> 'RequiredModifier':
|
def as_int(self) -> "RequiredModifier":
|
||||||
self.type_modifier = TypeModifier(int)
|
self.type_modifier = TypeModifier(int)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def as_float(self) -> 'RequiredModifier':
|
def as_float(self) -> "RequiredModifier":
|
||||||
self.type_modifier = TypeModifier(float)
|
self.type_modifier = TypeModifier(float)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def as_(self, type_: Type) -> 'RequiredModifier':
|
def as_(self, type_: Type) -> "RequiredModifier":
|
||||||
self.type_modifier = TypeModifier(type_)
|
self.type_modifier = TypeModifier(type_)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -771,9 +771,9 @@ def invariant(id: str) -> InvariantModifier:
|
||||||
|
|
||||||
class ProvidedInstance(Modifier):
|
class ProvidedInstance(Modifier):
|
||||||
|
|
||||||
TYPE_ATTRIBUTE = 'attr'
|
TYPE_ATTRIBUTE = "attr"
|
||||||
TYPE_ITEM = 'item'
|
TYPE_ITEM = "item"
|
||||||
TYPE_CALL = 'call'
|
TYPE_CALL = "call"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.segments = []
|
self.segments = []
|
||||||
|
|
32
tests/typing/aggregate.py
Normal file
32
tests/typing/aggregate.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
from dependency_injector import providers
|
||||||
|
|
||||||
|
|
||||||
|
class Animal:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Cat(Animal):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
# Test 1: to check Aggregate provider
|
||||||
|
provider1: providers.Aggregate[str] = providers.Aggregate(
|
||||||
|
a=providers.Object("str1"),
|
||||||
|
b=providers.Object("str2"),
|
||||||
|
)
|
||||||
|
provider_a_1: providers.Provider[str] = provider1.a
|
||||||
|
provider_b_1: providers.Provider[str] = provider1.b
|
||||||
|
val1: str = provider1("a")
|
||||||
|
|
||||||
|
provider1_set_non_string_keys: providers.Aggregate[str] = providers.Aggregate()
|
||||||
|
provider1_set_non_string_keys.set_providers({Cat: providers.Object("str")})
|
||||||
|
provider_set_non_string_1: providers.Provider[str] = provider1_set_non_string_keys.providers[Cat]
|
||||||
|
|
||||||
|
provider1_new_non_string_keys: providers.Aggregate[str] = providers.Aggregate(
|
||||||
|
{Cat: providers.Object("str")},
|
||||||
|
)
|
||||||
|
factory_new_non_string_1: providers.Provider[str] = provider1_new_non_string_keys.providers[Cat]
|
||||||
|
|
||||||
|
provider1_no_explicit_typing = providers.Aggregate(a=providers.Object("str"))
|
||||||
|
provider1_no_explicit_typing_factory: providers.Provider[str] = provider1_no_explicit_typing.providers["a"]
|
||||||
|
provider1_no_explicit_typing_object: str = provider1_no_explicit_typing("a")
|
|
@ -66,3 +66,7 @@ assert provides10 is Cat
|
||||||
provider11 = providers.Callable[Animal](Cat)
|
provider11 = providers.Callable[Animal](Cat)
|
||||||
provides11: Optional[Callable[..., Animal]] = provider11.provides
|
provides11: Optional[Callable[..., Animal]] = provider11.provides
|
||||||
assert provides11 is Cat
|
assert provides11 is Cat
|
||||||
|
|
||||||
|
# Test 12: to check string imports
|
||||||
|
provider12: providers.Callable[dict] = providers.Callable("builtins.dict")
|
||||||
|
provider12.set_provides("builtins.dict")
|
||||||
|
|
|
@ -14,7 +14,11 @@ config2.from_ini(Path("config.ini"))
|
||||||
|
|
||||||
config2.from_yaml("config.yml")
|
config2.from_yaml("config.yml")
|
||||||
config2.from_yaml(Path("config.yml"))
|
config2.from_yaml(Path("config.yml"))
|
||||||
|
|
||||||
config2.from_env("ENV", "default")
|
config2.from_env("ENV", "default")
|
||||||
|
config2.from_env("ENV", as_=int, default=123)
|
||||||
|
config2.from_env("ENV", as_=float, required=True)
|
||||||
|
config2.from_env("ENV", as_=lambda env: str(env))
|
||||||
|
|
||||||
# Test 3: to check as_*() methods
|
# Test 3: to check as_*() methods
|
||||||
config3 = providers.Configuration()
|
config3 = providers.Configuration()
|
||||||
|
|
|
@ -9,3 +9,7 @@ async def _coro() -> None:
|
||||||
# Test 1: to check the return type
|
# Test 1: to check the return type
|
||||||
provider1 = providers.Coroutine(_coro)
|
provider1 = providers.Coroutine(_coro)
|
||||||
var1: Coroutine = provider1()
|
var1: Coroutine = provider1()
|
||||||
|
|
||||||
|
# Test 2: to check string imports
|
||||||
|
provider2: providers.Coroutine[None] = providers.Coroutine("_coro")
|
||||||
|
provider2.set_provides("_coro")
|
||||||
|
|
|
@ -99,3 +99,7 @@ provided_cls13: Type[Animal] = provider13.cls
|
||||||
assert issubclass(provided_cls13, Animal)
|
assert issubclass(provided_cls13, Animal)
|
||||||
provided_provides13: Optional[Callable[..., Animal]] = provider13.provides
|
provided_provides13: Optional[Callable[..., Animal]] = provider13.provides
|
||||||
assert provided_provides13 is not None and provided_provides13() == Cat()
|
assert provided_provides13 is not None and provided_provides13() == Cat()
|
||||||
|
|
||||||
|
# Test 14: to check string imports
|
||||||
|
provider14: providers.Factory[dict] = providers.Factory("builtins.dict")
|
||||||
|
provider14.set_provides("builtins.dict")
|
||||||
|
|
|
@ -97,3 +97,8 @@ provider8 = providers.Resource(MyResource8)
|
||||||
async def _provide8() -> None:
|
async def _provide8() -> None:
|
||||||
var1: List[int] = await provider8() # type: ignore
|
var1: List[int] = await provider8() # type: ignore
|
||||||
var2: List[int] = await provider8.async_()
|
var2: List[int] = await provider8.async_()
|
||||||
|
|
||||||
|
|
||||||
|
# Test 9: to check string imports
|
||||||
|
provider9: providers.Resource[dict] = providers.Resource("builtins.dict")
|
||||||
|
provider9.set_provides("builtins.dict")
|
||||||
|
|
|
@ -89,3 +89,7 @@ provided_cls15: Type[Animal] = provider15.cls
|
||||||
assert issubclass(provided_cls15, Animal)
|
assert issubclass(provided_cls15, Animal)
|
||||||
provided_provides15: Optional[Callable[..., Animal]] = provider15.provides
|
provided_provides15: Optional[Callable[..., Animal]] = provider15.provides
|
||||||
assert provided_provides15 is not None and provided_provides15() == Cat()
|
assert provided_provides15 is not None and provided_provides15() == Cat()
|
||||||
|
|
||||||
|
# Test 16: to check string imports
|
||||||
|
provider16: providers.Singleton[dict] = providers.Singleton("builtins.dict")
|
||||||
|
provider16.set_provides("builtins.dict")
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
"""Callable provider tests."""
|
"""Callable provider tests."""
|
||||||
|
|
||||||
|
import decimal
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from dependency_injector import providers, errors
|
from dependency_injector import providers, errors
|
||||||
from pytest import raises
|
from pytest import raises, mark
|
||||||
|
|
||||||
from .common import example
|
from .common import example
|
||||||
|
|
||||||
|
@ -29,6 +30,20 @@ def test_set_provides_returns_():
|
||||||
assert provider.set_provides(object) is provider
|
assert provider.set_provides(object) is provider
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize(
|
||||||
|
"str_name,cls",
|
||||||
|
[
|
||||||
|
("dependency_injector.providers.Factory", providers.Factory),
|
||||||
|
("decimal.Decimal", decimal.Decimal),
|
||||||
|
("list", list),
|
||||||
|
(".common.example", example),
|
||||||
|
("test_is_provider", test_is_provider),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_set_provides_string_imports(str_name, cls):
|
||||||
|
assert providers.Callable(str_name).provides is cls
|
||||||
|
|
||||||
|
|
||||||
def test_provided_instance_provider():
|
def test_provided_instance_provider():
|
||||||
provider = providers.Callable(example)
|
provider = providers.Callable(example)
|
||||||
assert isinstance(provider.provided, providers.ProvidedInstance)
|
assert isinstance(provider.provided, providers.ProvidedInstance)
|
||||||
|
|
|
@ -106,7 +106,11 @@ def environment_variables():
|
||||||
os.environ["CONFIG_TEST_ENV"] = "test-value"
|
os.environ["CONFIG_TEST_ENV"] = "test-value"
|
||||||
os.environ["CONFIG_TEST_PATH"] = "test-path"
|
os.environ["CONFIG_TEST_PATH"] = "test-path"
|
||||||
os.environ["DEFINED"] = "defined"
|
os.environ["DEFINED"] = "defined"
|
||||||
|
os.environ["EMPTY"] = ""
|
||||||
|
os.environ["CONFIG_INT"] = "42"
|
||||||
yield
|
yield
|
||||||
os.environ.pop("CONFIG_TEST_ENV", None)
|
os.environ.pop("CONFIG_TEST_ENV", None)
|
||||||
os.environ.pop("CONFIG_TEST_PATH", None)
|
os.environ.pop("CONFIG_TEST_PATH", None)
|
||||||
os.environ.pop("DEFINED", None)
|
os.environ.pop("DEFINED", None)
|
||||||
|
os.environ.pop("EMPTY", None)
|
||||||
|
os.environ.pop("CONFIG_INT", None)
|
||||||
|
|
|
@ -31,6 +31,54 @@ def test_option_default_none(config):
|
||||||
assert config.option() is None
|
assert config.option() is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_as_(config):
|
||||||
|
config.from_env("CONFIG_INT", as_=int)
|
||||||
|
assert config() == 42
|
||||||
|
assert isinstance(config(), int)
|
||||||
|
|
||||||
|
|
||||||
|
def test_as__default(config):
|
||||||
|
config.from_env("UNDEFINED", as_=int, default="33")
|
||||||
|
assert config() == 33
|
||||||
|
assert isinstance(config(), int)
|
||||||
|
|
||||||
|
|
||||||
|
def test_as__undefined_required(config):
|
||||||
|
with raises(ValueError):
|
||||||
|
config.from_env("UNDEFINED", as_=int, required=True)
|
||||||
|
assert config() == {}
|
||||||
|
|
||||||
|
|
||||||
|
def test_as__defined_empty(config):
|
||||||
|
with raises(ValueError):
|
||||||
|
config.from_env("EMPTY", as_=int)
|
||||||
|
assert config() == {}
|
||||||
|
|
||||||
|
|
||||||
|
def test_option_as_(config):
|
||||||
|
config.option.from_env("CONFIG_INT", as_=int)
|
||||||
|
assert config.option() == 42
|
||||||
|
assert isinstance(config.option(), int)
|
||||||
|
|
||||||
|
|
||||||
|
def test_option_as__default(config):
|
||||||
|
config.option.from_env("UNDEFINED", as_=int, default="33")
|
||||||
|
assert config.option() == 33
|
||||||
|
assert isinstance(config.option(), int)
|
||||||
|
|
||||||
|
|
||||||
|
def test_option_as__undefined_required(config):
|
||||||
|
with raises(ValueError):
|
||||||
|
config.option.from_env("UNDEFINED", as_=int, required=True)
|
||||||
|
assert config.option() is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_option_as__defined_empty(config):
|
||||||
|
with raises(ValueError):
|
||||||
|
config.option.from_env("EMPTY", as_=int)
|
||||||
|
assert config.option() is None
|
||||||
|
|
||||||
|
|
||||||
@mark.parametrize("config_type", ["strict"])
|
@mark.parametrize("config_type", ["strict"])
|
||||||
def test_undefined_in_strict_mode(config):
|
def test_undefined_in_strict_mode(config):
|
||||||
with raises(ValueError):
|
with raises(ValueError):
|
||||||
|
|
|
@ -31,6 +31,17 @@ def test_set_provides_returns_self():
|
||||||
assert provider.set_provides(example) is provider
|
assert provider.set_provides(example) is provider
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize(
|
||||||
|
"str_name,cls",
|
||||||
|
[
|
||||||
|
(".common.example", example),
|
||||||
|
("example", example),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_set_provides_string_imports(str_name, cls):
|
||||||
|
assert providers.Coroutine(str_name).provides is cls
|
||||||
|
|
||||||
|
|
||||||
@mark.asyncio
|
@mark.asyncio
|
||||||
async def test_call_with_positional_args():
|
async def test_call_with_positional_args():
|
||||||
provider = providers.Coroutine(example, 1, 2, 3, 4)
|
provider = providers.Coroutine(example, 1, 2, 3, 4)
|
||||||
|
|
|
@ -78,6 +78,52 @@ def test_init_with_not_a_factory():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize("factory_type", ["empty"])
|
||||||
|
def test_init_optional_providers(factory_aggregate, factory_a, factory_b):
|
||||||
|
factory_aggregate.set_providers(
|
||||||
|
example_a=factory_a,
|
||||||
|
example_b=factory_b,
|
||||||
|
)
|
||||||
|
assert factory_aggregate.providers == {
|
||||||
|
"example_a": factory_a,
|
||||||
|
"example_b": factory_b,
|
||||||
|
}
|
||||||
|
assert isinstance(factory_aggregate("example_a"), ExampleA)
|
||||||
|
assert isinstance(factory_aggregate("example_b"), ExampleB)
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize("factory_type", ["non-string-keys"])
|
||||||
|
def test_set_factories_with_non_string_keys(factory_aggregate, factory_a, factory_b):
|
||||||
|
factory_aggregate.set_providers({
|
||||||
|
ExampleA: factory_a,
|
||||||
|
ExampleB: factory_b,
|
||||||
|
})
|
||||||
|
|
||||||
|
object_a = factory_aggregate(ExampleA, 1, 2, init_arg3=3, init_arg4=4)
|
||||||
|
object_b = factory_aggregate(ExampleB, 11, 22, init_arg3=33, init_arg4=44)
|
||||||
|
|
||||||
|
assert isinstance(object_a, ExampleA)
|
||||||
|
assert object_a.init_arg1 == 1
|
||||||
|
assert object_a.init_arg2 == 2
|
||||||
|
assert object_a.init_arg3 == 3
|
||||||
|
assert object_a.init_arg4 == 4
|
||||||
|
|
||||||
|
assert isinstance(object_b, ExampleB)
|
||||||
|
assert object_b.init_arg1 == 11
|
||||||
|
assert object_b.init_arg2 == 22
|
||||||
|
assert object_b.init_arg3 == 33
|
||||||
|
assert object_b.init_arg4 == 44
|
||||||
|
|
||||||
|
assert factory_aggregate.providers == {
|
||||||
|
ExampleA: factory_a,
|
||||||
|
ExampleB: factory_b,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_set_providers_returns_self(factory_aggregate, factory_a):
|
||||||
|
assert factory_aggregate.set_providers(example_a=factory_a) is factory_aggregate
|
||||||
|
|
||||||
|
|
||||||
@mark.parametrize("factory_type", ["empty"])
|
@mark.parametrize("factory_type", ["empty"])
|
||||||
def test_init_optional_factories(factory_aggregate, factory_a, factory_b):
|
def test_init_optional_factories(factory_aggregate, factory_a, factory_b):
|
||||||
factory_aggregate.set_factories(
|
factory_aggregate.set_factories(
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
"""Factory provider tests."""
|
"""Factory provider tests."""
|
||||||
|
|
||||||
|
import decimal
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from dependency_injector import providers, errors
|
from dependency_injector import providers, errors
|
||||||
from pytest import raises
|
from pytest import raises, mark
|
||||||
|
|
||||||
from .common import Example
|
from .common import Example
|
||||||
|
|
||||||
|
@ -29,6 +30,20 @@ def test_set_provides_returns_():
|
||||||
assert provider.set_provides(object) is provider
|
assert provider.set_provides(object) is provider
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize(
|
||||||
|
"str_name,cls",
|
||||||
|
[
|
||||||
|
("dependency_injector.providers.Factory", providers.Factory),
|
||||||
|
("decimal.Decimal", decimal.Decimal),
|
||||||
|
("list", list),
|
||||||
|
(".common.Example", Example),
|
||||||
|
("test_is_provider", test_is_provider),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_set_provides_string_imports(str_name, cls):
|
||||||
|
assert providers.Factory(str_name).provides is cls
|
||||||
|
|
||||||
|
|
||||||
def test_init_with_valid_provided_type():
|
def test_init_with_valid_provided_type():
|
||||||
class ExampleProvider(providers.Factory):
|
class ExampleProvider(providers.Factory):
|
||||||
provided_type = Example
|
provided_type = Example
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
"""Resource provider tests."""
|
"""Resource provider tests."""
|
||||||
|
|
||||||
|
import decimal
|
||||||
import sys
|
import sys
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from dependency_injector import containers, providers, resources, errors
|
from dependency_injector import containers, providers, resources, errors
|
||||||
from pytest import raises
|
from pytest import raises, mark
|
||||||
|
|
||||||
|
|
||||||
def init_fn(*args, **kwargs):
|
def init_fn(*args, **kwargs):
|
||||||
|
@ -27,6 +28,20 @@ def test_set_provides_returns_():
|
||||||
assert provider.set_provides(init_fn) is provider
|
assert provider.set_provides(init_fn) is provider
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize(
|
||||||
|
"str_name,cls",
|
||||||
|
[
|
||||||
|
("dependency_injector.providers.Factory", providers.Factory),
|
||||||
|
("decimal.Decimal", decimal.Decimal),
|
||||||
|
("list", list),
|
||||||
|
(".test_resource_py35.test_is_provider", test_is_provider),
|
||||||
|
("test_is_provider", test_is_provider),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_set_provides_string_imports(str_name, cls):
|
||||||
|
assert providers.Resource(str_name).provides is cls
|
||||||
|
|
||||||
|
|
||||||
def test_provided_instance_provider():
|
def test_provided_instance_provider():
|
||||||
provider = providers.Resource(init_fn)
|
provider = providers.Resource(init_fn)
|
||||||
assert isinstance(provider.provided, providers.ProvidedInstance)
|
assert isinstance(provider.provided, providers.ProvidedInstance)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
"""Singleton provider tests."""
|
"""Singleton provider tests."""
|
||||||
|
import decimal
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from dependency_injector import providers, errors
|
from dependency_injector import providers, errors
|
||||||
from pytest import fixture, raises
|
from pytest import fixture, raises, mark
|
||||||
|
|
||||||
from .common import Example
|
from .common import Example
|
||||||
|
|
||||||
|
@ -49,6 +49,20 @@ def test_set_provides_returns_self(provider):
|
||||||
assert provider.set_provides(object) is provider
|
assert provider.set_provides(object) is provider
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize(
|
||||||
|
"str_name,cls",
|
||||||
|
[
|
||||||
|
("dependency_injector.providers.Factory", providers.Factory),
|
||||||
|
("decimal.Decimal", decimal.Decimal),
|
||||||
|
("list", list),
|
||||||
|
(".common.Example", Example),
|
||||||
|
("test_is_provider", test_is_provider),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_set_provides_string_imports(str_name, cls):
|
||||||
|
assert providers.Singleton(str_name).provides is cls
|
||||||
|
|
||||||
|
|
||||||
def test_init_with_valid_provided_type(singleton_cls):
|
def test_init_with_valid_provided_type(singleton_cls):
|
||||||
class ExampleProvider(singleton_cls):
|
class ExampleProvider(singleton_cls):
|
||||||
provided_type = Example
|
provided_type = Example
|
||||||
|
|
292
tests/unit/providers/test_aggregate_py2_py3.py
Normal file
292
tests/unit/providers/test_aggregate_py2_py3.py
Normal file
|
@ -0,0 +1,292 @@
|
||||||
|
"""Aggregate provider tests."""
|
||||||
|
|
||||||
|
from dependency_injector import providers, errors
|
||||||
|
from pytest import fixture, mark, raises
|
||||||
|
|
||||||
|
|
||||||
|
class Example:
|
||||||
|
def __init__(self, init_arg1=None, init_arg2=None, init_arg3=None, init_arg4=None):
|
||||||
|
self.init_arg1 = init_arg1
|
||||||
|
self.init_arg2 = init_arg2
|
||||||
|
self.init_arg3 = init_arg3
|
||||||
|
self.init_arg4 = init_arg4
|
||||||
|
|
||||||
|
self.attribute1 = None
|
||||||
|
self.attribute2 = None
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleA(Example):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleB(Example):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@fixture
|
||||||
|
def factory_a():
|
||||||
|
return providers.Factory(ExampleA)
|
||||||
|
|
||||||
|
|
||||||
|
@fixture
|
||||||
|
def factory_b():
|
||||||
|
return providers.Factory(ExampleB)
|
||||||
|
|
||||||
|
|
||||||
|
@fixture
|
||||||
|
def aggregate_type():
|
||||||
|
return "default"
|
||||||
|
|
||||||
|
|
||||||
|
@fixture
|
||||||
|
def aggregate(aggregate_type, factory_a, factory_b):
|
||||||
|
if aggregate_type == "empty":
|
||||||
|
return providers.Aggregate()
|
||||||
|
elif aggregate_type == "non-string-keys":
|
||||||
|
return providers.Aggregate({
|
||||||
|
ExampleA: factory_a,
|
||||||
|
ExampleB: factory_b,
|
||||||
|
})
|
||||||
|
elif aggregate_type == "default":
|
||||||
|
return providers.Aggregate(
|
||||||
|
example_a=factory_a,
|
||||||
|
example_b=factory_b,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise ValueError("Unknown factory type \"{0}\"".format(aggregate_type))
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_provider(aggregate):
|
||||||
|
assert providers.is_provider(aggregate) is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_delegated_provider(aggregate):
|
||||||
|
assert providers.is_delegated(aggregate) is True
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize("aggregate_type", ["non-string-keys"])
|
||||||
|
def test_init_with_non_string_keys(aggregate, factory_a, factory_b):
|
||||||
|
object_a = aggregate(ExampleA, 1, 2, init_arg3=3, init_arg4=4)
|
||||||
|
object_b = aggregate(ExampleB, 11, 22, init_arg3=33, init_arg4=44)
|
||||||
|
|
||||||
|
assert isinstance(object_a, ExampleA)
|
||||||
|
assert object_a.init_arg1 == 1
|
||||||
|
assert object_a.init_arg2 == 2
|
||||||
|
assert object_a.init_arg3 == 3
|
||||||
|
assert object_a.init_arg4 == 4
|
||||||
|
|
||||||
|
assert isinstance(object_b, ExampleB)
|
||||||
|
assert object_b.init_arg1 == 11
|
||||||
|
assert object_b.init_arg2 == 22
|
||||||
|
assert object_b.init_arg3 == 33
|
||||||
|
assert object_b.init_arg4 == 44
|
||||||
|
|
||||||
|
assert aggregate.providers == {
|
||||||
|
ExampleA: factory_a,
|
||||||
|
ExampleB: factory_b,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_init_with_not_a_factory():
|
||||||
|
with raises(errors.Error):
|
||||||
|
providers.Aggregate(
|
||||||
|
example_a=providers.Factory(ExampleA),
|
||||||
|
example_b=object(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize("aggregate_type", ["empty"])
|
||||||
|
def test_init_optional_providers(aggregate, factory_a, factory_b):
|
||||||
|
aggregate.set_providers(
|
||||||
|
example_a=factory_a,
|
||||||
|
example_b=factory_b,
|
||||||
|
)
|
||||||
|
assert aggregate.providers == {
|
||||||
|
"example_a": factory_a,
|
||||||
|
"example_b": factory_b,
|
||||||
|
}
|
||||||
|
assert isinstance(aggregate("example_a"), ExampleA)
|
||||||
|
assert isinstance(aggregate("example_b"), ExampleB)
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize("aggregate_type", ["non-string-keys"])
|
||||||
|
def test_set_providers_with_non_string_keys(aggregate, factory_a, factory_b):
|
||||||
|
aggregate.set_providers({
|
||||||
|
ExampleA: factory_a,
|
||||||
|
ExampleB: factory_b,
|
||||||
|
})
|
||||||
|
|
||||||
|
object_a = aggregate(ExampleA, 1, 2, init_arg3=3, init_arg4=4)
|
||||||
|
object_b = aggregate(ExampleB, 11, 22, init_arg3=33, init_arg4=44)
|
||||||
|
|
||||||
|
assert isinstance(object_a, ExampleA)
|
||||||
|
assert object_a.init_arg1 == 1
|
||||||
|
assert object_a.init_arg2 == 2
|
||||||
|
assert object_a.init_arg3 == 3
|
||||||
|
assert object_a.init_arg4 == 4
|
||||||
|
|
||||||
|
assert isinstance(object_b, ExampleB)
|
||||||
|
assert object_b.init_arg1 == 11
|
||||||
|
assert object_b.init_arg2 == 22
|
||||||
|
assert object_b.init_arg3 == 33
|
||||||
|
assert object_b.init_arg4 == 44
|
||||||
|
|
||||||
|
assert aggregate.providers == {
|
||||||
|
ExampleA: factory_a,
|
||||||
|
ExampleB: factory_b,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_set_providers_returns_self(aggregate, factory_a):
|
||||||
|
assert aggregate.set_providers(example_a=factory_a) is aggregate
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize("aggregate_type", ["empty"])
|
||||||
|
def test_init_optional_providers(aggregate, factory_a, factory_b):
|
||||||
|
aggregate.set_providers(
|
||||||
|
example_a=factory_a,
|
||||||
|
example_b=factory_b,
|
||||||
|
)
|
||||||
|
assert aggregate.providers == {
|
||||||
|
"example_a": factory_a,
|
||||||
|
"example_b": factory_b,
|
||||||
|
}
|
||||||
|
assert isinstance(aggregate("example_a"), ExampleA)
|
||||||
|
assert isinstance(aggregate("example_b"), ExampleB)
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize("aggregate_type", ["non-string-keys"])
|
||||||
|
def test_set_providers_with_non_string_keys(aggregate, factory_a, factory_b):
|
||||||
|
aggregate.set_providers({
|
||||||
|
ExampleA: factory_a,
|
||||||
|
ExampleB: factory_b,
|
||||||
|
})
|
||||||
|
|
||||||
|
object_a = aggregate(ExampleA, 1, 2, init_arg3=3, init_arg4=4)
|
||||||
|
object_b = aggregate(ExampleB, 11, 22, init_arg3=33, init_arg4=44)
|
||||||
|
|
||||||
|
assert isinstance(object_a, ExampleA)
|
||||||
|
assert object_a.init_arg1 == 1
|
||||||
|
assert object_a.init_arg2 == 2
|
||||||
|
assert object_a.init_arg3 == 3
|
||||||
|
assert object_a.init_arg4 == 4
|
||||||
|
|
||||||
|
assert isinstance(object_b, ExampleB)
|
||||||
|
assert object_b.init_arg1 == 11
|
||||||
|
assert object_b.init_arg2 == 22
|
||||||
|
assert object_b.init_arg3 == 33
|
||||||
|
assert object_b.init_arg4 == 44
|
||||||
|
|
||||||
|
assert aggregate.providers == {
|
||||||
|
ExampleA: factory_a,
|
||||||
|
ExampleB: factory_b,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_set_providers_returns_self(aggregate, factory_a):
|
||||||
|
assert aggregate.set_providers(example_a=factory_a) is aggregate
|
||||||
|
|
||||||
|
|
||||||
|
def test_call(aggregate):
|
||||||
|
object_a = aggregate("example_a", 1, 2, init_arg3=3, init_arg4=4)
|
||||||
|
object_b = aggregate("example_b", 11, 22, init_arg3=33, init_arg4=44)
|
||||||
|
|
||||||
|
assert isinstance(object_a, ExampleA)
|
||||||
|
assert object_a.init_arg1 == 1
|
||||||
|
assert object_a.init_arg2 == 2
|
||||||
|
assert object_a.init_arg3 == 3
|
||||||
|
assert object_a.init_arg4 == 4
|
||||||
|
|
||||||
|
assert isinstance(object_b, ExampleB)
|
||||||
|
assert object_b.init_arg1 == 11
|
||||||
|
assert object_b.init_arg2 == 22
|
||||||
|
assert object_b.init_arg3 == 33
|
||||||
|
assert object_b.init_arg4 == 44
|
||||||
|
|
||||||
|
|
||||||
|
def test_call_factory_name_as_kwarg(aggregate):
|
||||||
|
object_a = aggregate(
|
||||||
|
factory_name="example_a",
|
||||||
|
init_arg1=1,
|
||||||
|
init_arg2=2,
|
||||||
|
init_arg3=3,
|
||||||
|
init_arg4=4,
|
||||||
|
)
|
||||||
|
assert isinstance(object_a, ExampleA)
|
||||||
|
assert object_a.init_arg1 == 1
|
||||||
|
assert object_a.init_arg2 == 2
|
||||||
|
assert object_a.init_arg3 == 3
|
||||||
|
assert object_a.init_arg4 == 4
|
||||||
|
|
||||||
|
|
||||||
|
def test_call_no_factory_name(aggregate):
|
||||||
|
with raises(TypeError):
|
||||||
|
aggregate()
|
||||||
|
|
||||||
|
|
||||||
|
def test_call_no_such_provider(aggregate):
|
||||||
|
with raises(errors.NoSuchProviderError):
|
||||||
|
aggregate("unknown")
|
||||||
|
|
||||||
|
|
||||||
|
def test_overridden(aggregate):
|
||||||
|
with raises(errors.Error):
|
||||||
|
aggregate.override(providers.Object(object()))
|
||||||
|
|
||||||
|
|
||||||
|
def test_getattr(aggregate, factory_a, factory_b):
|
||||||
|
assert aggregate.example_a is factory_a
|
||||||
|
assert aggregate.example_b is factory_b
|
||||||
|
|
||||||
|
|
||||||
|
def test_getattr_no_such_provider(aggregate):
|
||||||
|
with raises(errors.NoSuchProviderError):
|
||||||
|
aggregate.unknown
|
||||||
|
|
||||||
|
|
||||||
|
def test_providers(aggregate, factory_a, factory_b):
|
||||||
|
assert aggregate.providers == dict(
|
||||||
|
example_a=factory_a,
|
||||||
|
example_b=factory_b,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_deepcopy(aggregate):
|
||||||
|
provider_copy = providers.deepcopy(aggregate)
|
||||||
|
|
||||||
|
assert aggregate is not provider_copy
|
||||||
|
assert isinstance(provider_copy, type(aggregate))
|
||||||
|
|
||||||
|
assert aggregate.example_a is not provider_copy.example_a
|
||||||
|
assert isinstance(aggregate.example_a, type(provider_copy.example_a))
|
||||||
|
assert aggregate.example_a.cls is provider_copy.example_a.cls
|
||||||
|
|
||||||
|
assert aggregate.example_b is not provider_copy.example_b
|
||||||
|
assert isinstance(aggregate.example_b, type(provider_copy.example_b))
|
||||||
|
assert aggregate.example_b.cls is provider_copy.example_b.cls
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize("aggregate_type", ["non-string-keys"])
|
||||||
|
def test_deepcopy_with_non_string_keys(aggregate):
|
||||||
|
provider_copy = providers.deepcopy(aggregate)
|
||||||
|
|
||||||
|
assert aggregate is not provider_copy
|
||||||
|
assert isinstance(provider_copy, type(aggregate))
|
||||||
|
|
||||||
|
assert aggregate.providers[ExampleA] is not provider_copy.providers[ExampleA]
|
||||||
|
assert isinstance(aggregate.providers[ExampleA], type(provider_copy.providers[ExampleA]))
|
||||||
|
assert aggregate.providers[ExampleA].provides is provider_copy.providers[ExampleA].provides
|
||||||
|
|
||||||
|
assert aggregate.providers[ExampleB] is not provider_copy.providers[ExampleB]
|
||||||
|
assert isinstance(aggregate.providers[ExampleB], type(provider_copy.providers[ExampleB]))
|
||||||
|
assert aggregate.providers[ExampleB].provides is provider_copy.providers[ExampleB].provides
|
||||||
|
|
||||||
|
|
||||||
|
def test_repr(aggregate):
|
||||||
|
assert repr(aggregate) == (
|
||||||
|
"<dependency_injector.providers."
|
||||||
|
"Aggregate({0}) at {1}>".format(
|
||||||
|
repr(aggregate.providers),
|
||||||
|
hex(id(aggregate)),
|
||||||
|
)
|
||||||
|
)
|
|
@ -77,6 +77,22 @@ def test_default_attribute_provider():
|
||||||
assert provider.default is default
|
assert provider.default is default
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_with_empty_dict():
|
||||||
|
# See: https://github.com/ets-labs/python-dependency-injector/issues/550
|
||||||
|
default = {}
|
||||||
|
provider = providers.Dependency(instance_of=dict, default=default)
|
||||||
|
assert provider() == default
|
||||||
|
assert provider.default() == default
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_with_empty_string():
|
||||||
|
# See: https://github.com/ets-labs/python-dependency-injector/issues/550
|
||||||
|
default = ""
|
||||||
|
provider = providers.Dependency(instance_of=str, default=default)
|
||||||
|
assert provider() == default
|
||||||
|
assert provider.default() == default
|
||||||
|
|
||||||
|
|
||||||
def test_is_defined(provider):
|
def test_is_defined(provider):
|
||||||
assert provider.is_defined is False
|
assert provider.is_defined is False
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user