diff --git a/CHANGELOG.md b/CHANGELOG.md index c2a32064c2..0e344008d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Repair crash on Matplotlib 3.8 related to get_offset_position [[#4372](https://github.com/plotly/plotly.py/pull/4372)], - Handle deprecation of `pandas.Series.dt.to_pydatetime()` calls and suppress the `FutureWarning` they currently emit. [[#4379](https://github.com/plotly/plotly.py/pull/4379)] +- Add DeepnoteRenderer to pio.renderers [[#4389](https://github.com/plotly/plotly.py/pull/4389)] ## [5.17.0] - 2023-09-15 diff --git a/doc/python/renderers.md b/doc/python/renderers.md index 53c8a8b615..3ea9705b63 100644 --- a/doc/python/renderers.md +++ b/doc/python/renderers.md @@ -74,7 +74,7 @@ fig > To be precise, figures will display themselves using the current default renderer when the two following conditions are true. First, the last expression in a cell must evaluate to a figure. Second, `plotly.py` must be running from within an `IPython` kernel. -**In many contexts, an appropriate renderer will be chosen automatically and you will not need to perform any additional configuration.** These contexts include the classic [Jupyter Notebook](https://jupyter.org/), [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/), [Visual Studio Code notebooks](https://code.visualstudio.com/docs/python/jupyter-support), [Google Colaboratory](https://colab.research.google.com/notebooks/intro.ipynb), [Kaggle](https://www.kaggle.com/kernels) notebooks, [Azure](https://notebooks.azure.com/) notebooks, and the [Python interactive shell](https://www.python.org/shell/). +**In many contexts, an appropriate renderer will be chosen automatically and you will not need to perform any additional configuration.** These contexts include the classic [Jupyter Notebook](https://jupyter.org/), [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/), [Visual Studio Code notebooks](https://code.visualstudio.com/docs/python/jupyter-support), [Google Colaboratory](https://colab.research.google.com/notebooks/intro.ipynb), [Kaggle](https://www.kaggle.com/kernels) notebooks, [Azure](https://notebooks.azure.com/) notebooks, [Deepnote](https://deepnote.com/) notebooks, and the [Python interactive shell](https://www.python.org/shell/). Additional contexts are supported by choosing a compatible renderer including the [IPython console](https://docs.spyder-ide.org/ipythonconsole.html), [QtConsole](https://qtconsole.readthedocs.io/en/stable/), [Spyder](https://www.spyder-ide.org/), and more. @@ -138,6 +138,9 @@ These are aliases for `notebook_connected` because this renderer is a good choic ###### `colab` This is a custom renderer for use with [Google Colab](https://colab.research.google.com). +###### `deepnote` +This is a custom renderer for use with [Deepnote](https://deepnote.com/) notebooks. + ###### `browser` This renderer will open a figure in a browser tab using the default web browser. This renderer can only be used when the Python kernel is running locally on the same machine as the web browser, so it is not compatible with Jupyter Hub or online notebook services. diff --git a/packages/python/plotly/plotly/io/_base_renderers.py b/packages/python/plotly/plotly/io/_base_renderers.py index 5a75f01063..ecc505f1a2 100644 --- a/packages/python/plotly/plotly/io/_base_renderers.py +++ b/packages/python/plotly/plotly/io/_base_renderers.py @@ -506,6 +506,31 @@ def __init__( ) +class DeepnoteRenderer(HtmlRenderer): + """ + Renderer to display interactive figures in Deepnote Notebooks. + + This renderer is enabled by default when running in a Deepnote notebook. + + mime type: 'text/html' + """ + + def __init__( + self, config=None, auto_play=False, post_script=None, animation_opts=None + ): + + super(DeepnoteRenderer, self).__init__( + connected=True, + full_html=True, + requirejs=False, + global_init=False, + config=config, + auto_play=auto_play, + post_script=post_script, + animation_opts=animation_opts, + ) + + class IFrameRenderer(MimetypeRenderer): """ Renderer to display interactive figures using an IFrame. HTML diff --git a/packages/python/plotly/plotly/io/_renderers.py b/packages/python/plotly/plotly/io/_renderers.py index 325443262b..613df1241f 100644 --- a/packages/python/plotly/plotly/io/_renderers.py +++ b/packages/python/plotly/plotly/io/_renderers.py @@ -14,6 +14,7 @@ KaggleRenderer, AzureRenderer, ColabRenderer, + DeepnoteRenderer, JsonRenderer, PngRenderer, JpegRenderer, @@ -418,6 +419,7 @@ def show(fig, renderer=None, validate=True, **kwargs): renderers["kaggle"] = KaggleRenderer(config=config) renderers["azure"] = AzureRenderer(config=config) renderers["colab"] = ColabRenderer(config=config) +renderers["deepnote"] = DeepnoteRenderer(config=config) renderers["cocalc"] = CoCalcRenderer() renderers["databricks"] = DatabricksRenderer() diff --git a/packages/python/plotly/plotly/io/base_renderers.py b/packages/python/plotly/plotly/io/base_renderers.py index c47ffc4ca9..842e204c12 100644 --- a/packages/python/plotly/plotly/io/base_renderers.py +++ b/packages/python/plotly/plotly/io/base_renderers.py @@ -9,6 +9,7 @@ JpegRenderer, HtmlRenderer, ColabRenderer, + DeepnoteRenderer, KaggleRenderer, NotebookRenderer, ExternalRenderer, diff --git a/packages/python/plotly/plotly/tests/test_io/test_renderers.py b/packages/python/plotly/plotly/tests/test_io/test_renderers.py index 63305cc719..f6db25a066 100644 --- a/packages/python/plotly/plotly/tests/test_io/test_renderers.py +++ b/packages/python/plotly/plotly/tests/test_io/test_renderers.py @@ -177,6 +177,30 @@ def test_colab_renderer_show(fig1): assert mock_kwargs == {"raw": True} +def test_deepnote_renderer_show(fig1): + pio.renderers.default = "deepnote" + + with mock.patch("IPython.display.display") as mock_display: + pio.show(fig1) + + # Get display call arguments + mock_call_args = mock_display.call_args + mock_arg1 = mock_call_args[0][0] + + # Check for html bundle + assert list(mock_arg1) == ["text/html"] + + # Check html contents + html = mock_arg1["text/html"] + assert_full_html(html) + assert_html_renderer_connected(html) + assert_not_requirejs(html) + + # check kwargs + mock_kwargs = mock_call_args[1] + assert mock_kwargs == {"raw": True} + + @pytest.mark.parametrize( "name,connected", [("notebook", False), ("notebook_connected", True), ("kaggle", True)], @@ -344,6 +368,7 @@ def test_repr_html(renderer): "colab", "cocalc", "databricks", + "deepnote", "json", "browser", "firefox",