micropip icon indicating copy to clipboard operation
micropip copied to clipboard

Optional dependencies can not be combined with .whl URIs

Open chrysn opened this issue 11 months ago • 4 comments

To ease testing of unreleased versions, I'm publishing a wheel of any main branch build of my project aiocoap, so users can:

>>> import micropip
>>> await micropip.install("https://raw.codeberg.page/aiocoap/aiocoap/@pages/dist/aiocoap-0.4.12.post0-py3-none-any.whl")

Frequently, users need to install dependencies, so my recommendation outside of development is that they do

>>> import micropip
>>> await micropip.install("aiocoap[prettyprint,oscore]")

However, those can't be combined:

>>> import micropip
>>> await micropip.install("https://raw.codeberg.page/aiocoap/aiocoap/@pages/dist/aiocoap-0.4.12.post0-py3-none-any.whl[prettyprint]")
Traceback (most recent call last):
[...]
packaging._tokenizer.ParserSyntaxError: Expected end or semicolon (after name and no valid version specifier)
    https://raw.codeberg.page/aiocoap/aiocoap/@pages/dist/aiocoap-0.4.12.post0-py3-none-any.whl[prettyprint]
         ^

(tested on https://pyodide.org/en/latest/console.html)

As far as I understand, this is a shortcoming of micropip, which is not present in pip (can't compare directly because AIU pip doesn't do wheels from URIs, but pip install 'dist/aiocoap-0.4.12.post0-py3-none-any.whl[oscore]' works).

Is this something that might be added, or is there a known workaround?

chrysn avatar Feb 08 '25 23:02 chrysn

It seems to me like a reasonable feature request, particularly since pip implements an analogous feature. It is a bit horrible to write http://some-url.com/dist-name_plat.whl[extras] but it's better than not having a way to do it at all.

I can't say what workarounds people use maybe @agriyakhetarpal might know.

hoodmane avatar Feb 09 '25 08:02 hoodmane

Maybe we can allow putting extra suffix for emfs:// or file:// protocols only? Then people might be able to download the package first, and install it from the file system.

ryanking13 avatar Feb 11 '25 11:02 ryanking13

The interaction of those brackets with URIs is a bit odd in general -- and unlike pip, we're in an environment where explicit Python syntax is an option. So if combining this turns out to be problematic, it may be an option to introduce await micropip.install("https://…/my-version.whl", ["feature1", "feature2"]).

The micropip documentation also lists a syntax await micropip.install("snowballstemmer @ https://.../snowballstemmer.*.whl"), which might lend itself to trying out await micropip.install("snowballstemmer[all] @ https://.../snowballstemmer.*.whl"), but the latest pyodide version didn't seem to support that.

chrysn avatar Feb 11 '25 14:02 chrysn

The micropip documentation also lists a syntax await micropip.install("snowballstemmer @ https://.../snowballstemmer.*.whl")

Huh, I think that we never supported this syntax.

ryanking13 avatar Feb 12 '25 10:02 ryanking13

If I'm to write a patch (no promises), would you rather see snowballstemmer[all] @ https://….whl supported, or the extra micropip.install("….whl", features=["all"]) version?

chrysn avatar Sep 15 '25 13:09 chrysn

I prefer the latter (micropip.install("….whl", features=["all"])).

ryanking13 avatar Sep 15 '25 14:09 ryanking13

Exploring what's in micropip, I found that it'd be a viable workaround to produce an index and then install like await micropip.install("mypackage[feature1,feature2]", index_urls=["https://where/i/host", "PYPI"]) -- but then, that requires not just CORS but also setting proper media types (at least HTML), which is something my current build setup can't do. But it'd be an odd workaround anyway… 🦊🍇😖

I've tried out things at https://github.com/pyodide/micropip/pull/253 – not sure about whether that's a good solution, though. (*jumps up to grapes again* … or can we find the right hook in the vendored-in parsers to make foo[ex] @ https://.../foo.whl just work?)

chrysn avatar Sep 15 '25 20:09 chrysn