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 if optional argument has square/round brackets in metavar
Type: behavior Stage:
Components: Library (Lib) Versions: Python 2.7
process
Status: closed Resolution: duplicate
Dependencies: Superseder: argparse assertion failure with brackets in metavars
View: 11874
Assigned To: Nosy List: John Jones, bethard, miss-islington, ncoghlan, oxplot, paul.j3
Priority: normal Keywords:

Created on 2012-02-18 05:21 by oxplot, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
argparse_wrap_test.py oxplot, 2012-02-18 05:21 Test which causes assertion failure.
Pull Requests
URL Status Linked Edit
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 (7)
msg153632 - (view) Author: Mansour (oxplot) Date: 2012-02-18 05:21
I have a web server written in python which takes an optional argument telling it what IP and port to bind to. Here's the definition:

parser.add_argument(
  '-b', '--bind',
  metavar="[ip]:port",
  type=unicode,
  help="IP and port to bind to."
)

There are several other arguments as well. When the usage is printed (due to parse failures or -h), if the command line is longer than terminal width, it is wrapped. Here is the (relevant) code in argparse.py:311 which deals with this scenario:

# wrap the usage parts if it's too long
text_width = self._width - self._current_indent 
if len(prefix) + len(usage) > text_width: 
 
  # break usage into wrappable parts 
  part_regexp = r'\(.*?\)+|\[.*?\]+|\S+' 
  opt_usage = format(optionals, groups) 
  pos_usage = format(positionals, groups) 
  opt_parts = _re.findall(part_regexp, opt_usage) 
  pos_parts = _re.findall(part_regexp, pos_usage) 
  assert ' '.join(opt_parts) == opt_usage
  assert ' '.join(pos_parts) == pos_usage

Note how part_regexp extracts words, and text surrounded with round/square brackets. Now the argument I defined above, when displayed in usage text, looks like this: [-b [ip]:port]

part_regexp however, will cut it into "[-b [ip]" and ":port]" and concatenated later with " ", it will have an extra space which causes the first assertion to fail.

I fiddled with part_regexp but that proved unreliable at best. I think the opt_parts should be obtained, not from the final formatted text, but from actual argument objects.

For a demonstration, see the attachment.
msg154234 - (view) Author: Steven Bethard (bethard) * (Python committer) Date: 2012-02-25 10:33
Yes, this is a known bug (Issue 11874). Patches welcome.
msg245970 - (view) Author: John Jones (John Jones) Date: 2015-06-29 21:17
Im kind of surprised this bug has lasted for so many years :)

setting part_regexp to:
r'\(.*?\(.*?\).*?\)+|\[.*?\[.*?\].*?\]+|\S+'
fixes the issue for me, although its not very elegant
msg319040 - (view) Author: Nick 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
msg319049 - (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
msg319053 - (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
msg319126 - (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:26adminsetgithub: 58254
2018-06-09 01:28:05miss-islingtonsetmessages: + msg319126
2018-06-09 01:19:25miss-islingtonsetpull_requests: + pull_request7187
2018-06-08 11:33:53miss-islingtonsetmessages: + msg319053
2018-06-08 11:11:23miss-islingtonsetpull_requests: + pull_request7168
2018-06-08 11:06:01miss-islingtonsetnosy: + miss-islington
messages: + msg319049
2018-06-08 10:14:59miss-islingtonsetpull_requests: + pull_request7162
2018-06-08 10:14:00miss-islingtonsetpull_requests: + pull_request7158
2018-06-08 10:12:52ncoghlansetnosy: + ncoghlan
messages: + msg319040
2016-01-17 06:20:12martin.pantersetstatus: open -> closed
type: crash -> behavior
2015-06-29 21:17:57John Jonessetnosy: + John Jones
messages: + msg245970
2013-05-13 02:29:06paul.j3setnosy: + paul.j3
2012-02-25 10:33:25bethardsetresolution: duplicate
superseder: argparse assertion failure with brackets in metavars
messages: + msg154234
2012-02-24 22:41:31terry.reedysetnosy: + bethard
2012-02-18 05:21:48oxplotcreate