This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Improve argparse usage/help customization
Type: enhancement Stage: needs patch
Components: Library (Lib) Versions: Python 3.5, Python 2.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: berker.peksag, bethard, chris.jerdonek, jcon, paul.j3, petri.lehtinen
Priority: normal Keywords: patch

Created on 2011-03-27 14:05 by bethard, last changed 2022-04-11 14:57 by admin.

Files
File name Uploaded Description Edit
issue11695_1.patch paul.j3, 2014-06-20 21:11 review
Messages (5)
msg132322 - (view) Author: Steven Bethard (bethard) * (Python committer) Date: 2011-03-27 14:05
I'm going to try to merge several closely related issues here. Basically, people would like better control over the usage message formatting so that you could:

* Put program name and version information at the top of the message
* Customize the "usage:" string (e.g. capitalize it)

One proposal from anatoly techtonik would be to allow a format string so that you could write something like

"""My Program, version 3.5
Usage: %(usage)s

Some description of my program

%(argument_groups)%

My epliog text
"""

This should be implemented as a HelpFormatter class, but we might have to expose a little more of the HelpFormatter API (which is currently documented as a no-public API) to make this possible.

Patches welcome. ;-)
msg179522 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2013-01-10 05:10
+1 to the feature.

A closely-related use case is customizing the message displayed by error(), which is normally the usage string followed by the error message.  I wanted to append instructions on how to invoke --help, and implemented it this way for CPython's regrtest:

http://hg.python.org/cpython/file/6ee721029fd5/Lib/test/regrtest.py#l205

Also take a look at how regrtest formats its usage string as another use case to satisfy:

http://hg.python.org/cpython/file/6ee721029fd5/Lib/test/regrtest.py#l9

It seems like many argparse customizations take the form of "override this method."  Would it make sense for the API to be for customizers to override string-returning methods like make_usage() and make_error() (and that accept a dictionary)?  That may give a bit more control than a format string.
msg221063 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2014-06-20 03:09
Here's a function that implements the format string:

    def custom_help(template):
        def usage(self):
            formatter = self._get_formatter()
            formatter.add_usage(self.usage, self._actions,
                self._mutually_exclusive_groups, prefix='')
            return formatter.format_help().strip()
        def groups(self):
            formatter = self._get_formatter()
            for action_group in self._action_groups:
                 formatter.start_section(action_group.title)
                 formatter.add_text(action_group.description)
                 formatter.add_arguments(action_group._group_actions)
                 formatter.end_section()
            astr = formatter.format_help().rstrip()
            return astr
        dd = dict(
            usage=usage(parser),
            argument_groups=groups(parser),
            )
        return template%dd

     template = """My Program, version 3.5
     Usage: %(usage)s

     Some description of my program

     %(argument_groups)s

     My epilog text
     """
     print(custom_help(template))

This replaces 'parser.format_help' rather than the 'HelpFormatter' class.  It in effect uses pieces from 'format_help' to format strings like 'usage', and plugs those into the template.

While a template based formatter could be implemented as Formatter subclass, it seems to be an awkward fit.  In the current structure, the 'parser' method determines the overall layout of 'help', while the 'formatter' generates the pieces.  The proposed template deals with the layout, not the pieces.

'format_help' could cast into this form, using a default template.  

Possible generalization include:
- methods to format other parts of the help
- handling of multiline indented blocks
- utilizing other templating tools (string.Template, Py3 format, Mako)
msg221123 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2014-06-20 21:11
This patch has a 'custom_help' which, with a default template, is compatible with 'format_help' (i.e. it passes test_argparse).  It also handles the sample template in this issue.

Due to long line wrapping issues, the 'Usage: ' string the test template has to be entered separately as a usage 'prefix'.  Indenting of long wrapped values (like usage) is correct only if the '%(...)s' string is at the start of a line.

I see this as a test-of-concept patch.
msg221187 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2014-06-21 19:01
That original template can also be implemented with a customized 'format_help':

    def custom_help(self):
        formatter = self._get_formatter()
        formatter.add_text('My Program, version 3.5')
        formatter.add_usage(self.usage, self._actions,
                        self._mutually_exclusive_groups,
                        prefix='Usage: ')
        formatter.add_text('Some description of my program')
        for action_group in self._action_groups:
            with formatter.add_section(action_group.title):
                formatter.add_text(action_group.description)
                formatter.add_arguments(action_group._group_actions)
        formatter.add_text('My epilog text')
        return formatter.format_help()
History
Date User Action Args
2022-04-11 14:57:15adminsetgithub: 55904
2014-06-21 19:01:31paul.j3setmessages: + msg221187
2014-06-20 21:11:57paul.j3setfiles: + issue11695_1.patch
keywords: + patch
messages: + msg221123
2014-06-20 03:09:55paul.j3setmessages: + msg221063
2014-06-16 22:39:57BreamoreBoysetnosy: + paul.j3

versions: + Python 2.7, Python 3.5, - Python 3.3
2013-01-10 05:10:57chris.jerdoneksetnosy: + chris.jerdonek
messages: + msg179522
2013-01-10 04:41:26jconsetnosy: + jcon
2012-01-16 22:01:45berker.peksagsetnosy: + berker.peksag
2011-06-21 12:23:59petri.lehtinensetnosy: + petri.lehtinen
2011-03-27 14:23:07bethardlinkissue9653 superseder
2011-03-27 14:09:31bethardlinkissue9652 superseder
2011-03-27 14:07:05bethardlinkissue7284 superseder
2011-03-27 14:05:43bethardcreate