diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index 1887ba9be76c..676ac0ee452a 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -1170,9 +1170,20 @@ 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, + /// The Python interpreter or version to use for resolution. + /// + /// In previous versions of uv, `-p` was an alias for `--python-version` in `uv pip compile` but + /// an alias for `--python` in all other commands. This option is provided as a backwards + /// compatible shim, allowing `-p` to behave as `--python` without introducing a breaking + /// change. + /// + /// `UV_PYTHON` is respected, but overridden by `--python-version` or `--python`. + #[arg(short, hide = true, help_heading = "Python options")] + pub python_legacy: Option, + /// The platform for which requirements should be resolved. /// /// Represented as a "target triple", a string that describes the target platform in terms of diff --git a/crates/uv/src/commands/pip/compile.rs b/crates/uv/src/commands/pip/compile.rs index 0dc21a51273c..da8a6b1cf028 100644 --- a/crates/uv/src/commands/pip/compile.rs +++ b/crates/uv/src/commands/pip/compile.rs @@ -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}; @@ -38,6 +39,7 @@ use uv_resolver::{ InMemoryIndex, OptionsBuilder, PrereleaseMode, PythonRequirement, RequiresPython, ResolutionMode, ResolverEnvironment, }; +use uv_static::EnvVars; use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy}; use uv_warnings::warn_user; @@ -86,14 +88,15 @@ pub(crate) async fn pip_compile( no_build_isolation: bool, no_build_isolation_package: Vec, build_options: BuildOptions, - python_version: Option, + mut python_version: Option, python_platform: Option, universal: bool, exclude_newer: Option, sources: SourceStrategy, annotation_style: AnnotationStyle, link_mode: LinkMode, - python: Option, + mut python: Option, + mut python_legacy: Option, system: bool, python_preference: PythonPreference, concurrency: Concurrency, @@ -103,6 +106,38 @@ pub(crate) async fn pip_compile( printer: Printer, preview: PreviewMode, ) -> Result { + // If the user requests both `-p` and `--python` or `--python-version`, error + if let Some(python_legacy) = python_legacy.as_ref() { + if let Some(python) = python.as_ref() { + return Err(anyhow!( + "Cannot specify both `-p` ({python_legacy}) and `--python` ({python}).", + )); + } + if let Some(python_version) = python_version.as_ref() { + return Err(anyhow!( + "Cannot specify both `-p` ({python_legacy}) and `--python-version` ({python_version}).", + )); + } + } + + // Respect `UV_PYTHON` with legacy behavior + if python_legacy.is_none() && python_version.is_none() && python.is_none() { + if let Ok(python) = std::env::var(EnvVars::UV_PYTHON) { + if !python.is_empty() { + python_legacy = Some(python); + } + } + } + + // Resolve `-p` into `--python-version` or `--python` + if let Some(python_legacy) = python_legacy { + if let Ok(version) = PythonVersion::from_str(&python_legacy) { + python_version = Some(version); + } else { + python = Some(python_legacy); + } + } + // 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) { @@ -189,8 +224,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)) diff --git a/crates/uv/src/lib.rs b/crates/uv/src/lib.rs index 2cdb7df1455f..69fb4b3adf60 100644 --- a/crates/uv/src/lib.rs +++ b/crates/uv/src/lib.rs @@ -428,6 +428,7 @@ async fn run(mut cli: Cli) -> Result { args.settings.annotation_style, args.settings.link_mode, args.settings.python, + args.python_legacy, args.settings.system, globals.python_preference, globals.concurrency, diff --git a/crates/uv/src/settings.rs b/crates/uv/src/settings.rs index f5864066be0d..5c51b2b1cc64 100644 --- a/crates/uv/src/settings.rs +++ b/crates/uv/src/settings.rs @@ -1542,6 +1542,7 @@ pub(crate) struct PipCompileSettings { pub(crate) overrides_from_workspace: Vec, pub(crate) environments: SupportedEnvironments, pub(crate) refresh: Refresh, + pub(crate) python_legacy: Option, pub(crate) settings: PipSettings, } @@ -1581,6 +1582,7 @@ impl PipCompileSettings { no_binary, only_binary, python_version, + python_legacy, python_platform, universal, no_universal, @@ -1650,6 +1652,7 @@ impl PipCompileSettings { overrides_from_workspace, environments, refresh: Refresh::from(refresh), + python_legacy, settings: PipSettings::combine( PipOptions { python: python.and_then(Maybe::into_option), diff --git a/crates/uv/tests/it/pip_compile.rs b/crates/uv/tests/it/pip_compile.rs index 53836facf568..36cf065cb710 100644 --- a/crates/uv/tests/it/pip_compile.rs +++ b/crates/uv/tests/it/pip_compile.rs @@ -1309,6 +1309,89 @@ fn compile_python_312() -> Result<()> { "### ); + // This should work with the short flag + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .arg("-p") + .arg("3.12"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + # This file was autogenerated by uv via the following command: + # uv pip compile --cache-dir [CACHE_DIR] requirements.in -p 3.12 + black==23.10.1 + # via -r requirements.in + click==8.1.7 + # via black + mypy-extensions==1.0.0 + # via black + packaging==24.0 + # via black + pathspec==0.12.1 + # via black + platformdirs==4.2.0 + # via black + + ----- stderr ----- + Resolved 6 packages in [TIME] + "### + ); + + // And `--python` + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .arg("--python") + .arg("3.12"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + # This file was autogenerated by uv via the following command: + # uv pip compile --cache-dir [CACHE_DIR] requirements.in --python 3.12 + black==23.10.1 + # via -r requirements.in + click==8.1.7 + # via black + mypy-extensions==1.0.0 + # via black + packaging==24.0 + # via black + pathspec==0.12.1 + # via black + platformdirs==4.2.0 + # via black + + ----- stderr ----- + Resolved 6 packages in [TIME] + "### + ); + + // And `UV_PYTHON` + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .env("UV_PYTHON", "3.12"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + # This file was autogenerated by uv via the following command: + # uv pip compile --cache-dir [CACHE_DIR] requirements.in + black==23.10.1 + # via -r requirements.in + click==8.1.7 + # via black + mypy-extensions==1.0.0 + # via black + packaging==24.0 + # via black + pathspec==0.12.1 + # via black + platformdirs==4.2.0 + # via black + + ----- stderr ----- + Resolved 6 packages in [TIME] + "### + ); + Ok(()) } @@ -1379,6 +1462,252 @@ fn compile_fallback_interpreter() -> Result<()> { "### ); + // This should work for the short flag too + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .arg("-p") + .arg("3.12"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + # This file was autogenerated by uv via the following command: + # uv pip compile --cache-dir [CACHE_DIR] requirements.in -p 3.12 + black==23.10.[X] + # via -r requirements.in + click==8.1.7 + # via black + mypy-extensions==1.0.0 + # via black + packaging==24.0 + # via black + pathspec==0.12.1 + # via black + platformdirs==4.2.0 + # via black + + ----- stderr ----- + warning: The requested Python version 3.12 is not available; 3.10.[X] will be used to build dependencies instead. + Resolved 6 packages in [TIME] + "### + ); + + // And for `UV_PYTHON` + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .env(EnvVars::UV_PYTHON, "3.12"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + # This file was autogenerated by uv via the following command: + # uv pip compile --cache-dir [CACHE_DIR] requirements.in + black==23.10.[X] + # via -r requirements.in + click==8.1.7 + # via black + mypy-extensions==1.0.0 + # via black + packaging==24.0 + # via black + pathspec==0.12.1 + # via black + platformdirs==4.2.0 + # via black + + ----- stderr ----- + warning: The requested Python version 3.12 is not available; 3.10.[X] will be used to build dependencies instead. + Resolved 6 packages in [TIME] + "### + ); + + // But fail for `--python` + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .arg("--python") + .arg("3.12"), @r###" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + error: No interpreter found for Python 3.12 in virtual environments, managed installations, or search path + "### + ); + + // The short flag also allows complex requests, like alternative implementations, but we should + // not fallback if that cannot be found + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .arg("-p") + .arg("pypy"), @r###" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + error: No interpreter found for PyPy in virtual environments, managed installations, or search path + "### + ); + + // Similarly, we fail if we receive a range request that cannot be satisfied + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .arg("-p") + .arg(">=3.12"), @r###" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + error: No interpreter found for Python >=3.12 in virtual environments, managed installations, or search path + "### + ); + + Ok(()) +} + +#[test] +fn compile_python_conflicts() -> Result<()> { + let context = TestContext::new("3.12"); + let requirements_in = context.temp_dir.child("requirements.in"); + requirements_in.write_str("black==23.10.1")?; + + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .arg("--python-version") + .arg("3.12") + .arg("-p") + .arg("3.12"), @r###" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + error: Cannot specify both `-p` (3.12) and `--python-version` (3.12). + "### + ); + + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .arg("--python") + .arg("3.12") + .arg("-p") + .arg("3.12"), @r###" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + error: Cannot specify both `-p` (3.12) and `--python` (3.12). + "### + ); + + // `UV_PYTHON` should be usable with `-p` + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .arg("-p") + .arg("3.12") + .env("UV_PYTHON", "3.11"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + # This file was autogenerated by uv via the following command: + # uv pip compile --cache-dir [CACHE_DIR] requirements.in -p 3.12 + black==23.10.1 + # via -r requirements.in + click==8.1.7 + # via black + mypy-extensions==1.0.0 + # via black + packaging==24.0 + # via black + pathspec==0.12.1 + # via black + platformdirs==4.2.0 + # via black + + ----- stderr ----- + Resolved 6 packages in [TIME] + "### + ); + + // `UV_PYTHON` should be usable with `--python` + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .arg("--python") + .arg("3.12") + .env("UV_PYTHON", "3.11"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + # This file was autogenerated by uv via the following command: + # uv pip compile --cache-dir [CACHE_DIR] requirements.in --python 3.12 + black==23.10.1 + # via -r requirements.in + click==8.1.7 + # via black + mypy-extensions==1.0.0 + # via black + packaging==24.0 + # via black + pathspec==0.12.1 + # via black + platformdirs==4.2.0 + # via black + + ----- stderr ----- + Resolved 6 packages in [TIME] + "### + ); + + // `UV_PYTHON` should be usable with `--python-version` + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .arg("--python-version") + .arg("3.12") + .env("UV_PYTHON", "3.11"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + # This file was autogenerated by uv via the following command: + # uv pip compile --cache-dir [CACHE_DIR] requirements.in --python-version 3.12 + black==23.10.1 + # via -r requirements.in + click==8.1.7 + # via black + mypy-extensions==1.0.0 + # via black + packaging==24.0 + # via black + pathspec==0.12.1 + # via black + platformdirs==4.2.0 + # via black + + ----- stderr ----- + Resolved 6 packages in [TIME] + "### + ); + + // `--python-legacy` is not available in long-form + uv_snapshot!(context.filters(), context.pip_compile() + .arg("requirements.in") + .arg("--python-legacy") + .arg("3.12"), @r###" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + error: unexpected argument '--python-legacy' found + + tip: a similar argument exists: '--python' + + Usage: uv pip compile --cache-dir [CACHE_DIR] --python ... + + For more information, try '--help'. + "### + ); + Ok(()) } diff --git a/crates/uv/tests/it/show_settings.rs b/crates/uv/tests/it/show_settings.rs index cf05fc61b988..e708463d2101 100644 --- a/crates/uv/tests/it/show_settings.rs +++ b/crates/uv/tests/it/show_settings.rs @@ -51,7 +51,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> { // Resolution should use the lowest direct version, and generate hashes. uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") - .arg("requirements.in"), @r#" + .arg("requirements.in"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -101,6 +101,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -215,14 +216,14 @@ fn resolve_uv_toml() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // Resolution should use the highest version, and generate hashes. uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") .arg("requirements.in") - .arg("--resolution=highest"), @r#" + .arg("--resolution=highest"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -272,6 +273,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -386,7 +388,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // Resolution should use the highest version, and omit hashes. @@ -394,7 +396,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> { .arg("--show-settings") .arg("requirements.in") .arg("--resolution=highest") - .arg("--no-generate-hashes"), @r#" + .arg("--no-generate-hashes"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -444,6 +446,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -558,7 +561,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); Ok(()) @@ -598,7 +601,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> { // Resolution should use the lowest direct version, and generate hashes. uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") - .arg("requirements.in"), @r#" + .arg("requirements.in"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -648,6 +651,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -762,7 +766,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // Remove the `uv.toml` file. @@ -771,7 +775,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> { // Resolution should use the highest version, and omit hashes. uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") - .arg("requirements.in"), @r#" + .arg("requirements.in"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -821,6 +825,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [], @@ -905,7 +910,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // Add configuration to the `pyproject.toml` file. @@ -923,7 +928,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> { // Resolution should use the lowest direct version, and generate hashes. uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") - .arg("requirements.in"), @r#" + .arg("requirements.in"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -973,6 +978,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -1087,7 +1093,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); Ok(()) @@ -1119,7 +1125,7 @@ fn resolve_index_url() -> anyhow::Result<()> { uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") - .arg("requirements.in"), @r#" + .arg("requirements.in"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -1169,6 +1175,7 @@ fn resolve_index_url() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -1312,7 +1319,7 @@ fn resolve_index_url() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // Providing an additional index URL on the command-line should be merged with the @@ -1321,7 +1328,7 @@ fn resolve_index_url() -> anyhow::Result<()> { .arg("--show-settings") .arg("requirements.in") .arg("--extra-index-url") - .arg("https://test.pypi.org/simple"), @r#" + .arg("https://test.pypi.org/simple"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -1371,6 +1378,7 @@ fn resolve_index_url() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -1545,7 +1553,7 @@ fn resolve_index_url() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); Ok(()) @@ -1577,7 +1585,7 @@ fn resolve_find_links() -> anyhow::Result<()> { uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") - .arg("requirements.in"), @r#" + .arg("requirements.in"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -1627,6 +1635,7 @@ fn resolve_find_links() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [], @@ -1741,7 +1750,7 @@ fn resolve_find_links() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); Ok(()) @@ -1772,7 +1781,7 @@ fn resolve_top_level() -> anyhow::Result<()> { uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") - .arg("requirements.in"), @r#" + .arg("requirements.in"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -1822,6 +1831,7 @@ fn resolve_top_level() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [], @@ -1906,7 +1916,7 @@ fn resolve_top_level() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // Write out to both the top-level (`tool.uv`) and the pip section (`tool.uv.pip`). The @@ -1930,7 +1940,7 @@ fn resolve_top_level() -> anyhow::Result<()> { uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") - .arg("requirements.in"), @r#" + .arg("requirements.in"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -1980,6 +1990,7 @@ fn resolve_top_level() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -2123,14 +2134,14 @@ fn resolve_top_level() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // But the command-line should take precedence over both. uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") .arg("requirements.in") - .arg("--resolution=lowest-direct"), @r#" + .arg("--resolution=lowest-direct"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2180,6 +2191,7 @@ fn resolve_top_level() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -2323,7 +2335,7 @@ fn resolve_top_level() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); Ok(()) @@ -2354,7 +2366,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> { uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") .arg("requirements.in") - .env(EnvVars::XDG_CONFIG_HOME, xdg.path()), @r#" + .env(EnvVars::XDG_CONFIG_HOME, xdg.path()), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2404,6 +2416,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [], @@ -2488,7 +2501,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // Add a local configuration to generate hashes. @@ -2502,7 +2515,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> { uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") .arg("requirements.in") - .env(EnvVars::XDG_CONFIG_HOME, xdg.path()), @r#" + .env(EnvVars::XDG_CONFIG_HOME, xdg.path()), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2552,6 +2565,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [], @@ -2636,7 +2650,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // Add a local configuration to override the user configuration. @@ -2650,7 +2664,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> { uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") .arg("requirements.in") - .env(EnvVars::XDG_CONFIG_HOME, xdg.path()), @r#" + .env(EnvVars::XDG_CONFIG_HOME, xdg.path()), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2700,6 +2714,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [], @@ -2784,7 +2799,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // However, the user-level `tool.uv.pip` settings override the project-level `tool.uv` settings. @@ -2800,7 +2815,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> { uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") .arg("requirements.in") - .env(EnvVars::XDG_CONFIG_HOME, xdg.path()), @r#" + .env(EnvVars::XDG_CONFIG_HOME, xdg.path()), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2850,6 +2865,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [], @@ -2934,7 +2950,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); Ok(()) @@ -3128,7 +3144,7 @@ fn resolve_poetry_toml() -> anyhow::Result<()> { // Resolution should use the lowest direct version, and generate hashes. uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") - .arg("requirements.in"), @r#" + .arg("requirements.in"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -3178,6 +3194,7 @@ fn resolve_poetry_toml() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [], @@ -3262,7 +3279,7 @@ fn resolve_poetry_toml() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); Ok(()) @@ -3304,7 +3321,7 @@ fn resolve_both() -> anyhow::Result<()> { // Resolution should succeed, but warn that the `pip` section in `pyproject.toml` is ignored. uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") - .arg("requirements.in"), @r#" + .arg("requirements.in"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -3354,6 +3371,7 @@ fn resolve_both() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -3469,7 +3487,7 @@ fn resolve_both() -> anyhow::Result<()> { ----- stderr ----- warning: Found both a `uv.toml` file and a `[tool.uv]` section in an adjacent `pyproject.toml`. The `[tool.uv]` section will be ignored in favor of the `uv.toml` file. - "# + "### ); Ok(()) @@ -3598,7 +3616,7 @@ fn resolve_config_file() -> anyhow::Result<()> { .arg("--show-settings") .arg("--config-file") .arg(config.path()) - .arg("requirements.in"), @r#" + .arg("requirements.in"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -3648,6 +3666,7 @@ fn resolve_config_file() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -3762,7 +3781,7 @@ fn resolve_config_file() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // Write in `pyproject.toml` schema. @@ -3870,7 +3889,7 @@ fn resolve_skip_empty() -> anyhow::Result<()> { uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") .arg("requirements.in") - .current_dir(&child), @r#" + .current_dir(&child), @r###" success: true exit_code: 0 ----- stdout ----- @@ -3920,6 +3939,7 @@ fn resolve_skip_empty() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [], @@ -4004,7 +4024,7 @@ fn resolve_skip_empty() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // Adding a `tool.uv` section should cause us to ignore the `uv.toml`. @@ -4021,7 +4041,7 @@ fn resolve_skip_empty() -> anyhow::Result<()> { uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") .arg("requirements.in") - .current_dir(&child), @r#" + .current_dir(&child), @r###" success: true exit_code: 0 ----- stdout ----- @@ -4071,6 +4091,7 @@ fn resolve_skip_empty() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [], @@ -4155,7 +4176,7 @@ fn resolve_skip_empty() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); Ok(()) @@ -4180,7 +4201,7 @@ fn allow_insecure_host() -> anyhow::Result<()> { uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("--show-settings") - .arg("requirements.in"), @r#" + .arg("requirements.in"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -4241,6 +4262,7 @@ fn allow_insecure_host() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [], @@ -4325,7 +4347,7 @@ fn allow_insecure_host() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); Ok(()) @@ -4353,7 +4375,7 @@ fn index_priority() -> anyhow::Result<()> { .arg("requirements.in") .arg("--show-settings") .arg("--index-url") - .arg("https://cli.pypi.org/simple"), @r#" + .arg("https://cli.pypi.org/simple"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -4403,6 +4425,7 @@ fn index_priority() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -4548,14 +4571,14 @@ fn index_priority() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path()) .arg("requirements.in") .arg("--show-settings") .arg("--default-index") - .arg("https://cli.pypi.org/simple"), @r#" + .arg("https://cli.pypi.org/simple"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -4605,6 +4628,7 @@ fn index_priority() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -4750,7 +4774,7 @@ fn index_priority() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); let config = context.temp_dir.child("uv.toml"); @@ -4763,7 +4787,7 @@ fn index_priority() -> anyhow::Result<()> { .arg("requirements.in") .arg("--show-settings") .arg("--default-index") - .arg("https://cli.pypi.org/simple"), @r#" + .arg("https://cli.pypi.org/simple"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -4813,6 +4837,7 @@ fn index_priority() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -4958,7 +4983,7 @@ fn index_priority() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // Prefer the `--index` from the CLI, but treat the index from the file as the default. @@ -4966,7 +4991,7 @@ fn index_priority() -> anyhow::Result<()> { .arg("requirements.in") .arg("--show-settings") .arg("--index") - .arg("https://cli.pypi.org/simple"), @r#" + .arg("https://cli.pypi.org/simple"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -5016,6 +5041,7 @@ fn index_priority() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -5161,7 +5187,7 @@ fn index_priority() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); let config = context.temp_dir.child("uv.toml"); @@ -5176,7 +5202,7 @@ fn index_priority() -> anyhow::Result<()> { .arg("requirements.in") .arg("--show-settings") .arg("--index-url") - .arg("https://cli.pypi.org/simple"), @r#" + .arg("https://cli.pypi.org/simple"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -5226,6 +5252,7 @@ fn index_priority() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -5371,7 +5398,7 @@ fn index_priority() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); // Prefer the `--extra-index-url` from the CLI, but not as the default. @@ -5379,7 +5406,7 @@ fn index_priority() -> anyhow::Result<()> { .arg("requirements.in") .arg("--show-settings") .arg("--extra-index-url") - .arg("https://cli.pypi.org/simple"), @r#" + .arg("https://cli.pypi.org/simple"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -5429,6 +5456,7 @@ fn index_priority() -> anyhow::Result<()> { }, ), ), + python_legacy: None, settings: PipSettings { index_locations: IndexLocations { indexes: [ @@ -5574,7 +5602,7 @@ fn index_priority() -> anyhow::Result<()> { } ----- stderr ----- - "# + "### ); Ok(()) diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 8d6be84c413b..ab17a2654f3f 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -5955,7 +5955,7 @@ uv pip compile [OPTIONS] ...
  • only-system: Only use system Python installations; never use managed Python installations
  • -
    --python-version, -p python-version

    The Python version to use for resolution.

    +
    --python-version python-version

    The Python version to use for resolution.

    For example, 3.8 or 3.8.17.