Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit a10dbbf

Browse files
author
Anselm Kruis
committed
merge 3.4-slp (Stackless #107, __reduce__/__setstate__ protocol)
2 parents 29476f5 + 8a2d22a commit a10dbbf

File tree

2 files changed

+74
-2
lines changed

2 files changed

+74
-2
lines changed

Stackless/changelog.txt

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ What's New in Stackless 3.X.X?
7979
- https://bitbucket.org/stackless-dev/stackless/issues/107
8080
Improve unpickling of traceback objects. Stackless now reconstructs the
8181
frame.f_back linkage in frames directly referenced by traceback objects.
82+
Stackless no longer pretends to be able to pickle arbitrary frame objects.
8283

8384
- https://bitbucket.org/stackless-dev/stackless/issues/110
8485
Remove the already non functional remains of psyco support.

Stackless/pickling/prickelpit.c

+73-2
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,64 @@ slp_reduce_frame(PyFrameObject * frame) {
209209
return PyObject_CallFunctionObjArgs(reduce_frame_func, (PyObject *)frame, NULL);
210210
}
211211

212+
/* Helper function for gen_setstate and tb_setstate.
213+
* It unwraps the first argument of the args tuple, if it is a _Frame_Wrapper.
214+
* Returns a new reference to an argument tuple.
215+
*
216+
* This functionality is required, to adhere to the __reduce__/__setstate__ protocol.
217+
* It requires, that __setstate__ accepts the state returned by __reduce__. (copy.copy()
218+
* depends on it.)
219+
*/
220+
static PyObject *
221+
unwrap_frame_arg(PyObject * args) {
222+
PyObject *wrapper_type, *arg0, *result;
223+
int is_instance;
224+
Py_ssize_t len, i;
225+
226+
if (!PyTuple_Check(args) || (len = PyTuple_Size(args)) < 1) {
227+
if (len < 0)
228+
return NULL;
229+
Py_INCREF(args);
230+
return args;
231+
}
232+
if ((arg0 = PyTuple_GetItem(args, 0)) == NULL) /* arg0 is a borrowed reference */
233+
return NULL;
234+
if ((wrapper_type = PyObject_GetAttrString(reduce_frame_func, "__self__")) == NULL)
235+
return NULL;
236+
is_instance = PyObject_IsInstance(arg0, wrapper_type);
237+
Py_DECREF(wrapper_type);
238+
if (is_instance == 0) {
239+
Py_INCREF(args);
240+
return args;
241+
} else if (is_instance == -1) {
242+
return NULL;
243+
}
244+
if ((arg0 = PyObject_GetAttrString(arg0, "frame")) == NULL)
245+
return NULL;
246+
if ((result = PyTuple_New(len)) == NULL) {
247+
Py_DECREF(arg0);
248+
return NULL;
249+
}
250+
if (PyTuple_SetItem(result, 0, arg0)) { /* steals ref to arg0 */
251+
Py_DECREF(arg0);
252+
Py_DECREF(result);
253+
return NULL;
254+
}
255+
for (i=1; i<len; i++) {
256+
if ((arg0 = PyTuple_GetItem(args, i)) == NULL) {
257+
Py_DECREF(result);
258+
return NULL;
259+
}
260+
/* arg0 is a borrowed reference */
261+
Py_INCREF(arg0);
262+
if (PyTuple_SetItem(result, i, arg0)) { /* steals ref to arg0 */
263+
Py_DECREF(arg0);
264+
Py_DECREF(result);
265+
return NULL;
266+
}
267+
}
268+
return result;
269+
}
212270

213271
static struct PyMethodDef _new_methoddef[] = {
214272
{"__new__", (PyCFunction)_new_wrapper, METH_VARARGS | METH_KEYWORDS,
@@ -1230,11 +1288,17 @@ tb_setstate(PyObject *self, PyObject *args)
12301288

12311289
if (is_wrong_type(Py_TYPE(tb))) return NULL;
12321290

1291+
if ((args = unwrap_frame_arg(args)) == NULL) /* now args is a counted ref! */
1292+
return NULL;
1293+
12331294
if (!PyArg_ParseTuple(args,
12341295
"O!ii|O!:traceback",
12351296
&PyFrame_Type, &frame,
1236-
&lasti, &lineno,&PyTraceBack_Type, &next))
1297+
&lasti, &lineno,&PyTraceBack_Type, &next)) {
1298+
Py_DECREF(args);
12371299
return NULL;
1300+
}
1301+
Py_DECREF(args);
12381302

12391303
Py_XINCREF(next);
12401304
tb->tb_next = next;
@@ -2319,9 +2383,16 @@ gen_setstate(PyObject *self, PyObject *args)
23192383
PyObject *qualname = NULL;
23202384

23212385
if (is_wrong_type(Py_TYPE(self))) return NULL;
2386+
2387+
if ((args = unwrap_frame_arg(args)) == NULL) /* now args is a counted ref! */
2388+
return NULL;
2389+
23222390
if (!PyArg_ParseTuple(args, "O!i|OO:generator",
2323-
&PyFrame_Type, &f, &gi_running, &name, &qualname))
2391+
&PyFrame_Type, &f, &gi_running, &name, &qualname)) {
2392+
Py_DECREF(args);
23242393
return NULL;
2394+
}
2395+
Py_DECREF(args);
23252396

23262397
if (name == NULL) {
23272398
name = f->f_code->co_name;

0 commit comments

Comments
 (0)