From ee86bf24d269869012d5538c22d37588cec68685 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 8 Feb 2015 12:14:30 -0600 Subject: [PATCH] [1.8.x] 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. Backport of 82e0cd15711c7171aed7af5e481967cc721c9642 from master --- 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 37cc7c7f0f..628e02e8d8 100644 --- a/django/utils/functional.py +++ b/django/utils/functional.py @@ -205,6 +205,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)): @@ -212,7 +214,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()