degal/utils.py
author Tero Marttila <terom@fixme.fi>
Wed, 10 Jun 2009 23:33:28 +0300
changeset 84 891545a38a2b
parent 75 18b3b1926720
child 96 d9cf1e272e90
permissions -rw-r--r--
change utils.LazyProperty to store the cached value using obj.__dict__
"""
    Miscellaneous utilities
"""

import functools

class LazyProperty (property) :
    """
        Lazy-loaded cached properties.

        This functions by overriding the class's property attribute with the actual value attribute in the instance's
        dict, causing all future attribute lookups to return that directly.
    """

    def __init__ (self, func) :
        """
            Initialize with no value
        """

        super(LazyProperty, self).__init__(func)
        
        # the getter function
        self.func = func

        # the attribute name
        self.name = func.__name__

    def run (self, obj) :
        """
            Run the background func and return the to-be-cached value.

            `obj` is the object instance
        """

        return self.func(obj)
 
    def store (self, obj, value) :
        """
            Store the cached value, overring ourself
        """
        
        obj.__dict__[self.name] = value

    def __get__ (self, obj, owner) :
        """
            Generate the value, store it as the attribute and return it.
        """
        
        # compute value
        value = self.run(obj)

        # store it
        self.store(obj, value)
        
        # return it
        return value

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