astral-sh / uv

An extremely fast Python package and project manager, written in Rust.
https://docs.astral.sh/uv
Apache License 2.0
27.66k stars 796 forks source link

`--locked` does not always report an error even when the lockfile needs to be regenerated #9396

Open DetachHead opened 2 days ago

DetachHead commented 2 days ago

environment

note that the project uses pyprojectx so it installs uv automatically

  1. git clone https://github.com/detachhead/basedpyright (commit 6d94c2aca2683aaa1f36e5d1687c6240e239b315)
  2. cd basedpyright
  3. run ./pw uv lock --locked (no error)
  4. delete uv.lock
  5. run ./pw uv lock
  6. run git diff uv.lock
diff --git a/uv.lock b/uv.lock
index aca6ec6ee..f165035b0 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1,8 +1,7 @@
 version = 1
 requires-python = ">=3.8"
 resolution-markers = [
-    "python_full_version < '3.9'",
-    "python_full_version >= '3.9' and python_full_version < '3.11'",
+    "python_full_version < '3.11'",
     "python_full_version == '3.11.*'",
     "python_full_version >= '3.12'",
 ]
@@ -250,8 +249,7 @@ name = "docify"
 version = "1.0.0"
 source = { registry = "https://pypi.org/simple" }
 dependencies = [
-    { name = "libcst", version = "1.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
-    { name = "libcst", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
+    { name = "libcst" },
     { name = "tqdm" },
 ]
 sdist = { url = "https://files.pythonhosted.org/packages/b2/cc/d403e8dbe89826340a18909e0aa26ed917981d41579ba91145e2e1b954c8/docify-1.0.0.tar.gz", hash = "sha256:8d779f8348dd8d46796709c0db7d710cbc6354935d90a727c9ff3ab77b4cd3bf", size = 7186 }
@@ -356,13 +354,10 @@ wheels = [
 name = "libcst"
 version = "1.1.0"
 source = { registry = "https://pypi.org/simple" }
-resolution-markers = [
-    "python_full_version < '3.9'",
-]
 dependencies = [
-    { name = "pyyaml", marker = "python_full_version < '3.9'" },
-    { name = "typing-extensions", marker = "python_full_version < '3.9'" },
-    { name = "typing-inspect", marker = "python_full_version < '3.9'" },
+    { name = "pyyaml" },
+    { name = "typing-extensions" },
+    { name = "typing-inspect" },
 ]

(the diff is larger than this but i only included the first few changes)

FishAlchemist commented 2 days ago

I noticed you mentioned using this. Perhaps some of the comments in this issue(https://github.com/astral-sh/uv/issues/9379#issuecomment-2495472831) can shed some light on your problem. However, since I'm not familiar with dynamic metadata, if that doesn't solve it, we'll have to wait for someone more knowledgeable to explain.

dynamic = ["version"]

However, based on my observations of how UV behaves, the lockfile wouldn't be regenerated if you haven't modified the project metadata. Since there were no modifications, the lock file didn't need updating, so it passed the check.

Edit: If the lock files generated by different UV versions are not necessarily identical, forcing regeneration and then checking for verify seems prone to false positives

DetachHead commented 1 day ago

However, based on my observations of how UV behaves, the lockfile wouldn't be regenerated if you haven't modified the project metadata. Since there were no modifications, the lock file didn't need updating, so it passed the check.

in this case, the metadata had been updated since the lockfile was last generated. specifically, i removed this part from my pyproject.toml because i mistakenly thought it wasn't needed for my project, then i forgot to regenerate the lockfile:

[dependency-groups]
docstubs = [
    # ...
    "libcst>=1.5.0 ; python_version>='3.9'",
    "libcst==1.1.0 ; python_version<'3.9'",
]

in https://github.com/DetachHead/basedpyright/commit/4e58bf7a022ac7c2e7e94a021da5381b0c1c429f

it was only once i regenerated the lockfile a few days later and saw these changes that i realized it was necessary after all, because the uv lock --check in my ci failed to recognize that my lockfile needed to be updated

FishAlchemist commented 1 day ago

@DetachHead Actually, uv sync and uv run will automatically check if the lock file is up-to-date, unless you've used the --frozen flag. So theoretically, as long as you've used them before committing, your lock file should be up-to-date.

uv sync --frozen

Sync without updating the uv.lock file.

Instead of checking if the lockfile is up-to-date, uses the versions in the lockfile as the source of truth. If the lockfile is missing, uv will exit with an error. If the pyproject.toml includes changes to dependencies that have not been included in the lockfile yet, they will not be present in the environment.

May also be set with the UV_FROZEN environment variable.

https://docs.astral.sh/uv/concepts/projects/sync/#checking-if-the-lockfile-is-up-to-date

DetachHead commented 1 day ago

i think it only happens when deleting the lockfile before running uv sync or uv lock again. if the lockfile isn't deleted first, it doesn't seem to regenerate it which would explain why --locked doesn't think there are any changes