diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2023-01-04 07:03:10 -0500 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2023-01-04 07:03:10 -0500 |
commit | dbb94d570a2042409400c28ba3069dcb32a45159 (patch) | |
tree | 41caedd28b1d5cb99a76d8104566d309724eeeb7 /coverage | |
parent | faa62d3f3d90c15e72040479a9b237ca86bbeae1 (diff) | |
download | python-coveragepy-git-dbb94d570a2042409400c28ba3069dcb32a45159.tar.gz |
mypy: summary.py, test_summary.py, tests/coveragetest.py
Diffstat (limited to 'coverage')
-rw-r--r-- | coverage/config.py | 2 | ||||
-rw-r--r-- | coverage/control.py | 28 | ||||
-rw-r--r-- | coverage/debug.py | 5 | ||||
-rw-r--r-- | coverage/misc.py | 8 | ||||
-rw-r--r-- | coverage/parser.py | 2 | ||||
-rw-r--r-- | coverage/plugin.py | 2 | ||||
-rw-r--r-- | coverage/python.py | 2 | ||||
-rw-r--r-- | coverage/summary.py | 51 | ||||
-rw-r--r-- | coverage/types.py | 7 |
9 files changed, 71 insertions, 36 deletions
diff --git a/coverage/config.py b/coverage/config.py index 3e535949..04bde26f 100644 --- a/coverage/config.py +++ b/coverage/config.py @@ -518,7 +518,7 @@ class CoverageConfig(TConfigurable): for k, v in self.paths.items() ) - def debug_info(self) -> Iterable[Tuple[str, Any]]: + def debug_info(self) -> List[Tuple[str, Any]]: """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("_") diff --git a/coverage/control.py b/coverage/control.py index 8ac6781e..acd89b94 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -122,8 +122,8 @@ class Coverage(TConfigurable): config_file: Union[str, bool]=True, source: Optional[List[str]]=None, source_pkgs: Optional[List[str]]=None, - omit: Optional[List[str]]=None, - include: Optional[List[str]]=None, + omit: Optional[Union[str, List[str]]]=None, + include: Optional[Union[str, List[str]]]=None, debug: Optional[List[str]]=None, concurrency: Optional[Union[str, List[str]]]=None, check_preimported: bool=False, @@ -959,8 +959,8 @@ class Coverage(TConfigurable): show_missing: Optional[bool]=None, ignore_errors: Optional[bool]=None, file: Optional[IO[str]]=None, - omit: Optional[List[str]]=None, - include: Optional[List[str]]=None, + omit: Optional[Union[str, List[str]]]=None, + include: Optional[Union[str, List[str]]]=None, skip_covered: Optional[bool]=None, contexts: Optional[List[str]]=None, skip_empty: Optional[bool]=None, @@ -1040,8 +1040,8 @@ class Coverage(TConfigurable): morfs: Optional[Iterable[TMorf]]=None, directory: Optional[str]=None, ignore_errors: Optional[bool]=None, - omit: Optional[List[str]]=None, - include: Optional[List[str]]=None, + omit: Optional[Union[str, List[str]]]=None, + include: Optional[Union[str, List[str]]]=None, contexts: Optional[List[str]]=None, ) -> None: """Annotate a list of modules. @@ -1079,8 +1079,8 @@ class Coverage(TConfigurable): morfs: Optional[Iterable[TMorf]]=None, directory: Optional[str]=None, ignore_errors: Optional[bool]=None, - omit: Optional[List[str]]=None, - include: Optional[List[str]]=None, + omit: Optional[Union[str, List[str]]]=None, + include: Optional[Union[str, List[str]]]=None, extra_css: Optional[str]=None, title: Optional[str]=None, skip_covered: Optional[bool]=None, @@ -1137,8 +1137,8 @@ class Coverage(TConfigurable): morfs: Optional[Iterable[TMorf]]=None, outfile: Optional[str]=None, ignore_errors: Optional[bool]=None, - omit: Optional[List[str]]=None, - include: Optional[List[str]]=None, + omit: Optional[Union[str, List[str]]]=None, + include: Optional[Union[str, List[str]]]=None, contexts: Optional[List[str]]=None, skip_empty: Optional[bool]=None, ) -> float: @@ -1171,8 +1171,8 @@ class Coverage(TConfigurable): morfs: Optional[Iterable[TMorf]]=None, outfile: Optional[str]=None, ignore_errors: Optional[bool]=None, - omit: Optional[List[str]]=None, - include: Optional[List[str]]=None, + omit: Optional[Union[str, List[str]]]=None, + include: Optional[Union[str, List[str]]]=None, contexts: Optional[List[str]]=None, pretty_print: Optional[bool]=None, show_contexts: Optional[bool]=None, @@ -1209,8 +1209,8 @@ class Coverage(TConfigurable): morfs: Optional[Iterable[TMorf]]=None, outfile: Optional[str]=None, ignore_errors: Optional[bool]=None, - omit: Optional[List[str]]=None, - include: Optional[List[str]]=None, + omit: Optional[Union[str, List[str]]]=None, + include: Optional[Union[str, List[str]]]=None, contexts: Optional[List[str]]=None, ) -> float: """Generate an LCOV report of coverage results. diff --git a/coverage/debug.py b/coverage/debug.py index 82de3c29..a3d1dfa8 100644 --- a/coverage/debug.py +++ b/coverage/debug.py @@ -23,6 +23,7 @@ from typing import ( ) from coverage.misc import isolate_module +from coverage.types import TWritable os = isolate_module(os) @@ -184,7 +185,7 @@ def short_stack(limit: Optional[int]=None, skip: int=0) -> str: def dump_stack_frames( limit: Optional[int]=None, - out: Optional[IO[str]]=None, + out: Optional[TWritable]=None, skip: int=0 ) -> None: """Print a summary of the stack to stdout, or someplace else.""" @@ -371,7 +372,7 @@ class DebugOutputFile: # pragma: debugging self.outfile.flush() -def log(msg, stack=False): # pragma: debugging +def log(msg: str, stack: bool=False) -> None: # pragma: debugging """Write a log message as forcefully as possible.""" out = DebugOutputFile.get_one(interim=True) out.write(msg+"\n") diff --git a/coverage/misc.py b/coverage/misc.py index a2ac2fed..9b42d841 100644 --- a/coverage/misc.py +++ b/coverage/misc.py @@ -22,7 +22,7 @@ import types from types import ModuleType from typing import ( Any, Callable, Dict, Generator, IO, Iterable, List, Mapping, Optional, - Tuple, TypeVar, Union, + Sequence, Tuple, TypeVar, Union, ) from coverage import env @@ -361,10 +361,12 @@ def human_sorted(strings: Iterable[str]) -> List[str]: """ return sorted(strings, key=_human_key) +SortableItem = TypeVar("SortableItem", bound=Sequence[Any]) + def human_sorted_items( - items: Iterable[Tuple[str, Any]], + items: Iterable[SortableItem], reverse: bool=False, -) -> List[Tuple[str, Any]]: +) -> List[SortableItem]: """Sort (string, ...) items the way humans expect. The elements of `items` can be any tuple/list. They'll be sorted by the diff --git a/coverage/parser.py b/coverage/parser.py index 2a8d0a50..cb4e6474 100644 --- a/coverage/parser.py +++ b/coverage/parser.py @@ -328,7 +328,7 @@ class PythonParser: self, start: TLineNo, end: TLineNo, - executed_arcs: Optional[Set[TArc]]=None, + executed_arcs: Optional[Iterable[TArc]]=None, ) -> str: """Provide an English sentence describing a missing arc.""" if self._missing_arc_fragments is None: diff --git a/coverage/plugin.py b/coverage/plugin.py index ccc33337..da91aac4 100644 --- a/coverage/plugin.py +++ b/coverage/plugin.py @@ -496,7 +496,7 @@ class FileReporter(CoveragePluginBase): self, start: TLineNo, end: TLineNo, - executed_arcs: Optional[Set[TArc]]=None, # pylint: disable=unused-argument + executed_arcs: Optional[Iterable[TArc]]=None, # pylint: disable=unused-argument ) -> str: """Provide an English sentence describing a missing arc. diff --git a/coverage/python.py b/coverage/python.py index 2d2faa14..c25a03fd 100644 --- a/coverage/python.py +++ b/coverage/python.py @@ -224,7 +224,7 @@ class PythonFileReporter(FileReporter): self, start: TLineNo, end: TLineNo, - executed_arcs: Optional[Set[TArc]]=None, + executed_arcs: Optional[Iterable[TArc]]=None, ) -> str: return self.parser.missing_arc_description(start, end, executed_arcs) diff --git a/coverage/summary.py b/coverage/summary.py index 3f3fd688..287e7593 100644 --- a/coverage/summary.py +++ b/coverage/summary.py @@ -3,40 +3,56 @@ """Summary reporting""" +from __future__ import annotations + import sys +from typing import Any, IO, Iterable, List, Optional, Tuple, TYPE_CHECKING + from coverage.exceptions import ConfigError, NoDataError from coverage.misc import human_sorted_items +from coverage.plugin import FileReporter from coverage.report import get_analysis_to_report -from coverage.results import Numbers +from coverage.results import Analysis, Numbers +from coverage.types import TMorf + +if TYPE_CHECKING: + from coverage import Coverage class SummaryReporter: """A reporter for writing the summary report.""" - def __init__(self, coverage): + def __init__(self, coverage: Coverage) -> None: self.coverage = coverage self.config = self.coverage.config self.branches = coverage.get_data().has_arcs() - self.outfile = None + self.outfile: Optional[IO[str]] = None self.output_format = self.config.format or "text" if self.output_format not in {"text", "markdown", "total"}: raise ConfigError(f"Unknown report format choice: {self.output_format!r}") - self.fr_analysis = [] + self.fr_analysis: List[Tuple[FileReporter, Analysis]] = [] self.skipped_count = 0 self.empty_count = 0 self.total = Numbers(precision=self.config.precision) - def write(self, line): + def write(self, line: str) -> None: """Write a line to the output, adding a newline.""" + assert self.outfile is not None self.outfile.write(line.rstrip()) self.outfile.write("\n") - def write_items(self, items): + def write_items(self, items: Iterable[str]) -> None: """Write a list of strings, joined together.""" self.write("".join(items)) - def _report_text(self, header, lines_values, total_line, end_lines): + def _report_text( + self, + header: List[str], + lines_values: List[List[Any]], + total_line: List[Any], + end_lines: List[str], + ) -> None: """Internal method that prints report data in text format. `header` is a list with captions. @@ -91,7 +107,13 @@ class SummaryReporter: for end_line in end_lines: self.write(end_line) - def _report_markdown(self, header, lines_values, total_line, end_lines): + def _report_markdown( + self, + header: List[str], + lines_values: List[List[Any]], + total_line: List[Any], + end_lines: List[str], + ) -> None: """Internal method that prints report data in markdown format. `header` is a list with captions. @@ -134,7 +156,7 @@ class SummaryReporter: # Write the TOTAL line formats.update(dict(Name="|{:>{name_len}} |", Cover="{:>{n}} |")) - total_line_items = [] + total_line_items: List[str] = [] for item, value in zip(header, total_line): if value == "": insert = value @@ -147,7 +169,7 @@ class SummaryReporter: for end_line in end_lines: self.write(end_line) - def report(self, morfs, outfile=None) -> float: + def report(self, morfs: Optional[Iterable[TMorf]], outfile: Optional[IO[str]]=None) -> float: """Writes a report summarizing coverage statistics per module. `outfile` is a text-mode file object to write the summary to. @@ -169,7 +191,7 @@ class SummaryReporter: return self.total.pc_covered - def tabular_report(self): + def tabular_report(self) -> None: """Writes tabular report formats.""" # Prepare the header line and column sorting. header = ["Name", "Stmts", "Miss"] @@ -212,7 +234,10 @@ class SummaryReporter: if sort_option == "name": lines_values = human_sorted_items(lines_values, reverse=reverse) else: - lines_values.sort(key=lambda line: (line[sort_idx], line[0]), reverse=reverse) + lines_values.sort( + key=lambda line: (line[sort_idx], line[0]), # type: ignore[index] + reverse=reverse, + ) # Calculate total if we had at least one file. total_line = ["TOTAL", self.total.n_statements, self.total.n_missing] @@ -239,7 +264,7 @@ class SummaryReporter: formatter = self._report_text formatter(header, lines_values, total_line, end_lines) - def report_one_file(self, fr, analysis): + def report_one_file(self, fr: FileReporter, analysis: Analysis) -> None: """Report on just one file, the callback from report().""" nums = analysis.numbers self.total += nums diff --git a/coverage/types.py b/coverage/types.py index 54c1dfba..ed22e699 100644 --- a/coverage/types.py +++ b/coverage/types.py @@ -166,3 +166,10 @@ class TDebugCtl(Protocol): def write(self, msg: str) -> None: """Write a line of debug output.""" + + +class TWritable(Protocol): + """Anything that can be written to.""" + + def write(self, msg: str) -> None: + """Write a message.""" |