diff --git a/docs/known-limitations.rst b/docs/known-limitations.rst index 7230ebfc..2d18aa0e 100644 --- a/docs/known-limitations.rst +++ b/docs/known-limitations.rst @@ -11,7 +11,19 @@ then the following will still not be processed: - cells with code which ``IPython`` would transform magics into (e.g. ``get_ipython().system('ls')``). Because ``nbQA`` converts the code cells in Jupyter notebooks to temporary Python files for linting, certain flags like ``flake8``'s -``--per-file-ignores`` don't work. The temporary Python files will not match the specified file patterns and ignored error codes will still +``--per-file-ignores`` don't work perfectly. +The temporary Python files will not match the specified file patterns and ignored error codes will still surface (`GH issue `_). +nbqa-generated temporary files will contain the string ``nbqa_ipynb``, +so you can still apply per-file-ignores if you add an additional pattern: + +.. sourcecode:: ini + + [flake8] + per-file-ignores = + examples/*.ipynb: E402 + examples/*nbqa_ipynb.py: E402 + +The directory and the stem of the filename are preserved, so e.g. ``path/to/mynotebook.ipynb`` will be ``path/to/mynotebook{randomstring}_nbqa_ipynb.py`` when nbqa passes it to the linter. Any other limitation is likely unintentional - if you run into any, please do report an issue. diff --git a/nbqa/__main__.py b/nbqa/__main__.py index dbce5f0b..bcafbcbc 100644 --- a/nbqa/__main__.py +++ b/nbqa/__main__.py @@ -526,7 +526,7 @@ def _get_nb_to_tmp_mapping( prefix=remove_suffix( os.path.basename(notebook), os.path.splitext(notebook)[-1] ), - suffix=SUFFIX[md], + suffix="_nbqa_ipynb" + SUFFIX[md], ) ) relative_path, _ = get_relative_and_absolute_paths( diff --git a/tests/tools/test_flake8_works.py b/tests/tools/test_flake8_works.py index 3b25c559..b3f1cc50 100644 --- a/tests/tools/test_flake8_works.py +++ b/tests/tools/test_flake8_works.py @@ -1,6 +1,7 @@ """Check :code:`flake8` works as intended.""" import os +from pathlib import Path from textwrap import dedent from typing import TYPE_CHECKING @@ -91,3 +92,49 @@ def test_cell_with_all_magics(capsys: "CaptureFixture") -> None: out, err = capsys.readouterr() assert out == "" assert err == "" + + +def test_per_file_ignores( + tmp_notebook_for_testing: Path, capsys: "CaptureFixture" +) -> None: + """ + Check flake8 per-file-ignore patterns work. + + Parameters + ---------- + tmp_notebook_for_testing + notebook Path to test + capsys + Pytest fixture to capture stdout and stderr. + """ + # enable per-file ignores with nbqa glob + flake8_ini = Path(".flake8") + flake8_ini.write_text( + dedent( + """ + [flake8] + per-file-ignores = + **/*.ipynb: E402 + **/*nbqa_ipynb.py: E402 + """ + ), + encoding="utf-8", + ) + + main(["flake8", str(tmp_notebook_for_testing)]) + flake8_ini.unlink() + + expected_path_0 = os.path.join("tests", "data", "notebook_for_testing.ipynb") + + out, err = capsys.readouterr() + expected_out = dedent( + f"""\ + {expected_path_0}:cell_1:1:1: F401 'os' imported but unused + {expected_path_0}:cell_1:3:1: F401 'glob' imported but unused + {expected_path_0}:cell_1:5:1: F401 'nbqa' imported but unused + {expected_path_0}:cell_2:19:9: W291 trailing whitespace + {expected_path_0}:cell_4:1:1: F401 'random.randint' imported but unused + """ + ) + assert err == "" + assert sorted(out.splitlines()) == sorted(expected_out.splitlines())