summaryrefslogtreecommitdiff
path: root/coverage
diff options
context:
space:
mode:
Diffstat (limited to 'coverage')
-rw-r--r--coverage/cmdline.py25
-rw-r--r--coverage/config.py8
-rw-r--r--coverage/control.py30
-rw-r--r--coverage/debug.py13
-rw-r--r--coverage/env.py14
5 files changed, 49 insertions, 41 deletions
diff --git a/coverage/cmdline.py b/coverage/cmdline.py
index 4c850801..0c44378a 100644
--- a/coverage/cmdline.py
+++ b/coverage/cmdline.py
@@ -19,7 +19,7 @@ from coverage.collector import CTracer
from coverage.config import CoverageConfig
from coverage.control import DEFAULT_DATAFILE
from coverage.data import combinable_files, debug_data_file
-from coverage.debug import info_formatter, info_header, short_stack
+from coverage.debug import info_header, short_stack, write_formatted_info
from coverage.exceptions import _BaseCoverageException, _ExceptionDuringRun, NoSource
from coverage.execfile import PyRunner
from coverage.results import Numbers, should_fail_under
@@ -400,7 +400,8 @@ COMMANDS = {
"'data' to show a summary of the collected data; " +
"'sys' to show installation information; " +
"'config' to show the configuration; " +
- "'premain' to show what is calling coverage."
+ "'premain' to show what is calling coverage; " +
+ "'pybehave' to show internal flags describing Python behavior."
),
),
@@ -843,32 +844,28 @@ class CoverageScript:
"""Implementation of 'coverage debug'."""
if not args:
- show_help("What information would you like: config, data, sys, premain?")
+ show_help("What information would you like: config, data, sys, premain, pybehave?")
return ERR
if args[1:]:
show_help("Only one topic at a time, please")
return ERR
- if args[0] == 'sys':
- sys_info = self.coverage.sys_info()
- print(info_header("sys"))
- for line in info_formatter(sys_info):
- print(f" {line}")
- elif args[0] == 'data':
+ if args[0] == "sys":
+ write_formatted_info(print, "sys", self.coverage.sys_info())
+ elif args[0] == "data":
print(info_header("data"))
data_file = self.coverage.config.data_file
debug_data_file(data_file)
for filename in combinable_files(data_file):
print("-----")
debug_data_file(filename)
- elif args[0] == 'config':
- print(info_header("config"))
- config_info = sorted(self.coverage.config.__dict__.items())
- for line in info_formatter(config_info):
- print(f" {line}")
+ elif args[0] == "config":
+ write_formatted_info(print, "config", self.coverage.config.debug_info())
elif args[0] == "premain":
print(info_header("premain"))
print(short_stack())
+ elif args[0] == "pybehave":
+ write_formatted_info(print, "pybehave", env.debug_info())
else:
show_help(f"Don't know what you mean by {args[0]!r}")
return ERR
diff --git a/coverage/config.py b/coverage/config.py
index 9909c530..fbfb59f4 100644
--- a/coverage/config.py
+++ b/coverage/config.py
@@ -11,7 +11,7 @@ import os.path
import re
from coverage.exceptions import ConfigError
-from coverage.misc import contract, isolate_module, substitute_variables
+from coverage.misc import contract, isolate_module, human_sorted_items, substitute_variables
from coverage.tomlconfig import TomlConfigParser, TomlDecodeError
@@ -495,6 +495,12 @@ class CoverageConfig:
for k, v in self.paths.items()
)
+ def debug_info(self):
+ """Make a list of (name, value) pairs for writing debug info."""
+ return human_sorted_items(
+ (k, v) for k, v in self.__dict__.items() if not k.startswith("_")
+ )
+
def config_files_to_try(config_file):
"""What config files should we try to read?
diff --git a/coverage/control.py b/coverage/control.py
index a3fda8d8..0f9f675e 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -29,7 +29,7 @@ from coverage.html import HtmlReporter
from coverage.inorout import InOrOut
from coverage.jsonreport import JsonReporter
from coverage.lcovreport import LcovReporter
-from coverage.misc import bool_or_none, join_regex, human_sorted, human_sorted_items
+from coverage.misc import bool_or_none, join_regex, human_sorted
from coverage.misc import DefaultValue, ensure_dir_for_file, isolate_module
from coverage.plugin import FileReporter
from coverage.plugin_support import Plugins
@@ -315,35 +315,25 @@ class Coverage:
"""Write out debug info at startup if needed."""
wrote_any = False
with self._debug.without_callers():
- if self._debug.should('config'):
- config_info = human_sorted_items(self.config.__dict__.items())
- config_info = [(k, v) for k, v in config_info if not k.startswith('_')]
- write_formatted_info(self._debug, "config", config_info)
+ if self._debug.should("config"):
+ config_info = self.config.debug_info()
+ write_formatted_info(self._debug.write, "config", config_info)
wrote_any = True
- if self._debug.should('sys'):
- write_formatted_info(self._debug, "sys", self.sys_info())
+ if self._debug.should("sys"):
+ write_formatted_info(self._debug.write, "sys", self.sys_info())
for plugin in self._plugins:
header = "sys: " + plugin._coverage_plugin_name
info = plugin.sys_info()
- write_formatted_info(self._debug, header, info)
+ write_formatted_info(self._debug.write, header, info)
wrote_any = True
- if self._debug.should('pybehave'):
- info = [
- (name, value) for name, value in env.__dict__.items()
- if not name.startswith("_") and
- name != "PYBEHAVIOR" and
- not isinstance(value, type(os))
- ] + [
- (name, value) for name, value in env.PYBEHAVIOR.__dict__.items()
- if not name.startswith("_")
- ]
- write_formatted_info(self._debug, "pybehave", sorted(info))
+ if self._debug.should("pybehave"):
+ write_formatted_info(self._debug.write, "pybehave", env.debug_info())
wrote_any = True
if wrote_any:
- write_formatted_info(self._debug, "end", ())
+ write_formatted_info(self._debug.write, "end", ())
def _should_trace(self, filename, frame):
"""Decide whether to trace execution in `filename`.
diff --git a/coverage/debug.py b/coverage/debug.py
index e6f93aa6..8c5e3839 100644
--- a/coverage/debug.py
+++ b/coverage/debug.py
@@ -130,17 +130,18 @@ def info_formatter(info):
yield "%*s: %s" % (label_len, label, data)
-def write_formatted_info(writer, header, info):
+def write_formatted_info(write, header, info):
"""Write a sequence of (label,data) pairs nicely.
- `writer` has a .write(str) method. `header` is a string to start the
- section. `info` is a sequence of (label, data) pairs, where label
- is a str, and data can be a single value, or a list/set/tuple.
+ `write` is a function write(str) that accepts each line of output.
+ `header` is a string to start the section. `info` is a sequence of
+ (label, data) pairs, where label is a str, and data can be a single
+ value, or a list/set/tuple.
"""
- writer.write(info_header(header))
+ write(info_header(header))
for line in info_formatter(info):
- writer.write(" %s" % line)
+ write(f" {line}")
def short_stack(limit=None, skip=0):
diff --git a/coverage/env.py b/coverage/env.py
index 3b24c390..1922d93f 100644
--- a/coverage/env.py
+++ b/coverage/env.py
@@ -133,3 +133,17 @@ USE_CONTRACTS = (
and not bool(int(os.environ.get("COVERAGE_NO_CONTRACTS", 0)))
and (PYVERSION < (3, 11))
)
+
+def debug_info():
+ """Return a list of (name, value) pairs for printing debug information."""
+ info = [
+ (name, value) for name, value in globals().items()
+ if not name.startswith("_") and
+ name not in {"PYBEHAVIOR", "debug_info"} and
+ not isinstance(value, type(os))
+ ]
+ info += [
+ (name, value) for name, value in PYBEHAVIOR.__dict__.items()
+ if not name.startswith("_")
+ ]
+ return sorted(info)