From: gsegatti Date: Tue, 22 Feb 2022 11:05:35 +0000 (-0800) Subject: Adding an Enum class for verb comparison across Mkosi's code. X-Git-Tag: v13~76 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=989236a487d02abe9306d57a030446b43b41d684;p=thirdparty%2Fmkosi.git Adding an Enum class for verb comparison across Mkosi's code. --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index 28538f44b..eed7c2a99 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -77,6 +77,7 @@ from .backend import ( PartitionIdentifier, PartitionTable, SourceFileTransfer, + Verb, die, install_grub, nspawn_params_for_blockdev_access, @@ -115,10 +116,9 @@ else: SomeIO = Union[BinaryIO, TextIO] PathString = Union[Path, str] -MKOSI_COMMANDS_CMDLINE = ("build", "shell", "boot", "qemu", "ssh") -MKOSI_COMMANDS_NEED_BUILD = ("shell", "boot", "qemu", "serve") -MKOSI_COMMANDS_SUDO = ("build", "clean", "shell", "boot", "qemu", "serve") -MKOSI_COMMANDS = ("build", "clean", "help", "summary", "genkey", "bump", "serve") + MKOSI_COMMANDS_CMDLINE +MKOSI_COMMANDS_NEED_BUILD = (Verb.shell, Verb.boot, Verb.qemu, Verb.serve) +MKOSI_COMMANDS_SUDO = (Verb.build, Verb.clean, Verb.shell, Verb.boot, Verb.qemu, Verb.serve) +MKOSI_COMMANDS_CMDLINE = (Verb.build, Verb.shell, Verb.boot, Verb.qemu, Verb.ssh) DRACUT_SYSTEMD_EXTRAS = [ "/usr/bin/systemd-repart", @@ -5083,9 +5083,9 @@ def create_parser() -> ArgumentParserMkosi: parser = ArgumentParserMkosi(prog="mkosi", description="Build Bespoke OS Images", add_help=False) group = parser.add_argument_group("Commands") - group.add_argument("verb", choices=MKOSI_COMMANDS, default="build", help="Operation to execute") + group.add_argument("verb", type=Verb, choices=list(Verb), default=Verb.build, help="Operation to execute") group.add_argument( - "cmdline", nargs=argparse.REMAINDER, help="The command line to use for " + str(MKOSI_COMMANDS_CMDLINE)[1:-1] + "cmdline", nargs=argparse.REMAINDER, help="The command line to use for " + str([verb.name for verb in MKOSI_COMMANDS_CMDLINE])[1:-1] ) group.add_argument("-h", "--help", action="help", help="Show this help") group.add_argument("--version", action="version", version="%(prog)s " + __version__) @@ -5703,9 +5703,9 @@ def parse_args(argv: Optional[Sequence[str]] = None) -> Dict[str, argparse.Names # values of positional arguments. Make sure the verb command gets explicitly passed. # Insert a -- before the positional verb argument otherwise it might be considered as an argument of # a parameter with nargs='?'. For example mkosi -i summary would be treated as -i=summary. - for verb in MKOSI_COMMANDS: + for verb in Verb: try: - v_i = argv.index(verb) + v_i = argv.index(verb.name) except ValueError: continue @@ -5718,7 +5718,7 @@ def parse_args(argv: Optional[Sequence[str]] = None) -> Dict[str, argparse.Names # First run of command line arguments parsing to get the directory of mkosi.default file and the verb argument. args_pre_parsed, _ = parser.parse_known_args(argv) - if args_pre_parsed.verb == "help": + if args_pre_parsed.verb == Verb.help: parser.print_help() sys.exit(0) @@ -5902,7 +5902,7 @@ def empty_directory(path: Path) -> None: def unlink_output(args: MkosiArgs) -> None: - if not args.force and args.verb != "clean": + if not args.force and args.verb != Verb.clean: return if not args.skip_final_phase: @@ -5942,7 +5942,7 @@ def unlink_output(args: MkosiArgs) -> None: # remove the downloaded package cache if the user specified one # additional "--force". - if args.verb == "clean": + if args.verb == Verb.clean: remove_build_cache = args.force > 0 remove_package_cache = args.force > 1 else: @@ -6196,7 +6196,7 @@ def load_args(args: argparse.Namespace) -> MkosiArgs: args.extra_search_paths = expand_paths(args.extra_search_paths) if args.cmdline and args.verb not in MKOSI_COMMANDS_CMDLINE: - die("Additional parameters only accepted for " + str(MKOSI_COMMANDS_CMDLINE)[1:-1] + " invocations.") + die("Additional parameters only accepted for " + str([verb.name for verb in MKOSI_COMMANDS_CMDLINE])[1:-1] + " invocations.") if args.output_format is None: args.output_format = OutputFormat.gpt_ext4 @@ -6348,7 +6348,7 @@ def load_args(args: argparse.Namespace) -> MkosiArgs: else: warn("Ignoring configured output directory as output file is a qualified path.") - if args.incremental or args.verb == "clean": + if args.incremental or args.verb == Verb.clean: if args.image_id is not None: # If the image ID is specified, use cache file names that are independent of the image versions, so that # rebuilding and bumping versions is cheap and reuses previous versions if cached. @@ -6479,8 +6479,8 @@ def load_args(args: argparse.Namespace) -> MkosiArgs: "UEFI SecureBoot or signed Verity enabled, but couldn't find certificate. (Consider placing it in mkosi.secure-boot.crt?)" ) # NOQA: E501 - if args.verb in ("shell", "boot"): - opname = "acquire shell" if args.verb == "shell" else "boot" + if args.verb in (Verb.shell, Verb.boot): + opname = "acquire shell" if args.verb == Verb.shell else "boot" if args.output_format in (OutputFormat.tar, OutputFormat.cpio): die(f"Sorry, can't {opname} with a {args.output_format} archive.") if should_compress_output(args): @@ -6488,11 +6488,11 @@ def load_args(args: argparse.Namespace) -> MkosiArgs: if args.qcow2: die(f"Sorry, can't {opname} using a qcow2 image.") - if args.verb == "qemu": + if args.verb == Verb.qemu: if not args.output_format.is_disk(): die("Sorry, can't boot non-disk images with qemu.") - if needs_build(args) and args.verb == "qemu" and not args.bootable: + if needs_build(args) and args.verb == Verb.qemu and not args.bootable: die("Images built without the --bootable option cannot be booted using qemu") if needs_build(args) and args.qemu_headless and not args.bootable: @@ -6542,7 +6542,7 @@ def load_args(args: argparse.Namespace) -> MkosiArgs: if args.source_file_transfer_final == SourceFileTransfer.mount: die("Sorry, --source-file-transfer-final=mount is not supported") - if args.skip_final_phase and args.verb != "build": + if args.skip_final_phase and args.verb != Verb.build: die("--skip-final-phase can only be used when building an image using 'mkosi build'") if args.ssh_timeout < 0: @@ -6643,7 +6643,7 @@ def line_join_list(array: Sequence[PathString]) -> str: def print_summary(args: MkosiArgs) -> None: # FIXME: normal print MkosiPrinter.info("COMMANDS:") - MkosiPrinter.info(" verb: " + args.verb) + MkosiPrinter.info(f" verb: {args.verb}") MkosiPrinter.info(" cmdline: " + " ".join(args.cmdline)) MkosiPrinter.info("\nDISTRIBUTION:") MkosiPrinter.info(" Distribution: " + args.distribution.name) @@ -7378,14 +7378,14 @@ def has_networkd_vm_vt() -> bool: def ensure_networkd(args: MkosiArgs) -> bool: networkd_is_running = run(["systemctl", "is-active", "--quiet", "systemd-networkd"], check=False).returncode == 0 if not networkd_is_running: - if args.verb != "ssh": + if args.verb != Verb.ssh: # Some programs will use 'mkosi ssh' with pexpect, so don't print warnings that will break # them. warn("--network-veth requires systemd-networkd to be running to initialize the host interface " "of the veth link ('systemctl enable --now systemd-networkd')") return False - if args.verb == "qemu" and not has_networkd_vm_vt(): + if args.verb == Verb.qemu and not has_networkd_vm_vt(): warn(dedent(r"""\ mkosi didn't find 80-vm-vt.network. This is one of systemd's built-in systemd-networkd config files which configures vt-* interfaces. @@ -7432,7 +7432,7 @@ def run_shell_cmdline(args: MkosiArgs) -> List[str]: if args.nspawn_settings is not None: cmdline += ["--settings=trusted"] - if args.verb == "boot": + if args.verb == Verb.boot: cmdline += ["--boot"] else: cmdline += nspawn_rlimit_params() @@ -7452,7 +7452,7 @@ def run_shell_cmdline(args: MkosiArgs) -> List[str]: if args.cmdline: # If the verb is 'shell', args.cmdline contains the command to run. # Otherwise, the verb is 'boot', and we assume args.cmdline contains nspawn arguments. - if args.verb == "shell": + if args.verb == Verb.shell: cmdline += ["--"] cmdline += args.cmdline @@ -7697,7 +7697,7 @@ def find_address(args: MkosiArgs) -> Tuple[str, str]: def run_command_image(args: MkosiArgs, commands: Sequence[str], timeout: int, check: bool, stdout: _FILE = sys.stdout, stderr: _FILE = sys.stderr) -> CompletedProcess: - if args.verb == "qemu": + if args.verb == Verb.qemu: return run_ssh(args, commands, check, stdout, stderr, timeout) else: cmdline = ["systemd-run", "--quiet", "--wait", "--pipe", "-M", virt_name(args), "/usr/bin/env", *commands] @@ -7877,7 +7877,7 @@ def expand_specifier(s: str) -> str: def needs_build(args: Union[argparse.Namespace, MkosiArgs]) -> bool: - return args.verb == "build" or (args.verb in MKOSI_COMMANDS_NEED_BUILD and (not args.output.exists() or args.force > 0)) + return args.verb == Verb.build or (args.verb in MKOSI_COMMANDS_NEED_BUILD and (not args.output.exists() or args.force > 0)) def run_verb(raw: argparse.Namespace) -> None: @@ -7885,20 +7885,20 @@ def run_verb(raw: argparse.Namespace) -> None: prepend_to_environ_path(args.extra_search_paths) - if args.verb == "genkey": + if args.verb == Verb.genkey: generate_secure_boot_key(args) - if args.verb == "bump": + if args.verb == Verb.bump: bump_image_version(args) if args.verb in MKOSI_COMMANDS_SUDO: check_root() unlink_output(args) - if args.verb == "build": + if args.verb == Verb.build: check_output(args) - if args.verb == "summary": + if args.verb == Verb.summary: print_summary(args) if needs_build(args): @@ -7914,14 +7914,14 @@ def run_verb(raw: argparse.Namespace) -> None: print_output_size(args) - if args.verb in ("shell", "boot"): + if args.verb in (Verb.shell, Verb.boot): run_shell(args) - if args.verb == "qemu": + if args.verb == Verb.qemu: run_qemu(args) - if args.verb == "ssh": + if args.verb == Verb.ssh: run_ssh(args) - if args.verb == "serve": + if args.verb == Verb.serve: run_serve(args) diff --git a/mkosi/backend.py b/mkosi/backend.py index a01ab76e2..710fb93f7 100644 --- a/mkosi/backend.py +++ b/mkosi/backend.py @@ -112,6 +112,24 @@ class PackageType(enum.Enum): ebuild = 5 +class Verb(enum.Enum): + build = "build" + clean = "clean" + summary = "summary" + shell = "shell" + boot = "boot" + qemu = "qemu" + ssh = "ssh" + serve = "serve" + bump = "bump" + help = "help" + genkey = "genkey" + + # Defining __str__ is required to get "print_help()" output to include the human readable (values) of Verb. + def __str__(self) -> str: + return self.value + + class Distribution(enum.Enum): package_type: PackageType @@ -225,17 +243,17 @@ class ManifestFormat(Parseable, enum.Enum): class PartitionIdentifier(enum.Enum): - esp = 'esp' - bios = 'bios' - xbootldr = 'xbootldr' - root = 'root' - swap = 'swap' - home = 'home' - srv = 'srv' - var = 'var' - tmp = 'tmp' - verity = 'verity' - verity_sig = 'verity-sig' + esp = "esp" + bios = "bios" + xbootldr = "xbootldr" + root = "root" + swap = "swap" + home = "home" + srv = "srv" + var = "var" + tmp = "tmp" + verity = "verity" + verity_sig = "verity-sig" @dataclasses.dataclass @@ -371,7 +389,7 @@ class PartitionTable: class MkosiArgs: """Type-hinted storage for command line arguments.""" - verb: str + verb: Verb cmdline: List[str] force: int diff --git a/mkosi/machine.py b/mkosi/machine.py index e618f6ee0..cd0141c91 100644 --- a/mkosi/machine.py +++ b/mkosi/machine.py @@ -27,7 +27,7 @@ from . import ( run_shell_cmdline, unlink_output, ) -from .backend import MkosiArgs, die +from .backend import MkosiArgs, Verb, die class Machine: @@ -43,13 +43,13 @@ class Machine: tmp = parse_args(args)["default"] tmp.force = 1 tmp.autologin = True - if tmp.verb == "qemu": + if tmp.verb == Verb.qemu: tmp.bootable = True tmp.qemu_headless = True tmp.hostonly_initrd = True tmp.network_veth = True tmp.ssh = True - elif tmp.verb == "boot": + elif tmp.verb == Verb.boot: pass else: die("No valid verb was entered.") @@ -79,7 +79,7 @@ class Machine: check_root() unlink_output(self.args) - if self.args.verb == "build": + if self.args.verb == Verb.build: check_output(self.args) if needs_build(self.args): @@ -91,9 +91,9 @@ class Machine: with contextlib.ExitStack() as stack: prepend_to_environ_path(self.args.extra_search_paths) - if self.args.verb in ("shell", "boot"): + if self.args.verb in (Verb.shell, Verb.boot): cmdline = run_shell_cmdline(self.args) - elif self.args.verb == "qemu": + elif self.args.verb == Verb.qemu: # We must keep the temporary file opened at run_qemu_cmdline accessible, hence the context stack. cmdline = stack.enter_context(run_qemu_cmdline(self.args)) else: @@ -105,7 +105,7 @@ class Machine: # We use pexpect to boot an image that we will be able to interact with in the future # Then we tell the process to look for the # sign, which indicates the CLI for that image is active # Once we've build/boot an image the CLI will prompt "root@image ~]# " - # Then, when pexpects finds the "#" it means we're ready to interact with the process + # Then, when pexpects finds the '#' it means we're ready to interact with the process self._serial = pexpect.spawnu(cmd, logfile=None, timeout=240) self._serial.expect("#") self.stack = stack.pop_all() diff --git a/tests/test_config_parser.py b/tests/test_config_parser.py index a2113f8fd..ddb50aa80 100644 --- a/tests/test_config_parser.py +++ b/tests/test_config_parser.py @@ -10,6 +10,7 @@ from typing import Any, Generator, Mapping import pytest import mkosi +from mkosi.backend import Verb @contextlib.contextmanager @@ -119,7 +120,7 @@ class MkosiConfig: "tmp_size": None, "usr_only": False, "var_size": None, - "verb": "build", + "verb": Verb.build, "verity": False, "with_docs": False, "with_network": False, @@ -453,7 +454,7 @@ class MkosiConfigSummary(MkosiConfigOne): def __init__(self): super().__init__() for ref_c in self.reference_config.values(): - ref_c["verb"] = "summary" + ref_c["verb"] = Verb.summary self.cli_arguments = ["summary"] @@ -518,7 +519,7 @@ class MkosiConfigDistroDir(MkosiConfigDistro): def __init__(self): super().__init__("a_sub_dir") for ref_c in self.reference_config.values(): - ref_c["verb"] = "summary" + ref_c["verb"] = Verb.summary class MkosiConfigManyParams(MkosiConfigOne): @@ -832,20 +833,20 @@ def tested_config(request): def test_verb_none(tmpdir): with change_cwd(tmpdir.strpath): args = mkosi.parse_args([]) - assert args["default"].verb == "build" + assert args["default"].verb == Verb.build def test_verb_build(tmpdir): with change_cwd(tmpdir.strpath): args = mkosi.parse_args(["build"]) - assert args["default"].verb == "build" + assert args["default"].verb == Verb.build def test_verb_boot_no_cli_args1(tmpdir): with change_cwd(tmpdir.strpath): cmdline_ref = ["boot", "--par-for-sub", "--pom", "--for_sub", "1234"] args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == "boot" + assert args["default"].verb == Verb.boot assert args["default"].cmdline == cmdline_ref[1:] @@ -853,7 +854,7 @@ def test_verb_boot_no_cli_args2(tmpdir): with change_cwd(tmpdir.strpath): cmdline_ref = ["-pa-package", "boot", "--par-for-sub", "--popenssl", "--for_sub", "1234"] args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == "boot" + assert args["default"].verb == Verb.boot assert "a-package" in args["default"].packages assert args["default"].cmdline == cmdline_ref[2:] @@ -862,7 +863,7 @@ def test_verb_boot_no_cli_args3(tmpdir): with change_cwd(tmpdir.strpath): cmdline_ref = ["-pa-package", "-p", "another-package", "build"] args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == "build" + assert args["default"].verb == Verb.build assert args["default"].packages == ["a-package", "another-package"] @@ -870,7 +871,7 @@ def test_verb_summary_no_cli_args4(tmpdir): with change_cwd(tmpdir.strpath): cmdline_ref = ["-pa-package", "-p", "another-package", "summary"] args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == "summary" + assert args["default"].verb == Verb.summary assert args["default"].packages == ["a-package", "another-package"] @@ -878,7 +879,7 @@ def test_verb_shell_cli_args5(tmpdir): with change_cwd(tmpdir.strpath): cmdline_ref = ["-pa-package", "-p", "another-package", "shell", "python3 -foo -bar;", "ls --inode"] args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == "shell" + assert args["default"].verb == Verb.shell assert args["default"].packages == ["a-package", "another-package"] assert args["default"].cmdline == cmdline_ref[4:] @@ -887,7 +888,7 @@ def test_verb_shell_cli_args6(tmpdir): with change_cwd(tmpdir.strpath): cmdline_ref = ["-i", "yes", "summary"] args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == "summary" + assert args["default"].verb == Verb.summary assert args["default"].incremental == True @@ -895,7 +896,7 @@ def test_verb_shell_cli_args7(tmpdir): with change_cwd(tmpdir.strpath): cmdline_ref = ["-i", "summary"] args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == "summary" + assert args["default"].verb == Verb.summary assert args["default"].incremental == True diff --git a/tests/test_parse_load_args.py b/tests/test_parse_load_args.py index 6a6e46f9d..0052243a3 100644 --- a/tests/test_parse_load_args.py +++ b/tests/test_parse_load_args.py @@ -9,9 +9,10 @@ from os import chdir, getcwd from pathlib import Path from typing import List, Optional -import mkosi import pytest -from mkosi.backend import Distribution, MkosiArgs, MkosiException + +import mkosi +from mkosi.backend import Distribution, MkosiArgs, MkosiException, Verb def parse(argv: Optional[List[str]] = None) -> MkosiArgs: @@ -29,17 +30,17 @@ def cd_temp_dir(): chdir(old_dir) def test_parse_load_verb(): - assert parse(["build"]).verb == "build" - assert parse(["clean"]).verb == "clean" + assert parse(["build"]).verb == Verb.build + assert parse(["clean"]).verb == Verb.clean with pytest.raises(SystemExit): parse(["help"]) - assert parse(["genkey"]).verb == "genkey" - assert parse(["bump"]).verb == "bump" - assert parse(["serve"]).verb == "serve" - assert parse(["build"]).verb == "build" - assert parse(["shell"]).verb == "shell" - assert parse(["boot"]).verb == "boot" - assert parse(["--bootable", "qemu"]).verb == "qemu" + assert parse(["genkey"]).verb == Verb.genkey + assert parse(["bump"]).verb == Verb.bump + assert parse(["serve"]).verb == Verb.serve + assert parse(["build"]).verb == Verb.build + assert parse(["shell"]).verb == Verb.shell + assert parse(["boot"]).verb == Verb.boot + assert parse(["--bootable", "qemu"]).verb == Verb.qemu with pytest.raises(SystemExit): parse(["invalid"])