Skip to content

Commit

Permalink
Add CliRunner default catch_exceptions parameter (#2818)
Browse files Browse the repository at this point in the history
Co-authored-by: Luke Kuzmish <42181698+cosmastech@users.noreply.github.com>
Co-authored-by: Andreas Backx <andreas@backx.org>
  • Loading branch information
3 people authored Dec 19, 2024
1 parent 5961d31 commit 88328fc
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ Unreleased
- Parameters cannot be required nor prompted or an error is raised.
- A warning will be printed when something deprecated is used.

- Add a ``catch_exceptions`` parameter to :class:`CliRunner`. If
``catch_exceptions`` is not passed to :meth:`CliRunner.invoke`,
the value from :class:`CliRunner`. :issue:`2817` :pr:`2818`

Version 8.1.8
-------------
Expand Down
15 changes: 13 additions & 2 deletions src/click/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ class CliRunner:
to `<stdout>`. This is useful for showing examples in
some circumstances. Note that regular prompts
will automatically echo the input.
:param catch_exceptions: Whether to catch any exceptions other than
``SystemExit`` when running :meth:`~CliRunner.invoke`.
.. versionchanged:: 8.2
Added the ``catch_exceptions`` parameter.
.. versionchanged:: 8.2
``mix_stderr`` parameter has been removed.
Expand All @@ -237,10 +242,12 @@ def __init__(
charset: str = "utf-8",
env: cabc.Mapping[str, str | None] | None = None,
echo_stdin: bool = False,
catch_exceptions: bool = True,
) -> None:
self.charset = charset
self.env: cabc.Mapping[str, str | None] = env or {}
self.echo_stdin = echo_stdin
self.catch_exceptions = catch_exceptions

def get_default_prog_name(self, cli: Command) -> str:
"""Given a command object it will return the default program name
Expand Down Expand Up @@ -410,7 +417,7 @@ def invoke(
args: str | cabc.Sequence[str] | None = None,
input: str | bytes | t.IO[t.Any] | None = None,
env: cabc.Mapping[str, str | None] | None = None,
catch_exceptions: bool = True,
catch_exceptions: bool | None = None,
color: bool = False,
**extra: t.Any,
) -> Result:
Expand All @@ -429,7 +436,8 @@ def invoke(
:param input: the input data for `sys.stdin`.
:param env: the environment overrides.
:param catch_exceptions: Whether to catch any other exceptions than
``SystemExit``.
``SystemExit``. If :data:`None`, the value
from :class:`CliRunner` is used.
:param extra: the keyword arguments to pass to :meth:`main`.
:param color: whether the output should contain color codes. The
application can still override this explicitly.
Expand Down Expand Up @@ -457,6 +465,9 @@ def invoke(
traceback if available.
"""
exc_info = None
if catch_exceptions is None:
catch_exceptions = self.catch_exceptions

with self.isolation(input=input, env=env, color=color) as outstreams:
return_value = None
exception: BaseException | None = None
Expand Down
22 changes: 22 additions & 0 deletions tests/test_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,28 @@ def cli():
assert result.exit_code == 1


def test_catch_exceptions_cli_runner():
"""Test that invoke `catch_exceptions` takes the value from CliRunner if not set
explicitly."""

class CustomError(Exception):
pass

@click.command()
def cli():
raise CustomError(1)

runner = CliRunner(catch_exceptions=False)

result = runner.invoke(cli, catch_exceptions=True)
assert isinstance(result.exception, CustomError)
assert type(result.exc_info) is tuple
assert len(result.exc_info) == 3

with pytest.raises(CustomError):
runner.invoke(cli)


def test_with_color():
@click.command()
def cli():
Expand Down

0 comments on commit 88328fc

Please sign in to comment.