py.lib
py.lib/dataclass_utils.py
* С разбегу влетел в type hinting, пришлось обкладывать костылями. И этот процесс судя по всему длительный, и место больное будет долго...
1.1 --- a/dataclass_utils.py Sat Aug 13 13:21:35 2022 +0300 1.2 +++ b/dataclass_utils.py Sat Aug 13 20:06:47 2022 +0300 1.3 @@ -20,6 +20,52 @@ 1.4 return getattr(obj, key) 1.5 1.6 1.7 +def difficult_type_recognizer(type_obj, value): 1.8 + """\ 1.9 + Магия борющаяся с костылями type hinting 1.10 + """ 1.11 + if type(type_obj).__name__ == '_GenericAlias': 1.12 + if ( 1.13 + hasattr(type_obj, '__args__') 1.14 + and type(type_obj.__args__) == tuple 1.15 + and type_obj.__args__ 1.16 + ): 1.17 + if type_obj.__name__ == 'List': 1.18 + return list(map(type_obj.__args__[0], value)) 1.19 + 1.20 + elif type_obj.__name__ == 'Tuple': 1.21 + return tuple(map(type_obj.__args__[0], value)) 1.22 + 1.23 + else: 1.24 + raise ValueError('Неизвестный тип') 1.25 + 1.26 + else: 1.27 + ValueError('Неизвестный тип') 1.28 + 1.29 + elif type(type_obj).__name__ == '_UnionGenericAlias': 1.30 + if type_obj.__name__ not in ('Union', 'Optional'): 1.31 + raise TypeError(f'Неизвестный подтип _UnionGenericAlias: {type_obj.__name__}') 1.32 + 1.33 + if not ( 1.34 + hasattr(type_obj, '__args__') 1.35 + and type(type_obj.__args__) == tuple 1.36 + and type_obj.__args__ 1.37 + ): 1.38 + raise TypeError(f'Не ясно как работать с типом не вижу аргументов: {type_obj.__name__}') 1.39 + 1.40 + for _t in type_obj.__args__: 1.41 + if _t.__name__ == 'NoneType': 1.42 + continue 1.43 + 1.44 + try: 1.45 + return _t(value) 1.46 + 1.47 + except (TypeError, ValueError): 1.48 + continue 1.49 + 1.50 + raise ValueError('Не удалось привести значение к типу') 1.51 + 1.52 + 1.53 def dataobj_extract(obj: Union[object, Dict[str, Any]], dataclass_type: type) -> dataclass: 1.54 """\ 1.55 Извлекает объект данных из предоставленного объекта, путём получения из него 1.56 @@ -47,9 +93,13 @@ 1.57 val = fld.type(val) 1.58 1.59 except (ValueError, TypeError) as e: 1.60 - raise ValueError(f'Аттрибут {fld.name} не может быть получен из значения "{val}"' 1.61 - f' с типом {type(val).__name__} поскольку не может быть преобразован в' 1.62 - f' тип {fld.type.__name__}, заданный в классе данных: {e}') 1.63 + try: 1.64 + val = difficult_type_recognizer(fld.type, val) 1.65 + 1.66 + except (ValueError, TypeError): 1.67 + raise ValueError(f'Аттрибут {fld.name} не может быть получен из значения "{val}"' 1.68 + f' с типом {type(val).__name__} поскольку не может быть преобразован в' 1.69 + f' тип {fld.type.__name__}, заданный в классе данных: {e}') 1.70 1.71 params[fld.name] = val 1.72