From fff747d61befcae0777667c14055398c22c178dc Mon Sep 17 00:00:00 2001 From: Matej Aleksandrov Date: Mon, 14 Oct 2024 15:55:59 +0200 Subject: [PATCH] Fix formatting cells with magic methods and starting or trailing empty lines (#4484) --- CHANGES.md | 3 +++ src/black/handle_ipynb_magics.py | 6 ++++-- tests/test_ipynb.py | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d50bcb49e00..e2cc70f1661 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,9 @@ +- Fix formatting cells in IPython notebooks with magic methods and starting or trailing + empty lines (#4484) + ### Preview style diff --git a/src/black/handle_ipynb_magics.py b/src/black/handle_ipynb_magics.py index 792d22595aa..6b3367ca9db 100644 --- a/src/black/handle_ipynb_magics.py +++ b/src/black/handle_ipynb_magics.py @@ -178,12 +178,14 @@ def mask_cell(src: str) -> tuple[str, list[Replacement]]: from IPython.core.inputtransformer2 import TransformerManager transformer_manager = TransformerManager() + # A side effect of the following transformation is that it also removes any + # empty lines at the beginning of the cell. transformed = transformer_manager.transform_cell(src) transformed, cell_magic_replacements = replace_cell_magics(transformed) replacements += cell_magic_replacements transformed = transformer_manager.transform_cell(transformed) transformed, magic_replacements = replace_magics(transformed) - if len(transformed.splitlines()) != len(src.splitlines()): + if len(transformed.strip().splitlines()) != len(src.strip().splitlines()): # Multi-line magic, not supported. raise NothingChanged replacements += magic_replacements @@ -269,7 +271,7 @@ def replace_magics(src: str) -> tuple[str, list[Replacement]]: magic_finder = MagicFinder() magic_finder.visit(ast.parse(src)) new_srcs = [] - for i, line in enumerate(src.splitlines(), start=1): + for i, line in enumerate(src.split("\n"), start=1): if i in magic_finder.magics: offsets_and_magics = magic_finder.magics[i] if len(offsets_and_magics) != 1: # pragma: nocover diff --git a/tests/test_ipynb.py b/tests/test_ipynb.py index bdc2f27fcdb..3a3cc5fefdb 100644 --- a/tests/test_ipynb.py +++ b/tests/test_ipynb.py @@ -173,6 +173,22 @@ def test_cell_magic_with_magic() -> None: assert result == expected +@pytest.mark.parametrize( + "src, expected", + ( + ("\n\n\n%time \n\n", "%time"), + (" \n\t\n%%timeit -n4 \t \nx=2 \n\r\n", "%%timeit -n4\nx = 2"), + ( + " \t\n\n%%capture \nx=2 \n%config \n\n%env\n\t \n \n\n", + "%%capture\nx = 2\n%config\n\n%env", + ), + ), +) +def test_cell_magic_with_empty_lines(src: str, expected: str) -> None: + result = format_cell(src, fast=True, mode=JUPYTER_MODE) + assert result == expected + + @pytest.mark.parametrize( "mode, expected_output, expectation", [