summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2008-01-26 14:14:20 (GMT)
committerGeorg Brandl <georg@python.org>2008-01-26 14:14:20 (GMT)
commit0cdf9a36ec1b65a655a8af476077c7dd063d87da (patch)
tree0f4068bc8a244ef237f93cb61227dfdf9161f2ea
parent29604a1b4c09ae6efc47fa0f34412168a34aa7dd (diff)
downloadcpython-0cdf9a36ec1b65a655a8af476077c7dd063d87da.zip
cpython-0cdf9a36ec1b65a655a8af476077c7dd063d87da.tar.gz
cpython-0cdf9a36ec1b65a655a8af476077c7dd063d87da.tar.bz2
#1473257: add generator.gi_code attribute that refers to
the original code object backing the generator. Patch by Collin Winter.
-rw-r--r--Include/genobject.h3
-rw-r--r--Lib/test/test_generators.py20
-rw-r--r--Misc/NEWS6
-rw-r--r--Objects/genobject.c5
4 files changed, 32 insertions, 2 deletions
diff --git a/Include/genobject.h b/Include/genobject.h
index 11c6823..135561b 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 ce3db72..ab0fca0 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)
<type 'generator'>
>>> [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 1603418..2d46357 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 4ef710b..3868295 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);