LTS v21.12 Deprecations (#2306)
Co-authored-by: Néstor Pérez <25409753+prryplatypus@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
from sanic import Sanic, text
|
||||
from sanic.log import LOGGING_CONFIG_DEFAULTS, logger
|
||||
@@ -9,7 +8,7 @@ LOGGING_CONFIG = {**LOGGING_CONFIG_DEFAULTS}
|
||||
LOGGING_CONFIG["formatters"]["generic"]["format"] = "%(message)s"
|
||||
LOGGING_CONFIG["loggers"]["sanic.root"]["level"] = "DEBUG"
|
||||
|
||||
app = Sanic(__name__, log_config=LOGGING_CONFIG)
|
||||
app = Sanic("FakeServer", log_config=LOGGING_CONFIG)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
|
||||
@@ -8,14 +8,15 @@ from os import environ
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
import sanic
|
||||
|
||||
from sanic import Sanic
|
||||
from sanic.compat import OS_IS_WINDOWS, UVLOOP_INSTALLED
|
||||
from sanic.compat import OS_IS_WINDOWS
|
||||
from sanic.config import Config
|
||||
from sanic.exceptions import SanicException
|
||||
from sanic.response import text
|
||||
from sanic.helpers import _default
|
||||
from sanic.response import text
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@@ -392,6 +393,22 @@ def test_app_no_registry():
|
||||
Sanic.get_app("no-register")
|
||||
|
||||
|
||||
def test_app_no_registry_deprecation_message():
|
||||
with pytest.warns(DeprecationWarning) as records:
|
||||
Sanic("no-register", register=False)
|
||||
Sanic("yes-register", register=True)
|
||||
|
||||
message = (
|
||||
"[DEPRECATION v22.6] The register argument is deprecated and will "
|
||||
"stop working in v22.6. After v22.6 all apps will be added to the "
|
||||
"Sanic app registry."
|
||||
)
|
||||
|
||||
assert len(records) == 2
|
||||
for record in records:
|
||||
assert record.message.args[0] == message
|
||||
|
||||
|
||||
def test_app_no_registry_env():
|
||||
environ["SANIC_REGISTER"] = "False"
|
||||
Sanic("no-register")
|
||||
@@ -403,15 +420,12 @@ def test_app_no_registry_env():
|
||||
|
||||
|
||||
def test_app_set_attribute_warning(app):
|
||||
with pytest.warns(DeprecationWarning) 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.12. You should change your "
|
||||
"Sanic instance to use instance.ctx.foo instead."
|
||||
message = (
|
||||
"Setting variables on Sanic instances is not allowed. You should "
|
||||
"change your Sanic instance to use instance.ctx.foo instead."
|
||||
)
|
||||
with pytest.raises(AttributeError, match=message):
|
||||
app.foo = 1
|
||||
|
||||
|
||||
def test_app_set_context(app):
|
||||
@@ -433,15 +447,7 @@ def test_bad_custom_config():
|
||||
SanicException,
|
||||
match=(
|
||||
"When instantiating Sanic with config, you cannot also pass "
|
||||
"load_env or env_prefix"
|
||||
),
|
||||
):
|
||||
Sanic("test", config=1, load_env=1)
|
||||
with pytest.raises(
|
||||
SanicException,
|
||||
match=(
|
||||
"When instantiating Sanic with config, you cannot also pass "
|
||||
"load_env or env_prefix"
|
||||
"env_prefix"
|
||||
),
|
||||
):
|
||||
Sanic("test", config=1, env_prefix=1)
|
||||
@@ -494,11 +500,7 @@ def test_uvloop_config(app, monkeypatch):
|
||||
|
||||
|
||||
def test_uvloop_cannot_never_called_with_create_server(caplog, monkeypatch):
|
||||
apps = (
|
||||
Sanic("default-uvloop"),
|
||||
Sanic("no-uvloop"),
|
||||
Sanic("yes-uvloop")
|
||||
)
|
||||
apps = (Sanic("default-uvloop"), Sanic("no-uvloop"), Sanic("yes-uvloop"))
|
||||
|
||||
apps[1].config.USE_UVLOOP = False
|
||||
apps[2].config.USE_UVLOOP = True
|
||||
@@ -512,7 +514,7 @@ def test_uvloop_cannot_never_called_with_create_server(caplog, monkeypatch):
|
||||
for app in apps:
|
||||
srv_coro = app.create_server(
|
||||
return_asyncio_server=True,
|
||||
asyncio_server_kwargs=dict(start_serving=False)
|
||||
asyncio_server_kwargs=dict(start_serving=False),
|
||||
)
|
||||
loop.run_until_complete(srv_coro)
|
||||
|
||||
@@ -547,7 +549,7 @@ def test_multiple_uvloop_configs_display_warning(caplog):
|
||||
for app in (default_uvloop, no_uvloop, yes_uvloop):
|
||||
srv_coro = app.create_server(
|
||||
return_asyncio_server=True,
|
||||
asyncio_server_kwargs=dict(start_serving=False)
|
||||
asyncio_server_kwargs=dict(start_serving=False),
|
||||
)
|
||||
srv = loop.run_until_complete(srv_coro)
|
||||
loop.run_until_complete(srv.startup())
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from sanic import Blueprint, Sanic
|
||||
from sanic.exceptions import SanicException
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -79,24 +80,18 @@ def test_names_okay(name):
|
||||
)
|
||||
def test_names_not_okay(name):
|
||||
app_message = (
|
||||
f"Sanic instance named '{name}' uses a format that isdeprecated. "
|
||||
"Starting in version 21.12, Sanic objects must be named only using "
|
||||
"alphanumeric characters, _, or -."
|
||||
f"Sanic instance named '{name}' uses an invalid format. Names must "
|
||||
"begin with a character and may only contain alphanumeric "
|
||||
"characters, _, or -."
|
||||
)
|
||||
bp_message = (
|
||||
f"Blueprint instance named '{name}' uses a format that isdeprecated. "
|
||||
"Starting in version 21.12, Blueprint objects must be named only using "
|
||||
"alphanumeric characters, _, or -."
|
||||
f"Blueprint instance named '{name}' uses an invalid format. Names "
|
||||
"must begin with a character and may only contain alphanumeric "
|
||||
"characters, _, or -."
|
||||
)
|
||||
|
||||
with pytest.warns(DeprecationWarning) as app_e:
|
||||
app = Sanic(name)
|
||||
with pytest.raises(SanicException, match=app_message):
|
||||
Sanic(name)
|
||||
|
||||
with pytest.warns(DeprecationWarning) as bp_e:
|
||||
bp = Blueprint(name)
|
||||
|
||||
assert app.name == name
|
||||
assert bp.name == name
|
||||
|
||||
assert app_e[0].message.args[0] == app_message
|
||||
assert bp_e[0].message.args[0] == bp_message
|
||||
with pytest.raises(SanicException, match=bp_message):
|
||||
Blueprint(name)
|
||||
|
||||
@@ -15,7 +15,6 @@ from sanic.exceptions import (
|
||||
)
|
||||
from sanic.request import Request
|
||||
from sanic.response import json, text
|
||||
from sanic.views import CompositionView
|
||||
|
||||
|
||||
# ------------------------------------------------------------ #
|
||||
@@ -833,7 +832,7 @@ def test_static_blueprint_name(static_file_directory, file_name):
|
||||
|
||||
@pytest.mark.parametrize("file_name", ["test.file"])
|
||||
def test_static_blueprintp_mw(app: Sanic, static_file_directory, file_name):
|
||||
current_file = inspect.getfile(inspect.currentframe())
|
||||
current_file = inspect.getfile(inspect.currentframe()) # type: ignore
|
||||
with open(current_file, "rb") as file:
|
||||
file.read()
|
||||
|
||||
@@ -862,31 +861,6 @@ def test_static_blueprintp_mw(app: Sanic, static_file_directory, file_name):
|
||||
assert triggered is True
|
||||
|
||||
|
||||
def test_route_handler_add(app: Sanic):
|
||||
view = CompositionView()
|
||||
|
||||
async def get_handler(request):
|
||||
return json({"response": "OK"})
|
||||
|
||||
view.add(["GET"], get_handler, stream=False)
|
||||
|
||||
async def default_handler(request):
|
||||
return text("OK")
|
||||
|
||||
bp = Blueprint(name="handler", url_prefix="/handler")
|
||||
bp.add_route(default_handler, uri="/default/", strict_slashes=True)
|
||||
|
||||
bp.add_route(view, uri="/view", name="test")
|
||||
|
||||
app.blueprint(bp)
|
||||
|
||||
_, response = app.test_client.get("/handler/default/")
|
||||
assert response.text == "OK"
|
||||
|
||||
_, response = app.test_client.get("/handler/view")
|
||||
assert response.json["response"] == "OK"
|
||||
|
||||
|
||||
def test_websocket_route(app: Sanic):
|
||||
event = asyncio.Event()
|
||||
|
||||
@@ -1079,15 +1053,12 @@ def test_blueprint_registered_multiple_apps():
|
||||
|
||||
def test_bp_set_attribute_warning():
|
||||
bp = Blueprint("bp")
|
||||
with pytest.warns(DeprecationWarning) 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.12. You should change your "
|
||||
"Blueprint instance to use instance.ctx.foo instead."
|
||||
message = (
|
||||
"Setting variables on Blueprint instances is not allowed. You should "
|
||||
"change your Blueprint instance to use instance.ctx.foo instead."
|
||||
)
|
||||
with pytest.raises(AttributeError, match=message):
|
||||
bp.foo = 1
|
||||
|
||||
|
||||
def test_early_registration(app):
|
||||
|
||||
@@ -81,26 +81,6 @@ def test_auto_bool_env_prefix():
|
||||
del environ["SANIC_TEST_ANSWER"]
|
||||
|
||||
|
||||
def test_dont_load_env():
|
||||
environ["SANIC_TEST_ANSWER"] = "42"
|
||||
app = Sanic(name=__name__, load_env=False)
|
||||
assert getattr(app.config, "TEST_ANSWER", None) is None
|
||||
del environ["SANIC_TEST_ANSWER"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("load_env", [None, False, "", "MYAPP_"])
|
||||
def test_load_env_deprecation(load_env):
|
||||
with pytest.warns(DeprecationWarning, match=r"21\.12"):
|
||||
_ = Sanic(name=__name__, load_env=load_env)
|
||||
|
||||
|
||||
def test_load_env_prefix():
|
||||
environ["MYAPP_TEST_ANSWER"] = "42"
|
||||
app = Sanic(name=__name__, load_env="MYAPP_")
|
||||
assert app.config.TEST_ANSWER == 42
|
||||
del environ["MYAPP_TEST_ANSWER"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("env_prefix", [None, ""])
|
||||
def test_empty_load_env_prefix(env_prefix):
|
||||
environ["SANIC_TEST_ANSWER"] = "42"
|
||||
@@ -109,20 +89,6 @@ def test_empty_load_env_prefix(env_prefix):
|
||||
del environ["SANIC_TEST_ANSWER"]
|
||||
|
||||
|
||||
def test_load_env_prefix_float_values():
|
||||
environ["MYAPP_TEST_ROI"] = "2.3"
|
||||
app = Sanic(name=__name__, load_env="MYAPP_")
|
||||
assert app.config.TEST_ROI == 2.3
|
||||
del environ["MYAPP_TEST_ROI"]
|
||||
|
||||
|
||||
def test_load_env_prefix_string_value():
|
||||
environ["MYAPP_TEST_TOKEN"] = "somerandomtesttoken"
|
||||
app = Sanic(name=__name__, load_env="MYAPP_")
|
||||
assert app.config.TEST_TOKEN == "somerandomtesttoken"
|
||||
del environ["MYAPP_TEST_TOKEN"]
|
||||
|
||||
|
||||
def test_env_prefix():
|
||||
environ["MYAPP_TEST_ANSWER"] = "42"
|
||||
app = Sanic(name=__name__, env_prefix="MYAPP_")
|
||||
|
||||
9
tests/test_deprecation.py
Normal file
9
tests/test_deprecation.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import pytest
|
||||
|
||||
from sanic.log import deprecation
|
||||
|
||||
|
||||
def test_deprecation():
|
||||
message = r"\[DEPRECATION v9\.9\] hello"
|
||||
with pytest.warns(DeprecationWarning, match=message):
|
||||
deprecation("hello", 9.9)
|
||||
@@ -13,7 +13,6 @@ from sanic.exceptions import (
|
||||
SanicException,
|
||||
ServerError,
|
||||
Unauthorized,
|
||||
abort,
|
||||
)
|
||||
from sanic.response import text
|
||||
|
||||
@@ -88,10 +87,6 @@ def exception_app():
|
||||
def handler_500_error(request):
|
||||
raise SanicException(status_code=500)
|
||||
|
||||
@app.route("/old_abort")
|
||||
def handler_old_abort_error(request):
|
||||
abort(500)
|
||||
|
||||
@app.route("/abort/message")
|
||||
def handler_abort_message(request):
|
||||
raise SanicException(message="Custom Message", status_code=500)
|
||||
@@ -239,11 +234,6 @@ def test_sanic_exception(exception_app):
|
||||
assert response.status == 500
|
||||
assert "Custom Message" in response.text
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
request, response = exception_app.test_client.get("/old_abort")
|
||||
assert response.status == 500
|
||||
assert len(w) == 1 and "deprecated" in w[0].message.args[0]
|
||||
|
||||
|
||||
def test_custom_exception_default_message(exception_app):
|
||||
class TeaError(SanicException):
|
||||
@@ -262,7 +252,7 @@ def test_custom_exception_default_message(exception_app):
|
||||
|
||||
|
||||
def test_exception_in_ws_logged(caplog):
|
||||
app = Sanic(__file__)
|
||||
app = Sanic(__name__)
|
||||
|
||||
@app.websocket("/feed")
|
||||
async def feed(request, ws):
|
||||
|
||||
@@ -226,11 +226,12 @@ def test_single_arg_exception_handler_notice(
|
||||
exception_handler_app.error_handler = CustomErrorHandler()
|
||||
|
||||
message = (
|
||||
"You are using a deprecated error handler. The lookup method should "
|
||||
"accept two positional parameters: (exception, route_name: "
|
||||
"Optional[str]). Until you upgrade your ErrorHandler.lookup, "
|
||||
"Blueprint specific exceptions will not work properly. Beginning in "
|
||||
"v22.3, the legacy style lookup method will not work at all."
|
||||
"[DEPRECATION v22.3] You are using a deprecated error handler. The "
|
||||
"lookup method should accept two positional parameters: (exception, "
|
||||
"route_name: Optional[str]). Until you upgrade your "
|
||||
"ErrorHandler.lookup, Blueprint specific exceptions will not work "
|
||||
"properly. Beginning in v22.3, the legacy style lookup method will "
|
||||
"not work at all."
|
||||
)
|
||||
with pytest.warns(DeprecationWarning) as record:
|
||||
_, response = exception_handler_app.test_client.get("/1")
|
||||
|
||||
@@ -45,7 +45,7 @@ def default_back_to_ujson():
|
||||
|
||||
|
||||
def test_change_encoder():
|
||||
Sanic("...", dumps=sdumps)
|
||||
Sanic("Test", dumps=sdumps)
|
||||
assert BaseHTTPResponse._dumps == sdumps
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ def test_change_encoder_to_some_custom():
|
||||
def my_custom_encoder():
|
||||
return "foo"
|
||||
|
||||
Sanic("...", dumps=my_custom_encoder)
|
||||
Sanic("Test", dumps=my_custom_encoder)
|
||||
assert BaseHTTPResponse._dumps == my_custom_encoder
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ def test_json_response_ujson(payload):
|
||||
):
|
||||
json(payload, dumps=sdumps)
|
||||
|
||||
Sanic("...", dumps=sdumps)
|
||||
Sanic("Test", dumps=sdumps)
|
||||
with pytest.raises(
|
||||
TypeError, match="Object of type Foo is not JSON serializable"
|
||||
):
|
||||
@@ -87,6 +87,6 @@ def test_json_response_json():
|
||||
response = json(too_big_for_ujson, dumps=sdumps)
|
||||
assert sys.getsizeof(response.body) == 54
|
||||
|
||||
Sanic("...", dumps=sdumps)
|
||||
Sanic("Test", dumps=sdumps)
|
||||
response = json(too_big_for_ujson)
|
||||
assert sys.getsizeof(response.body) == 54
|
||||
|
||||
@@ -8,13 +8,13 @@ from sanic.response import stream, text
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_request_cancel_when_connection_lost(app):
|
||||
app.still_serving_cancelled_request = False
|
||||
app.ctx.still_serving_cancelled_request = False
|
||||
|
||||
@app.get("/")
|
||||
async def handler(request):
|
||||
await asyncio.sleep(1.0)
|
||||
# at this point client is already disconnected
|
||||
app.still_serving_cancelled_request = True
|
||||
app.ctx.still_serving_cancelled_request = True
|
||||
return text("OK")
|
||||
|
||||
# schedule client call
|
||||
@@ -32,12 +32,12 @@ async def test_request_cancel_when_connection_lost(app):
|
||||
# Wait for server and check if it's still serving the cancelled request
|
||||
await asyncio.sleep(1.0)
|
||||
|
||||
assert app.still_serving_cancelled_request is False
|
||||
assert app.ctx.still_serving_cancelled_request is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stream_request_cancel_when_conn_lost(app):
|
||||
app.still_serving_cancelled_request = False
|
||||
app.ctx.still_serving_cancelled_request = False
|
||||
|
||||
@app.post("/post/<id>", stream=True)
|
||||
async def post(request, id):
|
||||
@@ -52,7 +52,7 @@ async def test_stream_request_cancel_when_conn_lost(app):
|
||||
|
||||
await asyncio.sleep(1.0)
|
||||
# at this point client is already disconnected
|
||||
app.still_serving_cancelled_request = True
|
||||
app.ctx.still_serving_cancelled_request = True
|
||||
|
||||
return stream(streaming)
|
||||
|
||||
@@ -71,4 +71,4 @@ async def test_stream_request_cancel_when_conn_lost(app):
|
||||
# Wait for server and check if it's still serving the cancelled request
|
||||
await asyncio.sleep(1.0)
|
||||
|
||||
assert app.still_serving_cancelled_request is False
|
||||
assert app.ctx.still_serving_cancelled_request is False
|
||||
|
||||
@@ -68,11 +68,11 @@ def test_app_injection(app):
|
||||
|
||||
@app.listener("after_server_start")
|
||||
async def inject_data(app, loop):
|
||||
app.injected = expected
|
||||
app.ctx.injected = expected
|
||||
|
||||
@app.get("/")
|
||||
async def handler(request):
|
||||
return json({"injected": request.app.injected})
|
||||
return json({"injected": request.app.ctx.injected})
|
||||
|
||||
request, response = app.test_client.get("/")
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import pytest
|
||||
from sanic import Sanic
|
||||
from sanic.blueprints import Blueprint
|
||||
from sanic.response import json, text
|
||||
from sanic.views import CompositionView, HTTPMethodView
|
||||
from sanic.views import HTTPMethodView
|
||||
from sanic.views import stream as stream_decorator
|
||||
|
||||
|
||||
@@ -423,33 +423,6 @@ def test_request_stream_blueprint(app):
|
||||
assert response.text == data
|
||||
|
||||
|
||||
def test_request_stream_composition_view(app):
|
||||
def get_handler(request):
|
||||
return text("OK")
|
||||
|
||||
async def post_handler(request):
|
||||
result = ""
|
||||
while True:
|
||||
body = await request.stream.read()
|
||||
if body is None:
|
||||
break
|
||||
result += body.decode("utf-8")
|
||||
return text(result)
|
||||
|
||||
view = CompositionView()
|
||||
view.add(["GET"], get_handler)
|
||||
view.add(["POST"], post_handler, stream=True)
|
||||
app.add_route(view, "/composition_view")
|
||||
|
||||
request, response = app.test_client.get("/composition_view")
|
||||
assert response.status == 200
|
||||
assert response.text == "OK"
|
||||
|
||||
request, response = app.test_client.post("/composition_view", data=data)
|
||||
assert response.status == 200
|
||||
assert response.text == data
|
||||
|
||||
|
||||
def test_request_stream(app):
|
||||
"""test for complex application"""
|
||||
bp = Blueprint("test_blueprint_request_stream")
|
||||
@@ -510,14 +483,8 @@ def test_request_stream(app):
|
||||
|
||||
app.add_route(SimpleView.as_view(), "/method_view")
|
||||
|
||||
view = CompositionView()
|
||||
view.add(["GET"], get_handler)
|
||||
view.add(["POST"], post_handler, stream=True)
|
||||
|
||||
app.blueprint(bp)
|
||||
|
||||
app.add_route(view, "/composition_view")
|
||||
|
||||
request, response = app.test_client.get("/method_view")
|
||||
assert response.status == 200
|
||||
assert response.text == "OK"
|
||||
@@ -526,14 +493,6 @@ def test_request_stream(app):
|
||||
assert response.status == 200
|
||||
assert response.text == data
|
||||
|
||||
request, response = app.test_client.get("/composition_view")
|
||||
assert response.status == 200
|
||||
assert response.text == "OK"
|
||||
|
||||
request, response = app.test_client.post("/composition_view", data=data)
|
||||
assert response.status == 200
|
||||
assert response.text == data
|
||||
|
||||
request, response = app.test_client.get("/get")
|
||||
assert response.status == 200
|
||||
assert response.text == "OK"
|
||||
|
||||
@@ -15,6 +15,8 @@ from aiofiles import os as async_os
|
||||
from pytest import LogCaptureFixture
|
||||
|
||||
from sanic import Request, Sanic
|
||||
from sanic.compat import Header
|
||||
from sanic.cookies import CookieJar
|
||||
from sanic.response import (
|
||||
HTTPResponse,
|
||||
empty,
|
||||
@@ -277,7 +279,7 @@ def test_non_chunked_streaming_returns_correct_content(
|
||||
assert response.text == "foo,bar"
|
||||
|
||||
|
||||
def test_stream_response_with_cookies(app):
|
||||
def test_stream_response_with_cookies_legacy(app):
|
||||
@app.route("/")
|
||||
async def test(request: Request):
|
||||
response = stream(sample_streaming_fn, content_type="text/csv")
|
||||
@@ -289,6 +291,25 @@ def test_stream_response_with_cookies(app):
|
||||
assert response.cookies["test"] == "pass"
|
||||
|
||||
|
||||
def test_stream_response_with_cookies(app):
|
||||
@app.route("/")
|
||||
async def test(request: Request):
|
||||
headers = Header()
|
||||
cookies = CookieJar(headers)
|
||||
cookies["test"] = "modified"
|
||||
cookies["test"] = "pass"
|
||||
response = await request.respond(
|
||||
content_type="text/csv", headers=headers
|
||||
)
|
||||
|
||||
await response.send("foo,")
|
||||
await asyncio.sleep(0.001)
|
||||
await response.send("bar")
|
||||
|
||||
request, response = app.test_client.get("/")
|
||||
assert response.cookies["test"] == "pass"
|
||||
|
||||
|
||||
def test_stream_response_without_cookies(app):
|
||||
@app.route("/")
|
||||
async def test(request: Request):
|
||||
@@ -561,37 +582,37 @@ def test_multiple_responses(
|
||||
message_in_records: Callable[[List[LogRecord], str], bool],
|
||||
):
|
||||
@app.route("/1")
|
||||
async def handler(request: Request):
|
||||
async def handler1(request: Request):
|
||||
response = await request.respond()
|
||||
await response.send("foo")
|
||||
response = await request.respond()
|
||||
|
||||
@app.route("/2")
|
||||
async def handler(request: Request):
|
||||
async def handler2(request: Request):
|
||||
response = await request.respond()
|
||||
response = await request.respond()
|
||||
await response.send("foo")
|
||||
|
||||
@app.get("/3")
|
||||
async def handler(request: Request):
|
||||
async def handler3(request: Request):
|
||||
response = await request.respond()
|
||||
await response.send("foo,")
|
||||
response = await request.respond()
|
||||
await response.send("bar")
|
||||
|
||||
@app.get("/4")
|
||||
async def handler(request: Request):
|
||||
async def handler4(request: Request):
|
||||
response = await request.respond(headers={"one": "one"})
|
||||
return json({"foo": "bar"}, headers={"one": "two"})
|
||||
|
||||
@app.get("/5")
|
||||
async def handler(request: Request):
|
||||
async def handler5(request: Request):
|
||||
response = await request.respond(headers={"one": "one"})
|
||||
await response.send("foo")
|
||||
return json({"foo": "bar"}, headers={"one": "two"})
|
||||
|
||||
@app.get("/6")
|
||||
async def handler(request: Request):
|
||||
async def handler6(request: Request):
|
||||
response = await request.respond(headers={"one": "one"})
|
||||
await response.send("foo, ")
|
||||
json_response = json({"foo": "bar"}, headers={"one": "two"})
|
||||
|
||||
@@ -101,7 +101,7 @@ async def test_trigger_before_events_create_server(app):
|
||||
|
||||
@app.listener("before_server_start")
|
||||
async def init_db(app, loop):
|
||||
app.db = MySanicDb()
|
||||
app.ctx.db = MySanicDb()
|
||||
|
||||
srv = await app.create_server(
|
||||
debug=True, return_asyncio_server=True, port=PORT
|
||||
@@ -109,8 +109,8 @@ async def test_trigger_before_events_create_server(app):
|
||||
await srv.startup()
|
||||
await srv.before_start()
|
||||
|
||||
assert hasattr(app, "db")
|
||||
assert isinstance(app.db, MySanicDb)
|
||||
assert hasattr(app.ctx, "db")
|
||||
assert isinstance(app.ctx.db, MySanicDb)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -122,9 +122,9 @@ async def test_trigger_before_events_create_server_missing_event(app):
|
||||
|
||||
@app.listener
|
||||
async def init_db(app, loop):
|
||||
app.db = MySanicDb()
|
||||
app.ctx.db = MySanicDb()
|
||||
|
||||
assert not hasattr(app, "db")
|
||||
assert not hasattr(app.ctx, "db")
|
||||
|
||||
|
||||
def test_create_server_trigger_events(app):
|
||||
|
||||
@@ -76,8 +76,11 @@ async def test_purge_tasks(app: Sanic):
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason="Not supported in 3.7")
|
||||
def test_shutdown_tasks_on_app_stop(app: Sanic):
|
||||
app.shutdown_tasks = Mock()
|
||||
def test_shutdown_tasks_on_app_stop():
|
||||
class TestSanic(Sanic):
|
||||
shutdown_tasks = Mock()
|
||||
|
||||
app = TestSanic("Test")
|
||||
|
||||
@app.route("/")
|
||||
async def handler(_):
|
||||
|
||||
@@ -15,12 +15,12 @@ from sanic import Sanic
|
||||
from sanic.response import text
|
||||
|
||||
|
||||
httpx_version = tuple(
|
||||
map(int, httpx.__version__.strip(ascii_lowercase).split("."))
|
||||
)
|
||||
pytestmark = pytest.mark.skipif(os.name != "posix", reason="UNIX only")
|
||||
SOCKPATH = "/tmp/sanictest.sock"
|
||||
SOCKPATH2 = "/tmp/sanictest2.sock"
|
||||
httpx_version = tuple(
|
||||
map(int, httpx.__version__.strip(ascii_lowercase).split("."))
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@@ -222,7 +222,10 @@ async def test_zero_downtime():
|
||||
processes = [spawn()]
|
||||
while not os.path.exists(SOCKPATH):
|
||||
if processes[0].poll() is not None:
|
||||
raise Exception("Worker did not start properly")
|
||||
raise Exception(
|
||||
"Worker did not start properly. "
|
||||
f"stderr: {processes[0].stderr.read()}"
|
||||
)
|
||||
await asyncio.sleep(0.0001)
|
||||
ino = os.stat(SOCKPATH).st_ino
|
||||
task = asyncio.get_event_loop().create_task(client())
|
||||
|
||||
@@ -19,7 +19,7 @@ def test_route(app, handler):
|
||||
|
||||
|
||||
def test_bp(app, handler):
|
||||
bp = Blueprint(__file__, version=1)
|
||||
bp = Blueprint(__name__, version=1)
|
||||
bp.route("/")(handler)
|
||||
app.blueprint(bp)
|
||||
|
||||
@@ -28,7 +28,7 @@ def test_bp(app, handler):
|
||||
|
||||
|
||||
def test_bp_use_route(app, handler):
|
||||
bp = Blueprint(__file__, version=1)
|
||||
bp = Blueprint(__name__, version=1)
|
||||
bp.route("/", version=1.1)(handler)
|
||||
app.blueprint(bp)
|
||||
|
||||
@@ -37,7 +37,7 @@ def test_bp_use_route(app, handler):
|
||||
|
||||
|
||||
def test_bp_group(app, handler):
|
||||
bp = Blueprint(__file__)
|
||||
bp = Blueprint(__name__)
|
||||
bp.route("/")(handler)
|
||||
group = Blueprint.group(bp, version=1)
|
||||
app.blueprint(group)
|
||||
@@ -47,7 +47,7 @@ def test_bp_group(app, handler):
|
||||
|
||||
|
||||
def test_bp_group_use_bp(app, handler):
|
||||
bp = Blueprint(__file__, version=1.1)
|
||||
bp = Blueprint(__name__, version=1.1)
|
||||
bp.route("/")(handler)
|
||||
group = Blueprint.group(bp, version=1)
|
||||
app.blueprint(group)
|
||||
@@ -57,7 +57,7 @@ def test_bp_group_use_bp(app, handler):
|
||||
|
||||
|
||||
def test_bp_group_use_registration(app, handler):
|
||||
bp = Blueprint(__file__, version=1.1)
|
||||
bp = Blueprint(__name__, version=1.1)
|
||||
bp.route("/")(handler)
|
||||
group = Blueprint.group(bp, version=1)
|
||||
app.blueprint(group, version=1.2)
|
||||
@@ -67,7 +67,7 @@ def test_bp_group_use_registration(app, handler):
|
||||
|
||||
|
||||
def test_bp_group_use_route(app, handler):
|
||||
bp = Blueprint(__file__, version=1.1)
|
||||
bp = Blueprint(__name__, version=1.1)
|
||||
bp.route("/", version=1.3)(handler)
|
||||
group = Blueprint.group(bp, version=1)
|
||||
app.blueprint(group, version=1.2)
|
||||
@@ -84,7 +84,7 @@ def test_version_prefix_route(app, handler):
|
||||
|
||||
|
||||
def test_version_prefix_bp(app, handler):
|
||||
bp = Blueprint(__file__, version=1, version_prefix="/api/v")
|
||||
bp = Blueprint(__name__, version=1, version_prefix="/api/v")
|
||||
bp.route("/")(handler)
|
||||
app.blueprint(bp)
|
||||
|
||||
@@ -93,7 +93,7 @@ def test_version_prefix_bp(app, handler):
|
||||
|
||||
|
||||
def test_version_prefix_bp_use_route(app, handler):
|
||||
bp = Blueprint(__file__, version=1, version_prefix="/ignore/v")
|
||||
bp = Blueprint(__name__, version=1, version_prefix="/ignore/v")
|
||||
bp.route("/", version=1.1, version_prefix="/api/v")(handler)
|
||||
app.blueprint(bp)
|
||||
|
||||
@@ -102,7 +102,7 @@ def test_version_prefix_bp_use_route(app, handler):
|
||||
|
||||
|
||||
def test_version_prefix_bp_group(app, handler):
|
||||
bp = Blueprint(__file__)
|
||||
bp = Blueprint(__name__)
|
||||
bp.route("/")(handler)
|
||||
group = Blueprint.group(bp, version=1, version_prefix="/api/v")
|
||||
app.blueprint(group)
|
||||
@@ -112,7 +112,7 @@ def test_version_prefix_bp_group(app, handler):
|
||||
|
||||
|
||||
def test_version_prefix_bp_group_use_bp(app, handler):
|
||||
bp = Blueprint(__file__, version=1.1, version_prefix="/api/v")
|
||||
bp = Blueprint(__name__, version=1.1, version_prefix="/api/v")
|
||||
bp.route("/")(handler)
|
||||
group = Blueprint.group(bp, version=1, version_prefix="/ignore/v")
|
||||
app.blueprint(group)
|
||||
@@ -122,7 +122,7 @@ def test_version_prefix_bp_group_use_bp(app, handler):
|
||||
|
||||
|
||||
def test_version_prefix_bp_group_use_registration(app, handler):
|
||||
bp = Blueprint(__file__, version=1.1, version_prefix="/alsoignore/v")
|
||||
bp = Blueprint(__name__, version=1.1, version_prefix="/alsoignore/v")
|
||||
bp.route("/")(handler)
|
||||
group = Blueprint.group(bp, version=1, version_prefix="/ignore/v")
|
||||
app.blueprint(group, version=1.2, version_prefix="/api/v")
|
||||
@@ -132,7 +132,7 @@ def test_version_prefix_bp_group_use_registration(app, handler):
|
||||
|
||||
|
||||
def test_version_prefix_bp_group_use_route(app, handler):
|
||||
bp = Blueprint(__file__, version=1.1, version_prefix="/alsoignore/v")
|
||||
bp = Blueprint(__name__, version=1.1, version_prefix="/alsoignore/v")
|
||||
bp.route("/", version=1.3, version_prefix="/api/v")(handler)
|
||||
group = Blueprint.group(bp, version=1, version_prefix="/ignore/v")
|
||||
app.blueprint(group, version=1.2, version_prefix="/stillignoring/v")
|
||||
|
||||
@@ -5,7 +5,7 @@ from sanic.constants import HTTP_METHODS
|
||||
from sanic.exceptions import InvalidUsage
|
||||
from sanic.request import Request
|
||||
from sanic.response import HTTPResponse, text
|
||||
from sanic.views import CompositionView, HTTPMethodView
|
||||
from sanic.views import HTTPMethodView
|
||||
|
||||
|
||||
@pytest.mark.parametrize("method", HTTP_METHODS)
|
||||
@@ -225,81 +225,3 @@ def test_with_decorator(app):
|
||||
request, response = app.test_client.get("/")
|
||||
assert response.text == "I am get method"
|
||||
assert results[0] == 1
|
||||
|
||||
|
||||
def test_composition_view_rejects_incorrect_methods():
|
||||
def foo(request):
|
||||
return text("Foo")
|
||||
|
||||
view = CompositionView()
|
||||
|
||||
with pytest.raises(InvalidUsage) as e:
|
||||
view.add(["GET", "FOO"], foo)
|
||||
|
||||
assert str(e.value) == "FOO is not a valid HTTP method."
|
||||
|
||||
|
||||
def test_composition_view_rejects_duplicate_methods():
|
||||
def foo(request):
|
||||
return text("Foo")
|
||||
|
||||
view = CompositionView()
|
||||
|
||||
with pytest.raises(InvalidUsage) as e:
|
||||
view.add(["GET", "POST", "GET"], foo)
|
||||
|
||||
assert str(e.value) == "Method GET is already registered."
|
||||
|
||||
|
||||
@pytest.mark.parametrize("method", HTTP_METHODS)
|
||||
def test_composition_view_runs_methods_as_expected(app, method):
|
||||
view = CompositionView()
|
||||
|
||||
def first(request):
|
||||
return text("first method")
|
||||
|
||||
view.add(["GET", "POST", "PUT"], first)
|
||||
view.add(["DELETE", "PATCH"], lambda x: text("second method"))
|
||||
|
||||
app.add_route(view, "/")
|
||||
|
||||
if method in ["GET", "POST", "PUT"]:
|
||||
request, response = getattr(app.test_client, method.lower())("/")
|
||||
assert response.status == 200
|
||||
assert response.text == "first method"
|
||||
|
||||
response = view(request)
|
||||
assert response.body.decode() == "first method"
|
||||
|
||||
if method in ["DELETE", "PATCH"]:
|
||||
request, response = getattr(app.test_client, method.lower())("/")
|
||||
assert response.text == "second method"
|
||||
|
||||
response = view(request)
|
||||
assert response.body.decode() == "second method"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("method", HTTP_METHODS)
|
||||
def test_composition_view_rejects_invalid_methods(app, method):
|
||||
view = CompositionView()
|
||||
view.add(["GET", "POST", "PUT"], lambda x: text("first method"))
|
||||
|
||||
app.add_route(view, "/")
|
||||
|
||||
if method in ["GET", "POST", "PUT"]:
|
||||
request, response = getattr(app.test_client, method.lower())("/")
|
||||
assert response.status == 200
|
||||
assert response.text == "first method"
|
||||
|
||||
if method in ["DELETE", "PATCH"]:
|
||||
request, response = getattr(app.test_client, method.lower())("/")
|
||||
assert response.status == 405
|
||||
|
||||
|
||||
def test_composition_view_deprecation():
|
||||
message = (
|
||||
"CompositionView has been deprecated and will be removed in v21.12. "
|
||||
"Please update your view to HTTPMethodView."
|
||||
)
|
||||
with pytest.warns(DeprecationWarning, match=message):
|
||||
CompositionView()
|
||||
|
||||
Reference in New Issue
Block a user