diff options
| author | Alexandre Vassalotti <alexandre@peadrop.com> | 2013-11-30 16:21:20 -0800 | 
|---|---|---|
| committer | Alexandre Vassalotti <alexandre@peadrop.com> | 2013-11-30 16:21:20 -0800 | 
| commit | 3c23e7a5dcbc1972bd9e26dc26e61d856abb51f1 (patch) | |
| tree | 600903588902508759b5ad8e3cbeb9d4b8329c1c | |
| parent | 9204af42cc271690f57a4bc0d2af53201a796b51 (diff) | |
| parent | 19b6fa6ebb887e498437b4ae87d6e70b92b4742b (diff) | |
| download | cpython-git-3c23e7a5dcbc1972bd9e26dc26e61d856abb51f1.tar.gz | |
Issue #6477: Merge with 3.3.
| -rw-r--r-- | Include/object.h | 3 | ||||
| -rw-r--r-- | Lib/pickle.py | 11 | ||||
| -rw-r--r-- | Lib/test/pickletester.py | 9 | ||||
| -rw-r--r-- | Misc/NEWS | 3 | ||||
| -rw-r--r-- | Modules/_pickle.c | 32 | ||||
| -rw-r--r-- | Objects/object.c | 4 | 
6 files changed, 58 insertions, 4 deletions
| diff --git a/Include/object.h b/Include/object.h index 8de22086ac..cc22ae9559 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 cf8e2c5964..c57149a393 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 12b6c8f641..999eab0d5c 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): @@ -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 a83687b0cd..64452381ea 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 11718aaae2..8ccc91cd4b 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, | 
