`inspect.iscoroutinefunction` returns false on pool -> connection -> execute
stj opened this issue · 1 comments
- asyncpg version: 0.29
- PostgreSQL version: 13.11
- Do you use a PostgreSQL SaaS? If so, which? Can you reproduce
the issue with a local PostgreSQL install?: - Python version: 3.12.2
- Platform: linux
- Do you use pgbouncer?: No
- Did you install asyncpg with pip?: Yes
- If you built asyncpg locally, which version of Cython did you use?: -
- Can the issue be reproduced under both asyncio and
uvloop?: n/a
We noticed that some of our tests clean-up yield RuntimeWarning: coroutine 'Connection.execute' was never awaited
when the PYTHONASYNCIODEBUG
envvar is set. While investigating, we found that this code in an unittest is the cause of the warning.
The root cause is the inspect.iscoroutinefunction
on a asyncpg pool connection instance returns False
, causing the TestCase
class not to await it.
https://github.com/python/cpython/blob/16349868d396cc1bff5188de3638321e87fe0293/Lib/unittest/async_case.py#L112-L120
import asyncpg
import inspect
import unittest
class TestAsyncCleanupAwaitsAsyncpgPoolConnectionCoroutine(
unittest.IsolatedAsyncioTestCase
):
async def asyncSetUp(self):
self.pool = await asyncpg.create_pool(min_size=1, max_size=1)
self.addAsyncCleanup(self.pool.close)
self.conn = await self.pool.acquire()
self.addAsyncCleanup(self.pool.release, self.conn)
async def test_cleanup_awaited(self):
await self.conn.execute("SELECT now()")
self.addAsyncCleanup(self.conn.execute, "SELECT now()")
self.assertTrue(inspect.iscoroutinefunction(self.conn.execute))
class TestAsyncCleanupAwaitsAsyncpgConnectionCoroutine(
unittest.IsolatedAsyncioTestCase
):
async def asyncSetUp(self):
self.conn = await asyncpg.connect()
self.addAsyncCleanup(self.conn.close)
async def test_cleanup_awaited(self):
await self.conn.execute("SELECT now()")
self.addAsyncCleanup(self.conn.execute, "SELECT now()")
self.assertTrue(inspect.iscoroutinefunction(self.conn.execute))
if __name__ == "__main__":
unittest.main()
When running this python snippet with PYTHONASYNCIODEBUG=1
and PYTHONWARNINGS=once
and the output is
.F
/home/stj/.local/lib/python3.12/unittest/async_case.py:99: RuntimeWarning: coroutine 'Connection.execute' was never awaited
self._callMaybeAsync(function, *args, **kwargs)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
======================================================================
FAIL: test_cleanup_awaited (__main__.TestAsyncCleanupAwaitsAsyncpgPoolConnectionCoroutine.test_cleanup_awaited)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/stj/.local/lib/python3.12/unittest/async_case.py", line 90, in _callTestMethod
if self._callMaybeAsync(method) is not None:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/stj/.local/lib/python3.12/unittest/async_case.py", line 112, in _callMaybeAsync
return self._asyncioRunner.run(
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/stj/.local/lib/python3.12/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/stj/.local/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/home/stj/test_asyncpg.py", line 21, in test_cleanup_awaited
self.assertTrue(inspect.iscoroutinefunction(self.conn.execute))
AssertionError: False is not true
----------------------------------------------------------------------
Ran 2 tests in 0.060s
FAILED (failures=1)
Expectation is that both tests pass.
This is fairly easy to fix, though the mechanism to inform inspect
about wrappers returning coroutine functions is only available in Python 3.12.