App, cmds, lib: Fix Any returns from typed functions

Add type annotations and casts to functions that were returning Any
where a specific type was declared, satisfying the new warn_return_any
mypy rule.

Fixes:
- log.py: get_caller_pos return type via cast
- AsyncRunner.py: cast T for fut.result()
- util.py: cast for getattr result, str() for args.username
- FileContext.py: verbose_default bool annotation
- SSHClient.py: cast SSHClient for dynamic import
- lib/App.py: cast ArgumentParser, add return types to inner funcs
- pm/rpm.py, dpkg.py: cast Iterable[Package]
- App.py: cast for self.args.func(), add return types to inner funcs
- BaseCmdPkgRelations.py: cast str for args.delimiter

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 23:03:53 +02:00
commit 1e613a39c6
40 changed files with 228 additions and 179 deletions

View file

@ -10,7 +10,7 @@ import sys
from enum import Enum, auto
from functools import cache
from typing import Any, override, TYPE_CHECKING
from typing import Any, cast, override, TYPE_CHECKING
from .lib.App import App as Base
from .lib.Distro import Distro
@ -40,7 +40,7 @@ class ResultCache(object):
def __init__(self) -> None:
self.__cache: dict[str, Any] = {}
def run(self, func, args: list[Any]) -> object:
def run(self, func: Any, args: list[Any]) -> object:
d = self.__cache
depth = 0
keys = [func.__name__] + args
@ -137,21 +137,21 @@ class App(Base):
if search_absdirs is None:
search_absdirs = []
def __format_relpath(path: str):
def __format_relpath(path: str) -> str:
if path.startswith('./'):
return path[2:]
if path.endswith('/.'):
return path[:-2]
return path
def __relpath(target: str, base: str):
def __relpath(target: str, base: str) -> str:
return __format_relpath(os.path.relpath(target, base))
def __format_pd(name: str, pd: str, pretty: bool):
def __format_pd(name: str, pd: str, pretty: bool) -> str | None:
if not pretty:
return pd
if self.__topdir_fmt == 'absolute':
return os.path.abspath(pd)
return str(os.path.abspath(pd))
if self.__topdir_fmt == 'unaltered':
return pd
if self.__topdir_fmt == 'relative':
@ -175,6 +175,7 @@ class App(Base):
path = pd + '/' + sd
if os.path.isdir(path):
ret = __format_pd(name, pd, pretty)
assert ret is not None
if sd and sd[0] != '/':
if ret == '.':
ret = ''
@ -210,10 +211,13 @@ class App(Base):
add_self: bool,
scope: Scope,
names_only: bool,
):
return self.__res_cache.run(
self.__get_project_refs,
[buf, visited, spec, section, key, add_self, scope, names_only],
) -> list[str]:
return cast(
'list[str]',
self.__res_cache.run(
self.__get_project_refs,
[buf, visited, spec, section, key, add_self, scope, names_only],
),
)
def __get_project_refs(
@ -292,7 +296,7 @@ class App(Base):
for dep in deps:
self.__read_dep_graph([dep], sections, graph)
def __flip_dep_graph(self, graph: Graph):
def __flip_dep_graph(self, graph: Graph) -> Graph:
ret: Graph = {}
for project, deps in graph.items():
for d in deps:
@ -384,7 +388,7 @@ class App(Base):
)
@override
async def __aexit__(self, exc_type, exc, tb) -> None:
async def __aexit__(self, exc_type: Any, exc: Any, tb: Any) -> None:
if self.__exec_context is not None:
await self.__exec_context.close()
self.__exec_context = None
@ -494,7 +498,7 @@ class App(Base):
return self.__exec_context
@property
def top_name(self):
def top_name(self) -> str | None:
return self.__top_name
@property
@ -581,7 +585,7 @@ class App(Base):
return ret
@cache
def get_version(self, project) -> str:
def get_version(self, project: str) -> str:
ret = self.get_value(project, 'version', '')
if ret is None:
raise Exception(f"Can't get version of project {project}")
@ -610,9 +614,9 @@ class App(Base):
projects: list[str],
sections: list[str],
keys: str | list[str],
add_self: bool,
scope: Scope,
names_only = True,
scope: Scope = Scope.One,
add_self: bool = False,
names_only: bool = False,
) -> list[str]:
if isinstance(keys, str):
keys = [keys]