diff options
-rw-r--r-- | coverage/debug.py | 17 | ||||
-rw-r--r-- | coverage/misc.py | 10 | ||||
-rw-r--r-- | coverage/results.py | 3 | ||||
-rw-r--r-- | coverage/sqldata.py | 19 | ||||
-rw-r--r-- | doc/cmd.rst | 2 |
5 files changed, 35 insertions, 16 deletions
diff --git a/coverage/debug.py b/coverage/debug.py index d63a9070..fd27c731 100644 --- a/coverage/debug.py +++ b/coverage/debug.py @@ -31,6 +31,8 @@ _TEST_NAME_FILE = "" # "/tmp/covtest.txt" class DebugControl(object): """Control and output for debugging.""" + show_repr_attr = False # For SimpleRepr + def __init__(self, options, output): """Configure the options and output file for debugging.""" self.options = list(options) + FORCED_DEBUG @@ -71,6 +73,10 @@ class DebugControl(object): `msg` is the line to write. A newline will be appended. """ + if self.should('self'): + caller_self = inspect.stack()[1][0].f_locals.get('self') + if caller_self is not None: + msg = "[self: {!r}] {}".format(caller_self, msg) self.output.write(msg+"\n") if self.should('callers'): dump_stack_frames(out=self.output, skip=1) @@ -167,6 +173,17 @@ def add_pid_and_tid(text): return text +class SimpleRepr(object): + """A mixin implementing a simple __repr__.""" + def __repr__(self): + show_attrs = ((k, v) for k, v in self.__dict__.items() if getattr(v, "show_repr_attr", True)) + return "<{klass} @0x{id:x} {attrs}>".format( + klass=self.__class__.__name__, + id=id(self), + attrs=" ".join("{}={!r}".format(k, v) for k, v in show_attrs), + ) + + def filter_text(text, filters): """Run `text` through a series of filters. diff --git a/coverage/misc.py b/coverage/misc.py index fff2a187..78ec027f 100644 --- a/coverage/misc.py +++ b/coverage/misc.py @@ -249,16 +249,6 @@ def _needs_to_implement(that, func_name): ) -class SimpleRepr(object): - """A mixin implementing a simple __repr__.""" - def __repr__(self): - return "<{klass} @{id:x} {attrs}>".format( - klass=self.__class__.__name__, - id=id(self) & 0xFFFFFF, - attrs=" ".join("{}={!r}".format(k, v) for k, v in self.__dict__.items()), - ) - - class BaseCoverageException(Exception): """The base of all Coverage exceptions.""" pass diff --git a/coverage/results.py b/coverage/results.py index 7e3bd268..fb919c9b 100644 --- a/coverage/results.py +++ b/coverage/results.py @@ -6,7 +6,8 @@ import collections from coverage.backward import iitems -from coverage.misc import contract, format_lines, SimpleRepr +from coverage.debug import SimpleRepr +from coverage.misc import contract, format_lines class Analysis(object): diff --git a/coverage/sqldata.py b/coverage/sqldata.py index cddece31..296e353e 100644 --- a/coverage/sqldata.py +++ b/coverage/sqldata.py @@ -7,6 +7,7 @@ import os import sqlite3 from coverage.backward import iitems +from coverage.debug import SimpleRepr from coverage.misc import CoverageException, file_be_gone @@ -47,7 +48,7 @@ create table arc ( # (-1065448850,) APP_ID = -1065448850 -class CoverageSqliteData(object): +class CoverageSqliteData(SimpleRepr): def __init__(self, basename=None, warn=None, debug=None): self.filename = os.path.abspath(basename or ".coverage") self._warn = warn @@ -125,6 +126,10 @@ class CoverageSqliteData(object): { filename: { lineno: None, ... }, ...} """ + if self._debug and self._debug.should('dataop'): + self._debug.write("Adding lines: %d files, %d lines total" % ( + len(line_data), sum(len(lines) for lines in line_data.values()) + )) self._start_writing() self._choose_lines_or_arcs(lines=True) with self._connect() as con: @@ -144,6 +149,10 @@ class CoverageSqliteData(object): { filename: { (l1,l2): None, ... }, ...} """ + if self._debug and self._debug.should('dataop'): + self._debug.write("Adding arcs: %d files, %d arcs total" % ( + len(arc_data), sum(len(arcs) for arcs in arc_data.values()) + )) self._start_writing() self._choose_lines_or_arcs(arcs=True) with self._connect() as con: @@ -242,7 +251,7 @@ class CoverageSqliteData(object): return [pair for pair in con.execute("select fromno, tono from arc where file_id = ?", (file_id,))] -class Sqlite(object): +class Sqlite(SimpleRepr): def __init__(self, filename, debug): self.debug = debug if (debug and debug.should('sql')) else None if self.debug: @@ -250,9 +259,9 @@ class Sqlite(object): self.con = sqlite3.connect(filename) # This pragma makes writing faster. It disables rollbacks, but we never need them. - self.con.execute("pragma journal_mode=off") + self.execute("pragma journal_mode=off") # This pragma makes writing faster. - self.con.execute("pragma synchronous=off") + self.execute("pragma synchronous=off") def close(self): self.con.close() @@ -272,5 +281,5 @@ class Sqlite(object): def executemany(self, sql, data): if self.debug: - self.debug.write("Executing many {!r}".format(sql)) + self.debug.write("Executing many {!r} with {} rows".format(sql, len(data))) return self.con.executemany(sql, data) diff --git a/doc/cmd.rst b/doc/cmd.rst index d198178f..908b2ee9 100644 --- a/doc/cmd.rst +++ b/doc/cmd.rst @@ -486,6 +486,8 @@ to log: * ``process``: show process creation information, and changes in the current directory. +* ``self``: annotate each debug message with the object printing the message. + * ``sys``: before starting, dump all the system and environment information, as with :ref:`coverage debug sys <cmd_debug>`. |