[Python-checkins] cpython (merge 3.3 -> default): Issue #6477: Merge with 3.3.

alexandre.vassalotti python-checkins at python.org
Sun Dec 1 01:21:44 CET 2013


http://hg.python.org/cpython/rev/ff56f48b3277
changeset:   87666:ff56f48b3277
parent:      87664:5469e1a68dbd
parent:      87665:16eba94d3cfe
user:        Alexandre Vassalotti <alexandre at peadrop.com>
date:        Sat Nov 30 16:21:20 2013 -0800
summary:
  Issue #6477: Merge with 3.3.

files:
  Include/object.h         |   3 ++
  Lib/pickle.py            |  11 ++++++++-
  Lib/test/pickletester.py |   9 +++++++
  Misc/NEWS                |   3 ++
  Modules/_pickle.c        |  32 +++++++++++++++++++++++++++-
  Objects/object.c         |   4 +-
  6 files changed, 58 insertions(+), 4 deletions(-)


diff --git a/Include/object.h b/Include/object.h
--- a/Include/object.h
+++ b/Include/object.h
@@ -829,6 +829,9 @@
 PyAPI_FUNC(void) Py_IncRef(PyObject *);
 PyAPI_FUNC(void) Py_DecRef(PyObject *);
 
+PyAPI_DATA(PyTypeObject) PyNone_Type;
+PyAPI_DATA(PyTypeObject) PyNotImplemented_Type;
+
 /*
 _Py_NoneStruct is an object of undefined type which can be used in contexts
 where NULL (nil) is not suitable (since NULL often means 'error').
diff --git a/Lib/pickle.py b/Lib/pickle.py
--- a/Lib/pickle.py
+++ b/Lib/pickle.py
@@ -954,8 +954,17 @@
 
         self.memoize(obj)
 
+    def save_type(self, obj):
+        if obj is type(None):
+            return self.save_reduce(type, (None,), obj=obj)
+        elif obj is type(NotImplemented):
+            return self.save_reduce(type, (NotImplemented,), obj=obj)
+        elif obj is type(...):
+            return self.save_reduce(type, (...,), obj=obj)
+        return self.save_global(obj)
+
     dispatch[FunctionType] = save_global
-    dispatch[type] = save_global
+    dispatch[type] = save_type
 
 
 # Unpickling machinery
diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -804,6 +804,15 @@
             u = self.loads(s)
             self.assertIs(NotImplemented, u)
 
+    def test_singleton_types(self):
+        # Issue #6477: Test that types of built-in singletons can be pickled.
+        singletons = [None, ..., NotImplemented]
+        for singleton in singletons:
+            for proto in protocols:
+                s = self.dumps(type(singleton), proto)
+                u = self.loads(s)
+                self.assertIs(type(singleton), u)
+
     # Tests for protocol 2
 
     def test_proto(self):
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -33,6 +33,9 @@
 - Fixed _pickle.Unpickler to not fail when loading empty strings as
   persistent IDs.
 
+- Issue #6477: Added support for pickling the types of built-in singletons
+  (i.e., Ellipsis, NotImplemented, None).
+
 - ssl.create_default_context() sets OP_NO_COMPRESSION to prevent CRIME.
 
 - Issue #19802: Add socket.SO_PRIORITY.
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -3288,6 +3288,36 @@
 }
 
 static int
+save_singleton_type(PicklerObject *self, PyObject *obj, PyObject *singleton)
+{
+    PyObject *reduce_value;
+    int status;
+
+    reduce_value = Py_BuildValue("O(O)", &PyType_Type, singleton);
+    if (reduce_value == NULL) {
+        return -1;
+    }
+    status = save_reduce(self, reduce_value, obj);
+    Py_DECREF(reduce_value);
+    return status;
+}
+
+static int
+save_type(PicklerObject *self, PyObject *obj)
+{
+    if (obj == (PyObject *)&PyNone_Type) {
+        return save_singleton_type(self, obj, Py_None);
+    }
+    else if (obj == (PyObject *)&PyEllipsis_Type) {
+        return save_singleton_type(self, obj, Py_Ellipsis);
+    }
+    else if (obj == (PyObject *)&PyNotImplemented_Type) {
+        return save_singleton_type(self, obj, Py_NotImplemented);
+    }
+    return save_global(self, obj, NULL);
+}
+
+static int
 save_pers(PicklerObject *self, PyObject *obj, PyObject *func)
 {
     PyObject *pid = NULL;
@@ -3696,7 +3726,7 @@
         goto done;
     }
     else if (type == &PyType_Type) {
-        status = save_global(self, obj, NULL);
+        status = save_type(self, obj);
         goto done;
     }
     else if (type == &PyFunction_Type) {
diff --git a/Objects/object.c b/Objects/object.c
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1409,7 +1409,7 @@
     0,                          /* nb_index */
 };
 
-static PyTypeObject PyNone_Type = {
+PyTypeObject PyNone_Type = {
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     "NoneType",
     0,
@@ -1494,7 +1494,7 @@
     Py_FatalError("deallocating NotImplemented");
 }
 
-static PyTypeObject PyNotImplemented_Type = {
+PyTypeObject PyNotImplemented_Type = {
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     "NotImplementedType",
     0,

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list