diff --git a/README.md b/README.md index e0b23b1c1ef..11f117aca59 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ See the [Python documentation](https://plotly.com/python/) for more examples. Built on top of [plotly.js](https://github.com/plotly/plotly.js), `plotly.py` is a high-level, declarative charting library. plotly.js ships with over 30 chart types, including scientific charts, 3D graphs, statistical charts, SVG maps, financial charts, and more. -`plotly.py` is [MIT Licensed](https://github.com/plotly/plotly.py/blob/main/LICENSE.txt). Plotly graphs can be viewed in Jupyter notebooks, standalone HTML files, or integrated into [Dash applications](https://dash.plotly.com/). +`plotly.py` is [MIT Licensed](https://github.com/plotly/plotly.py/blob/main/LICENSE.txt). Plotly graphs can be viewed in [Jupyter notebooks](https://jupyter.org), other Python notebook software such as [marimo](https://marimo.io), as standalone HTML files, or integrated into [Dash applications](https://dash.plotly.com/). [Contact us](https://plotly.com/consulting-and-oem/) for consulting, dashboard development, application integration, and feature additions. diff --git a/plotly/io/_defaults.py b/plotly/io/_defaults.py index a2a98884c9c..c36530c342d 100644 --- a/plotly/io/_defaults.py +++ b/plotly/io/_defaults.py @@ -13,6 +13,7 @@ def __init__(self): self.default_scale = 1 self.mathjax = None self.topojson = None + self.plotlyjs = None defaults = _Defaults() diff --git a/plotly/io/_kaleido.py b/plotly/io/_kaleido.py index fe997a29920..a76ad460286 100644 --- a/plotly/io/_kaleido.py +++ b/plotly/io/_kaleido.py @@ -369,6 +369,12 @@ def to_image( from kaleido.errors import ChromeNotFoundError try: + kopts = {} + if defaults.plotlyjs: + kopts["plotlyjs"] = defaults.plotlyjs + if defaults.mathjax: + kopts["mathjax"] = defaults.mathjax + # TODO: Refactor to make it possible to use a shared Kaleido instance here img_bytes = kaleido.calc_fig_sync( fig_dict, @@ -379,13 +385,7 @@ def to_image( scale=scale or defaults.default_scale, ), topojson=defaults.topojson, - kopts=( - dict( - mathjax=defaults.mathjax, - ) - if defaults.mathjax - else None - ), + kopts=kopts, ) except ChromeNotFoundError: raise RuntimeError(PLOTLY_GET_CHROME_ERROR_MSG) @@ -692,15 +692,14 @@ def write_images( from kaleido.errors import ChromeNotFoundError try: + kopts = {} + if defaults.plotlyjs: + kopts["plotlyjs"] = defaults.plotlyjs + if defaults.mathjax: + kopts["mathjax"] = defaults.mathjax kaleido.write_fig_from_object_sync( kaleido_specs, - kopts=( - dict( - mathjax=defaults.mathjax, - ) - if defaults.mathjax - else None - ), + kopts=kopts, ) except ChromeNotFoundError: raise RuntimeError(PLOTLY_GET_CHROME_ERROR_MSG) diff --git a/pyproject.toml b/pyproject.toml index 98f9876bca9..426d98306f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ dependencies = [ [project.optional-dependencies] express = ["numpy"] -kaleido = ["kaleido==1.0.0rc13"] +kaleido = ["kaleido==1.0.0rc15"] dev = ["black==25.1.0"] [project.scripts] @@ -70,8 +70,7 @@ line-length = 88 target_version = ['py38', 'py39', 'py310', 'py311', 'py312'] include = '\.pyi?$' exclude = ''' - -( +/( \.eggs # exclude a few common directories in the | \.git # root of the project | \.hg @@ -85,7 +84,7 @@ exclude = ''' | js | submodules | plotly/matplotlylib/mplexporter -) +)/ ''' [tool.jupyter-packaging.builder] diff --git a/test_requirements/requirements_optional.txt b/test_requirements/requirements_optional.txt index 7aad4821610..1c385d989bd 100644 --- a/test_requirements/requirements_optional.txt +++ b/test_requirements/requirements_optional.txt @@ -18,7 +18,7 @@ matplotlib scikit-image psutil # kaleido>=1.0.0 # Uncomment and delete line below once Kaleido v1 is released -kaleido==1.0.0rc13 +kaleido==1.0.0rc15 orjson polars[timezone] pyarrow diff --git a/tests/test_optional/test_kaleido/test_kaleido.py b/tests/test_optional/test_kaleido/test_kaleido.py index 84b07772307..47ac263ccfc 100644 --- a/tests/test_optional/test_kaleido/test_kaleido.py +++ b/tests/test_optional/test_kaleido/test_kaleido.py @@ -154,15 +154,105 @@ def test_bytesio(): def test_defaults(): """Test that image output defaults can be set using pio.defaults.*""" + test_fig = go.Figure(fig) + test_image_bytes = b"mock image data" + + # Check initial defaults + assert pio.defaults.default_format == "png" + assert pio.defaults.default_width == 700 + assert pio.defaults.default_height == 500 + assert pio.defaults.default_scale == 1 + assert pio.defaults.mathjax is None + assert pio.defaults.topojson is None + assert pio.defaults.plotlyjs is None + try: - assert pio.defaults.default_format == "png" + # Set new defaults pio.defaults.default_format = "svg" + pio.defaults.default_width = 701 + pio.defaults.default_height = 501 + pio.defaults.default_scale = 2 + pio.defaults.mathjax = ( + "https://cdn.jsdelivr.net/npm/mathjax@3.1.2/es5/tex-svg.js" + ) + pio.defaults.topojson = "path/to/topojson/files/" + pio.defaults.plotlyjs = "https://cdn.plot.ly/plotly-3.0.0.js" + + # Check that new defaults are saved assert pio.defaults.default_format == "svg" - result = pio.to_image(fig, format="svg", validate=False) + assert pio.defaults.default_width == 701 + assert pio.defaults.default_height == 501 + assert pio.defaults.default_scale == 2 + assert ( + pio.defaults.mathjax + == "https://cdn.jsdelivr.net/npm/mathjax@3.1.2/es5/tex-svg.js" + ) + assert pio.defaults.topojson == "path/to/topojson/files/" + assert pio.defaults.plotlyjs == "https://cdn.plot.ly/plotly-3.0.0.js" + + if kaleido_major() > 0: + # Check that all the defaults values are passed through to the function call to calc_fig_sync + with patch( + "plotly.io._kaleido.kaleido.calc_fig_sync", + return_value=test_image_bytes, + ) as mock_calc_fig: + result = pio.to_image(test_fig, validate=False) + + # Verify calc_fig_sync was called with correct args + # taken from pio.defaults + mock_calc_fig.assert_called_once() + args, kwargs = mock_calc_fig.call_args + assert args[0] == test_fig.to_dict() + assert kwargs["opts"]["format"] == "svg" + assert kwargs["opts"]["width"] == 701 + assert kwargs["opts"]["height"] == 501 + assert kwargs["opts"]["scale"] == 2 + assert kwargs["topojson"] == "path/to/topojson/files/" + # mathjax and plotlyjs are passed through in kopts + assert ( + kwargs["kopts"]["mathjax"] + == "https://cdn.jsdelivr.net/npm/mathjax@3.1.2/es5/tex-svg.js" + ) + assert ( + kwargs["kopts"]["plotlyjs"] == "https://cdn.plot.ly/plotly-3.0.0.js" + ) + + else: + # Check that all the default values have been set in pio._kaleido.scope + assert pio._kaleido.scope.default_format == "svg" + assert pio._kaleido.scope.default_width == 701 + assert pio._kaleido.scope.default_height == 501 + assert pio._kaleido.scope.default_scale == 2 + assert ( + pio._kaleido.scope.mathjax + == "https://cdn.jsdelivr.net/npm/mathjax@3.1.2/es5/tex-svg.js" + ) + assert pio._kaleido.scope.topojson == "path/to/topojson/files/" + assert pio._kaleido.scope.plotlyjs == "https://cdn.plot.ly/plotly-3.0.0.js" + + # Set topojson default back to None + # (otherwise image generation will fail) + pio.defaults.topojson = None + # Generate image for real and make sure it's an SVG + result = test_fig.to_image(format="svg", validate=False) assert result.startswith(b" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy