2525
2626import pydal
2727from pydal ._globals import DEFAULT
28-
29- # from pydal.objects import Field as _Field
30- # from pydal.objects import Query as _Query
3128from pydal .objects import Row
32-
33- # from pydal.objects import Table as _Table
3429from typing_extensions import Self , Unpack
3530
36- # from .annotations import resolve_annotation
3731from .config import TypeDALConfig , load_config
3832from .helpers import (
3933 SYSTEM_SUPPORTS_TEMPLATES ,
@@ -249,7 +243,7 @@ class Relationship(typing.Generic[To_Type]):
249243 Define a relationship to another table.
250244 """
251245
252- _type : To_Type
246+ _type : Type [ To_Type ]
253247 table : Type ["TypedTable" ] | type | str
254248 condition : Condition
255249 condition_and : Condition
@@ -259,7 +253,7 @@ class Relationship(typing.Generic[To_Type]):
259253
260254 def __init__ (
261255 self ,
262- _type : To_Type ,
256+ _type : Type [ To_Type ] ,
263257 condition : Condition = None ,
264258 join : JOIN_OPTIONS = None ,
265259 on : OnQuery = None ,
@@ -282,7 +276,7 @@ def __init__(
282276 self .table = unwrap_type (args [0 ])
283277 self .multiple = True
284278 else :
285- self .table = _type
279+ self .table = typing . cast ( type [ TypedTable ], _type )
286280 self .multiple = False
287281
288282 if isinstance (self .table , str ):
@@ -977,7 +971,7 @@ def sql_expression(
977971 * raw_args : Any ,
978972 output_type : str | None = None ,
979973 ** raw_kwargs : Any ,
980- ):
974+ ) -> Expression :
981975 """
982976 Creates a pydal Expression object representing a raw SQL fragment.
983977
@@ -999,7 +993,7 @@ def default_representer(field: TypedField[T], value: T, table: Type[TypedTable])
999993 Simply call field.represent on the value.
1000994 """
1001995 if represent := getattr (field , "represent" , None ):
1002- return represent (value , table )
996+ return str ( represent (value , table ) )
1003997 else :
1004998 return repr (value )
1005999
@@ -1012,7 +1006,7 @@ def default_representer(field: TypedField[T], value: T, table: Type[TypedTable])
10121006
10131007def reorder_fields (
10141008 table : pydal .objects .Table ,
1015- fields : typing .Iterable [str | Field | TypedField ],
1009+ fields : typing .Iterable [str | Field | TypedField [ Any ] ],
10161010 keep_others : bool = True ,
10171011) -> None :
10181012 """
@@ -1588,7 +1582,7 @@ def after_delete_once(
15881582 """
15891583 return cls ._hook_once (cls ._after_delete , fn )
15901584
1591- def reorder_fields (cls , * fields : str | Field | TypedField , keep_others : bool = True ):
1585+ def reorder_fields (cls , * fields : str | Field | TypedField [ Any ] , keep_others : bool = True ) -> None :
15921586 """
15931587 Reorder fields of a typedal table.
15941588
@@ -1598,7 +1592,6 @@ def reorder_fields(cls, *fields: str | Field | TypedField, keep_others: bool = T
15981592 - True (default): keep other fields at the end, in their original order.
15991593 - False: remove other fields (only keep what's specified).
16001594 """
1601-
16021595 return reorder_fields (cls ._table , fields , keep_others = keep_others )
16031596
16041597
@@ -1935,13 +1928,13 @@ def __getattr__(self, item: str) -> Any:
19351928
19361929 raise AttributeError (item )
19371930
1938- def keys (self ):
1931+ def keys (self ) -> list [ str ] :
19391932 """
19401933 Return the combination of row + relationship keys.
19411934
19421935 Used by dict(row).
19431936 """
1944- return list (self ._row .keys ()) + getattr (self , "_with" , [])
1937+ return list (self ._row .keys () if self . _row else () ) + getattr (self , "_with" , [])
19451938
19461939 def get (self , item : str , default : Any = None ) -> Any :
19471940 """
@@ -2202,7 +2195,17 @@ def _sql(cls) -> str:
22022195
22032196 return pydal2sql .generate_sql (cls )
22042197
2205- def render (self , fields = None , compact = False ) -> Self :
2198+ def render (self , fields : list [Field ] = None , compact : bool = False ) -> Self :
2199+ """
2200+ Renders a copy of the object with potentially modified values.
2201+
2202+ Args:
2203+ fields: A list of fields to render. Defaults to all representable fields in the table.
2204+ compact: Whether to return only the value of the first field if there is only one field.
2205+
2206+ Returns:
2207+ A copy of the object with potentially modified values.
2208+ """
22062209 row = copy .deepcopy (self )
22072210 keys = list (row )
22082211 if not fields :
@@ -2256,7 +2259,7 @@ def render(self, fields=None, compact=False) -> Self:
22562259 )
22572260
22582261 if compact and len (keys ) == 1 and keys [0 ] != "_extra" : # pragma: no cover
2259- return row [keys [0 ]]
2262+ return typing . cast ( Self , row [keys [0 ]])
22602263 return row
22612264
22622265
@@ -2455,11 +2458,11 @@ def as_csv(self) -> str:
24552458
24562459 def as_dict (
24572460 self ,
2458- key : str | Field = None ,
2461+ key : str | Field | None = None ,
24592462 compact : bool = False ,
24602463 storage_to_dict : bool = False ,
24612464 datetime_to_str : bool = False ,
2462- custom_types : list [type ] = None ,
2465+ custom_types : list [type ] | None = None ,
24632466 ) -> dict [int , AnyDict ]:
24642467 """
24652468 Get the data in a dict of dicts.
@@ -2633,10 +2636,12 @@ def __setstate__(self, state: AnyDict) -> None:
26332636 self .__dict__ .update (state )
26342637 # db etc. set after undill by caching.py
26352638
2636- def render (self , i = None , fields = None ) -> typing .Generator [T_MetaInstance , None , None ]:
2639+ def render (
2640+ self , i : int | None = None , fields : list [Field ] | None = None
2641+ ) -> typing .Generator [T_MetaInstance , None , None ]:
26372642 """
2638- Takes an index and returns a copy of the indexed row with values
2639- transformed via the "represent" attributes of the associated fields.
2643+ Takes an index and returns a copy of the indexed row with values \
2644+ transformed via the "represent" attributes of the associated fields.
26402645
26412646 Args:
26422647 i: index. If not specified, a generator is returned for iteration
@@ -2646,7 +2651,7 @@ def render(self, i=None, fields=None) -> typing.Generator[T_MetaInstance, None,
26462651 """
26472652 if i is None :
26482653 # difference: uses .keys() instead of index
2649- return (self .render (i , fields = fields ) for i in self .records . keys () )
2654+ return (self .render (i , fields = fields ) for i in self .records )
26502655
26512656 if not self .db .has_representer ("rows_render" ): # pragma: no cover
26522657 raise RuntimeError (
@@ -2668,10 +2673,10 @@ def render(self, i=None, fields=None) -> typing.Generator[T_MetaInstance, None,
26682673)
26692674
26702675
2671- def normalize_table_keys (row : Row , pattern : re .Pattern = re .compile (r"^([a-zA-Z_]+)_(\d{5,})$" )) -> Row :
2676+ def normalize_table_keys (row : Row , pattern : re .Pattern [ str ] = re .compile (r"^([a-zA-Z_]+)_(\d{5,})$" )) -> Row :
26722677 """
2673- Normalize table keys in a PyDAL Row object by stripping numeric hash suffixes
2674- from table names, only if the suffix is 5 or more digits.
2678+ Normalize table keys in a PyDAL Row object by stripping numeric hash suffixes from table names, \
2679+ only if the suffix is 5 or more digits.
26752680
26762681 For example:
26772682 Row({'articles_12345': {...}}) -> Row({'articles': {...}})
@@ -2810,7 +2815,7 @@ def select(self, *fields: Any, **options: Unpack[SelectKwargs]) -> "QueryBuilder
28102815
28112816 def where (
28122817 self ,
2813- * queries_or_lambdas : Query | typing .Callable [[Type [T_MetaInstance ]], Query ] | dict ,
2818+ * queries_or_lambdas : Query | typing .Callable [[Type [T_MetaInstance ]], Query ] | dict [ str , Any ] ,
28142819 ** filters : Any ,
28152820 ) -> "QueryBuilder[T_MetaInstance]" :
28162821 """
@@ -2892,8 +2897,9 @@ def join(
28922897 if isinstance (condition , pydal .objects .Query ):
28932898 condition = as_lambda (condition )
28942899
2900+ to_field = typing .cast (Type [TypedTable ], fields [0 ])
28952901 relationships = {
2896- str (fields [ 0 ] ): Relationship (fields [ 0 ] , condition = condition , join = method , condition_and = condition_and )
2902+ str (to_field ): Relationship (to_field , condition = condition , join = method , condition_and = condition_and )
28972903 }
28982904 elif on :
28992905 if len (fields ) != 1 :
@@ -2904,7 +2910,9 @@ def join(
29042910
29052911 if isinstance (on , list ):
29062912 on = as_lambda (on )
2907- relationships = {str (fields [0 ]): Relationship (fields [0 ], on = on , join = method , condition_and = condition_and )}
2913+
2914+ to_field = typing .cast (Type [TypedTable ], fields [0 ])
2915+ relationships = {str (to_field ): Relationship (to_field , on = on , join = method , condition_and = condition_and )}
29082916
29092917 else :
29102918 if fields :
0 commit comments