mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Update some tests to 3.13.7 (#6171)
* Update `test_call.py` from 3.13.7 * Update `test_yield_from.py` from 3.13.7 * Update more tests to 3.13.7 * More tests to 3.13.7 * Remove patch from passing test
This commit is contained in:
1 parent
24f4fbad82
commit
3c01be29c4
9 files changed
+1331
-270
No files matched your search
Vendored
+681
-201
File diff suppressed because it is too large.
Load diff
Vendored
+2
-3
@@ -344,10 +344,9 @@ class OtherFileTests:
|
||||
class COtherFileTests(OtherFileTests, unittest.TestCase):
|
||||
open = io.open
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def testSetBufferSize(self):
|
||||
super().testSetBufferSize()
|
||||
return super().testSetBufferSize()
|
||||
|
||||
class PyOtherFileTests(OtherFileTests, unittest.TestCase):
|
||||
open = staticmethod(pyio.open)
|
||||
|
||||
Vendored
+16
-2
@@ -185,6 +185,21 @@ class TestCause(unittest.TestCase):
|
||||
else:
|
||||
self.fail("No exception raised")
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; TypeError: 'classmethod' object is not callable
|
||||
def test_class_cause_nonexception_result(self):
|
||||
class ConstructsNone(BaseException):
|
||||
@classmethod
|
||||
def __new__(*args, **kwargs):
|
||||
return None
|
||||
try:
|
||||
raise IndexError from ConstructsNone
|
||||
except TypeError as e:
|
||||
self.assertIn("should have returned an instance of BaseException", str(e))
|
||||
except IndexError:
|
||||
self.fail("Wrong kind of exception raised")
|
||||
else:
|
||||
self.fail("No exception raised")
|
||||
|
||||
def test_instance_cause(self):
|
||||
cause = KeyError()
|
||||
try:
|
||||
@@ -233,8 +248,7 @@ class TestTracebackType(unittest.TestCase):
|
||||
def raiser(self):
|
||||
raise ValueError
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_attrs(self):
|
||||
try:
|
||||
self.raiser()
|
||||
|
||||
Vendored
+76
-4
@@ -177,6 +177,57 @@ class ScopeTests(unittest.TestCase):
|
||||
self.assertEqual(foo(a=42), 50)
|
||||
self.assertEqual(foo(), 25)
|
||||
|
||||
def testCellIsArgAndEscapes(self):
|
||||
# We need to be sure that a cell passed in as an arg still
|
||||
# gets wrapped in a new cell if the arg escapes into an
|
||||
# inner function (closure).
|
||||
|
||||
def external():
|
||||
value = 42
|
||||
def inner():
|
||||
return value
|
||||
cell, = inner.__closure__
|
||||
return cell
|
||||
cell_ext = external()
|
||||
|
||||
def spam(arg):
|
||||
def eggs():
|
||||
return arg
|
||||
return eggs
|
||||
|
||||
eggs = spam(cell_ext)
|
||||
cell_closure, = eggs.__closure__
|
||||
cell_eggs = eggs()
|
||||
|
||||
self.assertIs(cell_eggs, cell_ext)
|
||||
self.assertIsNot(cell_eggs, cell_closure)
|
||||
|
||||
def testCellIsLocalAndEscapes(self):
|
||||
# We need to be sure that a cell bound to a local still
|
||||
# gets wrapped in a new cell if the local escapes into an
|
||||
# inner function (closure).
|
||||
|
||||
def external():
|
||||
value = 42
|
||||
def inner():
|
||||
return value
|
||||
cell, = inner.__closure__
|
||||
return cell
|
||||
cell_ext = external()
|
||||
|
||||
def spam(arg):
|
||||
cell = arg
|
||||
def eggs():
|
||||
return cell
|
||||
return eggs
|
||||
|
||||
eggs = spam(cell_ext)
|
||||
cell_closure, = eggs.__closure__
|
||||
cell_eggs = eggs()
|
||||
|
||||
self.assertIs(cell_eggs, cell_ext)
|
||||
self.assertIsNot(cell_eggs, cell_closure)
|
||||
|
||||
def testRecursion(self):
|
||||
|
||||
def f(x):
|
||||
@@ -641,10 +692,7 @@ class ScopeTests(unittest.TestCase):
|
||||
self.assertEqual(c.dec(), 1)
|
||||
self.assertEqual(c.dec(), 0)
|
||||
|
||||
# TODO: RUSTPYTHON, figure out how to communicate that `y = 9` should be
|
||||
# stored as a global rather than a STORE_NAME, even when
|
||||
# the `global y` is in a nested subscope
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; figure out how to communicate that `y = 9` should be stored as a global rather than a STORE_NAME, even when the `global y` is in a nested subscope
|
||||
def testGlobalInParallelNestedFunctions(self):
|
||||
# A symbol table bug leaked the global statement from one
|
||||
# function to other nested functions in the same block.
|
||||
@@ -763,6 +811,30 @@ class ScopeTests(unittest.TestCase):
|
||||
gc_collect() # For PyPy or other GCs.
|
||||
self.assertIsNone(ref())
|
||||
|
||||
def test_multiple_nesting(self):
|
||||
# Regression test for https://github.com/python/cpython/issues/121863
|
||||
class MultiplyNested:
|
||||
def f1(self):
|
||||
__arg = 1
|
||||
class D:
|
||||
def g(self, __arg):
|
||||
return __arg
|
||||
return D().g(_MultiplyNested__arg=2)
|
||||
|
||||
def f2(self):
|
||||
__arg = 1
|
||||
class D:
|
||||
def g(self, __arg):
|
||||
return __arg
|
||||
return D().g
|
||||
|
||||
inst = MultiplyNested()
|
||||
with self.assertRaises(TypeError):
|
||||
inst.f1()
|
||||
|
||||
closure = inst.f2()
|
||||
with self.assertRaises(TypeError):
|
||||
closure(_MultiplyNested__arg=2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Vendored
+1
-2
@@ -286,8 +286,7 @@ class SliceTest(unittest.TestCase):
|
||||
self.assertIsNot(s.stop, c.stop)
|
||||
self.assertIsNot(s.step, c.step)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_cycle(self):
|
||||
class myobj(): pass
|
||||
o = myobj()
|
||||
|
||||
Vendored
+5
-10
@@ -105,8 +105,7 @@ class TestLiterals(unittest.TestCase):
|
||||
self.assertRaises(SyntaxError, eval, r""" '\U000000' """)
|
||||
self.assertRaises(SyntaxError, eval, r""" '\U0000000' """)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_eval_str_invalid_escape(self):
|
||||
for b in range(1, 128):
|
||||
if b in b"""\n\r"'01234567NU\\abfnrtuvx""":
|
||||
@@ -145,8 +144,7 @@ class TestLiterals(unittest.TestCase):
|
||||
self.assertRegex(str(w[0].message), 'invalid escape sequence')
|
||||
self.assertEqual(w[0].filename, '<string>')
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_eval_str_invalid_octal_escape(self):
|
||||
for i in range(0o400, 0o1000):
|
||||
with self.assertWarns(SyntaxWarning):
|
||||
@@ -172,8 +170,7 @@ class TestLiterals(unittest.TestCase):
|
||||
self.assertEqual(exc.lineno, 2)
|
||||
self.assertEqual(exc.offset, 1)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_invalid_escape_locations_with_offset(self):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('error', category=SyntaxWarning)
|
||||
@@ -223,8 +220,7 @@ class TestLiterals(unittest.TestCase):
|
||||
self.assertRaises(SyntaxError, eval, r""" b'\x' """)
|
||||
self.assertRaises(SyntaxError, eval, r""" b'\x0' """)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_eval_bytes_invalid_escape(self):
|
||||
for b in range(1, 128):
|
||||
if b in b"""\n\r"'01234567\\abfnrtvx""":
|
||||
@@ -250,8 +246,7 @@ class TestLiterals(unittest.TestCase):
|
||||
self.assertEqual(exc.filename, '<string>')
|
||||
self.assertEqual(exc.lineno, 2)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_eval_bytes_invalid_octal_escape(self):
|
||||
for i in range(0o400, 0o1000):
|
||||
with self.assertWarns(SyntaxWarning):
|
||||
|
||||
Vendored
+6
-11
@@ -146,7 +146,7 @@ class StrtodTests(unittest.TestCase):
|
||||
digits *= 5
|
||||
exponent -= 1
|
||||
|
||||
@unittest.skip("TODO: RUSTPYTHON, fails on debug mode, flaky in release mode")
|
||||
@unittest.skip('TODO: RUSTPYTHON; fails on debug mode, flaky in release mode')
|
||||
def test_halfway_cases(self):
|
||||
# test halfway cases for the round-half-to-even rule
|
||||
for i in range(100 * TEST_SIZE):
|
||||
@@ -173,8 +173,7 @@ class StrtodTests(unittest.TestCase):
|
||||
s = '{}e{}'.format(digits, exponent)
|
||||
self.check_strtod(s)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_boundaries(self):
|
||||
# boundaries expressed as triples (n, e, u), where
|
||||
# n*10**e is an approximation to the boundary value and
|
||||
@@ -195,8 +194,7 @@ class StrtodTests(unittest.TestCase):
|
||||
u *= 10
|
||||
e -= 1
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_underflow_boundary(self):
|
||||
# test values close to 2**-1075, the underflow boundary; similar
|
||||
# to boundary_tests, except that the random error doesn't scale
|
||||
@@ -208,8 +206,7 @@ class StrtodTests(unittest.TestCase):
|
||||
s = '{}e{}'.format(digits, exponent)
|
||||
self.check_strtod(s)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_bigcomp(self):
|
||||
for ndigs in 5, 10, 14, 15, 16, 17, 18, 19, 20, 40, 41, 50:
|
||||
dig10 = 10**ndigs
|
||||
@@ -219,8 +216,7 @@ class StrtodTests(unittest.TestCase):
|
||||
s = '{}e{}'.format(digits, exponent)
|
||||
self.check_strtod(s)
|
||||
|
||||
# TODO: RUSTPYTHON, Incorrectly rounded str->float conversion for -07e-321
|
||||
@unittest.skip("TODO: RUSTPYTHON; flaky test")
|
||||
@unittest.skip('TODO: RUSTPYTHON; flaky test')
|
||||
def test_parsing(self):
|
||||
# make '0' more likely to be chosen than other digits
|
||||
digits = '000000123456789'
|
||||
@@ -288,8 +284,7 @@ class StrtodTests(unittest.TestCase):
|
||||
self.assertEqual(float(negative_exp(20000)), 1.0)
|
||||
self.assertEqual(float(negative_exp(30000)), 1.0)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_particular(self):
|
||||
# inputs that produced crashes or incorrectly rounded results with
|
||||
# previous versions of dtoa.c, for various reasons
|
||||
|
||||
Vendored
+1
-28
@@ -1,14 +1,11 @@
|
||||
"""Do a minimal test of all the modules that aren't otherwise tested."""
|
||||
import importlib
|
||||
import platform
|
||||
import sys
|
||||
from test import support
|
||||
from test.support import import_helper
|
||||
from test.support import warnings_helper
|
||||
import unittest
|
||||
|
||||
class TestUntestedModules(unittest.TestCase):
|
||||
@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON")
|
||||
def test_untested_modules_can_be_imported(self):
|
||||
untested = ('encodings',)
|
||||
with warnings_helper.check_warnings(quiet=True):
|
||||
@@ -21,31 +18,6 @@ class TestUntestedModules(unittest.TestCase):
|
||||
self.fail('{} has tests even though test_sundry claims '
|
||||
'otherwise'.format(name))
|
||||
|
||||
import distutils.bcppcompiler
|
||||
import distutils.ccompiler
|
||||
import distutils.cygwinccompiler
|
||||
import distutils.filelist
|
||||
import distutils.text_file
|
||||
import distutils.unixccompiler
|
||||
|
||||
import distutils.command.bdist_dumb
|
||||
if sys.platform.startswith('win') and not platform.win32_is_iot():
|
||||
import distutils.command.bdist_msi
|
||||
import distutils.command.bdist
|
||||
import distutils.command.bdist_rpm
|
||||
import distutils.command.build_clib
|
||||
import distutils.command.build_ext
|
||||
import distutils.command.build
|
||||
import distutils.command.clean
|
||||
import distutils.command.config
|
||||
import distutils.command.install_data
|
||||
import distutils.command.install_egg_info
|
||||
import distutils.command.install_headers
|
||||
import distutils.command.install_lib
|
||||
import distutils.command.register
|
||||
import distutils.command.sdist
|
||||
import distutils.command.upload
|
||||
|
||||
import html.entities
|
||||
|
||||
try:
|
||||
@@ -54,5 +26,6 @@ class TestUntestedModules(unittest.TestCase):
|
||||
if support.verbose:
|
||||
print("skipping tty")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Vendored
+543
-9
@@ -538,8 +538,7 @@ class TestPEP380Operation(unittest.TestCase):
|
||||
"finishing g",
|
||||
])
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_broken_getattr_handling(self):
|
||||
"""
|
||||
Test subiterator with a broken getattr implementation
|
||||
@@ -787,8 +786,7 @@ class TestPEP380Operation(unittest.TestCase):
|
||||
repr(value),
|
||||
])
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_throwing_GeneratorExit_into_subgen_that_returns(self):
|
||||
"""
|
||||
Test throwing GeneratorExit into a subgenerator that
|
||||
@@ -819,8 +817,7 @@ class TestPEP380Operation(unittest.TestCase):
|
||||
"Enter f",
|
||||
])
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_throwing_GeneratorExit_into_subgenerator_that_yields(self):
|
||||
"""
|
||||
Test throwing GeneratorExit into a subgenerator that
|
||||
@@ -887,8 +884,7 @@ class TestPEP380Operation(unittest.TestCase):
|
||||
yield from ()
|
||||
self.assertRaises(StopIteration, next, g())
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_delegating_generators_claim_to_be_running(self):
|
||||
# Check with basic iteration
|
||||
def one():
|
||||
@@ -904,6 +900,7 @@ class TestPEP380Operation(unittest.TestCase):
|
||||
yield 2
|
||||
g1 = one()
|
||||
self.assertEqual(list(g1), [0, 1, 2, 3])
|
||||
|
||||
# Check with send
|
||||
g1 = one()
|
||||
res = [next(g1)]
|
||||
@@ -913,6 +910,9 @@ class TestPEP380Operation(unittest.TestCase):
|
||||
except StopIteration:
|
||||
pass
|
||||
self.assertEqual(res, [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):
|
||||
pass
|
||||
@@ -949,8 +949,10 @@ class TestPEP380Operation(unittest.TestCase):
|
||||
except:
|
||||
self.assertEqual(res, [0, 1, 2, 3])
|
||||
raise
|
||||
|
||||
def test_delegating_generators_claim_to_be_running_with_close(self):
|
||||
# Check with close
|
||||
class MyIt(object):
|
||||
class MyIt:
|
||||
def __iter__(self):
|
||||
return self
|
||||
def __next__(self):
|
||||
@@ -1057,6 +1059,538 @@ class TestPEP380Operation(unittest.TestCase):
|
||||
g.send((1, 2, 3, 4))
|
||||
self.assertEqual(v, (1, 2, 3, 4))
|
||||
|
||||
class TestInterestingEdgeCases(unittest.TestCase):
|
||||
|
||||
def assert_stop_iteration(self, iterator):
|
||||
with self.assertRaises(StopIteration) as caught:
|
||||
next(iterator)
|
||||
self.assertIsNone(caught.exception.value)
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
|
||||
def assert_generator_raised_stop_iteration(self):
|
||||
return self.assertRaisesRegex(RuntimeError, r"^generator raised StopIteration$")
|
||||
|
||||
def assert_generator_ignored_generator_exit(self):
|
||||
return self.assertRaisesRegex(RuntimeError, r"^generator ignored GeneratorExit$")
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_close_and_throw_work(self):
|
||||
|
||||
yielded_first = object()
|
||||
yielded_second = object()
|
||||
returned = object()
|
||||
|
||||
def inner():
|
||||
yield yielded_first
|
||||
yield yielded_second
|
||||
return returned
|
||||
|
||||
def outer():
|
||||
return (yield from inner())
|
||||
|
||||
with self.subTest("close"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
g.close()
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw GeneratorExit"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
thrown = GeneratorExit()
|
||||
with self.assertRaises(GeneratorExit) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, thrown)
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw StopIteration"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
thrown = StopIteration()
|
||||
# PEP 479:
|
||||
with self.assert_generator_raised_stop_iteration() as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw BaseException"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
thrown = BaseException()
|
||||
with self.assertRaises(BaseException) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, thrown)
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw Exception"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
thrown = Exception()
|
||||
with self.assertRaises(Exception) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, thrown)
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: GeneratorExit() is not GeneratorExit()
|
||||
def test_close_and_throw_raise_generator_exit(self):
|
||||
|
||||
yielded_first = object()
|
||||
yielded_second = object()
|
||||
returned = object()
|
||||
|
||||
def inner():
|
||||
try:
|
||||
yield yielded_first
|
||||
yield yielded_second
|
||||
return returned
|
||||
finally:
|
||||
raise raised
|
||||
|
||||
def outer():
|
||||
return (yield from inner())
|
||||
|
||||
with self.subTest("close"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = GeneratorExit()
|
||||
# GeneratorExit is suppressed. This is consistent with PEP 342:
|
||||
# https://peps.python.org/pep-0342/#new-generator-method-close
|
||||
g.close()
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw GeneratorExit"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = GeneratorExit()
|
||||
thrown = GeneratorExit()
|
||||
with self.assertRaises(GeneratorExit) as caught:
|
||||
g.throw(thrown)
|
||||
# The raised GeneratorExit is suppressed, but the thrown one
|
||||
# propagates. This is consistent with PEP 380:
|
||||
# https://peps.python.org/pep-0380/#proposal
|
||||
self.assertIs(caught.exception, thrown)
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw StopIteration"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = GeneratorExit()
|
||||
thrown = StopIteration()
|
||||
with self.assertRaises(GeneratorExit) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, raised)
|
||||
self.assertIs(caught.exception.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw BaseException"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = GeneratorExit()
|
||||
thrown = BaseException()
|
||||
with self.assertRaises(GeneratorExit) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, raised)
|
||||
self.assertIs(caught.exception.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw Exception"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = GeneratorExit()
|
||||
thrown = Exception()
|
||||
with self.assertRaises(GeneratorExit) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, raised)
|
||||
self.assertIs(caught.exception.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: RuntimeError not raised
|
||||
def test_close_and_throw_raise_stop_iteration(self):
|
||||
|
||||
yielded_first = object()
|
||||
yielded_second = object()
|
||||
returned = object()
|
||||
|
||||
def inner():
|
||||
try:
|
||||
yield yielded_first
|
||||
yield yielded_second
|
||||
return returned
|
||||
finally:
|
||||
raise raised
|
||||
|
||||
def outer():
|
||||
return (yield from inner())
|
||||
|
||||
with self.subTest("close"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = StopIteration()
|
||||
# PEP 479:
|
||||
with self.assert_generator_raised_stop_iteration() as caught:
|
||||
g.close()
|
||||
self.assertIs(caught.exception.__context__, raised)
|
||||
self.assertIsInstance(caught.exception.__context__.__context__, GeneratorExit)
|
||||
self.assertIsNone(caught.exception.__context__.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw GeneratorExit"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = StopIteration()
|
||||
thrown = GeneratorExit()
|
||||
# PEP 479:
|
||||
with self.assert_generator_raised_stop_iteration() as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception.__context__, raised)
|
||||
# This isn't the same GeneratorExit as thrown! It's the one created
|
||||
# by calling inner.close():
|
||||
self.assertIsInstance(caught.exception.__context__.__context__, GeneratorExit)
|
||||
self.assertIsNone(caught.exception.__context__.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw StopIteration"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = StopIteration()
|
||||
thrown = StopIteration()
|
||||
# PEP 479:
|
||||
with self.assert_generator_raised_stop_iteration() as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception.__context__, raised)
|
||||
self.assertIs(caught.exception.__context__.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw BaseException"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = StopIteration()
|
||||
thrown = BaseException()
|
||||
# PEP 479:
|
||||
with self.assert_generator_raised_stop_iteration() as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception.__context__, raised)
|
||||
self.assertIs(caught.exception.__context__.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw Exception"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = StopIteration()
|
||||
thrown = Exception()
|
||||
# PEP 479:
|
||||
with self.assert_generator_raised_stop_iteration() as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception.__context__, raised)
|
||||
self.assertIs(caught.exception.__context__.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
def test_close_and_throw_raise_base_exception(self):
|
||||
|
||||
yielded_first = object()
|
||||
yielded_second = object()
|
||||
returned = object()
|
||||
|
||||
def inner():
|
||||
try:
|
||||
yield yielded_first
|
||||
yield yielded_second
|
||||
return returned
|
||||
finally:
|
||||
raise raised
|
||||
|
||||
def outer():
|
||||
return (yield from inner())
|
||||
|
||||
with self.subTest("close"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = BaseException()
|
||||
with self.assertRaises(BaseException) as caught:
|
||||
g.close()
|
||||
self.assertIs(caught.exception, raised)
|
||||
self.assertIsInstance(caught.exception.__context__, GeneratorExit)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw GeneratorExit"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = BaseException()
|
||||
thrown = GeneratorExit()
|
||||
with self.assertRaises(BaseException) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, raised)
|
||||
# This isn't the same GeneratorExit as thrown! It's the one created
|
||||
# by calling inner.close():
|
||||
self.assertIsInstance(caught.exception.__context__, GeneratorExit)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw StopIteration"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = BaseException()
|
||||
thrown = StopIteration()
|
||||
with self.assertRaises(BaseException) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, raised)
|
||||
self.assertIs(caught.exception.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw BaseException"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = BaseException()
|
||||
thrown = BaseException()
|
||||
with self.assertRaises(BaseException) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, raised)
|
||||
self.assertIs(caught.exception.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw Exception"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = BaseException()
|
||||
thrown = Exception()
|
||||
with self.assertRaises(BaseException) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, raised)
|
||||
self.assertIs(caught.exception.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
def test_close_and_throw_raise_exception(self):
|
||||
|
||||
yielded_first = object()
|
||||
yielded_second = object()
|
||||
returned = object()
|
||||
|
||||
def inner():
|
||||
try:
|
||||
yield yielded_first
|
||||
yield yielded_second
|
||||
return returned
|
||||
finally:
|
||||
raise raised
|
||||
|
||||
def outer():
|
||||
return (yield from inner())
|
||||
|
||||
with self.subTest("close"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = Exception()
|
||||
with self.assertRaises(Exception) as caught:
|
||||
g.close()
|
||||
self.assertIs(caught.exception, raised)
|
||||
self.assertIsInstance(caught.exception.__context__, GeneratorExit)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw GeneratorExit"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = Exception()
|
||||
thrown = GeneratorExit()
|
||||
with self.assertRaises(Exception) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, raised)
|
||||
# This isn't the same GeneratorExit as thrown! It's the one created
|
||||
# by calling inner.close():
|
||||
self.assertIsInstance(caught.exception.__context__, GeneratorExit)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw StopIteration"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = Exception()
|
||||
thrown = StopIteration()
|
||||
with self.assertRaises(Exception) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, raised)
|
||||
self.assertIs(caught.exception.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw BaseException"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = Exception()
|
||||
thrown = BaseException()
|
||||
with self.assertRaises(Exception) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, raised)
|
||||
self.assertIs(caught.exception.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw Exception"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
raised = Exception()
|
||||
thrown = Exception()
|
||||
with self.assertRaises(Exception) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, raised)
|
||||
self.assertIs(caught.exception.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: None is not StopIteration()
|
||||
def test_close_and_throw_yield(self):
|
||||
|
||||
yielded_first = object()
|
||||
yielded_second = object()
|
||||
returned = object()
|
||||
|
||||
def inner():
|
||||
try:
|
||||
yield yielded_first
|
||||
finally:
|
||||
yield yielded_second
|
||||
return returned
|
||||
|
||||
def outer():
|
||||
return (yield from inner())
|
||||
|
||||
with self.subTest("close"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
# No chaining happens. This is consistent with PEP 342:
|
||||
# https://peps.python.org/pep-0342/#new-generator-method-close
|
||||
with self.assert_generator_ignored_generator_exit() as caught:
|
||||
g.close()
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw GeneratorExit"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
thrown = GeneratorExit()
|
||||
# No chaining happens. This is consistent with PEP 342:
|
||||
# https://peps.python.org/pep-0342/#new-generator-method-close
|
||||
with self.assert_generator_ignored_generator_exit() as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw StopIteration"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
thrown = StopIteration()
|
||||
self.assertEqual(g.throw(thrown), yielded_second)
|
||||
# PEP 479:
|
||||
with self.assert_generator_raised_stop_iteration() as caught:
|
||||
next(g)
|
||||
self.assertIs(caught.exception.__context__, thrown)
|
||||
self.assertIsNone(caught.exception.__context__.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw BaseException"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
thrown = BaseException()
|
||||
self.assertEqual(g.throw(thrown), yielded_second)
|
||||
with self.assertRaises(BaseException) as caught:
|
||||
next(g)
|
||||
self.assertIs(caught.exception, thrown)
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw Exception"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
thrown = Exception()
|
||||
self.assertEqual(g.throw(thrown), yielded_second)
|
||||
with self.assertRaises(Exception) as caught:
|
||||
next(g)
|
||||
self.assertIs(caught.exception, thrown)
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_close_and_throw_return(self):
|
||||
|
||||
yielded_first = object()
|
||||
yielded_second = object()
|
||||
returned = object()
|
||||
|
||||
def inner():
|
||||
try:
|
||||
yield yielded_first
|
||||
yield yielded_second
|
||||
finally:
|
||||
return returned
|
||||
|
||||
def outer():
|
||||
return (yield from inner())
|
||||
|
||||
with self.subTest("close"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
# StopIteration is suppressed. This is consistent with PEP 342:
|
||||
# https://peps.python.org/pep-0342/#new-generator-method-close
|
||||
g.close()
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw GeneratorExit"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
thrown = GeneratorExit()
|
||||
# StopIteration is suppressed. This is consistent with PEP 342:
|
||||
# https://peps.python.org/pep-0342/#new-generator-method-close
|
||||
with self.assertRaises(GeneratorExit) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception, thrown)
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw StopIteration"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
thrown = StopIteration()
|
||||
with self.assertRaises(StopIteration) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception.value, returned)
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw BaseException"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
thrown = BaseException()
|
||||
with self.assertRaises(StopIteration) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception.value, returned)
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
with self.subTest("throw Exception"):
|
||||
g = outer()
|
||||
self.assertIs(next(g), yielded_first)
|
||||
thrown = Exception()
|
||||
with self.assertRaises(StopIteration) as caught:
|
||||
g.throw(thrown)
|
||||
self.assertIs(caught.exception.value, returned)
|
||||
self.assertIsNone(caught.exception.__context__)
|
||||
self.assert_stop_iteration(g)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user