mirror of
https://github.com/astral-sh/uv.git
synced 2025-09-27 04:29:10 +00:00
Ignore virtual environments in parent directories when choosing Python version for new projects (#9075)
Some checks are pending
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86_64 (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on linux (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on opensuse (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | python3.10 on windows (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on linux (push) Blocked by required conditions
CI / check system | conda3.8 on linux (push) Blocked by required conditions
CI / check system | conda3.11 on macos (push) Blocked by required conditions
CI / check system | conda3.8 on macos (push) Blocked by required conditions
CI / check system | conda3.11 on windows (push) Blocked by required conditions
CI / check system | conda3.8 on windows (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
Some checks are pending
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86_64 (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on linux (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on opensuse (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | python3.10 on windows (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on linux (push) Blocked by required conditions
CI / check system | conda3.8 on linux (push) Blocked by required conditions
CI / check system | conda3.11 on macos (push) Blocked by required conditions
CI / check system | conda3.8 on macos (push) Blocked by required conditions
CI / check system | conda3.11 on windows (push) Blocked by required conditions
CI / check system | conda3.8 on windows (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
`uv init` shouldn't have been using `EnvironmentPreference::Any` for discovery of a Python interpreter, it seems like an oversight that it was reading from virtual environments. I changed it to `EnvironmentPreference::OnlySystem` so we'll use the first Python on the `PATH` instead. However, I think we actually do want to respect a virtual environment's Python version if it's in the target project directory already, so I've implemented that as well. Closes https://github.com/astral-sh/uv/issues/9072 Closes https://github.com/astral-sh/uv/issues/8092
This commit is contained in:
parent
95e7d8702f
commit
cb430b8d44
2 changed files with 127 additions and 8 deletions
|
@ -17,8 +17,9 @@ use uv_git::GIT;
|
|||
use uv_pep440::Version;
|
||||
use uv_pep508::PackageName;
|
||||
use uv_python::{
|
||||
EnvironmentPreference, PythonDownloads, PythonInstallation, PythonPreference, PythonRequest,
|
||||
PythonVariant, PythonVersionFile, VersionFileDiscoveryOptions, VersionRequest,
|
||||
EnvironmentPreference, PythonDownloads, PythonEnvironment, PythonInstallation,
|
||||
PythonPreference, PythonRequest, PythonVariant, PythonVersionFile, VersionFileDiscoveryOptions,
|
||||
VersionRequest,
|
||||
};
|
||||
use uv_resolver::RequiresPython;
|
||||
use uv_scripts::{Pep723Script, ScriptTag};
|
||||
|
@ -409,7 +410,7 @@ async fn init_project(
|
|||
} else {
|
||||
let interpreter = PythonInstallation::find_or_download(
|
||||
Some(python_request),
|
||||
EnvironmentPreference::Any,
|
||||
EnvironmentPreference::OnlySystem,
|
||||
python_preference,
|
||||
python_downloads,
|
||||
&client_builder,
|
||||
|
@ -431,7 +432,7 @@ async fn init_project(
|
|||
python_request => {
|
||||
let interpreter = PythonInstallation::find_or_download(
|
||||
Some(&python_request),
|
||||
EnvironmentPreference::Any,
|
||||
EnvironmentPreference::OnlySystem,
|
||||
python_preference,
|
||||
python_downloads,
|
||||
&client_builder,
|
||||
|
@ -457,8 +458,29 @@ async fn init_project(
|
|||
(requires_python, python_request)
|
||||
}
|
||||
}
|
||||
} else if let Ok(virtualenv) = PythonEnvironment::from_root(path.join(".venv"), cache) {
|
||||
// (2) An existing Python environment in the target directory
|
||||
debug!("Using Python version from existing virtual environment in project");
|
||||
let interpreter = virtualenv.into_interpreter();
|
||||
|
||||
let requires_python =
|
||||
RequiresPython::greater_than_equal_version(&interpreter.python_minor_version());
|
||||
|
||||
// Pin to the minor version.
|
||||
let python_request = if no_pin_python {
|
||||
None
|
||||
} else {
|
||||
Some(PythonRequest::Version(VersionRequest::MajorMinor(
|
||||
interpreter.python_major(),
|
||||
interpreter.python_minor(),
|
||||
PythonVariant::Default,
|
||||
)))
|
||||
};
|
||||
|
||||
(requires_python, python_request)
|
||||
} else if let Some(requires_python) = workspace.as_ref().and_then(find_requires_python) {
|
||||
// (2) `requires-python` from the workspace
|
||||
// (3) `requires-python` from the workspace
|
||||
debug!("Using Python version from project workspace");
|
||||
let python_request = PythonRequest::Version(VersionRequest::Range(
|
||||
requires_python.specifiers().clone(),
|
||||
PythonVariant::Default,
|
||||
|
@ -470,7 +492,7 @@ async fn init_project(
|
|||
} else {
|
||||
let interpreter = PythonInstallation::find_or_download(
|
||||
Some(&python_request),
|
||||
EnvironmentPreference::Any,
|
||||
EnvironmentPreference::OnlySystem,
|
||||
python_preference,
|
||||
python_downloads,
|
||||
&client_builder,
|
||||
|
@ -489,10 +511,10 @@ async fn init_project(
|
|||
|
||||
(requires_python, python_request)
|
||||
} else {
|
||||
// (3) Default to the system Python
|
||||
// (4) Default to the system Python
|
||||
let interpreter = PythonInstallation::find_or_download(
|
||||
None,
|
||||
EnvironmentPreference::Any,
|
||||
EnvironmentPreference::OnlySystem,
|
||||
python_preference,
|
||||
python_downloads,
|
||||
&client_builder,
|
||||
|
|
|
@ -2042,6 +2042,103 @@ fn init_requires_python_version_file() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Run `uv init`, inferring the Python version from an existing `.venv`
|
||||
#[test]
|
||||
fn init_existing_environment() -> Result<()> {
|
||||
let context = TestContext::new_with_versions(&["3.8", "3.12"]);
|
||||
|
||||
let child = context.temp_dir.child("foo");
|
||||
child.create_dir_all()?;
|
||||
|
||||
// Create a new virtual environment in the directory
|
||||
uv_snapshot!(context.filters(), context.venv().current_dir(&child).arg("--python").arg("3.12"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
|
||||
Creating virtual environment at: .venv
|
||||
Activate with: source .venv/[BIN]/activate
|
||||
"###);
|
||||
|
||||
uv_snapshot!(context.filters(), context.init().current_dir(&context.temp_dir).arg(child.as_os_str()), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Initialized project `foo` at `[TEMP_DIR]/foo`
|
||||
"###);
|
||||
|
||||
let pyproject_toml = fs_err::read_to_string(child.join("pyproject.toml"))?;
|
||||
insta::with_settings!({
|
||||
filters => context.filters(),
|
||||
}, {
|
||||
assert_snapshot!(
|
||||
pyproject_toml, @r###"
|
||||
[project]
|
||||
name = "foo"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = []
|
||||
"###
|
||||
);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run `uv init`, it should ignore a the Python version from a parent `.venv`
|
||||
#[test]
|
||||
fn init_existing_environment_parent() -> Result<()> {
|
||||
let context = TestContext::new_with_versions(&["3.8", "3.12"]);
|
||||
|
||||
// Create a new virtual environment in the parent directory
|
||||
uv_snapshot!(context.filters(), context.venv().current_dir(&context.temp_dir).arg("--python").arg("3.12"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
|
||||
Creating virtual environment at: .venv
|
||||
Activate with: source .venv/[BIN]/activate
|
||||
"###);
|
||||
|
||||
let child = context.temp_dir.child("foo");
|
||||
|
||||
uv_snapshot!(context.filters(), context.init().current_dir(&context.temp_dir).arg(child.as_os_str()), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Initialized project `foo` at `[TEMP_DIR]/foo`
|
||||
"###);
|
||||
|
||||
let pyproject_toml = fs_err::read_to_string(child.join("pyproject.toml"))?;
|
||||
insta::with_settings!({
|
||||
filters => context.filters(),
|
||||
}, {
|
||||
assert_snapshot!(
|
||||
pyproject_toml, @r###"
|
||||
[project]
|
||||
name = "foo"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
dependencies = []
|
||||
"###
|
||||
);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run `uv init` from within an unmanaged project.
|
||||
#[test]
|
||||
fn init_unmanaged() -> Result<()> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue