# This file is part of craft-platforms.## Copyright 2024 Canonical Ltd.## This program is free software: you can redistribute it and/or modify it# under the terms of the GNU Lesser General Public License version 3, as# published by the Free Software Foundation.## This program is distributed in the hope that it will be useful, but WITHOUT# ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,# SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.# See the GNU Lesser General Public License for more details.## You should have received a copy of the GNU Lesser General Public License along# with this program. If not, see <http://www.gnu.org/licenses/>."""Architecture related utilities."""from__future__importannotationsimportenumimportplatformfromtypingimportLiteral,Tuple,Unionfromtyping_extensionsimportSelffromcraft_platformsimport_distro
[docs]classDebianArchitecture(str,enum.Enum):"""A Debian architecture."""AMD64="amd64"ARM64="arm64"ARMHF="armhf"I386="i386"PPC64EL="ppc64el"RISCV64="riscv64"S390X="s390x"def__str__(self)->str:returnself.valuedef__repr__(self)->str:"""Generate the repr of the string value. This is different from the Python/StringEnum default because of the very common idiom in Craft codebases of using a string's repr to pretty-print to users. """returnf"{self.value!r}"
[docs]@classmethoddeffrom_machine(cls,arch:str)->Self:"""Get a DebianArchitecture value from the given platform arch. :param arch: a string containing an architecture as returned by platform.machine() :returns: The DebianArchitecture enum value :raises: ValueError if the architecture is not a valid Debian architecture. """returncls(_ARCH_TRANSLATIONS_PLATFORM_TO_DEB.get(arch.lower(),arch.lower()))
[docs]@classmethoddeffrom_host(cls)->Self:"""Get the DebianArchitecture of the running host."""returncls.from_machine(platform.machine())
[docs]defto_platform_arch(self)->str:"""Convert this DebianArchitecture to a platform string. :returns: A string matching what platform.machine() or uname -m would return. """return_ARCH_TRANSLATIONS_DEB_TO_PLATFORM.get(self.value,self.value)
[docs]defto_efi_arch(self)->str:"""Convert this DebianArchitecture to an EFI firmware string. :returns: A string as matched by UKIFY in systemd (see https://github.com/systemd/systemd/blob/main/src/ukify/ukify.py) """return_ARCH_TRANSLATIONS_DEB_TO_EFI.get(self.value,self.value)
[docs]defto_grub_arch(self)->str:"""Convert this DebianArchitecture to a GRUB boot target. :returns: A string suitable for the --target argument to grub-install """return_ARCH_TRANSLATIONS_DEB_TO_GRUB.get(self.value,self.value)
# Architecture translation from the deb/snap syntax to (platform, efi, grub) syntaxes# platform: values as returned by uname -m_ARCH_TRANSLATIONS_DEB_TO_PLATFORM={"amd64":"x86_64","arm64":"aarch64","armhf":"armv7l","i386":"i686","ppc64el":"ppc64le","riscv64":"riscv64",}# see EFI_ARCH_MAP defined in systemd# https://github.com/systemd/systemd/blob/2fe2ee9adb18347efc0f6856830b63ba0aa874a2/src/ukify/ukify.py#L65-L75_ARCH_TRANSLATIONS_DEB_TO_EFI={"amd64":"x64","arm64":"aa64","armhf":"arm","i386":"ia32","riscv64":"riscv64",}# values from --target arg for grub-install (see man page)_ARCH_TRANSLATIONS_DEB_TO_GRUB={"amd64":"x86_64-efi","arm64":"arm64-efi","armhf":"arm-efi","i386":"i386-efi","riscv64":"riscv64-efi",}# architecture translations from the other syntaxes to deb/snap syntax_ARCH_TRANSLATIONS_PLATFORM_TO_DEB={platform:debfor(deb,platform)in_ARCH_TRANSLATIONS_DEB_TO_PLATFORM.items()}defparse_base_and_architecture(arch:str,)->Tuple[_distro.DistroBase|None,Union[DebianArchitecture,Literal["all"]]]:"""Get the debian arch and optional base from an architecture entry. The architecture may have an optional base prefixed as '[<base>:]<arch>'. :param arch: The architecture entry. :returns: A tuple of the DistroBase and the architecture. The architecture is either a DebianArchitecture or 'all'. :raises ValueError: If the architecture or base is invalid. """if":"inarch:base_str,_,arch_str=arch.partition(":")base=_distro.DistroBase.from_str(base_str)else:base=Nonearch_str=archtry:returnbase,DebianArchitecture(arch_str)ifarch_str!="all"else"all"exceptValueError:raiseValueError(f"{arch_str!r} is not a valid Debian architecture.")fromNone