Source code for pyutils.dataclass_utils

#!/usr/bin/env python3

"""Utilities for dealing with Dataclasses.  A non-official type hint and some
friendly wrappers around conversion to/from Dicts."""

from __future__ import annotations

import dataclasses
from typing import Any, Dict, Protocol


[docs] class Dataclass(Protocol): """Dataclass isn't really a first class type and therefore there is no offical type hint for Dataclasses in Python (yet). If you need one, here's a suitable stand in. Example usage:: def f(d: Dataclass) -> Any: pass def g(d: Dict[str, Any]) -> Dataclass: pass """ __dataclass_fields__: Dict
[docs] def dataclass_from_dict(dataclass: type, d: Dict[str, Any]) -> Dataclass: """Given a Dataclass type and a dict, return a populated instance. Args: dataclass: the Class type to return an instance of d: the dict to be used to populate the new instance Returns: A constructed and populated dataclass instance. >>> from dataclasses import dataclass >>> from datetime import date >>> @dataclass ... class Record: ... name: str ... phone: str ... address: str ... age: int ... member_since: date ... >>> d = { ... 'name': 'John Smith', ... 'phone': '555-1234', ... 'address': '994 Main St.', ... 'age': 26, ... 'member_since': date(2006, 5, 14), ... } >>> dataclass_from_dict(Record, d) Record(name='John Smith', phone='555-1234', address='994 Main St.', age=26, member_since=datetime.date(2006, 5, 14)) """ fields = {f.name for f in dataclasses.fields(dataclass) if f.init} filtered_args = {k: v for k, v in d.items() if k in fields} return dataclass(**filtered_args)
[docs] def dataclass_to_dict(dataclass: Dataclass) -> Dict[str, Any]: """ Returns: A dict-representation of a valid dataclass. >>> from dataclasses import dataclass >>> from datetime import date >>> @dataclass ... class Record: ... name: str ... phone: str ... address: str ... age: int ... member_since: date ... >>> r = Record(name='Jane Doe', phone='555-1232', address='998 Main St.', age=23, member_since=date(2008, 3, 1)) >>> dataclass_to_dict(r) {'name': 'Jane Doe', 'phone': '555-1232', 'address': '998 Main St.', 'age': 23, 'member_since': datetime.date(2008, 3, 1)} """ assert dataclasses.is_dataclass(dataclass) return dataclasses.asdict(dataclass)
if __name__ == '__main__': import doctest doctest.testmod()