MutableMapping,
Optional,
Pattern,
+ Sequence,
Set,
Sized,
Tuple,
"(useful when piping source on standard input)."
),
)
+@click.option(
+ "--python-cell-magics",
+ multiple=True,
+ help=(
+ "When processing Jupyter Notebooks, add the given magic to the list"
+ f" of known python-magics ({', '.join(PYTHON_CELL_MAGICS)})."
+ " Useful for formatting cells with custom python magics."
+ ),
+ default=[],
+)
@click.option(
"-S",
"--skip-string-normalization",
fast: bool,
pyi: bool,
ipynb: bool,
+ python_cell_magics: Sequence[str],
skip_string_normalization: bool,
skip_magic_trailing_comma: bool,
experimental_string_processing: bool,
magic_trailing_comma=not skip_magic_trailing_comma,
experimental_string_processing=experimental_string_processing,
preview=preview,
+ python_cell_magics=set(python_cell_magics),
)
if code is not None:
return dst_contents
-def validate_cell(src: str) -> None:
+def validate_cell(src: str, mode: Mode) -> None:
"""Check that cell does not already contain TransformerManager transformations,
or non-Python cell magics, which might cause tokenizer_rt to break because of
indentations.
"""
if any(transformed_magic in src for transformed_magic in TRANSFORMED_MAGICS):
raise NothingChanged
- if src[:2] == "%%" and src.split()[0][2:] not in PYTHON_CELL_MAGICS:
+ if (
+ src[:2] == "%%"
+ and src.split()[0][2:] not in PYTHON_CELL_MAGICS | mode.python_cell_magics
+ ):
raise NothingChanged
could potentially be automagics or multi-line magics, which
are currently not supported.
"""
- validate_cell(src)
+ validate_cell(src, mode)
src_without_trailing_semicolon, has_trailing_semicolon = remove_trailing_semicolon(
src
)
+from dataclasses import replace
import pathlib
import re
+from contextlib import ExitStack as does_not_raise
+from typing import ContextManager
from click.testing import CliRunner
from black.handle_ipynb_magics import jupyter_dependencies_are_installed
format_cell(src, fast=True, mode=JUPYTER_MODE)
-def test_cell_magic() -> None:
+@pytest.mark.parametrize(
+ "mode",
+ [
+ pytest.param(JUPYTER_MODE, id="default mode"),
+ pytest.param(
+ replace(JUPYTER_MODE, python_cell_magics={"cust1", "cust1"}),
+ id="custom cell magics mode",
+ ),
+ ],
+)
+def test_cell_magic(mode: Mode) -> None:
src = "%%time\nfoo =bar"
- result = format_cell(src, fast=True, mode=JUPYTER_MODE)
+ result = format_cell(src, fast=True, mode=mode)
expected = "%%time\nfoo = bar"
assert result == expected
format_cell(src, fast=True, mode=JUPYTER_MODE)
+@pytest.mark.parametrize(
+ "mode",
+ [
+ pytest.param(JUPYTER_MODE, id="default mode"),
+ pytest.param(
+ replace(JUPYTER_MODE, python_cell_magics={"cust1", "cust1"}),
+ id="custom cell magics mode",
+ ),
+ ],
+)
@pytest.mark.parametrize(
"src, expected",
(
pytest.param("env = %env", "env = %env", id="Assignment to magic"),
),
)
-def test_magic(src: str, expected: str) -> None:
- result = format_cell(src, fast=True, mode=JUPYTER_MODE)
+def test_magic(src: str, expected: str, mode: Mode) -> None:
+ result = format_cell(src, fast=True, mode=mode)
assert result == expected
assert result == expected
+@pytest.mark.parametrize(
+ "mode, expected_output, expectation",
+ [
+ pytest.param(
+ JUPYTER_MODE,
+ "%%custom_python_magic -n1 -n2\nx=2",
+ pytest.raises(NothingChanged),
+ id="No change when cell magic not registered",
+ ),
+ pytest.param(
+ replace(JUPYTER_MODE, python_cell_magics={"cust1", "cust1"}),
+ "%%custom_python_magic -n1 -n2\nx=2",
+ pytest.raises(NothingChanged),
+ id="No change when other cell magics registered",
+ ),
+ pytest.param(
+ replace(JUPYTER_MODE, python_cell_magics={"custom_python_magic", "cust1"}),
+ "%%custom_python_magic -n1 -n2\nx = 2",
+ does_not_raise(),
+ id="Correctly change when cell magic registered",
+ ),
+ ],
+)
+def test_cell_magic_with_custom_python_magic(
+ mode: Mode, expected_output: str, expectation: ContextManager[object]
+) -> None:
+ with expectation:
+ result = format_cell(
+ "%%custom_python_magic -n1 -n2\nx=2",
+ fast=True,
+ mode=mode,
+ )
+ assert result == expected_output
+
+
def test_cell_magic_nested() -> None:
src = "%%time\n%%time\n2+2"
result = format_cell(src, fast=True, mode=JUPYTER_MODE)