It's interesting that you mention Rust, since Rust takes backward compatibility quite seriously; that's why it's still on version 1.x. Granted, sometimes there is a compiler bug that causes some old code not to compile with newer versions of Rust, but that is rare and never intentional like this PEP.
(Just to be sorta pedantic) I don't think it's the version 1.x that promotes backward compatibility, but editions.
In 2016, you could call your function `fn async(...) { ... }` without any issues, and you can still compile this code with the modern version of rustc. If you want to use the async features of Rust, you need to change your edition to at least 2018, which brings breaking changes in the language.
And you can have a project that mixes those editions, and cargo will correctly use the edition asked for each crate.
(So, I guess the ideal world would to first look at the package management in Python, and *then* try to introduce breaking changes. And I'm withholding how much I'm angry at the PSF for postponing having a decent package manager for 20 years and investing in removing the GIL and adding JIT.)
Not meaning to apologize for Python here, but you have significantly more ability to segregate “editions” when you statically compile code.
All the more reason to take a breakage very seriously. This is even worse than the walrus operator. At least I can ignore that. This breaks working code for some notion of purity.
Code compilation doesn't really have much to do with it. Python already has a somewhat similar ability - opting into certain language features of python on a file-by-file basis - using __future__[0]. It'd be pretty easy to add something like Rust editions by looking for a special statement in the file. And to make it more convenient, put it in the __init__.py and have it be transitive to the module.
>> It's interesting that you mention Rust, since Rust takes backward compatibility quite seriously;
I mentioned Rust because the memory safety guarantees are a significant new thing for a language like that. I forgot about "managed" languages like C# because that's quite far from my mind, but that's another significant attempt at safety. This kind of little detail in the PIP is really insignificant by comparison, so I was speculating that it might be driven by some kind of "save everyone" mentality. If so, wondering if that's a trend lately and I hadn't noticed.
They do take it seriously, I agree. However, the commonly repeated meme that Rust only makes backwards-incompatible changes by mistake or to fix soundness issues is wrong. They allow themselves to make changes if they're judged to have a low (but nonzero) risk of causing backwards incompatibility in the wild. For example, adding a new function to a standard trait can be backwards incompatible but they do it all the time.
Indeed. Although it's worth noting that the same is true of e.g. stable enterprise favorites like Java, which regularly makes minor breaking changes that are judged to have little impact (which is why every Java release is accompanied by a compatibility guide; see the "Important Changes", "Removed Features", and "Other Notes" sections of the most recent release notes: https://www.oracle.com/java/technologies/javase/23-relnote-i...).