Skip to content
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

uv add should use ^ instead of >= when adding dependencies to pyproject.toml #10247

Closed
kishaningithub opened this issue Dec 31, 2024 · 7 comments
Labels
duplicate This issue or pull request already exists

Comments

@kishaningithub
Copy link

To add / remove dependencies i use the uv add and uv remove commands and i prefer not to edit pyproject.toml manually.

When i do something like uv add requests i see the following addition in pyproject.toml

dependencies = [
    "requests>=2.32.3"
]

The >= looks super scary as it semantically means my project will not break even if requests releases a major version. Yes, i know there is a uv.lock file to ensure reproducible builds but i prefer the following when i do uv add requests

dependencies = [
    "requests>=2.32.3,<3"
]

I believe poetry on several other semver tools use something like ^2.32.3 which is basically the equivalent of >=2.32.3,<3

@zanieb
Copy link
Member

zanieb commented Dec 31, 2024

Loosely a duplicate of #6783

There's a very strong argument for not including upper bounds when publishing libraries. I think in applications, an upper bound can be nice. There is further discussion linked in the referenced issue.

@zanieb zanieb added the duplicate This issue or pull request already exists label Dec 31, 2024
@kishaningithub
Copy link
Author

There's a very strong argument for not including upper bounds when publishing libraries.

@zanieb Can you point me to this? I am unable to find it

@charliermarsh
Copy link
Member

https://iscinumpy.dev/post/bound-version-constraints/

@zanieb
Copy link
Member

zanieb commented Dec 31, 2024

And more, at https://github.com/zanieb/poetry-relax?tab=readme-ov-file#references

@woutervh
Copy link

woutervh commented Jan 1, 2025

This caret-notation, made popular by poetry, is one of the most diabolical anti-patterns in the python-world.
Dependency-hell can be a pain. A fake dependency-hell is even worse.

It also conflates the notions of abstract and concrete dependencies.

  • Abstract dependencies are the toplevel direct dependencies we specify in pyproject.toml
  • concrete dependencies is the list all required packages with a concrete version-number need to create a reproducible build, aka lock-files.

Also a major new release does not mean "guaranteed backward incompatibility".
I've seen deployed projects break on dependencies with new major releases, minor releases, and not even rarely, patch-releases.
To check compatibililty use your own test-suite and don't rely on a vague external semantic version-number.

The >= looks super scary as it semantically means my project will not break even if requests releases a major version.

That is not what it means.
It means that the code is intended to be working on newer versions, even if those version don't exist yet.
And if it doesn't work, it will be considered a bug that should be fixed.

But how can you test this new major release, if that packages flat-out refuses to install in your venv?
uv's capability to override package-depencies has already been a great use for me, poetry does not even have an equivalent.

Specifying minimum-version on the other hand, means that the code likely does to work and there is no intention to fix that.

Try to read it like "intended to support"

If your package uses newer language-constructs introduced in python3.10, then use

python = ">3.10"

Only specify an upper bound, it you don't intend to support 3.11.

python = ">3.10<3.11"

If your package uses python2.7, and you don't the any intention to support python 3, use

python = ">=2.7,<3"

I never liked this caret notation, as the mathematical meaning is not intuitively clear:

python = "^2.7"

@woutervh
Copy link

woutervh commented Jan 1, 2025

I don't make the distinction between a python-library or a python-application, as long as there is a lock-file.
IMHO the distinction comes from not properly packaging applications.

For me an application is

  • a python-package
  • config-file(s)
  • entry-point to execute/start

In scripts with inline metadata, distributed without a lock-file, the upper bounds make sense.

@yakMM
Copy link

yakMM commented Jan 1, 2025

I agree the default lower bound constraint is enough for library.

I also think there is value in adding an option like --save-exact to bind the latest version (useful for applications and scripts)

@zanieb zanieb closed this as not planned Won't fix, can't repro, duplicate, stale Jan 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

5 participants