]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
*: Update type annotations to use python 3.10 features
authorBen Darnell <ben@bendarnell.com>
Thu, 19 Mar 2026 15:28:25 +0000 (11:28 -0400)
committerBen Darnell <ben@bendarnell.com>
Thu, 19 Mar 2026 15:34:58 +0000 (11:34 -0400)
Automated change by pyupgrade (typing plugins) followed by manual
fixes of unused imports

34 files changed:
tornado/auth.py
tornado/autoreload.py
tornado/concurrent.py
tornado/curl_httpclient.py
tornado/escape.py
tornado/gen.py
tornado/http1connection.py
tornado/httpclient.py
tornado/httpserver.py
tornado/iostream.py
tornado/locks.py
tornado/log.py
tornado/netutil.py
tornado/options.py
tornado/platform/asyncio.py
tornado/process.py
tornado/routing.py
tornado/simple_httpclient.py
tornado/tcpclient.py
tornado/tcpserver.py
tornado/template.py
tornado/test/circlerefs_test.py
tornado/test/escape_test.py
tornado/test/gen_test.py
tornado/test/http1connection_test.py
tornado/test/ioloop_test.py
tornado/test/iostream_test.py
tornado/test/locks_test.py
tornado/test/template_test.py
tornado/test/web_test.py
tornado/testing.py
tornado/web.py
tornado/websocket.py
tornado/wsgi.py

index d041b5fc4771ae9e818cfafc75bdf2d93a0c6c79..90479a0622ac0e469522da2955116b77ed6a6b9b 100644 (file)
@@ -84,7 +84,7 @@ from tornado.httputil import url_concat
 from tornado.util import unicode_type
 from tornado.web import RequestHandler
 
-from typing import Any, cast, Union, Optional
+from typing import Any, cast
 from collections.abc import Iterable
 
 
@@ -102,7 +102,7 @@ class OpenIdMixin:
 
     def authenticate_redirect(
         self,
-        callback_uri: Optional[str] = None,
+        callback_uri: str | None = None,
         ax_attrs: list[str] = ["name", "email", "language", "username"],
     ) -> None:
         """Redirects to the authentication URL for this service.
@@ -129,7 +129,7 @@ class OpenIdMixin:
         handler.redirect(endpoint + "?" + urllib.parse.urlencode(args))
 
     async def get_authenticated_user(
-        self, http_client: Optional[httpclient.AsyncHTTPClient] = None
+        self, http_client: httpclient.AsyncHTTPClient | None = None
     ) -> dict[str, Any]:
         """Fetches the authenticated user data upon redirect.
 
@@ -148,7 +148,7 @@ class OpenIdMixin:
         """
         handler = cast(RequestHandler, self)
         # Verify the OpenID response via direct request to the OP
-        args: dict[str, Union[str, bytes]] = {
+        args: dict[str, str | bytes] = {
             k: v[-1] for k, v in handler.request.arguments.items()
         }
         args["openid.mode"] = "check_authentication"
@@ -164,7 +164,7 @@ class OpenIdMixin:
         self,
         callback_uri: str,
         ax_attrs: Iterable[str] = [],
-        oauth_scope: Optional[str] = None,
+        oauth_scope: str | None = None,
     ) -> dict[str, str]:
         handler = cast(RequestHandler, self)
         url = urllib.parse.urljoin(handler.request.full_url(), callback_uri)
@@ -304,9 +304,9 @@ class OAuthMixin:
 
     async def authorize_redirect(
         self,
-        callback_uri: Optional[str] = None,
-        extra_params: Optional[dict[str, Any]] = None,
-        http_client: Optional[httpclient.AsyncHTTPClient] = None,
+        callback_uri: str | None = None,
+        extra_params: dict[str, Any] | None = None,
+        http_client: httpclient.AsyncHTTPClient | None = None,
     ) -> None:
         """Redirects the user to obtain OAuth authorization for this service.
 
@@ -352,7 +352,7 @@ class OAuthMixin:
         self._on_request_token(url, callback_uri, response)
 
     async def get_authenticated_user(
-        self, http_client: Optional[httpclient.AsyncHTTPClient] = None
+        self, http_client: httpclient.AsyncHTTPClient | None = None
     ) -> dict[str, Any]:
         """Gets the OAuth authorized user and access token.
 
@@ -381,7 +381,7 @@ class OAuthMixin:
         )
         if cookie_key != request_key:
             raise AuthError("Request token does not match cookie")
-        token: dict[str, Union[str, bytes]] = dict(key=cookie_key, secret=cookie_secret)
+        token: dict[str, str | bytes] = dict(key=cookie_key, secret=cookie_secret)
         if oauth_verifier:
             token["verifier"] = oauth_verifier
         if http_client is None:
@@ -397,8 +397,8 @@ class OAuthMixin:
 
     def _oauth_request_token_url(
         self,
-        callback_uri: Optional[str] = None,
-        extra_params: Optional[dict[str, Any]] = None,
+        callback_uri: str | None = None,
+        extra_params: dict[str, Any] | None = None,
     ) -> str:
         handler = cast(RequestHandler, self)
         consumer_token = self._oauth_consumer_token()
@@ -429,7 +429,7 @@ class OAuthMixin:
     def _on_request_token(
         self,
         authorize_url: str,
-        callback_uri: Optional[str],
+        callback_uri: str | None,
         response: httpclient.HTTPResponse,
     ) -> None:
         handler = cast(RequestHandler, self)
@@ -565,11 +565,11 @@ class OAuth2Mixin:
 
     def authorize_redirect(
         self,
-        redirect_uri: Optional[str] = None,
-        client_id: Optional[str] = None,
-        client_secret: Optional[str] = None,
-        extra_params: Optional[dict[str, Any]] = None,
-        scope: Optional[list[str]] = None,
+        redirect_uri: str | None = None,
+        client_id: str | None = None,
+        client_secret: str | None = None,
+        extra_params: dict[str, Any] | None = None,
+        scope: list[str] | None = None,
         response_type: str = "code",
     ) -> None:
         """Redirects the user to obtain OAuth authorization for this service.
@@ -606,11 +606,11 @@ class OAuth2Mixin:
 
     def _oauth_request_token_url(
         self,
-        redirect_uri: Optional[str] = None,
-        client_id: Optional[str] = None,
-        client_secret: Optional[str] = None,
-        code: Optional[str] = None,
-        extra_params: Optional[dict[str, Any]] = None,
+        redirect_uri: str | None = None,
+        client_id: str | None = None,
+        client_secret: str | None = None,
+        code: str | None = None,
+        extra_params: dict[str, Any] | None = None,
     ) -> str:
         url = self._OAUTH_ACCESS_TOKEN_URL  # type: ignore
         args: dict[str, str] = {}
@@ -629,8 +629,8 @@ class OAuth2Mixin:
     async def oauth2_request(
         self,
         url: str,
-        access_token: Optional[str] = None,
-        post_args: Optional[dict[str, Any]] = None,
+        access_token: str | None = None,
+        post_args: dict[str, Any] | None = None,
         **args: Any,
     ) -> Any:
         """Fetches the given URL auth an OAuth2 access token.
@@ -733,7 +733,7 @@ class TwitterMixin(OAuthMixin):
     _OAUTH_NO_CALLBACKS = False
     _TWITTER_BASE_URL = "https://api.twitter.com/1.1"
 
-    async def authenticate_redirect(self, callback_uri: Optional[str] = None) -> None:
+    async def authenticate_redirect(self, callback_uri: str | None = None) -> None:
         """Just like `~OAuthMixin.authorize_redirect`, but
         auto-redirects if authorized.
 
@@ -759,7 +759,7 @@ class TwitterMixin(OAuthMixin):
         self,
         path: str,
         access_token: dict[str, Any],
-        post_args: Optional[dict[str, Any]] = None,
+        post_args: dict[str, Any] | None = None,
         **args: Any,
     ) -> Any:
         """Fetches the given API path, e.g., ``statuses/user_timeline/btaylor``
@@ -897,8 +897,8 @@ class GoogleOAuth2Mixin(OAuth2Mixin):
         self,
         redirect_uri: str,
         code: str,
-        client_id: Optional[str] = None,
-        client_secret: Optional[str] = None,
+        client_id: str | None = None,
+        client_secret: str | None = None,
     ) -> dict[str, Any]:
         """Handles the login for the Google user, returning an access token.
 
@@ -991,8 +991,8 @@ class FacebookGraphMixin(OAuth2Mixin):
         client_id: str,
         client_secret: str,
         code: str,
-        extra_fields: Optional[dict[str, Any]] = None,
-    ) -> Optional[dict[str, Any]]:
+        extra_fields: dict[str, Any] | None = None,
+    ) -> dict[str, Any] | None:
         """Handles the login for the Facebook user, returning a user object.
 
         Example usage:
@@ -1093,8 +1093,8 @@ class FacebookGraphMixin(OAuth2Mixin):
     async def facebook_request(
         self,
         path: str,
-        access_token: Optional[str] = None,
-        post_args: Optional[dict[str, Any]] = None,
+        access_token: str | None = None,
+        post_args: dict[str, Any] | None = None,
         **args: Any,
     ) -> Any:
         """Fetches the given relative API path, e.g., "/btaylor/picture"
@@ -1155,7 +1155,7 @@ def _oauth_signature(
     method: str,
     url: str,
     parameters: dict[str, Any] = {},
-    token: Optional[dict[str, Any]] = None,
+    token: dict[str, Any] | None = None,
 ) -> bytes:
     """Calculates the HMAC-SHA1 OAuth signature for the given request.
 
@@ -1186,7 +1186,7 @@ def _oauth10a_signature(
     method: str,
     url: str,
     parameters: dict[str, Any] = {},
-    token: Optional[dict[str, Any]] = None,
+    token: dict[str, Any] | None = None,
 ) -> bytes:
     """Calculates the HMAC-SHA1 OAuth 1.0a signature for the given request.
 
@@ -1214,7 +1214,7 @@ def _oauth10a_signature(
     return binascii.b2a_base64(hash.digest())[:-1]
 
 
-def _oauth_escape(val: Union[str, bytes]) -> str:
+def _oauth_escape(val: str | bytes) -> str:
     if isinstance(val, unicode_type):
         val = val.encode("utf-8")
     return urllib.parse.quote(val, safe="~")
index dd05322e9061c1da6b1267a8591eee264a9dcee2..fd8d48e03ce1db5df96a392df5bff6787450c97e 100644 (file)
@@ -93,7 +93,7 @@ try:
 except ImportError:
     signal = None  # type: ignore
 
-from typing import Callable, Optional, Union
+from typing import Callable
 
 # os.execv is broken on Windows and can't properly parse command line
 # arguments and executable name if they contain whitespaces. subprocess
@@ -107,7 +107,7 @@ _io_loops: "weakref.WeakKeyDictionary[ioloop.IOLoop, bool]" = (
     weakref.WeakKeyDictionary()
 )
 _autoreload_is_main = False
-_original_argv: Optional[list[str]] = None
+_original_argv: list[str] | None = None
 _original_spec = None
 
 
@@ -300,7 +300,7 @@ def main() -> None:
 
     # SystemExit.code is typed funny: https://github.com/python/typeshed/issues/8513
     # All we care about is truthiness
-    exit_status: Union[int, str, None] = 1
+    exit_status: int | str | None = 1
     try:
         import runpy
 
index cf55053947f75d150c24374e62e4f6b63e669fda..29cc253463faa6821c015997f747b6d47445ce3a 100644 (file)
@@ -34,7 +34,7 @@ import types
 from tornado.log import app_log
 
 import typing
-from typing import Any, Callable, Optional, Union
+from typing import Any, Callable, Union
 
 _T = typing.TypeVar("_T")
 
@@ -213,9 +213,7 @@ def future_set_exception_unless_cancelled(
 
 def future_set_exc_info(
     future: "Union[futures.Future[_T], Future[_T]]",
-    exc_info: tuple[
-        Optional[type], Optional[BaseException], Optional[types.TracebackType]
-    ],
+    exc_info: tuple[type | None, BaseException | None, types.TracebackType | None],
 ) -> None:
     """Set the given ``exc_info`` as the `Future`'s exception.
 
index aa8980927e9e24e41f3d9c0dcc58540217b1c18d..0f3ee47209ea0419b4ecdf77a44b90f8406b1676 100644 (file)
@@ -39,7 +39,7 @@ from tornado.httpclient import (
 )
 from tornado.log import app_log
 
-from typing import Any, Callable, Union, Optional
+from typing import Any, Callable
 import typing
 
 if typing.TYPE_CHECKING:
@@ -52,7 +52,7 @@ CR_OR_LF_RE = re.compile(b"\r|\n")
 
 class CurlAsyncHTTPClient(AsyncHTTPClient):
     def initialize(  # type: ignore
-        self, max_clients: int = 10, defaults: Optional[dict[str, Any]] = None
+        self, max_clients: int = 10, defaults: dict[str, Any] | None = None
     ) -> None:
         super().initialize(defaults=defaults)
         # Typeshed is incomplete for CurlMulti, so just use Any for now.
@@ -65,7 +65,7 @@ class CurlAsyncHTTPClient(AsyncHTTPClient):
             tuple[HTTPRequest, Callable[[HTTPResponse], None], float]
         ] = collections.deque()
         self._fds: dict[int, int] = {}
-        self._timeout: Optional[object] = None
+        self._timeout: object | None = None
 
         # libcurl has bugs that sometimes cause it to not report all
         # relevant file descriptors and timeouts to TIMERFUNCTION/
@@ -262,8 +262,8 @@ class CurlAsyncHTTPClient(AsyncHTTPClient):
     def _finish(
         self,
         curl: pycurl.Curl,
-        curl_error: Optional[int] = None,
-        curl_message: Optional[str] = None,
+        curl_error: int | None = None,
+        curl_message: str | None = None,
     ) -> None:
         info = curl.info  # type: ignore
         curl.info = None  # type: ignore
@@ -272,7 +272,7 @@ class CurlAsyncHTTPClient(AsyncHTTPClient):
         buffer = info["buffer"]
         if curl_error:
             assert curl_message is not None
-            error: Optional[CurlError] = CurlError(curl_error, curl_message)
+            error: CurlError | None = CurlError(curl_error, curl_message)
             assert error is not None
             code = error.code
             effective_url = None
@@ -377,7 +377,7 @@ class CurlAsyncHTTPClient(AsyncHTTPClient):
                     "'CurlAsyncHTTPClient' does not support async streaming_callbacks."
                 )
 
-            def write_function(b: Union[bytes, bytearray]) -> int:
+            def write_function(b: bytes | bytearray) -> int:
                 assert request.streaming_callback is not None
                 self.io_loop.add_callback(request.streaming_callback, b)
                 return len(b)
@@ -553,7 +553,7 @@ class CurlAsyncHTTPClient(AsyncHTTPClient):
     def _curl_header_callback(
         self,
         headers: httputil.HTTPHeaders,
-        header_callback: Optional[Callable[[str], None]],
+        header_callback: Callable[[str], None] | None,
         header_line_bytes: bytes,
     ) -> None:
         header_line = native_str(header_line_bytes.decode("latin1"))
index c606597eb7a3cb8aff75d6535aa32871c751d84b..21ed0e5fcd8b77ab3e5727ef8cea123d892a0f62 100644 (file)
@@ -33,10 +33,10 @@ import urllib.parse
 from tornado.util import unicode_type
 
 import typing
-from typing import Union, Any, Optional, Callable
+from typing import Any, Callable
 
 
-def xhtml_escape(value: Union[str, bytes]) -> str:
+def xhtml_escape(value: str | bytes) -> str:
     """Escapes a string so it is valid within HTML or XML.
 
     Escapes the characters ``<``, ``>``, ``"``, ``'``, and ``&``.
@@ -59,7 +59,7 @@ def xhtml_escape(value: Union[str, bytes]) -> str:
     return html.escape(to_unicode(value))
 
 
-def xhtml_unescape(value: Union[str, bytes]) -> str:
+def xhtml_unescape(value: str | bytes) -> str:
     """Un-escapes an XML-escaped string.
 
     Equivalent to `html.unescape` except that this function always returns
@@ -96,7 +96,7 @@ def json_encode(value: Any) -> str:
     return json.dumps(value).replace("</", "<\\/")
 
 
-def json_decode(value: Union[str, bytes]) -> Any:
+def json_decode(value: str | bytes) -> Any:
     """Returns Python objects for the given JSON string.
 
     Supports both `str` and `bytes` inputs. Equvalent to `json.loads`.
@@ -109,7 +109,7 @@ def squeeze(value: str) -> str:
     return re.sub(r"[\x00-\x20]+", " ", value).strip()
 
 
-def url_escape(value: Union[str, bytes], plus: bool = True) -> str:
+def url_escape(value: str | bytes, plus: bool = True) -> str:
     """Returns a URL-encoded version of the given value.
 
     Equivalent to either `urllib.parse.quote_plus` or `urllib.parse.quote` depending on the ``plus``
@@ -129,20 +129,18 @@ def url_escape(value: Union[str, bytes], plus: bool = True) -> str:
 
 
 @typing.overload
-def url_unescape(value: Union[str, bytes], encoding: None, plus: bool = True) -> bytes:
+def url_unescape(value: str | bytes, encoding: None, plus: bool = True) -> bytes:
     pass
 
 
 @typing.overload
-def url_unescape(
-    value: Union[str, bytes], encoding: str = "utf-8", plus: bool = True
-) -> str:
+def url_unescape(value: str | bytes, encoding: str = "utf-8", plus: bool = True) -> str:
     pass
 
 
 def url_unescape(
-    value: Union[str, bytes], encoding: Optional[str] = "utf-8", plus: bool = True
-) -> Union[str, bytes]:
+    value: str | bytes, encoding: str | None = "utf-8", plus: bool = True
+) -> str | bytes:
     """Decodes the given value from a URL.
 
     The argument may be either a byte or unicode string.
@@ -171,7 +169,7 @@ def url_unescape(
 
 
 def parse_qs_bytes(
-    qs: Union[str, bytes], keep_blank_values: bool = False, strict_parsing: bool = False
+    qs: str | bytes, keep_blank_values: bool = False, strict_parsing: bool = False
 ) -> dict[str, list[bytes]]:
     """Parses a query string like urlparse.parse_qs,
     but takes bytes and returns the values as byte strings.
@@ -211,7 +209,7 @@ def utf8(value: None) -> None:
     pass
 
 
-def utf8(value: Union[None, str, bytes]) -> Optional[bytes]:
+def utf8(value: None | str | bytes) -> bytes | None:
     """Converts a string argument to a byte string.
 
     If the argument is already a byte string or None, it is returned unchanged.
@@ -242,7 +240,7 @@ def to_unicode(value: None) -> None:
     pass
 
 
-def to_unicode(value: Union[None, str, bytes]) -> Optional[str]:
+def to_unicode(value: None | str | bytes) -> str | None:
     """Converts a string argument to a unicode string.
 
     If the argument is already a unicode string or None, it is returned
@@ -297,9 +295,9 @@ _URL_RE = re.compile(
 
 
 def linkify(
-    text: Union[str, bytes],
+    text: str | bytes,
     shorten: bool = False,
-    extra_params: Union[str, Callable[[str], str]] = "",
+    extra_params: str | Callable[[str], str] = "",
     require_protocol: bool = False,
     permitted_protocols: list[str] = ["http", "https"],
 ) -> str:
index 2a2bb209286e53ad7567a436354f9716ae2ee52c..09a632940c882de7ae7f7a8aca3bde143895cea3 100644 (file)
@@ -179,7 +179,7 @@ def coroutine(func: Callable[..., _T]) -> Callable[..., "Future[_T]"]: ...
 
 
 def coroutine(
-    func: Union[Callable[..., "Generator[Any, Any, _T]"], Callable[..., _T]],
+    func: Callable[..., "Generator[Any, Any, _T]"] | Callable[..., _T],
 ) -> Callable[..., "Future[_T]"]:
     """Decorator for asynchronous generators.
 
@@ -362,7 +362,7 @@ class WaitIterator:
 
     """
 
-    _unfinished: dict[Future, Union[int, str]] = {}
+    _unfinished: dict[Future, int | str] = {}
 
     def __init__(self, *args: Future, **kwargs: Future) -> None:
         if args and kwargs:
@@ -376,9 +376,9 @@ class WaitIterator:
             futures = args
 
         self._finished: Deque[Future] = collections.deque()
-        self.current_index: Optional[Union[str, int]] = None
-        self.current_future: Optional[Future] = None
-        self._running_future: Optional[Future] = None
+        self.current_index: str | int | None = None
+        self.current_future: Future | None = None
+        self._running_future: Future | None = None
 
         for future in futures:
             future_add_done_callback(future, self._done_callback)
@@ -438,19 +438,19 @@ class WaitIterator:
 @overload
 def multi(
     children: Sequence[_Yieldable],
-    quiet_exceptions: Union[type[Exception], tuple[type[Exception], ...]] = (),
+    quiet_exceptions: type[Exception] | tuple[type[Exception], ...] = (),
 ) -> Future[list]: ...
 
 
 @overload
 def multi(
     children: Mapping[Any, _Yieldable],
-    quiet_exceptions: Union[type[Exception], tuple[type[Exception], ...]] = (),
+    quiet_exceptions: type[Exception] | tuple[type[Exception], ...] = (),
 ) -> Future[dict]: ...
 
 
 def multi(
-    children: Union[Sequence[_Yieldable], Mapping[Any, _Yieldable]],
+    children: Sequence[_Yieldable] | Mapping[Any, _Yieldable],
     quiet_exceptions: "Union[Type[Exception], Tuple[Type[Exception], ...]]" = (),
 ) -> "Union[Future[List], Future[Dict]]":
     """Runs multiple asynchronous operations in parallel.
@@ -504,7 +504,7 @@ Multi = multi
 
 
 def multi_future(
-    children: Union[Sequence[_Yieldable], Mapping[Any, _Yieldable]],
+    children: Sequence[_Yieldable] | Mapping[Any, _Yieldable],
     quiet_exceptions: "Union[Type[Exception], Tuple[Type[Exception], ...]]" = (),
 ) -> "Union[Future[List], Future[Dict]]":
     """Wait for multiple asynchronous futures in parallel.
@@ -522,7 +522,7 @@ def multi_future(
        Use `multi` instead.
     """
     if isinstance(children, dict):
-        keys: Optional[list] = list(children.keys())
+        keys: list | None = list(children.keys())
         children_seq: Iterable = children.values()
     else:
         keys = None
@@ -588,7 +588,7 @@ def maybe_future(x: Any) -> Future:
 
 
 def with_timeout(
-    timeout: Union[float, datetime.timedelta],
+    timeout: float | datetime.timedelta,
     future: _Yieldable,
     quiet_exceptions: "Union[Type[Exception], Tuple[Type[Exception], ...]]" = (),
 ) -> Future:
@@ -753,7 +753,7 @@ class Runner:
         self.ctx_run = ctx_run
         self.gen = gen
         self.result_future = result_future
-        self.future: Union[None, Future] = _null_future
+        self.future: None | Future = _null_future
         self.running = False
         self.finished = False
         self.io_loop = IOLoop.current()
@@ -783,7 +783,7 @@ class Runner:
                         # Save the exception for later. It's important that
                         # gen.throw() not be called inside this try/except block
                         # because that makes sys.exc_info behave unexpectedly.
-                        exc: Optional[Exception] = e
+                        exc: Exception | None = e
                     else:
                         exc = None
                     finally:
index c41b82f908163363e5a184453d00211aa34ff1e1..ee68d4e0ec2a43acb14f91cd8d1182f777e9fcb8 100644 (file)
@@ -36,7 +36,7 @@ from tornado.log import gen_log, app_log
 from tornado.util import GzipDecompressor
 
 
-from typing import cast, Optional, Type, Callable, Union
+from typing import cast, Optional, Type, Callable
 from collections.abc import Awaitable
 
 CR_OR_LF_RE = re.compile(b"\r|\n")
@@ -62,7 +62,7 @@ class _ExceptionLoggingContext:
     def __exit__(
         self,
         typ: "Optional[Type[BaseException]]",
-        value: Optional[BaseException],
+        value: BaseException | None,
         tb: types.TracebackType,
     ) -> None:
         if value is not None:
@@ -80,11 +80,11 @@ class HTTP1ConnectionParameters:
     def __init__(
         self,
         no_keep_alive: bool = False,
-        chunk_size: Optional[int] = None,
-        max_header_size: Optional[int] = None,
-        header_timeout: Optional[float] = None,
-        max_body_size: Optional[int] = None,
-        body_timeout: Optional[float] = None,
+        chunk_size: int | None = None,
+        max_header_size: int | None = None,
+        header_timeout: float | None = None,
+        max_body_size: int | None = None,
+        body_timeout: float | None = None,
         decompress: bool = False,
     ) -> None:
         """
@@ -118,8 +118,8 @@ class HTTP1Connection(httputil.HTTPConnection):
         self,
         stream: iostream.IOStream,
         is_client: bool,
-        params: Optional[HTTP1ConnectionParameters] = None,
-        context: Optional[object] = None,
+        params: HTTP1ConnectionParameters | None = None,
+        context: object | None = None,
     ) -> None:
         """
         :arg stream: an `.IOStream`
@@ -160,16 +160,16 @@ class HTTP1Connection(httputil.HTTPConnection):
         # Save the start lines after we read or write them; they
         # affect later processing (e.g. 304 responses and HEAD methods
         # have content-length but no bodies)
-        self._request_start_line: Optional[httputil.RequestStartLine] = None
-        self._response_start_line: Optional[httputil.ResponseStartLine] = None
-        self._request_headers: Optional[httputil.HTTPHeaders] = None
+        self._request_start_line: httputil.RequestStartLine | None = None
+        self._response_start_line: httputil.ResponseStartLine | None = None
+        self._request_headers: httputil.HTTPHeaders | None = None
         # True if we are writing output with chunked encoding.
         self._chunking_output = False
         # While reading a body with a content-length, this is the
         # amount left to read.
-        self._expected_content_remaining: Optional[int] = None
+        self._expected_content_remaining: int | None = None
         # A Future for our outgoing writes, returned by IOStream.write.
-        self._pending_write: Optional[Future[None]] = None
+        self._pending_write: Future[None] | None = None
 
     def read_response(self, delegate: httputil.HTTPMessageDelegate) -> Awaitable[bool]:
         """Read a single HTTP response.
@@ -208,9 +208,9 @@ class HTTP1Connection(httputil.HTTPConnection):
             if self.is_client:
                 resp_start_line = httputil.parse_response_start_line(start_line_str)
                 self._response_start_line = resp_start_line
-                start_line: Union[
-                    httputil.RequestStartLine, httputil.ResponseStartLine
-                ] = resp_start_line
+                start_line: httputil.RequestStartLine | httputil.ResponseStartLine = (
+                    resp_start_line
+                )
                 # TODO: this will need to change to support client-side keepalive
                 self._disconnect_on_finish = False
             else:
@@ -315,12 +315,12 @@ class HTTP1Connection(httputil.HTTPConnection):
         quickly in CPython by breaking up reference cycles.
         """
         self._write_callback = None
-        self._write_future: Optional[Future[None]] = None
-        self._close_callback: Optional[Callable[[], None]] = None
+        self._write_future: Future[None] | None = None
+        self._close_callback: Callable[[], None] | None = None
         if self.stream is not None:
             self.stream.set_close_callback(None)
 
-    def set_close_callback(self, callback: Optional[Callable[[], None]]) -> None:
+    def set_close_callback(self, callback: Callable[[], None] | None) -> None:
         """Sets a callback that will be run when the connection is closed.
 
         Note that this callback is slightly different from
@@ -384,9 +384,9 @@ class HTTP1Connection(httputil.HTTPConnection):
 
     def write_headers(
         self,
-        start_line: Union[httputil.RequestStartLine, httputil.ResponseStartLine],
+        start_line: httputil.RequestStartLine | httputil.ResponseStartLine,
         headers: httputil.HTTPHeaders,
-        chunk: Optional[bytes] = None,
+        chunk: bytes | None = None,
     ) -> "Future[None]":
         """Implements `.HTTPConnection.write_headers`."""
         lines = []
@@ -596,7 +596,7 @@ class HTTP1Connection(httputil.HTTPConnection):
         code: int,
         headers: httputil.HTTPHeaders,
         delegate: httputil.HTTPMessageDelegate,
-    ) -> Optional[Awaitable[None]]:
+    ) -> Awaitable[None] | None:
         if "Content-Length" in headers:
             if "," in headers["Content-Length"]:
                 # Proxies sometimes cause Content-Length headers to get
@@ -611,7 +611,7 @@ class HTTP1Connection(httputil.HTTPConnection):
                 headers["Content-Length"] = pieces[0]
 
             try:
-                content_length: Optional[int] = parse_int(headers["Content-Length"])
+                content_length: int | None = parse_int(headers["Content-Length"])
             except ValueError:
                 # Handles non-integer Content-Length value.
                 raise httputil.HTTPInputError(
@@ -709,13 +709,13 @@ class _GzipMessageDelegate(httputil.HTTPMessageDelegate):
     def __init__(self, delegate: httputil.HTTPMessageDelegate, chunk_size: int) -> None:
         self._delegate = delegate
         self._chunk_size = chunk_size
-        self._decompressor: Optional[GzipDecompressor] = None
+        self._decompressor: GzipDecompressor | None = None
 
     def headers_received(
         self,
-        start_line: Union[httputil.RequestStartLine, httputil.ResponseStartLine],
+        start_line: httputil.RequestStartLine | httputil.ResponseStartLine,
         headers: httputil.HTTPHeaders,
-    ) -> Optional[Awaitable[None]]:
+    ) -> Awaitable[None] | None:
         if headers.get("Content-Encoding", "").lower() == "gzip":
             self._decompressor = GzipDecompressor()
             # Downstream delegates will only see uncompressed data,
@@ -771,8 +771,8 @@ class HTTP1ServerConnection:
     def __init__(
         self,
         stream: iostream.IOStream,
-        params: Optional[HTTP1ConnectionParameters] = None,
-        context: Optional[object] = None,
+        params: HTTP1ConnectionParameters | None = None,
+        context: object | None = None,
     ) -> None:
         """
         :arg stream: an `.IOStream`
@@ -785,7 +785,7 @@ class HTTP1ServerConnection:
             params = HTTP1ConnectionParameters()
         self.params = params
         self.context = context
-        self._serving_future: Optional[Future[None]] = None
+        self._serving_future: Future[None] | None = None
 
     async def close(self) -> None:
         """Closes the connection.
index 915b7deb8ef7948622aad776c0d7ad9c95c91928..28860015af4ffea1bf767020eec1bb4a7360507e 100644 (file)
@@ -214,7 +214,7 @@ class AsyncHTTPClient(Configurable):
             instance_cache[instance.io_loop] = instance
         return instance
 
-    def initialize(self, defaults: Optional[dict[str, Any]] = None) -> None:
+    def initialize(self, defaults: dict[str, Any] | None = None) -> None:
         self.io_loop = IOLoop.current()
         self.defaults = dict(HTTPRequest._DEFAULTS)
         if defaults is not None:
@@ -340,7 +340,7 @@ class AsyncHTTPClient(Configurable):
 class HTTPRequest:
     """HTTP client request object."""
 
-    _headers: Union[dict[str, str], httputil.HTTPHeaders]
+    _headers: dict[str, str] | httputil.HTTPHeaders
 
     # Default values for HTTPRequest parameters.
     # Merged with the values on the request object by AsyncHTTPClient
@@ -360,41 +360,39 @@ class HTTPRequest:
         self,
         url: str,
         method: str = "GET",
-        headers: Optional[Union[dict[str, str], httputil.HTTPHeaders]] = None,
-        body: Optional[Union[bytes, str]] = None,
-        auth_username: Optional[str] = None,
-        auth_password: Optional[str] = None,
-        auth_mode: Optional[str] = None,
-        connect_timeout: Optional[float] = None,
-        request_timeout: Optional[float] = None,
-        if_modified_since: Optional[Union[float, datetime.datetime]] = None,
-        follow_redirects: Optional[bool] = None,
-        max_redirects: Optional[int] = None,
-        user_agent: Optional[str] = None,
-        use_gzip: Optional[bool] = None,
-        network_interface: Optional[str] = None,
-        streaming_callback: Optional[
-            Callable[[bytes], Optional[Awaitable[None]]]
-        ] = None,
-        header_callback: Optional[Callable[[str], None]] = None,
-        prepare_curl_callback: Optional[Callable[[Any], None]] = None,
-        proxy_host: Optional[str] = None,
-        proxy_port: Optional[int] = None,
-        proxy_username: Optional[str] = None,
-        proxy_password: Optional[str] = None,
-        proxy_auth_mode: Optional[str] = None,
-        allow_nonstandard_methods: Optional[bool] = None,
-        validate_cert: Optional[bool] = None,
-        ca_certs: Optional[str] = None,
-        allow_ipv6: Optional[bool] = None,
-        client_key: Optional[str] = None,
-        client_cert: Optional[str] = None,
-        body_producer: Optional[
+        headers: dict[str, str] | httputil.HTTPHeaders | None = None,
+        body: bytes | str | None = None,
+        auth_username: str | None = None,
+        auth_password: str | None = None,
+        auth_mode: str | None = None,
+        connect_timeout: float | None = None,
+        request_timeout: float | None = None,
+        if_modified_since: float | datetime.datetime | None = None,
+        follow_redirects: bool | None = None,
+        max_redirects: int | None = None,
+        user_agent: str | None = None,
+        use_gzip: bool | None = None,
+        network_interface: str | None = None,
+        streaming_callback: None | (Callable[[bytes], Awaitable[None] | None]) = None,
+        header_callback: Callable[[str], None] | None = None,
+        prepare_curl_callback: Callable[[Any], None] | None = None,
+        proxy_host: str | None = None,
+        proxy_port: int | None = None,
+        proxy_username: str | None = None,
+        proxy_password: str | None = None,
+        proxy_auth_mode: str | None = None,
+        allow_nonstandard_methods: bool | None = None,
+        validate_cert: bool | None = None,
+        ca_certs: str | None = None,
+        allow_ipv6: bool | None = None,
+        client_key: str | None = None,
+        client_cert: str | None = None,
+        body_producer: None | (
             Callable[[Callable[[bytes], None]], "Future[None]"]
-        ] = None,
+        ) = None,
         expect_100_continue: bool = False,
-        decompress_response: Optional[bool] = None,
-        ssl_options: Optional[Union[dict[str, Any], ssl.SSLContext]] = None,
+        decompress_response: bool | None = None,
+        ssl_options: dict[str, Any] | ssl.SSLContext | None = None,
     ) -> None:
         r"""All parameters except ``url`` are optional.
 
@@ -534,7 +532,7 @@ class HTTPRequest:
         self.max_redirects = max_redirects
         self.user_agent = user_agent
         if decompress_response is not None:
-            self.decompress_response: Optional[bool] = decompress_response
+            self.decompress_response: bool | None = decompress_response
         else:
             self.decompress_response = use_gzip
         self.network_interface = network_interface
@@ -559,7 +557,7 @@ class HTTPRequest:
         return self._headers  # type: ignore
 
     @headers.setter
-    def headers(self, value: Union[dict[str, str], httputil.HTTPHeaders]) -> None:
+    def headers(self, value: dict[str, str] | httputil.HTTPHeaders) -> None:
         if value is None:
             self._headers = httputil.HTTPHeaders()
         else:
@@ -570,7 +568,7 @@ class HTTPRequest:
         return self._body
 
     @body.setter
-    def body(self, value: Union[bytes, str]) -> None:
+    def body(self, value: bytes | str) -> None:
         self._body = utf8(value)
 
 
@@ -625,7 +623,7 @@ class HTTPResponse:
     """
 
     # I'm not sure why these don't get type-inferred from the references in __init__.
-    error: Optional[BaseException] = None
+    error: BaseException | None = None
     _error_is_response_code = False
     request: HTTPRequest
 
@@ -633,14 +631,14 @@ class HTTPResponse:
         self,
         request: HTTPRequest,
         code: int,
-        headers: Optional[httputil.HTTPHeaders] = None,
-        buffer: Optional[BytesIO] = None,
-        effective_url: Optional[str] = None,
-        error: Optional[BaseException] = None,
-        request_time: Optional[float] = None,
-        time_info: Optional[dict[str, float]] = None,
-        reason: Optional[str] = None,
-        start_time: Optional[float] = None,
+        headers: httputil.HTTPHeaders | None = None,
+        buffer: BytesIO | None = None,
+        effective_url: str | None = None,
+        error: BaseException | None = None,
+        request_time: float | None = None,
+        time_info: dict[str, float] | None = None,
+        reason: str | None = None,
+        start_time: float | None = None,
     ) -> None:
         if isinstance(request, _RequestProxy):
             self.request = request.request
@@ -653,7 +651,7 @@ class HTTPResponse:
         else:
             self.headers = httputil.HTTPHeaders()
         self.buffer = buffer
-        self._body: Optional[bytes] = None
+        self._body: bytes | None = None
         if effective_url is None:
             self.effective_url = request.url
         else:
@@ -714,8 +712,8 @@ class HTTPClientError(Exception):
     def __init__(
         self,
         code: int,
-        message: Optional[str] = None,
-        response: Optional[HTTPResponse] = None,
+        message: str | None = None,
+        response: HTTPResponse | None = None,
     ) -> None:
         self.code = code
         self.message = message or httputil.responses.get(code, "Unknown")
@@ -741,9 +739,7 @@ class _RequestProxy:
     Used internally by AsyncHTTPClient implementations.
     """
 
-    def __init__(
-        self, request: HTTPRequest, defaults: Optional[dict[str, Any]]
-    ) -> None:
+    def __init__(self, request: HTTPRequest, defaults: dict[str, Any] | None) -> None:
         self.request = request
         self.defaults = defaults
 
index d8ee9fadc52aa9244a1f99c46342fdf5e28378f9..8b575c99ee8991f7a708f53086c03c1fa8669079 100644 (file)
@@ -37,7 +37,7 @@ from tornado.tcpserver import TCPServer
 from tornado.util import Configurable
 
 import typing
-from typing import Union, Any, Callable, Optional
+from typing import Any, Callable
 from collections.abc import Awaitable
 
 if typing.TYPE_CHECKING:
@@ -164,22 +164,22 @@ class HTTPServer(TCPServer, Configurable, httputil.HTTPServerConnectionDelegate)
 
     def initialize(
         self,
-        request_callback: Union[
-            httputil.HTTPServerConnectionDelegate,
-            Callable[[httputil.HTTPServerRequest], None],
-        ],
+        request_callback: (
+            httputil.HTTPServerConnectionDelegate
+            | Callable[[httputil.HTTPServerRequest], None]
+        ),
         no_keep_alive: bool = False,
         xheaders: bool = False,
-        ssl_options: Optional[Union[dict[str, Any], ssl.SSLContext]] = None,
-        protocol: Optional[str] = None,
+        ssl_options: dict[str, Any] | ssl.SSLContext | None = None,
+        protocol: str | None = None,
         decompress_request: bool = False,
-        chunk_size: Optional[int] = None,
-        max_header_size: Optional[int] = None,
-        idle_connection_timeout: Optional[float] = None,
-        body_timeout: Optional[float] = None,
-        max_body_size: Optional[int] = None,
-        max_buffer_size: Optional[int] = None,
-        trusted_downstream: Optional[list[str]] = None,
+        chunk_size: int | None = None,
+        max_header_size: int | None = None,
+        idle_connection_timeout: float | None = None,
+        body_timeout: float | None = None,
+        max_body_size: int | None = None,
+        max_buffer_size: int | None = None,
+        trusted_downstream: list[str] | None = None,
     ) -> None:
         # This method's signature is not extracted with autodoc
         # because we want its arguments to appear on the class
@@ -266,15 +266,15 @@ class _CallableAdapter(httputil.HTTPMessageDelegate):
     ) -> None:
         self.connection = request_conn
         self.request_callback = request_callback
-        self.request: Optional[httputil.HTTPServerRequest] = None
+        self.request: httputil.HTTPServerRequest | None = None
         self.delegate = None
         self._chunks: list[bytes] = []
 
     def headers_received(
         self,
-        start_line: Union[httputil.RequestStartLine, httputil.ResponseStartLine],
+        start_line: httputil.RequestStartLine | httputil.ResponseStartLine,
         headers: httputil.HTTPHeaders,
-    ) -> Optional[Awaitable[None]]:
+    ) -> Awaitable[None] | None:
         self.request = httputil.HTTPServerRequest(
             connection=self.connection,
             start_line=typing.cast(httputil.RequestStartLine, start_line),
@@ -282,7 +282,7 @@ class _CallableAdapter(httputil.HTTPMessageDelegate):
         )
         return None
 
-    def data_received(self, chunk: bytes) -> Optional[Awaitable[None]]:
+    def data_received(self, chunk: bytes) -> Awaitable[None] | None:
         self._chunks.append(chunk)
         return None
 
@@ -301,8 +301,8 @@ class _HTTPRequestContext:
         self,
         stream: iostream.IOStream,
         address: tuple,
-        protocol: Optional[str],
-        trusted_downstream: Optional[list[str]] = None,
+        protocol: str | None,
+        trusted_downstream: list[str] | None = None,
     ) -> None:
         self.address = address
         # Save the socket's address family now so we know how to
@@ -385,15 +385,15 @@ class _ProxyAdapter(httputil.HTTPMessageDelegate):
 
     def headers_received(
         self,
-        start_line: Union[httputil.RequestStartLine, httputil.ResponseStartLine],
+        start_line: httputil.RequestStartLine | httputil.ResponseStartLine,
         headers: httputil.HTTPHeaders,
-    ) -> Optional[Awaitable[None]]:
+    ) -> Awaitable[None] | None:
         # TODO: either make context an official part of the
         # HTTPConnection interface or figure out some other way to do this.
         self.connection.context._apply_xheaders(headers)  # type: ignore
         return self.delegate.headers_received(start_line, headers)
 
-    def data_received(self, chunk: bytes) -> Optional[Awaitable[None]]:
+    def data_received(self, chunk: bytes) -> Awaitable[None] | None:
         return self.delegate.data_received(chunk)
 
     def finish(self) -> None:
index a8ee7f39f787ad8a6786488f36d8b0e4afe53ff5..20856aa0236e07eed1830e1fc1de15e45bf95ac3 100644 (file)
@@ -42,7 +42,6 @@ from tornado.util import errno_from_exception
 
 import typing
 from typing import (
-    Union,
     Optional,
     Callable,
     Any,
@@ -93,7 +92,7 @@ class StreamClosedError(IOError):
        Added the ``real_error`` attribute.
     """
 
-    def __init__(self, real_error: Optional[BaseException] = None) -> None:
+    def __init__(self, real_error: BaseException | None = None) -> None:
         super().__init__("Stream is closed")
         self.real_error = real_error
 
@@ -120,9 +119,7 @@ class _StreamBuffer:
 
     def __init__(self) -> None:
         # A sequence of (False, bytearray) and (True, memoryview) objects
-        self._buffers: Deque[tuple[bool, Union[bytearray, memoryview]]] = (
-            collections.deque()
-        )
+        self._buffers: Deque[tuple[bool, bytearray | memoryview]] = collections.deque()
         # Position in the first buffer
         self._first_pos = 0
         self._size = 0
@@ -134,7 +131,7 @@ class _StreamBuffer:
     # of extending an existing bytearray
     _large_buf_threshold = 2048
 
-    def append(self, data: Union[bytes, bytearray, memoryview]) -> None:
+    def append(self, data: bytes | bytearray | memoryview) -> None:
         """
         Append the given piece of data (should be a buffer-compatible object).
         """
@@ -222,9 +219,9 @@ class BaseIOStream:
 
     def __init__(
         self,
-        max_buffer_size: Optional[int] = None,
-        read_chunk_size: Optional[int] = None,
-        max_write_buffer_size: Optional[int] = None,
+        max_buffer_size: int | None = None,
+        read_chunk_size: int | None = None,
+        max_write_buffer_size: int | None = None,
     ) -> None:
         """`BaseIOStream` constructor.
 
@@ -248,34 +245,34 @@ class BaseIOStream:
         # spurious failures.
         self.read_chunk_size = min(read_chunk_size or 65536, self.max_buffer_size // 2)
         self.max_write_buffer_size = max_write_buffer_size
-        self.error: Optional[BaseException] = None
+        self.error: BaseException | None = None
         self._read_buffer = bytearray()
         self._read_buffer_size = 0
         self._user_read_buffer = False
-        self._after_user_read_buffer: Optional[bytearray] = None
+        self._after_user_read_buffer: bytearray | None = None
         self._write_buffer = _StreamBuffer()
         self._total_write_index = 0
         self._total_write_done_index = 0
-        self._read_delimiter: Optional[bytes] = None
-        self._read_regex: Optional[Pattern] = None
-        self._read_max_bytes: Optional[int] = None
-        self._read_bytes: Optional[int] = None
+        self._read_delimiter: bytes | None = None
+        self._read_regex: Pattern | None = None
+        self._read_max_bytes: int | None = None
+        self._read_bytes: int | None = None
         self._read_partial = False
         self._read_until_close = False
-        self._read_future: Optional[Future] = None
+        self._read_future: Future | None = None
         self._write_futures: Deque[tuple[int, Future[None]]] = collections.deque()
-        self._close_callback: Optional[Callable[[], None]] = None
-        self._connect_future: Optional[Future[IOStream]] = None
+        self._close_callback: Callable[[], None] | None = None
+        self._connect_future: Future[IOStream] | None = None
         # _ssl_connect_future should be defined in SSLIOStream
         # but it's here so we can clean it up in _signal_closed
         # TODO: refactor that so subclasses can add additional futures
         # to be cancelled.
-        self._ssl_connect_future: Optional[Future[SSLIOStream]] = None
+        self._ssl_connect_future: Future[SSLIOStream] | None = None
         self._connecting = False
-        self._state: Optional[int] = None
+        self._state: int | None = None
         self._closed = False
 
-    def fileno(self) -> Union[int, ioloop._Selectable]:
+    def fileno(self) -> int | ioloop._Selectable:
         """Returns the file descriptor for this stream."""
         raise NotImplementedError()
 
@@ -294,7 +291,7 @@ class BaseIOStream:
         """
         raise NotImplementedError()
 
-    def read_from_fd(self, buf: Union[bytearray, memoryview]) -> Optional[int]:
+    def read_from_fd(self, buf: bytearray | memoryview) -> int | None:
         """Attempts to read from the underlying file.
 
         Reads up to ``len(buf)`` bytes, storing them in the buffer.
@@ -309,7 +306,7 @@ class BaseIOStream:
         """
         raise NotImplementedError()
 
-    def get_fd_error(self) -> Optional[Exception]:
+    def get_fd_error(self) -> Exception | None:
         """Returns information about any error on the underlying file.
 
         This method is called after the `.IOLoop` has signaled an error on the
@@ -320,7 +317,7 @@ class BaseIOStream:
         return None
 
     def read_until_regex(
-        self, regex: bytes, max_bytes: Optional[int] = None
+        self, regex: bytes, max_bytes: int | None = None
     ) -> Awaitable[bytes]:
         """Asynchronously read until we have matched the given regex.
 
@@ -359,7 +356,7 @@ class BaseIOStream:
         return future
 
     def read_until(
-        self, delimiter: bytes, max_bytes: Optional[int] = None
+        self, delimiter: bytes, max_bytes: int | None = None
     ) -> Awaitable[bytes]:
         """Asynchronously read until we have found the given delimiter.
 
@@ -496,7 +493,7 @@ class BaseIOStream:
             raise
         return future
 
-    def write(self, data: Union[bytes, memoryview]) -> "Future[None]":
+    def write(self, data: bytes | memoryview) -> "Future[None]":
         """Asynchronously write the given data to this stream.
 
         This method returns a `.Future` that resolves (with a result
@@ -538,7 +535,7 @@ class BaseIOStream:
             self._maybe_add_error_listener()
         return future
 
-    def set_close_callback(self, callback: Optional[Callable[[], None]]) -> None:
+    def set_close_callback(self, callback: Callable[[], None] | None) -> None:
         """Call the given callback when the stream is closed.
 
         This mostly is not necessary for applications that use the
@@ -555,16 +552,16 @@ class BaseIOStream:
 
     def close(
         self,
-        exc_info: Union[
-            None,
-            bool,
-            BaseException,
-            tuple[
+        exc_info: (
+            None
+            | bool
+            | BaseException
+            tuple[
                 "Optional[Type[BaseException]]",
-                Optional[BaseException],
-                Optional[TracebackType],
-            ],
-        ] = False,
+                BaseException | None,
+                TracebackType | None,
+            ]
+        ) = False,
     ) -> None:
         """Close this stream.
 
@@ -670,7 +667,7 @@ class BaseIOStream:
     def _handle_connect(self) -> None:
         raise NotImplementedError()
 
-    def _handle_events(self, fd: Union[int, ioloop._Selectable], events: int) -> None:
+    def _handle_events(self, fd: int | ioloop._Selectable, events: int) -> None:
         if self.closed():
             gen_log.warning("Got events for closed stream %s", fd)
             return
@@ -723,10 +720,10 @@ class BaseIOStream:
             self.close(exc_info=e)
             raise
 
-    def _read_to_buffer_loop(self) -> Optional[int]:
+    def _read_to_buffer_loop(self) -> int | None:
         # This method is called from _handle_read and _try_inline_read.
         if self._read_bytes is not None:
-            target_bytes: Optional[int] = self._read_bytes
+            target_bytes: int | None = self._read_bytes
         elif self._read_max_bytes is not None:
             target_bytes = self._read_max_bytes
         elif self.reading():
@@ -807,7 +804,7 @@ class BaseIOStream:
             self._after_user_read_buffer = None
             self._read_buffer_size = len(self._read_buffer)
             self._user_read_buffer = False
-            result: Union[int, bytes] = size
+            result: int | bytes = size
         else:
             result = self._consume(size)
         if self._read_future is not None:
@@ -838,7 +835,7 @@ class BaseIOStream:
         if not self.closed():
             self._add_io_state(ioloop.IOLoop.READ)
 
-    def _read_to_buffer(self) -> Optional[int]:
+    def _read_to_buffer(self) -> int | None:
         """Reads from the socket and appends the result to the read buffer.
 
         Returns the number of bytes read.  Returns 0 if there is nothing
@@ -849,9 +846,9 @@ class BaseIOStream:
             while True:
                 try:
                     if self._user_read_buffer:
-                        buf: Union[memoryview, bytearray] = memoryview(
-                            self._read_buffer
-                        )[self._read_buffer_size :]
+                        buf: memoryview | bytearray = memoryview(self._read_buffer)[
+                            self._read_buffer_size :
+                        ]
                     else:
                         buf = bytearray(self.read_chunk_size)
                     bytes_read = self.read_from_fd(buf)
@@ -894,7 +891,7 @@ class BaseIOStream:
         self._read_partial = False
         self._finish_read(pos)
 
-    def _find_read_pos(self) -> Optional[int]:
+    def _find_read_pos(self) -> int | None:
         """Attempts to find a position in the read buffer that satisfies
         the currently-pending read.
 
@@ -933,7 +930,7 @@ class BaseIOStream:
                 self._check_max_bytes(self._read_regex, self._read_buffer_size)
         return None
 
-    def _check_max_bytes(self, delimiter: Union[bytes, Pattern], size: int) -> None:
+    def _check_max_bytes(self, delimiter: bytes | Pattern, size: int) -> None:
         if self._read_max_bytes is not None and size > self._read_max_bytes:
             raise UnsatisfiableReadError(
                 "delimiter %r not found within %d bytes"
@@ -1093,18 +1090,18 @@ class IOStream(BaseIOStream):
         self.socket.setblocking(False)
         super().__init__(*args, **kwargs)
 
-    def fileno(self) -> Union[int, ioloop._Selectable]:
+    def fileno(self) -> int | ioloop._Selectable:
         return self.socket
 
     def close_fd(self) -> None:
         self.socket.close()
         self.socket = None  # type: ignore
 
-    def get_fd_error(self) -> Optional[Exception]:
+    def get_fd_error(self) -> Exception | None:
         errno = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
         return socket.error(errno, os.strerror(errno))
 
-    def read_from_fd(self, buf: Union[bytearray, memoryview]) -> Optional[int]:
+    def read_from_fd(self, buf: bytearray | memoryview) -> int | None:
         try:
             return self.socket.recv_into(buf, len(buf))
         except BlockingIOError:
@@ -1121,7 +1118,7 @@ class IOStream(BaseIOStream):
             del data
 
     def connect(
-        self: _IOStreamType, address: Any, server_hostname: Optional[str] = None
+        self: _IOStreamType, address: Any, server_hostname: str | None = None
     ) -> "Future[_IOStreamType]":
         """Connects the socket to a remote address without blocking.
 
@@ -1190,8 +1187,8 @@ class IOStream(BaseIOStream):
     def start_tls(
         self,
         server_side: bool,
-        ssl_options: Optional[Union[dict[str, Any], ssl.SSLContext]] = None,
-        server_hostname: Optional[str] = None,
+        ssl_options: dict[str, Any] | ssl.SSLContext | None = None,
+        server_hostname: str | None = None,
     ) -> Awaitable["SSLIOStream"]:
         """Convert this `IOStream` to an `SSLIOStream`.
 
@@ -1332,7 +1329,7 @@ class SSLIOStream(IOStream):
         self._ssl_accepting = True
         self._handshake_reading = False
         self._handshake_writing = False
-        self._server_hostname: Optional[str] = None
+        self._server_hostname: str | None = None
 
         # If the socket is already connected, attempt to start the handshake.
         try:
@@ -1421,7 +1418,7 @@ class SSLIOStream(IOStream):
         super()._handle_write()
 
     def connect(
-        self, address: tuple, server_hostname: Optional[str] = None
+        self, address: tuple, server_hostname: str | None = None
     ) -> "Future[SSLIOStream]":
         self._server_hostname = server_hostname
         # Ignore the result of connect(). If it fails,
@@ -1522,7 +1519,7 @@ class SSLIOStream(IOStream):
             # See https://github.com/tornadoweb/tornado/pull/2008
             del data
 
-    def read_from_fd(self, buf: Union[bytearray, memoryview]) -> Optional[int]:
+    def read_from_fd(self, buf: bytearray | memoryview) -> int | None:
         try:
             if self._ssl_accepting:
                 # If the handshake hasn't finished yet, there can't be anything
@@ -1592,7 +1589,7 @@ class PipeIOStream(BaseIOStream):
             # See https://github.com/tornadoweb/tornado/pull/2008
             del data
 
-    def read_from_fd(self, buf: Union[bytearray, memoryview]) -> Optional[int]:
+    def read_from_fd(self, buf: bytearray | memoryview) -> int | None:
         try:
             return self._fio.readinto(buf)  # type: ignore
         except OSError as e:
index 28cde94616d36e696e92007f59ffda2343376156..9cc30276aa50a181c80528deb9a798eebb2d55d4 100644 (file)
@@ -19,7 +19,7 @@ import types
 from tornado import gen, ioloop
 from tornado.concurrent import Future, future_set_result_unless_cancelled
 
-from typing import Union, Optional, Type, Any
+from typing import Optional, Type, Any
 from collections.abc import Awaitable
 import typing
 
@@ -118,7 +118,7 @@ class Condition(_TimeoutGarbageCollector):
         return result + ">"
 
     def wait(
-        self, timeout: Optional[Union[float, datetime.timedelta]] = None
+        self, timeout: float | datetime.timedelta | None = None
     ) -> Awaitable[bool]:
         """Wait for `.notify`.
 
@@ -230,7 +230,7 @@ class Event:
         self._value = False
 
     def wait(
-        self, timeout: Optional[Union[float, datetime.timedelta]] = None
+        self, timeout: float | datetime.timedelta | None = None
     ) -> Awaitable[None]:
         """Block until the internal flag is true.
 
@@ -274,8 +274,8 @@ class _ReleasingContextManager:
     def __exit__(
         self,
         exc_type: "Optional[Type[BaseException]]",
-        exc_val: Optional[BaseException],
-        exc_tb: Optional[types.TracebackType],
+        exc_val: BaseException | None,
+        exc_tb: types.TracebackType | None,
     ) -> None:
         self._obj.release()
 
@@ -413,7 +413,7 @@ class Semaphore(_TimeoutGarbageCollector):
                 break
 
     def acquire(
-        self, timeout: Optional[Union[float, datetime.timedelta]] = None
+        self, timeout: float | datetime.timedelta | None = None
     ) -> Awaitable[_ReleasingContextManager]:
         """Decrement the counter. Returns an awaitable.
 
@@ -446,8 +446,8 @@ class Semaphore(_TimeoutGarbageCollector):
     def __exit__(
         self,
         typ: "Optional[Type[BaseException]]",
-        value: Optional[BaseException],
-        traceback: Optional[types.TracebackType],
+        value: BaseException | None,
+        traceback: types.TracebackType | None,
     ) -> None:
         self.__enter__()
 
@@ -457,8 +457,8 @@ class Semaphore(_TimeoutGarbageCollector):
     async def __aexit__(
         self,
         typ: "Optional[Type[BaseException]]",
-        value: Optional[BaseException],
-        tb: Optional[types.TracebackType],
+        value: BaseException | None,
+        tb: types.TracebackType | None,
     ) -> None:
         self.release()
 
@@ -527,7 +527,7 @@ class Lock:
         return f"<{self.__class__.__name__} _block={self._block}>"
 
     def acquire(
-        self, timeout: Optional[Union[float, datetime.timedelta]] = None
+        self, timeout: float | datetime.timedelta | None = None
     ) -> Awaitable[_ReleasingContextManager]:
         """Attempt to lock. Returns an awaitable.
 
@@ -554,8 +554,8 @@ class Lock:
     def __exit__(
         self,
         typ: "Optional[Type[BaseException]]",
-        value: Optional[BaseException],
-        tb: Optional[types.TracebackType],
+        value: BaseException | None,
+        tb: types.TracebackType | None,
     ) -> None:
         self.__enter__()
 
@@ -565,7 +565,7 @@ class Lock:
     async def __aexit__(
         self,
         typ: "Optional[Type[BaseException]]",
-        value: Optional[BaseException],
-        tb: Optional[types.TracebackType],
+        value: BaseException | None,
+        tb: types.TracebackType | None,
     ) -> None:
         self.release()
index dc9fcd2e90a7aae34adb80d2ecd9baee7d1bc902..978343d28d1a7d27ef568e259077e98132e79a1f 100644 (file)
@@ -45,7 +45,7 @@ try:
 except ImportError:
     curses = None  # type: ignore
 
-from typing import Any, cast, Optional
+from typing import Any, cast
 
 # Logger objects for internal tornado use
 access_log = logging.getLogger("tornado.access")
@@ -214,7 +214,7 @@ class LogFormatter(logging.Formatter):
 
 
 def enable_pretty_logging(
-    options: Any = None, logger: Optional[logging.Logger] = None
+    options: Any = None, logger: logging.Logger | None = None
 ) -> None:
     """Turns on formatted logging output as configured.
 
index 35f294e962ef559100b136b32f9127fcc6889943..96189295850cacfec8e4299ca34dfd9347186a3e 100644 (file)
@@ -28,7 +28,7 @@ from tornado.concurrent import dummy_executor, run_on_executor
 from tornado.ioloop import IOLoop
 from tornado.util import Configurable, errno_from_exception
 
-from typing import Callable, Any, Union, Optional
+from typing import Callable, Any
 from collections.abc import Awaitable
 
 # Note that the naming of ssl.Purpose is confusing; the purpose
@@ -56,10 +56,10 @@ _DEFAULT_BACKLOG = 128
 
 def bind_sockets(
     port: int,
-    address: Optional[str] = None,
+    address: str | None = None,
     family: socket.AddressFamily = socket.AF_UNSPEC,
     backlog: int = _DEFAULT_BACKLOG,
-    flags: Optional[int] = None,
+    flags: int | None = None,
     reuse_port: bool = False,
 ) -> list[socket.socket]:
     """Creates listening sockets bound to the given port and address.
@@ -462,7 +462,7 @@ class ExecutorResolver(Resolver):
 
     def initialize(
         self,
-        executor: Optional[concurrent.futures.Executor] = None,
+        executor: concurrent.futures.Executor | None = None,
         close_executor: bool = True,
     ) -> None:
         if executor is not None:
@@ -516,8 +516,8 @@ class ThreadedResolver(ExecutorResolver):
        of this class.
     """
 
-    _threadpool: Optional[concurrent.futures.ThreadPoolExecutor] = None
-    _threadpool_pid: Optional[int] = None
+    _threadpool: concurrent.futures.ThreadPoolExecutor | None = None
+    _threadpool_pid: int | None = None
 
     def initialize(self, num_threads: int = 10) -> None:  # type: ignore
         threadpool = ThreadedResolver._create_threadpool(num_threads)
@@ -589,8 +589,8 @@ _SSL_CONTEXT_KEYWORDS = frozenset(
 
 
 def ssl_options_to_context(
-    ssl_options: Union[dict[str, Any], ssl.SSLContext],
-    server_side: Optional[bool] = None,
+    ssl_options: dict[str, Any] | ssl.SSLContext,
+    server_side: bool | None = None,
 ) -> ssl.SSLContext:
     """Try to convert an ``ssl_options`` dictionary to an
     `~ssl.SSLContext` object.
@@ -643,9 +643,9 @@ def ssl_options_to_context(
 
 def ssl_wrap_socket(
     socket: socket.socket,
-    ssl_options: Union[dict[str, Any], ssl.SSLContext],
-    server_hostname: Optional[str] = None,
-    server_side: Optional[bool] = None,
+    ssl_options: dict[str, Any] | ssl.SSLContext,
+    server_hostname: str | None = None,
+    server_side: bool | None = None,
     **kwargs: Any,
 ) -> ssl.SSLSocket:
     """Returns an ``ssl.SSLSocket`` wrapping the given socket.
index ee3f22140aa7c045e543bda6e04c6b3216e11e2d..44775d0185e6628954b70fd5d51fbd724d10b0fc 100644 (file)
@@ -114,7 +114,6 @@ from typing import (
     Any,
     Callable,
     TextIO,
-    Optional,
 )
 from collections.abc import Iterator, Iterable
 
@@ -219,12 +218,12 @@ class OptionParser:
         self,
         name: str,
         default: Any = None,
-        type: Optional[type] = None,
-        help: Optional[str] = None,
-        metavar: Optional[str] = None,
+        type: type | None = None,
+        help: str | None = None,
+        metavar: str | None = None,
         multiple: bool = False,
-        group: Optional[str] = None,
-        callback: Optional[Callable[[Any], None]] = None,
+        group: str | None = None,
+        callback: Callable[[Any], None] | None = None,
     ) -> None:
         """Defines a new command line option.
 
@@ -291,7 +290,7 @@ class OptionParser:
             else:
                 type = str
         if group:
-            group_name: Optional[str] = group
+            group_name: str | None = group
         else:
             group_name = file_name
         option = _Option(
@@ -308,7 +307,7 @@ class OptionParser:
         self._options[normalized] = option
 
     def parse_command_line(
-        self, args: Optional[list[str]] = None, final: bool = True
+        self, args: list[str] | None = None, final: bool = True
     ) -> list[str]:
         """Parses all options given on the command line (defaults to
         `sys.argv`).
@@ -432,7 +431,7 @@ class OptionParser:
         if final:
             self.run_parse_callbacks()
 
-    def print_help(self, file: Optional[TextIO] = None) -> None:
+    def print_help(self, file: TextIO | None = None) -> None:
         """Prints all the command line options to stderr (or another file)."""
         if file is None:
             file = sys.stderr
@@ -529,13 +528,13 @@ class _Option:
         self,
         name: str,
         default: Any = None,
-        type: Optional[type] = None,
-        help: Optional[str] = None,
-        metavar: Optional[str] = None,
+        type: type | None = None,
+        help: str | None = None,
+        metavar: str | None = None,
         multiple: bool = False,
-        file_name: Optional[str] = None,
-        group_name: Optional[str] = None,
-        callback: Optional[Callable[[Any], None]] = None,
+        file_name: str | None = None,
+        group_name: str | None = None,
+        callback: Callable[[Any], None] | None = None,
     ) -> None:
         if default is None and multiple:
             default = []
@@ -677,12 +676,12 @@ All defined options are available as attributes on this object.
 def define(
     name: str,
     default: Any = None,
-    type: Optional[type] = None,
-    help: Optional[str] = None,
-    metavar: Optional[str] = None,
+    type: type | None = None,
+    help: str | None = None,
+    metavar: str | None = None,
     multiple: bool = False,
-    group: Optional[str] = None,
-    callback: Optional[Callable[[Any], None]] = None,
+    group: str | None = None,
+    callback: Callable[[Any], None] | None = None,
 ) -> None:
     """Defines an option in the global namespace.
 
@@ -700,9 +699,7 @@ def define(
     )
 
 
-def parse_command_line(
-    args: Optional[list[str]] = None, final: bool = True
-) -> list[str]:
+def parse_command_line(args: list[str] | None = None, final: bool = True) -> list[str]:
     """Parses global options from the command line.
 
     See `OptionParser.parse_command_line`.
@@ -718,7 +715,7 @@ def parse_config_file(path: str, final: bool = True) -> None:
     return options.parse_config_file(path, final=final)
 
 
-def print_help(file: Optional[TextIO] = None) -> None:
+def print_help(file: TextIO | None = None) -> None:
     """Prints all the command line options to stderr (or another file).
 
     See `OptionParser.print_help`.
index 72299bd014c32d81e94c69a6bef070ba36c486e9..3229cc239e5c9e0561d60097cee021e576cb5159 100644 (file)
@@ -40,7 +40,6 @@ from tornado.ioloop import IOLoop, _Selectable
 from typing import (
     Any,
     Callable,
-    Optional,
     Protocol,
     TypeVar,
     Union,
@@ -105,7 +104,7 @@ class BaseAsyncIOLoop(IOLoop):
             # doesn't understand dynamic proxies.
             self.selector_loop = AddThreadSelectorEventLoop(asyncio_loop)  # type: ignore
         # Maps fd to (fileobj, handler function) pair (as in IOLoop.add_handler)
-        self.handlers: dict[int, tuple[Union[int, _Selectable], Callable]] = {}
+        self.handlers: dict[int, tuple[int | _Selectable, Callable]] = {}
         # Set of fds listening for reads/writes
         self.readers: set[int] = set()
         self.writers: set[int] = set()
@@ -155,7 +154,7 @@ class BaseAsyncIOLoop(IOLoop):
         self.asyncio_loop.close()
 
     def add_handler(
-        self, fd: Union[int, _Selectable], handler: Callable[..., None], events: int
+        self, fd: int | _Selectable, handler: Callable[..., None], events: int
     ) -> None:
         fd, fileobj = self.split_fd(fd)
         if fd in self.handlers:
@@ -168,7 +167,7 @@ class BaseAsyncIOLoop(IOLoop):
             self.selector_loop.add_writer(fd, self._handle_events, fd, IOLoop.WRITE)
             self.writers.add(fd)
 
-    def update_handler(self, fd: Union[int, _Selectable], events: int) -> None:
+    def update_handler(self, fd: int | _Selectable, events: int) -> None:
         fd, fileobj = self.split_fd(fd)
         if events & IOLoop.READ:
             if fd not in self.readers:
@@ -187,7 +186,7 @@ class BaseAsyncIOLoop(IOLoop):
                 self.selector_loop.remove_writer(fd)
                 self.writers.remove(fd)
 
-    def remove_handler(self, fd: Union[int, _Selectable]) -> None:
+    def remove_handler(self, fd: int | _Selectable) -> None:
         fd, fileobj = self.split_fd(fd)
         if fd not in self.handlers:
             return
@@ -261,7 +260,7 @@ class BaseAsyncIOLoop(IOLoop):
 
     def run_in_executor(
         self,
-        executor: Optional[concurrent.futures.Executor],
+        executor: concurrent.futures.Executor | None,
         func: Callable[..., _T],
         *args: Any,
     ) -> "asyncio.Future[_T]":
@@ -474,11 +473,11 @@ class SelectorThread:
         self._real_loop = real_loop
 
         self._select_cond = threading.Condition()
-        self._select_args: Optional[
+        self._select_args: None | (
             tuple[list[_FileDescriptorLike], list[_FileDescriptorLike]]
-        ] = None
+        ) = None
         self._closing_selector = False
-        self._thread: Optional[threading.Thread] = None
+        self._thread: threading.Thread | None = None
         self._thread_manager_handle = self._thread_manager()
 
         async def thread_manager_anext() -> None:
index 1ff2c83988c4713fbe0a4ac57914afe791c982a0..f926c88521ce128fcd4415dd5972345c9d077561 100644 (file)
@@ -37,7 +37,7 @@ from tornado.iostream import PipeIOStream
 from tornado.log import gen_log
 
 import typing
-from typing import Optional, Any, Callable
+from typing import Any, Callable
 
 if typing.TYPE_CHECKING:
     from typing import List  # noqa: F401
@@ -80,9 +80,7 @@ def _reseed_random() -> None:
 _task_id = None
 
 
-def fork_processes(
-    num_processes: Optional[int], max_restarts: Optional[int] = None
-) -> int:
+def fork_processes(num_processes: int | None, max_restarts: int | None = None) -> int:
     """Starts multiple worker processes.
 
     If ``num_processes`` is None or <= 0, we detect the number of cores
@@ -123,7 +121,7 @@ def fork_processes(
     gen_log.info("Starting %d processes", num_processes)
     children = {}
 
-    def start_child(i: int) -> Optional[int]:
+    def start_child(i: int) -> int | None:
         pid = os.fork()
         if pid == 0:
             # child process
@@ -175,7 +173,7 @@ def fork_processes(
     sys.exit(0)
 
 
-def task_id() -> Optional[int]:
+def task_id() -> int | None:
     """Returns the current task id, if any.
 
     Returns None if this process was not created by `fork_processes`.
@@ -246,8 +244,8 @@ class Subprocess:
         for attr in ["stdin", "stdout", "stderr"]:
             if not hasattr(self, attr):  # don't clobber streams set above
                 setattr(self, attr, getattr(self.proc, attr))
-        self._exit_callback: Optional[Callable[[int], None]] = None
-        self.returncode: Optional[int] = None
+        self._exit_callback: Callable[[int], None] | None = None
+        self.returncode: int | None = None
 
     def set_exit_callback(self, callback: Callable[[int], None]) -> None:
         """Runs ``callback`` when this process exits.
index 82c034c63b3028d72ed5c88e5733ab2b3294aaa8..30d241e49ecc06f6a5c15b04cda5ba05312aaeac 100644 (file)
@@ -187,7 +187,6 @@ from tornado.util import basestring_type, import_object, re_unescape, unicode_ty
 from typing import (
     Any,
     Union,
-    Optional,
     overload,
 )
 from collections.abc import Awaitable, Sequence
@@ -199,7 +198,7 @@ class Router(httputil.HTTPServerConnectionDelegate):
 
     def find_handler(
         self, request: httputil.HTTPServerRequest, **kwargs: Any
-    ) -> Optional[httputil.HTTPMessageDelegate]:
+    ) -> httputil.HTTPMessageDelegate | None:
         """Must be implemented to return an appropriate instance of `~.httputil.HTTPMessageDelegate`
         that can serve the request.
         Routing implementations may pass additional kwargs to extend the routing logic.
@@ -222,7 +221,7 @@ class ReversibleRouter(Router):
     and support reversing them to original urls.
     """
 
-    def reverse_url(self, name: str, *args: Any) -> Optional[str]:
+    def reverse_url(self, name: str, *args: Any) -> str | None:
         """Returns url string for a given route name and arguments
         or ``None`` if no match is found.
 
@@ -239,14 +238,14 @@ class _RoutingDelegate(httputil.HTTPMessageDelegate):
     ) -> None:
         self.server_conn = server_conn
         self.request_conn = request_conn
-        self.delegate: Optional[httputil.HTTPMessageDelegate] = None
+        self.delegate: httputil.HTTPMessageDelegate | None = None
         self.router: Router = router
 
     def headers_received(
         self,
-        start_line: Union[httputil.RequestStartLine, httputil.ResponseStartLine],
+        start_line: httputil.RequestStartLine | httputil.ResponseStartLine,
         headers: httputil.HTTPHeaders,
-    ) -> Optional[Awaitable[None]]:
+    ) -> Awaitable[None] | None:
         assert isinstance(start_line, httputil.RequestStartLine)
         request = httputil.HTTPServerRequest(
             connection=self.request_conn,
@@ -266,7 +265,7 @@ class _RoutingDelegate(httputil.HTTPMessageDelegate):
 
         return self.delegate.headers_received(start_line, headers)
 
-    def data_received(self, chunk: bytes) -> Optional[Awaitable[None]]:
+    def data_received(self, chunk: bytes) -> Awaitable[None] | None:
         assert self.delegate is not None
         return self.delegate.data_received(chunk)
 
@@ -307,7 +306,7 @@ _RuleList = Sequence[
 class RuleRouter(Router):
     """Rule-based router implementation."""
 
-    def __init__(self, rules: Optional[_RuleList] = None) -> None:
+    def __init__(self, rules: _RuleList | None = None) -> None:
         """Constructs a router from an ordered list of rules::
 
             RuleRouter([
@@ -364,7 +363,7 @@ class RuleRouter(Router):
 
     def find_handler(
         self, request: httputil.HTTPServerRequest, **kwargs: Any
-    ) -> Optional[httputil.HTTPMessageDelegate]:
+    ) -> httputil.HTTPMessageDelegate | None:
         for rule in self.rules:
             target_params = rule.matcher.match(request)
             if target_params is not None:
@@ -382,7 +381,7 @@ class RuleRouter(Router):
 
     def get_target_delegate(
         self, target: Any, request: httputil.HTTPServerRequest, **target_params: Any
-    ) -> Optional[httputil.HTTPMessageDelegate]:
+    ) -> httputil.HTTPMessageDelegate | None:
         """Returns an instance of `~.httputil.HTTPMessageDelegate` for a
         Rule's target. This method is called by `~.find_handler` and can be
         extended to provide additional target types.
@@ -416,7 +415,7 @@ class ReversibleRuleRouter(ReversibleRouter, RuleRouter):
     in a rule's matcher (see `Matcher.reverse`).
     """
 
-    def __init__(self, rules: Optional[_RuleList] = None) -> None:
+    def __init__(self, rules: _RuleList | None = None) -> None:
         self.named_rules: dict[str, Any] = {}
         super().__init__(rules)
 
@@ -432,7 +431,7 @@ class ReversibleRuleRouter(ReversibleRouter, RuleRouter):
 
         return rule
 
-    def reverse_url(self, name: str, *args: Any) -> Optional[str]:
+    def reverse_url(self, name: str, *args: Any) -> str | None:
         if name in self.named_rules:
             return self.named_rules[name].matcher.reverse(*args)
 
@@ -452,8 +451,8 @@ class Rule:
         self,
         matcher: "Matcher",
         target: Any,
-        target_kwargs: Optional[dict[str, Any]] = None,
-        name: Optional[str] = None,
+        target_kwargs: dict[str, Any] | None = None,
+        name: str | None = None,
     ) -> None:
         """Constructs a Rule instance.
 
@@ -481,7 +480,7 @@ class Rule:
         self.target_kwargs = target_kwargs if target_kwargs else {}
         self.name = name
 
-    def reverse(self, *args: Any) -> Optional[str]:
+    def reverse(self, *args: Any) -> str | None:
         return self.matcher.reverse(*args)
 
     def __repr__(self) -> str:
@@ -497,7 +496,7 @@ class Rule:
 class Matcher:
     """Represents a matcher for request features."""
 
-    def match(self, request: httputil.HTTPServerRequest) -> Optional[dict[str, Any]]:
+    def match(self, request: httputil.HTTPServerRequest) -> dict[str, Any] | None:
         """Matches current instance against the request.
 
         :arg httputil.HTTPServerRequest request: current HTTP request
@@ -509,7 +508,7 @@ class Matcher:
             ``None`` must be returned to indicate that there is no match."""
         raise NotImplementedError()
 
-    def reverse(self, *args: Any) -> Optional[str]:
+    def reverse(self, *args: Any) -> str | None:
         """Reconstructs full url from matcher instance and additional arguments."""
         return None
 
@@ -517,14 +516,14 @@ class Matcher:
 class AnyMatches(Matcher):
     """Matches any request."""
 
-    def match(self, request: httputil.HTTPServerRequest) -> Optional[dict[str, Any]]:
+    def match(self, request: httputil.HTTPServerRequest) -> dict[str, Any] | None:
         return {}
 
 
 class HostMatches(Matcher):
     """Matches requests from hosts specified by ``host_pattern`` regex."""
 
-    def __init__(self, host_pattern: Union[str, Pattern]) -> None:
+    def __init__(self, host_pattern: str | Pattern) -> None:
         if isinstance(host_pattern, basestring_type):
             if not host_pattern.endswith("$"):
                 host_pattern += "$"
@@ -532,7 +531,7 @@ class HostMatches(Matcher):
         else:
             self.host_pattern = host_pattern
 
-    def match(self, request: httputil.HTTPServerRequest) -> Optional[dict[str, Any]]:
+    def match(self, request: httputil.HTTPServerRequest) -> dict[str, Any] | None:
         if self.host_pattern.match(request.host_name):
             return {}
 
@@ -548,7 +547,7 @@ class DefaultHostMatches(Matcher):
         self.application = application
         self.host_pattern = host_pattern
 
-    def match(self, request: httputil.HTTPServerRequest) -> Optional[dict[str, Any]]:
+    def match(self, request: httputil.HTTPServerRequest) -> dict[str, Any] | None:
         # Look for default host if not behind load balancer (for debugging)
         if "X-Real-Ip" not in request.headers:
             if self.host_pattern.match(self.application.default_host):
@@ -559,7 +558,7 @@ class DefaultHostMatches(Matcher):
 class PathMatches(Matcher):
     """Matches requests with paths specified by ``path_pattern`` regex."""
 
-    def __init__(self, path_pattern: Union[str, Pattern]) -> None:
+    def __init__(self, path_pattern: str | Pattern) -> None:
         if isinstance(path_pattern, basestring_type):
             if not path_pattern.endswith("$"):
                 path_pattern += "$"
@@ -574,7 +573,7 @@ class PathMatches(Matcher):
 
         self._path, self._group_count = self._find_groups()
 
-    def match(self, request: httputil.HTTPServerRequest) -> Optional[dict[str, Any]]:
+    def match(self, request: httputil.HTTPServerRequest) -> dict[str, Any] | None:
         match = self.regex.match(request.path)
         if match is None:
             return None
@@ -597,7 +596,7 @@ class PathMatches(Matcher):
 
         return dict(path_args=path_args, path_kwargs=path_kwargs)
 
-    def reverse(self, *args: Any) -> Optional[str]:
+    def reverse(self, *args: Any) -> str | None:
         if self._path is None:
             raise ValueError("Cannot reverse url regex " + self.regex.pattern)
         assert len(args) == self._group_count, (
@@ -612,7 +611,7 @@ class PathMatches(Matcher):
             converted_args.append(url_escape(utf8(a), plus=False))
         return self._path % tuple(converted_args)
 
-    def _find_groups(self) -> tuple[Optional[str], Optional[int]]:
+    def _find_groups(self) -> tuple[str | None, int | None]:
         """Returns a tuple (reverse string, group count) for a url.
 
         For example: Given the url pattern /([0-9]{4})/([a-z-]+)/, this method
@@ -663,10 +662,10 @@ class URLSpec(Rule):
 
     def __init__(
         self,
-        pattern: Union[str, Pattern],
+        pattern: str | Pattern,
         handler: Any,
-        kwargs: Optional[dict[str, Any]] = None,
-        name: Optional[str] = None,
+        kwargs: dict[str, Any] | None = None,
+        name: str | None = None,
     ) -> None:
         """Parameters:
 
@@ -712,7 +711,7 @@ def _unquote_or_none(s: None) -> None:
     pass
 
 
-def _unquote_or_none(s: Optional[str]) -> Optional[bytes]:  # noqa: F811
+def _unquote_or_none(s: str | None) -> bytes | None:  # noqa: F811
     """None-safe wrapper around url_unescape to handle unmatched optional
     groups correctly.
 
index 742678e64f3cfb8fb77cab9302368e72b39bd865..325a4a386521b1145580080b145208d7ad5d699d 100644 (file)
@@ -33,7 +33,7 @@ import time
 from io import BytesIO
 import urllib.parse
 
-from typing import Any, Callable, Optional, Type, Union
+from typing import Any, Callable, Optional, Type
 from collections.abc import Awaitable
 from types import TracebackType
 import typing
@@ -119,12 +119,12 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient):
     def initialize(  # type: ignore
         self,
         max_clients: int = 10,
-        hostname_mapping: Optional[dict[str, str]] = None,
+        hostname_mapping: dict[str, str] | None = None,
         max_buffer_size: int = 104857600,
-        resolver: Optional[Resolver] = None,
-        defaults: Optional[dict[str, Any]] = None,
-        max_header_size: Optional[int] = None,
-        max_body_size: Optional[int] = None,
+        resolver: Resolver | None = None,
+        defaults: dict[str, Any] | None = None,
+        max_header_size: int | None = None,
+        max_body_size: int | None = None,
     ) -> None:
         super().initialize(defaults=defaults)
         self.max_clients = max_clients
@@ -228,7 +228,7 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient):
                 self.io_loop.remove_timeout(timeout_handle)
             del self.waiting[key]
 
-    def _on_timeout(self, key: object, info: Optional[str] = None) -> None:
+    def _on_timeout(self, key: object, info: str | None = None) -> None:
         """Timeout callback of request.
 
         Construct a timeout HTTPResponse when a timeout occurs.
@@ -255,7 +255,7 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
 
     def __init__(
         self,
-        client: Optional[SimpleAsyncHTTPClient],
+        client: SimpleAsyncHTTPClient | None,
         request: HTTPRequest,
         release_callback: Callable[[], None],
         final_callback: Callable[[HTTPResponse], None],
@@ -275,8 +275,8 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
         self.tcp_client = tcp_client
         self.max_header_size = max_header_size
         self.max_body_size = max_body_size
-        self.code: Optional[int] = None
-        self.headers: Optional[httputil.HTTPHeaders] = None
+        self.code: int | None = None
+        self.headers: httputil.HTTPHeaders | None = None
         self.chunks: list[bytes] = []
         self._decompressor = None
         # Timeout handle returned by IOLoop.add_timeout
@@ -447,9 +447,7 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
             if not self._handle_exception(*sys.exc_info()):
                 raise
 
-    def _get_ssl_options(
-        self, scheme: str
-    ) -> Union[None, dict[str, Any], ssl.SSLContext]:
+    def _get_ssl_options(self, scheme: str) -> None | dict[str, Any] | ssl.SSLContext:
         if scheme == "https":
             if self.request.ssl_options is not None:
                 return self.request.ssl_options
@@ -478,7 +476,7 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
             return ssl_ctx
         return None
 
-    def _on_timeout(self, info: Optional[str] = None) -> None:
+    def _on_timeout(self, info: str | None = None) -> None:
         """Timeout callback of _HTTPConnection instance.
 
         Raise a `HTTPTimeoutError` when a timeout occurs.
@@ -543,8 +541,8 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
     def _handle_exception(
         self,
         typ: "Optional[Type[BaseException]]",
-        value: Optional[BaseException],
-        tb: Optional[TracebackType],
+        value: BaseException | None,
+        tb: TracebackType | None,
     ) -> bool:
         if self.final_callback is not None:
             self._remove_timeout()
@@ -588,7 +586,7 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
 
     async def headers_received(
         self,
-        first_line: Union[httputil.ResponseStartLine, httputil.RequestStartLine],
+        first_line: httputil.ResponseStartLine | httputil.RequestStartLine,
         headers: httputil.HTTPHeaders,
     ) -> None:
         assert isinstance(first_line, httputil.ResponseStartLine)
@@ -688,7 +686,7 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
     def _on_end_request(self) -> None:
         self.stream.close()
 
-    def data_received(self, chunk: bytes) -> Optional[Awaitable[None]]:
+    def data_received(self, chunk: bytes) -> Awaitable[None] | None:
         if self._should_follow_redirect():
             # We're going to follow a redirect so just discard the body.
             return None
index 132dd5e40351398fb5002d2be6d2917402fd6065..4a4bd4db602e2556e01f2620f0becc646f9b9cf2 100644 (file)
@@ -29,7 +29,7 @@ from tornado import gen
 from tornado.netutil import Resolver
 from tornado.gen import TimeoutError
 
-from typing import Any, Union, Tuple, Callable, Optional
+from typing import Any, Tuple, Callable
 from collections.abc import Iterator
 
 if typing.TYPE_CHECKING:
@@ -67,9 +67,9 @@ class _Connector:
         self.connect = connect
 
         self.future: Future[tuple[socket.AddressFamily, Any, IOStream]] = Future()
-        self.timeout: Optional[object] = None
-        self.connect_timeout: Optional[object] = None
-        self.last_error: Optional[Exception] = None
+        self.timeout: object | None = None
+        self.connect_timeout: object | None = None
+        self.last_error: Exception | None = None
         self.remaining = len(addrinfo)
         self.primary_addrs, self.secondary_addrs = self.split(addrinfo)
         self.streams: set[IOStream] = set()
@@ -102,7 +102,7 @@ class _Connector:
     def start(
         self,
         timeout: float = _INITIAL_CONNECT_TIMEOUT,
-        connect_timeout: Optional[Union[float, datetime.timedelta]] = None,
+        connect_timeout: float | datetime.timedelta | None = None,
     ) -> "Future[Tuple[socket.AddressFamily, Any, IOStream]]":
         self.try_connect(iter(self.primary_addrs))
         self.set_timeout(timeout)
@@ -174,9 +174,7 @@ class _Connector:
         if self.timeout is not None:
             self.io_loop.remove_timeout(self.timeout)
 
-    def set_connect_timeout(
-        self, connect_timeout: Union[float, datetime.timedelta]
-    ) -> None:
+    def set_connect_timeout(self, connect_timeout: float | datetime.timedelta) -> None:
         self.connect_timeout = self.io_loop.add_timeout(
             connect_timeout, self.on_connect_timeout
         )
@@ -204,7 +202,7 @@ class TCPClient:
        The ``io_loop`` argument (deprecated since version 4.1) has been removed.
     """
 
-    def __init__(self, resolver: Optional[Resolver] = None) -> None:
+    def __init__(self, resolver: Resolver | None = None) -> None:
         if resolver is not None:
             self.resolver = resolver
             self._own_resolver = False
@@ -221,11 +219,11 @@ class TCPClient:
         host: str,
         port: int,
         af: socket.AddressFamily = socket.AF_UNSPEC,
-        ssl_options: Optional[Union[dict[str, Any], ssl.SSLContext]] = None,
-        max_buffer_size: Optional[int] = None,
-        source_ip: Optional[str] = None,
-        source_port: Optional[int] = None,
-        timeout: Optional[Union[float, datetime.timedelta]] = None,
+        ssl_options: dict[str, Any] | ssl.SSLContext | None = None,
+        max_buffer_size: int | None = None,
+        source_ip: str | None = None,
+        source_port: int | None = None,
+        timeout: float | datetime.timedelta | None = None,
     ) -> IOStream:
         """Connect to the given host and port.
 
@@ -294,11 +292,11 @@ class TCPClient:
 
     def _create_stream(
         self,
-        max_buffer_size: Optional[int],
+        max_buffer_size: int | None,
         af: socket.AddressFamily,
         addr: tuple,
-        source_ip: Optional[str] = None,
-        source_port: Optional[int] = None,
+        source_ip: str | None = None,
+        source_port: int | None = None,
     ) -> tuple[IOStream, "Future[IOStream]"]:
         # Always connect in plaintext; we'll convert to ssl if necessary
         # after one connection has completed.
index a491a84884057254f1cb6c05ef4ede780e2d8412..5a9c48416656127a9afd39676f2c9ba4439bac38 100644 (file)
@@ -34,7 +34,7 @@ from tornado import process
 from tornado.util import errno_from_exception
 
 import typing
-from typing import Union, Any, Optional
+from typing import Any
 from collections.abc import Iterable, Awaitable
 
 if typing.TYPE_CHECKING:
@@ -124,9 +124,9 @@ class TCPServer:
 
     def __init__(
         self,
-        ssl_options: Optional[Union[dict[str, Any], ssl.SSLContext]] = None,
-        max_buffer_size: Optional[int] = None,
-        read_chunk_size: Optional[int] = None,
+        ssl_options: dict[str, Any] | ssl.SSLContext | None = None,
+        max_buffer_size: int | None = None,
+        read_chunk_size: int | None = None,
     ) -> None:
         self.ssl_options = ssl_options
         self._sockets: dict[int, socket.socket] = {}
@@ -160,10 +160,10 @@ class TCPServer:
     def listen(
         self,
         port: int,
-        address: Optional[str] = None,
+        address: str | None = None,
         family: socket.AddressFamily = socket.AF_UNSPEC,
         backlog: int = _DEFAULT_BACKLOG,
-        flags: Optional[int] = None,
+        flags: int | None = None,
         reuse_port: bool = False,
     ) -> None:
         """Starts accepting connections on the given port.
@@ -213,10 +213,10 @@ class TCPServer:
     def bind(
         self,
         port: int,
-        address: Optional[str] = None,
+        address: str | None = None,
         family: socket.AddressFamily = socket.AF_UNSPEC,
         backlog: int = _DEFAULT_BACKLOG,
-        flags: Optional[int] = None,
+        flags: int | None = None,
         reuse_port: bool = False,
     ) -> None:
         """Binds this server to the given port on the given address.
@@ -263,7 +263,7 @@ class TCPServer:
             self._pending_sockets.extend(sockets)
 
     def start(
-        self, num_processes: Optional[int] = 1, max_restarts: Optional[int] = None
+        self, num_processes: int | None = 1, max_restarts: int | None = None
     ) -> None:
         """Starts this server in the `.IOLoop`.
 
@@ -319,9 +319,7 @@ class TCPServer:
             self._handlers.pop(fd)()
             sock.close()
 
-    def handle_stream(
-        self, stream: IOStream, address: tuple
-    ) -> Optional[Awaitable[None]]:
+    def handle_stream(self, stream: IOStream, address: tuple) -> Awaitable[None] | None:
         """Override to handle a new `.IOStream` from an incoming connection.
 
         This method may be a coroutine; if so any exceptions it raises
index 03f33acc5458503a6b673b2073eebb8d672a0583..76eb4bb0194c7b4aa0e4c078b8151e3d0fdf1d5b 100644 (file)
@@ -208,7 +208,7 @@ from tornado import escape
 from tornado.log import app_log
 from tornado.util import ObjectDict, exec_in, unicode_type
 
-from typing import Any, Union, Callable, Optional, TextIO
+from typing import Any, Callable, Optional, TextIO
 from collections.abc import Iterable
 import typing
 
@@ -262,12 +262,12 @@ class Template:
     # this signature update website/sphinx/template.rst too.
     def __init__(
         self,
-        template_string: Union[str, bytes],
+        template_string: str | bytes,
         name: str = "<string>",
         loader: Optional["BaseLoader"] = None,
-        compress_whitespace: Union[bool, _UnsetMarker] = _UNSET,
-        autoescape: Optional[Union[str, _UnsetMarker]] = _UNSET,
-        whitespace: Optional[str] = None,
+        compress_whitespace: bool | _UnsetMarker = _UNSET,
+        autoescape: str | _UnsetMarker | None = _UNSET,
+        whitespace: str | None = None,
     ) -> None:
         """Construct a Template.
 
@@ -308,7 +308,7 @@ class Template:
         filter_whitespace(whitespace, "")
 
         if not isinstance(autoescape, _UnsetMarker):
-            self.autoescape: Optional[str] = autoescape
+            self.autoescape: str | None = autoescape
         elif loader:
             self.autoescape = loader.autoescape
         else:
@@ -400,9 +400,9 @@ class BaseLoader:
 
     def __init__(
         self,
-        autoescape: Optional[str] = _DEFAULT_AUTOESCAPE,
-        namespace: Optional[dict[str, Any]] = None,
-        whitespace: Optional[str] = None,
+        autoescape: str | None = _DEFAULT_AUTOESCAPE,
+        namespace: dict[str, Any] | None = None,
+        whitespace: str | None = None,
     ) -> None:
         """Construct a template loader.
 
@@ -435,11 +435,11 @@ class BaseLoader:
         with self.lock:
             self.templates = {}
 
-    def resolve_path(self, name: str, parent_path: Optional[str] = None) -> str:
+    def resolve_path(self, name: str, parent_path: str | None = None) -> str:
         """Converts a possibly-relative path to absolute (used internally)."""
         raise NotImplementedError()
 
-    def load(self, name: str, parent_path: Optional[str] = None) -> Template:
+    def load(self, name: str, parent_path: str | None = None) -> Template:
         """Loads a template."""
         name = self.resolve_path(name, parent_path=parent_path)
         with self.lock:
@@ -458,7 +458,7 @@ class Loader(BaseLoader):
         super().__init__(**kwargs)
         self.root = os.path.abspath(root_directory)
 
-    def resolve_path(self, name: str, parent_path: Optional[str] = None) -> str:
+    def resolve_path(self, name: str, parent_path: str | None = None) -> str:
         if (
             parent_path
             and not parent_path.startswith("<")
@@ -486,7 +486,7 @@ class DictLoader(BaseLoader):
         super().__init__(**kwargs)
         self.dict = dict
 
-    def resolve_path(self, name: str, parent_path: Optional[str] = None) -> str:
+    def resolve_path(self, name: str, parent_path: str | None = None) -> str:
         if (
             parent_path
             and not parent_path.startswith("<")
@@ -509,7 +509,7 @@ class _Node:
         raise NotImplementedError()
 
     def find_named_blocks(
-        self, loader: Optional[BaseLoader], named_blocks: dict[str, "_NamedBlock"]
+        self, loader: BaseLoader | None, named_blocks: dict[str, "_NamedBlock"]
     ) -> None:
         for child in self.each_child():
             child.find_named_blocks(loader, named_blocks)
@@ -561,7 +561,7 @@ class _NamedBlock(_Node):
             block.body.generate(writer)
 
     def find_named_blocks(
-        self, loader: Optional[BaseLoader], named_blocks: dict[str, "_NamedBlock"]
+        self, loader: BaseLoader | None, named_blocks: dict[str, "_NamedBlock"]
     ) -> None:
         named_blocks[self.name] = self
         _Node.find_named_blocks(self, loader, named_blocks)
@@ -579,7 +579,7 @@ class _IncludeBlock(_Node):
         self.line = line
 
     def find_named_blocks(
-        self, loader: Optional[BaseLoader], named_blocks: dict[str, _NamedBlock]
+        self, loader: BaseLoader | None, named_blocks: dict[str, _NamedBlock]
     ) -> None:
         assert loader is not None
         included = loader.load(self.name, self.template_name)
@@ -709,7 +709,7 @@ class ParseError(Exception):
     """
 
     def __init__(
-        self, message: str, filename: Optional[str] = None, lineno: int = 0
+        self, message: str, filename: str | None = None, lineno: int = 0
     ) -> None:
         self.message = message
         # The names "filename" and "lineno" are chosen for consistency
@@ -726,7 +726,7 @@ class _CodeWriter:
         self,
         file: TextIO,
         named_blocks: dict[str, _NamedBlock],
-        loader: Optional[BaseLoader],
+        loader: BaseLoader | None,
         current_template: Template,
     ) -> None:
         self.file = file
@@ -766,7 +766,7 @@ class _CodeWriter:
         return IncludeTemplate()
 
     def write_line(
-        self, line: str, line_number: int, indent: Optional[int] = None
+        self, line: str, line_number: int, indent: int | None = None
     ) -> None:
         if indent is None:
             indent = self._indent
@@ -787,7 +787,7 @@ class _TemplateReader:
         self.line = 1
         self.pos = 0
 
-    def find(self, needle: str, start: int = 0, end: Optional[int] = None) -> int:
+    def find(self, needle: str, start: int = 0, end: int | None = None) -> int:
         assert start >= 0, start
         pos = self.pos
         start += pos
@@ -801,7 +801,7 @@ class _TemplateReader:
             index -= pos
         return index
 
-    def consume(self, count: Optional[int] = None) -> str:
+    def consume(self, count: int | None = None) -> str:
         if count is None:
             count = len(self.text) - self.pos
         newpos = self.pos + count
@@ -816,7 +816,7 @@ class _TemplateReader:
     def __len__(self) -> int:
         return self.remaining()
 
-    def __getitem__(self, key: Union[int, slice]) -> str:
+    def __getitem__(self, key: int | slice) -> str:
         if isinstance(key, slice):
             size = len(self)
             start, stop, step = key.indices(size)
@@ -848,8 +848,8 @@ def _format_code(code: str) -> str:
 def _parse(
     reader: _TemplateReader,
     template: Template,
-    in_block: Optional[str] = None,
-    in_loop: Optional[str] = None,
+    in_block: str | None = None,
+    in_loop: str | None = None,
 ) -> _ChunkList:
     body = _ChunkList([])
     while True:
@@ -992,7 +992,7 @@ def _parse(
                     reader.raise_parse_error("set missing statement")
                 block = _Statement(suffix, line)
             elif operator == "autoescape":
-                fn: Optional[str] = suffix.strip()
+                fn: str | None = suffix.strip()
                 if fn == "None":
                     fn = None
                 template.autoescape = fn
index 4e2811a620dd792b47a38d949fa415f6c11776dc..6df6ad0e8738bfa2c86cb795fba33a738d1db134 100644 (file)
@@ -14,7 +14,6 @@ import io
 import sys
 import traceback
 import types
-import typing
 import unittest
 
 import tornado
@@ -108,9 +107,9 @@ class CircleRefsTest(unittest.TestCase):
         class C:
             def __init__(self, name):
                 self.name = name
-                self.a: typing.Optional[C] = None
-                self.b: typing.Optional[C] = None
-                self.c: typing.Optional[C] = None
+                self.a: C | None = None
+                self.b: C | None = None
+                self.c: C | None = None
 
             def __repr__(self):
                 return f"name={self.name}"
index 572add41a799977aea74df7e82c83c557ce0ab74..7331e64fe9b2b594635a9eff1da964e9b18a1721 100644 (file)
@@ -17,7 +17,7 @@ from tornado.util import unicode_type
 
 from typing import List, Tuple, Union, Dict, Any  # noqa: F401
 
-linkify_tests: list[tuple[Union[str, bytes], dict[str, Any], str]] = [
+linkify_tests: list[tuple[str | bytes, dict[str, Any], str]] = [
     # (input, linkify_kwargs, expected_output)
     (
         "hello http://world.com/!",
@@ -218,7 +218,7 @@ class EscapeTestCase(unittest.TestCase):
             self.assertEqual(linked, html)
 
     def test_xhtml_escape(self):
-        tests: list[tuple[Union[str, bytes], Union[str, bytes]]] = [
+        tests: list[tuple[str | bytes, str | bytes]] = [
             ("<foo>", "&lt;foo&gt;"),
             ("<foo>", "&lt;foo&gt;"),
             (b"<foo>", b"&lt;foo&gt;"),
@@ -245,7 +245,7 @@ class EscapeTestCase(unittest.TestCase):
             self.assertEqual(unescaped, xhtml_unescape(escaped))
 
     def test_url_escape_unicode(self):
-        tests: list[tuple[Union[str, bytes], str]] = [
+        tests: list[tuple[str | bytes, str]] = [
             # byte strings are passed through as-is
             ("\u00e9".encode(), "%C3%A9"),
             ("\u00e9".encode("latin1"), "%E9"),
index b3906a67b4250734c3ced2ba7d7b3e75e80d64f3..514dcd0de73ed377d43650e490d582ade5312e34 100644 (file)
@@ -948,7 +948,7 @@ class RunnerGCTest(AsyncTestCase):
     def test_gc(self):
         # GitHub issue 1769: Runner objects can get GCed unexpectedly
         # while their future is alive.
-        weakref_scope: list[Optional[weakref.ReferenceType]] = [None]
+        weakref_scope: list[weakref.ReferenceType | None] = [None]
 
         def callback():
             gc.collect(2)
@@ -968,7 +968,7 @@ class RunnerGCTest(AsyncTestCase):
         # their loop is closed, even if they're involved in a reference
         # cycle.
         loop = self.get_new_ioloop()
-        result: list[Optional[bool]] = []
+        result: list[bool | None] = []
         wfut = []
 
         @gen.coroutine
@@ -1013,7 +1013,7 @@ class RunnerGCTest(AsyncTestCase):
                 result.append(None)
 
         loop = self.get_new_ioloop()
-        result: list[Optional[bool]] = []
+        result: list[bool | None] = []
         wfut = []
 
         @gen.coroutine
index 49e7683800e8b3d7293883b691145610c8ba079e..d7acfb589b6f375165b9b833efb1b5fe4a2bbf58 100644 (file)
@@ -10,7 +10,7 @@ from tornado.testing import AsyncTestCase, bind_unused_port, gen_test
 
 
 class HTTP1ConnectionTest(AsyncTestCase):
-    code: typing.Optional[int] = None
+    code: int | None = None
 
     def setUp(self):
         super().setUp()
index 6555519fb07280874720efab1ddcddbf665c62bf..98c432aba219bfadd8546ed79a59b36a3fc46e13 100644 (file)
@@ -447,7 +447,7 @@ class TestIOLoop(AsyncTestCase):
 class TestIOLoopCurrent(unittest.TestCase):
     def setUp(self):
         setup_with_context_manager(self, ignore_deprecation())
-        self.io_loop: typing.Optional[IOLoop] = None
+        self.io_loop: IOLoop | None = None
         IOLoop.clear_current()
 
     def tearDown(self):
index dcbc4995ee2d8c9c69948d7b8d75f58b0a649185..cc0e1cbbb23b7314f908bfecaa04db1f5576b9d2 100644 (file)
@@ -987,7 +987,7 @@ class TestIOStreamStartTLS(AsyncTestCase):
             self.server_stream = None
             self.server_accepted: Future[None] = Future()
             netutil.add_accept_handler(self.listener, self.accept)
-            self.client_stream: typing.Optional[IOStream] = IOStream(socket.socket())
+            self.client_stream: IOStream | None = IOStream(socket.socket())
             self.io_loop.add_future(
                 self.client_stream.connect(("127.0.0.1", self.port)), self.stop
             )
index 8dc6f8ebabbc3e133bc1f988e18a2271b3bd3d60..b1f2a8e8e79437c81e6abef11f63a5348a89a22a 100644 (file)
@@ -23,7 +23,7 @@ from tornado.testing import gen_test, AsyncTestCase
 class ConditionTest(AsyncTestCase):
     def setUp(self):
         super().setUp()
-        self.history: list[typing.Union[int, str]] = []
+        self.history: list[int | str] = []
 
     def record_done(self, future, key):
         """Record the resolution of a Future returned by Condition.wait."""
index 3076cf9dd8f4bf72bf35fc749709520c37d5bcc6..d58d2088f75874d360edc4456fb6679311d8ad9e 100644 (file)
@@ -208,7 +208,7 @@ three{%end%}
             self.assertTrue("# test.html:2" in traceback.format_exc())
 
     def test_error_line_number_module(self):
-        loader: typing.Optional[DictLoader] = None
+        loader: DictLoader | None = None
 
         def load_generate(path, **kwargs):
             assert loader is not None
index 7936116a4e2a3cb3d36624c94a55ebacc7263689..0421cfe1140b931ec0d795bf46ff1faeac3f665b 100644 (file)
@@ -113,7 +113,7 @@ class CookieTestRequestHandler(RequestHandler):
                 settings=dict(cookie_secret=cookie_secret, key_version=key_version)
             )
 
-    def get_cookie(self, name) -> typing.Optional[str]:  # type: ignore[override]
+    def get_cookie(self, name) -> str | None:  # type: ignore[override]
         return to_unicode(self._cookies.get(name))
 
     def set_cookie(self, name, value, expires_days=None):  # type: ignore[override]
index f4c7406fee2cf1b92be9201befdb1fa6cf8c7476..83aa02379b5fca6c3e53e153102da831a2280e03 100644 (file)
@@ -137,12 +137,12 @@ class AsyncTestCase(unittest.TestCase):
         super().__init__(methodName)
         self.__stopped = False
         self.__running = False
-        self.__failure: Optional[_ExcInfoTuple] = None
+        self.__failure: _ExcInfoTuple | None = None
         self.__stop_args: Any = None
-        self.__timeout: Optional[object] = None
+        self.__timeout: object | None = None
 
         # Not used in this class itself, but used by @gen_test
-        self._test_generator: Optional[Union[Generator, Coroutine]] = None
+        self._test_generator: Generator | Coroutine | None = None
 
     def setUp(self) -> None:
         py_ver = sys.version_info
@@ -241,8 +241,8 @@ class AsyncTestCase(unittest.TestCase):
             raise_exc_info(failure)
 
     def run(
-        self, result: Optional[unittest.TestResult] = None
-    ) -> Optional[unittest.TestResult]:
+        self, result: unittest.TestResult | None = None
+    ) -> unittest.TestResult | None:
         ret = super().run(result)
         # As a last resort, if an exception escaped super.run() and wasn't
         # re-raised in tearDown, raise it here.  This will cause the
@@ -295,8 +295,8 @@ class AsyncTestCase(unittest.TestCase):
 
     def wait(
         self,
-        condition: Optional[Callable[..., bool]] = None,
-        timeout: Optional[float] = None,
+        condition: Callable[..., bool] | None = None,
+        timeout: float | None = None,
     ) -> Any:
         """Runs the `.IOLoop` until stop is called or timeout has passed.
 
@@ -518,7 +518,7 @@ class AsyncHTTPSTestCase(AsyncHTTPTestCase):
 
 @typing.overload
 def gen_test(
-    *, timeout: Optional[float] = None
+    *, timeout: float | None = None
 ) -> Callable[[Callable[..., Union[Generator, "Coroutine"]]], Callable[..., None]]:
     pass
 
@@ -529,12 +529,12 @@ def gen_test(func: Callable[..., Union[Generator, "Coroutine"]]) -> Callable[...
 
 
 def gen_test(  # noqa: F811
-    func: Optional[Callable[..., Union[Generator, "Coroutine"]]] = None,
-    timeout: Optional[float] = None,
-) -> Union[
-    Callable[..., None],
-    Callable[[Callable[..., Union[Generator, "Coroutine"]]], Callable[..., None]],
-]:
+    func: Callable[..., Union[Generator, "Coroutine"]] | None = None,
+    timeout: float | None = None,
+) -> (
+    Callable[..., None]
+    | Callable[[Callable[..., Union[Generator, "Coroutine"]]], Callable[..., None]]
+):
     """Testing equivalent of ``@gen.coroutine``, to be applied to test methods.
 
     ``@gen.coroutine`` cannot be used on tests because the `.IOLoop` is not
@@ -585,7 +585,7 @@ def gen_test(  # noqa: F811
         @functools.wraps(f)
         def pre_coroutine(
             self: AsyncTestCase, *args: Any, **kwargs: Any
-        ) -> Union[Generator, Coroutine]:
+        ) -> Generator | Coroutine:
             # Type comments used to avoid pypy3 bug.
             result = f(self, *args, **kwargs)
             if isinstance(result, Generator) or inspect.iscoroutine(result):
@@ -660,10 +660,10 @@ class ExpectLog(logging.Filter):
 
     def __init__(
         self,
-        logger: Union[logging.Logger, basestring_type],
+        logger: logging.Logger | basestring_type,
         regex: str,
         required: bool = True,
-        level: Optional[int] = None,
+        level: int | None = None,
     ) -> None:
         """Constructs an ExpectLog context manager.
 
@@ -700,7 +700,7 @@ class ExpectLog(logging.Filter):
         self.deprecated_level_matched = 0
         self.logged_stack = False
         self.level = level
-        self.orig_level: Optional[int] = None
+        self.orig_level: int | None = None
 
     def filter(self, record: logging.LogRecord) -> bool:
         if record.exc_info:
@@ -734,8 +734,8 @@ class ExpectLog(logging.Filter):
     def __exit__(
         self,
         typ: "Optional[Type[BaseException]]",
-        value: Optional[BaseException],
-        tb: Optional[TracebackType],
+        value: BaseException | None,
+        tb: TracebackType | None,
     ) -> None:
         if self.orig_level is not None:
             self.logger.setLevel(self.orig_level)
index aa48c1f3153d1bc01374c3c7703e9ac9da694843..131775288a00bcb962e71246c9d581ceef843819 100644 (file)
@@ -267,15 +267,15 @@ class RequestHandler:
     def _unimplemented_method(self, *args: str, **kwargs: str) -> None:
         raise HTTPError(405)
 
-    head: Callable[..., Optional[Awaitable[None]]] = _unimplemented_method
-    get: Callable[..., Optional[Awaitable[None]]] = _unimplemented_method
-    post: Callable[..., Optional[Awaitable[None]]] = _unimplemented_method
-    delete: Callable[..., Optional[Awaitable[None]]] = _unimplemented_method
-    patch: Callable[..., Optional[Awaitable[None]]] = _unimplemented_method
-    put: Callable[..., Optional[Awaitable[None]]] = _unimplemented_method
-    options: Callable[..., Optional[Awaitable[None]]] = _unimplemented_method
-
-    def prepare(self) -> Optional[Awaitable[None]]:
+    head: Callable[..., Awaitable[None] | None] = _unimplemented_method
+    get: Callable[..., Awaitable[None] | None] = _unimplemented_method
+    post: Callable[..., Awaitable[None] | None] = _unimplemented_method
+    delete: Callable[..., Awaitable[None] | None] = _unimplemented_method
+    patch: Callable[..., Awaitable[None] | None] = _unimplemented_method
+    put: Callable[..., Awaitable[None] | None] = _unimplemented_method
+    options: Callable[..., Awaitable[None] | None] = _unimplemented_method
+
+    def prepare(self) -> Awaitable[None] | None:
         """Called at the beginning of a request before  `get`/`post`/etc.
 
         Override this method to perform common initialization regardless
@@ -349,7 +349,7 @@ class RequestHandler:
         """
         pass
 
-    def set_status(self, status_code: int, reason: Optional[str] = None) -> None:
+    def set_status(self, status_code: int, reason: str | None = None) -> None:
         """Sets the status code for our response.
 
         :arg int status_code: Response status code.
@@ -449,15 +449,15 @@ class RequestHandler:
     @overload
     def get_argument(  # noqa: F811
         self, name: str, default: None, strip: bool = True
-    ) -> Optional[str]:
+    ) -> str | None:
         pass
 
     def get_argument(  # noqa: F811
         self,
         name: str,
-        default: Union[None, str, _ArgDefaultMarker] = _ARG_DEFAULT,
+        default: None | str | _ArgDefaultMarker = _ARG_DEFAULT,
         strip: bool = True,
-    ) -> Optional[str]:
+    ) -> str | None:
         """Returns the value of the argument with the given name.
 
         If default is not provided, the argument is considered to be
@@ -498,15 +498,15 @@ class RequestHandler:
     @overload
     def get_body_argument(  # noqa: F811
         self, name: str, default: None, strip: bool = True
-    ) -> Optional[str]:
+    ) -> str | None:
         pass
 
     def get_body_argument(  # noqa: F811
         self,
         name: str,
-        default: Union[None, str, _ArgDefaultMarker] = _ARG_DEFAULT,
+        default: None | str | _ArgDefaultMarker = _ARG_DEFAULT,
         strip: bool = True,
-    ) -> Optional[str]:
+    ) -> str | None:
         """Returns the value of the argument with the given name
         from the request body.
 
@@ -542,15 +542,15 @@ class RequestHandler:
     @overload
     def get_query_argument(  # noqa: F811
         self, name: str, default: None, strip: bool = True
-    ) -> Optional[str]:
+    ) -> str | None:
         pass
 
     def get_query_argument(  # noqa: F811
         self,
         name: str,
-        default: Union[None, str, _ArgDefaultMarker] = _ARG_DEFAULT,
+        default: None | str | _ArgDefaultMarker = _ARG_DEFAULT,
         strip: bool = True,
-    ) -> Optional[str]:
+    ) -> str | None:
         """Returns the value of the argument with the given name
         from the request query string.
 
@@ -576,10 +576,10 @@ class RequestHandler:
     def _get_argument(
         self,
         name: str,
-        default: Union[None, str, _ArgDefaultMarker],
+        default: None | str | _ArgDefaultMarker,
         source: dict[str, list[bytes]],
         strip: bool = True,
-    ) -> Optional[str]:
+    ) -> str | None:
         args = self._get_arguments(name, source, strip=strip)
         if not args:
             if isinstance(default, _ArgDefaultMarker):
@@ -602,7 +602,7 @@ class RequestHandler:
             values.append(s)
         return values
 
-    def decode_argument(self, value: bytes, name: Optional[str] = None) -> str:
+    def decode_argument(self, value: bytes, name: str | None = None) -> str:
         """Decodes an argument from the request.
 
         The argument has been percent-decoded and is now a byte string.
@@ -633,10 +633,10 @@ class RequestHandler:
         pass
 
     @overload
-    def get_cookie(self, name: str, default: None = None) -> Optional[str]:
+    def get_cookie(self, name: str, default: None = None) -> str | None:
         pass
 
-    def get_cookie(self, name: str, default: Optional[str] = None) -> Optional[str]:
+    def get_cookie(self, name: str, default: str | None = None) -> str | None:
         """Returns the value of the request cookie with the given name.
 
         If the named cookie is not present, returns ``default``.
@@ -652,17 +652,17 @@ class RequestHandler:
     def set_cookie(
         self,
         name: str,
-        value: Union[str, bytes],
-        domain: Optional[str] = None,
-        expires: Optional[Union[float, tuple, datetime.datetime]] = None,
+        value: str | bytes,
+        domain: str | None = None,
+        expires: float | tuple | datetime.datetime | None = None,
         path: str = "/",
-        expires_days: Optional[float] = None,
+        expires_days: float | None = None,
         # Keyword-only args start here for historical reasons.
         *,
-        max_age: Optional[int] = None,
+        max_age: int | None = None,
         httponly: bool = False,
         secure: bool = False,
-        samesite: Optional[str] = None,
+        samesite: str | None = None,
         **kwargs: Any,
     ) -> None:
         """Sets an outgoing cookie name/value with the given options.
@@ -814,9 +814,9 @@ class RequestHandler:
     def set_signed_cookie(
         self,
         name: str,
-        value: Union[str, bytes],
-        expires_days: Optional[float] = 30,
-        version: Optional[int] = None,
+        value: str | bytes,
+        expires_days: float | None = 30,
+        version: int | None = None,
         **kwargs: Any,
     ) -> None:
         """Signs and timestamps a cookie so it cannot be forged.
@@ -859,7 +859,7 @@ class RequestHandler:
     set_secure_cookie = set_signed_cookie
 
     def create_signed_value(
-        self, name: str, value: Union[str, bytes], version: Optional[int] = None
+        self, name: str, value: str | bytes, version: int | None = None
     ) -> bytes:
         """Signs and timestamps a string so it cannot be forged.
 
@@ -887,10 +887,10 @@ class RequestHandler:
     def get_signed_cookie(
         self,
         name: str,
-        value: Optional[str] = None,
+        value: str | None = None,
         max_age_days: float = 31,
-        min_version: Optional[int] = None,
-    ) -> Optional[bytes]:
+        min_version: int | None = None,
+    ) -> bytes | None:
         """Returns the given signed cookie if it validates, or None.
 
         The decoded cookie value is returned as a byte string (unlike
@@ -926,8 +926,8 @@ class RequestHandler:
     get_secure_cookie = get_signed_cookie
 
     def get_signed_cookie_key_version(
-        self, name: str, value: Optional[str] = None
-    ) -> Optional[int]:
+        self, name: str, value: str | None = None
+    ) -> int | None:
         """Returns the signing key version of the secure cookie.
 
         The version is returned as int.
@@ -950,7 +950,7 @@ class RequestHandler:
     get_secure_cookie_key_version = get_signed_cookie_key_version
 
     def redirect(
-        self, url: str, permanent: bool = False, status: Optional[int] = None
+        self, url: str, permanent: bool = False, status: int | None = None
     ) -> None:
         """Sends a redirect to the given (optionally relative) URL.
 
@@ -969,7 +969,7 @@ class RequestHandler:
         self.set_header("Location", utf8(url))
         self.finish()
 
-    def write(self, chunk: Union[str, bytes, dict]) -> None:
+    def write(self, chunk: str | bytes | dict) -> None:
         """Writes the given chunk to the output buffer.
 
         To write the output to the network, use the `flush()` method below.
@@ -1261,7 +1261,7 @@ class RequestHandler:
                 future.set_result(None)
                 return future
 
-    def finish(self, chunk: Optional[Union[str, bytes, dict]] = None) -> "Future[None]":
+    def finish(self, chunk: str | bytes | dict | None = None) -> "Future[None]":
         """Finishes this response, ending the HTTP request.
 
         Passing a ``chunk`` to ``finish()`` is equivalent to passing that
@@ -1427,7 +1427,7 @@ class RequestHandler:
     def locale(self, value: tornado.locale.Locale) -> None:
         self._locale = value
 
-    def get_user_locale(self) -> Optional[tornado.locale.Locale]:
+    def get_user_locale(self) -> tornado.locale.Locale | None:
         """Override to determine the locale from the authenticated user.
 
         If None is returned, we fall back to `get_browser_locale()`.
@@ -1519,7 +1519,7 @@ class RequestHandler:
         self.require_setting("login_url", "@tornado.web.authenticated")
         return self.application.settings["login_url"]
 
-    def get_template_path(self) -> Optional[str]:
+    def get_template_path(self) -> str | None:
         """Override to customize template path for each handler.
 
         By default, we use the ``template_path`` application setting.
@@ -1585,7 +1585,7 @@ class RequestHandler:
                 self.set_cookie(cookie_name, self._xsrf_token, **cookie_kwargs)
         return self._xsrf_token
 
-    def _get_raw_xsrf_token(self) -> tuple[Optional[int], bytes, float]:
+    def _get_raw_xsrf_token(self) -> tuple[int | None, bytes, float]:
         """Read or generate the xsrf token in its raw form.
 
         The raw_xsrf_token is a tuple containing:
@@ -1614,7 +1614,7 @@ class RequestHandler:
 
     def _decode_xsrf_token(
         self, cookie: str
-    ) -> tuple[Optional[int], Optional[bytes], Optional[float]]:
+    ) -> tuple[int | None, bytes | None, float | None]:
         """Convert a cookie string into a the tuple form returned by
         _get_raw_xsrf_token.
         """
@@ -1706,7 +1706,7 @@ class RequestHandler:
         )
 
     def static_url(
-        self, path: str, include_host: Optional[bool] = None, **kwargs: Any
+        self, path: str, include_host: bool | None = None, **kwargs: Any
     ) -> str:
         """Returns a static URL for the given relative static file path.
 
@@ -1755,7 +1755,7 @@ class RequestHandler:
         """Alias for `Application.reverse_url`."""
         return self.application.reverse_url(name, *args)
 
-    def compute_etag(self) -> Optional[str]:
+    def compute_etag(self) -> str | None:
         """Computes the etag header to be used for this request.
 
         By default uses a hash of the content written so far.
@@ -1888,7 +1888,7 @@ class RequestHandler:
                 # in a finally block to avoid GC issues prior to Python 3.4.
                 self._prepared_future.set_result(None)
 
-    def data_received(self, chunk: bytes) -> Optional[Awaitable[None]]:
+    def data_received(self, chunk: bytes) -> Awaitable[None] | None:
         """Implement this method to handle streamed request data.
 
         Requires the `.stream_request_body` decorator.
@@ -1938,8 +1938,8 @@ class RequestHandler:
     def log_exception(
         self,
         typ: "Optional[Type[BaseException]]",
-        value: Optional[BaseException],
-        tb: Optional[TracebackType],
+        value: BaseException | None,
+        tb: TracebackType | None,
     ) -> None:
         """Override to customize logging of uncaught exceptions.
 
@@ -2026,8 +2026,8 @@ def _has_stream_request_body(cls: type[RequestHandler]) -> bool:
 
 
 def removeslash(
-    method: Callable[..., Optional[Awaitable[None]]],
-) -> Callable[..., Optional[Awaitable[None]]]:
+    method: Callable[..., Awaitable[None] | None],
+) -> Callable[..., Awaitable[None] | None]:
     """Use this decorator to remove trailing slashes from the request path.
 
     For example, a request to ``/foo/`` would redirect to ``/foo`` with this
@@ -2038,7 +2038,7 @@ def removeslash(
     @functools.wraps(method)
     def wrapper(  # type: ignore
         self: RequestHandler, *args, **kwargs
-    ) -> Optional[Awaitable[None]]:
+    ) -> Awaitable[None] | None:
         if self.request.path.endswith("/"):
             if self.request.method in ("GET", "HEAD"):
                 uri = self.request.path.rstrip("/")
@@ -2055,8 +2055,8 @@ def removeslash(
 
 
 def addslash(
-    method: Callable[..., Optional[Awaitable[None]]],
-) -> Callable[..., Optional[Awaitable[None]]]:
+    method: Callable[..., Awaitable[None] | None],
+) -> Callable[..., Awaitable[None] | None]:
     """Use this decorator to add a missing trailing slash to the request path.
 
     For example, a request to ``/foo`` would redirect to ``/foo/`` with this
@@ -2067,7 +2067,7 @@ def addslash(
     @functools.wraps(method)
     def wrapper(  # type: ignore
         self: RequestHandler, *args, **kwargs
-    ) -> Optional[Awaitable[None]]:
+    ) -> Awaitable[None] | None:
         if not self.request.path.endswith("/"):
             if self.request.method in ("GET", "HEAD"):
                 uri = self.request.path + "/"
@@ -2093,7 +2093,7 @@ class _ApplicationRouter(ReversibleRuleRouter):
     """
 
     def __init__(
-        self, application: "Application", rules: Optional[_RuleList] = None
+        self, application: "Application", rules: _RuleList | None = None
     ) -> None:
         assert isinstance(application, Application)
         self.application = application
@@ -2111,7 +2111,7 @@ class _ApplicationRouter(ReversibleRuleRouter):
 
     def get_target_delegate(
         self, target: Any, request: httputil.HTTPServerRequest, **target_params: Any
-    ) -> Optional[httputil.HTTPMessageDelegate]:
+    ) -> httputil.HTTPMessageDelegate | None:
         if isclass(target) and issubclass(target, RequestHandler):
             return self.application.get_handler_delegate(
                 request, target, **target_params
@@ -2205,9 +2205,9 @@ class Application(ReversibleRouter):
 
     def __init__(
         self,
-        handlers: Optional[_RuleList] = None,
-        default_host: Optional[str] = None,
-        transforms: Optional[list[type["OutputTransform"]]] = None,
+        handlers: _RuleList | None = None,
+        default_host: str | None = None,
+        transforms: list[type["OutputTransform"]] | None = None,
         **settings: Any,
     ) -> None:
         if transforms is None:
@@ -2262,11 +2262,11 @@ class Application(ReversibleRouter):
     def listen(
         self,
         port: int,
-        address: Optional[str] = None,
+        address: str | None = None,
         *,
         family: socket.AddressFamily = socket.AF_UNSPEC,
         backlog: int = tornado.netutil._DEFAULT_BACKLOG,
-        flags: Optional[int] = None,
+        flags: int | None = None,
         reuse_port: bool = False,
         **kwargs: Any,
     ) -> HTTPServer:
@@ -2352,9 +2352,7 @@ class Application(ReversibleRouter):
                 except TypeError:
                     pass
 
-    def __call__(
-        self, request: httputil.HTTPServerRequest
-    ) -> Optional[Awaitable[None]]:
+    def __call__(self, request: httputil.HTTPServerRequest) -> Awaitable[None] | None:
         # Legacy HTTPServer interface
         dispatcher = self.find_handler(request)
         return dispatcher.execute()
@@ -2379,9 +2377,9 @@ class Application(ReversibleRouter):
         self,
         request: httputil.HTTPServerRequest,
         target_class: type[RequestHandler],
-        target_kwargs: Optional[dict[str, Any]] = None,
-        path_args: Optional[list[bytes]] = None,
-        path_kwargs: Optional[dict[str, bytes]] = None,
+        target_kwargs: dict[str, Any] | None = None,
+        path_args: list[bytes] | None = None,
+        path_kwargs: dict[str, bytes] | None = None,
     ) -> "_HandlerDelegate":
         """Returns `~.httputil.HTTPMessageDelegate` that can serve a request
         for application and `RequestHandler` subclass.
@@ -2444,9 +2442,9 @@ class _HandlerDelegate(httputil.HTTPMessageDelegate):
         application: Application,
         request: httputil.HTTPServerRequest,
         handler_class: type[RequestHandler],
-        handler_kwargs: Optional[dict[str, Any]],
-        path_args: Optional[list[bytes]],
-        path_kwargs: Optional[dict[str, bytes]],
+        handler_kwargs: dict[str, Any] | None,
+        path_args: list[bytes] | None,
+        path_kwargs: dict[str, bytes] | None,
     ) -> None:
         self.application = application
         self.connection = request.connection
@@ -2460,15 +2458,15 @@ class _HandlerDelegate(httputil.HTTPMessageDelegate):
 
     def headers_received(
         self,
-        start_line: Union[httputil.RequestStartLine, httputil.ResponseStartLine],
+        start_line: httputil.RequestStartLine | httputil.ResponseStartLine,
         headers: httputil.HTTPHeaders,
-    ) -> Optional[Awaitable[None]]:
+    ) -> Awaitable[None] | None:
         if self.stream_request_body:
             self.request._body_future = Future()
             return self.execute()
         return None
 
-    def data_received(self, data: bytes) -> Optional[Awaitable[None]]:
+    def data_received(self, data: bytes) -> Awaitable[None] | None:
         if self.stream_request_body:
             return self.handler.data_received(data)
         else:
@@ -2490,7 +2488,7 @@ class _HandlerDelegate(httputil.HTTPMessageDelegate):
         else:
             self.chunks = None  # type: ignore
 
-    def execute(self) -> Optional[Awaitable[None]]:
+    def execute(self) -> Awaitable[None] | None:
         # If template cache is disabled (usually in the debug mode),
         # re-compile templates and reload static files on every
         # request so you don't need to restart to see changes
@@ -2556,7 +2554,7 @@ class HTTPError(Exception):
     def __init__(
         self,
         status_code: int = 500,
-        log_message: Optional[str] = None,
+        log_message: str | None = None,
         *args: Any,
         **kwargs: Any,
     ) -> None:
@@ -2566,7 +2564,7 @@ class HTTPError(Exception):
         self.reason = kwargs.get("reason", None)
 
     @property
-    def log_message(self) -> Optional[str]:
+    def log_message(self) -> str | None:
         """
         A backwards compatible way of accessing log_message.
         """
@@ -2574,7 +2572,7 @@ class HTTPError(Exception):
             return self._log_message.replace("%", "%%")
         return self._log_message
 
-    def get_message(self) -> Optional[str]:
+    def get_message(self) -> str | None:
         if self._log_message and self.args:
             return self._log_message % self.args
         return self._log_message
@@ -2766,10 +2764,10 @@ class StaticFileHandler(RequestHandler):
 
     CACHE_MAX_AGE = 86400 * 365 * 10  # 10 years
 
-    _static_hashes: dict[str, Optional[str]] = {}
+    _static_hashes: dict[str, str | None] = {}
     _lock = threading.Lock()  # protects _static_hashes
 
-    def initialize(self, path: str, default_filename: Optional[str] = None) -> None:
+    def initialize(self, path: str, default_filename: str | None = None) -> None:
         self.root = path
         self.default_filename = default_filename
 
@@ -2864,7 +2862,7 @@ class StaticFileHandler(RequestHandler):
         else:
             assert self.request.method == "HEAD"
 
-    def compute_etag(self) -> Optional[str]:
+    def compute_etag(self) -> str | None:
         """Sets the ``Etag`` header based on static url version.
 
         This allows efficient ``If-None-Match`` checks against cached
@@ -2947,7 +2945,7 @@ class StaticFileHandler(RequestHandler):
         abspath = os.path.abspath(os.path.join(root, path))
         return abspath
 
-    def validate_absolute_path(self, root: str, absolute_path: str) -> Optional[str]:
+    def validate_absolute_path(self, root: str, absolute_path: str) -> str | None:
         """Validate and return the absolute path.
 
         ``root`` is the configured path for the `StaticFileHandler`,
@@ -3008,7 +3006,7 @@ class StaticFileHandler(RequestHandler):
 
     @classmethod
     def get_content(
-        cls, abspath: str, start: Optional[int] = None, end: Optional[int] = None
+        cls, abspath: str, start: int | None = None, end: int | None = None
     ) -> Generator[bytes, None, None]:
         """Retrieve the content of the requested resource which is located
         at the given absolute path.
@@ -3028,7 +3026,7 @@ class StaticFileHandler(RequestHandler):
             if start is not None:
                 file.seek(start)
             if end is not None:
-                remaining: Optional[int] = end - (start or 0)
+                remaining: int | None = end - (start or 0)
             else:
                 remaining = None
             while True:
@@ -3083,7 +3081,7 @@ class StaticFileHandler(RequestHandler):
         stat_result = self._stat()
         return stat_result.st_size
 
-    def get_modified_time(self) -> Optional[datetime.datetime]:
+    def get_modified_time(self) -> datetime.datetime | None:
         """Returns the time that ``self.absolute_path`` was last modified.
 
         May be overridden in subclasses.  Should return a `~datetime.datetime`
@@ -3135,7 +3133,7 @@ class StaticFileHandler(RequestHandler):
         pass
 
     def get_cache_time(
-        self, path: str, modified: Optional[datetime.datetime], mime_type: str
+        self, path: str, modified: datetime.datetime | None, mime_type: str
     ) -> int:
         """Override to customize cache control behavior.
 
@@ -3195,7 +3193,7 @@ class StaticFileHandler(RequestHandler):
         return url_path
 
     @classmethod
-    def get_version(cls, settings: dict[str, Any], path: str) -> Optional[str]:
+    def get_version(cls, settings: dict[str, Any], path: str) -> str | None:
         """Generate the version string to be used in static URLs.
 
         ``settings`` is the `Application.settings` dictionary and ``path``
@@ -3212,7 +3210,7 @@ class StaticFileHandler(RequestHandler):
         return cls._get_cached_version(abs_path)
 
     @classmethod
-    def _get_cached_version(cls, abs_path: str) -> Optional[str]:
+    def _get_cached_version(cls, abs_path: str) -> str | None:
         with cls._lock:
             hashes = cls._static_hashes
             if abs_path not in hashes:
@@ -3369,8 +3367,8 @@ class GZipContentEncoding(OutputTransform):
 
 
 def authenticated(
-    method: Callable[..., Optional[Awaitable[None]]],
-) -> Callable[..., Optional[Awaitable[None]]]:
+    method: Callable[..., Awaitable[None] | None],
+) -> Callable[..., Awaitable[None] | None]:
     """Decorate methods with this to require that the user be logged in.
 
     If the user is not logged in, they will be redirected to the configured
@@ -3385,7 +3383,7 @@ def authenticated(
     @functools.wraps(method)
     def wrapper(  # type: ignore
         self: RequestHandler, *args, **kwargs
-    ) -> Optional[Awaitable[None]]:
+    ) -> Awaitable[None] | None:
         if not self.current_user:
             if self.request.method in ("GET", "HEAD"):
                 url = self.get_login_url()
@@ -3425,16 +3423,16 @@ class UIModule:
     def current_user(self) -> Any:
         return self.handler.current_user
 
-    def render(self, *args: Any, **kwargs: Any) -> Union[str, bytes]:
+    def render(self, *args: Any, **kwargs: Any) -> str | bytes:
         """Override in subclasses to return this module's output."""
         raise NotImplementedError()
 
-    def embedded_javascript(self) -> Optional[str]:
+    def embedded_javascript(self) -> str | None:
         """Override to return a JavaScript string
         to be embedded in the page."""
         return None
 
-    def javascript_files(self) -> Optional[Iterable[str]]:
+    def javascript_files(self) -> Iterable[str] | None:
         """Override to return a list of JavaScript files needed by this module.
 
         If the return values are relative paths, they will be passed to
@@ -3442,12 +3440,12 @@ class UIModule:
         """
         return None
 
-    def embedded_css(self) -> Optional[str]:
+    def embedded_css(self) -> str | None:
         """Override to return a CSS string
         that will be embedded in the page."""
         return None
 
-    def css_files(self) -> Optional[Iterable[str]]:
+    def css_files(self) -> Iterable[str] | None:
         """Override to returns a list of CSS files required by this module.
 
         If the return values are relative paths, they will be passed to
@@ -3455,13 +3453,13 @@ class UIModule:
         """
         return None
 
-    def html_head(self) -> Optional[str]:
+    def html_head(self) -> str | None:
         """Override to return an HTML string that will be put in the <head/>
         element.
         """
         return None
 
-    def html_body(self) -> Optional[str]:
+    def html_body(self) -> str | None:
         """Override to return an HTML string that will be put at the end of
         the <body/> element.
         """
@@ -3575,10 +3573,10 @@ class _UIModuleNamespace:
 def create_signed_value(
     secret: _CookieSecretTypes,
     name: str,
-    value: Union[str, bytes],
-    version: Optional[int] = None,
-    clock: Optional[Callable[[], float]] = None,
-    key_version: Optional[int] = None,
+    value: str | bytes,
+    version: int | None = None,
+    clock: Callable[[], float] | None = None,
+    key_version: int | None = None,
 ) -> bytes:
     if version is None:
         version = DEFAULT_SIGNED_VALUE_VERSION
@@ -3607,7 +3605,7 @@ def create_signed_value(
         # - name (not encoded; assumed to be ~alphanumeric)
         # - value (base64-encoded)
         # - signature (hex-encoded; no length prefix)
-        def format_field(s: Union[str, bytes]) -> bytes:
+        def format_field(s: str | bytes) -> bytes:
             return utf8("%d:" % len(s)) + utf8(s)
 
         to_sign = b"|".join(
@@ -3665,11 +3663,11 @@ def _get_version(value: bytes) -> int:
 def decode_signed_value(
     secret: _CookieSecretTypes,
     name: str,
-    value: Union[None, str, bytes],
+    value: None | str | bytes,
     max_age_days: float = 31,
-    clock: Optional[Callable[[], float]] = None,
-    min_version: Optional[int] = None,
-) -> Optional[bytes]:
+    clock: Callable[[], float] | None = None,
+    min_version: int | None = None,
+) -> bytes | None:
     if clock is None:
         clock = time.time
     if min_version is None:
@@ -3694,12 +3692,12 @@ def decode_signed_value(
 
 
 def _decode_signed_value_v1(
-    secret: Union[str, bytes],
+    secret: str | bytes,
     name: str,
     value: bytes,
     max_age_days: float,
     clock: Callable[[], float],
-) -> Optional[bytes]:
+) -> bytes | None:
     parts = utf8(value).split(b"|")
     if len(parts) != 3:
         return None
@@ -3754,7 +3752,7 @@ def _decode_signed_value_v2(
     value: bytes,
     max_age_days: float,
     clock: Callable[[], float],
-) -> Optional[bytes]:
+) -> bytes | None:
     try:
         (
             key_version,
@@ -3788,7 +3786,7 @@ def _decode_signed_value_v2(
         return None
 
 
-def get_signature_key_version(value: Union[str, bytes]) -> Optional[int]:
+def get_signature_key_version(value: str | bytes) -> int | None:
     value = utf8(value)
     version = _get_version(value)
     if version < 2:
@@ -3801,14 +3799,14 @@ def get_signature_key_version(value: Union[str, bytes]) -> Optional[int]:
     return key_version
 
 
-def _create_signature_v1(secret: Union[str, bytes], *parts: Union[str, bytes]) -> bytes:
+def _create_signature_v1(secret: str | bytes, *parts: str | bytes) -> bytes:
     hash = hmac.new(utf8(secret), digestmod=hashlib.sha1)
     for part in parts:
         hash.update(utf8(part))
     return utf8(hash.hexdigest())
 
 
-def _create_signature_v2(secret: Union[str, bytes], s: bytes) -> bytes:
+def _create_signature_v2(secret: str | bytes, s: bytes) -> bytes:
     hash = hmac.new(utf8(secret), digestmod=hashlib.sha256)
     hash.update(utf8(s))
     return utf8(hash.hexdigest())
index b7eed5108cbf18ec76a3329c422712eecc94eca3..68b65d2dd0ec0455bca8f9b183cef07df6e719f5 100644 (file)
@@ -74,11 +74,11 @@ if TYPE_CHECKING:
         # the server side and WebSocketClientConnection on the client
         # side.
         def on_ws_connection_close(
-            self, close_code: Optional[int] = None, close_reason: Optional[str] = None
+            self, close_code: int | None = None, close_reason: str | None = None
         ) -> None:
             pass
 
-        def on_message(self, message: Union[str, bytes]) -> Optional["Awaitable[None]"]:
+        def on_message(self, message: str | bytes) -> Optional["Awaitable[None]"]:
             pass
 
         def on_ping(self, data: bytes) -> None:
@@ -89,9 +89,9 @@ if TYPE_CHECKING:
 
         def log_exception(
             self,
-            typ: Optional[type[BaseException]],
-            value: Optional[BaseException],
-            tb: Optional[TracebackType],
+            typ: type[BaseException] | None,
+            value: BaseException | None,
+            tb: TracebackType | None,
         ) -> None:
             pass
 
@@ -122,10 +122,10 @@ class _DecompressTooLargeError(Exception):
 class _WebSocketParams:
     def __init__(
         self,
-        ping_interval: Optional[float] = None,
-        ping_timeout: Optional[float] = None,
+        ping_interval: float | None = None,
+        ping_timeout: float | None = None,
         max_message_size: int = _default_max_message_size,
-        compression_options: Optional[dict[str, Any]] = None,
+        compression_options: dict[str, Any] | None = None,
     ) -> None:
         self.ping_interval = ping_interval
         self.ping_timeout = ping_timeout
@@ -221,9 +221,9 @@ class WebSocketHandler(tornado.web.RequestHandler):
         **kwargs: Any,
     ) -> None:
         super().__init__(application, request, **kwargs)
-        self.ws_connection: Optional[WebSocketProtocol] = None
-        self.close_code: Optional[int] = None
-        self.close_reason: Optional[str] = None
+        self.ws_connection: WebSocketProtocol | None = None
+        self.close_code: int | None = None
+        self.close_reason: str | None = None
         self._on_close_called = False
 
     async def get(self, *args: Any, **kwargs: Any) -> None:
@@ -279,7 +279,7 @@ class WebSocketHandler(tornado.web.RequestHandler):
             self.set_header("Sec-WebSocket-Version", "7, 8, 13")
 
     @property
-    def ping_interval(self) -> Optional[float]:
+    def ping_interval(self) -> float | None:
         """The interval for sending websocket pings.
 
         If this is non-zero, the websocket will send a ping every
@@ -294,7 +294,7 @@ class WebSocketHandler(tornado.web.RequestHandler):
         return self.settings.get("websocket_ping_interval", None)
 
     @property
-    def ping_timeout(self) -> Optional[float]:
+    def ping_timeout(self) -> float | None:
         """Timeout if no pong is received in this many seconds.
 
         To be used in combination with ``websocket_ping_interval > 0``.
@@ -332,7 +332,7 @@ class WebSocketHandler(tornado.web.RequestHandler):
         )
 
     def write_message(
-        self, message: Union[bytes, str, dict[str, Any]], binary: bool = False
+        self, message: bytes | str | dict[str, Any], binary: bool = False
     ) -> "Future[None]":
         """Sends the given message to the client of this Web Socket.
 
@@ -361,7 +361,7 @@ class WebSocketHandler(tornado.web.RequestHandler):
             message = tornado.escape.json_encode(message)
         return self.ws_connection.write_message(message, binary=binary)
 
-    def select_subprotocol(self, subprotocols: list[str]) -> Optional[str]:
+    def select_subprotocol(self, subprotocols: list[str]) -> str | None:
         """Override to implement subprotocol negotiation.
 
         ``subprotocols`` is a list of strings identifying the
@@ -387,7 +387,7 @@ class WebSocketHandler(tornado.web.RequestHandler):
         return None
 
     @property
-    def selected_subprotocol(self) -> Optional[str]:
+    def selected_subprotocol(self) -> str | None:
         """The subprotocol returned by `select_subprotocol`.
 
         .. versionadded:: 5.1
@@ -395,7 +395,7 @@ class WebSocketHandler(tornado.web.RequestHandler):
         assert self.ws_connection is not None
         return self.ws_connection.selected_subprotocol
 
-    def get_compression_options(self) -> Optional[dict[str, Any]]:
+    def get_compression_options(self) -> dict[str, Any] | None:
         """Override to return compression options for the connection.
 
         If this method returns None (the default), compression will
@@ -419,10 +419,10 @@ class WebSocketHandler(tornado.web.RequestHandler):
         # TODO: Add wbits option.
         return None
 
-    def _open(self, *args: str, **kwargs: str) -> Optional[Awaitable[None]]:
+    def _open(self, *args: str, **kwargs: str) -> Awaitable[None] | None:
         pass
 
-    open: Callable[..., Optional[Awaitable[None]]] = _open
+    open: Callable[..., Awaitable[None] | None] = _open
     """Invoked when a new WebSocket is opened.
 
     The arguments to `open` are extracted from the `tornado.web.URLSpec`
@@ -437,7 +437,7 @@ class WebSocketHandler(tornado.web.RequestHandler):
         ``open`` may be a coroutine.
     """
 
-    def on_message(self, message: Union[str, bytes]) -> Optional[Awaitable[None]]:
+    def on_message(self, message: str | bytes) -> Awaitable[None] | None:
         """Handle incoming messages on the WebSocket
 
         This method must be overridden.
@@ -448,7 +448,7 @@ class WebSocketHandler(tornado.web.RequestHandler):
         """
         raise NotImplementedError
 
-    def ping(self, data: Union[str, bytes] = b"") -> None:
+    def ping(self, data: str | bytes = b"") -> None:
         """Send ping frame to the remote end.
 
         The data argument allows a small amount of data (up to 125
@@ -490,7 +490,7 @@ class WebSocketHandler(tornado.web.RequestHandler):
         """
         pass
 
-    def close(self, code: Optional[int] = None, reason: Optional[str] = None) -> None:
+    def close(self, code: int | None = None, reason: str | None = None) -> None:
         """Closes this Web Socket.
 
         Once the close handshake is successful the socket will be closed.
@@ -593,7 +593,7 @@ class WebSocketHandler(tornado.web.RequestHandler):
             self._break_cycles()
 
     def on_ws_connection_close(
-        self, close_code: Optional[int] = None, close_reason: Optional[str] = None
+        self, close_code: int | None = None, close_reason: str | None = None
     ) -> None:
         self.close_code = close_code
         self.close_reason = close_reason
@@ -644,7 +644,7 @@ class WebSocketProtocol(abc.ABC):
 
     def __init__(self, handler: "_WebSocketDelegate") -> None:
         self.handler = handler
-        self.stream: Optional[IOStream] = None
+        self.stream: IOStream | None = None
         self.client_terminated = False
         self.server_terminated = False
 
@@ -681,7 +681,7 @@ class WebSocketProtocol(abc.ABC):
         self.close()  # let the subclass cleanup
 
     @abc.abstractmethod
-    def close(self, code: Optional[int] = None, reason: Optional[str] = None) -> None:
+    def close(self, code: int | None = None, reason: str | None = None) -> None:
         raise NotImplementedError()
 
     @abc.abstractmethod
@@ -694,13 +694,13 @@ class WebSocketProtocol(abc.ABC):
 
     @abc.abstractmethod
     def write_message(
-        self, message: Union[str, bytes, dict[str, Any]], binary: bool = False
+        self, message: str | bytes | dict[str, Any], binary: bool = False
     ) -> "Future[None]":
         raise NotImplementedError()
 
     @property
     @abc.abstractmethod
-    def selected_subprotocol(self) -> Optional[str]:
+    def selected_subprotocol(self) -> str | None:
         raise NotImplementedError()
 
     @abc.abstractmethod
@@ -713,7 +713,7 @@ class WebSocketProtocol(abc.ABC):
     # boundary is currently pretty ad-hoc.
     @abc.abstractmethod
     def _process_server_headers(
-        self, key: Union[str, bytes], headers: httputil.HTTPHeaders
+        self, key: str | bytes, headers: httputil.HTTPHeaders
     ) -> None:
         raise NotImplementedError()
 
@@ -734,8 +734,8 @@ class _PerMessageDeflateCompressor:
     def __init__(
         self,
         persistent: bool,
-        max_wbits: Optional[int],
-        compression_options: Optional[dict[str, Any]] = None,
+        max_wbits: int | None,
+        compression_options: dict[str, Any] | None = None,
     ) -> None:
         if max_wbits is None:
             max_wbits = zlib.MAX_WBITS
@@ -762,7 +762,7 @@ class _PerMessageDeflateCompressor:
             self._mem_level = compression_options["mem_level"]
 
         if persistent:
-            self._compressor: Optional[_Compressor] = self._create_compressor()
+            self._compressor: _Compressor | None = self._create_compressor()
         else:
             self._compressor = None
 
@@ -782,9 +782,9 @@ class _PerMessageDeflateDecompressor:
     def __init__(
         self,
         persistent: bool,
-        max_wbits: Optional[int],
+        max_wbits: int | None,
         max_message_size: int,
-        compression_options: Optional[dict[str, Any]] = None,
+        compression_options: dict[str, Any] | None = None,
     ) -> None:
         self._max_message_size = max_message_size
         if max_wbits is None:
@@ -797,7 +797,7 @@ class _PerMessageDeflateDecompressor:
             )
         self._max_wbits = max_wbits
         if persistent:
-            self._decompressor: Optional[_Decompressor] = self._create_decompressor()
+            self._decompressor: _Decompressor | None = self._create_decompressor()
         else:
             self._decompressor = None
 
@@ -843,15 +843,15 @@ class WebSocketProtocol13(WebSocketProtocol):
         self._final_frame = False
         self._frame_opcode = None
         self._masked_frame = None
-        self._frame_mask: Optional[bytes] = None
+        self._frame_mask: bytes | None = None
         self._frame_length = None
-        self._fragmented_message_buffer: Optional[bytearray] = None
+        self._fragmented_message_buffer: bytearray | None = None
         self._fragmented_message_opcode = None
         self._waiting: object = None
         self._compression_options = params.compression_options
-        self._decompressor: Optional[_PerMessageDeflateDecompressor] = None
-        self._compressor: Optional[_PerMessageDeflateCompressor] = None
-        self._frame_compressed: Optional[bool] = None
+        self._decompressor: _PerMessageDeflateDecompressor | None = None
+        self._compressor: _PerMessageDeflateCompressor | None = None
+        self._frame_compressed: bool | None = None
         # The total uncompressed size of all messages received or sent.
         # Unicode messages are encoded to utf8.
         # Only for testing; subject to change.
@@ -862,17 +862,17 @@ class WebSocketProtocol13(WebSocketProtocol):
         self._wire_bytes_in = 0
         self._wire_bytes_out = 0
         self._received_pong: bool = False
-        self.close_code: Optional[int] = None
-        self.close_reason: Optional[str] = None
-        self._ping_coroutine: Optional[asyncio.Task] = None
+        self.close_code: int | None = None
+        self.close_reason: str | None = None
+        self._ping_coroutine: asyncio.Task | None = None
 
     # Use a property for this to satisfy the abc.
     @property
-    def selected_subprotocol(self) -> Optional[str]:
+    def selected_subprotocol(self) -> str | None:
         return self._selected_subprotocol
 
     @selected_subprotocol.setter
-    def selected_subprotocol(self, value: Optional[str]) -> None:
+    def selected_subprotocol(self, value: str | None) -> None:
         self._selected_subprotocol = value
 
     async def accept_connection(self, handler: WebSocketHandler) -> None:
@@ -906,7 +906,7 @@ class WebSocketProtocol13(WebSocketProtocol):
             raise ValueError("Missing/Invalid WebSocket headers")
 
     @staticmethod
-    def compute_accept_value(key: Union[str, bytes]) -> str:
+    def compute_accept_value(key: str | bytes) -> str:
         """Computes the value for the Sec-WebSocket-Accept header,
         given the value for Sec-WebSocket-Key.
         """
@@ -980,7 +980,7 @@ class WebSocketProtocol13(WebSocketProtocol):
         return []
 
     def _process_server_headers(
-        self, key: Union[str, bytes], headers: httputil.HTTPHeaders
+        self, key: str | bytes, headers: httputil.HTTPHeaders
     ) -> None:
         """Process the headers sent by the server to this client connection.
 
@@ -1004,7 +1004,7 @@ class WebSocketProtocol13(WebSocketProtocol):
         self,
         side: str,
         agreed_parameters: dict[str, Any],
-        compression_options: Optional[dict[str, Any]] = None,
+        compression_options: dict[str, Any] | None = None,
     ) -> dict[str, Any]:
         """Converts a websocket agreed_parameters set to keyword arguments
         for our compressor objects.
@@ -1024,7 +1024,7 @@ class WebSocketProtocol13(WebSocketProtocol):
         self,
         side: str,
         agreed_parameters: dict[str, Any],
-        compression_options: Optional[dict[str, Any]] = None,
+        compression_options: dict[str, Any] | None = None,
     ) -> None:
         # TODO: handle invalid parameters gracefully
         allowed_keys = {
@@ -1081,7 +1081,7 @@ class WebSocketProtocol13(WebSocketProtocol):
         return self.stream.write(frame)
 
     def write_message(
-        self, message: Union[str, bytes, dict[str, Any]], binary: bool = False
+        self, message: str | bytes | dict[str, Any], binary: bool = False
     ) -> "Future[None]":
         """Sends the given message to the client of this Web Socket."""
         if binary:
@@ -1267,7 +1267,7 @@ class WebSocketProtocol13(WebSocketProtocol):
             self._abort()
         return None
 
-    def close(self, code: Optional[int] = None, reason: Optional[str] = None) -> None:
+    def close(self, code: int | None = None, reason: str | None = None) -> None:
         """Closes the WebSocket connection."""
         if not self.server_terminated:
             if not self.stream.closed():
@@ -1391,25 +1391,25 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection):
     `websocket_connect` function instead.
     """
 
-    protocol: Optional[WebSocketProtocol] = None
+    protocol: WebSocketProtocol | None = None
 
     def __init__(
         self,
         request: httpclient.HTTPRequest,
-        on_message_callback: Optional[Callable[[Union[None, str, bytes]], None]] = None,
-        compression_options: Optional[dict[str, Any]] = None,
-        ping_interval: Optional[float] = None,
-        ping_timeout: Optional[float] = None,
+        on_message_callback: Callable[[None | str | bytes], None] | None = None,
+        compression_options: dict[str, Any] | None = None,
+        ping_interval: float | None = None,
+        ping_timeout: float | None = None,
         max_message_size: int = _default_max_message_size,
-        subprotocols: Optional[list[str]] = None,
-        resolver: Optional[Resolver] = None,
+        subprotocols: list[str] | None = None,
+        resolver: Resolver | None = None,
     ) -> None:
         self.connect_future: Future[WebSocketClientConnection] = Future()
-        self.read_queue: Queue[Union[None, str, bytes]] = Queue(1)
+        self.read_queue: Queue[None | str | bytes] = Queue(1)
         self.key = base64.b64encode(os.urandom(16))
         self._on_message_callback = on_message_callback
-        self.close_code: Optional[int] = None
-        self.close_reason: Optional[str] = None
+        self.close_code: int | None = None
+        self.close_reason: str | None = None
         self.params = _WebSocketParams(
             ping_interval=ping_interval,
             ping_timeout=ping_timeout,
@@ -1464,7 +1464,7 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection):
             # dependent on GC timing).
             warnings.warn("Unclosed WebSocketClientConnection", ResourceWarning)
 
-    def close(self, code: Optional[int] = None, reason: Optional[str] = None) -> None:
+    def close(self, code: int | None = None, reason: str | None = None) -> None:
         """Closes the websocket connection.
 
         ``code`` and ``reason`` are documented under
@@ -1488,7 +1488,7 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection):
         super().on_connection_close()
 
     def on_ws_connection_close(
-        self, close_code: Optional[int] = None, close_reason: Optional[str] = None
+        self, close_code: int | None = None, close_reason: str | None = None
     ) -> None:
         self.close_code = close_code
         self.close_reason = close_reason
@@ -1505,7 +1505,7 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection):
 
     async def headers_received(
         self,
-        start_line: Union[httputil.RequestStartLine, httputil.ResponseStartLine],
+        start_line: httputil.RequestStartLine | httputil.ResponseStartLine,
         headers: httputil.HTTPHeaders,
     ) -> None:
         assert isinstance(start_line, httputil.ResponseStartLine)
@@ -1534,7 +1534,7 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection):
         future_set_result_unless_cancelled(self.connect_future, self)
 
     def write_message(
-        self, message: Union[str, bytes, dict[str, Any]], binary: bool = False
+        self, message: str | bytes | dict[str, Any], binary: bool = False
     ) -> "Future[None]":
         """Sends a message to the WebSocket server.
 
@@ -1551,8 +1551,8 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection):
 
     def read_message(
         self,
-        callback: Optional[Callable[["Future[Union[None, str, bytes]]"], None]] = None,
-    ) -> Awaitable[Union[None, str, bytes]]:
+        callback: Callable[["Future[Union[None, str, bytes]]"], None] | None = None,
+    ) -> Awaitable[None | str | bytes]:
         """Reads a message from the WebSocket server.
 
         If on_message_callback was specified at WebSocket
@@ -1569,12 +1569,10 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection):
             self.io_loop.add_future(asyncio.ensure_future(awaitable), callback)
         return awaitable
 
-    def on_message(self, message: Union[str, bytes]) -> Optional[Awaitable[None]]:
+    def on_message(self, message: str | bytes) -> Awaitable[None] | None:
         return self._on_message(message)
 
-    def _on_message(
-        self, message: Union[None, str, bytes]
-    ) -> Optional[Awaitable[None]]:
+    def _on_message(self, message: None | str | bytes) -> Awaitable[None] | None:
         if self._on_message_callback:
             self._on_message_callback(message)
             return None
@@ -1610,7 +1608,7 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection):
         return WebSocketProtocol13(self, mask_outgoing=True, params=self.params)
 
     @property
-    def selected_subprotocol(self) -> Optional[str]:
+    def selected_subprotocol(self) -> str | None:
         """The subprotocol selected by the server.
 
         .. versionadded:: 5.1
@@ -1621,8 +1619,8 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection):
     def log_exception(
         self,
         typ: "Optional[Type[BaseException]]",
-        value: Optional[BaseException],
-        tb: Optional[TracebackType],
+        value: BaseException | None,
+        tb: TracebackType | None,
     ) -> None:
         assert typ is not None
         assert value is not None
@@ -1630,16 +1628,16 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection):
 
 
 def websocket_connect(
-    url: Union[str, httpclient.HTTPRequest],
-    callback: Optional[Callable[["Future[WebSocketClientConnection]"], None]] = None,
-    connect_timeout: Optional[float] = None,
-    on_message_callback: Optional[Callable[[Union[None, str, bytes]], None]] = None,
-    compression_options: Optional[dict[str, Any]] = None,
-    ping_interval: Optional[float] = None,
-    ping_timeout: Optional[float] = None,
+    url: str | httpclient.HTTPRequest,
+    callback: Callable[["Future[WebSocketClientConnection]"], None] | None = None,
+    connect_timeout: float | None = None,
+    on_message_callback: Callable[[None | str | bytes], None] | None = None,
+    compression_options: dict[str, Any] | None = None,
+    ping_interval: float | None = None,
+    ping_timeout: float | None = None,
     max_message_size: int = _default_max_message_size,
-    subprotocols: Optional[list[str]] = None,
-    resolver: Optional[Resolver] = None,
+    subprotocols: list[str] | None = None,
+    resolver: Resolver | None = None,
 ) -> "Awaitable[WebSocketClientConnection]":
     """Client-side websocket support.
 
index f0837b181a93deeb9ea08e4e8efeba66444711df..b56efd7e3130f0b46f53a68357160c10069f73ea 100644 (file)
@@ -125,7 +125,7 @@ class WSGIContainer:
     def __init__(
         self,
         wsgi_application: "WSGIAppType",
-        executor: Optional[concurrent.futures.Executor] = None,
+        executor: concurrent.futures.Executor | None = None,
     ) -> None:
         self.wsgi_application = wsgi_application
         self.executor = dummy_executor if executor is None else executor
@@ -140,13 +140,13 @@ class WSGIContainer:
         def start_response(
             status: str,
             headers: list[tuple[str, str]],
-            exc_info: Optional[
+            exc_info: None | (
                 tuple[
                     "Optional[Type[BaseException]]",
-                    Optional[BaseException],
-                    Optional[TracebackType],
+                    BaseException | None,
+                    TracebackType | None,
                 ]
-            ] = None,
+            ) = None,
         ) -> Callable[[bytes], Any]:
             data["status"] = status
             data["headers"] = headers
@@ -162,7 +162,7 @@ class WSGIContainer:
         try:
             app_response_iter = iter(app_response)
 
-            def next_chunk() -> Optional[bytes]:
+            def next_chunk() -> bytes | None:
                 try:
                     return next(app_response_iter)
                 except StopIteration: