Skip to content

🐛 fix(ci): map absolute coverage paths#651

Merged
gaborbernat merged 1 commit into
mainfrom
fix/coverage-path-remapping
Jul 14, 2026
Merged

🐛 fix(ci): map absolute coverage paths#651
gaborbernat merged 1 commit into
mainfrom
fix/coverage-path-remapping

Conversation

@gaborbernat

Copy link
Copy Markdown
Member

Combined coverage cannot read artifacts from another runner because the current aliases start at a relative .tox directory. The failure affects the current main workflow and blocks otherwise successful pull requests.

The aliases now match the tox installation suffix after any absolute checkout root. Coverage maps Unix lib/<python>/site-packages and Windows Lib/site-packages paths back to src, following the coverage.py path remapping contract.

Cross-platform coverage jobs store installed package paths under each runner
checkout. Relative aliases leave macOS paths unresolved when Ubuntu combines
the artifacts.

Match the tox installation suffix after any checkout root so coverage can map
Unix and Windows artifacts to the source tree.
@gaborbernat gaborbernat self-assigned this Jul 14, 2026
@gaborbernat gaborbernat marked this pull request as ready for review July 14, 2026 04:40
@gaborbernat gaborbernat merged commit b2289d3 into main Jul 14, 2026
36 checks passed
@gaborbernat gaborbernat deleted the fix/coverage-path-remapping branch July 14, 2026 05:15
gaborbernat added a commit that referenced this pull request Jul 14, 2026
The `close_failure` fixture patches `filelock._api.os.close`, and
`filelock._api.os` is the `os` module, so mocking it swaps `os.close`
for the whole process. While a test holds the mock, any `os.close` in
the process raises `OSError`, including the ones a garbage collector
runs inside a finalizer.

CPython hides this. Refcounting reclaims lock objects as soon as a test
drops them, outside the window the mock covers. PyPy reclaims them
whenever a cycle runs, so a collection can land inside that window.
`BaseFileLock.__del__` then force-releases a lock an earlier test left
held, its close hits the mock, and the `OSError` escapes the finalizer
as an unraisable exception. Pytest reports it against whichever test
happens to be running, which is how the `pypy3.11` job on #654 failed
inside `test_context_group_handles_deep_body_context`, a test that
touches none of this.

The mock now raises for the descriptor the test captured through
`on_acquired` and hands every other descriptor to the real `os.close`.
The lock under test still fails to close, so the `close_error_policy`
cases keep their meaning, and a collector running a finalizer mid-test
stops tripping over an unrelated fd.

This also drops `docs/changelog/coverage-path-remapping.bugfix.rst`.
#651 changed how CI maps coverage paths across tox environments, which
no user of the library can observe, and the slug filename does not
render through the `:pr:` role that `issue_format` applies to every
fragment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant