-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support extras in @ requests for tools
- Loading branch information
1 parent
25e7209
commit 1d215e2
Showing
4 changed files
with
136 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -133,14 +133,15 @@ pub(crate) async fn install( | |
.unwrap() | ||
} | ||
// Ex) `[email protected]` | ||
Target::Version(name, ref version) | Target::FromVersion(_, name, ref version) => { | ||
Target::Version(name, ref extras, ref version) | ||
| Target::FromVersion(_, name, ref extras, ref version) => { | ||
if editable { | ||
bail!("`--editable` is only supported for local packages"); | ||
} | ||
|
||
Requirement { | ||
name: PackageName::from_str(name)?, | ||
extras: vec![], | ||
extras: extras.clone(), | ||
groups: vec![], | ||
marker: MarkerTree::default(), | ||
source: RequirementSource::Registry { | ||
|
@@ -154,14 +155,14 @@ pub(crate) async fn install( | |
} | ||
} | ||
// Ex) `ruff@latest` | ||
Target::Latest(name) | Target::FromLatest(_, name) => { | ||
Target::Latest(name, ref extras) | Target::FromLatest(_, name, ref extras) => { | ||
if editable { | ||
bail!("`--editable` is only supported for local packages"); | ||
} | ||
|
||
Requirement { | ||
name: PackageName::from_str(name)?, | ||
extras: vec![], | ||
extras: extras.clone(), | ||
groups: vec![], | ||
marker: MarkerTree::default(), | ||
source: RequirementSource::Registry { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ use std::str::FromStr; | |
|
||
use tracing::debug; | ||
|
||
use uv_normalize::PackageName; | ||
use uv_normalize::{ExtraName, PackageName}; | ||
use uv_pep440::Version; | ||
|
||
mod common; | ||
|
@@ -19,15 +19,15 @@ pub(crate) enum Target<'a> { | |
/// e.g., `ruff` | ||
Unspecified(&'a str), | ||
/// e.g., `[email protected]` | ||
Version(&'a str, Version), | ||
Version(&'a str, Vec<ExtraName>, Version), | ||
/// e.g., `ruff@latest` | ||
Latest(&'a str), | ||
Latest(&'a str, Vec<ExtraName>), | ||
/// e.g., `ruff --from ruff>=0.6.0` | ||
From(&'a str, &'a str), | ||
/// e.g., `ruff --from [email protected]` | ||
FromVersion(&'a str, &'a str, Version), | ||
FromVersion(&'a str, &'a str, Vec<ExtraName>, Version), | ||
/// e.g., `ruff --from ruff@latest` | ||
FromLatest(&'a str, &'a str), | ||
FromLatest(&'a str, &'a str, Vec<ExtraName>), | ||
} | ||
|
||
impl<'a> Target<'a> { | ||
|
@@ -45,19 +45,43 @@ impl<'a> Target<'a> { | |
return Self::From(target, from); | ||
} | ||
|
||
// Split into name and extras (e.g., `flask[dotenv]`). | ||
let (name, extras) = match name.split_once('[') { | ||
Some((name, extras)) => { | ||
let Some(extras) = extras.strip_suffix(']') else { | ||
// e.g., ignore `flask[dotenv`. | ||
debug!("Ignoring invalid extras in `--from`"); | ||
return Self::From(target, from); | ||
}; | ||
(name, extras) | ||
} | ||
None => (name, ""), | ||
}; | ||
|
||
// e.g., ignore `git+https://github.com/astral-sh/ruff.git@main` | ||
if PackageName::from_str(name).is_err() { | ||
debug!("Ignoring non-package name `{name}` in `--from`"); | ||
return Self::From(target, from); | ||
} | ||
|
||
// e.g., ignore `ruff[1.0.0]` or any other invalid extra. | ||
let Ok(extras) = extras | ||
.split(',') | ||
.map(str::trim) | ||
.map(ExtraName::from_str) | ||
.collect::<Result<Vec<_>, _>>() | ||
else { | ||
debug!("Ignoring invalid extras `{extras}` in `--from`"); | ||
return Self::From(target, from); | ||
}; | ||
|
||
match version { | ||
// e.g., `ruff@latest` | ||
"latest" => return Self::FromLatest(target, name), | ||
"latest" => return Self::FromLatest(target, name, extras), | ||
// e.g., `[email protected]` | ||
version => { | ||
if let Ok(version) = Version::from_str(version) { | ||
return Self::FromVersion(target, name, version); | ||
return Self::FromVersion(target, name, extras, version); | ||
} | ||
} | ||
}; | ||
|
@@ -78,19 +102,42 @@ impl<'a> Target<'a> { | |
return Self::Unspecified(target); | ||
} | ||
|
||
// Split into name and extras (e.g., `flask[dotenv]`). | ||
let (name, extras) = match name.split_once('[') { | ||
Some((name, extras)) => { | ||
let Some(extras) = extras.strip_suffix(']') else { | ||
// e.g., ignore `flask[dotenv`. | ||
return Self::Unspecified(name); | ||
}; | ||
(name, extras) | ||
} | ||
None => (name, ""), | ||
}; | ||
|
||
// e.g., ignore `git+https://github.com/astral-sh/ruff.git@main` | ||
if PackageName::from_str(name).is_err() { | ||
debug!("Ignoring non-package name `{name}` in command"); | ||
return Self::Unspecified(target); | ||
} | ||
|
||
// e.g., ignore `ruff[1.0.0]` or any other invalid extra. | ||
let Ok(extras) = extras | ||
.split(',') | ||
.map(str::trim) | ||
.map(ExtraName::from_str) | ||
.collect::<Result<Vec<_>, _>>() | ||
else { | ||
debug!("Ignoring invalid extras `{extras}` in command"); | ||
return Self::Unspecified(target); | ||
}; | ||
|
||
match version { | ||
// e.g., `ruff@latest` | ||
"latest" => return Self::Latest(name), | ||
"latest" => return Self::Latest(name, extras), | ||
// e.g., `[email protected]` | ||
version => { | ||
if let Ok(version) = Version::from_str(version) { | ||
return Self::Version(name, version); | ||
return Self::Version(name, extras, version); | ||
} | ||
} | ||
}; | ||
|
@@ -104,10 +151,10 @@ impl<'a> Target<'a> { | |
pub(crate) fn executable(&self) -> &str { | ||
match self { | ||
Self::Unspecified(name) => name, | ||
Self::Version(name, _) => name, | ||
Self::Latest(name) => name, | ||
Self::FromVersion(name, _, _) => name, | ||
Self::FromLatest(name, _) => name, | ||
Self::Version(name, _, _) => name, | ||
Self::Latest(name, _) => name, | ||
Self::FromVersion(name, _, _, _) => name, | ||
Self::FromLatest(name, _, _) => name, | ||
Self::From(name, _) => name, | ||
} | ||
} | ||
|
@@ -116,17 +163,17 @@ impl<'a> Target<'a> { | |
pub(crate) fn is_python(&self) -> bool { | ||
let name = match self { | ||
Self::Unspecified(name) => name, | ||
Self::Version(name, _) => name, | ||
Self::Latest(name) => name, | ||
Self::FromVersion(_, name, _) => name, | ||
Self::FromLatest(_, name) => name, | ||
Self::Version(name, _, _) => name, | ||
Self::Latest(name, _) => name, | ||
Self::FromVersion(_, name, _, _) => name, | ||
Self::FromLatest(_, name, _) => name, | ||
Self::From(_, name) => name, | ||
}; | ||
name.eq_ignore_ascii_case("python") || cfg!(windows) && name.eq_ignore_ascii_case("pythonw") | ||
} | ||
|
||
/// Returns `true` if the target is `latest`. | ||
fn is_latest(&self) -> bool { | ||
matches!(self, Self::Latest(_) | Self::FromLatest(_, _)) | ||
matches!(self, Self::Latest(..) | Self::FromLatest(..)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -460,13 +460,13 @@ async fn get_or_create_environment( | |
let python_request = if target.is_python() { | ||
let target_request = match target { | ||
Target::Unspecified(_) => None, | ||
Target::Version(_, version) | Target::FromVersion(_, _, version) => { | ||
Target::Version(_, _, version) | Target::FromVersion(_, _, _, version) => { | ||
Some(PythonRequest::Version( | ||
VersionRequest::from_str(&version.to_string()).map_err(anyhow::Error::from)?, | ||
)) | ||
} | ||
// TODO(zanieb): Add `PythonRequest::Latest` | ||
Target::Latest(_) | Target::FromLatest(_, _) => { | ||
Target::Latest(_, _) | Target::FromLatest(_, _, _) => { | ||
return Err(anyhow::anyhow!( | ||
"Requesting the 'latest' Python version is not yet supported" | ||
) | ||
|
@@ -531,9 +531,10 @@ async fn get_or_create_environment( | |
origin: None, | ||
}, | ||
// Ex) `[email protected]` | ||
Target::Version(name, version) | Target::FromVersion(_, name, version) => Requirement { | ||
Target::Version(name, extras, version) | ||
| Target::FromVersion(_, name, extras, version) => Requirement { | ||
name: PackageName::from_str(name)?, | ||
extras: vec![], | ||
extras: extras.clone(), | ||
groups: vec![], | ||
marker: MarkerTree::default(), | ||
source: RequirementSource::Registry { | ||
|
@@ -546,9 +547,9 @@ async fn get_or_create_environment( | |
origin: None, | ||
}, | ||
// Ex) `ruff@latest` | ||
Target::Latest(name) | Target::FromLatest(_, name) => Requirement { | ||
Target::Latest(name, extras) | Target::FromLatest(_, name, extras) => Requirement { | ||
name: PackageName::from_str(name)?, | ||
extras: vec![], | ||
extras: extras.clone(), | ||
groups: vec![], | ||
marker: MarkerTree::default(), | ||
source: RequirementSource::Registry { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters