Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow -p to use complex Python version requests in uv pip compile #11486

Merged
merged 6 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1079,15 +1079,23 @@ pub struct PipCompileArgs {

/// The Python interpreter to use during resolution.
///
/// A Python interpreter is required for building source distributions to
/// determine package metadata when there are not wheels.
/// A Python interpreter is required for building source distributions to determine package
/// metadata when there are not wheels.
///
/// The interpreter is also used to determine the default minimum Python version, unless
/// `--python-version` is provided.
///
/// The interpreter is also used to determine the default minimum Python
/// version, unless `--python-version` is provided.
/// This option respects `UV_PYTHON`, but when set via environment variable, it is overridden
/// by `--python-version`.
///
/// See `uv help python` for details on Python discovery and supported
/// request formats.
#[arg(long, verbatim_doc_comment, help_heading = "Python options", value_parser = parse_maybe_string)]
/// See `uv help python` for details on Python discovery and supported request formats.
#[arg(
long,
short,
verbatim_doc_comment,
help_heading = "Python options",
value_parser = parse_maybe_string
)]
pub python: Option<Maybe<String>>,

/// Install packages into the system Python environment.
Expand Down Expand Up @@ -1170,7 +1178,7 @@ pub struct PipCompileArgs {
///
/// If a patch version is omitted, the minimum patch version is assumed. For
/// example, `3.8` is mapped to `3.8.0`.
#[arg(long, short, help_heading = "Python options")]
#[arg(long, help_heading = "Python options")]
pub python_version: Option<PythonVersion>,

/// The platform for which requirements should be resolved.
Expand Down
33 changes: 29 additions & 4 deletions crates/uv/src/commands/pip/compile.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::BTreeSet;
use std::env;
use std::path::Path;
use std::str::FromStr;
use std::sync::Arc;

use anyhow::{anyhow, Result};
Expand Down Expand Up @@ -86,14 +87,14 @@ pub(crate) async fn pip_compile(
no_build_isolation: bool,
no_build_isolation_package: Vec<PackageName>,
build_options: BuildOptions,
python_version: Option<PythonVersion>,
mut python_version: Option<PythonVersion>,
python_platform: Option<TargetTriple>,
universal: bool,
exclude_newer: Option<ExcludeNewer>,
sources: SourceStrategy,
annotation_style: AnnotationStyle,
link_mode: LinkMode,
python: Option<String>,
mut python: Option<String>,
system: bool,
python_preference: PythonPreference,
concurrency: Concurrency,
Expand All @@ -103,6 +104,29 @@ pub(crate) async fn pip_compile(
printer: Printer,
preview: PreviewMode,
) -> Result<ExitStatus> {
// Respect `UV_PYTHON`
if python.is_none() && python_version.is_none() {
if let Ok(request) = std::env::var("UV_PYTHON") {
if !request.is_empty() {
python = Some(request);
}
}
}

// If `--python` / `-p` is a simple Python version request, we treat it as `--python-version`
// for backwards compatibility. `-p` was previously aliased to `--python-version` but changed to
// `--python` for consistency with the rest of the CLI in v0.6.0. Since we assume metadata is
// consistent across wheels, it's okay for us to build wheels (to determine metadata) with an
// alternative Python interpreter as long as we solve with the proper Python version tags.
if python_version.is_none() {
if let Some(request) = python.as_ref() {
if let Ok(version) = PythonVersion::from_str(request) {
python_version = Some(version);
python = None;
}
}
}

// If the user requests `extras` but does not provide a valid source (e.g., a `pyproject.toml`),
// return an error.
if !extras.is_empty() && !requirements.iter().any(RequirementsSource::allows_extras) {
Expand Down Expand Up @@ -189,8 +213,8 @@ pub(crate) async fn pip_compile(
let request = PythonRequest::parse(python);
PythonInstallation::find(&request, environment_preference, python_preference, &cache)
} else {
// TODO(zanieb): The split here hints at a problem with the abstraction; we should be able to use
// `PythonInstallation::find(...)` here.
// TODO(zanieb): The split here hints at a problem with the request abstraction; we should
// be able to use `PythonInstallation::find(...)` here.
let request = if let Some(version) = python_version.as_ref() {
// TODO(zanieb): We should consolidate `VersionRequest` and `PythonVersion`
PythonRequest::Version(VersionRequest::from(version))
Expand All @@ -216,6 +240,7 @@ pub(crate) async fn pip_compile(
&& python_version.minor() == interpreter.python_minor()
};
if no_build.is_none()
&& python.is_none()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoids warning if --python intentionally requested a different interpreter than --python-version.

&& python_version.version() != interpreter.python_version()
&& (python_version.patch().is_some() || !matches_without_patch)
{
Expand Down
Loading
Loading