From e47e7e758bfc48537f0f21d40cef8e5fa2a076c6 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Tue, 9 Jul 2024 20:56:24 -0400 Subject: [PATCH] refactor: move duplicate code into methods --- coverage/jsonreport.py | 81 ++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 47 deletions(-) diff --git a/coverage/jsonreport.py b/coverage/jsonreport.py index 3db266bd5..1b9b42eb6 100644 --- a/coverage/jsonreport.py +++ b/coverage/jsonreport.py @@ -9,7 +9,7 @@ import json import sys -from typing import Any, IO, Iterable, TYPE_CHECKING +from typing import Any, Dict, IO, Iterable, TYPE_CHECKING from coverage import __version__ from coverage.report_core import get_analysis_to_report @@ -22,6 +22,9 @@ from coverage.plugin import FileReporter +# A type for data that can be JSON-serialized. +JsonObj = Dict[str, Any] + # "Version 1" had no format number at all. # 2: add the meta.format field. # 3: add region information (functions, classes) @@ -36,7 +39,27 @@ def __init__(self, coverage: Coverage) -> None: self.coverage = coverage self.config = self.coverage.config self.total = Numbers(self.config.precision) - self.report_data: dict[str, Any] = {} + self.report_data: JsonObj = {} + + def make_summary(self, nums: Numbers) -> JsonObj: + """Create a dict summarizing `nums`.""" + return { + "covered_lines": nums.n_executed, + "num_statements": nums.n_statements, + "percent_covered": nums.pc_covered, + "percent_covered_display": nums.pc_covered_str, + "missing_lines": nums.n_missing, + "excluded_lines": nums.n_excluded, + } + + def make_branch_summary(self, nums: Numbers) -> JsonObj: + """Create a dict summarizing the branch info in `nums`.""" + return { + "num_branches": nums.n_branches, + "num_partial_branches": nums.n_partial_branches, + "covered_branches": nums.n_executed_branches, + "missing_branches": nums.n_missing_branches, + } def report(self, morfs: Iterable[TMorf] | None, outfile: IO[str]) -> float: """Generate a json report for `morfs`. @@ -66,23 +89,10 @@ def report(self, morfs: Iterable[TMorf] | None, outfile: IO[str]) -> float: ) self.report_data["files"] = measured_files - - self.report_data["totals"] = { - "covered_lines": self.total.n_executed, - "num_statements": self.total.n_statements, - "percent_covered": self.total.pc_covered, - "percent_covered_display": self.total.pc_covered_str, - "missing_lines": self.total.n_missing, - "excluded_lines": self.total.n_excluded, - } + self.report_data["totals"] = self.make_summary(self.total) if coverage_data.has_arcs(): - self.report_data["totals"].update({ - "num_branches": self.total.n_branches, - "num_partial_branches": self.total.n_partial_branches, - "covered_branches": self.total.n_executed_branches, - "missing_branches": self.total.n_missing_branches, - }) + self.report_data["totals"].update(self.make_branch_summary(self.total)) json.dump( self.report_data, @@ -94,19 +104,12 @@ def report(self, morfs: Iterable[TMorf] | None, outfile: IO[str]) -> float: def report_one_file( self, coverage_data: CoverageData, analysis: Analysis, file_reporter: FileReporter - ) -> dict[str, Any]: + ) -> JsonObj: """Extract the relevant report data for a single file.""" nums = analysis.numbers self.total += nums - summary = { - "covered_lines": nums.n_executed, - "num_statements": nums.n_statements, - "percent_covered": nums.pc_covered, - "percent_covered_display": nums.pc_covered_str, - "missing_lines": nums.n_missing, - "excluded_lines": nums.n_excluded, - } - reported_file: dict[str, Any] = { + summary = self.make_summary(nums) + reported_file: JsonObj = { "executed_lines": sorted(analysis.executed), "summary": summary, "missing_lines": sorted(analysis.missing), @@ -115,12 +118,7 @@ def report_one_file( if self.config.json_show_contexts: reported_file["contexts"] = coverage_data.contexts_by_lineno(analysis.filename) if coverage_data.has_arcs(): - summary.update({ - "num_branches": nums.n_branches, - "num_partial_branches": nums.n_partial_branches, - "covered_branches": nums.n_executed_branches, - "missing_branches": nums.n_missing_branches, - }) + summary.update(self.make_branch_summary(nums)) reported_file["executed_branches"] = list( _convert_branch_arcs(analysis.executed_branch_arcs()), ) @@ -136,14 +134,7 @@ def report_one_file( outside_lines -= region.lines narrowed_analysis = analysis.narrow(region.lines) narrowed_nums = narrowed_analysis.numbers - narrowed_summary = { - "covered_lines": narrowed_nums.n_executed, - "num_statements": narrowed_nums.n_statements, - "percent_covered": narrowed_nums.pc_covered, - "percent_covered_display": narrowed_nums.pc_covered_str, - "missing_lines": narrowed_nums.n_missing, - "excluded_lines": narrowed_nums.n_excluded, - } + narrowed_summary = self.make_summary(narrowed_nums) reported_file[region.kind][region.name] = { "executed_lines": sorted(narrowed_analysis.executed), "summary": narrowed_summary, @@ -154,18 +145,14 @@ def report_one_file( contexts = coverage_data.contexts_by_lineno(narrowed_analysis.filename) reported_file[region.kind][region.name]["contexts"] = contexts if coverage_data.has_arcs(): - narrowed_summary.update({ - "num_branches": narrowed_nums.n_branches, - "num_partial_branches": narrowed_nums.n_partial_branches, - "covered_branches": narrowed_nums.n_executed_branches, - "missing_branches": narrowed_nums.n_missing_branches, - }) + narrowed_summary.update(self.make_branch_summary(narrowed_nums)) reported_file[region.kind][region.name]["executed_branches"] = list( _convert_branch_arcs(narrowed_analysis.executed_branch_arcs()), ) reported_file[region.kind][region.name]["missing_branches"] = list( _convert_branch_arcs(narrowed_analysis.missing_branch_arcs()), ) + return reported_file