pmb.parse package

Submodules

pmb.parse.apkindex module

pmb.parse.apkindex.cache_key(path: Path) int
pmb.parse.apkindex.clear_cache(path: Path) bool

Clear the APKINDEX parsing cache.

Returns:

True on successful deletion, False otherwise

pmb.parse.apkindex.package(package: str, arch: Arch | None = None, must_exist: bool = True, indexes: list[Path] | None = None, user_repository: bool = True) ApkindexBlock | None

Get a specific package’s data from an apkindex.

Parameters:
  • package – of which you want to have the apkindex data

  • arch – defaults to native arch, only relevant for indexes=None

  • must_exist – When set to true, raise an exception when the package is not provided at all.

  • indexes – list of APKINDEX.tar.gz paths, defaults to all index files (depending on arch)

  • user_repository – add path to index of locally built packages

Returns:

ApkindexBlock or None when the package was not found.

pmb.parse.apkindex.parse(path: Path, multiple_providers: Literal[False] = True) dict[str, ApkindexBlock]
pmb.parse.apkindex.parse(path: Path, multiple_providers: Literal[True] = True) dict[str, dict[str, ApkindexBlock]]

Parse an APKINDEX.tar.gz file, and return its content as dictionary.

Parameters:
  • path – path to an APKINDEX.tar.gz file or apk package database (almost the same format, but not compressed).

  • multiple_providers – assume that there are more than one provider for the alias. This makes sense when parsing the APKINDEX files from a repository (#1122), but not when parsing apk’s installed packages DB.

Returns:

(without multiple_providers)

Generic format:

{ pkgname: ApkindexBlock, ... }

Example:

{ "postmarketos-mkinitfs": ApkindexBlock, "so:libGL.so.1": ApkindexBlock, ...}

Returns:

(with multiple_providers)

Generic format:

{ provide: { pkgname: ApkindexBlock, ... }, ... }

Example:

{ "postmarketos-mkinitfs": {"postmarketos-mkinitfs": ApkindexBlock},"so:libGL.so.1": {"mesa-egl": ApkindexBlock, "libhybris": ApkindexBlock}, ...}

NOTE: block is the return value from parse_next_block() above.

pmb.parse.apkindex.parse_add_block(ret: dict[str, ApkindexBlock], block: ApkindexBlock, alias: str | None = None, multiple_providers: bool = True) None
pmb.parse.apkindex.parse_add_block(ret: dict[str, dict[str, ApkindexBlock]], block: ApkindexBlock, alias: str | None = None, multiple_providers: Literal[True] = True) None

Add one block to the return dictionary of parse().

Parameters:
  • ret – dictionary of all packages in the APKINDEX that is getting built right now. This function will extend it.

  • block – return value from parse_next_block().

  • alias – defaults to the pkgname, could be an alias from the “provides” list.

  • multiple_providers – assume that there are more than one provider for the alias. This makes sense when parsing the APKINDEX files from a repository (#1122), but not when parsing apk’s installed packages DB.

pmb.parse.apkindex.parse_blocks(path: Path) list[ApkindexBlock]

Read all blocks from an APKINDEX.tar.gz into a list.

Path:

full path to the APKINDEX.tar.gz file.

Returns:

all blocks in the APKINDEX, without restructuring them by pkgname or removing duplicates with lower versions (use parse() if you need these features).

pmb.parse.apkindex.parse_next_block(path: Path, lines: list[str]) ApkindexBlock | None

Parse the next block in an APKINDEX.

Parameters:
  • path – to the APKINDEX.tar.gz

  • start – current index in lines, gets increased in this function. Wrapped into a list, so it can be modified “by reference”. Example: [5]

  • lines – all lines from the “APKINDEX” file inside the archive

Returns:

ApkindexBlock

Returns:

None, when there are no more blocks

pmb.parse.apkindex.provider_highest_priority(providers: dict[str, ApkindexBlock], pkgname: str) dict[str, ApkindexBlock]

Get the provider(s) with the highest provider_priority and log a message.

Parameters:
  • providers – returned dict from providers(), must not be empty

  • pkgname – the package name we are interested in (for the log message)

pmb.parse.apkindex.provider_shortest(providers: dict[str, ApkindexBlock], pkgname: str) ApkindexBlock

Get the provider with the shortest pkgname and log a message. In most cases this should be sufficient, e.g. ‘mesa-purism-gc7000-egl, mesa-egl’ or ‘gtk+2.0-maemo, gtk+2.0’.

Parameters:
  • providers – returned dict from providers(), must not be empty

  • pkgname – the package name we are interested in (for the log message)

pmb.parse.apkindex.providers(package: str, arch: Arch | None = None, must_exist: bool = True, indexes: list[Path] | None = None, user_repository: bool = True) dict[str, ApkindexBlock]

Get all packages, which provide one package.

Parameters:
  • package – of which you want to have the providers

  • arch – defaults to native arch, only relevant for indexes=None

  • must_exist – When set to true, raise an exception when the package is not provided at all.

  • indexes – list of APKINDEX.tar.gz paths, defaults to all index files (depending on arch)

  • user_repository – add path to index of locally built packages

Returns:

list of parsed packages. Example for package=”so:libGL.so.1”: {"mesa-egl": ApkindexBlock, "libhybris": ApkindexBlock}

pmb.parse.arguments module

pmb.parse.arguments.add_kernel_arg(subparser, name='package', nargs='?', *args, **kwargs)
pmb.parse.arguments.add_packages_arg(subparser, name='packages', *args, **kwargs)
pmb.parse.arguments.arguments()
pmb.parse.arguments.arguments_aportupgrade(subparser)
pmb.parse.arguments.arguments_ci(subparser)
pmb.parse.arguments.arguments_export(subparser)
pmb.parse.arguments.arguments_flasher(subparser)
pmb.parse.arguments.arguments_initfs(subparser)
pmb.parse.arguments.arguments_install(subparser)
pmb.parse.arguments.arguments_kconfig(subparser)
pmb.parse.arguments.arguments_lint(subparser)
pmb.parse.arguments.arguments_netboot(subparser)
pmb.parse.arguments.arguments_newapkbuild(subparser)

Wrapper for Alpine’s “newapkbuild” command.

Most parameters will get directly passed through, and they are defined in “pmb/config/__init__.py”. That way they can be used here and when passing them through in “pmb/helpers/frontend.py”. The order of the parameters is kept the same as in “newapkbuild -h”.

pmb.parse.arguments.arguments_pkgrel_bump(subparser)
pmb.parse.arguments.arguments_pkgver_bump(subparser)
pmb.parse.arguments.arguments_qemu(subparser)
pmb.parse.arguments.arguments_repo_bootstrap(subparser)
pmb.parse.arguments.arguments_repo_missing(subparser)
pmb.parse.arguments.arguments_sideload(subparser)
pmb.parse.arguments.arguments_status(subparser)
pmb.parse.arguments.arguments_test(subparser)
pmb.parse.arguments.get_parser()
pmb.parse.arguments.kernel_completer(prefix, action, parser=None, parsed_args=None)
Returns:

matched linux-* packages, with linux-* prefix and without

pmb.parse.arguments.package_completer(prefix, action, parser=None, parsed_args=None)
pmb.parse.arguments.toggle_other_boolean_flags(*other_destinations, value=True)

Group several argparse flags to one.

Sets multiple other_destination to value.

Parameters:

other_destinations – ‘the other argument names’ str

:param value ‘the value to set the other_destinations to’ bool

:returns custom Action

pmb.parse.arguments.type_ondev_cp(val)

Parse and validate arguments to ‘pmbootstrap install –ondev –cp’.

Parameters:

val – ‘HOST_SRC:CHROOT_DEST’ string

Returns:

(HOST_SRC, CHROOT_DEST)

pmb.parse.binfmt_info module

pmb.parse.binfmt_info.binfmt_info(arch_qemu)

pmb.parse.bootimg module

pmb.parse.bootimg.bootimg(path: Path) Bootimg
pmb.parse.bootimg.get_mtk_label(path: Path | str) str | None

Read the label from the MediaTek header of the kernel or ramdisk inside an extracted boot.img. :param path: to either the kernel or ramdisk extracted from boot.img :returns: * None: file does not exist or does not have MediaTek header * Label string (e.g. “ROOTFS”, “KERNEL”)

pmb.parse.bootimg.get_qcdt_type(path: Path | str) str | None

Get the dt.img type by reading the first four bytes of the file. :param path: to the qcdt image extracted from boot.img :returns: * None: dt.img is of unknown type * Type string (e.g. “qcom”, “sprd”, “exynos”)

pmb.parse.bootimg.is_dtb(path: Path | str) bool
pmb.parse.bootimg.trim_input(f: TextIO) str

pmb.parse.cpuinfo module

pmb.parse.cpuinfo.arm_big_little_first_group_ncpus() int | None

Infer from /proc/cpuinfo on aarch64 if this is a big/little architecture (if there is different processor models) and the number of cores in the first model group. https://en.wikipedia.org/wiki/ARM_big.LITTLE

Returns:

the number of cores of the first model in the order given by linux or None if not big/little architecture

pmb.parse.depends module

pmb.parse.depends.package_provider(pkgname: str, pkgnames_install: list[str], suffix: ~pmb.core.chroot.Chroot = <pmb.core.chroot.Chroot object>) ApkindexBlock | None
Parameters:

pkgnames_install – packages to be installed

Returns:

ApkindexBlock object or None (no provider found)

pmb.parse.deviceinfo module

class pmb.parse.deviceinfo.Deviceinfo(path: Path, kernel: str | None = None)

Bases: object

Variables from deviceinfo. Reference: <https://postmarketos.org/deviceinfo> Many of these are unused in pmbootstrap, and still more that are described on the wiki are missing. Eventually this class and associated code should be moved to a separate library and become the authoritative source of truth for the deviceinfo format.

append_dtb: str | None = ''
arch: Arch
boot_filesystem: str | None = ''
boot_part_start: str | None = ''
bootimg_custom_args: str | None = ''
bootimg_dtb_second: str | None = ''
bootimg_mtk_label_kernel: str | None = ''
bootimg_mtk_label_ramdisk: str | None = ''
bootimg_mtk_mkimage: str | None = ''
bootimg_qcdt: str | None = ''
cgpt_kpart: str | None = ''
cgpt_kpart_size: str | None = ''
cgpt_kpart_start: str | None = ''
chassis: str
codename: str
dev_touchscreen: str | None = ''
dev_touchscreen_calibration: str | None = ''
dtb: str = ''
external_storage: str | None = ''
flash_fastboot_max_size: str | None = ''
flash_fastboot_partition_dtbo: str | None = ''
flash_fastboot_partition_kernel: str | None = ''
flash_fastboot_partition_rootfs: str | None = ''
flash_fastboot_partition_system: str | None = ''
flash_fastboot_partition_vbmeta: str | None = ''
flash_heimdall_partition_dtbo: str | None = ''
flash_heimdall_partition_initfs: str | None = ''
flash_heimdall_partition_kernel: str | None = ''
flash_heimdall_partition_rootfs: str | None = ''
flash_heimdall_partition_system: str | None = ''
flash_heimdall_partition_vbmeta: str | None = ''
flash_kernel_on_update: str | None = ''
flash_method: str = ''
flash_mtkclient_partition_dtbo: str | None = ''
flash_mtkclient_partition_kernel: str | None = ''
flash_mtkclient_partition_rootfs: str | None = ''
flash_mtkclient_partition_vbmeta: str | None = ''
flash_offset_base: str | None = ''
flash_offset_dtb: str | None = ''
flash_offset_kernel: str | None = ''
flash_offset_ramdisk: str | None = ''
flash_offset_second: str | None = ''
flash_offset_tags: str | None = ''
flash_pagesize: str | None = ''
flash_rk_partition_kernel: str | None = ''
flash_rk_partition_rootfs: str | None = ''
flash_rk_partition_system: str | None = ''
flash_sparse: str | None = ''
flash_sparse_samsung_format: str | None = ''
format_version: str
generate_bootimg: str | None = ''
generate_legacy_uboot_initfs: str | None = ''
gpu_accelerated: bool | None = False
header_version: str | None = ''
kernel_cmdline: str | None = ''
keyboard: str | None = ''
keymaps: str | None = ''
manufacturer: str
name: str
partition_blacklist: str | None = ''
partition_type: str | None = ''
path: Path
root_filesystem: str | None = ''
rootfs_image_sector_size: str | None = ''
sd_embed_firmware: str | None = ''
sd_embed_firmware_step_size: str | None = ''
weston_pixman_type: str | None = ''
year: str

pmb.parse.kconfig module

pmb.parse.kconfig.check(pkgname, components_list=[], details=False, must_exist=True)

Check for necessary kernel config options in a package.

Parameters:
  • pkgname – the package to check for, optionally without “linux-”

  • components_list – what to check for, e.g. [“waydroid”, “iwd”]

  • details – print all warnings if True, otherwise one generic warning

  • must_exist – if False, just return if the package does not exist

Returns:

True when the check was successful, False otherwise None if the aport cannot be found (only if must_exist=False)

pmb.parse.kconfig.check_config(config_path: Path | str, config_arch: str, pkgver: str, categories: list[str], details: bool = False) bool

Check, whether one kernel config passes the rules of multiple components.

Parameters:
  • config_path – full path to kernel config file

  • config_arch – architecture name (alpine format, e.g. aarch64, x86_64)

  • pkgver – kernel version

  • categories – what to check for, e.g. [“waydroid”, “iwd”]

  • details – print all warnings if True, otherwise one per component

Returns:

True if the check passed, False otherwise

pmb.parse.kconfig.check_config_options_set(config, config_path, config_arch, options, component, pkgver, details=False)

Check, whether all the kernel config passes all rules of one component.

Print a warning if any is missing.

Parameters:
  • config – full kernel config as string

  • config_path – full path to kernel config file

  • config_arch – architecture name (alpine format, e.g. aarch64, x86_64)

  • options – kconfig_options* var passed from pmb/config/__init__.py: kconfig_options_example = { “>=0.0.0”: { # all versions “all”: { # all arches “ANDROID_PARANOID_NETWORK”: False, }, }

  • component – name of the component to test (postmarketOS, waydroid, …)

  • pkgver – kernel version

  • details – print all warnings if True, otherwise one per component

Returns:

True if the check passed, False otherwise

pmb.parse.kconfig.check_file(config_path: Path | str, components_list: list[str] = [], details: bool = False) bool

Check for necessary kernel config options in a kconfig file.

Parameters:
  • config_path – full path to kernel config file

  • components_list – what to check for, e.g. [“waydroid”, “iwd”]

  • details – print all warnings if True, otherwise one generic warning

Returns:

True when the check was successful, False otherwise

pmb.parse.kconfig.check_option(component, details, config, config_path, option, option_value)

Check, whether one kernel config option has a given value.

Parameters:
  • component – name of the component to test (postmarketOS, waydroid, …)

  • details – print all warnings if True, otherwise one per component

  • config – full kernel config as string

  • config_path – full path to kernel config file

  • option – name of the option to check, e.g. EXT4_FS

  • option_value – expected value, e.g. True, “str”, [“str1”, “str2”]

Returns:

True if the check passed, False otherwise

pmb.parse.kconfig.extract_arch(config_path)
pmb.parse.kconfig.extract_version(config_path)
pmb.parse.kconfig.is_in_array(config, option, string)

Check, whether a config option contains string as an array element

Parameters:
  • config – full kernel config as string

  • option – name of the option to check, e.g. EXT4_FS

  • string – the string expected to be an element of the array

Returns:

True if the check passed, False otherwise

pmb.parse.kconfig.is_set(config, option)

Check, whether a boolean or tristate option is enabled either as builtin or module.

Parameters:
  • config – full kernel config as string

  • option – name of the option to check, e.g. EXT4_FS

Returns:

True if the check passed, False otherwise

pmb.parse.kconfig.is_set_str(config, option, string)

Check, whether a config option contains a string as value.

Parameters:
  • config – full kernel config as string

  • option – name of the option to check, e.g. EXT4_FS

  • string – the expected string

Returns:

True if the check passed, False otherwise

pmb.parse.kconfigcheck module

pmb.parse.kconfigcheck.sanity_check(toml: dict) None

Ensure the kconfigcheck.toml file has the expected structure.

pmb.parse.version module

pmb.parse.version.check_string(a_version, rule)

Compare a version against a check string. This is used in “pmbootstrap kconfig check”, to only require certain options if the pkgver is in a specified range (#1795).

Parameters:
  • a_version – “3.4.1”

  • rule – “>=1.0.0”

Returns:

True if a_version matches rule, false otherwise.

pmb.parse.version.compare(a_version: str, b_version: str, fuzzy: bool = False) int

Compare two versions A and B to find out which one is higher, or if both are equal.

Parameters:
  • a_version – full version string A

  • b_version – full version string B

  • fuzzy – treat version strings, which end in different token types as equal

Returns:

(a < b): -1 (a == b): 0 (a > b): 1

C equivalent: apk_version_compare_blob_fuzzy()

pmb.parse.version.get_token(previous, rest)

This function does three things: * get the next token * get the token value * cut-off the whole token from rest

Parameters:
  • previous – the token before

  • rest – of the version string

Returns:

(next, value, rest) next is the new token string, value is an integer for comparing, rest is the rest of the input string.

C equivalent: get_token()

pmb.parse.version.next_token(previous, rest)

Parse the next token in the rest of the version string, we’re currently looking at.

We do not get the value of the token, or advance the rest string beyond the whole token that is what the get_token() function does (see below).

Parameters:
  • previous – the token before

  • rest – of the version string

Returns:

(next, rest) next is the upcoming token, rest is the input “rest” string with one leading ‘.’, ‘_’ or ‘-’ character removed (if there was any).

C equivalent: next_token()

pmb.parse.version.parse_suffix(rest)

Cut off the suffix of rest (which is now at the beginning of the rest variable, but regarding the whole version string, it is a suffix), and return a value integer (so it can be compared later, “beta” > “alpha” etc).

Parameters:

rest – what is left of the version string that we are currently parsing, starts with a “suffix” value (see below for valid suffixes).

Returns:

(rest, value, invalid_suffix) - rest: is the input “rest” string without the suffix - value: is a signed integer (negative for pre-, positive for post-suffixes). - invalid_suffix: is true, when rest does not start with anything from the suffixes variable.

C equivalent: get_token(), case TOKEN_SUFFIX

pmb.parse.version.token_value(string)

Return the associated value for a given token string (we parse through the version string one token at a time).

Parameters:

string – a token string

Returns:

integer associated to the token (so we can compare them in functions further below, a digit (1) looses against a letter (2), because “letter” has a higher value).

C equivalent: enum PARTS

pmb.parse.version.validate(version)

Check whether one version string is valid.

Parameters:

version – full version string

Returns:

True when the version string is valid

C equivalent: apk_version_validate()

pmb.parse._apkbuild module

pmb.parse._apkbuild.archived(path: Path) str | None

Return if (and why) an APKBUILD might be archived. This should be defined using a # Archived: <reason> tag in the APKBUILD.

Parameters:

path – full path to the APKBUILD

Returns:

reason why APKBUILD is archived, or None

pmb.parse._apkbuild.function_body(path: Path, func: str) list[str]

Get the body of a function in an APKBUILD.

Parameters:
  • path – full path to the APKBUILD

  • func – name of function to get the body of.

Returns:

function body in an array of strings.

pmb.parse._apkbuild.kernels(device: str) dict[str, str] | None

Get the possible kernels from a device-* APKBUILD.

Parameters:

device – the device name, e.g. “lg-mako”

Returns:

None when the kernel is hardcoded in depends

Returns:

kernel types and their description (as read from the subpackages) possible types: “downstream”, “stable”, “mainline” example: {“mainline”: “Mainline description”, “downstream”: “Downstream description”}

pmb.parse._apkbuild.maintainers(path: Path) list[str] | None

Parse maintainers of an APKBUILD file. They should be defined using # Maintainer: (first maintainer) and # Co-Maintainer: (additional maintainers).

Parameters:

path – full path to the APKBUILD

Returns:

array of (at least one) maintainer, or None

pmb.parse._apkbuild.parse_next_attribute(lines: list[str], i: int, path: Path) tuple[str, str, int] | tuple[None, None, int]

Parse one attribute from the APKBUILD.

It may be written across multiple lines, use a quoting sign and/or have a comment at the end. Some examples:

pkgrel=3 options=”!check” # ignore this comment arch=’all !armhf’ depends=”first-pkg second-pkg”

Parameters:
  • lines – newline-terminated list of lines from the APKBUILD

  • i – index of the line we are currently looking at

  • path – full path to the APKBUILD (for error message)

Returns:

(attribute, value, i) attribute: attribute name if any was found in line i / None value: that was parsed from the line i: line that was parsed last

pmb.parse._apkbuild.read_file(path: Path) list[str]

Read an APKBUILD file

Parameters:

path – full path to the APKBUILD

Returns:

contents of an APKBUILD as a list of strings

pmb.parse._apkbuild.replace_variable(apkbuild: dict[str, Any], value: str) str

Module contents