1010import json
1111import logging
1212import os
13- import typing as t
13+ from collections . abc import Callable , Coroutine , Sequence
1414from dataclasses import dataclass
1515from datetime import timedelta
1616from functools import partial
17+ from typing import Any , Optional , TypeVar , Union
1718
1819import typing_extensions
1920from fastapi import FastAPI , File , Form , UploadFile
@@ -100,15 +101,15 @@ class GroupItem(BaseModel):
100101
101102
102103class 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
107108class 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
326327class 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__(
408409class FormConfigResponseModel (BaseModel ):
409410 name : str
410411 slug : str
411- description : t . Optional [str ] = None
412+ description : Optional [str ] = None
412413
413414
414415def 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
11501149def 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
11821181def 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