Created
July 11, 2011 13:38
-
-
Save aliles/1075858 to your computer and use it in GitHub Desktop.
One time use dictionary subclass for Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"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]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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