| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 | from __future__ import annotationsfrom itertools import repeatfrom .._internal import _missingdef is_immutable(self):    raise TypeError(f"{type(self).__name__!r} objects are immutable")class ImmutableListMixin:    """Makes a :class:`list` immutable.    .. versionadded:: 0.5    :private:    """    _hash_cache = None    def __hash__(self):        if self._hash_cache is not None:            return self._hash_cache        rv = self._hash_cache = hash(tuple(self))        return rv    def __reduce_ex__(self, protocol):        return type(self), (list(self),)    def __delitem__(self, key):        is_immutable(self)    def __iadd__(self, other):        is_immutable(self)    def __imul__(self, other):        is_immutable(self)    def __setitem__(self, key, value):        is_immutable(self)    def append(self, item):        is_immutable(self)    def remove(self, item):        is_immutable(self)    def extend(self, iterable):        is_immutable(self)    def insert(self, pos, value):        is_immutable(self)    def pop(self, index=-1):        is_immutable(self)    def reverse(self):        is_immutable(self)    def sort(self, key=None, reverse=False):        is_immutable(self)class ImmutableDictMixin:    """Makes a :class:`dict` immutable.    .. versionadded:: 0.5    :private:    """    _hash_cache = None    @classmethod    def fromkeys(cls, keys, value=None):        instance = super().__new__(cls)        instance.__init__(zip(keys, repeat(value)))        return instance    def __reduce_ex__(self, protocol):        return type(self), (dict(self),)    def _iter_hashitems(self):        return self.items()    def __hash__(self):        if self._hash_cache is not None:            return self._hash_cache        rv = self._hash_cache = hash(frozenset(self._iter_hashitems()))        return rv    def setdefault(self, key, default=None):        is_immutable(self)    def update(self, *args, **kwargs):        is_immutable(self)    def pop(self, key, default=None):        is_immutable(self)    def popitem(self):        is_immutable(self)    def __setitem__(self, key, value):        is_immutable(self)    def __delitem__(self, key):        is_immutable(self)    def clear(self):        is_immutable(self)class ImmutableMultiDictMixin(ImmutableDictMixin):    """Makes a :class:`MultiDict` immutable.    .. versionadded:: 0.5    :private:    """    def __reduce_ex__(self, protocol):        return type(self), (list(self.items(multi=True)),)    def _iter_hashitems(self):        return self.items(multi=True)    def add(self, key, value):        is_immutable(self)    def popitemlist(self):        is_immutable(self)    def poplist(self, key):        is_immutable(self)    def setlist(self, key, new_list):        is_immutable(self)    def setlistdefault(self, key, default_list=None):        is_immutable(self)class ImmutableHeadersMixin:    """Makes a :class:`Headers` immutable.  We do not mark them as    hashable though since the only usecase for this datastructure    in Werkzeug is a view on a mutable structure.    .. versionadded:: 0.5    :private:    """    def __delitem__(self, key, **kwargs):        is_immutable(self)    def __setitem__(self, key, value):        is_immutable(self)    def set(self, _key, _value, **kwargs):        is_immutable(self)    def setlist(self, key, values):        is_immutable(self)    def add(self, _key, _value, **kwargs):        is_immutable(self)    def add_header(self, _key, _value, **_kwargs):        is_immutable(self)    def remove(self, key):        is_immutable(self)    def extend(self, *args, **kwargs):        is_immutable(self)    def update(self, *args, **kwargs):        is_immutable(self)    def insert(self, pos, value):        is_immutable(self)    def pop(self, key=None, default=_missing):        is_immutable(self)    def popitem(self):        is_immutable(self)    def setdefault(self, key, default):        is_immutable(self)    def setlistdefault(self, key, default):        is_immutable(self)def _calls_update(name):    def oncall(self, *args, **kw):        rv = getattr(super(UpdateDictMixin, self), name)(*args, **kw)        if self.on_update is not None:            self.on_update(self)        return rv    oncall.__name__ = name    return oncallclass UpdateDictMixin(dict):    """Makes dicts call `self.on_update` on modifications.    .. versionadded:: 0.5    :private:    """    on_update = None    def setdefault(self, key, default=None):        modified = key not in self        rv = super().setdefault(key, default)        if modified and self.on_update is not None:            self.on_update(self)        return rv    def pop(self, key, default=_missing):        modified = key in self        if default is _missing:            rv = super().pop(key)        else:            rv = super().pop(key, default)        if modified and self.on_update is not None:            self.on_update(self)        return rv    __setitem__ = _calls_update("__setitem__")    __delitem__ = _calls_update("__delitem__")    clear = _calls_update("clear")    popitem = _calls_update("popitem")    update = _calls_update("update")
 |