uv icon indicating copy to clipboard operation
uv copied to clipboard

Allow extras in `uvx` command

Open dimaqq opened this issue 1 year ago • 5 comments

How to specify package extras with uvx?

Or, in other words, how to run httpx with uvx?

> uvx --version
uv-tool-uvx 0.3.0 (Homebrew 2024-08-20)
> uvx httpx
The httpx command line client could not run because the required dependencies were not installed.
Make sure you've installed everything with: pip install 'httpx[cli]'
> uvx httpx[cli]
error: Not a valid package or extra name: "httpx[cli]". Names must start and end with a letter or digit and may only contain -, _, ., and alphanumeric characters.

dimaqq avatar Aug 21 '24 04:08 dimaqq

Try uvx 'httpx[cli]'

Eyal-Shalev avatar Aug 21 '24 04:08 Eyal-Shalev

uvx --with 'httpx[cli]' httpx works, but this is something we should support better.

konstin avatar Aug 21 '24 06:08 konstin

Yeah I think httpx[cli] could be supported (install httpx[cli], then run the httpx entrypoint).

charliermarsh avatar Aug 21 '24 13:08 charliermarsh

pipx run does this; you can specify version specifiers and extras. When making the package name, it runs them through packaging and just picks the package name out.

henryiii avatar Aug 23 '24 20:08 henryiii

I'm not opposed to supporting this in the short-term. If there's a reason uvx httpx[cli] shouldn't work lmk.

zanieb avatar Aug 23 '24 20:08 zanieb

We need to decide on the following cases:

  • uvx httpx==0.6.0
  • uvx httpx[cli]
  • uvx httpx[cli]==0.6.0
  • uvx httpx[cli]@0.6.0

charliermarsh avatar Sep 16 '24 01:09 charliermarsh

I think including the extra is arguably just an extension of the name, whereas the == syntax is in another category. So I'd basically say just the following are allowed:

  • uvx httpx[cli]
  • uvx httpx[cli]@0.6.0

Alternatively, we could support --extra, e.g., uvx --extra cli httpx?

zanieb avatar Sep 16 '24 02:09 zanieb

I know pipx supports the first three. Haven’t seen the forth.

henryiii avatar Sep 16 '24 03:09 henryiii

Note, the benefits of just parsing the version and extra syntax like normal, and passing on the package name, is that people don't have to learn a new syntax (it works just like pip), and you can do things like uvx cmake~=3.23.0, uvx "https[cli]<0.6", uvx "ruff>=0.6", etc. It's literally just what you'd pass to pip. That's how pipx works, anyway, and I don't think anyone's complained (though I don't follow too closely).

Might make sense to support the extras first, then decide on version stuff later, though.

henryiii avatar Sep 16 '24 03:09 henryiii

I think one more usage pattern belongs here:

I wanted to do:

> uvx 'git+https://github.com/tox-dev/tox.git@main#egg=tox' --version
error: Not a valid package or extra name: "git+https://github.com/tox-dev/tox.git@main#egg=tox". Names must start and end with a letter or digit and may only contain -, _, ., and alphanumeric characters.

I can work around that with:

> uvx --with 'git+https://github.com/tox-dev/tox.git@main#egg=tox' tox --version
 Updated https://github.com/tox-dev/tox.git (343fe92)
4.23.3.dev10+g343fe92 from /Users/dima/Library/Caches/uv/archive-v0/guRzVYUj3CZf_BUckU7HB/lib/python3.11/site-packages/tox/__init__.py

dimaqq avatar Nov 12 '24 04:11 dimaqq

I'm personally okay with supporting uvx httpx==0.6.0 (and any valid specifier).

charliermarsh avatar Nov 23 '24 03:11 charliermarsh

Looking at this issue, I'm a bit confused why --from is not recommended here, as it is the way of specifying what package to actually install?

From my understanding, the specified command of uvx has some "magic" to it:

On one hand there is the command to run and then there is the package to install it from.

Usually, these are the same -- hence one can just do uvx ruff. However, that is just a shorthand for uvx --from ruff ruff.

Similarly, uvx [email protected] will expand to something akin to uvx --from ruff~=0.8 ruff.

Note that if --from is specified, there is no attempt to decode the command:

$ uvx --from "ruff~=0.8" [email protected]                                                                                                                                       
The executable `[email protected]` was not found.
warning: An executable named `[email protected]` is not provided by package `ruff`.

With that established, the question becomes how to populate --from, if only the command is specified.

What I understand from the docs, the current allowed formats for command are:

  • <package> (e.g., ruff) and
  • <package>@<version> (e.g., ruff@latest).

Now, we might want to add:

  • <package>[<extras>], e.g. (httpx[cli])
  • <package>==<version>, e.g. httpx==0.6.0, httpx~=0.6.0
  • <git-url>, e.g. git+https://github.com/tox-dev/tox.git@main#egg=tox`

The implementation for the first two should be relatively simple

  • uvx <package>[<extras>] becomes uvx --from <package>[<extras>] package
  • uvx <package>==<version> becomes uvx --from <package>==<version> package
  • uvx <package>[<extras>]==<version> becomes uvx --from <package>[<extras>]==<version> package

In the case of the git repository we can't assume the package name (and thus command) from the specified url, rather we would need to install the package first to receive the package (and command) name.

I think there is also an argument to support mixing extras with uv's version requirements (uvx httpx[cli]@0.6.0). But in that case, one should not be able to also specify version pip-like requirements (uvx httpx[cli][email protected]).


In my view, uv should at least support extras and ==1.2.3 like version specifiers to be as compatible with pipx as possible.

Mixing @<version> and ==<version> specifiers should not be allowed.

Support for path-resources could also be nice, but is less important in my eyes. One can argue that is more explicit to require the command name, if it can't be derived from the package-path.

jaheba avatar Jan 08 '25 09:01 jaheba