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.

Title: argparse usage should preserve () in metavars such as range(20)
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.11, Python 3.10, Python 3.9
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: iritkatriel, paul.j3
Priority: normal Keywords: patch

Created on 2013-07-03 06:16 by paul.j3, last changed 2022-04-11 14:57 by admin.

File name Uploaded Description Edit
metaparen.patch paul.j3, 2013-07-03 06:16 review
Messages (5)
msg192222 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2013-07-03 06:16
As discussed in issue 16468, a metavar may be used to provide an alternative representation of a choices option.  However if a metvar like 'range(20)' is used, usage formatter strips off the '()'.

    >>> parser.add_argument('foo', type=int, 
        choices=range(20), metavar='range(0,20)')
    >>> parser.format_usage()
    # expect: 'usage: PROG [-h] range(0,20)\n'
    # actual: 'usage: PROG [-h] range0,20\n'

This is done by a line in the help formater that removes excess mutually exclusive group notation:

       text = _re.sub(r'\(([^|]*)\)', r'\1', text)

A solution is to change this line to distinguish between a case like ' (...)' and 'range(...)'

    text = _re.sub(r'( )\(([^|]*)\)', r'\1\2', text)
msg192717 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2013-07-09 03:08
I just posted a patch to that uses (and tests) this fix.
msg193077 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2013-07-15 07:15
This issue should also preserve a metavar like: '(one)two', i.e. '(' at the start.  

In these _re replacements are applied to individual action strings as well as the whole usage line.  So if () are to be removed from '[-h] (-y)', they should also be removed from '(-y)'.
msg193188 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2013-07-16 20:34
I just submitted at patch to that takes care of this issue as well.

I rewrote _format_actions_usage() so it formats the parts directly, so there is no need cleanup or parse the full text string.
msg408214 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2021-12-10 15:48
Reproduced on 3.11:

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('foo', type=int, choices=range(20), metavar='range(0,20)')
_StoreAction(option_strings=[], dest='foo', nargs=None, const=None, default=None, type=<class 'int'>, choices=range(0, 20), help=None, metavar='range(0,20)')
>>> parser.format_usage()
'usage: [-h] range0,20\n'
Date User Action Args
2022-04-11 14:57:47adminsetgithub: 62549
2021-12-10 15:48:45iritkatrielsetnosy: + iritkatriel

messages: + msg408214
versions: + Python 3.9, Python 3.10, Python 3.11, - Python 3.4
2013-07-16 20:34:49paul.j3setmessages: + msg193188
2013-07-15 07:15:36paul.j3setmessages: + msg193077
2013-07-09 03:08:49paul.j3setmessages: + msg192717
2013-07-03 06:19:39paul.j3settype: behavior
components: + Library (Lib)
versions: + Python 3.4
2013-07-03 06:16:51paul.j3create