def sys_info(self): """Return a list of (key, value) pairs showing internal information.""" import coverage as covmod self._init() self._post_init() def plugin_info(plugins): """Make an entry for the sys_info from a list of plug-ins.""" entries = [] for plugin in plugins: entry = plugin._coverage_plugin_name if not plugin._coverage_enabled: entry += " (disabled)" entries.append(entry) return entries info = [ ('coverage_version', covmod.__version__), ('coverage_module', covmod.__file__), ('tracer', self._collector.tracer_name() if self._collector else "-none-"), ('CTracer', 'available' if CTracer else "unavailable"), ('plugins.file_tracers', plugin_info(self._plugins.file_tracers)), ('plugins.configurers', plugin_info(self._plugins.configurers)), ('plugins.context_switchers', plugin_info(self._plugins.context_switchers)), ('configs_attempted', self.config.attempted_config_files), ('configs_read', self.config.config_files_read), ('config_file', self.config.config_file), ('config_contents', repr(self.config._config_contents) if self.config._config_contents else '-none-'), ('data_file', self._data.data_filename() if self._data is not None else "-none-"), ('python', sys.version.replace('\n', '')), ('platform', platform.platform()), ('implementation', platform.python_implementation()), ('executable', sys.executable), ('def_encoding', sys.getdefaultencoding()), ('fs_encoding', sys.getfilesystemencoding()), ('pid', os.getpid()), ('cwd', os.getcwd()), ('path', sys.path), ('environment', human_sorted( f"{k} = {v}" for k, v in os.environ.items() if (any(slug in k for slug in ("COV", "PY")) or (k in ("HOME", "TEMP", "TMP"))))), ('command_line', " ".join(getattr(sys, 'argv', ['-none-']))), ] if self._inorout: info.extend(self._inorout.sys_info()) info.extend(CoverageData.sys_info()) return info
def pause(self): """Pause tracing, but be prepared to `resume`.""" for tracer in self.tracers: tracer.stop() stats = tracer.get_stats() if stats: print("\nCoverage.py tracer stats:") for k in human_sorted(stats.keys()): print(f"{k:>20}: {stats[k]}") if self.threading: self.threading.settrace(None)
def do_debug(self, args): """Implementation of 'coverage debug'.""" if not args: show_help( "What information would you like: config, data, sys, premain?") return ERR for info in args: if info == 'sys': sys_info = self.coverage.sys_info() print(info_header("sys")) for line in info_formatter(sys_info): print(f" {line}") elif info == 'data': self.coverage.load() data = self.coverage.get_data() print(info_header("data")) print(f"path: {data.data_filename()}") if data: print(f"has_arcs: {data.has_arcs()!r}") summary = line_counts(data, fullpath=True) filenames = human_sorted(summary.keys()) print(f"\n{len(filenames)} files:") for f in filenames: line = f"{f}: {summary[f]} lines" plugin = data.file_tracer(f) if plugin: line += f" [{plugin}]" print(line) else: print("No data collected") elif info == 'config': print(info_header("config")) config_info = self.coverage.config.__dict__.items() for line in info_formatter(config_info): print(f" {line}") elif info == "premain": print(info_header("premain")) print(short_stack()) else: show_help(f"Don't know what you mean by {info!r}") return ERR return OK
def debug_data_file(filename): """Implementation of 'coverage debug data'.""" data = CoverageData(filename) filename = data.data_filename() print(f"path: {filename}") if not os.path.exists(filename): print("No data collected: file doesn't exist") return data.read() print(f"has_arcs: {data.has_arcs()!r}") summary = line_counts(data, fullpath=True) filenames = human_sorted(summary.keys()) nfiles = len(filenames) print(f"{nfiles} file{plural(nfiles)}:") for f in filenames: line = f"{f}: {summary[f]} line{plural(summary[f])}" plugin = data.file_tracer(f) if plugin: line += f" [{plugin}]" print(line)
def data_for_file(self, fr, analysis): """Produce the data needed for one file's report.""" if self.has_arcs: missing_branch_arcs = analysis.missing_branch_arcs() arcs_executed = analysis.arcs_executed() if self.config.show_contexts: contexts_by_lineno = analysis.data.contexts_by_lineno( analysis.filename) lines = [] for lineno, tokens in enumerate(fr.source_token_lines(), start=1): # Figure out how to mark this line. category = None short_annotations = [] long_annotations = [] if lineno in analysis.excluded: category = 'exc' elif lineno in analysis.missing: category = 'mis' elif self.has_arcs and lineno in missing_branch_arcs: category = 'par' for b in missing_branch_arcs[lineno]: if b < 0: short_annotations.append("exit") else: short_annotations.append(b) long_annotations.append( fr.missing_arc_description(lineno, b, arcs_executed)) elif lineno in analysis.statements: category = 'run' contexts = contexts_label = None context_list = None if category and self.config.show_contexts: contexts = human_sorted( c or self.EMPTY for c in contexts_by_lineno.get(lineno, ())) if contexts == [self.EMPTY]: contexts_label = self.EMPTY else: contexts_label = f"{len(contexts)} ctx" context_list = contexts lines.append( types.SimpleNamespace( tokens=tokens, number=lineno, category=category, statement=(lineno in analysis.statements), contexts=contexts, contexts_label=contexts_label, context_list=context_list, short_annotations=short_annotations, long_annotations=long_annotations, )) file_data = types.SimpleNamespace( relative_filename=fr.relative_filename(), nums=analysis.numbers, lines=lines, ) return file_data
def test_human_sorted(words, ordered): assert " ".join(human_sorted(words.split())) == ordered
def __init__(self, paths, name): self.original_paths = human_sorted(paths) self.paths = list(map(os.path.normcase, paths)) self.name = name
def report(self, morfs, outfile=None): """Generate a Cobertura-compatible XML report for `morfs`. `morfs` is a list of modules or file names. `outfile` is a file object to write the XML to. """ # Initial setup. outfile = outfile or sys.stdout has_arcs = self.coverage.get_data().has_arcs() # Create the DOM that will store the data. impl = xml.dom.minidom.getDOMImplementation() self.xml_out = impl.createDocument(None, "coverage", None) # Write header stuff. xcoverage = self.xml_out.documentElement xcoverage.setAttribute("version", __version__) xcoverage.setAttribute("timestamp", str(int(time.time() * 1000))) xcoverage.appendChild( self.xml_out.createComment( f" Generated by coverage.py: {__url__} ")) xcoverage.appendChild( self.xml_out.createComment(f" Based on {DTD_URL} ")) # Call xml_file for each file in the data. for fr, analysis in get_analysis_to_report(self.coverage, morfs): self.xml_file(fr, analysis, has_arcs) xsources = self.xml_out.createElement("sources") xcoverage.appendChild(xsources) # Populate the XML DOM with the source info. for path in human_sorted(self.source_paths): xsource = self.xml_out.createElement("source") xsources.appendChild(xsource) txt = self.xml_out.createTextNode(path) xsource.appendChild(txt) lnum_tot, lhits_tot = 0, 0 bnum_tot, bhits_tot = 0, 0 xpackages = self.xml_out.createElement("packages") xcoverage.appendChild(xpackages) # Populate the XML DOM with the package info. for pkg_name, pkg_data in human_sorted_items(self.packages.items()): class_elts, lhits, lnum, bhits, bnum = pkg_data xpackage = self.xml_out.createElement("package") xpackages.appendChild(xpackage) xclasses = self.xml_out.createElement("classes") xpackage.appendChild(xclasses) for _, class_elt in human_sorted_items(class_elts.items()): xclasses.appendChild(class_elt) xpackage.setAttribute("name", pkg_name.replace(os.sep, '.')) xpackage.setAttribute("line-rate", rate(lhits, lnum)) if has_arcs: branch_rate = rate(bhits, bnum) else: branch_rate = "0" xpackage.setAttribute("branch-rate", branch_rate) xpackage.setAttribute("complexity", "0") lnum_tot += lnum lhits_tot += lhits bnum_tot += bnum bhits_tot += bhits xcoverage.setAttribute("lines-valid", str(lnum_tot)) xcoverage.setAttribute("lines-covered", str(lhits_tot)) xcoverage.setAttribute("line-rate", rate(lhits_tot, lnum_tot)) if has_arcs: xcoverage.setAttribute("branches-valid", str(bnum_tot)) xcoverage.setAttribute("branches-covered", str(bhits_tot)) xcoverage.setAttribute("branch-rate", rate(bhits_tot, bnum_tot)) else: xcoverage.setAttribute("branches-covered", "0") xcoverage.setAttribute("branches-valid", "0") xcoverage.setAttribute("branch-rate", "0") xcoverage.setAttribute("complexity", "0") # Write the output file. outfile.write(serialize_xml(self.xml_out)) # Return the total percentage. denom = lnum_tot + bnum_tot if denom == 0: pct = 0.0 else: pct = 100.0 * (lhits_tot + bhits_tot) / denom return pct