py.lib
33:57f63bf31fd8 Browse Files
* С разбегу влетел в type hinting, пришлось обкладывать костылями. И этот процесс судя по всему длительный, и место больное будет долго...
config_parse_helper.py dataclass_utils.py
1.1 --- a/config_parse_helper.py Sat Aug 13 13:21:35 2022 +0300 1.2 +++ b/config_parse_helper.py Sat Aug 13 20:06:47 2022 +0300 1.3 @@ -18,6 +18,52 @@ 1.4 """ 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 class CPHSectionBase: 1.54 """\ 1.55 Базовый класс обработки секции конфигурационного файла 1.56 @@ -68,9 +114,13 @@ 1.57 res = fld.type(param_val) 1.58 1.59 except (ValueError, TypeError) as e: 1.60 - raise ConfigParseHelperError(f'При приведении параметра к ' 1.61 - f'заданному типу произошла ошибка: ' 1.62 - f'значение="{param_val}" ошибка="{e}"') 1.63 + try: 1.64 + res = difficult_type_recognizer(fld.type, param_val) 1.65 + 1.66 + except (ValueError, TypeError): 1.67 + raise ConfigParseHelperError(f'При приведении параметра к ' 1.68 + f'заданному типу произошла ошибка: ' 1.69 + f'значение="{param_val}" ошибка="{e}"') 1.70 1.71 else: 1.72 if fld.default is not MISSING:
2.1 --- a/dataclass_utils.py Sat Aug 13 13:21:35 2022 +0300 2.2 +++ b/dataclass_utils.py Sat Aug 13 20:06:47 2022 +0300 2.3 @@ -20,6 +20,52 @@ 2.4 return getattr(obj, key) 2.5 2.6 2.7 +def difficult_type_recognizer(type_obj, value): 2.8 + """\ 2.9 + Магия борющаяся с костылями type hinting 2.10 + """ 2.11 + if type(type_obj).__name__ == '_GenericAlias': 2.12 + if ( 2.13 + hasattr(type_obj, '__args__') 2.14 + and type(type_obj.__args__) == tuple 2.15 + and type_obj.__args__ 2.16 + ): 2.17 + if type_obj.__name__ == 'List': 2.18 + return list(map(type_obj.__args__[0], value)) 2.19 + 2.20 + elif type_obj.__name__ == 'Tuple': 2.21 + return tuple(map(type_obj.__args__[0], value)) 2.22 + 2.23 + else: 2.24 + raise ValueError('Неизвестный тип') 2.25 + 2.26 + else: 2.27 + ValueError('Неизвестный тип') 2.28 + 2.29 + elif type(type_obj).__name__ == '_UnionGenericAlias': 2.30 + if type_obj.__name__ not in ('Union', 'Optional'): 2.31 + raise TypeError(f'Неизвестный подтип _UnionGenericAlias: {type_obj.__name__}') 2.32 + 2.33 + if not ( 2.34 + hasattr(type_obj, '__args__') 2.35 + and type(type_obj.__args__) == tuple 2.36 + and type_obj.__args__ 2.37 + ): 2.38 + raise TypeError(f'Не ясно как работать с типом не вижу аргументов: {type_obj.__name__}') 2.39 + 2.40 + for _t in type_obj.__args__: 2.41 + if _t.__name__ == 'NoneType': 2.42 + continue 2.43 + 2.44 + try: 2.45 + return _t(value) 2.46 + 2.47 + except (TypeError, ValueError): 2.48 + continue 2.49 + 2.50 + raise ValueError('Не удалось привести значение к типу') 2.51 + 2.52 + 2.53 def dataobj_extract(obj: Union[object, Dict[str, Any]], dataclass_type: type) -> dataclass: 2.54 """\ 2.55 Извлекает объект данных из предоставленного объекта, путём получения из него 2.56 @@ -47,9 +93,13 @@ 2.57 val = fld.type(val) 2.58 2.59 except (ValueError, TypeError) as e: 2.60 - raise ValueError(f'Аттрибут {fld.name} не может быть получен из значения "{val}"' 2.61 - f' с типом {type(val).__name__} поскольку не может быть преобразован в' 2.62 - f' тип {fld.type.__name__}, заданный в классе данных: {e}') 2.63 + try: 2.64 + val = difficult_type_recognizer(fld.type, val) 2.65 + 2.66 + except (ValueError, TypeError): 2.67 + raise ValueError(f'Аттрибут {fld.name} не может быть получен из значения "{val}"' 2.68 + f' с типом {type(val).__name__} поскольку не может быть преобразован в' 2.69 + f' тип {fld.type.__name__}, заданный в классе данных: {e}') 2.70 2.71 params[fld.name] = val 2.72