-
-
Notifications
You must be signed in to change notification settings - Fork 16.5k
Closed
Description
Consider this trivial route + test in app.py
:
import flask
from flask import Flask
from flask import Response
import pytest
app = Flask(__name__)
@app.route("/foo")
async def foo():
def gen():
yield "bar"
return Response(flask.stream_with_context(gen()))
def test_foo():
with app.test_client() as client:
client.get("/foo")
With the following requirements.txt
:
flask[async]==3.1.1
pytest==8.4.1
werkzeug==3.1.3
Running pytest app.py
results in:
============================= test session starts ==============================
platform darwin -- Python 3.12.11, pytest-8.4.1, pluggy-1.6.0
rootdir: /private/tmp/stream_with_context
collected 1 item
app.py F [100%]
=================================== FAILURES ===================================
___________________________________ test_foo ___________________________________
def test_foo():
with app.test_client() as client:
> client.get("/foo")
app.py:20:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.12/site-packages/werkzeug/test.py:1162: in get
return self.open(*args, **kw)
^^^^^^^^^^^^^^^^^^^^^^
venv/lib/python3.12/site-packages/flask/testing.py:235: in open
response = super().open(
venv/lib/python3.12/site-packages/werkzeug/test.py:1116: in open
response_parts = self.run_wsgi_app(request.environ, buffered=buffered)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
venv/lib/python3.12/site-packages/werkzeug/test.py:988: in run_wsgi_app
rv = run_wsgi_app(self.application, environ, buffered=buffered)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
venv/lib/python3.12/site-packages/werkzeug/test.py:1264: in run_wsgi_app
app_rv = app(environ, start_response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
venv/lib/python3.12/site-packages/flask/app.py:1536: in __call__
return self.wsgi_app(environ, start_response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
venv/lib/python3.12/site-packages/flask/app.py:1527: in wsgi_app
ctx.pop(error)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <RequestContext 'http://localhost/foo' [GET] of app>, exc = None
def pop(self, exc: BaseException | None = _sentinel) -> None: # type: ignore
"""Pops the request context and unbinds it by doing that. This will
also trigger the execution of functions registered by the
:meth:`~flask.Flask.teardown_request` decorator.
.. versionchanged:: 0.9
Added the `exc` argument.
"""
clear_request = len(self._cv_tokens) == 1
try:
if clear_request:
if exc is _sentinel:
exc = sys.exc_info()[1]
self.app.do_teardown_request(exc)
request_close = getattr(self.request, "close", None)
if request_close is not None:
request_close()
finally:
ctx = _cv_request.get()
token, app_ctx = self._cv_tokens.pop()
> _cv_request.reset(token)
E ValueError: <Token var=<ContextVar name='flask.request_ctx' at 0x103cd9a30> at 0x104b23a40> was created in a different Context
venv/lib/python3.12/site-packages/flask/ctx.py:418: ValueError
=========================== short test summary info ============================
FAILED app.py::test_foo - ValueError: <Token var=<ContextVar name='flask.request_ctx' at 0x103cd9a30>...
============================== 1 failed in 0.11s ===============================
Similarly, python -m flask run
and then curl http://127.0.0.1:5000/foo
results in:
127.0.0.1 - - [15/Jul/2025 13:40:14] "GET /foo HTTP/1.1" 500 -
Error on request:
Traceback (most recent call last):
File "/private/tmp/stream_with_context/venv/lib/python3.12/site-packages/werkzeug/serving.py", line 370, in run_wsgi
execute(self.server.app)
File "/private/tmp/stream_with_context/venv/lib/python3.12/site-packages/werkzeug/serving.py", line 331, in execute
application_iter = app(environ, start_response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/private/tmp/stream_with_context/venv/lib/python3.12/site-packages/flask/app.py", line 1536, in __call__
return self.wsgi_app(environ, start_response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/private/tmp/stream_with_context/venv/lib/python3.12/site-packages/flask/app.py", line 1527, in wsgi_app
ctx.pop(error)
File "/private/tmp/stream_with_context/venv/lib/python3.12/site-packages/flask/ctx.py", line 418, in pop
_cv_request.reset(token)
ValueError: <Token var=<ContextVar name='flask.request_ctx' at 0x1029ccea0> at 0x1049e1980> was created in a different Context
If the route is defined def foo():
without async
, then this works without issue.
Or if we remove stream_with_context
and just return Response(gen())
, also works.
But the combination of async
+ stream_with_context
fails.
There's also no issue with e.g. flask 2.1.0; I believe this was introduced in flask 2.2.0, specifically by #4682.
Environment:
- Python version: 3.12.11
- Flask version: 3.1.1