Skip to content

Commit

Permalink
Add support for PyPI local versions (#1419)
Browse files Browse the repository at this point in the history
Closes #1416.
  • Loading branch information
cd-work authored May 13, 2024
1 parent 95c96af commit 16ab00e
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Fixed

- Sandboxed processes sticking around after CLI is killed with a signal
- Lockfiles with local versions breaking the pip parser

## 6.3.0 - 2024-04-18

Expand Down
5 changes: 5 additions & 0 deletions lockfile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,11 @@ pub enum PackageVersion {
Git(String),
/// Version distributed over HTTP(S).
DownloadUrl(String),
/// Untracked version source.
///
/// Used for package versions which cannot clearly be identified, like
/// Python's local version.
Unknown,
}

/// Version from a foreign package registry.
Expand Down
4 changes: 4 additions & 0 deletions lockfile/src/parse_depfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ fn filter_packages(mut packages: Vec<Package>) -> Vec<PackageDescriptor> {
log::debug!("Ignoring remote dependency {} ({url:?})", package.name);
return None;
},
PackageVersion::Unknown => {
log::debug!("Ignoring dependency {}", package.name);
return None;
},
};

Some(PackageDescriptor {
Expand Down
22 changes: 18 additions & 4 deletions lockfile/src/parsers/pypi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,17 @@ fn package<'a>(input: &'a str, registry: Option<&str>) -> IResult<&'a str, Packa

// Parse first-party dependencies.
let (input, version) = package_version(input)?;
let version = match registry {
Some(registry) => PackageVersion::ThirdParty(ThirdPartyVersion {
version: version.trim().into(),

// Parse local version specifier.
let (input, local_version) = opt(local_version)(input)?;

let version = match (registry, local_version) {
(_, Some(_)) => PackageVersion::Unknown,
(Some(registry), _) => PackageVersion::ThirdParty(ThirdPartyVersion {
version: local_version.unwrap_or(version).trim().into(),
registry: registry.into(),
}),
None => PackageVersion::FirstParty(version.trim().into()),
(None, None) => PackageVersion::FirstParty(version.trim().into()),
};

// Ensure line is empty after the dependency.
Expand Down Expand Up @@ -185,6 +190,15 @@ fn package_version(input: &str) -> IResult<&str, &str> {
recognize(many1(alt((alphanumeric1, tag(".")))))(input)
}

/// Parse local version specifiers.
///
/// https://packaging.python.org/en/latest/specifications/version-specifiers/#local-version-identifiers
fn local_version(input: &str) -> IResult<&str, &str> {
let (input, _) = tag("+")(input)?;

recognize(many1(alt((alphanumeric1, tag(".")))))(input)
}

fn identifier(input: &str) -> IResult<&str, &str> {
recognize(pair(alphanumeric1, many0(alt((alphanumeric1, alt((tag("-"), tag("_"), tag("."))))))))(
input,
Expand Down
7 changes: 6 additions & 1 deletion lockfile/src/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ mod tests {
let pkgs = PyRequirements
.parse(include_str!("../../tests/fixtures/requirements-locked.txt"))
.unwrap();
assert_eq!(pkgs.len(), 14);
assert_eq!(pkgs.len(), 15);

let expected_pkgs = [
Package {
Expand Down Expand Up @@ -317,6 +317,11 @@ mod tests {
}),
package_type: PackageType::PyPi,
},
Package {
name: "localversion".into(),
version: PackageVersion::Unknown,
package_type: PackageType::PyPi,
},
];

for expected_pkg in expected_pkgs {
Expand Down
2 changes: 2 additions & 0 deletions tests/fixtures/requirements-locked.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ requests[security,tests]==2.28.1

werkzeug==2.9.2 ; python_version >= "3.7" and python_version < "3.12"

localversion==2.3.4+1.0.99.local

attr @ file:///tmp/attr

numpy @ file:///tmp/testing/numpy-1.23.5-pp38-pypy38_pp73-win_amd64.whl
Expand Down
1 change: 1 addition & 0 deletions tests/fixtures/requirements-unlocked.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ FooProject8 > 1.8.*
FooProject9 > 2.0.*, !=2.1
FooProject10==1.2.3 --random-flag
git+https://github.com/matiascodesal/git-for-pip-example.git@v1.0.0#egg=my-git-package
localversion >= 2.3.4+1.0.99.local

0 comments on commit 16ab00e

Please sign in to comment.