Skip to content

Nonresolvable Type Hint on Non-Injected Argument Causes Error #258

@macdjord

Description

@macdjord

Steps To Reproduce

test.py:

#!/usr/bin/env python3
import injector as _injector
import test2

@_injector.inject
@_injector.noninjectable('body')
def patch(body: test2.RecursiveDict) -> None:
    ...

injector = _injector.Injector()
injector.call_with_injection(patch, kwargs={"body": {}})

test2.py:

#!/usr/bin/env python3
import typing as _tp
RecursiveDict: _tp.TypeAlias = dict[str, _tp.Optional["RecursiveDict"]]

Run test.py

Expected Results

Call proceeds without error

Actual Results

Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/injector/__init__.py", line 1213, in _infer_injected_bindings
    bindings = get_type_hints(cast(Callable, _NoReturnAnnotationProxy(callable)), include_extras=True)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/typing.py", line 2342, in get_type_hints
    hints[name] = _eval_type(value, globalns, localns)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/typing.py", line 373, in _eval_type
    ev_args = tuple(_eval_type(a, globalns, localns, recursive_guard) for a in t.__args__)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/typing.py", line 373, in <genexpr>
    ev_args = tuple(_eval_type(a, globalns, localns, recursive_guard) for a in t.__args__)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/typing.py", line 373, in _eval_type
    ev_args = tuple(_eval_type(a, globalns, localns, recursive_guard) for a in t.__args__)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/typing.py", line 373, in <genexpr>
    ev_args = tuple(_eval_type(a, globalns, localns, recursive_guard) for a in t.__args__)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/typing.py", line 359, in _eval_type
    return t._evaluate(globalns, localns, recursive_guard)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/typing.py", line 857, in _evaluate
    eval(self.__forward_code__, globalns, localns),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<string>", line 1, in <module>
NameError: name 'RecursiveDict' is not defined

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/app/test.py", line 11, in <module>
    injector.call_with_injection(patch, kwargs={"body": {}})
  File "/usr/local/lib/python3.11/site-packages/injector/__init__.py", line 1020, in call_with_injection
    bindings = get_bindings(callable)
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/injector/__init__.py", line 1173, in get_bindings
    callable, _infer_injected_bindings(callable, only_explicit_bindings=look_for_explicit_bindings)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/injector/__init__.py", line 1215, in _infer_injected_bindings
    raise _BindingNotYetAvailable(e)
injector._BindingNotYetAvailable: name 'RecursiveDict' is not defined

Notes

The error raised in get_type_hints() is not Injector's fault; that is a bug in Python itself. However, the fact that Injector fails due to an issue with the type hint of a parameter I explicitly told it not to even try to inject is an Injector issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions