2
2
from nose import with_setup
3
3
from nose .plugins .attrib import attr
4
4
5
+ from unittest import TestCase
6
+
7
+ import math
8
+ import pytz
5
9
from datetime import datetime as dt
6
10
import datetime
7
11
import numpy as np
16
20
from plotly .matplotlylib import Exporter , PlotlyRenderer
17
21
from plotly .plotly import plot
18
22
23
+
24
+ class TestJSONEncoder (TestCase ):
25
+
26
+ def test_encode_as_plotly (self ):
27
+
28
+ # should *fail* when object doesn't have `to_plotly_json` attribute
29
+ objs_without_attr = [
30
+ 1 , 'one' , {'a' , 'set' }, {'a' : 'dict' }, ['a' , 'list' ]
31
+ ]
32
+ for obj in objs_without_attr :
33
+ self .assertRaises (utils .NotEncodable ,
34
+ utils .PlotlyJSONEncoder .encode_as_plotly , obj )
35
+
36
+ # should return without exception when obj has `to_plotly_josn` attr
37
+ expected_res = 'wedidit'
38
+
39
+ class ObjWithAttr (object ):
40
+
41
+ def to_plotly_json (self ):
42
+ return expected_res
43
+
44
+ res = utils .PlotlyJSONEncoder .encode_as_plotly (ObjWithAttr ())
45
+ self .assertEqual (res , expected_res )
46
+
47
+ def test_encode_as_list (self ):
48
+
49
+ # should *fail* when object doesn't have `tolist` method
50
+ objs_without_attr = [
51
+ 1 , 'one' , {'a' , 'set' }, {'a' : 'dict' }, ['a' , 'list' ]
52
+ ]
53
+ for obj in objs_without_attr :
54
+ self .assertRaises (utils .NotEncodable ,
55
+ utils .PlotlyJSONEncoder .encode_as_list , obj )
56
+
57
+ # should return without exception when obj has `tolist` attr
58
+ expected_res = ['some' , 'list' ]
59
+
60
+ class ObjWithAttr (object ):
61
+
62
+ def tolist (self ):
63
+ return expected_res
64
+
65
+ res = utils .PlotlyJSONEncoder .encode_as_list (ObjWithAttr ())
66
+ self .assertEqual (res , expected_res )
67
+
68
+ def test_encode_as_pandas (self ):
69
+
70
+ # should *fail* on things that are not specific pandas objects
71
+ not_pandas = ['giraffe' , 6 , float ('nan' ), ['a' , 'list' ]]
72
+ for obj in not_pandas :
73
+ self .assertRaises (utils .NotEncodable ,
74
+ utils .PlotlyJSONEncoder .encode_as_pandas , obj )
75
+
76
+ # should succeed when we've got specific pandas thingies
77
+ res = utils .PlotlyJSONEncoder .encode_as_pandas (pd .NaT )
78
+ self .assertIs (res , None )
79
+
80
+ def test_encode_as_numpy (self ):
81
+
82
+ # should *fail* on non-numpy-y things
83
+ not_numpy = ['hippo' , 8 , float ('nan' ), {'a' : 'dict' }]
84
+ for obj in not_numpy :
85
+ self .assertRaises (utils .NotEncodable ,
86
+ utils .PlotlyJSONEncoder .encode_as_numpy , obj )
87
+
88
+ # should succeed with numpy-y-thingies
89
+ res = utils .PlotlyJSONEncoder .encode_as_numpy (np .ma .core .masked )
90
+ self .assertTrue (math .isnan (res ))
91
+
92
+ def test_encode_as_datetime (self ):
93
+
94
+ # should *fail* without 'utcoffset' and 'isoformat' and '__sub__' attrs
95
+ non_datetimes = [datetime .date (2013 , 10 , 1 ), 'noon' , 56 , '00:00:00' ]
96
+ for obj in non_datetimes :
97
+ self .assertRaises (utils .NotEncodable ,
98
+ utils .PlotlyJSONEncoder .encode_as_datetime , obj )
99
+
100
+ # should succeed with 'utcoffset', 'isoformat' and '__sub__' attrs
101
+ res = utils .PlotlyJSONEncoder .encode_as_datetime (
102
+ datetime .datetime (2013 , 10 , 1 )
103
+ )
104
+ self .assertEqual (res , '2013-10-01' )
105
+
106
+ # should not include extraneous microsecond info if DNE
107
+ res = utils .PlotlyJSONEncoder .encode_as_datetime (
108
+ datetime .datetime (2013 , 10 , 1 , microsecond = 0 )
109
+ )
110
+ self .assertEqual (res , '2013-10-01' )
111
+
112
+ # should include microsecond info if present
113
+ res = utils .PlotlyJSONEncoder .encode_as_datetime (
114
+ datetime .datetime (2013 , 10 , 1 , microsecond = 10 )
115
+ )
116
+ self .assertEqual (res , '2013-10-01 00:00:00.000010' )
117
+
118
+ # should convert tzinfo to utc. Note that in october, we're in EDT!
119
+ # therefore the 4 hour difference is correct.
120
+ naive_datetime = datetime .datetime (2013 , 10 , 1 )
121
+ aware_datetime = pytz .timezone ('US/Eastern' ).localize (naive_datetime )
122
+
123
+ res = utils .PlotlyJSONEncoder .encode_as_datetime (aware_datetime )
124
+ self .assertEqual (res , '2013-10-01 04:00:00' )
125
+
126
+ def test_encode_as_date (self ):
127
+
128
+ # should *fail* without 'utcoffset' and 'isoformat' and '__sub__' attrs
129
+ non_datetimes = ['noon' , 56 , '00:00:00' ]
130
+ for obj in non_datetimes :
131
+ self .assertRaises (utils .NotEncodable ,
132
+ utils .PlotlyJSONEncoder .encode_as_date , obj )
133
+
134
+ # should work with a date
135
+ a_date = datetime .date (2013 , 10 , 01 )
136
+ res = utils .PlotlyJSONEncoder .encode_as_date (a_date )
137
+ self .assertEqual (res , '2013-10-01' )
138
+
139
+ # should also work with a date time without a utc offset!
140
+ # TODO: is this OK? We could raise errors after checking isinstance...
141
+ res = utils .PlotlyJSONEncoder .encode_as_date (
142
+ datetime .datetime (2013 , 10 , 1 , microsecond = 10 )
143
+ )
144
+ self .assertEqual (res , '2013-10-01 00:00:00.000010' )
145
+
146
+
19
147
## JSON encoding
20
148
numeric_list = [1 , 2 , 3 ]
21
149
np_list = np .array ([1 , 2 , 3 , np .NaN , np .NAN , np .Inf , dt (2014 , 1 , 5 )])
@@ -38,7 +166,7 @@ def test_column_json_encoding():
38
166
Column (np_list , 'col 3' )
39
167
]
40
168
json_columns = json .dumps (
41
- columns , cls = utils ._plotlyJSONEncoder , sort_keys = True
169
+ columns , cls = utils .PlotlyJSONEncoder , sort_keys = True
42
170
)
43
171
assert ('[{"data": [1, 2, 3], "name": "col 1"}, '
44
172
'{"data": [1, "A", "2014-01-05", '
@@ -56,8 +184,8 @@ def test_figure_json_encoding():
56
184
data = Data ([s1 , s2 ])
57
185
figure = Figure (data = data )
58
186
59
- js1 = json .dumps (s1 , cls = utils ._plotlyJSONEncoder , sort_keys = True )
60
- js2 = json .dumps (s2 , cls = utils ._plotlyJSONEncoder , sort_keys = True )
187
+ js1 = json .dumps (s1 , cls = utils .PlotlyJSONEncoder , sort_keys = True )
188
+ js2 = json .dumps (s2 , cls = utils .PlotlyJSONEncoder , sort_keys = True )
61
189
62
190
assert (js1 == '{"type": "scatter3d", "x": [1, 2, 3], '
63
191
'"y": [1, 2, 3, NaN, NaN, Infinity, "2014-01-05"], '
@@ -66,8 +194,8 @@ def test_figure_json_encoding():
66
194
assert (js2 == '{"type": "scatter", "x": [1, 2, 3]}' )
67
195
68
196
# Test JSON encoding works
69
- json .dumps (data , cls = utils ._plotlyJSONEncoder , sort_keys = True )
70
- json .dumps (figure , cls = utils ._plotlyJSONEncoder , sort_keys = True )
197
+ json .dumps (data , cls = utils .PlotlyJSONEncoder , sort_keys = True )
198
+ json .dumps (figure , cls = utils .PlotlyJSONEncoder , sort_keys = True )
71
199
72
200
# Test data wasn't mutated
73
201
assert (bool (np .asarray (np_list ==
@@ -79,47 +207,48 @@ def test_figure_json_encoding():
79
207
80
208
81
209
def test_datetime_json_encoding ():
82
- j1 = json .dumps (dt_list , cls = utils ._plotlyJSONEncoder )
210
+ j1 = json .dumps (dt_list , cls = utils .PlotlyJSONEncoder )
83
211
assert (j1 == '["2014-01-05", '
84
212
'"2014-01-05 01:01:01", '
85
213
'"2014-01-05 01:01:01.000001"]' )
86
- j2 = json .dumps ({"x" : dt_list }, cls = utils ._plotlyJSONEncoder )
214
+ j2 = json .dumps ({"x" : dt_list }, cls = utils .PlotlyJSONEncoder )
87
215
assert (j2 == '{"x": ["2014-01-05", '
88
216
'"2014-01-05 01:01:01", '
89
217
'"2014-01-05 01:01:01.000001"]}' )
90
218
91
219
92
220
def test_pandas_json_encoding ():
93
- j1 = json .dumps (df ['col 1' ], cls = utils ._plotlyJSONEncoder )
221
+ j1 = json .dumps (df ['col 1' ], cls = utils .PlotlyJSONEncoder )
94
222
assert (j1 == '[1, 2, 3, "2014-01-05", null, NaN, Infinity]' )
95
223
96
224
# Test that data wasn't mutated
97
225
assert_series_equal (df ['col 1' ],
98
226
pd .Series ([1 , 2 , 3 , dt (2014 , 1 , 5 ),
99
227
pd .NaT , np .NaN , np .Inf ]))
100
228
101
- j2 = json .dumps (df .index , cls = utils ._plotlyJSONEncoder )
229
+ j2 = json .dumps (df .index , cls = utils .PlotlyJSONEncoder )
102
230
assert (j2 == '[0, 1, 2, 3, 4, 5, 6]' )
103
231
104
232
nat = [pd .NaT ]
105
- j3 = json .dumps (nat , cls = utils ._plotlyJSONEncoder )
233
+ j3 = json .dumps (nat , cls = utils .PlotlyJSONEncoder )
106
234
assert (j3 == '[null]' )
107
235
assert (nat [0 ] is pd .NaT )
108
236
109
- j4 = json .dumps (rng , cls = utils ._plotlyJSONEncoder )
237
+ j4 = json .dumps (rng , cls = utils .PlotlyJSONEncoder )
110
238
assert (j4 == '["2011-01-01", "2011-01-01 01:00:00"]' )
111
239
112
- j5 = json .dumps (ts , cls = utils ._plotlyJSONEncoder )
240
+ j5 = json .dumps (ts , cls = utils .PlotlyJSONEncoder )
113
241
assert (j5 == '[1.5, 2.5]' )
114
242
assert_series_equal (ts , pd .Series ([1.5 , 2.5 ], index = rng ))
115
243
116
- j6 = json .dumps (ts .index , cls = utils ._plotlyJSONEncoder )
244
+ j6 = json .dumps (ts .index , cls = utils .PlotlyJSONEncoder )
117
245
assert (j6 == '["2011-01-01", "2011-01-01 01:00:00"]' )
118
246
119
247
120
248
def test_numpy_masked_json_encoding ():
121
249
l = [1 , 2 , np .ma .core .masked ]
122
- j1 = json .dumps (l , cls = utils ._plotlyJSONEncoder )
250
+ j1 = json .dumps (l , cls = utils .PlotlyJSONEncoder )
251
+ print j1
123
252
assert (j1 == '[1, 2, NaN]' )
124
253
assert (set (l ) == set ([1 , 2 , np .ma .core .masked ]))
125
254
@@ -142,23 +271,23 @@ def test_masked_constants_example():
142
271
renderer = PlotlyRenderer ()
143
272
Exporter (renderer ).run (fig )
144
273
145
- json .dumps (renderer .plotly_fig , cls = utils ._plotlyJSONEncoder )
274
+ json .dumps (renderer .plotly_fig , cls = utils .PlotlyJSONEncoder )
146
275
147
276
jy = json .dumps (renderer .plotly_fig ['data' ][1 ]['y' ],
148
- cls = utils ._plotlyJSONEncoder )
277
+ cls = utils .PlotlyJSONEncoder )
149
278
assert (jy == '[-398.11793026999999, -398.11792966000002, '
150
279
'-398.11786308000001, NaN]' )
151
280
152
281
153
282
def test_numpy_dates ():
154
283
a = np .arange (np .datetime64 ('2011-07-11' ), np .datetime64 ('2011-07-18' ))
155
- j1 = json .dumps (a , cls = utils ._plotlyJSONEncoder )
284
+ j1 = json .dumps (a , cls = utils .PlotlyJSONEncoder )
156
285
assert (j1 == '["2011-07-11", "2011-07-12", "2011-07-13", '
157
286
'"2011-07-14", "2011-07-15", "2011-07-16", '
158
287
'"2011-07-17"]' )
159
288
160
289
161
290
def test_datetime_dot_date ():
162
291
a = [datetime .date (2014 , 1 , 1 ), datetime .date (2014 , 1 , 2 )]
163
- j1 = json .dumps (a , cls = utils ._plotlyJSONEncoder )
292
+ j1 = json .dumps (a , cls = utils .PlotlyJSONEncoder )
164
293
assert (j1 == '["2014-01-01", "2014-01-02"]' )
0 commit comments