Skip to content

Commit

Permalink
Help shown via no_args_is_help results in exit code 2, was 0 (pallets…
Browse files Browse the repository at this point in the history
…#1489)

Co-authored-by: David Lord <[email protected]>
Co-authored-by: Andreas Backx <[email protected]>
  • Loading branch information
3 people authored Nov 3, 2024
1 parent 4271fe2 commit d8763b9
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 13 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ Unreleased
:issue:`2746` :pr:`2788`
- Add ``Choice.get_invalid_choice_message`` method for customizing the
invalid choice message. :issue:`2621` :pr:`2622`
- If help is shown because ``no_args_is_help`` is enabled (defaults to ``True``
for groups, ``False`` for commands), the exit code is 2 instead of 0.
:issue:`1489` :pr:`1489`


Version 8.1.8
Expand Down
9 changes: 4 additions & 5 deletions src/click/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from .exceptions import ClickException
from .exceptions import Exit
from .exceptions import MissingParameter
from .exceptions import NoArgsIsHelpError
from .exceptions import UsageError
from .formatting import HelpFormatter
from .formatting import join_options
Expand Down Expand Up @@ -1156,8 +1157,7 @@ def make_context(

def parse_args(self, ctx: Context, args: list[str]) -> list[str]:
if not args and self.no_args_is_help and not ctx.resilient_parsing:
echo(ctx.get_help(), color=ctx.color)
ctx.exit()
raise NoArgsIsHelpError(ctx)

parser = self.make_parser(ctx)
opts, args, param_order = parser.parse_args(args=args)
Expand Down Expand Up @@ -1747,8 +1747,7 @@ def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None:

def parse_args(self, ctx: Context, args: list[str]) -> list[str]:
if not args and self.no_args_is_help and not ctx.resilient_parsing:
echo(ctx.get_help(), color=ctx.color)
ctx.exit()
raise NoArgsIsHelpError(ctx)

rest = super().parse_args(ctx, args)

Expand Down Expand Up @@ -1851,7 +1850,7 @@ def resolve_command(
# place.
if cmd is None and not ctx.resilient_parsing:
if _split_opt(cmd_name)[0]:
self.parse_args(ctx, ctx.args)
self.parse_args(ctx, args)
ctx.fail(_("No such command {name!r}.").format(name=original_cmd_name))
return cmd_name if cmd else None, cmd, args[1:]

Expand Down
9 changes: 9 additions & 0 deletions src/click/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,15 @@ class BadArgumentUsage(UsageError):
"""


class NoArgsIsHelpError(UsageError):
def __init__(self, ctx: Context) -> None:
self.ctx: Context
super().__init__(ctx.get_help(), ctx=ctx)

def show(self, file: t.IO[t.Any] | None = None) -> None:
echo(self.format_message(), file=file, err=True, color=self.ctx.color)


class FileError(ClickException):
"""Raised if a file cannot be opened."""

Expand Down
12 changes: 4 additions & 8 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,9 @@ def long():
)


def test_no_args_is_help(runner):
@click.command(no_args_is_help=True)
def cli():
pass

result = runner.invoke(cli, [])
assert result.exit_code == 0
def test_command_no_args_is_help(runner):
result = runner.invoke(click.Command("test", no_args_is_help=True))
assert result.exit_code == 2
assert "Show this message and exit." in result.output


Expand All @@ -127,7 +123,7 @@ def foo(name):
(["obj1"], 2, "Error: Missing command."),
(["obj1", "--help"], 0, "Show this message and exit."),
(["obj1", "move"], 0, "obj=obj1\nmove\n"),
([], 0, "Show this message and exit."),
([], 2, "Show this message and exit."),
],
)
def test_group_with_args(runner, args, exit_code, expect):
Expand Down

0 comments on commit d8763b9

Please sign in to comment.