Description
Summary
When developing with uv
, we often begin by depending on a dev release of a library (e.g. ~=1.0.0.dev0
). Once the changes are approved and that dev version is promoted to a stable release (e.g. 1.0.0
), we update the constraint in pyproject.toml
to ~=1.0
and run uv lock
.
However, the lockfile continues to contain the previously locked dev version unless we explicitly pass -P
, even though it no longer matches the new constraint.
Expected Behavior
uv lock
should detect that the current dev version no longer satisfies the new constraint and automatically resolve to the latest matching stable version (1.0.0
), without requiring -P foo
.
Possible Improvements
- Automatically replace prerelease/dev versions in the lockfile when they no longer satisfy the updated constraint.
- Emit a warning when a prerelease version is locked but no prerelease is permitted by
pyproject.toml
. - Support a pre-release hook that checks for this situation and can enforce clean production locks.
Why It Matters
This workflow — developing against a dev version, then locking to a stable release — is common in CI/CD pipelines and collaborative team workflows.
Without automatic resolution or feedback, it's easy to accidentally retain prerelease dependencies in the lockfile even after bumping the constraint to a stable track.
Example
Example
- Initial state:
# pyproject.toml
dependencies = ["foo ~=1.0.0.dev0"]
uv lock
Lockfile result:
foo==1.0.0.dev0
- Later, we update to:
# pyproject.toml
dependencies = ["foo ~=1.0"]
But after running:
uv lock
The lockfile still incorrectly contains:
foo==1.0.0.dev0
even though the latest valid version is 1.0.0
.