Context: a Python CLI whose exec subcommand calls os.execvpe; the tests run it as a subprocess. Without patches, every line from the subprocess shows as missed. With patch=subprocess only, the lines before exec still go missing, because execvpe replaces the process before coverage's atexit save. patch=execv fixes that by saving data before exec.
Problems (coverage 7.13.5, tox 4.64):
- coverage/patch.py
_patch_execv:if env.WINDOWS: raise CoverageException("patch=execv isn't supported yet on Windows."). With a static config, the whole Windows CI job fails. - Once patch=subprocess is on,
omit = ["pkg/tests/*"]no longer matches inside children started with cwd=tmp_path, so tests/ and vendored code leak into the report at 0-17%.
Fix (EXECV is a placeholder; use a more specific variable name in real configs):
[tool.coverage.run]
omit = ["*/pkg/tests/*", "*/pkg/_vendor/*"]
patch = ["subprocess", "${EXECV-subprocess}"][testenv]
set_env =
EXECV = execv; sys_platform != 'win32'Notes:
- coverage expands env vars inside TOML list items (quoted strings only). Checked: config.patch was ['subprocess','subprocess'] with the variable unset and ['subprocess','execv'] with it set.
apply_patchesiteratessorted(set(config.patch)), so the duplicate is harmless. - tox 4 INI set_env supports PEP 508 markers;
tox config -e py312 -k set_envshows the variable only when the marker is true. - Pin
coverage>=7.10:[run] patchwas added in 7.10 (https://coverage.readthedocs.io/en/latest/config.html). - Children also get the config through COVERAGE_PROCESS_CONFIG, and parallel data files landed next to the parent's data file.
Result: the exec block and the console-script __main__ went from 0% to covered. CI on Linux, Mac and Windows was green.