Documenting Argument Types With Click

2020-05-04

Building a Python CLI interface with click, how can I get the same argument "type" twice in usage instructions?

Say we have a very simple interface that has two arguments of the same, and say we have implemented our own ParameterType for some reason:

from typing import Optional

import click


class NameParamType(click.ParamType):
    name = "name"

    def convert(self, value, param, ctx):
        return value.capitalize()


NAME = NameParamType()


@click.command()
@click.argument("callee", type=NAME)
@click.argument("caller", type=NAME, required=False)
def hello(callee: str, caller: Optional[str]):
    greeting = f"Hello {callee}"
    introduction = f", this is {caller}" if caller else ""
    print(f"{greeting}{introduction}!")


if __name__ == '__main__':
    hello()

Note how the name parameter of @click.argument has to match the parameter name of hello and also shows up in the usage instruction:

$ python hello.py --help
Usage: hello.py [OPTIONS] CALLEE [CALLER]

This is unfortunate in this case: it would be much clearer to see the "type" NAME reflected here! Turns out we can add metavar to NameParamType. For instance:

def get_metavar(self, param):
    return self.name.upper()

Et voilà:

$ ../venv/bin/python hello.py --help
Usage: hello.py [OPTIONS] NAME [NAME]
ProgrammingLibrary

Authorizing Only Your Team With Ansible

Rescue a Lost Commit