mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00

Three edition 2021 compatible sets of changes in preparation for the edition 2025 split out from #11724. In edition 2025, `gen` is a keyword, so we escape it as `r#gen`. `ref` and `ref mut` are not allowed anymore for `&T` and `&mut T`, so we remove them. `cargo fmt` now formats inside of macros, which the 2021 formatter doesn't undo.
129 lines
4.1 KiB
Rust
129 lines
4.1 KiB
Rust
use std::str::FromStr;
|
|
|
|
use uv_pep508::PackageName;
|
|
|
|
/// A specifier used for (e.g.) pip's `--no-binary` flag.
|
|
///
|
|
/// This is a superset of the package name format, allowing for special values `:all:` and `:none:`.
|
|
#[derive(Debug, Clone)]
|
|
pub enum PackageNameSpecifier {
|
|
All,
|
|
None,
|
|
Package(PackageName),
|
|
}
|
|
|
|
impl FromStr for PackageNameSpecifier {
|
|
type Err = uv_normalize::InvalidNameError;
|
|
|
|
fn from_str(name: &str) -> Result<Self, Self::Err> {
|
|
match name {
|
|
":all:" => Ok(Self::All),
|
|
":none:" => Ok(Self::None),
|
|
_ => Ok(Self::Package(PackageName::from_str(name)?)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'de> serde::Deserialize<'de> for PackageNameSpecifier {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: serde::Deserializer<'de>,
|
|
{
|
|
struct Visitor;
|
|
|
|
impl serde::de::Visitor<'_> for Visitor {
|
|
type Value = PackageNameSpecifier;
|
|
|
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
formatter.write_str("a package name or `:all:` or `:none:`")
|
|
}
|
|
|
|
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
|
where
|
|
E: serde::de::Error,
|
|
{
|
|
// Accept the special values `:all:` and `:none:`.
|
|
match value {
|
|
":all:" => Ok(PackageNameSpecifier::All),
|
|
":none:" => Ok(PackageNameSpecifier::None),
|
|
_ => {
|
|
// Otherwise, parse the value as a package name.
|
|
match PackageName::from_str(value) {
|
|
Ok(name) => Ok(PackageNameSpecifier::Package(name)),
|
|
Err(err) => Err(E::custom(err)),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
deserializer.deserialize_str(Visitor)
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "schemars")]
|
|
impl schemars::JsonSchema for PackageNameSpecifier {
|
|
fn schema_name() -> String {
|
|
"PackageNameSpecifier".to_string()
|
|
}
|
|
|
|
fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
|
|
schemars::schema::SchemaObject {
|
|
instance_type: Some(schemars::schema::InstanceType::String.into()),
|
|
string: Some(Box::new(schemars::schema::StringValidation {
|
|
// See: https://packaging.python.org/en/latest/specifications/name-normalization/#name-format
|
|
pattern: Some(
|
|
r"^(:none:|:all:|([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]))$"
|
|
.to_string(),
|
|
),
|
|
..schemars::schema::StringValidation::default()
|
|
})),
|
|
metadata: Some(Box::new(schemars::schema::Metadata {
|
|
description: Some("The name of a package, or `:all:` or `:none:` to select or omit all packages, respectively.".to_string()),
|
|
..schemars::schema::Metadata::default()
|
|
})),
|
|
..schemars::schema::SchemaObject::default()
|
|
}
|
|
.into()
|
|
}
|
|
}
|
|
|
|
/// A repeated specifier used for (e.g.) pip's `--no-binary` flag.
|
|
///
|
|
/// This is a superset of the package name format, allowing for special values `:all:` and `:none:`.
|
|
#[derive(Debug, Clone)]
|
|
pub enum PackageNameSpecifiers {
|
|
All,
|
|
None,
|
|
Packages(Vec<PackageName>),
|
|
}
|
|
|
|
impl PackageNameSpecifiers {
|
|
pub(crate) fn from_iter(specifiers: impl Iterator<Item = PackageNameSpecifier>) -> Self {
|
|
let mut packages = Vec::new();
|
|
let mut all: bool = false;
|
|
|
|
for specifier in specifiers {
|
|
match specifier {
|
|
PackageNameSpecifier::None => {
|
|
packages.clear();
|
|
all = false;
|
|
}
|
|
PackageNameSpecifier::All => {
|
|
all = true;
|
|
}
|
|
PackageNameSpecifier::Package(name) => {
|
|
packages.push(name);
|
|
}
|
|
}
|
|
}
|
|
|
|
if all {
|
|
Self::All
|
|
} else if packages.is_empty() {
|
|
Self::None
|
|
} else {
|
|
Self::Packages(packages)
|
|
}
|
|
}
|
|
}
|