@@ -31,6 +31,7 @@ def add(
3131 fallback : Any = None ,
3232 filters : Optional [List [BaseFilter ]] = None ,
3333 validators : Optional [List [BaseValidator ]] = None ,
34+ steps : Optional [List [Union [BaseFilter , BaseValidator ]]] = None ,
3435 external_api : Optional [ExternalApiConfig ] = None ,
3536 ) -> None :
3637 """
@@ -43,6 +44,7 @@ def add(
4344 or field None, although it is required .
4445 :param filters: The filters to apply to the field value.
4546 :param validators: The validators to apply to the field value.
47+ :param steps:
4648 :param external_api: Configuration for an external API call.
4749 """
4850
@@ -52,6 +54,7 @@ def add(
5254 "fallback" : fallback ,
5355 "filters" : filters or [],
5456 "validators" : validators or [],
57+ "steps" : steps or [],
5558 "external_api" : external_api ,
5659 }
5760
@@ -73,11 +76,14 @@ def addGlobalValidator(self, validator: BaseValidator) -> None:
7376 """
7477 self .global_validators .append (validator )
7578
76- def _applyFilters (self , field_name : str , value : Any ) -> Any :
79+ def __applyFilters (self , field_name : str , value : Any ) -> Any :
7780 """
7881 Apply filters to the field value.
7982 """
8083
84+ if value is None :
85+ return value
86+
8187 for filter_ in self .global_filters :
8288 value = filter_ .apply (value )
8389
@@ -88,27 +94,38 @@ def _applyFilters(self, field_name: str, value: Any) -> Any:
8894
8995 return value
9096
91- def _validateField (self , field_name : str , value : Any ) -> None :
97+ def __validateField (self , field_name : str , field_info , value : Any ) -> None :
9298 """
9399 Validate the field value.
94100 """
95101
96- for validator in self . global_validators :
97- validator . validate ( value )
102+ if value is None :
103+ return
98104
99- field = self .fields .get (field_name )
105+ try :
106+ for validator in self .global_validators :
107+ validator .validate (value )
108+
109+ field = self .fields .get (field_name )
100110
101- for validator in field ["validators" ]:
102- validator .validate (value )
111+ for validator in field ["validators" ]:
112+ validator .validate (value )
113+ except ValidationError :
114+ if field_info .get ("fallback" ) is None :
115+ raise
103116
104- def _callExternalApi (
105- self , config : ExternalApiConfig , validated_data : dict
117+ return field_info .get ("fallback" )
118+
119+ def __callExternalApi (
120+ self , field_info , validated_data : dict
106121 ) -> Optional [Any ]:
107122 """
108123 Führt den API-Aufruf durch und gibt den Wert zurück,
109124 der im Antwortkörper zu finden ist.
110125 """
111126
127+ config : ExternalApiConfig = field_info .get ("external_api" )
128+
112129 requestData = {
113130 "headers" : {},
114131 "params" : {},
@@ -132,21 +149,30 @@ def _callExternalApi(
132149 )
133150 requestData ["method" ] = config .method
134151
135- response = requests .request (** requestData )
152+ try :
153+ response = requests .request (** requestData )
136154
137- if response .status_code != 200 :
138- raise ValidationError (
139- f"External API call failed with "
140- f"status code { response .status_code } "
141- )
155+ if response .status_code != 200 :
156+ raise ValidationError (
157+ f"External API call failed with "
158+ f"status code { response .status_code } "
159+ )
160+
161+ result = response .json ()
142162
143- result = response .json ()
163+ data_key = config .data_key
164+ if data_key :
165+ return result .get (data_key )
144166
145- data_key = config .data_key
146- if data_key :
147- return result .get (data_key )
167+ return result
168+ except Exception :
169+ if field_info and field_info .get ("fallback" ) is None :
170+ raise ValidationError (
171+ f"External API call failed for field "
172+ f"'{ config .data_key } '."
173+ )
148174
149- return result
175+ return field_info . get ( "fallback" )
150176
151177 @staticmethod
152178 def __replacePlaceholders (value : str , validated_data : dict ) -> str :
@@ -175,6 +201,34 @@ def __replacePlaceholdersInParams(
175201 for key , value in params .items ()
176202 }
177203
204+ @staticmethod
205+ def __checkForRequired (
206+ field_name : str , field_info : dict , value : Any
207+ ) -> Any :
208+ """
209+ Determine the value of the field, considering the required and fallback attributes.
210+
211+ If the field is not required and no value is provided, the default value is returned.
212+ If the field is required and no value is provided, the fallback value is returned.
213+ If no of the above conditions are met, a ValidationError is raised.
214+ """
215+
216+ if value is not None :
217+ return value
218+
219+ if not field_info .get ("required" ):
220+ return field_info .get ("default" )
221+
222+ if field_info .get ("fallback" ) is not None :
223+ return field_info .get ("fallback" )
224+
225+ raise ValidationError (f"Field '{ field_name } ' is required." )
226+
227+ def __checkConditions (self , validated_data : dict ) -> None :
228+ for condition in self .conditions :
229+ if not condition .check (validated_data ):
230+ raise ValidationError (f"Condition '{ condition } ' not met." )
231+
178232 def validateData (
179233 self , data : Dict [str , Any ], kwargs : Dict [str , Any ] = None
180234 ) -> Dict [str , Any ]:
@@ -192,71 +246,20 @@ def validateData(
192246 for field_name , field_info in self .fields .items ():
193247 value = combined_data .get (field_name )
194248
195- # Apply filters
196- value = self ._applyFilters (field_name , value )
197-
198- # Check for required field
199- if value is None :
200- if (
201- field_info .get ("required" )
202- and field_info .get ("external_api" ) is None
203- ):
204- if field_info .get ("fallback" ) is None :
205- raise ValidationError (
206- f"Field '{ field_name } ' is required."
207- )
249+ value = self .__applyFilters (field_name , value )
208250
209- value = field_info .get ("fallback" )
210-
211- if field_info .get ("default" ) is not None :
212- value = field_info .get ("default" )
251+ value = (
252+ self .__validateField (field_name , field_info , value ) or value
253+ )
213254
214- # Validate field
215- if value is not None :
216- try :
217- self ._validateField (field_name , value )
218- except ValidationError :
219- if field_info .get ("fallback" ) is not None :
220- value = field_info .get ("fallback" )
221- else :
222- raise
223-
224- # External API call
225255 if field_info .get ("external_api" ):
226- external_api_config = field_info .get ("external_api" )
227-
228- try :
229- value = self ._callExternalApi (
230- external_api_config , validated_data
231- )
232-
233- except Exception :
234- if field_info .get ("fallback" ) is None :
235- raise ValidationError (
236- f"External API call failed for field "
237- f"'{ field_name } '."
238- )
239-
240- value = field_info .get ("fallback" )
241-
242- if value is None :
243- if field_info .get ("required" ):
244- if field_info .get ("fallback" ) is None :
245- raise ValidationError (
246- f"Field '{ field_name } ' is required."
247- )
256+ value = self .__callExternalApi (field_info , validated_data )
248257
249- value = field_info .get ("fallback" )
250-
251- if field_info .get ("default" ) is not None :
252- value = field_info .get ("default" )
258+ value = self .__checkForRequired (field_name , field_info , value )
253259
254260 validated_data [field_name ] = value
255261
256- # Check conditions
257- for condition in self .conditions :
258- if not condition .check (validated_data ):
259- raise ValidationError (f"Condition '{ condition } ' not met." )
262+ self .__checkConditions (validated_data )
260263
261264 return validated_data
262265
0 commit comments