From 0cdf9a36ec1b65a655a8af476077c7dd063d87da Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 26 Jan 2008 14:14:20 +0000 Subject: [PATCH] #1473257: add generator.gi_code attribute that refers to the original code object backing the generator. Patch by Collin Winter. --- Include/genobject.h | 3 +++ Lib/test/test_generators.py | 20 +++++++++++++++++++- Misc/NEWS | 6 +++++- Objects/genobject.c | 5 +++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Include/genobject.h b/Include/genobject.h index 11c6823eaa2..135561b701b 100644 --- a/Include/genobject.h +++ b/Include/genobject.h @@ -18,6 +18,9 @@ typedef struct { /* True if generator is being executed. */ int gi_running; + + /* The code object backing the generator */ + PyObject *gi_code; /* List of weak reference. */ PyObject *gi_weakreflist; diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index ce3db72e66c..ab0fca05064 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -382,7 +382,7 @@ From the Iterators list, about the types of these things. >>> type(i) >>> [s for s in dir(i) if not s.startswith('_')] -['close', 'gi_frame', 'gi_running', 'next', 'send', 'throw'] +['close', 'gi_code', 'gi_frame', 'gi_running', 'next', 'send', 'throw'] >>> print i.next.__doc__ x.next() -> the next value, or raise StopIteration >>> iter(i) is i @@ -899,6 +899,24 @@ This one caused a crash (see SF bug 567538): >>> print g.next() Traceback (most recent call last): StopIteration + + +Test the gi_code attribute + +>>> def f(): +... yield 5 +... +>>> g = f() +>>> g.gi_code is f.func_code +True +>>> g.next() +5 +>>> g.next() +Traceback (most recent call last): +StopIteration +>>> g.gi_code is f.func_code +True + """ # conjoin is a simple backtracking generator, named in honor of Icon's diff --git a/Misc/NEWS b/Misc/NEWS index 16034183e4e..2d463571d4b 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,7 +12,11 @@ What's New in Python 2.6 alpha 1? Core and builtins ----------------- -- Backport of PyUnicode_FromString(), _FromStringAndSize(), _Format and +- Patch #1473257: generator objects gain a gi_code attribute. This is the + same object as the func_code attribute of the function that produced the + generator. + + Backport of PyUnicode_FromString(), _FromStringAndSize(), _Format and _FormatV from Python 3.0. Made PyLong_AsSsize_t and PyLong_FromSsize_t public functions. diff --git a/Objects/genobject.c b/Objects/genobject.c index 4ef710bfcd9..38682955c3a 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -11,6 +11,7 @@ static int gen_traverse(PyGenObject *gen, visitproc visit, void *arg) { Py_VISIT((PyObject *)gen->gi_frame); + Py_VISIT(gen->gi_code); return 0; } @@ -35,6 +36,7 @@ gen_dealloc(PyGenObject *gen) _PyObject_GC_UNTRACK(self); Py_CLEAR(gen->gi_frame); + Py_CLEAR(gen->gi_code); PyObject_GC_Del(gen); } @@ -282,6 +284,7 @@ gen_iternext(PyGenObject *gen) static PyMemberDef gen_memberlist[] = { {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), RO}, {"gi_running", T_INT, offsetof(PyGenObject, gi_running), RO}, + {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), RO}, {NULL} /* Sentinel */ }; @@ -352,6 +355,8 @@ PyGen_New(PyFrameObject *f) return NULL; } gen->gi_frame = f; + Py_INCREF(f->f_code); + gen->gi_code = (PyObject *)(f->f_code); gen->gi_running = 0; gen->gi_weakreflist = NULL; _PyObject_GC_TRACK(gen);