forked from Mirror/pmbootstrap
pmb: Add more type hints (MR 2513)
And fix some consequential type errors. [ci:skip-build]: already built successfully in CI
This commit is contained in:
parent
c8194302fc
commit
0925b3e425
12 changed files with 69 additions and 19 deletions
|
@ -8,7 +8,7 @@ from pmb.core.arch import Arch
|
||||||
from pmb.core.context import Context
|
from pmb.core.context import Context
|
||||||
from pmb.core.pkgrepo import pkgrepo_relative_path
|
from pmb.core.pkgrepo import pkgrepo_relative_path
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pmb.types import CrossCompileType
|
from pmb.types import Apkbuild, CrossCompileType
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pmb.build
|
import pmb.build
|
||||||
|
@ -187,7 +187,7 @@ def is_cached_or_cache(arch: Arch, pkgname: str) -> bool:
|
||||||
return visited
|
return visited
|
||||||
|
|
||||||
|
|
||||||
def get_apkbuild(pkgname):
|
def get_apkbuild(pkgname: str) -> tuple[Path | None, Apkbuild | None]:
|
||||||
"""Parse the APKBUILD path for pkgname.
|
"""Parse the APKBUILD path for pkgname.
|
||||||
|
|
||||||
When there is none, try to find it in the binary package APKINDEX files or raise an exception.
|
When there is none, try to find it in the binary package APKINDEX files or raise an exception.
|
||||||
|
@ -580,7 +580,7 @@ def packages(
|
||||||
for pkgname in pmb.config.build_packages:
|
for pkgname in pmb.config.build_packages:
|
||||||
if pkgname not in pkgnames:
|
if pkgname not in pkgnames:
|
||||||
aport, apkbuild = get_apkbuild(pkgname)
|
aport, apkbuild = get_apkbuild(pkgname)
|
||||||
if not aport:
|
if not aport or not apkbuild:
|
||||||
continue
|
continue
|
||||||
bstatus = pmb.build.get_status(arch, apkbuild)
|
bstatus = pmb.build.get_status(arch, apkbuild)
|
||||||
if bstatus.necessary():
|
if bstatus.necessary():
|
||||||
|
|
|
@ -4,7 +4,6 @@ import enum
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
|
||||||
import shlex
|
import shlex
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
@ -20,6 +19,7 @@ import pmb.parse.version
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot
|
||||||
from pmb.core.arch import Arch
|
from pmb.core.arch import Arch
|
||||||
from pmb.core.context import get_context
|
from pmb.core.context import get_context
|
||||||
|
from pmb.types import Apkbuild
|
||||||
|
|
||||||
|
|
||||||
def copy_to_buildpath(
|
def copy_to_buildpath(
|
||||||
|
@ -81,7 +81,7 @@ class BuildStatus(enum.Enum):
|
||||||
return self in [BuildStatus.OUTDATED, BuildStatus.NEW]
|
return self in [BuildStatus.OUTDATED, BuildStatus.NEW]
|
||||||
|
|
||||||
|
|
||||||
def get_status(arch: Arch | None, apkbuild: dict[str, Any]) -> BuildStatus:
|
def get_status(arch: Arch | None, apkbuild: Apkbuild) -> BuildStatus:
|
||||||
"""Check if the package has already been built.
|
"""Check if the package has already been built.
|
||||||
|
|
||||||
Compared to abuild's check, this check also works for different architectures.
|
Compared to abuild's check, this check also works for different architectures.
|
||||||
|
|
|
@ -83,7 +83,7 @@ def init_usr_merge(chroot: Chroot) -> None:
|
||||||
|
|
||||||
|
|
||||||
@Cache()
|
@Cache()
|
||||||
def warn_if_chroots_outdated():
|
def warn_if_chroots_outdated() -> None:
|
||||||
outdated = pmb.config.workdir.chroots_outdated()
|
outdated = pmb.config.workdir.chroots_outdated()
|
||||||
if outdated:
|
if outdated:
|
||||||
days_warn = int(pmb.config.chroot_outdated / 3600 / 24)
|
days_warn = int(pmb.config.chroot_outdated / 3600 / 24)
|
||||||
|
|
|
@ -13,11 +13,11 @@ class Log(commands.Command):
|
||||||
clear_log: bool
|
clear_log: bool
|
||||||
lines: int
|
lines: int
|
||||||
|
|
||||||
def __init__(self, clear_log: bool, lines: int):
|
def __init__(self, clear_log: bool, lines: int) -> None:
|
||||||
self.clear_log = clear_log
|
self.clear_log = clear_log
|
||||||
self.lines = lines
|
self.lines = lines
|
||||||
|
|
||||||
def run(self):
|
def run(self) -> None:
|
||||||
context = get_context()
|
context = get_context()
|
||||||
log_testsuite = pmb.config.pmb_src / ".pytest_tmp/log_testsuite.txt"
|
log_testsuite = pmb.config.pmb_src / ".pytest_tmp/log_testsuite.txt"
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,9 @@ def replace_apkbuild(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def is_up_to_date(path_sources, path_target=None, lastmod_target=None):
|
def is_up_to_date(
|
||||||
|
path_sources: list[Path], path_target: Path | None = None, lastmod_target: float | None = None
|
||||||
|
) -> bool:
|
||||||
"""Check if a file is up-to-date by comparing the last modified timestamps.
|
"""Check if a file is up-to-date by comparing the last modified timestamps.
|
||||||
|
|
||||||
(just like make does it).
|
(just like make does it).
|
||||||
|
@ -81,6 +83,9 @@ def is_up_to_date(path_sources, path_target=None, lastmod_target=None):
|
||||||
if path_target:
|
if path_target:
|
||||||
lastmod_target = os.path.getmtime(path_target)
|
lastmod_target = os.path.getmtime(path_target)
|
||||||
|
|
||||||
|
if lastmod_target is None or lastmod_source is None:
|
||||||
|
raise AssertionError
|
||||||
|
|
||||||
return lastmod_target >= lastmod_source
|
return lastmod_target >= lastmod_source
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -285,6 +285,8 @@ def config(args: PmbArgs) -> None:
|
||||||
|
|
||||||
|
|
||||||
def repo_missing(args: PmbArgs) -> None:
|
def repo_missing(args: PmbArgs) -> None:
|
||||||
|
if args.arch is None or isinstance(args.package, list):
|
||||||
|
raise AssertionError
|
||||||
missing = pmb.helpers.repo_missing.generate(args.arch, args.overview, args.package, args.built)
|
missing = pmb.helpers.repo_missing.generate(args.arch, args.overview, args.package, args.built)
|
||||||
print(json.dumps(missing, indent=4))
|
print(json.dumps(missing, indent=4))
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ class log_handler(logging.StreamHandler):
|
||||||
|
|
||||||
self.styles = pmb.config.styles
|
self.styles = pmb.config.styles
|
||||||
|
|
||||||
def emit(self, record):
|
def emit(self, record: logging.LogRecord) -> None:
|
||||||
try:
|
try:
|
||||||
msg = self.format(record)
|
msg = self.format(record)
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,8 @@ from pmb.core.arch import Arch
|
||||||
from pmb.core.pkgrepo import pkgrepo_iter_package_dirs
|
from pmb.core.pkgrepo import pkgrepo_iter_package_dirs
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import overload, Any, Literal
|
||||||
from pmb.types import WithExtraRepos
|
from pmb.types import Apkbuild, WithExtraRepos
|
||||||
|
|
||||||
from pmb.meta import Cache
|
from pmb.meta import Cache
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
|
@ -260,7 +260,7 @@ def get_with_path(
|
||||||
must_exist: bool = True,
|
must_exist: bool = True,
|
||||||
subpackages: bool = True,
|
subpackages: bool = True,
|
||||||
with_extra_repos: WithExtraRepos = "default",
|
with_extra_repos: WithExtraRepos = "default",
|
||||||
) -> tuple[Path | None, dict[str, Any] | None]:
|
) -> tuple[Path | None, Apkbuild | None]:
|
||||||
"""Find and parse an APKBUILD file.
|
"""Find and parse an APKBUILD file.
|
||||||
|
|
||||||
Run 'pmbootstrap apkbuild_parse hello-world' for a full output example.
|
Run 'pmbootstrap apkbuild_parse hello-world' for a full output example.
|
||||||
|
@ -288,12 +288,30 @@ def get_with_path(
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def get(
|
||||||
|
pkgname: str,
|
||||||
|
must_exist: Literal[True] = ...,
|
||||||
|
subpackages: bool = ...,
|
||||||
|
with_extra_repos: WithExtraRepos = ...,
|
||||||
|
) -> Apkbuild: ...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def get(
|
||||||
|
pkgname: str,
|
||||||
|
must_exist: bool = ...,
|
||||||
|
subpackages: bool = ...,
|
||||||
|
with_extra_repos: WithExtraRepos = ...,
|
||||||
|
) -> Apkbuild | None: ...
|
||||||
|
|
||||||
|
|
||||||
def get(
|
def get(
|
||||||
pkgname: str,
|
pkgname: str,
|
||||||
must_exist: bool = True,
|
must_exist: bool = True,
|
||||||
subpackages: bool = True,
|
subpackages: bool = True,
|
||||||
with_extra_repos: WithExtraRepos = "default",
|
with_extra_repos: WithExtraRepos = "default",
|
||||||
) -> dict[str, Any]:
|
) -> Apkbuild | None:
|
||||||
return get_with_path(pkgname, must_exist, subpackages, with_extra_repos)[1]
|
return get_with_path(pkgname, must_exist, subpackages, with_extra_repos)[1]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from typing import overload, Literal
|
||||||
|
|
||||||
from pmb.core.arch import Arch
|
from pmb.core.arch import Arch
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pmb.types import Apkbuild
|
from pmb.types import Apkbuild
|
||||||
|
@ -126,7 +128,27 @@ def generate_output_format(arch: Arch, pkgnames: list[str]) -> list[Apkbuild]:
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def generate(arch, overview, pkgname=None, built=False):
|
@overload
|
||||||
|
def generate(
|
||||||
|
arch: Arch, overview: Literal[False], pkgname: str | None = ..., built: bool = ...
|
||||||
|
) -> list[Apkbuild]: ...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def generate(
|
||||||
|
arch: Arch, overview: Literal[True], pkgname: str | None = ..., built: bool = ...
|
||||||
|
) -> list[str]: ...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def generate(
|
||||||
|
arch: Arch, overview: bool, pkgname: str | None = ..., built: bool = ...
|
||||||
|
) -> list[Apkbuild] | list[str]: ...
|
||||||
|
|
||||||
|
|
||||||
|
def generate(
|
||||||
|
arch: Arch, overview: bool, pkgname: str | None = None, built: bool = False
|
||||||
|
) -> list[Apkbuild] | list[str]:
|
||||||
"""Get packages that need to be built, with all their dependencies.
|
"""Get packages that need to be built, with all their dependencies.
|
||||||
|
|
||||||
:param arch: architecture (e.g. "armhf")
|
:param arch: architecture (e.g. "armhf")
|
||||||
|
|
|
@ -4,6 +4,7 @@ import argparse
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import sys
|
import sys
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
from pmb.core.arch import Arch
|
from pmb.core.arch import Arch
|
||||||
from pmb.core import Config
|
from pmb.core import Config
|
||||||
|
@ -827,7 +828,7 @@ def add_kernel_arg(subparser, name="package", nargs="?", *args, **kwargs):
|
||||||
arg.completer = kernel_completer
|
arg.completer = kernel_completer
|
||||||
|
|
||||||
|
|
||||||
def get_parser():
|
def get_parser() -> argparse.ArgumentParser:
|
||||||
parser = argparse.ArgumentParser(prog="pmbootstrap")
|
parser = argparse.ArgumentParser(prog="pmbootstrap")
|
||||||
arch_native = Arch.native()
|
arch_native = Arch.native()
|
||||||
arch_choices = Arch.supported()
|
arch_choices = Arch.supported()
|
||||||
|
@ -1297,7 +1298,8 @@ def get_parser():
|
||||||
|
|
||||||
|
|
||||||
def arguments() -> PmbArgs:
|
def arguments() -> PmbArgs:
|
||||||
args: PmbArgs = get_parser().parse_args()
|
# FIXME: It would be nice to not use cast here, but I don't know what else we could do.
|
||||||
|
args = cast(PmbArgs, get_parser().parse_args())
|
||||||
|
|
||||||
if getattr(args, "fork_alpine_retain_branch", False):
|
if getattr(args, "fork_alpine_retain_branch", False):
|
||||||
# fork_alpine_retain_branch largely matches the behaviour of fork_alpine, so
|
# fork_alpine_retain_branch largely matches the behaviour of fork_alpine, so
|
||||||
|
|
|
@ -18,7 +18,7 @@ from pmb.meta import Cache
|
||||||
# to specify which one they're using.
|
# to specify which one they're using.
|
||||||
# Basically: treat Deviceinfo as a standalone type that
|
# Basically: treat Deviceinfo as a standalone type that
|
||||||
# doesn't need to traverse pmaports.
|
# doesn't need to traverse pmaports.
|
||||||
def _parse_kernel_suffix(info, device, kernel):
|
def _parse_kernel_suffix(info: dict[str, str], device: str, kernel: str | None) -> dict[str, str]:
|
||||||
"""
|
"""
|
||||||
Remove the kernel suffix (as selected in 'pmbootstrap init') from
|
Remove the kernel suffix (as selected in 'pmbootstrap init') from
|
||||||
deviceinfo variables. Related:
|
deviceinfo variables. Related:
|
||||||
|
|
|
@ -12,6 +12,7 @@ import re
|
||||||
import signal
|
import signal
|
||||||
import shlex
|
import shlex
|
||||||
import shutil
|
import shutil
|
||||||
|
from types import FrameType
|
||||||
|
|
||||||
import pmb.build
|
import pmb.build
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
|
@ -327,7 +328,7 @@ def resize_image(img_size_new: str, img_path: Path) -> None:
|
||||||
raise RuntimeError(f"IMAGE_SIZE must be {img_size_str} or greater")
|
raise RuntimeError(f"IMAGE_SIZE must be {img_size_str} or greater")
|
||||||
|
|
||||||
|
|
||||||
def sigterm_handler(number, frame):
|
def sigterm_handler(number: int, stack_frame: FrameType | None) -> None:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"pmbootstrap was terminated by another process, and killed the QEMU VM it was running."
|
"pmbootstrap was terminated by another process, and killed the QEMU VM it was running."
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue