py.lib

Yohn Y. 2022-08-05 Child:57f63bf31fd8

31:4186c3b229fa Go to Latest

py.lib/dataclass_utils.py

+ Модуль работы с датаклассами и их наполнения из ORM + Утилиты Bottle + Утилиты JWT + Помошник в парсинге конфигурационных файлов

History
1 # coding: utf-8
3 from dataclasses import fields, dataclass, is_dataclass
4 from typing import Union, Dict, Any
7 def _dict_has(obj: Dict[str, Any], key: str) -> bool:
8 return key in obj
11 def _dict_get(obj: Dict[str, Any], key: str) -> Any:
12 return obj[key]
15 def _obj_has(obj: object, key: str) -> bool:
16 return hasattr(obj, key)
19 def _obj_get(obj: object, key: str) -> Any:
20 return getattr(obj, key)
23 def dataobj_extract(obj: Union[object, Dict[str, Any]], dataclass_type: type) -> dataclass:
24 """\
25 Извлекает объект данных из предоставленного объекта, путём получения из него
26 указанных в классе данных аттрибутов и поиска их в данном объекте.
27 """
29 params = {}
31 if isinstance(obj, dict):
32 _has = _dict_has
33 _get = _dict_get
35 else:
36 _has = _obj_has
37 _get = _obj_get
39 if not is_dataclass(dataclass_type):
40 raise ValueError(f'Не относится к классам данных: {dataclass_type.__name__}')
42 for fld in fields(dataclass_type):
43 if _has(obj, fld.name):
44 val = _get(obj, fld.name)
45 if val is not None and not isinstance(val, fld.type):
46 try:
47 val = fld.type(val)
49 except (ValueError, TypeError) as e:
50 raise ValueError(f'Аттрибут {fld.name} не может быть получен из значения "{val}"'
51 f' с типом {type(val).__name__} поскольку не может быть преобразован в'
52 f' тип {fld.type.__name__}, заданный в классе данных: {e}')
54 params[fld.name] = val
56 try:
57 res = dataclass_type(**params)
59 except (ValueError, TypeError) as e:
60 _params = ', '.join(map(lambda x: f'{x[0]}="{x[1]}"', params.items()))
61 raise ValueError(f'Не удалось получить объект'
62 f' класс {dataclass_type.__name__}'
63 f' из параметров: {_params}'
64 f' ошибка: {e}')
66 return res