From: Alexandre Vassalotti Date: Sun, 1 Dec 2013 00:21:20 +0000 (-0800) Subject: Issue #6477: Merge with 3.3. X-Git-Tag: v3.4.0b2~419 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3c23e7a5dcbc1972bd9e26dc26e61d856abb51f1;p=python Issue #6477: Merge with 3.3. --- 3c23e7a5dcbc1972bd9e26dc26e61d856abb51f1 diff --cc Lib/pickle.py index cf8e2c5964,386ffba7e2..c57149a393 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@@ -954,9 -728,68 +954,18 @@@ 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[BuiltinFunctionType] = save_global + dispatch[type] = save_type -# Pickling helpers - -def _keep_alive(x, memo): - """Keeps a reference to the object x in the memo. - - Because we remember objects by their id, we have - to assure that possibly temporary objects are kept - alive by referencing them. - We store a reference at the id of the memo, which should - normally not be used unless someone tries to deepcopy - the memo itself... - """ - try: - memo[id(memo)].append(x) - except KeyError: - # aha, this is the first one :-) - memo[id(memo)]=[x] - - -# A cache for whichmodule(), mapping a function object to the name of -# the module in which the function was found. - -classmap = {} # called classmap for backwards compatibility - -def whichmodule(func, funcname): - """Figure out the module in which a function occurs. - - Search sys.modules for the module. - Cache in classmap. - Return a module name. - If the function cannot be found, return "__main__". - """ - # Python functions should always get an __module__ from their globals. - mod = getattr(func, "__module__", None) - if mod is not None: - return mod - if func in classmap: - return classmap[func] - - for name, module in list(sys.modules.items()): - if module is None: - continue # skip dummy package entries - if name != '__main__' and getattr(module, funcname, None) is func: - break - else: - name = '__main__' - classmap[func] = name - return name - # Unpickling machinery diff --cc Lib/test/pickletester.py index 12b6c8f641,86d668ef6f..999eab0d5c --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@@ -802,8 -766,17 +802,17 @@@ class AbstractPickleTests(unittest.Test for proto in protocols: s = self.dumps(NotImplemented, proto) u = self.loads(s) - self.assertEqual(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 def test_proto(self): diff --cc Misc/NEWS index 660980a9c4,0acbafd600..7bfce3ff77 --- a/Misc/NEWS +++ b/Misc/NEWS @@@ -33,10 -24,9 +33,13 @@@ Librar - 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. + - Issue #11508: Fixed uuid.getnode() and uuid.uuid1() on environment with virtual interface. Original patch by Kent Frazier. diff --cc Modules/_pickle.c index a83687b0cd,ba192fb78d..64452381ea --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@@ -3287,6 -2811,60 +3287,36 @@@ save_global(PicklerObject *self, PyObje return status; } -static int -save_ellipsis(PicklerObject *self, PyObject *obj) -{ - PyObject *str = PyUnicode_FromString("Ellipsis"); - int res; - if (str == NULL) - return -1; - res = save_global(self, Py_Ellipsis, str); - Py_DECREF(str); - return res; -} - -static int -save_notimplemented(PicklerObject *self, PyObject *obj) -{ - PyObject *str = PyUnicode_FromString("NotImplemented"); - int res; - if (str == NULL) - return -1; - res = save_global(self, Py_NotImplemented, str); - Py_DECREF(str); - 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 save_pers(PicklerObject *self, PyObject *obj, PyObject *func) { @@@ -3696,10 -3219,20 +3726,10 @@@ save(PicklerObject *self, PyObject *obj 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) { - status = save_global(self, obj, NULL); - if (status < 0 && PyErr_ExceptionMatches(PickleError)) { - /* fall back to reduce */ - PyErr_Clear(); - } - else { - goto done; - } - } - else if (type == &PyCFunction_Type) { + else if (type == &PyFunction_Type) { status = save_global(self, obj, NULL); goto done; } diff --cc Objects/object.c index 11718aaae2,83da6a4ff0..8ccc91cd4b --- a/Objects/object.c +++ b/Objects/object.c @@@ -1485,16 -1524,7 +1485,16 @@@ notimplemented_new(PyTypeObject *type, Py_RETURN_NOTIMPLEMENTED; } +static void +notimplemented_dealloc(PyObject* ignore) +{ + /* This should never get called, but we also don't want to SEGV if + * we accidentally decref NotImplemented out of existence. + */ + Py_FatalError("deallocating NotImplemented"); +} + - static PyTypeObject PyNotImplemented_Type = { + PyTypeObject PyNotImplemented_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "NotImplementedType", 0,