Commit fa53d215 authored by Alexandre Vassalotti's avatar Alexandre Vassalotti

Issue #6477: Merge with 3.3.

parents ea29612b eb2bce5d
...@@ -829,6 +829,9 @@ they can have object code that is not dependent on Python compilation flags. ...@@ -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_IncRef(PyObject *);
PyAPI_FUNC(void) Py_DecRef(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 _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'). where NULL (nil) is not suitable (since NULL often means 'error').
......
...@@ -954,8 +954,17 @@ class _Pickler: ...@@ -954,8 +954,17 @@ class _Pickler:
self.memoize(obj) 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[FunctionType] = save_global
dispatch[type] = save_global dispatch[type] = save_type
# Unpickling machinery # Unpickling machinery
......
...@@ -804,6 +804,15 @@ class AbstractPickleTests(unittest.TestCase): ...@@ -804,6 +804,15 @@ class AbstractPickleTests(unittest.TestCase):
u = self.loads(s) u = self.loads(s)
self.assertIs(NotImplemented, u) 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 # Tests for protocol 2
def test_proto(self): def test_proto(self):
......
...@@ -33,6 +33,9 @@ Library ...@@ -33,6 +33,9 @@ Library
- Fixed _pickle.Unpickler to not fail when loading empty strings as - Fixed _pickle.Unpickler to not fail when loading empty strings as
persistent IDs. 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. - ssl.create_default_context() sets OP_NO_COMPRESSION to prevent CRIME.
- Issue #19802: Add socket.SO_PRIORITY. - Issue #19802: Add socket.SO_PRIORITY.
......
...@@ -3287,6 +3287,36 @@ save_global(PicklerObject *self, PyObject *obj, PyObject *name) ...@@ -3287,6 +3287,36 @@ save_global(PicklerObject *self, PyObject *obj, PyObject *name)
return status; return status;
} }
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 static int
save_pers(PicklerObject *self, PyObject *obj, PyObject *func) save_pers(PicklerObject *self, PyObject *obj, PyObject *func)
{ {
...@@ -3696,7 +3726,7 @@ save(PicklerObject *self, PyObject *obj, int pers_save) ...@@ -3696,7 +3726,7 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
goto done; goto done;
} }
else if (type == &PyType_Type) { else if (type == &PyType_Type) {
status = save_global(self, obj, NULL); status = save_type(self, obj);
goto done; goto done;
} }
else if (type == &PyFunction_Type) { else if (type == &PyFunction_Type) {
......
...@@ -1409,7 +1409,7 @@ static PyNumberMethods none_as_number = { ...@@ -1409,7 +1409,7 @@ static PyNumberMethods none_as_number = {
0, /* nb_index */ 0, /* nb_index */
}; };
static PyTypeObject PyNone_Type = { PyTypeObject PyNone_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT(&PyType_Type, 0)
"NoneType", "NoneType",
0, 0,
...@@ -1494,7 +1494,7 @@ notimplemented_dealloc(PyObject* ignore) ...@@ -1494,7 +1494,7 @@ notimplemented_dealloc(PyObject* ignore)
Py_FatalError("deallocating NotImplemented"); Py_FatalError("deallocating NotImplemented");
} }
static PyTypeObject PyNotImplemented_Type = { PyTypeObject PyNotImplemented_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT(&PyType_Type, 0)
"NotImplementedType", "NotImplementedType",
0, 0,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment