Commit b2c5022c authored by Tim Peters's avatar Tim Peters

gen_getattr: make the gi_running and gi_frame members discoverable (but

not writable -- too dangerous!) from Python code.
parent ae858111
...@@ -368,7 +368,7 @@ Next one was posted to c.l.py. ...@@ -368,7 +368,7 @@ Next one was posted to c.l.py.
[1, 2, 3, 4] [1, 2, 3, 4]
5-combs of [1, 2, 3, 4]: 5-combs of [1, 2, 3, 4]:
# From the Iterators list, about the types of these things. From the Iterators list, about the types of these things.
>>> def g(): >>> def g():
... yield 1 ... yield 1
...@@ -379,7 +379,7 @@ Next one was posted to c.l.py. ...@@ -379,7 +379,7 @@ Next one was posted to c.l.py.
>>> type(i) >>> type(i)
<type 'generator'> <type 'generator'>
>>> dir(i) >>> dir(i)
['next'] ['gi_frame', 'gi_running', 'next']
>>> print i.next.__doc__ >>> print i.next.__doc__
next() -- get the next value, or raise StopIteration next() -- get the next value, or raise StopIteration
>>> iter(i) is i >>> iter(i) is i
...@@ -387,6 +387,26 @@ next() -- get the next value, or raise StopIteration ...@@ -387,6 +387,26 @@ next() -- get the next value, or raise StopIteration
>>> import types >>> import types
>>> isinstance(i, types.GeneratorType) >>> isinstance(i, types.GeneratorType)
1 1
And more, added later.
>>> i.gi_running
0
>>> type(i.gi_frame)
<type 'frame'>
>>> i.gi_running = 42
Traceback (most recent call last):
...
TypeError: object has read-only attributes
>>> def g():
... yield me.gi_running
>>> me = g()
>>> me.gi_running
0
>>> me.next()
1
>>> me.gi_running
0
""" """
# Fun tests (for sufficiently warped notions of "fun"). # Fun tests (for sufficiently warped notions of "fun").
......
...@@ -115,8 +115,8 @@ typedef struct { ...@@ -115,8 +115,8 @@ typedef struct {
PyFrameObject *gi_frame; PyFrameObject *gi_frame;
/* True if generator is being executed. */ /* True if generator is being executed. */
int gi_running; int gi_running;
} genobject; } genobject;
static PyObject * static PyObject *
...@@ -207,14 +207,27 @@ gen_getiter(PyObject *gen) ...@@ -207,14 +207,27 @@ gen_getiter(PyObject *gen)
static struct PyMethodDef gen_methods[] = { static struct PyMethodDef gen_methods[] = {
{"next", (PyCFunction)gen_next, METH_VARARGS, {"next", (PyCFunction)gen_next, METH_VARARGS,
"next() -- get the next value, or raise StopIteration"}, "next() -- get the next value, or raise StopIteration"},
{NULL, NULL} /* Sentinel */ {NULL, NULL} /* Sentinel */
}; };
static PyObject * static PyObject *
gen_getattr(genobject *gen, char *name) gen_getattr(genobject *gen, char *name)
{ {
return Py_FindMethod(gen_methods, (PyObject *)gen, name); PyObject *result;
if (strcmp(name, "gi_frame") == 0) {
result = (PyObject *)gen->gi_frame;
assert(result != NULL);
Py_INCREF(result);
}
else if (strcmp(name, "gi_running") == 0)
result = (PyObject *)PyInt_FromLong((long)gen->gi_running);
else if (strcmp(name, "__members__") == 0)
result = Py_BuildValue("[ss]", "gi_frame", "gi_running");
else
result = Py_FindMethod(gen_methods, (PyObject *)gen, name);
return result;
} }
statichere PyTypeObject gentype = { statichere PyTypeObject gentype = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment