-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
gh-108558: Add a couple more sqlite Row.keys() tests #108628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gh-108558: Add a couple more sqlite Row.keys() tests #108628
Conversation
Nice! Can you split it up in multiple tests? |
with self.assertRaises(AttributeError): | ||
row = self.con.execute("select 1 as a where a == 'THISDOESNOTEXIST'").fetchone() | ||
row.keys() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you narrow this down? Where is the AttributeError raised? Consider also using assertRaisesRegex
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the type of row
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So .fetchone()
is returning None as per the comment below,
# Returns either a row (as created by the row_factory) or None, but
# putting None in the return annotation causes annoying false positives.
def fetchone(self) -> Any: ...
and the type of keys
has to be a list of strings,
class Row:
def __init__(self, __cursor: Cursor, __data: tuple[Any, ...]) -> None: ...
def keys(self) -> list[str]: ...
and here is the C code for the keys method,
static PyObject *
pysqlite_row_keys_impl(pysqlite_Row *self)
/*[clinic end generated code: output=efe3dfb3af6edc07 input=7549a122827c5563]*/
{
PyObject* list;
Py_ssize_t nitems, i;
list = PyList_New(0);
if (!list) {
return NULL;
}
nitems = PyTuple_Size(self->description);
for (i = 0; i < nitems; i++) {
if (PyList_Append(list, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)) != 0) {
Py_DECREF(list);
return NULL;
}
}
return list;
}
however I'm not familiar with the codebase enough to go between the C code and the Python code to find where the error is being raised :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the query fails, no rows are returned, so fetchone
returns None
, so what you are really testing here is that None
does not have a keys
attribute :) I think we can do without this test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the type of
row
?
None :) As already mentioned, we don't need this test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If fetchone()
returns not a Row
, this code has no any relation to testing Row.keys()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #108628 (comment), Serhiy.
cur.execute("select 1 as a") | ||
row = cur.fetchone() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FTR, it is also possible to do:
cur.execute("select 1 as a") | |
row = cur.fetchone() | |
row ,= cur.execute("select 1 as a") |
and:
cur.execute("select 1 as a") | |
row = cur.fetchone() | |
[row] = cur.execute("select 1 as a") |
... though they are pretty cryptic 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure that the new tests have any value. It is not clear what they do, why they are necessary. They just distract attention from more meaningful tests.
with self.assertRaises(AttributeError): | ||
row = self.con.execute("select 1 as a where a == 'THISDOESNOTEXIST'").fetchone() | ||
row.keys() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the type of row
?
def test_sqlite_row_keys_are_equal_if_rows_are_equal(self): | ||
# Two Row objects compare equal if they have identical column names | ||
# and values. Assert the keys values are the same too. | ||
row_1 = self.con.execute("select 1 as a, 2 as b").fetchone() | ||
row_2 = self.con.execute("select 1 as a, 2 as b").fetchone() | ||
self.assertEqual(row_1, row_2) | ||
self.assertEqual(row_1.keys(), row_2.keys()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you object to this test as well, @serhiy-storchaka?
I think it would be simplified as such, though:
def test_sqlite_row_keys_are_equal_if_rows_are_equal(self): | |
# Two Row objects compare equal if they have identical column names | |
# and values. Assert the keys values are the same too. | |
row_1 = self.con.execute("select 1 as a, 2 as b").fetchone() | |
row_2 = self.con.execute("select 1 as a, 2 as b").fetchone() | |
self.assertEqual(row_1, row_2) | |
self.assertEqual(row_1.keys(), row_2.keys()) | |
def test_sqlite_row_equality(self): | |
# Two Row objects compare equal if they have identical column names | |
# and values. | |
row_1 = self.con.execute("select 1 as a, 2 as b").fetchone() | |
row_2 = self.con.execute("select 1 as a, 2 as b").fetchone() | |
self.assertEqual(row_1, row_2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OTOH, this is already tested by test_sqlite_row_hash_cmp
, so it is redundant.
.keys()
on an empty row, check the documented statement thatkeys()
return the first value from the description tuple, and the (possibly trivial) fact that.keys()
are equal when theRow
is equal.