homepage

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: argparse: choices override default metavar
Type: behavior Stage: resolved
Components: Documentation Versions: Python 3.10, Python 3.9
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: rhettinger Nosy List: bethard, cykerway, martin.panter, miss-islington, paul.j3, r.david.murray, rhettinger
Priority: normal Keywords: patch

Created on 2016年12月21日 00:52 by cykerway, last changed 2022年04月11日 14:58 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 23884 merged rhettinger, 2020年12月21日 23:26
PR 23894 merged miss-islington, 2020年12月22日 17:24
Messages (7)
msg283713 - (view) Author: Cyker Way (cykerway) * Date: 2016年12月21日 00:52
Using `choices` option in `argparse` module caused unwanted behavior.
# Without `choices`
 parser = argparse.ArgumentParser()
 parser.add_argument('length')
 parser.print_help()
## Output
 usage: demo.py [-h] length
 positional arguments:
 length
 optional arguments:
 -h, --help show this help message and exit
# With choices
 parser = argparse.ArgumentParser()
 parser.add_argument('length', choices=[1,2,3])
 parser.print_help()
## Output
 usage: demo.py [-h] {1,2,3}
 positional arguments:
 {1,2,3}
 optional arguments:
 -h, --help show this help message and exit
I think the doc says ArgumentParser objects use the `dest` value as the "name" of each object. And the doc doesn't mention anything about `dest` be changed by `choices`. The help text looks ugly when there is a long list of choices.
Currently the problem can be remedied by adding a `metavar` option. But I hope it will be fixed in the library itself.
msg283714 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2016年12月21日 01:37
metavar is, I believe, the intended way to change the default behavior. Whether or not this needs better documentation is a separate question :)
msg284858 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2017年01月06日 21:44
Here's the method in HelpFormatter that creates the metavar:
 def _metavar_formatter(self, action, default_metavar):
 if action.metavar is not None:
 result = action.metavar
 elif action.choices is not None:
 choice_strs = [str(choice) for choice in action.choices]
 result = '{%s}' % ','.join(choice_strs)
 else:
 result = default_metavar
 def format(tuple_size):
 if isinstance(result, tuple):
 return result
 else:
 return (result, ) * tuple_size
 return format
So in order of priority it uses: 
 the explicit metavar parameter
 formatted choices
 a default metavar (normally derived from the dest)
The MetavarTypeHelpFormatter subclass changes how that default is derived. In the same spirit, you could write your own Formatter subclass that changes the above method, and its priority order.
In your example, the use of choices in the 'usage' like looks good to me. I agree that its use in the 'help' line does not look so good. But don't forget that for your end user, the positional 'dest' (or name) has no value. Only you as the programmer sees and uses it.
This is one of many implementation details that could be included in the argparse docs. But for some users those docs are already too complex. The existing docs are not a formal module reference.
msg284874 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2017年01月06日 23:49
subparsers is an example of choices displaying as the metavar. From the documentation example:
usage: PROG [-h] [--foo] {a,b} ...
positional arguments:
 {a,b} sub-command help
-----------------
To the main parser, the 'subparser' is a positional argument, with an optional 'dest' parameter (default is SUPPRESS), and {a,b} are the choices derived from the define subparser names.
The 'title' and 'description' parameters are used to create an Argument_group.
So any attempt to change how the metavar is created from choices has the potential of changing the subparser display.
That does suggest another formatting option - put your positional argument (with choices) in a custom Argument_Group.
In [658]: p=argparse.ArgumentParser()
In [659]: g=p.add_argument_group(title='lengths')
In [660]: g.add_argument('length',choices=[1,2,3]);
In [661]: p.print_help()
usage: ipython3 [-h] {1,2,3}
optional arguments:
 -h, --help show this help message and exit
lengths:
 {1,2,3}
msg291405 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2017年04月10日 02:56
I think the documentation should be fixed to say choices overrides dest, and the implementation should be left alone. Even if the documentation is not a "formal module reference", it should not be wrong or misleading.
Also, Issue 14039 is related, about "metavar" with "add_subparsers".
msg383595 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2020年12月22日 17:24
New changeset 6afb730e2a8bf0b472b4c3157bcf5b44aa7e6d56 by Raymond Hettinger in branch 'master':
bpo-29030: Document interaction between *choices* and *metavar*. (GH-23884)
https://github.com/python/cpython/commit/6afb730e2a8bf0b472b4c3157bcf5b44aa7e6d56
msg383597 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2020年12月22日 18:19
New changeset 4ec2149708c7c06ebeccc27e28e2bbc51c4abeca by Miss Islington (bot) in branch '3.9':
bpo-29030: Document interaction between *choices* and *metavar*. (GH-23884) (GH-23894)
https://github.com/python/cpython/commit/4ec2149708c7c06ebeccc27e28e2bbc51c4abeca
History
Date User Action Args
2022年04月11日 14:58:40adminsetgithub: 73216
2020年12月22日 18:19:56rhettingersetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2020年12月22日 18:19:42rhettingersetmessages: + msg383597
2020年12月22日 17:24:45rhettingersetmessages: + msg383595
2020年12月22日 17:24:45miss-islingtonsetnosy: + miss-islington
pull_requests: + pull_request22749
2020年12月21日 23:38:08rhettingersettitle: argparse: choices override metavar -> argparse: choices override default metavar
2020年12月21日 23:26:32rhettingersetkeywords: + patch
stage: patch review
pull_requests: + pull_request22743
2020年12月19日 20:14:27rhettingersetcomponents: + Documentation, - Library (Lib)
versions: + Python 3.9, Python 3.10, - Python 2.7, Python 3.5
2019年08月30日 03:31:35rhettingersetassignee: bethard -> rhettinger

nosy: + rhettinger
2017年04月11日 02:14:40rhettingersetassignee: bethard

nosy: + bethard
2017年04月10日 02:56:09martin.pantersetnosy: + martin.panter

messages: + msg291405
versions: + Python 2.7
2017年01月06日 23:49:16paul.j3setmessages: + msg284874
2017年01月06日 21:44:59paul.j3setnosy: + paul.j3
messages: + msg284858
2016年12月21日 01:37:08r.david.murraysetnosy: + r.david.murray
messages: + msg283714
2016年12月21日 00:52:25cykerwaycreate

AltStyle によって変換されたページ (->オリジナル) /