1
- import plotly .io as pio
2
- import plotly .io .kaleido
3
- from contextlib import contextmanager
4
1
from io import BytesIO
5
2
from pathlib import Path
6
- from unittest .mock import Mock
7
-
8
- fig = {"layout" : {"title" : {"text" : "figure title" }}}
9
-
10
-
11
- def make_writeable_mocks ():
12
- """Produce some mocks which we will use for testing the `write_image()` function.
13
-
14
- These mocks should be passed as the `file=` argument to `write_image()`.
15
-
16
- The tests should verify that the method specified in the `active_write_function`
17
- attribute is called once, and that scope.transform is called with the `format=`
18
- argument specified by the `.expected_format` attribute.
19
-
20
- In total we provide two mocks: one for a writable file descriptor, and other for a
21
- pathlib.Path object.
22
- """
23
-
24
- # Part 1: A mock for a file descriptor
25
- # ------------------------------------
26
- mock_file_descriptor = Mock ()
3
+ import tempfile
27
4
28
- # A file descriptor has no write_bytes method, unlike a pathlib Path.
29
- del mock_file_descriptor .write_bytes
30
-
31
- # The expected write method for a file descriptor is .write
32
- mock_file_descriptor .active_write_function = mock_file_descriptor .write
33
-
34
- # Since there is no filename, there should be no format detected.
35
- mock_file_descriptor .expected_format = None
36
-
37
- # Part 2: A mock for a pathlib path
38
- # ---------------------------------
39
- mock_pathlib_path = Mock (spec = Path )
40
-
41
- # A pathlib Path object has no write method, unlike a file descriptor.
42
- del mock_pathlib_path .write
43
-
44
- # The expected write method for a pathlib Path is .write_bytes
45
- mock_pathlib_path .active_write_function = mock_pathlib_path .write_bytes
46
-
47
- # Mock a path with PNG suffix
48
- mock_pathlib_path .suffix = ".png"
49
- mock_pathlib_path .expected_format = "png"
5
+ from pdfrw import PdfReader
6
+ from PIL import Image
7
+ import plotly .io as pio
50
8
51
- return mock_file_descriptor , mock_pathlib_path
9
+ fig = { "data" : [], "layout" : { "title" : { "text" : "figure title" }}}
52
10
53
11
54
- @contextmanager
55
- def mocked_scope ():
56
- # Code to acquire resource, e.g.:
57
- scope_mock = Mock ()
58
- original_scope = pio ._kaleido .scope
59
- pio ._kaleido .scope = scope_mock
60
- try :
61
- yield scope_mock
62
- finally :
63
- pio ._kaleido .scope = original_scope
12
+ def check_image (path_or_buffer , size = (700 , 500 ), format = "PNG" ):
13
+ if format == "PDF" :
14
+ img = PdfReader (path_or_buffer )
15
+ # TODO: There is a conversion factor needed here
16
+ # In Kaleido v0 the conversion factor is 0.75
17
+ factor = 0.75
18
+ expected_size = tuple (int (s * factor ) for s in size )
19
+ actual_size = tuple (int (s ) for s in img .pages [0 ].MediaBox [2 :])
20
+ assert actual_size == expected_size
21
+ else :
22
+ if isinstance (path_or_buffer , (str , Path )):
23
+ with open (path_or_buffer , "rb" ) as f :
24
+ img = Image .open (f )
25
+ else :
26
+ img = Image .open (path_or_buffer )
27
+ assert img .size == size
28
+ assert img .format == format
64
29
65
30
66
31
def test_kaleido_engine_to_image_returns_bytes ():
@@ -75,80 +40,66 @@ def test_kaleido_fulljson():
75
40
76
41
77
42
def test_kaleido_engine_to_image ():
78
- with mocked_scope () as scope :
79
- pio .to_image (fig , engine = "kaleido" , validate = False )
43
+ bytes = pio .to_image (fig , engine = "kaleido" , validate = False )
80
44
81
- scope . transform . assert_called_with (
82
- fig , format = None , width = None , height = None , scale = None
83
- )
45
+ # Check that image dimensions match default dimensions (700x500)
46
+ # and format is default format (png)
47
+ check_image ( BytesIO ( bytes ) )
84
48
85
49
86
- def test_kaleido_engine_write_image ():
87
- for writeable_mock in make_writeable_mocks ():
88
- with mocked_scope () as scope :
89
- pio .write_image (fig , writeable_mock , engine = "kaleido" , validate = False )
50
+ def test_kaleido_engine_write_image (tmp_path ):
51
+ path_str = tempfile .mkstemp (suffix = ".png" , dir = tmp_path )[1 ]
52
+ path_path = Path (tempfile .mkstemp (suffix = ".png" , dir = tmp_path )[1 ])
90
53
91
- scope .transform .assert_called_with (
92
- fig ,
93
- format = writeable_mock .expected_format ,
94
- width = None ,
95
- height = None ,
96
- scale = None ,
97
- )
98
-
99
- assert writeable_mock .active_write_function .call_count == 1
54
+ for out_path in [path_str , path_path ]:
55
+ pio .write_image (fig , out_path , engine = "kaleido" , validate = False )
56
+ check_image (out_path )
100
57
101
58
102
59
def test_kaleido_engine_to_image_kwargs ():
103
- with mocked_scope () as scope :
104
- pio .to_image (
60
+ bytes = pio .to_image (
61
+ fig ,
62
+ format = "pdf" ,
63
+ width = 700 ,
64
+ height = 600 ,
65
+ scale = 2 ,
66
+ engine = "kaleido" ,
67
+ validate = False ,
68
+ )
69
+ check_image (BytesIO (bytes ), size = (700 * 2 , 600 * 2 ), format = "PDF" )
70
+
71
+
72
+ def test_kaleido_engine_write_image_kwargs (tmp_path ):
73
+ path_str = tempfile .mkstemp (suffix = ".png" , dir = tmp_path )[1 ]
74
+ path_path = Path (tempfile .mkstemp (suffix = ".png" , dir = tmp_path )[1 ])
75
+
76
+ for out_path in [path_str , path_path ]:
77
+ pio .write_image (
105
78
fig ,
106
- format = "pdf" ,
79
+ out_path ,
80
+ format = "jpg" ,
107
81
width = 700 ,
108
82
height = 600 ,
109
83
scale = 2 ,
110
84
engine = "kaleido" ,
111
85
validate = False ,
112
86
)
113
-
114
- scope .transform .assert_called_with (
115
- fig , format = "pdf" , width = 700 , height = 600 , scale = 2
116
- )
117
-
118
-
119
- def test_kaleido_engine_write_image_kwargs ():
120
- for writeable_mock in make_writeable_mocks ():
121
- with mocked_scope () as scope :
122
- pio .write_image (
123
- fig ,
124
- writeable_mock ,
125
- format = "jpg" ,
126
- width = 700 ,
127
- height = 600 ,
128
- scale = 2 ,
129
- engine = "kaleido" ,
130
- validate = False ,
131
- )
132
-
133
- scope .transform .assert_called_with (
134
- fig , format = "jpg" , width = 700 , height = 600 , scale = 2
135
- )
136
-
137
- assert writeable_mock .active_write_function .call_count == 1
87
+ check_image (out_path , size = (700 * 2 , 600 * 2 ), format = "JPEG" )
138
88
139
89
140
90
def test_image_renderer ():
141
- with mocked_scope () as scope :
142
- pio .show (fig , renderer = "svg" , engine = "kaleido" , validate = False )
91
+ # TODO: How to replicate this test using kaleido v1?
92
+ # with mocked_scope() as scope:
93
+ pio .show (fig , renderer = "svg" , engine = "kaleido" , validate = False )
143
94
144
95
renderer = pio .renderers ["svg" ]
145
- scope .transform .assert_called_with (
146
- fig ,
147
- format = "svg" ,
148
- width = None ,
149
- height = None ,
150
- scale = renderer .scale ,
151
- )
96
+ # scope.transform.assert_called_with(
97
+ # fig,
98
+ # format="svg",
99
+ # width=None,
100
+ # height=None,
101
+ # scale=renderer.scale,
102
+ # )
152
103
153
104
154
105
def test_bytesio ():
0 commit comments