diff --git a/.github/workflows/system-install.yml b/.github/workflows/system-install.yml index 82172f4bf..011fb08cd 100644 --- a/.github/workflows/system-install.yml +++ b/.github/workflows/system-install.yml @@ -67,8 +67,9 @@ jobs: steps: - uses: actions/checkout@v4 -# - name: "Install Python" -# run: choco install python + - uses: actions/setup-python@v5 + with: + python-version: "3.10" - name: "Install Rust toolchain" run: rustup show @@ -82,7 +83,7 @@ jobs: run: echo $(which python) - name: "Validate global Python install" - run: py -3.12 ./scripts/check_system_python.py --uv ./target/debug/uv + run: py -3.10 ./scripts/check_system_python.py --uv ./target/debug/uv install-pyenv: name: "Install Python using pyenv" diff --git a/README.md b/README.md index f1cc3d7e4..4395e14f4 100644 --- a/README.md +++ b/README.md @@ -164,10 +164,10 @@ search for a Python interpreter matching that version in the following order: - An activated virtual environment based on the `VIRTUAL_ENV` environment variable. - An activated Conda environment based on the `CONDA_PREFIX` environment variable. - A virtual environment at `.venv` in the current directory, or in the nearest parent directory. -- The Python interpreter available as, e.g., `python3.7` on macOS and Linux. On Windows, uv - will use the same mechanism as `py --list-paths` to discover all available Python interpreters, - and will select the first interpreter matching the requested version. +- The Python interpreter available as, e.g., `python3.7` on macOS and Linux. - The Python interpreter available as `python3` on macOS and Linux, or `python.exe` on Windows. +- On Windows, the Python interpreter returned by `py --list-paths` that matches the requested + version. Since uv has no dependency on Python, it can even install into virtual environments other than its own. For example, setting `VIRTUAL_ENV=/path/to/venv` will cause uv to install into diff --git a/crates/uv-interpreter/src/python_query.rs b/crates/uv-interpreter/src/python_query.rs index 503d4564a..ebddb2f64 100644 --- a/crates/uv-interpreter/src/python_query.rs +++ b/crates/uv-interpreter/src/python_query.rs @@ -96,7 +96,6 @@ pub(crate) fn try_find_default_python( /// Finds a python version matching `selector`. /// It searches for an existing installation in the following order: -/// * (windows): Discover installations using `py --list-paths` (PEP514). Continue if `py` is not installed. /// * Search for the python binary in `PATH` (or `UV_TEST_PYTHON_PATH` if set). Visits each path and for each path resolves the /// files in the following order: /// * Major.Minor.Patch: `pythonx.y.z`, `pythonx.y`, `python.x`, `python` @@ -104,6 +103,7 @@ pub(crate) fn try_find_default_python( /// * Major: `pythonx`, `python` /// * Default: `python3`, `python` /// * (windows): For each of the above, test for the existence of `python.bat` shim (pyenv-windows) last. +/// * (windows): Discover installations using `py --list-paths` (PEP514). Continue if `py` is not installed. /// /// (Windows): Filter out the windows store shim (Enabled in Settings/Apps/Advanced app settings/App execution aliases). fn find_python( @@ -114,23 +114,7 @@ fn find_python( #[allow(non_snake_case)] let UV_TEST_PYTHON_PATH = env::var_os("UV_TEST_PYTHON_PATH"); - if cfg!(windows) && UV_TEST_PYTHON_PATH.is_none() { - // Use `py` to find the python installation on the system. - match windows::py_list_paths(selector, platform, cache) { - Ok(Some(interpreter)) => return Ok(Some(interpreter)), - Ok(None) => { - // No matching Python version found, continue searching PATH - } - Err(Error::PyList(error)) => { - if error.kind() == std::io::ErrorKind::NotFound { - debug!("`py` is not installed. Falling back to searching Python on the path"); - // Continue searching for python installations on the path. - } - } - Err(error) => return Err(error), - } - } - + let override_path = UV_TEST_PYTHON_PATH.is_some(); let possible_names = selector.possible_names(); #[allow(non_snake_case)] @@ -197,6 +181,20 @@ fn find_python( } } + if cfg!(windows) && !override_path { + // Use `py` to find the python installation on the system. + match windows::py_list_paths(selector, platform, cache) { + Ok(Some(interpreter)) => return Ok(Some(interpreter)), + Ok(None) => {} + Err(Error::PyList(error)) => { + if error.kind() == std::io::ErrorKind::NotFound { + debug!("`py` is not installed"); + } + } + Err(error) => return Err(error), + } + } + Ok(None) }