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

Respect --project during uv python find (#11990) #12049

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
102 changes: 74 additions & 28 deletions crates/uv-python/src/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::managed::ManagedPythonInstallations;
use crate::microsoft_store::find_microsoft_store_pythons;
use crate::virtualenv::Error as VirtualEnvError;
use crate::virtualenv::{
conda_environment_from_env, virtualenv_from_env, virtualenv_from_working_dir,
conda_environment_from_env, virtualenv_from_dir, virtualenv_from_env,
virtualenv_python_executable, CondaEnvironmentKind,
};
#[cfg(windows)]
Expand Down Expand Up @@ -250,8 +250,9 @@ pub enum Error {
/// - Discovered virtual environment (e.g. `.venv` in a parent directory)
///
/// Notably, "system" environments are excluded. See [`python_executables_from_installed`].
fn python_executables_from_virtual_environments<'a>(
) -> impl Iterator<Item = Result<(PythonSource, PathBuf), Error>> + 'a {
fn python_executables_from_virtual_environments(
discovery_root: &Path,
) -> impl Iterator<Item = Result<(PythonSource, PathBuf), Error>> + '_ {
let from_active_environment = iter::once_with(|| {
virtualenv_from_env()
.into_iter()
Expand All @@ -269,8 +270,8 @@ fn python_executables_from_virtual_environments<'a>(
})
.flatten();

let from_discovered_environment = iter::once_with(|| {
virtualenv_from_working_dir()
let from_discovered_environment = iter::once_with(move || {
virtualenv_from_dir(discovery_root)
.map(|path| {
path.map(virtualenv_python_executable)
.map(|path| (PythonSource::DiscoveredEnvironment, path))
Expand Down Expand Up @@ -420,6 +421,7 @@ fn python_executables<'a>(
implementation: Option<&'a ImplementationName>,
environments: EnvironmentPreference,
preference: PythonPreference,
discovery_root: &'a Path,
) -> Box<dyn Iterator<Item = Result<(PythonSource, PathBuf), Error>> + 'a> {
// Always read from `UV_INTERNAL__PARENT_INTERPRETER` — it could be a system interpreter
let from_parent_interpreter = iter::once_with(|| {
Expand All @@ -438,7 +440,7 @@ fn python_executables<'a>(
})
.flatten();

let from_virtual_environments = python_executables_from_virtual_environments();
let from_virtual_environments = python_executables_from_virtual_environments(discovery_root);
let from_installed = python_executables_from_installed(version, implementation, preference);

// Limit the search to the relevant environment preference; this avoids unnecessary work like
Expand Down Expand Up @@ -615,16 +617,22 @@ fn python_interpreters<'a>(
environments: EnvironmentPreference,
preference: PythonPreference,
cache: &'a Cache,
discovery_root: &'a Path,
) -> impl Iterator<Item = Result<(PythonSource, Interpreter), Error>> + 'a {
python_interpreters_from_executables(
// Perform filtering on the discovered executables based on their source. This avoids
// unnecessary interpreter queries, which are generally expensive. We'll filter again
// with `interpreter_satisfies_environment_preference` after querying.
python_executables(version, implementation, environments, preference).filter_ok(
move |(source, path)| {
source_satisfies_environment_preference(*source, path, environments)
},
),
python_executables(
version,
implementation,
environments,
preference,
discovery_root,
)
.filter_ok(move |(source, path)| {
source_satisfies_environment_preference(*source, path, environments)
}),
cache,
)
.filter_ok(move |(source, interpreter)| {
Expand Down Expand Up @@ -862,6 +870,7 @@ pub fn find_python_installations<'a>(
environments: EnvironmentPreference,
preference: PythonPreference,
cache: &'a Cache,
discovery_root: &'a Path,
) -> Box<dyn Iterator<Item = Result<FindPythonResult, Error>> + 'a> {
let sources = DiscoveryPreferences {
python_preference: preference,
Expand Down Expand Up @@ -942,8 +951,15 @@ pub fn find_python_installations<'a>(
}
PythonRequest::Any => Box::new({
debug!("Searching for any Python interpreter in {sources}");
python_interpreters(&VersionRequest::Any, None, environments, preference, cache)
.map_ok(|tuple| Ok(PythonInstallation::from_tuple(tuple)))
python_interpreters(
&VersionRequest::Any,
None,
environments,
preference,
cache,
discovery_root,
)
.map_ok(|tuple| Ok(PythonInstallation::from_tuple(tuple)))
}),
PythonRequest::Default => Box::new({
debug!("Searching for default Python interpreter in {sources}");
Expand All @@ -953,6 +969,7 @@ pub fn find_python_installations<'a>(
environments,
preference,
cache,
discovery_root,
)
.map_ok(|tuple| Ok(PythonInstallation::from_tuple(tuple)))
}),
Expand All @@ -962,8 +979,15 @@ pub fn find_python_installations<'a>(
};
Box::new({
debug!("Searching for {request} in {sources}");
python_interpreters(version, None, environments, preference, cache)
.map_ok(|tuple| Ok(PythonInstallation::from_tuple(tuple)))
python_interpreters(
version,
None,
environments,
preference,
cache,
discovery_root,
)
.map_ok(|tuple| Ok(PythonInstallation::from_tuple(tuple)))
})
}
PythonRequest::Implementation(implementation) => Box::new({
Expand All @@ -974,6 +998,7 @@ pub fn find_python_installations<'a>(
environments,
preference,
cache,
discovery_root,
)
.filter_ok(|(_source, interpreter)| {
interpreter
Expand All @@ -994,6 +1019,7 @@ pub fn find_python_installations<'a>(
environments,
preference,
cache,
discovery_root,
)
.filter_ok(|(_source, interpreter)| {
interpreter
Expand All @@ -1017,6 +1043,7 @@ pub fn find_python_installations<'a>(
environments,
preference,
cache,
discovery_root,
)
.filter_ok(|(_source, interpreter)| request.satisfied_by_interpreter(interpreter))
.map_ok(|tuple| Ok(PythonInstallation::from_tuple(tuple)))
Expand All @@ -1034,8 +1061,10 @@ pub(crate) fn find_python_installation(
environments: EnvironmentPreference,
preference: PythonPreference,
cache: &Cache,
discovery_root: &Path,
) -> Result<FindPythonResult, Error> {
let installations = find_python_installations(request, environments, preference, cache);
let installations =
find_python_installations(request, environments, preference, cache, discovery_root);
let mut first_prerelease = None;
let mut first_error = None;
for result in installations {
Expand Down Expand Up @@ -1136,7 +1165,13 @@ pub fn find_best_python_installation(

// First, check for an exact match (or the first available version if no Python version was provided)
debug!("Looking for exact match for request {request}");
let result = find_python_installation(request, environments, preference, cache);
let result = find_python_installation(
request,
environments,
preference,
cache,
crate::current_dir()?.as_path(),
);
match result {
Ok(Ok(installation)) => {
warn_on_unsupported_python(installation.interpreter());
Expand Down Expand Up @@ -1164,7 +1199,13 @@ pub fn find_best_python_installation(
_ => None,
} {
debug!("Looking for relaxed patch version {request}");
let result = find_python_installation(&request, environments, preference, cache);
let result = find_python_installation(
&request,
environments,
preference,
cache,
crate::current_dir()?.as_path(),
);
match result {
Ok(Ok(installation)) => {
warn_on_unsupported_python(installation.interpreter());
Expand All @@ -1180,16 +1221,21 @@ pub fn find_best_python_installation(
// If a Python version was requested but cannot be fulfilled, just take any version
debug!("Looking for a default Python installation");
let request = PythonRequest::Default;
Ok(
find_python_installation(&request, environments, preference, cache)?.map_err(|err| {
// Use a more general error in this case since we looked for multiple versions
PythonNotFound {
request,
python_preference: err.python_preference,
environment_preference: err.environment_preference,
}
}),
)
Ok(find_python_installation(
&request,
environments,
preference,
cache,
crate::current_dir()?.as_path(),
)?
.map_err(|err| {
// Use a more general error in this case since we looked for multiple versions
PythonNotFound {
request,
python_preference: err.python_preference,
environment_preference: err.environment_preference,
}
}))
}

/// Display a warning if the Python version of the [`Interpreter`] is unsupported by uv.
Expand Down
1 change: 1 addition & 0 deletions crates/uv-python/src/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ impl PythonEnvironment {
// Ignore managed installations when looking for environments
PythonPreference::OnlySystem,
cache,
crate::current_dir()?.as_path(),
)? {
Ok(installation) => installation,
Err(err) => return Err(EnvironmentNotFound::from(err).into()),
Expand Down
14 changes: 12 additions & 2 deletions crates/uv-python/src/installation.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fmt;
use std::path::Path;
use std::str::FromStr;

use tracing::{debug, info};
Expand Down Expand Up @@ -54,8 +55,10 @@ impl PythonInstallation {
environments: EnvironmentPreference,
preference: PythonPreference,
cache: &Cache,
discovery_root: &Path,
) -> Result<Self, Error> {
let installation = find_python_installation(request, environments, preference, cache)??;
let installation =
find_python_installation(request, environments, preference, cache, discovery_root)??;
Ok(installation)
}

Expand Down Expand Up @@ -90,9 +93,16 @@ impl PythonInstallation {
pypy_install_mirror: Option<&str>,
) -> Result<Self, Error> {
let request = request.unwrap_or(&PythonRequest::Default);
let root_directory = crate::current_dir()?;

// Search for the installation
let err = match Self::find(request, environments, preference, cache) {
let err = match Self::find(
request,
environments,
preference,
cache,
root_directory.as_path(),
) {
Ok(installation) => return Ok(installation),
Err(err) => err,
};
Expand Down
Loading
Loading