diff --git a/injector/__init__.py b/injector/__init__.py index 0e79b22..731c1c1 100644 --- a/injector/__init__.py +++ b/injector/__init__.py @@ -1190,7 +1190,20 @@ def _infer_injected_bindings(callable: Callable, only_explicit_bindings: bool) - # mypy complains about this construct: # error: The type alias is invalid in runtime context # See: https://github.com/python/mypy/issues/5354 - bindings[k] = new_union # type: ignore + union_metadata = { + metadata + for member in new_members + for metadata in getattr(member, '__metadata__', tuple()) + if _is_specialization(member, Annotated) + } + if ( + only_explicit_bindings + and _inject_marker not in union_metadata + or _noinject_marker in union_metadata + ): + del bindings[k] + else: + bindings[k] = new_union # type: ignore return bindings diff --git a/injector_test.py b/injector_test.py index 9e3a601..76e9bd2 100644 --- a/injector_test.py +++ b/injector_test.py @@ -11,7 +11,7 @@ """Functional tests for the "Injector" dependency injection framework.""" from contextlib import contextmanager -from typing import Any, NewType +from typing import Any, NewType, Optional import abc import sys import threading @@ -1481,3 +1481,16 @@ def test_get_bindings(): pass assert get_bindings(function8) == {} + + # Default arguments to NoInject annotations should behave the same as noninjectable decorator w.r.t 'None' + @inject + @noninjectable('b') + def function9(self, a: int, b: Optional[str] = None): + pass + + @inject + def function10(self, a: int, b: NoInject[Optional[str]] = None): + # b:s type is Union[NoInject[Union[str, None]], None] + pass + + assert get_bindings(function9) == {'a': int} == get_bindings(function10)