Skip to content

Commit

Permalink
fix: inspect union arguments for annotations (#195)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
tobni committed Jun 14, 2022
1 parent 92212fe commit ce957ab
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
15 changes: 14 additions & 1 deletion injector/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
15 changes: 14 additions & 1 deletion injector_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1481,3 +1481,16 @@ def function8(a: NoInject[int], b: NoInject[int]) -> None:
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)

0 comments on commit ce957ab

Please sign in to comment.