Skip to content

Commit cbddac0

Browse files
committed
fix: ensure needs always works
Signed-off-by: Henry Schreiner <[email protected]>
1 parent c2c2dd2 commit cbddac0

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

src/scikit_build_core/builder/_load_provider.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
if TYPE_CHECKING:
1111
from collections.abc import Generator, Iterable, Mapping
1212

13+
from ..metadata import _ALL_FIELDS
14+
1315
__all__ = ["load_dynamic_metadata", "load_provider"]
1416

1517

@@ -80,6 +82,9 @@ def _load_dynamic_metadata(
8082
]:
8183
for field, orig_config in metadata.items():
8284
if "provider" in orig_config:
85+
if field not in _ALL_FIELDS:
86+
msg = f"{field} is not a valid field"
87+
raise KeyError(msg)
8388
config = dict(orig_config)
8489
provider = config.pop("provider")
8590
provider_path = config.pop("provider-path", None)
@@ -89,6 +94,9 @@ def _load_dynamic_metadata(
8994
if isinstance(loaded_provider, DynamicMetadataNeeds)
9095
else []
9196
)
97+
if needs > _ALL_FIELDS:
98+
msg = f"Invalid dyanmic_metada_needs: {needs - _ALL_FIELDS}"
99+
raise KeyError(msg)
92100
yield field, loaded_provider, config, needs
93101
else:
94102
yield field, None, dict(orig_config), frozenset()
@@ -98,6 +106,10 @@ def load_dynamic_metadata(
98106
metadata: Mapping[str, Mapping[str, str]],
99107
) -> list[tuple[str, DMProtocols | None, dict[str, str]]]:
100108
initial = {f: (p, c, n) for (f, p, c, n) in _load_dynamic_metadata(metadata)}
101-
sorter = TopologicalSorter({f: n for f, (_, _, n) in initial.items()})
109+
110+
dynamic_fields = initial.keys()
111+
sorter = TopologicalSorter(
112+
{f: n & dynamic_fields for f, (_, _, n) in initial.items()}
113+
)
102114
order = sorter.static_order()
103115
return [(f, *initial[f][:2]) for f in order]

src/scikit_build_core/metadata/__init__.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from collections.abc import Callable
77

88

9-
__all__: list[str] = ["_process_dynamic_metadata"]
9+
__all__: list[str] = ["_ALL_FIELDS", "_process_dynamic_metadata"]
1010

1111

1212
# Name is not dynamically settable, so not in this list
@@ -29,6 +29,27 @@
2929
]
3030
)
3131

32+
_DICT_STR_FIELDS = frozenset(
33+
[
34+
"urls",
35+
"authors",
36+
"maintainers",
37+
]
38+
)
39+
40+
# "dynamic" and "name" can't be set or requested
41+
_ALL_FIELDS = (
42+
_STR_FIELDS
43+
| _LIST_STR_FIELDS
44+
| _DICT_STR_FIELDS
45+
| frozenset(
46+
[
47+
"optional-dependencies",
48+
"readme",
49+
]
50+
)
51+
)
52+
3253
T = typing.TypeVar("T", bound="str | list[str] | dict[str, str] | dict[str, list[str]]")
3354

3455

@@ -47,11 +68,11 @@ def _process_dynamic_metadata(field: str, action: Callable[[str], str], result:
4768
msg = f"Field {field!r} must be a list of strings"
4869
raise RuntimeError(msg)
4970
return [action(r) for r in result] # type: ignore[return-value]
50-
if field == "urls":
71+
if field in _DICT_STR_FIELDS:
5172
if not isinstance(result, dict) or not all(
5273
isinstance(v, str) for v in result.values()
5374
):
54-
msg = "Field 'urls' must be a dictionary of strings"
75+
msg = f"Field {field!r} must be a dictionary of strings"
5576
raise RuntimeError(msg)
5677
return {k: action(v) for k, v in result.items()} # type: ignore[return-value]
5778
if field == "optional-dependencies":

0 commit comments

Comments
 (0)