Current File : /home/inlingua/miniconda3/lib/python3.1/site-packages/frozendict/_frozendict_py.py |
from copy import deepcopy
def immutable(self, *args, **kwargs):
r"""
Function for not implemented method since the object is immutable
"""
raise AttributeError(
f"'{self.__class__.__name__}' object is read-only"
)
_empty_frozendict = None
class frozendict(dict):
r"""
A simple immutable dictionary.
The API is the same as `dict`, without methods that can change the
immutability. In addition, it supports __hash__().
"""
__slots__ = (
"_hash",
)
@classmethod
def fromkeys(cls, *args, **kwargs):
r"""
Identical to dict.fromkeys().
"""
return cls(dict.fromkeys(*args, **kwargs))
def __new__(e4b37cdf_d78a_4632_bade_6f0579d8efac, *args, **kwargs):
cls = e4b37cdf_d78a_4632_bade_6f0579d8efac
has_kwargs = bool(kwargs)
continue_creation = True
# check if there's only an argument and it's of the same class
if len(args) == 1 and not has_kwargs:
it = args[0]
# no isinstance, to avoid subclassing problems
if it.__class__ == frozendict and cls == frozendict:
self = it
continue_creation = False
if continue_creation:
self = dict.__new__(cls, *args, **kwargs)
dict.__init__(self, *args, **kwargs)
# empty singleton - start
if self.__class__ == frozendict and not len(self):
global _empty_frozendict
if _empty_frozendict is None:
_empty_frozendict = self
else:
self = _empty_frozendict
continue_creation = False
# empty singleton - end
if continue_creation:
object.__setattr__(self, "_hash", -1)
return self
def __init__(self, *args, **kwargs):
pass
def __hash__(self, *args, **kwargs):
r"""
Calculates the hash if all values are hashable, otherwise
raises a TypeError.
"""
if self._hash != -1:
_hash = self._hash
else:
fs = frozenset(self.items())
_hash = hash(fs)
object.__setattr__(self, "_hash", _hash)
return _hash
def __repr__(self, *args, **kwargs):
r"""
Identical to dict.__repr__().
"""
body = super().__repr__(*args, **kwargs)
klass = self.__class__
if klass == frozendict:
name = f"frozendict.{klass.__name__}"
else:
name = klass.__name__
return f"{name}({body})"
def copy(self):
r"""
Return the object itself, as it's an immutable.
"""
klass = self.__class__
if klass == frozendict:
return self
return klass(self)
def __copy__(self, *args, **kwargs):
r"""
See copy().
"""
return self.copy()
def __deepcopy__(self, memo, *args, **kwargs):
r"""
As for tuples, if hashable, see copy(); otherwise, it returns a
deepcopy.
"""
klass = self.__class__
return_copy = klass == frozendict
if return_copy:
try:
hash(self)
except TypeError:
return_copy = False
if return_copy:
return self.copy()
tmp = deepcopy(dict(self))
return klass(tmp)
def __reduce__(self, *args, **kwargs):
r"""
Support for `pickle`.
"""
return (self.__class__, (dict(self),))
def set(self, key, val):
new_self = deepcopy(dict(self))
new_self[key] = val
return self.__class__(new_self)
def setdefault(self, key, default=None):
if key in self:
return self
new_self = deepcopy(dict(self))
new_self[key] = default
return self.__class__(new_self)
def delete(self, key):
new_self = deepcopy(dict(self))
del new_self[key]
if new_self:
return self.__class__(new_self)
return self.__class__()
def _get_by_index(self, collection, index):
try:
return collection[index]
except IndexError:
maxindex = len(collection) - 1
name = self.__class__.__name__
raise IndexError(
f"{name} index {index} out of range {maxindex}"
) from None
def key(self, index=0):
collection = tuple(self.keys())
return self._get_by_index(collection, index)
def value(self, index=0):
collection = tuple(self.values())
return self._get_by_index(collection, index)
def item(self, index=0):
collection = tuple(self.items())
return self._get_by_index(collection, index)
def __setitem__(self, key, val, *args, **kwargs):
raise TypeError(
f"'{self.__class__.__name__}' object doesn't support item "
"assignment"
)
def __delitem__(self, key, *args, **kwargs):
raise TypeError(
f"'{self.__class__.__name__}' object doesn't support item "
"deletion"
)
def frozendict_or(self, other, *args, **kwargs):
res = {}
res.update(self)
res.update(other)
return self.__class__(res)
frozendict.__or__ = frozendict_or
frozendict.__ior__ = frozendict_or
try:
frozendict.__reversed__
except AttributeError:
def frozendict_reversed(self, *args, **kwargs):
return reversed(tuple(self))
frozendict.__reversed__ = frozendict_reversed
frozendict.clear = immutable
frozendict.pop = immutable
frozendict.popitem = immutable
frozendict.update = immutable
frozendict.__delattr__ = immutable
frozendict.__setattr__ = immutable
frozendict.__module__ = 'frozendict'
__all__ = (frozendict.__name__,)