Skip to content

Commit a342a3f

Browse files
use union types based on pipe operator
1 parent 0c54212 commit a342a3f

11 files changed

Lines changed: 81 additions & 105 deletions

File tree

src/quart/app.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from typing import NoReturn
2222
from typing import Optional
2323
from typing import overload
24+
from typing import ParamSpec
2425
from typing import TypeVar
2526
from urllib.parse import quote
2627

@@ -126,11 +127,6 @@
126127
from .wrappers import Response
127128
from .wrappers import Websocket
128129

129-
if sys.version_info >= (3, 10):
130-
from typing import ParamSpec
131-
else:
132-
from typing_extensions import ParamSpec
133-
134130
# Python 3.14 deprecated asyncio.iscoroutinefunction, but suggested
135131
# inspect.iscoroutinefunction does not work correctly in some Python
136132
# versions before 3.12.

src/quart/asgi.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from functools import partial
66
from typing import AnyStr
77
from typing import cast
8-
from typing import Optional
98
from typing import TYPE_CHECKING
109
from urllib.parse import urlparse
1110

@@ -110,7 +109,7 @@ async def handle_request(self, request: Request, send: ASGISendCallable) -> None
110109
response = await _handle_exception(self.app, error)
111110

112111
if isinstance(response, Response) and response.timeout != Ellipsis:
113-
timeout = cast(Optional[float], response.timeout)
112+
timeout = cast(float | None, response.timeout)
114113
else:
115114
timeout = self.app.config["RESPONSE_TIMEOUT"]
116115
try:

src/quart/cli.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
import re
1111
import sys
1212
import traceback
13+
from collections.abc import Callable
1314
from importlib import import_module
15+
from importlib.metadata import entry_points
1416
from operator import attrgetter
1517
from types import ModuleType
1618
from typing import Any
17-
from typing import Callable
1819
from typing import TYPE_CHECKING
1920

2021
import click
@@ -488,15 +489,6 @@ def __init__(
488489
def _load_plugin_commands(self) -> None:
489490
if self._loaded_plugin_commands:
490491
return
491-
492-
if sys.version_info >= (3, 10):
493-
from importlib.metadata import entry_points
494-
else:
495-
# Use a backport on Python < 3.10. We technically have
496-
# importlib.metadata on 3.8+, but the API changed in 3.10,
497-
# so use the backport for consistency.
498-
from importlib_metadata import entry_points
499-
500492
for point in entry_points(group="quart.commands"):
501493
self.add_command(point.load(), point.name)
502494

src/quart/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from __future__ import annotations
22

33
import json
4+
from collections.abc import Callable
45
from typing import Any
5-
from typing import Callable
66

77
from flask.config import Config as FlaskConfig # noqa: F401
88
from flask.config import ConfigAttribute as ConfigAttribute # noqa: F401

src/quart/ctx.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
from __future__ import annotations
22

33
import sys
4+
from collections.abc import Callable
45
from contextvars import Token
56
from functools import wraps
67
from types import TracebackType
78
from typing import Any
8-
from typing import Callable
99
from typing import cast
1010
from typing import TYPE_CHECKING
1111

src/quart/formparser.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
from __future__ import annotations
22

33
from collections.abc import Awaitable
4+
from collections.abc import Callable
45
from typing import Any
5-
from typing import Callable
66
from typing import cast
77
from typing import IO
88
from typing import NoReturn
9-
from typing import Optional
109
from typing import TYPE_CHECKING
1110
from urllib.parse import parse_qsl
1211

@@ -28,12 +27,12 @@
2827
from .wrappers.request import Body
2928

3029
StreamFactory = Callable[
31-
[Optional[int], Optional[str], Optional[str], Optional[int]],
30+
[int | None, str | None, str | None, int | None],
3231
IO[bytes],
3332
]
3433

3534
ParserFunc = Callable[
36-
["FormDataParser", "Body", str, Optional[int], dict[str, str]],
35+
["FormDataParser", "Body", str, int | None, dict[str, str]],
3736
Awaitable[tuple[MultiDict, MultiDict]],
3837
]
3938

src/quart/helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os
55
import pkgutil
66
import sys
7+
from collections.abc import Callable
78
from collections.abc import Iterable
89
from datetime import datetime
910
from datetime import timedelta
@@ -13,7 +14,6 @@
1314
from io import BytesIO
1415
from pathlib import Path
1516
from typing import Any
16-
from typing import Callable
1717
from typing import cast
1818
from typing import NoReturn
1919
from zlib import adler32

src/quart/typing.py

Lines changed: 68 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,18 @@
11
from __future__ import annotations
22

33
import os
4-
import sys
54
from collections.abc import AsyncGenerator
65
from collections.abc import Awaitable
7-
from collections.abc import Iterator
8-
from collections.abc import Mapping
9-
from collections.abc import Sequence
6+
from collections.abc import Callable
107
from contextlib import AbstractAsyncContextManager
118
from datetime import datetime
129
from datetime import timedelta
1310
from http.cookiejar import CookieJar
1411
from types import TracebackType
1512
from typing import Any
1613
from typing import AnyStr
17-
from typing import Callable
18-
from typing import Optional
14+
from typing import Protocol
1915
from typing import TYPE_CHECKING
20-
from typing import Union
2116

2217
from hypercorn.typing import ASGIReceiveCallable
2318
from hypercorn.typing import ASGISendCallable
@@ -27,102 +22,97 @@
2722

2823
from .datastructures import FileStorage
2924

30-
if sys.version_info >= (3, 10):
31-
from typing import Protocol
32-
else:
33-
from typing_extensions import Protocol
34-
3525
if TYPE_CHECKING:
3626
from werkzeug.datastructures import Authorization # noqa: F401
3727
from werkzeug.datastructures import Headers # noqa: F401
38-
from werkzeug.wrappers import Response as WerkzeugResponse
3928

4029
from .app import Quart
4130
from .sessions import SessionMixin
4231
from .wrappers.response import Response # noqa: F401
4332

44-
FilePath = Union[bytes, str, os.PathLike]
33+
FilePath = bytes | str | os.PathLike
4534

4635
# The possible types that are directly convertible or are a Response object.
47-
ResponseValue = Union[
48-
"Response",
49-
"WerkzeugResponse",
50-
bytes,
51-
str,
52-
Mapping[str, Any], # any jsonify-able dict
53-
list[Any], # any jsonify-able list
54-
Iterator[bytes],
55-
Iterator[str],
56-
]
36+
ResponseValue = (
37+
"Response"
38+
" | WerkzeugResponse"
39+
" | bytes"
40+
" | str"
41+
" | Mapping[str, Any]" # any jsonify-able dict
42+
" | list[Any]" # any jsonify-able list
43+
" | Iterator[bytes]"
44+
" | Iterator[str]"
45+
)
5746
StatusCode = int
5847

5948
# the possible types for an individual HTTP header
6049
HeaderName = str
61-
HeaderValue = Union[str, list[str], tuple[str, ...]]
50+
HeaderValue = str | list[str] | tuple[str, ...]
6251

6352
# the possible types for HTTP headers
64-
HeadersValue = Union[
65-
"Headers",
66-
Mapping[HeaderName, HeaderValue],
67-
Sequence[tuple[HeaderName, HeaderValue]],
68-
]
53+
HeadersValue = (
54+
"Headers"
55+
" | Mapping[HeaderName, HeaderValue]"
56+
" | Sequence[tuple[HeaderName, HeaderValue]]"
57+
)
6958

7059
# The possible types returned by a route function.
71-
ResponseReturnValue = Union[
72-
ResponseValue,
73-
tuple[ResponseValue, HeadersValue],
74-
tuple[ResponseValue, StatusCode],
75-
tuple[ResponseValue, StatusCode, HeadersValue],
76-
]
77-
78-
ResponseTypes = Union["Response", "WerkzeugResponse"]
79-
80-
AppOrBlueprintKey = Optional[str] # The App key is None, whereas blueprints are named
81-
AfterRequestCallable = Union[
82-
Callable[[ResponseTypes], ResponseTypes],
83-
Callable[[ResponseTypes], Awaitable[ResponseTypes]],
84-
]
85-
AfterServingCallable = Union[Callable[[], None], Callable[[], Awaitable[None]]]
86-
AfterWebsocketCallable = Union[
87-
Callable[[Optional[ResponseTypes]], Optional[ResponseTypes]],
88-
Callable[[Optional[ResponseTypes]], Awaitable[Optional[ResponseTypes]]],
89-
]
90-
BeforeRequestCallable = Union[
91-
Callable[[], Optional[ResponseReturnValue]],
92-
Callable[[], Awaitable[Optional[ResponseReturnValue]]],
93-
]
94-
BeforeServingCallable = Union[Callable[[], None], Callable[[], Awaitable[None]]]
95-
BeforeWebsocketCallable = Union[
96-
Callable[[], Optional[ResponseReturnValue]],
97-
Callable[[], Awaitable[Optional[ResponseReturnValue]]],
98-
]
99-
ErrorHandlerCallable = Union[
100-
Callable[[Any], ResponseReturnValue],
101-
Callable[[Any], Awaitable[ResponseReturnValue]],
102-
]
60+
ResponseReturnValue = (
61+
"ResponseValue"
62+
" | tuple[ResponseValue, HeadersValue]"
63+
" | tuple[ResponseValue, StatusCode]"
64+
" | tuple[ResponseValue, StatusCode, HeadersValue]"
65+
)
66+
67+
ResponseTypes = "Response | WerkzeugResponse"
68+
69+
AppOrBlueprintKey = str | None # The App key is None, whereas blueprints are named
70+
AfterRequestCallable = (
71+
"Callable[[ResponseTypes], ResponseTypes]"
72+
" | Callable[[ResponseTypes], Awaitable[ResponseTypes]]"
73+
)
74+
AfterServingCallable = Callable[[], None] | Callable[[], Awaitable[None]]
75+
AfterWebsocketCallable = (
76+
"Callable[[ResponseTypes | None], ResponseTypes | None]"
77+
" | Callable[[ResponseTypes | None], Awaitable[ResponseTypes | None]]"
78+
)
79+
80+
BeforeRequestCallable = (
81+
"Callable[[], ResponseReturnValue | None]"
82+
" | Callable[[], Awaitable[ResponseReturnValue | None]]"
83+
)
84+
85+
BeforeServingCallable = Callable[[], None] | Callable[[], Awaitable[None]]
86+
BeforeWebsocketCallable = (
87+
"Callable[[], ResponseReturnValue | None]"
88+
" | Callable[[], Awaitable[ResponseReturnValue | None]]"
89+
)
90+
ErrorHandlerCallable = (
91+
"Callable[[Any], ResponseReturnValue]"
92+
" | Callable[[Any], Awaitable[ResponseReturnValue]]"
93+
)
10394
ShellContextProcessorCallable = Callable[[], dict[str, Any]]
104-
TeardownCallable = Union[
105-
Callable[[Optional[BaseException]], None],
106-
Callable[[Optional[BaseException]], Awaitable[None]],
107-
]
108-
TemplateContextProcessorCallable = Union[
109-
Callable[[], dict[str, Any]], Callable[[], Awaitable[dict[str, Any]]]
110-
]
95+
TeardownCallable = (
96+
"Callable[[BaseException | None], None]"
97+
" | Callable[[BaseException | None], Awaitable[None]]"
98+
)
99+
TemplateContextProcessorCallable = (
100+
Callable[[], dict[str, Any]] | Callable[[], Awaitable[dict[str, Any]]]
101+
)
111102
TemplateFilterCallable = Callable[[Any], Any]
112103
TemplateGlobalCallable = Callable[[Any], Any]
113104
TemplateTestCallable = Callable[[Any], bool]
114105
URLDefaultCallable = Callable[[str, dict], None]
115-
URLValuePreprocessorCallable = Callable[[Optional[str], Optional[dict]], None]
106+
URLValuePreprocessorCallable = Callable[[str | None, dict | None], None]
116107
WhileServingCallable = Callable[[], AsyncGenerator[None, None]]
117108

118-
RouteCallable = Union[
119-
Callable[..., ResponseReturnValue],
120-
Callable[..., Awaitable[ResponseReturnValue]],
121-
]
122-
WebsocketCallable = Union[
123-
Callable[..., Optional[ResponseReturnValue]],
124-
Callable[..., Awaitable[Optional[ResponseReturnValue]]],
125-
]
109+
RouteCallable = (
110+
"Callable[..., ResponseReturnValue] | Callable[..., Awaitable[ResponseReturnValue]]"
111+
)
112+
WebsocketCallable = (
113+
"Callable[..., ResponseReturnValue | None]"
114+
" | Callable[..., Awaitable[ResponseReturnValue | None]]"
115+
)
126116

127117

128118
class ASGIHTTPProtocol(Protocol):

src/quart/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from __future__ import annotations
22

3+
from collections.abc import Callable
34
from collections.abc import Collection
45
from typing import Any
5-
from typing import Callable
66
from typing import ClassVar
77

88
from .globals import current_app

src/quart/wrappers/request.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import asyncio
44
from collections.abc import Awaitable
5+
from collections.abc import Callable
56
from collections.abc import Generator
67
from typing import Any
7-
from typing import Callable
88
from typing import Literal
99
from typing import NoReturn
1010
from typing import overload

0 commit comments

Comments
 (0)