Skip to content

Commit 6bfe9fe

Browse files
authored
Use __future__.annotations (#2433)
* Use `__future__.annotations` * fix linter
1 parent b5126b2 commit 6bfe9fe

22 files changed

+365
-393
lines changed

starlette/_exception_handler.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import typing
24

35
from starlette._utils import is_async_callable
@@ -22,16 +24,14 @@
2224

2325
def _lookup_exception_handler(
2426
exc_handlers: ExceptionHandlers, exc: Exception
25-
) -> typing.Optional[ExceptionHandler]:
27+
) -> ExceptionHandler | None:
2628
for cls in type(exc).__mro__:
2729
if cls in exc_handlers:
2830
return exc_handlers[cls]
2931
return None
3032

3133

32-
def wrap_app_handling_exceptions(
33-
app: ASGIApp, conn: typing.Union[Request, WebSocket]
34-
) -> ASGIApp:
34+
def wrap_app_handling_exceptions(app: ASGIApp, conn: Request | WebSocket) -> ASGIApp:
3535
exception_handlers: ExceptionHandlers
3636
status_handlers: StatusHandlers
3737
try:

starlette/_utils.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import asyncio
24
import functools
35
import re
@@ -74,7 +76,7 @@ async def __aenter__(self) -> SupportsAsyncCloseType:
7476
self.entered = await self.aw
7577
return self.entered
7678

77-
async def __aexit__(self, *args: typing.Any) -> typing.Union[None, bool]:
79+
async def __aexit__(self, *args: typing.Any) -> None | bool:
7880
await self.entered.close()
7981
return None
8082

starlette/applications.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ class Starlette:
5555
"""
5656

5757
def __init__(
58-
self: "AppType",
58+
self: AppType,
5959
debug: bool = False,
6060
routes: typing.Sequence[BaseRoute] | None = None,
6161
middleware: typing.Sequence[Middleware] | None = None,
6262
exception_handlers: typing.Mapping[typing.Any, ExceptionHandler] | None = None,
6363
on_startup: typing.Sequence[typing.Callable[[], typing.Any]] | None = None,
6464
on_shutdown: typing.Sequence[typing.Callable[[], typing.Any]] | None = None,
65-
lifespan: typing.Optional[Lifespan["AppType"]] = None,
65+
lifespan: Lifespan[AppType] | None = None,
6666
) -> None:
6767
# The lifespan context function is a newer style that replaces
6868
# on_startup / on_shutdown handlers. Use one or the other, not both.
@@ -84,7 +84,7 @@ def __init__(
8484
def build_middleware_stack(self) -> ASGIApp:
8585
debug = self.debug
8686
error_handler = None
87-
exception_handlers: typing.Dict[
87+
exception_handlers: dict[
8888
typing.Any, typing.Callable[[Request, Exception], Response]
8989
] = {}
9090

@@ -110,7 +110,7 @@ def build_middleware_stack(self) -> ASGIApp:
110110
return app
111111

112112
@property
113-
def routes(self) -> typing.List[BaseRoute]:
113+
def routes(self) -> list[BaseRoute]:
114114
return self.router.routes
115115

116116
def url_path_for(self, name: str, /, **path_params: typing.Any) -> URLPath:
@@ -193,7 +193,7 @@ def decorator(func: typing.Callable) -> typing.Callable: # type: ignore[type-ar
193193
def route(
194194
self,
195195
path: str,
196-
methods: typing.List[str] | None = None,
196+
methods: list[str] | None = None,
197197
name: str | None = None,
198198
include_in_schema: bool = True,
199199
) -> typing.Callable: # type: ignore[type-arg]

starlette/authentication.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import functools
24
import inspect
35
import sys
@@ -26,9 +28,9 @@ def has_required_scope(conn: HTTPConnection, scopes: typing.Sequence[str]) -> bo
2628

2729

2830
def requires(
29-
scopes: typing.Union[str, typing.Sequence[str]],
31+
scopes: str | typing.Sequence[str],
3032
status_code: int = 403,
31-
redirect: typing.Optional[str] = None,
33+
redirect: str | None = None,
3234
) -> typing.Callable[
3335
[typing.Callable[_P, typing.Any]], typing.Callable[_P, typing.Any]
3436
]:
@@ -113,12 +115,12 @@ class AuthenticationError(Exception):
113115
class AuthenticationBackend:
114116
async def authenticate(
115117
self, conn: HTTPConnection
116-
) -> typing.Optional[typing.Tuple["AuthCredentials", "BaseUser"]]:
118+
) -> tuple[AuthCredentials, BaseUser] | None:
117119
raise NotImplementedError() # pragma: no cover
118120

119121

120122
class AuthCredentials:
121-
def __init__(self, scopes: typing.Optional[typing.Sequence[str]] = None):
123+
def __init__(self, scopes: typing.Sequence[str] | None = None):
122124
self.scopes = [] if scopes is None else list(scopes)
123125

124126

starlette/background.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import sys
24
import typing
35

@@ -29,7 +31,7 @@ async def __call__(self) -> None:
2931

3032

3133
class BackgroundTasks(BackgroundTask):
32-
def __init__(self, tasks: typing.Optional[typing.Sequence[BackgroundTask]] = None):
34+
def __init__(self, tasks: typing.Sequence[BackgroundTask] | None = None):
3335
self.tasks = list(tasks) if tasks else []
3436

3537
def add_task(

starlette/concurrency.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import functools
24
import sys
35
import typing
@@ -14,7 +16,7 @@
1416
T = typing.TypeVar("T")
1517

1618

17-
async def run_until_first_complete(*args: typing.Tuple[typing.Callable, dict]) -> None: # type: ignore[type-arg] # noqa: E501
19+
async def run_until_first_complete(*args: tuple[typing.Callable, dict]) -> None: # type: ignore[type-arg] # noqa: E501
1820
warnings.warn(
1921
"run_until_first_complete is deprecated "
2022
"and will be removed in a future version.",

starlette/config.py

+11-13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import os
24
import typing
35
from pathlib import Path
@@ -51,7 +53,7 @@ def __len__(self) -> int:
5153
class Config:
5254
def __init__(
5355
self,
54-
env_file: typing.Optional[typing.Union[str, Path]] = None,
56+
env_file: str | Path | None = None,
5557
environ: typing.Mapping[str, str] = environ,
5658
env_prefix: str = "",
5759
) -> None:
@@ -64,17 +66,15 @@ def __init__(
6466
self.file_values = self._read_file(env_file)
6567

6668
@typing.overload
67-
def __call__(self, key: str, *, default: None) -> typing.Optional[str]:
69+
def __call__(self, key: str, *, default: None) -> str | None:
6870
...
6971

7072
@typing.overload
71-
def __call__(self, key: str, cast: typing.Type[T], default: T = ...) -> T:
73+
def __call__(self, key: str, cast: type[T], default: T = ...) -> T:
7274
...
7375

7476
@typing.overload
75-
def __call__(
76-
self, key: str, cast: typing.Type[str] = ..., default: str = ...
77-
) -> str:
77+
def __call__(self, key: str, cast: type[str] = ..., default: str = ...) -> str:
7878
...
7979

8080
@typing.overload
@@ -87,23 +87,21 @@ def __call__(
8787
...
8888

8989
@typing.overload
90-
def __call__(
91-
self, key: str, cast: typing.Type[str] = ..., default: T = ...
92-
) -> typing.Union[T, str]:
90+
def __call__(self, key: str, cast: type[str] = ..., default: T = ...) -> T | str:
9391
...
9492

9593
def __call__(
9694
self,
9795
key: str,
98-
cast: typing.Optional[typing.Callable[[typing.Any], typing.Any]] = None,
96+
cast: typing.Callable[[typing.Any], typing.Any] | None = None,
9997
default: typing.Any = undefined,
10098
) -> typing.Any:
10199
return self.get(key, cast, default)
102100

103101
def get(
104102
self,
105103
key: str,
106-
cast: typing.Optional[typing.Callable[[typing.Any], typing.Any]] = None,
104+
cast: typing.Callable[[typing.Any], typing.Any] | None = None,
107105
default: typing.Any = undefined,
108106
) -> typing.Any:
109107
key = self.env_prefix + key
@@ -117,7 +115,7 @@ def get(
117115
return self._perform_cast(key, default, cast)
118116
raise KeyError(f"Config '{key}' is missing, and has no default.")
119117

120-
def _read_file(self, file_name: typing.Union[str, Path]) -> typing.Dict[str, str]:
118+
def _read_file(self, file_name: str | Path) -> dict[str, str]:
121119
file_values: typing.Dict[str, str] = {}
122120
with open(file_name) as input_file:
123121
for line in input_file.readlines():
@@ -133,7 +131,7 @@ def _perform_cast(
133131
self,
134132
key: str,
135133
value: typing.Any,
136-
cast: typing.Optional[typing.Callable[[typing.Any], typing.Any]] = None,
134+
cast: typing.Callable[[typing.Any], typing.Any] | None = None,
137135
) -> typing.Any:
138136
if cast is None or value is None:
139137
return value

0 commit comments

Comments
 (0)