Skip to content

Commit

Permalink
Merge pull request #709 from sirosen/bugfix/error-hints/let-param-decide
Browse files Browse the repository at this point in the history
Derive "param_hint" in errors from param itself
  • Loading branch information
LokiHokie committed May 14, 2018
2 parents 9c456ec + f99c8d5 commit 3cb9973
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 12 deletions.
10 changes: 10 additions & 0 deletions click/core.py
Expand Up @@ -1431,6 +1431,13 @@ def get_help_record(self, ctx):
def get_usage_pieces(self, ctx):
return []

def get_error_hint(self, ctx):
"""Get a stringified version of the param for use in error messages to
indicate which param caused the error.
"""
hint_list = self.opts or [self.human_readable_name]
return ' / '.join('"%s"' % x for x in hint_list)


class Option(Parameter):
"""Options are usually optional values on the command line and
Expand Down Expand Up @@ -1755,6 +1762,9 @@ def _parse_decls(self, decls, expose_value):
def get_usage_pieces(self, ctx):
return [self.make_metavar()]

def get_error_hint(self, ctx):
return '"%s"' % self.make_metavar()

def add_to_parser(self, parser, ctx):
parser.add_argument(dest=self.name, nargs=self.nargs,
obj=self)
Expand Down
17 changes: 11 additions & 6 deletions click/exceptions.py
Expand Up @@ -2,6 +2,12 @@
from .utils import echo


def _join_param_hints(param_hint):
if isinstance(param_hint, (tuple, list)):
return ' / '.join('"%s"' % x for x in param_hint)
return param_hint


class ClickException(Exception):
"""An exception that Click can handle and show to the user."""

Expand Down Expand Up @@ -92,11 +98,11 @@ def format_message(self):
if self.param_hint is not None:
param_hint = self.param_hint
elif self.param is not None:
param_hint = self.param.opts or [self.param.human_readable_name]
param_hint = self.param.get_error_hint(self.ctx)
else:
return 'Invalid value: %s' % self.message
if isinstance(param_hint, (tuple, list)):
param_hint = ' / '.join('"%s"' % x for x in param_hint)
param_hint = _join_param_hints(param_hint)

return 'Invalid value for %s: %s' % (param_hint, self.message)


Expand All @@ -121,11 +127,10 @@ def format_message(self):
if self.param_hint is not None:
param_hint = self.param_hint
elif self.param is not None:
param_hint = self.param.opts or [self.param.human_readable_name]
param_hint = self.param.get_error_hint(self.ctx)
else:
param_hint = None
if isinstance(param_hint, (tuple, list)):
param_hint = ' / '.join('"%s"' % x for x in param_hint)
param_hint = _join_param_hints(param_hint)

param_type = self.param_type
if param_type is None and self.param is not None:
Expand Down
4 changes: 2 additions & 2 deletions tests/test_arguments.py
Expand Up @@ -188,7 +188,7 @@ def cmd2(arg):

result = runner.invoke(cmd2, [])
assert result.exit_code == 2
assert 'Missing argument "arg"' in result.output
assert 'Missing argument "ARG..."' in result.output


def test_missing_arg(runner):
Expand All @@ -199,7 +199,7 @@ def cmd(arg):

result = runner.invoke(cmd, [])
assert result.exit_code == 2
assert 'Missing argument "arg".' in result.output
assert 'Missing argument "ARG".' in result.output


def test_implicit_non_required(runner):
Expand Down
44 changes: 40 additions & 4 deletions tests/test_formatting.py
Expand Up @@ -159,7 +159,43 @@ def cmd(arg):
'Usage: cmd [OPTIONS] ARG',
'Try "cmd --help" for help.',
'',
'Error: Missing argument "arg".'
'Error: Missing argument "ARG".'
]


def test_formatting_usage_error_metavar_missing_arg(runner):
"""
:author: @r-m-n
Including attribution to #612
"""
@click.command()
@click.argument('arg', metavar='metavar')
def cmd(arg):
pass

result = runner.invoke(cmd, [])
assert result.exit_code == 2
assert result.output.splitlines() == [
'Usage: cmd [OPTIONS] metavar',
'Try "cmd --help" for help.',
'',
'Error: Missing argument "metavar".'
]


def test_formatting_usage_error_metavar_bad_arg(runner):
@click.command()
@click.argument('arg', type=click.INT, metavar='metavar')
def cmd(arg):
pass

result = runner.invoke(cmd, ['3.14'])
assert result.exit_code == 2
assert result.output.splitlines() == [
'Usage: cmd [OPTIONS] metavar',
'Try "cmd --help" for help.',
'',
'Error: Invalid value for "metavar": 3.14 is not a valid integer'
]


Expand All @@ -179,7 +215,7 @@ def foo(bar):
'Usage: cmd foo [OPTIONS] BAR',
'Try "cmd foo --help" for help.',
'',
'Error: Missing argument "bar".'
'Error: Missing argument "BAR".'
]


Expand All @@ -194,7 +230,7 @@ def cmd(arg):
assert result.output.splitlines() == [
'Usage: cmd [OPTIONS] ARG',
'',
'Error: Missing argument "arg".'
'Error: Missing argument "ARG".'
]


Expand All @@ -210,5 +246,5 @@ def cmd(arg):
'Usage: cmd [OPTIONS] ARG',
'Try "cmd --man" for help.',
'',
'Error: Missing argument "arg".'
'Error: Missing argument "ARG".'
]

0 comments on commit 3cb9973

Please sign in to comment.