Last active
August 29, 2015 13:57
-
-
Save adoc/9588060 to your computer and use it in GitHub Desktop.
safedict: A threadsafe dict-like object.
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
""" | |
""" | |
import threading | |
__all__ = ('SafeDict', ) | |
class SafeDict: | |
"""A threadsafe dict-like object. | |
Simply access like a dict" | |
>>> t = SafeDict() | |
>>> t['foo'] = 'bar' | |
>>> t['foo'] | |
bar | |
>>> t.get('boo', false) | |
false | |
""" | |
# TODO: use *args for construction to pass a dict. | |
__registry = {} | |
def __init__(self, default_types={}, get_ident=threading.get_ident): | |
"""""" | |
self.__get_ident = get_ident | |
self.__default_types = default_types | |
@property | |
def thread_id(self): | |
"""Executes the thread id function and returns the result.""" | |
return self.__get_ident() | |
@property | |
def registry(self): | |
""" """ | |
try: | |
return self.__registry[self.thread_id] | |
except KeyError: | |
reg = self.__registry[self.thread_id] = {} | |
return reg | |
def __contains__(self, key): | |
return key in self.registry | |
def __delitem__(self, key): | |
del self.registry[key] | |
def __getitem__(self, key): | |
try: | |
return self.registry[key] | |
except KeyError: | |
if key in self.__default_types.keys(): | |
reg = self.registry[key] = self.__default_types[key]() | |
return reg | |
else: | |
raise KeyError("'%s' was not found in safedict or in `default_types`." % key) | |
def __setitem__(self, key, val): | |
self.registry[key] = val | |
''' | |
try: | |
registry = self.__registry[key] | |
except KeyError: | |
# default_type = self.__default_types.get(key) or dict | |
registry = self.__registry[key] = {} | |
registry[self.thread_id] = val''' | |
#def get(self, key, *args): | |
"""Mimics a dict.get (I think)""" | |
''' | |
try: | |
item = self[key] | |
except KeyError: | |
if args: | |
return args[0] | |
else: | |
return None | |
else: | |
return item''' | |
#def set(self, key, val): | |
"""This seems too simple, but okay!""" | |
''' | |
self[key] = val''' | |
# TESTS | |
import unittest | |
import threading | |
threadfunc = lambda func: threading.Thread(target=func) | |
class SafeDictTests(unittest.TestCase): | |
""" """ | |
def test_empty(self): | |
registry = SafeDict() | |
self.assertRaises(KeyError, lambda: registry['foo']) | |
def test_set_get(self): | |
registry = SafeDict() | |
def do(key, val): | |
registry.set(key, val) | |
self.assertEqual(registry.get(key), val) | |
threads = (threadfunc(lambda: do('foo', 'bar')), | |
threadfunc(lambda: do('foo', 'bar')), | |
threadfunc(lambda: do('boo', True)), | |
threadfunc(lambda: do('boo', 'boop'))) | |
def threadstart(t): | |
t.start() | |
t.join() | |
map(threadstart, threads) | |
def test_inner_registry(self): | |
registry = SafeDict() | |
def assign(key, val): | |
registry[key] = val | |
t1 = threadfunc(lambda: assign('foo', 'bar')) | |
t2 = threadfunc(lambda: assign('bip', True)) | |
# Fire threads. | |
t1.start() | |
t2.start() | |
# Wait for threads to finish! | |
t1.join() | |
t2.join() | |
self.assertEqual(registry._SafeDict__registry, | |
{'foo': {t1._ident: 'bar'}, | |
'bip': {t2._ident: True}}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment