| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  | import asyncio | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import pytest | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-25 04:47:55 +08:00
										 |  |  | from flask import Blueprint | 
					
						
							| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  | from flask import Flask | 
					
						
							|  |  |  | from flask import request | 
					
						
							| 
									
										
										
										
											2021-05-28 07:01:48 +08:00
										 |  |  | from flask.views import MethodView | 
					
						
							|  |  |  | from flask.views import View | 
					
						
							| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-07 06:31:16 +08:00
										 |  |  | pytest.importorskip("asgiref") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-25 04:47:55 +08:00
										 |  |  | class AppError(Exception): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BlueprintError(Exception): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 07:01:48 +08:00
										 |  |  | class AsyncView(View): | 
					
						
							|  |  |  |     methods = ["GET", "POST"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def dispatch_request(self): | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         return request.method | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class AsyncMethodView(MethodView): | 
					
						
							|  |  |  |     async def get(self): | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2021-06-02 01:56:33 +08:00
										 |  |  |         return "GET" | 
					
						
							| 
									
										
										
										
											2021-05-28 07:01:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     async def post(self): | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2021-06-02 01:56:33 +08:00
										 |  |  |         return "POST" | 
					
						
							| 
									
										
										
										
											2021-05-28 07:01:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  | @pytest.fixture(name="async_app") | 
					
						
							|  |  |  | def _async_app(): | 
					
						
							|  |  |  |     app = Flask(__name__) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @app.route("/", methods=["GET", "POST"]) | 
					
						
							| 
									
										
										
										
											2021-04-16 19:34:51 +08:00
										 |  |  |     @app.route("/home", methods=["GET", "POST"]) | 
					
						
							| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  |     async def index(): | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         return request.method | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-25 04:47:55 +08:00
										 |  |  |     @app.errorhandler(AppError) | 
					
						
							|  |  |  |     async def handle(_): | 
					
						
							|  |  |  |         return "", 412 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  |     @app.route("/error") | 
					
						
							|  |  |  |     async def error(): | 
					
						
							| 
									
										
										
										
											2021-03-25 04:47:55 +08:00
										 |  |  |         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") | 
					
						
							| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-02 01:56:33 +08:00
										 |  |  |     app.add_url_rule("/view", view_func=AsyncView.as_view("view")) | 
					
						
							|  |  |  |     app.add_url_rule("/methodview", view_func=AsyncMethodView.as_view("methodview")) | 
					
						
							| 
									
										
										
										
											2021-05-28 07:01:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  |     return app | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 07:01:48 +08:00
										 |  |  | @pytest.mark.parametrize("path", ["/", "/home", "/bp/", "/view", "/methodview"]) | 
					
						
							| 
									
										
										
										
											2021-03-25 04:47:55 +08:00
										 |  |  | def test_async_route(path, async_app): | 
					
						
							| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  |     test_client = async_app.test_client() | 
					
						
							| 
									
										
										
										
											2021-03-25 04:47:55 +08:00
										 |  |  |     response = test_client.get(path) | 
					
						
							| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  |     assert b"GET" in response.get_data() | 
					
						
							| 
									
										
										
										
											2021-03-25 04:47:55 +08:00
										 |  |  |     response = test_client.post(path) | 
					
						
							| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  |     assert b"POST" in response.get_data() | 
					
						
							| 
									
										
										
										
											2021-03-25 04:47:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @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) | 
					
						
							| 
									
										
										
										
											2020-07-07 03:54:26 +08:00
										 |  |  |     assert response.status_code == 412 | 
					
						
							| 
									
										
										
										
											2021-02-11 05:14:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-25 04:47:55 +08:00
										 |  |  | def test_async_before_after_request(): | 
					
						
							|  |  |  |     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_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_before_called | 
					
						
							|  |  |  |     assert app_after_called | 
					
						
							|  |  |  |     test_client.get("/bp/") | 
					
						
							|  |  |  |     assert bp_before_called | 
					
						
							|  |  |  |     assert bp_after_called |