def addLazyItem(self, item_key, value_callable, *pargs, **kwargs):
"""Add a lazy item for the given key. When the item is requested,
value_callable will be called with *pargs and **kwargs arguments."""
- if not pargs:
- pargs = None
- if not kwargs:
- kwargs = None
- self.lazy_items[item_key] = (value_callable, pargs, kwargs)
+ self.lazy_items[item_key] = \
+ self._LazyItem(value_callable, pargs, kwargs, False)
# make it show up in self.keys(), etc...
dict.__setitem__(self, item_key, None)
+
def addLazySingleton(self, item_key, value_callable, *pargs, **kwargs):
"""This is like addLazyItem except value_callable will only be called
a maximum of 1 time and the result will be cached for future requests."""
- self.addLazyItem(item_key,
- self._SingletonWrapper(self, item_key, value_callable),
- *pargs, **kwargs)
+ self.lazy_items[item_key] = \
+ self._LazyItem(value_callable, pargs, kwargs, True)
+ # make it show up in self.keys(), etc...
+ dict.__setitem__(self, item_key, None)
def update(self, *args, **kwargs):
if len(args) > 1:
dict.__setitem__(self, k, None)
else:
dict.__setitem__(self, k, map_obj[k])
- for k, v in map_obj.lazy_items.iteritems():
- if isinstance(v[0], self._SingletonWrapper):
- # Create a new wrapper that references self.
- v = (self._SingletonWrapper(self, k, v[0]._callable),
- v[1], v[2])
- self.lazy_items[k] = v
+ self.lazy_items.update(map_obj.lazy_items)
else:
dict.update(self, map_obj)
if kwargs:
def __getitem__(self, item_key):
if item_key in self.lazy_items:
- value_callable, pargs, kwargs = self.lazy_items[item_key]
+ lazy_item = self.lazy_items[item_key]
+ pargs = lazy_item.pargs
if pargs is None:
pargs = ()
+ kwargs = lazy_item.kwargs
if kwargs is None:
kwargs = {}
- return value_callable(*pargs, **kwargs)
+ result = lazy_item.func(*pargs, **kwargs)
+ if lazy_item.singleton:
+ self[item_key] = result
+ return result
+
else:
return dict.__getitem__(self, item_key)
+
def __setitem__(self, item_key, value):
if item_key in self.lazy_items:
del self.lazy_items[item_key]
except TypeError:
# If deepcopy fails for a lazy singleton, try to
# evaluate the singleton and deepcopy the result.
- if not isinstance(lazy_item[0], self._SingletonWrapper):
+ if not lazy_item.singleton:
raise
dict.__setitem__(result, k_copy, deepcopy(self[k], memo))
else:
dict.__setitem__(result, k_copy, deepcopy(self[k], memo))
return result
- class _SingletonWrapper(object):
+ class _LazyItem(object):
+
+ __slots__ = ('func', 'pargs', 'kwargs', 'singleton')
- __slots__ = ('_parent', '_key', '_callable')
+ def __init__(self, func, pargs, kwargs, singleton):
- def __init__(self, parent, key, value_callable):
- self._parent = parent
- self._key = key
- self._callable = value_callable
+ if not pargs:
+ pargs = None
+ if not kwargs:
+ kwargs = None
- def __call__(self, *pargs, **kwargs):
- value = self._callable(*pargs, **kwargs)
- self._parent[self._key] = value
- return value
+ self.func = func
+ self.pargs = pargs
+ self.kwargs = kwargs
+ self.singleton = singleton
class ConfigProtect(object):
def __init__(self, myroot, protect_list, mask_list):