Skip to content

Commit a49ca09

Browse files
committed
feat: a new debug option sqldata shows all the data being written to the db.
1 parent 8991e9d commit a49ca09

File tree

4 files changed

+41
-15
lines changed

4 files changed

+41
-15
lines changed

CHANGES.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ Unreleased
3636
- The timestamp and version are displayed at the top of the report. Thanks,
3737
`Ammar Askar <pull 1354_>`_. Closes `issue 1351`_.
3838

39+
- A new debug option ``debug=sqldata`` adds more detail to ``debug=sql``,
40+
logging all the data being written to the database.
41+
3942
- On Python 3.11, the ``[toml]`` extra no longer installs tomli, instead using
4043
tomllib from the standard library. Thanks `Shantanu <pull 1359_>`_.
4144

coverage/sqldata.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
22
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
33

4-
"""Sqlite coverage data."""
5-
6-
# TODO: factor out dataop debugging to a wrapper class?
7-
# TODO: make sure all dataop debugging is in place somehow
4+
"""SQLite coverage data."""
85

96
import collections
107
import datetime
@@ -31,7 +28,7 @@
3128
os = isolate_module(os)
3229

3330
# If you change the schema, increment the SCHEMA_VERSION, and update the
34-
# docs in docs/dbschema.rst also.
31+
# docs in docs/dbschema.rst by running "make cogdoc".
3532

3633
SCHEMA_VERSION = 7
3734

@@ -390,8 +387,10 @@ def _file_id(self, filename, add=False):
390387
if filename not in self._file_map:
391388
if add:
392389
with self._connect() as con:
393-
cur = con.execute("insert or replace into file (path) values (?)", (filename,))
394-
self._file_map[filename] = cur.lastrowid
390+
self._file_map[filename] = con.execute_for_rowid(
391+
"insert or replace into file (path) values (?)",
392+
(filename,)
393+
)
395394
return self._file_map.get(filename)
396395

397396
def _context_id(self, context):
@@ -428,8 +427,10 @@ def _set_context_id(self):
428427
self._current_context_id = context_id
429428
else:
430429
with self._connect() as con:
431-
cur = con.execute("insert into context (context) values (?)", (context,))
432-
self._current_context_id = cur.lastrowid
430+
self._current_context_id = con.execute_for_rowid(
431+
"insert into context (context) values (?)",
432+
(context,)
433+
)
433434

434435
def base_filename(self):
435436
"""The base filename for storing data.
@@ -1126,6 +1127,14 @@ def execute(self, sql, parameters=()):
11261127
self.debug.write(f"EXCEPTION from execute: {msg}")
11271128
raise DataError(f"Couldn't use data file {self.filename!r}: {msg}") from exc
11281129

1130+
def execute_for_rowid(self, sql, parameters=()):
1131+
"""Like execute, but returns the lastrowid."""
1132+
con = self.execute(sql, parameters)
1133+
rowid = con.lastrowid
1134+
if self.debug.should("sqldata"):
1135+
self.debug.write(f"Row id result: {rowid!r}")
1136+
return rowid
1137+
11291138
def execute_one(self, sql, parameters=()):
11301139
"""Execute a statement and return the one row that results.
11311140
@@ -1147,7 +1156,11 @@ def executemany(self, sql, data):
11471156
"""Same as :meth:`python:sqlite3.Connection.executemany`."""
11481157
if self.debug.should("sql"):
11491158
data = list(data)
1150-
self.debug.write(f"Executing many {sql!r} with {len(data)} rows")
1159+
final = ":" if self.debug.should("sqldata") else ""
1160+
self.debug.write(f"Executing many {sql!r} with {len(data)} rows{final}")
1161+
if self.debug.should("sqldata"):
1162+
for i, row in enumerate(data):
1163+
self.debug.write(f"{i:4d}: {row!r}")
11511164
try:
11521165
return self.con.executemany(sql, data)
11531166
except Exception: # pragma: cant happen

doc/cmd.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,9 @@ of operation to log:
10141014

10151015
* ``sql``: log the SQL statements used for recording data.
10161016

1017+
* ``sqldata``: when used with ``debug=sql``, also log the full data being used
1018+
in SQL statements.
1019+
10171020
* ``sys``: before starting, dump all the system and environment information,
10181021
as with :ref:`coverage debug sys <cmd_debug>`.
10191022

tests/test_data.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,12 @@ def DebugCoverageData(*args, **kwargs):
6767
lines in our coverage reports.
6868
"""
6969
assert "debug" not in kwargs
70-
debug = DebugControlString(options=["dataio", "dataop", "sql"])
70+
options = ["dataio", "dataop", "sql"]
71+
if kwargs:
72+
# There's no reason kwargs should imply sqldata debugging.
73+
# This is a way to get a mix of debug options across the tests.
74+
options.extend(["sqldata"])
75+
debug = DebugControlString(options=options)
7176
return CoverageData(*args, debug=debug, **kwargs)
7277

7378

@@ -160,15 +165,17 @@ def test_ok_to_add_arcs_twice(self):
160165
assert_line_counts(covdata, SUMMARY_3_4)
161166
assert_measured_files(covdata, MEASURED_FILES_3_4)
162167

163-
def test_cant_add_arcs_with_lines(self):
164-
covdata = DebugCoverageData()
168+
@pytest.mark.parametrize("klass", [CoverageData, DebugCoverageData])
169+
def test_cant_add_arcs_with_lines(self, klass):
170+
covdata = klass()
165171
covdata.add_lines(LINES_1)
166172
msg = "Can't add branch measurements to existing line data"
167173
with pytest.raises(DataError, match=msg):
168174
covdata.add_arcs(ARCS_3)
169175

170-
def test_cant_add_lines_with_arcs(self):
171-
covdata = DebugCoverageData()
176+
@pytest.mark.parametrize("klass", [CoverageData, DebugCoverageData])
177+
def test_cant_add_lines_with_arcs(self, klass):
178+
covdata = klass()
172179
covdata.add_arcs(ARCS_3)
173180
msg = "Can't add line measurements to existing branch data"
174181
with pytest.raises(DataError, match=msg):

0 commit comments

Comments
 (0)