| ▲ | the_mitsuhiko 3 hours ago |
| > Note the lack of an upper bound Since uv needs a singular resolution that's entirely intentional. In npm you can install diverging resolutions for different parts of the tree but that is not an option with Python. I had to make the same decision in Rye and there is just no better solution here. If an upper bound were to be supplied you would end up with trees that can no longer resolve in practice. Some package ecosystems in Python even went as far as publishing overrides for old packages that got published with assumed upper bounds that ended up wrong. Don't forget that you cannot know today if your package is going to be compatible or incompatible with a not yet released package. |
|
| ▲ | kjmr 41 minutes ago | parent | next [-] |
| The lack of an upper bound in pyproject.toml isn’t the real problem. The real problem is that `uv lock —-upgrade` does a wholesale upgrade of everything without an upper bound. If there was a way to upgrade packages without updating the major version, this command would be a lot safer to run. |
|
| ▲ | thayne an hour ago | parent | prev | next [-] |
| Personally, I'd rather get an error from uv that packages aren't compatible when I run update, with a way to override that if needed, than get an error at runtime that may be difficult to track down to incompatible versions. |
|
| ▲ | kjmr 28 minutes ago | parent | prev | next [-] |
| What you’re saying makes sense for library authors. But when I make a website and I depend on a bunch of packages, that’s where I want to be safe when upgrading and I want that upper bound. The —-bound flag really helps, but is one more thing to type and remember. Maybe when uv knows the project isn’t a library it could default to upper bounds? |
|
| ▲ | saghm an hour ago | parent | prev | next [-] |
| As much as uv has improved the situation, I have to imagine that there's plenty of stuff like this that fundamentally is impossible to address via tooling. It's incredible how much the situation seems to have improved compared to before it was around, but it seems like things might never be totally good without the ecosystem as a whole making some breaking changes, and I'm guessing after the whole 2->3 situation there's not much appetite for something like that any time soon. |
|
| ▲ | 2 hours ago | parent | prev | next [-] |
| [deleted] |
|
| ▲ | jim33442 2 hours ago | parent | prev | next [-] |
| Also it doesn't even matter because the real way to use both uv and npm is to switch everything to = and only update manually, rather than trusting non-major updates not to break anything |
| |
| ▲ | rtpg an hour ago | parent | next [-] | | The distinction here is on application vs library, IMO. I basically agree that applications, as a default, `==`'ing everything makes sense. For libraries, having loose bounds might mean that users upgrade and hit issues due to a lack of an upper bound. But given how lightly maintained most projects are, the risk of upper bounds simply getting in the way are higher IMO. (Put an upper bound if you know of an issue, of course!) It's a bit tricky though. Django deps in particular tend to want to explicitly check support for newer versions, but the more I think about it the more I ask myself if this is the right strategy | |
| ▲ | elyobo an hour ago | parent | prev | next [-] | | non major updates in the npm ecosystem are pretty reliable in my experience; my much more limited python experience suggests that semver is much less respected on that side of the fence | | |
| ▲ | jim33442 36 minutes ago | parent [-] | | I've noticed it's better in npm than in python, but still been burned enough times |
| |
| ▲ | galangalalgol 2 hours ago | parent | prev | next [-] | | Isn't there a lock file for that? I'm mostly a rust dev, but I thought I saw a lock file in a uv project I was vibe coding | | |
| ▲ | jim33442 2 hours ago | parent [-] | | The lockfile does more than just pin the versions of your immediate deps, so one might reset it for some other reason. Or you might want to update individual packages without caring about the specific commands for that, so you edit the package file, delete lockfile, reinstall. | | |
| ▲ | galangalalgol 3 minutes ago | parent [-] | | But if I use uv sync and the package I want I don't ever need to toss the whole file right. In rust I'd never sign off on a mr that just randomly updated lots of deps with no reason tied to the issue they were resolving |
|
| |
| ▲ | mrtranscendence 2 hours ago | parent | prev | next [-] | | That doesn't work for library projects, though. | | |
| ▲ | jim33442 2 hours ago | parent [-] | | Yeah that's true. I can't imagine someone making a lib would just install deps without specifying version ranges, but maybe they do. |
| |
| ▲ | chippiewill 2 hours ago | parent | prev | next [-] | | But that's why you have a lockfile? | |
| ▲ | jimbokun an hour ago | parent | prev [-] | | Or to introduce a major exploit. |
|
|
| ▲ | wrs 2 hours ago | parent | prev | next [-] |
| The entire purpose of semver is to give you a way to resolve that conundrum. New major version = assume it's incompatible. I mean, it may not actually work, but that's what it's for. |
| |
| ▲ | kibwen 2 hours ago | parent | next [-] | | The use or adherence to semver isn't the problem here. As you say, if a package follows semver, it's easy enough for the package managers to automatically update to newer compatible versions. The problem is when you want to have two different incompatible versions of the same package `foo` in the same program, because then you have to figure out what `import foo` means. You might say "just don't do that", but that package could be an indirect dependency of several of your direct dependencies. Some languages handle this natively, e.g. in Rust it just works if you have multiple versions of the same library in different parts of your dependency tree (and you'll get a compilation error if you try to pass a type from one version into a function of an incompatible version). But Python does not handle this use case very well. | | |
| ▲ | skeledrew 27 minutes ago | parent [-] | | > Python does not handle this use case very well I solved this issue a few months ago. Created a tool that essentially allows the use of multiple envs at once, with their own versions of packages at any level. |
| |
| ▲ | saghm an hour ago | parent | prev | next [-] | | > The entire purpose of semver is to give you a way to resolve that conundrum. New major version = assume it's incompatible. I'm not sure I'd agree with that characterization. The point of semver is that you can assume that certain types of bumps won't include certain types of changes, not that you assume that the types of changes that can happen in a type of bump will happen. A major version bump not breaking anything is completely valid semver, and breaking one function (which plenty of users might not use, or might use in a way that doesn't get broken) in an API with thousands is still technically only valid in a major version bump (outside of specific exceptions like the major version being 0). It's a subtle difference, and I'm optimistic that it's something you understand, but misunderstandings of semver seem so common that I can't help but feel like precision when discussing it is important. I've encountered so many smart people who misunderstand aspects of semver (and not just minutia like "what constraints are there on tags after the version numbers"), and almost all of them seemed to have stemmed from people learning a few of basic tenets of it and inferring how to fill in the large gaps in a way that isn't at all how its specified. The semver specification is pretty clear in my opinion even about where some of the edge cases someone less informed might assume, and if we don't agree on that as the definition, I don't know how we avoid the (completely realistic) scenario where everyone in the room has an idea of what "semver" means that's maybe 80% compatible with the spec, but the 80% is different for each of them, and trying to resolve disagreements when people don't agree about what words mean is really hard. | |
| ▲ | KlayLay 2 hours ago | parent | prev | next [-] | | Semantic versioning is about versioning individual dependencies, no? The issue here seems to be about transitive dependencies, where different versions of the same package is used by multiple packages which depend on it. uv's default being to always select the latest version seems to be what Clojure's tools.deps does. | |
| ▲ | chippiewill 2 hours ago | parent | prev [-] | | There isn't a good way to know if a given package is using semver though. There's a lot of packages in the Python ecosystem that use time based versioning rather than semver (literally `year.minor`) and closed ranges cause untold problems. |
|
|
| ▲ | smitty1e 2 hours ago | parent | prev | next [-] |
| “It’s tough to make predictions, especially about the future.”--Yogi Berra |
|
| ▲ | throwaway613746 an hour ago | parent | prev [-] |
| [dead] |