diff --git a/crates/uv-build/src/lib.rs b/crates/uv-build/src/lib.rs index 8dae416ce917..9041b1c0fc48 100644 --- a/crates/uv-build/src/lib.rs +++ b/crates/uv-build/src/lib.rs @@ -14,9 +14,9 @@ use std::{env, iter}; use fs_err as fs; use indoc::formatdoc; -use itertools::Itertools; +use itertools::{Either, Itertools}; use once_cell::sync::Lazy; -use pyproject_toml::{BuildSystem, Project}; +use pyproject_toml::Project; use regex::Regex; use serde::{Deserialize, Serialize}; use tempfile::{tempdir_in, TempDir}; @@ -183,6 +183,37 @@ pub struct PyProjectToml { pub project: Option, } +/// The `[build-system]` section of a pyproject.toml as specified in PEP 517. +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub struct BuildSystem { + /// PEP 508 dependencies required to execute the build system. + pub requires: Vec, + /// A string naming a Python object that will be used to perform the build. + pub build_backend: Option, + /// Specify that their backend code is hosted in-tree, this key contains a list of directories. + pub backend_path: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[serde(untagged)] +pub enum BackendPath { + /// A list of paths (matching the schema). + List(Vec), + /// A single path, included for compatibility (see, e.g., `flit_core==2.3.0`, which uses + /// `backend-path = "."`). + String(String), +} + +impl BackendPath { + fn iter(&self) -> impl Iterator { + match self { + BackendPath::List(list) => Either::Left(list.iter().map(std::string::String::as_str)), + BackendPath::String(s) => Either::Right(iter::once(s.as_str())), + } + } +} + /// `[build-backend]` from pyproject.toml #[derive(Debug, Clone, PartialEq, Eq)] struct Pep517Backend { @@ -194,7 +225,7 @@ struct Pep517Backend { /// `build-backend.requirements` in pyproject.toml requirements: Vec, /// - backend_path: Option>, + backend_path: Option, } impl Pep517Backend { @@ -207,9 +238,8 @@ impl Pep517Backend { let backend_path_encoded = self .backend_path - .clone() - .unwrap_or_default() .iter() + .flat_map(BackendPath::iter) .map(|path| { // Turn into properly escaped python string '"'.to_string()