1
1
from __future__ import annotations
2
2
3
+ from collections .abc import Mapping
3
4
from dataclasses import _HAS_DEFAULT_FACTORY # type: ignore
4
5
from typing import (
5
6
Any ,
6
7
Literal ,
7
8
NamedTuple ,
8
9
Optional ,
9
- Tuple ,
10
10
Union ,
11
11
get_args ,
12
12
get_origin ,
13
13
)
14
- from collections .abc import Mapping
15
14
16
15
from sanic_ext .utils .typing import (
17
16
UnionType ,
@@ -54,9 +53,7 @@ class Hint(NamedTuple):
54
53
allowed : tuple [Hint , ...] # type: ignore
55
54
allow_missing : bool
56
55
57
- def validate (
58
- self , value , schema , allow_multiple = False , allow_coerce = False
59
- ):
56
+ def validate (self , value , schema , allow_multiple = False , allow_coerce = False ):
60
57
if not self .typed :
61
58
if self .model :
62
59
return check_data (
@@ -188,11 +185,16 @@ def check_data(model, data, schema, allow_multiple=False, allow_coerce=False):
188
185
189
186
if MSGSPEC and is_msgspec (model ):
190
187
try :
191
- return msgspec .from_builtins (
192
- hydration_values , model , str_values = True , str_keys = True
193
- )
194
- except msgspec .ValidationError as e :
195
- raise TypeError (e )
188
+ try :
189
+ return msgspec .to_builtins (hydration_values , str_keys = True )
190
+ except msgspec .ValidationError as e :
191
+ raise TypeError (e )
192
+ except AttributeError :
193
+ try :
194
+ return msgspec .convert (hydration_values , model , str_keys = True )
195
+ except msgspec .ValidationError as e :
196
+ raise TypeError (e )
197
+
196
198
else :
197
199
return model (** hydration_values )
198
200
@@ -213,18 +215,14 @@ def _check_types(value, literal, expected):
213
215
raise ValueError (f"Value '{ value } ' is not of type { expected } " )
214
216
215
217
216
- def _check_nullability (
217
- value , nullable , allowed , schema , allow_multiple , allow_coerce
218
- ):
218
+ def _check_nullability (value , nullable , allowed , schema , allow_multiple , allow_coerce ):
219
219
if not nullable and value is None :
220
220
raise ValueError ("Value cannot be None" )
221
221
if nullable and value is not None :
222
222
exc = None
223
223
for hint in allowed :
224
224
try :
225
- value = hint .validate (
226
- value , schema , allow_multiple , allow_coerce
227
- )
225
+ value = hint .validate (value , schema , allow_multiple , allow_coerce )
228
226
except ValueError as e :
229
227
exc = e
230
228
else :
@@ -234,9 +232,7 @@ def _check_nullability(
234
232
if len (allowed ) == 1 :
235
233
raise exc
236
234
else :
237
- options = ", " .join (
238
- [str (option .hint ) for option in allowed ]
239
- )
235
+ options = ", " .join ([str (option .hint ) for option in allowed ])
240
236
raise ValueError (
241
237
f"Value '{ value } ' must be one of { options } , or None"
242
238
)
@@ -258,9 +254,7 @@ def _check_list(value, allowed, hint, schema, allow_multiple, allow_coerce):
258
254
if isinstance (value , list ):
259
255
try :
260
256
return [
261
- _check_inclusion (
262
- item , allowed , schema , allow_multiple , allow_coerce
263
- )
257
+ _check_inclusion (item , allowed , schema , allow_multiple , allow_coerce )
264
258
for item in value
265
259
]
266
260
except (ValueError , TypeError ):
0 commit comments