1919T_ = t .TypeVar ("T_" )
2020
2121
22+ class FieldTransientData :
23+ def __init__ (self ) -> None :
24+ self ._data = None
25+ self .errors = []
26+ self .raw_data = None
27+ self ._value = None
28+
29+ @property
30+ def value (self ) -> t .Any :
31+ return self ._value
32+
33+ @value .setter
34+ def value (self , value : t .Any ) -> None :
35+ """
36+ Set the data associated with the field.
37+
38+ Args:
39+ value: The data to set.
40+ """
41+ self ._value = value
42+
43+ @property
44+ def data (self ) -> t .Any :
45+ """
46+ Get the data associated with the field.
47+
48+ Returns:
49+ t.Any: The data associated with the field.
50+ """
51+ return self .raw_data if self .raw_data else self ._data
52+
53+ @data .setter
54+ def data (self , value : t .Any ) -> None :
55+ """
56+ Set the data associated with the field.
57+
58+ Args:
59+ value: The data to set.
60+ """
61+ self ._data = value
62+
63+ def clear (self ):
64+ self .data = None
65+ self .errors = []
66+ self .raw_data = None
67+ self ._value = None
68+
69+
2270class FieldBaseMeta (type ):
2371 def __call__ (cls , * args : t .Any , ** kwargs : t .Any ):
2472 field_info_args = kwargs .pop ("field_info_args" , None )
@@ -65,18 +113,14 @@ def __init__(
65113 disabled : t .Optional [bool ] = False ,
66114 read_only : t .Optional [bool ] = False ,
67115 field_info_args : t .Optional [t .Union [AttributeDict , t .Dict ]] = None ,
116+ help_text : t .Optional [str ] = None ,
68117 ** attrs : t .Any ,
69118 ) -> None :
70119 # A field is fully configured when __field_info_args__ is provided
71120 assert self .type
72121
73- self ._value = None
74122 self .name = name or "no-name"
75123 self .id = id
76-
77- self ._data = None
78- self .raw_data = None
79- self .errors = []
80124 self ._default = None
81125 self .attrs = AttributeDict (
82126 attrs ,
@@ -86,7 +130,7 @@ def __init__(
86130 "class" : class_ ,
87131 },
88132 )
89- self .help_text = None
133+ self .help_text = help_text
90134 self .label = None
91135
92136 self ._field_info_args = AttributeDict (
@@ -103,7 +147,9 @@ def __init__(
103147 self .id = self ._field_info .alias
104148 self .label = FormLabel (self .id , label or self .name .capitalize ())
105149 self .help_text = self .help_text or self ._field_info_args .description
150+
106151 self ._widget : t .Optional [FieldWidget ] = None
152+ self ._transient_data = FieldTransientData ()
107153
108154 @property
109155 def widget (self ) -> FieldWidget :
@@ -157,23 +203,41 @@ def required(self) -> bool:
157203
158204 @property
159205 def data (self ) -> t .Any :
160- """
161- Get the data associated with the field.
162-
163- Returns:
164- t.Any: The data associated with the field.
165- """
166- return self .raw_data if self .raw_data else self ._data
206+ return self ._transient_data .data
167207
168208 @data .setter
169209 def data (self , value : t .Any ) -> None :
210+ self ._transient_data .data = value
211+
212+ @property
213+ def errors (self ) -> t .List [str ]:
214+ return self ._transient_data .errors
215+
216+ @errors .setter
217+ def errors (self , value : t .Any ) -> None :
218+ self ._transient_data .errors = value
219+
220+ @property
221+ def raw_data (self ) -> t .Any :
222+ return self ._transient_data .raw_data
223+
224+ @raw_data .setter
225+ def raw_data (self , value : t .Any ) -> None :
226+ self ._transient_data .raw_data = value
227+
228+ @property
229+ def value (self ) -> T_ :
170230 """
171- Set the data associated with the field.
231+ Get the processed value of the field.
172232
173- Args :
174- value : The data to set .
233+ Returns :
234+ T_ : The processed value of the field .
175235 """
176- self ._data = value
236+ return t .cast (T_ , self ._transient_data .value )
237+
238+ @value .setter
239+ def value (self , value : t .Any ) -> t .Any :
240+ self ._transient_data .value = value
177241
178242 @default .setter
179243 def default (self , value : t .Any ) -> None :
@@ -196,24 +260,11 @@ def model_field(self) -> ModelField:
196260 """
197261 return self .__resolver .model_field
198262
199- @property
200- def value (self ) -> T_ :
263+ def clear (self ) -> None :
201264 """
202- Get the processed value of the field.
203-
204- Returns:
205- T_: The processed value of the field.
206- """
207- return self ._value
208-
209- def clear (self ):
265+ Clear the field's value and errors.
210266 """
211- Clear all field inputs and validation.
212- """
213- self .raw_data = None
214- self .errors = []
215- self ._data = None
216- self ._value = None
267+ self ._transient_data .clear ()
217268
218269 def validate_setup (self ) -> None :
219270 """
@@ -234,13 +285,13 @@ def process(
234285 data: The input data to process.
235286 suppress_error: Whether to suppress validation errors.
236287 """
237- self .errors .clear ()
288+ self ._transient_data . errors .clear ()
238289 v_ , errors_ = self .model_field .validate (
239290 data , {"processing_data" : True }, loc = (self .__class__ .__name__ ,)
240291 )
241292
242293 if not errors_ :
243- self ._value = v_
294+ self .value = v_
244295 # export to JSON for UI to understand
245296 self .data = fail_silently (self .model_field .serialize , v_ ) or v_
246297
@@ -254,6 +305,7 @@ def load(self) -> "FieldBase":
254305 Returns:
255306 FieldBase: The field instance with the default value loaded.
256307 """
308+ self ._transient_data .clear ()
257309 self .process (self .default , suppress_error = True )
258310 return self
259311
@@ -343,7 +395,7 @@ def __apply_model_field(self) -> None:
343395 self .__resolver = FormParameterResolver (new_model_field )
344396
345397 async def process_form_data (
346- self , ctx : IExecutionContext , body : t .Any
398+ self , ctx : IExecutionContext , body : t .Any , ** kwargs : t . Any
347399 ) -> ResolverResult :
348400 """
349401 Process form data for the field.
@@ -355,12 +407,12 @@ async def process_form_data(
355407 Returns:
356408 ResolverResult: The result of the form data processing.
357409 """
358- res = await self .__resolver .resolve (ctx , body = body )
410+ res = await self .__resolver .resolve (ctx , body = body , ** kwargs )
359411 _ , self .raw_data = dict (res .raw_data ).popitem ()
360412 self .errors = format_errors (res .errors )
361413
362414 if not res .errors :
363- self ._value = res .data [self .model_field .name ]
415+ self .value = res .data [self .model_field .name ]
364416
365417 return res
366418
@@ -452,7 +504,7 @@ def rebuild(
452504 z_field_info_args .update (
453505 name = name ,
454506 field_info_args = AttributeDict (
455- ** field_info_args ,
507+ field_info_args ,
456508 alias = alias ,
457509 annotation = annotation or get_form_field_python_type (self ),
458510 default = default ,
0 commit comments