Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- [#3646](https://github.com/plotly/dash/pull/3646) Remove React 16 support (`16.14.0` is no longer an accepted value for `REACT_VERSION` / `_set_react_version`).

### Changed
- [#4037](https://github.com/plotly/dash/pull/4037) Only load the IPython and Jupyter integration modules when Dash is imported inside IPython. Roughly halves `import dash` time in environments that have IPython installed.
- [#3987](https://github.com/plotly/dash/pull/3987) Forward FastAPI reload scope options (`reload_dirs`, `reload_excludes`, and `reload_includes`) to Uvicorn when reloading.
- [#3986](https://github.com/plotly/dash/pull/3986) Adjust `_run_before_hooks` in the `fastapi` backend to honor a response returned by a `before_request` function, matching the `flask` backend's behavior.

Expand Down
3 changes: 3 additions & 0 deletions dash/_jupyter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
from werkzeug.serving import make_server

try:
if "IPython" not in sys.modules:
# Not inside IPython: skip the heavy imports, they double the cost of `import dash`.
raise ImportError
from IPython import get_ipython # type: ignore[attr-defined]
Comment on lines +18 to 21
from IPython.display import IFrame, display, Javascript # type: ignore[import-not-found]
from IPython.core.display import HTML # type: ignore[import-not-found]
Expand Down
27 changes: 27 additions & 0 deletions tests/unit/test_jupyter_import.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import subprocess
import sys

import pytest

pytest.importorskip("IPython")


def _run(*args):
result = subprocess.run(
[sys.executable, *args], capture_output=True, text=True, check=False
)
assert result.returncode == 0, result.stderr


def test_import_dash_does_not_load_ipython():
_run("-c", "import dash, sys; assert 'IPython' not in sys.modules")


def test_jupyter_support_loads_inside_ipython():
_run(
"-m",
"IPython",
"-c",
"from dash import _jupyter; "
"assert _jupyter._dep_installed and _jupyter.jupyter_dash.in_ipython",
)
Loading