terom@44: """ terom@44: Miscellaneous utilities terom@44: """ terom@44: terom@59: import functools terom@23: terom@59: class LazyProperty (property) : terom@12: """ terom@59: Lazy-loaded properties terom@12: """ terom@12: terom@59: def __init__ (self, func) : terom@59: """ terom@59: Initialize with no value terom@59: """ terom@12: terom@59: super(LazyProperty, self).__init__(func) terom@19: terom@59: self.value = None terom@26: terom@59: def run (self) : terom@59: """ terom@59: Run the background func and return the to-be-cached value terom@59: """ terom@28: terom@59: return super(LazyProperty, self).__call__() terom@59: terom@59: def __call__ (self) : terom@59: """ terom@59: Return the cached value if it exists, otherwise, call the func terom@59: """ terom@59: terom@59: if not self.value : terom@59: # generate it terom@59: self.value = self.run() terom@59: terom@59: return self.value terom@59: terom@59: class LazyIteratorProperty (LazyProperty) : terom@59: """ terom@59: A lazy-loaded property that automatically converts an iterator/genexp into a list. terom@59: """ terom@59: terom@59: def run (self) : terom@59: """ terom@59: Wrap LazyProperty.run to return a list terom@59: """ terom@59: terom@59: return list(super(LazyIteratorProperty, self).run()) terom@59: terom@59: lazy_load = LazyProperty terom@59: lazy_load_iter = LazyIteratorProperty terom@59: