diff --git a/src/python/jw/pkg/App.py b/src/python/jw/pkg/App.py index cc57a6a8..cdc82c4d 100644 --- a/src/python/jw/pkg/App.py +++ b/src/python/jw/pkg/App.py @@ -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] diff --git a/src/python/jw/pkg/cmds/Cmd.py b/src/python/jw/pkg/cmds/Cmd.py index 5f9509cd..d9240e08 100644 --- a/src/python/jw/pkg/cmds/Cmd.py +++ b/src/python/jw/pkg/cmds/Cmd.py @@ -6,6 +6,7 @@ from ..App import App as Parent from ..CmdBase import CmdBase as Base if TYPE_CHECKING: + from argparse import Namespace from typing import Iterable from ..lib.Distro import Distro @@ -21,7 +22,7 @@ class Cmd(Base): # export super().__init__(parent, name, help, aliases = aliases) @override - async def _run(self, args): + async def _run(self, args: 'Namespace') -> None: # Missing subcommand self.print_help(1) diff --git a/src/python/jw/pkg/cmds/CmdPkg.py b/src/python/jw/pkg/cmds/CmdPkg.py index 48bd21ac..34bd2732 100644 --- a/src/python/jw/pkg/cmds/CmdPkg.py +++ b/src/python/jw/pkg/cmds/CmdPkg.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, override from .Cmd import Cmd, Parent if TYPE_CHECKING: - from argparse import ArgumentParser + from argparse import ArgumentParser, Namespace class CmdPkg(Cmd): # export @@ -19,7 +19,7 @@ class CmdPkg(Cmd): # export self.load_subcommands() @override - async def _run(self, args): + async def _run(self, args: Namespace) -> None: import sys # Missing subcommand diff --git a/src/python/jw/pkg/cmds/CmdPlatform.py b/src/python/jw/pkg/cmds/CmdPlatform.py index 130b2b5b..f8aa9606 100644 --- a/src/python/jw/pkg/cmds/CmdPlatform.py +++ b/src/python/jw/pkg/cmds/CmdPlatform.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, override from .Cmd import Cmd, Parent if TYPE_CHECKING: - from argparse import ArgumentParser + from argparse import ArgumentParser, Namespace class CmdPlatform(Cmd): # export @@ -16,7 +16,7 @@ class CmdPlatform(Cmd): # export self.load_subcommands() @override - async def _run(self, args): + async def _run(self, args: Namespace) -> None: import sys # Missing subcommand diff --git a/src/python/jw/pkg/cmds/CmdPosix.py b/src/python/jw/pkg/cmds/CmdPosix.py index 3e3a3747..4be4e8d1 100644 --- a/src/python/jw/pkg/cmds/CmdPosix.py +++ b/src/python/jw/pkg/cmds/CmdPosix.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, override from .Cmd import Cmd, Parent if TYPE_CHECKING: - from argparse import ArgumentParser + from argparse import ArgumentParser, Namespace class CmdPosix(Cmd): # export @@ -21,7 +21,7 @@ class CmdPosix(Cmd): # export self.load_subcommands() @override - async def _run(self, args): + async def _run(self, args: Namespace) -> None: import sys # Missing subcommand diff --git a/src/python/jw/pkg/cmds/CmdProjects.py b/src/python/jw/pkg/cmds/CmdProjects.py index 2bde3392..871a5c06 100644 --- a/src/python/jw/pkg/cmds/CmdProjects.py +++ b/src/python/jw/pkg/cmds/CmdProjects.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, override from .Cmd import Cmd, Parent if TYPE_CHECKING: - from argparse import ArgumentParser + from argparse import ArgumentParser, Namespace class CmdProjects(Cmd): # export @@ -18,7 +18,7 @@ class CmdProjects(Cmd): # export self.load_subcommands() @override - async def _run(self, args): + async def _run(self, args: Namespace) -> None: import sys # Missing subcommand diff --git a/src/python/jw/pkg/cmds/CmdSecrets.py b/src/python/jw/pkg/cmds/CmdSecrets.py index 3b28ed0a..ecf71f5b 100644 --- a/src/python/jw/pkg/cmds/CmdSecrets.py +++ b/src/python/jw/pkg/cmds/CmdSecrets.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, override from .Cmd import Cmd, Parent if TYPE_CHECKING: - from argparse import ArgumentParser + from argparse import ArgumentParser, Namespace class CmdSecrets(Cmd): # export @@ -14,7 +14,7 @@ class CmdSecrets(Cmd): # export self.load_subcommands() @override - async def _run(self, args): + async def _run(self, args: Namespace) -> None: import sys # Missing subcommand diff --git a/src/python/jw/pkg/cmds/posix/CmdTar.py b/src/python/jw/pkg/cmds/posix/CmdTar.py index 80355a24..bdb6b33d 100644 --- a/src/python/jw/pkg/cmds/posix/CmdTar.py +++ b/src/python/jw/pkg/cmds/posix/CmdTar.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, override from .Cmd import Cmd, Parent if TYPE_CHECKING: - from argparse import ArgumentParser + from argparse import ArgumentParser, Namespace class CmdTar(Cmd): # export @@ -14,7 +14,7 @@ class CmdTar(Cmd): # export self.load_subcommands() @override - async def _run(self, args): + async def _run(self, args: Namespace) -> None: import sys # Missing subcommand diff --git a/src/python/jw/pkg/cmds/posix/tar/Cmd.py b/src/python/jw/pkg/cmds/posix/tar/Cmd.py index f3bf5e5d..cc6e1aed 100644 --- a/src/python/jw/pkg/cmds/posix/tar/Cmd.py +++ b/src/python/jw/pkg/cmds/posix/tar/Cmd.py @@ -1,7 +1,7 @@ from __future__ import annotations from contextlib import asynccontextmanager -from typing import override, TYPE_CHECKING +from typing import Any, override, TYPE_CHECKING from ....CmdBase import CmdBase as Base from ....lib.FileContext import FileContext @@ -20,7 +20,7 @@ class Cmd(Base): # export self.__tar_io: None = None @asynccontextmanager - async def ctx(self, **kwargs) -> AsyncIterator[TarIo]: + async def ctx(self, **kwargs: Any) -> AsyncIterator[TarIo]: async with TarIo.create(src = self.app.args.archive_path, **kwargs) as ret: ret.src.add_proc_filter( FileContext.Direction.In, ProcFilterGpg(ec = self.app.exec_context) diff --git a/src/python/jw/pkg/cmds/projects/BaseCmdPkgRelations.py b/src/python/jw/pkg/cmds/projects/BaseCmdPkgRelations.py index 8d5c9cb2..66004f96 100644 --- a/src/python/jw/pkg/cmds/projects/BaseCmdPkgRelations.py +++ b/src/python/jw/pkg/cmds/projects/BaseCmdPkgRelations.py @@ -2,7 +2,7 @@ from __future__ import annotations import re -from typing import TYPE_CHECKING, override +from typing import TYPE_CHECKING, cast, override from .Cmd import Cmd, Parent from .lib.pkg_relations import VersionSyntax @@ -17,7 +17,7 @@ class BaseCmdPkgRelations(Cmd): def pkg_relations(self, rel_type: str, args: Namespace) -> str: - return args.delimiter.join( + return cast('str', args.delimiter).join( pkg_relations_list( self.app, rel_type = rel_type, diff --git a/src/python/jw/pkg/cmds/projects/CmdCanonicalizeRemotes.py b/src/python/jw/pkg/cmds/projects/CmdCanonicalizeRemotes.py index f167cfa7..7dbe24ba 100644 --- a/src/python/jw/pkg/cmds/projects/CmdCanonicalizeRemotes.py +++ b/src/python/jw/pkg/cmds/projects/CmdCanonicalizeRemotes.py @@ -34,7 +34,7 @@ class CmdCanonicalizeRemotes(Cmd): # export @override async def _run(self, args: Namespace) -> None: - async def git(cmd: list[str], ro = False, throw = True) -> Result: + async def git(cmd: list[str], ro: bool = False, throw: bool = True) -> Result: cmd = ['/usr/bin/git', *cmd] log(NOTICE, f'-- {" ".join(cmd)}') if ro or not args.dry_run: diff --git a/src/python/jw/pkg/cmds/projects/CmdCheck.py b/src/python/jw/pkg/cmds/projects/CmdCheck.py index 84198475..e53bbcba 100644 --- a/src/python/jw/pkg/cmds/projects/CmdCheck.py +++ b/src/python/jw/pkg/cmds/projects/CmdCheck.py @@ -4,7 +4,7 @@ from .Cmd import Cmd, Parent from typing import TYPE_CHECKING, override if TYPE_CHECKING: - from argparse import ArgumentParser + from argparse import ArgumentParser, Namespace class CmdCheck(Cmd): # export @@ -17,7 +17,7 @@ class CmdCheck(Cmd): # export self.load_subcommands() @override - async def _run(self, args): + async def _run(self, args: Namespace) -> None: import sys # Missing subcommand diff --git a/src/python/jw/pkg/cmds/projects/CmdCreateFile.py b/src/python/jw/pkg/cmds/projects/CmdCreateFile.py index 03e455d6..b852ac80 100644 --- a/src/python/jw/pkg/cmds/projects/CmdCreateFile.py +++ b/src/python/jw/pkg/cmds/projects/CmdCreateFile.py @@ -7,7 +7,7 @@ from .Cmd import Cmd, Parent from .lib.pkg_relations import VersionSyntax, pkg_relations from .lib.templates import ListDict, RenderValues, tmpl_render -def key_value(s): +def key_value(s: str) -> tuple[str, str]: try: key, value = s.split('=', 1) except ValueError: @@ -51,8 +51,8 @@ class CmdCreateFile(Cmd): # export self, template_name: str, values: list[RenderValues], - li_quote = False, - li_delimiter = '\n', + li_quote: bool = False, + li_delimiter: str = '\n', ) -> str: return tmpl_render( template_name, diff --git a/src/python/jw/pkg/cmds/projects/lib/pkg_relations.py b/src/python/jw/pkg/cmds/projects/lib/pkg_relations.py index ea1f64b3..2b470d79 100644 --- a/src/python/jw/pkg/cmds/projects/lib/pkg_relations.py +++ b/src/python/jw/pkg/cmds/projects/lib/pkg_relations.py @@ -26,8 +26,8 @@ def pkg_relations( ignore: set[str] = set(), quote: bool = False, skip_excluded: bool = False, - hide_self = False, - hide_jw_pkg = False, + hide_self: bool = False, + hide_jw_pkg: bool = False, ) -> list[str]: if subsections is None: diff --git a/src/python/jw/pkg/cmds/projects/lib/templates.py b/src/python/jw/pkg/cmds/projects/lib/templates.py index 134135f2..5d209d84 100644 --- a/src/python/jw/pkg/cmds/projects/lib/templates.py +++ b/src/python/jw/pkg/cmds/projects/lib/templates.py @@ -1,5 +1,5 @@ import textwrap -from typing import Iterable, TypeAlias, TypeGuard +from typing import Any, Iterable, TypeAlias, TypeGuard TupleList: TypeAlias = Iterable[tuple[str, str]] ListDict: TypeAlias = dict[str, list[str]] @@ -73,7 +73,7 @@ def format_list_dict( template: str, values: ListDict | dict[str, str], li_quote: bool, li_delimiter: str ) -> str: - def __format_value(val): + def __format_value(val: Any) -> str: if not li_quote: return str(val) return f'"{val}"' @@ -144,9 +144,9 @@ _templates = { def tmpl_render( template_name: str, values: list[RenderValues], - li_quote = False, - li_delimiter = '\n', - search_path: list[str] = [] + li_quote: bool = False, + li_delimiter: str = '\n', + search_path: list[str] | None = None, ) -> str: def __format(template: str) -> str: @@ -157,7 +157,7 @@ def tmpl_render( li_delimiter = li_delimiter, ) - for d in search_path: + for d in search_path if search_path else []: path = d + '/' + template_name try: with open(path, 'r') as f: diff --git a/src/python/jw/pkg/cmds/secrets/lib/FilesContext.py b/src/python/jw/pkg/cmds/secrets/lib/FilesContext.py index 4dccb1c9..29464597 100644 --- a/src/python/jw/pkg/cmds/secrets/lib/FilesContext.py +++ b/src/python/jw/pkg/cmds/secrets/lib/FilesContext.py @@ -23,7 +23,11 @@ class FilesContext: def ctx(self) -> FileContext: return self.__ctx - async def _read_key_value_file(self, path: str, throw = False) -> dict[str, str]: + async def _read_key_value_file( + self, + path: str, + throw: bool = False, + ) -> dict[str, str]: ret: dict[str, str] = {} try: result = await self.ctx.get(path) diff --git a/src/python/jw/pkg/lib/App.py b/src/python/jw/pkg/lib/App.py index a2357ec0..9f482319 100644 --- a/src/python/jw/pkg/lib/App.py +++ b/src/python/jw/pkg/lib/App.py @@ -6,7 +6,7 @@ import os import sys from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser, Namespace -from typing import override, TYPE_CHECKING, Any +from typing import Any, cast, override, TYPE_CHECKING from .AsyncRunner import AsyncRunner from .log import DEBUG, ERR, NOTICE, log, log_m, set_log_flags, set_log_level @@ -52,12 +52,15 @@ class App: # export ) -> None: def add_cmd_to_parser(cmd: AbstractCmd, parsers: Any) -> ArgumentParser: - parser = parsers.add_parser( - cmd.name, - help = cmd.help, - description = cmd.description, - aliases = cmd.aliases, - formatter_class = ArgumentDefaultsHelpFormatter, + parser = cast( + 'ArgumentParser', + parsers.add_parser( + cmd.name, + help = cmd.help, + description = cmd.description, + aliases = cmd.aliases, + formatter_class = ArgumentDefaultsHelpFormatter, + ) ) parser.set_defaults(func = cmd.run) cmd.add_arguments(parser) @@ -68,7 +71,7 @@ class App: # export parent: AbstractCmd | App, parser: ArgumentParser, cmds: Collection[AbstractCmd], - all = False + all: bool = False ) -> None: if not cmds: return @@ -168,7 +171,7 @@ class App: # export '-h', '--help', action = 'help', help = 'Show this help message and exit' ) - def __del__(self): + def __del__(self) -> None: if self.__own_eloop: if self.__eloop is not None: self.__eloop.close() @@ -178,10 +181,10 @@ class App: # export async def __aenter__(self) -> None: pass - async def __aexit__(self, exc_type, exc, tb) -> None: + async def __aexit__(self, exc_type: Any, exc: Any, tb: Any) -> None: pass - async def __run(self, argv = None) -> None: + async def __run(self, argv: list[str] | None = None) -> None: try: # Import argcomplete only here to not require it to be compatible @@ -194,8 +197,8 @@ class App: # export @override def __call__( # pyright: ignore[reportGeneralTypeIssues] - self, *args, **kwargs - ): + self, *args: Any, **kwargs: Any + ) -> None: return None import argcomplete # type: ignore[import-not-found, unused-ignore] @@ -249,7 +252,7 @@ class App: # export self.__parser.print_help() return None # Run sub-command. Overwrite if you want to do anything before or after - return await self.args.func(args) + return cast('None | int', await self.args.func(args)) def call_async(self, awaitable: Awaitable[T], timeout: float | None = None) -> T: return self.async_runner.call(awaitable, timeout) @@ -286,7 +289,7 @@ class App: # export def parser(self) -> ArgumentParser: return self.__parser - def run(self, argv = None) -> None: + def run(self, argv: list[str] | None = None) -> None: try: ret = self.eloop.run_until_complete(self.__run(argv)) finally: @@ -296,7 +299,10 @@ class App: # export return ret def run_sub_commands( # export - description = '', name_filter = '^Cmd.*', modules = None, argv = None -): + description: str = '', + name_filter: str = '^Cmd.*', + modules: list[str] | None = None, + argv: list[str] | None = None, +) -> None: app = App(description, name_filter, modules) - return app.run(argv = argv) + app.run(argv = argv) diff --git a/src/python/jw/pkg/lib/AsyncRunner.py b/src/python/jw/pkg/lib/AsyncRunner.py index d1569be4..66c723a2 100644 --- a/src/python/jw/pkg/lib/AsyncRunner.py +++ b/src/python/jw/pkg/lib/AsyncRunner.py @@ -4,7 +4,7 @@ import asyncio import concurrent.futures import contextlib -from typing import TypeVar, TYPE_CHECKING +from typing import Any, TypeVar, TYPE_CHECKING, cast if TYPE_CHECKING: from collections.abc import Awaitable, Generator @@ -48,7 +48,7 @@ class AsyncRunner: awaitable, # type: ignore[arg-type, var-annotated] self._loop, ) - return fut.result(timeout) + return cast('T', fut.result(timeout)) def close(self) -> None: self._cm.__exit__(None, None, None) @@ -56,5 +56,5 @@ class AsyncRunner: def __enter__(self) -> AsyncRunner: return self - def __exit__(self, exc_type, exc, tb) -> None: + def __exit__(self, exc_type: Any, exc: Any, tb: Any) -> None: self.close() diff --git a/src/python/jw/pkg/lib/Cmd.py b/src/python/jw/pkg/lib/Cmd.py index 0cca8e7c..51fea68f 100644 --- a/src/python/jw/pkg/lib/Cmd.py +++ b/src/python/jw/pkg/lib/Cmd.py @@ -9,7 +9,7 @@ from .log import ERR from .Types import LoadTypes, Types if TYPE_CHECKING: - from argparse import ArgumentParser + from argparse import ArgumentParser, Namespace from typing import Iterable from .App import App @@ -26,7 +26,7 @@ class AbstractCmd(abc.ABC): self.__child_classes: list[type[Cmd]] = [] self.__parser: ArgumentParser | None = None - def set_parent(self, parent: Any | Cmd): + def set_parent(self, parent: Any | Cmd) -> None: self.__parent = parent @property @@ -76,7 +76,7 @@ class AbstractCmd(abc.ABC): return self.__parser # Don't use a setter decorator to force using a grepable method - def set_parser(self, parser: ArgumentParser): + def set_parser(self, parser: ArgumentParser) -> None: self.__parser = parser def print_help(self, exit_status: int | None = None) -> None: @@ -129,11 +129,11 @@ class AbstractCmd(abc.ABC): pass @abc.abstractmethod - async def _run(self, args) -> None: + async def _run(self, args: Namespace) -> None: if isinstance(self.__parent, Cmd): # Calling App.run() would loop return await self.__parent._run(args) - async def run(self, args): + async def run(self, args: Namespace) -> None: return await self._run(args) @abc.abstractmethod diff --git a/src/python/jw/pkg/lib/CopyContext.py b/src/python/jw/pkg/lib/CopyContext.py index 9eefbdbe..3690d7b7 100644 --- a/src/python/jw/pkg/lib/CopyContext.py +++ b/src/python/jw/pkg/lib/CopyContext.py @@ -1,4 +1,4 @@ -from typing import Self +from typing import Any, Self from .FileContext import FileContext from .Uri import Uri @@ -9,7 +9,7 @@ class CopyContext: self, src: Uri | str | FileContext, dst: Uri | str | FileContext, - chroot = False + chroot: bool = False, ) -> None: def __uri(ctx: FileContext | Uri | str) -> Uri | str: @@ -43,7 +43,7 @@ class CopyContext: await self.__dst.open() return self - async def __aexit__(self, exc_type, exc, tb): + async def __aexit__(self, exc_type: Any, exc: Any, tb: Any) -> None: if self.__src is not None: await self.__src.close() self.__src = None diff --git a/src/python/jw/pkg/lib/Distro.py b/src/python/jw/pkg/lib/Distro.py index 0a40dbd4..d45ae54f 100644 --- a/src/python/jw/pkg/lib/Distro.py +++ b/src/python/jw/pkg/lib/Distro.py @@ -6,7 +6,7 @@ import re import sys from functools import cached_property -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any from .log import ERR, INFO, WARNING, log from .base import InputMode @@ -108,8 +108,8 @@ class Distro(abc.ABC): ec: ExecContext, id: str | None = None, os_release_str: str | None = None, - **kwargs, - ): + **kwargs: Any, + ) -> 'Distro': if id is None: os_release_str = await cls.read_os_release_str(ec) id = cls.parse_os_release_field_id(os_release_str) @@ -142,8 +142,9 @@ class Distro(abc.ABC): @cached_property def os_cascade(self) -> list[str]: + ret: list[str] = [] - def __append(entry: str): + def __append(entry: str) -> None: if entry not in ret: ret.append(entry) @@ -322,10 +323,10 @@ class Distro(abc.ABC): def default_pkg_filter(self) -> PackageFilter | None: return self.__default_pkg_filter - async def run(self, *args, **kwargs) -> Result: + async def run(self, *args: Any, **kwargs: Any) -> Result: return await self.__exec_context.run(*args, **kwargs) - async def sudo(self, *args, **kwargs) -> Result: + async def sudo(self, *args: Any, **kwargs: Any) -> Result: return await self.__exec_context.sudo(*args, **kwargs) @property diff --git a/src/python/jw/pkg/lib/ExecContext.py b/src/python/jw/pkg/lib/ExecContext.py index 7ee85b82..855b30dc 100644 --- a/src/python/jw/pkg/lib/ExecContext.py +++ b/src/python/jw/pkg/lib/ExecContext.py @@ -5,7 +5,7 @@ import errno import sys from decimal import ROUND_FLOOR, Decimal -from typing import override, TYPE_CHECKING, NamedTuple +from typing import Any, override, TYPE_CHECKING, NamedTuple if TYPE_CHECKING: from typing import Type @@ -214,7 +214,7 @@ class ExecContext(Base): self.__pretty_cmd = pretty_cmd(self.__cmd, self.__wd) return self.__pretty_cmd - def log(self, prio: int, *args, **kwargs) -> None: + def log(self, prio: int, *args: Any, **kwargs: Any) -> None: log(prio, self.__log_prefix, *args, **kwargs) def log_delim(self, start: bool) -> None: @@ -244,12 +244,12 @@ class ExecContext(Base): def __mode_str(cls, mode: int) -> str: return f'{mode:0o}' - def __init__(self, *args, **kwargs) -> None: + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) @classmethod @override - def create(cls, *args, **kwargs) -> ExecContext: + def create(cls, *args: Any, **kwargs: Any) -> ExecContext: ret = super().create(*args, **kwargs) if not isinstance(ret, cls): raise TypeError(f'Expected {cls.__name__}, got {type(ret).__name__}') @@ -505,7 +505,7 @@ class ExecContext(Base): async def __run( cmd: list[str], cmd_input: Input = InputMode.NonInteractive, - **kwargs + **kwargs: Any ) -> Result: return await self.run(cmd, cmd_input = cmd_input, **kwargs) diff --git a/src/python/jw/pkg/lib/FileContext.py b/src/python/jw/pkg/lib/FileContext.py index 5658db74..0ba119ce 100644 --- a/src/python/jw/pkg/lib/FileContext.py +++ b/src/python/jw/pkg/lib/FileContext.py @@ -4,7 +4,7 @@ import abc from enum import Enum, auto from functools import cached_property -from typing import override, TYPE_CHECKING +from typing import Any, override, TYPE_CHECKING from .log import DEBUG, ERR, log from .Uri import Uri @@ -24,7 +24,7 @@ class FileContext(abc.ABC): self, uri: str | Uri, interactive: bool | None = None, - verbose_default = False, + verbose_default: bool = False, chroot: bool = False, in_pipe: ProcPipeline | None = None, out_pipe: ProcPipeline | None = None, @@ -43,18 +43,18 @@ class FileContext(abc.ABC): f'= "{verbose_default}"' ) - async def __aenter__(self): + async def __aenter__(self) -> 'FileContext': await self.open() return self - async def __aexit__(self, exc_type, exc, tb): + async def __aexit__(self, exc_type: Any, exc: Any, tb: Any) -> None: await self.close() @override def __repr__(self) -> str: return self.__uri.id - def __pipe(self, d: Direction): + def __pipe(self, d: Direction) -> 'ProcPipeline': match d: case self.Direction.In: if not self.__in_pipe: @@ -76,7 +76,7 @@ class FileContext(abc.ABC): return self.root + path return self.root + '/' + path - def add_proc_filter(self, d: Direction, proc_filter: ProcFilter): + def add_proc_filter(self, d: Direction, proc_filter: ProcFilter) -> None: self.__pipe(d).append(proc_filter) async def _open(self) -> None: @@ -298,11 +298,11 @@ class FileContext(abc.ABC): log(ERR, f'{self.log_name}: Failed to stat({path}) ({str(e)})') raise - async def is_dir(self, path: str, follow_symlinks = True) -> bool: + async def is_dir(self, path: str, follow_symlinks: bool = True) -> bool: return await self._is_dir(self._chroot(path), follow_symlinks = follow_symlinks) @classmethod - def create(cls, uri: str | Uri, *args, **kwargs) -> FileContext: + def create(cls, uri: str | Uri, *args: Any, **kwargs: Any) -> 'FileContext': uri = Uri.pimp(uri) match uri.protocol: case 'local' | 'file': diff --git a/src/python/jw/pkg/lib/Package.py b/src/python/jw/pkg/lib/Package.py index 1f3fb2dc..1d3e9bbc 100644 --- a/src/python/jw/pkg/lib/Package.py +++ b/src/python/jw/pkg/lib/Package.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import override, Any meta_tags = [ @@ -16,7 +18,7 @@ class Package: maintainer: str | None = None @classmethod - def parse_spec_str(cls, spec: str, delimiter = '|'): + def parse_spec_str(cls, spec: str, delimiter: str = '|') -> 'Package': tags = spec.split(delimiter) if len(tags) != 5: raise ValueError(f'Invalid package spec string "{spec}"') @@ -29,14 +31,14 @@ class Package: ) @classmethod - def parse_specs_str(cls, specs: str, delimiter = '|'): + def parse_specs_str(cls, specs: str, delimiter: str = '|') -> list[Package]: ret: list[Package] = [] for spec in specs.splitlines(): ret.append(cls.parse_spec_str(spec)) return ret @classmethod - def order_tags(cls, mapping: dict[str, Any]): + def order_tags(cls, mapping: dict[str, Any]) -> dict[str, Any]: ret: dict[str, Any] = {} for tag in meta_tags: ret[tag] = mapping.get(tag, '') diff --git a/src/python/jw/pkg/lib/Result.py b/src/python/jw/pkg/lib/Result.py index 644fe186..38584fe0 100644 --- a/src/python/jw/pkg/lib/Result.py +++ b/src/python/jw/pkg/lib/Result.py @@ -33,7 +33,7 @@ class Result: def __try_decode( self, stdxxx: bytes | None, - quote = False, + quote: bool = False, truncate: int | None = None, annotate: bool = True, label: str | None = None, @@ -59,7 +59,7 @@ class Result: self, cmd: list[str] | None = None, wd: str | None = None, - verbose = True + verbose: bool = True, ) -> str: def __status_str(cmd: list[str] | None, wd: str | None, verbose: bool) -> str: diff --git a/src/python/jw/pkg/lib/TarIo.py b/src/python/jw/pkg/lib/TarIo.py index 67774d5c..6e508c6a 100644 --- a/src/python/jw/pkg/lib/TarIo.py +++ b/src/python/jw/pkg/lib/TarIo.py @@ -9,14 +9,14 @@ from tarfile import TarFile, TarInfo from .CopyContext import CopyContext from .ExecContext import ExecContext from .log import DEBUG, ERR, log -from typing import TYPE_CHECKING, override +from typing import TYPE_CHECKING, Any, override if TYPE_CHECKING: from .base import StatResult class TarIo(CopyContext): - def __init__(self, *args, **kwargs) -> None: + def __init__(self, *args: Any, **kwargs: Any) -> None: kwargs['chroot'] = False super().__init__(*args, **kwargs) @@ -44,7 +44,7 @@ class TarIo(CopyContext): async def _read_filtered( self, - path, + path: str, path_filter: list[str] | None = None, matched: list[str] | None = None, ) -> bytes: @@ -81,7 +81,7 @@ class TarIo(CopyContext): return ret @classmethod - def create(cls, *args, type: str | None = None, **kwargs): + def create(cls, *args: Any, type: str | None = None, **kwargs: Any) -> 'TarIo': if type is not None: raise NotImplementedError # return TarIoTarFile(*args, **kwargs) diff --git a/src/python/jw/pkg/lib/Types.py b/src/python/jw/pkg/lib/Types.py index 04827aac..82073059 100644 --- a/src/python/jw/pkg/lib/Types.py +++ b/src/python/jw/pkg/lib/Types.py @@ -5,7 +5,7 @@ import os import re import sys -from typing import override, TYPE_CHECKING, Generic, Iterable, TypeVar +from typing import Any, override, TYPE_CHECKING, Generic, Iterable, TypeVar from .log import ERR, OFF, log, parse_log_level @@ -33,7 +33,7 @@ class Types(abc.ABC, Iterable[type[T]], Generic[T]): # export def _stringify(self) -> list[str]: pass - def dump(self, prio: int, *args, **kwargs) -> None: + def dump(self, prio: int, *args: Any, **kwargs: Any) -> None: contents = self._stringify() log(prio, ',--- ', *args, **kwargs) for line in contents: @@ -47,8 +47,8 @@ class LoadTypes(Types[T]): # export mod_names: Iterable[str], type_name_filter: str | None = None, type_filter: Sequence[type[Any]] | None = None, - debug_level = None, - ): + debug_level: int | None = None, + ) -> None: if debug_level is None: val = os.getenv('JW_LOG_LEVEL_LOAD_TYPES') if val is not None: @@ -61,12 +61,12 @@ class LoadTypes(Types[T]): # export self.__mod_names = mod_names self.__classes: list[type[T]] | None = None - def _debug(self, *args, **kwargs) -> None: + def _debug(self, *args: Any, **kwargs: Any) -> None: if self.__debug_level != OFF: log(self.__debug_level, *args, **kwargs) @override - def _stringify(self): + def _stringify(self) -> list[str]: tf = 'None' if self.__type_filter is None else ( ', '.join([str(f) for f in self.__type_filter]) ) diff --git a/src/python/jw/pkg/lib/distros/arch/Distro.py b/src/python/jw/pkg/lib/distros/arch/Distro.py index ded2a903..c772a4f3 100644 --- a/src/python/jw/pkg/lib/distros/arch/Distro.py +++ b/src/python/jw/pkg/lib/distros/arch/Distro.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import override, TYPE_CHECKING +from typing import Any, override, TYPE_CHECKING from ...Distro import Distro as Base @@ -23,7 +23,7 @@ class Distro(Base): return await self.sudo(cmd, verbose = verbose) return await self.run(cmd, verbose = verbose) - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) @override diff --git a/src/python/jw/pkg/lib/distros/debian/Distro.py b/src/python/jw/pkg/lib/distros/debian/Distro.py index fb242192..8cf88a18 100644 --- a/src/python/jw/pkg/lib/distros/debian/Distro.py +++ b/src/python/jw/pkg/lib/distros/debian/Distro.py @@ -2,7 +2,7 @@ from __future__ import annotations import os -from typing import override, TYPE_CHECKING +from typing import Any, override, TYPE_CHECKING from ...Distro import Distro as Base from ...log import NOTICE, log @@ -31,11 +31,11 @@ class Distro(Base): if sudo else await self.run(cmd, verbose = verbose) ) - async def dpkg(self, *args, **kwargs) -> str: + async def dpkg(self, *args: Any, **kwargs: Any) -> str: kwargs.setdefault('ec', self.ctx) return await run_dpkg(*args, **kwargs) - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) @override diff --git a/src/python/jw/pkg/lib/distros/suse/Distro.py b/src/python/jw/pkg/lib/distros/suse/Distro.py index 44675cc6..02967ef6 100644 --- a/src/python/jw/pkg/lib/distros/suse/Distro.py +++ b/src/python/jw/pkg/lib/distros/suse/Distro.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import override, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, override from ...Distro import Distro as Base from ...pm.rpm import list_files, query_packages, run_rpm @@ -35,13 +35,18 @@ class Distro(Base): if sudo else await self.run(cmd, verbose = verbose) ) - async def rpm(self, *args, ec: ExecContext | None = None, **kwargs) -> str: + async def rpm( + self, + *args: Any, + ec: ExecContext | None = None, + **kwargs: Any, + ) -> str: if ec is None: ec = self.ctx kwargs['ec'] = ec return await run_rpm(*args, **kwargs) - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) @override diff --git a/src/python/jw/pkg/lib/ec/Curl.py b/src/python/jw/pkg/lib/ec/Curl.py index d2fd158f..6757008d 100644 --- a/src/python/jw/pkg/lib/ec/Curl.py +++ b/src/python/jw/pkg/lib/ec/Curl.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import override, TYPE_CHECKING +from typing import Any, override, TYPE_CHECKING from ..FileContext import FileContext as Base @@ -13,7 +13,11 @@ if TYPE_CHECKING: class Curl(Base): def __init__( - self, uri: str | Uri, *args, ec: ExecContext | None = None, **kwargs + self, + uri: str | Uri, + *args: Any, + ec: ExecContext | None = None, + **kwargs: Any ) -> None: def __local() -> Local: diff --git a/src/python/jw/pkg/lib/ec/Local.py b/src/python/jw/pkg/lib/ec/Local.py index 243a969a..9eca6817 100644 --- a/src/python/jw/pkg/lib/ec/Local.py +++ b/src/python/jw/pkg/lib/ec/Local.py @@ -7,20 +7,20 @@ import pwd import sys from functools import cache -from typing import override, TYPE_CHECKING +from typing import TYPE_CHECKING, override from ..base import Result, StatResult from ..ExecContext import ExecContext as Base from ..log import ERR, NOTICE, log if TYPE_CHECKING: - from typing import Any + from typing import Any, Callable from ..Uri import Uri class Local(Base): - def __init__(self, uri: str | Uri = 'local', *args, **kwargs) -> None: + def __init__(self, uri: str | Uri = 'local', *args: Any, **kwargs: Any) -> None: super().__init__(uri, *args, **kwargs) @cache @@ -43,9 +43,12 @@ class Local(Base): if verbose: log(prio, log_prefix, *args) - def __make_pty_reader(collector: list[bytes], enc_for_verbose: str): + def __make_pty_reader( + collector: list[bytes], + enc_for_verbose: str, + ) -> Callable[[int], bytes]: - def _read(fd): + def _read(fd: int) -> bytes: ret = os.read(fd, 1024) if not ret: return ret @@ -65,7 +68,7 @@ class Local(Base): if interactive: import pty - def _spawn(): + def _spawn() -> int: # Apply env in PTY mode by temporarily updating os.environ # around spawn. if mod_env: @@ -115,7 +118,9 @@ class Local(Base): stdout_log_enc = sys.stdout.encoding or 'utf-8' stderr_log_enc = sys.stderr.encoding or 'utf-8' - async def read_stream(stream, prio, collector: list[bytes], log_enc: str): + async def read_stream( + stream: Any, prio: int, collector: list[bytes], log_enc: str + ) -> None: buf = b'' while True: chunk = await stream.read(4096) diff --git a/src/python/jw/pkg/lib/ec/SSHClient.py b/src/python/jw/pkg/lib/ec/SSHClient.py index 02814380..03ad0283 100644 --- a/src/python/jw/pkg/lib/ec/SSHClient.py +++ b/src/python/jw/pkg/lib/ec/SSHClient.py @@ -5,7 +5,7 @@ import os import pwd from enum import Flag, auto -from typing import TYPE_CHECKING, override +from typing import TYPE_CHECKING, Any, cast, override from ..ExecContext import ExecContext from ..log import DEBUG, ERR, INFO, NOTICE, get_caller_pos, log, log_m @@ -22,7 +22,9 @@ class SSHClient(ExecContext): ModEnv = auto() Wd = auto() - def __init__(self, uri: Uri | str, caps: Caps = Caps(0), *args, **kwargs) -> None: + def __init__( + self, uri: Uri | str, caps: Caps = Caps(0), *args: Any, **kwargs: Any + ) -> None: uri = Uri.pimp(uri) if uri.username is None: uri.set_username(pwd.getpwuid(os.getuid()).pw_name) @@ -54,13 +56,13 @@ class SSHClient(ExecContext): log_prefix: str, ) -> Result: - def __log(prio: int, *args, **kwargs): + def __log(prio: int, *args: Any, **kwargs: Any) -> None: caller = kwargs.get('caller') if caller is None: kwargs['caller'] = get_caller_pos(1) log(prio, log_prefix, *args, **kwargs) - def __log_block(prio: int, title: str, block: str | None): + def __log_block(prio: int, title: str, block: str | None) -> None: if self.__caps & self.Caps.LogOutput: return if block is None: @@ -112,8 +114,10 @@ class SSHClient(ExecContext): return self.uri.password def ssh_client( # export - *args, type: str | list[str] | None = None, **kwargs -) -> SSHClient: + *args: Any, + type: str | list[str] | None = None, + **kwargs: Any +) -> 'SSHClient': from importlib import import_module errors: list[str] = [] @@ -130,7 +134,7 @@ def ssh_client( # export ret = getattr(import_module(f'jw.pkg.lib.ec.ssh.{name}'), name)(*args, **kwargs) log(INFO, f'Using SSH-client "{name}"') - return ret + return cast('SSHClient', ret) except Exception as e: msg = f"Can't instantiate SSH client class {name} ({str(e)})" errors.append(msg) diff --git a/src/python/jw/pkg/lib/ec/ssh/AsyncSSH.py b/src/python/jw/pkg/lib/ec/ssh/AsyncSSH.py index a2fbb12f..c1e3fd99 100644 --- a/src/python/jw/pkg/lib/ec/ssh/AsyncSSH.py +++ b/src/python/jw/pkg/lib/ec/ssh/AsyncSSH.py @@ -1,4 +1,3 @@ -from typing import Any, override import asyncio import os import shlex @@ -6,8 +5,12 @@ import shutil import signal import sys +from typing import Any, override + import asyncssh # type: ignore[import-not-found, unused-ignore] +from asyncssh import SSHReader # type: ignore[import-not-found, unused-ignore] + from ...base import Result from ...log import DEBUG, ERR, NOTICE, log from ..SSHClient import SSHClient as Base @@ -22,10 +25,10 @@ class AsyncSSH(Base): uri: str, *, client_keys: list[str] | None = None, - known_hosts = _USE_DEFAULT_KNOWN_HOSTS, + known_hosts: Any = _USE_DEFAULT_KNOWN_HOSTS, term_type: str | None = None, connect_timeout: float | None = 30.0, - **kwargs, + **kwargs: Any, ) -> None: super().__init__( @@ -121,8 +124,8 @@ class AsyncSSH(Base): async def _read_stream( self, - stream, - prio, + stream: SSHReader[bytes], + prio: int, collector: list[bytes], *, verbose: bool, @@ -222,7 +225,7 @@ class AsyncSSH(Base): stdout_parts.append(chunk) _write_local(chunk) - def _on_winch(*_args) -> None: + def _on_winch(*_args: Any) -> None: try: proc.change_terminal_size(*self._get_local_term_size()) diff --git a/src/python/jw/pkg/lib/ec/ssh/Exec.py b/src/python/jw/pkg/lib/ec/ssh/Exec.py index 17bd35e4..e431dc90 100644 --- a/src/python/jw/pkg/lib/ec/ssh/Exec.py +++ b/src/python/jw/pkg/lib/ec/ssh/Exec.py @@ -2,7 +2,7 @@ from __future__ import annotations import os -from typing import override, TYPE_CHECKING +from typing import Any, override, TYPE_CHECKING from ...base import InputMode from ...util import run_cmd @@ -14,12 +14,12 @@ if TYPE_CHECKING: class Exec(Base): - def __init__(self, uri, *args, **kwargs) -> None: + def __init__(self, uri: Any, *args: Any, **kwargs: Any) -> None: self.__askpass: str | None = None self.__askpass_orig: dict[str, str | None] = dict() super().__init__(uri = uri, caps = self.Caps.ModEnv, **kwargs) - def __del__(self): + def __del__(self) -> None: for key, val in self.__askpass_orig.items(): if val is None: del os.environ[key] diff --git a/src/python/jw/pkg/lib/ec/ssh/Paramiko.py b/src/python/jw/pkg/lib/ec/ssh/Paramiko.py index 866c3f67..3b080da9 100644 --- a/src/python/jw/pkg/lib/ec/ssh/Paramiko.py +++ b/src/python/jw/pkg/lib/ec/ssh/Paramiko.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import override, TYPE_CHECKING +from typing import Any, override, TYPE_CHECKING # Tolerate missing paramiko imports. jw-pkg is designed to work with what it # finds. @@ -18,7 +18,7 @@ if TYPE_CHECKING: class Paramiko(Base): - def __init__(self, uri, *args, **kwargs) -> None: + def __init__(self, uri: Any, *args: Any, **kwargs: Any) -> None: kwargs['caps'] = (self.Caps.ModEnv, ) super().__init__(uri, *args, **kwargs) self.__timeout: float | None = None # Untested diff --git a/src/python/jw/pkg/lib/log.py b/src/python/jw/pkg/lib/log.py index 98f0f4e3..6e9f70e7 100644 --- a/src/python/jw/pkg/lib/log.py +++ b/src/python/jw/pkg/lib/log.py @@ -7,7 +7,7 @@ import syslog from datetime import datetime from os.path import basename -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, cast if TYPE_CHECKING: import io @@ -126,7 +126,7 @@ _prio_colors = { class Stream: - def __init__(self, stream, flags): + def __init__(self, stream: Any, flags: int): self.stream = stream self.flags = flags @@ -142,12 +142,12 @@ def pad(token: str, total_size: int, right_align: bool = False) -> str: return space + token return token + space -def add_capture_stream(stream, flags = 0x0): +def add_capture_stream(stream: Any, flags: int = 0x0) -> int: ret = _stream_descriptors.pop() _streams[ret] = Stream(stream = stream, flags = flags) return ret -def rm_capture_stream(sd): +def rm_capture_stream(sd: int) -> None: del _streams[sd] _stream_descriptors.append(sd) @@ -166,13 +166,13 @@ def get_caller_pos(up: int = 1, if kwargs and 'caller' in kwargs: r = kwargs['caller'] del kwargs['caller'] - return r + return cast('Tuple[str, str, int]', r) caller = inspect.stack()[up + 1] mod = inspect.getmodule(caller[0]) mod_name = '' if mod is None else mod.__name__ return (mod_name, basename(caller.filename), caller.lineno) -def log_m(prio: int, *args, **kwargs) -> None: # export +def log_m(prio: int, *args: Any, **kwargs: Any) -> None: # export if prio > _level: return margs = '' @@ -190,7 +190,12 @@ def log_m(prio: int, *args, **kwargs) -> None: # export for line in margs[1:].split('\n'): log(prio, line, **kwargs, caller = caller) -def log(prio: int, *args, only_printable: bool = False, **kwargs) -> None: # export +def log( # export + prio: int, + *args: Any, + only_printable: bool = False, + **kwargs: Any +) -> None: if prio > _level: return @@ -259,7 +264,12 @@ def log(prio: int, *args, only_printable: bool = False, **kwargs) -> None: # ex for file in files: print(msg, file = file) -def throw(*args, prio = ERR, caller = None, **kwargs) -> None: +def throw( + *args: Any, + prio: int = ERR, + caller: Tuple[str, str, int] | None = None, + **kwargs: Any +) -> None: if caller is None: caller = get_caller_pos(1) msg = ' '.join([str(arg) for arg in args]) @@ -331,7 +341,7 @@ def append_to_prefix(prefix: str) -> str: # export _clean_log_prefix = _clean_str_regex.sub('', _log_prefix) return r -def remove_from_prefix(count) -> str: # export +def remove_from_prefix(count: int | str) -> str: # export if isinstance(count, str): count = len(count) global _log_prefix diff --git a/src/python/jw/pkg/lib/pm/dpkg.py b/src/python/jw/pkg/lib/pm/dpkg.py index 12b5d9e8..a7b30813 100644 --- a/src/python/jw/pkg/lib/pm/dpkg.py +++ b/src/python/jw/pkg/lib/pm/dpkg.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Iterable +from typing import TYPE_CHECKING, Iterable, cast if TYPE_CHECKING: from ..ExecContext import ExecContext @@ -59,7 +59,7 @@ async def query_packages(names: Iterable[str] = [], ) # dpkg-query -W -f='${binary:Package}|${Maintainer}| ... \n' specs = await run_dpkg_query(['-W', '-f=' + fmt_str, *names], sudo = False, ec = ec) - return Package.parse_specs_str(specs) + return cast('Iterable[Package]', Package.parse_specs_str(specs)) async def list_files(pkg: str, ec: ExecContext | None = None) -> list[str]: file_list_str = await run_dpkg(['-L', pkg], sudo = False, ec = ec) diff --git a/src/python/jw/pkg/lib/pm/rpm.py b/src/python/jw/pkg/lib/pm/rpm.py index 68421e81..c326bba0 100644 --- a/src/python/jw/pkg/lib/pm/rpm.py +++ b/src/python/jw/pkg/lib/pm/rpm.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Collection, Iterable +from typing import Any, TYPE_CHECKING, Collection, Iterable, cast from ..base import InputMode from ..Package import Package @@ -30,7 +30,7 @@ async def run_rpm( # export sudo: bool = False, ec: ExecContext | None = None, mode: InputMode = InputMode.OptInteractive, - **kwargs, + **kwargs: Any, ) -> str: cmd = ['/usr/bin/rpm'] cmd.extend(args) @@ -58,7 +58,7 @@ async def query_packages( # export mode = InputMode.NonInteractive, ec = ec ) - return Package.parse_specs_str(specs) + return cast('Iterable[Package]', Package.parse_specs_str(specs)) async def list_files(pkg: str, ec: ExecContext | None = None) -> list[str]: stdout = await run_rpm( diff --git a/src/python/jw/pkg/lib/util.py b/src/python/jw/pkg/lib/util.py index db0eb5e1..27812391 100644 --- a/src/python/jw/pkg/lib/util.py +++ b/src/python/jw/pkg/lib/util.py @@ -5,7 +5,7 @@ import os import sys from enum import Enum, auto -from typing import TYPE_CHECKING, Iterable, TypeVar +from typing import TYPE_CHECKING, Any, Iterable, TypeVar, cast from .base import Input, InputMode, Result from .log import DEBUG, ERR, log @@ -23,7 +23,7 @@ class AskpassKey(Enum): Username = auto() Password = auto() -def pretty_cmd(cmd: list[str] | None = None, wd = None): +def pretty_cmd(cmd: list[str] | None = None, wd: str | None = None) -> str: if cmd is None: cmd = sys.argv tokens = [cmd[0]] @@ -38,11 +38,11 @@ def pretty_cmd(cmd: list[str] | None = None, wd = None): # See ExecContext.run() for what this function does async def run_cmd( - *args, + *args: Any, ec: ExecContext | None = None, verbose: bool | None = None, cmd_input: Input = InputMode.NonInteractive, - **kwargs, + **kwargs: Any, ) -> Result: if verbose is None: verbose = False if ec is None else ec.verbose_default @@ -56,12 +56,12 @@ async def run_cmd( async def run_curl( args: list[str], - wd = None, - throw = None, - verbose = None, - cmd_input = InputMode.NonInteractive, + wd: str | None = None, + throw: bool | None = None, + verbose: bool | None = None, + cmd_input: Input = InputMode.NonInteractive, ec: ExecContext | None = None, - decode = False, + decode: bool = False, ) -> Result: if verbose is None: verbose = False if ec is None else ec.verbose_default @@ -76,7 +76,7 @@ async def run_curl( async def run_curl_into( expected_type: type[T], args: list[str], - **kwargs, + **kwargs: Any, ) -> T: result = await run_curl(args, **kwargs) stdout = result.stdout_str @@ -139,11 +139,11 @@ async def run_askpass( async def run_sudo( cmd: list[str], - *args, + *args: Any, interactive: bool = True, ec: ExecContext | None = None, - **kwargs, -): + **kwargs: Any, +) -> Result: if ec is None: from .ec.Local import Local @@ -152,10 +152,10 @@ async def run_sudo( async def get( uri: str | Uri, - *args, + *args: Any, ctx: FileContext | None = None, content_filter: ProcFilter | list[ProcFilter] | ProcPipeline | None = None, - **kwargs, + **kwargs: Any, ) -> Result: uri = Uri.pimp(uri) if ctx is None or uri.id != ctx.uri.id: @@ -172,7 +172,7 @@ async def copy( owner: str | None = None, group: str | None = None, mode: int | None = None, - throw = True, + throw: bool = True, ) -> Exception | str | list[str]: if not isinstance(src_uri, str): ret: list[str] = [] @@ -225,7 +225,7 @@ async def get_username( # export f'Username mismatch: called with --username="{args.username}", ' f'URL has user name "{url_user}"' ) - return args.username + return str(args.username) if url_user is not None: return url_user return await run_askpass(askpass_env, AskpassKey.Username, ec = ec) @@ -244,7 +244,7 @@ async def get_password( # export if args is not None and hasattr(args, 'password'): # use getattr(), because we don't necessarily want to have insecure # --password among options - ret = getattr(args, 'password') + ret = cast('str | None', getattr(args, 'password')) if ret is not None: return ret if url is not None: