fix: inspect union arguments for annotations (#195)

NoInject[T] = None has the runtime typehint NoInject[T] | None,
instead of the expected NoInject[T | None].
NoInject[str] = 'blarb' works as expected

Resolves #192
This commit is contained in:
Tobias Nilsson 2022-06-15 01:01:32 +02:00 committed by GitHub
parent 92212fe08b
commit ce957ab42a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 2 deletions

View File

@ -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

View File

@ -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)