Improve handling of unicode errors

Fixes #12669
pull/12695/head
James Cammarata 9 years ago
parent 5a0f5f1254
commit de792ba3c2

@ -38,6 +38,7 @@ import traceback
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
from ansible.utils.display import Display from ansible.utils.display import Display
from ansible.utils.unicode import to_unicode
######################################## ########################################
### OUTPUT OF LAST RESORT ### ### OUTPUT OF LAST RESORT ###
@ -82,10 +83,10 @@ if __name__ == '__main__':
except AnsibleOptionsError as e: except AnsibleOptionsError as e:
cli.parser.print_help() cli.parser.print_help()
display.error(str(e), wrap_text=False) display.error(to_unicode(e), wrap_text=False)
sys.exit(5) sys.exit(5)
except AnsibleParserError as e: except AnsibleParserError as e:
display.error(str(e), wrap_text=False) display.error(to_unicode(e), wrap_text=False)
sys.exit(4) sys.exit(4)
# TQM takes care of these, but leaving comment to reserve the exit codes # TQM takes care of these, but leaving comment to reserve the exit codes
# except AnsibleHostUnreachable as e: # except AnsibleHostUnreachable as e:
@ -95,14 +96,14 @@ if __name__ == '__main__':
# display.error(str(e)) # display.error(str(e))
# sys.exit(2) # sys.exit(2)
except AnsibleError as e: except AnsibleError as e:
display.error(str(e), wrap_text=False) display.error(to_unicode(e), wrap_text=False)
sys.exit(1) sys.exit(1)
except KeyboardInterrupt: except KeyboardInterrupt:
display.error("User interrupted execution") display.error("User interrupted execution")
sys.exit(99) sys.exit(99)
except Exception as e: except Exception as e:
have_cli_options = cli is not None and cli.options is not None have_cli_options = cli is not None and cli.options is not None
display.error("Unexpected Exception: %s" % str(e), wrap_text=False) display.error("Unexpected Exception: %s" % to_unicode(e), wrap_text=False)
if not have_cli_options or have_cli_options and cli.options.verbosity > 2: if not have_cli_options or have_cli_options and cli.options.verbosity > 2:
display.display("the full traceback was:\n\n%s" % traceback.format_exc()) display.display("the full traceback was:\n\n%s" % traceback.format_exc())
else: else:

@ -22,6 +22,7 @@ __metaclass__ = type
import os import os
from ansible.errors.yaml_strings import * from ansible.errors.yaml_strings import *
from ansible.utils.unicode import to_unicode, to_bytes
class AnsibleError(Exception): class AnsibleError(Exception):
''' '''
@ -48,7 +49,7 @@ class AnsibleError(Exception):
if obj and isinstance(obj, AnsibleBaseYAMLObject): if obj and isinstance(obj, AnsibleBaseYAMLObject):
extended_error = self._get_extended_error() extended_error = self._get_extended_error()
if extended_error: if extended_error:
self.message = 'ERROR! %s\n\n%s' % (message, extended_error) self.message = 'ERROR! %s\n\n%s' % (message, to_bytes(extended_error))
else: else:
self.message = 'ERROR! %s' % message self.message = 'ERROR! %s' % message
@ -96,6 +97,8 @@ class AnsibleError(Exception):
error_message += YAML_POSITION_DETAILS % (src_file, line_number, col_number) error_message += YAML_POSITION_DETAILS % (src_file, line_number, col_number)
if src_file not in ('<string>', '<unicode>') and self._show_content: if src_file not in ('<string>', '<unicode>') and self._show_content:
(target_line, prev_line) = self._get_error_lines_from_file(src_file, line_number - 1) (target_line, prev_line) = self._get_error_lines_from_file(src_file, line_number - 1)
target_line = to_unicode(target_line)
prev_line = to_unicode(prev_line)
if target_line: if target_line:
stripped_line = target_line.replace(" ","") stripped_line = target_line.replace(" ","")
arrow_line = (" " * (col_number-1)) + "^ here" arrow_line = (" " * (col_number-1)) + "^ here"

@ -31,6 +31,7 @@ class TestErrors(unittest.TestCase):
def setUp(self): def setUp(self):
self.message = 'This is the error message' self.message = 'This is the error message'
self.unicode_message = 'This is an error with \xf0\x9f\x98\xa8 in it'
self.obj = AnsibleBaseYAMLObject() self.obj = AnsibleBaseYAMLObject()
@ -42,6 +43,11 @@ class TestErrors(unittest.TestCase):
self.assertEqual(e.message, 'ERROR! ' + self.message) self.assertEqual(e.message, 'ERROR! ' + self.message)
self.assertEqual(e.__repr__(), 'ERROR! ' + self.message) self.assertEqual(e.__repr__(), 'ERROR! ' + self.message)
def test_basic_unicode_error(self):
e = AnsibleError(self.unicode_message)
self.assertEqual(e.message, 'ERROR! ' + self.unicode_message)
self.assertEqual(e.__repr__(), 'ERROR! ' + self.unicode_message)
@patch.object(AnsibleError, '_get_error_lines_from_file') @patch.object(AnsibleError, '_get_error_lines_from_file')
def test_error_with_object(self, mock_method): def test_error_with_object(self, mock_method):
self.obj.ansible_pos = ('foo.yml', 1, 1) self.obj.ansible_pos = ('foo.yml', 1, 1)
@ -66,3 +72,12 @@ class TestErrors(unittest.TestCase):
e = AnsibleError(self.message, self.obj) e = AnsibleError(self.message, self.obj)
self.assertEqual(e.message, "ERROR! This is the error message\n\nThe error appears to have been in 'foo.yml': line 2, column 1, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\n(specified line no longer in file, maybe it changed?)") self.assertEqual(e.message, "ERROR! This is the error message\n\nThe error appears to have been in 'foo.yml': line 2, column 1, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\n(specified line no longer in file, maybe it changed?)")
m = mock_open()
m.return_value.readlines.return_value = ['this line has unicode \xf0\x9f\x98\xa8 in it!\n']
with patch('{0}.open'.format(BUILTINS), m):
# this line will be found in the file
self.obj.ansible_pos = ('foo.yml', 1, 1)
e = AnsibleError(self.unicode_message, self.obj)
self.assertEqual(e.message, "ERROR! This is an error with \xf0\x9f\x98\xa8 in it\n\nThe error appears to have been in 'foo.yml': line 1, column 1, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\nthis line has unicode \xf0\x9f\x98\xa8 in it!\n^ here\n")

Loading…
Cancel
Save