"""Check whether changed source lines were executed in Coverage.py data."""
from __future__ import annotations
from pathlib import Path
def _measured_path_for_source(data: object, repo_root: Path, source_rel_path: str) -> str | None:
target = (repo_root / source_rel_path).resolve()
measured_files = getattr(data, "measured_files", None)
if measured_files is None:
return None
for measured in measured_files():
if Path(measured).resolve() == target:
return measured
return None
def symbol_lines_covered_in_data(
repo_root: Path,
source_rel_path: str,
symbol: str,
lines: set[int],
coverage_path: Path,
) -> bool:
"""Return True when any *lines* was executed (any coverage context).
Context may be a pytest node id, empty string (import-time), or conftest.
*symbol* is part of the public API for call-site clarity.
"""
_ = symbol
if not lines or not coverage_path.is_file():
return False
from coverage.data import CoverageData
from coverage.misc import CoverageException
data = CoverageData(str(coverage_path))
try:
data.read()
except (CoverageException, OSError):
return False
measured = _measured_path_for_source(data, repo_root, source_rel_path)
if measured is None:
return False
executed_lines: set[int] = set()
lines_fn = getattr(data, "lines", None)
if lines_fn is not None:
executed_lines = set(lines_fn(measured) or ())
ctxmap = data.contexts_by_lineno(measured)
for line_no in lines:
if line_no in executed_lines:
return True
if ctxmap and ctxmap.get(line_no):
return True
return False