From 2cf546623fa78de692e8479e1a9a20583b23b7c1 Mon Sep 17 00:00:00 2001 From: Marco Gorelli Date: Wed, 9 Dec 2020 09:47:37 +0000 Subject: [PATCH 1/5] parse error message in case of assignment to literal --- nbqa/output_parser.py | 4 ++- tests/data/assignment_to_literal.ipynb | 35 ++++++++++++++++++++++++++ tests/tools/test_black.py | 25 ++++++++++++++++++ tests/tools/test_mypy_works.py | 2 +- 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 tests/data/assignment_to_literal.ipynb diff --git a/nbqa/output_parser.py b/nbqa/output_parser.py index c9d5406f..bbef03e4 100644 --- a/nbqa/output_parser.py +++ b/nbqa/output_parser.py @@ -38,7 +38,9 @@ def _get_pattern( ( rf"(?<=^error: cannot format {re.escape(str(notebook))}: Cannot parse: )\d+", standard_substitution, - ) + ), + (r"(?<=line )\d+(?=\)\nOh no! )", standard_substitution), + ("line cell_", "cell_"), ] if command == "doctest": diff --git a/tests/data/assignment_to_literal.ipynb b/tests/data/assignment_to_literal.ipynb new file mode 100644 index 00000000..d207c831 --- /dev/null +++ b/tests/data/assignment_to_literal.ipynb @@ -0,0 +1,35 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "1 = [1,2,3]" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0-final" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/tests/tools/test_black.py b/tests/tools/test_black.py index 91362188..7927c2ed 100644 --- a/tests/tools/test_black.py +++ b/tests/tools/test_black.py @@ -343,3 +343,28 @@ def test_black_works_with_leading_comment(capsys: "CaptureFixture") -> None: expected_err = "" assert expected_out == out assert expected_err == err + + +def test_black_works_with_literal_assignment(capsys: "CaptureFixture") -> None: + """ + Check black works with notebooks with commented-out magics. + + Parameters + ---------- + capsys + Pytest fixture to capture stdout and stderr. + """ + path = os.path.abspath(os.path.join("tests", "data", "assignment_to_literal.ipynb")) + + with pytest.raises(SystemExit): + main(["black", path]) + + out, err = capsys.readouterr() + expected_out = "" + expected_err = ( + "error: cannot format /home/marco/nbQA-dev/tests/data/assignment_to_literal.ipynb: " + "cannot use --safe with this file; failed to parse source file. AST error message: " + "can't assign to literal (, cell_1:1)\nOh no! 💥 💔 💥\n1 file failed to reformat.\n" + ) + assert expected_out == out + assert expected_err == err diff --git a/tests/tools/test_mypy_works.py b/tests/tools/test_mypy_works.py index 5c03d42f..cd769e7d 100644 --- a/tests/tools/test_mypy_works.py +++ b/tests/tools/test_mypy_works.py @@ -45,7 +45,7 @@ def test_mypy_works(capsys: "CaptureFixture") -> None: {path_0}:cell_2:19: error: Argument 1 to "hello" has incompatible type "int"; expected "str" {path_3}:cell_8:3: error: Name 'flake8_version' is not defined {path_3}:cell_8:4: error: Name 'flake8_version' is not defined - Found 5 errors in 4 files (checked 18 source files) + Found 5 errors in 4 files (checked 19 source files) """ # noqa ) expected_err = "" From dab49295088976bdd3932812032d0ade592d1036 Mon Sep 17 00:00:00 2001 From: Marco Gorelli Date: Wed, 9 Dec 2020 09:52:12 +0000 Subject: [PATCH 2/5] move to invalid data folder --- tests/{data => invalid_data}/assignment_to_literal.ipynb | 0 tests/tools/test_black.py | 6 ++++-- tests/tools/test_mypy_works.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) rename tests/{data => invalid_data}/assignment_to_literal.ipynb (100%) diff --git a/tests/data/assignment_to_literal.ipynb b/tests/invalid_data/assignment_to_literal.ipynb similarity index 100% rename from tests/data/assignment_to_literal.ipynb rename to tests/invalid_data/assignment_to_literal.ipynb diff --git a/tests/tools/test_black.py b/tests/tools/test_black.py index 7927c2ed..82ce1283 100644 --- a/tests/tools/test_black.py +++ b/tests/tools/test_black.py @@ -354,7 +354,9 @@ def test_black_works_with_literal_assignment(capsys: "CaptureFixture") -> None: capsys Pytest fixture to capture stdout and stderr. """ - path = os.path.abspath(os.path.join("tests", "data", "assignment_to_literal.ipynb")) + path = os.path.abspath( + os.path.join("tests", "invalid_data", "assignment_to_literal.ipynb") + ) with pytest.raises(SystemExit): main(["black", path]) @@ -362,7 +364,7 @@ def test_black_works_with_literal_assignment(capsys: "CaptureFixture") -> None: out, err = capsys.readouterr() expected_out = "" expected_err = ( - "error: cannot format /home/marco/nbQA-dev/tests/data/assignment_to_literal.ipynb: " + f"error: cannot format {path}: " "cannot use --safe with this file; failed to parse source file. AST error message: " "can't assign to literal (, cell_1:1)\nOh no! 💥 💔 💥\n1 file failed to reformat.\n" ) diff --git a/tests/tools/test_mypy_works.py b/tests/tools/test_mypy_works.py index cd769e7d..5c03d42f 100644 --- a/tests/tools/test_mypy_works.py +++ b/tests/tools/test_mypy_works.py @@ -45,7 +45,7 @@ def test_mypy_works(capsys: "CaptureFixture") -> None: {path_0}:cell_2:19: error: Argument 1 to "hello" has incompatible type "int"; expected "str" {path_3}:cell_8:3: error: Name 'flake8_version' is not defined {path_3}:cell_8:4: error: Name 'flake8_version' is not defined - Found 5 errors in 4 files (checked 19 source files) + Found 5 errors in 4 files (checked 18 source files) """ # noqa ) expected_err = "" From 3476f5360bd762642e8eca366e33a3f4f6b330d8 Mon Sep 17 00:00:00 2001 From: Marco Gorelli Date: Wed, 9 Dec 2020 09:54:22 +0000 Subject: [PATCH 3/5] :doc: --- tests/tools/test_black.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tools/test_black.py b/tests/tools/test_black.py index 82ce1283..8ff70d22 100644 --- a/tests/tools/test_black.py +++ b/tests/tools/test_black.py @@ -347,7 +347,7 @@ def test_black_works_with_leading_comment(capsys: "CaptureFixture") -> None: def test_black_works_with_literal_assignment(capsys: "CaptureFixture") -> None: """ - Check black works with notebooks with commented-out magics. + Check black works with notebooks with invalid syntax (e.g. assignment to literal). Parameters ---------- From cfd24bf44a685f81dc66182f8ca432601a8dfc7d Mon Sep 17 00:00:00 2001 From: Marco Gorelli Date: Wed, 9 Dec 2020 10:02:05 +0000 Subject: [PATCH 4/5] test emojis --- tests/tools/test_black.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/tools/test_black.py b/tests/tools/test_black.py index 8ff70d22..27cc2887 100644 --- a/tests/tools/test_black.py +++ b/tests/tools/test_black.py @@ -19,6 +19,8 @@ SPARKLES = "\N{sparkles}" SHORTCAKE = "\N{shortcake}" +COLLISION = "\N{collision symbol}" +BROKEN_HEART = "\N{broken heart}" def test_black_works(tmp_notebook_for_testing: Path, capsys: "CaptureFixture") -> None: @@ -364,9 +366,18 @@ def test_black_works_with_literal_assignment(capsys: "CaptureFixture") -> None: out, err = capsys.readouterr() expected_out = "" expected_err = ( - f"error: cannot format {path}: " - "cannot use --safe with this file; failed to parse source file. AST error message: " - "can't assign to literal (, cell_1:1)\nOh no! 💥 💔 💥\n1 file failed to reformat.\n" + ( + f"error: cannot format {path}: " + "cannot use --safe with this file; failed to parse source file. AST error message: " + "can't assign to literal (, cell_1:1)\nOh no! " + f"{COLLISION} {BROKEN_HEART} {COLLISION}\n1 file failed to reformat.\n" + ) + .encode("ascii", "backslashreplace") + .decode() ) + # This is required because linux supports emojis + # so both should have \\ for comparison + err = err.encode("ascii", "backslashreplace").decode() + assert expected_out == out assert expected_err == err From b732dcf543fbfdf5e3b33f5e1efd31dd3fb0d1ef Mon Sep 17 00:00:00 2001 From: Marco Gorelli Date: Wed, 9 Dec 2020 10:07:48 +0000 Subject: [PATCH 5/5] more specific regex --- nbqa/output_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nbqa/output_parser.py b/nbqa/output_parser.py index bbef03e4..79a91c49 100644 --- a/nbqa/output_parser.py +++ b/nbqa/output_parser.py @@ -40,7 +40,7 @@ def _get_pattern( standard_substitution, ), (r"(?<=line )\d+(?=\)\nOh no! )", standard_substitution), - ("line cell_", "cell_"), + (r"line cell_(?=\d+:\d+\)\nOh no! )", "cell_"), ] if command == "doctest":