|
193 | 193 | import inspect |
194 | 194 | import sys |
195 | 195 | from collections import namedtuple, OrderedDict |
| 196 | +from json import JSONDecodeError |
196 | 197 | from types import MemberDescriptorType |
197 | 198 | from typing import Dict, Optional, NamedTuple, Union, Type, List, Generator, Iterable, TypeVar |
198 | 199 | from privex.helpers.types import T, K |
@@ -1252,12 +1253,20 @@ def _dc_dict_config(self) -> Union[_DictConfig, DictObject]: |
1252 | 1253 | DictConfig = copy_class(_DictConfig, name='DictConfig', quiet=True) |
1253 | 1254 |
|
1254 | 1255 | def __iter__(self): |
| 1256 | + cls_name = self.__class__.__name__ |
1255 | 1257 | # The raw_data attribute isn't required, and isn't guaranteed to have been set on a dataclass, so |
1256 | 1258 | # we fallback to a blank DictObject if it's not found. |
1257 | 1259 | dict_rd = DictObject() |
1258 | 1260 | if hasattr(self, 'raw_data'): |
1259 | 1261 | dict_rd = dict(self.raw_data) |
1260 | | - dict_dc = dataclasses.asdict(self, dict_factory=dict) |
| 1262 | + |
| 1263 | + # dataclasses.asdict can sometimes freak out when a dataclass contains un-serializable objects such as arbitrary |
| 1264 | + # class instances (which may even be excluded already in DictConfig. In such a case, we can fallback to __dict__ :) |
| 1265 | + try: |
| 1266 | + dict_dc = dataclasses.asdict(self, dict_factory=dict) |
| 1267 | + except (TypeError, ValueError, JSONDecodeError) as e: |
| 1268 | + log.warning("Dictifying %s using dataclasses.asdict failed (%s %s)... falling back to __dict__", cls_name, type(e), str(e)) |
| 1269 | + dict_dc = dict(self.__dict__) |
1261 | 1270 |
|
1262 | 1271 | from privex.helpers import empty |
1263 | 1272 | dconf = self._dc_dict_config |
|
0 commit comments