v23.3 Deprecation Removal (#2717)
This commit is contained in:
@@ -448,7 +448,7 @@ def test_custom_context():
|
||||
|
||||
@pytest.mark.parametrize("use", (False, True))
|
||||
def test_uvloop_config(app: Sanic, monkeypatch, use):
|
||||
@app.get("/test")
|
||||
@app.get("/test", name="test")
|
||||
def handler(request):
|
||||
return text("ok")
|
||||
|
||||
@@ -571,21 +571,6 @@ def test_cannot_run_single_process_and_workers_or_auto_reload(
|
||||
app.run(single_process=True, **extra)
|
||||
|
||||
|
||||
def test_cannot_run_single_process_and_legacy(app: Sanic):
|
||||
message = "Cannot run single process and legacy mode"
|
||||
with pytest.raises(RuntimeError, match=message):
|
||||
app.run(single_process=True, legacy=True)
|
||||
|
||||
|
||||
def test_cannot_run_without_sys_signals_with_workers(app: Sanic):
|
||||
message = (
|
||||
"Cannot run Sanic.serve with register_sys_signals=False. "
|
||||
"Use either Sanic.serve_single or Sanic.serve_legacy."
|
||||
)
|
||||
with pytest.raises(RuntimeError, match=message):
|
||||
app.run(register_sys_signals=False, single_process=False, legacy=False)
|
||||
|
||||
|
||||
def test_default_configure_logging():
|
||||
with patch("sanic.app.logging") as mock:
|
||||
Sanic("Test")
|
||||
|
||||
@@ -66,3 +66,11 @@ def test_bp_copy(app: Sanic):
|
||||
|
||||
_, response = app.test_client.get("/version6/page")
|
||||
assert "Hello world!" in response.text
|
||||
|
||||
route_names = [route.name for route in app.router.routes]
|
||||
assert "test_bp_copy.test_bp1.handle_request" in route_names
|
||||
assert "test_bp_copy.test_bp2.handle_request" in route_names
|
||||
assert "test_bp_copy.test_bp3.handle_request" in route_names
|
||||
assert "test_bp_copy.test_bp4.handle_request" in route_names
|
||||
assert "test_bp_copy.test_bp5.handle_request" in route_names
|
||||
assert "test_bp_copy.test_bp6.handle_request" in route_names
|
||||
|
||||
@@ -303,6 +303,10 @@ def test_bp_with_host_list(app: Sanic):
|
||||
|
||||
assert response.text == "Hello subdomain!"
|
||||
|
||||
route_names = [r.name for r in app.router.routes]
|
||||
assert "test_bp_with_host_list.test_bp_host.handler1" in route_names
|
||||
assert "test_bp_with_host_list.test_bp_host.handler2" in route_names
|
||||
|
||||
|
||||
def test_several_bp_with_host_list(app: Sanic):
|
||||
bp = Blueprint(
|
||||
|
||||
@@ -248,9 +248,9 @@ def test_fallback_with_content_type_mismatch_accept(app):
|
||||
|
||||
app.router.reset()
|
||||
|
||||
@app.route("/alt1")
|
||||
@app.route("/alt2", error_format="text")
|
||||
@app.route("/alt3", error_format="html")
|
||||
@app.route("/alt1", name="alt1")
|
||||
@app.route("/alt2", error_format="text", name="alt2")
|
||||
@app.route("/alt3", error_format="html", name="alt3")
|
||||
def handler(_):
|
||||
raise Exception("problem here")
|
||||
# Yes, we know this return value is unreachable. This is on purpose.
|
||||
|
||||
@@ -285,9 +285,15 @@ def test_contextual_exception_context(debug):
|
||||
def fail():
|
||||
raise TeapotError(context={"foo": "bar"})
|
||||
|
||||
app.post("/coffee/json", error_format="json")(lambda _: fail())
|
||||
app.post("/coffee/html", error_format="html")(lambda _: fail())
|
||||
app.post("/coffee/text", error_format="text")(lambda _: fail())
|
||||
app.post("/coffee/json", error_format="json", name="json")(
|
||||
lambda _: fail()
|
||||
)
|
||||
app.post("/coffee/html", error_format="html", name="html")(
|
||||
lambda _: fail()
|
||||
)
|
||||
app.post("/coffee/text", error_format="text", name="text")(
|
||||
lambda _: fail()
|
||||
)
|
||||
|
||||
_, response = app.test_client.post("/coffee/json", debug=debug)
|
||||
assert response.status == 418
|
||||
@@ -323,9 +329,15 @@ def test_contextual_exception_extra(debug):
|
||||
def fail():
|
||||
raise TeapotError(extra={"foo": "bar"})
|
||||
|
||||
app.post("/coffee/json", error_format="json")(lambda _: fail())
|
||||
app.post("/coffee/html", error_format="html")(lambda _: fail())
|
||||
app.post("/coffee/text", error_format="text")(lambda _: fail())
|
||||
app.post("/coffee/json", error_format="json", name="json")(
|
||||
lambda _: fail()
|
||||
)
|
||||
app.post("/coffee/html", error_format="html", name="html")(
|
||||
lambda _: fail()
|
||||
)
|
||||
app.post("/coffee/text", error_format="text", name="text")(
|
||||
lambda _: fail()
|
||||
)
|
||||
|
||||
_, response = app.test_client.post("/coffee/json", debug=debug)
|
||||
assert response.status == 418
|
||||
|
||||
@@ -266,20 +266,17 @@ def test_exception_handler_response_was_sent(
|
||||
assert "Error" in response.text
|
||||
|
||||
|
||||
def test_warn_on_duplicate(
|
||||
app: Sanic, caplog: LogCaptureFixture, recwarn: WarningsRecorder
|
||||
):
|
||||
def test_errir_on_duplicate(app: Sanic):
|
||||
@app.exception(ServerError)
|
||||
async def exception_handler_1(request, exception):
|
||||
...
|
||||
|
||||
@app.exception(ServerError)
|
||||
async def exception_handler_2(request, exception):
|
||||
...
|
||||
|
||||
assert len(caplog.records) == 1
|
||||
assert len(recwarn) == 1
|
||||
assert caplog.records[0].message == (
|
||||
message = (
|
||||
"Duplicate exception handler definition on: route=__ALL_ROUTES__ and "
|
||||
"exception=<class 'sanic.exceptions.ServerError'>"
|
||||
)
|
||||
with pytest.raises(ServerError, match=message):
|
||||
|
||||
@app.exception(ServerError)
|
||||
async def exception_handler_2(request, exception):
|
||||
...
|
||||
|
||||
@@ -49,96 +49,6 @@ def test_multiprocessing(app):
|
||||
assert len(process_list) == num_workers + 1
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not hasattr(signal, "SIGALRM"),
|
||||
reason="SIGALRM is not implemented for this platform, we have to come "
|
||||
"up with another timeout strategy to test these",
|
||||
)
|
||||
def test_multiprocessing_legacy(app):
|
||||
"""Tests that the number of children we produce is correct"""
|
||||
# Selects a number at random so we can spot check
|
||||
num_workers = random.choice(range(2, multiprocessing.cpu_count() * 2 + 1))
|
||||
process_list = set()
|
||||
|
||||
@app.after_server_start
|
||||
async def shutdown(app):
|
||||
await sleep(2.1)
|
||||
app.stop()
|
||||
|
||||
def stop_on_alarm(*args):
|
||||
for process in multiprocessing.active_children():
|
||||
process_list.add(process.pid)
|
||||
|
||||
signal.signal(signal.SIGALRM, stop_on_alarm)
|
||||
signal.alarm(2)
|
||||
app.run(HOST, 4121, workers=num_workers, debug=True, legacy=True)
|
||||
|
||||
assert len(process_list) == num_workers
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not hasattr(signal, "SIGALRM"),
|
||||
reason="SIGALRM is not implemented for this platform, we have to come "
|
||||
"up with another timeout strategy to test these",
|
||||
)
|
||||
def test_multiprocessing_legacy_sock(app):
|
||||
"""Tests that the number of children we produce is correct"""
|
||||
# Selects a number at random so we can spot check
|
||||
num_workers = random.choice(range(2, multiprocessing.cpu_count() * 2 + 1))
|
||||
process_list = set()
|
||||
|
||||
@app.after_server_start
|
||||
async def shutdown(app):
|
||||
await sleep(2.1)
|
||||
app.stop()
|
||||
|
||||
def stop_on_alarm(*args):
|
||||
for process in multiprocessing.active_children():
|
||||
process_list.add(process.pid)
|
||||
|
||||
signal.signal(signal.SIGALRM, stop_on_alarm)
|
||||
signal.alarm(2)
|
||||
sock = configure_socket(
|
||||
{
|
||||
"host": HOST,
|
||||
"port": 4121,
|
||||
"unix": None,
|
||||
"backlog": 100,
|
||||
}
|
||||
)
|
||||
app.run(workers=num_workers, debug=True, legacy=True, sock=sock)
|
||||
sock.close()
|
||||
|
||||
assert len(process_list) == num_workers
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not hasattr(signal, "SIGALRM"),
|
||||
reason="SIGALRM is not implemented for this platform, we have to come "
|
||||
"up with another timeout strategy to test these",
|
||||
)
|
||||
def test_multiprocessing_legacy_unix(app):
|
||||
"""Tests that the number of children we produce is correct"""
|
||||
# Selects a number at random so we can spot check
|
||||
num_workers = random.choice(range(2, multiprocessing.cpu_count() * 2 + 1))
|
||||
process_list = set()
|
||||
|
||||
@app.after_server_start
|
||||
async def shutdown(app):
|
||||
await sleep(2.1)
|
||||
app.stop()
|
||||
|
||||
def stop_on_alarm(*args):
|
||||
for process in multiprocessing.active_children():
|
||||
process_list.add(process.pid)
|
||||
|
||||
signal.signal(signal.SIGALRM, stop_on_alarm)
|
||||
signal.alarm(2)
|
||||
app.run(workers=num_workers, debug=True, legacy=True, unix="./test.sock")
|
||||
|
||||
assert len(process_list) == num_workers
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not hasattr(signal, "SIGALRM"),
|
||||
reason="SIGALRM is not implemented for this platform",
|
||||
|
||||
@@ -105,11 +105,11 @@ def test_html(app):
|
||||
return html("<h1>Hello</h1>")
|
||||
|
||||
@app.route("/foo")
|
||||
async def handler(request):
|
||||
async def handler_foo(request):
|
||||
return html(Foo())
|
||||
|
||||
@app.route("/bar")
|
||||
async def handler(request):
|
||||
async def handler_bar(request):
|
||||
return html(Bar())
|
||||
|
||||
request, response = app.test_client.get("/")
|
||||
@@ -2199,10 +2199,25 @@ def test_safe_method_with_body(app):
|
||||
assert response.body == b"OK"
|
||||
|
||||
|
||||
def test_conflicting_body_methods_overload(app):
|
||||
@pytest.mark.asyncio
|
||||
async def test_conflicting_body_methods_overload_error(app: Sanic):
|
||||
@app.put("/")
|
||||
@app.put("/p/")
|
||||
@app.put("/p/<foo>")
|
||||
async def put(request, foo=None):
|
||||
...
|
||||
|
||||
with pytest.raises(
|
||||
ServerError,
|
||||
match="Duplicate route names detected: test_conflicting_body_methods_overload_error\.put.*",
|
||||
):
|
||||
await app._startup()
|
||||
|
||||
|
||||
def test_conflicting_body_methods_overload(app: Sanic):
|
||||
@app.put("/", name="one")
|
||||
@app.put("/p/", name="two")
|
||||
@app.put("/p/<foo>", name="three")
|
||||
async def put(request, foo=None):
|
||||
return json(
|
||||
{"name": request.route.name, "body": str(request.body), "foo": foo}
|
||||
@@ -2220,21 +2235,21 @@ def test_conflicting_body_methods_overload(app):
|
||||
_, response = app.test_client.put("/", json=payload)
|
||||
assert response.status == 200
|
||||
assert response.json == {
|
||||
"name": "test_conflicting_body_methods_overload.put",
|
||||
"name": "test_conflicting_body_methods_overload.one",
|
||||
"foo": None,
|
||||
"body": data,
|
||||
}
|
||||
_, response = app.test_client.put("/p", json=payload)
|
||||
assert response.status == 200
|
||||
assert response.json == {
|
||||
"name": "test_conflicting_body_methods_overload.put",
|
||||
"name": "test_conflicting_body_methods_overload.two",
|
||||
"foo": None,
|
||||
"body": data,
|
||||
}
|
||||
_, response = app.test_client.put("/p/test", json=payload)
|
||||
assert response.status == 200
|
||||
assert response.json == {
|
||||
"name": "test_conflicting_body_methods_overload.put",
|
||||
"name": "test_conflicting_body_methods_overload.three",
|
||||
"foo": "test",
|
||||
"body": data,
|
||||
}
|
||||
@@ -2247,9 +2262,26 @@ def test_conflicting_body_methods_overload(app):
|
||||
}
|
||||
|
||||
|
||||
def test_handler_overload(app):
|
||||
@pytest.mark.asyncio
|
||||
async def test_handler_overload_error(app: Sanic):
|
||||
@app.get("/long/sub/route/param_a/<param_a:str>/param_b/<param_b:str>")
|
||||
@app.post("/long/sub/route/")
|
||||
def handler(request, **kwargs):
|
||||
...
|
||||
|
||||
with pytest.raises(
|
||||
ServerError,
|
||||
match="Duplicate route names detected: test_handler_overload_error\.handler.*",
|
||||
):
|
||||
await app._startup()
|
||||
|
||||
|
||||
def test_handler_overload(app: Sanic):
|
||||
@app.get(
|
||||
"/long/sub/route/param_a/<param_a:str>/param_b/<param_b:str>",
|
||||
name="one",
|
||||
)
|
||||
@app.post("/long/sub/route/", name="two")
|
||||
def handler(request, **kwargs):
|
||||
return json(kwargs)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ from sanic_testing.testing import SanicTestClient
|
||||
|
||||
from sanic import Blueprint, Sanic
|
||||
from sanic.constants import HTTP_METHODS
|
||||
from sanic.exceptions import NotFound, SanicException
|
||||
from sanic.exceptions import NotFound, SanicException, ServerError
|
||||
from sanic.request import Request
|
||||
from sanic.response import empty, json, text
|
||||
|
||||
@@ -744,8 +744,8 @@ def test_route_duplicate(app):
|
||||
|
||||
|
||||
def test_double_stack_route(app):
|
||||
@app.route("/test/1")
|
||||
@app.route("/test/2")
|
||||
@app.route("/test/1", name="test1")
|
||||
@app.route("/test/2", name="test2")
|
||||
async def handler1(request):
|
||||
return text("OK")
|
||||
|
||||
@@ -759,8 +759,8 @@ def test_double_stack_route(app):
|
||||
async def test_websocket_route_asgi(app):
|
||||
ev = asyncio.Event()
|
||||
|
||||
@app.websocket("/test/1")
|
||||
@app.websocket("/test/2")
|
||||
@app.websocket("/test/1", name="test1")
|
||||
@app.websocket("/test/2", name="test2")
|
||||
async def handler(request, ws):
|
||||
ev.set()
|
||||
|
||||
@@ -1279,7 +1279,7 @@ async def test_added_callable_route_ctx_kwargs(app):
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_duplicate_route_deprecation(app):
|
||||
async def test_duplicate_route_error(app):
|
||||
@app.route("/foo", name="duped")
|
||||
async def handler_foo(request):
|
||||
return text("...")
|
||||
@@ -1289,9 +1289,7 @@ async def test_duplicate_route_deprecation(app):
|
||||
return text("...")
|
||||
|
||||
message = (
|
||||
r"\[DEPRECATION v23\.3\] Duplicate route names detected: "
|
||||
r"test_duplicate_route_deprecation\.duped\. In the future, "
|
||||
r"Sanic will enforce uniqueness in route naming\."
|
||||
"Duplicate route names detected: test_duplicate_route_error.duped."
|
||||
)
|
||||
with pytest.warns(DeprecationWarning, match=message):
|
||||
with pytest.raises(ServerError, match=message):
|
||||
await app._startup()
|
||||
|
||||
@@ -66,8 +66,8 @@ def test_no_register_system_signals_fails(app):
|
||||
app.listener("after_server_stop")(after)
|
||||
|
||||
message = (
|
||||
"Cannot run Sanic.serve with register_sys_signals=False. Use "
|
||||
"either Sanic.serve_single or Sanic.serve_legacy."
|
||||
r"Cannot run Sanic\.serve with register_sys_signals=False\. Use "
|
||||
r"Sanic.serve_single\."
|
||||
)
|
||||
with pytest.raises(RuntimeError, match=message):
|
||||
app.prepare(HOST, PORT, register_sys_signals=False)
|
||||
|
||||
@@ -9,7 +9,7 @@ from time import gmtime, strftime
|
||||
import pytest
|
||||
|
||||
from sanic import Sanic, text
|
||||
from sanic.exceptions import FileNotFound
|
||||
from sanic.exceptions import FileNotFound, ServerError
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
@@ -108,14 +108,9 @@ def test_static_file_pathlib(app, static_file_directory, file_name):
|
||||
def test_static_file_bytes(app, static_file_directory, file_name):
|
||||
bsep = os.path.sep.encode("utf-8")
|
||||
file_path = static_file_directory.encode("utf-8") + bsep + file_name
|
||||
message = (
|
||||
"Serving a static directory with a bytes "
|
||||
"string is deprecated and will be removed in v22.9."
|
||||
)
|
||||
with pytest.warns(DeprecationWarning, match=message):
|
||||
message = "Static file or directory must be a path-like object or string"
|
||||
with pytest.raises(TypeError, match=message):
|
||||
app.static("/testing.file", file_path)
|
||||
request, response = app.test_client.get("/testing.file")
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -523,10 +518,26 @@ def test_no_stack_trace_on_not_found(app, static_file_directory, caplog):
|
||||
assert response.text == "No file: /static/non_existing_file.file"
|
||||
|
||||
|
||||
def test_multiple_statics(app, static_file_directory):
|
||||
@pytest.mark.asyncio
|
||||
async def test_multiple_statics_error(app, static_file_directory):
|
||||
app.static("/file", get_file_path(static_file_directory, "test.file"))
|
||||
app.static("/png", get_file_path(static_file_directory, "python.png"))
|
||||
|
||||
message = (
|
||||
r"Duplicate route names detected: test_multiple_statics_error\.static"
|
||||
)
|
||||
with pytest.raises(ServerError, match=message):
|
||||
await app._startup()
|
||||
|
||||
|
||||
def test_multiple_statics(app, static_file_directory):
|
||||
app.static(
|
||||
"/file", get_file_path(static_file_directory, "test.file"), name="file"
|
||||
)
|
||||
app.static(
|
||||
"/png", get_file_path(static_file_directory, "python.png"), name="png"
|
||||
)
|
||||
|
||||
_, response = app.test_client.get("/file")
|
||||
assert response.status == 200
|
||||
assert response.body == get_file_content(
|
||||
@@ -540,10 +551,22 @@ def test_multiple_statics(app, static_file_directory):
|
||||
)
|
||||
|
||||
|
||||
def test_resource_type_default(app, static_file_directory):
|
||||
@pytest.mark.asyncio
|
||||
async def test_resource_type_default_error(app, static_file_directory):
|
||||
app.static("/static", static_file_directory)
|
||||
app.static("/file", get_file_path(static_file_directory, "test.file"))
|
||||
|
||||
message = r"Duplicate route names detected: test_resource_type_default_error\.static"
|
||||
with pytest.raises(ServerError, match=message):
|
||||
await app._startup()
|
||||
|
||||
|
||||
def test_resource_type_default(app, static_file_directory):
|
||||
app.static("/static", static_file_directory, name="static")
|
||||
app.static(
|
||||
"/file", get_file_path(static_file_directory, "test.file"), name="file"
|
||||
)
|
||||
|
||||
_, response = app.test_client.get("/static")
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
@@ -72,24 +72,6 @@ def test_not_have_multiplexer_single(app: Sanic):
|
||||
assert not event.is_set()
|
||||
|
||||
|
||||
def test_not_have_multiplexer_legacy(app: Sanic):
|
||||
event = Event()
|
||||
|
||||
@app.main_process_start
|
||||
async def setup(app, _):
|
||||
app.shared_ctx.event = event
|
||||
|
||||
@app.after_server_start
|
||||
def stop(app):
|
||||
if hasattr(app, "m") and isinstance(app.m, WorkerMultiplexer):
|
||||
app.shared_ctx.event.set()
|
||||
app.stop()
|
||||
|
||||
app.run(legacy=True)
|
||||
|
||||
assert not event.is_set()
|
||||
|
||||
|
||||
def test_ack(worker_state: Dict[str, Any], m: WorkerMultiplexer):
|
||||
worker_state["Test"] = {"foo": "bar"}
|
||||
m.ack()
|
||||
|
||||
Reference in New Issue
Block a user