summaryrefslogtreecommitdiff
path: root/django/utils/functional.py
diff options
context:
space:
mode:
authorJustin Bronn <jbronn@gmail.com>2007-08-26 01:10:53 +0000
committerJustin Bronn <jbronn@gmail.com>2007-08-26 01:10:53 +0000
commit2052b508eb92c62fc0678efd4936c5ec1e0e735b (patch)
treee510109b74b28c8ccef5f6955727cb9dce3da655 /django/utils/functional.py
parenta7297a255f4bb86f608ea251e00253d18c31d9d4 (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.py67
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