summaryrefslogtreecommitdiff
path: root/coverage/plugin_support.py
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2023-01-01 18:57:42 -0500
committerNed Batchelder <ned@nedbatchelder.com>2023-01-01 19:27:47 -0500
commit0c9b5e0e9da9c2cffd50db7b28142d22d0f66cee (patch)
treee407697322a76e40ccc38ac44aa4d2f2489d6dcc /coverage/plugin_support.py
parent8f4d404c8f9044ea1c3bf2479236f51d7706cb76 (diff)
downloadpython-coveragepy-git-0c9b5e0e9da9c2cffd50db7b28142d22d0f66cee.tar.gz
mypy: check collector.py and plugin_support.py
Diffstat (limited to 'coverage/plugin_support.py')
-rw-r--r--coverage/plugin_support.py108
1 files changed, 62 insertions, 46 deletions
diff --git a/coverage/plugin_support.py b/coverage/plugin_support.py
index 0b892391..8ac42491 100644
--- a/coverage/plugin_support.py
+++ b/coverage/plugin_support.py
@@ -3,13 +3,20 @@
"""Support for plugins."""
+from __future__ import annotations
+
import os
import os.path
import sys
+from types import FrameType
+from typing import Any, Dict, Iterable, Iterator, List, Optional, Set, Tuple, Union
+
+from coverage.config import CoverageConfig
from coverage.exceptions import PluginError
from coverage.misc import isolate_module
from coverage.plugin import CoveragePlugin, FileTracer, FileReporter
+from coverage.types import TArc, TConfigurable, TDebugCtl, TLineNo, TSourceTokenLines
os = isolate_module(os)
@@ -17,18 +24,23 @@ os = isolate_module(os)
class Plugins:
"""The currently loaded collection of coverage.py plugins."""
- def __init__(self):
- self.order = []
- self.names = {}
- self.file_tracers = []
- self.configurers = []
- self.context_switchers = []
+ def __init__(self) -> None:
+ self.order: List[CoveragePlugin] = []
+ self.names: Dict[str, CoveragePlugin] = {}
+ self.file_tracers: List[CoveragePlugin] = []
+ self.configurers: List[CoveragePlugin] = []
+ self.context_switchers: List[CoveragePlugin] = []
- self.current_module = None
- self.debug = None
+ self.current_module: Optional[str] = None
+ self.debug: Optional[TDebugCtl]
@classmethod
- def load_plugins(cls, modules, config, debug=None):
+ def load_plugins(
+ cls,
+ modules: Iterable[str],
+ config: CoverageConfig,
+ debug: Optional[TDebugCtl]=None,
+ ) -> Plugins:
"""Load plugins from `modules`.
Returns a Plugins object with the loaded and configured plugins.
@@ -54,7 +66,7 @@ class Plugins:
plugins.current_module = None
return plugins
- def add_file_tracer(self, plugin):
+ def add_file_tracer(self, plugin: CoveragePlugin) -> None:
"""Add a file tracer plugin.
`plugin` is an instance of a third-party plugin class. It must
@@ -63,7 +75,7 @@ class Plugins:
"""
self._add_plugin(plugin, self.file_tracers)
- def add_configurer(self, plugin):
+ def add_configurer(self, plugin: CoveragePlugin) -> None:
"""Add a configuring plugin.
`plugin` is an instance of a third-party plugin class. It must
@@ -72,7 +84,7 @@ class Plugins:
"""
self._add_plugin(plugin, self.configurers)
- def add_dynamic_context(self, plugin):
+ def add_dynamic_context(self, plugin: CoveragePlugin) -> None:
"""Add a dynamic context plugin.
`plugin` is an instance of a third-party plugin class. It must
@@ -81,7 +93,7 @@ class Plugins:
"""
self._add_plugin(plugin, self.context_switchers)
- def add_noop(self, plugin):
+ def add_noop(self, plugin: CoveragePlugin) -> None:
"""Add a plugin that does nothing.
This is only useful for testing the plugin support.
@@ -89,7 +101,11 @@ class Plugins:
"""
self._add_plugin(plugin, None)
- def _add_plugin(self, plugin, specialized):
+ def _add_plugin(
+ self,
+ plugin: CoveragePlugin,
+ specialized: Optional[List[CoveragePlugin]],
+ ) -> None:
"""Add a plugin object.
`plugin` is a :class:`CoveragePlugin` instance to add. `specialized`
@@ -102,7 +118,6 @@ class Plugins:
labelled = LabelledDebug(f"plugin {self.current_module!r}", self.debug)
plugin = DebugPluginWrapper(plugin, labelled)
- # pylint: disable=attribute-defined-outside-init
plugin._coverage_plugin_name = plugin_name
plugin._coverage_enabled = True
self.order.append(plugin)
@@ -110,13 +125,13 @@ class Plugins:
if specialized is not None:
specialized.append(plugin)
- def __bool__(self):
+ def __bool__(self) -> bool:
return bool(self.order)
- def __iter__(self):
+ def __iter__(self) -> Iterator[CoveragePlugin]:
return iter(self.order)
- def get(self, plugin_name):
+ def get(self, plugin_name: str) -> CoveragePlugin:
"""Return a plugin by name."""
return self.names[plugin_name]
@@ -124,20 +139,20 @@ class Plugins:
class LabelledDebug:
"""A Debug writer, but with labels for prepending to the messages."""
- def __init__(self, label, debug, prev_labels=()):
+ def __init__(self, label: str, debug: TDebugCtl, prev_labels: Iterable[str]=()):
self.labels = list(prev_labels) + [label]
self.debug = debug
- def add_label(self, label):
+ def add_label(self, label: str) -> LabelledDebug:
"""Add a label to the writer, and return a new `LabelledDebug`."""
return LabelledDebug(label, self.debug, self.labels)
- def message_prefix(self):
+ def message_prefix(self) -> str:
"""The prefix to use on messages, combining the labels."""
prefixes = self.labels + ['']
return ":\n".join(" "*i+label for i, label in enumerate(prefixes))
- def write(self, message):
+ def write(self, message: str) -> None:
"""Write `message`, but with the labels prepended."""
self.debug.write(f"{self.message_prefix()}{message}")
@@ -145,12 +160,12 @@ class LabelledDebug:
class DebugPluginWrapper(CoveragePlugin):
"""Wrap a plugin, and use debug to report on what it's doing."""
- def __init__(self, plugin, debug):
+ def __init__(self, plugin: CoveragePlugin, debug: LabelledDebug) -> None:
super().__init__()
self.plugin = plugin
self.debug = debug
- def file_tracer(self, filename):
+ def file_tracer(self, filename: str) -> Optional[FileTracer]:
tracer = self.plugin.file_tracer(filename)
self.debug.write(f"file_tracer({filename!r}) --> {tracer!r}")
if tracer:
@@ -158,64 +173,65 @@ class DebugPluginWrapper(CoveragePlugin):
tracer = DebugFileTracerWrapper(tracer, debug)
return tracer
- def file_reporter(self, filename):
+ def file_reporter(self, filename: str) -> Union[FileReporter, str]:
reporter = self.plugin.file_reporter(filename)
+ assert isinstance(reporter, FileReporter)
self.debug.write(f"file_reporter({filename!r}) --> {reporter!r}")
if reporter:
debug = self.debug.add_label(f"file {filename!r}")
reporter = DebugFileReporterWrapper(filename, reporter, debug)
return reporter
- def dynamic_context(self, frame):
+ def dynamic_context(self, frame: FrameType) -> Optional[str]:
context = self.plugin.dynamic_context(frame)
self.debug.write(f"dynamic_context({frame!r}) --> {context!r}")
return context
- def find_executable_files(self, src_dir):
+ def find_executable_files(self, src_dir: str) -> Iterable[str]:
executable_files = self.plugin.find_executable_files(src_dir)
self.debug.write(f"find_executable_files({src_dir!r}) --> {executable_files!r}")
return executable_files
- def configure(self, config):
+ def configure(self, config: TConfigurable) -> None:
self.debug.write(f"configure({config!r})")
self.plugin.configure(config)
- def sys_info(self):
+ def sys_info(self) -> Iterable[Tuple[str, Any]]:
return self.plugin.sys_info()
class DebugFileTracerWrapper(FileTracer):
"""A debugging `FileTracer`."""
- def __init__(self, tracer, debug):
+ def __init__(self, tracer: FileTracer, debug: LabelledDebug) -> None:
self.tracer = tracer
self.debug = debug
- def _show_frame(self, frame):
+ def _show_frame(self, frame: FrameType) -> str:
"""A short string identifying a frame, for debug messages."""
return "%s@%d" % (
os.path.basename(frame.f_code.co_filename),
frame.f_lineno,
)
- def source_filename(self):
+ def source_filename(self) -> str:
sfilename = self.tracer.source_filename()
self.debug.write(f"source_filename() --> {sfilename!r}")
return sfilename
- def has_dynamic_source_filename(self):
+ def has_dynamic_source_filename(self) -> bool:
has = self.tracer.has_dynamic_source_filename()
self.debug.write(f"has_dynamic_source_filename() --> {has!r}")
return has
- def dynamic_source_filename(self, filename, frame):
+ def dynamic_source_filename(self, filename: str, frame: FrameType) -> Optional[str]:
dyn = self.tracer.dynamic_source_filename(filename, frame)
self.debug.write("dynamic_source_filename({!r}, {}) --> {!r}".format(
filename, self._show_frame(frame), dyn,
))
return dyn
- def line_number_range(self, frame):
+ def line_number_range(self, frame: FrameType) -> Tuple[TLineNo, TLineNo]:
pair = self.tracer.line_number_range(frame)
self.debug.write(f"line_number_range({self._show_frame(frame)}) --> {pair!r}")
return pair
@@ -224,57 +240,57 @@ class DebugFileTracerWrapper(FileTracer):
class DebugFileReporterWrapper(FileReporter):
"""A debugging `FileReporter`."""
- def __init__(self, filename, reporter, debug):
+ def __init__(self, filename: str, reporter: FileReporter, debug: LabelledDebug) -> None:
super().__init__(filename)
self.reporter = reporter
self.debug = debug
- def relative_filename(self):
+ def relative_filename(self) -> str:
ret = self.reporter.relative_filename()
self.debug.write(f"relative_filename() --> {ret!r}")
return ret
- def lines(self):
+ def lines(self) -> Set[TLineNo]:
ret = self.reporter.lines()
self.debug.write(f"lines() --> {ret!r}")
return ret
- def excluded_lines(self):
+ def excluded_lines(self) -> Set[TLineNo]:
ret = self.reporter.excluded_lines()
self.debug.write(f"excluded_lines() --> {ret!r}")
return ret
- def translate_lines(self, lines):
+ def translate_lines(self, lines: Iterable[TLineNo]) -> Set[TLineNo]:
ret = self.reporter.translate_lines(lines)
self.debug.write(f"translate_lines({lines!r}) --> {ret!r}")
return ret
- def translate_arcs(self, arcs):
+ def translate_arcs(self, arcs: Iterable[TArc]) -> Set[TArc]:
ret = self.reporter.translate_arcs(arcs)
self.debug.write(f"translate_arcs({arcs!r}) --> {ret!r}")
return ret
- def no_branch_lines(self):
+ def no_branch_lines(self) -> Set[TLineNo]:
ret = self.reporter.no_branch_lines()
self.debug.write(f"no_branch_lines() --> {ret!r}")
return ret
- def exit_counts(self):
+ def exit_counts(self) -> Dict[TLineNo, int]:
ret = self.reporter.exit_counts()
self.debug.write(f"exit_counts() --> {ret!r}")
return ret
- def arcs(self):
+ def arcs(self) -> Set[TArc]:
ret = self.reporter.arcs()
self.debug.write(f"arcs() --> {ret!r}")
return ret
- def source(self):
+ def source(self) -> str:
ret = self.reporter.source()
self.debug.write("source() --> %d chars" % (len(ret),))
return ret
- def source_token_lines(self):
+ def source_token_lines(self) -> TSourceTokenLines:
ret = list(self.reporter.source_token_lines())
self.debug.write("source_token_lines() --> %d tokens" % (len(ret),))
return ret