diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2010-10-22 19:43:59 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2010-10-22 19:43:59 (GMT) |
commit | 7eecffd05dcef6666f3f75bd960d5087cb85d629 (patch) | |
tree | e611782a95c748524410c2062951118dfb5ec065 /Modules | |
parent | 61ec8de8097237e83a42bf6c732abf15c3fd7610 (diff) | |
download | cpython-7eecffd05dcef6666f3f75bd960d5087cb85d629.zip cpython-7eecffd05dcef6666f3f75bd960d5087cb85d629.tar.gz cpython-7eecffd05dcef6666f3f75bd960d5087cb85d629.tar.bz2 |
Issue #9935: Speed up pickling of instances of user-defined classes.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_pickle.c | 51 |
1 files changed, 34 insertions, 17 deletions
diff --git a/Modules/_pickle.c b/Modules/_pickle.c index e2d6406..fca9f2c 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -2840,6 +2840,28 @@ 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. */ @@ -2905,17 +2927,18 @@ 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; - PyObject *name_str; + static PyObject *newobj_str = NULL, *name_str = NULL; + PyObject *name; if (newobj_str == NULL) { newobj_str = PyUnicode_InternFromString("__newobj__"); - if (newobj_str == NULL) + name_str = PyUnicode_InternFromString("__name__"); + if (newobj_str == NULL || name_str == NULL) return -1; } - name_str = PyObject_GetAttrString(callable, "__name__"); - if (name_str == NULL) { + name = PyObject_GetAttr(callable, name_str); + if (name == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) PyErr_Clear(); else @@ -2923,9 +2946,9 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj) use_newobj = 0; } else { - use_newobj = PyUnicode_Check(name_str) && - PyUnicode_Compare(name_str, newobj_str) == 0; - Py_DECREF(name_str); + use_newobj = PyUnicode_Check(name) && + PyUnicode_Compare(name, newobj_str) == 0; + Py_DECREF(name); } } if (use_newobj) { @@ -2941,20 +2964,14 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj) } cls = PyTuple_GET_ITEM(argtup, 0); - if (!PyObject_HasAttrString(cls, "__new__")) { + if (!PyType_Check(cls)) { PyErr_SetString(PicklingError, "args[0] from " - "__newobj__ args has no __new__"); + "__newobj__ args is not a type"); return -1; } if (obj != NULL) { - obj_class = PyObject_GetAttrString(obj, "__class__"); - if (obj_class == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) - PyErr_Clear(); - else - return -1; - } + obj_class = get_class(obj); p = obj_class != cls; /* true iff a problem */ Py_DECREF(obj_class); if (p) { |