py.lib
2022-08-27
Parent:366c9fe26d76
py.lib/type_utils/dataclass_utils.py
+ Возможность удалить cookie при формировании штатного ответа.
| awgur@31 | 1 # coding: utf-8 |
| awgur@38 | 2 """\ |
| awgur@38 | 3 Наполнение заданного класса данных из предоставленного словаря или объекта. |
| awgur@38 | 4 |
| awgur@38 | 5 НЕ РАБОТАЕТ БЕЗ ОСТАЛЬНОГО МОДУЛЯ type_utils |
| awgur@38 | 6 """ |
| awgur@31 | 7 |
| awgur@40 | 8 from dataclasses import fields, is_dataclass |
| awgur@40 | 9 from typing import Union, Dict, Any |
| awgur@38 | 10 from .type_descriptor import get_type_describer |
| awgur@31 | 11 |
| awgur@31 | 12 |
| awgur@31 | 13 def _dict_has(obj: Dict[str, Any], key: str) -> bool: |
| awgur@31 | 14 return key in obj |
| awgur@31 | 15 |
| awgur@31 | 16 |
| awgur@31 | 17 def _dict_get(obj: Dict[str, Any], key: str) -> Any: |
| awgur@31 | 18 return obj[key] |
| awgur@31 | 19 |
| awgur@31 | 20 |
| awgur@31 | 21 def _obj_has(obj: object, key: str) -> bool: |
| awgur@31 | 22 return hasattr(obj, key) |
| awgur@31 | 23 |
| awgur@31 | 24 |
| awgur@31 | 25 def _obj_get(obj: object, key: str) -> Any: |
| awgur@31 | 26 return getattr(obj, key) |
| awgur@31 | 27 |
| awgur@31 | 28 |
| awgur@38 | 29 def dataobj_extract(obj: Union[object, Dict[str, Any]], dataclass_type: type, type_convert: bool = False) -> object: |
| awgur@31 | 30 """\ |
| awgur@31 | 31 Извлекает объект данных из предоставленного объекта, путём получения из него |
| awgur@31 | 32 указанных в классе данных аттрибутов и поиска их в данном объекте. |
| awgur@38 | 33 :param obj: Объект, из которого берутся данные для класса данных |
| awgur@38 | 34 :param dataclass_type: Класс данных, наполняемый из ``obj`` |
| awgur@38 | 35 :param type_convert: Признак конвертирования данных. Если задан, выполняет попытку сконвертировать имеющееся |
| awgur@38 | 36 в параметре значение в тип, указанных в классе данных. Чудес не бывает, и процесс может |
| awgur@38 | 37 ошибиться особенно с Union |
| awgur@31 | 38 """ |
| awgur@31 | 39 |
| awgur@31 | 40 params = {} |
| awgur@31 | 41 |
| awgur@31 | 42 if isinstance(obj, dict): |
| awgur@31 | 43 _has = _dict_has |
| awgur@31 | 44 _get = _dict_get |
| awgur@31 | 45 |
| awgur@31 | 46 else: |
| awgur@31 | 47 _has = _obj_has |
| awgur@31 | 48 _get = _obj_get |
| awgur@31 | 49 |
| awgur@31 | 50 if not is_dataclass(dataclass_type): |
| awgur@31 | 51 raise ValueError(f'Не относится к классам данных: {dataclass_type.__name__}') |
| awgur@31 | 52 |
| awgur@31 | 53 for fld in fields(dataclass_type): |
| awgur@31 | 54 if _has(obj, fld.name): |
| awgur@31 | 55 val = _get(obj, fld.name) |
| awgur@36 | 56 type_desc = get_type_describer(fld.type) |
| awgur@37 | 57 if val is not None: |
| awgur@38 | 58 if not type_desc.check(val): |
| awgur@38 | 59 if not type_convert: |
| awgur@38 | 60 raise ValueError(f'Аттрибут {fld.name} не может быть получен из значения "{val}"' |
| awgur@38 | 61 f' с типом {type(val).__name__} поскольку не может быть преобразован в' |
| awgur@38 | 62 f' тип {type_desc}, заданный в классе данных: {type_desc.event_description}') |
| awgur@31 | 63 |
| awgur@38 | 64 try: |
| awgur@38 | 65 val = type_desc(val) |
| awgur@38 | 66 |
| awgur@38 | 67 except (ValueError, TypeError) as e: |
| awgur@38 | 68 raise ValueError(f'Аттрибут {fld.name} не может быть получен из значения "{val}"' |
| awgur@38 | 69 f' с типом {type(val).__name__} поскольку не может быть преобразован в' |
| awgur@38 | 70 f' тип {type_desc}, заданный в классе данных: {e}') |
| awgur@38 | 71 |
| awgur@38 | 72 elif not (type_desc.is_nullable or type_convert): |
| awgur@38 | 73 raise ValueError(f'Передан "None" в поле "{fld.name}", хотя он не ожидался') |
| awgur@31 | 74 |
| awgur@31 | 75 params[fld.name] = val |
| awgur@31 | 76 |
| awgur@31 | 77 try: |
| awgur@31 | 78 res = dataclass_type(**params) |
| awgur@31 | 79 |
| awgur@31 | 80 except (ValueError, TypeError) as e: |
| awgur@31 | 81 _params = ', '.join(map(lambda x: f'{x[0]}="{x[1]}"', params.items())) |
| awgur@31 | 82 raise ValueError(f'Не удалось получить объект' |
| awgur@31 | 83 f' класс {dataclass_type.__name__}' |
| awgur@31 | 84 f' из параметров: {_params}' |
| awgur@31 | 85 f' ошибка: {e}') |
| awgur@31 | 86 |
| awgur@31 | 87 return res |
| awgur@35 | 88 |
| awgur@35 | 89 |