Cleanup type checking

This commit is contained in:
Adam Hopkins 2021-02-21 21:29:41 +02:00
parent 209579f280
commit d402d0362e
9 changed files with 63 additions and 35 deletions

View File

@ -243,6 +243,7 @@ class Sanic(BaseSanic):
self.named_response_middleware[_rn] = deque()
if middleware not in self.named_response_middleware[_rn]:
self.named_response_middleware[_rn].appendleft(middleware)
return middleware
def _apply_exception_handler(self, handler: FutureException):
"""Decorate a function to be registered as a handler for exceptions
@ -257,12 +258,12 @@ class Sanic(BaseSanic):
self.error_handler.add(e, handler.handler)
else:
self.error_handler.add(exception, handler.handler)
return handler
return handler.handler
def _apply_listener(self, listener: FutureListener):
return self.register_listener(listener.listener, listener.event)
def _apply_route(self, route: FutureRoute) -> Route:
def _apply_route(self, route: FutureRoute) -> List[Route]:
params = route._asdict()
websocket = params.pop("websocket", False)
subprotocols = params.pop("subprotocols", None)
@ -277,7 +278,15 @@ class Sanic(BaseSanic):
websocket_handler.__name__ = route.handler.__name__ # type: ignore
websocket_handler.is_websocket = True # type: ignore
params["handler"] = websocket_handler
return self.router.add(**params)
routes = self.router.add(**params)
if isinstance(routes, Route):
routes = [routes]
for r in routes:
r.ctx.websocket = websocket
r.ctx.static = params.get("static", False)
return routes
def _apply_static(self, static: FutureStatic) -> Route:
return self._register_static(static)

View File

@ -1,8 +1,11 @@
from collections import defaultdict
from typing import Optional
from typing import Dict, List, Optional
from sanic_routing.route import Route # type: ignore
from sanic.base import BaseSanic
from sanic.blueprint_group import BlueprintGroup
from sanic.handlers import ListenerType, MiddlewareType, RouteHandler
from sanic.models.futures import FutureRoute, FutureStatic
@ -37,12 +40,12 @@ class Blueprint(BaseSanic):
self.url_prefix = url_prefix
self.host = host
self.routes = []
self.websocket_routes = []
self.exceptions = []
self.listeners = defaultdict(list)
self.middlewares = []
self.statics = []
self.routes: List[Route] = []
self.websocket_routes: List[Route] = []
self.exceptions: List[RouteHandler] = []
self.listeners: Dict[str, List[ListenerType]] = {}
self.middlewares: List[MiddlewareType] = []
self.statics: List[RouteHandler] = []
self.version = version
self.strict_slashes = strict_slashes
@ -107,6 +110,9 @@ class Blueprint(BaseSanic):
url_prefix = options.get("url_prefix", self.url_prefix)
routes = []
middleware = []
exception_handlers = []
listeners = defaultdict(list)
# Routes
for future in self._future_routes:
@ -159,12 +165,22 @@ class Blueprint(BaseSanic):
# Middleware
if route_names:
for future in self._future_middleware:
app._apply_middleware(future, route_names)
middleware.append(app._apply_middleware(future, route_names))
# Exceptions
for future in self._future_exceptions:
app._apply_exception_handler(future)
exception_handlers.append(app._apply_exception_handler(future))
# Event listeners
for listener in self._future_listeners:
app._apply_listener(listener)
listeners[listener.event].append(app._apply_listener(listener))
self.routes = [route for route in routes if isinstance(route, Route)]
# Deprecate these in 21.6
self.websocket_routes = [
route for route in self.routes if route.ctx.websocket
]
self.middlewares = middleware
self.exceptions = exception_handlers
self.listeners = dict(listeners)

View File

@ -113,8 +113,8 @@ class Config(dict):
config.update_config("${some}/py/file")
Yes you can put environment variable here, but they must be provided
in format: ``${some_env_var}``, and mark that ``$some_env_var`` is treated
as plain string.
in format: ``${some_env_var}``, and mark that ``$some_env_var`` is
treated as plain string.
You can upload app config by providing dict holding settings.
@ -134,7 +134,8 @@ class Config(dict):
config.update_config(C)
`See user guide <https://sanicframework.org/guide/deployment/configuration.html>`__
`See user guide
<https://sanicframework.org/guide/deployment/configuration.html>`__
"""
if isinstance(config, (bytes, str, Path)):

View File

@ -1,5 +1,6 @@
"""
Sanic `provides a pattern <https://sanicframework.org/guide/best-practices/exceptions.html#using-sanic-exceptions>`_
Sanic `provides a pattern
<https://sanicframework.org/guide/best-practices/exceptions.html#using-sanic-exceptions>`_
for providing a response when an exception occurs. However, if you do no handle
an exception, it will provide a fallback. There are three fallback types:
@ -72,9 +73,9 @@ class BaseRenderer:
status_text = STATUS_CODES.get(self.status, b"Error Occurred").decode()
return f"{self.status}{status_text}"
def render(self) -> str:
def render(self) -> HTTPResponse:
"""
Outputs the exception as a ``str`` for response.
Outputs the exception as a :class:`HTTPResponse`.
:return: The formatted exception
:rtype: str
@ -86,14 +87,14 @@ class BaseRenderer:
)
return output()
def minimal(self) -> str: # noqa
def minimal(self) -> HTTPResponse: # noqa
"""
Provide a formatted message that is meant to not show any sensitive
data or details.
"""
raise NotImplementedError
def full(self) -> str: # noqa
def full(self) -> HTTPResponse: # noqa
"""
Provide a formatted message that has all details and is mean to be used
primarily for debugging and non-production environments.
@ -145,7 +146,7 @@ class HTMLRenderer(BaseRenderer):
"{body}"
)
def full(self):
def full(self) -> HTTPResponse:
return html(
self.OUTPUT_HTML.format(
title=self.title,
@ -156,7 +157,7 @@ class HTMLRenderer(BaseRenderer):
status=self.status,
)
def minimal(self):
def minimal(self) -> HTTPResponse:
return html(
self.OUTPUT_HTML.format(
title=self.title,
@ -217,7 +218,7 @@ class TextRenderer(BaseRenderer):
OUTPUT_TEXT = "{title}\n{bar}\n{text}\n\n{body}"
SPACER = " "
def full(self):
def full(self) -> HTTPResponse:
return text(
self.OUTPUT_TEXT.format(
title=self.title,
@ -228,7 +229,7 @@ class TextRenderer(BaseRenderer):
status=self.status,
)
def minimal(self):
def minimal(self) -> HTTPResponse:
return text(
self.OUTPUT_TEXT.format(
title=self.title,
@ -277,11 +278,11 @@ class JSONRenderer(BaseRenderer):
Render an exception as JSON.
"""
def full(self):
def full(self) -> HTTPResponse:
output = self._generate_output(full=True)
return json(output, status=self.status, dumps=dumps)
def minimal(self):
def minimal(self) -> HTTPResponse:
output = self._generate_output(full=False)
return json(output, status=self.status, dumps=dumps)

View File

@ -1,6 +1,6 @@
from enum import Enum, auto
from functools import partial
from typing import Any, Callable, Coroutine, List, Optional, Set, Union
from typing import Any, Callable, Coroutine, List, Optional, Union
from sanic.models.futures import FutureListener

View File

@ -30,7 +30,7 @@ class RouteMixin:
self._future_routes: Set[FutureRoute] = set()
self._future_statics: Set[FutureStatic] = set()
self.name = ""
self.strict_slashes = False
self.strict_slashes: Optional[bool] = False
def _apply_route(self, route: FutureRoute) -> Route:
raise NotImplementedError # noqa
@ -41,7 +41,7 @@ class RouteMixin:
def route(
self,
uri: str,
methods: Iterable[str] = frozenset({"GET"}),
methods: Optional[Iterable[str]] = None,
host: Optional[str] = None,
strict_slashes: Optional[bool] = None,
stream: bool = False,

View File

@ -21,7 +21,6 @@ if TYPE_CHECKING:
import email.utils
import uuid
from asyncio.transports import Transport
from collections import defaultdict
from http.cookies import SimpleCookie
from types import SimpleNamespace
@ -39,6 +38,7 @@ from sanic.headers import (
parse_xforwarded,
)
from sanic.log import error_logger, logger
from sanic.models.protocol_types import TransportProtocol
from sanic.response import BaseHTTPResponse, HTTPResponse
@ -116,7 +116,7 @@ class Request:
headers: Header,
version: str,
method: str,
transport: Transport,
transport: TransportProtocol,
app: Sanic,
):
self.raw_url = url_bytes
@ -148,7 +148,7 @@ class Request:
self.uri_template: Optional[str] = None
self.request_middleware_started = False
self._cookies: Optional[Dict[str, str]] = None
self._match_info = {}
self._match_info: Dict[str, Any] = {}
self.stream: Optional[Http] = None
self.endpoint: Optional[str] = None

View File

@ -33,7 +33,7 @@ class Router(BaseRouter):
@lru_cache(maxsize=ROUTER_CACHE_SIZE)
def _get(
self, path, method, host
) -> Tuple[RouteHandler, Dict[str, Any], str, str, bool,]:
) -> Tuple[RouteHandler, Dict[str, Any], str, str, bool]:
try:
route, handler, params = self.resolve(
path=path,

View File

@ -40,6 +40,7 @@ from sanic.config import Config
from sanic.exceptions import RequestTimeout, ServiceUnavailable
from sanic.http import Http, Stage
from sanic.log import logger
from sanic.models.protocol_types import TransportProtocol
from sanic.request import Request
@ -69,7 +70,7 @@ class ConnInfo:
"ssl",
)
def __init__(self, transport: Transport, unix=None):
def __init__(self, transport: TransportProtocol, unix=None):
self.ssl: bool = bool(transport.get_extra_info("sslcontext"))
self.server = self.client = ""
self.server_port = self.client_port = 0