No-op the asyncio package on PyPI

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.

Some packages mistakenly list it as a dependency.

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"?

5 Likes

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?

1 Like

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.

1 Like

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 :sweat_smile:

I created a no-op package in this fork: GitHub - lordmauve/asyncio: Fork of asyncio to develop no-op package .

I created the packages with uvx --from=build pyproject-build.

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.

2 Likes

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 will try Daniel’s dummy repo.

–Guido

I successfully uploaded the asyncio 4.0.0 dummy package to PyPI: asyncio · PyPI

If someone could test that this works and doesn’t break existing apps listing ‘asyncio’ as a dependency, that would be great.

I’ve found 1400 reverse dependencies that published wheels, that were indexed by wheelodex. Find reverse dependencies · JamesParrott/asyncio_obsolete@526c597 · GitHub

I’m mulling over how to programmatically try to test each one. Does anyone have any ideas how this should be done?

1 Like

This resolved the issue we saw.

1 Like

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.

2 Likes

Excellent! I think we can lay this issue to rest.

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.

2 Likes