diff --git a/CHANGES/5275.feature b/CHANGES/5275.feature new file mode 100644 index 0000000000..e44960a322 --- /dev/null +++ b/CHANGES/5275.feature @@ -0,0 +1 @@ +Add final declarations for constants. diff --git a/aiohttp/client.py b/aiohttp/client.py index bea1198991..7bb823fb14 100644 --- a/aiohttp/client.py +++ b/aiohttp/client.py @@ -30,7 +30,7 @@ ) from multidict import CIMultiDict, MultiDict, MultiDictProxy, istr -from typing_extensions import final +from typing_extensions import Final, final from yarl import URL from . import hdrs, http, payload @@ -158,7 +158,7 @@ class ClientTimeout: # 5 Minute default read timeout -DEFAULT_TIMEOUT = ClientTimeout(total=5 * 60) +DEFAULT_TIMEOUT: Final[ClientTimeout] = ClientTimeout(total=5 * 60) _RetType = TypeVar("_RetType") diff --git a/aiohttp/client_proto.py b/aiohttp/client_proto.py index 640d1272cd..c265521ba3 100644 --- a/aiohttp/client_proto.py +++ b/aiohttp/client_proto.py @@ -149,7 +149,7 @@ def set_response_params( read_until_eof: bool = False, auto_decompress: bool = True, read_timeout: Optional[float] = None, - read_bufsize: int = 2 ** 16 + read_bufsize: int = 2 ** 16, ) -> None: self._skip_payload = skip_payload diff --git a/aiohttp/client_ws.py b/aiohttp/client_ws.py index 4bf5a3754b..f25c4dd072 100644 --- a/aiohttp/client_ws.py +++ b/aiohttp/client_ws.py @@ -5,6 +5,7 @@ from typing import Any, Optional import async_timeout +from typing_extensions import Final from .client_exceptions import ClientError from .client_reqrep import ClientResponse @@ -33,7 +34,9 @@ class ClientWSTimeout: ws_close: Optional[float] = None -DEFAULT_WS_CLIENT_TIMEOUT = ClientWSTimeout(ws_receive=None, ws_close=10.0) +DEFAULT_WS_CLIENT_TIMEOUT: Final[ClientWSTimeout] = ClientWSTimeout( + ws_receive=None, ws_close=10.0 +) class ClientWebSocketResponse: diff --git a/aiohttp/formdata.py b/aiohttp/formdata.py index 12cfda77ce..7eaf122a52 100644 --- a/aiohttp/formdata.py +++ b/aiohttp/formdata.py @@ -45,7 +45,7 @@ def add_field( *, content_type: Optional[str] = None, filename: Optional[str] = None, - content_transfer_encoding: Optional[str] = None + content_transfer_encoding: Optional[str] = None, ) -> None: if isinstance(value, io.IOBase): diff --git a/aiohttp/hdrs.py b/aiohttp/hdrs.py index f04a5457f9..d7d8e5000f 100644 --- a/aiohttp/hdrs.py +++ b/aiohttp/hdrs.py @@ -2,21 +2,23 @@ # After changing the file content call ./tools/gen.py # to regenerate the headers parser +from typing import Set from multidict import istr +from typing_extensions import Final -METH_ANY = "*" -METH_CONNECT = "CONNECT" -METH_HEAD = "HEAD" -METH_GET = "GET" -METH_DELETE = "DELETE" -METH_OPTIONS = "OPTIONS" -METH_PATCH = "PATCH" -METH_POST = "POST" -METH_PUT = "PUT" -METH_TRACE = "TRACE" +METH_ANY: Final[str] = "*" +METH_CONNECT: Final[str] = "CONNECT" +METH_HEAD: Final[str] = "HEAD" +METH_GET: Final[str] = "GET" +METH_DELETE: Final[str] = "DELETE" +METH_OPTIONS: Final[str] = "OPTIONS" +METH_PATCH: Final[str] = "PATCH" +METH_POST: Final[str] = "POST" +METH_PUT: Final[str] = "PUT" +METH_TRACE: Final[str] = "TRACE" -METH_ALL = { +METH_ALL: Final[Set[str]] = { METH_CONNECT, METH_HEAD, METH_GET, @@ -28,81 +30,80 @@ METH_TRACE, } - -ACCEPT = istr("Accept") -ACCEPT_CHARSET = istr("Accept-Charset") -ACCEPT_ENCODING = istr("Accept-Encoding") -ACCEPT_LANGUAGE = istr("Accept-Language") -ACCEPT_RANGES = istr("Accept-Ranges") -ACCESS_CONTROL_MAX_AGE = istr("Access-Control-Max-Age") -ACCESS_CONTROL_ALLOW_CREDENTIALS = istr("Access-Control-Allow-Credentials") -ACCESS_CONTROL_ALLOW_HEADERS = istr("Access-Control-Allow-Headers") -ACCESS_CONTROL_ALLOW_METHODS = istr("Access-Control-Allow-Methods") -ACCESS_CONTROL_ALLOW_ORIGIN = istr("Access-Control-Allow-Origin") -ACCESS_CONTROL_EXPOSE_HEADERS = istr("Access-Control-Expose-Headers") -ACCESS_CONTROL_REQUEST_HEADERS = istr("Access-Control-Request-Headers") -ACCESS_CONTROL_REQUEST_METHOD = istr("Access-Control-Request-Method") -AGE = istr("Age") -ALLOW = istr("Allow") -AUTHORIZATION = istr("Authorization") -CACHE_CONTROL = istr("Cache-Control") -CONNECTION = istr("Connection") -CONTENT_DISPOSITION = istr("Content-Disposition") -CONTENT_ENCODING = istr("Content-Encoding") -CONTENT_LANGUAGE = istr("Content-Language") -CONTENT_LENGTH = istr("Content-Length") -CONTENT_LOCATION = istr("Content-Location") -CONTENT_MD5 = istr("Content-MD5") -CONTENT_RANGE = istr("Content-Range") -CONTENT_TRANSFER_ENCODING = istr("Content-Transfer-Encoding") -CONTENT_TYPE = istr("Content-Type") -COOKIE = istr("Cookie") -DATE = istr("Date") -DESTINATION = istr("Destination") -DIGEST = istr("Digest") -ETAG = istr("Etag") -EXPECT = istr("Expect") -EXPIRES = istr("Expires") -FORWARDED = istr("Forwarded") -FROM = istr("From") -HOST = istr("Host") -IF_MATCH = istr("If-Match") -IF_MODIFIED_SINCE = istr("If-Modified-Since") -IF_NONE_MATCH = istr("If-None-Match") -IF_RANGE = istr("If-Range") -IF_UNMODIFIED_SINCE = istr("If-Unmodified-Since") -KEEP_ALIVE = istr("Keep-Alive") -LAST_EVENT_ID = istr("Last-Event-ID") -LAST_MODIFIED = istr("Last-Modified") -LINK = istr("Link") -LOCATION = istr("Location") -MAX_FORWARDS = istr("Max-Forwards") -ORIGIN = istr("Origin") -PRAGMA = istr("Pragma") -PROXY_AUTHENTICATE = istr("Proxy-Authenticate") -PROXY_AUTHORIZATION = istr("Proxy-Authorization") -RANGE = istr("Range") -REFERER = istr("Referer") -RETRY_AFTER = istr("Retry-After") -SEC_WEBSOCKET_ACCEPT = istr("Sec-WebSocket-Accept") -SEC_WEBSOCKET_VERSION = istr("Sec-WebSocket-Version") -SEC_WEBSOCKET_PROTOCOL = istr("Sec-WebSocket-Protocol") -SEC_WEBSOCKET_EXTENSIONS = istr("Sec-WebSocket-Extensions") -SEC_WEBSOCKET_KEY = istr("Sec-WebSocket-Key") -SEC_WEBSOCKET_KEY1 = istr("Sec-WebSocket-Key1") -SERVER = istr("Server") -SET_COOKIE = istr("Set-Cookie") -TE = istr("TE") -TRAILER = istr("Trailer") -TRANSFER_ENCODING = istr("Transfer-Encoding") -UPGRADE = istr("Upgrade") -URI = istr("URI") -USER_AGENT = istr("User-Agent") -VARY = istr("Vary") -VIA = istr("Via") -WANT_DIGEST = istr("Want-Digest") -WARNING = istr("Warning") -WWW_AUTHENTICATE = istr("WWW-Authenticate") -X_FORWARDED_FOR = istr("X-Forwarded-For") -X_FORWARDED_HOST = istr("X-Forwarded-Host") -X_FORWARDED_PROTO = istr("X-Forwarded-Proto") +ACCEPT: Final[istr] = istr("Accept") +ACCEPT_CHARSET: Final[istr] = istr("Accept-Charset") +ACCEPT_ENCODING: Final[istr] = istr("Accept-Encoding") +ACCEPT_LANGUAGE: Final[istr] = istr("Accept-Language") +ACCEPT_RANGES: Final[istr] = istr("Accept-Ranges") +ACCESS_CONTROL_MAX_AGE: Final[istr] = istr("Access-Control-Max-Age") +ACCESS_CONTROL_ALLOW_CREDENTIALS: Final[istr] = istr("Access-Control-Allow-Credentials") +ACCESS_CONTROL_ALLOW_HEADERS: Final[istr] = istr("Access-Control-Allow-Headers") +ACCESS_CONTROL_ALLOW_METHODS: Final[istr] = istr("Access-Control-Allow-Methods") +ACCESS_CONTROL_ALLOW_ORIGIN: Final[istr] = istr("Access-Control-Allow-Origin") +ACCESS_CONTROL_EXPOSE_HEADERS: Final[istr] = istr("Access-Control-Expose-Headers") +ACCESS_CONTROL_REQUEST_HEADERS: Final[istr] = istr("Access-Control-Request-Headers") +ACCESS_CONTROL_REQUEST_METHOD: Final[istr] = istr("Access-Control-Request-Method") +AGE: Final[istr] = istr("Age") +ALLOW: Final[istr] = istr("Allow") +AUTHORIZATION: Final[istr] = istr("Authorization") +CACHE_CONTROL: Final[istr] = istr("Cache-Control") +CONNECTION: Final[istr] = istr("Connection") +CONTENT_DISPOSITION: Final[istr] = istr("Content-Disposition") +CONTENT_ENCODING: Final[istr] = istr("Content-Encoding") +CONTENT_LANGUAGE: Final[istr] = istr("Content-Language") +CONTENT_LENGTH: Final[istr] = istr("Content-Length") +CONTENT_LOCATION: Final[istr] = istr("Content-Location") +CONTENT_MD5: Final[istr] = istr("Content-MD5") +CONTENT_RANGE: Final[istr] = istr("Content-Range") +CONTENT_TRANSFER_ENCODING: Final[istr] = istr("Content-Transfer-Encoding") +CONTENT_TYPE: Final[istr] = istr("Content-Type") +COOKIE: Final[istr] = istr("Cookie") +DATE: Final[istr] = istr("Date") +DESTINATION: Final[istr] = istr("Destination") +DIGEST: Final[istr] = istr("Digest") +ETAG: Final[istr] = istr("Etag") +EXPECT: Final[istr] = istr("Expect") +EXPIRES: Final[istr] = istr("Expires") +FORWARDED: Final[istr] = istr("Forwarded") +FROM: Final[istr] = istr("From") +HOST: Final[istr] = istr("Host") +IF_MATCH: Final[istr] = istr("If-Match") +IF_MODIFIED_SINCE: Final[istr] = istr("If-Modified-Since") +IF_NONE_MATCH: Final[istr] = istr("If-None-Match") +IF_RANGE: Final[istr] = istr("If-Range") +IF_UNMODIFIED_SINCE: Final[istr] = istr("If-Unmodified-Since") +KEEP_ALIVE: Final[istr] = istr("Keep-Alive") +LAST_EVENT_ID: Final[istr] = istr("Last-Event-ID") +LAST_MODIFIED: Final[istr] = istr("Last-Modified") +LINK: Final[istr] = istr("Link") +LOCATION: Final[istr] = istr("Location") +MAX_FORWARDS: Final[istr] = istr("Max-Forwards") +ORIGIN: Final[istr] = istr("Origin") +PRAGMA: Final[istr] = istr("Pragma") +PROXY_AUTHENTICATE: Final[istr] = istr("Proxy-Authenticate") +PROXY_AUTHORIZATION: Final[istr] = istr("Proxy-Authorization") +RANGE: Final[istr] = istr("Range") +REFERER: Final[istr] = istr("Referer") +RETRY_AFTER: Final[istr] = istr("Retry-After") +SEC_WEBSOCKET_ACCEPT: Final[istr] = istr("Sec-WebSocket-Accept") +SEC_WEBSOCKET_VERSION: Final[istr] = istr("Sec-WebSocket-Version") +SEC_WEBSOCKET_PROTOCOL: Final[istr] = istr("Sec-WebSocket-Protocol") +SEC_WEBSOCKET_EXTENSIONS: Final[istr] = istr("Sec-WebSocket-Extensions") +SEC_WEBSOCKET_KEY: Final[istr] = istr("Sec-WebSocket-Key") +SEC_WEBSOCKET_KEY1: Final[istr] = istr("Sec-WebSocket-Key1") +SERVER: Final[istr] = istr("Server") +SET_COOKIE: Final[istr] = istr("Set-Cookie") +TE: Final[istr] = istr("TE") +TRAILER: Final[istr] = istr("Trailer") +TRANSFER_ENCODING: Final[istr] = istr("Transfer-Encoding") +UPGRADE: Final[istr] = istr("Upgrade") +URI: Final[istr] = istr("URI") +USER_AGENT: Final[istr] = istr("User-Agent") +VARY: Final[istr] = istr("Vary") +VIA: Final[istr] = istr("Via") +WANT_DIGEST: Final[istr] = istr("Want-Digest") +WARNING: Final[istr] = istr("Warning") +WWW_AUTHENTICATE: Final[istr] = istr("WWW-Authenticate") +X_FORWARDED_FOR: Final[istr] = istr("X-Forwarded-For") +X_FORWARDED_HOST: Final[istr] = istr("X-Forwarded-Host") +X_FORWARDED_PROTO: Final[istr] = istr("X-Forwarded-Proto") diff --git a/aiohttp/http_parser.py b/aiohttp/http_parser.py index 2ea0387ce4..8fe60a82c7 100644 --- a/aiohttp/http_parser.py +++ b/aiohttp/http_parser.py @@ -6,9 +6,21 @@ import zlib from contextlib import suppress from enum import IntEnum -from typing import Any, Generic, List, Optional, Tuple, Type, TypeVar, Union +from typing import ( + Any, + Generic, + List, + Optional, + Pattern, + Set, + Tuple, + Type, + TypeVar, + Union, +) from multidict import CIMultiDict, CIMultiDictProxy, istr +from typing_extensions import Final from yarl import URL from . import hdrs @@ -44,7 +56,7 @@ "RawResponseMessage", ) -ASCIISET = set(string.printable) +ASCIISET: Final[Set[str]] = set(string.printable) # See https://tools.ietf.org/html/rfc7230#section-3.1.1 # and https://tools.ietf.org/html/rfc7230#appendix-B @@ -53,9 +65,9 @@ # tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / # "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA # token = 1*tchar -METHRE = re.compile(r"[!#$%&'*+\-.^_`|~0-9A-Za-z]+") -VERSRE = re.compile(r"HTTP/(\d+).(\d+)") -HDRRE = re.compile(rb"[\x00-\x1F\x7F()<>@,;:\[\]={} \t\\\\\"]") +METHRE: Final[Pattern[str]] = re.compile(r"[!#$%&'*+\-.^_`|~0-9A-Za-z]+") +VERSRE: Final[Pattern[str]] = re.compile(r"HTTP/(\d+).(\d+)") +HDRRE: Final[Pattern[bytes]] = re.compile(rb"[\x00-\x1F\x7F()<>@,;:\[\]={} \t\\\\\"]") RawRequestMessage = collections.namedtuple( "RawRequestMessage", diff --git a/aiohttp/http_websocket.py b/aiohttp/http_websocket.py index d0dee7f451..bff70f0968 100644 --- a/aiohttp/http_websocket.py +++ b/aiohttp/http_websocket.py @@ -9,7 +9,9 @@ import zlib from enum import IntEnum from struct import Struct -from typing import Any, Callable, List, Optional, Tuple, Union +from typing import Any, Callable, List, Optional, Pattern, Set, Tuple, Union + +from typing_extensions import Final from .base_protocol import BaseProtocol from .helpers import NO_EXTENSIONS @@ -44,7 +46,7 @@ class WSCloseCode(IntEnum): BAD_GATEWAY = 1014 -ALLOWED_CLOSE_CODES = {int(i) for i in WSCloseCode} +ALLOWED_CLOSE_CODES: Final[Set[int]] = {int(i) for i in WSCloseCode} class WSMsgType(IntEnum): @@ -62,7 +64,7 @@ class WSMsgType(IntEnum): ERROR = 0x102 -WS_KEY = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11" +WS_KEY: Final[bytes] = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11" UNPACK_LEN2 = Struct("!H").unpack_from @@ -72,8 +74,8 @@ class WSMsgType(IntEnum): PACK_LEN2 = Struct("!BBH").pack PACK_LEN3 = Struct("!BBQ").pack PACK_CLOSE_CODE = Struct("!H").pack -MSG_SIZE = 2 ** 14 -DEFAULT_LIMIT = 2 ** 16 +MSG_SIZE: Final[int] = 2 ** 14 +DEFAULT_LIMIT: Final[int] = 2 ** 16 _WSMessageBase = collections.namedtuple("_WSMessageBase", ["type", "data", "extra"]) @@ -107,11 +109,11 @@ class WSHandshakeError(Exception): """WebSocket protocol handshake error.""" -native_byteorder = sys.byteorder +native_byteorder: Final[str] = sys.byteorder # Used by _websocket_mask_python -_XOR_TABLE = [bytes(a ^ b for a in range(256)) for b in range(256)] +_XOR_TABLE: Final[List[bytes]] = [bytes(a ^ b for a in range(256)) for b in range(256)] def _websocket_mask_python(mask: bytes, data: bytearray) -> None: @@ -148,10 +150,10 @@ def _websocket_mask_python(mask: bytes, data: bytearray) -> None: except ImportError: # pragma: no cover _websocket_mask = _websocket_mask_python -_WS_DEFLATE_TRAILING = bytes([0x00, 0x00, 0xFF, 0xFF]) +_WS_DEFLATE_TRAILING: Final[bytes] = bytes([0x00, 0x00, 0xFF, 0xFF]) -_WS_EXT_RE = re.compile( +_WS_EXT_RE: Final[Pattern[str]] = re.compile( r"^(?:;\s*(?:" r"(server_no_context_takeover)|" r"(client_no_context_takeover)|" @@ -159,7 +161,7 @@ def _websocket_mask_python(mask: bytes, data: bytearray) -> None: r"(client_max_window_bits(?:=(\d+))?)))*$" ) -_WS_EXT_RE_SPLIT = re.compile(r"permessage-deflate([^,]+)?") +_WS_EXT_RE_SPLIT: Final[Pattern[str]] = re.compile(r"permessage-deflate([^,]+)?") def ws_ext_parse(extstr: Optional[str], isserver: bool = False) -> Tuple[int, bool]: diff --git a/aiohttp/payload.py b/aiohttp/payload.py index 0e881e41ea..b3f5f842e4 100644 --- a/aiohttp/payload.py +++ b/aiohttp/payload.py @@ -23,6 +23,7 @@ ) from multidict import CIMultiDict +from typing_extensions import Final from . import hdrs from .abc import AbstractStreamWriter @@ -52,7 +53,7 @@ "AsyncIterablePayload", ) -TOO_LARGE_BYTES_BODY = 2 ** 20 # 1 MB +TOO_LARGE_BYTES_BODY: Final[int] = 2 ** 20 # 1 MB if TYPE_CHECKING: # pragma: no cover diff --git a/aiohttp/streams.py b/aiohttp/streams.py index d8182b3d5f..d07b16e61c 100644 --- a/aiohttp/streams.py +++ b/aiohttp/streams.py @@ -111,7 +111,7 @@ def __init__( limit: int, *, timer: Optional[BaseTimerContext] = None, - loop: asyncio.AbstractEventLoop + loop: asyncio.AbstractEventLoop, ) -> None: self._protocol = protocol self._low_water = limit diff --git a/aiohttp/web.py b/aiohttp/web.py index eb23dd3ff7..8a5030cc26 100644 --- a/aiohttp/web.py +++ b/aiohttp/web.py @@ -6,16 +6,16 @@ from collections.abc import Iterable from importlib import import_module from typing import ( - Any as Any, - Awaitable as Awaitable, - Callable as Callable, + Any, + Awaitable, + Callable, Iterable as TypingIterable, - List as List, - Optional as Optional, - Set as Set, - Type as Type, - Union as Union, - cast as cast, + List, + Optional, + Set, + Type, + Union, + cast, ) from .abc import AbstractAccessLogger diff --git a/aiohttp/web_fileresponse.py b/aiohttp/web_fileresponse.py index 0737c4f42d..6e475010fc 100644 --- a/aiohttp/web_fileresponse.py +++ b/aiohttp/web_fileresponse.py @@ -15,6 +15,8 @@ cast, ) +from typing_extensions import Final + from . import hdrs from .abc import AbstractStreamWriter from .typedefs import LooseHeaders @@ -35,7 +37,7 @@ _T_OnChunkSent = Optional[Callable[[bytes], Awaitable[None]]] -NOSENDFILE = bool(os.environ.get("AIOHTTP_NOSENDFILE")) +NOSENDFILE: Final[bool] = bool(os.environ.get("AIOHTTP_NOSENDFILE")) class FileResponse(StreamResponse): diff --git a/aiohttp/web_middlewares.py b/aiohttp/web_middlewares.py index b122bd14fe..1c30b93f9f 100644 --- a/aiohttp/web_middlewares.py +++ b/aiohttp/web_middlewares.py @@ -50,7 +50,7 @@ def normalize_path_middleware( append_slash: bool = True, remove_slash: bool = False, merge_slashes: bool = True, - redirect_class: Type[HTTPMove] = HTTPPermanentRedirect + redirect_class: Type[HTTPMove] = HTTPPermanentRedirect, ) -> _Middleware: """ Middleware factory which produces a middleware that normalizes diff --git a/aiohttp/web_request.py b/aiohttp/web_request.py index b95a5631a8..7493b4ac58 100644 --- a/aiohttp/web_request.py +++ b/aiohttp/web_request.py @@ -18,6 +18,7 @@ Mapping, MutableMapping, Optional, + Pattern, Set, Tuple, Union, @@ -26,6 +27,7 @@ from urllib.parse import parse_qsl from multidict import CIMultiDict, CIMultiDictProxy, MultiDict, MultiDictProxy +from typing_extensions import Final from yarl import URL from . import hdrs @@ -75,31 +77,33 @@ class FileField: headers: "CIMultiDictProxy[str]" -_TCHAR = string.digits + string.ascii_letters + r"!#$%&'*+.^_`|~-" +_TCHAR: Final[str] = string.digits + string.ascii_letters + r"!#$%&'*+.^_`|~-" # '-' at the end to prevent interpretation as range in a char class -_TOKEN = fr"[{_TCHAR}]+" +_TOKEN: Final[str] = fr"[{_TCHAR}]+" -_QDTEXT = r"[{}]".format( +_QDTEXT: Final[str] = r"[{}]".format( r"".join(chr(c) for c in (0x09, 0x20, 0x21) + tuple(range(0x23, 0x7F))) ) # qdtext includes 0x5C to escape 0x5D ('\]') # qdtext excludes obs-text (because obsoleted, and encoding not specified) -_QUOTED_PAIR = r"\\[\t !-~]" +_QUOTED_PAIR: Final[str] = r"\\[\t !-~]" -_QUOTED_STRING = r'"(?:{quoted_pair}|{qdtext})*"'.format( +_QUOTED_STRING: Final[str] = r'"(?:{quoted_pair}|{qdtext})*"'.format( qdtext=_QDTEXT, quoted_pair=_QUOTED_PAIR ) -_FORWARDED_PAIR = r"({token})=({token}|{quoted_string})(:\d{{1,4}})?".format( +_FORWARDED_PAIR: Final[ + str +] = r"({token})=({token}|{quoted_string})(:\d{{1,4}})?".format( token=_TOKEN, quoted_string=_QUOTED_STRING ) -_QUOTED_PAIR_REPLACE_RE = re.compile(r"\\([\t !-~])") +_QUOTED_PAIR_REPLACE_RE: Final[Pattern[str]] = re.compile(r"\\([\t !-~])") # same pattern as _QUOTED_PAIR but contains a capture group -_FORWARDED_PAIR_RE = re.compile(_FORWARDED_PAIR) +_FORWARDED_PAIR_RE: Final[Pattern[str]] = re.compile(_FORWARDED_PAIR) ############################################################ # HTTP Request diff --git a/aiohttp/web_server.py b/aiohttp/web_server.py index 8fdee1891c..1c9fbf34ca 100644 --- a/aiohttp/web_server.py +++ b/aiohttp/web_server.py @@ -19,7 +19,7 @@ def __init__( *, request_factory: Optional[_RequestFactory] = None, debug: Optional[bool] = None, - **kwargs: Any + **kwargs: Any, ) -> None: if debug is not None: warnings.warn( diff --git a/aiohttp/web_urldispatcher.py b/aiohttp/web_urldispatcher.py index 590b376afe..28e9232911 100644 --- a/aiohttp/web_urldispatcher.py +++ b/aiohttp/web_urldispatcher.py @@ -29,7 +29,7 @@ cast, ) -from typing_extensions import TypedDict +from typing_extensions import Final, TypedDict from yarl import URL, __version__ as yarl_version # type: ignore from . import hdrs @@ -70,11 +70,15 @@ else: BaseDict = dict -YARL_VERSION = tuple(map(int, yarl_version.split(".")[:2])) +YARL_VERSION: Final[Tuple[int, ...]] = tuple(map(int, yarl_version.split(".")[:2])) -HTTP_METHOD_RE = re.compile(r"^[0-9A-Za-z!#\$%&'\*\+\-\.\^_`\|~]+$") -ROUTE_RE = re.compile(r"(\{[_a-zA-Z][^{}]*(?:\{[^{}]*\}[^{}]*)*\})") -PATH_SEP = re.escape("/") +HTTP_METHOD_RE: Final[Pattern[str]] = re.compile( + r"^[0-9A-Za-z!#\$%&'\*\+\-\.\^_`\|~]+$" +) +ROUTE_RE: Final[Pattern[str]] = re.compile( + r"(\{[_a-zA-Z][^{}]*(?:\{[^{}]*\}[^{}]*)*\})" +) +PATH_SEP: Final[str] = re.escape("/") _WebHandler = Callable[[Request], Awaitable[StreamResponse]] diff --git a/aiohttp/web_ws.py b/aiohttp/web_ws.py index 6b295e773b..f23313d77b 100644 --- a/aiohttp/web_ws.py +++ b/aiohttp/web_ws.py @@ -8,6 +8,7 @@ import async_timeout from multidict import CIMultiDict +from typing_extensions import Final from . import hdrs from .abc import AbstractStreamWriter @@ -38,7 +39,7 @@ "WSMsgType", ) -THRESHOLD_CONNLOST_ACCESS = 5 +THRESHOLD_CONNLOST_ACCESS: Final[int] = 5 @dataclasses.dataclass(frozen=True) diff --git a/requirements/cython.txt b/requirements/cython.txt index e478589498..2d3627402e 100644 --- a/requirements/cython.txt +++ b/requirements/cython.txt @@ -1,2 +1,3 @@ -r multidict.txt cython==0.29.21 +typing_extensions==3.7.4.3 # required for parsing aiohttp/hdrs.py by tools/gen.py