0

I've found the documenation for the python argparse module, and it mentions the formatter_class. I see nothing on that page for things like the width parameter or max_help_position. Where are those documented?

https://docs.python.org/3/library/argparse.html

kdubs
  • 1,303
  • 1
  • 17
  • 32
  • On that page, there is a link to the source. You could look through it and see how it works. – wwii Mar 14 '18 at 00:25

2 Answers2

2

Argparse uses a helper class argparse.helpformatter() which uses the max_help_position and width parameter (among others). See this excellent answer that explains how it is used Explain lambda argparse.HelpFormatter(prog, width).

The problem you are having with finding documentation for it, is because the HelpFormatter is only public in the sense of its name. All its methods are private.

This is taken from the source linked in the documentation you provided https://github.com/python/cpython/blob/2.7/Lib/argparse.py:

class HelpFormatter(object):

Formatter for generating usage messages and argument help strings.

Only the name of this class is considered a public API. All the methods provided by the class are considered an implementation detail.

So the the argparse documentation itself is a mix of how-to and formal API description. Mostly it describes how to perform common parsing tasks. Even though argparse consists of classes, the documentation does not formally describe the classes, and their subclassing and all methods. It's not a reference API.

A workaround, would be to find another service that uses the HelpFormatter class that better document its variables, like this one from Discord https://discordpy.readthedocs.io/en/rewrite/ext/commands/api.html#discord.ext.commands.HelpFormatter.

Hope this helps.

Update

Discord updated its links so the above link is now broken. Find it in the WayBackMachine instead: https://web.archive.org/web/20180306073319/https://discordpy.readthedocs.io/en/rewrite/ext/commands/api.html#discord.ext.commands.HelpFormatter

Community
  • 1
  • 1
pastaleg
  • 1,627
  • 2
  • 15
  • 21
1

The argparse documentation more of a common usage manual than a formal module documentation. It doesn't, for example, list all (public) classes, and their methods. So for more custom uses you will have to look at the code, which fortunately is in just one file, argparse.py.

The help calling sequence is:

parser.print_help
   parser.format_help
       parser._get_formatter
           self.formatter_class(prog=self.prog)

In that use only the prog parameter is set; other values are default.

class HelpFormatter(object):
         def __init__(self,
             prog,
             indent_increment=2,
             max_help_position=24,
             width=None):

So these other parameters are available in the __init__ but not readily accessible to users.

Customizing the _get_formatter method is one way of customizing these values. Another is to subclass HelpFormatter. It might also be possible to use partial to set these values in the formatter_class parameter.

I see @Magnus has found my earlier answer on this topic.

So despite name, the formater_class parameter does not have to be a class. In Python duck_typing, it just has to be something that _get_formatter can use. It can be any function or lambda that takes prog paramater.

Drawing on the previous answer:

f = lambda prog: argparse.HelpFormatter(prog, width=100)
f = functools.partial(argparse.HelpFormatter, width=100)

can both be used as:

parser = argparse.ArgumentParser(formatter_class=f)

(illustration)

Let's see if I can illustrate how argparse uses the formatter class.

print_usage uses format_usage (print_help is similar but longer)

def format_usage(self):
    formatter = self._get_formatter()
    formatter.add_usage(self.usage, self._actions,
                        self._mutually_exclusive_groups)
    return formatter.format_help()

With parser from a previous question:

In [459]: p.print_usage()
usage: ipython3 [-h] [-f F] [-g [G [G ...]]] [-k [K [K ...]]]

I can replicate that with a direct call to the HelpFormatter class:

In [460]: f = argparse.HelpFormatter(prog='foo')
In [461]: f.add_usage(p.usage, p._actions,p._mutually_exclusive_groups)
In [462]: print(f.format_help())
usage: foo [-h] [-f F] [-g [G [G ...]]] [-k [K [K ...]]]

If I create a formatter with a width parameter I get some line wrapping:

In [463]: f = argparse.HelpFormatter(prog='foo',width=40)
In [464]: f.add_usage(p.usage, p._actions,p._mutually_exclusive_groups)
In [465]: print(f.format_help())
usage: foo [-h] [-f F] [-g [G [G ...]]]
           [-k [K [K ...]]]

The purpose of the suggested lambda (and variations) is to replace the default formatter creation as in [460] with a custom one. The formatter_class parameter lets us do that. It requires more Python knowledge than a simple width parameter would, but ultimately gives us a lot more customizing power.

hpaulj
  • 175,871
  • 13
  • 170
  • 282
  • is there a way to pass the width other than with a lamda function? – kdubs Mar 14 '18 at 02:14
  • Here and in the other answer I attempted to describe various ways. But, no, there isn't a simple parameter that you can use that will change the width. – hpaulj Mar 14 '18 at 05:18
  • 1
    I found that I can adjust the width by setting this: os.environ["COLUMNS"]='200' – kdubs Mar 14 '18 at 17:40
  • 1
    @kdubs, With `width` as the default `None`, it looks to the environment for a value. – hpaulj Mar 14 '18 at 18:34