Skip to content

Invalidate rewritten pyc files by source hash - #14905

Open
RonnyPfannschmidt wants to merge 3 commits into
pytest-dev:mainfrom
RonnyPfannschmidt:pr11418-checked-hash-pyc
Open

Invalidate rewritten pyc files by source hash#14905
RonnyPfannschmidt wants to merge 3 commits into
pytest-dev:mainfrom
RonnyPfannschmidt:pr11418-checked-hash-pyc

Conversation

@RonnyPfannschmidt

Copy link
Copy Markdown
Member

Supersedes #11418, rebased onto main with @cdce8p's two commits preserved.

Rewritten pycs are invalidated by mtime+size. A checkout gives every source file
a new mtime, so a restored CI cache is thrown away in full and every test module
is rewritten again. This switches them to PEP 552 checked-hash pycs.

The third commit drops the --invalidation-mode option #11418 added and always
writes checked-hash — measured, hashing does not need a timestamp fast path.
500 assert-dense modules (~9 KB each), --collect-only, CPython 3.12:

main this PR
cold, rewrite everything 99.3 s 93.9 s
warm cache 5.85 s 5.96 s
after touching every source 93.8 s 5.96 s

Per file that is ~15 µs to read and hash the source, against ~1.1 ms for a cache
hit that unmarshals the code object anyway and ~110 ms for the rewrite it avoids.

Also fixes #13292: the pyc header records whole seconds only, so an edit made
within one second of the previous one, and of the same size, was invisible.

Notes:

  • _imp.check_hash_based_pycs is not consulted. It governs how the builtin
    import system treats hash-based pycs, and it never sees these.
  • Existing timestamp pycs read as "unsupported flags" and are rewritten once.
    PYTEST_TAG already contains the pytest version, so no two pytest versions
    share a pyc file.
  • Private signatures change: _rewrite_test, _write_pyc and _write_pyc_fp
    no longer take or return an os.stat_result; the source stat is gone from
    both the read and the write path.

cdce8p and others added 3 commits August 18, 2026 23:04
Drop the --invalidation-mode option and write checked-hash pycs
unconditionally.

The option existed because hashing was assumed to cost enough to want a
timestamp fast path. Measured, it does not: reading the source and hashing it
costs ~15us per file, against ~1.1ms for a cache hit that has to unmarshal the
code object anyway, and ~110ms for the rewrite the cache avoids.

With one format there is no reason to consult _imp.check_hash_based_pycs
either. That is a private CPython attribute governing how the *builtin* import
system treats hash based pycs, and it never sees the pycs written here.

The source stat disappears from both paths: _rewrite_test no longer needs it
for the header, and _read_pyc reads the source instead of stat'ing it.

Also fixes pytest-dev#13292, where an edit within one mtime second of the previous one
was invisible to the timestamp comparison.
@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided (automation) changelog entry is part of PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect pyc cache loaded when test file is updated in short time

2 participants