diff --git a/pre_commit/error_handler.py b/pre_commit/error_handler.py index afacab9bb..023dd3596 100644 --- a/pre_commit/error_handler.py +++ b/pre_commit/error_handler.py @@ -12,7 +12,12 @@ from pre_commit.util import force_bytes -def _log_and_exit(msg: str, exc: BaseException, formatted: str) -> None: +def _log_and_exit( + msg: str, + ret_code: int, + exc: BaseException, + formatted: str, +) -> None: error_msg = f'{msg}: {type(exc).__name__}: '.encode() + force_bytes(exc) output.write_line_b(error_msg) @@ -51,7 +56,7 @@ def _log_and_exit(msg: str, exc: BaseException, formatted: str) -> None: _log_line('```') _log_line(formatted.rstrip()) _log_line('```') - raise SystemExit(1) + raise SystemExit(ret_code) @contextlib.contextmanager @@ -60,9 +65,9 @@ def error_handler() -> Generator[None, None, None]: yield except (Exception, KeyboardInterrupt) as e: if isinstance(e, FatalError): - msg = 'An error has occurred' + msg, ret_code = 'An error has occurred', 1 elif isinstance(e, KeyboardInterrupt): - msg = 'Interrupted (^C)' + msg, ret_code = 'Interrupted (^C)', 130 else: - msg = 'An unexpected error has occurred' - _log_and_exit(msg, e, traceback.format_exc()) + msg, ret_code = 'An unexpected error has occurred', 3 + _log_and_exit(msg, ret_code, e, traceback.format_exc()) diff --git a/tests/error_handler_test.py b/tests/error_handler_test.py index 804701f05..6b0bb86d7 100644 --- a/tests/error_handler_test.py +++ b/tests/error_handler_test.py @@ -33,6 +33,7 @@ def test_error_handler_fatal_error(mocked_log_and_exit): mocked_log_and_exit.assert_called_once_with( 'An error has occurred', + 1, exc, # Tested below mock.ANY, @@ -47,7 +48,7 @@ def test_error_handler_fatal_error(mocked_log_and_exit): r' raise exc\n' r'(pre_commit\.errors\.)?FatalError: just a test\n', ) - pattern.assert_matches(mocked_log_and_exit.call_args[0][2]) + pattern.assert_matches(mocked_log_and_exit.call_args[0][3]) def test_error_handler_uncaught_error(mocked_log_and_exit): @@ -57,6 +58,7 @@ def test_error_handler_uncaught_error(mocked_log_and_exit): mocked_log_and_exit.assert_called_once_with( 'An unexpected error has occurred', + 3, exc, # Tested below mock.ANY, @@ -70,7 +72,7 @@ def test_error_handler_uncaught_error(mocked_log_and_exit): r' raise exc\n' r'ValueError: another test\n', ) - pattern.assert_matches(mocked_log_and_exit.call_args[0][2]) + pattern.assert_matches(mocked_log_and_exit.call_args[0][3]) def test_error_handler_keyboardinterrupt(mocked_log_and_exit): @@ -80,6 +82,7 @@ def test_error_handler_keyboardinterrupt(mocked_log_and_exit): mocked_log_and_exit.assert_called_once_with( 'Interrupted (^C)', + 130, exc, # Tested below mock.ANY, @@ -93,7 +96,7 @@ def test_error_handler_keyboardinterrupt(mocked_log_and_exit): r' raise exc\n' r'KeyboardInterrupt\n', ) - pattern.assert_matches(mocked_log_and_exit.call_args[0][2]) + pattern.assert_matches(mocked_log_and_exit.call_args[0][3]) def test_log_and_exit(cap_out, mock_store_dir): @@ -103,8 +106,9 @@ def test_log_and_exit(cap_out, mock_store_dir): 'pre_commit.errors.FatalError: hai\n' ) - with pytest.raises(SystemExit): - error_handler._log_and_exit('msg', FatalError('hai'), tb) + with pytest.raises(SystemExit) as excinfo: + error_handler._log_and_exit('msg', 1, FatalError('hai'), tb) + assert excinfo.value.code == 1 printed = cap_out.get() log_file = os.path.join(mock_store_dir, 'pre-commit.log') @@ -170,7 +174,7 @@ def test_error_handler_no_tty(tempdir_factory): 'from pre_commit.error_handler import error_handler\n' 'with error_handler():\n' ' raise ValueError("\\u2603")\n', - retcode=1, + retcode=3, tempdir_factory=tempdir_factory, pre_commit_home=pre_commit_home, )