Source code for utilipy.utils.collections._ObjDict

# -*- coding: utf-8 -*-

# ----------------------------------------------------------------------------
#
# TITLE   : ObjDict
# PROJECT : utilipy
#
# ----------------------------------------------------------------------------

# Docstring and Metadata
"""initialization file for util."""

__author__ = "Nathaniel Starkman"


##############################################################################
# IMPORTS

# GENERAL

from collections import OrderedDict
from typing import Any, Union, Sequence, Tuple, Callable, Optional


# PROJECT-SPECIFIC

from ..pickle import dump as _dump, load as _load
from ...decorators.docstring import format_doc


##############################################################################
# PARAMETERS

odict_values = type(OrderedDict().values())
odict_items = type(OrderedDict().items())


##############################################################################
# CODE


[docs]class ObjDict(OrderedDict): """Dictionary-like object intended to store information. instantiated with a name (str) supports __getattr__ as a redirect to __getitem__. Parameters ---------- name: str the name of the object **kw items for ObjDict Examples -------- >>> obj = ObjDict('NAME', a=1, b=2) >>> print(obj.name, obj.a, obj['b']) NAME 1 2 """ def __init__(self, name: str = "", **kw: Any) -> None: """Initialize ObjDict.""" super().__init__() object.__setattr__(self, "name", name) # TODO better fix for inspect._is_wrapper object.__setattr__(self, "__wrapped__", None) for key, value in kw.items(): self[key] = value return # /def # ---------------------------------- # item get / set def __getitem__( self, keys: Union[str, Sequence[str]], _as_generator: bool = False ) -> Any: """Override __getitem__. Parameters ---------- keys: str, list of str the keys into ObjDict if str: just the value from key-value pair if list: list of values _as_generator: bool (default False) whether to return as a generator only if keys is a list Returns ------- value(s): anything if str, just the value from key-value pair if list, list of values if _as_generator, generator for list Examples -------- obj = ObjDict('NAME', a=1, b=2) print(obj['a']) >> 1, [NAME, 2] print(obj['name', 'b']) >> [NAME, 2] """ # single key if isinstance(keys, str): return super().__getitem__(keys) # multiple keys if _as_generator: # return generator return (OrderedDict.__getitem__(self, k) for k in keys) return [OrderedDict.__getitem__(self, k) for k in keys] # /def
[docs] @format_doc(__getitem__.__doc__) def getitem( self, keys: Union[str, Sequence[str]], _as_generator: bool = False ) -> Any: """Docstring from __getitem__.""" return self.__getitem__(keys, _as_generator=_as_generator)
# /def # ---------------------------------- # attribute get / set # redirects to item get / set def __setattr__(self, key: Any, value: Any) -> None: """Setattr -> setitem.""" self[key] = value # /def def __getattr__(self, key: Any) -> Any: """Getattr -> getitem.""" return self[key] # /def # ---------------------------------- # Printing def __repr__(self) -> str: """__repr__.""" if self.name == "": return super().__repr__() else: return self.name + super().__repr__().replace("ObjDict", "") # /def # ----------------------------------
[docs] def values(self, *keys: Any) -> Union[odict_values, tuple]: """Values. Parameters ---------- *keys: keys for values subset, default is all keys Returns ------- values: list list of values for `*keys` """ if not keys: # if no specific keys provided return super().values() return tuple([self[k] for k in keys])
# /def
[docs] def items(self, *keys: Any) -> Union[odict_items, dict]: """Items. Parameters ---------- *keys: keys for items subset, default is all keys Returns ------- items: dictionary items for `*keys` """ if not keys: return super().items() return self.subset(*keys).items()
# /def
[docs] def subset(self, *keys: Any) -> Any: """Subset. Parameters ---------- *keys: keys for subset dictionary, default is all keys Returns ------- subset: list items for `*keys` """ if not keys: return self return {k: self[k] for k in keys}
# /def
[docs] def keyslist(self) -> list: """Keys in list form. Parameters ---------- *keys: keys for subset dictionary, default is all keys Returns ------- subset: list items for `*keys` """ return list(self.keys())
# /def # ---------------------------------- # Serialize (I/O) def __reduce__(self) -> Tuple[Callable, str, odict_items]: """Reduction method for serialization. structured as: 1. the class 2. (ObjDict name, ) 3. items """ return (self.__class__, (self.name,), OrderedDict(self.items())) def __setstate__(self, state: dict) -> None: """Set-state method for loading from pickle. sets by key, value pairs """ for key, value in state.items(): self[key] = value # /def
[docs] def dump( self, fname: str, protocol: Optional[int] = None, *, fopt: str = "b", fix_imports: bool = True ): """Dump to pickle file. uses .utils.pickle.dump """ _dump( self, fname, protocol=protocol, fopt=fopt, fix_imports=fix_imports )
# /def
[docs] @format_doc(dump.__doc__) def save( self, fname: str, protocol: Optional[int] = None, *, fopt: str = "b", fix_imports: bool = True ): """.Dump alias.""" self.dump(fname, protocol=protocol, fopt=fopt, fix_imports=fix_imports)
# /def
[docs] @staticmethod def load( fname: str, *, fopt: str = "b", fix_imports: bool = True, encoding: str = "ASCII", errors: str = "strict" ): """Load from pickle file. uses .utils.pickle.load """ self = _load( fname, fopt=fopt, fix_imports=fix_imports, encoding=encoding, errors=errors, ) return self
# /def # ----------------------------------
[docs] def print(self): """Print.""" print(self.__repr__())
# /class ############################################################################## # END