Skip to content

Commit 2463738

Browse files
committed
Fix printing of non-ascii in error handler
1 parent 6b005cf commit 2463738

File tree

2 files changed

+38
-11
lines changed

2 files changed

+38
-11
lines changed

pre_commit/error_handler.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
import os.path
88
import traceback
99

10+
from pre_commit import five
1011
from pre_commit.errors import FatalError
12+
from pre_commit.output import sys_stdout_write_wrapper
1113
from pre_commit.store import Store
1214

1315

@@ -16,15 +18,15 @@ class PreCommitSystemExit(SystemExit):
1618
pass
1719

1820

19-
def _log_and_exit(msg, exc, formatted, print_fn=print):
20-
error_msg = '{0}: {1}: {2}'.format(msg, type(exc).__name__, exc)
21-
print_fn(error_msg)
22-
print_fn('Check the log at ~/.pre-commit/pre-commit.log')
21+
def _log_and_exit(msg, exc, formatted, write_fn=sys_stdout_write_wrapper):
22+
error_msg = '{0}: {1}: {2}\n'.format(msg, type(exc).__name__, exc)
23+
write_fn(error_msg)
24+
write_fn('Check the log at ~/.pre-commit/pre-commit.log\n')
2325
store = Store()
2426
store.require_created()
25-
with io.open(os.path.join(store.directory, 'pre-commit.log'), 'w') as log:
26-
log.write(error_msg + '\n')
27-
log.write(formatted + '\n')
27+
with io.open(os.path.join(store.directory, 'pre-commit.log'), 'wb') as log:
28+
log.write(five.to_bytes(error_msg))
29+
log.write(five.to_bytes(formatted) + b'\n')
2830
raise PreCommitSystemExit(1)
2931

3032

tests/error_handler_test.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1+
# -*- coding: utf-8 -*-
12
from __future__ import absolute_import
23
from __future__ import unicode_literals
34

45
import io
56
import os.path
67
import re
8+
import sys
79

810
import mock
911
import pytest
1012

1113
from pre_commit import error_handler
1214
from pre_commit.errors import FatalError
15+
from pre_commit.util import cmd_output
1316

1417

1518
@pytest.yield_fixture
@@ -72,17 +75,17 @@ def test_error_handler_uncaught_error(mocked_log_and_exit):
7275

7376

7477
def test_log_and_exit(mock_out_store_directory):
75-
mocked_print = mock.Mock()
78+
mocked_write = mock.Mock()
7679
with pytest.raises(error_handler.PreCommitSystemExit):
7780
error_handler._log_and_exit(
7881
'msg', FatalError('hai'), "I'm a stacktrace",
79-
print_fn=mocked_print,
82+
write_fn=mocked_write,
8083
)
8184

82-
printed = '\n'.join(call[0][0] for call in mocked_print.call_args_list)
85+
printed = ''.join(call[0][0] for call in mocked_write.call_args_list)
8386
assert printed == (
8487
'msg: FatalError: hai\n'
85-
'Check the log at ~/.pre-commit/pre-commit.log'
88+
'Check the log at ~/.pre-commit/pre-commit.log\n'
8689
)
8790

8891
log_file = os.path.join(mock_out_store_directory, 'pre-commit.log')
@@ -92,3 +95,25 @@ def test_log_and_exit(mock_out_store_directory):
9295
'msg: FatalError: hai\n'
9396
"I'm a stacktrace\n"
9497
)
98+
99+
100+
def test_error_handler_non_ascii_exception(mock_out_store_directory):
101+
with pytest.raises(error_handler.PreCommitSystemExit):
102+
with error_handler.error_handler():
103+
raise ValueError('☃')
104+
105+
106+
def test_error_handler_no_tty(tempdir_factory):
107+
output = cmd_output(
108+
sys.executable, '-c',
109+
'from __future__ import unicode_literals\n'
110+
'from pre_commit.error_handler import error_handler\n'
111+
'with error_handler():\n'
112+
' raise ValueError("\\u2603")\n',
113+
env=dict(os.environ, PRE_COMMIT_HOME=tempdir_factory.get()),
114+
retcode=1,
115+
)
116+
assert output[1].replace('\r', '') == (
117+
'An unexpected error has occurred: ValueError: ☃\n'
118+
'Check the log at ~/.pre-commit/pre-commit.log\n'
119+
)

0 commit comments

Comments
 (0)