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 assertion failure with brackets in metavars
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.7, Python 3.6, Python 3.4, Python 3.5, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: ncoghlan Nosy List: bethard, eric.araujo, htnieman, mZarjk, manveru, mattpr, miss-islington, ncoghlan, paul.j3, spaceone, vajrasky, wim.glenn, wolma, xuanji, ysj.ray
Priority: high Keywords: patch

Created on 2011年04月19日 08:20 by htnieman, last changed 2022年04月11日 14:57 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
issue_11874.diff ysj.ray, 2011年04月29日 09:06
unit_test_for_inner_bracket_metavar.txt vajrasky, 2013年07月14日 03:44 Unit test review
unit_test_argparse.txt vajrasky, 2013年07月14日 09:42 Revamped unit test review
fix_and_unit_test_for_argparse_inner_bracket_bug.txt vajrasky, 2013年07月14日 10:58 Fix and unit test for the argparse inner bracket metavar bug review
format_usage.patch paul.j3, 2014年04月24日 22:12 review
Pull Requests
URL Status Linked Edit
PR 1826 merged wim.glenn, 2017年05月27日 00:54
PR 7527 closed miss-islington, 2018年06月08日 10:14
PR 7528 merged miss-islington, 2018年06月08日 10:14
PR 7530 merged miss-islington, 2018年06月08日 11:11
PR 7553 merged miss-islington, 2018年06月09日 01:19
Messages (23)
msg134021 - (view) Author: Hartmut Niemann (htnieman) Date: 2011年04月19日 08:20
I run this script with option --help
-----8<------------------
import argparse
parser = argparse.ArgumentParser()
parser.add_argument ('--from-itm', dest="from_itm",action="store",default=None,help ="Source ITM file", metavar="ITMFILENAME")
parser.add_argument ("--from-fbm-sigtab",dest="from_sigtab",action="store",default=None,help="Source signal FB", metavar=" [LIB,]FBNAME")
parser.add_argument ("--c",dest="f",metavar="x]d")
args = parser.parse_args()
---------8<--------------------
and I get an assertion failure:
---------8<--------------------
D:\temp>argparsebug.py --help
Traceback (most recent call last):
 File "D:\temp\argparsebug.py", line 6, in <module>
 args = parser.parse_args()
 File "C:\Python27\lib\argparse.py", line 1678, in parse_args
 args, argv = self.parse_known_args(args, namespace)
 File "C:\Python27\lib\argparse.py", line 1710, in parse_known_args
 namespace, args = self._parse_known_args(args, namespace)
 File "C:\Python27\lib\argparse.py", line 1916, in _parse_known_args
 start_index = consume_optional(start_index)
 File "C:\Python27\lib\argparse.py", line 1856, in consume_optional
 take_action(action, args, option_string)
 File "C:\Python27\lib\argparse.py", line 1784, in take_action
 action(self, namespace, argument_values, option_string)
 File "C:\Python27\lib\argparse.py", line 993, in __call__
 parser.print_help()
 File "C:\Python27\lib\argparse.py", line 2303, in print_help
 self._print_message(self.format_help(), file)
 File "C:\Python27\lib\argparse.py", line 2277, in format_help
 return formatter.format_help()
 File "C:\Python27\lib\argparse.py", line 278, in format_help
 help = self._root_section.format_help()
 File "C:\Python27\lib\argparse.py", line 208, in format_help
 func(*args)
 File "C:\Python27\lib\argparse.py", line 329, in _format_usage
 assert ' '.join(opt_parts) == opt_usage
AssertionError
--------------8<-------------------------------
It must be the combination of several argument lines because when I 
comment out one of the add_arguments, it works.
Is this a bug or do I do things I shouln't?
If it is not allowed to use [] in metavars (what I wanted was metavar='[optional,]mantatory'), I' like to receive a readable error message.
With best regards
Hartmut Niemann
msg134558 - (view) Author: Manveru (manveru) Date: 2011年04月27日 12:41
I was a victim of the same issue, but only after my usage list does not fit in one line. Please fix!
msg134741 - (view) Author: ysj.ray (ysj.ray) Date: 2011年04月29日 09:06
Seem as a problem in optparse.HelpFormatter._format_usage(): when the generated usage string is too long(longer than 78, e.g.), python tries to break the usage string into parts at some proper positions and group them to multiple lines, then join the parts with space and assert it equal with original usage string. The regular expression used to break the usage string into parts is:
 """r'\(.*?\)+|\[.*?\]+|\S+'"""
So when there is '[]' in usage string, like in the example(there is '[]' in metavar), the assertion fails.
metavar="[LIB,]FBNAME" seems quite reasonable and usable, in the case that one want to define an option who has tow values and the first is optional. So I suggest '[]' should be allowed in metavar, and the _format_usage() needs fixed.
Here is a patch that fixes by changing the way breaking the usage string to parts and remove joining the parts and assert it equal to original usage string. Now the usage string is broken into intact each action of group usage strings. I think this breaking granularity is enough.
msg149547 - (view) Author: Steven Bethard (bethard) * (Python committer) Date: 2011年12月15日 12:42
I agree this is a bug. The patch needs to add unit tests that make sure metavars with [] work as expected.
msg193021 - (view) Author: Vajrasky Kok (vajrasky) * Date: 2013年07月14日 03:37
Attached the unit test.
Here is the simpler script to product the bug:
------------------------
import argparse
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument ('--a', metavar='a'*76)
parser.add_argument ('--b', metavar="[innerpart]outerpart")
parser.add_argument ('c', metavar='c'*76)
parser.add_argument ('d', metavar="[innerpart2]outerpart2")
args = parser.parse_args()
------------------------
python thefile.py --help
msg193022 - (view) Author: Vajrasky Kok (vajrasky) * Date: 2013年07月14日 03:44
Sorry, got typo in last unit test.
msg193042 - (view) Author: Vajrasky Kok (vajrasky) * Date: 2013年07月14日 09:42
Tidied up the unit test. Mixed with arguments without metavar.
msg193046 - (view) Author: Vajrasky Kok (vajrasky) * Date: 2013年07月14日 10:58
Attached the preliminary fix and the unit test for this ticket.
msg193068 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2013年07月14日 21:41
If the arg_parts are passed through the same cleanup as the 'text' (and empty strings removed), then 
 text = ' '.join(arg_parts)
In that case there would be no need to return both (text, arg_parts).
Parenthesis in the metavar could also create the problem addressed in this thread, except as noted in http://bugs.python.org/issue18349 that 'text' cleanup removes them.
nargs='*' or '+' or integer is another way in which [] could be introduced into the metavar.
msg193072 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2013年07月15日 03:58
I just filed a patch with http://bugs.python.org/issue10984 (argparse add_mutually_exclusive_group should accept existing arguments to register conflicts) that includes the latest patch from this issue. I tweaked it so _format_actions_usage only returns arg_parts. The block of _re. statements (# clean up separators for mutually exclusive groups) are in a nested function so it can be applied to each of the parts.
In that issue I wrote a custom formatter that handles groups even if they share actions, or the action order does not match definition order. For that it is easier to work with the arg_parts as generated here rather than the whole usage line.
msg193112 - (view) Author: Vajrasky Kok (vajrasky) * Date: 2013年07月15日 15:45
paul j3, thanks for reviewing my patch and giving me credit in your patch for another ticket.
Yeah, as you could see, the reason I return arg_parts and text is because the text still needs to undergo the cleanup process. You solved it by putting cleaning up in inner function.
I am thinking whether it is best to do "assert ' '.join(opt_parts) == opt_usage" inside _format_actions_usage helper function.
In that way, we can avoid returning the text. We can return only the arg_parts.
Anyway, my patch still got some unused variables, notably part_regexp and inner. My bad.
Let me check the code more deeply. See whether I can architect my patch in a better way. Maybe we can avoid building separate list inside _format_actions_usage.
Beside of that, this bug is not introduced solely by bracket character. It needs another non-space character on the right side of it.
This line is fine:
parser.add_argument ('--b', metavar="[innerpart] outerpart")
This line will fail the assertion:
parser.add_argument ('--b', metavar="[innerpart]outerpart")
msg193187 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2013年07月16日 20:26
Here's a patch that takes a different approach - rewrite _format_actions_usage() so it formats groups (and unattached actions) directly. 
It uses the same logic to determine when to format a group, but then it calls _format_group_usage() to format the group, without the error prone insert and cleanup business. And by keeping a list of the parts, it avoids the complications of parsing the text. The only cleanup regex removes () from single element groups.
In the nested get_lines function, I added 'line and' to 
 if line and line_len + 1 + len(part) > text_width:
so it does not create a blank line before an extra long entry (e.g. 'c'*76).
I'm using the _format_group_usage() and _format_just_actions_usage() in the Issue 10984 MultiGroupFormatter, just rearranging the logic in its _format_actions_usage() method. That patch could be rewritten to depend on this one.
This patch also fixes http://bugs.python.org/issue18349, since the metavar is never parsed.
msg216812 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2014年04月18日 22:09
Another example of code hitting this AssertionError. Here the problem was a space in the option argument, '--out '.
http://stackoverflow.com/questions/23159845/python-argparse-assertionerror
'parser.add_argument('-o', '--out ', help='b', required = True)'
That space would have cause problems later when trying access the 'args' attributes. But producing the error during the help formatting didn't help.
msg230187 - (view) Author: Wolfgang Maier (wolma) * Date: 2014年10月28日 23:16
It doesn't seem to be the exact same problem, but still this very simple example with parentheses in metavar fails to format correctly:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("inputfiles", metavar = 'input_file(s)', nargs = "+", help = 'one or more input files')
args = parser.parse_args()
-->
usage: -m [-h] input_files) [input_file(s ...]
positional arguments:
 input_file(s) one or more input files
optional arguments:
 -h, --help show this help message and exit
with the two occurences of input_file(s) being formatted wrong, but differently.
msg230198 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2014年10月29日 05:30
The patch with a major rewrite of '_format_actions_usage' handles this usage problem correctly:
 usage: try_para_in_meta.py [-h] input_file(s) [input_file(s) ...]
The error is the result of usage group formatter trying to remove excess `()`. To give an idea of what is happening I replaced the missing () with {}.
 input_file(s) [input_file(s) ...]
 input_file{s) [input_file(s} ...]
msg262105 - (view) Author: Matt Pr (mattpr) Date: 2016年03月21日 08:33
Same AssertionError is also caused by having certain "choices".
Python 2.7.10
global_options.add_argument('--field-sep', choices=[',',';','|','\t'], required=True, help='Field separator that separates columns in a row.')
Removing required=True or removing the tab (\t) from the options both work around this usage formatter issue for me.
I know this is an old issue but figured I would add another repro case to help whoever might work on this.
msg294575 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2017年05月27日 02:49
Any changes here including the latest pull request might conflict with
http://bugs.python.org/issue29553
Argparser does not display closing parentheses in nested mutex groups
If someone uses nested mutually exclusive groups (which I don't think they should, but anyways ...), the usage formatter gets confused by the nested brackets, and weeds out the wrong one(s).
That issue hasn't been settle yet; my feeling is that fixing this assertion error properly is more important.
msg295214 - (view) Author: wim glenn (wim.glenn) * Date: 2017年06月05日 22:02
May I ask, how to assign reviewers for CPython pull requests? https://github.com/python/cpython/pull/1826 has been sitting there for 10 days and the only comment was from a bot.
msg319041 - (view) Author: Alyssa Coghlan (ncoghlan) * (Python committer) Date: 2018年06月08日 10:12
New changeset 66f02aa32f1e4adb9f24cf186f8c495399d5ce9b by Nick Coghlan (wim glenn) in branch 'master':
bpo-11874: fix assertion failure in argparse metavar handling (GH-1826)
https://github.com/python/cpython/commit/66f02aa32f1e4adb9f24cf186f8c495399d5ce9b
msg319050 - (view) Author: miss-islington (miss-islington) Date: 2018年06月08日 11:06
New changeset 376c272d68cca0975ff0be3d12abf5f67da342d7 by Miss Islington (bot) in branch '3.6':
bpo-11874: fix assertion failure in argparse metavar handling (GH-1826)
https://github.com/python/cpython/commit/376c272d68cca0975ff0be3d12abf5f67da342d7
msg319054 - (view) Author: miss-islington (miss-islington) Date: 2018年06月08日 11:33
New changeset 842985f6c70484ed7b8fc30d0bc05aec73236a98 by Miss Islington (bot) in branch '3.7':
bpo-11874: fix assertion failure in argparse metavar handling (GH-1826)
https://github.com/python/cpython/commit/842985f6c70484ed7b8fc30d0bc05aec73236a98
msg319124 - (view) Author: Alyssa Coghlan (ncoghlan) * (Python committer) Date: 2018年06月09日 01:23
Thanks for the PR, and your patience!
The change has now been merged for all active 3.x versions.
It turns out the 2.7 argparse code is still close enough to the 3.x code for the automated backport to work, so the CI for that is currently running.
msg319127 - (view) Author: miss-islington (miss-islington) Date: 2018年06月09日 01:28
New changeset 4e6bd247aa955056626bf0cf8dc1c65a587b871f by Miss Islington (bot) in branch '2.7':
bpo-11874: fix assertion failure in argparse metavar handling (GH-1826)
https://github.com/python/cpython/commit/4e6bd247aa955056626bf0cf8dc1c65a587b871f
History
Date User Action Args
2022年04月11日 14:57:16adminsetgithub: 56083
2018年06月09日 10:53:29ncoghlansetstatus: open -> closed
stage: backport needed -> resolved
2018年06月09日 01:28:05miss-islingtonsetmessages: + msg319127
2018年06月09日 01:23:22ncoghlansetassignee: ncoghlan
resolution: fixed
messages: + msg319124
stage: patch review -> backport needed
2018年06月09日 01:19:24miss-islingtonsetpull_requests: + pull_request7185
2018年06月08日 11:33:53miss-islingtonsetmessages: + msg319054
2018年06月08日 11:11:23miss-islingtonsetpull_requests: + pull_request7166
2018年06月08日 11:06:01miss-islingtonsetnosy: + miss-islington
messages: + msg319050
2018年06月08日 10:14:59miss-islingtonsetpull_requests: + pull_request7160
2018年06月08日 10:14:00miss-islingtonsetpull_requests: + pull_request7156
2018年06月08日 10:12:52ncoghlansetnosy: + ncoghlan
messages: + msg319041
2017年09月14日 20:27:01wim.glennsetversions: + Python 3.6, Python 3.7
2017年06月05日 22:02:45wim.glennsetmessages: + msg295214
2017年05月30日 15:44:55wim.glennsetnosy: + wim.glenn
2017年05月27日 02:50:00paul.j3setmessages: + msg294575
2017年05月27日 00:54:04wim.glennsetpull_requests: + pull_request1912
2016年12月12日 19:17:31paul.j3setpriority: normal -> high
2016年03月21日 08:33:19mattprsetnosy: + mattpr
messages: + msg262105
2016年01月17日 06:32:01martin.panterlinkissue25058 superseder
2015年05月05日 21:08:44spaceonesetnosy: + spaceone
2015年05月05日 21:06:35ned.deilylinkissue24089 superseder
2015年05月05日 21:05:04ned.deilysetstage: patch review
versions: + Python 3.4, Python 3.5, - Python 3.2, Python 3.3
2014年10月30日 06:27:45tshepangsetnosy: - tshepang
2014年10月29日 05:30:38paul.j3setmessages: + msg230198
2014年10月28日 23:16:39wolmasetnosy: + wolma
messages: + msg230187
2014年09月09日 07:40:53mZarjksetnosy: + mZarjk
2014年04月24日 22:12:27paul.j3setfiles: - format_usage.patch
2014年04月24日 22:12:12paul.j3setfiles: + format_usage.patch
2014年04月18日 22:09:02paul.j3setmessages: + msg216812
2013年07月16日 20:26:25paul.j3setfiles: + format_usage.patch

messages: + msg193187
2013年07月15日 15:45:27vajraskysetmessages: + msg193112
2013年07月15日 03:58:39paul.j3setmessages: + msg193072
2013年07月14日 21:41:40paul.j3setmessages: + msg193068
2013年07月14日 10:58:15vajraskysetfiles: + fix_and_unit_test_for_argparse_inner_bracket_bug.txt

messages: + msg193046
2013年07月14日 09:42:30vajraskysetfiles: + unit_test_argparse.txt

messages: + msg193042
2013年07月14日 03:44:13vajraskysetfiles: + unit_test_for_inner_bracket_metavar.txt

messages: + msg193022
2013年07月14日 03:43:48vajraskysetfiles: - unit_test_for_inner_bracket_metavar.txt
2013年07月14日 03:37:45vajraskysetfiles: + unit_test_for_inner_bracket_metavar.txt
nosy: + vajrasky
messages: + msg193021

2013年07月13日 23:22:37paul.j3setnosy: + paul.j3
2012年03月18日 22:41:11tshepangsetnosy: + tshepang
2012年02月25日 10:33:25bethardlinkissue14046 superseder
2011年12月15日 12:42:30bethardsetmessages: + msg149547
2011年04月29日 09:14:52ysj.raysetcomponents: + Library (Lib), - None
2011年04月29日 09:06:43ysj.raysetfiles: + issue_11874.diff

nosy: + ysj.ray
messages: + msg134741

keywords: + patch
2011年04月27日 15:28:16xuanjisetnosy: + xuanji
2011年04月27日 12:41:50manverusetnosy: + manveru
messages: + msg134558
2011年04月22日 16:53:49eric.araujosetnosy: + bethard, eric.araujo

versions: + Python 3.2, Python 3.3
2011年04月19日 08:20:50htniemancreate

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