diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ed4634415..5f53980dee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,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 +- [#4073](https://github.com/plotly/dash/pull/4073) Move `plotly-cloud` back to the optional `dash[cloud]` extra (it was a default dependency in 4.5.0rc0/rc1), since it is not available on conda-forge. - [#4026](https://github.com/plotly/dash/pull/4026) Log a warning, once per process, when a streaming request is refused because its stream token failed verification, which on multi-worker deployments usually means the workers do not share a signing secret. - [#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. diff --git a/dash/_plotly_cli.py b/dash/_plotly_cli.py index 4456962746..9974cd23b9 100644 --- a/dash/_plotly_cli.py +++ b/dash/_plotly_cli.py @@ -9,8 +9,7 @@ def cli(): except ImportError: print( "Plotly cloud is not installed," - " install it with `pip install plotly-cloud` (or reinstall dash)" - " to use the plotly command", + " install it with `pip install dash[cloud]` to use the plotly command", file=sys.stderr, ) sys.exit(-1) diff --git a/requirements/install.txt b/requirements/install.txt index 71e0dafb32..795f0c85c8 100644 --- a/requirements/install.txt +++ b/requirements/install.txt @@ -1,7 +1,6 @@ Flask>=1.0.4,<3.2 Werkzeug<3.2 plotly>=5.0.0 -plotly-cloud importlib-metadata typing_extensions>=4.1.1 requests diff --git a/tests/integration/devtools/test_callback_validation.py b/tests/integration/devtools/test_callback_validation.py index e4f89432d5..33a5ad485d 100644 --- a/tests/integration/devtools/test_callback_validation.py +++ b/tests/integration/devtools/test_callback_validation.py @@ -33,7 +33,7 @@ def check_errors(dash_duo, specs): found = [] for i in range(cnt): msg = dash_duo.find_elements(".dash-fe-error__title")[i].text - # plotly-cloud (a default install dep) injects a `_plotly-cloud-*` + # plotly-cloud (installed with dash[cloud]) injects a `_plotly-cloud-*` # component into every layout via a dash_hooks entry point, so it # shows up in the "string ids in the current layout" list. Strip it # so these assertions hold whether or not plotly-cloud is installed. diff --git a/tests/unit/test_plotly_cli.py b/tests/unit/test_plotly_cli.py new file mode 100644 index 0000000000..9cbe34021e --- /dev/null +++ b/tests/unit/test_plotly_cli.py @@ -0,0 +1,24 @@ +import sys +from pathlib import Path + +import pytest + +from dash._plotly_cli import cli + + +def test_plotly_cli_hints_cloud_extra_when_missing(monkeypatch, capsys): + # A None entry in sys.modules makes the import raise ImportError. + monkeypatch.setitem(sys.modules, "plotly_cloud", None) + monkeypatch.setitem(sys.modules, "plotly_cloud.cli", None) + + with pytest.raises(SystemExit) as exc: + cli() + + assert exc.value.code == -1 + assert "pip install dash[cloud]" in capsys.readouterr().err + + +def test_plotly_cloud_is_not_an_install_requirement(): + install = Path(__file__).parents[2] / "requirements" / "install.txt" + required = install.read_text(encoding="utf-8").lower().split() + assert "plotly-cloud" not in required