test: Fix mypy strict errors in unit tests

The unit test files below test/unit/python/jw/pkg/lib/ define Cmd and App
subclasses with unannotated methods: __init__(), add_arguments(), _run()
and close() lack signatures, the made class attribute lacks a type, and the
_cleanup() and exit_context() helpers are untyped, so a strict mypy run
over the test tree fails on them. Likewise, the ExecApp and version tests
carry list formatting that yapf rejects.

Annotate the test classes following the library conventions: parent is App
| Cmd, the parser is ArgumentParser, and args is Namespace, and mark every
overridden method with @override. Guard the imports that are only used for
annotations behind TYPE_CHECKING, and add the future annotations import so
they stay out of the runtime path. Then reformat the test tree with yapf.
That folds the opts list of the ExecApp test and re-indents the rejected
operator list of the version test.

Signed-off-by: Jan Lindemann <jan@janware.com>
Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v0.85.1
This commit is contained in:
Jan Lindemann 2026-09-11 14:22:26 +02:00
commit 64f1a73650
Signed by: Jan Lindemann
GPG key ID: 3750640C9E25DD61
4 changed files with 46 additions and 27 deletions

View file

@ -1,10 +1,16 @@
import asyncio
from __future__ import annotations
import asyncio
import sys
from typing import TYPE_CHECKING, override
from jw.pkg.lib.App import App
from jw.pkg.lib.Cmd import Cmd
if TYPE_CHECKING:
from argparse import ArgumentParser, Namespace
# -- A minimal command tree: a root command hosting one child command. The
# root mimics the "run + opts" unit the App can now mount at the top level:
# it adds options, sets up, dispatches to the selected child (or runs its own
@ -12,24 +18,26 @@ from jw.pkg.lib.Cmd import Cmd
class ChildCmd(Cmd):
def __init__(self, parent):
def __init__(self, parent: App | Cmd) -> None:
super().__init__(parent, 'child', 'A child command')
self.ran = False
self.got_opt = None
def add_arguments(self, parser):
@override
def add_arguments(self, parser: ArgumentParser) -> None:
super().add_arguments(parser)
parser.add_argument('--child-opt', default = 'child-default')
async def _run(self, args):
@override
async def _run(self, args: Namespace) -> None:
self.ran = True
self.got_opt = args.child_opt
class RootCmd(Cmd):
made = []
made: list['RootCmd'] = []
def __init__(self, parent):
def __init__(self, parent: App | Cmd) -> None:
super().__init__(parent, 'root', 'Root command')
self.child = ChildCmd(self)
self.add_subcommands(self.child)
@ -38,11 +46,13 @@ class RootCmd(Cmd):
self.default = False
RootCmd.made.append(self)
def add_arguments(self, parser):
@override
def add_arguments(self, parser: ArgumentParser) -> None:
super().add_arguments(parser)
parser.add_argument('--root-opt', default = 'root-default')
async def _run(self, args):
@override
async def _run(self, args: Namespace) -> None:
self.setup = True
try:
if hasattr(args, 'func'):