Issue #6477: Merge with 3.3.

This commit is contained in:
Alexandre Vassalotti 2013-11-30 16:21:20 -08:00
commit 3c23e7a5dc
6 changed files with 58 additions and 4 deletions

View file

@ -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').

View file

@ -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

View file

@ -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):

View file

@ -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.

View file

@ -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)
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) {

View file

@ -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)
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,