From 7e2099877c5fbc8ca6cee332f06e986a48c21051 Mon Sep 17 00:00:00 2001 From: Jan Lindemann Date: Fri, 1 May 2026 10:17:24 +0200 Subject: [PATCH] lib.Cmd.load_subcommands(): Add method Push cmds.Cmd._add_subcommands() as lib.Cmd.load_subcommands() one step up to the top of the type hierarchy ladder. By default, it does the same thing, i.e. load subcommands matching frobnicate.Cmd* if called on class CmdFrobnicate. This commit also replaces invocations of Cmd._add_subcommands() by invocations of this new method. Signed-off-by: Jan Lindemann --- src/python/jw/pkg/cmds/Cmd.py | 7 ------- src/python/jw/pkg/cmds/CmdPkg.py | 2 +- src/python/jw/pkg/cmds/CmdPlatform.py | 2 +- src/python/jw/pkg/cmds/CmdPosix.py | 2 +- src/python/jw/pkg/cmds/CmdProjects.py | 2 +- src/python/jw/pkg/cmds/CmdSecrets.py | 2 +- src/python/jw/pkg/cmds/posix/CmdTar.py | 2 +- src/python/jw/pkg/lib/Cmd.py | 11 ++++++++++- 8 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/python/jw/pkg/cmds/Cmd.py b/src/python/jw/pkg/cmds/Cmd.py index 86f66aa4..8614bebf 100644 --- a/src/python/jw/pkg/cmds/Cmd.py +++ b/src/python/jw/pkg/cmds/Cmd.py @@ -6,19 +6,12 @@ from argparse import ArgumentParser from ..App import App from ..lib.Cmd import Cmd as Base -from ..lib.Types import LoadTypes class Cmd(Base): # export def __init__(self, parent: App|Base, name: str, help: str) -> None: super().__init__(parent, name, help) - def _add_subcommands(self) -> None: - # Derive module search path for the calling module's subcommands from - # the module path of the calling module itself - cmds_module = type(self).__module__.replace('Cmd', '').lower() - self.add_subcommands(LoadTypes([cmds_module], type_name_filter=r'Cmd[^.]')) - async def _run(self, args): import sys # Missing subcommand diff --git a/src/python/jw/pkg/cmds/CmdPkg.py b/src/python/jw/pkg/cmds/CmdPkg.py index a447d769..836eb3a3 100644 --- a/src/python/jw/pkg/cmds/CmdPkg.py +++ b/src/python/jw/pkg/cmds/CmdPkg.py @@ -9,7 +9,7 @@ class CmdPkg(CmdBase): # export def __init__(self, parent: App) -> None: super().__init__(parent, 'pkg', help="System package manager wrapper") - self._add_subcommands() + self.load_subcommands() def add_arguments(self, p: ArgumentParser) -> None: super().add_arguments(p) diff --git a/src/python/jw/pkg/cmds/CmdPlatform.py b/src/python/jw/pkg/cmds/CmdPlatform.py index e64b3283..0db24096 100644 --- a/src/python/jw/pkg/cmds/CmdPlatform.py +++ b/src/python/jw/pkg/cmds/CmdPlatform.py @@ -9,7 +9,7 @@ class CmdPlatform(CmdBase): # export def __init__(self, parent: App) -> None: super().__init__(parent, 'platform', help="Miscellaneous platform-related comamnds") - self._add_subcommands() + self.load_subcommands() def add_arguments(self, p: ArgumentParser) -> None: super().add_arguments(p) diff --git a/src/python/jw/pkg/cmds/CmdPosix.py b/src/python/jw/pkg/cmds/CmdPosix.py index d183cc8c..c98d67ab 100644 --- a/src/python/jw/pkg/cmds/CmdPosix.py +++ b/src/python/jw/pkg/cmds/CmdPosix.py @@ -9,7 +9,7 @@ class CmdPosix(CmdBase): # export def __init__(self, parent: App) -> None: super().__init__(parent, 'posix', help='Perform various operations on a distro through its POSIX utility interface') - self._add_subcommands() + self.load_subcommands() def add_arguments(self, p: ArgumentParser) -> None: super().add_arguments(p) diff --git a/src/python/jw/pkg/cmds/CmdProjects.py b/src/python/jw/pkg/cmds/CmdProjects.py index a09d3baf..f266c417 100644 --- a/src/python/jw/pkg/cmds/CmdProjects.py +++ b/src/python/jw/pkg/cmds/CmdProjects.py @@ -10,7 +10,7 @@ class CmdProjects(CmdBase): # export def __init__(self, parent: App) -> None: super().__init__(parent, 'projects', help='Project metadata evaluation for building packages') - self._add_subcommands() + self.load_subcommands() def add_arguments(self, p: ArgumentParser) -> None: super().add_arguments(p) diff --git a/src/python/jw/pkg/cmds/CmdSecrets.py b/src/python/jw/pkg/cmds/CmdSecrets.py index 4af73e72..7d3f5ce8 100644 --- a/src/python/jw/pkg/cmds/CmdSecrets.py +++ b/src/python/jw/pkg/cmds/CmdSecrets.py @@ -9,7 +9,7 @@ class CmdSecrets(CmdBase): # export def __init__(self, parent: App) -> None: super().__init__(parent, 'secrets', help="Manage package secrets") - self._add_subcommands() + self.load_subcommands() def add_arguments(self, p: ArgumentParser) -> None: super().add_arguments(p) diff --git a/src/python/jw/pkg/cmds/posix/CmdTar.py b/src/python/jw/pkg/cmds/posix/CmdTar.py index 18c5b379..87239a27 100644 --- a/src/python/jw/pkg/cmds/posix/CmdTar.py +++ b/src/python/jw/pkg/cmds/posix/CmdTar.py @@ -9,7 +9,7 @@ class CmdTar(Cmd): # export def __init__(self, parent: CmdPosix) -> None: super().__init__(parent, 'tar', help='Handle tar archives') - self._add_subcommands() + self.load_subcommands() def add_arguments(self, parser: ArgumentParser) -> None: super().add_arguments(parser) diff --git a/src/python/jw/pkg/lib/Cmd.py b/src/python/jw/pkg/lib/Cmd.py index a3c6d6f9..65ff78bf 100644 --- a/src/python/jw/pkg/lib/Cmd.py +++ b/src/python/jw/pkg/lib/Cmd.py @@ -8,7 +8,7 @@ import inspect, sys, re, abc, argparse from argparse import ArgumentParser, _SubParsersAction from .log import * -from .Types import Types +from .Types import Types, LoadTypes class Cmd(abc.ABC): # export @@ -106,6 +106,15 @@ class Cmd(abc.ABC): # export return raise Exception(f'Tried to add sub-commands of unknown type {type(cmds)}') + def load_subcommands(self, modules: str|list[str]|None=None, name_filter: str=r'Cmd[^.]') -> None: + if modules is None: + # Derive module search path for the calling module's subcommands + # from the module path of the calling module itself + modules = [type(self).__module__.replace('Cmd', '').lower()] + elif isinstance(modules, str): + modules = [modules] + self.add_subcommands(LoadTypes(modules, type_name_filter=name_filter)) + # To be overridden by derived class in case the command does take arguments. # Will be called from App base class constructor and set up the parser hierarchy def add_arguments(self, parser: ArgumentParser) -> None: