Skip to content

Commit 3afcd45

Browse files
authored
Merge pull request #5207 from plotly/support-setting-plotlyjs-path
Support setting plotly.js path for Kaleido v1 image export
2 parents 1d6d3bc + fdab92c commit 3afcd45

File tree

5 files changed

+108
-18
lines changed

5 files changed

+108
-18
lines changed

plotly/io/_defaults.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ def __init__(self):
1313
self.default_scale = 1
1414
self.mathjax = None
1515
self.topojson = None
16+
self.plotlyjs = None
1617

1718

1819
defaults = _Defaults()

plotly/io/_kaleido.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,12 @@ def to_image(
369369
from kaleido.errors import ChromeNotFoundError
370370

371371
try:
372+
kopts = {}
373+
if defaults.plotlyjs:
374+
kopts["plotlyjs"] = defaults.plotlyjs
375+
if defaults.mathjax:
376+
kopts["mathjax"] = defaults.mathjax
377+
372378
# TODO: Refactor to make it possible to use a shared Kaleido instance here
373379
img_bytes = kaleido.calc_fig_sync(
374380
fig_dict,
@@ -379,13 +385,7 @@ def to_image(
379385
scale=scale or defaults.default_scale,
380386
),
381387
topojson=defaults.topojson,
382-
kopts=(
383-
dict(
384-
mathjax=defaults.mathjax,
385-
)
386-
if defaults.mathjax
387-
else None
388-
),
388+
kopts=kopts,
389389
)
390390
except ChromeNotFoundError:
391391
raise RuntimeError(PLOTLY_GET_CHROME_ERROR_MSG)
@@ -692,15 +692,14 @@ def write_images(
692692
from kaleido.errors import ChromeNotFoundError
693693

694694
try:
695+
kopts = {}
696+
if defaults.plotlyjs:
697+
kopts["plotlyjs"] = defaults.plotlyjs
698+
if defaults.mathjax:
699+
kopts["mathjax"] = defaults.mathjax
695700
kaleido.write_fig_from_object_sync(
696701
kaleido_specs,
697-
kopts=(
698-
dict(
699-
mathjax=defaults.mathjax,
700-
)
701-
if defaults.mathjax
702-
else None
703-
),
702+
kopts=kopts,
704703
)
705704
except ChromeNotFoundError:
706705
raise RuntimeError(PLOTLY_GET_CHROME_ERROR_MSG)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ dependencies = [
4646

4747
[project.optional-dependencies]
4848
express = ["numpy"]
49-
kaleido = ["kaleido==1.0.0rc13"]
49+
kaleido = ["kaleido==1.0.0rc15"]
5050
dev = ["black==25.1.0"]
5151

5252
[project.scripts]

test_requirements/requirements_optional.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ matplotlib
1818
scikit-image
1919
psutil
2020
# kaleido>=1.0.0 # Uncomment and delete line below once Kaleido v1 is released
21-
kaleido==1.0.0rc13
21+
kaleido==1.0.0rc15
2222
orjson
2323
polars[timezone]
2424
pyarrow

tests/test_optional/test_kaleido/test_kaleido.py

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,105 @@ def test_bytesio():
154154

155155
def test_defaults():
156156
"""Test that image output defaults can be set using pio.defaults.*"""
157+
test_fig = go.Figure(fig)
158+
test_image_bytes = b"mock image data"
159+
160+
# Check initial defaults
161+
assert pio.defaults.default_format == "png"
162+
assert pio.defaults.default_width == 700
163+
assert pio.defaults.default_height == 500
164+
assert pio.defaults.default_scale == 1
165+
assert pio.defaults.mathjax is None
166+
assert pio.defaults.topojson is None
167+
assert pio.defaults.plotlyjs is None
168+
157169
try:
158-
assert pio.defaults.default_format == "png"
170+
# Set new defaults
159171
pio.defaults.default_format = "svg"
172+
pio.defaults.default_width = 701
173+
pio.defaults.default_height = 501
174+
pio.defaults.default_scale = 2
175+
pio.defaults.mathjax = (
176+
"https://cdn.jsdelivr.net/npm/[email protected]/es5/tex-svg.js"
177+
)
178+
pio.defaults.topojson = "path/to/topojson/files/"
179+
pio.defaults.plotlyjs = "https://cdn.plot.ly/plotly-3.0.0.js"
180+
181+
# Check that new defaults are saved
160182
assert pio.defaults.default_format == "svg"
161-
result = pio.to_image(fig, format="svg", validate=False)
183+
assert pio.defaults.default_width == 701
184+
assert pio.defaults.default_height == 501
185+
assert pio.defaults.default_scale == 2
186+
assert (
187+
pio.defaults.mathjax
188+
== "https://cdn.jsdelivr.net/npm/[email protected]/es5/tex-svg.js"
189+
)
190+
assert pio.defaults.topojson == "path/to/topojson/files/"
191+
assert pio.defaults.plotlyjs == "https://cdn.plot.ly/plotly-3.0.0.js"
192+
193+
if kaleido_major() > 0:
194+
# Check that all the defaults values are passed through to the function call to calc_fig_sync
195+
with patch(
196+
"plotly.io._kaleido.kaleido.calc_fig_sync",
197+
return_value=test_image_bytes,
198+
) as mock_calc_fig:
199+
result = pio.to_image(test_fig, validate=False)
200+
201+
# Verify calc_fig_sync was called with correct args
202+
# taken from pio.defaults
203+
mock_calc_fig.assert_called_once()
204+
args, kwargs = mock_calc_fig.call_args
205+
assert args[0] == test_fig.to_dict()
206+
assert kwargs["opts"]["format"] == "svg"
207+
assert kwargs["opts"]["width"] == 701
208+
assert kwargs["opts"]["height"] == 501
209+
assert kwargs["opts"]["scale"] == 2
210+
assert kwargs["topojson"] == "path/to/topojson/files/"
211+
# mathjax and plotlyjs are passed through in kopts
212+
assert (
213+
kwargs["kopts"]["mathjax"]
214+
== "https://cdn.jsdelivr.net/npm/[email protected]/es5/tex-svg.js"
215+
)
216+
assert (
217+
kwargs["kopts"]["plotlyjs"] == "https://cdn.plot.ly/plotly-3.0.0.js"
218+
)
219+
220+
else:
221+
# Check that all the default values have been set in pio._kaleido.scope
222+
assert pio._kaleido.scope.default_format == "svg"
223+
assert pio._kaleido.scope.default_width == 701
224+
assert pio._kaleido.scope.default_height == 501
225+
assert pio._kaleido.scope.default_scale == 2
226+
assert (
227+
pio._kaleido.scope.mathjax
228+
== "https://cdn.jsdelivr.net/npm/[email protected]/es5/tex-svg.js"
229+
)
230+
assert pio._kaleido.scope.topojson == "path/to/topojson/files/"
231+
assert pio._kaleido.scope.plotlyjs == "https://cdn.plot.ly/plotly-3.0.0.js"
232+
233+
# Set topojson default back to None
234+
# (otherwise image generation will fail)
235+
pio.defaults.topojson = None
236+
# Generate image for real and make sure it's an SVG
237+
result = test_fig.to_image(format="svg", validate=False)
162238
assert result.startswith(b"<svg")
239+
163240
finally:
241+
# Reset defaults to original values and check that they are restored
164242
pio.defaults.default_format = "png"
243+
pio.defaults.default_width = 700
244+
pio.defaults.default_height = 500
245+
pio.defaults.default_scale = 1
246+
pio.defaults.mathjax = None
247+
pio.defaults.topojson = None
248+
pio.defaults.plotlyjs = None
165249
assert pio.defaults.default_format == "png"
250+
assert pio.defaults.default_width == 700
251+
assert pio.defaults.default_height == 500
252+
assert pio.defaults.default_scale == 1
253+
assert pio.defaults.mathjax is None
254+
assert pio.defaults.topojson is None
255+
assert pio.defaults.plotlyjs is None
166256

167257

168258
def test_fig_write_image():

0 commit comments

Comments
 (0)