from threading import local
from contextlib import contextmanager
[docs]class Bunch(dict):
def __getattr__(self, name):
try:
return self[name]
except KeyError:
raise AttributeError, name
[docs]class LazyProperty(object):
def __init__(self, func):
self._func = func
self.__name__ = func.__name__
self.__doc__ = func.__doc__
def __get__(self, obj, klass=None):
if obj is None: return None
result = obj.__dict__[self.__name__] = self._func(obj)
return result
@contextmanager
[docs]def push_context(obj, **kw):
'''Temporarily add attributes to 'obj', restoring 'obj' to its original
state on __exit__
'''
new_keys = [ k for k in kw if not hasattr(obj, k) ]
saved_items = [
(k, getattr(obj, k)) for k in kw
if hasattr(obj, k) ]
for k,v in kw.iteritems():
setattr(obj, k, v)
yield obj
for nk in new_keys:
delattr(obj, nk)
for k,v in saved_items:
setattr(obj, k, v)
[docs]class NameListItem(object):
'''An item that 'remembers' its order of instantiation within a thread'''
_local = local()
name=None
def __init__(self):
self._ordinal = getattr(NameListItem._local, '_ordinal', 0)
NameListItem._local._ordinal = self._ordinal + 1
class _NameListMeta(type):
def __new__(meta, name, bases, dct):
if bases == (list,):
return type.__new__(meta, name, bases, dct)
lst = []
for k,v in dct.iteritems():
if isinstance(v, NameListItem):
if getattr(v, 'name') is None:
v.name = k
lst.append(v)
# Maintain declaration order
lst.sort(key=lambda x:x._ordinal)
return NameList(lst, dct)
[docs]class NameList(list):
'''Simple class to let you create a list of widgets declaratively'''
__metaclass__ = _NameListMeta
def __init__(self, iterator=None, index=None):
if iterator is None: iterator = []
super(NameList, self).__init__(iterator)
if index is None:
index = dict(
(v.name, v) for v in self
if hasattr(v, 'name'))
self._index = index
def __getitem__(self, index):
if isinstance(index, basestring):
return self._index[index]
return super(NameList, self).__getitem__(index)
def __getattr__(self, name):
try:
return self._index[name]
except KeyError:
raise AttributeError, name
[docs] def append(self, item):
if hasattr(item, 'name'):
self._index[item.name] = item
super(NameList, self).append(item)
[docs]class NoDefault(tuple): pass
[docs]def safe_getitem(dct, key, item):
'''Return either dct[key][item], dct[key].item, or None, whichever
is appropriate
'''
if key not in dct: return None
value = dct[key]
try:
result = value[item]
except TypeError:
if isinstance(item, str):
result = getattr(value, item, None)
else:
result = None
except (KeyError, IndexError), ex:
result = None
return result