mirror of https://github.com/django/django.git
Fixed #6217 -- Reduced the memory used by each ugettext_lazy() call.
Thanks to Jakub Wilk for analysis and the initial patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@8120 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
7d1c147bb4
commit
6a287ed946
1
AUTHORS
1
AUTHORS
|
@ -407,6 +407,7 @@ answer newbie questions, and generally made Django that much better:
|
||||||
charly.wilhelm@gmail.com
|
charly.wilhelm@gmail.com
|
||||||
Rachel Willmer <http://www.willmer.com/kb/>
|
Rachel Willmer <http://www.willmer.com/kb/>
|
||||||
Gary Wilson <gary.wilson@gmail.com>
|
Gary Wilson <gary.wilson@gmail.com>
|
||||||
|
Jakub Wilk <ubanus@users.sf.net>
|
||||||
Jakub Wiśniowski <restless.being@gmail.com>
|
Jakub Wiśniowski <restless.being@gmail.com>
|
||||||
Maciej Wiśniowski <pigletto@gmail.com>
|
Maciej Wiśniowski <pigletto@gmail.com>
|
||||||
wojtek
|
wojtek
|
||||||
|
|
|
@ -191,7 +191,8 @@ class Field(object):
|
||||||
def set_attributes_from_name(self, name):
|
def set_attributes_from_name(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.attname, self.column = self.get_attname_column()
|
self.attname, self.column = self.get_attname_column()
|
||||||
self.verbose_name = self.verbose_name or (name and name.replace('_', ' '))
|
if self.verbose_name is None and name:
|
||||||
|
self.verbose_name = name.replace('_', ' ')
|
||||||
|
|
||||||
def contribute_to_class(self, cls, name):
|
def contribute_to_class(self, cls, name):
|
||||||
self.set_attributes_from_name(name)
|
self.set_attributes_from_name(name)
|
||||||
|
|
|
@ -148,42 +148,51 @@ def lazy(func, *resultclasses):
|
||||||
function is evaluated on every access.
|
function is evaluated on every access.
|
||||||
"""
|
"""
|
||||||
class __proxy__(Promise):
|
class __proxy__(Promise):
|
||||||
# This inner class encapsulates the code that should be evaluated
|
"""
|
||||||
# lazily. On calling of one of the magic methods it will force
|
Encapsulate a function call and act as a proxy for methods that are
|
||||||
# the evaluation and store the result. Afterwards, the result
|
called on the result of that function. The function is not evaluated
|
||||||
# is delivered directly. So the result is memoized.
|
until one of the methods on the result is called.
|
||||||
|
"""
|
||||||
|
__dispatch = None
|
||||||
|
|
||||||
def __init__(self, args, kw):
|
def __init__(self, args, kw):
|
||||||
self.__func = func
|
self.__func = func
|
||||||
self.__args = args
|
self.__args = args
|
||||||
self.__kw = kw
|
self.__kw = kw
|
||||||
self.__dispatch = {}
|
if self.__dispatch is None:
|
||||||
for resultclass in resultclasses:
|
self.__prepare_class__()
|
||||||
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:
|
|
||||||
# Each call to lazy() makes a new __proxy__ object, so this
|
|
||||||
# doesn't interfere with any other lazy() results.
|
|
||||||
__proxy__.__unicode__ = __proxy__.__unicode_cast
|
|
||||||
elif self._delegate_str:
|
|
||||||
__proxy__.__str__ = __proxy__.__str_cast
|
|
||||||
|
|
||||||
def __promise__(self, klass, funcname, func):
|
def __prepare_class__(cls):
|
||||||
|
cls.__dispatch = {}
|
||||||
|
for resultclass in resultclasses:
|
||||||
|
cls.__dispatch[resultclass] = {}
|
||||||
|
for (k, v) in resultclass.__dict__.items():
|
||||||
|
if hasattr(cls, k):
|
||||||
|
continue
|
||||||
|
setattr(cls, k, cls.__promise__(resultclass, k, v))
|
||||||
|
cls._delegate_str = str in resultclasses
|
||||||
|
cls._delegate_unicode = unicode in resultclasses
|
||||||
|
assert not (cls._delegate_str and cls._delegate_unicode), "Cannot call lazy() with both str and unicode return types."
|
||||||
|
if cls._delegate_unicode:
|
||||||
|
cls.__unicode__ = cls.__unicode_cast
|
||||||
|
elif cls._delegate_str:
|
||||||
|
cls.__str__ = cls.__str_cast
|
||||||
|
__prepare_class__ = classmethod(__prepare_class__)
|
||||||
|
|
||||||
|
def __promise__(cls, klass, funcname, func):
|
||||||
# Builds a wrapper around some magic method and registers that magic
|
# Builds a wrapper around some magic method and registers that magic
|
||||||
# method for the given type and method name.
|
# method for the given type and method name.
|
||||||
def __wrapper__(*args, **kw):
|
def __wrapper__(self, *args, **kw):
|
||||||
# Automatically triggers the evaluation of a lazy value and
|
# Automatically triggers the evaluation of a lazy value and
|
||||||
# applies the given magic method of the result type.
|
# applies the given magic method of the result type.
|
||||||
res = self.__func(*self.__args, **self.__kw)
|
res = self.__func(*self.__args, **self.__kw)
|
||||||
return self.__dispatch[type(res)][funcname](res, *args, **kw)
|
return self.__dispatch[type(res)][funcname](res, *args, **kw)
|
||||||
|
|
||||||
if klass not in self.__dispatch:
|
if klass not in cls.__dispatch:
|
||||||
self.__dispatch[klass] = {}
|
cls.__dispatch[klass] = {}
|
||||||
self.__dispatch[klass][funcname] = func
|
cls.__dispatch[klass][funcname] = func
|
||||||
return __wrapper__
|
return __wrapper__
|
||||||
|
__promise__ = classmethod(__promise__)
|
||||||
|
|
||||||
def __unicode_cast(self):
|
def __unicode_cast(self):
|
||||||
return self.__func(*self.__args, **self.__kw)
|
return self.__func(*self.__args, **self.__kw)
|
||||||
|
|
Loading…
Reference in New Issue