Skip to content

Commit d0b07ca

Browse files
author
Letsch22
committed
Add multibind class provider
1 parent 8122b89 commit d0b07ca

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ coverage.xml
1010
/dist/
1111
/injector.egg-info/
1212
/.coverage
13+
venv/

injector/__init__.py

+20
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,17 @@ def __repr__(self) -> str:
369369
return '%s(%r)' % (type(self).__name__, self._providers)
370370

371371

372+
@private
373+
class ClassListProvider(Provider[List[T]]):
374+
"""Provides a list of instances from a given class."""
375+
376+
def __init__(self, cls: Type[T]) -> None:
377+
self._cls = cls
378+
379+
def get(self, injector: 'Injector') -> List[T]:
380+
return [injector.create_object(self._cls)]
381+
382+
372383
class MultiBindProvider(ListOfProviders[List[T]]):
373384
"""Used by :meth:`Binder.multibind` to flatten results of providers that
374385
return sequences."""
@@ -377,6 +388,15 @@ def get(self, injector: 'Injector') -> List[T]:
377388
return [i for provider in self._providers for i in provider.get(injector)]
378389

379390

391+
class MultiBindClassProvider(MultiBindProvider):
392+
"""A provider for a list of classes from a list of class instances"""
393+
394+
def __init__(self, classes: List[Type[T]]) -> None:
395+
super().__init__()
396+
for cls in classes:
397+
self.append(ClassListProvider(cls))
398+
399+
380400
class MapBindProvider(ListOfProviders[Dict[str, T]]):
381401
"""A provider for map bindings."""
382402

injector_test.py

+13
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
Binder,
2727
CallError,
2828
Injector,
29+
MultiBindClassProvider,
2930
Scope,
3031
InstanceProvider,
3132
ClassProvider,
@@ -473,6 +474,14 @@ def provide_description(self, age: int, weight: float) -> str:
473474

474475

475476
def test_multibind():
477+
class A:
478+
def print(self) -> str:
479+
return 'A'
480+
481+
class B(A):
482+
def print(self) -> str:
483+
return 'B'
484+
476485
# First let's have some explicit multibindings
477486
def configure(binder):
478487
binder.multibind(List[str], to=['not a name'])
@@ -483,6 +492,8 @@ def configure(binder):
483492
# To see that NewTypes are treated distinctly
484493
binder.multibind(Names, to=['Bob'])
485494
binder.multibind(Passwords, to={'Bob': 'password1'})
495+
# To see that MultiBindClassProvider works for lists of types
496+
binder.multibind(List[A], to=MultiBindClassProvider([A, B]))
486497

487498
# Then @multiprovider-decorated Module methods
488499
class CustomModule(Module):
@@ -517,6 +528,8 @@ def provide_passwords(self) -> Passwords:
517528
assert injector.get(Dict[str, int]) == {'weight': 12, 'height': 33}
518529
assert injector.get(Names) == ['Bob', 'Alice', 'Clarice']
519530
assert injector.get(Passwords) == {'Bob': 'password1', 'Alice': 'aojrioeg3', 'Clarice': 'clarice30'}
531+
assert injector.get(List[A])[0].print() == 'A'
532+
assert injector.get(List[A])[1].print() == 'B'
520533

521534

522535
def test_regular_bind_and_provider_dont_work_with_multibind():

0 commit comments

Comments
 (0)