Viewing file: lazy.py (5.14 KB) -rwxr-xr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
from threading import RLock try: from UserDict import DictMixin except ImportError: from collections import Mapping as DictMixin
# With lazy loading, we might end up with multiple threads triggering # it at the same time. We need a lock. _fill_lock = RLock()
class LazyDict(DictMixin): """Dictionary populated on first use.""" data = None def __getitem__(self, key): if self.data is None: _fill_lock.acquire() try: if self.data is None: self._fill() finally: _fill_lock.release() return self.data[key.upper()]
def __contains__(self, key): if self.data is None: _fill_lock.acquire() try: if self.data is None: self._fill() finally: _fill_lock.release() return key in self.data
def __iter__(self): if self.data is None: _fill_lock.acquire() try: if self.data is None: self._fill() finally: _fill_lock.release() return iter(self.data)
def __len__(self): if self.data is None: _fill_lock.acquire() try: if self.data is None: self._fill() finally: _fill_lock.release() return len(self.data)
def keys(self): if self.data is None: _fill_lock.acquire() try: if self.data is None: self._fill() finally: _fill_lock.release() return self.data.keys()
class LazyList(list): """List populated on first use."""
_props = [ '__str__', '__repr__', '__unicode__', '__hash__', '__sizeof__', '__cmp__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', 'append', 'count', 'index', 'extend', 'insert', 'pop', 'remove', 'reverse', 'sort', '__add__', '__radd__', '__iadd__', '__mul__', '__rmul__', '__imul__', '__contains__', '__len__', '__nonzero__', '__getitem__', '__setitem__', '__delitem__', '__iter__', '__reversed__', '__getslice__', '__setslice__', '__delslice__']
def __new__(cls, fill_iter=None):
if fill_iter is None: return list()
# We need a new class as we will be dynamically messing with its # methods. class LazyList(list): pass
fill_iter = [fill_iter]
def lazy(name): def _lazy(self, *args, **kw): _fill_lock.acquire() try: if len(fill_iter) > 0: list.extend(self, fill_iter.pop()) for method_name in cls._props: delattr(LazyList, method_name) finally: _fill_lock.release() return getattr(list, name)(self, *args, **kw) return _lazy
for name in cls._props: setattr(LazyList, name, lazy(name))
new_list = LazyList() return new_list
# Not all versions of Python declare the same magic methods. # Filter out properties that don't exist in this version of Python # from the list. LazyList._props = [prop for prop in LazyList._props if hasattr(list, prop)]
class LazySet(set): """Set populated on first use."""
_props = ( '__str__', '__repr__', '__unicode__', '__hash__', '__sizeof__', '__cmp__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__contains__', '__len__', '__nonzero__', '__getitem__', '__setitem__', '__delitem__', '__iter__', '__sub__', '__and__', '__xor__', '__or__', '__rsub__', '__rand__', '__rxor__', '__ror__', '__isub__', '__iand__', '__ixor__', '__ior__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update')
def __new__(cls, fill_iter=None):
if fill_iter is None: return set()
class LazySet(set): pass
fill_iter = [fill_iter]
def lazy(name): def _lazy(self, *args, **kw): _fill_lock.acquire() try: if len(fill_iter) > 0: for i in fill_iter.pop(): set.add(self, i) for method_name in cls._props: delattr(LazySet, method_name) finally: _fill_lock.release() return getattr(set, name)(self, *args, **kw) return _lazy
for name in cls._props: setattr(LazySet, name, lazy(name))
new_set = LazySet() return new_set
# Not all versions of Python declare the same magic methods. # Filter out properties that don't exist in this version of Python # from the list. LazySet._props = [prop for prop in LazySet._props if hasattr(set, prop)]
|