Make Requirement generic over url type (#3253)

This change allows switching out the url type for requirements. The
original idea was to allow different types for different requirement
origins, so that core metadata reads can ban non-pep 508 requirements
while we only allow them for requirements.txt. This didn't work out
because we expect `&Requirement`s from all sources to match.

I also tried to split `pep508_rs` into a PEP 508 compliant crate and
into our extensions, but they are to tightly coupled.

I think this change is an improvement still as it reduces the hardcoded
dependence on `VerbatimUrl`.
This commit is contained in:
konsti 2024-05-07 16:45:49 +02:00 committed by GitHub
parent 8e86cd0c73
commit 55f6e4e66b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 560 additions and 478 deletions

View file

@ -7,7 +7,7 @@ use serde::{de, Deserialize, Deserializer, Serialize};
use tracing::warn;
use pep440_rs::{VersionSpecifiers, VersionSpecifiersParseError};
use pep508_rs::{Pep508Error, Requirement};
use pep508_rs::{Pep508Error, Pep508Url, Requirement, VerbatimUrl};
/// Ex) `>=7.2.0<8.0.0`
static MISSING_COMMA: Lazy<Regex> = Lazy::new(|| Regex::new(r"(\d)([<>=~^!])").unwrap());
@ -114,18 +114,18 @@ fn parse_with_fixups<Err, T: FromStr<Err = Err>>(input: &str, type_name: &str) -
/// Like [`Requirement`], but attempts to correct some common errors in user-provided requirements.
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub struct LenientRequirement(Requirement);
pub struct LenientRequirement<T: Pep508Url = VerbatimUrl>(Requirement<T>);
impl FromStr for LenientRequirement {
type Err = Pep508Error;
impl<T: Pep508Url> FromStr for LenientRequirement<T> {
type Err = Pep508Error<T>;
fn from_str(input: &str) -> Result<Self, Self::Err> {
Ok(Self(parse_with_fixups(input, "requirement")?))
}
}
impl From<LenientRequirement> for Requirement {
fn from(requirement: LenientRequirement) -> Self {
impl<T: Pep508Url> From<LenientRequirement<T>> for Requirement<T> {
fn from(requirement: LenientRequirement<T>) -> Self {
requirement.0
}
}

View file

@ -9,7 +9,7 @@ use thiserror::Error;
use tracing::warn;
use pep440_rs::{Version, VersionParseError, VersionSpecifiers, VersionSpecifiersParseError};
use pep508_rs::{Pep508Error, Requirement};
use pep508_rs::{Pep508Error, Requirement, VerbatimUrl};
use uv_normalize::{ExtraName, InvalidNameError, PackageName};
use crate::lenient_requirement::LenientRequirement;
@ -29,7 +29,7 @@ pub struct Metadata23 {
pub name: PackageName,
pub version: Version,
// Optional fields
pub requires_dist: Vec<Requirement>,
pub requires_dist: Vec<Requirement<VerbatimUrl>>,
pub requires_python: Option<VersionSpecifiers>,
pub provides_extras: Vec<ExtraName>,
}
@ -50,7 +50,7 @@ pub enum MetadataError {
#[error(transparent)]
Pep440Error(#[from] VersionSpecifiersParseError),
#[error(transparent)]
Pep508Error(#[from] Pep508Error),
Pep508Error(#[from] Pep508Error<VerbatimUrl>),
#[error(transparent)]
InvalidName(#[from] InvalidNameError),
#[error("Invalid `Metadata-Version` field: {0}")]