mirror of https://github.com/astral-sh/uv
Add `--python` support to `uv run` (#3189)
This commit is contained in:
parent
005b76770e
commit
eb27d742b9
|
|
@ -1706,6 +1706,20 @@ pub(crate) struct RunArgs {
|
|||
#[arg(long)]
|
||||
pub(crate) with: Vec<String>,
|
||||
|
||||
/// The Python interpreter to use to build the run environment.
|
||||
///
|
||||
/// By default, `uv` uses the virtual environment in the current working directory or any parent
|
||||
/// directory, falling back to searching for a Python executable in `PATH`. The `--python`
|
||||
/// option allows you to specify a different interpreter.
|
||||
///
|
||||
/// Supported formats:
|
||||
/// - `3.10` looks for an installed Python 3.10 using `py --list-paths` on Windows, or
|
||||
/// `python3.10` on Linux and macOS.
|
||||
/// - `python3.10` or `python.exe` looks for a binary with the given name in `PATH`.
|
||||
/// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path.
|
||||
#[arg(long, short, verbatim_doc_comment, group = "discovery")]
|
||||
pub(crate) python: Option<String>,
|
||||
|
||||
/// Run without the current workspace installed.
|
||||
#[arg(long)]
|
||||
pub(crate) no_workspace: bool,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ pub(crate) async fn run(
|
|||
target: Option<String>,
|
||||
mut args: Vec<OsString>,
|
||||
mut requirements: Vec<RequirementsSource>,
|
||||
python: Option<String>,
|
||||
isolated: bool,
|
||||
no_workspace: bool,
|
||||
preview: PreviewMode,
|
||||
|
|
@ -86,7 +87,15 @@ pub(crate) async fn run(
|
|||
// Detect the current Python interpreter.
|
||||
// TODO(zanieb): Create ephemeral environments
|
||||
// TODO(zanieb): Accept `--python`
|
||||
let run_env = environment_for_run(&requirements, &overrides, isolated, cache, printer).await?;
|
||||
let run_env = environment_for_run(
|
||||
&requirements,
|
||||
&overrides,
|
||||
python.as_deref(),
|
||||
isolated,
|
||||
cache,
|
||||
printer,
|
||||
)
|
||||
.await?;
|
||||
let python_env = run_env.python;
|
||||
|
||||
// Construct the command
|
||||
|
|
@ -164,6 +173,7 @@ fn find_workspace_requirements() -> Result<Option<Vec<RequirementsSource>>> {
|
|||
async fn environment_for_run(
|
||||
requirements: &[RequirementsSource],
|
||||
overrides: &[RequirementsSource],
|
||||
python: Option<&str>,
|
||||
isolated: bool,
|
||||
cache: &Cache,
|
||||
printer: Printer,
|
||||
|
|
@ -194,35 +204,42 @@ async fn environment_for_run(
|
|||
)
|
||||
.await?;
|
||||
|
||||
// Check if the current environment satisfies the requirements
|
||||
if let Some(venv) = current_venv {
|
||||
// Determine the set of installed packages.
|
||||
let site_packages = SitePackages::from_executable(&venv)?;
|
||||
|
||||
// If the requirements are already satisfied, we're done. Ideally, the resolver would be fast
|
||||
// enough to let us remove this check. But right now, for large environments, it's an order of
|
||||
// magnitude faster to validate the environment than to resolve the requirements.
|
||||
if spec.source_trees.is_empty()
|
||||
&& site_packages.satisfies(&spec.requirements, &spec.editables, &spec.constraints)?
|
||||
{
|
||||
debug!("Current environment satisfies requirements");
|
||||
return Ok(RunEnvironment {
|
||||
python: venv,
|
||||
_temp_dir_drop: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
// Otherwise, we need a new environment
|
||||
|
||||
// Find an interpreter to use
|
||||
// TODO(zanieb): Populate `python` from the user
|
||||
let python = None;
|
||||
// Determine an interpreter to use
|
||||
let python_env = if let Some(python) = python {
|
||||
PythonEnvironment::from_requested_python(python, cache)?
|
||||
} else {
|
||||
PythonEnvironment::from_default_python(cache)?
|
||||
};
|
||||
|
||||
// Check if the current environment satisfies the requirements
|
||||
if let Some(venv) = current_venv {
|
||||
// Ensure it matches the selected interpreter
|
||||
// TODO(zanieb): We should check if a version was requested and see if the environment meets that
|
||||
// too but this can wait until we refactor interpreter discovery
|
||||
if venv.root() == python_env.root() {
|
||||
// Determine the set of installed packages.
|
||||
let site_packages = SitePackages::from_executable(&venv)?;
|
||||
|
||||
// If the requirements are already satisfied, we're done. Ideally, the resolver would be fast
|
||||
// enough to let us remove this check. But right now, for large environments, it's an order of
|
||||
// magnitude faster to validate the environment than to resolve the requirements.
|
||||
if spec.source_trees.is_empty()
|
||||
&& site_packages.satisfies(
|
||||
&spec.requirements,
|
||||
&spec.editables,
|
||||
&spec.constraints,
|
||||
)?
|
||||
{
|
||||
debug!("Current environment satisfies requirements");
|
||||
return Ok(RunEnvironment {
|
||||
python: venv,
|
||||
_temp_dir_drop: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// Otherwise, we need a new environment
|
||||
|
||||
// Create a virtual environment
|
||||
// TODO(zanieb): Move this path derivation elsewhere
|
||||
let uv_state_path = std::env::current_dir()?.join(".uv");
|
||||
|
|
|
|||
|
|
@ -507,6 +507,7 @@ async fn run() -> Result<ExitStatus> {
|
|||
args.target,
|
||||
args.args,
|
||||
requirements,
|
||||
args.python,
|
||||
args.isolated,
|
||||
args.no_workspace,
|
||||
globals.preview,
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ pub(crate) struct RunSettings {
|
|||
pub(crate) isolated: bool,
|
||||
pub(crate) with: Vec<String>,
|
||||
pub(crate) no_workspace: bool,
|
||||
pub(crate) python: Option<String>,
|
||||
}
|
||||
|
||||
impl RunSettings {
|
||||
|
|
@ -100,6 +101,7 @@ impl RunSettings {
|
|||
isolated,
|
||||
with,
|
||||
no_workspace,
|
||||
python,
|
||||
} = args;
|
||||
|
||||
Self {
|
||||
|
|
@ -109,6 +111,7 @@ impl RunSettings {
|
|||
isolated,
|
||||
with,
|
||||
no_workspace,
|
||||
python,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue