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

Created on 2019-02-02 13:02 by vlad, last changed 2019-02-14 16:34 by berker.peksag.

Pull Requests
URL Status Linked Edit
PR 11820 open python-dev, 2019-02-11 15:44
Messages (4)
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):

    >>>'([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. 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() ( with something like reprlib.recursive_repr() would work better for Row objects with several fields.
Date User Action Args
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