Hi colleagues I have the code (max_help_position is 2000):
formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=2000)
parser = argparse.ArgumentParser(formatter_class=formatter_class)subparsers = parser.add_subparsers(title="Commands", metavar="<command>")cmd_parser = subparsers.add_parser('long_long_long_long_long_long_long',help='- jksljdalkjda',formatter_class=formatter_class)args = parser.parse_args(['-h'])
print args
we have
optional arguments:-h, --help show this help message and exitCommands:<command>long_long_long_long_long_long_long- jksljdalkjdasmall - descr
instead
optional arguments:-h, --help show this help message and exitCommands:<command>long_long_long_long_long_long_long - jksljdalkjdasmall - descr
Do you know simply way how to fix this?
The code:
class MyFormatter(argparse.HelpFormatter):def __init__(self, prog):super(MyFormatter, self).__init__(prog, max_help_position=2000)self._max_help_position = 2000self._action_max_length += 4formatter_class = MyFormatter
parser = argparse.ArgumentParser(formatter_class=formatter_class)
got same result.
The code (with width=2000)
formatter_class = lambda prog: argparse.HelpFormatter(prog,max_help_position=2000, width=2000)
got same result.
Thank you.
P.S. Also some additional small issue: this is odd spaces in "optional arguments". Do you know how to separate "Commands" and "optional arguments" for do not have spaces in "optional arguments" and have spaces in "Commands" since these are different essences?
You need to increase the width as well
try:
formatter_class=lambda prog: argparse.HelpFormatter(prog,max_help_position=100, width=200)
As my earlier thoughts (below) show, the formatting considers overall width as well as the max_position value.
(earlier)
In my limited testing, your formatter subclass seems to work. But I haven't pushed the limits.
You many need to dig more into the Formatter code.
For example there is a format_action
method that actually uses the max_width
def _format_action(self, action):# determine the required width and the entry labelhelp_position = min(self._action_max_length + 2,self._max_help_position)help_width = self._width - help_positionaction_width = help_position - self._current_indent - 2...
Notice that it interacts with the width. Then it goes on to actually format the help lines and perform wrapping. So the actual implementation is not simple.
I'm not following your question about spaces. format_help
commands the formatter to format a number of sections (including argument groups). The sections (usually) end with a couple of line feeds. Upon assembling them the formatter removes 'unnecessary' line feeds, leaving one space between groups. The subparser doesn't fit other categories, so I'd have to study the code to see exactly how it is handled.
Your lambda
definition works as well. I haven't seen it before, and I don't think it's what the developers intended, but Python that doesn't matter - if it works.
Playing around with values and strings, I see that max_position up to about 56 works. Then it sort of sticks. But if I also change width
(default is from CONSOLE), I can increase max_position further.
I was testing this with a long parser
argument. Adding
parser.add_argument('-l','--long','--longlonglonglong', help='help after long option strings')
produces:
usage: issue25297.py [-h] [-l LONG] <command> ...optional arguments:-h, --help show this help message andexit-l LONG, --long LONG, --longlonglonglong LONG help after long optionstringsCommands:<command>long_long_long_long_long_long_long - jksljdalkjda
So max_help_position
does work in regular parser formatting. But for some reason, when only the subparser names are long, it does not. That section requires some special formatting. It is indented, and the subparser names are not real actions (arguments) but rather choices the subparsers
argument. I'll have study it in more detail.
The subparser name string is indented 2 extra characters (compared to other arguments). The code that collects self._action_max_length
does not take this into account. Hence if the subparser name is the longest string, this max_length will end up 2 spaces short. Compare actual v desired:
long_long_long_long_long_long_long- jksljdalkjda
long_long_long_long_long_long_long - jksljdalkjda
(Formatting is done in 2 steps; once to calculate values like this _action_max_length
, and a 2nd time to produce the actual output).
Subparsers are formatted with a recursive call to _format_action
, so I'm not optimistic about an easy fix.
Corrected formatter
Here's a patched Formatter that correctly accounts for the indenting of subactions (sub parsers). When an argument (action) is added to the Formatter, this function figures how wide its invocation strings are, and adjusts self._max_action_length. This is used latter to indent the help strings.
class MyFormatter(argparse.HelpFormatter):"""Corrected _max_action_length for the indenting of subactions"""def add_argument(self, action):if action.help is not argparse.SUPPRESS:# find all invocationsget_invocation = self._format_action_invocationinvocations = [get_invocation(action)]current_indent = self._current_indentfor subaction in self._iter_indented_subactions(action):# compensate for the indent that will be addedindent_chg = self._current_indent - current_indentadded_indent = 'x'*indent_chginvocations.append(added_indent+get_invocation(subaction))# print('inv', invocations)# update the maximum item lengthinvocation_length = max([len(s) for s in invocations])action_length = invocation_length + self._current_indentself._action_max_length = max(self._action_max_length,action_length)# add the item to the listself._add_item(self._format_action, [action])
An example of its use (without going real wide):
# call class with alternate parameters
formatter_class=lambda prog: MyFormatter(prog, max_help_position=40,width=100)parser = argparse.ArgumentParser(formatter_class=formatter_class)parser.add_argument('-l','--long', help='help after long option strings')subparsers = parser.add_subparsers(title="Commands", metavar="<command>")cmd_parser = subparsers.add_parser('long_long_cmd',help='longish command',formatter_class=formatter_class,aliases=['long', 'long_cmd'])# newer arpgarse take aliases
sht_parser = subparsers.add_parser('short', help = 'short cmd')args = parser.parse_args(['-h'])
which displays:
usage: issue25297.py [-h] [-l LONG] <command> ...optional arguments:-h, --help show this help message and exit-l LONG, --long LONG help after long option stringsCommands:<command>long_long_cmd (long, long_cmd) longish commandshort short cmd