Merge "Usage String has Positionals after Optionals"
This commit is contained in:
@@ -35,10 +35,9 @@ import six
|
||||
|
||||
import troveclient
|
||||
from troveclient import client
|
||||
#from troveclient import exceptions as exc
|
||||
#import troveclient.extension
|
||||
from troveclient.openstack.common import strutils
|
||||
from troveclient.openstack.common.apiclient import exceptions as exc
|
||||
from troveclient.openstack.common.gettextutils import _
|
||||
from troveclient import utils
|
||||
from troveclient.v1 import shell as shell_v1
|
||||
|
||||
@@ -525,6 +524,106 @@ class OpenStackHelpFormatter(argparse.HelpFormatter):
|
||||
heading = '%s%s' % (heading[0].upper(), heading[1:])
|
||||
super(OpenStackHelpFormatter, self).start_section(heading)
|
||||
|
||||
def _format_usage(self, usage, actions, groups, prefix):
|
||||
"""
|
||||
Print positionals before optionals in the usage string to help
|
||||
users avoid argparse nargs='*' problems.
|
||||
|
||||
ex: 'trove create --databases <db_name> <name> <flavor_id>'
|
||||
fails with 'error: too few arguments', but this succeeds:
|
||||
'trove create <name> <flavor_id> --databases <db_name>'
|
||||
"""
|
||||
if prefix is None:
|
||||
prefix = _('usage: ')
|
||||
|
||||
# if usage is specified, use that
|
||||
if usage is not None:
|
||||
usage = usage % dict(prog=self._prog)
|
||||
|
||||
# if no optionals or positionals are available, usage is just prog
|
||||
elif usage is None and not actions:
|
||||
usage = '%(prog)s' % dict(prog=self._prog)
|
||||
|
||||
# if optionals and positionals are available, calculate usage
|
||||
elif usage is None:
|
||||
prog = '%(prog)s' % dict(prog=self._prog)
|
||||
|
||||
# split optionals from positionals
|
||||
optionals = []
|
||||
positionals = []
|
||||
for action in actions:
|
||||
if action.option_strings:
|
||||
optionals.append(action)
|
||||
else:
|
||||
positionals.append(action)
|
||||
|
||||
# build full usage string
|
||||
format = self._format_actions_usage
|
||||
action_usage = format(optionals + positionals, groups)
|
||||
usage = ' '.join([s for s in [prog, action_usage] if s])
|
||||
|
||||
# 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 = argparse._re.findall(part_regexp, opt_usage)
|
||||
pos_parts = argparse._re.findall(part_regexp, pos_usage)
|
||||
assert ' '.join(opt_parts) == opt_usage
|
||||
assert ' '.join(pos_parts) == pos_usage
|
||||
|
||||
# helper for wrapping lines
|
||||
def get_lines(parts, indent, prefix=None):
|
||||
lines = []
|
||||
line = []
|
||||
if prefix is not None:
|
||||
line_len = len(prefix) - 1
|
||||
else:
|
||||
line_len = len(indent) - 1
|
||||
for part in parts:
|
||||
if line_len + 1 + len(part) > text_width:
|
||||
lines.append(indent + ' '.join(line))
|
||||
line = []
|
||||
line_len = len(indent) - 1
|
||||
line.append(part)
|
||||
line_len += len(part) + 1
|
||||
if line:
|
||||
lines.append(indent + ' '.join(line))
|
||||
if prefix is not None:
|
||||
lines[0] = lines[0][len(indent):]
|
||||
return lines
|
||||
|
||||
# if prog is short, follow it with optionals or positionals
|
||||
if len(prefix) + len(prog) <= 0.75 * text_width:
|
||||
indent = ' ' * (len(prefix) + len(prog) + 1)
|
||||
if pos_parts:
|
||||
lines = get_lines([prog] + pos_parts, indent, prefix)
|
||||
lines.extend(get_lines(opt_parts, indent))
|
||||
elif opt_parts:
|
||||
lines = get_lines([prog] + opt_parts, indent, prefix)
|
||||
else:
|
||||
lines = [prog]
|
||||
|
||||
# if prog is long, put it on its own line
|
||||
else:
|
||||
indent = ' ' * len(prefix)
|
||||
parts = pos_parts + opt_parts
|
||||
lines = get_lines(parts, indent)
|
||||
if len(lines) > 1:
|
||||
lines = []
|
||||
lines.extend(get_lines(pos_parts, indent))
|
||||
lines.extend(get_lines(opt_parts, indent))
|
||||
lines = [prog] + lines
|
||||
|
||||
# join lines into usage
|
||||
usage = '\n'.join(lines)
|
||||
|
||||
# prefix with 'usage:'
|
||||
return '%s%s\n\n' % (prefix, usage)
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
|
Reference in New Issue
Block a user