Coverage.py database schema
Added in version 5.0.
Coverage.py stores data in a SQLite database, by default called .coverage
.
For most needs, the CoverageData
API will be sufficient, and should
be preferred to accessing the database directly. Only advanced uses will need
to use the database.
The schema can change without changing the major version of coverage.py, so be
careful when accessing the database directly. The coverage_schema
table
has the schema number of the database. The schema described here corresponds
to:
SCHEMA_VERSION = 7
You can use SQLite tools such as the sqlite3
module in
the Python standard library to access the data. Some data is stored in a
packed format that will need custom functions to access. See
register_sqlite_functions()
.
Database schema
This is the database schema:
CREATE TABLE coverage_schema (
-- One row, to record the version of the schema in this db.
version integer
);
CREATE TABLE meta (
-- Key-value pairs, to record metadata about the data
key text,
value text,
unique (key)
-- Possible keys:
-- 'has_arcs' boolean -- Is this data recording branches?
-- 'sys_argv' text -- The coverage command line that recorded the data.
-- 'version' text -- The version of coverage.py that made the file.
-- 'when' text -- Datetime when the file was created.
);
CREATE TABLE file (
-- A row per file measured.
id integer primary key,
path text,
unique (path)
);
CREATE TABLE context (
-- A row per context measured.
id integer primary key,
context text,
unique (context)
);
CREATE TABLE line_bits (
-- If recording lines, a row per context per file executed.
-- All of the line numbers for that file/context are in one numbits.
file_id integer, -- foreign key to `file`.
context_id integer, -- foreign key to `context`.
numbits blob, -- see the numbits functions in coverage.numbits
foreign key (file_id) references file (id),
foreign key (context_id) references context (id),
unique (file_id, context_id)
);
CREATE TABLE arc (
-- If recording branches, a row per context per from/to line transition executed.
file_id integer, -- foreign key to `file`.
context_id integer, -- foreign key to `context`.
fromno integer, -- line number jumped from.
tono integer, -- line number jumped to.
foreign key (file_id) references file (id),
foreign key (context_id) references context (id),
unique (file_id, context_id, fromno, tono)
);
CREATE TABLE tracer (
-- A row per file indicating the tracer used for that file.
file_id integer primary key,
tracer text,
foreign key (file_id) references file (id)
);
Numbits
Functions to manipulate packed binary representations of number sets.
To save space, coverage stores sets of line numbers in SQLite using a packed binary representation called a numbits. A numbits is a set of positive integers.
A numbits is stored as a blob in the database. The exact meaning of the bytes in the blobs should be considered an implementation detail that might change in the future. Use these functions to work with those binary blobs of data.
- coverage.numbits.num_in_numbits(num, numbits)
Does the integer num appear in numbits?
- coverage.numbits.numbits_any_intersection(numbits1, numbits2)
Is there any number that appears in both numbits?
Determine whether two number sets have a non-empty intersection. This is faster than computing the intersection.
- coverage.numbits.numbits_intersection(numbits1, numbits2)
Compute the intersection of two numbits.
- coverage.numbits.numbits_to_nums(numbits)
Convert a numbits into a list of numbers.
- Parameters:
numbits (bytes) – a binary blob, the packed number set.
- Returns:
A list of ints.
- Return type:
When registered as a SQLite function by
register_sqlite_functions()
, this returns a string, a JSON-encoded list of ints.
- coverage.numbits.numbits_union(numbits1, numbits2)
Compute the union of two numbits.
- coverage.numbits.nums_to_numbits(nums)
Convert nums into a numbits.
- coverage.numbits.register_sqlite_functions(connection)
Define numbits functions in a SQLite connection.
This defines these functions for use in SQLite statements:
connection is a
sqlite3.Connection
object. After creating the connection, pass it to this function to register the numbits functions. Then you can use numbits functions in your queries:import sqlite3 from coverage.numbits import register_sqlite_functions conn = sqlite3.connect("example.db") register_sqlite_functions(conn) c = conn.cursor() # Kind of a nonsense query: # Find all the files and contexts that executed line 47 in any file: c.execute( "select file_id, context_id from line_bits where num_in_numbits(?, numbits)", (47,) )
- Parameters:
connection (Connection)
- Return type:
None