from ._pystruct import Struct
try:
from ._cstruct import _Struct as FastStruct # noqa
except ImportError: # pragma: no cover
FastStruct = None
__version__ = '4.0.0' # pragma: no mutate
__all__ = ['Struct', 'FastStruct', 'FrozenStruct', 'merged', 'DefaultStruct', 'to_default_struct'] # pragma: no mutate
class Frozen(object):
"""
Mixin to create an immutable class.
"""
__slots__ = ()
def __hash__(self):
hash_key = '_hash'
try:
_hash = dict.__getattribute__(self, hash_key)
except AttributeError:
_hash = hash(tuple((k, self[k]) for k in sorted(self.keys())))
dict.__setattr__(self, hash_key, _hash)
return _hash
def __setitem__(self, *_, **__):
raise TypeError("'%s' object attributes are read-only" % (type(self).__name__, ))
def __setattr__(self, key, value):
raise TypeError("'%s' object attributes are read-only" % (type(self).__name__,))
def setdefault(self, *_, **__):
raise TypeError("'%s' object attributes are read-only" % (type(self).__name__, ))
def update(self, *_, **__):
raise TypeError("'%s' object attributes are read-only" % (type(self).__name__, ))
def clear(self, *_, **__):
raise TypeError("'%s' object attributes are read-only" % (type(self).__name__, ))
def __delitem__(self, *_, **__):
raise TypeError("'%s' object attributes are read-only" % (type(self).__name__, ))
def __delattr__(self, *_, **__):
raise TypeError("'%s' object attributes are read-only" % (type(self).__name__,))
def __reduce__(self):
return type(self), (), dict(self)
def __setstate__(self, state):
dict.update(self, state)
def __copy__(self):
return self
[docs]class FrozenStruct(Frozen, Struct):
__slots__ = ('_hash', )
[docs]def merged(*dicts, **kwargs):
"""
Merge dictionaries. Later keys overwrite.
.. code-block:: python
merged(dict(a=1), dict(b=2), c=3, d=1)
"""
if not dicts:
return Struct()
result = dict()
for d in dicts:
result.update(d)
result.update(kwargs)
struct_type = type(dicts[0])
return struct_type(**result)
[docs]class DefaultStruct(Struct):
__slots__ = ('_default_factory',)
[docs] def __init__(self, default_factory=None, *args, **kwargs):
if default_factory is None:
default_factory = DefaultStruct
object.__setattr__(self, '_default_factory', default_factory)
super(DefaultStruct, self).__init__(*args, **kwargs)
def __missing__(self, key):
try:
return object.__getattribute__(self, key)
except AttributeError:
default_factory = object.__getattribute__(self, '_default_factory')
self[key] = new = default_factory()
return new
[docs]def to_default_struct(d):
if isinstance(d, DefaultStruct):
return d
elif isinstance(d, dict):
return DefaultStruct(None, ((k, to_default_struct(v)) for k, v in d.items()))
else:
return d