Skip to content

Commit ca584d5

Browse files
author
Anselm Kruis
committed
merge 3.3-slp (Stackless python#111)
2 parents dec0d83 + 380bd7a commit ca584d5

File tree

6 files changed

+75
-63
lines changed

6 files changed

+75
-63
lines changed

Include/genobject.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@ PyAPI_DATA(PyTypeObject) PyGen_Type;
3333
#define PyGen_CheckExact(op) (Py_TYPE(op) == &PyGen_Type)
3434

3535
PyAPI_FUNC(PyObject *) PyGen_New(struct _frame *);
36-
#ifdef STACKLESS
37-
#define PyGen_New PyGenerator_New
38-
#endif
3936
PyAPI_FUNC(int) PyGen_NeedsFinalizing(PyGenObject *);
4037
PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **);
4138
PyObject *_PyGen_Send(PyGenObject *, PyObject *);

Objects/genobject.c

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -518,13 +518,8 @@ PyTypeObject PyGen_Type = {
518518

519519
STACKLESS_DECLARE_METHOD(&PyGen_Type, tp_iternext);
520520

521-
#ifdef STACKLESS
522-
PyObject *
523-
PyGenerator_New(PyFrameObject *f)
524-
#else
525521
PyObject *
526522
PyGen_New(PyFrameObject *f)
527-
#endif
528523
{
529524
PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type);
530525
if (gen == NULL) {
@@ -533,19 +528,8 @@ PyGen_New(PyFrameObject *f)
533528
}
534529
gen->gi_frame = f;
535530
f->f_gen = (PyObject *) gen;
536-
#ifdef STACKLESS
537-
/* Support for unpickling generators. This will segmentation fault if
538-
called by pricklepit.c:gen_new as that passes Py_None as a placeholder. */
539-
if ((PyObject*)f == Py_None) {
540-
Py_INCREF(Py_None);
541-
gen->gi_code = Py_None;
542-
} else {
543-
#endif
544531
Py_INCREF(f->f_code);
545532
gen->gi_code = (PyObject *)(f->f_code);
546-
#ifdef STACKLESS
547-
}
548-
#endif
549533
gen->gi_running = 0;
550534
gen->gi_weakreflist = NULL;
551535
_PyObject_GC_TRACK(gen);

Stackless/changelog.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ What's New in Stackless 3.X.X?
99

1010
*Release date: 20XX-XX-XX*
1111

12+
- https://bitbucket.org/stackless-dev/stackless/issues/111
13+
Restore the Python ABI function PyGen_New(). Previously Stackless named this
14+
function PyGenerator_New() and used a macro the redefine PyGen_New as
15+
PyGenerator_New. Stackless is now again binary compatible with Python-
16+
extensions using PyGen_New().
17+
1218
- https://bitbucket.org/stackless-dev/stackless/issues/107
1319
Improve unpickling of traceback objects. Stackless now reconstructs the
1420
frame.f_back linkage in frames directly referenced by traceback objects.

Stackless/core/stackless_impl.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,7 @@ struct _frame * slp_clone_frame(struct _frame *f);
128128
struct _frame * slp_ensure_new_frame(struct _frame *f);
129129

130130
/* exposing some hidden types */
131-
132-
PyAPI_DATA(PyTypeObject) PyGen_Type;
133-
PyAPI_FUNC(PyObject *) PyGenerator_New(struct _frame *f);
134131
PyObject * slp_gen_send_ex(PyGenObject *gen, PyObject *arg, int exc);
135-
#define PyGenerator_Check(op) PyObject_TypeCheck(op, &PyGen_Type)
136132

137133
PyAPI_DATA(PyTypeObject) PyMethodDescr_Type;
138134
PyAPI_DATA(PyTypeObject) PyClassMethodDescr_Type;

Stackless/pickling/prickelpit.c

Lines changed: 51 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2232,29 +2232,12 @@ static int init_methodwrappertype(void)
22322232
22332233
******************************************************/
22342234

2235-
/* Note: this definition is not compatible to 2.2.3, since
2236-
the gi_weakreflist does not exist. Therefore, we don't
2237-
create the object ourselves, but use the provided function
2238-
with a fake frame. The gi_weakreflist is not touched.
2239-
*/
2240-
2241-
typedef struct {
2242-
PyObject_HEAD
2243-
/* The gi_ prefix is intended to remind of generator-iterator. */
2244-
2245-
PyFrameObject *gi_frame;
2246-
2247-
/* True if generator is being executed. */
2248-
char gi_running;
2249-
2250-
/* List of weak reference. */
2251-
PyObject *gi_weakreflist;
2252-
} genobject;
2253-
22542235
static PyTypeObject wrap_PyGen_Type;
2236+
/* Used to initialize a generator created by gen_new. */
2237+
static PyFrameObject *gen_exhausted_frame;
22552238

22562239
static PyObject *
2257-
gen_reduce(genobject *gen)
2240+
gen_reduce(PyGenObject *gen)
22582241
{
22592242
PyObject *tup;
22602243
tup = Py_BuildValue("(O()(Oi))",
@@ -2268,11 +2251,13 @@ gen_reduce(genobject *gen)
22682251
static PyObject *
22692252
gen_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
22702253
{
2271-
genobject *gen;
2272-
2254+
PyGenObject *gen;
22732255
if (is_wrong_type(type)) return NULL;
2274-
Py_INCREF(Py_None);
2275-
gen = (genobject *) PyGenerator_New((PyFrameObject *) Py_None);
2256+
2257+
/* A reference to frame is stolen by PyGen_New. */
2258+
assert(gen_exhausted_frame != NULL);
2259+
assert(PyFrame_Check(gen_exhausted_frame));
2260+
gen = (PyGenObject *) PyGen_New(slp_ensure_new_frame(gen_exhausted_frame));
22762261
if (gen == NULL)
22772262
return NULL;
22782263
Py_TYPE(gen) = type;
@@ -2282,7 +2267,7 @@ gen_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
22822267
static PyObject *
22832268
gen_setstate(PyObject *self, PyObject *args)
22842269
{
2285-
genobject *gen = (genobject *) self;
2270+
PyGenObject *gen = (PyGenObject *) self;
22862271
PyFrameObject *f;
22872272
int gi_running;
22882273

@@ -2294,16 +2279,17 @@ gen_setstate(PyObject *self, PyObject *args)
22942279
if (!gi_running) {
22952280
if ((f = slp_ensure_new_frame(f)) != NULL) {
22962281
/* use a second one for late initialization */
2297-
genobject *tmpgen;
2282+
PyGenObject *tmpgen;
22982283
/* PyGenerator_New eats an existing reference */
2299-
if ((tmpgen = (genobject *)
2300-
PyGenerator_New(f)) == NULL) {
2284+
if ((tmpgen = (PyGenObject *)
2285+
PyGen_New(f)) == NULL) {
23012286
Py_DECREF(f);
23022287
return NULL;
23032288
}
23042289
Py_INCREF(f);
2305-
Py_CLEAR(gen->gi_frame);
2306-
gen->gi_frame = f;
2290+
Py_SETREF(gen->gi_frame, f);
2291+
Py_INCREF(f->f_code);
2292+
Py_SETREF(gen->gi_code, (PyObject *)f->f_code);
23072293
/* The frame the temporary generator references
23082294
will have GeneratorExit raised on it, when the
23092295
temporary generator is torn down. So clearing
@@ -2327,8 +2313,9 @@ gen_setstate(PyObject *self, PyObject *args)
23272313
* generator without the corresponding tasklet.
23282314
*/
23292315
Py_INCREF(f);
2330-
Py_CLEAR(gen->gi_frame);
2331-
gen->gi_frame = f;
2316+
Py_SETREF(gen->gi_frame, f);
2317+
Py_INCREF(f->f_code);
2318+
Py_SETREF(gen->gi_code, (PyObject *)f->f_code);
23322319
gen->gi_running = gi_running;
23332320
Py_TYPE(gen) = Py_TYPE(gen)->tp_base;
23342321
Py_INCREF(gen);
@@ -2343,10 +2330,10 @@ DEF_INVALID_EXEC(gen_iternext_callback)
23432330
static int init_generatortype(void)
23442331
{
23452332
int res;
2346-
genobject *gen = (genobject *) run_script(
2347-
"def f(): yield 42\n" /* define a generator */
2348-
"g = f()\n" /* instanciate it */
2349-
"g.__next__()\n", "g"); /* force callback frame creation */
2333+
PyGenObject *gen = (PyGenObject *) run_script(
2334+
"def exhausted_generator(): yield 42\n" /* define a generator */
2335+
"g = exhausted_generator()\n" /* instanciate it */
2336+
"g.__next__()\n", "g"); /* force callback frame creation */
23502337
PyFrameObject *cbframe;
23512338

23522339
if (gen == NULL || gen->gi_frame->f_back == NULL)
@@ -2356,6 +2343,13 @@ static int init_generatortype(void)
23562343
gen->gi_frame->f_back->f_execute,
23572344
REF_INVALID_EXEC(gen_iternext_callback))
23582345
|| init_type(&wrap_PyGen_Type, initchain);
2346+
2347+
assert(gen_exhausted_frame == NULL);
2348+
gen_exhausted_frame = slp_ensure_new_frame(gen->gi_frame);
2349+
if (gen_exhausted_frame == NULL) {
2350+
return -1;
2351+
}
2352+
23592353
Py_DECREF(gen);
23602354
return res;
23612355
}
@@ -2458,23 +2452,36 @@ slp_pickle_moduledict(PyObject *self, PyObject *args)
24582452
source module initialization
24592453
24602454
******************************************************/
2455+
static int
2456+
_wrapmodule_traverse(PyObject *self, visitproc visit, void *arg)
2457+
{
2458+
Py_VISIT(gen_exhausted_frame);
2459+
return 0;
2460+
}
2461+
2462+
static int
2463+
_wrapmodule_clear(PyObject *self)
2464+
{
2465+
Py_CLEAR(gen_exhausted_frame);
2466+
return 0;
2467+
}
2468+
24612469
static struct PyModuleDef _wrapmodule = {
24622470
PyModuleDef_HEAD_INIT,
24632471
"_stackless._wrap",
24642472
NULL,
24652473
-1,
24662474
NULL,
24672475
NULL,
2468-
NULL,
2469-
NULL,
2476+
_wrapmodule_traverse,
2477+
_wrapmodule_clear,
24702478
NULL
24712479
};
24722480

24732481
PyObject*
24742482
init_prickelpit(void)
24752483
{
24762484
PyObject *copy_reg, *tmp;
2477-
int ret = 0;
24782485

24792486
types_mod = PyModule_Create(&_wrapmodule);
24802487
if (types_mod == NULL)
@@ -2491,7 +2498,11 @@ init_prickelpit(void)
24912498
Py_CLEAR(types_mod);
24922499
return NULL;
24932500
}
2494-
ret = initchain();
2501+
if (initchain()) {
2502+
Py_CLEAR(pickle_reg);
2503+
Py_CLEAR(types_mod);
2504+
return NULL;
2505+
}
24952506
Py_CLEAR(pickle_reg);
24962507
tmp = types_mod;
24972508
types_mod = NULL;

Stackless/unittests/test_generator.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import unittest
22
import gc
33
import stackless
4+
import types
45

56
from support import StacklessTestCase
67

@@ -31,5 +32,22 @@ def testSimpleLeakage(self):
3132
if len(leakage):
3233
self.failUnless(len(leakage) == 0, "Leaked %s" % repr(leakage))
3334

35+
36+
class TestGeneratorWrapper(StacklessTestCase):
37+
def test_run_wrap_generator(self):
38+
g = stackless._wrap.generator()
39+
self.assertIsInstance(g, types.GeneratorType)
40+
self.assertIsNot(type(g), types.GeneratorType)
41+
self.assertRaises(StopIteration, next, g)
42+
43+
def test_wrap_generator_frame_code(self):
44+
g0 = stackless._wrap.generator()
45+
g1 = stackless._wrap.generator()
46+
self.assertIsInstance(g0.gi_frame, types.FrameType)
47+
self.assertIsInstance(g0.gi_code, types.CodeType)
48+
self.assertIs(g0.gi_code, g1.gi_code)
49+
self.assertIsNot(g0.gi_frame, g1.gi_frame)
50+
self.assertEqual(g0.__name__, "exhausted_generator")
51+
3452
if __name__ == '__main__':
3553
unittest.main()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy