From 281a8f383e9a70357b4baa247e82ce1414b6b0d4 Mon Sep 17 00:00:00 2001 From: Jan Lindemann Date: Mon, 7 Sep 2026 09:06:40 +0200 Subject: [PATCH] lib.Types: Restrict LoadTypes to ABC-derived classes The previous commit reads __abstractmethods__ via a getattr() with an empty frozenset fallback, because in mypy 2.3.1 the scanned classes are typed as type[object], which does not declare the attribute. Add is_abc_class() as a TypeGuard, and skip the classes it rejects with a debug line: LoadTypes now yields only ABC-derived classes. The guard narrows to the classes that carry the attribute, so that the debug line can now read __abstractmethods__ directly. The command loaders are unaffected: every class they load is derived from AbstractCmd, and hence from ABC. For loads that rely on the name filter alone, plain classes are now skipped instead of being yielded. Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v0.84.2 Signed-off-by: Jan Lindemann --- src/python/jw/pkg/lib/Types.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/python/jw/pkg/lib/Types.py b/src/python/jw/pkg/lib/Types.py index 344da9ca..6b27ea85 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 TYPE_CHECKING, Any, Generic, Iterable, TypeVar, override +from typing import TYPE_CHECKING, Any, Generic, Iterable, TypeGuard, TypeVar, override from .log import ERR, OFF, log, parse_log_level @@ -15,6 +15,9 @@ if TYPE_CHECKING: T = TypeVar('T') +def is_abc_class(c: type[object]) -> TypeGuard[abc.ABCMeta]: + return isinstance(c, abc.ABCMeta) + class Types(abc.ABC, Iterable[type[T]], Generic[T]): # export @override @@ -101,11 +104,11 @@ class LoadTypes(Types[T]): # export if rx is not None and not re.match(rx, member_name): self._debug(f'o "{name}" has wrong name') continue + if not is_abc_class(c): + self._debug(f'o "{name}" is not derived from ABCMeta') + continue if inspect.isabstract(c): - abstract: frozenset[str] = getattr( - c, '__abstractmethods__', frozenset() - ) - self._debug(f'o "{name}" is abstract: {abstract}') + self._debug(f'o "{name}" is abstract: {c.__abstractmethods__}') continue if self.__type_filter: for tp in self.__type_filter: -- 2.55.0