py.lib

Yohn Y. 2022-08-13 Parent:4186c3b229fa Child:84b54a8a6d4c

33:57f63bf31fd8 Go to Latest

py.lib/dataclass_utils.py

* С разбегу влетел в type hinting, пришлось обкладывать костылями. И этот процесс судя по всему длительный, и место больное будет долго...

History
     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