1 # License for code in this file that was taken from Python 2.5.
3 # PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
4 # --------------------------------------------
6 # 1. This LICENSE AGREEMENT is between the Python Software Foundation
7 # ("PSF"), and the Individual or Organization ("Licensee") accessing and
8 # otherwise using this software ("Python") in source or binary form and
9 # its associated documentation.
11 # 2. Subject to the terms and conditions of this License Agreement, PSF
12 # hereby grants Licensee a nonexclusive, royalty-free, world-wide
13 # license to reproduce, analyze, test, perform and/or display publicly,
14 # prepare derivative works, distribute, and otherwise use Python
15 # alone or in any derivative version, provided, however, that PSF's
16 # License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
17 # 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation;
18 # All Rights Reserved" are retained in Python alone or in any derivative
19 # version prepared by Licensee.
21 # 3. In the event Licensee prepares a derivative work that is based on
22 # or incorporates Python or any part thereof, and wants to make
23 # the derivative work available to others as provided herein, then
24 # Licensee hereby agrees to include in any such work a brief summary of
25 # the changes made to Python.
27 # 4. PSF is making Python available to Licensee on an "AS IS"
28 # basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
29 # IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
30 # DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
31 # FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
32 # INFRINGE ANY THIRD PARTY RIGHTS.
34 # 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
35 # FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
36 # A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
37 # OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
39 # 6. This License Agreement will automatically terminate upon a material
40 # breach of its terms and conditions.
42 # 7. Nothing in this License Agreement shall be deemed to create any
43 # relationship of agency, partnership, or joint venture between PSF and
44 # Licensee. This License Agreement does not grant permission to use PSF
45 # trademarks or trade name in a trademark sense to endorse or promote
46 # products or services of Licensee, or any third party.
48 # 8. By copying, installing or otherwise using Python, Licensee
49 # agrees to be bound by the terms and conditions of this License
53 def curry(_curried_func
, *args
, **kwargs
):
54 def _curried(*moreargs
, **morekwargs
):
55 return _curried_func(*(args
+moreargs
), **dict(kwargs
, **morekwargs
))
58 ### Begin from Python 2.5 functools.py ########################################
60 # Summary of changes made to the Python 2.5 code below:
61 # * swapped ``partial`` for ``curry`` to maintain backwards-compatibility
64 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation.
65 # All Rights Reserved.
67 ###############################################################################
69 # update_wrapper() and wraps() are tools to help write
70 # wrapper functions that can handle naive introspection
72 WRAPPER_ASSIGNMENTS
= ('__module__', '__name__', '__doc__')
73 WRAPPER_UPDATES
= ('__dict__',)
74 def update_wrapper(wrapper
,
76 assigned
= WRAPPER_ASSIGNMENTS
,
77 updated
= WRAPPER_UPDATES
):
78 """Update a wrapper function to look like the wrapped function
80 wrapper is the function to be updated
81 wrapped is the original function
82 assigned is a tuple naming the attributes assigned directly
83 from the wrapped function to the wrapper function (defaults to
84 functools.WRAPPER_ASSIGNMENTS)
85 updated is a tuple naming the attributes off the wrapper that
86 are updated with the corresponding attribute from the wrapped
87 function (defaults to functools.WRAPPER_UPDATES)
90 setattr(wrapper
, attr
, getattr(wrapped
, attr
))
92 getattr(wrapper
, attr
).update(getattr(wrapped
, attr
))
93 # Return the wrapper so this can be used as a decorator via curry()
97 assigned
= WRAPPER_ASSIGNMENTS
,
98 updated
= WRAPPER_UPDATES
):
99 """Decorator factory to apply update_wrapper() to a wrapper function
101 Returns a decorator that invokes update_wrapper() with the decorated
102 function as the wrapper argument and the arguments to wraps() as the
103 remaining arguments. Default arguments are as for update_wrapper().
104 This is a convenience function to simplify applying curry() to
107 return curry(update_wrapper
, wrapped
=wrapped
,
108 assigned
=assigned
, updated
=updated
)
110 ### End from Python 2.5 functools.py ##########################################
112 def memoize(func
, cache
, num_args
):
114 Wrap a function so that results for any argument tuple are stored in
115 'cache'. Note that the args to the function must be usable as dictionary
118 Only the first num_args are considered when creating the key.
121 mem_args
= args
[:num_args
]
122 if mem_args
in cache
:
123 return cache
[mem_args
]
125 cache
[mem_args
] = result
127 return wraps(func
)(wrapper
)
129 class Promise(object):
131 This is just a base class for the proxy class created in
132 the closure of the lazy function. It can be used to recognize
137 def lazy(func
, *resultclasses
):
139 Turns any callable into a lazy evaluated callable. You need to give result
140 classes or types -- at least one is needed so that the automatic forcing of
141 the lazy evaluation code is triggered. Results are not memoized; the
142 function is evaluated on every access.
145 class __proxy__(Promise
):
147 Encapsulate a function call and act as a proxy for methods that are
148 called on the result of that function. The function is not evaluated
149 until one of the methods on the result is called.
153 def __init__(self
, args
, kw
):
157 if self
.__dispatch
is None:
158 self
.__prepare
_class
__()
160 def __reduce__(self
):
162 _lazy_proxy_unpickle
,
163 (self
.__func
, self
.__args
, self
.__kw
) + resultclasses
166 def __prepare_class__(cls
):
168 for resultclass
in resultclasses
:
169 cls
.__dispatch
[resultclass
] = {}
170 for (k
, v
) in resultclass
.__dict
__.items():
171 # All __promise__ return the same wrapper method, but they
172 # also do setup, inserting the method into the dispatch
174 meth
= cls
.__promise
__(resultclass
, k
, v
)
177 setattr(cls
, k
, meth
)
178 cls
._delegate
_str
= str in resultclasses
179 cls
._delegate
_unicode
= unicode in resultclasses
180 assert not (cls
._delegate
_str
and cls
._delegate
_unicode
), "Cannot call lazy() with both str and unicode return types."
181 if cls
._delegate
_unicode
:
182 cls
.__unicode
__ = cls
.__unicode
_cast
183 elif cls
._delegate
_str
:
184 cls
.__str
__ = cls
.__str
_cast
185 __prepare_class__
= classmethod(__prepare_class__
)
187 def __promise__(cls
, klass
, funcname
, func
):
188 # Builds a wrapper around some magic method and registers that magic
189 # method for the given type and method name.
190 def __wrapper__(self
, *args
, **kw
):
191 # Automatically triggers the evaluation of a lazy value and
192 # applies the given magic method of the result type.
193 res
= self
.__func
(*self
.__args
, **self
.__kw
)
194 for t
in type(res
).mro():
195 if t
in self
.__dispatch
:
196 return self
.__dispatch
[t
][funcname
](res
, *args
, **kw
)
197 raise TypeError("Lazy object returned unexpected type.")
199 if klass
not in cls
.__dispatch
:
200 cls
.__dispatch
[klass
] = {}
201 cls
.__dispatch
[klass
][funcname
] = func
203 __promise__
= classmethod(__promise__
)
205 def __unicode_cast(self
):
206 return self
.__func
(*self
.__args
, **self
.__kw
)
208 def __str_cast(self
):
209 return str(self
.__func
(*self
.__args
, **self
.__kw
))
211 def __cmp__(self
, rhs
):
212 if self
._delegate
_str
:
213 s
= str(self
.__func
(*self
.__args
, **self
.__kw
))
214 elif self
._delegate
_unicode
:
215 s
= unicode(self
.__func
(*self
.__args
, **self
.__kw
))
217 s
= self
.__func
(*self
.__args
, **self
.__kw
)
218 if isinstance(rhs
, Promise
):
223 def __mod__(self
, rhs
):
224 if self
._delegate
_str
:
225 return str(self
) % rhs
226 elif self
._delegate
_unicode
:
227 return unicode(self
) % rhs
229 raise AssertionError('__mod__ not supported for non-string types')
231 def __deepcopy__(self
, memo
):
232 # Instances of this class are effectively immutable. It's just a
233 # collection of functions. So we don't need to do anything
234 # complicated for copying.
235 memo
[id(self
)] = self
238 def __wrapper__(*args
, **kw
):
239 # Creates the proxy object, instead of the actual value.
240 return __proxy__(args
, kw
)
242 return wraps(func
)(__wrapper__
)
244 def _lazy_proxy_unpickle(func
, args
, kwargs
, *resultclasses
):
245 return lazy(func
, *resultclasses
)(*args
, **kwargs
)
247 def allow_lazy(func
, *resultclasses
):
249 A decorator that allows a function to be called with one or more lazy
250 arguments. If none of the args are lazy, the function is evaluated
251 immediately, otherwise a __proxy__ is returned that will evaluate the
252 function when needed.
254 def wrapper(*args
, **kwargs
):
255 for arg
in list(args
) + kwargs
.values():
256 if isinstance(arg
, Promise
):
259 return func(*args
, **kwargs
)
260 return lazy(func
, *resultclasses
)(*args
, **kwargs
)
261 return wraps(func
)(wrapper
)
263 class LazyObject(object):
265 A wrapper for another class that can be used to delay instantiation of the
268 By subclassing, you have the opportunity to intercept and alter the
269 instantiation. If you don't need to do that, use SimpleLazyObject.
274 def __getattr__(self
, name
):
275 if self
._wrapped
is None:
277 return getattr(self
._wrapped
, name
)
279 def __setattr__(self
, name
, value
):
280 if name
== "_wrapped":
281 # Assign to __dict__ to avoid infinite __setattr__ loops.
282 self
.__dict
__["_wrapped"] = value
284 if self
._wrapped
is None:
286 setattr(self
._wrapped
, name
, value
)
288 def __delattr__(self
, name
):
289 if name
== "_wrapped":
290 raise TypeError("can't delete _wrapped.")
291 if self
._wrapped
is None:
293 delattr(self
._wrapped
, name
)
297 Must be implemented by subclasses to initialise the wrapped object.
299 raise NotImplementedError
301 # introspection support:
302 __members__
= property(lambda self
: self
.__dir
__())
305 if self
._wrapped
is None:
307 return dir(self
._wrapped
)
309 class SimpleLazyObject(LazyObject
):
311 A lazy object initialised from any function.
313 Designed for compound objects of unknown type. For builtins or objects of
314 known type, use django.utils.functional.lazy.
316 def __init__(self
, func
):
318 Pass in a callable that returns the object to be wrapped.
320 If copies are made of the resulting SimpleLazyObject, which can happen
321 in various circumstances within Django, then you must ensure that the
322 callable can be safely run more than once and will return the same
325 self
.__dict
__['_setupfunc'] = func
326 # For some reason, we have to inline LazyObject.__init__ here to avoid
331 if self
._wrapped
is None: self
._setup
()
332 return str(self
._wrapped
)
334 def __unicode__(self
):
335 if self
._wrapped
is None: self
._setup
()
336 return unicode(self
._wrapped
)
338 def __deepcopy__(self
, memo
):
339 if self
._wrapped
is None:
340 # We have to use SimpleLazyObject, not self.__class__, because the
342 result
= SimpleLazyObject(self
._setupfunc
)
343 memo
[id(self
)] = result
346 # Changed to use deepcopy from copycompat, instead of copy
348 from django
.utils
.copycompat
import deepcopy
349 return deepcopy(self
._wrapped
, memo
)
351 # Need to pretend to be the wrapped class, for the sake of objects that care
352 # about this (especially in equality tests)
353 def __get_class(self
):
354 if self
._wrapped
is None: self
._setup
()
355 return self
._wrapped
.__class
__
356 __class__
= property(__get_class
)
358 def __eq__(self
, other
):
359 if self
._wrapped
is None: self
._setup
()
360 return self
._wrapped
== other
363 if self
._wrapped
is None: self
._setup
()
364 return hash(self
._wrapped
)
367 self
._wrapped
= self
._setupfunc
()