]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
In save_newobj(), if an object's __getnewargs__ and __getstate__ are
authorGuido van Rossum <guido@python.org>
Thu, 30 Jan 2003 05:39:04 +0000 (05:39 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 30 Jan 2003 05:39:04 +0000 (05:39 +0000)
the same function, don't save the state or write a BUILD opcode.  This
is so that a type (e.g. datetime :-) can support protocol 2 using
__getnewargs__ while also supporting protocol 0 and 1 using
__getstate__.  (Without this, the state would be pickled twice with
protocol 2, unless __getstate__ is defined to return None, which
breaks protocol 0 and 1.)

Lib/pickle.py

index 9630d33942352974f35986b0a06efe368e5ca881..d62a5bd69145d70548dd53eb4c2f3dc87572cbbf 100644 (file)
@@ -416,6 +416,29 @@ class Pickler:
                 write(SETITEM)
 
         getstate = getattr(obj, "__getstate__", None)
+
+        # A class may define both __getstate__ and __getnewargs__.
+        # If they are the same function, we ignore __getstate__.
+        # This is for the benefit of protocols 0 and 1, which don't
+        # use __getnewargs__.  Note that the only way to make them
+        # the same function is something like this:
+        #
+        #   class C(object):
+        #       def __getstate__(self):
+        #           return ...
+        #       __getnewargs__ = __getstate__
+        #
+        # No tricks are needed to ignore __setstate__; it simply
+        # won't be called when we don't generate BUILD.
+        # Also note that when __getnewargs__ and __getstate__ are
+        # the same function, we don't do the default thing of
+        # looking for __dict__ and slots either -- it is assumed
+        # that __getnewargs__ returns all the state there is
+        # (which should be a safe assumption since __getstate__
+        # returns the *same* state).
+        if getstate and getstate == getnewargs:
+            return
+
         if getstate:
             try:
                 state = getstate()