Normalize optional dependency group names in pyproject files (#253)

Going to add some tests.

Extends #239 
Closes #245 

Normalizes optional dependency group names found in pyproject files
before comparing them to the normalized user-requested extras.
This commit is contained in:
Zanie Blue 2023-10-31 14:15:00 -05:00 committed by GitHub
parent 3312ce30f5
commit 322532d6f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 94 additions and 7 deletions

View file

@ -82,13 +82,16 @@ impl RequirementsSpecification {
// Include any optional dependencies specified in `extras`
project.optional_dependencies.into_iter().flat_map(
|optional_dependencies| {
extras.iter().flat_map(move |extra| {
optional_dependencies
.get(extra.as_ref())
.cloned()
// undefined extra requests are ignored silently
.unwrap_or_default()
})
optional_dependencies
.iter()
.flat_map(|(name, requirements)| {
if extras.contains(&ExtraName::normalize(name)) {
requirements.clone()
} else {
vec![]
}
})
.collect::<Vec<Requirement>>()
},
),
)

View file

@ -280,3 +280,56 @@ optional-dependencies.foo = [
Ok(())
}
/// Resolve a package from an extra with unnormalized names in a `pyproject.toml` file.
#[test]
fn compile_pyproject_toml_extra_name_normalization() -> Result<()> {
let temp_dir = assert_fs::TempDir::new()?;
let cache_dir = assert_fs::TempDir::new()?;
let venv = temp_dir.child(".venv");
Command::new(get_cargo_bin(BIN_NAME))
.arg("venv")
.arg(venv.as_os_str())
.arg("--cache-dir")
.arg(cache_dir.path())
.current_dir(&temp_dir)
.assert()
.success();
venv.assert(predicates::path::is_dir());
let pyproject_toml = temp_dir.child("pyproject.toml");
pyproject_toml.touch()?;
pyproject_toml.write_str(
r#"[build-system]
requires = ["setuptools", "wheel"]
[project]
name = "project"
dependencies = []
optional-dependencies."FrIeNdLy-._.-bArD" = [
"django==5.0b1",
]
"#,
)?;
insta::with_settings!({
filters => vec![
(r"\d+(ms|s)", "[TIME]"),
(r"# .* pip-compile", "# [BIN_PATH] pip-compile"),
(r"--cache-dir .*", "--cache-dir [CACHE_DIR]"),
]
}, {
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.arg("pip-compile")
.arg("pyproject.toml")
.arg("--extra")
.arg("FRiENDlY-...-_-BARd")
.arg("--cache-dir")
.arg(cache_dir.path())
.env("VIRTUAL_ENV", venv.as_os_str())
.current_dir(&temp_dir));
});
Ok(())
}

View file

@ -0,0 +1,28 @@
---
source: crates/puffin-cli/tests/pip_compile.rs
info:
program: puffin
args:
- pip-compile
- pyproject.toml
- "--extra"
- FRiENDlY-...-_-BARd
- "--cache-dir"
- /var/folders/bc/qlsk3t6x7c9fhhbvvcg68k9c0000gp/T/.tmpFyLXQn
env:
VIRTUAL_ENV: /var/folders/bc/qlsk3t6x7c9fhhbvvcg68k9c0000gp/T/.tmpxfZatv/.venv
---
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by Puffin v0.0.1 via the following command:
# [BIN_PATH] pip-compile pyproject.toml --extra FRiENDlY-...-_-BARd --cache-dir [CACHE_DIR]
asgiref==3.7.2
# via django
django==5.0b1
sqlparse==0.4.4
# via django
----- stderr -----
Resolved 3 packages in [TIME]

View file

@ -22,6 +22,9 @@ impl Display for ExtraName {
static NAME_NORMALIZE: Lazy<Regex> = Lazy::new(|| Regex::new(r"[-_.]+").unwrap());
impl ExtraName {
/// Collapses any run of the characters `-`, `_` and `.` down to a single `-`.
/// Ex) "---", ".", and "__" all get converted to just "."
///
/// See: <https://peps.python.org/pep-0685/#specification/>
/// <https://packaging.python.org/en/latest/specifications/name-normalization/>
pub fn normalize(name: impl AsRef<str>) -> Self {