import operator
import os.path
import platform
+import re
import shlex
import shutil
import subprocess
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]:
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":
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]:
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":
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(
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"
}}
"""
)
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",
"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"
"/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
"/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"
}
"""
)