]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
json: move JSON keys to PascalCase
authorJoerg Behrmann <behrmann@physik.fu-berlin.de>
Wed, 4 Oct 2023 15:41:46 +0000 (17:41 +0200)
committerJoerg Behrmann <behrmann@physik.fu-berlin.de>
Thu, 5 Oct 2023 10:50:27 +0000 (12:50 +0200)
mkosi/config.py
tests/test_json.py

index 6150a0db1083b6a4cdd041518e522db497cc09b5..577a8b7653df88f6bdd63be843b8d86cf59819d4 100644 (file)
@@ -16,6 +16,7 @@ import math
 import operator
 import os.path
 import platform
+import re
 import shlex
 import shutil
 import subprocess
@@ -684,7 +685,11 @@ class MkosiArgs:
 
     def to_json(self, *, indent: Optional[int] = 4, sort_keys: bool = True) -> str:
         """Dump MKosiArgs as JSON string."""
-        return json.dumps(dataclasses.asdict(self), cls=MkosiJsonEncoder, indent=indent, sort_keys=sort_keys)
+        def key_transformer(k: str) -> str:
+            return "".join(p.capitalize() for p in k.split("_"))
+
+        d = {key_transformer(k): v for k, v in dataclasses.asdict(self).items()}
+        return json.dumps(d, cls=MkosiJsonEncoder, indent=indent, sort_keys=sort_keys)
 
     @classmethod
     def _load_json(cls, s: Union[str, dict[str, Any], SupportsRead[str], SupportsRead[bytes]]) -> dict[str, Any]:
@@ -698,8 +703,11 @@ class MkosiArgs:
         else:
             raise ValueError(f"{cls.__name__} can only be constructed from JSON from strings, dictionaries and files.")
 
-        transformer = json_type_transformer(cls)
-        return {k: transformer(k, v) for k, v in j.items()}
+        value_transformer = json_type_transformer(cls)
+        def key_transformer(k: str) -> str:
+            return "_".join(part.lower() for part in FALLBACK_NAME_TO_DEST_SPLITTER.split(k))
+
+        return {(tk := key_transformer(k)): value_transformer(tk, v) for k, v in j.items()}
 
     @classmethod
     def from_json(cls, s: Union[str, dict[str, Any], SupportsRead[str], SupportsRead[bytes]]) -> "MkosiArgs":
@@ -936,7 +944,13 @@ class MkosiConfig:
 
     def to_json(self, *, indent: Optional[int] = 4, sort_keys: bool = True) -> str:
         """Dump MKosiConfig as JSON string."""
-        return json.dumps(dataclasses.asdict(self), cls=MkosiJsonEncoder, indent=indent, sort_keys=sort_keys)
+        def key_transformer(k: str) -> str:
+            if (s := SETTINGS_LOOKUP_BY_DEST.get(k)) is not None:
+                return s.name
+            return "".join(p.capitalize() for p in k.split("_"))
+
+        d = {key_transformer(k): v for k, v in dataclasses.asdict(self).items()}
+        return json.dumps(d, cls=MkosiJsonEncoder, indent=indent, sort_keys=sort_keys)
 
     @classmethod
     def _load_json(cls, s: Union[str, dict[str, Any], SupportsRead[str], SupportsRead[bytes]]) -> dict[str, Any]:
@@ -950,8 +964,13 @@ class MkosiConfig:
         else:
             raise ValueError(f"{cls.__name__} can only be constructed from JSON from strings, dictionaries and files.")
 
-        transformer = json_type_transformer(cls)
-        return {k: transformer(k, v) for k, v in j.items()}
+        value_transformer = json_type_transformer(cls)
+        def key_transformer(k: str) -> str:
+            if (s := SETTINGS_LOOKUP_BY_NAME.get(k)) is not None:
+                return s.dest
+            return "_".join(part.lower() for part in FALLBACK_NAME_TO_DEST_SPLITTER.split(k))
+
+        return {(tk := key_transformer(k)): value_transformer(tk, v) for k, v in j.items()}
 
     @classmethod
     def from_json(cls, s: Union[str, dict[str, Any], SupportsRead[str], SupportsRead[bytes]]) -> "MkosiConfig":
@@ -1879,6 +1898,13 @@ MATCHES = (
 
 MATCH_LOOKUP = {m.name: m for m in MATCHES}
 
+# This regular expression can be used to split "AutoBump" -> ["Auto", "Bump"]
+# and "NSpawnSettings" -> ["NSpawn", "Settings"]
+# The first part (?<=[a-z]) is a positive look behind for a lower case letter
+# and (?=[A-Z]) is a lookahead assertion matching an upper case letter but not
+# consuming it
+FALLBACK_NAME_TO_DEST_SPLITTER = re.compile("(?<=[a-z])(?=[A-Z])")
+
 
 def create_argument_parser(action: type[argparse.Action]) -> argparse.ArgumentParser:
     parser = argparse.ArgumentParser(
index cbf5b2008ab09652b6a92cdf9155148d4f0955dc..e137e936c58f04da7a7cc9e7175ddaf4a50ce4cf 100644 (file)
@@ -31,20 +31,20 @@ def test_args(path: Optional[Path]) -> None:
     dump = textwrap.dedent(
         f"""\
         {{
-            "auto_bump": false,
-            "cmdline": [
+            "AutoBump": false,
+            "Cmdline": [
                 "foo",
                 "bar"
             ],
-            "debug": false,
-            "debug_shell": false,
-            "directory": {f'"{os.fspath(path)}"' if path is not None else 'null'},
-            "doc_format": "auto",
-            "force": 9001,
-            "genkey_common_name": "test",
-            "genkey_valid_days": "100",
-            "pager": true,
-            "verb": "build"
+            "Debug": false,
+            "DebugShell": false,
+            "Directory": {f'"{os.fspath(path)}"' if path is not None else 'null'},
+            "DocFormat": "auto",
+            "Force": 9001,
+            "GenkeyCommonName": "test",
+            "GenkeyValidDays": "100",
+            "Pager": true,
+            "Verb": "build"
         }}
         """
     )
@@ -71,60 +71,61 @@ def test_config() -> None:
     dump = textwrap.dedent(
         """\
         {
-            "acl": true,
-            "architecture": "ia64",
-            "autologin": false,
-            "base_trees": [
+            "Acl": true,
+            "Architecture": "ia64",
+            "Autologin": false,
+            "BaseTrees": [
                 "/hello/world"
             ],
-            "bios_bootloader": "none",
-            "bootable": "disabled",
-            "bootloader": "grub",
-            "build_dir": null,
-            "build_packages": [
+            "BiosBootloader": "none",
+            "Bootable": "disabled",
+            "Bootloader": "grub",
+            "BuildDirectory": null,
+            "BuildPackages": [
                 "pkg1",
                 "pkg2"
             ],
-            "build_scripts": [
+            "BuildScripts": [
                 "/path/to/buildscript"
             ],
-            "build_sources": [
+            "BuildSources": [
                 [
                     "/qux",
                     "/frob"
                 ]
             ],
-            "cache_dir": "/is/this/the/cachedir",
-            "cache_only": true,
-            "checksum": false,
-            "clean_package_metadata": "auto",
-            "compress_output": "bz2",
-            "credentials": {
+            "CacheDirectory": "/is/this/the/cachedir",
+            "CacheOnly": true,
+            "Checksum": false,
+            "CleanPackageMetadata": "auto",
+            "CompressOutput": "bz2",
+            "Credentials": {
                 "credkey": "credval"
             },
-            "dependencies": [
+            "Dependencies": [
                 "dep1"
             ],
-            "distribution": "fedora",
-            "environment": {},
-            "ephemeral": true,
-            "extra_search_paths": [],
-            "extra_trees": [],
-            "finalize_scripts": [],
-            "hostname": null,
-            "image_id": "myimage",
-            "image_version": "5",
-            "include": [],
-            "incremental": false,
-            "initrd_packages": [
+            "Distribution": "fedora",
+            "Environment": {},
+            "Ephemeral": true,
+            "ExtraSearchPaths": [],
+            "ExtraTrees": [],
+            "FinalizeScripts": [],
+            "Format": "uki",
+            "Hostname": null,
+            "ImageId": "myimage",
+            "ImageVersion": "5",
+            "Include": [],
+            "Incremental": false,
+            "InitrdPackages": [
                 "clevis"
             ],
-            "initrds": [
+            "Initrds": [
                 "/efi/initrd1",
                 "/efi/initrd2"
             ],
-            "kernel_command_line": [],
-            "kernel_command_line_extra": [
+            "KernelCommandLine": [],
+            "KernelCommandLineExtra": [
                 "look",
                 "im",
                 "on",
@@ -133,75 +134,74 @@ def test_config() -> None:
                 "command",
                 "line"
             ],
-            "kernel_modules_exclude": [
+            "KernelModulesExclude": [
                 "nvidia"
             ],
-            "kernel_modules_include": [
+            "KernelModulesInclude": [
                 "loop"
             ],
-            "kernel_modules_initrd": true,
-            "kernel_modules_initrd_exclude": [],
-            "kernel_modules_initrd_include": [],
-            "key": null,
-            "keymap": "wow, so much keymap",
-            "local_mirror": null,
-            "locale": "en_C.UTF-8",
-            "locale_messages": "",
-            "make_initrd": false,
-            "manifest_format": [
+            "KernelModulesInitrd": true,
+            "KernelModulesInitrdExclude": [],
+            "KernelModulesInitrdInclude": [],
+            "Key": null,
+            "Keymap": "wow, so much keymap",
+            "LocalMirror": null,
+            "Locale": "en_C.UTF-8",
+            "LocaleMessages": "",
+            "MakeInitrd": false,
+            "ManifestFormat": [
                 "json",
                 "changelog"
             ],
-            "mirror": null,
-            "nspawn_settings": null,
-            "output": "outfile",
-            "output_dir": "/your/output/here",
-            "output_format": "uki",
-            "overlay": true,
-            "package_manager_trees": [
+            "Mirror": null,
+            "NSpawnSettings": null,
+            "Output": "outfile",
+            "OutputDirectory": "/your/output/here",
+            "Overlay": true,
+            "PackageManagerTrees": [
                 [
                     "/foo/bar",
                     null
                 ]
             ],
-            "packages": [],
-            "passphrase": null,
-            "postinst_scripts": [
+            "Packages": [],
+            "Passphrase": null,
+            "PostInstallationScripts": [
                 "/bar/qux"
             ],
-            "prepare_scripts": [
+            "PrepareScripts": [
                 "/run/foo"
             ],
-            "preset": "default",
-            "presets": [
+            "Preset": "default",
+            "Presets": [
                 "default",
                 "initrd"
             ],
-            "qemu_args": [],
-            "qemu_cdrom": false,
-            "qemu_firmware": "linux",
-            "qemu_gui": true,
-            "qemu_kernel": null,
-            "qemu_kvm": "auto",
-            "qemu_mem": "",
-            "qemu_smp": "yes",
-            "qemu_swtpm": "auto",
-            "qemu_vsock": "enabled",
-            "release": "53",
-            "remove_files": [],
-            "remove_packages": [
+            "QemuArgs": [],
+            "QemuCdrom": false,
+            "QemuFirmware": "linux",
+            "QemuGui": true,
+            "QemuKernel": null,
+            "QemuKvm": "auto",
+            "QemuMem": "",
+            "QemuSmp": "yes",
+            "QemuSwtpm": "auto",
+            "QemuVsock": "enabled",
+            "Release": "53",
+            "RemoveFiles": [],
+            "RemovePackages": [
                 "all"
             ],
-            "repart_dirs": [],
-            "repositories": [],
-            "repository_key_check": false,
-            "root_password": [
+            "RepartDirectories": [],
+            "Repositories": [],
+            "RepositoryKeyCheck": false,
+            "RootPassword": [
                 "test1234",
                 false
             ],
-            "root_shell": "/bin/tcsh",
-            "runtime_size": 8589934592,
-            "runtime_trees": [
+            "RootShell": "/bin/tcsh",
+            "RuntimeSize": 8589934592,
+            "RuntimeTrees": [
                 [
                     "/foo/bar",
                     "/baz"
@@ -211,15 +211,15 @@ def test_config() -> None:
                     "/qux"
                 ]
             ],
-            "sector_size": null,
-            "secure_boot": true,
-            "secure_boot_certificate": null,
-            "secure_boot_key": "/path/to/keyfile",
-            "secure_boot_sign_tool": "pesign",
-            "seed": "7496d7d8-7f08-4a2b-96c6-ec8c43791b60",
-            "sign": false,
-            "sign_expected_pcr": "disabled",
-            "skeleton_trees": [
+            "SectorSize": null,
+            "SecureBoot": true,
+            "SecureBootCertificate": null,
+            "SecureBootKey": "/path/to/keyfile",
+            "SecureBootSignTool": "pesign",
+            "Seed": "7496d7d8-7f08-4a2b-96c6-ec8c43791b60",
+            "Sign": false,
+            "SignExpectedPcr": "disabled",
+            "SkeletonTrees": [
                 [
                     "/foo/bar",
                     null
@@ -229,21 +229,21 @@ def test_config() -> None:
                     "/qux"
                 ]
             ],
-            "source_date_epoch": 12345,
-            "split_artifacts": true,
-            "ssh": false,
-            "timezone": null,
-            "tools_tree": null,
-            "tools_tree_distribution": null,
-            "tools_tree_packages": [],
-            "tools_tree_release": null,
-            "use_subvolumes": "auto",
-            "verity_certificate": "/path/to/cert",
-            "verity_key": null,
-            "with_docs": true,
-            "with_network": false,
-            "with_tests": true,
-            "workspace_dir": "/cwd"
+            "SourceDateEpoch": 12345,
+            "SplitArtifacts": true,
+            "Ssh": false,
+            "Timezone": null,
+            "ToolsTree": null,
+            "ToolsTreeDistribution": null,
+            "ToolsTreePackages": [],
+            "ToolsTreeRelease": null,
+            "UseSubvolumes": "auto",
+            "VerityCertificate": "/path/to/cert",
+            "VerityKey": null,
+            "WithDocs": true,
+            "WithNetwork": false,
+            "WithTests": true,
+            "WorkspaceDirectory": "/cwd"
         }
         """
     )