LTS v21.12 Deprecations (#2306)

Co-authored-by: Néstor Pérez <25409753+prryplatypus@users.noreply.github.com>
This commit is contained in:
Adam Hopkins
2021-12-24 00:30:27 +02:00
committed by GitHub
parent 98ce4bdeb2
commit 8c07e388cd
72 changed files with 638 additions and 847 deletions

View File

@@ -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("/")

View File

@@ -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())

View File

@@ -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)

View File

@@ -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):

View File

@@ -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_")

View 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)

View File

@@ -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):

View File

@@ -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")

View File

@@ -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

View File

@@ -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

View File

@@ -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("/")

View File

@@ -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"

View File

@@ -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"})

View File

@@ -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):

View File

@@ -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(_):

View File

@@ -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())

View File

@@ -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")

View File

@@ -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()