-
Notifications
You must be signed in to change notification settings - Fork 964
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lock files don't mesh with dynamic package version info #7533
Comments
@hynek have you seen |
I have while searching this bug tracker, but I couldn't find a way for it to affect From the documentation (and its name 🤓) I've gathered it's mostly about how caching, not about locking? And TBH it sounds to me as if adding git as a git key, I'm actually adding cache busting. |
I think you could pass [tool.uv]
upgrade-package = ["attrs"] But there's sort of an infinite loop here, right? Since every time you commit the lockfile, it will be outdated. So you then re-lock, and commit again, etc. I don't know how to solve this holistically. We could omit versions for editables, maybe? Or even, write "dynamic" or something for the version, for packages that have dynamic versions? |
Yeah that's what I meant in my last sentence, but I'm always assuming Chesterton's Fence. :) Setting it to |
I too have this problem. I generally subscribe to the philosophy that I use a VCS for versioning, thus what is in the VSC repo shouldn't track it's own version because that's what I'm using the VCS for. Said another way, at best a version tracked within repo is imperfect for exactly the reasons described above about how you can't update a version from a commit without making another commit, i.e., a new version. I'd love to understand the rationale behind storing this version in the lock file. Can anyone elaborate on that? |
We are also facing a similar problem over at cda-tum/mqt-core#706 where we use renovate to keep the |
This problem is not only for dynamic versioning. We have a release-please workflow, which will create a PR for the next release. This will update the pyproject.toml version correctly but of course does not know about the uv.lock version. |
As I mentioned in ttps://github.com//issues/7994 I use As a workaround, I also added |
I've just encountered this. We are also using release-please and uv in an internal project, after a release then the surprise is that the uv.lock was outdated. Ours plans were to add uv to https://github.com/timescale/pgai but since we are already using release-please, we are hesitant due to this issue. |
While the setuptools-scm case seems difficult to solve, I think another common reason1 a dynamic version is used is when the version is statically defined but not in
What I expected: version = 1
requires-python = ">=3.12"
[[package]]
name = "mpypkg"
-version = "1.0"
+version = "1.1"
source = { editable = "." } What happened: uv.lock still has I've also tried The version doesn't change until I do an unrelated
Footnotes
|
We can fix this, but I still strongly recommend against setting the version dynamically like that. |
Hi @charliermarsh, you mention "inherent incompatibility of lock files and VCS-based versioning" , but you also mentioned:
To me the above workaround seems good enough, specially if it is controlled by an opt-in configuration (e.g. Is there any fundamental problem with this approach? |
my use case is that I use |
@charliermarsh Out of curiosity, why? |
I just discovered this issue with the recent release 0.5.0. Using --locked when syncing the project makes everything fails. I have a dynamic version based on git tags, and when we release we tag our repository. So the lock file can be outdated without any code change. I think excluding editable dependencies in the lock file could be a good workaround. Or we can also write "dynamic" as a version. By the way I will check what tools like poetry for example are doing in this use case. By the way I would suggest to list it in the breaking changes of the release Thanks !!! Edit: Forgot to mention, I was wondering if you already have some implementation ideas, I totally volunteer to work on this if needed. I will try a draft pull-request on my side for fun |
If references or opinion articles exist around this topic, they are few in number. I think a few on this issue would be interested in wider discussion around this. PEP 621 introduced toml metadata, and as of writing the official specification still allows It's a pretty standard paradigm (see hatch-vcs, setuptools-scm, poetry-dynamic-versioning) for single project repos where versioning, point release branches, development builds, etc. are all managed and controlled via VCS change control. Whilst alternatives exist for separating static versions (such as
My expectation for the project package that has a dynamic version ( It's worth noting that although version is defined dynamically in source control, builds of the package provide the version statically: ❯ ls -1 dist/*
dist/mypackage-0.5.0.dev5+g5d056c1-py3-none-any.whl
dist/mypackage-0.5.0.dev5+g5d056c1.tar.gz
❯ unzip -p dist/*.whl '*.dist-info/METADATA' | grep -E '^Version: '
Version: 0.5.0.dev5+g5d056c1
❯ tar -Oxf dist/*.tar.gz '*.egg-info/PKG-INFO' | grep -E '^Version: '
Version: 0.5.0.dev5+g5d056c1 |
This is just my personal opinion! Dynamic metadata makes a number of things more complicated than they need to be. I understand the use-case for scm versioning, but in my opinion using dynamic metadata to read a version from |
Unfortunately it's not super simple -- it breaks the fundamental assumption that packages have versions, so we have to take that into account everywhere. |
Yes this is what I saw this week-end when I was trying to contribute on this 🥲 Thanks! |
Not exactly, I don't think. The package always DOES have a version. It's just that the version may change outside of uv's immediate notice. Perhaps it would be fine if That said, I feel like a cleaner solution would be to omit the main package from |
By the way, this can be inverted and made more standard-compliant while doing so by putting something like this into your def __getattr__(name: str) -> str:
if name != "__version__":
msg = f"module {__name__} has no attribute {name}"
raise AttributeError(msg)
from importlib.metadata import version
return version("YOUR-PACKAGE") You get static metadata with no duplication. |
I have the same pain point and would like to share how many projects in the wild do Git based versioning for your information.
|
add to that:
|
I think #8867 released in This is textbook Hyrum's Law 😆 To share on the SCM versioning debate, I use |
Sorry to pipe in on a largely completed debate but I have one idea to put. My issue here seems the same as many other users:
Changing any one of these links could fix the issue. I think most of the discussion has been about 1 and 2. That is, either moving away from dynamic versioning or changing how lock files work for local packages. However, a simpler resolution might be via step 3? If uv were to allow users to check that lock files are up to date apart from the versions of any current workspace packages that have dynamic versions then the current workflow would be able to continue. Effectively this returns to the workflow of the pre 0.5.0 uv, while still correctly updating the lock file (and re-installing the package). I would expect this would catch most of the current use cases for This could work by adding an option to |
I think the solution here will ultimately be to stop storing versions for source trees (either entirely, or when dynamic -- I prefer doing so entirely, and not based on whether it's dynamic). I just want PEP 751 to play out a little more before I make any change. |
(Once we have clarity on what we want to do, I'll prioritize the change.) |
As a temporary kind of hacky semi-workaround, I am using In theory, the user could still get around this by modifying both the It protects against a situation where a dependency gets declared in My plan is to get my organization to stop using dynamic versioning in packages... |
We use a
and then, when linting:
This lets us at least avoid recording the current dynamic version in the lock file. |
Just checking- is there any way to use dynamic versioning and build with GitHub Actions while also including I haven't been able to get it working, and I'm not sure whether this is a problem with actions/checkout, with hatch-vcs, with setuptools-scm or with uv. I can run The only way that I can find to prevent this from happening is removing I'd love to know if there's something I'm missing, and it's possible to use |
@thcrt This probably isn't exactly what you're looking for, but I've found this works: https://gist.github.com/nathanjmcdougall/42135563c719cfda59a1de317da5116b Note that this deliberately avoids running |
@nathanjmcdougall Incredible. You are a saint (and a fellow Kiwi!) Genuinely, thank you so much, this has been a major headache for me in two different projects. I imagine that not running Thank you so much again. |
Since PEP 751 and therefore a holistic solution within uv looks like it will take some more time, here is my work-around to avoid the Instead of running
I take care to only commit the modified tasks:
dynamic-version:
desc: replace next line in uv.lock with dynamic version if previous line matches name of our package, see https://stackoverflow.com/questions/18620153/find-matching-text-and-replace-next-line/18620241#comment76950756_18620241
cmds:
- sed -i -e '/myapp/ {' -e 'n; s/.*/version = \"0.0+dynamic\"/' -e '}' uv.lock
sync:
desc: runs a uv sync followed by resetting the package version to dynamic
cmds:
- uv sync
- task: dynamic-version
run:
desc: runs myapp
cmds:
- task: sync
- uv run --frozen myentrypoint
For the moment, this serves me well. If there are any unintentional side-effects, I'm eager to learn about them |
Would it be possible to allow for this behaviour?
|
from @charliermarsh:
Narrowing things down, this specific issue is only when you are trying to pin the version of the repository you are currently working in. No other dependency matters, editable, dynamic, or not, since Furthermore, you don't need to mark the version in So I propose something like
Side Note: Further Spooky Behavior (extra notes I'm writing for if I come back to this convo)nevermind about side note, its just #6860 + not knowing when |
If you're using Eg, I've added this to my # `uv` pins the version in the `uv.lock` file, but this leads to churn with each commit when using
# `hatch-vcs`. Instead, we can override the version to force stability until [1] is resolved.
#
# 1: https://github.com/astral-sh/uv/issues/7533
export SETUPTOOLS_SCM_PRETEND_VERSION="0.1.0" and then all Seems to be working fine, but I'm not sure what other ramifications it might have - at the least, it probably doesn't play as well with projects with non-python (ie: built) dependencies. edit: ah, I see |
We also want to automate the updating of the lockfile, but I think this also helps make sure that they're always in sync before merging, in case someone updates the dependency locally. The version overloading is related to this issue in uv, which is that it doesn't have an official mechanism to support dynamic versions: astral-sh/uv#7533
Note that neither setting package = false in [tool.uv] nor using --no-install-project addresses the issue, because it seems like the project is still included in uv.lock regardless. |
Here's a temporary fix for those using Copy the following code block, paste it into a file named # hatch_build.py
"""Hatchling custom metadata hook.
Temporary fix until Astral decides how to handle dynamic project versions
in the uv.lock file.
See https://github.com/astral-sh/uv/issues/7533
To enable, place this file next to and add the following line to the
pyproject.toml file:
[tool.hatch.metadata.hooks.custom]
To override, set SETUPTOOLS_SCM_PRETEND_VERSION environment variable to the
desired version before building, or set CI=1 (already set in GitHub actions)
to let hatch-vcs (using setuptools-scm) determine the version from the git tag.
"""
import os
from hatchling.metadata.plugin.interface import MetadataHookInterface
if not os.environ.get("SETUPTOOLS_SCM_PRETEND_VERSION") and not os.environ.get("CI"):
os.environ["SETUPTOOLS_SCM_PRETEND_VERSION"] = "0.dev0+local"
class CustomMetadataHook(MetadataHookInterface):
def update(self, metadata: dict) -> None:
pass This uses the Of course, feel free to set the default version to something that fits your project. |
The solution here is what should be preferred for |
`env SETUPTOOLS_SCM_PRETEND_VERSION=99.0 uv lock --upgrade` as per astral-sh/uv#7533 (comment)
Since tox-uv just shipped lock files, I took a stab at moving attrs to a fully-locked dev environment.
Here's the experiment PR: python-attrs/attrs#1349
A problem I've run into is that packages often use dynamic packaging data that is based on git metadata (setuptools-scm, hatch-vcs, etc). As such, attrs's package version changes after every commit, which allows us to upload to test PyPI and continually verify our package. See, for example, https://test.pypi.org/project/attrs/24.2.1.dev19/
Unfortunately the current project gets locked like this:
Which means it's outdated after each commit, because every commit increments the number behind
dev
.Is there a way around this that I've missed? If not, could there be built one? 😇 AFAICT, this is currently the biggest blocker for FOSS use from uv's side. I'm also not sure what the point of that version lock is in the first place for the current, editable project? But that's a topic for another day. :)
The text was updated successfully, but these errors were encountered: