From 82e0cd15711c7171aed7af5e481967cc721c9642 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 8 Feb 2015 12:14:30 -0600 Subject: [PATCH] Optimized allow_lazy() by not generating a new lazy wrapper on each invocation. This dramatically improves performance on PyPy. The following benchmark: python -mtimeit -s "from django.utils.functional import allow_lazy; from django.utils.translation import ugettext_lazy; f = allow_lazy(lambda s: s, str)" "f(ugettext_lazy('abc'))" goes from 390us per loop to 165us. --- django/utils/functional.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/django/utils/functional.py b/django/utils/functional.py index 50ff8824f9..ddfd882e51 100644 --- a/django/utils/functional.py +++ b/django/utils/functional.py @@ -180,6 +180,8 @@ def allow_lazy(func, *resultclasses): immediately, otherwise a __proxy__ is returned that will evaluate the function when needed. """ + lazy_func = lazy(func, *resultclasses) + @wraps(func) def wrapper(*args, **kwargs): for arg in list(args) + list(six.itervalues(kwargs)): @@ -187,7 +189,7 @@ def allow_lazy(func, *resultclasses): break else: return func(*args, **kwargs) - return lazy(func, *resultclasses)(*args, **kwargs) + return lazy_func(*args, **kwargs) return wrapper empty = object()