I just discovered (via supporting a user) that there’s an old backport package asyncio · PyPI on PyPI and installing it on modern Python actually breaks asyncio depending on installation layout and sys.path order.
The GitHub repo for asyncio is archived so I can’t PR or open issues, but how about publishing a 4.0.0 which is an empty wheel, with a requires_python = ">=3.4"?
Good idea. I’ve run into this too – I found quite a few packages that still have it in their requirements. Usually it’s harmless since the stdlib package takes precedence over a 3rd party package of the same name, but people can and do manipulate sys.path to change this.
Your solution looks like a good one. You’re lucky that I am one of the co-owners of the PyPI entry! I’ve forgotten practical details of how to do what you propose, but if you give me some hints (e.g. an empty temporary repo that implements your suggestion) I can build it and do the upload for you.
I guess if people explicitly require asyncio 3.4.3, nothing can help them. Or could we replace 3.4.3 with a dummy too?
It is not possible to replace old releases. I would not worry about someone pinning it though.
An alternative possibility would be to upload a 4.0.0 release that is sdist only and that fails to build (giving a helpful error message). That would break anyone who has asyncio in requirements so that they can see and fix the problem.
people can and do manipulate sys.path to change this.
We hit this without actually modifying sys.path. In my firm we copy the entire interpreter, delete EXTERNALLY-MANAGED, and then pip install into the interpreter’s system directory, in order to get self-contained executable distributions.
you give me some hints (e.g. an empty temporary repo that implements your suggestion)
If you could unarchive the repo temporarily I can send a PR? Otherwise I will fork and get this working. I’ve definitely created empty wheels accidentally, it just requires misconfiguring setuptools slightly
This would make any libraries that request a dependency on asyncio uninstallable until they remove it. So it doesn’t just affect applications managing their own dependencies without lock files, it could cause library maintainers to field issues and to have to cut releases in order to remain installable.
The effect of installing asyncio from PyPI has been a no-op for practical purposes for over a decade. Making it genuinely a no-op is kinder than causing people grief about what is mostly a non-issue.
You could set requires-python >= 3.15 to limit the scope of that.
Ultimately it depends if you think that the end goal should be that no one installs the package or not. If it is the end goal that no one installs it then you cannot fully reach it without a break at some point. Having people install a no op package only sounds like a temporary solution to me.
We can (presumably) track how many downloads there are of each version on PyPI? Then when the numbers for 3.4.3 have dwindled enough we can yank it, and ditto for 4.0.0.
The goal is, indeed, to avoid breaking code that has this dependency – we don’t want to punish people for this dependency, we just want to avoid getting the 3.4.3 version somehow being used, since it’s ancient and will likely break every modern asyncio use (mostly because it’s missing many new APIs but also because it’s got many bugs that have long been fixed).
I pulled the metadata for the above packages from PyPi, and naively tried to run Pytest against all 220 or so that listed pytest as a dependency, with asyncio 3.4.3. Thirty passed, and all of those viable candidates also passed against asyncio 4.0.0.
Maybe in 5 years someone can pull down some download numbers for both versions of the package and we can decide whether to entirely delete one or both.