aiopg icon indicating copy to clipboard operation
aiopg copied to clipboard

cleanup aiopg.pool.Pool.cursor method

Open thehesiod opened this issue 8 years ago • 2 comments

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__

thehesiod avatar Jan 26 '17 00:01 thehesiod

I've added a sample impl here: https://github.com/aio-libs/aiopg/pull/265

thehesiod avatar Jan 26 '17 00:01 thehesiod

I just ran into this. The documented usage is:

Core API Reference — Welcome to AIOPG 2020-09-30 07-10-25

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.

dave-shawley avatar Sep 30 '20 11:09 dave-shawley