Skip to content

Commit c3d5b9a

Browse files
committed
update tests for kaleido v0 removal, and add test for error when kaleido v0 is used
1 parent bd54170 commit c3d5b9a

3 files changed

Lines changed: 125 additions & 91 deletions

File tree

tests/test_io/test_renderers.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,6 @@ def test_plotly_mimetype_renderer_show(fig1, renderer):
121121
mock_display.assert_called_once_with(expected, raw=True)
122122

123123

124-
# Static Image
125-
# ------------
126-
# See tests/test_orca/test_image_renderers.py
127-
128-
129124
# HTML
130125
# ----
131126
def assert_full_html(html):
@@ -327,7 +322,7 @@ def test_repr_html(renderer):
327322
assert str_html.replace(id_html, "") == template.replace(id_pattern, "")
328323

329324

330-
all_renderers_without_orca = [
325+
all_renderers = [
331326
"plotly_mimetype",
332327
"jupyterlab",
333328
"nteract",
@@ -350,7 +345,7 @@ def test_repr_html(renderer):
350345
]
351346

352347

353-
@pytest.mark.parametrize("renderer_str", all_renderers_without_orca)
348+
@pytest.mark.parametrize("renderer_str", all_renderers)
354349
def test_repr_mimebundle(renderer_str):
355350
pio.renderers.default = renderer_str
356351
fig = go.Figure()

tests/test_optional/test_kaleido/test_kaleido.py

Lines changed: 45 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
from PIL import Image
1111
import plotly.graph_objects as go
1212
import plotly.io as pio
13-
from plotly.io.kaleido import kaleido_available, kaleido_major
14-
import pytest
1513

1614

1715
fig = {"data": [], "layout": {"title": {"text": "figure title"}}}
@@ -56,8 +54,8 @@ def check_image(path_or_buffer, size=(700, 500), format="PNG"):
5654
assert img.format == format
5755

5856

59-
def test_kaleido_engine_to_image_returns_bytes():
60-
result = pio.to_image(fig, format="svg", engine="kaleido", validate=False)
57+
def test_kaleido_to_image_returns_bytes():
58+
result = pio.to_image(fig, format="svg", validate=False)
6159
assert result.startswith(b"<svg")
6260

6361

@@ -67,37 +65,36 @@ def test_kaleido_fulljson():
6765
assert result["layout"]["calendar"] == "gregorian"
6866

6967

70-
def test_kaleido_engine_to_image():
71-
bytes = pio.to_image(fig, engine="kaleido", validate=False)
68+
def test_kaleido_to_image():
69+
bytes = pio.to_image(fig, validate=False)
7270

7371
# Check that image dimensions match default dimensions (700x500)
7472
# and format is default format (png)
7573
check_image(BytesIO(bytes))
7674

7775

78-
def test_kaleido_engine_write_image(tmp_path):
76+
def test_kaleido_write_image(tmp_path):
7977
path_str = tempfile.mkstemp(suffix=".png", dir=tmp_path)[1]
8078
path_path = Path(tempfile.mkstemp(suffix=".png", dir=tmp_path)[1])
8179

8280
for out_path in [path_str, path_path]:
83-
pio.write_image(fig, out_path, engine="kaleido", validate=False)
81+
pio.write_image(fig, out_path, validate=False)
8482
check_image(out_path)
8583

8684

87-
def test_kaleido_engine_to_image_kwargs():
85+
def test_kaleido_to_image_kwargs():
8886
bytes = pio.to_image(
8987
fig,
9088
format="pdf",
9189
width=700,
9290
height=600,
9391
scale=2,
94-
engine="kaleido",
9592
validate=False,
9693
)
9794
check_image(BytesIO(bytes), size=(700 * 2, 600 * 2), format="PDF")
9895

9996

100-
def test_kaleido_engine_write_image_kwargs(tmp_path):
97+
def test_kaleido_write_image_kwargs(tmp_path):
10198
path_str = tempfile.mkstemp(suffix=".png", dir=tmp_path)[1]
10299
path_path = Path(tempfile.mkstemp(suffix=".png", dir=tmp_path)[1])
103100

@@ -109,17 +106,12 @@ def test_kaleido_engine_write_image_kwargs(tmp_path):
109106
width=700,
110107
height=600,
111108
scale=2,
112-
engine="kaleido",
113109
validate=False,
114110
)
115111
check_image(out_path, size=(700 * 2, 600 * 2), format="JPEG")
116112

117113

118-
@pytest.mark.skipif(
119-
not kaleido_available() or kaleido_major() < 1,
120-
reason="requires Kaleido v1.0.0 or higher",
121-
)
122-
def test_kaleido_engine_write_images(tmp_path):
114+
def test_kaleido_write_images(tmp_path):
123115
fig1 = {"data": [], "layout": {"title": {"text": "figure 1"}}}
124116
fig2 = {"data": [], "layout": {"title": {"text": "figure 2"}}}
125117

@@ -142,15 +134,14 @@ def test_kaleido_engine_write_images(tmp_path):
142134
def test_image_renderer():
143135
"""Verify that the image renderer returns the expected mimebundle."""
144136
with redirect_stdout(StringIO()) as f:
145-
pio.show(fig, renderer="png", engine="kaleido", validate=False)
137+
pio.show(fig, renderer="png", validate=False)
146138
mimebundle = f.getvalue().strip()
147139
mimebundle_expected = str(
148140
{
149141
"image/png": base64.b64encode(
150142
pio.to_image(
151143
fig,
152144
format="png",
153-
engine="kaleido",
154145
validate=False,
155146
)
156147
).decode("utf8")
@@ -166,10 +157,10 @@ def test_bytesio():
166157
which doesn't correspond to a filesystem path.
167158
"""
168159
bio = BytesIO()
169-
pio.write_image(fig, bio, format="jpg", engine="kaleido", validate=False)
160+
pio.write_image(fig, bio, format="jpg", validate=False)
170161
bio.seek(0) # Rewind to the beginning of the buffer, otherwise read() returns b''.
171162
bio_bytes = bio.read()
172-
to_image_bytes = pio.to_image(fig, format="jpg", engine="kaleido", validate=False)
163+
to_image_bytes = pio.to_image(fig, format="jpg", validate=False)
173164
assert bio_bytes == to_image_bytes
174165

175166

@@ -211,45 +202,29 @@ def test_defaults():
211202
assert pio.defaults.topojson == "path/to/topojson/files/"
212203
assert pio.defaults.plotlyjs == "https://cdn.plot.ly/plotly-3.0.0.js"
213204

214-
if kaleido_major() > 0:
215-
# Check that all the defaults values are passed through to the function call to calc_fig_sync
216-
with patch(
217-
"plotly.io._kaleido.kaleido.calc_fig_sync",
218-
return_value=test_image_bytes,
219-
) as mock_calc_fig:
220-
result = pio.to_image(test_fig, validate=False)
221-
222-
# Verify calc_fig_sync was called with correct args
223-
# taken from pio.defaults
224-
mock_calc_fig.assert_called_once()
225-
args, kwargs = mock_calc_fig.call_args
226-
assert args[0] == test_fig.to_dict()
227-
assert kwargs["opts"]["format"] == "svg"
228-
assert kwargs["opts"]["width"] == 701
229-
assert kwargs["opts"]["height"] == 501
230-
assert kwargs["opts"]["scale"] == 2
231-
assert kwargs["topojson"] == "path/to/topojson/files/"
232-
# mathjax and plotlyjs are passed through in kopts
233-
assert (
234-
kwargs["kopts"]["mathjax"]
235-
== "https://cdn.jsdelivr.net/npm/mathjax@3.1.2/es5/tex-svg.js"
236-
)
237-
assert (
238-
kwargs["kopts"]["plotlyjs"] == "https://cdn.plot.ly/plotly-3.0.0.js"
239-
)
240-
241-
else:
242-
# Check that all the default values have been set in pio._kaleido.scope
243-
assert pio._kaleido.scope.default_format == "svg"
244-
assert pio._kaleido.scope.default_width == 701
245-
assert pio._kaleido.scope.default_height == 501
246-
assert pio._kaleido.scope.default_scale == 2
205+
# Check that all the defaults values are passed through to the function call to calc_fig_sync
206+
with patch(
207+
"plotly.io._kaleido.kaleido.calc_fig_sync",
208+
return_value=test_image_bytes,
209+
) as mock_calc_fig:
210+
result = pio.to_image(test_fig, validate=False)
211+
212+
# Verify calc_fig_sync was called with correct args
213+
# taken from pio.defaults
214+
mock_calc_fig.assert_called_once()
215+
args, kwargs = mock_calc_fig.call_args
216+
assert args[0] == test_fig.to_dict()
217+
assert kwargs["opts"]["format"] == "svg"
218+
assert kwargs["opts"]["width"] == 701
219+
assert kwargs["opts"]["height"] == 501
220+
assert kwargs["opts"]["scale"] == 2
221+
assert kwargs["topojson"] == "path/to/topojson/files/"
222+
# mathjax and plotlyjs are passed through in kopts
247223
assert (
248-
pio._kaleido.scope.mathjax
224+
kwargs["kopts"]["mathjax"]
249225
== "https://cdn.jsdelivr.net/npm/mathjax@3.1.2/es5/tex-svg.js"
250226
)
251-
assert pio._kaleido.scope.topojson == "path/to/topojson/files/"
252-
assert pio._kaleido.scope.plotlyjs == "https://cdn.plot.ly/plotly-3.0.0.js"
227+
assert kwargs["kopts"]["plotlyjs"] == "https://cdn.plot.ly/plotly-3.0.0.js"
253228

254229
# Set topojson default back to None
255230
# (otherwise image generation will fail)
@@ -282,12 +257,9 @@ def test_fig_write_image():
282257
test_fig = go.Figure(fig)
283258
test_image_bytes = b"mock image data"
284259

285-
if kaleido_major() > 0:
286-
patch_funcname = "plotly.io._kaleido.kaleido.calc_fig_sync"
287-
else:
288-
patch_funcname = "plotly.io._kaleido.scope.transform"
289-
290-
with patch(patch_funcname, return_value=test_image_bytes) as mock_calc_fig:
260+
with patch(
261+
"plotly.io._kaleido.kaleido.calc_fig_sync", return_value=test_image_bytes
262+
) as mock_calc_fig:
291263
test_fig.write_image("test_path.png")
292264

293265
# Verify patched function was called once with fig dict as first argument
@@ -302,12 +274,9 @@ def test_fig_to_image():
302274
test_fig = go.Figure(fig)
303275
test_image_bytes = b"mock image data"
304276

305-
if kaleido_major() > 0:
306-
patch_funcname = "plotly.io._kaleido.kaleido.calc_fig_sync"
307-
else:
308-
patch_funcname = "plotly.io._kaleido.scope.transform"
309-
310-
with patch(patch_funcname, return_value=test_image_bytes) as mock_calc_fig:
277+
with patch(
278+
"plotly.io._kaleido.kaleido.calc_fig_sync", return_value=test_image_bytes
279+
) as mock_calc_fig:
311280
test_fig.to_image()
312281

313282
# Verify patched function was called once with fig dict as first argument
@@ -319,22 +288,14 @@ def test_fig_to_image():
319288
def test_get_chrome():
320289
"""Test that plotly.io.get_chrome() can be called."""
321290

322-
if not kaleido_available() or kaleido_major() < 1:
323-
# Test that ValueError is raised when Kaleido requirements aren't met
324-
with pytest.raises(
325-
ValueError, match="This command requires Kaleido v1.0.0 or greater"
326-
):
327-
pio.get_chrome()
328-
else:
329-
# Test normal operation when Kaleido v1+ is available
330-
with patch(
331-
"plotly.io._kaleido.kaleido.get_chrome_sync",
332-
return_value="/mock/path/to/chrome",
333-
) as mock_get_chrome:
334-
pio.get_chrome()
291+
with patch(
292+
"plotly.io._kaleido.kaleido.get_chrome_sync",
293+
return_value="/mock/path/to/chrome",
294+
) as mock_get_chrome:
295+
pio.get_chrome()
335296

336-
# Verify that kaleido.get_chrome_sync was called
337-
mock_get_chrome.assert_called_once()
297+
# Verify that kaleido.get_chrome_sync was called
298+
mock_get_chrome.assert_called_once()
338299

339300

340301
def test_width_height_priority():
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""
2+
Tests that every function requiring Kaleido raises a RuntimeError with the
3+
correct message when Kaleido v0 is installed.
4+
"""
5+
6+
import pytest
7+
8+
import plotly.graph_objects as go
9+
import plotly.io as pio
10+
from plotly.io._kaleido import kaleido_available
11+
12+
13+
# Skip every test in this module if Kaleido v1 is installed
14+
pytestmark = pytest.mark.skipif(
15+
kaleido_available(),
16+
reason="These tests only apply when Kaleido v1 is not installed.",
17+
)
18+
19+
20+
fig = {"data": [], "layout": {"title": {"text": "figure title"}}}
21+
22+
23+
def assert_error_message_contents(excinfo):
24+
"""Check that the raised RuntimeError has the expected wording."""
25+
assert "Image export requires the Kaleido package, v1.0.0 or greater" in str(
26+
excinfo.value
27+
)
28+
29+
30+
# plotly/io/_kaleido.py
31+
32+
33+
def test_to_image_raises():
34+
with pytest.raises(RuntimeError) as excinfo:
35+
pio.to_image(fig, format="png", validate=False)
36+
assert_error_message_contents(excinfo)
37+
38+
39+
def test_write_image_raises(tmp_path):
40+
with pytest.raises(RuntimeError) as excinfo:
41+
pio.write_image(fig, tmp_path / "test.png", validate=False)
42+
assert_error_message_contents(excinfo)
43+
44+
45+
def test_full_figure_for_development_raises():
46+
with pytest.raises(RuntimeError) as excinfo:
47+
pio.full_figure_for_development(fig, warn=False)
48+
assert_error_message_contents(excinfo)
49+
50+
51+
def test_get_chrome_raises():
52+
with pytest.raises(RuntimeError) as excinfo:
53+
pio.get_chrome()
54+
assert_error_message_contents(excinfo)
55+
56+
57+
# plotly/basedatatypes.py
58+
59+
60+
def test_figure_to_image_raises():
61+
test_fig = go.Figure(fig)
62+
with pytest.raises(RuntimeError) as excinfo:
63+
test_fig.to_image(format="png", validate=False)
64+
assert_error_message_contents(excinfo)
65+
66+
67+
def test_figure_write_image_raises(tmp_path):
68+
test_fig = go.Figure(fig)
69+
with pytest.raises(RuntimeError) as excinfo:
70+
test_fig.write_image(tmp_path / "test.png", validate=False)
71+
assert_error_message_contents(excinfo)
72+
73+
74+
def test_figure_full_figure_for_development_raises():
75+
test_fig = go.Figure(fig)
76+
with pytest.raises(RuntimeError) as excinfo:
77+
test_fig.full_figure_for_development(warn=False)
78+
assert_error_message_contents(excinfo)

0 commit comments

Comments
 (0)