mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 02:48:17 +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?")]
|
||||
PythonNotFound,
|
||||
#[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)]
|
||||
Io(#[from] io::Error),
|
||||
#[error("Failed to query python interpreter `{interpreter}`")]
|
||||
|
|
|
@ -9,7 +9,7 @@ use uv_fs::{LockedFile, Normalized};
|
|||
|
||||
use crate::cfg::PyVenvConfiguration;
|
||||
use crate::python_platform::PythonPlatform;
|
||||
use crate::{Error, Interpreter};
|
||||
use crate::{find_requested_python, Error, Interpreter};
|
||||
|
||||
/// A Python executable and its associated platform markers.
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -19,24 +19,11 @@ pub struct Virtualenv {
|
|||
}
|
||||
|
||||
impl Virtualenv {
|
||||
/// Create a new virtual environment for a pre-provided Python interpreter.
|
||||
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.
|
||||
/// Create a [`Virtualenv`] for an existing virtual environment.
|
||||
pub fn from_env(platform: Platform, cache: &Cache) -> Result<Self, Error> {
|
||||
let platform = PythonPlatform::from(platform);
|
||||
let Some(venv) = detect_virtual_env(&platform)? else {
|
||||
return Err(Error::NotFound);
|
||||
return Err(Error::VenvNotFound);
|
||||
};
|
||||
let venv = fs_err::canonicalize(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 {
|
||||
Self {
|
||||
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.
|
||||
pub fn root(&self) -> &Path {
|
||||
&self.root
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::collections::HashSet;
|
||||
use std::fmt::Write;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
|
||||
use anstream::eprint;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
|
@ -63,7 +62,7 @@ pub(crate) async fn pip_install(
|
|||
no_binary: &NoBinary,
|
||||
strict: bool,
|
||||
exclude_newer: Option<DateTime<Utc>>,
|
||||
python: Option<PathBuf>,
|
||||
python: Option<String>,
|
||||
cache: Cache,
|
||||
mut printer: Printer,
|
||||
) -> Result<ExitStatus> {
|
||||
|
@ -106,8 +105,8 @@ pub(crate) async fn pip_install(
|
|||
|
||||
// Detect the current Python interpreter.
|
||||
let platform = Platform::current()?;
|
||||
let venv = if let Some(python) = python {
|
||||
Virtualenv::from_python(python, platform, &cache)?
|
||||
let venv = if let Some(python) = python.as_ref() {
|
||||
Virtualenv::from_requested_python(python, &platform, &cache)?
|
||||
} else {
|
||||
Virtualenv::from_env(platform, &cache)?
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use std::fmt::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use itertools::Itertools;
|
||||
|
@ -42,7 +41,7 @@ pub(crate) async fn pip_sync(
|
|||
no_build: &NoBuild,
|
||||
no_binary: &NoBinary,
|
||||
strict: bool,
|
||||
python: Option<PathBuf>,
|
||||
python: Option<String>,
|
||||
cache: Cache,
|
||||
mut printer: Printer,
|
||||
) -> Result<ExitStatus> {
|
||||
|
@ -74,8 +73,8 @@ pub(crate) async fn pip_sync(
|
|||
|
||||
// Detect the current Python interpreter.
|
||||
let platform = Platform::current()?;
|
||||
let venv = if let Some(python) = python {
|
||||
Virtualenv::from_python(python, platform, &cache)?
|
||||
let venv = if let Some(python) = python.as_ref() {
|
||||
Virtualenv::from_requested_python(python, &platform, &cache)?
|
||||
} else {
|
||||
Virtualenv::from_env(platform, &cache)?
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use std::fmt::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Result;
|
||||
use owo_colors::OwoColorize;
|
||||
|
@ -18,7 +17,7 @@ use crate::requirements::{RequirementsSource, RequirementsSpecification};
|
|||
/// Uninstall packages from the current environment.
|
||||
pub(crate) async fn pip_uninstall(
|
||||
sources: &[RequirementsSource],
|
||||
python: Option<PathBuf>,
|
||||
python: Option<String>,
|
||||
cache: Cache,
|
||||
mut printer: Printer,
|
||||
) -> Result<ExitStatus> {
|
||||
|
@ -40,8 +39,8 @@ pub(crate) async fn pip_uninstall(
|
|||
|
||||
// Detect the current Python interpreter.
|
||||
let platform = Platform::current()?;
|
||||
let venv = if let Some(python) = python {
|
||||
Virtualenv::from_python(python, platform, &cache)?
|
||||
let venv = if let Some(python) = python.as_ref() {
|
||||
Virtualenv::from_requested_python(python, &platform, &cache)?
|
||||
} else {
|
||||
Virtualenv::from_env(platform, &cache)?
|
||||
};
|
||||
|
|
|
@ -445,8 +445,14 @@ struct PipSyncArgs {
|
|||
/// 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
|
||||
/// 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
|
||||
/// `pyproject.toml`.
|
||||
|
@ -623,8 +629,14 @@ struct PipInstallArgs {
|
|||
/// 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
|
||||
/// 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
|
||||
/// `pyproject.toml`.
|
||||
|
@ -701,8 +713,14 @@ struct PipUninstallArgs {
|
|||
/// 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
|
||||
/// 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)]
|
||||
|
@ -741,14 +759,13 @@ struct VenvArgs {
|
|||
/// The Python interpreter to use for the virtual environment.
|
||||
///
|
||||
/// Supported formats:
|
||||
/// - `3.10` searches for an installed Python 3.10 (`py --list-paths` on Windows, `python3.10` on Linux/Mac).
|
||||
/// Specifying a patch version is not supported.
|
||||
/// - `python3.10` or `python.exe` looks for a binary in `PATH`.
|
||||
/// - `/home/ferris/.local/bin/python3.10` uses this exact Python.
|
||||
/// - `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.
|
||||
///
|
||||
/// 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.
|
||||
// Short `-p` to match `virtualenv`
|
||||
#[clap(long, short, verbatim_doc_comment)]
|
||||
python: Option<String>,
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue