Skip to content

Instantly share code, notes, and snippets.

@aliles
Created July 11, 2011 13:38
Show Gist options
  • Save aliles/1075858 to your computer and use it in GitHub Desktop.
Save aliles/1075858 to your computer and use it in GitHub Desktop.
One time use dictionary subclass for Python
"One time dictionary class"
from functools import partial, wraps as full_wrap
__all__ = ['OneTimeDict']
wraps = partial(full_wrap, assigned=('__name__', '__doc__'))
class OneTimeDict(dict):
"""One time dictionary object.
Allows a key to be set only once. If an attempt is made to set a key that
is already set a KeyError exception will be raised. If an attempt is made
to remove a key a NotImplementedError exception will be raised.
"""
def _raise_if_frozen(self, key):
"Raise KeyError if the key is already set."
if key in self:
raise KeyError, "'%s' already set" % key
@wraps(dict.__delattr__)
def __delitem__(self, key):
raise NotImplementedError, "Can not delete a key from a %s" % self.__class__.__name__
@wraps(dict.__setitem__)
def __setitem__(self, key, value):
self._raise_if_frozen(key)
super(OneTimeDict, self).__setitem__(key, value)
@wraps(dict.clear)
def clear(self):
raise NotImplementedError, "Can not clear a %s" % self.__class__.__name__
@wraps(dict.fromkeys)
def fromkeys(self, iterable, value=None):
for key in iterable:
self._raise_if_frozen(key)
super(OneTimeDict, self).__setitem__(key, value)
@wraps(dict.pop)
def pop(self, key, *args):
raise NotImplementedError, "Can not pop an item from a %s" % self.__class__.__name__
@wraps(dict.popitem)
def popitem(self):
raise NotImplementedError, "Can not pop an item from a %s" % self.__class__.__name__
@wraps(dict.setdefault)
def setdefault(self, key, value=None):
if not super(OneTimeDict, self).__contains__(key):
supet(OneTimeDict, self).__setitem__(key, value)
return super(OneTimeDict, self).__getitem__(key)
@wraps(dict.update)
def update(self, iterable, **kwargs):
if hasattr(iterable, 'keys'):
for key in iterable:
self.__setitem__(key, iterable[key])
else:
for (key, value) in iterable:
self.__setitem(self, key, kwargs[key])
from otd import OneTimeDict
def assert_raises(exception, function, *args, **kwargs):
try:
function(*args, **kwargs)
except exception as err:
pass
else:
raise AssertionError, "Exception failed to be raised"
if __name__ == '__main__':
d = OneTimeDict()
d['a'] = 1
d.fromkeys(('b', 'c', 'd'), 2)
d.update({'e': 3})
assert_raises(KeyError, d.__setitem__, 'a', None)
assert_raises(KeyError, d.fromkeys, ('e', 'a'), None)
assert_raises(KeyError, d.update, {'a': None})
assert_raises(NotImplementedError, d.__delitem__, 'a')
assert_raises(NotImplementedError, d.clear)
assert_raises(NotImplementedError, d.pop, 'a')
assert_raises(NotImplementedError, d.popitem)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment