DanCardin / cappa

Declarative CLI argument parser
Apache License 2.0
132 stars 9 forks source link

ux: Default value custom format with `cappa.invoke` #173

Closed pawamoy closed 1 hour ago

pawamoy commented 2 hours ago

The docs lead me to think I could do this:

import sys
import cappa
from dataclasses import dataclass
from typing import Annotated

@cappa.command(name="sub")
@dataclass(kw_only=True)
class CommandSub:
    """Subcommand."""

    opt: Annotated[int, cappa.Arg(short=True, long=True, help="Some option.")] = 2

    def __call__(self):
        print("sub", self.opt)

@cappa.command(name="main")
@dataclass(kw_only=True)
class CommandMain:
    """Main command."""

    subcommand: Annotated[CommandSub, cappa.Subcommand()]

    opt: Annotated[int, cappa.Arg(short=True, long=True, help="Some option.")] = 1

def main(args: list[str] | None = None) -> int:
    help_formatter = cappa.HelpFormatter(default_format="Default: {default}.")
    return cappa.invoke(CommandMain, argv=args, help_formatter=help_formatter)

if __name__ == "__main__":
    main(sys.argv[1:])

...but the default value format is left unchanged.

Looking at cappa.invoke's signature, help_formatter accetps a HelpFormatable there, which is callable accepting a Command and a string and return a list of Displayable.

Is it expected that cappa.invoke and cappa.parse handle the help_formatter argument differently?

pawamoy commented 2 hours ago

Hmm, actually cappa.parse also accepts a HelpFormatable, and in fact HelpFormatter.__call__ matches the expected signature. So I'm not sure what's wrong here and why I'm not seeing any change in the default format :thinking:

pawamoy commented 2 hours ago

In cappa.base.collect, this line:

command: Command[T] = Command.get(obj, help_formatter=help_formatter)

...seems to return obj.__cappa__, which has the default help formatter attached.

pawamoy commented 2 hours ago

OK so I'm probably supposed to pass the help formatter to each @cappa.command decorator :thinking:

DanCardin commented 1 hour ago

you should be able to do either, it was just early returning in cases where the command was already decorated with @command and failing to apply the help_formatter option.