Skip to content
Merged
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
40 changes: 39 additions & 1 deletion crates/pixi_build_python/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ pub enum MetadataError {
PyProjectToml(#[from] toml::de::Error),
#[error("failed to parse version from pyproject.toml, {0}")]
ParseVersion(ParseVersionError),
#[error("`pixi-build-python` requires a `pyproject.toml` at {0}")]
#[diagnostic(help(
"Add a PEP 517/518 `pyproject.toml` to the package source directory, or use a different build backend."
))]
MissingPyProjectToml(PathBuf),
#[error(transparent)]
Io(#[from] std::io::Error),
}
Expand Down Expand Up @@ -72,8 +77,15 @@ impl PyprojectMetadataProvider {
/// Ensures that the manifest is loaded
fn ensure_manifest(&self) -> Result<&PyProjectToml, MetadataError> {
self.pyproject_manifest.get_or_try_init(move || {
let pyproject_toml_path = self.manifest_root.join("pyproject.toml");
let pyproject_toml_content =
fs_err::read_to_string(self.manifest_root.join("pyproject.toml"))?;
fs_err::read_to_string(&pyproject_toml_path).map_err(|err| {
if err.kind() == std::io::ErrorKind::NotFound {
MetadataError::MissingPyProjectToml(pyproject_toml_path.clone())
} else {
MetadataError::Io(err)
}
})?;
toml::from_str(&pyproject_toml_content).map_err(MetadataError::PyProjectToml)
})
}
Expand Down Expand Up @@ -750,6 +762,32 @@ version = "1.0.0"
}
}

#[test]
fn test_missing_pyproject_toml_errors_clearly() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let mut provider = create_metadata_provider(temp_dir.path());

let err = provider
.name()
.expect_err("missing pyproject.toml should return an error");
let message = err.to_string();
let expected_path = temp_dir.path().join("pyproject.toml");

match &err {
MetadataError::MissingPyProjectToml(path) => assert_eq!(path, &expected_path),
other => panic!("Expected MissingPyProjectToml, got: {other:?}"),
}

assert!(
message.contains("requires a `pyproject.toml`"),
"unexpected error message: {message}"
);
assert!(
message.contains(&expected_path.display().to_string()),
"error should mention the `pyproject.toml` path: {message}"
);
}

#[test]
fn test_summary_equals_description() {
let pyproject_toml_content = r#"
Expand Down
Loading