Skip to content

Commit

Permalink
Avoid importing IPython if notebook cells do not contain magics (#3782
Browse files Browse the repository at this point in the history
)

Co-authored-by: hauntsaninja <hauntsaninja@gmail.com>
Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
  • Loading branch information
3 people committed Jul 17, 2023
1 parent 0e26ada commit 92e0f5b
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 29 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Expand Up @@ -30,6 +30,8 @@

<!-- Changes that improve Black's performance. -->

- Avoid importing `IPython` if notebook cells do not contain magics (#3782)

### Output

<!-- Changes to Black's terminal output and error messages -->
Expand Down
2 changes: 1 addition & 1 deletion src/black/__init__.py
Expand Up @@ -668,7 +668,7 @@ def get_sources(
p = Path(f"{STDIN_PLACEHOLDER}{str(p)}")

if p.suffix == ".ipynb" and not jupyter_dependencies_are_installed(
verbose=verbose, quiet=quiet
warn=verbose or not quiet
):
continue

Expand Down
2 changes: 1 addition & 1 deletion src/black/files.py
Expand Up @@ -384,7 +384,7 @@ def gen_python_files(

elif child.is_file():
if child.suffix == ".ipynb" and not jupyter_dependencies_are_installed(
verbose=verbose, quiet=quiet
warn=verbose or not quiet
):
continue
include_match = include.search(normalized_path) if include else True
Expand Down
31 changes: 12 additions & 19 deletions src/black/handle_ipynb_magics.py
Expand Up @@ -6,6 +6,7 @@
import secrets
import sys
from functools import lru_cache
from importlib.util import find_spec
from typing import Dict, List, Optional, Tuple

if sys.version_info >= (3, 10):
Expand Down Expand Up @@ -56,25 +57,17 @@ class Replacement:


@lru_cache
def jupyter_dependencies_are_installed(*, verbose: bool, quiet: bool) -> bool:
try:
# isort: off
# tokenize_rt is less commonly installed than IPython
# and IPython is expensive to import
import tokenize_rt # noqa:F401
import IPython # noqa:F401

# isort: on
except ModuleNotFoundError:
if verbose or not quiet:
msg = (
"Skipping .ipynb files as Jupyter dependencies are not installed.\n"
'You can fix this by running ``pip install "black[jupyter]"``'
)
out(msg)
return False
else:
return True
def jupyter_dependencies_are_installed(*, warn: bool) -> bool:
installed = (
find_spec("tokenize_rt") is not None and find_spec("IPython") is not None
)
if not installed and warn:
msg = (
"Skipping .ipynb files as Jupyter dependencies are not installed.\n"
'You can fix this by running ``pip install "black[jupyter]"``'
)
out(msg)
return installed


def remove_trailing_semicolon(src: str) -> Tuple[str, bool]:
Expand Down
12 changes: 4 additions & 8 deletions tests/test_ipynb.py
Expand Up @@ -440,17 +440,13 @@ def test_cache_isnt_written_if_no_jupyter_deps_single(
nb = get_case_path("jupyter", "notebook_trailing_newline.ipynb")
tmp_nb = tmp_path / "notebook.ipynb"
tmp_nb.write_bytes(nb.read_bytes())
monkeypatch.setattr(
"black.jupyter_dependencies_are_installed", lambda verbose, quiet: False
)
monkeypatch.setattr("black.jupyter_dependencies_are_installed", lambda warn: False)
result = runner.invoke(
main, [str(tmp_path / "notebook.ipynb"), f"--config={EMPTY_CONFIG}"]
)
assert "No Python files are present to be formatted. Nothing to do" in result.output
jupyter_dependencies_are_installed.cache_clear()
monkeypatch.setattr(
"black.jupyter_dependencies_are_installed", lambda verbose, quiet: True
)
monkeypatch.setattr("black.jupyter_dependencies_are_installed", lambda warn: True)
result = runner.invoke(
main, [str(tmp_path / "notebook.ipynb"), f"--config={EMPTY_CONFIG}"]
)
Expand All @@ -466,13 +462,13 @@ def test_cache_isnt_written_if_no_jupyter_deps_dir(
tmp_nb = tmp_path / "notebook.ipynb"
tmp_nb.write_bytes(nb.read_bytes())
monkeypatch.setattr(
"black.files.jupyter_dependencies_are_installed", lambda verbose, quiet: False
"black.files.jupyter_dependencies_are_installed", lambda warn: False
)
result = runner.invoke(main, [str(tmp_path), f"--config={EMPTY_CONFIG}"])
assert "No Python files are present to be formatted. Nothing to do" in result.output
jupyter_dependencies_are_installed.cache_clear()
monkeypatch.setattr(
"black.files.jupyter_dependencies_are_installed", lambda verbose, quiet: True
"black.files.jupyter_dependencies_are_installed", lambda warn: True
)
result = runner.invoke(main, [str(tmp_path), f"--config={EMPTY_CONFIG}"])
assert "reformatted" in result.output
Expand Down

0 comments on commit 92e0f5b

Please sign in to comment.