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

Be compatible with non-PEP440 version under env var UV_NON_PEP440_COMPAT #11434

Closed
wants to merge 2 commits into from
Closed
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
32 changes: 32 additions & 0 deletions crates/uv-pep440/src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1673,6 +1673,8 @@ impl Ord for LocalSegment {
/// [pep440]: https://packaging.python.org/en/latest/specifications/version-specifiers/
#[derive(Debug)]
struct Parser<'a> {
/// Try to be compatible with non-PEP 440 versions
compat: bool,
/// The version string we are parsing.
v: &'a [u8],
/// The current position of the parser.
Expand Down Expand Up @@ -1703,7 +1705,10 @@ impl<'a> Parser<'a> {

/// Create a new `Parser` for parsing the version in the given byte string.
fn new(version: &'a [u8]) -> Parser<'a> {
static NON_PEP440_COMPAT: LazyLock<bool> =
LazyLock::new(|| std::env::var("UV_NON_PEP440_COMPAT").is_ok());
Parser {
compat: *NON_PEP440_COMPAT,
v: version,
i: 0,
epoch: 0,
Expand All @@ -1720,6 +1725,8 @@ impl<'a> Parser<'a> {
///
/// If a version pattern is found, then an error is returned.
fn parse(self) -> Result<Version, VersionParseError> {
let compat = self.compat;
let _version = self.v;
match self.parse_pattern() {
Ok(vpat) => {
if vpat.is_wildcard() {
Expand All @@ -1728,6 +1735,17 @@ impl<'a> Parser<'a> {
Ok(vpat.into_version())
}
}
Err(_err) if compat => {
#[cfg(feature = "tracing")]
{
tracing::warn!(
"Accepted non-PEP 440 version: {} {}",
String::from_utf8_lossy(_version),
_err
);
}
Ok(MIN_VERSION.clone())
}
// If we get an error when parsing a version pattern, then
// usually it will actually just be a VersionParseError.
// But if it's specific to version patterns, and since
Expand Down Expand Up @@ -3696,7 +3714,21 @@ mod tests {
.into()
);
}
#[test]
fn parse_version_invalid_compat() {
let p = |s: &str| {
let mut parser = Parser::new(s.as_bytes());
parser.compat = true;

match parser.parse() {
Ok(v) => v,
Err(err) => unreachable!("expected valid version, but got error: {err:?}"),
}
};

// release-only tests
assert_eq!(p("invalid-version"), MIN_VERSION.clone());
}
#[test]
fn parse_version_pattern_valid() {
let p = |s: &str| match Parser::new(s.as_bytes()).parse_pattern() {
Expand Down
Loading