Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e77f2e2

Browse files
committed
gen_getattr: make the gi_running and gi_frame members discoverable (but
not writable -- too dangerous!) from Python code.
1 parent 0ba70cc commit e77f2e2

2 files changed

Lines changed: 39 additions & 6 deletions

File tree

Lib/test/test_generators.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@
368368
[1, 2, 3, 4]
369369
5-combs of [1, 2, 3, 4]:
370370
371-
# From the Iterators list, about the types of these things.
371+
From the Iterators list, about the types of these things.
372372
373373
>>> def g():
374374
... yield 1
@@ -379,14 +379,34 @@
379379
>>> type(i)
380380
<type 'generator'>
381381
>>> dir(i)
382-
['next']
382+
['gi_frame', 'gi_running', 'next']
383383
>>> print i.next.__doc__
384384
next() -- get the next value, or raise StopIteration
385385
>>> iter(i) is i
386386
1
387387
>>> import types
388388
>>> isinstance(i, types.GeneratorType)
389389
1
390+
391+
And more, added later.
392+
393+
>>> i.gi_running
394+
0
395+
>>> type(i.gi_frame)
396+
<type 'frame'>
397+
>>> i.gi_running = 42
398+
Traceback (most recent call last):
399+
...
400+
TypeError: object has read-only attributes
401+
>>> def g():
402+
... yield me.gi_running
403+
>>> me = g()
404+
>>> me.gi_running
405+
0
406+
>>> me.next()
407+
1
408+
>>> me.gi_running
409+
0
390410
"""
391411

392412
# Fun tests (for sufficiently warped notions of "fun").

Python/ceval.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ typedef struct {
115115

116116
PyFrameObject *gi_frame;
117117

118-
/* True if generator is being executed. */
119-
int gi_running;
118+
/* True if generator is being executed. */
119+
int gi_running;
120120
} genobject;
121121

122122
static PyObject *
@@ -207,14 +207,27 @@ gen_getiter(PyObject *gen)
207207

208208
static struct PyMethodDef gen_methods[] = {
209209
{"next", (PyCFunction)gen_next, METH_VARARGS,
210-
"next() -- get the next value, or raise StopIteration"},
210+
"next() -- get the next value, or raise StopIteration"},
211211
{NULL, NULL} /* Sentinel */
212212
};
213213

214214
static PyObject *
215215
gen_getattr(genobject *gen, char *name)
216216
{
217-
return Py_FindMethod(gen_methods, (PyObject *)gen, name);
217+
PyObject *result;
218+
219+
if (strcmp(name, "gi_frame") == 0) {
220+
result = (PyObject *)gen->gi_frame;
221+
assert(result != NULL);
222+
Py_INCREF(result);
223+
}
224+
else if (strcmp(name, "gi_running") == 0)
225+
result = (PyObject *)PyInt_FromLong((long)gen->gi_running);
226+
else if (strcmp(name, "__members__") == 0)
227+
result = Py_BuildValue("[ss]", "gi_frame", "gi_running");
228+
else
229+
result = Py_FindMethod(gen_methods, (PyObject *)gen, name);
230+
return result;
218231
}
219232

220233
statichere PyTypeObject gentype = {

0 commit comments

Comments
 (0)