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

Add an initial implementation of PEP 735 Dependency Groups #24

Merged
merged 3 commits into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pyproject-toml"
version = "0.11.0"
version = "0.12.0"
description = "pyproject.toml parser in Rust"
edition = "2021"
license = "MIT"
Expand Down
4 changes: 4 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.12.0

* Support dependency groups (PEP 735)

## 0.11.0

* Update pep440_rs to 0.6.0
Expand Down
67 changes: 66 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use indexmap::IndexMap;
use pep440_rs::{Version, VersionSpecifiers};
use pep508_rs::Requirement;
use serde::{Deserialize, Serialize};
use std::ops::Deref;

/// The `[build-system]` section of a pyproject.toml as specified in PEP 517
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
Expand All @@ -23,6 +24,8 @@ pub struct PyProjectToml {
pub build_system: Option<BuildSystem>,
/// Project metadata
pub project: Option<Project>,
/// Dependency groups table
pub dependency_groups: Option<DependencyGroups>,
}

/// PEP 621 project metadata
Expand Down Expand Up @@ -161,6 +164,33 @@ pub struct Contact {
pub email: Option<String>,
}

/// The `[dependency-groups]` section of pyproject.toml, as specified in PEP 735
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(transparent)]
pub struct DependencyGroups(pub IndexMap<String, Vec<DependencyGroupSpecifier>>);

impl Deref for DependencyGroups {
type Target = IndexMap<String, Vec<DependencyGroupSpecifier>>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

/// A specifier item in a Dependency Group
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(rename_all = "kebab-case", untagged)]
pub enum DependencyGroupSpecifier {
/// PEP 508 requirement string
String(Requirement),
/// Include another dependency group
#[serde(rename_all = "kebab-case")]
Table {
/// The name of the group to include
include_group: Option<String>,
},
}

impl PyProjectToml {
/// Parse `pyproject.toml` content
pub fn new(content: &str) -> Result<Self, toml::de::Error> {
Expand All @@ -170,7 +200,7 @@ impl PyProjectToml {

#[cfg(test)]
mod tests {
use super::{License, LicenseFiles, PyProjectToml, ReadMe};
use super::{DependencyGroupSpecifier, License, LicenseFiles, PyProjectToml, ReadMe};
use pep440_rs::{Version, VersionSpecifiers};
use pep508_rs::Requirement;
use std::str::FromStr;
Expand Down Expand Up @@ -408,4 +438,39 @@ readme = {text = "ReadMe!", content-type = "text/plain"}
})
);
}

#[test]
fn test_parse_pyproject_toml_dependency_groups() {
let source = r#"[dependency-groups]
alpha = ["beta", "gamma", "delta"]
epsilon = ["eta<2.0", "theta==2024.09.01"]
iota = [{include-group = "alpha"}]
"#;
let project_toml = PyProjectToml::new(source).unwrap();
let dependency_groups = project_toml.dependency_groups.as_ref().unwrap();

assert_eq!(
dependency_groups["alpha"],
vec![
DependencyGroupSpecifier::String(Requirement::from_str("beta").unwrap()),
DependencyGroupSpecifier::String(Requirement::from_str("gamma").unwrap()),
DependencyGroupSpecifier::String(Requirement::from_str("delta").unwrap(),)
]
);
assert_eq!(
dependency_groups["epsilon"],
vec![
DependencyGroupSpecifier::String(Requirement::from_str("eta<2.0").unwrap()),
DependencyGroupSpecifier::String(
Requirement::from_str("theta==2024.09.01").unwrap()
)
]
);
assert_eq!(
dependency_groups["iota"],
vec![DependencyGroupSpecifier::Table {
include_group: Some("alpha".to_string())
}]
);
}
}