Skip to content

Commit

Permalink
config: capitalise inner keys in JSON dump
Browse files Browse the repository at this point in the history
  • Loading branch information
behrmann committed Mar 26, 2024
1 parent 878bb3f commit b5b07db
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 44 deletions.
44 changes: 28 additions & 16 deletions mkosi/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,18 @@ def __call__(
parser.exit()


S = TypeVar("S", bound=Any)
T = TypeVar("T", bound=Any)


def transform_dict_keys(obj: T, key_transformer: Callable[[S], S]) -> T:
if isinstance(obj, list):
return cast(T, [transform_dict_keys(e, key_transformer) for e in obj])
elif isinstance(obj, dict) and type(obj) is dict:
return cast(T, {key_transformer(k): transform_dict_keys(v, key_transformer) for k, v in obj.items()})
return obj # type: ignore


@dataclasses.dataclass(frozen=True)
class Args:
verb: Verb
Expand Down Expand Up @@ -1233,7 +1245,7 @@ def to_dict(self) -> dict[str, Any]:
def key_transformer(k: str) -> str:
return "".join(p.capitalize() for p in k.split("_"))

return {key_transformer(k): v for k, v in dataclasses.asdict(self).items()}
return transform_dict_keys(dataclasses.asdict(self), key_transformer)

def to_json(self, *, indent: Optional[int] = 4, sort_keys: bool = True) -> str:
"""Dump MkosiArgs as JSON string."""
Expand Down Expand Up @@ -1553,7 +1565,7 @@ def key_transformer(k: str) -> str:
return s.name
return "".join(p.capitalize() for p in k.split("_"))

return {key_transformer(k): v for k, v in dataclasses.asdict(self).items()}
return transform_dict_keys(dataclasses.asdict(self), key_transformer)

def to_json(self, *, indent: Optional[int] = 4, sort_keys: bool = True) -> str:
"""Dump MkosiConfig as JSON string."""
Expand Down Expand Up @@ -3899,12 +3911,12 @@ def config_tree_transformer(trees: list[dict[str, Any]], fieldtype: type[ConfigT
# TODO: exchange for TypeGuard and list comprehension once on 3.10
ret = []
for d in trees:
assert "source" in d
assert "target" in d
assert "Source" in d
assert "Target" in d
ret.append(
ConfigTree(
source=Path(d["source"]),
target=Path(d["target"]) if d["target"] is not None else None,
source=Path(d["Source"]),
target=Path(d["Target"]) if d["Target"] is not None else None,
)
)
return ret
Expand All @@ -3926,16 +3938,16 @@ def config_drive_transformer(drives: list[dict[str, Any]], fieldtype: type[QemuD
# TODO: exchange for TypeGuard and list comprehension once on 3.10
ret = []
for d in drives:
assert "id" in d
assert "size" in d
assert "directory" in d
assert "options" in d
assert "Id" in d
assert "Size" in d
assert "Directory" in d
assert "Options" in d
ret.append(
QemuDrive(
id=d["id"],
size=int(d["size"]),
directory=Path(d["directory"]) if d["directory"] else None,
options=d["options"],
id=d["Id"],
size=int(d["Size"]),
directory=Path(d["Directory"]) if d["Directory"] else None,
options=d["Options"],
)
)
return ret
Expand All @@ -3947,8 +3959,8 @@ def generic_version_transformer(
return GenericVersion(version) if version is not None else None

def key_source_transformer(keysource: dict[str, Any], fieldtype: type[KeySource]) -> KeySource:
assert "type" in keysource
return KeySource(type=KeySource.Type(keysource["type"]), source=keysource.get("source", ""))
assert "Type" in keysource
return KeySource(type=KeySource.Type(keysource["Type"]), source=keysource.get("Source", ""))

transformers = {
Path: path_transformer,
Expand Down
58 changes: 30 additions & 28 deletions tests/test_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
Config,
ConfigFeature,
ConfigTree,
Credentials,
DocFormat,
Environment,
KeySource,
ManifestFormat,
Network,
Expand Down Expand Up @@ -103,8 +105,8 @@ def test_config() -> None:
],
"BuildSources": [
{
"source": "/qux",
"target": "/frob"
"Source": "/qux",
"Target": "/frob"
}
],
"BuildSourcesEphemeral": true,
Expand Down Expand Up @@ -194,8 +196,8 @@ def test_config() -> None:
"PackageDirectories": [],
"PackageManagerTrees": [
{
"source": "/foo/bar",
"target": null
"Source": "/foo/bar",
"Target": null
}
],
"Packages": [],
Expand All @@ -215,16 +217,16 @@ def test_config() -> None:
"QemuCdrom": false,
"QemuDrives": [
{
"directory": "/foo/bar",
"id": "abc",
"options": "abc,qed",
"size": 200
"Directory": "/foo/bar",
"Id": "abc",
"Options": "abc,qed",
"Size": 200
},
{
"directory": null,
"id": "abc",
"options": "",
"size": 200
"Directory": null,
"Id": "abc",
"Options": "",
"Size": 200
}
],
"QemuFirmware": "linux",
Expand Down Expand Up @@ -256,12 +258,12 @@ def test_config() -> None:
"RuntimeSize": 8589934592,
"RuntimeTrees": [
{
"source": "/foo/bar",
"target": "/baz"
"Source": "/foo/bar",
"Target": "/baz"
},
{
"source": "/bar/baz",
"target": "/qux"
"Source": "/bar/baz",
"Target": "/qux"
}
],
"SELinuxRelabel": "disabled",
Expand All @@ -271,8 +273,8 @@ def test_config() -> None:
"SecureBootCertificate": null,
"SecureBootKey": "/path/to/keyfile",
"SecureBootKeySource": {
"source": "",
"type": "file"
"Source": "",
"Type": "file"
},
"SecureBootSignTool": "pesign",
"Seed": "7496d7d8-7f08-4a2b-96c6-ec8c43791b60",
Expand All @@ -281,12 +283,12 @@ def test_config() -> None:
"SignExpectedPcr": "disabled",
"SkeletonTrees": [
{
"source": "/foo/bar",
"target": "/"
"Source": "/foo/bar",
"Target": "/"
},
{
"source": "/bar/baz",
"target": "/qux"
"Source": "/bar/baz",
"Target": "/qux"
}
],
"SourceDateEpoch": 12345,
Expand All @@ -303,8 +305,8 @@ def test_config() -> None:
"ToolsTreeMirror": null,
"ToolsTreePackageManagerTrees": [
{
"source": "/a/b/c",
"target": "/"
"Source": "/a/b/c",
"Target": "/"
}
],
"ToolsTreePackages": [],
Expand All @@ -317,8 +319,8 @@ def test_config() -> None:
"VerityCertificate": "/path/to/cert",
"VerityKey": null,
"VerityKeySource": {
"source": "",
"type": "file"
"Source": "",
"Type": "file"
},
"VirtualMachineMonitor": "qemu",
"WithDocs": true,
Expand Down Expand Up @@ -349,10 +351,10 @@ def test_config() -> None:
clean_package_metadata = ConfigFeature.auto,
compress_level = 3,
compress_output = Compression.bz2,
credentials = {"credkey": "credval"},
credentials = Credentials({"credkey": "credval"}),
dependencies = ("dep1",),
distribution = Distribution.fedora,
environment = {"foo": "foo", "BAR": "BAR", "Qux": "Qux"},
environment = Environment({"foo": "foo", "BAR": "BAR", "Qux": "Qux"}),
environment_files = [],
ephemeral = True,
extra_search_paths = [],
Expand Down

0 comments on commit b5b07db

Please sign in to comment.