classification
Title: Improve text for file arguments in argparse.ArgumentDefaultsHelpFormatter class
Type: Stage: resolved
Components: Library (Lib) Versions: Python 3.8, Python 3.7, Python 3.6, Python 3.4, Python 3.5
process
Status: closed Resolution: duplicate
Dependencies: Superseder:
Assigned To: Nosy List: elypter, paul.j3
Priority: normal Keywords:

Created on 2018-01-15 00:35 by elypter, last changed 2018-09-30 06:15 by paul.j3. This issue is now closed.

Messages (4)
msg309940 - (view) Author: elypter (elypter) Date: 2018-01-15 00:35
If you use formatter_class=argparse.ArgumentDefaultsHelpFormatter in the constructor then the defaults that you include in arguments get automatically added to the help text. this looks great for int and Strings but not for files.

example:
  -suffixes [SUFFIXES]
                        suffixes file which contains keywords that are often
                        the last part of a class or style name of a sticky bar
                        (default: <open file 'sources/suffixes.txt', mode 'r'
                        at 0xb71385f8>)

it should rather look like

  -suffixes [SUFFIXES]
                        suffixes file which contains keywords that are often
                        the last part of a class or style name of a sticky bar
                        (default:'sources/suffixes.txt')


the same holds probably true for more exotic datatypes. so an alternative or an addition could be to add an option to arguments to not add the default to the help text
msg315713 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2018-04-24 19:05
This subclass makes are one method change:

from:

    def _get_help_string(self, action):
        return action.help

to:

    def _get_help_string(self, action):
        help = action.help
        if '%(default)' not in action.help:
            if action.default is not SUPPRESS:
                defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
                if action.option_strings or action.nargs in defaulting_nargs:
                    help += ' (default: %(default)s)'
        return help

So it conditionally adds a '%(default)s' to the help string.  

And in:

    def _expand_help(self, action):
       ...
       return self._get_help_string(action) % params

where 'params' is derived from the attributes of the 'Action' object.

I don't off hand see a clean way of suppressing this addition.  We don't want to add a parameter to 'add_argument' just for this.

As a user you can explicitly add the `%(default)s` to selected arguments, and use the regular formatter.  Admittedly it involves a bit more typing.

Or write your own version of the formatter subclass.
msg326596 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2018-09-27 21:11
An alternative to customizing a HelpFormatter is to write your own utility `add_argument` function, e.g.

def my_add_argument(parser, *args, add_default=True, **kwargs):
    if add_default:
        help = kwargs.get('help','')
        help += ' (default: %(default)s)'
        kwargs['help'] = help
    return parser.add_argument(*args, **kwargs)

which could be used as

my_add_argument(parser, '-g', help='bar help', default='other', add_default=False)

There are some refinements to the _get_help_string() that I showed earlier, such as only adding the '%s' to actions where default makes sense (optionals and a subset positionals).  One could also skip it if the default is the default default None, etc.

One way or other the user can already control whether the help line shows the default.  ArgumentDefaultsHelpFormatter just automates this for a straight forward parser.  

I'm going to close this issue since it isn't really needed (and no one has proposed a clever patch).
msg326705 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2018-09-30 06:15
https://bugs.python.org/issue28742
argparse.ArgumentDefaultsHelpFormatter sometimes provides inaccurate documentation of defaults, so they should be overrideable

is asking for something similar - the ability to override the automatic `%(default)s` in certain cases.

The proposed fix is to look for a string that is already displaying a default, such as '(default:'.

    if '%(default)' not in action.help and '(default:' not in action.help:
History
Date User Action Args
2018-09-30 06:15:41paul.j3setresolution: rejected -> duplicate
messages: + msg326705
2018-09-27 21:11:14paul.j3setstatus: open -> closed
resolution: rejected
messages: + msg326596

stage: resolved
2018-04-24 19:05:46paul.j3setnosy: + paul.j3
messages: + msg315713
2018-01-15 00:35:36elyptercreate