Rename PythonRequest::Any -> PythonRequest::Default (#7514)

As we support more complex Python discovery behaviors such as:

- #7431 
- #7335 
- #7300 

`Any` is no longer accurate, we actually are looking for a reasonable
default Python version to use which may exclude the first one we find.
Separately, we need the idea of `Any` to improve behavior when listing
versions (e.g., #7286) where we do actually want to match _any_ Python
version. As a first step, we'll rename `Any` to `Default`. Then, we'll
introduce a new `Any` that actually behaves as we'd expect.
This commit is contained in:
Zanie Blue 2024-09-19 05:56:05 -05:00 committed by GitHub
parent 209c870232
commit 5941709e55
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 62 additions and 59 deletions

View file

@ -36,9 +36,12 @@ use crate::{Interpreter, PythonVersion};
/// See [`PythonRequest::from_str`].
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum PythonRequest {
/// Use any discovered Python installation
/// Use an appropriate default Python installation
///
/// This may skip some Python installations, such as pre-release versions or alternative
/// implementations.
#[default]
Any,
Default,
/// A Python version without an implementation name e.g. `3.10` or `>=3.12,<3.13`
Version(VersionRequest),
/// A path to a directory containing a Python installation, e.g. `.venv`
@ -776,7 +779,7 @@ pub fn find_python_installations<'a>(
))))
}
}
PythonRequest::Any => Box::new({
PythonRequest::Default => Box::new({
debug!("Searching for Python interpreter in {preference}");
python_interpreters(None, None, environments, preference, cache).map(|result| {
result
@ -976,7 +979,7 @@ pub fn find_best_python_installation(
// If a Python version was requested but cannot be fulfilled, just take any version
debug!("Looking for Python installation with any version");
let request = PythonRequest::Any;
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
@ -1142,7 +1145,7 @@ impl PythonRequest {
pub fn parse(value: &str) -> Self {
// e.g. `any`
if value.eq_ignore_ascii_case("any") {
return Self::Any;
return Self::Default;
}
// e.g. `3.12.1`, `312`, or `>=3.12`
@ -1246,7 +1249,7 @@ impl PythonRequest {
}
match self {
PythonRequest::Any => true,
PythonRequest::Default => true,
PythonRequest::Version(version_request) => {
version_request.matches_interpreter(interpreter)
}
@ -1330,7 +1333,7 @@ impl PythonRequest {
pub(crate) fn allows_prereleases(&self) -> bool {
match self {
Self::Any => false,
Self::Default => false,
Self::Version(version) => version.allows_prereleases(),
Self::Directory(_) | Self::File(_) | Self::ExecutableName(_) => true,
Self::Implementation(_) => false,
@ -1348,7 +1351,7 @@ impl PythonRequest {
/// [`Self::parse`] should always return the same request when given the output of this method.
pub fn to_canonical_string(&self) -> String {
match self {
Self::Any => "any".to_string(),
Self::Default => "any".to_string(),
Self::Version(version) => version.to_string(),
Self::Directory(path) => path.display().to_string(),
Self::File(path) => path.display().to_string(),
@ -1801,7 +1804,7 @@ impl fmt::Display for VersionRequest {
impl fmt::Display for PythonRequest {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Any => write!(f, "any Python"),
Self::Default => write!(f, "any Python"),
Self::Version(version) => write!(f, "Python {version}"),
Self::Directory(path) => write!(f, "directory `{}`", path.user_display()),
Self::File(path) => write!(f, "path `{}`", path.user_display()),
@ -1883,7 +1886,7 @@ impl fmt::Display for PythonNotFound {
};
match self.request {
PythonRequest::Any => {
PythonRequest::Default => {
write!(f, "No interpreter found in {sources}")
}
_ => {
@ -1961,7 +1964,7 @@ mod tests {
#[test]
fn interpreter_request_from_str() {
assert_eq!(PythonRequest::parse("any"), PythonRequest::Any);
assert_eq!(PythonRequest::parse("any"), PythonRequest::Default);
assert_eq!(
PythonRequest::parse("3.12"),
PythonRequest::Version(VersionRequest::from_str("3.12").unwrap())
@ -2123,7 +2126,7 @@ mod tests {
#[test]
fn interpreter_request_to_canonical_string() {
assert_eq!(PythonRequest::Any.to_canonical_string(), "any");
assert_eq!(PythonRequest::Default.to_canonical_string(), "any");
assert_eq!(
PythonRequest::Version(VersionRequest::from_str("3.12").unwrap()).to_canonical_string(),
"3.12"

View file

@ -173,7 +173,7 @@ impl PythonDownloadRequest {
.with_version(version.clone()),
),
PythonRequest::Key(request) => Some(request.clone()),
PythonRequest::Any => Some(Self::default()),
PythonRequest::Default => Some(Self::default()),
// We can't download a managed installation for these request kinds
PythonRequest::Directory(_)
| PythonRequest::ExecutableName(_)

View file

@ -80,7 +80,7 @@ impl fmt::Display for EnvironmentNotFound {
EnvironmentPreference::OnlyVirtual => SearchType::Virtual,
};
if matches!(self.request, PythonRequest::Any) {
if matches!(self.request, PythonRequest::Default) {
write!(f, "No {search_type} found")?;
} else {
write!(f, "No {search_type} found for {}", self.request)?;

View file

@ -87,7 +87,7 @@ impl PythonInstallation {
cache: &Cache,
reporter: Option<&dyn Reporter>,
) -> Result<Self, Error> {
let request = request.unwrap_or_else(|| &PythonRequest::Any);
let request = request.unwrap_or_else(|| &PythonRequest::Default);
// Search for the installation
match Self::find(request, environments, preference, cache) {

View file

@ -416,7 +416,7 @@ mod tests {
context.search_path = Some(vec![]);
let result = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
PythonPreference::default(),
&context.cache,
@ -430,7 +430,7 @@ mod tests {
context.search_path = None;
let result = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
PythonPreference::default(),
&context.cache,
@ -454,7 +454,7 @@ mod tests {
let result = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
PythonPreference::default(),
&context.cache,
@ -478,7 +478,7 @@ mod tests {
let interpreter = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
PythonPreference::default(),
&context.cache,
@ -538,7 +538,7 @@ mod tests {
let python = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
PythonPreference::default(),
&context.cache,
@ -569,7 +569,7 @@ mod tests {
let result = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
PythonPreference::default(),
&context.cache,
@ -605,7 +605,7 @@ mod tests {
let python = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
PythonPreference::default(),
&context.cache,
@ -636,7 +636,7 @@ mod tests {
let python = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -657,7 +657,7 @@ mod tests {
let python = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -682,7 +682,7 @@ mod tests {
let python = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
PythonPreference::OnlySystem,
&context.cache,
@ -707,7 +707,7 @@ mod tests {
let python = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -970,7 +970,7 @@ mod tests {
let python =
context.run_with_vars(&[("VIRTUAL_ENV", Some(venv.as_os_str()))], || {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -995,7 +995,7 @@ mod tests {
let python =
context.run_with_vars(&[("VIRTUAL_ENV", Some(venv.as_os_str()))], || {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -1020,7 +1020,7 @@ mod tests {
context.run_with_vars(&[("CONDA_PREFIX", Some(condaenv.as_os_str()))], || {
// Note this python is not treated as a system interpreter
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlyVirtual,
PythonPreference::OnlySystem,
&context.cache,
@ -1050,7 +1050,7 @@ mod tests {
],
|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -1069,7 +1069,7 @@ mod tests {
let python =
context.run_with_vars(&[("CONDA_PREFIX", Some(condaenv.as_os_str()))], || {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -1094,7 +1094,7 @@ mod tests {
let python = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -1111,7 +1111,7 @@ mod tests {
context.add_python_versions(&["3.12.1", "3.12.2"])?;
let python = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -1139,7 +1139,7 @@ mod tests {
let python =
context.run_with_vars(&[("VIRTUAL_ENV", Some(venv.as_os_str()))], || {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -1172,7 +1172,7 @@ mod tests {
&[("UV_INTERNAL__PARENT_INTERPRETER", Some(parent.as_os_str()))],
|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -1196,7 +1196,7 @@ mod tests {
],
|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -1217,7 +1217,7 @@ mod tests {
],
|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::ExplicitSystem,
PythonPreference::OnlySystem,
&context.cache,
@ -1238,7 +1238,7 @@ mod tests {
],
|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
PythonPreference::OnlySystem,
&context.cache,
@ -1259,7 +1259,7 @@ mod tests {
],
|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlyVirtual,
PythonPreference::OnlySystem,
&context.cache,
@ -1292,7 +1292,7 @@ mod tests {
&[("UV_INTERNAL__PARENT_INTERPRETER", Some(parent.as_os_str()))],
|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -1319,7 +1319,7 @@ mod tests {
let python =
context.run_with_vars(&[("VIRTUAL_ENV", Some(venv.as_os_str()))], || {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
PythonPreference::OnlySystem,
&context.cache,
@ -1371,7 +1371,7 @@ mod tests {
let result = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlyVirtual,
PythonPreference::OnlySystem,
&context.cache,
@ -1422,7 +1422,7 @@ mod tests {
let result = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -1767,7 +1767,7 @@ mod tests {
context.add_python_interpreters(&[(true, ImplementationName::PyPy, "pypy", "3.10.0")])?;
let result = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -1783,7 +1783,7 @@ mod tests {
context.add_python_interpreters(&[(true, ImplementationName::PyPy, "python", "3.10.1")])?;
let python = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -1836,7 +1836,7 @@ mod tests {
let python = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -2110,7 +2110,7 @@ mod tests {
)])?;
let result = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -2131,7 +2131,7 @@ mod tests {
)])?;
let python = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,
@ -2184,7 +2184,7 @@ mod tests {
let python = context.run(|| {
find_python_installation(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::Any,
PythonPreference::OnlySystem,
&context.cache,

View file

@ -305,7 +305,7 @@ impl ManagedPythonInstallation {
pub fn satisfies(&self, request: &PythonRequest) -> bool {
match request {
PythonRequest::File(path) => self.executable() == *path,
PythonRequest::Any => true,
PythonRequest::Default => true,
PythonRequest::Directory(path) => self.path() == *path,
PythonRequest::ExecutableName(name) => self
.executable()

View file

@ -139,7 +139,7 @@ pub(crate) async fn add(
request
} else {
// (3) Assume any Python version
PythonRequest::Any
PythonRequest::Default
};
let interpreter = PythonInstallation::find_or_download(

View file

@ -41,7 +41,7 @@ pub(crate) async fn install(
PythonVersionFile::discover(&*CWD, no_config, true)
.await?
.map(uv_python::PythonVersionFile::into_versions)
.unwrap_or_else(|| vec![PythonRequest::Any])
.unwrap_or_else(|| vec![PythonRequest::Default])
} else {
targets
.iter()
@ -62,7 +62,7 @@ pub(crate) async fn install(
let mut unfilled_requests = Vec::new();
let mut uninstalled = Vec::new();
for (request, download_request) in requests.iter().zip(download_requests) {
if matches!(requests.as_slice(), [PythonRequest::Any]) {
if matches!(requests.as_slice(), [PythonRequest::Default]) {
writeln!(printer.stderr(), "Searching for Python installations")?;
} else {
writeln!(
@ -75,7 +75,7 @@ pub(crate) async fn install(
.iter()
.find(|installation| download_request.satisfied_by_key(installation.key()))
{
if matches!(request, PythonRequest::Any) {
if matches!(request, PythonRequest::Default) {
writeln!(printer.stderr(), "Found: {}", installation.key().green())?;
} else {
writeln!(
@ -96,7 +96,7 @@ pub(crate) async fn install(
}
if unfilled_requests.is_empty() {
if matches!(requests.as_slice(), [PythonRequest::Any]) {
if matches!(requests.as_slice(), [PythonRequest::Default]) {
writeln!(
printer.stderr(),
"Python is already available. Use `uv python install <request>` to install a specific version.",

View file

@ -66,7 +66,7 @@ pub(crate) async fn list(
};
let installed = find_python_installations(
&PythonRequest::Any,
&PythonRequest::Default,
EnvironmentPreference::OnlySystem,
python_preference,
cache,

View file

@ -59,7 +59,7 @@ async fn do_uninstall(
let start = std::time::Instant::now();
let requests = if all {
vec![PythonRequest::Any]
vec![PythonRequest::Default]
} else {
let targets = targets.into_iter().collect::<BTreeSet<_>>();
targets
@ -82,7 +82,7 @@ async fn do_uninstall(
let installed_installations: Vec<_> = installations.find_all()?.collect();
let mut matching_installations = BTreeSet::default();
for (request, download_request) in requests.iter().zip(download_requests) {
if matches!(requests.as_slice(), [PythonRequest::Any]) {
if matches!(requests.as_slice(), [PythonRequest::Default]) {
writeln!(printer.stderr(), "Searching for Python installations")?;
} else {
writeln!(
@ -100,7 +100,7 @@ async fn do_uninstall(
matching_installations.insert(installation.clone());
}
if !found {
if matches!(requests.as_slice(), [PythonRequest::Any]) {
if matches!(requests.as_slice(), [PythonRequest::Default]) {
writeln!(printer.stderr(), "No Python installations found")?;
return Ok(ExitStatus::Failure);
}