forked from orbit-oss/flask
Alter ensure_sync implementation to support extensions
This allows extensions to override the Flask.ensure_sync method and have the change apply to blueprints as well. Without this change it is possible for differing blueprints to have differing ensure_sync approaches depending on the extension used - which would likely result in event-loop blocking issues. This also allows blueprints to have a custom ensure_sync, although this is a by product rather than an expected use case.
This commit is contained in:
parent
c6c6408c3f
commit
00f5a3e55c
5 changed files with 169 additions and 32 deletions
|
|
@ -3,12 +3,20 @@ import sys
|
|||
|
||||
import pytest
|
||||
|
||||
from flask import abort
|
||||
from flask import Blueprint
|
||||
from flask import Flask
|
||||
from flask import request
|
||||
from flask.helpers import run_async
|
||||
|
||||
|
||||
class AppError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class BlueprintError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
@pytest.fixture(name="async_app")
|
||||
def _async_app():
|
||||
app = Flask(__name__)
|
||||
|
|
@ -18,24 +26,111 @@ def _async_app():
|
|||
await asyncio.sleep(0)
|
||||
return request.method
|
||||
|
||||
@app.errorhandler(AppError)
|
||||
async def handle(_):
|
||||
return "", 412
|
||||
|
||||
@app.route("/error")
|
||||
async def error():
|
||||
abort(412)
|
||||
raise AppError()
|
||||
|
||||
blueprint = Blueprint("bp", __name__)
|
||||
|
||||
@blueprint.route("/", methods=["GET", "POST"])
|
||||
async def bp_index():
|
||||
await asyncio.sleep(0)
|
||||
return request.method
|
||||
|
||||
@blueprint.errorhandler(BlueprintError)
|
||||
async def bp_handle(_):
|
||||
return "", 412
|
||||
|
||||
@blueprint.route("/error")
|
||||
async def bp_error():
|
||||
raise BlueprintError()
|
||||
|
||||
app.register_blueprint(blueprint, url_prefix="/bp")
|
||||
|
||||
return app
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 7), reason="requires Python >= 3.7")
|
||||
def test_async_request_context(async_app):
|
||||
@pytest.mark.parametrize("path", ["/", "/bp/"])
|
||||
def test_async_route(path, async_app):
|
||||
test_client = async_app.test_client()
|
||||
response = test_client.get("/")
|
||||
response = test_client.get(path)
|
||||
assert b"GET" in response.get_data()
|
||||
response = test_client.post("/")
|
||||
response = test_client.post(path)
|
||||
assert b"POST" in response.get_data()
|
||||
response = test_client.get("/error")
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 7), reason="requires Python >= 3.7")
|
||||
@pytest.mark.parametrize("path", ["/error", "/bp/error"])
|
||||
def test_async_error_handler(path, async_app):
|
||||
test_client = async_app.test_client()
|
||||
response = test_client.get(path)
|
||||
assert response.status_code == 412
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 7), reason="requires Python >= 3.7")
|
||||
def test_async_before_after_request():
|
||||
app_first_called = False
|
||||
app_before_called = False
|
||||
app_after_called = False
|
||||
bp_before_called = False
|
||||
bp_after_called = False
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
return ""
|
||||
|
||||
@app.before_first_request
|
||||
async def before_first():
|
||||
nonlocal app_first_called
|
||||
app_first_called = True
|
||||
|
||||
@app.before_request
|
||||
async def before():
|
||||
nonlocal app_before_called
|
||||
app_before_called = True
|
||||
|
||||
@app.after_request
|
||||
async def after(response):
|
||||
nonlocal app_after_called
|
||||
app_after_called = True
|
||||
return response
|
||||
|
||||
blueprint = Blueprint("bp", __name__)
|
||||
|
||||
@blueprint.route("/")
|
||||
def bp_index():
|
||||
return ""
|
||||
|
||||
@blueprint.before_request
|
||||
async def bp_before():
|
||||
nonlocal bp_before_called
|
||||
bp_before_called = True
|
||||
|
||||
@blueprint.after_request
|
||||
async def bp_after(response):
|
||||
nonlocal bp_after_called
|
||||
bp_after_called = True
|
||||
return response
|
||||
|
||||
app.register_blueprint(blueprint, url_prefix="/bp")
|
||||
|
||||
test_client = app.test_client()
|
||||
test_client.get("/")
|
||||
assert app_first_called
|
||||
assert app_before_called
|
||||
assert app_after_called
|
||||
test_client.get("/bp/")
|
||||
assert bp_before_called
|
||||
assert bp_after_called
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info >= (3, 7), reason="should only raise Python < 3.7")
|
||||
def test_async_runtime_error():
|
||||
with pytest.raises(RuntimeError):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue