python-trio / trio

Trio – a friendly Python library for async concurrency and I/O
https://trio.readthedocs.io
Other
5.98k stars 325 forks source link

Please switch to v1.0 and start using semantic version numbers #2961

Open smurfix opened 4 months ago

smurfix commented 4 months ago

The last change to Trio (dropping MultiError) caused some compatibility mayhem, most recently here.

I'd thus like to ask for a release tagged 1.0, followed by semantic version numbers. That will allow other packages that depend on Trio to use a dependency like ~1.0, thus telling pip-or-whatever that upgrading Trio from say 1.9 to 2.1 is not going to work.

IMHO Trio is sufficiently stable (and widely used) that zero-dot-anything version numbers are no longer a good idea.

A5rocks commented 4 months ago

There's one more scary-compatibility thing (https://github.com/python-trio/trio/pull/2886) that's probably better being done before v1. (yes this has been deprecated for a while, but so was MultiError!)

I don't have any comments for 1.0 after that.

Fuyukai commented 4 months ago

That will allow other packages that depend on Trio to use a dependency like ~1.0, thus telling pip-or-whatever that upgrading Trio from say 1.9 to 2.1 is not going to work.

Do not do this.

See: https://hynek.me/articles/semver-will-not-save-you/, https://iscinumpy.dev/post/bound-version-constraints/.

jakkdl commented 4 months ago

That will allow other packages that depend on Trio to use a dependency like ~1.0, thus telling pip-or-whatever that upgrading Trio from say 1.9 to 2.1 is not going to work.

Do not do this.

See: https://hynek.me/articles/semver-will-not-save-you/, https://iscinumpy.dev/post/bound-version-constraints/.

While I generally agree with the sentiment, we knowingly did do a breaking change (after MultiError has been deprecated and raising warnings since 2022-09) and while overrelying on SemVer is Bad :tm: I think conveying some information with the versioning numbers can be quite helpful.

Speaking of, when are we ripping off the bandaid and releasing #2886?

smurfix commented 4 months ago

conveying some information with the versioning numbers can be quite helpful.

Agreed. I mean, yes backwards compatibility is great but at some point the you got to drop the workarounds.

So if you're uptodate on version 2 and you know that any deprecation will take two releases, specifying >2.1,<5 leaves ample time to upgrade.

Do not do this.

Well, I disagree.

"Semver will not save you" — well of course it won't. Not on its own. But semver plus a sensible deprecation strategy is a whole lot better than just going with a date-based versioning scheme and watching the chips fall where they may. IMHO.

NB: the first link recommends, quite strongly,

Pin your dependencies and their transitive dependencies to their exact versions.

Well, yeah. You can and probably should do this when you're writing an application that needs to be thoroughly tested and deployed under your control.

However, things get murky when the app is intended to be installed into an existing infrastructure or, worse, when it's not an app but a package. Pinning a package to an exact version of everything it depends on doesn't scale.

A5rocks commented 4 months ago

For what it's worth I think the reply was specifically about speculatively pinning deps as a library. Not so much saying semver is bad for a library maintainer (if that's what you like) but that users shouldn't trust the version guarantees and libraries shouldn't use semver as justification for adding upper bounds (though if a version removes an API then that's a fine upper bound, just not ">=1,<2, because semver:tm:").

I'll note the original issue wouldn't have happened if there were no upper bound on anyio for moat-mqtt. It's your choice but that's the kind of thing we want to generally discourage.

(my rephased tl;dr of the iscinumpy post is: libraries should expect users to set the upper bounds based on what works. if a doesn't work with the latest b, then a user can just pip install a b<=[working version].)

mikenerone commented 4 months ago

As the article states itself, there's value in advertising intent, and SemVer lets us do that. It's better than the Wild West. That said, it might not hurt for the documentation to try to edify users by referencing that article. :)

richardsheridan commented 4 months ago

Matplotlib recently switched to EffVer and I think that's worth considering here too:

https://github.com/matplotlib/matplotlib/pull/27795

CoolCat467 commented 4 months ago

I don't think changing versions on a whim is worth it. Trio ships releases when they are ready.

dhirschfeld commented 4 months ago

IMO, in practice there's no difference between EffVer and SemVer - it's just different marketing for users who might otherwise take SemVer too literally.

smurfix commented 4 months ago

Well, SemVer also regards backwards compatibility, i.e. if my code wants 2.6.4, it ought to work (modulo some bug fixes) with 2.6.2 or 2.7.4, but if I drop 2.5.8 or 3.0.2 in there's at least one bit that's going to break.

EffVer doesn't think about backwards compatibility at all; it considers the forward change's impact on your code instead of the question whether there is a change, no matter how large (in theory).

While all versioning methods are kindof suboptimal given that we try to squeeze a multi-dimensional array of features (and bug fixes) onto an one-dimensional vector, SemVer at least tries to say "install the latest version that satisfies every user and your code should [continue to] work", while EffVer does no such thing.

@CoolCat467 What whim? We can change versioning when we do the next when-it's-ready release.

njsmith commented 4 months ago

I think we ultimately want some form of CalVer. The only really viable / honest / user-respecting way to make backward incompatible changes at all to a complex project like Trio is to scope them as tightly as possible and phase them in over multiple releases (e.g. quiet warning -> louder warning -> error -> new behavior, etc.), which means you likely have multiple such changes in different stages all the time, and each of them effects as small a slice of the userbase as you can manage. In these circumstances SemVer doesn't give you any useful information -- either you bump the major version every release or you never bump it at all, and either way no-one learns what they want to know (whether an upgrade will break their usage). Plus when things do break, SemVer tends to encourage people to start playing the blame game instead of fixing things.

jakkdl commented 3 months ago

We have had a couple recent releases that has been quite major, and the switch to defaulting to strict_exception_groups=True didn't have a deprecation period*. We've also had several bugfix or typing releases that had ~0 error on users. So I don't think EffVer/SemVer is entirely unviable, but I also don't mind CalVer.

* because it was deemed to be more disruptive to raise warnings whenever a user didn't explicitly specify.

dhirschfeld commented 3 months ago

As a consumer of packages, I really struggle with CalVer - should I update from 2024-02-07 to 2024-03-02? I've got zero basis to make an informed decision from the output (the version string) of my packaging tool. There might be any number of breaking changes between those versions and I've got no way to rank those possibilities.

Instead, if an update were to bump a package from 1.2.6 to 1.2.8 I'd immediately hit y to update with the assumption that there are no breaking changes. If instead my install wanted to update a package from 1.2.6 to 2.0.0 I'd hit n and go to the GitHub releases page of that package to understand the changes between those versions before updating.

Using SemVer/EffVer lets me make an informed decision to not do the necessary due-diligence based on the probability of breakage. In contrast, since you have no information for a package using CalVer you have to pessimistically investigate the changes between every single release date to ensure they don't affect you.

Sure, doing that is best practice anyway, but it can add a significant overhead for run-of-the-mill updates which can be ~mostly avoided if the developer indicates, in some imperfect way, the chance that this update will break code using their library.

mikenerone commented 3 months ago

It's a bit complicated in Trio's case because of our release pattern. SemVer (or EffVer, which tbh I'm a bit ambivalent about) is much more helpful in conjunction with a continuous delivery cycle. Historically, we basically hold releases until there's something that would be considered worthy of at least a minor version bump, but often a major version bump (setting aside the actual wild-west of being in 0.x.x). OTOH, I generally find CalVer in my deps to be harmful to my blood pressure. :P

Actually, my question is: Why not release continuously? I ask here because SemVer/EffVer would naturally make more sense as the answer if we did.

A5rocks commented 3 months ago

If by releasing continuously you mean releasing every commit to main (like hypothesis), I believe the idea is that we want to accept PRs that potentially aren't complete. (e.g. newcomer comes by, does some nice work but missing a few complicated edge cases. it's probably worth merging and making a new pr instead of having comments on their PR for changes they didn't do).

Oh yeah I forgot some other reasoning. Just look here: https://github.com/python-trio/trio/issues/220#issuecomment-402074276

CoolCat467 commented 3 months ago

I agree with what was mentioned in https://github.com/python-trio/trio/issues/220#issuecomment-402074276, I definitely think making a release on every commit to main would drive people away. I know I would feel uncomfortable if I knew every pull request I made was going to be a new release, and if I had made any errors anywhere that tests hadn't caught and no one reviewing had caught, we would have a broken release end users would be attempting to use and it would be my fault and I would likely avoid making any future changes. With existing system, if anything is wrong there is way more time to catch issues before a release happens and we can revert changes if need be much easier.

mikenerone commented 3 months ago

Oh yeah I forgot some other reasoning. Just look here: #220 (comment)

Ah yes, the "inexperienced contributor" problem is very real. I guess perhaps I'd argue to simply release more often, then. It doesn't have to be full-on CD for SemVer(/EffVer) to start to become more helpful. Just often enough that there's such a thing as minor and patch releases (which Trio generally hasn't done except in pretty impactful hotfix situations).