Skip to content

Conversation

eirikur-nc
Copy link
Contributor

@eirikur-nc eirikur-nc commented Oct 12, 2025

What

Change how the scope argument of the multibind method works, so that it applies to the target rather than the containing list or dictionary. Also, consider explicit class bindings when resolving multibindings, and honor the scope of the class binding when the multibinding has no scope.

Why

So that it becomes possible to control the scope of individual multi-bindings. E.g.

def configure(binder: Binder) -> None:
    binder.multibind(List[Plugin], to=PluginA, scope=singleton)
    binder.multibind(List[Plugin], to=PluginB)

injector = Injector([configure])
first_list = injector.get(List[Plugin])
second_list = injector.get(List[Plugin])

assert first_list is not second_list
assert first_list[0] is second_list[0]
assert first_list[1] is not second_list[1]

Closes #283

Copy link

codecov bot commented Oct 12, 2025

Codecov Report

❌ Patch coverage is 98.14815% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 95.98%. Comparing base (5a30e9a) to head (9faa32a).

Files with missing lines Patch % Lines
injector/__init__.py 98.14% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #284      +/-   ##
==========================================
+ Coverage   95.84%   95.98%   +0.13%     
==========================================
  Files           1        1              
  Lines         602      623      +21     
  Branches      103      106       +3     
==========================================
+ Hits          577      598      +21     
  Misses         19       19              
  Partials        6        6              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines -390 to +414
_BindingBase = namedtuple('_BindingBase', 'interface provider scope')
@dataclass
class _BindingBase:
interface: type
provider: Provider
scope: Type['Scope']
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to get more type-checking confidence in my work, I converted this named tuple to a dataclass.

Comment on lines +27 to +43
TYPE_CHECKING,
Any,
Callable,
cast,
Dict,
Generator,
Generic,
get_args,
Iterable,
List,
Optional,
overload,
Set,
Tuple,
Type,
TypeVar,
TYPE_CHECKING,
Union,
cast,
get_args,
overload,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imports got sorted when I ran black

Comment on lines -820 to +847
def get(self, unused_key: Type[T], provider: Provider[T]) -> Provider[T]:
def get(self, key: Type[T], provider: Provider[T]) -> Provider[T]:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drive-by: fix invalid override (keyword arguments must match that of the method being overridden).

Comment on lines +32 to 46
AssistedBuilder,
Binder,
CallError,
CircularDependency,
ClassAssistedBuilder,
ClassProvider,
Error,
Inject,
Injector,
InstanceProvider,
InvalidInterface,
Module,
NoInject,
ProviderOf,
Scope,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran black on this file as well, which caused the imports to be sorted

@eirikur-nc eirikur-nc marked this pull request as ready for review October 13, 2025 23:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support scopes for multibind types

1 participant