|
1 # License for code in this file that was taken from Python 2.5. |
|
2 |
|
3 # PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 |
|
4 # -------------------------------------------- |
|
5 # |
|
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. |
|
10 # |
|
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. |
|
20 # |
|
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. |
|
26 # |
|
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. |
|
33 # |
|
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. |
|
38 # |
|
39 # 6. This License Agreement will automatically terminate upon a material |
|
40 # breach of its terms and conditions. |
|
41 # |
|
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. |
|
47 # |
|
48 # 8. By copying, installing or otherwise using Python, Licensee |
|
49 # agrees to be bound by the terms and conditions of this License |
|
50 # Agreement. |
|
51 |
|
52 |
|
53 def curry(_curried_func, *args, **kwargs): |
|
54 def _curried(*moreargs, **morekwargs): |
|
55 return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs)) |
|
56 return _curried |
|
57 |
|
58 ### Begin from Python 2.5 functools.py ######################################## |
|
59 |
|
60 # Summary of changes made to the Python 2.5 code below: |
|
61 # * swapped ``partial`` for ``curry`` to maintain backwards-compatibility |
|
62 # in Django. |
|
63 |
|
64 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation. |
|
65 # All Rights Reserved. |
|
66 |
|
67 ############################################################################### |
|
68 |
|
69 # update_wrapper() and wraps() are tools to help write |
|
70 # wrapper functions that can handle naive introspection |
|
71 |
|
72 WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__') |
|
73 WRAPPER_UPDATES = ('__dict__',) |
|
74 def update_wrapper(wrapper, |
|
75 wrapped, |
|
76 assigned = WRAPPER_ASSIGNMENTS, |
|
77 updated = WRAPPER_UPDATES): |
|
78 """Update a wrapper function to look like the wrapped function |
|
79 |
|
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) |
|
88 """ |
|
89 for attr in assigned: |
|
90 setattr(wrapper, attr, getattr(wrapped, attr)) |
|
91 for attr in updated: |
|
92 getattr(wrapper, attr).update(getattr(wrapped, attr)) |
|
93 # Return the wrapper so this can be used as a decorator via curry() |
|
94 return wrapper |
|
95 |
|
96 def wraps(wrapped, |
|
97 assigned = WRAPPER_ASSIGNMENTS, |
|
98 updated = WRAPPER_UPDATES): |
|
99 """Decorator factory to apply update_wrapper() to a wrapper function |
|
100 |
|
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 |
|
105 update_wrapper(). |
|
106 """ |
|
107 return curry(update_wrapper, wrapped=wrapped, |
|
108 assigned=assigned, updated=updated) |
|
109 |
|
110 ### End from Python 2.5 functools.py ########################################## |
|
111 |
|
112 def memoize(func, cache, num_args): |
|
113 """ |
|
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 |
|
116 keys. |
|
117 |
|
118 Only the first num_args are considered when creating the key. |
|
119 """ |
|
120 def wrapper(*args): |
|
121 mem_args = args[:num_args] |
|
122 if mem_args in cache: |
|
123 return cache[mem_args] |
|
124 result = func(*args) |
|
125 cache[mem_args] = result |
|
126 return result |
|
127 return wraps(func)(wrapper) |
|
128 |
|
129 class Promise(object): |
|
130 """ |
|
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 |
|
133 promises in code. |
|
134 """ |
|
135 pass |
|
136 |
|
137 def lazy(func, *resultclasses): |
|
138 """ |
|
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. |
|
143 """ |
|
144 |
|
145 class __proxy__(Promise): |
|
146 """ |
|
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. |
|
150 """ |
|
151 __dispatch = None |
|
152 |
|
153 def __init__(self, args, kw): |
|
154 self.__func = func |
|
155 self.__args = args |
|
156 self.__kw = kw |
|
157 if self.__dispatch is None: |
|
158 self.__prepare_class__() |
|
159 |
|
160 def __reduce__(self): |
|
161 return ( |
|
162 _lazy_proxy_unpickle, |
|
163 (self.__func, self.__args, self.__kw) + resultclasses |
|
164 ) |
|
165 |
|
166 def __prepare_class__(cls): |
|
167 cls.__dispatch = {} |
|
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 |
|
173 # dict. |
|
174 meth = cls.__promise__(resultclass, k, v) |
|
175 if hasattr(cls, k): |
|
176 continue |
|
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__) |
|
186 |
|
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.") |
|
198 |
|
199 if klass not in cls.__dispatch: |
|
200 cls.__dispatch[klass] = {} |
|
201 cls.__dispatch[klass][funcname] = func |
|
202 return __wrapper__ |
|
203 __promise__ = classmethod(__promise__) |
|
204 |
|
205 def __unicode_cast(self): |
|
206 return self.__func(*self.__args, **self.__kw) |
|
207 |
|
208 def __str_cast(self): |
|
209 return str(self.__func(*self.__args, **self.__kw)) |
|
210 |
|
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)) |
|
216 else: |
|
217 s = self.__func(*self.__args, **self.__kw) |
|
218 if isinstance(rhs, Promise): |
|
219 return -cmp(rhs, s) |
|
220 else: |
|
221 return cmp(s, rhs) |
|
222 |
|
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 |
|
228 else: |
|
229 raise AssertionError('__mod__ not supported for non-string types') |
|
230 |
|
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 |
|
236 return self |
|
237 |
|
238 def __wrapper__(*args, **kw): |
|
239 # Creates the proxy object, instead of the actual value. |
|
240 return __proxy__(args, kw) |
|
241 |
|
242 return wraps(func)(__wrapper__) |
|
243 |
|
244 def _lazy_proxy_unpickle(func, args, kwargs, *resultclasses): |
|
245 return lazy(func, *resultclasses)(*args, **kwargs) |
|
246 |
|
247 def allow_lazy(func, *resultclasses): |
|
248 """ |
|
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. |
|
253 """ |
|
254 def wrapper(*args, **kwargs): |
|
255 for arg in list(args) + kwargs.values(): |
|
256 if isinstance(arg, Promise): |
|
257 break |
|
258 else: |
|
259 return func(*args, **kwargs) |
|
260 return lazy(func, *resultclasses)(*args, **kwargs) |
|
261 return wraps(func)(wrapper) |
|
262 |
|
263 class LazyObject(object): |
|
264 """ |
|
265 A wrapper for another class that can be used to delay instantiation of the |
|
266 wrapped class. |
|
267 |
|
268 By subclassing, you have the opportunity to intercept and alter the |
|
269 instantiation. If you don't need to do that, use SimpleLazyObject. |
|
270 """ |
|
271 def __init__(self): |
|
272 self._wrapped = None |
|
273 |
|
274 def __getattr__(self, name): |
|
275 if self._wrapped is None: |
|
276 self._setup() |
|
277 return getattr(self._wrapped, name) |
|
278 |
|
279 def __setattr__(self, name, value): |
|
280 if name == "_wrapped": |
|
281 # Assign to __dict__ to avoid infinite __setattr__ loops. |
|
282 self.__dict__["_wrapped"] = value |
|
283 else: |
|
284 if self._wrapped is None: |
|
285 self._setup() |
|
286 setattr(self._wrapped, name, value) |
|
287 |
|
288 def __delattr__(self, name): |
|
289 if name == "_wrapped": |
|
290 raise TypeError("can't delete _wrapped.") |
|
291 if self._wrapped is None: |
|
292 self._setup() |
|
293 delattr(self._wrapped, name) |
|
294 |
|
295 def _setup(self): |
|
296 """ |
|
297 Must be implemented by subclasses to initialise the wrapped object. |
|
298 """ |
|
299 raise NotImplementedError |
|
300 |
|
301 # introspection support: |
|
302 __members__ = property(lambda self: self.__dir__()) |
|
303 |
|
304 def __dir__(self): |
|
305 if self._wrapped is None: |
|
306 self._setup() |
|
307 return dir(self._wrapped) |
|
308 |
|
309 class SimpleLazyObject(LazyObject): |
|
310 """ |
|
311 A lazy object initialised from any function. |
|
312 |
|
313 Designed for compound objects of unknown type. For builtins or objects of |
|
314 known type, use django.utils.functional.lazy. |
|
315 """ |
|
316 def __init__(self, func): |
|
317 """ |
|
318 Pass in a callable that returns the object to be wrapped. |
|
319 |
|
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 |
|
323 value. |
|
324 """ |
|
325 self.__dict__['_setupfunc'] = func |
|
326 # For some reason, we have to inline LazyObject.__init__ here to avoid |
|
327 # recursion |
|
328 self._wrapped = None |
|
329 |
|
330 def __str__(self): |
|
331 if self._wrapped is None: self._setup() |
|
332 return str(self._wrapped) |
|
333 |
|
334 def __unicode__(self): |
|
335 if self._wrapped is None: self._setup() |
|
336 return unicode(self._wrapped) |
|
337 |
|
338 def __deepcopy__(self, memo): |
|
339 if self._wrapped is None: |
|
340 # We have to use SimpleLazyObject, not self.__class__, because the |
|
341 # latter is proxied. |
|
342 result = SimpleLazyObject(self._setupfunc) |
|
343 memo[id(self)] = result |
|
344 return result |
|
345 else: |
|
346 # Changed to use deepcopy from copycompat, instead of copy |
|
347 # For Python 2.4. |
|
348 from django.utils.copycompat import deepcopy |
|
349 return deepcopy(self._wrapped, memo) |
|
350 |
|
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) |
|
357 |
|
358 def __eq__(self, other): |
|
359 if self._wrapped is None: self._setup() |
|
360 return self._wrapped == other |
|
361 |
|
362 def __hash__(self): |
|
363 if self._wrapped is None: self._setup() |
|
364 return hash(self._wrapped) |
|
365 |
|
366 def _setup(self): |
|
367 self._wrapped = self._setupfunc() |