diff options
Diffstat (limited to 'coverage')
-rw-r--r-- | coverage/cmdline.py | 25 | ||||
-rw-r--r-- | coverage/config.py | 8 | ||||
-rw-r--r-- | coverage/control.py | 30 | ||||
-rw-r--r-- | coverage/debug.py | 13 | ||||
-rw-r--r-- | coverage/env.py | 14 |
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) |