Merge branch 'main' of github.com:sanic-org/sanic into feat/optional-uvloop-use

This commit is contained in:
prryplatypus 2021-10-24 21:09:52 +02:00
commit 348c358d72
No known key found for this signature in database
GPG Key ID: 6687E128FB70819B
6 changed files with 104 additions and 22 deletions

View File

@ -68,6 +68,7 @@ from sanic.models.futures import (
FutureStatic,
)
from sanic.models.handler_types import ListenerType, MiddlewareType
from sanic.models.handler_types import Sanic as SanicVar
from sanic.request import Request
from sanic.response import BaseHTTPResponse, HTTPResponse
from sanic.router import Router
@ -184,7 +185,7 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
)
self.is_running = False
self.is_stopping = False
self.listeners: Dict[str, List[ListenerType]] = defaultdict(list)
self.listeners: Dict[str, List[ListenerType[Any]]] = defaultdict(list)
self.named_request_middleware: Dict[str, Deque[MiddlewareType]] = {}
self.named_response_middleware: Dict[str, Deque[MiddlewareType]] = {}
self.reload_dirs: Set[Path] = set()
@ -196,7 +197,7 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
self.sock = None
self.strict_slashes = strict_slashes
self.websocket_enabled = False
self.websocket_tasks: Set[Future] = set()
self.websocket_tasks: Set[Future[Any]] = set()
# Register alternative method names
self.go_fast = self.run
@ -232,7 +233,10 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
# Registration
# -------------------------------------------------------------------- #
def add_task(self, task) -> None:
def add_task(
self,
task: Union[Future[Any], Coroutine[Any, Any, Any], Awaitable[Any]],
) -> None:
"""
Schedule a task to run later, after the loop has started.
Different from asyncio.ensure_future in that it does not
@ -255,7 +259,9 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
self.signal(task_name)(partial(self.run_delayed_task, task=task))
self._delayed_tasks.append(task_name)
def register_listener(self, listener: Callable, event: str) -> Any:
def register_listener(
self, listener: ListenerType[SanicVar], event: str
) -> ListenerType[SanicVar]:
"""
Register the listener for a given event.
@ -281,7 +287,9 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
return listener
def register_middleware(self, middleware, attach_to: str = "request"):
def register_middleware(
self, middleware: MiddlewareType, attach_to: str = "request"
) -> MiddlewareType:
"""
Register an application level middleware that will be attached
to all the API URLs registered under this application.
@ -307,7 +315,7 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
def register_named_middleware(
self,
middleware,
middleware: MiddlewareType,
route_names: Iterable[str],
attach_to: str = "request",
):
@ -1337,7 +1345,9 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
if unix:
logger.info(f"Goin' Fast @ {unix} {proto}://...")
else:
logger.info(f"Goin' Fast @ {proto}://{host}:{port}")
# colon(:) is legal for a host only in an ipv6 address
display_host = f"[{host}]" if ":" in host else host
logger.info(f"Goin' Fast @ {proto}://{display_host}:{port}")
debug_mode = "enabled" if self.debug else "disabled"
reload_mode = "enabled" if auto_reload else "disabled"

View File

@ -23,7 +23,7 @@ class BaseSanic(
):
__fake_slots__: Tuple[str, ...]
def __init__(self, name: str = None, *args, **kwargs) -> None:
def __init__(self, name: str = None, *args: Any, **kwargs: Any) -> None:
class_name = self.__class__.__name__
if name is None:

View File

@ -208,7 +208,7 @@ class BlueprintGroup(MutableSequence):
:param args: List of Python exceptions to be caught by the handler
:param kwargs: Additional optional arguments to be passed to the
exception handler
:return a decorated method to handle global exceptions for any
:return: a decorated method to handle global exceptions for any
blueprint registered under this group.
"""

View File

@ -5,7 +5,16 @@ import asyncio
from collections import defaultdict
from copy import deepcopy
from types import SimpleNamespace
from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Set, Union
from typing import (
TYPE_CHECKING,
Any,
Dict,
Iterable,
List,
Optional,
Set,
Union,
)
from sanic_routing.exceptions import NotFound # type: ignore
from sanic_routing.route import Route # type: ignore
@ -142,7 +151,7 @@ class Blueprint(BaseSanic):
def reset(self):
self._apps: Set[Sanic] = set()
self.exceptions: List[RouteHandler] = []
self.listeners: Dict[str, List[ListenerType]] = {}
self.listeners: Dict[str, List[ListenerType[Any]]] = {}
self.middlewares: List[MiddlewareType] = []
self.routes: List[Route] = []
self.statics: List[RouteHandler] = []
@ -221,7 +230,7 @@ class Blueprint(BaseSanic):
version: Optional[Union[int, str, float]] = None,
strict_slashes: Optional[bool] = None,
version_prefix: str = "/v",
):
) -> BlueprintGroup:
"""
Create a list of blueprints, optionally grouping them under a
general URL prefix.

View File

@ -3,7 +3,7 @@ from functools import partial
from typing import List, Optional, Union
from sanic.models.futures import FutureListener
from sanic.models.handler_types import ListenerType
from sanic.models.handler_types import ListenerType, Sanic
class ListenerEvent(str, Enum):
@ -27,10 +27,10 @@ class ListenerMixin:
def listener(
self,
listener_or_event: Union[ListenerType, str],
listener_or_event: Union[ListenerType[Sanic], str],
event_or_none: Optional[str] = None,
apply: bool = True,
):
) -> ListenerType[Sanic]:
"""
Create a listener from a decorated function.
@ -62,20 +62,32 @@ class ListenerMixin:
else:
return partial(register_listener, event=listener_or_event)
def main_process_start(self, listener: ListenerType) -> ListenerType:
def main_process_start(
self, listener: ListenerType[Sanic]
) -> ListenerType[Sanic]:
return self.listener(listener, "main_process_start")
def main_process_stop(self, listener: ListenerType) -> ListenerType:
def main_process_stop(
self, listener: ListenerType[Sanic]
) -> ListenerType[Sanic]:
return self.listener(listener, "main_process_stop")
def before_server_start(self, listener: ListenerType) -> ListenerType:
def before_server_start(
self, listener: ListenerType[Sanic]
) -> ListenerType[Sanic]:
return self.listener(listener, "before_server_start")
def after_server_start(self, listener: ListenerType) -> ListenerType:
def after_server_start(
self, listener: ListenerType[Sanic]
) -> ListenerType[Sanic]:
return self.listener(listener, "after_server_start")
def before_server_stop(self, listener: ListenerType) -> ListenerType:
def before_server_stop(
self, listener: ListenerType[Sanic]
) -> ListenerType[Sanic]:
return self.listener(listener, "before_server_stop")
def after_server_stop(self, listener: ListenerType) -> ListenerType:
def after_server_stop(
self, listener: ListenerType[Sanic]
) -> ListenerType[Sanic]:
return self.listener(listener, "after_server_stop")

View File

@ -52,7 +52,7 @@ def test_server_run(appname):
("-H", "localhost", "-p", "9999"),
),
)
def test_host_port(cmd):
def test_host_port_localhost(cmd):
command = ["sanic", "fake.server.app", *cmd]
out, err, exitcode = capture(command)
lines = out.split(b"\n")
@ -62,6 +62,57 @@ def test_host_port(cmd):
assert firstline == b"Goin' Fast @ http://localhost:9999"
@pytest.mark.parametrize(
"cmd",
(
("--host=127.0.0.127", "--port=9999"),
("-H", "127.0.0.127", "-p", "9999"),
),
)
def test_host_port_ipv4(cmd):
command = ["sanic", "fake.server.app", *cmd]
out, err, exitcode = capture(command)
lines = out.split(b"\n")
firstline = lines[6]
assert exitcode != 1
assert firstline == b"Goin' Fast @ http://127.0.0.127:9999"
@pytest.mark.parametrize(
"cmd",
(
("--host=::", "--port=9999"),
("-H", "::", "-p", "9999"),
),
)
def test_host_port_ipv6_any(cmd):
command = ["sanic", "fake.server.app", *cmd]
out, err, exitcode = capture(command)
lines = out.split(b"\n")
firstline = lines[6]
assert exitcode != 1
assert firstline == b"Goin' Fast @ http://[::]:9999"
@pytest.mark.parametrize(
"cmd",
(
("--host=::1", "--port=9999"),
("-H", "::1", "-p", "9999"),
),
)
def test_host_port_ipv6_loopback(cmd):
command = ["sanic", "fake.server.app", *cmd]
out, err, exitcode = capture(command)
lines = out.split(b"\n")
firstline = lines[6]
assert exitcode != 1
assert firstline == b"Goin' Fast @ http://[::1]:9999"
@pytest.mark.parametrize(
"num,cmd",
(