Fix local wheel cache invalidation#17628
Conversation
Resolves astral-sh#16617 When using `uv run --with path/to/wheel.whl`, rebuilding the wheel file at the same path now properly invalidates the cached environment. Changes: - Include file modification timestamps in cache key for local wheels and source archives - Add `local_distribution_timestamps()` helper to extract mtimes - Exclude directory timestamps to avoid false cache invalidation - Add integration test to verify the fix The cached environment hash now combines both the resolution and local file timestamps, ensuring that rebuilt local wheels are detected and the environment is regenerated.
|
Was this authored by using an LLM? Could you disclose how you decided on this design and iterated on the fix? |
|
I did use LLM tools to iterate through the solution space and draft/validate alternative approaches, but the investigation, design choice, and code changes were mine. My first iteration was to disable venv caching whenever local files/projects were present, but that was too broad for my use case. As a middle ground, I now fold file timestamps for local wheel/source archive files into the env hash, so rebuilding a local wheel at the same path invalidates the cache while keeping caching on for the rest. I’m intentionally not including local project directories yet because a directory’s mtime is a noisy proxy: it can change for incidental file churn (temp files, build outputs, IDE caches, etc.) and may not change for content-only edits. This change only tracks concrete files. If you think it’s worth covering local projects too, I’m happy to discuss other signals (e.g., a targeted file list like pyproject.toml/lockfiles, or content hashing). |
Fixes #16617
Problem
When using
uv run --with path/to/wheel.whl, rebuilding the wheel file doesn't invalidate the cached environment. Users must runuv cache pruneto see changes from a rebuilt wheel.Root Cause
The
CachedEnvironmentcreates a cache key from only the resolution (distribution paths) and interpreter hash. It doesn't account for file modification times of local wheels, so when a file at the same path is modified, the cache key remains unchanged.Solution
Include file modification times (mtime) in the cache hash for local distributions:
local_distribution_timestamps()helper to extract mtimes for local wheels and source archivesrun_with_local_wheel_rebuildto verify the fixChanges
Modified files:
crates/uv/src/commands/project/environment.rs- Core cache logiccrates/uv/tests/it/run.rs- Integration testTesting
Performance Considerations
fs::metadata()call per local file distribution