summaryrefslogtreecommitdiff
path: root/django/utils/functional.py
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2013-06-07 11:15:34 +0100
committerAndrew Godwin <andrew@aeracode.org>2013-06-07 11:15:34 +0100
commit3c296382b8dea5de7f4e1e11b66bd7cecaf2ee51 (patch)
tree0ca12593be82971691ffca01a836d00d3fcb3bd4 /django/utils/functional.py
parent7609e0b42e0014a6ad0adf9dafc7018cb268070e (diff)
parent357d62d9f2972bf1bc21e5835c12c849143e06af (diff)
Merge remote-tracking branch 'core/master' into schema-alteration
Conflicts: django/db/models/fields/related.py
Diffstat (limited to 'django/utils/functional.py')
-rw-r--r--django/utils/functional.py19
1 files changed, 14 insertions, 5 deletions
diff --git a/django/utils/functional.py b/django/utils/functional.py
index cab74886d3..0606c775ef 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -4,6 +4,7 @@ from functools import wraps
import sys
from django.utils import six
+from django.utils.six.moves import copyreg
# You can't trivially replace this with `functools.partial` because this binds
@@ -328,15 +329,23 @@ class SimpleLazyObject(LazyObject):
self._setup()
return self._wrapped.__dict__
- # Python 3.3 will call __reduce__ when pickling; these methods are needed
- # to serialize and deserialize correctly. They are not called in earlier
- # versions of Python.
+ # Python 3.3 will call __reduce__ when pickling; this method is needed
+ # to serialize and deserialize correctly.
@classmethod
def __newobj__(cls, *args):
return cls.__new__(cls, *args)
- def __reduce__(self):
- return (self.__newobj__, (self.__class__,), self.__getstate__())
+ def __reduce_ex__(self, proto):
+ if proto >= 2:
+ # On Py3, since the default protocol is 3, pickle uses the
+ # ``__newobj__`` method (& more efficient opcodes) for writing.
+ return (self.__newobj__, (self.__class__,), self.__getstate__())
+ else:
+ # On Py2, the default protocol is 0 (for back-compat) & the above
+ # code fails miserably (see regression test). Instead, we return
+ # exactly what's returned if there's no ``__reduce__`` method at
+ # all.
+ return (copyreg._reconstructor, (self.__class__, object, None), self.__getstate__())
# Return a meaningful representation of the lazy object for debugging
# without evaluating the wrapped object.