pesterchum/pnc/dep/attrdict.py
karxi 02019c7dc5 Adjustments/retabbing for attrdict.py
Redid some of the logic behind AttrDict. It now raises AttributeError
when necessary, instead of giving the incorrect KeyError response.

This has restored compatibility with copy.deepcopy().
2016-12-30 20:59:47 -05:00

68 lines
2.7 KiB
Python

# Modified version of the code featured at the given link
## {{{ http://code.activestate.com/recipes/473786/ (r1)
class AttrDict(dict):
"""A dictionary with attribute-style access. It maps attribute access to
the real dictionary."""
def __init__(self, init={}): super(AttrDict, self).__init__(init)
def __getstate__(self): return self.__dict__.items()
def __setstate__(self, items):
for key, val in items: self.__dict__[key] = val
def __repr__(self):
return "{}({})".format(
type(self).__name__,
super(AttrDict, self).__repr__()
)
def __setitem__(self, key, value):
return super(AttrDict, self).__setitem__(key, value)
def __getitem__(self, name):
return super(AttrDict, self).__getitem__(name)
def __delitem__(self, name):
return super(AttrDict, self).__delitem__(name)
def __getattr__(self, name):
# Basically, fall back on __getitem__ first
# Try to access ourselves as a dict. Failing that, check for attributes
# with the same name. Failing *that*, throw AttributeError to keep
# other code happy.
try: retval = self[name]
except KeyError as err:
try: retval = self.__dict__[name]
except KeyError:
# Raising KeyError here will confuse __deepcopy__, so don't do
# that.
raise AttributeError("No key/attr {!r}".format(name))
return retval
__setattr__ = __setitem__
def __delattr__(self, name):
try: del self[name]
except KeyError as err:
try: del self.__dict__[name]
except KeyError:
raise AttributeError(str(err))
def copy(self): return type(self)(self)
__copy__ = copy
## end of http://code.activestate.com/recipes/473786/ }}}
class DefAttrDict(AttrDict):
def __init__(self, default_factory=None, *args, **kwargs):
self.__dict__["default_factory"] = default_factory
super(DefAttrDict, self).__init__(*args, **kwargs)
def __repr__(self):
return "%s(%r, %s)" % (
type(self).__name__,
self.default_factory,
super(AttrDict, self).__repr__()
)
def __getitem__(self, name):
try:
return super(DefAttrDict, self).__getitem__(name)
except KeyError:
##if self.default_factory is None: return None
##return self.default_factory()
result = None
if self.default_factory is not None:
result = self.default_factory()
self[name] = result
return result
__getattr__ = __getitem__
def copy(self): return type(self)(self.default_factory, self)