mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-22 09:36:48 +03:00
531 Provider import from string (#555)
* Implement string imports for Factory, Callable, Singletons, and Resource * Refactor the implementation * Add tests * Update tests to pass on Python 2 * Update typing and add typing tests * Update changelog * Update docs
This commit is contained in:
parent
38ca1cdeed
commit
86df7f91f6
|
@ -21,6 +21,10 @@ Development version
|
||||||
``FactoryAggregate.factories`` attribute.
|
``FactoryAggregate.factories`` attribute.
|
||||||
- Add ``.set_providers()`` method to the ``FactoryAggregate`` provider. It is an alias for
|
- Add ``.set_providers()`` method to the ``FactoryAggregate`` provider. It is an alias for
|
||||||
``FactoryAggregate.set_factories()`` method.
|
``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``
|
- Fix ``Dependency`` provider to don't raise "Dependency is not defined" error when the ``default``
|
||||||
is a falsy value of proper type.
|
is a falsy value of proper type.
|
||||||
See issue `#550 <https://github.com/ets-labs/python-dependency-injector/issues/550>`_. Thanks to
|
See issue `#550 <https://github.com/ets-labs/python-dependency-injector/issues/550>`_. Thanks to
|
||||||
|
|
|
@ -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
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -158,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]: ...
|
||||||
|
@ -283,12 +283,12 @@ class Configuration(Object[Any]):
|
||||||
|
|
||||||
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]: ...
|
||||||
|
@ -326,12 +326,12 @@ class FactoryAggregate(Aggregate[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]: ...
|
||||||
|
@ -377,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]):
|
||||||
|
@ -410,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]: ...
|
||||||
|
|
|
@ -6,6 +6,7 @@ import copy
|
||||||
import errno
|
import errno
|
||||||
import functools
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
|
import importlib
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
@ -18,6 +19,11 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
contextvars = None
|
contextvars = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import builtins
|
||||||
|
except ImportError:
|
||||||
|
# Python 2.7
|
||||||
|
import __builtin__ as builtins
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import asyncio
|
import asyncio
|
||||||
|
@ -1221,6 +1227,7 @@ cdef class Callable(Provider):
|
||||||
|
|
||||||
def set_provides(self, provides):
|
def set_provides(self, provides):
|
||||||
"""Set provider provides."""
|
"""Set provider provides."""
|
||||||
|
provides = _resolve_provides(provides)
|
||||||
if provides and not callable(provides):
|
if provides and not callable(provides):
|
||||||
raise Error(
|
raise Error(
|
||||||
"Provider {0} expected to get callable, got {1} instead".format(
|
"Provider {0} expected to get callable, got {1} instead".format(
|
||||||
|
@ -1426,9 +1433,10 @@ cdef class Coroutine(Callable):
|
||||||
_is_coroutine = _is_coroutine_marker
|
_is_coroutine = _is_coroutine_marker
|
||||||
|
|
||||||
def set_provides(self, provides):
|
def set_provides(self, provides):
|
||||||
"""Set provider"s provides."""
|
"""Set provider provides."""
|
||||||
if not asyncio:
|
if not asyncio:
|
||||||
raise Error("Package asyncio is not available")
|
raise Error("Package asyncio is not available")
|
||||||
|
provides = _resolve_provides(provides)
|
||||||
if provides and not asyncio.iscoroutinefunction(provides):
|
if provides and not asyncio.iscoroutinefunction(provides):
|
||||||
raise Error(f"Provider {_class_qualname(self)} expected to get coroutine function, "
|
raise Error(f"Provider {_class_qualname(self)} expected to get coroutine function, "
|
||||||
f"got {provides} instead")
|
f"got {provides} instead")
|
||||||
|
@ -2452,6 +2460,7 @@ cdef class Factory(Provider):
|
||||||
|
|
||||||
def set_provides(self, provides):
|
def set_provides(self, provides):
|
||||||
"""Set provider provides."""
|
"""Set provider provides."""
|
||||||
|
provides = _resolve_provides(provides)
|
||||||
if (provides
|
if (provides
|
||||||
and self.__class__.provided_type and
|
and self.__class__.provided_type and
|
||||||
not issubclass(provides, self.__class__.provided_type)):
|
not issubclass(provides, self.__class__.provided_type)):
|
||||||
|
@ -2742,6 +2751,7 @@ cdef class BaseSingleton(Provider):
|
||||||
|
|
||||||
def set_provides(self, provides):
|
def set_provides(self, provides):
|
||||||
"""Set provider provides."""
|
"""Set provider provides."""
|
||||||
|
provides = _resolve_provides(provides)
|
||||||
if (provides
|
if (provides
|
||||||
and self.__class__.provided_type and
|
and self.__class__.provided_type and
|
||||||
not issubclass(provides, self.__class__.provided_type)):
|
not issubclass(provides, self.__class__.provided_type)):
|
||||||
|
@ -3580,6 +3590,7 @@ cdef class Resource(Provider):
|
||||||
|
|
||||||
def set_provides(self, provides):
|
def set_provides(self, provides):
|
||||||
"""Set provider provides."""
|
"""Set provider provides."""
|
||||||
|
provides = _resolve_provides(provides)
|
||||||
self.__provides = provides
|
self.__provides = provides
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -4882,6 +4893,44 @@ def isasyncgenfunction(obj):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_provides(provides):
|
||||||
|
if provides is None:
|
||||||
|
return provides
|
||||||
|
|
||||||
|
if not isinstance(provides, str):
|
||||||
|
return provides
|
||||||
|
|
||||||
|
segments = provides.split(".")
|
||||||
|
member_name = segments[-1]
|
||||||
|
|
||||||
|
if len(segments) == 1:
|
||||||
|
if member_name in dir(builtins):
|
||||||
|
module = builtins
|
||||||
|
else:
|
||||||
|
module = _resolve_calling_module()
|
||||||
|
return getattr(module, member_name)
|
||||||
|
|
||||||
|
module_name = ".".join(segments[:-1])
|
||||||
|
|
||||||
|
package_name = _resolve_calling_package_name()
|
||||||
|
if module_name.startswith(".") and package_name is None:
|
||||||
|
raise ImportError("Attempted relative import with no known parent package")
|
||||||
|
|
||||||
|
module = importlib.import_module(module_name, package=package_name)
|
||||||
|
return getattr(module, member_name)
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_calling_module():
|
||||||
|
stack = inspect.stack()
|
||||||
|
pre_last_frame = stack[0]
|
||||||
|
return inspect.getmodule(pre_last_frame[0])
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_calling_package_name():
|
||||||
|
module = _resolve_calling_module()
|
||||||
|
return module.__package__
|
||||||
|
|
||||||
|
|
||||||
cpdef _copy_parent(object from_, object to, dict memo):
|
cpdef _copy_parent(object from_, object to, dict memo):
|
||||||
"""Copy and assign provider parent."""
|
"""Copy and assign provider parent."""
|
||||||
copied_parent = (
|
copied_parent = (
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user