summaryrefslogtreecommitdiff
path: root/django/utils/functional.py
blob: 2b3ca8293ee55cde88bf20f5fd9df1c830754c52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def curry(*args, **kwargs):
    def _curried(*moreargs, **morekwargs):
        return args[0](*(args[1:]+moreargs), **dict(kwargs.items() + morekwargs.items()))
    return _curried

def lazy(func, *resultclasses):

    """
    lazy turns any callable passed in into a lazy evaluated callable.
    you need to give result classes or types - at least one is needed
    so that the automatic forcing of the lazy evaluation code is
    triggered. Results are not memoized - the function is evaluated
    on every access.
    """

    class __proxy__:
    
        """
        This inner class encapsulates the code that should be evaluated
        lazyly. On calling of one of the magic methods it will force
        the evaluation and store the result - afterwards the result
        is delivered directly. So the result is memoized.
        """

        def __init__(self, args, kw):
           self.__func = func
           self.__args = args
           self.__kw = kw
           self.__dispatch = {}
           for resultclass in resultclasses:
               self.__dispatch[resultclass] = {}
               for (k, v) in resultclass.__dict__.items():
                   setattr(self, k, self.__promise__(resultclass, k, v))
	
        def __promise__(self, klass, funcname, func):
        
            """
            This function builds a wrapper around some magic method and
            registers that magic method for the given type and methodname.
            """
    
            def __wrapper__(*args, **kw):
                """
                This wrapper function automatically triggers the evaluation of
                a lazy value. It then applies the given magic method of the
                result type.
                """
                res = self.__func(*self.__args, **self.__kw)
                return self.__dispatch[type(res)][funcname](res, *args, **kw)
  
            if not self.__dispatch.has_key(klass):
                self.__dispatch[klass] = {}
            self.__dispatch[klass][funcname] = func
            return __wrapper__
  
    def __wrapper__(*args, **kw):
        """
        This wrapper function just creates the proxy object that is returned
        instead of the actual value.
        """
        return __proxy__(args, kw)

    return __wrapper__