mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
Respect .python-version
in uv venv --preview
(#4360)
Adds support for reading Python version files (introduced in #4335) to `uv venv`. If present, we'll use the file version as the default.
This commit is contained in:
parent
76c26db444
commit
903dfc2f1f
6 changed files with 125 additions and 12 deletions
|
@ -1,6 +1,6 @@
|
|||
3.8.12
|
||||
3.8.18
|
||||
3.9.18
|
||||
3.10.13
|
||||
3.11.7
|
||||
3.12.1
|
||||
3.11.7
|
||||
3.10.13
|
||||
3.9.18
|
||||
3.8.18
|
||||
3.8.12
|
||||
|
|
|
@ -13,7 +13,7 @@ pub use crate::prefix::Prefix;
|
|||
pub use crate::python_version::PythonVersion;
|
||||
pub use crate::target::Target;
|
||||
pub use crate::toolchain::Toolchain;
|
||||
pub use crate::version_files::{request_from_version_files, requests_from_version_files};
|
||||
pub use crate::version_files::{request_from_version_file, requests_from_version_file};
|
||||
pub use crate::virtualenv::{Error as VirtualEnvError, PyVenvConfiguration, VirtualEnvironment};
|
||||
|
||||
mod discovery;
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::ToolchainRequest;
|
|||
///
|
||||
/// Prefers `.python-versions` then `.python-version`.
|
||||
/// If only one Python version is desired, use [`request_from_version_files`] which prefers the `.python-version` file.
|
||||
pub async fn requests_from_version_files() -> Result<Option<Vec<ToolchainRequest>>, io::Error> {
|
||||
pub async fn requests_from_version_file() -> Result<Option<Vec<ToolchainRequest>>, io::Error> {
|
||||
if let Some(versions) = read_versions_file().await? {
|
||||
Ok(Some(
|
||||
versions
|
||||
|
@ -27,7 +27,7 @@ pub async fn requests_from_version_files() -> Result<Option<Vec<ToolchainRequest
|
|||
///
|
||||
/// Prefers `.python-version` then the first entry of `.python-versions`.
|
||||
/// If multiple Python versions are desired, use [`requests_from_version_files`] instead.
|
||||
pub async fn request_from_version_files() -> Result<Option<ToolchainRequest>, io::Error> {
|
||||
pub async fn request_from_version_file() -> Result<Option<ToolchainRequest>, io::Error> {
|
||||
if let Some(version) = read_version_file().await? {
|
||||
Ok(Some(ToolchainRequest::parse(&version)))
|
||||
} else if let Some(versions) = read_versions_file().await? {
|
||||
|
|
|
@ -8,7 +8,7 @@ use uv_configuration::PreviewMode;
|
|||
use uv_fs::Simplified;
|
||||
use uv_toolchain::downloads::{self, DownloadResult, PythonDownload, PythonDownloadRequest};
|
||||
use uv_toolchain::managed::{InstalledToolchain, InstalledToolchains};
|
||||
use uv_toolchain::{requests_from_version_files, ToolchainRequest};
|
||||
use uv_toolchain::{requests_from_version_file, ToolchainRequest};
|
||||
use uv_warnings::warn_user;
|
||||
|
||||
use crate::commands::ExitStatus;
|
||||
|
@ -35,7 +35,7 @@ pub(crate) async fn install(
|
|||
let toolchain_dir = toolchains.root();
|
||||
|
||||
let requests: Vec<_> = if targets.is_empty() {
|
||||
if let Some(requests) = requests_from_version_files().await? {
|
||||
if let Some(requests) = requests_from_version_file().await? {
|
||||
requests
|
||||
} else {
|
||||
vec![ToolchainRequest::Any]
|
||||
|
|
|
@ -23,7 +23,7 @@ use uv_dispatch::BuildDispatch;
|
|||
use uv_fs::Simplified;
|
||||
use uv_git::GitResolver;
|
||||
use uv_resolver::{ExcludeNewer, FlatIndex, InMemoryIndex, OptionsBuilder};
|
||||
use uv_toolchain::{SystemPython, Toolchain, ToolchainRequest};
|
||||
use uv_toolchain::{request_from_version_file, SystemPython, Toolchain, ToolchainRequest};
|
||||
use uv_types::{BuildContext, BuildIsolation, HashStrategy, InFlight};
|
||||
|
||||
use crate::commands::{pip, ExitStatus};
|
||||
|
@ -125,9 +125,14 @@ async fn venv_impl(
|
|||
.connectivity(connectivity)
|
||||
.native_tls(native_tls);
|
||||
|
||||
let mut interpreter_request = python_request.map(ToolchainRequest::parse);
|
||||
if preview.is_enabled() && interpreter_request.is_none() {
|
||||
interpreter_request = request_from_version_file().await.into_diagnostic()?;
|
||||
}
|
||||
|
||||
// Locate the Python interpreter to use in the environment
|
||||
let interpreter = Toolchain::find_or_fetch(
|
||||
python_request.map(ToolchainRequest::parse),
|
||||
interpreter_request,
|
||||
SystemPython::Required,
|
||||
preview,
|
||||
client_builder,
|
||||
|
|
|
@ -88,6 +88,114 @@ fn create_venv_ignores_virtual_env_variable() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_venv_reads_request_from_python_version_file() {
|
||||
let context = TestContext::new_with_versions(&["3.11", "3.12"]);
|
||||
|
||||
// Without the file, we should use the first on the PATH
|
||||
uv_snapshot!(context.filters(), context.venv()
|
||||
.arg("--preview"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.11.[X] interpreter at: [PYTHON-3.11]
|
||||
Creating virtualenv at: .venv
|
||||
Activate with: source .venv/bin/activate
|
||||
"###
|
||||
);
|
||||
|
||||
// With a version file, we should prefer that version
|
||||
context
|
||||
.temp_dir
|
||||
.child(".python-version")
|
||||
.write_str("3.12")
|
||||
.unwrap();
|
||||
|
||||
uv_snapshot!(context.filters(), context.venv()
|
||||
.arg("--preview"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.12.[X] interpreter at: [PYTHON-3.12]
|
||||
Creating virtualenv at: .venv
|
||||
Activate with: source .venv/bin/activate
|
||||
"###
|
||||
);
|
||||
|
||||
context.venv.assert(predicates::path::is_dir());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_venv_reads_request_from_python_versions_file() {
|
||||
let context = TestContext::new_with_versions(&["3.11", "3.12"]);
|
||||
|
||||
// Without the file, we should use the first on the PATH
|
||||
uv_snapshot!(context.filters(), context.venv()
|
||||
.arg("--preview"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.11.[X] interpreter at: [PYTHON-3.11]
|
||||
Creating virtualenv at: .venv
|
||||
Activate with: source .venv/bin/activate
|
||||
"###
|
||||
);
|
||||
|
||||
// With a versions file, we should prefer the first listed version
|
||||
context
|
||||
.temp_dir
|
||||
.child(".python-versions")
|
||||
.write_str("3.12\n3.11")
|
||||
.unwrap();
|
||||
|
||||
uv_snapshot!(context.filters(), context.venv()
|
||||
.arg("--preview"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.12.[X] interpreter at: [PYTHON-3.12]
|
||||
Creating virtualenv at: .venv
|
||||
Activate with: source .venv/bin/activate
|
||||
"###
|
||||
);
|
||||
|
||||
context.venv.assert(predicates::path::is_dir());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_venv_explicit_request_takes_priority_over_python_version_file() {
|
||||
let context = TestContext::new_with_versions(&["3.11", "3.12"]);
|
||||
|
||||
context
|
||||
.temp_dir
|
||||
.child(".python-version")
|
||||
.write_str("3.12")
|
||||
.unwrap();
|
||||
|
||||
uv_snapshot!(context.filters(), context.venv()
|
||||
.arg("--preview").arg("--python").arg("3.11"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.11.[X] interpreter at: [PYTHON-3.11]
|
||||
Creating virtualenv at: .venv
|
||||
Activate with: source .venv/bin/activate
|
||||
"###
|
||||
);
|
||||
|
||||
context.venv.assert(predicates::path::is_dir());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn seed() {
|
||||
let context = TestContext::new_with_versions(&["3.12"]);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue