Skip to content

Commit b6c3cea

Browse files
committed
SF bug #436207: "if 0: yield x" is ignored.
Not anymore <wink>. Pure hack. Doesn't fix any other "if 0:" glitches.
1 parent 3e7b1a0 commit b6c3cea

File tree

2 files changed

+161
-8
lines changed

2 files changed

+161
-8
lines changed

Diff for: Lib/test/test_generators.py

+128-7
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,9 @@
431431
Try writing it without generators, and correctly, and without generating
432432
3 internal results for each result output.
433433
434+
XXX Suspect there's memory leaks in this one; definitely in the next
435+
XXX version.
436+
434437
>>> def times(n, g):
435438
... for i in g:
436439
... yield n * i
@@ -482,6 +485,8 @@
482485
functions can be reused as-is, because they only assume their stream
483486
arguments are iterable -- a LazyList is the same as a generator to times().
484487
488+
XXX Massive memory leaks in this; see Python-Iterators.
489+
485490
>>> class LazyList:
486491
... def __init__(self, g):
487492
... self.sofar = []
@@ -514,7 +519,8 @@
514519
[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
515520
"""
516521

517-
# syntax_tests mostly provokes SyntaxErrors.
522+
# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
523+
# hackery.
518524

519525
syntax_tests = """
520526
@@ -588,13 +594,128 @@
588594
... return
589595
>>> list(f())
590596
[12, 666]
597+
598+
>>> def f():
599+
... if 0:
600+
... yield 1
601+
>>> type(f())
602+
<type 'generator'>
603+
604+
>>> def f():
605+
... if "":
606+
... yield None
607+
>>> type(f())
608+
<type 'generator'>
609+
610+
>>> def f():
611+
... return
612+
... try:
613+
... if x==4:
614+
... pass
615+
... elif 0:
616+
... try:
617+
... 1/0
618+
... except SyntaxError:
619+
... pass
620+
... else:
621+
... if 0:
622+
... while 12:
623+
... x += 1
624+
... yield 2 # don't blink
625+
... f(a, b, c, d, e)
626+
... else:
627+
... pass
628+
... except:
629+
... x = 1
630+
... return
631+
>>> type(f())
632+
<type 'generator'>
633+
634+
>>> def f():
635+
... if 0:
636+
... def g():
637+
... yield 1
638+
...
639+
>>> type(f())
640+
<type 'None'>
641+
642+
>>> def f():
643+
... if 0:
644+
... class C:
645+
... def __init__(self):
646+
... yield 1
647+
... def f(self):
648+
... yield 2
649+
>>> type(f())
650+
<type 'None'>
651+
"""
652+
653+
654+
x_tests = """
655+
656+
>>> def firstn(g, n):
657+
... return [g.next() for i in range(n)]
658+
659+
>>> def times(n, g):
660+
... for i in g:
661+
... yield n * i
662+
663+
>>> def merge(g, h):
664+
... ng = g.next()
665+
... nh = h.next()
666+
... while 1:
667+
... if ng < nh:
668+
... yield ng
669+
... ng = g.next()
670+
... elif ng > nh:
671+
... yield nh
672+
... nh = h.next()
673+
... else:
674+
... yield ng
675+
... ng = g.next()
676+
... nh = h.next()
677+
678+
>>> class LazyList:
679+
... def __init__(self, g):
680+
... self.sofar = []
681+
... self.fetch = g.next
682+
...
683+
... def __getitem__(self, i):
684+
... sofar, fetch = self.sofar, self.fetch
685+
... while i >= len(sofar):
686+
... sofar.append(fetch())
687+
... return sofar[i]
688+
689+
>>> def m235():
690+
... yield 1
691+
... # Gack: m235 below actually refers to a LazyList.
692+
... me_times2 = times(2, m235)
693+
... me_times3 = times(3, m235)
694+
... me_times5 = times(5, m235)
695+
... for i in merge(merge(me_times2,
696+
... me_times3),
697+
... me_times5):
698+
... yield i
699+
700+
>>> m235 = LazyList(m235())
701+
>>> for i in range(5):
702+
... x = [m235[j] for j in range(15*i, 15*(i+1))]
703+
704+
705+
[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
706+
[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
707+
[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
708+
[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
709+
[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
591710
"""
592711

593-
__test__ = {"tut": tutorial_tests,
594-
"pep": pep_tests,
595-
"email": email_tests,
596-
"fun": fun_tests,
597-
"syntax": syntax_tests}
712+
__test__ = {"tut": tutorial_tests, # clean
713+
"pep": pep_tests, # clean
714+
"email": email_tests, # clean
715+
"fun": fun_tests, # leaks
716+
"syntax": syntax_tests # clean
717+
#"x": x_tests
718+
}
598719

599720
# Magic test name that regrtest.py invokes *after* importing this module.
600721
# This worms around a bootstrap problem.
@@ -605,7 +726,7 @@ def test_main():
605726
if 0:
606727
# Temporary block to help track down leaks. So far, the blame
607728
# has fallen mostly on doctest.
608-
for i in range(1000):
729+
for i in range(5000):
609730
doctest.master = None
610731
doctest.testmod(test_generators)
611732
else:

Diff for: Python/compile.c

+33-1
Original file line numberDiff line numberDiff line change
@@ -4840,6 +4840,34 @@ symtable_add_def_o(struct symtable *st, PyObject *dict,
48404840

48414841
#define symtable_add_use(ST, NAME) symtable_add_def((ST), (NAME), USE)
48424842

4843+
/* Look for a yield stmt under n. Return 1 if found, else 0. */
4844+
static int
4845+
look_for_yield(node *n)
4846+
{
4847+
int i;
4848+
4849+
for (i = 0; i < NCH(n); ++i) {
4850+
node *kid = CHILD(n, i);
4851+
4852+
switch (TYPE(kid)) {
4853+
4854+
case classdef:
4855+
case funcdef:
4856+
/* Stuff in nested functions and classes can't make
4857+
the parent a generator. */
4858+
return 0;
4859+
4860+
case yield_stmt:
4861+
return 1;
4862+
4863+
default:
4864+
if (look_for_yield(kid))
4865+
return 1;
4866+
}
4867+
}
4868+
return 0;
4869+
}
4870+
48434871
static void
48444872
symtable_node(struct symtable *st, node *n)
48454873
{
@@ -4883,8 +4911,12 @@ symtable_node(struct symtable *st, node *n)
48834911
}
48844912
case if_stmt:
48854913
for (i = 0; i + 3 < NCH(n); i += 4) {
4886-
if (is_constant_false(NULL, (CHILD(n, i + 1))))
4914+
if (is_constant_false(NULL, (CHILD(n, i + 1)))) {
4915+
if (st->st_cur->ste_generator == 0)
4916+
st->st_cur->ste_generator =
4917+
look_for_yield(CHILD(n, i+3));
48874918
continue;
4919+
}
48884920
symtable_node(st, CHILD(n, i + 1));
48894921
symtable_node(st, CHILD(n, i + 3));
48904922
}

0 commit comments

Comments
 (0)