classification
Title: sqlite3.Row doesn't have useful repr
Type: enhancement Stage: patch review
Components: Library (Lib) Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: berker.peksag, ghaering, rhettinger, serhiy.storchaka, terry.reedy, vlad
Priority: normal Keywords: patch, patch, patch, patch

Created on 2019-02-02 13:02 by vlad, last changed 2019-03-03 13:39 by serhiy.storchaka.

Pull Requests
URL Status Linked Edit
PR 11820 open python-dev, 2019-02-11 15:44
Messages (6)
msg334746 - (view) Author: Vlad Shcherbina (vlad) * Date: 2019-02-02 13:02
To reproduce, run the following program:

import sqlite3
conn = sqlite3.connect(':memory:')
conn.row_factory = sqlite3.Row
print(conn.execute("SELECT 'John' AS name, 42 AS salary").fetchone())

It prints '<sqlite3.Row object at 0xffffffffffffff>'.
It would be nice if it printed something like "sqlite3.Row(name='Smith', saraly=42)" instead.
It wouldn't satisfy the 'eval(repr(x)) == x' property, but it's still better than nothing.

If the maintainers agree this is useful, I'll implement.
msg335102 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2019-02-08 18:35
Enhancements only go into future versions.

This would have the same pluses and minuses as printing dicts in full.  I don't know the general feeling about expanding the classes printed out like this, or whether Gerhard is still active.  If you don't get responses within a few days, you might try posting to python-ideas list.
msg335189 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2019-02-11 02:30
+1 from me.  We're already made regular expression match objects less opaque and that has been useful.  There's no need for a python-ideas discussion for this.

If a repr doesn't round-trip, we generally put it angle brackets (see PEP 8):

    >>> re.search(r'([a-z]+)(\d*)', 'alpha7')
    <re.Match object; span=(0, 6), match='alpha7'>

The Row object access style uses square brackets and has a keys() method.  That suggests a dict-like representation would be intuitive and match how Row objects are used:  ro['salary'] and ro.keys().

Putting those two ideas together we get:

    <sqlite3.Row object; {'name': 'John', 'salary': 42}>

Note the OP's suggestion for keyword argument style doesn't make sense for two reasons: 1) Row objects don't allow attribute access (i.e. ro.name is invalid) and 2) the field names are not required to be valid Python identifiers (i.e. ro['class'] is possible but ro.class is syntactically invalid because "class" is a keyword).
msg335540 - (view) Author: Berker Peksag (berker.peksag) * (Python committer) Date: 2019-02-14 16:33
While the proposed formats look nice for artificial inputs, the Row object can have more than two fields and the value of a field can be much longer than that. So, in practice the new repr can make the situation worse than the current repr.

I think wrapping the output of row.keys() (https://docs.python.org/3/library/sqlite3.html#sqlite3.Row.keys) with something like reprlib.recursive_repr() would work better for Row objects with several fields.
msg336291 - (view) Author: Vlad Shcherbina (vlad) * Date: 2019-02-22 10:21
There is no need to add explicit knowledge of reprlib to the Row object or vice versa.

Those who use reprlib to limit output size will have no problem. Reprlib already truncates arbitrary reprs at the string level: https://github.com/python/cpython/blob/22bfe637ca7728e9f74d4dc8bb7a15ee2a913815/Lib/reprlib.py#L144

Those who use builtin repr() have to be prepared for the possibility of unbounded repr anyway, because all collection-like objects in Python have unbounded __repr__.

It would be annoying if some collection-like objects decided to be clever and omit parts of their regular __repr__ because they feel it's too much for the user to handle.
msg337030 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2019-03-03 13:39
I have the same doubts as Berker. sqlite3.Row represents a data from a database. Databases are used in particularly for storing a large amount of data which can not be all loaded in RAM. Therefore sqlite3.Row can contain a data with a very long repr.

If you need to inspect the sqlite3.Row object, it is easy to convert it to a list. If you want to see keys together with values, it is not hard to make a list of key-value pairs or a dict: list(zip(row.keys(), row)) or dict(zip(row.keys(), row)).
History
Date User Action Args
2019-03-03 13:39:02serhiy.storchakasetkeywords: patch, patch, patch, patch
nosy: + serhiy.storchaka
messages: + msg337030

2019-02-22 10:21:37vladsetmessages: + msg336291
2019-02-14 16:34:16berker.peksagsetpull_requests: - pull_request11844
2019-02-14 16:34:12berker.peksagsetpull_requests: - pull_request11845
2019-02-14 16:34:07berker.peksagsetpull_requests: - pull_request11846
2019-02-14 16:33:48berker.peksagsetkeywords: patch, patch, patch, patch
nosy: + berker.peksag
messages: + msg335540

2019-02-11 15:44:41python-devsetkeywords: + patch
stage: patch review
pull_requests: + pull_request11846
2019-02-11 15:44:31python-devsetkeywords: + patch
stage: (no value)
pull_requests: + pull_request11847
2019-02-11 15:44:23python-devsetkeywords: + patch
stage: (no value)
pull_requests: + pull_request11845
2019-02-11 15:44:15python-devsetkeywords: + patch
stage: (no value)
pull_requests: + pull_request11844
2019-02-11 02:30:05rhettingersetnosy: + rhettinger
messages: + msg335189
2019-02-08 18:35:02terry.reedysetnosy: + terry.reedy, ghaering

messages: + msg335102
versions: - Python 2.7, Python 3.4, Python 3.5, Python 3.6, Python 3.7
2019-02-02 13:02:16vladcreate