mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
PEP 479 wraps a StopIteration raised from a generator/coroutine into a RuntimeError. CPython sets both __cause__ and __context__ of the new RuntimeError to the original StopIteration (the same object). RustPython's wrapping sites set __cause__ only, leaving __context__ as None. set___cause__ already toggles __suppress_context__ to true, so the user-facing traceback is unchanged — only assertions that inspect __context__ directly observe the gap. Three sites all wrap StopIteration / StopAsyncIteration into RuntimeError for PEP 479. Set __context__ to the same exception instance before setting __cause__ at each: - frame.rs::StopIterationError intrinsic (generator yield-expression path) - coroutine.rs generator __next__ StopIteration branch - coroutine.rs async-generator __anext__ StopAsyncIteration branch PyBaseExceptionRef is Arc-backed, so e.clone() is a refcount bump; 'cause is context' holds, matching CPython. Unmasks: - test_generator_stop.TestPEP479.test_stopiteration_wrapping_context - test_yield_from.TestInterestingEdgeCases.test_close_and_throw_work - test_yield_from.TestInterestingEdgeCases.test_close_and_throw_raise_stop_iteration - test_yield_from.TestInterestingEdgeCases.test_close_and_throw_yield
35 lines
943 B
Python
Vendored
35 lines
943 B
Python
Vendored
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())
|
|
|
|
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()
|