the source code in utils.functional about lazy function

15 views
Skip to first unread message

Fred Zhang

unread,
Feb 5, 2015, 10:50:52 AM2/5/15
to django...@googlegroups.com
Recently I am learning about django source code from utils folder.
But about functional file, I don't know the meaning of lazy function.
Can anyboby help me to explain about the meaning about it?
Thanks



The code:


class Promise(object):
   
"""
    This is just a base class for the proxy class created in
    the closure of the lazy function. It can be used to recognize
    promises in code.
    """

   
pass




def lazy(func, *resultclasses):
   
"""
    Turns any callable 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.
    """

 
 
'''
 @functools.total_ordering
 Given a class defining one or more rich comparison ordering methods,
 this class decorator supplies the rest.
 This simplifies the effort involved in specifying all of the possible rich comparison operations:


 The class must define one of __lt__(), __le__(), __gt__(), or __ge__().
 In addition, the class should supply an __eq__() method.


 For example:


 @total_ordering
 class Student:
 def _is_valid_operand(self, other):
 return (hasattr(other, "lastname") and
 hasattr(other, "firstname"))
 def __eq__(self, other):
 if not self._is_valid_operand(other):
 return NotImplemented
 return ((self.lastname.lower(), self.firstname.lower()) ==
 (other.lastname.lower(), other.firstname.lower()))
 def __lt__(self, other):
 if not self._is_valid_operand(other):
 return NotImplemented
 return ((self.lastname.lower(), self.firstname.lower()) <
 (other.lastname.lower(), other.firstname.lower()))






 '''

   
@total_ordering
   
class __proxy__(Promise):
       
"""
        Encapsulate a function call and act as a proxy for methods that are
        called on the result of that function. The function is not evaluated
        until one of the methods on the result is called.
        """

        __dispatch
= None


       
def __init__(self, args, kw):
           
self.__args = args
           
self.__kw = kw
           
if self.__dispatch is None:
               
self.__prepare_class__()


       
def __reduce__(self):
           
return (
                _lazy_proxy_unpickle
,
               
(func, self.__args, self.__kw) + resultclasses
           
)


       
@classmethod
       
def __prepare_class__(cls):
            cls
.__dispatch = {}
           
for resultclass in resultclasses:
                cls
.__dispatch[resultclass] = {}
               
for type_ in reversed(resultclass.mro()):
                   
for (k, v) in type_.__dict__.items():
                       
# All __promise__ return the same wrapper method, but
                       
# they also do setup, inserting the method into the
                       
# dispatch dict.
                        meth
= cls.__promise__(resultclass, k, v)
                       
if hasattr(cls, k):
                           
continue
                        setattr
(cls, k, meth)
            cls
._delegate_bytes = bytes in resultclasses
            cls
._delegate_text = six.text_type in resultclasses
           
assert not (cls._delegate_bytes and cls._delegate_text), "Cannot call lazy() with both bytes and text return types."
           
if cls._delegate_text:
               
if six.PY3:
                    cls
.__str__ = cls.__text_cast
               
else:
                    cls
.__unicode__ = cls.__text_cast
           
elif cls._delegate_bytes:
               
if six.PY3:
                    cls
.__bytes__ = cls.__bytes_cast
               
else:
                    cls
.__str__ = cls.__bytes_cast


       
@classmethod
       
def __promise__(cls, klass, funcname, method):
           
# Builds a wrapper around some magic method and registers that
           
# magic method for the given type and method name.
           
def __wrapper__(self, *args, **kw):
               
# Automatically triggers the evaluation of a lazy value and
               
# applies the given magic method of the result type.
                res
= func(*self.__args, **self.__kw)
               
for t in type(res).mro():
                   
if t in self.__dispatch:
                       
return self.__dispatch[t][funcname](res, *args, **kw)
               
raise TypeError("Lazy object returned unexpected type.")


           
if klass not in cls.__dispatch:
                cls
.__dispatch[klass] = {}
            cls
.__dispatch[klass][funcname] = method
           
return __wrapper__


       
def __text_cast(self):
           
return func(*self.__args, **self.__kw)


       
def __bytes_cast(self):
           
return bytes(func(*self.__args, **self.__kw))


       
def __cast(self):
           
if self._delegate_bytes:
               
return self.__bytes_cast()
           
elif self._delegate_text:
               
return self.__text_cast()
           
else:
               
return func(*self.__args, **self.__kw)


       
def __ne__(self, other):
           
if isinstance(other, Promise):
                other
= other.__cast()
           
return self.__cast() != other


       
def __eq__(self, other):
           
if isinstance(other, Promise):
                other
= other.__cast()
           
return self.__cast() == other


       
def __lt__(self, other):
           
if isinstance(other, Promise):
                other
= other.__cast()
           
return self.__cast() < other


       
def __hash__(self):
           
return hash(self.__cast())


       
def __mod__(self, rhs):
           
if self._delegate_bytes and six.PY2:
               
return bytes(self) % rhs
           
elif self._delegate_text:
               
return six.text_type(self) % rhs
           
return self.__cast() % rhs


       
def __deepcopy__(self, memo):
           
# Instances of this class are effectively immutable. It's just a
           
# collection of functions. So we don't need to do anything
           
# complicated for copying.
            memo
[id(self)] = self
           
return self


   
@wraps(func)
   
def __wrapper__(*args, **kw):
       
# Creates the proxy object, instead of the actual value.
       
return __proxy__(args, kw)


   
return __wrapper__


Reply all
Reply to author
Forward
0 new messages