(obj, dict_factory)
| 1498 | |
| 1499 | |
| 1500 | def _asdict_inner(obj, dict_factory): |
| 1501 | obj_type = type(obj) |
| 1502 | if obj_type in _ATOMIC_TYPES: |
| 1503 | return obj |
| 1504 | elif hasattr(obj_type, _FIELDS): |
| 1505 | # dataclass instance: fast path for the common case |
| 1506 | if dict_factory is dict: |
| 1507 | return { |
| 1508 | f.name: _asdict_inner(getattr(obj, f.name), dict) |
| 1509 | for f in fields(obj) |
| 1510 | } |
| 1511 | else: |
| 1512 | return dict_factory([ |
| 1513 | (f.name, _asdict_inner(getattr(obj, f.name), dict_factory)) |
| 1514 | for f in fields(obj) |
| 1515 | ]) |
| 1516 | # handle the builtin types first for speed; subclasses handled below |
| 1517 | elif obj_type is list: |
| 1518 | return [_asdict_inner(v, dict_factory) for v in obj] |
| 1519 | elif obj_type is dict: |
| 1520 | return { |
| 1521 | _asdict_inner(k, dict_factory): _asdict_inner(v, dict_factory) |
| 1522 | for k, v in obj.items() |
| 1523 | } |
| 1524 | elif obj_type is tuple: |
| 1525 | return tuple([_asdict_inner(v, dict_factory) for v in obj]) |
| 1526 | elif issubclass(obj_type, tuple): |
| 1527 | if hasattr(obj, '_fields'): |
| 1528 | # obj is a namedtuple. Recurse into it, but the returned |
| 1529 | # object is another namedtuple of the same type. This is |
| 1530 | # similar to how other list- or tuple-derived classes are |
| 1531 | # treated (see below), but we just need to create them |
| 1532 | # differently because a namedtuple's __init__ needs to be |
| 1533 | # called differently (see bpo-34363). |
| 1534 | |
| 1535 | # I'm not using namedtuple's _asdict() |
| 1536 | # method, because: |
| 1537 | # - it does not recurse in to the namedtuple fields and |
| 1538 | # convert them to dicts (using dict_factory). |
| 1539 | # - I don't actually want to return a dict here. The main |
| 1540 | # use case here is json.dumps, and it handles converting |
| 1541 | # namedtuples to lists. Admittedly we're losing some |
| 1542 | # information here when we produce a json list instead of a |
| 1543 | # dict. Note that if we returned dicts here instead of |
| 1544 | # namedtuples, we could no longer call asdict() on a data |
| 1545 | # structure where a namedtuple was used as a dict key. |
| 1546 | return obj_type(*[_asdict_inner(v, dict_factory) for v in obj]) |
| 1547 | else: |
| 1548 | return obj_type(_asdict_inner(v, dict_factory) for v in obj) |
| 1549 | elif issubclass(obj_type, dict): |
| 1550 | if hasattr(obj_type, 'default_factory'): |
| 1551 | # obj is a defaultdict, which has a different constructor from |
| 1552 | # dict as it requires the default_factory as its first arg. |
| 1553 | result = obj_type(obj.default_factory) |
| 1554 | for k, v in obj.items(): |
| 1555 | result[_asdict_inner(k, dict_factory)] = _asdict_inner(v, dict_factory) |
| 1556 | return result |
| 1557 | return obj_type((_asdict_inner(k, dict_factory), |
no test coverage detected
searching dependent graphs…