Skip to content

Commit 12ff140

Browse files
committed
fix: support and test more configurations
Signed-off-by: Henry Schreiner <[email protected]>
1 parent f21d1ee commit 12ff140

File tree

2 files changed

+66
-5
lines changed

2 files changed

+66
-5
lines changed

src/scikit_build_core/metadata/__init__.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,24 @@
3232
_DICT_STR_FIELDS = frozenset(
3333
[
3434
"urls",
35-
"authors",
36-
"maintainers",
3735
"scripts",
3836
"gui-scripts",
3937
]
4038
)
4139

40+
_LIST_DICT_FIELDS = frozenset(
41+
[
42+
"authors",
43+
"maintainers",
44+
]
45+
)
46+
4247
# "dynamic" and "name" can't be set or requested
4348
_ALL_FIELDS = (
4449
_STR_FIELDS
4550
| _LIST_STR_FIELDS
4651
| _DICT_STR_FIELDS
52+
| _LIST_DICT_FIELDS
4753
| frozenset(
4854
[
4955
"optional-dependencies",
@@ -53,12 +59,15 @@
5359
)
5460
)
5561

56-
T = typing.TypeVar("T", bound="str | list[str] | dict[str, str] | dict[str, list[str]]")
62+
T = typing.TypeVar(
63+
"T",
64+
bound="str | list[str] | list[dict[str, str]] | dict[str, str] | dict[str, list[str]] | dict[str, dict[str, str]]",
65+
)
5766

5867

5968
def _process_dynamic_metadata(field: str, action: Callable[[str], str], result: T) -> T:
6069
"""
61-
Helper function for processing the an action on the various possible metadata fields.
70+
Helper function for processing an action on the various possible metadata fields.
6271
"""
6372

6473
if field in _STR_FIELDS:
@@ -77,7 +86,16 @@ def _process_dynamic_metadata(field: str, action: Callable[[str], str], result:
7786
):
7887
msg = f"Field {field!r} must be a dictionary of strings"
7988
raise RuntimeError(msg)
80-
return {k: action(v) for k, v in result.items()} # type: ignore[return-value]
89+
return {action(k): action(v) for k, v in result.items()} # type: ignore[return-value]
90+
if field in _LIST_DICT_FIELDS:
91+
if not isinstance(result, list) or not all(
92+
isinstance(k, str) and isinstance(v, str)
93+
for d in result
94+
for k, v in d.items()
95+
):
96+
msg = f"Field {field!r} must be a dictionary of strings"
97+
raise RuntimeError(msg)
98+
return [{k: action(v) for k, v in d.items()} for d in result] # type: ignore[return-value]
8199
if field == "entry-points":
82100
if not isinstance(result, dict) or not all(
83101
isinstance(d, dict)
@@ -86,6 +104,10 @@ def _process_dynamic_metadata(field: str, action: Callable[[str], str], result:
86104
):
87105
msg = "Field 'entry-points' must be a dictionary of dictionary of strings"
88106
raise RuntimeError(msg)
107+
return {
108+
dk: {action(k): action(v) for k, v in dv.items()}
109+
for dk, dv in result.items()
110+
} # type: ignore[return-value]
89111
if field == "optional-dependencies":
90112
if not isinstance(result, dict) or not all(
91113
isinstance(v, list) for v in result.values()

tests/test_dynamic_metadata_unit.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1+
from typing import Any
2+
3+
import pytest
4+
15
from scikit_build_core.builder._load_provider import process_dynamic_metadata
6+
from scikit_build_core.metadata import _process_dynamic_metadata
27

38

49
def test_template_basic() -> None:
@@ -64,3 +69,37 @@ def test_regex() -> None:
6469
)
6570

6671
assert pyproject["requires-python"] == ">=scikit_build_core"
72+
73+
74+
@pytest.mark.parametrize(
75+
("field", "input", "output"),
76+
[
77+
pytest.param("version", "{sub}", "42", id="str"),
78+
pytest.param("classifiers", ["a", "{sub}"], ["a", "42"], id="list-str"),
79+
pytest.param(
80+
"scripts",
81+
{"a": "{sub}", "{sub}": "b"},
82+
{"a": "42", "42": "b"},
83+
id="dict-str",
84+
),
85+
pytest.param(
86+
"authors", [{"name": "{sub}"}], [{"name": "42"}], id="list-dict-str"
87+
),
88+
pytest.param(
89+
"optional-dependencies",
90+
{"dev": ["{sub}"]},
91+
{"dev": ["42"]},
92+
id="dict-list-str",
93+
),
94+
pytest.param("readme", {"text": "{sub}"}, {"text": "42"}, id="readme"),
95+
pytest.param(
96+
"entry-points",
97+
{"ep": {"{sub}": "{sub}"}},
98+
{"ep": {"42": "42"}},
99+
id="dict-dict-str",
100+
),
101+
],
102+
)
103+
def test_actions(field: str, input: Any, output: Any) -> None:
104+
result = _process_dynamic_metadata(field, lambda x: x.format(sub=42), input)
105+
assert output == result

0 commit comments

Comments
 (0)