Skip to content

Commit e7203f1

Browse files
authored
type hint update for Python 3.9 and later (#450)
1 parent 9ceb266 commit e7203f1

File tree

9 files changed

+106
-115
lines changed

9 files changed

+106
-115
lines changed

e2e/pages.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
https://playwright.dev/docs/pom
55
"""
66

7-
import typing as t
8-
97
from playwright.sync_api import Page
108

119
from piccolo_admin.example.app import OrderBy
@@ -89,7 +87,7 @@ def get_column_count(self) -> int:
8987
"""
9088
return self.column_selects.count()
9189

92-
def populate_form(self, order_by_list: t.List[OrderBy]):
90+
def populate_form(self, order_by_list: list[OrderBy]):
9391
"""
9492
Make sure we have enough column select elements, and populate them.
9593
"""

piccolo_admin/endpoints.py

Lines changed: 79 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
import json
1111
import logging
1212
import os
13-
import typing as t
13+
from collections.abc import Callable, Coroutine, Sequence
1414
from dataclasses import dataclass
1515
from datetime import timedelta
1616
from functools import partial
17+
from typing import Any, Optional, TypeVar, Union
1718

1819
import typing_extensions
1920
from fastapi import FastAPI, File, Form, UploadFile
@@ -100,15 +101,15 @@ class GroupItem(BaseModel):
100101

101102

102103
class GroupedTableNamesResponseModel(BaseModel):
103-
grouped: t.Dict[str, t.List[str]] = Field(default_factory=dict)
104-
ungrouped: t.List[str] = Field(default_factory=list)
104+
grouped: dict[str, list[str]] = Field(default_factory=dict)
105+
ungrouped: list[str] = Field(default_factory=list)
105106

106107

107108
class GroupedFormsResponseModel(BaseModel):
108-
grouped: t.Dict[str, t.List[FormConfigResponseModel]] = Field(
109+
grouped: dict[str, list[FormConfigResponseModel]] = Field(
109110
default_factory=dict
110111
)
111-
ungrouped: t.List[FormConfigResponseModel] = Field(default_factory=list)
112+
ungrouped: list[FormConfigResponseModel] = Field(default_factory=list)
112113

113114

114115
@dataclass
@@ -210,20 +211,20 @@ async def manager_only(
210211
211212
"""
212213

213-
table_class: t.Type[Table]
214-
visible_columns: t.Optional[t.List[Column]] = None
215-
exclude_visible_columns: t.Optional[t.List[Column]] = None
216-
visible_filters: t.Optional[t.List[Column]] = None
217-
exclude_visible_filters: t.Optional[t.List[Column]] = None
218-
rich_text_columns: t.Optional[t.List[Column]] = None
219-
hooks: t.Optional[t.List[Hook]] = None
220-
media_storage: t.Optional[t.Sequence[MediaStorage]] = None
221-
validators: t.Optional[Validators] = None
222-
menu_group: t.Optional[str] = None
223-
link_column: t.Optional[Column] = None
224-
order_by: t.Optional[t.List[OrderBy]] = None
225-
time_resolution: t.Optional[
226-
t.Dict[t.Union[Timestamp, Timestamptz, Time], t.Union[float, int]]
214+
table_class: type[Table]
215+
visible_columns: Optional[list[Column]] = None
216+
exclude_visible_columns: Optional[list[Column]] = None
217+
visible_filters: Optional[list[Column]] = None
218+
exclude_visible_filters: Optional[list[Column]] = None
219+
rich_text_columns: Optional[list[Column]] = None
220+
hooks: Optional[list[Hook]] = None
221+
media_storage: Optional[Sequence[MediaStorage]] = None
222+
validators: Optional[Validators] = None
223+
menu_group: Optional[str] = None
224+
link_column: Optional[Column] = None
225+
order_by: Optional[list[OrderBy]] = None
226+
time_resolution: Optional[
227+
dict[Union[Timestamp, Timestamptz, Time], Union[float, int]]
227228
] = None
228229

229230
def __post_init__(self):
@@ -253,10 +254,10 @@ def __post_init__(self):
253254

254255
def _get_columns(
255256
self,
256-
include_columns: t.Optional[t.List[Column]],
257-
exclude_columns: t.Optional[t.List[Column]],
258-
all_columns: t.List[Column],
259-
) -> t.List[Column]:
257+
include_columns: Optional[list[Column]],
258+
exclude_columns: Optional[list[Column]],
259+
all_columns: list[Column],
260+
) -> list[Column]:
260261
if include_columns and not exclude_columns:
261262
return include_columns
262263

@@ -266,34 +267,34 @@ def _get_columns(
266267

267268
return all_columns
268269

269-
def get_visible_columns(self) -> t.List[Column]:
270+
def get_visible_columns(self) -> list[Column]:
270271
return self._get_columns(
271272
include_columns=self.visible_columns,
272273
exclude_columns=self.exclude_visible_columns,
273274
all_columns=self.table_class._meta.columns,
274275
)
275276

276-
def get_visible_column_names(self) -> t.Tuple[str, ...]:
277+
def get_visible_column_names(self) -> tuple[str, ...]:
277278
return tuple(i._meta.name for i in self.get_visible_columns())
278279

279-
def get_visible_filters(self) -> t.List[Column]:
280+
def get_visible_filters(self) -> list[Column]:
280281
return self._get_columns(
281282
include_columns=self.visible_filters,
282283
exclude_columns=self.exclude_visible_filters,
283284
all_columns=self.table_class._meta.columns,
284285
)
285286

286-
def get_visible_filter_names(self) -> t.Tuple[str, ...]:
287+
def get_visible_filter_names(self) -> tuple[str, ...]:
287288
return tuple(i._meta.name for i in self.get_visible_filters())
288289

289-
def get_rich_text_columns_names(self) -> t.Tuple[str, ...]:
290+
def get_rich_text_columns_names(self) -> tuple[str, ...]:
290291
return (
291292
tuple(i._meta.name for i in self.rich_text_columns)
292293
if self.rich_text_columns
293294
else ()
294295
)
295296

296-
def get_media_columns_names(self) -> t.Tuple[str, ...]:
297+
def get_media_columns_names(self) -> tuple[str, ...]:
297298
return (
298299
tuple(i._meta.name for i in self.media_columns)
299300
if self.media_columns
@@ -303,12 +304,12 @@ def get_media_columns_names(self) -> t.Tuple[str, ...]:
303304
def get_link_column(self) -> Column:
304305
return self.link_column or self.table_class._meta.primary_key
305306

306-
def get_order_by(self) -> t.List[OrderBy]:
307+
def get_order_by(self) -> list[OrderBy]:
307308
return self.order_by or [
308309
OrderBy(column=self.table_class._meta.primary_key, ascending=True)
309310
]
310311

311-
def get_time_resolution(self) -> t.Dict[str, t.Union[int, float]]:
312+
def get_time_resolution(self) -> dict[str, Union[int, float]]:
312313
return (
313314
{
314315
column._meta.name: resolution
@@ -319,17 +320,17 @@ def get_time_resolution(self) -> t.Dict[str, t.Union[int, float]]:
319320
)
320321

321322

322-
PydanticModel = t.TypeVar("PydanticModel", bound=BaseModel)
323+
PydanticModel = TypeVar("PydanticModel", bound=BaseModel)
323324

324325

325326
@dataclass
326327
class FileResponse:
327-
contents: t.Union[io.StringIO, io.BytesIO]
328+
contents: Union[io.StringIO, io.BytesIO]
328329
file_name: str
329330
media_type: str
330331

331332

332-
FormResponse: typing_extensions.TypeAlias = t.Union[str, FileResponse, None]
333+
FormResponse: typing_extensions.TypeAlias = Union[str, FileResponse, None]
333334

334335

335336
@dataclass
@@ -389,13 +390,13 @@ def my_endpoint(request: Request, data: MyModel):
389390
def __init__(
390391
self,
391392
name: str,
392-
pydantic_model: t.Type[PydanticModel],
393-
endpoint: t.Callable[
393+
pydantic_model: type[PydanticModel],
394+
endpoint: Callable[
394395
[Request, PydanticModel],
395-
t.Union[FormResponse, t.Coroutine[None, None, FormResponse]],
396+
Union[FormResponse, Coroutine[None, None, FormResponse]],
396397
],
397-
description: t.Optional[str] = None,
398-
form_group: t.Optional[str] = None,
398+
description: Optional[str] = None,
399+
form_group: Optional[str] = None,
399400
):
400401
self.name = name
401402
self.pydantic_model = pydantic_model
@@ -408,7 +409,7 @@ def __init__(
408409
class FormConfigResponseModel(BaseModel):
409410
name: str
410411
slug: str
411-
description: t.Optional[str] = None
412+
description: Optional[str] = None
412413

413414

414415
def handle_auth_exception(request: Request, exc: Exception):
@@ -441,30 +442,30 @@ class AdminRouter(FastAPI):
441442
The root returns a single page app. The other URLs are REST endpoints.
442443
"""
443444

444-
table: t.List[Table] = []
445-
auth_table: t.Type[BaseUser] = BaseUser
445+
table: list[Table] = []
446+
auth_table: type[BaseUser] = BaseUser
446447
template: str = ""
447448

448449
def __init__(
449450
self,
450-
*tables: t.Union[t.Type[Table], TableConfig],
451-
forms: t.List[FormConfig] = [],
452-
auth_table: t.Type[BaseUser] = BaseUser,
453-
session_table: t.Type[SessionsBase] = SessionsBase,
451+
*tables: Union[type[Table], TableConfig],
452+
forms: list[FormConfig] = [],
453+
auth_table: type[BaseUser] = BaseUser,
454+
session_table: type[SessionsBase] = SessionsBase,
454455
session_expiry: timedelta = timedelta(hours=1),
455456
max_session_expiry: timedelta = timedelta(days=7),
456-
increase_expiry: t.Optional[timedelta] = timedelta(minutes=20),
457+
increase_expiry: Optional[timedelta] = timedelta(minutes=20),
457458
page_size: int = 15,
458459
read_only: bool = False,
459-
rate_limit_provider: t.Optional[RateLimitProvider] = None,
460+
rate_limit_provider: Optional[RateLimitProvider] = None,
460461
production: bool = False,
461462
site_name: str = "Piccolo Admin",
462463
default_language_code: str = "auto",
463-
translations: t.Optional[t.List[Translation]] = None,
464-
allowed_hosts: t.Sequence[str] = [],
464+
translations: Optional[list[Translation]] = None,
465+
allowed_hosts: Sequence[str] = [],
465466
debug: bool = False,
466-
sidebar_links: t.Dict[str, str] = {},
467-
mfa_providers: t.Optional[t.Sequence[MFAProvider]] = None,
467+
sidebar_links: dict[str, str] = {},
468+
mfa_providers: Optional[Sequence[MFAProvider]] = None,
468469
) -> None:
469470
super().__init__(
470471
title=site_name,
@@ -486,7 +487,7 @@ def __init__(
486487
# Convert any table arguments which are plain ``Table`` classes into
487488
# ``TableConfig`` instances.
488489

489-
table_configs: t.List[TableConfig] = []
490+
table_configs: list[TableConfig] = []
490491

491492
for table in tables:
492493
if isinstance(table, TableConfig):
@@ -614,7 +615,7 @@ def __init__(
614615
path="/tables/",
615616
endpoint=self.get_table_list, # type: ignore
616617
methods=["GET"],
617-
response_model=t.List[str],
618+
response_model=list[str],
618619
tags=["Tables"],
619620
)
620621

@@ -638,7 +639,7 @@ def __init__(
638639
endpoint=self.get_forms, # type: ignore
639640
methods=["GET"],
640641
tags=["Forms"],
641-
response_model=t.List[FormConfigResponseModel],
642+
response_model=list[FormConfigResponseModel],
642643
)
643644

644645
private_app.add_api_route(
@@ -953,7 +954,7 @@ def get_user(self, request: Request) -> UserResponseModel:
953954
###########################################################################
954955
# Custom forms
955956

956-
def get_forms(self) -> t.List[FormConfigResponseModel]:
957+
def get_forms(self) -> list[FormConfigResponseModel]:
957958
"""
958959
Returns a list of all forms registered with the admin.
959960
"""
@@ -1006,17 +1007,15 @@ def get_single_form(self, form_slug: str) -> FormConfigResponseModel:
10061007
description=form.description,
10071008
)
10081009

1009-
def get_single_form_schema(self, form_slug: str) -> t.Dict[str, t.Any]:
1010+
def get_single_form_schema(self, form_slug: str) -> dict[str, Any]:
10101011
form_config = self.form_config_map.get(form_slug)
10111012

10121013
if form_config is None:
10131014
raise HTTPException(status_code=404, detail="No such form found")
10141015
else:
10151016
return form_config.pydantic_model.model_json_schema()
10161017

1017-
async def post_single_form(
1018-
self, request: Request, form_slug: str
1019-
) -> t.Any:
1018+
async def post_single_form(self, request: Request, form_slug: str) -> Any:
10201019
"""
10211020
Handles posting of custom forms.
10221021
"""
@@ -1077,15 +1076,15 @@ def get_meta(self) -> MetaResponseModel:
10771076

10781077
###########################################################################
10791078

1080-
def get_sidebar_links(self) -> t.Dict[str, str]:
1079+
def get_sidebar_links(self) -> dict[str, str]:
10811080
"""
10821081
Returns the custom links registered with the admin.
10831082
"""
10841083
return self.sidebar_links
10851084

10861085
###########################################################################
10871086

1088-
def get_table_list(self) -> t.List[str]:
1087+
def get_table_list(self) -> list[str]:
10891088
"""
10901089
Returns the list of table groups registered with the admin.
10911090
"""
@@ -1148,15 +1147,15 @@ def get_translation(self, language_code: str = "en") -> Translation:
11481147

11491148

11501149
def get_all_tables(
1151-
tables: t.Sequence[t.Type[Table]],
1152-
) -> t.Sequence[t.Type[Table]]:
1150+
tables: Sequence[type[Table]],
1151+
) -> Sequence[type[Table]]:
11531152
"""
11541153
Fetch any related tables, and include them.
11551154
"""
1156-
output: t.List[t.Type[Table]] = []
1155+
output: list[type[Table]] = []
11571156

1158-
def get_references(table: t.Type[Table]):
1159-
references: t.List[t.Union[t.Type[Table], t.Any]] = [
1157+
def get_references(table: type[Table]):
1158+
references: list[Union[type[Table], Any]] = [
11601159
i._foreign_key_meta.references
11611160
for i in table._meta.foreign_key_columns
11621161
]
@@ -1180,25 +1179,25 @@ def get_references(table: t.Type[Table]):
11801179

11811180

11821181
def create_admin(
1183-
tables: t.Sequence[t.Union[t.Type[Table], TableConfig]],
1184-
forms: t.List[FormConfig] = [],
1185-
auth_table: t.Optional[t.Type[BaseUser]] = None,
1186-
session_table: t.Optional[t.Type[SessionsBase]] = None,
1182+
tables: Sequence[Union[type[Table], TableConfig]],
1183+
forms: list[FormConfig] = [],
1184+
auth_table: Optional[type[BaseUser]] = None,
1185+
session_table: Optional[type[SessionsBase]] = None,
11871186
session_expiry: timedelta = timedelta(hours=1),
11881187
max_session_expiry: timedelta = timedelta(days=7),
1189-
increase_expiry: t.Optional[timedelta] = timedelta(minutes=20),
1188+
increase_expiry: Optional[timedelta] = timedelta(minutes=20),
11901189
page_size: int = 15,
11911190
read_only: bool = False,
1192-
rate_limit_provider: t.Optional[RateLimitProvider] = None,
1191+
rate_limit_provider: Optional[RateLimitProvider] = None,
11931192
production: bool = False,
11941193
site_name: str = "Piccolo Admin",
11951194
default_language_code: str = "auto",
1196-
translations: t.Optional[t.List[Translation]] = None,
1195+
translations: Optional[list[Translation]] = None,
11971196
auto_include_related: bool = True,
1198-
allowed_hosts: t.Sequence[str] = [],
1197+
allowed_hosts: Sequence[str] = [],
11991198
debug: bool = False,
1200-
sidebar_links: t.Dict[str, str] = {},
1201-
mfa_providers: t.Optional[t.Sequence[MFAProvider]] = None,
1199+
sidebar_links: dict[str, str] = {},
1200+
mfa_providers: Optional[Sequence[MFAProvider]] = None,
12021201
):
12031202
"""
12041203
:param tables:
@@ -1328,7 +1327,7 @@ def create_admin(
13281327
session_table = session_table or SessionsBase
13291328

13301329
if auto_include_related:
1331-
table_config_map: t.Dict[t.Type[Table], t.Optional[TableConfig]] = {}
1330+
table_config_map: dict[type[Table], Optional[TableConfig]] = {}
13321331

13331332
for i in tables:
13341333
if isinstance(i, TableConfig):
@@ -1338,8 +1337,8 @@ def create_admin(
13381337

13391338
all_table_classes = get_all_tables(tuple(table_config_map.keys()))
13401339

1341-
all_table_classes_with_configs: t.List[
1342-
t.Union[t.Type[Table], TableConfig]
1340+
all_table_classes_with_configs: list[
1341+
Union[type[Table], TableConfig]
13431342
] = []
13441343
for i in all_table_classes:
13451344
table_config = table_config_map.get(i)

0 commit comments

Comments
 (0)