1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
"""
Types for use throughout coverage.py.
"""
from __future__ import annotations
import os
import pathlib
from types import FrameType, ModuleType
from typing import (
Any, Callable, Dict, Iterable, List, Mapping, Optional, Protocol,
Set, Tuple, Type, Union, TYPE_CHECKING,
)
if TYPE_CHECKING:
from coverage.plugin import FileTracer
AnyCallable = Callable[..., Any]
## File paths
# For arguments that are file paths:
if TYPE_CHECKING:
FilePath = Union[str, os.PathLike[str]]
else:
# PathLike < python3.9 doesn't support subscription
FilePath = Union[str, os.PathLike]
# For testing FilePath arguments
FilePathClasses = [str, pathlib.Path]
FilePathType = Union[Type[str], Type[pathlib.Path]]
## Python tracing
class TTraceFn(Protocol):
"""A Python trace function."""
def __call__(
self,
frame: FrameType,
event: str,
arg: Any,
lineno: TLineNo | None = None, # Our own twist, see collector.py
) -> TTraceFn | None:
...
## Coverage.py tracing
# Line numbers are pervasive enough that they deserve their own type.
TLineNo = int
TArc = Tuple[TLineNo, TLineNo]
class TFileDisposition(Protocol):
"""A simple value type for recording what to do with a file."""
original_filename: str
canonical_filename: str
source_filename: str | None
trace: bool
reason: str
file_tracer: FileTracer | None
has_dynamic_filename: bool
# When collecting data, we use a dictionary with a few possible shapes. The
# keys are always file names.
# - If measuring line coverage, the values are sets of line numbers.
# - If measuring arcs in the Python tracer, the values are sets of arcs (pairs
# of line numbers).
# - If measuring arcs in the C tracer, the values are sets of packed arcs (two
# line numbers combined into one integer).
TTraceFileData = Union[Set[TLineNo], Set[TArc], Set[int]]
TTraceData = Dict[str, TTraceFileData]
class TracerCore(Protocol):
"""Anything that can report on Python execution."""
data: TTraceData
trace_arcs: bool
should_trace: Callable[[str, FrameType], TFileDisposition]
should_trace_cache: Mapping[str, TFileDisposition | None]
should_start_context: Callable[[FrameType], str | None] | None
switch_context: Callable[[str | None], None] | None
lock_data: Callable[[], None]
unlock_data: Callable[[], None]
warn: TWarnFn
def __init__(self) -> None:
...
def start(self) -> TTraceFn | None:
"""Start this tracer, return a trace function if based on sys.settrace."""
def stop(self) -> None:
"""Stop this tracer."""
def activity(self) -> bool:
"""Has there been any activity?"""
def reset_activity(self) -> None:
"""Reset the activity() flag."""
def get_stats(self) -> dict[str, int] | None:
"""Return a dictionary of statistics, or None."""
## Coverage
# Many places use kwargs as Coverage kwargs.
TCovKwargs = Any
## Configuration
# One value read from a config file.
TConfigValueIn = Optional[Union[bool, int, float, str, Iterable[str]]]
TConfigValueOut = Optional[Union[bool, int, float, str, List[str]]]
# An entire config section, mapping option names to values.
TConfigSectionIn = Mapping[str, TConfigValueIn]
TConfigSectionOut = Mapping[str, TConfigValueOut]
class TConfigurable(Protocol):
"""Something that can proxy to the coverage configuration settings."""
def get_option(self, option_name: str) -> TConfigValueOut | None:
"""Get an option from the configuration.
`option_name` is a colon-separated string indicating the section and
option name. For example, the ``branch`` option in the ``[run]``
section of the config file would be indicated with `"run:branch"`.
Returns the value of the option.
"""
def set_option(self, option_name: str, value: TConfigValueIn | TConfigSectionIn) -> None:
"""Set an option in the configuration.
`option_name` is a colon-separated string indicating the section and
option name. For example, the ``branch`` option in the ``[run]``
section of the config file would be indicated with `"run:branch"`.
`value` is the new value for the option.
"""
class TPluginConfig(Protocol):
"""Something that can provide options to a plugin."""
def get_plugin_options(self, plugin: str) -> TConfigSectionOut:
"""Get the options for a plugin."""
## Parsing
TMorf = Union[ModuleType, str]
TSourceTokenLines = Iterable[List[Tuple[str, str]]]
## Plugins
class TPlugin(Protocol):
"""What all plugins have in common."""
_coverage_plugin_name: str
_coverage_enabled: bool
## Debugging
class TWarnFn(Protocol):
"""A callable warn() function."""
def __call__(self, msg: str, slug: str | None = None, once: bool = False) -> None:
...
class TDebugCtl(Protocol):
"""A DebugControl object, or something like it."""
def should(self, option: str) -> bool:
"""Decide whether to output debug information in category `option`."""
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."""
|