Posted by miketheman 3 days ago
Of course, this is already miles better than the current state of affairs where an old but popular package could become an infection vector at any time.
I guess the use case is that you might want to build a wheel for an older release for a newer version of Python?
(This will hopefully change pretty soon, with the “upload 2.0” work.)
The time limit is needed because a release can contain different binary wheels for different architectures.
Consider the simplest case: your releases go out via GitHub Actions and separate wheels are built on the Windows, Linux, and macOS runners.
Those won't all end at exactly the same time, so you need a release window during which they can finish and upload their generated files.
That window used to be unlimited, now it's 14 days.
That might seem like a long time, but it means more manual release processes still have time to coordinate, or release processes that need access to less common hardware that might require queuing for a while.
Every one I’m aware of works either as a one-shot (you have to submit everything in one push) or lets you keep adding new assets forever (other, obviously, than PyPI with the addition of this 14 day wall).
While this may quantify how disruptive the change would be to those projects that are able to and do upload additional binaries to PyPI later, it fails to quantify how many projects already completely circumvent this block before it is even introduced.
e.g. If you tell pip to install from source.. the result may already be that you install a binary that PyPI never saw. A common hack for dealing with NVidia internals, which can explode into a large CUDA major version x GPU arch x platform x implementation x python_version cartesian product. The "extras" mechanism is not quite sufficient to model such combinations.
sample code: https://github.com/Dao-AILab/causal-conv1d/blob/4f6ae4e26ae5... https://pypi.org/project/causal-conv1d/
The way it's done with rubygems, if you messed something up with the gem (pushed secrets, etc.), you "yank" (remove) the release and push a new one (different version). You can't work with the files in a release once it's been pushed.
In concept why can’t the full set of files in a release be a single, one-way hash value, with both adding or releasing changing the hash value?
(Also: we’d need to determine what it even means to hash a set of files. Do we order by canonicalized filename, by upload time, etc. Each of these has surprising implications!)
Edit: to be clear, it’s not ideal or fully intentional that uploads to PyPI are not atomic. But it’s the status quo and any change will take years.
You lock to the distribution instead of the release so your build doesn't have to download distributions for platforms you're not using.
PyPi just decided to do what VCSes already did, worse
The release consists of one sdist and zero or more wheels. Until now you were able to upload additional wheels at later time.
(This doesn’t change your observations at all! Just as a demonstration of how Python packaging’s data model can be unintuitive.)
We also figured out 20 years ago that SHA1 was not quite as strong as initially estimated, and not quite 10 years ago that generating two colliding documents was merely a matter of some serious computing power. A few projects went ahead and changed the name of their master branch, but SHA256 preference remains elusive.
This is unintuitive, but the TL;DR is that files will never change on PyPI, but (previously) a user could upload a new file to a release years after their last upload to that release. This has some legitimate use cases (like allowing people to support new Python versions without bumping a package’s version), but also makes introduces challenges around locking and release security that are elaborated in the thread linked by the blog post.
I agree this could probably be ratcheted down from 14 days over time, though.
You can’t go back later and add “evil.py” to a bunch of existing release files, but you could previously go find a bunch of releases that didn’t have arm64 files, publish malicious ones, and use that to catch people using those versions on arm64 systems
...why Python is just breaking compatibility so bad with new version it needs that ?