Skip to content

Commit 88328fc

Browse files
azmeukcosmastechAndreasBackx
authored
Add CliRunner default catch_exceptions parameter (pallets#2818)
Co-authored-by: Luke Kuzmish <[email protected]> Co-authored-by: Andreas Backx <[email protected]>
1 parent 5961d31 commit 88328fc

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

CHANGES.rst

+3
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ Unreleased
8888
- Parameters cannot be required nor prompted or an error is raised.
8989
- A warning will be printed when something deprecated is used.
9090

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

9295
Version 8.1.8
9396
-------------

src/click/testing.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,11 @@ class CliRunner:
227227
to `<stdout>`. This is useful for showing examples in
228228
some circumstances. Note that regular prompts
229229
will automatically echo the input.
230+
:param catch_exceptions: Whether to catch any exceptions other than
231+
``SystemExit`` when running :meth:`~CliRunner.invoke`.
232+
233+
.. versionchanged:: 8.2
234+
Added the ``catch_exceptions`` parameter.
230235
231236
.. versionchanged:: 8.2
232237
``mix_stderr`` parameter has been removed.
@@ -237,10 +242,12 @@ def __init__(
237242
charset: str = "utf-8",
238243
env: cabc.Mapping[str, str | None] | None = None,
239244
echo_stdin: bool = False,
245+
catch_exceptions: bool = True,
240246
) -> None:
241247
self.charset = charset
242248
self.env: cabc.Mapping[str, str | None] = env or {}
243249
self.echo_stdin = echo_stdin
250+
self.catch_exceptions = catch_exceptions
244251

245252
def get_default_prog_name(self, cli: Command) -> str:
246253
"""Given a command object it will return the default program name
@@ -410,7 +417,7 @@ def invoke(
410417
args: str | cabc.Sequence[str] | None = None,
411418
input: str | bytes | t.IO[t.Any] | None = None,
412419
env: cabc.Mapping[str, str | None] | None = None,
413-
catch_exceptions: bool = True,
420+
catch_exceptions: bool | None = None,
414421
color: bool = False,
415422
**extra: t.Any,
416423
) -> Result:
@@ -429,7 +436,8 @@ def invoke(
429436
:param input: the input data for `sys.stdin`.
430437
:param env: the environment overrides.
431438
:param catch_exceptions: Whether to catch any other exceptions than
432-
``SystemExit``.
439+
``SystemExit``. If :data:`None`, the value
440+
from :class:`CliRunner` is used.
433441
:param extra: the keyword arguments to pass to :meth:`main`.
434442
:param color: whether the output should contain color codes. The
435443
application can still override this explicitly.
@@ -457,6 +465,9 @@ def invoke(
457465
traceback if available.
458466
"""
459467
exc_info = None
468+
if catch_exceptions is None:
469+
catch_exceptions = self.catch_exceptions
470+
460471
with self.isolation(input=input, env=env, color=color) as outstreams:
461472
return_value = None
462473
exception: BaseException | None = None

tests/test_testing.py

+22
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,28 @@ def cli():
184184
assert result.exit_code == 1
185185

186186

187+
def test_catch_exceptions_cli_runner():
188+
"""Test that invoke `catch_exceptions` takes the value from CliRunner if not set
189+
explicitly."""
190+
191+
class CustomError(Exception):
192+
pass
193+
194+
@click.command()
195+
def cli():
196+
raise CustomError(1)
197+
198+
runner = CliRunner(catch_exceptions=False)
199+
200+
result = runner.invoke(cli, catch_exceptions=True)
201+
assert isinstance(result.exception, CustomError)
202+
assert type(result.exc_info) is tuple
203+
assert len(result.exc_info) == 3
204+
205+
with pytest.raises(CustomError):
206+
runner.invoke(cli)
207+
208+
187209
def test_with_color():
188210
@click.command()
189211
def cli():

0 commit comments

Comments
 (0)