9
9
import pathlib
10
10
import platform
11
11
import typing
12
+ import sys
12
13
from dataclasses import fields , is_dataclass
13
14
from datetime import datetime , timedelta
14
15
from enum import Enum , IntEnum , EnumMeta
@@ -58,7 +59,10 @@ def _get_type_vars_map(cls: Type, type_map=None):
58
59
generic_type_args = get_args (cls )
59
60
i = 0
60
61
for t in generic_def .__parameters__ :
61
- type_map [t ] = generic_type_args [i ]
62
+ k = t
63
+ if type (k ) == TypeVar :
64
+ k = k .__name__
65
+ type_map [k ] = generic_type_args [i ]
62
66
i += 1
63
67
return type_map
64
68
@@ -232,9 +236,11 @@ def _resolve_forwardref(cls: Type, orig: Type = None):
232
236
return globals ()[type_name ]
233
237
234
238
235
- def unwrap (cls : Type ):
239
+ def unwrap (cls : Type , module : str ):
236
240
if type (cls ) == ForwardRef :
237
241
cls = _resolve_forwardref (cls )
242
+ if isinstance (cls , str ):
243
+ cls = eval (cls , {}, vars (sys .modules [module ]))
238
244
if is_optional (cls ):
239
245
return generic_arg (cls )
240
246
return cls
@@ -282,16 +288,20 @@ def enum_get(cls: Union[Enum, Type], key: Union[str, int]):
282
288
raise TypeError (f"{ key } is not a member of { nameof (Enum )} " )
283
289
284
290
285
- def _resolve_type (cls : Type , substitute_types : Dict [Type , type ]):
291
+ def _resolve_type (cls : Type , substitute_types : Dict [Type , type ] ):
292
+ if type (cls ) == TypeVar :
293
+ # TypeVar('T') == TypeVar('T') is false,
294
+ # I think this should work
295
+ cls = cls .__name__
286
296
if substitute_types is None :
287
297
return cls
288
298
return substitute_types [cls ] if cls in substitute_types else cls
289
299
290
300
291
- def convert (into : Type , obj : Any , substitute_types : Dict [Type , type ] = None ):
301
+ def convert (into : Type , obj : Any , substitute_types : Dict [Type , type ] = None , module = None ):
292
302
if obj is None :
293
303
return None
294
- into = unwrap (into )
304
+ into = unwrap (into , module )
295
305
into = _resolve_type (into , substitute_types )
296
306
if Log .debug_enabled ():
297
307
Log .debug (f"convert({ into } , { substitute_types } , { obj } )" )
@@ -310,14 +320,14 @@ def convert(into: Type, obj: Any, substitute_types: Dict[Type, type] = None):
310
320
for f in fields (into ):
311
321
val = dict_get (f .name , obj )
312
322
# print(f"to[{f.name}] = convert({f.type}, {val}, {substitute_types})")
313
- to [f .name ] = convert (f .type , val , substitute_types )
323
+ to [f .name ] = convert (f .type , val , substitute_types , into . __module__ )
314
324
# print(f"to[{f.name}] = {to[f.name]}")
315
325
return into (** to )
316
326
elif is_list (into ):
317
327
el_type = _resolve_type (generic_arg (into ), substitute_types )
318
328
to = []
319
329
for item in obj :
320
- to .append (convert (el_type , item , substitute_types ))
330
+ to .append (convert (el_type , item , substitute_types , into . __module__ ))
321
331
return to
322
332
elif is_dict (into ):
323
333
key_type , val_type = generic_args (into )
@@ -327,8 +337,8 @@ def convert(into: Type, obj: Any, substitute_types: Dict[Type, type] = None):
327
337
if not hasattr (obj , 'items' ):
328
338
Log .warn (f"dict { obj } ({ type (type )} ) does not have items()" )
329
339
for key , val in obj .items ():
330
- to_key = convert (key_type , key , substitute_types )
331
- to_val = convert (val_type , val , substitute_types )
340
+ to_key = convert (key_type , key , substitute_types , into . __module__ )
341
+ to_val = convert (val_type , val , substitute_types , into . __module__ )
332
342
to [to_key ] = to_val
333
343
return to
334
344
else :
0 commit comments