Source code for dachs.additemstoattrs

#!/usr/bin/env python
# coding: utf-8

"""
An add=on that will add an items() method to an attrs-created dataclass.
Useful for iterating over keys, for example for storing in an HDF5 file.
"""

__author__ = "Brian R. Pauw"
__contact__ = "brian@stack.nl"
__license__ = "GPLv3+"
__date__ = "2022/11/07"
__status__ = "beta"

from collections.abc import Iterable
from typing import Any, NoReturn

from attrs import fields

# Mixin class for making a dict-like object out of an attrs class
# from: https://github.com/python-attrs/attrs/issues/879


[docs] class addItemsToAttrs: # used to be MutableMappingMixin(MutableMapping) """Mixin class to make attrs classes quack like a dictionary (well, technically a mutable mapping). ONLY use this with attrs classes. Provides keys(), values(), and items() methods in order to be dict-like in addition to MutableMapping-like. Also provides pop(), but it just raises a TypeError :) """ __slots__ = () # May as well save on memory? _storeKeys = list() _loadKeys = list() def __iter__(self) -> Iterable: for ifield in fields(self.__class__): yield ifield.name def __len__(self) -> int: return len(fields(self.__class__)) def __getitem__(self, k: str) -> Any: """ Adapted from: https://github.com/python-attrs/attrs/issues/487#issuecomment-660727537 """ try: return self.__getattribute__(k) except AttributeError as exc: raise KeyError(str(exc)) from None def __delitem__(self, v: str) -> NoReturn: raise TypeError("Cannot delete fields for attrs classes.") def __setitem__(self, k: str, v: Any) -> None: self.__setattr__(k, v) def pop(self, key, default=None) -> NoReturn: raise TypeError("Cannot pop fields from attrs classes.") def keys(self) -> Iterable: return self.__iter__() def values(self) -> Iterable: for key in self.__iter__(): yield self.__getattribute__(key) def items(self) -> Iterable: for key in self.__iter__(): yield key, self.__getattribute__(key) def __attrs_post_init__(self): # auto-generate the store and load key lists: self._storeKeys = [i for i in self.keys() if (i not in self._excludeKeys and not i.startswith("_"))] self._loadKeys = [i for i in self.keys() if (i not in self._excludeKeys and not i.startswith("_"))]