Skip to content

Commit f26752c

Browse files
authored
Merge pull request #7408 from ShaharNaveh/update-test-gen
Update generator related tests from 3.14.3
2 parents 04b1feb + 93865e6 commit f26752c

File tree

3 files changed

+98
-8
lines changed

3 files changed

+98
-8
lines changed

Lib/test/test_generator_stop.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from __future__ import generator_stop
2+
3+
import unittest
4+
5+
6+
class TestPEP479(unittest.TestCase):
7+
def test_stopiteration_wrapping(self):
8+
def f():
9+
raise StopIteration
10+
def g():
11+
yield f()
12+
with self.assertRaisesRegex(RuntimeError,
13+
"generator raised StopIteration"):
14+
next(g())
15+
16+
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: <class 'NoneType'> is not <class 'StopIteration'>
17+
def test_stopiteration_wrapping_context(self):
18+
def f():
19+
raise StopIteration
20+
def g():
21+
yield f()
22+
23+
try:
24+
next(g())
25+
except RuntimeError as exc:
26+
self.assertIs(type(exc.__cause__), StopIteration)
27+
self.assertIs(type(exc.__context__), StopIteration)
28+
self.assertTrue(exc.__suppress_context__)
29+
else:
30+
self.fail('__cause__, __context__, or __suppress_context__ '
31+
'were not properly set')
32+
33+
34+
if __name__ == '__main__':
35+
unittest.main()

Lib/test/test_generators.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,19 @@ def gen():
136136
self.assertEqual(len(resurrected), 1)
137137
self.assertIsInstance(resurrected[0].gi_code, types.CodeType)
138138

139+
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: <frame object at 0xb4000073269f09e0> is not None
140+
def test_exhausted_generator_frame_cycle(self):
141+
def g():
142+
yield
143+
144+
generator = g()
145+
frame = generator.gi_frame
146+
self.assertIsNone(frame.f_back)
147+
next(generator)
148+
self.assertIsNone(frame.f_back)
149+
next(generator, None)
150+
self.assertIsNone(frame.f_back)
151+
139152

140153
class GeneratorTest(unittest.TestCase):
141154

@@ -292,6 +305,34 @@ def __iter__(self):
292305

293306
self.assertEqual([1, 2], list(i for i in C()))
294307

308+
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: False is not true
309+
def test_close_clears_frame(self):
310+
# gh-142766: Test that closing a generator clears its frame
311+
class DetectDelete:
312+
def __init__(self):
313+
DetectDelete.deleted = False
314+
315+
def __del__(self):
316+
DetectDelete.deleted = True
317+
318+
def generator(arg):
319+
yield
320+
321+
# Test a freshly created generator (not suspended)
322+
g = generator(DetectDelete())
323+
g.close()
324+
self.assertTrue(DetectDelete.deleted)
325+
326+
# Test a suspended generator
327+
g = generator(DetectDelete())
328+
next(g)
329+
g.close()
330+
self.assertTrue(DetectDelete.deleted)
331+
332+
# Clear via gi_frame.clear()
333+
g = generator(DetectDelete())
334+
g.gi_frame.clear()
335+
self.assertTrue(DetectDelete.deleted)
295336

296337
class ModifyUnderlyingIterableTest(unittest.TestCase):
297338
iterables = [

Lib/test/test_yield_from.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ def g():
538538
"finishing g",
539539
])
540540

541-
@unittest.expectedFailure # TODO: RUSTPYTHON
541+
@unittest.expectedFailure # TODO: RUSTPYTHON
542542
def test_broken_getattr_handling(self):
543543
"""
544544
Test subiterator with a broken getattr implementation
@@ -882,7 +882,7 @@ def g():
882882
yield from ()
883883
self.assertRaises(StopIteration, next, g())
884884

885-
@unittest.expectedFailure # TODO: RUSTPYTHON
885+
@unittest.expectedFailure # TODO: RUSTPYTHON
886886
def test_delegating_generators_claim_to_be_running(self):
887887
# Check with basic iteration
888888
def one():
@@ -909,7 +909,7 @@ def two():
909909
pass
910910
self.assertEqual(res, [0, 1, 2, 3])
911911

912-
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: Lists differ: [0, 1, 2] != [0, 1, 2, 3]
912+
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: Lists differ: [0, 1, 2] != [0, 1, 2, 3]
913913
def test_delegating_generators_claim_to_be_running_with_throw(self):
914914
# Check with throw
915915
class MyErr(Exception):
@@ -1071,7 +1071,7 @@ def assert_generator_raised_stop_iteration(self):
10711071
def assert_generator_ignored_generator_exit(self):
10721072
return self.assertRaisesRegex(RuntimeError, r"^generator ignored GeneratorExit$")
10731073

1074-
@unittest.expectedFailure # TODO: RUSTPYTHON
1074+
@unittest.expectedFailure # TODO: RUSTPYTHON
10751075
def test_close_and_throw_work(self):
10761076

10771077
yielded_first = object()
@@ -1209,7 +1209,7 @@ def outer():
12091209
self.assertIsNone(caught.exception.__context__.__context__)
12101210
self.assert_stop_iteration(g)
12111211

1212-
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: RuntimeError not raised
1212+
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: RuntimeError not raised
12131213
def test_close_and_throw_raise_stop_iteration(self):
12141214

12151215
yielded_first = object()
@@ -1449,7 +1449,7 @@ def outer():
14491449
self.assertIsNone(caught.exception.__context__.__context__)
14501450
self.assert_stop_iteration(g)
14511451

1452-
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: None is not StopIteration()
1452+
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: None is not StopIteration()
14531453
def test_close_and_throw_yield(self):
14541454

14551455
yielded_first = object()
@@ -1531,8 +1531,9 @@ def inner():
15311531
try:
15321532
yield yielded_first
15331533
yield yielded_second
1534-
finally:
1535-
return returned
1534+
except:
1535+
pass
1536+
return returned
15361537

15371538
def outer():
15381539
return (yield from inner())
@@ -1587,6 +1588,19 @@ def outer():
15871588
self.assertIsNone(caught.exception.__context__)
15881589
self.assert_stop_iteration(g)
15891590

1591+
def test_throws_in_iter(self):
1592+
# See GH-126366: NULL pointer dereference if __iter__
1593+
# threw an exception.
1594+
class Silly:
1595+
def __iter__(self):
1596+
raise RuntimeError("nobody expects the spanish inquisition")
1597+
1598+
def my_generator():
1599+
yield from Silly()
1600+
1601+
with self.assertRaisesRegex(RuntimeError, "nobody expects the spanish inquisition"):
1602+
next(iter(my_generator()))
1603+
15901604

15911605
if __name__ == '__main__':
15921606
unittest.main()

0 commit comments

Comments
 (0)