lib: Change Iterable to Collection for truthy checks

Change parameter types from Iterable[str] to Collection[str] wherever
the parameter is tested for emptiness (if not names). This satisfies
the new truthy-iterable mypy rule, since bare Iterable values are
always truthy even when empty.

Affected files:
- Distro.py: install, delete, select, _select, _select_by_name
- rpm.py: query_packages
- suse/Distro.py: _select_by_name
- Cmd.py (secrets): _match_files, _list_template_files, etc.
- DistroContext.py: list_template_files, list_secret_paths, etc.

Assisted-by: unsloth/Qwen3.6-35B-A3B-GGUF:IQ4_NL and pi.dev 0.81.1
Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2026-07-22 22:29:27 +02:00
commit dcbd4b1c84
5 changed files with 25 additions and 23 deletions

View file

@ -8,8 +8,8 @@ from ..CmdSecrets import CmdSecrets as Parent
from .lib.DistroContext import DistroContext
if TYPE_CHECKING:
from collections.abc import Collection
from argparse import ArgumentParser
from typing import Iterable
from .lib.base import Attrs
@ -19,27 +19,27 @@ class Cmd(Base): # export
def ctx(self) -> DistroContext:
return DistroContext(self.app.distro)
async def _match_files(self, packages: Iterable[str], pattern: str) -> list[str]:
async def _match_files(self, packages: Collection[str], pattern: str) -> list[str]:
return await self.ctx.match_files(packages, pattern)
async def _list_template_files(self, packages: Iterable[str]) -> list[str]:
async def _list_template_files(self, packages: Collection[str]) -> list[str]:
return await self.ctx.list_template_files(packages)
async def _list_secret_paths(
self, packages: Iterable[str], ignore_missing: bool = False
self, packages: Collection[str], ignore_missing: bool = False
) -> list[str]:
return await self.ctx.list_secret_paths(packages, ignore_missing)
async def _list_compilation_targets(
self, packages: Iterable[str], ignore_missing: bool = False
self, packages: Collection[str], ignore_missing: bool = False
) -> list[str]:
return await self.ctx.list_compilation_targets(packages, ignore_missing)
async def _remove_compilation_targets(self, packages: Iterable[str]) -> list[str]:
async def _remove_compilation_targets(self, packages: Collection[str]) -> list[str]:
return await self.ctx.remove_compilation_targets(packages)
async def _compile_template_files(
self, packages: Iterable[str], default_attrs: Attrs
self, packages: Collection[str], default_attrs: Attrs
) -> list[str]:
return await self.ctx.compile_template_files(packages, default_attrs)

View file

@ -11,8 +11,8 @@ from ....lib.ProcFilterGpg import ProcFilterGpg
from .FilesContext import FilesContext
if TYPE_CHECKING:
from collections.abc import Collection
from .base import Attrs
from typing import Iterable
from ....lib.Distro import Distro
@ -22,7 +22,7 @@ class DistroContext(FilesContext):
super().__init__(distro.ctx)
self.__distro = distro
async def match_files(self, pkg_names: Iterable[str], pattern: str) -> list[str]:
async def match_files(self, pkg_names: Collection[str], pattern: str) -> list[str]:
ret: list[str] = []
for pkg_name in pkg_names:
for path in await self.__distro.pkg_files(pkg_name):
@ -30,13 +30,13 @@ class DistroContext(FilesContext):
ret.append(path)
return ret
async def list_template_files(self, pkg_names: Iterable[str]) -> list[str]:
async def list_template_files(self, pkg_names: Collection[str]) -> list[str]:
if not pkg_names:
pkg_names = [p.name for p in await self.__distro.select()]
return await self.match_files(pkg_names, pattern = r'.*\.jw-tmpl$')
async def list_secret_paths(
self, pkg_names: Iterable[str], ignore_missing: bool = False
self, pkg_names: Collection[str], ignore_missing: bool = False
) -> list[str]:
ret = []
for tmpl in await self.list_template_files(pkg_names):
@ -47,7 +47,7 @@ class DistroContext(FilesContext):
return ret
async def list_compilation_targets(
self, pkg_names: Iterable[str], ignore_missing: bool = False
self, pkg_names: Collection[str], ignore_missing: bool = False
) -> list[str]:
ret = []
for tmpl in await self.list_template_files(pkg_names):
@ -57,7 +57,7 @@ class DistroContext(FilesContext):
ret.append(path)
return ret
async def remove_compilation_targets(self, pkg_names: Iterable[str]) -> list[str]:
async def remove_compilation_targets(self, pkg_names: Collection[str]) -> list[str]:
ret: list[str] = []
for path in await self.list_compilation_targets(pkg_names):
try:
@ -71,7 +71,7 @@ class DistroContext(FilesContext):
return ret
async def compile_template_files(
self, pkg_names: Iterable[str], default_attrs: Attrs
self, pkg_names: Collection[str], default_attrs: Attrs
) -> list[str]:
ret: list[str] = []
missing = 0
@ -96,7 +96,7 @@ class DistroContext(FilesContext):
async def install(
self,
src_uri: str,
pkg_names: Iterable[str],
pkg_names: Collection[str],
only_missing: bool = False,
verbose: bool = False,
) -> None:

View file

@ -12,6 +12,7 @@ from .log import ERR, INFO, WARNING, log
from .base import InputMode
if TYPE_CHECKING:
from collections.abc import Collection
from typing import Iterable
from .base import Result
@ -359,16 +360,16 @@ class Distro(abc.ABC):
# -- select
@abc.abstractmethod
async def _select_by_name(self, names: Iterable[str]) -> Iterable[Package]:
async def _select_by_name(self, names: Collection[str]) -> Iterable[Package]:
pass
async def _select(self, names: Iterable[str],
async def _select(self, names: Collection[str],
filter: PackageFilter) -> Iterable[Package]:
return [p for p in await self._select_by_name(names) if filter.match(p)]
async def select(
self,
names: Iterable[str] = [],
names: Collection[str] = [],
filter: PackageFilter | None = None
) -> Iterable[Package]:
if not filter:
@ -434,7 +435,7 @@ class Distro(abc.ABC):
if names:
await self._install(names, only_update = only_update)
async def install(self, names: Iterable[str], only_update: bool = False) -> None:
async def install(self, names: Collection[str], only_update: bool = False) -> None:
if not names:
log(WARNING, 'No packages specified for installation')
return
@ -446,7 +447,7 @@ class Distro(abc.ABC):
async def _delete(self, names: Iterable[str]) -> None:
pass
async def delete(self, names: Iterable[str]) -> None:
async def delete(self, names: Collection[str]) -> None:
if not names:
log(WARNING, 'No packages specified for deletion')
return

View file

@ -6,6 +6,7 @@ from ...Distro import Distro as Base
from ...pm.rpm import list_files, query_packages, run_rpm
if TYPE_CHECKING:
from collections.abc import Collection
from typing import Iterable
from ...base import Result
@ -68,7 +69,7 @@ class Distro(Base):
return False
@override
async def _select_by_name(self, names: Iterable[str]) -> Iterable[Package]:
async def _select_by_name(self, names: Collection[str]) -> Iterable[Package]:
return await query_packages(names, ec = self.ctx)
@override

View file

@ -1,6 +1,6 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Iterable
from typing import TYPE_CHECKING, Collection, Iterable
from ..base import InputMode
from ..Package import Package
@ -41,7 +41,7 @@ async def run_rpm( # export
return result.stdout_str
async def query_packages( # export
names: Iterable[str] = [],
names: Collection[str] = [],
ec: ExecContext | None = None,
) -> Iterable[Package]:
fmt_str = (