diff --git a/pmb/aportgen/busybox_static.py b/pmb/aportgen/busybox_static.py index 39300d38..45b735d2 100644 --- a/pmb/aportgen/busybox_static.py +++ b/pmb/aportgen/busybox_static.py @@ -67,7 +67,6 @@ def generate(pkgname: str) -> None: rm .PKGINFO .SIGN.* }} """ - for line in apkbuild.split("\n"): - handle.write(line[12:].replace(" " * 4, "\t") + "\n") + handle.writelines(line[12:].replace(" " * 4, "\t") + "\n" for line in apkbuild.split("\n")) pmb.aportgen.core.generate_checksums(tempdir, apkbuild_path) diff --git a/pmb/aportgen/core.py b/pmb/aportgen/core.py index 13a44b3a..a4692086 100644 --- a/pmb/aportgen/core.py +++ b/pmb/aportgen/core.py @@ -106,7 +106,7 @@ def rewrite( path = get_context().config.work / "aportgen/APKBUILD" with open(path, "r+", encoding="utf-8") as handle: skip_in_func = False - for line in handle.readlines(): + for line in handle: # Skip maintainer/contributor if line.startswith(("# Maintainer", "# Contributor")): continue diff --git a/pmb/aportgen/device.py b/pmb/aportgen/device.py index 337df357..c4c94276 100644 --- a/pmb/aportgen/device.py +++ b/pmb/aportgen/device.py @@ -252,8 +252,7 @@ def generate_deviceinfo( pmb.helpers.run.user(["mkdir", "-p", work / "aportgen"]) path = work / "aportgen/deviceinfo" with open(path, "w", encoding="utf-8") as handle: - for line in content.rstrip().split("\n"): - handle.write(line.lstrip() + "\n") + handle.writelines(line.lstrip() + "\n" for line in content.rstrip().split("\n")) def generate_modules_initfs() -> None: @@ -274,8 +273,7 @@ def generate_modules_initfs() -> None: pmb.helpers.run.user(["mkdir", "-p", work / "aportgen"]) path = work / "aportgen/modules-initfs" with open(path, "w", encoding="utf-8") as handle: - for line in content.rstrip().split("\n"): - handle.write(line.lstrip() + "\n") + handle.writelines(line.lstrip() + "\n" for line in content.rstrip().split("\n")) def generate_apkbuild(pkgname: str, name: str, arch: Arch, flash_method: str) -> None: @@ -324,8 +322,9 @@ def generate_apkbuild(pkgname: str, name: str, arch: Arch, flash_method: str) -> pmb.helpers.run.user(["mkdir", "-p", work / "aportgen"]) path = work / "aportgen/APKBUILD" with open(path, "w", encoding="utf-8") as handle: - for line in content.rstrip().split("\n"): - handle.write(line[8:].replace(" " * 4, "\t") + "\n") + handle.writelines( + line[8:].replace(" " * 4, "\t") + "\n" for line in content.rstrip().split("\n") + ) def generate(pkgname: str) -> None: diff --git a/pmb/aportgen/grub_efi.py b/pmb/aportgen/grub_efi.py index 186cd771..0b9c5cbc 100644 --- a/pmb/aportgen/grub_efi.py +++ b/pmb/aportgen/grub_efi.py @@ -56,7 +56,6 @@ def generate(pkgname: str) -> None: rm .PKGINFO .SIGN.* }} """ - for line in apkbuild.split("\n"): - handle.write(line[12:].replace(" " * 4, "\t") + "\n") + handle.writelines(line[12:].replace(" " * 4, "\t") + "\n" for line in apkbuild.split("\n")) pmb.aportgen.core.generate_checksums(tempdir, apkbuild_path) diff --git a/pmb/aportgen/musl.py b/pmb/aportgen/musl.py index 14898101..61809129 100644 --- a/pmb/aportgen/musl.py +++ b/pmb/aportgen/musl.py @@ -91,7 +91,6 @@ def generate(pkgname: str) -> None: done }} """ - for line in apkbuild.split("\n"): - handle.write(line[12:].replace(" " * 4, "\t") + "\n") + handle.writelines(line[12:].replace(" " * 4, "\t") + "\n" for line in apkbuild.split("\n")) pmb.aportgen.core.generate_checksums(tempdir, apkbuild_path) diff --git a/pmb/build/backend.py b/pmb/build/backend.py index ad426039..56525ab0 100644 --- a/pmb/build/backend.py +++ b/pmb/build/backend.py @@ -109,8 +109,7 @@ def override_source( # Write and log append file with open(append_path_outside, "w", encoding="utf-8") as handle: - for line in append.split("\n"): - handle.write(line[13:].replace(" " * 4, "\t") + "\n") + handle.writelines(line[13:].replace(" " * 4, "\t") + "\n" for line in append.split("\n")) pmb.chroot.user(["cat", append_path], chroot) # Append it to the APKBUILD diff --git a/pmb/chroot/initfs_hooks.py b/pmb/chroot/initfs_hooks.py index 70f1f554..60e8d4b9 100644 --- a/pmb/chroot/initfs_hooks.py +++ b/pmb/chroot/initfs_hooks.py @@ -22,11 +22,8 @@ def list_chroot(suffix: Chroot, remove_prefix: bool = True) -> list[str]: def list_aports() -> list[str]: - ret = [] prefix = pmb.config.initfs_hook_prefix - for path in pkgrepo_iglob(f"*/{prefix}*"): - ret.append(os.path.basename(path)[len(prefix) :]) - return ret + return [os.path.basename(path)[len(prefix) :] for path in pkgrepo_iglob(f"*/{prefix}*")] def ls(suffix: Chroot) -> None: diff --git a/pmb/commands/pull.py b/pmb/commands/pull.py index 8f1be73b..1314f873 100644 --- a/pmb/commands/pull.py +++ b/pmb/commands/pull.py @@ -13,10 +13,7 @@ class Pull(commands.Command): pass def run(self) -> None: - failed = [] - for repo in pmb.config.git_repos.keys(): - if pmb.helpers.git.pull(repo) < 0: - failed.append(repo) + failed = [repo for repo in pmb.config.git_repos.keys() if pmb.helpers.git.pull(repo) < 0] if not failed: return diff --git a/pmb/config/init.py b/pmb/config/init.py index fd010b53..dc16bd9c 100644 --- a/pmb/config/init.py +++ b/pmb/config/init.py @@ -367,8 +367,7 @@ def ask_for_provider_select(apkbuild: dict[str, Any], providers_cfg: dict[str, s for pkgname, pkg in providers: # Strip provider prefix if possible short = pkgname - if short.startswith(f"{select}-"): - short = short[len(f"{select}-") :] + short = short.removeprefix(f"{select}-") # Allow selecting the package using both short and long name providers_short[pkgname] = pkgname diff --git a/pmb/config/pmaports.py b/pmb/config/pmaports.py index b91c127e..23fd6384 100644 --- a/pmb/config/pmaports.py +++ b/pmb/config/pmaports.py @@ -138,11 +138,9 @@ def read_config( def all_channels() -> list[str]: """Get a list of all channels for all pkgrepos.""" - ret = set() - for repo in pkgrepo_paths(): - ret.add(read_config(repo)["channel"]) + ret = {read_config(repo)["channel"] for repo in pkgrepo_paths()} - logging.verbose(f"all_chanels: {ret}") + logging.verbose(f"all_channels: {ret}") return list(ret) diff --git a/pmb/helpers/aportupgrade.py b/pmb/helpers/aportupgrade.py index 566be5da..02087220 100644 --- a/pmb/helpers/aportupgrade.py +++ b/pmb/helpers/aportupgrade.py @@ -34,8 +34,7 @@ GITLAB_HOSTS = [ def init_req_headers() -> None: - global req_headers - global req_headers_github + global req_headers, req_headers_github # Only initialize them once if req_headers and req_headers_github: return diff --git a/pmb/helpers/args.py b/pmb/helpers/args.py index 1233bed2..e8b70f57 100644 --- a/pmb/helpers/args.py +++ b/pmb/helpers/args.py @@ -64,7 +64,7 @@ def init(args: PmbArgs) -> PmbArgs: ) # Override config at runtime with command line arguments - for key, _ in vars(config).items(): + for key in vars(config).keys(): if key.startswith("_") or key == "user": continue value = getattr(args, key, None) diff --git a/pmb/helpers/lint.py b/pmb/helpers/lint.py index cdbc4eb5..7756e864 100644 --- a/pmb/helpers/lint.py +++ b/pmb/helpers/lint.py @@ -94,7 +94,7 @@ def check(pkgnames: Sequence[str]) -> None: # For each pkgrepo run the linter on the relevant packages has_failed = False - for pkgrepo, apkbuild_paths in apkbuilds.items(): + for apkbuild_paths in apkbuilds.values(): # We search for the pkgnames in both the normal and systemd repository, # so unless the pkgname exists in both the apkbuild_paths is empty for # one of them and needs to be skipped here. This is not very elegant, diff --git a/pmb/helpers/repo.py b/pmb/helpers/repo.py index 1b4b1bb4..d14d53d5 100644 --- a/pmb/helpers/repo.py +++ b/pmb/helpers/repo.py @@ -77,8 +77,7 @@ def urls( # Local user repository (for packages compiled with pmbootstrap) if user_repository: - for channel in pmb.config.pmaports.all_channels(): - ret.append(str(user_repository / channel)) + ret.extend(str(user_repository / channel) for channel in pmb.config.pmaports.all_channels()) if mirrors_exclude is True: return ret @@ -137,15 +136,19 @@ def apkindex_files( if not arch: arch = Arch.native() - ret = [] + ret: list[Path] = [] # Local user repository (for packages compiled with pmbootstrap) if user_repository: - for channel in pmb.config.pmaports.all_channels(): - ret.append(get_context().config.work / "packages" / channel / arch / "APKINDEX.tar.gz") + ret.extend( + get_context().config.work / "packages" / channel / arch / "APKINDEX.tar.gz" + for channel in pmb.config.pmaports.all_channels() + ) # Resolve the APKINDEX.$HASH.tar.gz files - for url in urls(False, exclude_mirrors): - ret.append(get_context().config.work / f"cache_apk_{arch}" / apkindex_hash(url)) + ret.extend( + get_context().config.work / f"cache_apk_{arch}" / apkindex_hash(url) + for url in urls(False, exclude_mirrors) + ) return ret diff --git a/pmb/helpers/run_core.py b/pmb/helpers/run_core.py index 2d5bafd7..4c501d0f 100644 --- a/pmb/helpers/run_core.py +++ b/pmb/helpers/run_core.py @@ -38,8 +38,7 @@ def flat_cmd( # Merge env and cmd into escaped list escaped = [f"{key}={shlex.quote(os.fspath(value))}" for key, value in env.items()] for cmd in cmds: - for i in range(len(cmd)): - escaped.append(shlex.quote(os.fspath(cmd[i]))) + escaped.extend(shlex.quote(os.fspath(cmd[i])) for i in range(len(cmd))) escaped.append(";") # Prepend working dir diff --git a/pmb/parse/_apkbuild.py b/pmb/parse/_apkbuild.py index 62d07fc5..6cc7c649 100644 --- a/pmb/parse/_apkbuild.py +++ b/pmb/parse/_apkbuild.py @@ -423,11 +423,7 @@ def _parse_comment_tags(lines: list[str], tag: str) -> list[str]: :returns: array of values of the tag, one per line """ prefix = f"# {tag}:" - ret = [] - for line in lines: - if line.startswith(prefix): - ret.append(line[len(prefix) :].strip()) - return ret + return [line[len(prefix) :].strip() for line in lines if line.startswith(prefix)] def maintainers(path: Path) -> list[str] | None: diff --git a/pmb/parse/kconfig.py b/pmb/parse/kconfig.py index 63b588cc..cefb877d 100644 --- a/pmb/parse/kconfig.py +++ b/pmb/parse/kconfig.py @@ -24,7 +24,7 @@ def is_set(config: str, option: str) -> bool: :param option: name of the option to check, e.g. EXT4_FS :returns: True if the check passed, False otherwise """ - return re.search("^CONFIG_" + option + "=[ym]$", config, re.M) is not None + return re.search("^CONFIG_" + option + "=[ym]$", config, re.MULTILINE) is not None def is_set_str(config: str, option: str, string: str) -> bool: @@ -36,7 +36,7 @@ def is_set_str(config: str, option: str, string: str) -> bool: :param string: the expected string :returns: True if the check passed, False otherwise """ - match = re.search("^CONFIG_" + option + '="(.*)"$', config, re.M) + match = re.search("^CONFIG_" + option + '="(.*)"$', config, re.MULTILINE) if match: return string == match.group(1) else: @@ -52,7 +52,7 @@ def is_in_array(config: str, option: str, string: str) -> bool: :param string: the string expected to be an element of the array :returns: True if the check passed, False otherwise """ - match = re.search("^CONFIG_" + option + '="(.*)"$', config, re.M) + match = re.search("^CONFIG_" + option + '="(.*)"$', config, re.MULTILINE) if match: values = match.group(1).split(",") return string in values diff --git a/pmb/sideload/__init__.py b/pmb/sideload/__init__.py index b28c7ebc..6d8f2393 100644 --- a/pmb/sideload/__init__.py +++ b/pmb/sideload/__init__.py @@ -71,9 +71,7 @@ def ssh_install_apks(args: PmbArgs, user: str, host: str, port: str, paths: list :param paths: list of absolute paths to locally stored apks """ - remote_paths = [] - for path in paths: - remote_paths.append(os.path.join("/tmp", os.path.basename(path))) + remote_paths = [os.path.join("/tmp", os.path.basename(path)) for path in paths] logging.info(f"Copying packages to {user}@{host}") command: list[PathString] = ["scp", "-P", port, *paths, f"{user}@{host}:/tmp"] diff --git a/pyproject.toml b/pyproject.toml index adcdd805..9ee88048 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,10 +34,13 @@ line-length=100 target-version = "py310" [tool.ruff.lint] +# FURB101, FURB103: Easier to do if str gets replaced with Path in more places. +# PERF203: Negligible performance improvement on Python 3.11 and newer, and +# not worth the required rework. # RUF021: Could be fixed if someone cares about this. # RUF052: Needs a lot of changes, feel free to fix and then remove this ignore. -extend-ignore = ["RUF021", "RUF052"] -extend-select = ["CPY001", "N", "PIE", "RUF", "UP"] +extend-ignore = ["FURB101", "FURB103", "PERF203", "RUF021", "RUF052"] +extend-select = ["CPY001", "FURB", "N", "PERF", "PIE", "RUF", "UP"] preview = true [tool.ruff.format] diff --git a/test/parse/test_deviceinfo.py b/test/parse/test_deviceinfo.py index 84c32d56..14643930 100644 --- a/test/parse/test_deviceinfo.py +++ b/test/parse/test_deviceinfo.py @@ -178,8 +178,7 @@ def random_valid_deviceinfo(tmp_path): # Now write it all out to a file with open(path, "w") as f: - for key, value in info.items(): - f.write(f'deviceinfo_{key}="{value}"\n') + f.writelines(f'deviceinfo_{key}="{value}"\n' for key, value in info.items()) return path