parent
927c0e082e
commit
6fc3381229
|
@ -21,6 +21,12 @@ matrix:
|
|||
dist: xenial
|
||||
sudo: true
|
||||
name: "Python 3.7 without Extensions"
|
||||
- env: TOX_ENV=type-checking
|
||||
python: 3.6
|
||||
name: "Python 3.6 Type checks"
|
||||
- env: TOX_ENV=type-checking
|
||||
python: 3.7
|
||||
name: "Python 3.7 Type checks"
|
||||
- env: TOX_ENV=lint
|
||||
python: 3.6
|
||||
name: "Python 3.6 Linter checks"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from argparse import ArgumentParser
|
||||
from importlib import import_module
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from sanic.app import Sanic
|
||||
from sanic.log import logger
|
||||
|
@ -35,7 +36,10 @@ if __name__ == "__main__":
|
|||
)
|
||||
)
|
||||
if args.cert is not None or args.key is not None:
|
||||
ssl = {"cert": args.cert, "key": args.key}
|
||||
ssl = {
|
||||
"cert": args.cert,
|
||||
"key": args.key,
|
||||
} # type: Optional[Dict[str, Any]]
|
||||
else:
|
||||
ssl = None
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ from inspect import getmodulename, isawaitable, signature, stack
|
|||
from socket import socket
|
||||
from ssl import Purpose, SSLContext, create_default_context
|
||||
from traceback import format_exc
|
||||
from typing import Any, Optional, Type, Union
|
||||
from typing import Any, Dict, Optional, Type, Union
|
||||
from urllib.parse import urlencode, urlunparse
|
||||
|
||||
from sanic import reloader_helpers
|
||||
|
@ -768,7 +768,7 @@ class Sanic:
|
|||
URLBuildError
|
||||
"""
|
||||
# find the route by the supplied view name
|
||||
kw = {}
|
||||
kw: Dict[str, str] = {}
|
||||
# special static files url_for
|
||||
if view_name == "static":
|
||||
kw.update(name=kwargs.pop("name", "static"))
|
||||
|
|
|
@ -2,9 +2,23 @@ import asyncio
|
|||
import warnings
|
||||
|
||||
from inspect import isawaitable
|
||||
from typing import Any, Awaitable, Callable, MutableMapping, Union
|
||||
from typing import (
|
||||
Any,
|
||||
Awaitable,
|
||||
Callable,
|
||||
Dict,
|
||||
List,
|
||||
MutableMapping,
|
||||
Optional,
|
||||
Tuple,
|
||||
Union,
|
||||
)
|
||||
from urllib.parse import quote
|
||||
|
||||
from requests_async import ASGISession # type: ignore
|
||||
|
||||
import sanic.app # noqa
|
||||
|
||||
from sanic.compat import Header
|
||||
from sanic.exceptions import InvalidUsage, ServerError
|
||||
from sanic.log import logger
|
||||
|
@ -54,6 +68,8 @@ class MockProtocol:
|
|||
|
||||
|
||||
class MockTransport:
|
||||
_protocol: Optional[MockProtocol]
|
||||
|
||||
def __init__(
|
||||
self, scope: ASGIScope, receive: ASGIReceive, send: ASGISend
|
||||
) -> None:
|
||||
|
@ -68,11 +84,12 @@ class MockTransport:
|
|||
self._protocol = MockProtocol(self, self.loop)
|
||||
return self._protocol
|
||||
|
||||
def get_extra_info(self, info: str) -> Union[str, bool]:
|
||||
def get_extra_info(self, info: str) -> Union[str, bool, None]:
|
||||
if info == "peername":
|
||||
return self.scope.get("server")
|
||||
elif info == "sslcontext":
|
||||
return self.scope.get("scheme") in ["https", "wss"]
|
||||
return None
|
||||
|
||||
def get_websocket_connection(self) -> WebSocketConnection:
|
||||
try:
|
||||
|
@ -172,6 +189,13 @@ class Lifespan:
|
|||
|
||||
|
||||
class ASGIApp:
|
||||
sanic_app: Union[ASGISession, "sanic.app.Sanic"]
|
||||
request: Request
|
||||
transport: MockTransport
|
||||
do_stream: bool
|
||||
lifespan: Lifespan
|
||||
ws: Optional[WebSocketConnection]
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.ws = None
|
||||
|
||||
|
@ -182,8 +206,8 @@ class ASGIApp:
|
|||
instance = cls()
|
||||
instance.sanic_app = sanic_app
|
||||
instance.transport = MockTransport(scope, receive, send)
|
||||
instance.transport.add_task = sanic_app.loop.create_task
|
||||
instance.transport.loop = sanic_app.loop
|
||||
setattr(instance.transport, "add_task", sanic_app.loop.create_task)
|
||||
|
||||
headers = Header(
|
||||
[
|
||||
|
@ -286,8 +310,8 @@ class ASGIApp:
|
|||
"""
|
||||
Write the response.
|
||||
"""
|
||||
headers = []
|
||||
cookies = {}
|
||||
headers: List[Tuple[bytes, bytes]] = []
|
||||
cookies: Dict[str, str] = {}
|
||||
try:
|
||||
cookies = {
|
||||
v.key: v
|
||||
|
|
|
@ -56,7 +56,7 @@ class BlueprintGroup(MutableSequence):
|
|||
"""
|
||||
return self._blueprints[item]
|
||||
|
||||
def __setitem__(self, index: int, item: object) -> None:
|
||||
def __setitem__(self, index, item) -> None:
|
||||
"""
|
||||
Abstract method implemented to turn the `BlueprintGroup` class
|
||||
into a list like object to support all the existing behavior.
|
||||
|
@ -69,7 +69,7 @@ class BlueprintGroup(MutableSequence):
|
|||
"""
|
||||
self._blueprints[index] = item
|
||||
|
||||
def __delitem__(self, index: int) -> None:
|
||||
def __delitem__(self, index) -> None:
|
||||
"""
|
||||
Abstract method implemented to turn the `BlueprintGroup` class
|
||||
into a list like object to support all the existing behavior.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from multidict import CIMultiDict
|
||||
from multidict import CIMultiDict # type: ignore
|
||||
|
||||
|
||||
class Header(CIMultiDict):
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import re
|
||||
|
||||
from typing import Dict, Iterable, Optional, Tuple
|
||||
from typing import Dict, Iterable, List, Optional, Tuple, Union
|
||||
from urllib.parse import unquote
|
||||
|
||||
|
||||
Options = Dict[str, str] # key=value fields in various headers
|
||||
Options = Dict[str, Union[int, str]] # key=value fields in various headers
|
||||
OptionsIterable = Iterable[Tuple[str, str]] # May contain duplicate keys
|
||||
|
||||
_token, _quoted = r"([\w!#$%&'*+\-.^_`|~]+)", r'"([^"]*)"'
|
||||
|
@ -35,7 +35,7 @@ def parse_content_header(value: str) -> Tuple[str, Options]:
|
|||
value = _firefox_quote_escape.sub("%22", value)
|
||||
pos = value.find(";")
|
||||
if pos == -1:
|
||||
options = {}
|
||||
options: Dict[str, Union[int, str]] = {}
|
||||
else:
|
||||
options = {
|
||||
m.group(1).lower(): m.group(2) or m.group(3).replace("%22", '"')
|
||||
|
@ -67,7 +67,7 @@ def parse_forwarded(headers, config) -> Optional[Options]:
|
|||
return None
|
||||
# Loop over <separator><key>=<value> elements from right to left
|
||||
sep = pos = None
|
||||
options = []
|
||||
options: List[Tuple[str, str]] = []
|
||||
found = False
|
||||
for m in _rparam.finditer(header[::-1]):
|
||||
# Start of new element? (on parser skips and non-semicolon right sep)
|
||||
|
@ -101,8 +101,13 @@ def parse_xforwarded(headers, config) -> Optional[Options]:
|
|||
try:
|
||||
# Combine, split and filter multiple headers' entries
|
||||
forwarded_for = headers.getall(config.FORWARDED_FOR_HEADER)
|
||||
proxies = (p.strip() for h in forwarded_for for p in h.split(","))
|
||||
proxies = [p for p in proxies if p]
|
||||
proxies = [
|
||||
p
|
||||
for p in (
|
||||
p.strip() for h in forwarded_for for p in h.split(",")
|
||||
)
|
||||
if p
|
||||
]
|
||||
addr = proxies[-proxies_count]
|
||||
except (KeyError, IndexError):
|
||||
pass
|
||||
|
@ -126,7 +131,7 @@ def parse_xforwarded(headers, config) -> Optional[Options]:
|
|||
|
||||
def fwd_normalize(fwd: OptionsIterable) -> Options:
|
||||
"""Normalize and convert values extracted from forwarded headers."""
|
||||
ret = {}
|
||||
ret: Dict[str, Union[int, str]] = {}
|
||||
for key, val in fwd:
|
||||
if val is not None:
|
||||
try:
|
||||
|
@ -164,4 +169,4 @@ def parse_host(host: str) -> Tuple[Optional[str], Optional[int]]:
|
|||
if not m:
|
||||
return None, None
|
||||
host, port = m.groups()
|
||||
return host.lower(), port and int(port)
|
||||
return host.lower(), int(port) if port is not None else None
|
||||
|
|
|
@ -6,7 +6,7 @@ from collections import defaultdict, namedtuple
|
|||
from http.cookies import SimpleCookie
|
||||
from urllib.parse import parse_qs, parse_qsl, unquote, urlunparse
|
||||
|
||||
from httptools import parse_url
|
||||
from httptools import parse_url # type: ignore
|
||||
|
||||
from sanic.exceptions import InvalidUsage
|
||||
from sanic.headers import (
|
||||
|
@ -19,9 +19,9 @@ from sanic.log import error_logger, logger
|
|||
|
||||
|
||||
try:
|
||||
from ujson import loads as json_loads
|
||||
from ujson import loads as json_loads # type: ignore
|
||||
except ImportError:
|
||||
from json import loads as json_loads
|
||||
from json import loads as json_loads # type: ignore
|
||||
|
||||
DEFAULT_HTTP_CONTENT_TYPE = "application/octet-stream"
|
||||
EXPECT_HEADER = "EXPECT"
|
||||
|
|
|
@ -3,7 +3,7 @@ from mimetypes import guess_type
|
|||
from os import path
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
from aiofiles import open as open_async
|
||||
from aiofiles import open as open_async # type: ignore
|
||||
|
||||
from sanic.compat import Header
|
||||
from sanic.cookies import CookieJar
|
||||
|
|
|
@ -10,8 +10,8 @@ from signal import signal as signal_func
|
|||
from socket import SO_REUSEADDR, SOL_SOCKET, socket
|
||||
from time import time
|
||||
|
||||
from httptools import HttpRequestParser
|
||||
from httptools.parser.errors import HttpParserError
|
||||
from httptools import HttpRequestParser # type: ignore
|
||||
from httptools.parser.errors import HttpParserError # type: ignore
|
||||
|
||||
from sanic.compat import Header
|
||||
from sanic.exceptions import (
|
||||
|
@ -28,7 +28,7 @@ from sanic.response import HTTPResponse
|
|||
|
||||
|
||||
try:
|
||||
import uvloop
|
||||
import uvloop # type: ignore
|
||||
|
||||
if not isinstance(asyncio.get_event_loop_policy(), uvloop.EventLoopPolicy):
|
||||
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
|
||||
|
|
|
@ -4,7 +4,7 @@ from re import sub
|
|||
from time import gmtime, strftime
|
||||
from urllib.parse import unquote
|
||||
|
||||
from aiofiles.os import stat
|
||||
from aiofiles.os import stat # type: ignore
|
||||
|
||||
from sanic.exceptions import (
|
||||
ContentRangeError,
|
||||
|
|
|
@ -6,9 +6,9 @@ from json import JSONDecodeError
|
|||
from socket import socket
|
||||
from urllib.parse import unquote, urlsplit
|
||||
|
||||
import httpcore
|
||||
import requests_async as requests
|
||||
import websockets
|
||||
import httpcore # type: ignore
|
||||
import requests_async as requests # type: ignore
|
||||
import websockets # type: ignore
|
||||
|
||||
from sanic.asgi import ASGIApp
|
||||
from sanic.exceptions import MethodNotSupported
|
||||
|
@ -288,6 +288,14 @@ class SanicASGIAdapter(requests.asgi.ASGIAdapter): # noqa
|
|||
request_complete = True
|
||||
return {"type": "http.request", "body": body_bytes}
|
||||
|
||||
request_complete = False
|
||||
response_started = False
|
||||
response_complete = False
|
||||
raw_kwargs = {"content": b""} # type: typing.Dict[str, typing.Any]
|
||||
template = None
|
||||
context = None
|
||||
return_value = None
|
||||
|
||||
async def send(message) -> None:
|
||||
nonlocal raw_kwargs, response_started, response_complete, template, context # noqa
|
||||
|
||||
|
@ -316,14 +324,6 @@ class SanicASGIAdapter(requests.asgi.ASGIAdapter): # noqa
|
|||
template = message["template"]
|
||||
context = message["context"]
|
||||
|
||||
request_complete = False
|
||||
response_started = False
|
||||
response_complete = False
|
||||
raw_kwargs = {"content": b""} # type: typing.Dict[str, typing.Any]
|
||||
template = None
|
||||
context = None
|
||||
return_value = None
|
||||
|
||||
try:
|
||||
return_value = await self.app(scope, receive, send)
|
||||
except BaseException as exc:
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from typing import Any, Callable, List
|
||||
|
||||
from sanic.constants import HTTP_METHODS
|
||||
from sanic.exceptions import InvalidUsage
|
||||
|
||||
|
@ -37,7 +39,7 @@ class HTTPMethodView:
|
|||
To add any decorator you could set it into decorators variable
|
||||
"""
|
||||
|
||||
decorators = []
|
||||
decorators: List[Callable[[Callable[..., Any]], Callable[..., Any]]] = []
|
||||
|
||||
def dispatch_request(self, request, *args, **kwargs):
|
||||
handler = getattr(self, request.method.lower(), None)
|
||||
|
|
|
@ -1,13 +1,27 @@
|
|||
from typing import Any, Awaitable, Callable, MutableMapping, Optional, Union
|
||||
from typing import (
|
||||
Any,
|
||||
Awaitable,
|
||||
Callable,
|
||||
Dict,
|
||||
MutableMapping,
|
||||
Optional,
|
||||
Union,
|
||||
)
|
||||
|
||||
from httptools import HttpParserUpgrade
|
||||
from websockets import ConnectionClosed # noqa
|
||||
from websockets import InvalidHandshake, WebSocketCommonProtocol, handshake
|
||||
from httptools import HttpParserUpgrade # type: ignore
|
||||
from websockets import ( # type: ignore
|
||||
ConnectionClosed,
|
||||
InvalidHandshake,
|
||||
WebSocketCommonProtocol,
|
||||
handshake,
|
||||
)
|
||||
|
||||
from sanic.exceptions import InvalidUsage
|
||||
from sanic.server import HttpProtocol
|
||||
|
||||
|
||||
__all__ = ["ConnectionClosed", "WebSocketProtocol", "WebSocketConnection"]
|
||||
|
||||
ASIMessage = MutableMapping[str, Any]
|
||||
|
||||
|
||||
|
@ -125,14 +139,12 @@ class WebSocketConnection:
|
|||
self._receive = receive
|
||||
|
||||
async def send(self, data: Union[str, bytes], *args, **kwargs) -> None:
|
||||
message = {"type": "websocket.send"}
|
||||
message: Dict[str, Union[str, bytes]] = {"type": "websocket.send"}
|
||||
|
||||
try:
|
||||
data.decode()
|
||||
except AttributeError:
|
||||
message.update({"text": str(data)})
|
||||
else:
|
||||
if isinstance(data, bytes):
|
||||
message.update({"bytes": data})
|
||||
else:
|
||||
message.update({"text": str(data)})
|
||||
|
||||
await self._send(message)
|
||||
|
||||
|
@ -144,6 +156,8 @@ class WebSocketConnection:
|
|||
elif message["type"] == "websocket.disconnect":
|
||||
pass
|
||||
|
||||
return None
|
||||
|
||||
receive = recv
|
||||
|
||||
async def accept(self) -> None:
|
||||
|
|
|
@ -5,19 +5,19 @@ import signal
|
|||
import sys
|
||||
import traceback
|
||||
|
||||
import gunicorn.workers.base as base
|
||||
import gunicorn.workers.base as base # type: ignore
|
||||
|
||||
from sanic.server import HttpProtocol, Signal, serve, trigger_events
|
||||
from sanic.websocket import WebSocketProtocol
|
||||
|
||||
|
||||
try:
|
||||
import ssl
|
||||
import ssl # type: ignore
|
||||
except ImportError:
|
||||
ssl = None
|
||||
ssl = None # type: ignore
|
||||
|
||||
try:
|
||||
import uvloop
|
||||
import uvloop # type: ignore
|
||||
|
||||
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
|
||||
except ImportError:
|
||||
|
|
Loading…
Reference in New Issue
Block a user