diff options
| author | Justin Bronn <jbronn@gmail.com> | 2007-08-26 01:10:53 +0000 |
|---|---|---|
| committer | Justin Bronn <jbronn@gmail.com> | 2007-08-26 01:10:53 +0000 |
| commit | 2052b508eb92c62fc0678efd4936c5ec1e0e735b (patch) | |
| tree | e510109b74b28c8ccef5f6955727cb9dce3da655 /django/utils/functional.py | |
| parent | a7297a255f4bb86f608ea251e00253d18c31d9d4 (diff) | |
gis: Made necessary modifications for unicode, manage refactor, backend refactor and merged 5584-6000 via svnmerge from [repos:django/trunk trunk].
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@6018 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/utils/functional.py')
| -rw-r--r-- | django/utils/functional.py | 67 |
1 files changed, 61 insertions, 6 deletions
diff --git a/django/utils/functional.py b/django/utils/functional.py index a57546ad2d..734704f6f3 100644 --- a/django/utils/functional.py +++ b/django/utils/functional.py @@ -3,22 +3,24 @@ def curry(_curried_func, *args, **kwargs): return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs)) return _curried -def memoize(func, cache): +def memoize(func, cache, num_args): """ Wrap a function so that results for any argument tuple are stored in 'cache'. Note that the args to the function must be usable as dictionary keys. + + Only the first num_args are considered when creating the key. """ def wrapper(*args): - if args in cache: - return cache[args] - + mem_args = args[:num_args] + if mem_args in cache: + return cache[mem_args] result = func(*args) - cache[args] = result + cache[mem_args] = result return result return wrapper -class Promise: +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 @@ -47,6 +49,11 @@ def lazy(func, *resultclasses): self.__dispatch[resultclass] = {} for (k, v) in resultclass.__dict__.items(): setattr(self, k, self.__promise__(resultclass, k, v)) + self._delegate_str = str in resultclasses + self._delegate_unicode = unicode in resultclasses + assert not (self._delegate_str and self._delegate_unicode), "Cannot call lazy() with both str and unicode return types." + if self._delegate_unicode: + self.__unicode__ = self.__unicode_cast def __promise__(self, klass, funcname, func): # Builds a wrapper around some magic method and registers that magic @@ -62,8 +69,56 @@ def lazy(func, *resultclasses): self.__dispatch[klass][funcname] = func return __wrapper__ + def __unicode_cast(self): + return self.__func(*self.__args, **self.__kw) + + def __str__(self): + # As __str__ is always a method on the type (class), it is looked + # up (and found) there first. So we can't just assign to it on a + # per-instance basis in __init__. + if self._delegate_str: + return str(self.__func(*self.__args, **self.__kw)) + else: + return Promise.__str__(self) + + def __cmp__(self, rhs): + if self._delegate_str: + s = str(self.__func(*self.__args, **self.__kw)) + elif self._delegate_unicode: + s = unicode(self.__func(*self.__args, **self.__kw)) + else: + s = self.__func(*self.__args, **self.__kw) + if isinstance(rhs, Promise): + return -cmp(rhs, s) + else: + return cmp(s, rhs) + + def __mod__(self, rhs): + if self._delegate_str: + return str(self) % rhs + elif self._delegate_unicode: + return unicode(self) % rhs + else: + raise AssertionError('__mod__ not supported for non-string types') + def __wrapper__(*args, **kw): # Creates the proxy object, instead of the actual value. return __proxy__(args, kw) return __wrapper__ + +def allow_lazy(func, *resultclasses): + """ + A decorator that allows a function to be called with one or more lazy + arguments. If none of the args are lazy, the function is evaluated + immediately, otherwise a __proxy__ is returned that will evaluate the + function when needed. + """ + def wrapper(*args, **kwargs): + for arg in list(args) + kwargs.values(): + if isinstance(arg, Promise): + break + else: + return func(*args, **kwargs) + return lazy(func, *resultclasses)(*args, **kwargs) + return wrapper |
