Skip to content

Commit

Permalink
feat: a new debug option sqldata shows all the data being written t…
Browse files Browse the repository at this point in the history
…o the db.
  • Loading branch information
nedbat committed May 22, 2022
1 parent 8991e9d commit a49ca09
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 15 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ Unreleased
- The timestamp and version are displayed at the top of the report. Thanks,
`Ammar Askar <pull 1354_>`_. Closes `issue 1351`_.

- A new debug option ``debug=sqldata`` adds more detail to ``debug=sql``,
logging all the data being written to the database.

- On Python 3.11, the ``[toml]`` extra no longer installs tomli, instead using
tomllib from the standard library. Thanks `Shantanu <pull 1359_>`_.

Expand Down
33 changes: 23 additions & 10 deletions coverage/sqldata.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt

"""Sqlite coverage data."""

# TODO: factor out dataop debugging to a wrapper class?
# TODO: make sure all dataop debugging is in place somehow
"""SQLite coverage data."""

import collections
import datetime
Expand All @@ -31,7 +28,7 @@
os = isolate_module(os)

# If you change the schema, increment the SCHEMA_VERSION, and update the
# docs in docs/dbschema.rst also.
# docs in docs/dbschema.rst by running "make cogdoc".

SCHEMA_VERSION = 7

Expand Down Expand Up @@ -390,8 +387,10 @@ def _file_id(self, filename, add=False):
if filename not in self._file_map:
if add:
with self._connect() as con:
cur = con.execute("insert or replace into file (path) values (?)", (filename,))
self._file_map[filename] = cur.lastrowid
self._file_map[filename] = con.execute_for_rowid(
"insert or replace into file (path) values (?)",
(filename,)
)
return self._file_map.get(filename)

def _context_id(self, context):
Expand Down Expand Up @@ -428,8 +427,10 @@ def _set_context_id(self):
self._current_context_id = context_id
else:
with self._connect() as con:
cur = con.execute("insert into context (context) values (?)", (context,))
self._current_context_id = cur.lastrowid
self._current_context_id = con.execute_for_rowid(
"insert into context (context) values (?)",
(context,)
)

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

def execute_for_rowid(self, sql, parameters=()):
"""Like execute, but returns the lastrowid."""
con = self.execute(sql, parameters)
rowid = con.lastrowid
if self.debug.should("sqldata"):
self.debug.write(f"Row id result: {rowid!r}")
return rowid

def execute_one(self, sql, parameters=()):
"""Execute a statement and return the one row that results.
Expand All @@ -1147,7 +1156,11 @@ def executemany(self, sql, data):
"""Same as :meth:`python:sqlite3.Connection.executemany`."""
if self.debug.should("sql"):
data = list(data)
self.debug.write(f"Executing many {sql!r} with {len(data)} rows")
final = ":" if self.debug.should("sqldata") else ""
self.debug.write(f"Executing many {sql!r} with {len(data)} rows{final}")
if self.debug.should("sqldata"):
for i, row in enumerate(data):
self.debug.write(f"{i:4d}: {row!r}")
try:
return self.con.executemany(sql, data)
except Exception: # pragma: cant happen
Expand Down
3 changes: 3 additions & 0 deletions doc/cmd.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,9 @@ of operation to log:

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

* ``sqldata``: when used with ``debug=sql``, also log the full data being used
in SQL statements.

* ``sys``: before starting, dump all the system and environment information,
as with :ref:`coverage debug sys <cmd_debug>`.

Expand Down
17 changes: 12 additions & 5 deletions tests/test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ def DebugCoverageData(*args, **kwargs):
lines in our coverage reports.
"""
assert "debug" not in kwargs
debug = DebugControlString(options=["dataio", "dataop", "sql"])
options = ["dataio", "dataop", "sql"]
if kwargs:
# There's no reason kwargs should imply sqldata debugging.
# This is a way to get a mix of debug options across the tests.
options.extend(["sqldata"])
debug = DebugControlString(options=options)
return CoverageData(*args, debug=debug, **kwargs)


Expand Down Expand Up @@ -160,15 +165,17 @@ def test_ok_to_add_arcs_twice(self):
assert_line_counts(covdata, SUMMARY_3_4)
assert_measured_files(covdata, MEASURED_FILES_3_4)

def test_cant_add_arcs_with_lines(self):
covdata = DebugCoverageData()
@pytest.mark.parametrize("klass", [CoverageData, DebugCoverageData])
def test_cant_add_arcs_with_lines(self, klass):
covdata = klass()
covdata.add_lines(LINES_1)
msg = "Can't add branch measurements to existing line data"
with pytest.raises(DataError, match=msg):
covdata.add_arcs(ARCS_3)

def test_cant_add_lines_with_arcs(self):
covdata = DebugCoverageData()
@pytest.mark.parametrize("klass", [CoverageData, DebugCoverageData])
def test_cant_add_lines_with_arcs(self, klass):
covdata = klass()
covdata.add_arcs(ARCS_3)
msg = "Can't add line measurements to existing branch data"
with pytest.raises(DataError, match=msg):
Expand Down

0 comments on commit a49ca09

Please sign in to comment.