Skip to content

Commit f6277d1

Browse files
authored
Merge pull request #307 from python-injector/covariant-type
Use covariant types for multibind collections/mappings
2 parents 602caec + 1589f3f commit f6277d1

2 files changed

Lines changed: 13 additions & 5 deletions

File tree

injector/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@
2727
TYPE_CHECKING,
2828
Any,
2929
Callable,
30+
Collection,
3031
Dict,
3132
Generator,
3233
Generic,
3334
Iterable,
3435
List,
36+
Mapping,
3537
Optional,
3638
Set,
3739
Tuple,
@@ -387,7 +389,7 @@ def multibind(
387389
element_type = get_args(_punch_through_alias(interface))[0]
388390
except IndexError:
389391
raise InvalidInterface(f"Use typing.List[T] or list[T] to specify the element type of the list")
390-
if isinstance(to, list):
392+
if isinstance(to, Collection):
391393
for element in to:
392394
element_binding = self._binder.create_binding(element_type, element, scope)
393395
self.append(element_binding.provider, element_binding.scope)
@@ -415,7 +417,7 @@ def multibind(
415417
raise InvalidInterface(
416418
f"Use typing.Dict[K, V] or dict[K, V] to specify the value type of the dict"
417419
)
418-
if isinstance(to, dict):
420+
if isinstance(to, Mapping):
419421
for key, value in to.items():
420422
element_binding = self._binder.create_binding(value_type, value, scope)
421423
self.append(KeyValueProvider(key, element_binding.provider), element_binding.scope)
@@ -544,7 +546,7 @@ def bind(
544546
def multibind(
545547
self,
546548
interface: Type[List[T]],
547-
to: Union[List[Union[T, Type[T]]], Callable[..., List[T]], Provider[List[T]], Type[T]],
549+
to: Union[Collection[Union[T, Type[T]]], Callable[..., List[T]], Provider[List[T]], Type[T]],
548550
scope: Union[Type['Scope'], 'ScopeDecorator', None] = None,
549551
) -> None: # pragma: no cover
550552
pass
@@ -553,7 +555,7 @@ def multibind(
553555
def multibind(
554556
self,
555557
interface: Type[Dict[K, V]],
556-
to: Union[Dict[K, Union[V, Type[V]]], Callable[..., Dict[K, V]], Provider[Dict[K, V]]],
558+
to: Union[Mapping[K, Union[V, Type[V]]], Callable[..., Dict[K, V]], Provider[Dict[K, V]]],
557559
scope: Union[Type['Scope'], 'ScopeDecorator', None] = None,
558560
) -> None: # pragma: no cover
559561
pass

injector_test.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,19 +733,25 @@ class PluginD(Plugin):
733733
pass
734734

735735

736+
class PluginE(Plugin):
737+
pass
738+
739+
736740
def test_multibind_list_of_plugins():
737741
def configure(binder: Binder):
738742
binder.multibind(List[Plugin], to=PluginA)
739743
binder.multibind(List[Plugin], to=[PluginB, PluginC()])
740744
binder.multibind(List[Plugin], to=lambda: [PluginD()])
745+
binder.multibind(List[Plugin], to=(PluginE,))
741746

742747
injector = Injector([configure])
743748
plugins = injector.get(List[Plugin])
744-
assert len(plugins) == 4
749+
assert len(plugins) == 5
745750
assert isinstance(plugins[0], PluginA)
746751
assert isinstance(plugins[1], PluginB)
747752
assert isinstance(plugins[2], PluginC)
748753
assert isinstance(plugins[3], PluginD)
754+
assert isinstance(plugins[4], PluginE)
749755

750756

751757
def test_multibind_dict_of_plugins():

0 commit comments

Comments
 (0)