aiopg
aiopg copied to clipboard
Broken aiopg.sa.RowProxy unpacking
So RowProxy doesn't behave like the SQLAlchemy one, I find it really misleading.
'dtid': dtid,
'username': username,
}
query = psa.insert(User) \
.values(entry) \
.returning(User.c.id) \
.on_conflict_do_update(
index_elements=[User.c.dtid],
set_=entry
)
user_id = await (await conn.execute(query)).first()
print(type(user_id), user_id) # Output: "<class 'aiopg.sa.result.RowProxy'> (1,)"
print(user_id[0]) # Output: "<class 'int'> 1"
user_id, = user_id
print(user_id) # Output: "<class 'str'> id"
As you see, everything goes well until I try to unpack the row...
use as_tuple
method of the class RowProxy
in the RowProxy implements method __iter__
for keys
return iter(self._result_proxy.keys)
for insert the return id you can use scalar
print(await (await conn.execute(query)).scalar()) # Output: 1
Yes, I am using as_tuple()
as a temporal measure. I was just reporting the bug :)
I'm not sure if this is a bug. this is described in the documentation. without any doubts, he behaves differently from that of sqlalchemy. I do not think that the fix will be cheap,someone could already use this in their code
this is described in the documentation.
http://aiopg.readthedocs.io/en/stable/sa.html#aiopg.sa.RowProxy says: Individual columns may be accessed by their integer position, case-sensitive column name, or by ``sqlalchemy.schema.Column`` object.
The interface is broken because you cannot support indexing and unpacking, and return different data.
To have a pythonic interface you need to choose one of both, either it works like a dict
or as a tuple
. I personally would go for the SQLAlchemy way, because creating a wrapper around aiopg to supports SQLAlchemy that then behaves different to it doesn't make much sense to me.
Finally, aiopg is still not in a major version, so a minor release with proper Changelog warning should be enough, people using non stable releases should read it before upgrading.
I also got caught by this, and I also very much agree with
I personally would go for the SQLAlchemy way, because creating a wrapper around aiopg to supports SQLAlchemy that then behaves different to it doesn't make much sense to me.