diff options
-rw-r--r-- | Doc/whatsnew/3.2.rst | 3 | ||||
-rw-r--r-- | Lib/test/pickletester.py | 21 | ||||
-rw-r--r-- | Misc/NEWS | 2 | ||||
-rw-r--r-- | Modules/_pickle.c | 51 | ||||
-rw-r--r-- | Objects/typeobject.c | 78 |
5 files changed, 49 insertions, 106 deletions
diff --git a/Doc/whatsnew/3.2.rst b/Doc/whatsnew/3.2.rst index 0a561f1..c16fe87 100644 --- a/Doc/whatsnew/3.2.rst +++ b/Doc/whatsnew/3.2.rst @@ -563,8 +563,7 @@ A number of small performance enhancements have been added: * Serializing and unserializing data using the :mod:`pickle` module is now several times faster. (Contributed by Alexandre Vassalotti, Antoine Pitrou - and the Unladen Swallow team in :issue:`9410`, :issue:`3873` and - :issue:`9935`.) + and the Unladen Swallow team in :issue:`9410` and :issue:`3873`.) Filenames and Unicode diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index e21d490..7645b54 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -3,7 +3,6 @@ import unittest import pickle import pickletools import copyreg -import weakref from http.cookies import SimpleCookie from test.support import TestFailed, TESTFN, run_with_locale @@ -843,25 +842,6 @@ class AbstractPickleTests(unittest.TestCase): self.assertEqual(B(x), B(y), detail) self.assertEqual(x.__dict__, y.__dict__, detail) - def test_newobj_proxies(self): - # NEWOBJ should use the __class__ rather than the raw type - classes = myclasses[:] - # Cannot create weakproxies to these classes - for c in (MyInt, MyTuple): - classes.remove(c) - for proto in protocols: - for C in classes: - B = C.__base__ - x = C(C.sample) - x.foo = 42 - p = weakref.proxy(x) - s = self.dumps(p, proto) - y = self.loads(s) - self.assertEqual(type(y), type(x)) # rather than type(p) - detail = (proto, C, B, x, y, type(y)) - self.assertEqual(B(x), B(y), detail) - self.assertEqual(x.__dict__, y.__dict__, detail) - # Register a type with copyreg, with extension code extcode. Pickle # an object of that type. Check that the resulting pickle uses opcode # (EXT[124]) under proto 2, and not in proto 1. @@ -1028,6 +1008,7 @@ class AbstractPickleTests(unittest.TestCase): self.assertRaises(RuntimeError, self.dumps, x, proto) # protocol 2 don't raise a RuntimeError. d = self.dumps(x, 2) + self.assertRaises(RuntimeError, self.loads, d) def test_reduce_bad_iterator(self): # Issue4176: crash when 4th and 5th items of __reduce__() @@ -43,8 +43,6 @@ Core and Builtins Library ------- -- Issue #9935: Speed up pickling of instances of user-defined classes. - - Issue #5639: Add a *server_hostname* argument to ``SSLContext.wrap_socket`` in order to support the TLS SNI extension. ``HTTPSConnection`` and ``urlopen()`` also use this argument, so that HTTPS virtual hosts are now diff --git a/Modules/_pickle.c b/Modules/_pickle.c index fca9f2c..e2d6406 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -2840,28 +2840,6 @@ save_pers(PicklerObject *self, PyObject *obj, PyObject *func) return status; } -static PyObject * -get_class(PyObject *obj) -{ - PyObject *cls; - static PyObject *str_class; - - if (str_class == NULL) { - str_class = PyUnicode_InternFromString("__class__"); - if (str_class == NULL) - return NULL; - } - cls = PyObject_GetAttr(obj, str_class); - if (cls == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - cls = (PyObject *) Py_TYPE(obj); - Py_INCREF(cls); - } - } - return cls; -} - /* We're saving obj, and args is the 2-thru-5 tuple returned by the * appropriate __reduce__ method for obj. */ @@ -2927,18 +2905,17 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj) /* Protocol 2 special case: if callable's name is __newobj__, use NEWOBJ. */ if (use_newobj) { - static PyObject *newobj_str = NULL, *name_str = NULL; - PyObject *name; + static PyObject *newobj_str = NULL; + PyObject *name_str; if (newobj_str == NULL) { newobj_str = PyUnicode_InternFromString("__newobj__"); - name_str = PyUnicode_InternFromString("__name__"); - if (newobj_str == NULL || name_str == NULL) + if (newobj_str == NULL) return -1; } - name = PyObject_GetAttr(callable, name_str); - if (name == NULL) { + name_str = PyObject_GetAttrString(callable, "__name__"); + if (name_str == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) PyErr_Clear(); else @@ -2946,9 +2923,9 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj) use_newobj = 0; } else { - use_newobj = PyUnicode_Check(name) && - PyUnicode_Compare(name, newobj_str) == 0; - Py_DECREF(name); + use_newobj = PyUnicode_Check(name_str) && + PyUnicode_Compare(name_str, newobj_str) == 0; + Py_DECREF(name_str); } } if (use_newobj) { @@ -2964,14 +2941,20 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj) } cls = PyTuple_GET_ITEM(argtup, 0); - if (!PyType_Check(cls)) { + if (!PyObject_HasAttrString(cls, "__new__")) { PyErr_SetString(PicklingError, "args[0] from " - "__newobj__ args is not a type"); + "__newobj__ args has no __new__"); return -1; } if (obj != NULL) { - obj_class = get_class(obj); + obj_class = PyObject_GetAttrString(obj, "__class__"); + if (obj_class == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) + PyErr_Clear(); + else + return -1; + } p = obj_class != cls; /* true iff a problem */ Py_DECREF(obj_class); if (p) { diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 5302a73..2c1bf88 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3010,19 +3010,14 @@ static PyObject * import_copyreg(void) { static PyObject *copyreg_str; - static PyObject *mod_copyreg = NULL; if (!copyreg_str) { copyreg_str = PyUnicode_InternFromString("copyreg"); if (copyreg_str == NULL) return NULL; } - if (!mod_copyreg) { - mod_copyreg = PyImport_Import(copyreg_str); - } - Py_XINCREF(mod_copyreg); - return mod_copyreg; + return PyImport_Import(copyreg_str); } static PyObject * @@ -3031,16 +3026,14 @@ slotnames(PyObject *cls) PyObject *clsdict; PyObject *copyreg; PyObject *slotnames; - static PyObject *str_slotnames; - if (str_slotnames == NULL) { - str_slotnames = PyUnicode_InternFromString("__slotnames__"); - if (str_slotnames == NULL) - return NULL; + if (!PyType_Check(cls)) { + Py_INCREF(Py_None); + return Py_None; } clsdict = ((PyTypeObject *)cls)->tp_dict; - slotnames = PyDict_GetItem(clsdict, str_slotnames); + slotnames = PyDict_GetItemString(clsdict, "__slotnames__"); if (slotnames != NULL && PyList_Check(slotnames)) { Py_INCREF(slotnames); return slotnames; @@ -3074,20 +3067,12 @@ reduce_2(PyObject *obj) PyObject *slots = NULL, *listitems = NULL, *dictitems = NULL; PyObject *copyreg = NULL, *newobj = NULL, *res = NULL; Py_ssize_t i, n; - static PyObject *str_getnewargs = NULL, *str_getstate = NULL, - *str_newobj = NULL; - - if (str_getnewargs == NULL) { - str_getnewargs = PyUnicode_InternFromString("__getnewargs__"); - str_getstate = PyUnicode_InternFromString("__getstate__"); - str_newobj = PyUnicode_InternFromString("__newobj__"); - if (!str_getnewargs || !str_getstate || !str_newobj) - return NULL; - } - cls = (PyObject *) Py_TYPE(obj); + cls = PyObject_GetAttrString(obj, "__class__"); + if (cls == NULL) + return NULL; - getnewargs = PyObject_GetAttr(obj, str_getnewargs); + getnewargs = PyObject_GetAttrString(obj, "__getnewargs__"); if (getnewargs != NULL) { args = PyObject_CallObject(getnewargs, NULL); Py_DECREF(getnewargs); @@ -3105,7 +3090,7 @@ reduce_2(PyObject *obj) if (args == NULL) goto end; - getstate = PyObject_GetAttr(obj, str_getstate); + getstate = PyObject_GetAttrString(obj, "__getstate__"); if (getstate != NULL) { state = PyObject_CallObject(getstate, NULL); Py_DECREF(getstate); @@ -3113,18 +3098,17 @@ reduce_2(PyObject *obj) goto end; } else { - PyObject **dict; PyErr_Clear(); - dict = _PyObject_GetDictPtr(obj); - if (dict && *dict) - state = *dict; - else + state = PyObject_GetAttrString(obj, "__dict__"); + if (state == NULL) { + PyErr_Clear(); state = Py_None; - Py_INCREF(state); + Py_INCREF(state); + } names = slotnames(cls); if (names == NULL) goto end; - if (names != Py_None && PyList_GET_SIZE(names) > 0) { + if (names != Py_None) { assert(PyList_Check(names)); slots = PyDict_New(); if (slots == NULL) @@ -3183,7 +3167,7 @@ reduce_2(PyObject *obj) copyreg = import_copyreg(); if (copyreg == NULL) goto end; - newobj = PyObject_GetAttr(copyreg, str_newobj); + newobj = PyObject_GetAttrString(copyreg, "__newobj__"); if (newobj == NULL) goto end; @@ -3191,8 +3175,8 @@ reduce_2(PyObject *obj) args2 = PyTuple_New(n+1); if (args2 == NULL) goto end; - Py_INCREF(cls); PyTuple_SET_ITEM(args2, 0, cls); + cls = NULL; for (i = 0; i < n; i++) { PyObject *v = PyTuple_GET_ITEM(args, i); Py_INCREF(v); @@ -3202,6 +3186,7 @@ reduce_2(PyObject *obj) res = PyTuple_Pack(5, newobj, args2, state, listitems, dictitems); end: + Py_XDECREF(cls); Py_XDECREF(args); Py_XDECREF(args2); Py_XDECREF(slots); @@ -3261,34 +3246,31 @@ object_reduce(PyObject *self, PyObject *args) static PyObject * object_reduce_ex(PyObject *self, PyObject *args) { - static PyObject *str_reduce = NULL, *objreduce; PyObject *reduce, *res; int proto = 0; if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto)) return NULL; - if (str_reduce == NULL) { - str_reduce = PyUnicode_InternFromString("__reduce__"); - objreduce = PyDict_GetItemString(PyBaseObject_Type.tp_dict, - "__reduce__"); - if (str_reduce == NULL || objreduce == NULL) - return NULL; - } - - reduce = PyObject_GetAttr(self, str_reduce); + reduce = PyObject_GetAttrString(self, "__reduce__"); if (reduce == NULL) PyErr_Clear(); else { - PyObject *cls, *clsreduce; + PyObject *cls, *clsreduce, *objreduce; int override; - - cls = (PyObject *) Py_TYPE(self); - clsreduce = PyObject_GetAttr(cls, str_reduce); + cls = PyObject_GetAttrString(self, "__class__"); + if (cls == NULL) { + Py_DECREF(reduce); + return NULL; + } + clsreduce = PyObject_GetAttrString(cls, "__reduce__"); + Py_DECREF(cls); if (clsreduce == NULL) { Py_DECREF(reduce); return NULL; } + objreduce = PyDict_GetItemString(PyBaseObject_Type.tp_dict, + "__reduce__"); override = (clsreduce != objreduce); Py_DECREF(clsreduce); if (override) { |