Merge pull request #7408 from ShaharNaveh/update-test-gen

Update generator related tests from 3.14.3
This commit is contained in:
Jeong, YunWon
2026-03-12 23:47:31 +09:00
committed by GitHub
3 changed files with 98 additions and 8 deletions

35
Lib/test/test_generator_stop.py vendored Normal file
View File

@@ -0,0 +1,35 @@
from __future__ import generator_stop
import unittest
class TestPEP479(unittest.TestCase):
def test_stopiteration_wrapping(self):
def f():
raise StopIteration
def g():
yield f()
with self.assertRaisesRegex(RuntimeError,
"generator raised StopIteration"):
next(g())
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: <class 'NoneType'> is not <class 'StopIteration'>
def test_stopiteration_wrapping_context(self):
def f():
raise StopIteration
def g():
yield f()
try:
next(g())
except RuntimeError as exc:
self.assertIs(type(exc.__cause__), StopIteration)
self.assertIs(type(exc.__context__), StopIteration)
self.assertTrue(exc.__suppress_context__)
else:
self.fail('__cause__, __context__, or __suppress_context__ '
'were not properly set')
if __name__ == '__main__':
unittest.main()

View File

@@ -136,6 +136,19 @@ class FinalizationTest(unittest.TestCase):
self.assertEqual(len(resurrected), 1)
self.assertIsInstance(resurrected[0].gi_code, types.CodeType)
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: <frame object at 0xb4000073269f09e0> is not None
def test_exhausted_generator_frame_cycle(self):
def g():
yield
generator = g()
frame = generator.gi_frame
self.assertIsNone(frame.f_back)
next(generator)
self.assertIsNone(frame.f_back)
next(generator, None)
self.assertIsNone(frame.f_back)
class GeneratorTest(unittest.TestCase):
@@ -292,6 +305,34 @@ class GeneratorTest(unittest.TestCase):
self.assertEqual([1, 2], list(i for i in C()))
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: False is not true
def test_close_clears_frame(self):
# gh-142766: Test that closing a generator clears its frame
class DetectDelete:
def __init__(self):
DetectDelete.deleted = False
def __del__(self):
DetectDelete.deleted = True
def generator(arg):
yield
# Test a freshly created generator (not suspended)
g = generator(DetectDelete())
g.close()
self.assertTrue(DetectDelete.deleted)
# Test a suspended generator
g = generator(DetectDelete())
next(g)
g.close()
self.assertTrue(DetectDelete.deleted)
# Clear via gi_frame.clear()
g = generator(DetectDelete())
g.gi_frame.clear()
self.assertTrue(DetectDelete.deleted)
class ModifyUnderlyingIterableTest(unittest.TestCase):
iterables = [

View File

@@ -538,7 +538,7 @@ class TestPEP380Operation(unittest.TestCase):
"finishing g",
])
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_broken_getattr_handling(self):
"""
Test subiterator with a broken getattr implementation
@@ -882,7 +882,7 @@ class TestPEP380Operation(unittest.TestCase):
yield from ()
self.assertRaises(StopIteration, next, g())
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_delegating_generators_claim_to_be_running(self):
# Check with basic iteration
def one():
@@ -909,7 +909,7 @@ class TestPEP380Operation(unittest.TestCase):
pass
self.assertEqual(res, [0, 1, 2, 3])
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: Lists differ: [0, 1, 2] != [0, 1, 2, 3]
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: Lists differ: [0, 1, 2] != [0, 1, 2, 3]
def test_delegating_generators_claim_to_be_running_with_throw(self):
# Check with throw
class MyErr(Exception):
@@ -1071,7 +1071,7 @@ class TestInterestingEdgeCases(unittest.TestCase):
def assert_generator_ignored_generator_exit(self):
return self.assertRaisesRegex(RuntimeError, r"^generator ignored GeneratorExit$")
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_close_and_throw_work(self):
yielded_first = object()
@@ -1209,7 +1209,7 @@ class TestInterestingEdgeCases(unittest.TestCase):
self.assertIsNone(caught.exception.__context__.__context__)
self.assert_stop_iteration(g)
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: RuntimeError not raised
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: RuntimeError not raised
def test_close_and_throw_raise_stop_iteration(self):
yielded_first = object()
@@ -1449,7 +1449,7 @@ class TestInterestingEdgeCases(unittest.TestCase):
self.assertIsNone(caught.exception.__context__.__context__)
self.assert_stop_iteration(g)
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: None is not StopIteration()
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: None is not StopIteration()
def test_close_and_throw_yield(self):
yielded_first = object()
@@ -1531,8 +1531,9 @@ class TestInterestingEdgeCases(unittest.TestCase):
try:
yield yielded_first
yield yielded_second
finally:
return returned
except:
pass
return returned
def outer():
return (yield from inner())
@@ -1587,6 +1588,19 @@ class TestInterestingEdgeCases(unittest.TestCase):
self.assertIsNone(caught.exception.__context__)
self.assert_stop_iteration(g)
def test_throws_in_iter(self):
# See GH-126366: NULL pointer dereference if __iter__
# threw an exception.
class Silly:
def __iter__(self):
raise RuntimeError("nobody expects the spanish inquisition")
def my_generator():
yield from Silly()
with self.assertRaisesRegex(RuntimeError, "nobody expects the spanish inquisition"):
next(iter(my_generator()))
if __name__ == '__main__':
unittest.main()