RFC/1684 Context objects (#2063)
* Initial setup * connection context * Add tests * move ctx to conn_info * Move __setattr__ for __fake_slots__ check into base calss
This commit is contained in:
@@ -386,3 +386,22 @@ def test_app_no_registry_env():
|
||||
):
|
||||
Sanic.get_app("no-register")
|
||||
del environ["SANIC_REGISTER"]
|
||||
|
||||
|
||||
def test_app_set_attribute_warning(app):
|
||||
with pytest.warns(UserWarning) as record:
|
||||
app.foo = 1
|
||||
|
||||
assert len(record) == 1
|
||||
assert record[0].message.args[0] == (
|
||||
"Setting variables on Sanic instances is deprecated "
|
||||
"and will be removed in version 21.9. You should change your "
|
||||
"Sanic instance to use instance.ctx.foo instead."
|
||||
)
|
||||
|
||||
|
||||
def test_app_set_context(app):
|
||||
app.ctx.foo = 1
|
||||
|
||||
retrieved = Sanic.get_app(app.name)
|
||||
assert retrieved.ctx.foo == 1
|
||||
|
||||
@@ -1024,3 +1024,16 @@ def test_blueprint_registered_multiple_apps():
|
||||
for app in (app1, app2):
|
||||
_, response = app.test_client.get("/")
|
||||
assert response.text == f"{app.name}.bp.handler"
|
||||
|
||||
|
||||
def test_bp_set_attribute_warning():
|
||||
bp = Blueprint("bp")
|
||||
with pytest.warns(UserWarning) as record:
|
||||
bp.foo = 1
|
||||
|
||||
assert len(record) == 1
|
||||
assert record[0].message.args[0] == (
|
||||
"Setting variables on Blueprint instances is deprecated "
|
||||
"and will be removed in version 21.9. You should change your "
|
||||
"Blueprint instance to use instance.ctx.foo instead."
|
||||
)
|
||||
|
||||
@@ -19,10 +19,6 @@ CONFIG_FOR_TESTS = {"KEEP_ALIVE_TIMEOUT": 2, "KEEP_ALIVE": True}
|
||||
|
||||
PORT = 42101 # test_keep_alive_timeout_reuse doesn't work with random port
|
||||
|
||||
from httpcore._async.base import ConnectionState
|
||||
from httpcore._async.connection import AsyncHTTPConnection
|
||||
from httpcore._types import Origin
|
||||
|
||||
|
||||
class ReusableSanicConnectionPool(httpcore.AsyncConnectionPool):
|
||||
last_reused_connection = None
|
||||
@@ -185,10 +181,12 @@ class ReuseableSanicTestClient(SanicTestClient):
|
||||
keep_alive_timeout_app_reuse = Sanic("test_ka_timeout_reuse")
|
||||
keep_alive_app_client_timeout = Sanic("test_ka_client_timeout")
|
||||
keep_alive_app_server_timeout = Sanic("test_ka_server_timeout")
|
||||
keep_alive_app_context = Sanic("keep_alive_app_context")
|
||||
|
||||
keep_alive_timeout_app_reuse.config.update(CONFIG_FOR_TESTS)
|
||||
keep_alive_app_client_timeout.config.update(CONFIG_FOR_TESTS)
|
||||
keep_alive_app_server_timeout.config.update(CONFIG_FOR_TESTS)
|
||||
keep_alive_app_context.config.update(CONFIG_FOR_TESTS)
|
||||
|
||||
|
||||
@keep_alive_timeout_app_reuse.route("/1")
|
||||
@@ -206,6 +204,17 @@ async def handler3(request):
|
||||
return text("OK")
|
||||
|
||||
|
||||
@keep_alive_app_context.post("/ctx")
|
||||
def set_ctx(request):
|
||||
request.conn_info.ctx.foo = "hello"
|
||||
return text("OK")
|
||||
|
||||
|
||||
@keep_alive_app_context.get("/ctx")
|
||||
def get_ctx(request):
|
||||
return text(request.conn_info.ctx.foo)
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
bool(environ.get("SANIC_NO_UVLOOP")) or OS_IS_WINDOWS,
|
||||
reason="Not testable with current client",
|
||||
@@ -243,14 +252,14 @@ def test_keep_alive_client_timeout():
|
||||
asyncio.set_event_loop(loop)
|
||||
client = ReuseableSanicTestClient(keep_alive_app_client_timeout, loop)
|
||||
headers = {"Connection": "keep-alive"}
|
||||
request, response = client.get(
|
||||
"/1", headers=headers, request_keepalive=1
|
||||
)
|
||||
_, response = client.get("/1", headers=headers, request_keepalive=1)
|
||||
|
||||
assert response.status == 200
|
||||
assert response.text == "OK"
|
||||
|
||||
loop.run_until_complete(aio_sleep(2))
|
||||
exception = None
|
||||
request, response = client.get("/1", request_keepalive=1)
|
||||
_, response = client.get("/1", request_keepalive=1)
|
||||
|
||||
assert ReusableSanicConnectionPool.last_reused_connection is None
|
||||
finally:
|
||||
client.kill_server()
|
||||
@@ -270,14 +279,38 @@ def test_keep_alive_server_timeout():
|
||||
asyncio.set_event_loop(loop)
|
||||
client = ReuseableSanicTestClient(keep_alive_app_server_timeout, loop)
|
||||
headers = {"Connection": "keep-alive"}
|
||||
request, response = client.get(
|
||||
"/1", headers=headers, request_keepalive=60
|
||||
)
|
||||
_, response = client.get("/1", headers=headers, request_keepalive=60)
|
||||
|
||||
assert response.status == 200
|
||||
assert response.text == "OK"
|
||||
|
||||
loop.run_until_complete(aio_sleep(3))
|
||||
exception = None
|
||||
request, response = client.get("/1", request_keepalive=60)
|
||||
_, response = client.get("/1", request_keepalive=60)
|
||||
|
||||
assert ReusableSanicConnectionPool.last_reused_connection is None
|
||||
finally:
|
||||
client.kill_server()
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
bool(environ.get("SANIC_NO_UVLOOP")) or OS_IS_WINDOWS,
|
||||
reason="Not testable with current client",
|
||||
)
|
||||
def test_keep_alive_connection_context():
|
||||
try:
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
client = ReuseableSanicTestClient(keep_alive_app_context, loop)
|
||||
headers = {"Connection": "keep-alive"}
|
||||
request1, _ = client.post("/ctx", headers=headers)
|
||||
|
||||
loop.run_until_complete(aio_sleep(1))
|
||||
request2, response = client.get("/ctx")
|
||||
|
||||
assert response.text == "hello"
|
||||
assert id(request1.conn_info.ctx) == id(request2.conn_info.ctx)
|
||||
assert (
|
||||
request1.conn_info.ctx.foo == request2.conn_info.ctx.foo == "hello"
|
||||
)
|
||||
finally:
|
||||
client.kill_server()
|
||||
|
||||
@@ -5,6 +5,7 @@ import pytest
|
||||
|
||||
from sanic import Sanic, response
|
||||
from sanic.request import Request, uuid
|
||||
from sanic.server import HttpProtocol
|
||||
|
||||
|
||||
def test_no_request_id_not_called(monkeypatch):
|
||||
@@ -83,3 +84,18 @@ def test_route_assigned_to_request(app):
|
||||
|
||||
request, _ = app.test_client.get("/")
|
||||
assert request.route is list(app.router.routes.values())[0]
|
||||
|
||||
|
||||
def test_protocol_attribute(app):
|
||||
retrieved = None
|
||||
|
||||
@app.get("/")
|
||||
async def get(request):
|
||||
nonlocal retrieved
|
||||
retrieved = request.protocol
|
||||
return response.empty()
|
||||
|
||||
headers = {"Connection": "keep-alive"}
|
||||
_ = app.test_client.get("/", headers=headers)
|
||||
|
||||
assert isinstance(retrieved, HttpProtocol)
|
||||
|
||||
Reference in New Issue
Block a user