|
from threading import RLock |
|
try: |
|
from collections.abc import Mapping as DictMixin |
|
except ImportError: |
|
try: |
|
from UserDict import DictMixin |
|
except ImportError: |
|
from collections import Mapping as DictMixin |
|
|
|
|
|
|
|
|
|
_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() |
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
LazySet._props = [prop for prop in LazySet._props if hasattr(set, prop)] |
|
|