mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
gh-79940: add introspection API for asynchronous generators to inspect
module (#11590)
This commit is contained in:
parent
aa0a73d1bc
commit
ced13c96a4
6 changed files with 199 additions and 2 deletions
|
@ -1,3 +1,4 @@
|
|||
import asyncio
|
||||
import builtins
|
||||
import collections
|
||||
import datetime
|
||||
|
@ -65,6 +66,10 @@ def revise(filename, *args):
|
|||
git = mod.StupidGit()
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
asyncio.set_event_loop_policy(None)
|
||||
|
||||
|
||||
def signatures_with_lexicographic_keyword_only_parameters():
|
||||
"""
|
||||
Yields a whole bunch of functions with only keyword-only parameters,
|
||||
|
@ -2321,6 +2326,108 @@ class TestGetCoroutineState(unittest.TestCase):
|
|||
{'a': None, 'gencoro': gencoro, 'b': 'spam'})
|
||||
|
||||
|
||||
class TestGetAsyncGenState(unittest.IsolatedAsyncioTestCase):
|
||||
|
||||
def setUp(self):
|
||||
async def number_asyncgen():
|
||||
for number in range(5):
|
||||
yield number
|
||||
self.asyncgen = number_asyncgen()
|
||||
|
||||
async def asyncTearDown(self):
|
||||
await self.asyncgen.aclose()
|
||||
|
||||
def _asyncgenstate(self):
|
||||
return inspect.getasyncgenstate(self.asyncgen)
|
||||
|
||||
def test_created(self):
|
||||
self.assertEqual(self._asyncgenstate(), inspect.AGEN_CREATED)
|
||||
|
||||
async def test_suspended(self):
|
||||
value = await anext(self.asyncgen)
|
||||
self.assertEqual(self._asyncgenstate(), inspect.AGEN_SUSPENDED)
|
||||
self.assertEqual(value, 0)
|
||||
|
||||
async def test_closed_after_exhaustion(self):
|
||||
countdown = 7
|
||||
with self.assertRaises(StopAsyncIteration):
|
||||
while countdown := countdown - 1:
|
||||
await anext(self.asyncgen)
|
||||
self.assertEqual(countdown, 1)
|
||||
self.assertEqual(self._asyncgenstate(), inspect.AGEN_CLOSED)
|
||||
|
||||
async def test_closed_after_immediate_exception(self):
|
||||
with self.assertRaises(RuntimeError):
|
||||
await self.asyncgen.athrow(RuntimeError)
|
||||
self.assertEqual(self._asyncgenstate(), inspect.AGEN_CLOSED)
|
||||
|
||||
async def test_running(self):
|
||||
async def running_check_asyncgen():
|
||||
for number in range(5):
|
||||
self.assertEqual(self._asyncgenstate(), inspect.AGEN_RUNNING)
|
||||
yield number
|
||||
self.assertEqual(self._asyncgenstate(), inspect.AGEN_RUNNING)
|
||||
self.asyncgen = running_check_asyncgen()
|
||||
# Running up to the first yield
|
||||
await anext(self.asyncgen)
|
||||
self.assertEqual(self._asyncgenstate(), inspect.AGEN_SUSPENDED)
|
||||
# Running after the first yield
|
||||
await anext(self.asyncgen)
|
||||
self.assertEqual(self._asyncgenstate(), inspect.AGEN_SUSPENDED)
|
||||
|
||||
def test_easy_debugging(self):
|
||||
# repr() and str() of a asyncgen state should contain the state name
|
||||
names = 'AGEN_CREATED AGEN_RUNNING AGEN_SUSPENDED AGEN_CLOSED'.split()
|
||||
for name in names:
|
||||
state = getattr(inspect, name)
|
||||
self.assertIn(name, repr(state))
|
||||
self.assertIn(name, str(state))
|
||||
|
||||
async def test_getasyncgenlocals(self):
|
||||
async def each(lst, a=None):
|
||||
b=(1, 2, 3)
|
||||
for v in lst:
|
||||
if v == 3:
|
||||
c = 12
|
||||
yield v
|
||||
|
||||
numbers = each([1, 2, 3])
|
||||
self.assertEqual(inspect.getasyncgenlocals(numbers),
|
||||
{'a': None, 'lst': [1, 2, 3]})
|
||||
await anext(numbers)
|
||||
self.assertEqual(inspect.getasyncgenlocals(numbers),
|
||||
{'a': None, 'lst': [1, 2, 3], 'v': 1,
|
||||
'b': (1, 2, 3)})
|
||||
await anext(numbers)
|
||||
self.assertEqual(inspect.getasyncgenlocals(numbers),
|
||||
{'a': None, 'lst': [1, 2, 3], 'v': 2,
|
||||
'b': (1, 2, 3)})
|
||||
await anext(numbers)
|
||||
self.assertEqual(inspect.getasyncgenlocals(numbers),
|
||||
{'a': None, 'lst': [1, 2, 3], 'v': 3,
|
||||
'b': (1, 2, 3), 'c': 12})
|
||||
with self.assertRaises(StopAsyncIteration):
|
||||
await anext(numbers)
|
||||
self.assertEqual(inspect.getasyncgenlocals(numbers), {})
|
||||
|
||||
async def test_getasyncgenlocals_empty(self):
|
||||
async def yield_one():
|
||||
yield 1
|
||||
one = yield_one()
|
||||
self.assertEqual(inspect.getasyncgenlocals(one), {})
|
||||
await anext(one)
|
||||
self.assertEqual(inspect.getasyncgenlocals(one), {})
|
||||
with self.assertRaises(StopAsyncIteration):
|
||||
await anext(one)
|
||||
self.assertEqual(inspect.getasyncgenlocals(one), {})
|
||||
|
||||
def test_getasyncgenlocals_error(self):
|
||||
self.assertRaises(TypeError, inspect.getasyncgenlocals, 1)
|
||||
self.assertRaises(TypeError, inspect.getasyncgenlocals, lambda x: True)
|
||||
self.assertRaises(TypeError, inspect.getasyncgenlocals, set)
|
||||
self.assertRaises(TypeError, inspect.getasyncgenlocals, (2,3))
|
||||
|
||||
|
||||
class MySignature(inspect.Signature):
|
||||
# Top-level to make it picklable;
|
||||
# used in test_signature_object_pickle
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue