Exemple #1
0
PyObject *
run_frame(PyObject *self, PyObject *args)
{
    PyThreadState *current_state = PyThreadState_Get(); 
    PyFrameObject *f;
    if (!PyArg_UnpackTuple(args, "run_frame", 1, 1, &f))
        return NULL;
    current_state->frame = f;
    f->f_back=f;
    return PyEval_EvalFrame(f);
}
Exemple #2
0
static PyObject *
gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)
{
	PyThreadState *tstate = PyThreadState_GET();
	PyFrameObject *f = gen->gi_frame;
	PyObject *result;

	if (gen->gi_running) {
		PyErr_SetString(PyExc_ValueError,
				"generator already executing");
		return NULL;
	}
	if (f==NULL || f->f_stacktop == NULL) {
		/* Only set exception if called from send() */
		if (arg && !exc)
			PyErr_SetNone(PyExc_StopIteration);
		return NULL;
	}

	if (f->f_lasti == -1) {
		if (arg && arg != Py_None) {
			PyErr_SetString(PyExc_TypeError,
					"can't send non-None value to a "
					"just-started generator");
			return NULL;
		}
	} else {
		/* Push arg onto the frame's value stack */
		result = arg ? arg : Py_None;
	        Py_INCREF(result);
	        *(f->f_stacktop++) = result;
	}

	/* Generators always return to their most recent caller, not
	 * necessarily their creator. */
	Py_XINCREF(tstate->frame);
	assert(f->f_back == NULL);
	f->f_back = tstate->frame;

	gen->gi_running = 1;
	f->f_throwflag = exc;
	result = PyEval_EvalFrame(f);
	f->f_throwflag = 0;
	gen->gi_running = 0;

	/* Don't keep the reference to f_back any longer than necessary.  It
	 * may keep a chain of frames alive or it could create a reference
	 * cycle. */
	assert(f->f_back == tstate->frame);
	Py_CLEAR(f->f_back);

	/* If the generator just returned (as opposed to yielding), signal
	 * that the generator is exhausted. */
	if (result == Py_None && f->f_stacktop == NULL) {
		Py_DECREF(result);
		result = NULL;
		/* Set exception if not called by gen_iternext() */
		if (arg)
			PyErr_SetNone(PyExc_StopIteration);
	}

	if (!result || f->f_stacktop == NULL) {
		/* generator can't be rerun, so release the frame */
		Py_DECREF(f);
		gen->gi_frame = NULL;
	}

	return result;
}