Skip to content

Commit 0d27a42

Browse files
committed
Save a record of the override actions
Used for further validations Signed-off-by: Cristian Le <git@lecris.dev>
1 parent bdf5a4a commit 0d27a42

File tree

2 files changed

+97
-4
lines changed

2 files changed

+97
-4
lines changed

src/scikit_build_core/settings/skbuild_overrides.py

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import dataclasses
34
import os
45
import platform
56
import re
@@ -18,7 +19,7 @@
1819
from ..errors import CMakeNotFoundError
1920
from ..resources import resources
2021

21-
__all__ = ["process_overides", "regex_match"]
22+
__all__ = ["OverrideRecord", "process_overides", "regex_match"]
2223

2324

2425
def __dir__() -> list[str]:
@@ -29,6 +30,30 @@ def __dir__() -> list[str]:
2930
from collections.abc import Mapping
3031

3132

33+
@dataclasses.dataclass
34+
class OverrideRecord:
35+
"""
36+
Record of the override action.
37+
38+
Saves the original and final values, and the override reasons.
39+
"""
40+
41+
key: str
42+
"""Settings key that is overridden."""
43+
original_value: Any | None
44+
"""
45+
Original value in the pyproject table.
46+
47+
If the pyproject table did not have the key, this is a ``None``.
48+
"""
49+
value: Any
50+
"""Final value."""
51+
passed_all: dict[str, str] | None
52+
"""All if statements that passed (except the effective ``match_any``)."""
53+
passed_any: dict[str, str] | None
54+
"""All if.any statements that passed."""
55+
56+
3257
def strtobool(value: str) -> bool:
3358
"""
3459
Converts a environment variable string into a boolean value.
@@ -257,20 +282,72 @@ def inherit_join(
257282
raise TypeError(msg)
258283

259284

285+
def record_override(
286+
*keys: str,
287+
value: Any,
288+
tool_skb: dict[str, Any],
289+
overriden_items: dict[str, OverrideRecord],
290+
passed_all: dict[str, str] | None,
291+
passed_any: dict[str, str] | None,
292+
) -> None:
293+
full_key = ".".join(keys)
294+
# Get the original_value to construct the record
295+
if full_key in overriden_items:
296+
# We found the original value from a previous override record
297+
original_value = overriden_items[full_key].original_value
298+
else:
299+
# Otherwise navigate the original pyproject table until we resolved all keys
300+
_dict_or_value = tool_skb
301+
keys_list = [*keys]
302+
while keys_list:
303+
k = keys_list.pop(0)
304+
if k not in _dict_or_value:
305+
# We hit a dead end so we imply the original_value was not set (`None`)
306+
original_value = None
307+
break
308+
_dict_or_value = _dict_or_value[k]
309+
if isinstance(_dict_or_value, dict):
310+
# If the value is a dict it is either the final value or we continue
311+
# to navigate it
312+
continue
313+
# Otherwise it should be the final value
314+
original_value = _dict_or_value
315+
if keys_list:
316+
msg = f"Could not navigate to the key {full_key} because {k} is a {type(_dict_or_value)}"
317+
raise TypeError(msg)
318+
break
319+
else:
320+
# We exhausted all keys so the current value should be the table key we are
321+
# interested in
322+
original_value = _dict_or_value
323+
# Now save the override record
324+
overriden_items[full_key] = OverrideRecord(
325+
key=keys[-1],
326+
original_value=original_value,
327+
value=value,
328+
passed_any=passed_any,
329+
passed_all=passed_all,
330+
)
331+
332+
260333
def process_overides(
261334
tool_skb: dict[str, Any],
262335
*,
263336
state: Literal["sdist", "wheel", "editable", "metadata_wheel", "metadata_editable"],
264337
retry: bool,
265338
env: Mapping[str, str] | None = None,
266-
) -> set[str]:
339+
) -> tuple[set[str], dict[str, OverrideRecord]]:
267340
"""
268341
Process overrides into the main dictionary if they match. Modifies the input
269342
dictionary. Must be run from the package directory.
343+
344+
:return: A tuple of the set of matching overrides and a dict of changed keys and
345+
override record
270346
"""
271347
has_dist_info = Path("PKG-INFO").is_file()
272348

273349
global_matched: set[str] = set()
350+
overriden_items: dict[str, OverrideRecord] = {}
274351
for override in tool_skb.pop("overrides", []):
275352
passed_any: dict[str, str] | None = None
276353
passed_all: dict[str, str] | None = None
@@ -354,17 +431,33 @@ def process_overides(
354431
inherit1 = inherit_override.get(key, {})
355432
if isinstance(value, dict):
356433
for key2, value2 in value.items():
434+
record_override(
435+
*[key, key2],
436+
value=value,
437+
tool_skb=tool_skb,
438+
overriden_items=overriden_items,
439+
passed_all=passed_all,
440+
passed_any=passed_any,
441+
)
357442
inherit2 = inherit1.get(key2, "none")
358443
inner = tool_skb.get(key, {})
359444
inner[key2] = inherit_join(
360445
value2, inner.get(key2, None), inherit2
361446
)
362447
tool_skb[key] = inner
363448
else:
449+
record_override(
450+
key,
451+
value=value,
452+
tool_skb=tool_skb,
453+
overriden_items=overriden_items,
454+
passed_all=passed_all,
455+
passed_any=passed_any,
456+
)
364457
inherit_override_tmp = inherit_override or "none"
365458
if isinstance(inherit_override_tmp, dict):
366459
assert not inherit_override_tmp
367460
tool_skb[key] = inherit_join(
368461
value, tool_skb.get(key), inherit_override_tmp
369462
)
370-
return global_matched
463+
return global_matched, overriden_items

src/scikit_build_core/settings/skbuild_read_settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ def __init__(
151151

152152
# Handle overrides
153153
pyproject = copy.deepcopy(pyproject)
154-
self.overrides = process_overides(
154+
self.overrides, self.overriden_items = process_overides(
155155
pyproject.get("tool", {}).get("scikit-build", {}),
156156
state=state,
157157
env=env,

0 commit comments

Comments
 (0)