degal/utils.py
author Tero Marttila <terom@fixme.fi>
Fri, 05 Jun 2009 23:41:57 +0300
changeset 75 18b3b1926720
parent 73 8897352630a5
child 84 891545a38a2b
permissions -rw-r--r--
fix utils.LazyProperty
"""
    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