"""
Miscellaneous utilities
"""
import functools
class LazyProperty (property) :
"""
Lazy-loaded properties
"""
ATTRNAME = '_LazyProperty_values'
def __init__ (self, func) :
"""
Initialize with no value
"""
super(LazyProperty, self).__init__(func)
self.func = func
self.name = func.__name__
self.value = None
def run (self, obj) :
"""
Run the background func and return the to-be-cached value
"""
return self.func(obj)
def obj_dict (self, obj):
"""
Get the lazy-property dict of the given obj
"""
dict = getattr(obj, self.ATTRNAME, None)
if dict is None :
dict = {}
setattr(obj, self.ATTRNAME, dict)
return dict
def get (self, obj) :
"""
Return the cached value
"""
return self.obj_dict(obj)[self.name]
def set (self, obj, value) :
"""
Set the cached value
"""
self.obj_dict(obj)[self.name] = value
def test (self, obj) :
"""
Tests if a value is set
"""
return self.name in self.obj_dict(obj)
def __get__ (self, obj, owner) :
"""
Return the cached value if it exists, otherwise, call the func
"""
if not obj :
return self
if not self.test(obj) :
# generate it
self.set(obj, self.run(obj))
return self.get(obj)
class LazyIteratorProperty (LazyProperty) :
"""
A lazy-loaded property that automatically converts an iterator/genexp into a list.
"""
def run (self, obj) :
"""
Wrap LazyProperty.run to return a list
"""
return list(super(LazyIteratorProperty, self).run(obj))
lazy_load = LazyProperty
lazy_load_iter = LazyIteratorProperty