Skip to content

Commit

Permalink
22.3 Deprecations and changes (sanic-org#2362)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahopkins authored and ChihweiLHBird committed Jun 1, 2022
1 parent e2dc070 commit 0ea0c48
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 115 deletions.
9 changes: 6 additions & 3 deletions sanic/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,7 @@ def run(
host: Optional[str] = None,
port: Optional[int] = None,
*,
dev: bool = False,
debug: bool = False,
auto_reload: Optional[bool] = None,
ssl: Union[None, SSLContext, dict, str, list, tuple] = None,
Expand Down Expand Up @@ -1143,10 +1144,12 @@ def run(
"#asynchronous-support"
)

if auto_reload or auto_reload is None and debug:
if dev:
debug = True
auto_reload = True
if os.environ.get("SANIC_SERVER_RUNNING") != "true":
return reloader_helpers.watchdog(1.0, self)

if auto_reload and os.environ.get("SANIC_SERVER_RUNNING") != "true":
return reloader_helpers.watchdog(1.0, self)

if sock is None:
host, port = host or "127.0.0.1", port or 8000
Expand Down
12 changes: 3 additions & 9 deletions sanic/cli/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,6 @@ def run(self):
error_logger.exception("Failed to run app")

def _precheck(self):
if self.args.debug and self.main_process:
error_logger.warning(
"Starting in v22.3, --debug will no "
"longer automatically run the auto-reloader.\n Switch to "
"--dev to continue using that functionality."
)

# # Custom TLS mismatch handling for better diagnostics
if self.main_process and (
# one of cert/key missing
Expand Down Expand Up @@ -174,8 +167,9 @@ def _build_run_kwargs(self):
"workers": self.args.workers,
}

if self.args.auto_reload:
kwargs["auto_reload"] = True
for maybe_arg in ("auto_reload", "dev"):
if getattr(self.args, maybe_arg, False):
kwargs[maybe_arg] = True

if self.args.path:
if self.args.auto_reload or self.args.debug:
Expand Down
15 changes: 7 additions & 8 deletions sanic/cli/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,19 +180,18 @@ def attach(self):
"--debug",
dest="debug",
action="store_true",
help="Run the server in debug mode",
help=(
"Run the server in DEBUG mode. It includes DEBUG logging, "
"additional context on exceptions, and other settings "
"not-safe for PRODUCTION, but helpful for debugging problems."
),
)
self.container.add_argument(
"-d",
"--dev",
dest="debug",
dest="dev",
action="store_true",
help=(
"Currently is an alias for --debug. But starting in v22.3, \n"
"--debug will no longer automatically trigger auto_restart. \n"
"However, --dev will continue, effectively making it the \n"
"same as debug + auto_reload."
),
help=("Debug + auto_reload."),
)
self.container.add_argument(
"-r",
Expand Down
40 changes: 6 additions & 34 deletions sanic/handlers.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from __future__ import annotations

from inspect import signature
from typing import Dict, List, Optional, Tuple, Type, Union

from sanic.config import Config
from sanic.errorpages import (
DEFAULT_FORMAT,
BaseRenderer,
HTMLRenderer,
TextRenderer,
exception_response,
)
from sanic.exceptions import (
Expand Down Expand Up @@ -35,13 +34,11 @@ class ErrorHandler:
"""

# Beginning in v22.3, the base renderer will be TextRenderer
def __init__(
self,
fallback: Union[str, Default] = _default,
base: Type[BaseRenderer] = HTMLRenderer,
base: Type[BaseRenderer] = TextRenderer,
):
self.handlers: List[Tuple[Type[BaseException], RouteHandler]] = []
self.cached_handlers: Dict[
Tuple[Type[BaseException], Optional[str]], Optional[RouteHandler]
] = {}
Expand Down Expand Up @@ -95,8 +92,8 @@ def _get_fallback_value(cls, error_handler: ErrorHandler, config: Config):
def finalize(
cls,
error_handler: ErrorHandler,
config: Config,
fallback: Optional[str] = None,
config: Optional[Config] = None,
):
if fallback:
deprecation(
Expand All @@ -107,14 +104,10 @@ def finalize(
22.6,
)

if config is None:
deprecation(
"Starting in v22.3, config will be a required argument "
"for ErrorHandler.finalize().",
22.3,
)
if not fallback:
fallback = config.FALLBACK_ERROR_FORMAT

if fallback and fallback != DEFAULT_FORMAT:
if fallback != DEFAULT_FORMAT:
if error_handler._fallback is not _default:
error_logger.warning(
f"Setting the fallback value to {fallback}. This changes "
Expand All @@ -128,27 +121,9 @@ def finalize(
f"Error handler is non-conforming: {type(error_handler)}"
)

sig = signature(error_handler.lookup)
if len(sig.parameters) == 1:
deprecation(
"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.",
22.3,
)
legacy_lookup = error_handler._legacy_lookup
error_handler._lookup = legacy_lookup # type: ignore

def _full_lookup(self, exception, route_name: Optional[str] = None):
return self.lookup(exception, route_name)

def _legacy_lookup(self, exception, route_name: Optional[str] = None):
return self.lookup(exception)

def add(self, exception, handler, route_names: Optional[List[str]] = None):
"""
Add a new exception handler to an already existing handler object.
Expand All @@ -162,9 +137,6 @@ def add(self, exception, handler, route_names: Optional[List[str]] = None):
:return: None
"""
# self.handlers is deprecated and will be removed in version 22.3
self.handlers.append((exception, handler))

if route_names:
for route in route_names:
self.cached_handlers[(exception, route)] = handler
Expand Down
26 changes: 1 addition & 25 deletions sanic/server/protocols/websocket_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from websockets.typing import Subprotocol

from sanic.exceptions import ServerError
from sanic.log import deprecation, error_logger
from sanic.log import error_logger
from sanic.server import HttpProtocol

from ..websockets.impl import WebsocketImplProtocol
Expand All @@ -29,9 +29,6 @@ def __init__(
*args,
websocket_timeout: float = 10.0,
websocket_max_size: Optional[int] = None,
websocket_max_queue: Optional[int] = None, # max_queue is deprecated
websocket_read_limit: Optional[int] = None, # read_limit is deprecated
websocket_write_limit: Optional[int] = None, # write_limit deprecated
websocket_ping_interval: Optional[float] = 20.0,
websocket_ping_timeout: Optional[float] = 20.0,
**kwargs,
Expand All @@ -40,27 +37,6 @@ def __init__(
self.websocket: Optional[WebsocketImplProtocol] = None
self.websocket_timeout = websocket_timeout
self.websocket_max_size = websocket_max_size
if websocket_max_queue is not None and websocket_max_queue > 0:
# TODO: Reminder remove this warning in v22.3
deprecation(
"Websocket no longer uses queueing, so websocket_max_queue"
" is no longer required.",
22.3,
)
if websocket_read_limit is not None and websocket_read_limit > 0:
# TODO: Reminder remove this warning in v22.3
deprecation(
"Websocket no longer uses read buffers, so "
"websocket_read_limit is not required.",
22.3,
)
if websocket_write_limit is not None and websocket_write_limit > 0:
# TODO: Reminder remove this warning in v22.3
deprecation(
"Websocket no longer uses write buffers, so "
"websocket_write_limit is not required.",
22.3,
)
self.websocket_ping_interval = websocket_ping_interval
self.websocket_ping_timeout = websocket_ping_timeout

Expand Down
34 changes: 34 additions & 0 deletions tests/asyncmock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""
For 3.7 compat
"""


from unittest.mock import Mock


class AsyncMock(Mock):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.await_count = 0

def __call__(self, *args, **kwargs):
self.call_count += 1
parent = super(AsyncMock, self)

async def dummy():
self.await_count += 1
return parent.__call__(*args, **kwargs)

return dummy()

def __await__(self):
return self().__await__()

def assert_awaited_once(self):
if not self.await_count == 1:
msg = (
f"Expected to have been awaited once."
f" Awaited {self.await_count} times."
)
raise AssertionError(msg)
17 changes: 15 additions & 2 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def test_tls_wrong_options(cmd):
assert not out
lines = err.decode().split("\n")

errmsg = lines[8]
errmsg = lines[6]
assert errmsg == "TLS certificates must be specified by either of:"


Expand Down Expand Up @@ -200,13 +200,25 @@ def test_num_workers(num, cmd):
assert len(worker_lines) == num * 2, f"Lines found: {lines}"


@pytest.mark.parametrize("cmd", ("--debug", "-d"))
@pytest.mark.parametrize("cmd", ("--debug",))
def test_debug(cmd):
command = ["sanic", "fake.server.app", cmd]
out, err, exitcode = capture(command)
lines = out.split(b"\n")
info = read_app_info(lines)

assert info["debug"] is True
assert info["auto_reload"] is False
assert "dev" not in info


@pytest.mark.parametrize("cmd", ("--dev", "-d"))
def test_dev(cmd):
command = ["sanic", "fake.server.app", cmd]
out, err, exitcode = capture(command)
lines = out.split(b"\n")
info = read_app_info(lines)

assert info["debug"] is True
assert info["auto_reload"] is True

Expand All @@ -220,6 +232,7 @@ def test_auto_reload(cmd):

assert info["debug"] is False
assert info["auto_reload"] is True
assert "dev" not in info


@pytest.mark.parametrize(
Expand Down
36 changes: 29 additions & 7 deletions tests/test_errorpages.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,15 @@ def test_auto_fallback_with_data(app):

_, response = app.test_client.get("/error")
assert response.status == 500
assert response.content_type == "text/html; charset=utf-8"
assert response.content_type == "text/plain; charset=utf-8"

_, response = app.test_client.post("/error", json={"foo": "bar"})
assert response.status == 500
assert response.content_type == "application/json"

_, response = app.test_client.post("/error", data={"foo": "bar"})
assert response.status == 500
assert response.content_type == "text/html; charset=utf-8"
assert response.content_type == "text/plain; charset=utf-8"


def test_auto_fallback_with_content_type(app):
Expand All @@ -91,7 +91,7 @@ def test_auto_fallback_with_content_type(app):
"/error", headers={"content-type": "foo/bar", "accept": "*/*"}
)
assert response.status == 500
assert response.content_type == "text/html; charset=utf-8"
assert response.content_type == "text/plain; charset=utf-8"


def test_route_error_format_set_on_auto(app):
Expand Down Expand Up @@ -174,6 +174,17 @@ def handler(request):
...


def test_fallback_with_content_type_html(app):
app.config.FALLBACK_ERROR_FORMAT = "auto"

_, response = app.test_client.get(
"/error",
headers={"content-type": "application/json", "accept": "text/html"},
)
assert response.status == 500
assert response.content_type == "text/html; charset=utf-8"


def test_fallback_with_content_type_mismatch_accept(app):
app.config.FALLBACK_ERROR_FORMAT = "auto"

Expand All @@ -186,10 +197,10 @@ def test_fallback_with_content_type_mismatch_accept(app):

_, response = app.test_client.get(
"/error",
headers={"content-type": "text/plain", "accept": "foo/bar"},
headers={"content-type": "text/html", "accept": "foo/bar"},
)
assert response.status == 500
assert response.content_type == "text/html; charset=utf-8"
assert response.content_type == "text/plain; charset=utf-8"

app.router.reset()

Expand All @@ -208,7 +219,7 @@ def handler(_):
headers={"accept": "foo/bar"},
)
assert response.status == 500
assert response.content_type == "text/html; charset=utf-8"
assert response.content_type == "text/plain; charset=utf-8"
_, response = app.test_client.get(
"/alt1",
headers={"accept": "foo/bar,*/*"},
Expand All @@ -221,7 +232,7 @@ def handler(_):
headers={"accept": "foo/bar"},
)
assert response.status == 500
assert response.content_type == "text/html; charset=utf-8"
assert response.content_type == "text/plain; charset=utf-8"
_, response = app.test_client.get(
"/alt2",
headers={"accept": "foo/bar,*/*"},
Expand All @@ -234,6 +245,13 @@ def handler(_):
headers={"accept": "foo/bar"},
)
assert response.status == 500
assert response.content_type == "text/plain; charset=utf-8"

_, response = app.test_client.get(
"/alt3",
headers={"accept": "foo/bar,text/html"},
)
assert response.status == 500
assert response.content_type == "text/html; charset=utf-8"


Expand Down Expand Up @@ -288,6 +306,10 @@ async def start(app, _):
def test_setting_fallback_on_config_changes_as_expected(app):
app.error_handler = ErrorHandler()

_, response = app.test_client.get("/error")
assert response.content_type == "text/plain; charset=utf-8"

app.config.FALLBACK_ERROR_FORMAT = "html"
_, response = app.test_client.get("/error")
assert response.content_type == "text/html; charset=utf-8"

Expand Down
Loading

0 comments on commit 0ea0c48

Please sign in to comment.