aiopg
aiopg copied to clipboard
cleanup aiopg.pool.Pool.cursor method
right now using this method is not async with nice, with the syntax:
with (yield from pool.cursor()) as cur:
yield from cur.execute("SELECT 1")
Based on the usage of context managers in aiopg, it should instead behavior like aiopg.create_pool, to yield the following usage:
async with pool.cursor() as cur:
yield from cur.execute("SELECT 1")
In order to accomplish this aiopg.pool.Pool.cursor should not be marked a coroutine, and the acquisition of the connection and cursor should not happen until __aenter__
of _PoolCursorContextManager. With the current design probably the easiest way would be to pass a coroutine closure to _PoolCursorContextManager to return the conn and cur during __aenter__
I've added a sample impl here: https://github.com/aio-libs/aiopg/pull/265
I just ran into this. The documented usage is:

https://aiopg.readthedocs.io/en/stable/core.html#aiopg.Pool.cursor
When I try this in Python 3.8.4, it does fail since cursor()
is a co-routine instead of a async context manager:
zsh% python -m asyncio
asyncio REPL 3.8.4 (tags/v3.8.4:dfa645a65e, Jul 16 2020, 06:56:07)
[Clang 11.0.0 (clang-1100.0.33.16)] on darwin
Use "await" directly instead of "asyncio.run()".
Type "help", "copyright", "credits" or "license" for more information.
>>> import asyncio
>>> import aiopg
>>> pool = aiopg.Pool('postgresql://postgres:[email protected]:32778',
... minsize=1, maxsize=5, timeout=5.0, enable_json=True,
... enable_hstore=False, enable_uuid=True, echo=False,
... on_connect=None, pool_recycle=-1)
>>> async with pool.cursor() as c:
... await c.execute('SELECT 1')
...
<console>:1: RuntimeWarning: coroutine 'Pool.cursor' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Traceback (most recent call last):
File "/Users/daveshawley/opt/lib/python3.8/concurrent/futures/_base.py", line 439, in result
return self.__get_result()
File "/Users/daveshawley/opt/lib/python3.8/concurrent/futures/_base.py", line 388, in __get_result
raise self._exception
File "<console>", line 1, in <module>
AttributeError: __aexit__
>>>
The cleanest spelling seems to be:
>>> with await pool.cursor() as c:
... await c.execute('SELECT 1')
... row = await c.fetchone()
...
At the very least, we should update the documentation.