lib.Cmd.AbstractCmd.aliases: Add property

Add a property aliases to AbstractCmd in prepeparation for commands
to bear multiple names / abbreviations / aliases.

The App.add_cmds_to_parser() function uses parse_known_args() to
determine which subcommand was invoked, then conditionally registers
nested subcommands. The lookup dictionary (scs) contains only
canonical names, not aliases, so add them too, otherwise using the
alias instead of the canonical name causes the lookup to fail and
nested subcommands to never be registered.

Fix: Register each alias in scs pointing to the same SubCommand
object, and deduplicate with id(sc) when iterating in all=True mode
to avoid infinite recursion on help output.

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2026-06-18 10:15:08 +02:00
commit 3b0f7727a7
Signed by: Jan Lindemann
GPG key ID: 3750640C9E25DD61
3 changed files with 35 additions and 7 deletions

View file

@ -56,6 +56,7 @@ class App: # export
cmd.name,
help = cmd.help,
description = cmd.description,
aliases = cmd.aliases,
formatter_class = ArgumentDefaultsHelpFormatter,
)
parser.set_defaults(func = cmd.run)
@ -88,13 +89,21 @@ class App: # export
for cmd in cmds:
cmd.set_parent(parent)
scs[cmd.name] = SubCommand(cmd, add_cmd_to_parser(cmd, subparsers))
for alias in cmd.aliases:
scs[alias] = scs[cmd.name]
if all:
seen: set[int] = set()
for sc in scs.values():
add_cmds_to_parser(sc.cmd, sc.parser, sc.cmd.children, all = all)
if id(sc) not in seen:
seen.add(id(sc))
add_cmds_to_parser(
sc.cmd, sc.parser, sc.cmd.children, all = all
)
return
args, unknown = self.__parser.parse_known_args()
if args.command in scs:
sc = scs[args.command]
cmd_name = getattr(args, 'command', None)
if cmd_name in scs:
sc = scs[cmd_name]
add_cmds_to_parser(sc.cmd, sc.parser, sc.cmd.children, all = all)
from .Cmd import AbstractCmd