summaryrefslogtreecommitdiff
path: root/coverage/types.py
diff options
context:
space:
mode:
Diffstat (limited to 'coverage/types.py')
-rw-r--r--coverage/types.py99
1 files changed, 92 insertions, 7 deletions
diff --git a/coverage/types.py b/coverage/types.py
index 79cf5d3a..ddfcdb81 100644
--- a/coverage/types.py
+++ b/coverage/types.py
@@ -5,19 +5,101 @@
Types for use throughout coverage.py.
"""
-from types import ModuleType
+from __future__ import annotations
+
+from types import FrameType, ModuleType
from typing import (
- Any, Dict, Iterable, List, Optional, Tuple, Union,
+ Any, Callable, Dict, Iterable, List, Mapping, Optional, Set, Tuple, Union,
TYPE_CHECKING,
)
if TYPE_CHECKING:
# Protocol is new in 3.8. PYVERSIONS
from typing import Protocol
+
+ from coverage.plugin import FileTracer
+
else:
class Protocol: # pylint: disable=missing-class-docstring
pass
+## Python tracing
+
+class TTraceFn(Protocol):
+ """A Python trace function."""
+ def __call__(
+ self,
+ frame: FrameType,
+ event: str,
+ arg: Any,
+ lineno: Optional[int]=None # Our own twist, see collector.py
+ ) -> TTraceFn:
+ ...
+
+## 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: Optional[str]
+ trace: bool
+ reason: str
+ file_tracer: Optional[FileTracer]
+ 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).
+
+TTraceData = Union[
+ Dict[str, Set[TLineNo]],
+ Dict[str, Set[TArc]],
+ Dict[str, Set[int]],
+]
+
+class TTracer(Protocol):
+ """Either CTracer or PyTracer."""
+
+ data: TTraceData
+ trace_arcs: bool
+ should_trace: Callable[[str, FrameType], TFileDisposition]
+ should_trace_cache: Mapping[str, Optional[TFileDisposition]]
+ should_start_context: Optional[Callable[[FrameType], Optional[str]]]
+ switch_context: Optional[Callable[[Optional[str]], None]]
+ warn: TWarnFn
+
+ def __init__(self) -> None:
+ ...
+
+ def start(self) -> TTraceFn:
+ """Start this tracer, returning a trace function."""
+
+ 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) -> Optional[Dict[str, int]]:
+ """Return a dictionary of statistics, or None."""
+
+## Coverage
+
# Many places use kwargs as Coverage kwargs.
TCovKwargs = Any
@@ -56,15 +138,18 @@ class TConfigurable(Protocol):
## Parsing
-# Line numbers are pervasive enough that they deserve their own type.
-TLineNo = int
-
-TArc = Tuple[TLineNo, TLineNo]
-
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):