From 6f7ae97382d44b21bf1196e0ea312637dc9596c5 Mon Sep 17 00:00:00 2001 From: Sorin Sbarnea Date: Sat, 2 May 2020 13:54:06 +0100 Subject: [PATCH] Fix confusing ReadError traceback Avoids confusing tracebacks when ReadErrors exceptions are raised from the yaml reader. Now we do print the filename that failed to load and stop processing in order to avoid additional exceptions. Also adds tests to prevent future regressions. Fixes: #261 --- tests/test_syntax_errors.py | 25 +++++++++++++++++++++++++ yamllint/linter.py | 9 +++++++++ yamllint/parser.py | 5 +++-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/tests/test_syntax_errors.py b/tests/test_syntax_errors.py index bd4ddd2e..12d57806 100644 --- a/tests/test_syntax_errors.py +++ b/tests/test_syntax_errors.py @@ -92,3 +92,28 @@ def test_sets(self): ' a:\n' ' set\n' '...\n', None) + + def test_invalid_char_last(self): + self.check('---\nkey: value\t\n', + None, problem=(2, 11)) + + def test_invalid_char_first(self): + self.check('---\n\tkey: value\n', + None, problem=(2, 1)) + + def test_invalid_char_on_second_line(self): + self.check('---\nfoo: bar\n\toutput: foo\n', + None, problem=(3, 1)) + + def test_invalid_chars(self): + # We expect to identify only the first syntax error as this kind of + # error is fatal (stops parsing) + self.check('---\nkey: \tfoo\tbar\n', + None, + problem=(2, 6)) + + def test_invalid_char_with_other_rule(self): + self.check('key: value\t\n', + None, + problem1=(1, 1, 'document-start'), + problem2=(1, 11)) diff --git a/yamllint/linter.py b/yamllint/linter.py index 83e792cc..bcc99f14 100644 --- a/yamllint/linter.py +++ b/yamllint/linter.py @@ -186,6 +186,15 @@ def get_syntax_error(buffer): 'syntax error: ' + e.problem + ' (syntax)') problem.level = 'error' return problem + except yaml.reader.ReaderError as e: + # we need to convert position into line+column + line = buffer.count('\n', 0, e.position) + col = e.position - (buffer.rindex('\n', 0, e.position) if line else 1) + problem = LintProblem(line + 1, + col, + 'syntax error: ' + e.reason + ' (syntax)') + problem.level = 'error' + return problem def _run(buffer, conf, filepath): diff --git a/yamllint/parser.py b/yamllint/parser.py index de331f47..e6a74a32 100644 --- a/yamllint/parser.py +++ b/yamllint/parser.py @@ -121,9 +121,9 @@ def comments_between_tokens(token1, token2): def token_or_comment_generator(buffer): - yaml_loader = yaml.BaseLoader(buffer) try: + yaml_loader = yaml.BaseLoader(buffer) prev = None curr = yaml_loader.get_token() while curr is not None: @@ -139,7 +139,8 @@ def token_or_comment_generator(buffer): prev = curr curr = next - except yaml.scanner.ScannerError: + # errors like this are already analysed by get_syntax_error + except (yaml.scanner.ScannerError, yaml.reader.ReaderError): pass