summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Vassalotti <alexandre@peadrop.com>2013-12-01 00:21:20 (GMT)
committerAlexandre Vassalotti <alexandre@peadrop.com>2013-12-01 00:21:20 (GMT)
commit3c23e7a5dcbc1972bd9e26dc26e61d856abb51f1 (patch)
tree600903588902508759b5ad8e3cbeb9d4b8329c1c
parent9204af42cc271690f57a4bc0d2af53201a796b51 (diff)
parent19b6fa6ebb887e498437b4ae87d6e70b92b4742b (diff)
downloadcpython-3c23e7a5dcbc1972bd9e26dc26e61d856abb51f1.zip
cpython-3c23e7a5dcbc1972bd9e26dc26e61d856abb51f1.tar.gz
cpython-3c23e7a5dcbc1972bd9e26dc26e61d856abb51f1.tar.bz2
Issue #6477: Merge with 3.3.
-rw-r--r--Include/object.h3
-rw-r--r--Lib/pickle.py11
-rw-r--r--Lib/test/pickletester.py9
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_pickle.c32
-rw-r--r--Objects/object.c4
6 files changed, 58 insertions, 4 deletions
diff --git a/Include/object.h b/Include/object.h
index 8de2208..cc22ae9 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -829,6 +829,9 @@ they can have object code that is not dependent on Python compilation flags.
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
index cf8e2c5..c57149a 100644
--- a/Lib/pickle.py
+++ b/Lib/pickle.py
@@ -954,8 +954,17 @@ class _Pickler:
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
index 12b6c8f..999eab0 100644
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -804,6 +804,15 @@ class AbstractPickleTests(unittest.TestCase):
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
index 660980a..7bfce3f 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -33,6 +33,9 @@ Library
- 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
index a83687b..6445238 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -3288,6 +3288,36 @@ save_global(PicklerObject *self, PyObject *obj, PyObject *name)
}
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 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
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
index 11718aa..8ccc91c 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1409,7 +1409,7 @@ static PyNumberMethods none_as_number = {
0, /* nb_index */
};
-static PyTypeObject PyNone_Type = {
+PyTypeObject PyNone_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"NoneType",
0,
@@ -1494,7 +1494,7 @@ notimplemented_dealloc(PyObject* ignore)
Py_FatalError("deallocating NotImplemented");
}
-static PyTypeObject PyNotImplemented_Type = {
+PyTypeObject PyNotImplemented_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"NotImplementedType",
0,