Compare commits
73 Commits
main
...
sml-change
Author | SHA1 | Date | |
---|---|---|---|
|
d9f7086ee6 | ||
|
26e999dec0 | ||
|
8f305047c0 | ||
|
59f9b5cc28 | ||
|
94eff28fda | ||
|
c111d93840 | ||
|
3587a4fe15 | ||
|
51a9605668 | ||
|
14f16352fc | ||
|
ecf34896c8 | ||
|
e544cd8af6 | ||
|
aa8af0dcea | ||
|
db0b9046d7 | ||
|
f798eda446 | ||
|
21ad1ae61b | ||
|
d8bf65ad1b | ||
|
844cab2d6b | ||
|
b0cb01d1a4 | ||
|
4c55051442 | ||
|
37f3607ebc | ||
|
7e617c1769 | ||
|
a5f732cc80 | ||
|
ce19908bc0 | ||
|
a6efebda56 | ||
|
da9ff33fa7 | ||
|
526115c3c5 | ||
|
12ba685bf6 | ||
|
39b98e6b45 | ||
|
3ddbda61d9 | ||
|
68bf26df17 | ||
|
a773ad2354 | ||
|
47b2459811 | ||
|
7491d567a3 | ||
|
783a29bc0b | ||
|
cf76c05d3f | ||
|
d6f2613623 | ||
|
a6ff13ceed | ||
|
207f8af11f | ||
|
5c65118d12 | ||
|
f4792a2bc6 | ||
|
53b7a5a5a1 | ||
|
ebc2f46682 | ||
|
ff47448585 | ||
|
2df5b19fd4 | ||
|
5dfd48f855 | ||
|
ddf3a49988 | ||
|
1b43aa5f2f | ||
|
713abe3cf2 | ||
|
b46b81d43a | ||
|
4f000ab59c | ||
|
ae757c8ad6 | ||
|
f30f53f67d | ||
|
ea09906e0a | ||
|
77bdfa14ed | ||
|
faf1ff8d4f | ||
|
b5175238fb | ||
|
32d62c2db4 | ||
|
a00ec8ab37 | ||
|
859a8130c1 | ||
|
2038799d7a | ||
|
41da8bbd61 | ||
|
e328d4406b | ||
|
d9c883eb9b | ||
|
10d4f2803a | ||
|
fa6dbddf69 | ||
|
2c8f1807d8 | ||
|
ca0e933813 | ||
|
2e36507a60 | ||
|
39a4a75dcb | ||
|
e8bb2834d6 | ||
|
36e3cc9df7 | ||
|
fed2ef3527 | ||
|
6673acf544 |
|
@ -1 +1 @@
|
||||||
__version__ = "22.12.0"
|
__version__ = "23.3.0"
|
||||||
|
|
|
@ -157,6 +157,7 @@ class Sanic(StaticHandleMixin, BaseSanic, StartupMixin, metaclass=TouchUpMeta):
|
||||||
"strict_slashes",
|
"strict_slashes",
|
||||||
"websocket_enabled",
|
"websocket_enabled",
|
||||||
"websocket_tasks",
|
"websocket_tasks",
|
||||||
|
"wrappers",
|
||||||
)
|
)
|
||||||
|
|
||||||
_app_registry: Dict[str, "Sanic"] = {}
|
_app_registry: Dict[str, "Sanic"] = {}
|
||||||
|
@ -875,6 +876,8 @@ class Sanic(StaticHandleMixin, BaseSanic, StartupMixin, metaclass=TouchUpMeta):
|
||||||
:param request: HTTP Request object
|
:param request: HTTP Request object
|
||||||
:return: Nothing
|
:return: Nothing
|
||||||
"""
|
"""
|
||||||
|
__tracebackhide__ = True
|
||||||
|
|
||||||
await self.dispatch(
|
await self.dispatch(
|
||||||
"http.lifecycle.handle",
|
"http.lifecycle.handle",
|
||||||
inline=True,
|
inline=True,
|
||||||
|
|
|
@ -40,7 +40,7 @@ FULL_COLOR_LOGO = """
|
||||||
|
|
||||||
""" # noqa
|
""" # noqa
|
||||||
|
|
||||||
SVG_LOGO = """<svg id=logo alt=Sanic viewBox="0 0 964 279"><path d="M107 222c9-2 10-20 1-22s-20-2-30-2-17 7-16 14 6 10 15 10h30zm115-1c16-2 30-11 35-23s6-24 2-33-6-14-15-20-24-11-38-10c-7 3-10 13-5 19s17-1 24 4 15 14 13 24-5 15-14 18-50 0-74 0h-17c-6 4-10 15-4 20s16 2 23 3zM251 83q9-1 9-7 0-15-10-16h-13c-10 6-10 20 0 22zM147 60c-4 0-10 3-11 11s5 13 10 12 42 0 67 0c5-3 7-10 6-15s-4-8-9-8zm-33 1c-8 0-16 0-24 3s-20 10-25 20-6 24-4 36 15 22 26 27 78 8 94 3c4-4 4-12 0-18s-69 8-93-10c-8-7-9-23 0-30s12-10 20-10 12 2 16-3 1-15-5-18z" fill="#ff0d68"/><path d="M676 74c0-14-18-9-20 0s0 30 0 39 20 9 20 2zm-297-10c-12 2-15 12-23 23l-41 58H340l22-30c8-12 23-13 30-4s20 24 24 38-10 10-17 10l-68 2q-17 1-48 30c-7 6-10 20 0 24s15-8 20-13 20 -20 58-21h50 c20 2 33 9 52 30 8 10 24-4 16-13L384 65q-3-2-5-1zm131 0c-10 1-12 12-11 20v96c1 10-3 23 5 32s20-5 17-15c0-23-3-46 2-67 5-12 22-14 32-5l103 87c7 5 19 1 18-9v-64c-3-10-20-9-21 2s-20 22-30 13l-97-80c-5-4-10-10-18-10zM701 76v128c2 10 15 12 20 4s0-102 0-124s-20-18-20-7z M850 63c-35 0-69-2-86 15s-20 60-13 66 13 8 16 0 1-10 1-27 12-26 20-32 66-5 85-5 31 4 31-10-18-7-54-7M764 159c-6-2-15-2-16 12s19 37 33 43 23 8 25-4-4-11-11-14q-9-3-22-18c-4-7-3-16-10-19zM828 196c-4 0-8 1-10 5s-4 12 0 15 8 2 12 2h60c5 0 10-2 12-6 3-7-1-16-8-16z" fill="#e1e1e1"/></svg>""" # noqa
|
SVG_LOGO_SIMPLE = """<svg id=logo-simple viewBox="0 0 964 279"><desc>Sanic</desc><path d="M107 222c9-2 10-20 1-22s-20-2-30-2-17 7-16 14 6 10 15 10h30zm115-1c16-2 30-11 35-23s6-24 2-33-6-14-15-20-24-11-38-10c-7 3-10 13-5 19s17-1 24 4 15 14 13 24-5 15-14 18-50 0-74 0h-17c-6 4-10 15-4 20s16 2 23 3zM251 83q9-1 9-7 0-15-10-16h-13c-10 6-10 20 0 22zM147 60c-4 0-10 3-11 11s5 13 10 12 42 0 67 0c5-3 7-10 6-15s-4-8-9-8zm-33 1c-8 0-16 0-24 3s-20 10-25 20-6 24-4 36 15 22 26 27 78 8 94 3c4-4 4-12 0-18s-69 8-93-10c-8-7-9-23 0-30s12-10 20-10 12 2 16-3 1-15-5-18z" fill="#ff0d68"/><path d="M676 74c0-14-18-9-20 0s0 30 0 39 20 9 20 2zm-297-10c-12 2-15 12-23 23l-41 58H340l22-30c8-12 23-13 30-4s20 24 24 38-10 10-17 10l-68 2q-17 1-48 30c-7 6-10 20 0 24s15-8 20-13 20 -20 58-21h50 c20 2 33 9 52 30 8 10 24-4 16-13L384 65q-3-2-5-1zm131 0c-10 1-12 12-11 20v96c1 10-3 23 5 32s20-5 17-15c0-23-3-46 2-67 5-12 22-14 32-5l103 87c7 5 19 1 18-9v-64c-3-10-20-9-21 2s-20 22-30 13l-97-80c-5-4-10-10-18-10zM701 76v128c2 10 15 12 20 4s0-102 0-124s-20-18-20-7z M850 63c-35 0-69-2-86 15s-20 60-13 66 13 8 16 0 1-10 1-27 12-26 20-32 66-5 85-5 31 4 31-10-18-7-54-7M764 159c-6-2-15-2-16 12s19 37 33 43 23 8 25-4-4-11-11-14q-9-3-22-18c-4-7-3-16-10-19zM828 196c-4 0-8 1-10 5s-4 12 0 15 8 2 12 2h60c5 0 10-2 12-6 3-7-1-16-8-16z" fill="#1f1f1f"/></svg>""" # noqa
|
||||||
|
|
||||||
ansi_pattern = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
|
ansi_pattern = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,7 @@ class Blueprint(BaseSanic):
|
||||||
"version",
|
"version",
|
||||||
"version_prefix",
|
"version_prefix",
|
||||||
"websocket_routes",
|
"websocket_routes",
|
||||||
|
"wrappers",
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|
|
@ -22,6 +22,7 @@ from traceback import extract_tb
|
||||||
|
|
||||||
from sanic.exceptions import BadRequest, SanicException
|
from sanic.exceptions import BadRequest, SanicException
|
||||||
from sanic.helpers import STATUS_CODES
|
from sanic.helpers import STATUS_CODES
|
||||||
|
from sanic.pages.error import ErrorPage
|
||||||
from sanic.response import html, json, text
|
from sanic.response import html, json, text
|
||||||
|
|
||||||
|
|
||||||
|
@ -159,36 +160,21 @@ class HTMLRenderer(BaseRenderer):
|
||||||
"{body}"
|
"{body}"
|
||||||
)
|
)
|
||||||
|
|
||||||
def full(self) -> HTTPResponse:
|
def _page(self, full: bool) -> HTTPResponse:
|
||||||
return html(
|
page = ErrorPage(
|
||||||
self.OUTPUT_HTML.format(
|
title=super().title,
|
||||||
title=self.title,
|
text=super().text,
|
||||||
text=self.text,
|
request=self.request,
|
||||||
style=self.TRACEBACK_STYLE,
|
exc=self.exception,
|
||||||
body=self._generate_body(full=True),
|
full=full,
|
||||||
),
|
|
||||||
status=self.status,
|
|
||||||
)
|
)
|
||||||
|
return html(page.render(), status=self.status, headers=self.headers)
|
||||||
|
|
||||||
|
def full(self) -> HTTPResponse:
|
||||||
|
return self._page(full=True)
|
||||||
|
|
||||||
def minimal(self) -> HTTPResponse:
|
def minimal(self) -> HTTPResponse:
|
||||||
return html(
|
return self._page(full=False)
|
||||||
self.OUTPUT_HTML.format(
|
|
||||||
title=self.title,
|
|
||||||
text=self.text,
|
|
||||||
style=self.TRACEBACK_STYLE,
|
|
||||||
body=self._generate_body(full=False),
|
|
||||||
),
|
|
||||||
status=self.status,
|
|
||||||
headers=self.headers,
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def text(self):
|
|
||||||
return escape(super().text)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def title(self):
|
|
||||||
return escape(f"⚠️ {super().title}")
|
|
||||||
|
|
||||||
def _generate_body(self, *, full):
|
def _generate_body(self, *, full):
|
||||||
lines = []
|
lines = []
|
||||||
|
|
|
@ -14,6 +14,7 @@ class MiddlewareMixin(metaclass=SanicMeta):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs) -> None:
|
def __init__(self, *args, **kwargs) -> None:
|
||||||
self._future_middleware: List[FutureMiddleware] = []
|
self._future_middleware: List[FutureMiddleware] = []
|
||||||
|
self.wrappers = []
|
||||||
|
|
||||||
def _apply_middleware(self, middleware: FutureMiddleware):
|
def _apply_middleware(self, middleware: FutureMiddleware):
|
||||||
raise NotImplementedError # noqa
|
raise NotImplementedError # noqa
|
||||||
|
@ -140,3 +141,7 @@ class MiddlewareMixin(metaclass=SanicMeta):
|
||||||
reverse=True,
|
reverse=True,
|
||||||
)[::-1]
|
)[::-1]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def wrap(self, handler):
|
||||||
|
self.wrappers.append(handler)
|
||||||
|
return handler
|
||||||
|
|
|
@ -267,11 +267,11 @@ class StartupMixin(metaclass=SanicMeta):
|
||||||
if single_process and legacy:
|
if single_process and legacy:
|
||||||
raise RuntimeError("Cannot run single process and legacy mode")
|
raise RuntimeError("Cannot run single process and legacy mode")
|
||||||
|
|
||||||
if register_sys_signals is False and not (single_process or legacy):
|
# if register_sys_signals is False and not (single_process or legacy):
|
||||||
raise RuntimeError(
|
# raise RuntimeError(
|
||||||
"Cannot run Sanic.serve with register_sys_signals=False. "
|
# "Cannot run Sanic.serve with register_sys_signals=False. "
|
||||||
"Use either Sanic.serve_single or Sanic.serve_legacy."
|
# "Use either Sanic.serve_single or Sanic.serve_legacy."
|
||||||
)
|
# )
|
||||||
|
|
||||||
if motd_display:
|
if motd_display:
|
||||||
self.config.MOTD_DISPLAY.update(motd_display)
|
self.config.MOTD_DISPLAY.update(motd_display)
|
||||||
|
|
|
@ -3,16 +3,16 @@ from abc import ABC, abstractmethod
|
||||||
from html5tagger import HTML, Document
|
from html5tagger import HTML, Document
|
||||||
|
|
||||||
from sanic import __version__ as VERSION
|
from sanic import __version__ as VERSION
|
||||||
from sanic.application.logo import SVG_LOGO
|
from sanic.application.logo import SVG_LOGO_SIMPLE
|
||||||
from sanic.pages.css import CSS
|
from sanic.pages.css import CSS
|
||||||
|
|
||||||
|
|
||||||
class BasePage(ABC, metaclass=CSS): # no cov
|
class BasePage(ABC, metaclass=CSS): # no cov
|
||||||
TITLE = "Unknown"
|
TITLE = "Sanic"
|
||||||
CSS: str
|
CSS: str
|
||||||
|
|
||||||
def __init__(self, debug: bool = True) -> None:
|
def __init__(self, debug: bool = True) -> None:
|
||||||
self.doc = Document(self.TITLE, lang="en")
|
self.doc = None
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -20,6 +20,7 @@ class BasePage(ABC, metaclass=CSS): # no cov
|
||||||
return self.CSS
|
return self.CSS
|
||||||
|
|
||||||
def render(self) -> str:
|
def render(self) -> str:
|
||||||
|
self.doc = Document(self.TITLE, lang="en")
|
||||||
self._head()
|
self._head()
|
||||||
self._body()
|
self._body()
|
||||||
self._foot()
|
self._foot()
|
||||||
|
@ -44,7 +45,7 @@ class BasePage(ABC, metaclass=CSS): # no cov
|
||||||
|
|
||||||
def _sanic_logo(self) -> None:
|
def _sanic_logo(self) -> None:
|
||||||
self.doc.a(
|
self.doc.a(
|
||||||
HTML(SVG_LOGO),
|
HTML(SVG_LOGO_SIMPLE),
|
||||||
href="https://sanic.dev",
|
href="https://sanic.dev",
|
||||||
target="_blank",
|
target="_blank",
|
||||||
referrerpolicy="no-referrer",
|
referrerpolicy="no-referrer",
|
||||||
|
|
|
@ -24,8 +24,8 @@ class CSS(ABCMeta):
|
||||||
def __new__(cls, name, bases, attrs):
|
def __new__(cls, name, bases, attrs):
|
||||||
Page = super().__new__(cls, name, bases, attrs)
|
Page = super().__new__(cls, name, bases, attrs)
|
||||||
# Use a locally defined STYLE or the one from styles directory
|
# Use a locally defined STYLE or the one from styles directory
|
||||||
s = _extract_style(attrs.get("STYLE"), name)
|
Page.STYLE = _extract_style(attrs.get("STYLE_FILE"), name)
|
||||||
Page.STYLE = f"\n/* {name} */\n{s.strip()}\n" if s else ""
|
Page.STYLE += attrs.get("STYLE_APPEND", "")
|
||||||
# Combine with all ancestor styles
|
# Combine with all ancestor styles
|
||||||
Page.CSS = "".join(
|
Page.CSS = "".join(
|
||||||
Class.STYLE
|
Class.STYLE
|
||||||
|
|
105
sanic/pages/error.py
Normal file
105
sanic/pages/error.py
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
from typing import Any, Mapping
|
||||||
|
|
||||||
|
import tracerite.html
|
||||||
|
|
||||||
|
from html5tagger import E
|
||||||
|
from tracerite import html_traceback, inspector
|
||||||
|
|
||||||
|
from sanic.request import Request
|
||||||
|
|
||||||
|
from .base import BasePage
|
||||||
|
|
||||||
|
|
||||||
|
# Avoid showing the request in the traceback variable inspectors
|
||||||
|
inspector.blacklist_types += (Request,)
|
||||||
|
|
||||||
|
ENDUSER_TEXT = """We're sorry, but it looks like something went wrong. Please try refreshing the page or navigating back to the homepage. If the issue persists, our technical team is working to resolve it as soon as possible. We apologize for the inconvenience and appreciate your patience.""" # noqa: E501
|
||||||
|
|
||||||
|
|
||||||
|
class ErrorPage(BasePage):
|
||||||
|
STYLE_APPEND = tracerite.html.style
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
title: str,
|
||||||
|
text: str,
|
||||||
|
request: Request,
|
||||||
|
exc: Exception,
|
||||||
|
full: bool,
|
||||||
|
) -> None:
|
||||||
|
super().__init__()
|
||||||
|
# Internal server errors come with the text of the exception,
|
||||||
|
# which we don't want to show to the user.
|
||||||
|
# FIXME: Needs to be done in a better way, elsewhere
|
||||||
|
if "Internal Server Error" in title:
|
||||||
|
text = "The application encountered an unexpected error and could not continue." # noqa: E501
|
||||||
|
name = request.app.name.replace("_", " ").strip()
|
||||||
|
if name.islower():
|
||||||
|
name = name.title()
|
||||||
|
self.TITLE = E("Application ").strong(name)(
|
||||||
|
" cannot handle your request"
|
||||||
|
)
|
||||||
|
self.title = title
|
||||||
|
self.text = text
|
||||||
|
self.request = request
|
||||||
|
self.exc = exc
|
||||||
|
self.full = full
|
||||||
|
|
||||||
|
def _head(self) -> None:
|
||||||
|
self.doc._script(tracerite.html.javascript)
|
||||||
|
super()._head()
|
||||||
|
|
||||||
|
def _body(self) -> None:
|
||||||
|
debug = self.request.app.debug
|
||||||
|
try:
|
||||||
|
route_name = self.request.route.name
|
||||||
|
except AttributeError:
|
||||||
|
route_name = "[route not found]"
|
||||||
|
with self.doc.main:
|
||||||
|
self.doc.h1(f"⚠️ {self.title}").p(self.text)
|
||||||
|
# Show context details if available on the exception
|
||||||
|
context = getattr(self.exc, "context", None)
|
||||||
|
if context:
|
||||||
|
self._key_value_table(
|
||||||
|
"Issue context", "exception-context", context
|
||||||
|
)
|
||||||
|
|
||||||
|
if not debug:
|
||||||
|
with self.doc.div(id="enduser"):
|
||||||
|
self.doc.p(ENDUSER_TEXT).p.a("Front Page", href="/")
|
||||||
|
return
|
||||||
|
# Show additional details in debug mode,
|
||||||
|
# open by default for 500 errors
|
||||||
|
with self.doc.details(open=self.full, class_="smalltext"):
|
||||||
|
# Show extra details if available on the exception
|
||||||
|
extra = getattr(self.exc, "extra", None)
|
||||||
|
if extra:
|
||||||
|
self._key_value_table(
|
||||||
|
"Issue extra data", "exception-extra", extra
|
||||||
|
)
|
||||||
|
|
||||||
|
self.doc.summary(
|
||||||
|
"Details for developers (Sanic debug mode only)"
|
||||||
|
)
|
||||||
|
if self.exc:
|
||||||
|
self.doc.h2(f"Exception in {route_name}:")
|
||||||
|
self.doc(html_traceback(self.exc, include_js_css=False))
|
||||||
|
|
||||||
|
self._key_value_table(
|
||||||
|
f"{self.request.method} {self.request.path}",
|
||||||
|
"request-headers",
|
||||||
|
self.request.headers,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _key_value_table(
|
||||||
|
self, title: str, table_id: str, data: Mapping[str, Any]
|
||||||
|
) -> None:
|
||||||
|
self.doc.h2(title)
|
||||||
|
with self.doc.dl(id=table_id, class_="key-value-table smalltext"):
|
||||||
|
for key, value in data.items():
|
||||||
|
# Reading values may cause a new exception, so suppress it
|
||||||
|
try:
|
||||||
|
value = str(value)
|
||||||
|
except Exception:
|
||||||
|
value = E.em("Unable to display value")
|
||||||
|
self.doc.dt.span(key, class_="nobr key").span(": ").dd(value)
|
|
@ -1,28 +1,76 @@
|
||||||
|
/** BasePage **/
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--sanic: #ff0d68;
|
||||||
|
--sanic-blue: #0092FF;
|
||||||
|
--sanic-yellow: #FFE900;
|
||||||
|
--sanic-purple: #833FE3;
|
||||||
|
--sanic-green: #37ae6f;
|
||||||
|
--sanic-background: #f1f5f9;
|
||||||
|
--sanic-text: #1f2937;
|
||||||
|
--sanic-tab-background: #fff;
|
||||||
|
--sanic-tab-text: #0f172a;
|
||||||
|
--sanic-tab-shadow: #adadad;
|
||||||
|
--sanic-highlight-background: var(--sanic-yellow);
|
||||||
|
--sanic-highlight-text: var(--sanic-text);
|
||||||
|
--sanic-header-background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--sanic-purple: #D246DE;
|
||||||
|
--sanic-green: #16DB93;
|
||||||
|
--sanic-background: #111;
|
||||||
|
--sanic-text: #e7e7e7;
|
||||||
|
--sanic-tab-background: #484848;
|
||||||
|
--sanic-tab-text: #e1e1e1;
|
||||||
|
--sanic-tab-shadow: #000;
|
||||||
|
--sanic-highlight-background: var(--sanic-yellow);
|
||||||
|
--sanic-highlight-text: #000;
|
||||||
|
--sanic-header-background: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
font: 16px sans-serif;
|
font: 16px sans-serif;
|
||||||
background: #eee;
|
background: var(--sanic-background);
|
||||||
color: #111;
|
color: var(--sanic-text);
|
||||||
|
scrollbar-gutter: stable;
|
||||||
|
overflow: hidden auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
|
line-height: 125%;
|
||||||
}
|
}
|
||||||
|
|
||||||
body>* {
|
body>* {
|
||||||
padding: 1rem 2vw;
|
padding: 1rem 2vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1200px) {
|
@media (max-width: 1000px) {
|
||||||
body>* {
|
body>* {
|
||||||
padding: 0.5rem 1.5vw;
|
padding: 0.5rem 1.5vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
html {
|
||||||
font-size: 1rem;
|
/* Scale everything by rem of 6px-16px by viewport width */
|
||||||
|
font-size: calc(6px + 10 * 100vw / 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
min-height: 70vh;
|
||||||
|
/* Make sure the footer is closer to bottom */
|
||||||
|
padding: 1rem 2.5rem;
|
||||||
|
/* Generous padding for readability */
|
||||||
|
}
|
||||||
|
|
||||||
|
.smalltext {
|
||||||
|
font-size: 1.0rem;
|
||||||
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
min-width: 600px;
|
min-width: 600px;
|
||||||
max-width: 1600px;
|
max-width: 1600px;
|
||||||
|
@ -62,18 +110,19 @@ a:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#logo {
|
|
||||||
height: 1.75rem;
|
|
||||||
padding: 0 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.icon {
|
span.icon {
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#logo-simple {
|
||||||
|
height: 1.75rem;
|
||||||
|
padding: 0 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
html {
|
#logo-simple path:last-child {
|
||||||
background: #111;
|
fill: #e1e1e1;
|
||||||
color: #ccc;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/** DirectoryPage **/
|
||||||
#breadcrumbs>a:hover {
|
#breadcrumbs>a:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
105
sanic/pages/styles/ErrorPage.css
Normal file
105
sanic/pages/styles/ErrorPage.css
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/** ErrorPage **/
|
||||||
|
#enduser {
|
||||||
|
max-width: 30em;
|
||||||
|
margin: 5em auto 5em auto;
|
||||||
|
text-align: justify;
|
||||||
|
/*text-justify: both;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#enduser a {
|
||||||
|
color: var(--sanic-blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
#enduser p:last-child {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary {
|
||||||
|
margin-top: 3em;
|
||||||
|
color: var(--sanic-blue);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracerite {
|
||||||
|
--tracerite-var: var(--sanic-blue);
|
||||||
|
--tracerite-val: var(--sanic-text);
|
||||||
|
--tracerite-type: var(--sanic-green);
|
||||||
|
--tracerite-exception: var(--sanic);
|
||||||
|
--tracerite-highlight: var(--sanic-yellow);
|
||||||
|
--tracerite-tab: var(--sanic-tab-background);
|
||||||
|
--tracerite-tab-text: var(--sanic-tab-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracerite>h3 {
|
||||||
|
margin: 0.5rem 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracerite .traceback-labels button {
|
||||||
|
font-size: 0.8rem !important;
|
||||||
|
line-height: 120% !important;
|
||||||
|
background: var(--tracerite-tab) !important;
|
||||||
|
color: var(--tracerite-tab-text) !important;
|
||||||
|
transition: 0.3s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracerite .traceback-labels {
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracerite .traceback-labels button:hover {
|
||||||
|
filter: contrast(150%) brightness(120%) drop-shadow(0 -0 2px var(--sanic-tab-shadow));
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracerite .traceback-details mark span {
|
||||||
|
background: var(--sanic-highlight-background) !important;
|
||||||
|
color: var(--sanic-highlight-text) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
background: var(--sanic-header-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
/*margin-left: -1.5rem; !* Emoji partially in the left margin *!*/
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 1em 0 0.2em 0;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: var(--sanic-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.key-value-table {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 5fr;
|
||||||
|
grid-gap: .3em;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.key-value-table * {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.key-value-table dt {
|
||||||
|
color: #888;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.key-value-table dd {
|
||||||
|
word-break: break-all;
|
||||||
|
/* Better breaking for cookies header and such */
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracerite .codeline {
|
||||||
|
font-family:
|
||||||
|
"Fira Code",
|
||||||
|
"Source Code Pro",
|
||||||
|
Menlo,
|
||||||
|
Monaco,
|
||||||
|
Consolas,
|
||||||
|
Lucida Console,
|
||||||
|
monospace;
|
||||||
|
}
|
|
@ -39,13 +39,13 @@ class Router(BaseRouter):
|
||||||
extra={"host": host} if host else None,
|
extra={"host": host} if host else None,
|
||||||
)
|
)
|
||||||
except RoutingNotFound as e:
|
except RoutingNotFound as e:
|
||||||
raise NotFound("Requested URL {} not found".format(e.path))
|
raise NotFound(f"Requested URL {e.path} not found") from None
|
||||||
except NoMethod as e:
|
except NoMethod as e:
|
||||||
raise MethodNotAllowed(
|
raise MethodNotAllowed(
|
||||||
"Method {} not allowed for URL {}".format(method, path),
|
f"Method {method} not allowed for URL {path}",
|
||||||
method=method,
|
method=method,
|
||||||
allowed_methods=e.allowed_methods,
|
allowed_methods=e.allowed_methods,
|
||||||
)
|
) from None
|
||||||
|
|
||||||
@lru_cache(maxsize=ROUTER_CACHE_SIZE)
|
@lru_cache(maxsize=ROUTER_CACHE_SIZE)
|
||||||
def get( # type: ignore
|
def get( # type: ignore
|
||||||
|
@ -61,6 +61,7 @@ class Router(BaseRouter):
|
||||||
correct response
|
correct response
|
||||||
:rtype: Tuple[ Route, RouteHandler, Dict[str, Any]]
|
:rtype: Tuple[ Route, RouteHandler, Dict[str, Any]]
|
||||||
"""
|
"""
|
||||||
|
__tracebackhide__ = True
|
||||||
return self._get(path, method, host)
|
return self._get(path, method, host)
|
||||||
|
|
||||||
def add( # type: ignore
|
def add( # type: ignore
|
||||||
|
|
|
@ -130,13 +130,14 @@ def _setup_system_signals(
|
||||||
register_sys_signals: bool,
|
register_sys_signals: bool,
|
||||||
loop: asyncio.AbstractEventLoop,
|
loop: asyncio.AbstractEventLoop,
|
||||||
) -> None: # no cov
|
) -> None: # no cov
|
||||||
|
print(">>>>>>>>>>>>>>>>>.", run_multiple)
|
||||||
# Ignore SIGINT when run_multiple
|
# Ignore SIGINT when run_multiple
|
||||||
if run_multiple:
|
if run_multiple:
|
||||||
signal_func(SIGINT, SIG_IGN)
|
signal_func(SIGINT, SIG_IGN)
|
||||||
os.environ["SANIC_WORKER_PROCESS"] = "true"
|
os.environ["SANIC_WORKER_PROCESS"] = "true"
|
||||||
|
|
||||||
# Register signals for graceful termination
|
# Register signals for graceful termination
|
||||||
if register_sys_signals:
|
if register_sys_signals and False:
|
||||||
if OS_IS_WINDOWS:
|
if OS_IS_WINDOWS:
|
||||||
ctrlc_workaround_for_windows(app)
|
ctrlc_workaround_for_windows(app)
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user