Add custom typing to config and ctx (#2785)

This commit is contained in:
Adam Hopkins
2023-07-12 23:47:58 +03:00
committed by GitHub
parent 929d270569
commit dc3c4d1393
21 changed files with 433 additions and 20 deletions

View File

@@ -2,11 +2,13 @@ from __future__ import annotations
from contextvars import ContextVar
from inspect import isawaitable
from types import SimpleNamespace
from typing import (
TYPE_CHECKING,
Any,
DefaultDict,
Dict,
Generic,
List,
Optional,
Tuple,
@@ -15,6 +17,7 @@ from typing import (
)
from sanic_routing.route import Route
from typing_extensions import TypeVar
from sanic.http.constants import HTTP # type: ignore
from sanic.http.stream import Stream
@@ -23,13 +26,13 @@ from sanic.models.http_types import Credentials
if TYPE_CHECKING:
from sanic.server import ConnInfo
from sanic.app import Sanic
from sanic.config import Config
from sanic.server import ConnInfo
import uuid
from collections import defaultdict
from types import SimpleNamespace
from urllib.parse import parse_qs, parse_qsl, urlunparse
from httptools import parse_url
@@ -68,8 +71,21 @@ try:
except ImportError:
from json import loads as json_loads # type: ignore
if TYPE_CHECKING:
# The default argument of TypeVar is proposed to be added in Python 3.13
# by PEP 696 (https://www.python.org/dev/peps/pep-0696/).
# Therefore, we use typing_extensions.TypeVar for compatibility.
# For more information, see:
# https://discuss.python.org/t/pep-696-type-defaults-for-typevarlikes
sanic_type = TypeVar(
"sanic_type", bound=Sanic, default=Sanic[Config, SimpleNamespace]
)
else:
sanic_type = TypeVar("sanic_type")
ctx_type = TypeVar("ctx_type")
class Request:
class Request(Generic[sanic_type, ctx_type]):
"""
Properties of an HTTP request such as URL, headers, etc.
"""
@@ -80,6 +96,7 @@ class Request:
__slots__ = (
"__weakref__",
"_cookies",
"_ctx",
"_id",
"_ip",
"_parsed_url",
@@ -96,7 +113,6 @@ class Request:
"app",
"body",
"conn_info",
"ctx",
"head",
"headers",
"method",
@@ -125,7 +141,7 @@ class Request:
version: str,
method: str,
transport: TransportProtocol,
app: Sanic,
app: sanic_type,
head: bytes = b"",
stream_id: int = 0,
):
@@ -149,7 +165,7 @@ class Request:
# Init but do not inhale
self.body = b""
self.conn_info: Optional[ConnInfo] = None
self.ctx = SimpleNamespace()
self._ctx: Optional[ctx_type] = None
self.parsed_accept: Optional[AcceptList] = None
self.parsed_args: DefaultDict[
Tuple[bool, bool, str, str], RequestParameters
@@ -176,6 +192,10 @@ class Request:
class_name = self.__class__.__name__
return f"<{class_name}: {self.method} {self.path}>"
@staticmethod
def make_context() -> ctx_type:
return cast(ctx_type, SimpleNamespace())
@classmethod
def get_current(cls) -> Request:
"""
@@ -205,6 +225,15 @@ class Request:
def generate_id(*_):
return uuid.uuid4()
@property
def ctx(self) -> ctx_type:
"""
:return: The current request context
"""
if not self._ctx:
self._ctx = self.make_context()
return self._ctx
@property
def stream_id(self):
"""