mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-13 17:25:41 +00:00
Accept (e.g.) 'python3.8' as --python argument (#2031)
## Summary This PR aligns the `uv pip install --python` flag with the `uv venv --python` flag, such that the former now accepts binary names and Python versions by way of using the same `find_requested_python` method under the hood.
This commit is contained in:
parent
995fba8fec
commit
23afa09fae
6 changed files with 60 additions and 42 deletions
|
|
@ -28,7 +28,9 @@ pub enum Error {
|
||||||
#[error("No versions of Python could be found. Is Python installed?")]
|
#[error("No versions of Python could be found. Is Python installed?")]
|
||||||
PythonNotFound,
|
PythonNotFound,
|
||||||
#[error("Failed to locate a virtualenv or Conda environment (checked: `VIRTUAL_ENV`, `CONDA_PREFIX`, and `.venv`). Run `uv venv` to create a virtualenv.")]
|
#[error("Failed to locate a virtualenv or Conda environment (checked: `VIRTUAL_ENV`, `CONDA_PREFIX`, and `.venv`). Run `uv venv` to create a virtualenv.")]
|
||||||
NotFound,
|
VenvNotFound,
|
||||||
|
#[error("Failed to locate Python interpreter at: `{0}`")]
|
||||||
|
RequestedPythonNotFound(String),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Io(#[from] io::Error),
|
Io(#[from] io::Error),
|
||||||
#[error("Failed to query python interpreter `{interpreter}`")]
|
#[error("Failed to query python interpreter `{interpreter}`")]
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use uv_fs::{LockedFile, Normalized};
|
||||||
|
|
||||||
use crate::cfg::PyVenvConfiguration;
|
use crate::cfg::PyVenvConfiguration;
|
||||||
use crate::python_platform::PythonPlatform;
|
use crate::python_platform::PythonPlatform;
|
||||||
use crate::{Error, Interpreter};
|
use crate::{find_requested_python, Error, Interpreter};
|
||||||
|
|
||||||
/// A Python executable and its associated platform markers.
|
/// A Python executable and its associated platform markers.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -19,24 +19,11 @@ pub struct Virtualenv {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Virtualenv {
|
impl Virtualenv {
|
||||||
/// Create a new virtual environment for a pre-provided Python interpreter.
|
/// Create a [`Virtualenv`] for an existing virtual environment.
|
||||||
pub fn from_python(
|
|
||||||
python: impl AsRef<Path>,
|
|
||||||
platform: Platform,
|
|
||||||
cache: &Cache,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
let interpreter = Interpreter::query(python.as_ref(), platform, cache)?;
|
|
||||||
Ok(Self {
|
|
||||||
root: interpreter.base_prefix().to_path_buf(),
|
|
||||||
interpreter,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Venv the current Python executable from the host environment.
|
|
||||||
pub fn from_env(platform: Platform, cache: &Cache) -> Result<Self, Error> {
|
pub fn from_env(platform: Platform, cache: &Cache) -> Result<Self, Error> {
|
||||||
let platform = PythonPlatform::from(platform);
|
let platform = PythonPlatform::from(platform);
|
||||||
let Some(venv) = detect_virtual_env(&platform)? else {
|
let Some(venv) = detect_virtual_env(&platform)? else {
|
||||||
return Err(Error::NotFound);
|
return Err(Error::VenvNotFound);
|
||||||
};
|
};
|
||||||
let venv = fs_err::canonicalize(venv)?;
|
let venv = fs_err::canonicalize(venv)?;
|
||||||
let executable = platform.venv_python(&venv);
|
let executable = platform.venv_python(&venv);
|
||||||
|
|
@ -55,7 +42,7 @@ impl Virtualenv {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creating a new venv from a Python interpreter changes this.
|
/// Create a [`Virtualenv`] for a new virtual environment, created with the given interpreter.
|
||||||
pub fn from_interpreter(interpreter: Interpreter, venv: &Path) -> Self {
|
pub fn from_interpreter(interpreter: Interpreter, venv: &Path) -> Self {
|
||||||
Self {
|
Self {
|
||||||
interpreter: interpreter.with_venv_root(venv.to_path_buf()),
|
interpreter: interpreter.with_venv_root(venv.to_path_buf()),
|
||||||
|
|
@ -63,6 +50,21 @@ impl Virtualenv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a [`Virtualenv`] for a Python interpreter specifier (e.g., a path or a binary name).
|
||||||
|
pub fn from_requested_python(
|
||||||
|
python: &str,
|
||||||
|
platform: &Platform,
|
||||||
|
cache: &Cache,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let Some(interpreter) = find_requested_python(python, platform, cache)? else {
|
||||||
|
return Err(Error::RequestedPythonNotFound(python.to_string()));
|
||||||
|
};
|
||||||
|
Ok(Self {
|
||||||
|
root: interpreter.base_prefix().to_path_buf(),
|
||||||
|
interpreter,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the location of the Python interpreter.
|
/// Returns the location of the Python interpreter.
|
||||||
pub fn root(&self) -> &Path {
|
pub fn root(&self) -> &Path {
|
||||||
&self.root
|
&self.root
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
use std::path::Path;
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
use anstream::eprint;
|
use anstream::eprint;
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
|
|
@ -63,7 +62,7 @@ pub(crate) async fn pip_install(
|
||||||
no_binary: &NoBinary,
|
no_binary: &NoBinary,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
exclude_newer: Option<DateTime<Utc>>,
|
exclude_newer: Option<DateTime<Utc>>,
|
||||||
python: Option<PathBuf>,
|
python: Option<String>,
|
||||||
cache: Cache,
|
cache: Cache,
|
||||||
mut printer: Printer,
|
mut printer: Printer,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
|
|
@ -106,8 +105,8 @@ pub(crate) async fn pip_install(
|
||||||
|
|
||||||
// Detect the current Python interpreter.
|
// Detect the current Python interpreter.
|
||||||
let platform = Platform::current()?;
|
let platform = Platform::current()?;
|
||||||
let venv = if let Some(python) = python {
|
let venv = if let Some(python) = python.as_ref() {
|
||||||
Virtualenv::from_python(python, platform, &cache)?
|
Virtualenv::from_requested_python(python, &platform, &cache)?
|
||||||
} else {
|
} else {
|
||||||
Virtualenv::from_env(platform, &cache)?
|
Virtualenv::from_env(platform, &cache)?
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
@ -42,7 +41,7 @@ pub(crate) async fn pip_sync(
|
||||||
no_build: &NoBuild,
|
no_build: &NoBuild,
|
||||||
no_binary: &NoBinary,
|
no_binary: &NoBinary,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
python: Option<PathBuf>,
|
python: Option<String>,
|
||||||
cache: Cache,
|
cache: Cache,
|
||||||
mut printer: Printer,
|
mut printer: Printer,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
|
|
@ -74,8 +73,8 @@ pub(crate) async fn pip_sync(
|
||||||
|
|
||||||
// Detect the current Python interpreter.
|
// Detect the current Python interpreter.
|
||||||
let platform = Platform::current()?;
|
let platform = Platform::current()?;
|
||||||
let venv = if let Some(python) = python {
|
let venv = if let Some(python) = python.as_ref() {
|
||||||
Virtualenv::from_python(python, platform, &cache)?
|
Virtualenv::from_requested_python(python, &platform, &cache)?
|
||||||
} else {
|
} else {
|
||||||
Virtualenv::from_env(platform, &cache)?
|
Virtualenv::from_env(platform, &cache)?
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
|
|
@ -18,7 +17,7 @@ use crate::requirements::{RequirementsSource, RequirementsSpecification};
|
||||||
/// Uninstall packages from the current environment.
|
/// Uninstall packages from the current environment.
|
||||||
pub(crate) async fn pip_uninstall(
|
pub(crate) async fn pip_uninstall(
|
||||||
sources: &[RequirementsSource],
|
sources: &[RequirementsSource],
|
||||||
python: Option<PathBuf>,
|
python: Option<String>,
|
||||||
cache: Cache,
|
cache: Cache,
|
||||||
mut printer: Printer,
|
mut printer: Printer,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
|
|
@ -40,8 +39,8 @@ pub(crate) async fn pip_uninstall(
|
||||||
|
|
||||||
// Detect the current Python interpreter.
|
// Detect the current Python interpreter.
|
||||||
let platform = Platform::current()?;
|
let platform = Platform::current()?;
|
||||||
let venv = if let Some(python) = python {
|
let venv = if let Some(python) = python.as_ref() {
|
||||||
Virtualenv::from_python(python, platform, &cache)?
|
Virtualenv::from_requested_python(python, &platform, &cache)?
|
||||||
} else {
|
} else {
|
||||||
Virtualenv::from_env(platform, &cache)?
|
Virtualenv::from_env(platform, &cache)?
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -445,8 +445,14 @@ struct PipSyncArgs {
|
||||||
/// any parent directory. The `--python` option allows you to specify a different interpreter,
|
/// any parent directory. The `--python` option allows you to specify a different interpreter,
|
||||||
/// which is intended for use in continuous integration (CI) environments or other automated
|
/// which is intended for use in continuous integration (CI) environments or other automated
|
||||||
/// workflows.
|
/// workflows.
|
||||||
#[clap(long)]
|
///
|
||||||
python: Option<PathBuf>,
|
/// Supported formats:
|
||||||
|
/// - `3.10` looks for an installed Python 3.10 using `py --list-paths` on Windows, or
|
||||||
|
/// `python3.10` on Linux and macOS. (Specifying a patch version is not supported.)
|
||||||
|
/// - `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.
|
||||||
|
#[clap(long, short, verbatim_doc_comment)]
|
||||||
|
python: Option<String>,
|
||||||
|
|
||||||
/// Use legacy `setuptools` behavior when building source distributions without a
|
/// Use legacy `setuptools` behavior when building source distributions without a
|
||||||
/// `pyproject.toml`.
|
/// `pyproject.toml`.
|
||||||
|
|
@ -623,8 +629,14 @@ struct PipInstallArgs {
|
||||||
/// any parent directory. The `--python` option allows you to specify a different interpreter,
|
/// any parent directory. The `--python` option allows you to specify a different interpreter,
|
||||||
/// which is intended for use in continuous integration (CI) environments or other automated
|
/// which is intended for use in continuous integration (CI) environments or other automated
|
||||||
/// workflows.
|
/// workflows.
|
||||||
#[clap(long)]
|
///
|
||||||
python: Option<PathBuf>,
|
/// Supported formats:
|
||||||
|
/// - `3.10` looks for an installed Python 3.10 using `py --list-paths` on Windows, or
|
||||||
|
/// `python3.10` on Linux and macOS. (Specifying a patch version is not supported.)
|
||||||
|
/// - `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.
|
||||||
|
#[clap(long, short, verbatim_doc_comment)]
|
||||||
|
python: Option<String>,
|
||||||
|
|
||||||
/// Use legacy `setuptools` behavior when building source distributions without a
|
/// Use legacy `setuptools` behavior when building source distributions without a
|
||||||
/// `pyproject.toml`.
|
/// `pyproject.toml`.
|
||||||
|
|
@ -701,8 +713,14 @@ struct PipUninstallArgs {
|
||||||
/// any parent directory. The `--python` option allows you to specify a different interpreter,
|
/// any parent directory. The `--python` option allows you to specify a different interpreter,
|
||||||
/// which is intended for use in continuous integration (CI) environments or other automated
|
/// which is intended for use in continuous integration (CI) environments or other automated
|
||||||
/// workflows.
|
/// workflows.
|
||||||
#[clap(long)]
|
///
|
||||||
python: Option<PathBuf>,
|
/// Supported formats:
|
||||||
|
/// - `3.10` looks for an installed Python 3.10 using `py --list-paths` on Windows, or
|
||||||
|
/// `python3.10` on Linux and macOS. (Specifying a patch version is not supported.)
|
||||||
|
/// - `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.
|
||||||
|
#[clap(long, short, verbatim_doc_comment)]
|
||||||
|
python: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|
@ -741,14 +759,13 @@ struct VenvArgs {
|
||||||
/// The Python interpreter to use for the virtual environment.
|
/// The Python interpreter to use for the virtual environment.
|
||||||
///
|
///
|
||||||
/// Supported formats:
|
/// Supported formats:
|
||||||
/// - `3.10` searches for an installed Python 3.10 (`py --list-paths` on Windows, `python3.10` on Linux/Mac).
|
/// - `3.10` looks for an installed Python 3.10 using `py --list-paths` on Windows, or
|
||||||
/// Specifying a patch version is not supported.
|
/// `python3.10` on Linux and macOS. (Specifying a patch version is not supported.)
|
||||||
/// - `python3.10` or `python.exe` looks for a binary in `PATH`.
|
/// - `python3.10` or `python.exe` looks for a binary with the given name in `PATH`.
|
||||||
/// - `/home/ferris/.local/bin/python3.10` uses this exact Python.
|
/// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path.
|
||||||
///
|
///
|
||||||
/// Note that this is different from `--python-version` in `pip compile`, which takes `3.10` or `3.10.13` and
|
/// Note that this is different from `--python-version` in `pip compile`, which takes `3.10` or `3.10.13` and
|
||||||
/// doesn't look for a Python interpreter on disk.
|
/// doesn't look for a Python interpreter on disk.
|
||||||
// Short `-p` to match `virtualenv`
|
|
||||||
#[clap(long, short, verbatim_doc_comment)]
|
#[clap(long, short, verbatim_doc_comment)]
|
||||||
python: Option<String>,
|
python: Option<String>,
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue