summaryrefslogtreecommitdiff
path: root/coverage/plugin.py
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2022-12-29 10:19:14 -0500
committerNed Batchelder <ned@nedbatchelder.com>2022-12-29 11:28:00 -0500
commitd4c2b18bdd0102ff873514e53ec560c3083c3413 (patch)
tree4e91bacd91f5a0fbcf4976376bbc87e88d46b551 /coverage/plugin.py
parent0accb68cd9ac353bd5464750987e02012bdb8e0c (diff)
downloadpython-coveragepy-git-d4c2b18bdd0102ff873514e53ec560c3083c3413.tar.gz
mypy: mypy checks plugin.py
Diffstat (limited to 'coverage/plugin.py')
-rw-r--r--coverage/plugin.py84
1 files changed, 54 insertions, 30 deletions
diff --git a/coverage/plugin.py b/coverage/plugin.py
index bf30b1b7..b6df72e4 100644
--- a/coverage/plugin.py
+++ b/coverage/plugin.py
@@ -112,16 +112,22 @@ register your dynamic context switcher.
"""
+from __future__ import annotations
+
import functools
+from types import FrameType
+from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Union
+
from coverage import files
-from coverage.misc import contract, _needs_to_implement
+from coverage.misc import _needs_to_implement
+from coverage.types import TArc, TConfigurable
class CoveragePlugin:
"""Base class for coverage.py plug-ins."""
- def file_tracer(self, filename): # pylint: disable=unused-argument
+ def file_tracer(self, filename: str) -> Optional[FileTracer]: # pylint: disable=unused-argument
"""Get a :class:`FileTracer` object for a file.
Plug-in type: file tracer.
@@ -161,7 +167,10 @@ class CoveragePlugin:
"""
return None
- def file_reporter(self, filename): # pylint: disable=unused-argument
+ def file_reporter( # type: ignore[return]
+ self,
+ filename: str, # pylint: disable=unused-argument
+ ) -> Union[FileReporter, str]: # str should be Literal["python"]
"""Get the :class:`FileReporter` class to use for a file.
Plug-in type: file tracer.
@@ -175,7 +184,10 @@ class CoveragePlugin:
"""
_needs_to_implement(self, "file_reporter")
- def dynamic_context(self, frame): # pylint: disable=unused-argument
+ def dynamic_context(
+ self,
+ frame: FrameType, # pylint: disable=unused-argument
+ ) -> Optional[str]:
"""Get the dynamically computed context label for `frame`.
Plug-in type: dynamic context.
@@ -191,7 +203,10 @@ class CoveragePlugin:
"""
return None
- def find_executable_files(self, src_dir): # pylint: disable=unused-argument
+ def find_executable_files(
+ self,
+ src_dir: str, # pylint: disable=unused-argument
+ ) -> Iterable[str]:
"""Yield all of the executable files in `src_dir`, recursively.
Plug-in type: file tracer.
@@ -206,7 +221,7 @@ class CoveragePlugin:
"""
return []
- def configure(self, config):
+ def configure(self, config: TConfigurable) -> None:
"""Modify the configuration of coverage.py.
Plug-in type: configurer.
@@ -220,7 +235,7 @@ class CoveragePlugin:
"""
pass
- def sys_info(self):
+ def sys_info(self) -> List[Tuple[str, str]]:
"""Get a list of information useful for debugging.
Plug-in type: any.
@@ -251,7 +266,7 @@ class FileTracer:
"""
- def source_filename(self):
+ def source_filename(self) -> str: # type: ignore[return]
"""The source file name for this file.
This may be any file name you like. A key responsibility of a plug-in
@@ -266,7 +281,7 @@ class FileTracer:
"""
_needs_to_implement(self, "source_filename")
- def has_dynamic_source_filename(self):
+ def has_dynamic_source_filename(self) -> bool:
"""Does this FileTracer have dynamic source file names?
FileTracers can provide dynamically determined file names by
@@ -284,7 +299,11 @@ class FileTracer:
"""
return False
- def dynamic_source_filename(self, filename, frame): # pylint: disable=unused-argument
+ def dynamic_source_filename(
+ self,
+ filename: str, # pylint: disable=unused-argument
+ frame: FrameType, # pylint: disable=unused-argument
+ ) -> Optional[str]:
"""Get a dynamically computed source file name.
Some plug-ins need to compute the source file name dynamically for each
@@ -299,7 +318,7 @@ class FileTracer:
"""
return None
- def line_number_range(self, frame):
+ def line_number_range(self, frame: FrameType) -> Tuple[int, int]:
"""Get the range of source line numbers for a given a call frame.
The call frame is examined, and the source line number in the original
@@ -331,7 +350,7 @@ class FileReporter:
"""
- def __init__(self, filename):
+ def __init__(self, filename: str) -> None:
"""Simple initialization of a `FileReporter`.
The `filename` argument is the path to the file being reported. This
@@ -341,10 +360,10 @@ class FileReporter:
"""
self.filename = filename
- def __repr__(self):
+ def __repr__(self) -> str:
return "<{0.__class__.__name__} filename={0.filename!r}>".format(self)
- def relative_filename(self):
+ def relative_filename(self) -> str:
"""Get the relative file name for this file.
This file path will be displayed in reports. The default
@@ -355,8 +374,7 @@ class FileReporter:
"""
return files.relative_filename(self.filename)
- @contract(returns='unicode')
- def source(self):
+ def source(self) -> str:
"""Get the source for the file.
Returns a Unicode string.
@@ -366,10 +384,10 @@ class FileReporter:
as a text file, or if you need other encoding support.
"""
- with open(self.filename, "rb") as f:
- return f.read().decode("utf-8")
+ with open(self.filename, encoding="utf-8") as f:
+ return f.read()
- def lines(self):
+ def lines(self) -> Set[int]: # type: ignore[return]
"""Get the executable lines in this file.
Your plug-in must determine which lines in the file were possibly
@@ -380,7 +398,7 @@ class FileReporter:
"""
_needs_to_implement(self, "lines")
- def excluded_lines(self):
+ def excluded_lines(self) -> Set[int]:
"""Get the excluded executable lines in this file.
Your plug-in can use any method it likes to allow the user to exclude
@@ -393,7 +411,7 @@ class FileReporter:
"""
return set()
- def translate_lines(self, lines):
+ def translate_lines(self, lines: Iterable[int]) -> Set[int]:
"""Translate recorded lines into reported lines.
Some file formats will want to report lines slightly differently than
@@ -413,7 +431,7 @@ class FileReporter:
"""
return set(lines)
- def arcs(self):
+ def arcs(self) -> Set[TArc]:
"""Get the executable arcs in this file.
To support branch coverage, your plug-in needs to be able to indicate
@@ -427,7 +445,7 @@ class FileReporter:
"""
return set()
- def no_branch_lines(self):
+ def no_branch_lines(self) -> Set[int]:
"""Get the lines excused from branch coverage in this file.
Your plug-in can use any method it likes to allow the user to exclude
@@ -440,7 +458,7 @@ class FileReporter:
"""
return set()
- def translate_arcs(self, arcs):
+ def translate_arcs(self, arcs: Set[TArc]) -> Set[TArc]:
"""Translate recorded arcs into reported arcs.
Similar to :meth:`translate_lines`, but for arcs. `arcs` is a set of
@@ -453,7 +471,7 @@ class FileReporter:
"""
return arcs
- def exit_counts(self):
+ def exit_counts(self) -> Dict[int, int]:
"""Get a count of exits from that each line.
To determine which lines are branches, coverage.py looks for lines that
@@ -466,7 +484,12 @@ class FileReporter:
"""
return {}
- def missing_arc_description(self, start, end, executed_arcs=None): # pylint: disable=unused-argument
+ def missing_arc_description(
+ self,
+ start: int,
+ end: int,
+ executed_arcs: Optional[Set[TArc]]=None, # pylint: disable=unused-argument
+ ) -> str:
"""Provide an English sentence describing a missing arc.
The `start` and `end` arguments are the line numbers of the missing
@@ -481,7 +504,7 @@ class FileReporter:
"""
return f"Line {start} didn't jump to line {end}"
- def source_token_lines(self):
+ def source_token_lines(self) -> Iterable[List[Tuple[str, str]]]:
"""Generate a series of tokenized lines, one for each line in `source`.
These tokens are used for syntax-colored reports.
@@ -512,10 +535,11 @@ class FileReporter:
for line in self.source().splitlines():
yield [('txt', line)]
- def __eq__(self, other):
+ def __eq__(self, other: Any) -> bool:
return isinstance(other, FileReporter) and self.filename == other.filename
- def __lt__(self, other):
+ def __lt__(self, other: Any) -> bool:
return isinstance(other, FileReporter) and self.filename < other.filename
- __hash__ = None # This object doesn't need to be hashed.
+ # This object doesn't need to be hashed.
+ __hash__ = None # type: ignore[assignment]