uv run: List available scripts when a script is not specified (#7687)

Signed-off-by: Kemal Akkoyun <kakkoyun@gmail.com>
## Summary

This PR adds the ability to list available scripts in the environment
when `uv run` is invoked without any arguments.
It somewhat mimics the behavior of `rye run` command
(See https://rye.astral.sh/guide/commands/run).

This is an attempt to fix #4024.

## Test Plan

I added test cases. The CI pipeline should pass.

### Manuel Tests

```shell
❯ uv run
Provide a command or script to invoke with `uv run <command>` or `uv run script.py`.

The following scripts are available:

normalizer
python
python3
python3.12

See `uv run --help` for more information.
```

---------

Signed-off-by: Kemal Akkoyun <kakkoyun@gmail.com>
Co-authored-by: Zanie Blue <contact@zanie.dev>
This commit is contained in:
Kemal Akkoyun 2024-10-08 21:34:50 +02:00 committed by GitHub
parent 282fab5f70
commit 1a39ffe391
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 152 additions and 16 deletions

View file

@ -53,12 +53,8 @@ tracing = { workspace = true }
url = { workspace = true }
which = { workspace = true }
[target.'cfg(any(unix, target_os = "wasi", target_os = "redox"))'.dependencies]
rustix = { workspace = true }
[target.'cfg(target_os = "windows")'.dependencies]
windows-sys = { workspace = true }
winsafe = { workspace = true }
windows-registry = { workspace = true }
windows-result = { workspace = true }

View file

@ -10,6 +10,7 @@ use tracing::{debug, instrument, trace};
use which::{which, which_all};
use uv_cache::Cache;
use uv_fs::which::is_executable;
use uv_fs::Simplified;
use uv_pep440::{Prerelease, Version, VersionSpecifier, VersionSpecifiers};
use uv_warnings::warn_user_once;
@ -27,7 +28,6 @@ use crate::virtualenv::{
conda_prefix_from_env, virtualenv_from_env, virtualenv_from_working_dir,
virtualenv_python_executable,
};
use crate::which::is_executable;
use crate::{Interpreter, PythonVersion};
/// A request to find a Python installation.

View file

@ -37,7 +37,6 @@ mod python_version;
mod target;
mod version_files;
mod virtualenv;
mod which;
#[cfg(not(test))]
pub(crate) fn current_dir() -> Result<std::path::PathBuf, std::io::Error> {

View file

@ -1,40 +0,0 @@
use std::path::Path;
/// Check whether a path in PATH is a valid executable.
///
/// Derived from `which`'s `Checker`.
pub(crate) fn is_executable(path: &Path) -> bool {
#[cfg(any(unix, target_os = "wasi", target_os = "redox"))]
{
if rustix::fs::access(path, rustix::fs::Access::EXEC_OK).is_err() {
return false;
}
}
#[cfg(target_os = "windows")]
{
let Ok(file_type) = fs_err::symlink_metadata(path).map(|metadata| metadata.file_type())
else {
return false;
};
if !file_type.is_file() && !file_type.is_symlink() {
return false;
}
if path.extension().is_none()
&& winsafe::GetBinaryType(&path.display().to_string()).is_err()
{
return false;
}
}
if cfg!(not(target_os = "windows")) {
if !fs_err::metadata(path)
.map(|metadata| metadata.is_file())
.unwrap_or(false)
{
return false;
}
}
true
}