from collections import OrderedDict class LimitedSizeDict(OrderedDict): def __init__(self, *args, **kwds): if "size_limit" not in kwds: raise ValueError("'size_limit' must be passed as a keyword " "argument") self.size_limit = kwds.pop("size_limit") if len(args) > 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) if len(args) == 1 and len(args[0]) + len(kwds) > self.size_limit: raise ValueError("Tried to initialize LimitedSizedDict with more " "value than permitted with 'limit_size'") super(LimitedSizeDict, self).__init__(*args, **kwds) def __setitem__(self, key, value, dict_setitem=OrderedDict.__setitem__): dict_setitem(self, key, value) self._check_size_limit() def _check_size_limit(self): if self.size_limit is not None: while len(self) > self.size_limit: self.popitem(last=False) def __eq__(self, other): if self.size_limit != other.size_limit: return False return super(LimitedSizeDict, self).__eq__(other) class UnupdatableDict(dict): def __setitem__(self, key, value): if key in self: raise KeyError("Can't update key '%s'" % key) super(UnupdatableDict, self).__setitem__(key, value)