Add support of non-string keys for Dict provider

This commit is contained in:
Roman Mogylatov 2020-11-20 17:30:42 -05:00
parent c8178cecda
commit 034e4814da
7 changed files with 1794 additions and 1437 deletions

View File

@ -9,6 +9,7 @@ follows `Semantic versioning`_
Develop Develop
------- -------
- Add support of non-string keys for ``Dict`` provider.
- Add simple ``FastAPI`` example. - Add simple ``FastAPI`` example.
- Add extra typing test for provided instance of ``DependenciesContainer`` provider. - Add extra typing test for provided instance of ``DependenciesContainer`` provider.

File diff suppressed because it is too large Load Diff

View File

@ -270,12 +270,12 @@ class List(Provider):
class Dict(Provider): class Dict(Provider):
def __init__(self, **kwargs: Injection): ... def __init__(self, dict_: Optional[_Dict[Any, Injection]] = None, **kwargs: Injection): ...
def __call__(self, *args: Injection, **kwargs: Injection) -> _Dict[Any, Any]: ... def __call__(self, *args: Injection, **kwargs: Injection) -> _Dict[Any, Any]: ...
@property @property
def kwargs(self) -> _Dict[Any, Injection]: ... def kwargs(self) -> _Dict[Any, Injection]: ...
def add_kwargs(self, **kwargs: Injection) -> Dict: ... def add_kwargs(self, dict_: Optional[_Dict[Any, Injection]] = None, **kwargs: Injection) -> Dict: ...
def set_kwargs(self, **kwargs: Injection) -> Dict: ... def set_kwargs(self, dict_: Optional[_Dict[Any, Injection]] = None, **kwargs: Injection) -> Dict: ...
def clear_kwargs(self) -> Dict: ... def clear_kwargs(self) -> Dict: ...

View File

@ -2484,11 +2484,11 @@ cdef class Dict(Provider):
) )
""" """
def __init__(self, **kwargs): def __init__(self, dict_=None, **kwargs):
"""Initializer.""" """Initializer."""
self.__kwargs = tuple() self.__kwargs = tuple()
self.__kwargs_len = 0 self.__kwargs_len = 0
self.set_kwargs(**kwargs) self.add_kwargs(dict_, **kwargs)
super(Dict, self).__init__() super(Dict, self).__init__()
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
@ -2497,7 +2497,7 @@ cdef class Dict(Provider):
if copied is not None: if copied is not None:
return copied return copied
copied = self.__class__(**deepcopy(self.kwargs, memo)) copied = self.__class__(deepcopy(self.kwargs, memo))
self._copy_overridings(copied, memo) self._copy_overridings(copied, memo)
return copied return copied
@ -2522,24 +2522,34 @@ cdef class Dict(Provider):
kwargs[kwarg.__name] = kwarg.__value kwargs[kwarg.__name] = kwarg.__value
return kwargs return kwargs
def add_kwargs(self, **kwargs): def add_kwargs(self, dict_=None, **kwargs):
"""Add keyword argument injections. """Add keyword argument injections.
:return: Reference ``self`` :return: Reference ``self``
""" """
if dict_ is None:
dict_ = {}
self.__kwargs += parse_named_injections(dict_)
self.__kwargs += parse_named_injections(kwargs) self.__kwargs += parse_named_injections(kwargs)
self.__kwargs_len = len(self.__kwargs) self.__kwargs_len = len(self.__kwargs)
return self return self
def set_kwargs(self, **kwargs): def set_kwargs(self, dict_=None, **kwargs):
"""Set keyword argument injections. """Set keyword argument injections.
Existing keyword argument injections are dropped. Existing keyword argument injections are dropped.
:return: Reference ``self`` :return: Reference ``self``
""" """
self.__kwargs = parse_named_injections(kwargs) if dict_ is None:
dict_ = {}
self.__kwargs = parse_named_injections(dict_)
self.__kwargs += parse_named_injections(kwargs)
self.__kwargs_len = len(self.__kwargs) self.__kwargs_len = len(self.__kwargs)
return self return self
def clear_kwargs(self): def clear_kwargs(self):

37
tests/typing/dict.py Normal file
View File

@ -0,0 +1,37 @@
from typing import Any, Dict
from dependency_injector import providers
# Test 1: to check the return type (class)
provider1 = providers.Dict(
a1=providers.Factory(object),
a2=providers.Factory(object),
)
var1: Dict[Any, Any] = provider1()
# Test 2: to check init with non-string keys
provider2 = providers.Dict({object(): providers.Factory(object)})
var2: Dict[Any, Any] = provider2()
# Test 3: to check init with non-string keys
provider3 = providers.Dict({object(): providers.Factory(object)}, a2=providers.Factory(object))
var3: Dict[Any, Any] = provider3()
# Test 4: to check the .args attributes
provider4 = providers.Dict(
a1=providers.Factory(object),
a2=providers.Factory(object),
)
args4: Dict[Any, Any] = provider4.kwargs
# Test 5: to check the provided instance interface
provider5 = providers.Dict(
a1=providers.Factory(object),
a2=providers.Factory(object),
)
provided5: providers.ProvidedInstance = provider5.provided

View File

@ -18,7 +18,7 @@ provider2 = providers.List(
) )
args2: Tuple[Any] = provider2.args args2: Tuple[Any] = provider2.args
# Test 5: to check the provided instance interface # Test 3: to check the provided instance interface
provider3 = providers.List( provider3 = providers.List(
providers.Factory(object), providers.Factory(object),
providers.Factory(object), providers.Factory(object),

View File

@ -16,6 +16,31 @@ class DictTests(unittest.TestCase):
provider = providers.Dict() provider = providers.Dict()
self.assertIsInstance(provider.provided, providers.ProvidedInstance) self.assertIsInstance(provider.provided, providers.ProvidedInstance)
def test_init_with_non_string_keys(self):
a1 = object()
a2 = object()
provider = providers.Dict({a1: 'i1', a2: 'i2'})
dict1 = provider()
dict2 = provider()
self.assertEqual(dict1, {a1: 'i1', a2: 'i2'})
self.assertEqual(dict2, {a1: 'i1', a2: 'i2'})
self.assertIsNot(dict1, dict2)
def test_init_with_string_and_non_string_keys(self):
a1 = object()
provider = providers.Dict({a1: 'i1'}, a2='i2')
dict1 = provider()
dict2 = provider()
self.assertEqual(dict1, {a1: 'i1', 'a2': 'i2'})
self.assertEqual(dict2, {a1: 'i1', 'a2': 'i2'})
self.assertIsNot(dict1, dict2)
def test_call_with_init_keyword_args(self): def test_call_with_init_keyword_args(self):
provider = providers.Dict(a1='i1', a2='i2') provider = providers.Dict(a1='i1', a2='i2')
@ -46,12 +71,48 @@ class DictTests(unittest.TestCase):
.add_kwargs(a1='i1', a2='i2') .add_kwargs(a1='i1', a2='i2')
self.assertEqual(provider(), {'a1': 'i1', 'a2': 'i2'}) self.assertEqual(provider(), {'a1': 'i1', 'a2': 'i2'})
def test_add_kwargs(self):
provider = providers.Dict() \
.add_kwargs(a1='i1') \
.add_kwargs(a2='i2')
self.assertEqual(provider.kwargs, {'a1': 'i1', 'a2': 'i2'})
def test_add_kwargs_non_string_keys(self):
a1 = object()
a2 = object()
provider = providers.Dict() \
.add_kwargs({a1: 'i1'}) \
.add_kwargs({a2: 'i2'})
self.assertEqual(provider.kwargs, {a1: 'i1', a2: 'i2'})
def test_add_kwargs_string_and_non_string_keys(self):
a2 = object()
provider = providers.Dict() \
.add_kwargs(a1='i1') \
.add_kwargs({a2: 'i2'})
self.assertEqual(provider.kwargs, {'a1': 'i1', a2: 'i2'})
def test_set_kwargs(self): def test_set_kwargs(self):
provider = providers.Dict() \ provider = providers.Dict() \
.add_kwargs(a1='i1', a2='i2') \ .add_kwargs(a1='i1', a2='i2') \
.set_kwargs(a3='i3', a4='i4') .set_kwargs(a3='i3', a4='i4')
self.assertEqual(provider.kwargs, {'a3': 'i3', 'a4': 'i4'}) self.assertEqual(provider.kwargs, {'a3': 'i3', 'a4': 'i4'})
def test_set_kwargs_non_string_keys(self):
a3 = object()
a4 = object()
provider = providers.Dict() \
.add_kwargs(a1='i1', a2='i2') \
.set_kwargs({a3: 'i3', a4: 'i4'})
self.assertEqual(provider.kwargs, {a3: 'i3', a4: 'i4'})
def test_set_kwargs_string_and_non_string_keys(self):
a3 = object()
provider = providers.Dict() \
.add_kwargs(a1='i1', a2='i2') \
.set_kwargs({a3: 'i3'}, a4='i4')
self.assertEqual(provider.kwargs, {a3: 'i3', 'a4': 'i4'})
def test_clear_kwargs(self): def test_clear_kwargs(self):
provider = providers.Dict() \ provider = providers.Dict() \
.add_kwargs(a1='i1', a2='i2') \ .add_kwargs(a1='i1', a2='i2') \