8000 name 'Response' is not defined · Issue #69 · python-injector/flask_injector · GitHub
[go: up one dir, main page]

Skip to content

name 'Response' is not defined #69

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
FabienArcellier opened this issue Sep 9, 2021 · 7 comments · Fixed by #71, python-injector/injector#200 or #75
Closed

name 'Response' is not defined #69

FabienArcellier opened this issue Sep 9, 2021 · 7 comments · Fixed by #71, python-injector/injector#200 or #75

Comments

@FabienArcellier
Copy link
FabienArcellier commented Sep 9, 2021

On Flask 2, I get this error every time I run a query. I have solved the issue only changing the code of Flask-Injector but I am not confident with the impact of the change I have done.

This error is present when you run the unit test suite.
The fix I propose broke the test test_forward_references_work :(.

Version:

flask: 2.0.1
flask-injector: 0.13.0
flask-restx: 0.5.1
injector: 0.18.4
127.0.0.1 - - [09/Sep/2021 10:23:38] "GET /swaggerui/favicon-16x16.png HTTP/1.1" 500 -
Error on request:
Traceback (most recent call last):
  File "/home/project/.venv/lib/python3.8/site-packages/injector/__init__.py", line 1176, in _infer_injected_bindings
    bindings = get_type_hints(callable, include_extras=True)
  File "/home/project/.venv/lib/python3.8/site-packages/typing_extensions.py", line 1924, in get_type_hints
    hint = typing.get_type_hints(obj, globalns=globalns, localns=localns)
  File "/usr/lib/python3.8/typing.py", line 1264, in get_type_hints
    value = _eval_type(value, globalns, localns)
  File "/usr/lib/python3.8/typing.py", line 270, in _eval_type
    return t._evaluate(globalns, localns)
  File "/usr/lib/python3.8/typing.py", line 518, in _evaluate
    eval(self.__forward_code__, globalns, localns),
  File "<string>", line 1, in <module>
    import importlib.util
NameError: name 'Response' is not defined
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/home/project/.venv/lib/python3.8/site-packages/werkzeug/serving.py", line 319, in run_wsgi
    execute(self.server.app)
  File "/home/project/.venv/lib/python3.8/site-packages/werkzeug/serving.py", line 308, in execute
    application_iter = app(environ, start_response)
  File "/home/project/.venv/lib/python3.8/site-packages/flask/app.py", line 2088, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/project/.venv/lib/python3.8/site-packages/flask/app.py", line 2073, in wsgi_app
    response = self.handle_exception(e)
  File "/home/project/.venv/lib/python3.8/site-packages/flask_restx/api.py", line 672, in error_router
    return original_handler(e)
  File "/home/project/.venv/lib/python3.8/site-packages/flask/app.py", line 2070, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/project/.venv/lib/python3.8/site-packages/flask/app.py", line 1515, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/project/.venv/lib/python3.8/site-packages/flask_restx/api.py", line 672, in error_router
    return original_handler(e)
  File "/home/project/.venv/lib/python3.8/site-packages/flask/app.py", line 1513, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/project/.venv/lib/python3.8/site-packages/flask/app.py", line 1499, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "/home/project/.venv/lib/python3.8/site-packages/flask_injector/__init__.py", line 89, in wrapper
    return injector.call_with_injection(callable=fun, args=args, kwargs=kwargs)
  File "/home/project/.venv/lib/python3.8/site-packages/injector/__init__.py", line 1010, in call_with_injection
    bindings = get_bindings(callable)
  File "/home/project/.venv/lib/python3.8/site-packages/injector/__init__.py", line 1163, in get_bindings
    callable, _infer_injected_bindings(callable, only_explicit_bindings=look_for_explicit_bindings)
  File "/home/project/.venv/lib/python3.8/site-packages/injector/__init__.py", line 1178, in _infer_injected_bindings
    raise _BindingNotYetAvailable(e)

I track the root cause in wrap_fun that is supposed to managed this sort of error. On Flask,

  if hasattr(fun, '__call__') and not isinstance(fun, type):
      try:
          type_hints = get_type_hints(fun)
      except (AttributeError, TypeError):
          # Some callables aren't introspectable with get_type_hints,
          # let's assume they don't have anything to inject. The exception
          # types handled here are what I encountered so far.
          # It used to be AttributeError, then https://github.com/python/typing/pull/314
          # changed it to TypeError.
          wrap_it = False
      except NameError:
          wrap_it = True

On Flask, the error is due to the usage of typehint with in flask/scaffold.py

if t.TYPE_CHECKING:
    from .wrappers import Response

[...]
    def send_static_file(self, filename: str) -> "Response":

The function get_type_hints raise a NameError exception in this context.

Proposition of fix

I suppose the existance of NameError has a reason but moving it in Non wrapping condition solve the issue I have. I didn't find the reason of the existence of this condition.

  if hasattr(fun, '__call__') and not isinstance(fun, type):
      try:
          type_hints = get_type_hints(fun)
      except (AttributeError, TypeError, NameError):
          # Some callables aren't introspectable with get_type_hints,
          # let's assume they don't have anything to inject. The exception
          # types handled here are what I encountered so far.
          # It used to be AttributeError, then https://github.com/python/typing/pull/314
          # changed it to TypeError.
          wrap_it = False

More information

the issue with get_type_hints and Forward Ref

@zhangcheng
Copy link
Contributor

At current release tag of v0.13.0, make test has 4 test cases failed with this exception.

% make test
nosetests -v flask_injector \
		--with-coverage --cover-package=flask_injector --cover-html --cover-branches --cover-xml
flask_injector.tests.test_injections ... FAIL
flask_injector.tests.test_resets ... ok
flask_injector.tests.test_memory_leak ... ok
flask_injector.tests.test_doesnt_raise_deprecation_warning ... ok
flask_injector.tests.test_jinja_env_globals_support_injection ... ok
flask_injector.tests.test_error_handlers_support_injection ... ok
flask_injector.tests.test_view_functions_arent_modified_globally ... ok
flask_injector.tests.test_view_args_and_class_args_are_passed_to_class_based_views ... FAIL
flask_injector.tests.test_flask_restful_integration_works ... FAIL
flask_injector.tests.test_flask_restx_integration_works ... FAIL
flask_injector.tests.test_request_scope_not_started_before_any_request_made_regression ... ok
flask_injector.tests.test_noninstrospectable_hooks_dont_crash_everything ... ok
flask_injector.tests.test_instance_methods ... ok
flask_injector.tests.test_forward_references_work ... ok
flask_injector.tests.test_request_scope_covers_teardown_request_handlers ... ok
flask_injector.tests.test_request_scope_covers_blueprint_teardown_request_handlers ... ok

Exception stack trace such as:

-------------------- >> begin captured logging << --------------------
flask_injector.tests: ERROR: Exception on /view2 [GET]
Traceback (most recent call last):
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/injector/__init__.py", line 1172, in _infer_injected_bindings
    bindings = get_type_hints(callable, include_extras=True)
  File "/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/typing.py", line 1496, in get_type_hints
    value = _eval_type(value, globalns, localns)
  File "/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/typing.py", line 294, in _eval_type
    ev_args = tuple(_eval_type(a, globalns, localns, recursive_guard) for a in t.__args__)
  File "/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/typing.py", line 294, in <genexpr>
    ev_args = tuple(_eval_type(a, globalns, localns, recursive_guard) for a in t.__args__)
  File "/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/typing.py", line 292, in _eval_type
    return t._evaluate(globalns, localns, recursive_guard)
  File "/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/typing.py", line 554, in _evaluate
    eval(self.__forward_code__, globalns, localns),
  File "<string>", line 1, in <module>
NameError: name 'Response' is not defined

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/flask/app.py", line 2073, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/flask/app.py", line 1518, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/flask/app.py", line 1516, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/flask/app.py", line 1502, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "/Users/czhang/workspace/vendor/flask_injector/flask_injector/__init__.py", line 89, in wrapper
    return injector.call_with_injection(callable=fun, args=args, kwargs=kwargs)
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/injector/__init__.py", line 1006, in call_with_injection
    bindings = get_bindings(callable)
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/injector/__init__.py", line 1159, in get_bindings
    callable, _infer_injected_bindings(callable, only_explicit_bindings=look_for_explicit_bindings)
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/injector/__init__.py", line 1174, in _infer_injected_bindings
    raise _BindingNotYetAvailable(e)
injector._BindingNotYetAvailable: name 'Response' is not defined
--------------------- >> end captured logging << ---------------------

Current state of dependencies (partial):

Flask==2.0.3
injector==0.19.0

@alecthomas would you please advise here?

zhangcheng added a commit to zhangcheng/flask_injector that referenced this issue Mar 5, 2022
zhangcheng added a commit to zhangcheng/flask_injector that referenced this issue Mar 5, 2022
@zhangcheng
Copy link
Contributor

The above PR #71 is the proposed fix from @FabienArcellier, and as he said, now only the case test_forward_references_work failed.
But I have no idea how to fix here, more wisdom is indeed very needed. 🥲

FAIL: flask_injector.tests.test_forward_references_work
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/nose/case.py", line 198, in runTest
    self.test(*self.arg)
  File "/Users/czhang/workspace/vendor/flask_injector/flask_injector/tests.py", line 412, in test_forward_references_work
    eq_(response.data.decode(), 'Hello World')
AssertionError: '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n<title>500 Internal Server Error</title>\n<h1>Internal Server Error</h1>\n<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>\n' != 'Hello World'
-------------------- >> begin captured logging << --------------------
flask_injector.tests: ERROR: Exception on / [GET]
Traceback (most recent call last):
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/flask/app.py", line 2073, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/flask/app.py", line 1518, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/flask/app.py", line 1516, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/czhang/workspace/vendor/flask_injector/ve3.9/lib/python3.9/site-packages/flask/app.py", line 1502, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
TypeError: index() missing 1 required positional argument: 'x'
--------------------- >> end captured logging << ---------------------

@wgebis
Copy link
wgebis commented Apr 19, 2022

Any updates here? I'm facing he same issue, hot from @FabienArcellier works for me. Anyone know what about the failing tests?

@rshah88
Copy link
rshah88 commented Apr 19, 2022

Hitting same issue when upgrading to Flask 2.x, any workarounds available ?

@wgebis
Copy link
wgebis commented Apr 20, 2022

@rshah88 I forked fix from PR and now flask_injector is a part of source code of my project - it's only one file, easy to embed. It's not elegant ;) but in the meantime it's good enough.

@acamu
Copy link
acamu commented May 13, 2022

Hi all,
Same issue for me. If a contributor can look the issue, it will be appreciated :)

alecthomas pushed a commit that referenced this issue May 31, 2022
jstasiak added a commit to python-injector/injector that referenced this issue Jun 14, 2022
Seems like something that's good to have anyway but the main purpose is
to fix python-injector/flask_injector#69.
jstasiak added a commit to python-injector/injector that referenced this issue Jun 14, 2022
Seems like something that's good to have anyway but the main purpose is
to fix python-injector/flask_injector#69.
jstasiak added a commit that referenced this issue Jun 15, 2022
Thanks to injector 0.20.0 invalid forward references in return type
annotation positions no longer break injection/detecting dependencies
(which is what GH-69 is actually about).

This PR fixes #69

This PR also effectively reverts [1] as [1] was breaking forward
reference support.

One more thing being fixed here is class-based view failures
that started happening for some reason, reordering some internal
logic handles that (we prioritize treating views as class-based views
and all is well).

[1] Fixes: 4d8bfe8 ("(wip) fix: name 'Response' is not defined")
@jstasiak
Copy link
Collaborator

This is finally resolved in Flask-Injector 0.14.0 (fingers crossed). Warning: there are hard requirements for the latest Flask and Injector involved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
0