Skip to content

Commit 065b662

Browse files
LecrisUThenryiii
authored andcommitted
Save a record of the override actions
Used for further validations Signed-off-by: Cristian Le <git@lecris.dev>
1 parent 3f371ff commit 065b662

File tree

2 files changed

+98
-4
lines changed

2 files changed

+98
-4
lines changed

src/scikit_build_core/settings/skbuild_overrides.py

Lines changed: 97 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,8 @@
1819
from ..errors import CMakeNotFoundError
1920
from ..resources import resources
2021

21-
__all__ = ["process_overrides", "regex_match"]
22+
23+
__all__ = ["OverrideRecord", "process_overrides", "regex_match"]
2224

2325

2426
def __dir__() -> list[str]:
@@ -29,6 +31,30 @@ def __dir__() -> list[str]:
2931
from collections.abc import Mapping
3032

3133

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

259285

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

273350
global_matched: set[str] = set()
351+
overriden_items: dict[str, OverrideRecord] = {}
274352
for override in tool_skb.pop("overrides", []):
275353
passed_any: dict[str, str] | None = None
276354
passed_all: dict[str, str] | None = None
@@ -354,17 +432,33 @@ def process_overrides(
354432
inherit1 = inherit_override.get(key, {})
355433
if isinstance(value, dict):
356434
for key2, value2 in value.items():
435+
record_override(
436+
*[key, key2],
437+
value=value,
438+
tool_skb=tool_skb,
439+
overriden_items=overriden_items,
440+
passed_all=passed_all,
441+
passed_any=passed_any,
442+
)
357443
inherit2 = inherit1.get(key2, "none")
358444
inner = tool_skb.get(key, {})
359445
inner[key2] = inherit_join(
360446
value2, inner.get(key2, None), inherit2
361447
)
362448
tool_skb[key] = inner
363449
else:
450+
record_override(
451+
key,
452+
value=value,
453+
tool_skb=tool_skb,
454+
overriden_items=overriden_items,
455+
passed_all=passed_all,
456+
passed_any=passed_any,
457+
)
364458
inherit_override_tmp = inherit_override or "none"
365459
if isinstance(inherit_override_tmp, dict):
366460
assert not inherit_override_tmp
367461
tool_skb[key] = inherit_join(
368462
value, tool_skb.get(key), inherit_override_tmp
369463
)
370-
return global_matched
464+
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_overrides(
154+
self.overrides, self.overriden_items = process_overrides(
155155
pyproject.get("tool", {}).get("scikit-build", {}),
156156
state=state,
157157
env=env,

0 commit comments

Comments
 (0)