~ubuntu-branches/ubuntu/maverick/python2.7/maverick-proposed

« back to all changes in this revision

Viewing changes to Objects/genobject.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2010-06-29 00:57:00 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20100629005700-fz6zs37e3uv26o82
Tags: 2.7~rc2-1
* Python 2.7 release candidate 2.
* Update to 20100628, taken from the trunk.
* Merge packaging changes from python2.6 (2.6.5+20100628-1).

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
static int
11
11
gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
12
12
{
13
 
        Py_VISIT((PyObject *)gen->gi_frame);
14
 
        Py_VISIT(gen->gi_code);
15
 
        return 0;
 
13
    Py_VISIT((PyObject *)gen->gi_frame);
 
14
    Py_VISIT(gen->gi_code);
 
15
    return 0;
16
16
}
17
17
 
18
18
static void
19
19
gen_dealloc(PyGenObject *gen)
20
20
{
21
 
        PyObject *self = (PyObject *) gen;
22
 
 
23
 
        _PyObject_GC_UNTRACK(gen);
24
 
 
25
 
        if (gen->gi_weakreflist != NULL)
26
 
                PyObject_ClearWeakRefs(self);
27
 
 
28
 
        _PyObject_GC_TRACK(self);
29
 
 
30
 
        if (gen->gi_frame != NULL && gen->gi_frame->f_stacktop != NULL) {
31
 
                /* Generator is paused, so we need to close */
32
 
                Py_TYPE(gen)->tp_del(self);
33
 
                if (self->ob_refcnt > 0)
34
 
                        return;         /* resurrected.  :( */
35
 
        }
36
 
 
37
 
        _PyObject_GC_UNTRACK(self);
38
 
        Py_CLEAR(gen->gi_frame);
39
 
        Py_CLEAR(gen->gi_code);
40
 
        PyObject_GC_Del(gen);
 
21
    PyObject *self = (PyObject *) gen;
 
22
 
 
23
    _PyObject_GC_UNTRACK(gen);
 
24
 
 
25
    if (gen->gi_weakreflist != NULL)
 
26
        PyObject_ClearWeakRefs(self);
 
27
 
 
28
    _PyObject_GC_TRACK(self);
 
29
 
 
30
    if (gen->gi_frame != NULL && gen->gi_frame->f_stacktop != NULL) {
 
31
        /* Generator is paused, so we need to close */
 
32
        Py_TYPE(gen)->tp_del(self);
 
33
        if (self->ob_refcnt > 0)
 
34
            return;                     /* resurrected.  :( */
 
35
    }
 
36
 
 
37
    _PyObject_GC_UNTRACK(self);
 
38
    Py_CLEAR(gen->gi_frame);
 
39
    Py_CLEAR(gen->gi_code);
 
40
    PyObject_GC_Del(gen);
41
41
}
42
42
 
43
43
 
44
44
static PyObject *
45
45
gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)
46
46
{
47
 
        PyThreadState *tstate = PyThreadState_GET();
48
 
        PyFrameObject *f = gen->gi_frame;
49
 
        PyObject *result;
50
 
 
51
 
        if (gen->gi_running) {
52
 
                PyErr_SetString(PyExc_ValueError,
53
 
                                "generator already executing");
54
 
                return NULL;
55
 
        }
56
 
        if (f==NULL || f->f_stacktop == NULL) {
57
 
                /* Only set exception if called from send() */
58
 
                if (arg && !exc)
59
 
                        PyErr_SetNone(PyExc_StopIteration);
60
 
                return NULL;
61
 
        }
62
 
 
63
 
        if (f->f_lasti == -1) {
64
 
                if (arg && arg != Py_None) {
65
 
                        PyErr_SetString(PyExc_TypeError,
66
 
                                        "can't send non-None value to a "
67
 
                                        "just-started generator");
68
 
                        return NULL;
69
 
                }
70
 
        } else {
71
 
                /* Push arg onto the frame's value stack */
72
 
                result = arg ? arg : Py_None;
73
 
                Py_INCREF(result);
74
 
                *(f->f_stacktop++) = result;
75
 
        }
76
 
 
77
 
        /* Generators always return to their most recent caller, not
78
 
         * necessarily their creator. */
79
 
        Py_XINCREF(tstate->frame);
80
 
        assert(f->f_back == NULL);
81
 
        f->f_back = tstate->frame;
82
 
 
83
 
        gen->gi_running = 1;
84
 
        result = PyEval_EvalFrameEx(f, exc);
85
 
        gen->gi_running = 0;
86
 
 
87
 
        /* Don't keep the reference to f_back any longer than necessary.  It
88
 
         * may keep a chain of frames alive or it could create a reference
89
 
         * cycle. */
90
 
        assert(f->f_back == tstate->frame);
91
 
        Py_CLEAR(f->f_back);
92
 
 
93
 
        /* If the generator just returned (as opposed to yielding), signal
94
 
         * that the generator is exhausted. */
95
 
        if (result == Py_None && f->f_stacktop == NULL) {
96
 
                Py_DECREF(result);
97
 
                result = NULL;
98
 
                /* Set exception if not called by gen_iternext() */
99
 
                if (arg)
100
 
                        PyErr_SetNone(PyExc_StopIteration);
101
 
        }
102
 
 
103
 
        if (!result || f->f_stacktop == NULL) {
104
 
                /* generator can't be rerun, so release the frame */
105
 
                Py_DECREF(f);
106
 
                gen->gi_frame = NULL;
107
 
        }
108
 
 
109
 
        return result;
 
47
    PyThreadState *tstate = PyThreadState_GET();
 
48
    PyFrameObject *f = gen->gi_frame;
 
49
    PyObject *result;
 
50
 
 
51
    if (gen->gi_running) {
 
52
        PyErr_SetString(PyExc_ValueError,
 
53
                        "generator already executing");
 
54
        return NULL;
 
55
    }
 
56
    if (f==NULL || f->f_stacktop == NULL) {
 
57
        /* Only set exception if called from send() */
 
58
        if (arg && !exc)
 
59
            PyErr_SetNone(PyExc_StopIteration);
 
60
        return NULL;
 
61
    }
 
62
 
 
63
    if (f->f_lasti == -1) {
 
64
        if (arg && arg != Py_None) {
 
65
            PyErr_SetString(PyExc_TypeError,
 
66
                            "can't send non-None value to a "
 
67
                            "just-started generator");
 
68
            return NULL;
 
69
        }
 
70
    } else {
 
71
        /* Push arg onto the frame's value stack */
 
72
        result = arg ? arg : Py_None;
 
73
        Py_INCREF(result);
 
74
        *(f->f_stacktop++) = result;
 
75
    }
 
76
 
 
77
    /* Generators always return to their most recent caller, not
 
78
     * necessarily their creator. */
 
79
    Py_XINCREF(tstate->frame);
 
80
    assert(f->f_back == NULL);
 
81
    f->f_back = tstate->frame;
 
82
 
 
83
    gen->gi_running = 1;
 
84
    result = PyEval_EvalFrameEx(f, exc);
 
85
    gen->gi_running = 0;
 
86
 
 
87
    /* Don't keep the reference to f_back any longer than necessary.  It
 
88
     * may keep a chain of frames alive or it could create a reference
 
89
     * cycle. */
 
90
    assert(f->f_back == tstate->frame);
 
91
    Py_CLEAR(f->f_back);
 
92
 
 
93
    /* If the generator just returned (as opposed to yielding), signal
 
94
     * that the generator is exhausted. */
 
95
    if (result == Py_None && f->f_stacktop == NULL) {
 
96
        Py_DECREF(result);
 
97
        result = NULL;
 
98
        /* Set exception if not called by gen_iternext() */
 
99
        if (arg)
 
100
            PyErr_SetNone(PyExc_StopIteration);
 
101
    }
 
102
 
 
103
    if (!result || f->f_stacktop == NULL) {
 
104
        /* generator can't be rerun, so release the frame */
 
105
        Py_DECREF(f);
 
106
        gen->gi_frame = NULL;
 
107
    }
 
108
 
 
109
    return result;
110
110
}
111
111
 
112
112
PyDoc_STRVAR(send_doc,
116
116
static PyObject *
117
117
gen_send(PyGenObject *gen, PyObject *arg)
118
118
{
119
 
        return gen_send_ex(gen, arg, 0);
 
119
    return gen_send_ex(gen, arg, 0);
120
120
}
121
121
 
122
122
PyDoc_STRVAR(close_doc,
125
125
static PyObject *
126
126
gen_close(PyGenObject *gen, PyObject *args)
127
127
{
128
 
        PyObject *retval;
129
 
        PyErr_SetNone(PyExc_GeneratorExit);
130
 
        retval = gen_send_ex(gen, Py_None, 1);
131
 
        if (retval) {
132
 
                Py_DECREF(retval);
133
 
                PyErr_SetString(PyExc_RuntimeError,
134
 
                                "generator ignored GeneratorExit");
135
 
                return NULL;
136
 
        }
137
 
        if (PyErr_ExceptionMatches(PyExc_StopIteration)
138
 
            || PyErr_ExceptionMatches(PyExc_GeneratorExit))
139
 
        {
140
 
                PyErr_Clear();  /* ignore these errors */
141
 
                Py_INCREF(Py_None);
142
 
                return Py_None;
143
 
        }
144
 
        return NULL;
 
128
    PyObject *retval;
 
129
    PyErr_SetNone(PyExc_GeneratorExit);
 
130
    retval = gen_send_ex(gen, Py_None, 1);
 
131
    if (retval) {
 
132
        Py_DECREF(retval);
 
133
        PyErr_SetString(PyExc_RuntimeError,
 
134
                        "generator ignored GeneratorExit");
 
135
        return NULL;
 
136
    }
 
137
    if (PyErr_ExceptionMatches(PyExc_StopIteration)
 
138
        || PyErr_ExceptionMatches(PyExc_GeneratorExit))
 
139
    {
 
140
        PyErr_Clear();          /* ignore these errors */
 
141
        Py_INCREF(Py_None);
 
142
        return Py_None;
 
143
    }
 
144
    return NULL;
145
145
}
146
146
 
147
147
static void
148
148
gen_del(PyObject *self)
149
149
{
150
 
        PyObject *res;
151
 
        PyObject *error_type, *error_value, *error_traceback;
152
 
        PyGenObject *gen = (PyGenObject *)self;
153
 
 
154
 
        if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL)
155
 
                /* Generator isn't paused, so no need to close */
156
 
                return;
157
 
 
158
 
        /* Temporarily resurrect the object. */
159
 
        assert(self->ob_refcnt == 0);
160
 
        self->ob_refcnt = 1;
161
 
 
162
 
        /* Save the current exception, if any. */
163
 
        PyErr_Fetch(&error_type, &error_value, &error_traceback);
164
 
 
165
 
        res = gen_close(gen, NULL);
166
 
 
167
 
        if (res == NULL)
168
 
                PyErr_WriteUnraisable(self);
169
 
        else
170
 
                Py_DECREF(res);
171
 
 
172
 
        /* Restore the saved exception. */
173
 
        PyErr_Restore(error_type, error_value, error_traceback);
174
 
 
175
 
        /* Undo the temporary resurrection; can't use DECREF here, it would
176
 
         * cause a recursive call.
177
 
         */
178
 
        assert(self->ob_refcnt > 0);
179
 
        if (--self->ob_refcnt == 0)
180
 
                return; /* this is the normal path out */
181
 
 
182
 
        /* close() resurrected it!  Make it look like the original Py_DECREF
183
 
         * never happened.
184
 
         */
185
 
        {
186
 
                Py_ssize_t refcnt = self->ob_refcnt;
187
 
                _Py_NewReference(self);
188
 
                self->ob_refcnt = refcnt;
189
 
        }
190
 
        assert(PyType_IS_GC(self->ob_type) &&
191
 
               _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
192
 
 
193
 
        /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
194
 
         * we need to undo that. */
195
 
        _Py_DEC_REFTOTAL;
196
 
        /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
197
 
         * chain, so no more to do there.
198
 
         * If COUNT_ALLOCS, the original decref bumped tp_frees, and
199
 
         * _Py_NewReference bumped tp_allocs:  both of those need to be
200
 
         * undone.
201
 
         */
 
150
    PyObject *res;
 
151
    PyObject *error_type, *error_value, *error_traceback;
 
152
    PyGenObject *gen = (PyGenObject *)self;
 
153
 
 
154
    if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL)
 
155
        /* Generator isn't paused, so no need to close */
 
156
        return;
 
157
 
 
158
    /* Temporarily resurrect the object. */
 
159
    assert(self->ob_refcnt == 0);
 
160
    self->ob_refcnt = 1;
 
161
 
 
162
    /* Save the current exception, if any. */
 
163
    PyErr_Fetch(&error_type, &error_value, &error_traceback);
 
164
 
 
165
    res = gen_close(gen, NULL);
 
166
 
 
167
    if (res == NULL)
 
168
        PyErr_WriteUnraisable(self);
 
169
    else
 
170
        Py_DECREF(res);
 
171
 
 
172
    /* Restore the saved exception. */
 
173
    PyErr_Restore(error_type, error_value, error_traceback);
 
174
 
 
175
    /* Undo the temporary resurrection; can't use DECREF here, it would
 
176
     * cause a recursive call.
 
177
     */
 
178
    assert(self->ob_refcnt > 0);
 
179
    if (--self->ob_refcnt == 0)
 
180
        return; /* this is the normal path out */
 
181
 
 
182
    /* close() resurrected it!  Make it look like the original Py_DECREF
 
183
     * never happened.
 
184
     */
 
185
    {
 
186
        Py_ssize_t refcnt = self->ob_refcnt;
 
187
        _Py_NewReference(self);
 
188
        self->ob_refcnt = refcnt;
 
189
    }
 
190
    assert(PyType_IS_GC(self->ob_type) &&
 
191
           _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
 
192
 
 
193
    /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
 
194
     * we need to undo that. */
 
195
    _Py_DEC_REFTOTAL;
 
196
    /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
 
197
     * chain, so no more to do there.
 
198
     * If COUNT_ALLOCS, the original decref bumped tp_frees, and
 
199
     * _Py_NewReference bumped tp_allocs:  both of those need to be
 
200
     * undone.
 
201
     */
202
202
#ifdef COUNT_ALLOCS
203
 
        --self->ob_type->tp_frees;
204
 
        --self->ob_type->tp_allocs;
 
203
    --self->ob_type->tp_frees;
 
204
    --self->ob_type->tp_allocs;
205
205
#endif
206
206
}
207
207
 
214
214
static PyObject *
215
215
gen_throw(PyGenObject *gen, PyObject *args)
216
216
{
217
 
        PyObject *typ;
218
 
        PyObject *tb = NULL;
219
 
        PyObject *val = NULL;
220
 
 
221
 
        if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb))
222
 
                return NULL;
223
 
 
224
 
        /* First, check the traceback argument, replacing None with
225
 
           NULL. */
226
 
        if (tb == Py_None)
227
 
                tb = NULL;
228
 
        else if (tb != NULL && !PyTraceBack_Check(tb)) {
229
 
                PyErr_SetString(PyExc_TypeError,
230
 
                        "throw() third argument must be a traceback object");
231
 
                return NULL;
232
 
        }
233
 
 
234
 
        Py_INCREF(typ);
235
 
        Py_XINCREF(val);
236
 
        Py_XINCREF(tb);
237
 
 
238
 
        if (PyExceptionClass_Check(typ)) {
239
 
                PyErr_NormalizeException(&typ, &val, &tb);
240
 
        }
241
 
 
242
 
        else if (PyExceptionInstance_Check(typ)) {
243
 
                /* Raising an instance.  The value should be a dummy. */
244
 
                if (val && val != Py_None) {
245
 
                        PyErr_SetString(PyExc_TypeError,
246
 
                          "instance exception may not have a separate value");
247
 
                        goto failed_throw;
248
 
                }
249
 
                else {
250
 
                        /* Normalize to raise <class>, <instance> */
251
 
                        Py_XDECREF(val);
252
 
                        val = typ;
253
 
                        typ = PyExceptionInstance_Class(typ);
254
 
                        Py_INCREF(typ);
255
 
                }
256
 
        }
257
 
        else {
258
 
                /* Not something you can raise.  throw() fails. */
259
 
                PyErr_Format(PyExc_TypeError,
260
 
                             "exceptions must be classes, or instances, not %s",
261
 
                             typ->ob_type->tp_name);
262
 
                        goto failed_throw;
263
 
        }
264
 
 
265
 
        PyErr_Restore(typ, val, tb);
266
 
        return gen_send_ex(gen, Py_None, 1);
 
217
    PyObject *typ;
 
218
    PyObject *tb = NULL;
 
219
    PyObject *val = NULL;
 
220
 
 
221
    if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb))
 
222
        return NULL;
 
223
 
 
224
    /* First, check the traceback argument, replacing None with
 
225
       NULL. */
 
226
    if (tb == Py_None)
 
227
        tb = NULL;
 
228
    else if (tb != NULL && !PyTraceBack_Check(tb)) {
 
229
        PyErr_SetString(PyExc_TypeError,
 
230
            "throw() third argument must be a traceback object");
 
231
        return NULL;
 
232
    }
 
233
 
 
234
    Py_INCREF(typ);
 
235
    Py_XINCREF(val);
 
236
    Py_XINCREF(tb);
 
237
 
 
238
    if (PyExceptionClass_Check(typ)) {
 
239
        PyErr_NormalizeException(&typ, &val, &tb);
 
240
    }
 
241
 
 
242
    else if (PyExceptionInstance_Check(typ)) {
 
243
        /* Raising an instance.  The value should be a dummy. */
 
244
        if (val && val != Py_None) {
 
245
            PyErr_SetString(PyExc_TypeError,
 
246
              "instance exception may not have a separate value");
 
247
            goto failed_throw;
 
248
        }
 
249
        else {
 
250
            /* Normalize to raise <class>, <instance> */
 
251
            Py_XDECREF(val);
 
252
            val = typ;
 
253
            typ = PyExceptionInstance_Class(typ);
 
254
            Py_INCREF(typ);
 
255
        }
 
256
    }
 
257
    else {
 
258
        /* Not something you can raise.  throw() fails. */
 
259
        PyErr_Format(PyExc_TypeError,
 
260
                     "exceptions must be classes, or instances, not %s",
 
261
                     typ->ob_type->tp_name);
 
262
            goto failed_throw;
 
263
    }
 
264
 
 
265
    PyErr_Restore(typ, val, tb);
 
266
    return gen_send_ex(gen, Py_None, 1);
267
267
 
268
268
failed_throw:
269
 
        /* Didn't use our arguments, so restore their original refcounts */
270
 
        Py_DECREF(typ);
271
 
        Py_XDECREF(val);
272
 
        Py_XDECREF(tb);
273
 
        return NULL;
 
269
    /* Didn't use our arguments, so restore their original refcounts */
 
270
    Py_DECREF(typ);
 
271
    Py_XDECREF(val);
 
272
    Py_XDECREF(tb);
 
273
    return NULL;
274
274
}
275
275
 
276
276
 
277
277
static PyObject *
278
278
gen_iternext(PyGenObject *gen)
279
279
{
280
 
        return gen_send_ex(gen, NULL, 0);
 
280
    return gen_send_ex(gen, NULL, 0);
281
281
}
282
282
 
283
283
 
284
284
static PyObject *
285
285
gen_repr(PyGenObject *gen)
286
286
{
287
 
        char *code_name;
288
 
        code_name = PyString_AsString(((PyCodeObject *)gen->gi_code)->co_name);
289
 
        if (code_name == NULL)
290
 
                return NULL;
291
 
        return PyString_FromFormat("<generator object %.200s at %p>",
292
 
                                   code_name, gen);
 
287
    char *code_name;
 
288
    code_name = PyString_AsString(((PyCodeObject *)gen->gi_code)->co_name);
 
289
    if (code_name == NULL)
 
290
        return NULL;
 
291
    return PyString_FromFormat("<generator object %.200s at %p>",
 
292
                               code_name, gen);
293
293
}
294
294
 
295
295
 
296
296
static PyObject *
297
297
gen_get_name(PyGenObject *gen)
298
298
{
299
 
        PyObject *name = ((PyCodeObject *)gen->gi_code)->co_name;
300
 
        Py_INCREF(name);
301
 
        return name;
 
299
    PyObject *name = ((PyCodeObject *)gen->gi_code)->co_name;
 
300
    Py_INCREF(name);
 
301
    return name;
302
302
}
303
303
 
304
304
 
306
306
"Return the name of the generator's associated code object.");
307
307
 
308
308
static PyGetSetDef gen_getsetlist[] = {
309
 
        {"__name__", (getter)gen_get_name, NULL, gen__name__doc__},
310
 
        {NULL}
 
309
    {"__name__", (getter)gen_get_name, NULL, gen__name__doc__},
 
310
    {NULL}
311
311
};
312
312
 
313
313
 
314
314
static PyMemberDef gen_memberlist[] = {
315
 
        {"gi_frame",    T_OBJECT, offsetof(PyGenObject, gi_frame),      RO},
316
 
        {"gi_running",  T_INT,    offsetof(PyGenObject, gi_running),    RO},
317
 
        {"gi_code",     T_OBJECT, offsetof(PyGenObject, gi_code),  RO},
318
 
        {NULL}  /* Sentinel */
 
315
    {"gi_frame",        T_OBJECT, offsetof(PyGenObject, gi_frame),      RO},
 
316
    {"gi_running",      T_INT,    offsetof(PyGenObject, gi_running),    RO},
 
317
    {"gi_code",     T_OBJECT, offsetof(PyGenObject, gi_code),  RO},
 
318
    {NULL}      /* Sentinel */
319
319
};
320
320
 
321
321
static PyMethodDef gen_methods[] = {
322
 
        {"send",(PyCFunction)gen_send, METH_O, send_doc},
323
 
        {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc},
324
 
        {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},
325
 
        {NULL, NULL}    /* Sentinel */
 
322
    {"send",(PyCFunction)gen_send, METH_O, send_doc},
 
323
    {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc},
 
324
    {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},
 
325
    {NULL, NULL}        /* Sentinel */
326
326
};
327
327
 
328
328
PyTypeObject PyGen_Type = {
329
 
        PyVarObject_HEAD_INIT(&PyType_Type, 0)
330
 
        "generator",                            /* tp_name */
331
 
        sizeof(PyGenObject),                    /* tp_basicsize */
332
 
        0,                                      /* tp_itemsize */
333
 
        /* methods */
334
 
        (destructor)gen_dealloc,                /* tp_dealloc */
335
 
        0,                                      /* tp_print */
336
 
        0,                                      /* tp_getattr */
337
 
        0,                                      /* tp_setattr */
338
 
        0,                                      /* tp_compare */
339
 
        (reprfunc)gen_repr,                     /* tp_repr */
340
 
        0,                                      /* tp_as_number */
341
 
        0,                                      /* tp_as_sequence */
342
 
        0,                                      /* tp_as_mapping */
343
 
        0,                                      /* tp_hash */
344
 
        0,                                      /* tp_call */
345
 
        0,                                      /* tp_str */
346
 
        PyObject_GenericGetAttr,                /* tp_getattro */
347
 
        0,                                      /* tp_setattro */
348
 
        0,                                      /* tp_as_buffer */
349
 
        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
350
 
        0,                                      /* tp_doc */
351
 
        (traverseproc)gen_traverse,             /* tp_traverse */
352
 
        0,                                      /* tp_clear */
353
 
        0,                                      /* tp_richcompare */
354
 
        offsetof(PyGenObject, gi_weakreflist),  /* tp_weaklistoffset */
355
 
        PyObject_SelfIter,                      /* tp_iter */
356
 
        (iternextfunc)gen_iternext,             /* tp_iternext */
357
 
        gen_methods,                            /* tp_methods */
358
 
        gen_memberlist,                         /* tp_members */
359
 
        gen_getsetlist,                         /* tp_getset */
360
 
        0,                                      /* tp_base */
361
 
        0,                                      /* tp_dict */
 
329
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
 
330
    "generator",                                /* tp_name */
 
331
    sizeof(PyGenObject),                        /* tp_basicsize */
 
332
    0,                                          /* tp_itemsize */
 
333
    /* methods */
 
334
    (destructor)gen_dealloc,                    /* tp_dealloc */
 
335
    0,                                          /* tp_print */
 
336
    0,                                          /* tp_getattr */
 
337
    0,                                          /* tp_setattr */
 
338
    0,                                          /* tp_compare */
 
339
    (reprfunc)gen_repr,                         /* tp_repr */
 
340
    0,                                          /* tp_as_number */
 
341
    0,                                          /* tp_as_sequence */
 
342
    0,                                          /* tp_as_mapping */
 
343
    0,                                          /* tp_hash */
 
344
    0,                                          /* tp_call */
 
345
    0,                                          /* tp_str */
 
346
    PyObject_GenericGetAttr,                    /* tp_getattro */
 
347
    0,                                          /* tp_setattro */
 
348
    0,                                          /* tp_as_buffer */
 
349
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
 
350
    0,                                          /* tp_doc */
 
351
    (traverseproc)gen_traverse,                 /* tp_traverse */
 
352
    0,                                          /* tp_clear */
 
353
    0,                                          /* tp_richcompare */
 
354
    offsetof(PyGenObject, gi_weakreflist),      /* tp_weaklistoffset */
 
355
    PyObject_SelfIter,                          /* tp_iter */
 
356
    (iternextfunc)gen_iternext,                 /* tp_iternext */
 
357
    gen_methods,                                /* tp_methods */
 
358
    gen_memberlist,                             /* tp_members */
 
359
    gen_getsetlist,                             /* tp_getset */
 
360
    0,                                          /* tp_base */
 
361
    0,                                          /* tp_dict */
362
362
 
363
 
        0,                                      /* tp_descr_get */
364
 
        0,                                      /* tp_descr_set */
365
 
        0,                                      /* tp_dictoffset */
366
 
        0,                                      /* tp_init */
367
 
        0,                                      /* tp_alloc */
368
 
        0,                                      /* tp_new */
369
 
        0,                                      /* tp_free */
370
 
        0,                                      /* tp_is_gc */
371
 
        0,                                      /* tp_bases */
372
 
        0,                                      /* tp_mro */
373
 
        0,                                      /* tp_cache */
374
 
        0,                                      /* tp_subclasses */
375
 
        0,                                      /* tp_weaklist */
376
 
        gen_del,                                /* tp_del */
 
363
    0,                                          /* tp_descr_get */
 
364
    0,                                          /* tp_descr_set */
 
365
    0,                                          /* tp_dictoffset */
 
366
    0,                                          /* tp_init */
 
367
    0,                                          /* tp_alloc */
 
368
    0,                                          /* tp_new */
 
369
    0,                                          /* tp_free */
 
370
    0,                                          /* tp_is_gc */
 
371
    0,                                          /* tp_bases */
 
372
    0,                                          /* tp_mro */
 
373
    0,                                          /* tp_cache */
 
374
    0,                                          /* tp_subclasses */
 
375
    0,                                          /* tp_weaklist */
 
376
    gen_del,                                    /* tp_del */
377
377
};
378
378
 
379
379
PyObject *
380
380
PyGen_New(PyFrameObject *f)
381
381
{
382
 
        PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type);
383
 
        if (gen == NULL) {
384
 
                Py_DECREF(f);
385
 
                return NULL;
386
 
        }
387
 
        gen->gi_frame = f;
388
 
        Py_INCREF(f->f_code);
389
 
        gen->gi_code = (PyObject *)(f->f_code);
390
 
        gen->gi_running = 0;
391
 
        gen->gi_weakreflist = NULL;
392
 
        _PyObject_GC_TRACK(gen);
393
 
        return (PyObject *)gen;
 
382
    PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type);
 
383
    if (gen == NULL) {
 
384
        Py_DECREF(f);
 
385
        return NULL;
 
386
    }
 
387
    gen->gi_frame = f;
 
388
    Py_INCREF(f->f_code);
 
389
    gen->gi_code = (PyObject *)(f->f_code);
 
390
    gen->gi_running = 0;
 
391
    gen->gi_weakreflist = NULL;
 
392
    _PyObject_GC_TRACK(gen);
 
393
    return (PyObject *)gen;
394
394
}
395
395
 
396
396
int
397
397
PyGen_NeedsFinalizing(PyGenObject *gen)
398
398
{
399
 
        int i;
400
 
        PyFrameObject *f = gen->gi_frame;
401
 
 
402
 
        if (f == NULL || f->f_stacktop == NULL || f->f_iblock <= 0)
403
 
                return 0; /* no frame or empty blockstack == no finalization */
404
 
 
405
 
        /* Any block type besides a loop requires cleanup. */
406
 
        i = f->f_iblock;
407
 
        while (--i >= 0) {
408
 
                if (f->f_blockstack[i].b_type != SETUP_LOOP)
409
 
                        return 1;
410
 
        }
411
 
 
412
 
        /* No blocks except loops, it's safe to skip finalization. */
413
 
        return 0;
 
399
    int i;
 
400
    PyFrameObject *f = gen->gi_frame;
 
401
 
 
402
    if (f == NULL || f->f_stacktop == NULL || f->f_iblock <= 0)
 
403
        return 0; /* no frame or empty blockstack == no finalization */
 
404
 
 
405
    /* Any block type besides a loop requires cleanup. */
 
406
    i = f->f_iblock;
 
407
    while (--i >= 0) {
 
408
        if (f->f_blockstack[i].b_type != SETUP_LOOP)
 
409
            return 1;
 
410
    }
 
411
 
 
412
    /* No blocks except loops, it's safe to skip finalization. */
 
413
    return 0;
414
414
}