fbahr
fbahr

Reputation: 883

Custom usage message for many-valued argument

Given sth. like (or similar to):

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("FILES", nargs="+", type=str)
args = parser.parse_args()

Now I'd like to have the many-valued positional argument FILES displayed in the usage message as

usage: cli.py [-h] FILES

instead of

usage: cli.py [-h] FILES [FILES ...]

Any step-by-step explanations or pointers are appreciated.

Upvotes: 2

Views: 548

Answers (2)

JoshuaCS
JoshuaCS

Reputation: 2624

fbahr, I just decided to dive into the source code of argparse. I found out the formatting of the usage is hardcoded, look at it here. The only way you can override it is inheriting from HelpFormatter (the default class used when creating a new ArgumentParser instance) and say to the parser to use the class you created, to use your own formatter. You will have to override a "private" method (it is prefixed with an underscore) named _format_args, which is a little ugly and anti-pattern (in fact the only reason you can do that is because we are using Python) but it seems to be the only way to customize argparse the way you wanna do it.

import argparse

class NArgsCustomUsageHelpFormatter(argparse.HelpFormatter):

    def _format_args(self, action, default_metavar):
        get_metavar = self._metavar_formatter(action, default_metavar)

        if action.nargs == argparse.ONE_OR_MORE:
            result = '%s' % get_metavar(1)
        else:
            result = argparse.HelpFormatter._format_args(self, action, default_metavar)

        return result

parser = argparse.ArgumentParser(formatter_class=NArgsCustomUsageHelpFormatter)

parser.add_argument("FILES", nargs="+", type=str)
args = parser.parse_args()

The code above just change the default behaviour if the action to be formatted needs at least one argument (nargs='+'), otherwise it doesn't do anything different.

This is the output

I hope this help you!

Upvotes: 1

alecxe
alecxe

Reputation: 473873

This is the built-in behavior of the default formatter: source.

You could have your custom formatter with special handling for the nargs="+" type arguments:

import argparse


class CustomFormatter(argparse.HelpFormatter):
    def _format_args(self, action, default_metavar):
        get_metavar = self._metavar_formatter(action, default_metavar)
        if action.nargs == argparse.ONE_OR_MORE:
            return '%s' % get_metavar(1)
        else:
            return super(CustomFormatter, self)._format_args(action, default_metavar)


parser = argparse.ArgumentParser(formatter_class=CustomFormatter)
parser.add_argument("FILES", nargs="+", type=str)
args = parser.parse_args()

Would print out:

usage: cli.py [-h] FILES
cli.py: error: the following arguments are required: FILES

Upvotes: 4

Related Questions