Skip to content

Commit 86701ad

Browse files
authored
feat: implement package.build.configuration parsing (#3115)
1 parent 889b6a6 commit 86701ad

File tree

7 files changed

+154
-3
lines changed

7 files changed

+154
-3
lines changed

crates/pixi_build_frontend/src/protocols/builders/pixi.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,17 @@ impl ProtocolBuilder {
8080
workspace_manifest: WorkspaceManifest,
8181
package_manifest: PackageManifest,
8282
) -> Self {
83+
let configuration = package_manifest.build.configuration.clone().map(|v| {
84+
v.deserialize_into()
85+
.expect("Configuration dictionary should be serializable to JSON")
86+
});
87+
8388
Self {
8489
source_dir,
8590
manifest_path,
8691
workspace_manifest,
8792
package_manifest,
88-
configuration: None,
93+
configuration,
8994
backend_override: None,
9095
channel_config: None,
9196
cache_dir: None,

crates/pixi_manifest/src/build_system.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ pub struct PackageBuild {
2020
/// The channels to use for fetching build tools. If this is `None` the
2121
/// channels from the containing workspace should be used.
2222
pub channels: Option<Vec<NamedChannelOrUrl>>,
23+
24+
/// Additional configuration for the build backend.
25+
pub configuration: Option<serde_value::Value>,
2326
}
2427

2528
#[derive(Debug, Clone)]

crates/pixi_manifest/src/toml/build_system.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
use std::collections::BTreeMap;
2+
13
use itertools::Either;
24
use pixi_spec::TomlSpec;
35
use pixi_toml::{TomlFromStr, TomlWith};
46
use rattler_conda_types::NamedChannelOrUrl;
5-
use toml_span::{de_helpers::TableHelper, DeserError, Spanned, Value};
7+
use toml_span::{de_helpers::TableHelper, value::ValueInner, DeserError, Spanned, Value};
68

79
use crate::{
810
build_system::BuildBackend,
@@ -16,6 +18,7 @@ pub struct TomlPackageBuild {
1618
pub backend: PixiSpanned<TomlBuildBackend>,
1719
pub channels: Option<PixiSpanned<Vec<NamedChannelOrUrl>>>,
1820
pub additional_dependencies: UniquePackageMap,
21+
pub configuration: Option<serde_value::Value>,
1922
}
2023

2124
#[derive(Debug)]
@@ -74,10 +77,37 @@ impl TomlPackageBuild {
7477
},
7578
additional_dependencies,
7679
channels: self.channels.map(|channels| channels.value),
80+
configuration: self.configuration,
7781
})
7882
}
7983
}
8084

85+
fn convert_toml_to_serde(value: &mut Value) -> Result<serde_value::Value, DeserError> {
86+
Ok(match value.take() {
87+
ValueInner::String(s) => serde_value::Value::String(s.to_string()),
88+
ValueInner::Integer(i) => serde_value::Value::I64(i),
89+
ValueInner::Float(f) => serde_value::Value::F64(f),
90+
ValueInner::Boolean(b) => serde_value::Value::Bool(b),
91+
ValueInner::Array(mut arr) => {
92+
let mut json_arr = Vec::new();
93+
for item in &mut arr {
94+
json_arr.push(convert_toml_to_serde(item)?);
95+
}
96+
serde_value::Value::Seq(json_arr)
97+
}
98+
ValueInner::Table(table) => {
99+
let mut map = BTreeMap::new();
100+
for (key, mut val) in table {
101+
map.insert(
102+
serde_value::Value::String(key.to_string()),
103+
convert_toml_to_serde(&mut val)?,
104+
);
105+
}
106+
serde_value::Value::Map(map)
107+
}
108+
})
109+
}
110+
81111
impl<'de> toml_span::Deserialize<'de> for TomlBuildBackend {
82112
fn deserialize(value: &mut Value<'de>) -> Result<Self, DeserError> {
83113
let mut th = TableHelper::new(value)?;
@@ -107,11 +137,18 @@ impl<'de> toml_span::Deserialize<'de> for TomlPackageBuild {
107137
span: Some(s.span.start..s.span.end),
108138
});
109139
let additional_dependencies = th.optional("additional-dependencies").unwrap_or_default();
140+
141+
let configuration = th
142+
.take("configuration")
143+
.map(|(_, mut value)| convert_toml_to_serde(&mut value))
144+
.transpose()?;
145+
110146
th.finalize(None)?;
111147
Ok(Self {
112148
backend: build_backend,
113149
channels,
114150
additional_dependencies,
151+
configuration,
115152
})
116153
}
117154
}
@@ -131,6 +168,18 @@ mod test {
131168
format_parse_error(pixi_toml, parse_error)
132169
}
133170

171+
#[test]
172+
fn test_configuration_parsing() {
173+
let toml = r#"
174+
backend = { name = "foobar", version = "*" }
175+
configuration = { key = "value", other = ["foo", "bar"], integer = 1234, nested = { abc = "def" } }
176+
"#;
177+
let parsed = <TomlPackageBuild as crate::toml::FromTomlStr>::from_toml_str(toml)
178+
.expect("parsing should succeed");
179+
180+
insta::assert_debug_snapshot!(parsed);
181+
}
182+
134183
#[test]
135184
fn test_disallow_source() {
136185
assert_snapshot!(expect_parse_failure(

crates/pixi_manifest/src/toml/snapshots/pixi_manifest__toml__build_system__test__additional_keys.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
source: crates/pixi_manifest/src/toml/build_system.rs
33
expression: "expect_parse_failure(r#\"\n backend = { name = \"foobar\", version = \"*\" }\n additional = \"key\"\n \"#)"
44
---
5-
× Unexpected keys, expected only 'backend', 'channels', 'additional-dependencies'
5+
× Unexpected keys, expected only 'backend', 'channels', 'additional-dependencies', 'configuration'
66
╭─[pixi.toml:3:13]
77
2backend = { name = "foobar", version = "*" }
88
3additional = "key"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
source: crates/pixi_manifest/src/toml/build_system.rs
3+
expression: parsed
4+
---
5+
TomlPackageBuild {
6+
backend: PixiSpanned {
7+
span: Some(
8+
23..57,
9+
),
10+
value: TomlBuildBackend {
11+
name: PixiSpanned {
12+
span: Some(
13+
33..39,
14+
),
15+
value: PackageName {
16+
normalized: None,
17+
source: "foobar",
18+
},
19+
},
20+
spec: TomlSpec {
21+
version: Some(
22+
Any,
23+
),
24+
url: None,
25+
git: None,
26+
path: None,
27+
branch: None,
28+
rev: None,
29+
tag: None,
30+
subdirectory: None,
31+
build: None,
32+
build_number: None,
33+
file_name: None,
34+
channel: None,
35+
subdir: None,
36+
md5: None,
37+
sha256: None,
38+
},
39+
},
40+
},
41+
channels: None,
42+
additional_dependencies: UniquePackageMap {
43+
specs: {},
44+
name_spans: {},
45+
value_spans: {},
46+
},
47+
configuration: Some(
48+
Map(
49+
{
50+
String(
51+
"integer",
52+
): I64(
53+
1234,
54+
),
55+
String(
56+
"key",
57+
): String(
58+
"value",
59+
),
60+
String(
61+
"nested",
62+
): Map(
63+
{
64+
String(
65+
"abc",
66+
): String(
67+
"def",
68+
),
69+
},
70+
),
71+
String(
72+
"other",
73+
): Seq(
74+
[
75+
String(
76+
"foo",
77+
),
78+
String(
79+
"bar",
80+
),
81+
],
82+
),
83+
},
84+
),
85+
),
86+
}

schema/model.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,9 @@ class Build(StrictBaseModel):
601601
additional_dependencies: Dependencies = Field(
602602
None, description="Additional dependencies to install alongside the build backend"
603603
)
604+
configuration: dict[str, Any] = Field(
605+
None, description="The configuration of the build backend"
606+
)
604607

605608

606609
class BuildBackend(MatchspecTable):

schema/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,11 @@
295295
}
296296
]
297297
}
298+
},
299+
"configuration": {
300+
"title": "Configuration",
301+
"description": "The configuration of the build backend",
302+
"type": "object"
298303
}
299304
}
300305
},

0 commit comments

Comments
 (0)