mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
Issue #6477: Added support for pickling the types of built-in singletons.
This commit is contained in:
parent
f8ceb04fcf
commit
19b6fa6ebb
6 changed files with 58 additions and 4 deletions
|
@ -831,6 +831,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').
|
||||||
|
|
|
@ -728,9 +728,18 @@ 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[BuiltinFunctionType] = save_global
|
dispatch[BuiltinFunctionType] = save_global
|
||||||
dispatch[type] = save_global
|
dispatch[type] = save_type
|
||||||
|
|
||||||
# Pickling helpers
|
# Pickling helpers
|
||||||
|
|
||||||
|
|
|
@ -768,6 +768,15 @@ class AbstractPickleTests(unittest.TestCase):
|
||||||
u = self.loads(s)
|
u = self.loads(s)
|
||||||
self.assertEqual(NotImplemented, u)
|
self.assertEqual(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):
|
||||||
|
|
|
@ -24,6 +24,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).
|
||||||
|
|
||||||
- Issue #11508: Fixed uuid.getnode() and uuid.uuid1() on environment with
|
- Issue #11508: Fixed uuid.getnode() and uuid.uuid1() on environment with
|
||||||
virtual interface. Original patch by Kent Frazier.
|
virtual interface. Original patch by Kent Frazier.
|
||||||
|
|
||||||
|
|
|
@ -2835,6 +2835,36 @@ save_notimplemented(PicklerObject *self, PyObject *obj)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
|
@ -3189,7 +3219,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) {
|
||||||
|
|
|
@ -1459,7 +1459,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,
|
||||||
|
@ -1524,7 +1524,7 @@ notimplemented_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||||
Py_RETURN_NOTIMPLEMENTED;
|
Py_RETURN_NOTIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyTypeObject PyNotImplemented_Type = {
|
PyTypeObject PyNotImplemented_Type = {
|
||||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||||
"NotImplementedType",
|
"NotImplementedType",
|
||||||
0,
|
0,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue