Raise a runtime error if run_async is called without real ContextVars

Werkzeug offers a ContextVar replacement for Python < 3.7, however it
doesn't work across asyncio tasks, hence it makes sense to error out
rather than find there are odd bugs.

Note the docs build requires the latest (dev) Werkzeug due to this
change (to import ContextVar from werkzeug.local).
This commit is contained in:
pgjones 2021-02-10 21:14:58 +00:00 committed by David Lord
parent 6979265fa6
commit c6c6408c3f
No known key found for this signature in database
GPG key ID: 7A1C87E3F5BC42A8
3 changed files with 19 additions and 1 deletions

View file

@ -7,6 +7,7 @@ from threading import RLock
import werkzeug.utils
from werkzeug.exceptions import NotFound
from werkzeug.local import ContextVar
from werkzeug.routing import BuildError
from werkzeug.urls import url_quote
@ -741,6 +742,11 @@ def run_async(func):
"Install Flask with the 'async' extra in order to use async views."
)
if ContextVar.__module__ == "werkzeug.local":
raise RuntimeError(
"async cannot be used with this combination of Python & Greenlet versions"
)
@wraps(func)
def outer(*args, **kwargs):
"""This function grabs the current context for the inner function.

View file

@ -1,10 +1,12 @@
import asyncio
import sys
import pytest
from flask import abort
from flask import Flask
from flask import request
from flask.helpers import run_async
@pytest.fixture(name="async_app")
@ -23,6 +25,7 @@ def _async_app():
return app
@pytest.mark.skipif(sys.version_info < (3, 7), reason="requires Python >= 3.7")
def test_async_request_context(async_app):
test_client = async_app.test_client()
response = test_client.get("/")
@ -31,3 +34,9 @@ def test_async_request_context(async_app):
assert b"POST" in response.get_data()
response = test_client.get("/error")
assert response.status_code == 412
@pytest.mark.skipif(sys.version_info >= (3, 7), reason="should only raise Python < 3.7")
def test_async_runtime_error():
with pytest.raises(RuntimeError):
run_async(None)

View file

@ -25,5 +25,8 @@ skip_install = true
commands = pre-commit run --all-files --show-diff-on-failure
[testenv:docs]
deps = -r requirements/docs.txt
deps =
-r requirements/docs.txt
https://github.com/pallets/werkzeug/archive/master.tar.gz
commands = sphinx-build -W -b html -d {envtmpdir}/doctrees docs {envtmpdir}/html