Nicer traceback formatting (#2667)
Co-authored-by: L. Kärkkäinen <98187+Tronic@users.noreply.github.com> Co-authored-by: Adam Hopkins <adam@amhopkins.com> Co-authored-by: L. Karkkainen <tronic@users.noreply.github.com> Co-authored-by: SML <smlbiobot@gmail.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import pytest
|
||||
|
||||
from sanic import Sanic
|
||||
from sanic.config import Config
|
||||
from sanic.errorpages import TextRenderer, guess_mime, exception_response
|
||||
from sanic.errorpages import TextRenderer, exception_response, guess_mime
|
||||
from sanic.exceptions import NotFound, SanicException
|
||||
from sanic.handlers import ErrorHandler
|
||||
from sanic.request import Request
|
||||
@@ -57,7 +57,6 @@ def app():
|
||||
raise Exception
|
||||
return json({}) if param == "json" else html("")
|
||||
|
||||
|
||||
return app
|
||||
|
||||
|
||||
@@ -314,7 +313,6 @@ def test_fallback_with_content_type_mismatch_accept(app):
|
||||
("*/*", "application/json", "application/json"),
|
||||
# App wants text/plain but accept has equal entries for it
|
||||
("text/*,*/plain", None, "text/plain; charset=utf-8"),
|
||||
|
||||
),
|
||||
)
|
||||
def test_combinations_for_auto(fake_request, accept, content_type, expected):
|
||||
@@ -428,25 +426,83 @@ def test_config_fallback_bad_value(app):
|
||||
@pytest.mark.parametrize(
|
||||
"route_format,fallback,accept,expected",
|
||||
(
|
||||
("json", "html", "*/*", "The client accepts */*, using 'json' from fakeroute"),
|
||||
("json", "auto", "text/html,*/*;q=0.8", "The client accepts text/html, using 'html' from any"),
|
||||
("json", "json", "text/html,*/*;q=0.8", "The client accepts */*;q=0.8, using 'json' from fakeroute"),
|
||||
("", "html", "text/*,*/plain", "The client accepts text/*, using 'html' from FALLBACK_ERROR_FORMAT"),
|
||||
("", "json", "text/*,*/*", "The client accepts */*, using 'json' from FALLBACK_ERROR_FORMAT"),
|
||||
("", "auto", "*/*,application/json;q=0.5", "The client accepts */*, using 'json' from request.accept"),
|
||||
("", "auto", "*/*", "The client accepts */*, using 'json' from content-type"),
|
||||
("", "auto", "text/html,text/plain", "The client accepts text/plain, using 'text' from any"),
|
||||
("", "auto", "text/html,text/plain;q=0.9", "The client accepts text/html, using 'html' from any"),
|
||||
("html", "json", "application/xml", "No format found, the client accepts [application/xml]"),
|
||||
(
|
||||
"json",
|
||||
"html",
|
||||
"*/*",
|
||||
"The client accepts */*, using 'json' from fakeroute",
|
||||
),
|
||||
(
|
||||
"json",
|
||||
"auto",
|
||||
"text/html,*/*;q=0.8",
|
||||
"The client accepts text/html, using 'html' from any",
|
||||
),
|
||||
(
|
||||
"json",
|
||||
"json",
|
||||
"text/html,*/*;q=0.8",
|
||||
"The client accepts */*;q=0.8, using 'json' from fakeroute",
|
||||
),
|
||||
(
|
||||
"",
|
||||
"html",
|
||||
"text/*,*/plain",
|
||||
"The client accepts text/*, using 'html' from FALLBACK_ERROR_FORMAT",
|
||||
),
|
||||
(
|
||||
"",
|
||||
"json",
|
||||
"text/*,*/*",
|
||||
"The client accepts */*, using 'json' from FALLBACK_ERROR_FORMAT",
|
||||
),
|
||||
(
|
||||
"",
|
||||
"auto",
|
||||
"*/*,application/json;q=0.5",
|
||||
"The client accepts */*, using 'json' from request.accept",
|
||||
),
|
||||
(
|
||||
"",
|
||||
"auto",
|
||||
"*/*",
|
||||
"The client accepts */*, using 'json' from content-type",
|
||||
),
|
||||
(
|
||||
"",
|
||||
"auto",
|
||||
"text/html,text/plain",
|
||||
"The client accepts text/plain, using 'text' from any",
|
||||
),
|
||||
(
|
||||
"",
|
||||
"auto",
|
||||
"text/html,text/plain;q=0.9",
|
||||
"The client accepts text/html, using 'html' from any",
|
||||
),
|
||||
(
|
||||
"html",
|
||||
"json",
|
||||
"application/xml",
|
||||
"No format found, the client accepts [application/xml]",
|
||||
),
|
||||
("", "auto", "*/*", "The client accepts */*, using 'text' from any"),
|
||||
("", "", "*/*", "No format found, the client accepts [*/*]"),
|
||||
# DEPRECATED: remove in 24.3
|
||||
("", "auto", "*/*", "The client accepts */*, using 'json' from request.json"),
|
||||
(
|
||||
"",
|
||||
"auto",
|
||||
"*/*",
|
||||
"The client accepts */*, using 'json' from request.json",
|
||||
),
|
||||
),
|
||||
)
|
||||
def test_guess_mime_logging(caplog, fake_request, route_format, fallback, accept, expected):
|
||||
def test_guess_mime_logging(
|
||||
caplog, fake_request, route_format, fallback, accept, expected
|
||||
):
|
||||
class FakeObject:
|
||||
pass
|
||||
|
||||
fake_request.route = FakeObject()
|
||||
fake_request.route.name = "fakeroute"
|
||||
fake_request.route.extra = FakeObject()
|
||||
@@ -466,6 +522,8 @@ def test_guess_mime_logging(caplog, fake_request, route_format, fallback, accept
|
||||
with caplog.at_level(logging.DEBUG, logger="sanic.root"):
|
||||
guess_mime(fake_request, fallback)
|
||||
|
||||
logmsg, = [r.message for r in caplog.records if r.funcName == "guess_mime"]
|
||||
(logmsg,) = [
|
||||
r.message for r in caplog.records if r.funcName == "guess_mime"
|
||||
]
|
||||
|
||||
assert logmsg == expected
|
||||
|
||||
@@ -23,11 +23,11 @@ from sanic.exceptions import (
|
||||
from sanic.response import text
|
||||
|
||||
|
||||
def dl_to_dict(soup, css_class):
|
||||
def dl_to_dict(soup, dl_id):
|
||||
keys, values = [], []
|
||||
for dl in soup.find_all("dl", {"class": css_class}):
|
||||
for dl in soup.find_all("dl", {"id": dl_id}):
|
||||
for dt in dl.find_all("dt"):
|
||||
keys.append(dt.text.strip())
|
||||
keys.append(dt.text.split(":", 1)[0])
|
||||
for dd in dl.find_all("dd"):
|
||||
values.append(dd.text.strip())
|
||||
return dict(zip(keys, values))
|
||||
@@ -194,10 +194,7 @@ def test_handled_unhandled_exception(exception_app):
|
||||
assert "Internal Server Error" in soup.h1.text
|
||||
|
||||
message = " ".join(soup.p.text.split())
|
||||
assert message == (
|
||||
"The server encountered an internal error and "
|
||||
"cannot complete your request."
|
||||
)
|
||||
assert "The application encountered an unexpected error" in message
|
||||
|
||||
|
||||
def test_exception_in_exception_handler(exception_app):
|
||||
@@ -299,7 +296,7 @@ def test_contextual_exception_context(debug):
|
||||
|
||||
_, response = app.test_client.post("/coffee/html", debug=debug)
|
||||
soup = BeautifulSoup(response.body, "html.parser")
|
||||
dl = dl_to_dict(soup, "context")
|
||||
dl = dl_to_dict(soup, "exception-context")
|
||||
assert response.status == 418
|
||||
assert "Sorry, I cannot brew coffee" in soup.find("p").text
|
||||
assert dl == {"foo": "bar"}
|
||||
@@ -340,7 +337,7 @@ def test_contextual_exception_extra(debug):
|
||||
|
||||
_, response = app.test_client.post("/coffee/html", debug=debug)
|
||||
soup = BeautifulSoup(response.body, "html.parser")
|
||||
dl = dl_to_dict(soup, "extra")
|
||||
dl = dl_to_dict(soup, "exception-extra")
|
||||
assert response.status == 418
|
||||
assert "Found bar" in soup.find("p").text
|
||||
if debug:
|
||||
|
||||
@@ -123,10 +123,10 @@ def test_html_traceback_output_in_debug_mode(exception_handler_app: Sanic):
|
||||
assert "handler_4" in html
|
||||
assert "foo = bar" in html
|
||||
|
||||
summary_text = " ".join(soup.select(".summary")[0].text.split())
|
||||
assert (
|
||||
"NameError: name 'bar' is not defined while handling path /4"
|
||||
) == summary_text
|
||||
summary_text = soup.select("h3")[0].text
|
||||
assert "NameError: name 'bar' is not defined" == summary_text
|
||||
request_text = soup.select("h2")[-1].text
|
||||
assert "GET /4" == request_text
|
||||
|
||||
|
||||
def test_inherited_exception_handler(exception_handler_app: Sanic):
|
||||
@@ -146,11 +146,10 @@ def test_chained_exception_handler(exception_handler_app: Sanic):
|
||||
assert "handler_6" in html
|
||||
assert "foo = 1 / arg" in html
|
||||
assert "ValueError" in html
|
||||
assert "GET /6" in html
|
||||
|
||||
summary_text = " ".join(soup.select(".summary")[0].text.split())
|
||||
assert (
|
||||
"ZeroDivisionError: division by zero while handling path /6/0"
|
||||
) == summary_text
|
||||
summary_text = soup.select("h3")[0].text
|
||||
assert "ZeroDivisionError: division by zero" == summary_text
|
||||
|
||||
|
||||
def test_exception_handler_lookup(exception_handler_app: Sanic):
|
||||
|
||||
@@ -50,7 +50,7 @@ def raised_ceiling():
|
||||
),
|
||||
(
|
||||
'form-data; name="foo"; value="%22\\%0D%0A"',
|
||||
("form-data", {"name": "foo", "value": '\"\\\n'})
|
||||
("form-data", {"name": "foo", "value": '"\\\n'}),
|
||||
),
|
||||
# <input type=file name="foo";bar\"> with Unicode filename!
|
||||
(
|
||||
|
||||
Reference in New Issue
Block a user