11import inspect
22import json
3- from typing import Any , Optional
3+ from typing import Any , Optional , Union
44
55import pydantic
66from aiohttp import web
@@ -32,8 +32,10 @@ def __init__(
3232 self .alias = alias
3333 self .multiple = multiple
3434 self .description = description
35+ self .type_initialized = False
36+ self .type_cache : "Union[pydantic.TypeAdapter[Any], None]" = None
3537
36- def __call__ ( # noqa: C901, WPS210
38+ def __call__ ( # noqa: C901
3739 self ,
3840 param_info : ParamInfo = Depends (),
3941 request : web .Request = Depends (),
@@ -52,23 +54,26 @@ def __call__( # noqa: C901, WPS210
5254 if self .default is not ...:
5355 default_value = self .default
5456
57+ if not self .type_initialized :
58+ if (
59+ param_info .definition
60+ and param_info .definition .annotation != inspect .Parameter .empty
61+ ):
62+ self .type_cache = pydantic .TypeAdapter (param_info .definition .annotation )
63+ else :
64+ self .type_cache = None
65+ self .type_initialized = True
66+
5567 if self .multiple :
5668 value = request .headers .getall (header_name , default_value )
5769 else :
5870 value = request .headers .getone (header_name , default_value )
5971
60- definition = None
61- if (
62- param_info .definition
63- and param_info .definition .annotation != inspect .Parameter .empty
64- ):
65- definition = param_info .definition .annotation
66-
67- if definition is None :
72+ if self .type_cache is None :
6873 return value
6974
7075 try :
71- return pydantic . TypeAdapter ( definition ) .validate_python (value )
76+ return self . type_cache .validate_python (value )
7277 except pydantic .ValidationError as err :
7378 errors = err .errors (include_url = False )
7479 for error in errors :
@@ -91,6 +96,10 @@ class Json:
9196 and then converts it to type from your typehints.
9297 """
9398
99+ def __init__ (self ) -> None :
100+ self .type_initialized = False
101+ self .type_cache : "Union[pydantic.TypeAdapter[Any], None]" = None
102+
94103 async def __call__ ( # noqa: C901
95104 self ,
96105 param_info : ParamInfo = Depends (),
@@ -110,18 +119,21 @@ async def __call__( # noqa: C901
110119 except ValueError :
111120 body = None
112121
113- definition = None
114- if (
115- param_info .definition
116- and param_info .definition .annotation != inspect .Parameter .empty
117- ):
118- definition = param_info .definition .annotation
119-
120- if definition is None :
122+ if not self .type_initialized :
123+ if (
124+ param_info .definition
125+ and param_info .definition .annotation != inspect .Parameter .empty
126+ ):
127+ self .type_cache = pydantic .TypeAdapter (param_info .definition .annotation )
128+ else :
129+ self .type_cache = None
130+ self .type_initialized = True
131+
132+ if self .type_cache is None :
121133 return body
122134
123135 try :
124- return pydantic . TypeAdapter ( definition ) .validate_python (body )
136+ return self . type_cache .validate_python (body )
125137 except pydantic .ValidationError as err :
126138 errors = err .errors (include_url = False )
127139 for error in errors :
@@ -158,8 +170,10 @@ def __init__(
158170 self .alias = alias
159171 self .multiple = multiple
160172 self .description = description
173+ self .type_initialized = False
174+ self .type_cache : "Union[pydantic.TypeAdapter[Any], None]" = None
161175
162- def __call__ ( # noqa: C901, WPS210
176+ def __call__ ( # noqa: C901
163177 self ,
164178 param_info : ParamInfo = Depends (),
165179 request : web .Request = Depends (),
@@ -178,23 +192,26 @@ def __call__( # noqa: C901, WPS210
178192 if self .default is not ...:
179193 default_value = self .default
180194
195+ if not self .type_initialized :
196+ if (
197+ param_info .definition
198+ and param_info .definition .annotation != inspect .Parameter .empty
199+ ):
200+ self .type_cache = pydantic .TypeAdapter (param_info .definition .annotation )
201+ else :
202+ self .type_cache = None
203+ self .type_initialized = True
204+
181205 if self .multiple :
182206 value = request .query .getall (param_name , default_value )
183207 else :
184208 value = request .query .getone (param_name , default_value )
185209
186- definition = None
187- if (
188- param_info .definition
189- and param_info .definition .annotation != inspect .Parameter .empty
190- ):
191- definition = param_info .definition .annotation
192-
193- if definition is None :
210+ if self .type_cache is None :
194211 return value
195212
196213 try :
197- return pydantic . TypeAdapter ( definition ) .validate_python (value )
214+ return self . type_cache .validate_python (value )
198215 except pydantic .ValidationError as err :
199216 errors = err .errors (include_url = False )
200217 for error in errors :
@@ -219,7 +236,11 @@ class Form:
219236 You should provide schema with typehints.
220237 """
221238
222- async def __call__ (
239+ def __init__ (self ) -> None :
240+ self .type_initialized = False
241+ self .type_cache : "Union[pydantic.TypeAdapter[Any], None]" = None
242+
243+ async def __call__ ( # noqa: C901
223244 self ,
224245 param_info : ParamInfo = Depends (),
225246 request : web .Request = Depends (),
@@ -234,18 +255,22 @@ async def __call__(
234255 :return: parsed data.
235256 """
236257 form_data = await request .post ()
237- definition = None
238- if (
239- param_info .definition
240- and param_info .definition .annotation != inspect .Parameter .empty
241- ):
242- definition = param_info .definition .annotation
243-
244- if definition is None :
258+
259+ if not self .type_initialized :
260+ if (
261+ param_info .definition
262+ and param_info .definition .annotation != inspect .Parameter .empty
263+ ):
264+ self .type_cache = pydantic .TypeAdapter (param_info .definition .annotation )
265+ else :
266+ self .type_cache = None
267+ self .type_initialized = True
268+
269+ if self .type_cache is None :
245270 return form_data
246271
247272 try :
248- return pydantic . TypeAdapter ( definition ) .validate_python (form_data )
273+ return self . type_cache .validate_python (form_data )
249274 except pydantic .ValidationError as err :
250275 errors = err .errors (include_url = False )
251276 for error in errors :
@@ -276,8 +301,10 @@ def __init__(
276301 self .default = default
277302 self .alias = alias
278303 self .description = description
304+ self .type_initialized = False
305+ self .type_cache : "Union[pydantic.TypeAdapter[Any], None]" = None
279306
280- def __call__ (
307+ def __call__ ( # noqa: C901
281308 self ,
282309 param_info : ParamInfo = Depends (),
283310 request : web .Request = Depends (),
@@ -292,18 +319,22 @@ def __call__(
292319 :return: parsed data.
293320 """
294321 matched_data = request .match_info .get (self .alias or param_info .name )
295- definition = None
296- if (
297- param_info .definition
298- and param_info .definition .annotation != inspect .Parameter .empty
299- ):
300- definition = param_info .definition .annotation
301-
302- if definition is None :
322+
323+ if not self .type_initialized :
324+ if (
325+ param_info .definition
326+ and param_info .definition .annotation != inspect .Parameter .empty
327+ ):
328+ self .type_cache = pydantic .TypeAdapter (param_info .definition .annotation )
329+ else :
330+ self .type_cache = None
331+ self .type_initialized = True
332+
333+ if self .type_cache is None :
303334 return matched_data
304335
305336 try :
306- return pydantic . TypeAdapter ( definition ) .validate_python (matched_data )
337+ return self . type_cache .validate_python (matched_data )
307338 except pydantic .ValidationError as err :
308339 errors = err .errors (include_url = False )
309340 for error in errors :
0 commit comments