import tempfile
import time
import uuid
+from collections.abc import Iterable, Iterator, Sequence
from pathlib import Path
from textwrap import dedent, wrap
from typing import (
Any,
BinaryIO,
Callable,
- Dict,
- Iterable,
- Iterator,
- List,
NoReturn,
Optional,
- Sequence,
- Set,
TextIO,
- Tuple,
TypeVar,
Union,
cast,
state.root.joinpath("etc/kernel/install.conf").write_text("layout=bls\n")
-def flatten(lists: Iterable[Iterable[T]]) -> List[T]:
+def flatten(lists: Iterable[Iterable[T]]) -> list[T]:
"""Flatten a sequence of sequences into a single list."""
return list(itertools.chain.from_iterable(lists))
patch_file(state.root / "etc/shadow", set_root_pw)
-def pam_add_autologin(root: Path, ttys: List[str]) -> None:
+def pam_add_autologin(root: Path, ttys: list[str]) -> None:
login = root / "etc/pam.d/login"
original = login.read_text() if login.exists() else ""
return ret.returncode == 0
-def nspawn_params_for_build_sources(config: MkosiConfig, sft: SourceFileTransfer) -> List[str]:
+def nspawn_params_for_build_sources(config: MkosiConfig, sft: SourceFileTransfer) -> list[str]:
params = ["--setenv=SRCDIR=/root/src",
"--chdir=/root/src"]
if sft == SourceFileTransfer.mount:
uid = int(os.getenv("SUDO_UID", 0))
c = run(["git", "-C", src, "ls-files", "-z", *what_files], stdout=subprocess.PIPE, text=False, user=uid)
- files: Set[str] = {x.decode("utf-8") for x in c.stdout.rstrip(b"\0").split(b"\0")}
+ files = {x.decode("utf-8") for x in c.stdout.rstrip(b"\0").split(b"\0")}
# Add the .git/ directory in as well.
if source_file_transfer == SourceFileTransfer.copy_git_more:
return "pxz" if shutil.which("pxz") else "xz"
-def compressor_command(option: Union[str, bool], src: Path) -> List[PathString]:
+def compressor_command(option: Union[str, bool], src: Path) -> list[PathString]:
"""Returns a command suitable for compressing archives."""
if option == "xz":
if state.for_cache:
return
- cmd: List[PathString] = [tar_binary(), "-C", state.root, "-c", "--xattrs", "--xattrs-include=*"]
+ cmd: list[PathString] = [tar_binary(), "-C", state.root, "-c", "--xattrs", "--xattrs-include=*"]
if state.config.tar_strip_selinux_context:
cmd += ["--xattrs-exclude=security.selinux"]
with complete_step("Creating archive…"), open(state.staging / state.config.output.name, "wb") as f:
files = find_files(state.root)
- cmd: List[PathString] = [
+ cmd: list[PathString] = [
"cpio", "-o", "--reproducible", "--null", "-H", "newc", "--quiet", "-D", state.root
]
os.rename(state.root, state.staging / state.config.output.name)
-def gen_kernel_images(state: MkosiState) -> Iterator[Tuple[str, Path]]:
+def gen_kernel_images(state: MkosiState) -> Iterator[tuple[str, Path]]:
# Apparently openmandriva hasn't yet completed its usrmerge so we use lib here instead of usr/lib.
if not state.root.joinpath("lib/modules").exists():
return
option = "mount.usr" if usr_only else "root"
boot_options = f"{boot_options} {option}=LABEL={label}"
- cmd: List[PathString] = [
+ cmd: list[PathString] = [
"ukify",
"--cmdline", boot_options,
"--os-release", f"@{state.root / 'usr/lib/os-release'}",
return None
with complete_step("Signing SHA256SUMS…"):
- cmdline: List[PathString] = [
+ cmdline: list[PathString] = [
"gpg",
"--detach-sign",
"-o", state.staging / state.config.output_signature.name,
return
with complete_step("Creating BMAP file…"):
- cmdline: List[PathString] = [
+ cmdline: list[PathString] = [
"bmaptool",
"create",
"--output", state.staging / state.config.output_bmap.name,
return cache
-def remove_duplicates(items: List[T]) -> List[T]:
+def remove_duplicates(items: list[T]) -> list[T]:
"Return list with any repetitions removed"
# We use a dictionary to simulate an ordered set
return list({x: None for x in items})
args_string = self._format_args(action, default)
return ", ".join(action.option_strings) + " " + args_string
- def _split_lines(self, text: str, width: int) -> List[str]:
+ def _split_lines(self, text: str, width: int) -> list[str]:
"""Wraps text to width, each line separately.
If the first line of text ends in a colon, we assume that
this is a list of option descriptions, and subindent them.
def _ini_key_to_cli_arg(cls, key: str) -> str:
return cls.SPECIAL_MKOSI_DEFAULT_PARAMS.get(key) or ("--" + cls._camel_to_arg(key))
- def _read_args_from_files(self, arg_strings: List[str]) -> List[str]:
+ def _read_args_from_files(self, arg_strings: list[str]) -> list[str]:
"""Convert @-prefixed command line arguments with corresponding file content
Regular arguments are just returned. Arguments prefixed with @ are considered
return parse_boolean(value)
-def parse_remove_files(value: str) -> List[str]:
+def parse_remove_files(value: str) -> list[str]:
"""Normalize paths as relative to / to ensure we don't go outside of our root."""
# os.path.normpath() leaves leading '//' untouched, even though it normalizes '///'.
return args
-def parse_args(argv: Optional[Sequence[str]] = None) -> Dict[str, argparse.Namespace]:
+def parse_args(argv: Optional[Sequence[str]] = None) -> dict[str, argparse.Namespace]:
"""Load config values from files and parse command line arguments
Do all about config files and command line arguments parsing. If --all argument is passed
return args_all
-def parse_args_file(argv: List[str], config_path: Path) -> argparse.Namespace:
+def parse_args_file(argv: list[str], config_path: Path) -> argparse.Namespace:
"""Parse just one mkosi.* file (--all mode)."""
# Parse all parameters handled by mkosi.
def parse_args_file_group(
- argv: List[str], config_path: Path, distribution: Optional[Distribution] = None
+ argv: list[str], config_path: Path, distribution: Optional[Distribution] = None
) -> argparse.Namespace:
"""Parse a set of mkosi config files"""
# Add the @ prefixed filenames to current argument list in inverse priority order.
def remove_glob(*patterns: PathString) -> None:
pathgen = (glob.glob(str(pattern)) for pattern in patterns)
- paths: Set[str] = set(sum(pathgen, [])) # uniquify
+ paths: set[str] = set(sum(pathgen, [])) # uniquify
for path in paths:
unlink_try_hard(Path(path))
state: MkosiState,
skip: Sequence[str] = [],
split: bool = False,
-) -> Tuple[Optional[str], Optional[str], bool]:
+) -> tuple[Optional[str], Optional[str], bool]:
if not state.config.output_format == OutputFormat.disk or state.for_cache or state.do_run_build_script:
return (None, None, False)
- cmdline: List[PathString] = [
+ cmdline: list[PathString] = [
"systemd-repart",
"--empty=allow",
"--size=auto",
die("Couldn't find QEMU/KVM binary")
-def find_qemu_firmware(config: MkosiConfig) -> Tuple[Path, bool]:
+def find_qemu_firmware(config: MkosiConfig) -> tuple[Path, bool]:
FIRMWARE_LOCATIONS = {
"x86_64": ["/usr/share/ovmf/x64/OVMF_CODE.secboot.fd"],
"i386": [
else:
machine = f"type=q35,accel={accel},smm={smm}"
- cmdline: List[PathString] = [
+ cmdline: list[PathString] = [
find_qemu_binary(config),
"-machine",
machine,
return rc == 0
-def find_address(config: MkosiConfig) -> Tuple[str, str]:
+def find_address(config: MkosiConfig) -> tuple[str, str]:
if not ensure_networkd(config) and config.ssh_port != 22:
return "", "127.0.0.1"
)
)
- cmd: List[PathString] = [
+ cmd: list[PathString] = [
"openssl",
"req",
"-new",
Path("mkosi.version").write_text(new_version + "\n")
-def expand_paths(paths: Sequence[str]) -> List[Path]:
+def expand_paths(paths: Sequence[str]) -> list[Path]:
if not paths:
return []
import contextlib
import os
import sys
+from collections.abc import Iterator
from subprocess import CalledProcessError
-from typing import Iterator
from mkosi import complete_step, parse_args, run_verb
from mkosi.backend import MkosiException, die
import sys
import tarfile
import uuid
+from collections.abc import Iterable, Iterator, Mapping, Sequence
from pathlib import Path
from types import FrameType
from typing import (
Any,
Callable,
Deque,
- Dict,
- Iterable,
- Iterator,
- List,
- Mapping,
NoReturn,
Optional,
- Sequence,
- Set,
- Tuple,
- Type,
TypeVar,
Union,
cast,
# This global should be initialized after parsing arguments
-ARG_DEBUG: Set[str] = set()
+ARG_DEBUG: set[str] = set()
class Parseable:
raise argparse.ArgumentTypeError(f"unknown Format: {name!r}")
@classmethod
- def parse_list(cls: Any, string: str) -> List[Any]:
+ def parse_list(cls: Any, string: str) -> list[Any]:
return [cls.from_string(p) for p in string.split(",") if p]
return self.name
-def dictify(f: Callable[..., Iterator[Tuple[T, V]]]) -> Callable[..., Dict[T, V]]:
- def wrapper(*args: Any, **kwargs: Any) -> Dict[T, V]:
+def dictify(f: Callable[..., Iterator[tuple[T, V]]]) -> Callable[..., dict[T, V]]:
+ def wrapper(*args: Any, **kwargs: Any) -> dict[T, V]:
return dict(f(*args, **kwargs))
return functools.update_wrapper(wrapper, f)
@dictify
-def read_os_release() -> Iterator[Tuple[str, str]]:
+def read_os_release() -> Iterator[tuple[str, str]]:
try:
filename = "/etc/os-release"
f = open(filename)
print(f"{filename}:{line_number}: bad line {line!r}", file=sys.stderr)
-def detect_distribution() -> Tuple[Optional[Distribution], Optional[str]]:
+def detect_distribution() -> tuple[Optional[Distribution], Optional[str]]:
try:
os_release = read_os_release()
except FileNotFoundError:
return self.value
@classmethod
- def doc(cls) -> Dict["SourceFileTransfer", str]:
+ def doc(cls) -> dict["SourceFileTransfer", str]:
return {
cls.copy_all: "normal file copy",
cls.copy_git_cached: "use git ls-files --cached, ignoring any file that git itself ignores",
"""
verb: Verb
- cmdline: List[str]
+ cmdline: list[str]
force: int
distribution: Distribution
mirror: Optional[str]
local_mirror: Optional[str]
repository_key_check: bool
- repositories: List[str]
+ repositories: list[str]
use_host_repositories: bool
repos_dir: Optional[str]
repart_dir: Optional[str]
architecture: str
output_format: OutputFormat
- manifest_format: List[ManifestFormat]
+ manifest_format: list[ManifestFormat]
output: Path
output_dir: Optional[Path]
bootable: bool
- kernel_command_line: List[str]
+ kernel_command_line: list[str]
secure_boot: bool
secure_boot_key: Path
secure_boot_certificate: Path
incremental: bool
cache_initrd: bool
base_packages: Union[str, bool]
- packages: List[str]
- remove_packages: List[str]
+ packages: list[str]
+ remove_packages: list[str]
with_docs: bool
with_tests: bool
cache_path: Path
- extra_trees: List[Path]
- skeleton_trees: List[Path]
+ extra_trees: list[Path]
+ skeleton_trees: list[Path]
clean_package_metadata: Union[bool, str]
- remove_files: List[Path]
- environment: Dict[str, str]
+ remove_files: list[Path]
+ environment: dict[str, str]
build_sources: Path
build_dir: Optional[Path]
include_dir: Optional[Path]
install_dir: Optional[Path]
- build_packages: List[str]
+ build_packages: list[str]
skip_final_phase: bool
build_script: Optional[Path]
prepare_script: Optional[Path]
password: Optional[str]
password_is_hashed: bool
autologin: bool
- extra_search_paths: List[Path]
+ extra_search_paths: list[Path]
netdev: bool
ephemeral: bool
ssh: bool
ssh_agent: Optional[Path]
ssh_timeout: int
ssh_port: int
- credentials: Dict[str, str]
+ credentials: dict[str, str]
directory: Optional[Path]
config_path: Optional[Path]
all: bool
all_directory: Optional[Path]
- debug: List[str]
+ debug: list[str]
auto_bump: bool
workspace_dir: Optional[Path]
machine_id: Optional[str]
def output_changelog(self) -> Path:
return build_auxiliary_output_path(self, ".changelog")
- def output_paths(self) -> Tuple[Path, ...]:
+ def output_paths(self) -> tuple[Path, ...]:
return (
self.output,
self.output_split_kernel,
do_run_build_script: bool
machine_id: str
for_cache: bool
- environment: Dict[str, str] = dataclasses.field(init=False)
+ environment: dict[str, str] = dataclasses.field(init=False)
installer: DistributionInstaller = dataclasses.field(init=False)
def __post_init__(self) -> None:
cmd: Sequence[PathString],
network: bool = False,
env: Optional[Mapping[str, str]] = None,
- nspawn_params: Optional[List[str]] = None,
+ nspawn_params: Optional[list[str]] = None,
capture_stdout: bool = False,
check: bool = True,
) -> CompletedProcess:
return path
-def die(message: str, exception: Type[MkosiException] = MkosiException) -> NoReturn:
+def die(message: str, exception: type[MkosiException] = MkosiException) -> NoReturn:
MkosiPrinter.warn(f"Error: {message}")
raise exception(message)
@classmethod
@contextlib.contextmanager
- def complete_step(cls, text: str, text2: Optional[str] = None) -> Iterator[List[Any]]:
+ def complete_step(cls, text: str, text2: Optional[str] = None) -> Iterator[list[Any]]:
cls.print_step(text)
cls.level += 1
try:
- args: List[Any] = []
+ args: list[Any] = []
yield args
finally:
cls.level -= 1
def add_packages(
- config: MkosiConfig, packages: Set[str], *names: str, conditional: Optional[str] = None
+ config: MkosiConfig, packages: set[str], *names: str, conditional: Optional[str] = None
) -> None:
"""Add packages in @names to @packages, if enabled by --base-packages.
packages.add(f"({name} if {conditional})" if conditional else name)
-def sort_packages(packages: Iterable[str]) -> List[str]:
+def sort_packages(packages: Iterable[str]) -> list[str]:
"""Sorts packages: normal first, paths second, conditional third"""
m = {"(": 2, "/": 1}
# SPDX-License-Identifier: LGPL-2.1+
from pathlib import Path
-from typing import TYPE_CHECKING, List
+from typing import TYPE_CHECKING
if TYPE_CHECKING:
from mkosi.backend import MkosiState
return Path("lib/modules") / name / "vmlinuz"
@classmethod
- def cache_path(cls) -> List[str]:
+ def cache_path(cls) -> list[str]:
raise NotImplementedError
@classmethod
- def remove_packages(cls, state: "MkosiState", remove: List[str]) -> None:
+ def remove_packages(cls, state: "MkosiState", remove: list[str]) -> None:
raise NotImplementedError
# SPDX-License-Identifier: LGPL-2.1+
from pathlib import Path
-from typing import Tuple
from mkosi.backend import MkosiConfig
from mkosi.distributions.centos import CentosInstaller
class AlmaInstaller(CentosInstaller):
@staticmethod
- def _gpg_locations(epel_release: int) -> Tuple[Path, str]:
+ def _gpg_locations(epel_release: int) -> tuple[Path, str]:
return (
Path(f"/etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux-{epel_release}"),
f"https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux-{epel_release}",
import os
from textwrap import dedent
-from typing import List, Set
from mkosi.backend import (
MkosiPrinter,
class ArchInstaller(DistributionInstaller):
@classmethod
- def cache_path(cls) -> List[str]:
+ def cache_path(cls) -> list[str]:
return ["var/cache/pacman/pkg"]
@classmethod
)
)
- packages: Set[str] = set()
+ packages: set[str] = set()
add_packages(state.config, packages, "base")
if not state.do_run_build_script and state.config.bootable:
import shutil
from pathlib import Path
-from typing import List, Tuple
from mkosi.backend import (
Distribution,
class CentosInstaller(DistributionInstaller):
@classmethod
- def cache_path(cls) -> List[str]:
+ def cache_path(cls) -> list[str]:
return ["var/cache/yum", "var/cache/dnf"]
@classmethod
run_workspace_command(state, cmdline)
@classmethod
- def remove_packages(cls, state: MkosiState, remove: List[str]) -> None:
+ def remove_packages(cls, state: MkosiState, remove: list[str]) -> None:
invoke_dnf(state, 'remove', remove)
@classmethod
return int(fields[0].removesuffix("-stream"))
@staticmethod
- def _gpg_locations(epel_release: int) -> Tuple[Path, str]:
+ def _gpg_locations(epel_release: int) -> tuple[Path, str]:
return (
Path("/etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial"),
"https://www.centos.org/keys/RPM-GPG-KEY-CentOS-Official"
)
@staticmethod
- def _epel_gpg_locations(epel_release: int) -> Tuple[Path, str]:
+ def _epel_gpg_locations(epel_release: int) -> tuple[Path, str]:
return (
Path(f"/etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-{epel_release}"),
f"https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-{epel_release}",
return f"http://mirrorlist.centos.org/?release={config.release}&arch=$basearch&repo={repo}"
@classmethod
- def _variant_repos(cls, config: MkosiConfig, epel_release: int) -> List[Repo]:
+ def _variant_repos(cls, config: MkosiConfig, epel_release: int) -> list[Repo]:
# Repos for CentOS Linux 8, CentOS Stream 8 and CentOS variants
directory = cls._mirror_directory()
return repos
@classmethod
- def _stream_repos(cls, config: MkosiConfig, epel_release: int) -> List[Repo]:
+ def _stream_repos(cls, config: MkosiConfig, epel_release: int) -> list[Repo]:
# Repos for CentOS Stream 9 and later
gpgpath, gpgurl = cls._gpg_locations(epel_release)
import contextlib
import os
import subprocess
+from collections.abc import Iterable, Iterator
from pathlib import Path
from textwrap import dedent
-from typing import TYPE_CHECKING, Any, Iterable, Iterator, List, Set
+from typing import TYPE_CHECKING, Any
from mkosi.backend import (
MkosiState,
class DebianInstaller(DistributionInstaller):
needs_skeletons_after_bootstrap = True
- repositories_for_boot: Set[str] = set()
+ repositories_for_boot: set[str] = set()
@classmethod
- def _add_default_kernel_package(cls, state: MkosiState, extra_packages: Set[str]) -> None:
+ def _add_default_kernel_package(cls, state: MkosiState, extra_packages: set[str]) -> None:
# Don't pull in a kernel if users specify one, but otherwise try to pick a default
# one - try to infer from the architecture.
if not any(package.startswith("linux-image") for package in extra_packages):
add_packages(state.config, extra_packages, f"linux-image-{DEBIAN_KERNEL_ARCHITECTURES[state.config.architecture]}")
@classmethod
- def _fixup_resolved(cls, state: MkosiState, extra_packages: Set[str]) -> None:
+ def _fixup_resolved(cls, state: MkosiState, extra_packages: set[str]) -> None:
if "systemd" in extra_packages and "systemd-resolved" not in extra_packages:
# The default resolv.conf points to 127.0.0.1, and resolved is disabled, fix it in
# the base image.
run(["systemctl", "--root", state.root, "enable", "systemd-resolved"])
@classmethod
- def cache_path(cls) -> List[str]:
+ def cache_path(cls) -> list[str]:
return ["var/cache/apt/archives"]
@staticmethod
# debootstrap fails if a base image is used with an already populated root, so skip it.
if state.config.base_image is None:
- cmdline: List[PathString] = [
+ cmdline: list[PathString] = [
"debootstrap",
"--variant=minbase",
"--include=ca-certificates",
# Install extra packages via the secondary APT run, because it is smarter and can deal better with any
# conflicts. dbus and libpam-systemd are optional dependencies for systemd in debian so we include them
# explicitly.
- extra_packages: Set[str] = set()
+ extra_packages: set[str] = set()
add_packages(state.config, extra_packages, "systemd", "systemd-sysv", "dbus", "libpam-systemd")
extra_packages.update(state.config.packages)
state.root.joinpath("etc/default/locale").symlink_to("../locale.conf")
@classmethod
- def _add_apt_auxiliary_repos(cls, state: MkosiState, repos: Set[str]) -> None:
+ def _add_apt_auxiliary_repos(cls, state: MkosiState, repos: set[str]) -> None:
if state.config.release in ("unstable", "sid"):
return
state.root.joinpath(f"etc/apt/sources.list.d/{state.config.release}-security.list").write_text(f"{security}\n")
@classmethod
- def remove_packages(cls, state: MkosiState, remove: List[str]) -> None:
+ def remove_packages(cls, state: MkosiState, remove: list[str]) -> None:
invoke_apt(state, "get", "purge", ["--assume-yes", "--auto-remove", *remove])
return run(cmdline, env=env, text=True, **kwargs)
-def add_apt_package_if_exists(state: MkosiState, extra_packages: Set[str], package: str) -> None:
+def add_apt_package_if_exists(state: MkosiState, extra_packages: set[str], package: str) -> None:
if invoke_apt(state, "cache", "search", ["--names-only", f"^{package}$"], stdout=subprocess.PIPE).stdout.strip():
add_packages(state.config, extra_packages, package)
import shutil
import urllib.parse
import urllib.request
+from collections.abc import Iterable, Sequence
from pathlib import Path
from textwrap import dedent
-from typing import Iterable, List, NamedTuple, Optional, Sequence, Set, Tuple
+from typing import NamedTuple, Optional
from mkosi.backend import (
Distribution,
class FedoraInstaller(DistributionInstaller):
@classmethod
- def cache_path(cls) -> List[str]:
+ def cache_path(cls) -> list[str]:
return ["var/cache/dnf"]
@classmethod
return install_fedora(state)
@classmethod
- def remove_packages(cls, state: MkosiState, remove: List[str]) -> None:
+ def remove_packages(cls, state: MkosiState, remove: list[str]) -> None:
invoke_dnf(state, 'remove', remove)
-def parse_fedora_release(release: str) -> Tuple[str, str]:
+def parse_fedora_release(release: str) -> tuple[str, str]:
if release.startswith("rawhide-"):
release, releasever = release.split("-")
MkosiPrinter.info(f"Fedora rawhide — release version: {releasever}")
return False
-def make_rpm_list(state: MkosiState, packages: Set[str]) -> Set[str]:
+def make_rpm_list(state: MkosiState, packages: set[str]) -> set[str]:
packages = packages.copy()
if not state.do_run_build_script and state.config.ssh:
return packages
-def install_packages_dnf(state: MkosiState, packages: Set[str],) -> None:
+def install_packages_dnf(state: MkosiState, packages: set[str],) -> None:
packages = make_rpm_list(state, packages)
invoke_dnf(state, 'install', packages)
import tarfile
import urllib.parse
import urllib.request
+from collections.abc import Generator, Sequence
from pathlib import Path
from textwrap import dedent
-from typing import Dict, Generator, List, Sequence
from mkosi.backend import (
ARG_DEBUG,
arch_profile: Path
arch: str
custom_profile_path: Path
- DEFAULT_NSPAWN_PARAMS: List[str]
+ DEFAULT_NSPAWN_PARAMS: list[str]
ebuild_sh_env_dir: Path
- emerge_default_opts: List[str]
- emerge_vars: Dict[str, str]
+ emerge_default_opts: list[str]
+ emerge_vars: dict[str, str]
portage_cfg_dir: Path
profile_path: Path
root: Path
- pkgs: Dict[str, List[str]] = {}
+ pkgs: dict[str, list[str]] = {}
dracut_atom = "sys-kernel/dracut"
EMERGE_UPDATE_OPTS = [
]
@staticmethod
- def try_import_portage() -> Dict[str, str]:
+ def try_import_portage() -> dict[str, str]:
NEED_PORTAGE_MSG = "You need portage(5) for Gentoo"
PORTAGE_INSTALL_INSTRUCTIONS = """\
# Following is known to work on most systemd-based systems:
if not inside_stage3:
from _emerge.main import emerge_main # type: ignore
- PREFIX_OPTS: List[str] = []
+ PREFIX_OPTS: list[str] = []
if "--sync" not in actions:
PREFIX_OPTS = [
f"--config-root={self.root.resolve()}",
class GentooInstaller(DistributionInstaller):
@classmethod
- def cache_path(cls) -> List[str]:
+ def cache_path(cls) -> list[str]:
return ["var/cache/binpkgs", "var/cache/distfiles"]
@staticmethod
# SPDX-License-Identifier: LGPL-2.1+
from pathlib import Path
-from typing import List
from mkosi.backend import MkosiState, add_packages, complete_step, disable_pam_securetty
from mkosi.distributions import DistributionInstaller
class MageiaInstaller(DistributionInstaller):
@classmethod
- def cache_path(cls) -> List[str]:
+ def cache_path(cls) -> list[str]:
return ["var/cache/dnf"]
@classmethod
return install_mageia(state)
@classmethod
- def remove_packages(cls, state: MkosiState, remove: List[str]) -> None:
+ def remove_packages(cls, state: MkosiState, remove: list[str]) -> None:
invoke_dnf(state, 'remove', remove)
# SPDX-License-Identifier: LGPL-2.1+
from pathlib import Path
-from typing import List
from mkosi.backend import MkosiState, add_packages, complete_step
from mkosi.distributions import DistributionInstaller
class OpenmandrivaInstaller(DistributionInstaller):
@classmethod
- def cache_path(cls) -> List[str]:
+ def cache_path(cls) -> list[str]:
return ["var/cache/dnf"]
@classmethod
return install_openmandriva(state)
@classmethod
- def remove_packages(cls, state: MkosiState, remove: List[str]) -> None:
+ def remove_packages(cls, state: MkosiState, remove: list[str]) -> None:
invoke_dnf(state, 'remove', remove)
# SPDX-License-Identifier: LGPL-2.1+
import shutil
-from typing import List
from mkosi.backend import (
MkosiState,
class OpensuseInstaller(DistributionInstaller):
@classmethod
- def cache_path(cls) -> List[str]:
+ def cache_path(cls) -> list[str]:
return ["var/cache/zypp/packages"]
@classmethod
if not state.do_run_build_script and state.config.ssh:
add_packages(state.config, packages, "openssh-server")
- cmdline: List[PathString] = ["zypper"]
+ cmdline: list[PathString] = ["zypper"]
# --reposd-dir needs to be before the verb
if state.config.local_mirror:
cmdline += ["--reposd-dir", state.workspace / "zypper-repos.d"]
# SPDX-License-Identifier: LGPL-2.1+
from pathlib import Path
-from typing import Tuple
from mkosi.backend import MkosiConfig
from mkosi.distributions.centos import CentosInstaller
class RockyInstaller(CentosInstaller):
@staticmethod
- def _gpg_locations(epel_release: int) -> Tuple[Path, str]:
+ def _gpg_locations(epel_release: int) -> tuple[Path, str]:
keyname = f"Rocky-{epel_release}" if epel_release >= 9 else "rockyofficial"
return (
Path(f"/etc/pki/rpm-gpg/RPM-GPG-KEY-{keyname}"),
# SPDX-License-Identifier: LGPL-2.1+
-from typing import Set
-
from mkosi.backend import MkosiState, add_packages
from mkosi.distributions.debian import DebianInstaller
repositories_for_boot = {"universe"}
@classmethod
- def _add_default_kernel_package(cls, state: MkosiState, extra_packages: Set[str]) -> None:
+ def _add_default_kernel_package(cls, state: MkosiState, extra_packages: set[str]) -> None:
# use the global metapckage linux-generic if the user didn't pick one
if ("linux-generic" not in extra_packages and
not any(package.startswith("linux-image") for package in extra_packages)):
add_packages(state.config, extra_packages, "linux-generic")
@classmethod
- def _add_apt_auxiliary_repos(cls, state: MkosiState, repos: Set[str]) -> None:
+ def _add_apt_auxiliary_repos(cls, state: MkosiState, repos: set[str]) -> None:
if state.config.release in ("unstable", "sid"):
return
state.root.joinpath(f"etc/apt/sources.list.d/{state.config.release}-security.list").write_text(f"{security}\n")
@classmethod
- def _fixup_resolved(cls, state: MkosiState, extra_packages: Set[str]) -> None:
+ def _fixup_resolved(cls, state: MkosiState, extra_packages: set[str]) -> None:
pass
import os
import shutil
import stat
+from collections.abc import Iterator
from pathlib import Path
from textwrap import dedent
-from typing import Any, BinaryIO, Iterator, Optional, cast
+from typing import Any, BinaryIO, Optional, cast
from mkosi.backend import MkosiState, PathString, complete_step
from pathlib import Path
from subprocess import DEVNULL, PIPE
from textwrap import dedent
-from typing import IO, Any, Dict, List, Optional, Tuple
+from typing import IO, Any, Optional
from mkosi.backend import Distribution, ManifestFormat, MkosiConfig, PackageType, run
architecture: str
size: int
- def as_dict(self) -> Dict[str, str]:
+ def as_dict(self) -> dict[str, str]:
return {
"type": self.type,
"name": self.name,
class SourcePackageManifest:
name: str
changelog: Optional[str]
- packages: List[PackageManifest] = dataclasses.field(default_factory=list)
+ packages: list[PackageManifest] = dataclasses.field(default_factory=list)
def add(self, package: PackageManifest) -> None:
self.packages.append(package)
return t
-def parse_pkg_desc(f: Path) -> Tuple[str, str, str, str]:
+def parse_pkg_desc(f: Path) -> tuple[str, str, str, str]:
name = version = base = arch = ""
with f.open() as desc:
for line in desc:
@dataclasses.dataclass
class Manifest:
config: MkosiConfig
- packages: List[PackageManifest] = dataclasses.field(default_factory=list)
- source_packages: Dict[str, SourcePackageManifest] = dataclasses.field(default_factory=dict)
+ packages: list[PackageManifest] = dataclasses.field(default_factory=list)
+ source_packages: dict[str, SourcePackageManifest] = dataclasses.field(default_factory=dict)
_init_timestamp: datetime = dataclasses.field(init=False, default_factory=datetime.now)
# We might add more data in the future
return len(self.packages) > 0
- def as_dict(self) -> Dict[str, Any]:
+ def as_dict(self) -> dict[str, Any]:
config = {
"name": self.config.image_id or "image",
"distribution": self.config.distribution.name,
import contextlib
import os
import stat
+from collections.abc import Iterator, Sequence
from pathlib import Path
-from typing import ContextManager, Iterator, List, Optional, Sequence, Union, cast
+from typing import ContextManager, Optional, Union, cast
from mkosi.backend import complete_step, run, scandir_recursive
if read_only:
options = ["ro", *options]
- cmd: List[PathString] = ["mount", "--no-mtab"]
+ cmd: list[PathString] = ["mount", "--no-mtab"]
if operation:
cmd += [operation]