Optional dependencies can not be combined with .whl URIs
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?
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.
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.
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.
The micropip documentation also lists a syntax await micropip.install("snowballstemmer @ https://.../snowballstemmer.*.whl")
Huh, I think that we never supported this syntax.
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?
I prefer the latter (micropip.install("….whl", features=["all"])).
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?)