diff options
author | Nick Coghlan <ncoghlan@gmail.com> | 2015-05-13 05:54:02 (GMT) |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2015-05-13 05:54:02 (GMT) |
commit | baaadbf70d024142ec6a519006e960ec74309f92 (patch) | |
tree | 14d1110d7379aa17d17e7c1311a2bceb0324bcbe /Lib/test/test_coroutines.py | |
parent | 84d3e764d717a5c31af1a282463425a24f83f1de (diff) | |
download | cpython-baaadbf70d024142ec6a519006e960ec74309f92.zip cpython-baaadbf70d024142ec6a519006e960ec74309f92.tar.gz cpython-baaadbf70d024142ec6a519006e960ec74309f92.tar.bz2 |
Issue 24017: fix for "async with" refcounting
* adds missing INCREF in WITH_CLEANUP_START
* adds missing DECREF in WITH_CLEANUP_FINISH
* adds several new tests Yury created while investigating this
Diffstat (limited to 'Lib/test/test_coroutines.py')
-rw-r--r-- | Lib/test/test_coroutines.py | 118 |
1 files changed, 117 insertions, 1 deletions
diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index aa2a5e8..6a6f868 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -497,17 +497,133 @@ class CoroutineTest(unittest.TestCase): return self def __aexit__(self, *e): + return 444 + + async def foo(): + async with CM(): + 1/0 + + try: + run_async(foo()) + except TypeError as exc: + self.assertRegex( + exc.args[0], "object int can't be used in 'await' expression") + self.assertTrue(exc.__context__ is not None) + self.assertTrue(isinstance(exc.__context__, ZeroDivisionError)) + else: + self.fail('invalid asynchronous context manager did not fail') + + + def test_with_8(self): + CNT = 0 + + class CM: + async def __aenter__(self): + return self + + def __aexit__(self, *e): return 456 async def foo(): + nonlocal CNT async with CM(): - pass + CNT += 1 + with self.assertRaisesRegex( TypeError, "object int can't be used in 'await' expression"): run_async(foo()) + self.assertEqual(CNT, 1) + + + def test_with_9(self): + CNT = 0 + + class CM: + async def __aenter__(self): + return self + + async def __aexit__(self, *e): + 1/0 + + async def foo(): + nonlocal CNT + async with CM(): + CNT += 1 + + with self.assertRaises(ZeroDivisionError): + run_async(foo()) + + self.assertEqual(CNT, 1) + + def test_with_10(self): + CNT = 0 + + class CM: + async def __aenter__(self): + return self + + async def __aexit__(self, *e): + 1/0 + + async def foo(): + nonlocal CNT + async with CM(): + async with CM(): + raise RuntimeError + + try: + run_async(foo()) + except ZeroDivisionError as exc: + self.assertTrue(exc.__context__ is not None) + self.assertTrue(isinstance(exc.__context__, ZeroDivisionError)) + self.assertTrue(isinstance(exc.__context__.__context__, + RuntimeError)) + else: + self.fail('exception from __aexit__ did not propagate') + + def test_with_11(self): + CNT = 0 + + class CM: + async def __aenter__(self): + raise NotImplementedError + + async def __aexit__(self, *e): + 1/0 + + async def foo(): + nonlocal CNT + async with CM(): + raise RuntimeError + + try: + run_async(foo()) + except NotImplementedError as exc: + self.assertTrue(exc.__context__ is None) + else: + self.fail('exception from __aenter__ did not propagate') + + def test_with_12(self): + CNT = 0 + + class CM: + async def __aenter__(self): + return self + + async def __aexit__(self, *e): + return True + + async def foo(): + nonlocal CNT + async with CM() as cm: + self.assertIs(cm.__class__, CM) + raise RuntimeError + + run_async(foo()) + def test_for_1(self): aiter_calls = 0 |