holoviz / panel
1 7
import os
2 7
import json
3 7
import glob
4 7
import pytest
5

6 7
from io import StringIO
7

8 7
from bokeh.models import CustomJS
9

10 7
from panel import Row
11 7
from panel.config import config
12 7
from panel.io.embed import embed_state
13 7
from panel.pane import Str
14 7
from panel.param import Param
15 7
from panel.widgets import IntSlider, Select, FloatSlider, Checkbox, StaticText
16

17

18 7
def test_embed_param_jslink(document, comm):
19 7
    select = Select(options=['A', 'B', 'C'])
20 7
    params = Param(select, parameters=['disabled']).layout
21 7
    panel = Row(select, params)
22 7
    with config.set(embed=True):
23 7
        model = panel.get_root(document, comm)
24 7
    embed_state(panel, model, document)
25 7
    assert len(document.roots) == 1
26

27 7
    ref = model.ref['id']
28 7
    cbs = list(model.select({'type': CustomJS}))
29 7
    assert len(cbs) == 2
30 7
    cb1, cb2 = cbs
31 7
    cb1, cb2 = (cb1, cb2) if select._models[ref][0] is cb1.args['target'] else (cb2, cb1)
32 7
    assert cb1.code == """
33
    var value = source['active'];
34
    value = value.indexOf(0) >= 0;
35
    value = value;
36
    try {
37
      var property = target.properties['disabled'];
38
      if (property !== undefined) { property.validate(value); }
39
    } catch(err) {
40
      console.log('WARNING: Could not set disabled on target, raised error: ' + err);
41
      return;
42
    }
43
    try {
44
      target['disabled'] = value;
45
    } catch(err) {
46
      console.log(err)
47
    }
48
    """
49

50 7
    assert cb2.code == """
51
    var value = source['disabled'];
52
    value = value;
53
    value = value ? [0] : [];
54
    try {
55
      var property = target.properties['active'];
56
      if (property !== undefined) { property.validate(value); }
57
    } catch(err) {
58
      console.log('WARNING: Could not set active on target, raised error: ' + err);
59
      return;
60
    }
61
    try {
62
      target['active'] = value;
63
    } catch(err) {
64
      console.log(err)
65
    }
66
    """
67

68

69 7
def test_embed_select_str_link(document, comm):
70 7
    select = Select(options=['A', 'B', 'C'])
71 7
    string = Str()
72 7
    def link(target, event):
73 7
        target.object = event.new
74 7
    select.link(string, callbacks={'value': link})
75 7
    panel = Row(select, string)
76 7
    with config.set(embed=True):
77 7
        model = panel.get_root(document, comm)
78 7
    embed_state(panel, model, document)
79 7
    _, state = document.roots
80 7
    assert set(state.state) == {'A', 'B', 'C'}
81 7
    for k, v in state.state.items():
82 7
        content = json.loads(v['content'])
83 7
        assert 'events' in content
84 7
        events = content['events']
85 7
        assert len(events) == 1
86 7
        event = events[0]
87 7
        assert event['kind'] == 'ModelChanged'
88 7
        assert event['attr'] == 'text'
89 7
        assert event['model'] == model.children[1].ref
90 7
        assert event['new'] == '<pre>%s</pre>' % k
91

92

93 7
def test_embed_float_slider_explicit_values(document, comm):
94 7
    select = FloatSlider()
95 7
    string = Str()
96 7
    def link(target, event):
97 7
        target.object = event.new
98 7
    select.link(string, callbacks={'value': link})
99 7
    panel = Row(select, string)
100 7
    with config.set(embed=True):
101 7
        model = panel.get_root(document, comm)
102 7
    embed_state(panel, model, document, states={select: [0.1, 0.7, 1]})
103 7
    _, state = document.roots
104 7
    assert set(state.state) == {0, 1, 2}
105 7
    states = {0: 0.1, 1: 0.7, 2: 1}
106 7
    for (k, v) in state.state.items():
107 7
        content = json.loads(v['content'])
108 7
        assert 'events' in content
109 7
        events = content['events']
110 7
        assert len(events) == 1
111 7
        event = events[0]
112 7
        assert event['kind'] == 'ModelChanged'
113 7
        assert event['attr'] == 'text'
114 7
        assert event['model'] == model.children[1].ref
115 7
        assert event['new'] == '<pre>%s</pre>' % states[k]
116

117

118 7
def test_embed_select_explicit_values(document, comm):
119 7
    select = Select(options=['A', 'B', 'C'])
120 7
    string = Str()
121 7
    def link(target, event):
122 7
        target.object = event.new
123 7
    select.link(string, callbacks={'value': link})
124 7
    panel = Row(select, string)
125 7
    with config.set(embed=True):
126 7
        model = panel.get_root(document, comm)
127 7
    embed_state(panel, model, document, states={select: ['A', 'B']})
128 7
    _, state = document.roots
129 7
    assert set(state.state) == {'A', 'B'}
130 7
    for k, v in state.state.items():
131 7
        content = json.loads(v['content'])
132 7
        assert 'events' in content
133 7
        events = content['events']
134 7
        assert len(events) == 1
135 7
        event = events[0]
136 7
        assert event['kind'] == 'ModelChanged'
137 7
        assert event['attr'] == 'text'
138 7
        assert event['model'] == model.children[1].ref
139 7
        assert event['new'] == '<pre>%s</pre>' % k
140

141

142 7
def test_embed_select_str_explicit_values_not_found(document, comm):
143 7
    select = Select(options=['A', 'B', 'C'])
144 7
    string = Str()
145 7
    def link(target, event):
146 0
        target.object = event.new
147 7
    select.link(string, callbacks={'value': link})
148 7
    panel = Row(select, string)
149 7
    with config.set(embed=True):
150 7
        model = panel.get_root(document, comm)
151 7
    with pytest.raises(ValueError):
152 7
        embed_state(panel, model, document, states={select: ['A', 'D']})
153

154

155 7
def test_embed_float_slider_explicit_values_out_of_bounds(document, comm):
156 7
    select = FloatSlider()
157 7
    string = Str()
158 7
    def link(target, event):
159 0
        target.object = event.new
160 7
    select.link(string, callbacks={'value': link})
161 7
    panel = Row(select, string)
162 7
    with config.set(embed=True):
163 7
        model = panel.get_root(document, comm)
164 7
    with pytest.raises(ValueError):
165 7
        embed_state(panel, model, document, states={select: [0.1, 0.7, 2]})
166

167

168 7
def test_embed_select_str_link_two_steps(document, comm):
169 7
    select = Select(options=['A', 'B', 'C'])
170 7
    string1 = Str()
171 7
    select.link(string1, value='object')
172 7
    string2 = Str()
173 7
    string1.link(string2, object='object')
174 7
    panel = Row(select, string1, string2)
175 7
    with config.set(embed=True):
176 7
        model = panel.get_root(document, comm)
177 7
    embed_state(panel, model, document)
178 7
    _, state = document.roots
179 7
    assert set(state.state) == {'A', 'B', 'C'}
180 7
    for k, v in state.state.items():
181 7
        content = json.loads(v['content'])
182 7
        assert 'events' in content
183 7
        events = content['events']
184 7
        assert len(events) == 2
185 7
        event = events[0]
186 7
        assert event['kind'] == 'ModelChanged'
187 7
        assert event['attr'] == 'text'
188 7
        assert event['model'] == model.children[1].ref
189 7
        assert event['new'] == '<pre>%s</pre>' % k
190

191 7
        event = events[1]
192 7
        assert event['kind'] == 'ModelChanged'
193 7
        assert event['attr'] == 'text'
194 7
        assert event['model'] == model.children[2].ref
195 7
        assert event['new'] == '<pre>%s</pre>' % k
196

197

198 7
def test_embed_select_str_link_with_secondary_watch(document, comm):
199 7
    select = Select(options=['A', 'B', 'C'])
200 7
    string = Str()
201 7
    select.link(string, value='object')
202 7
    string.param.watch(print, 'object')
203 7
    panel = Row(select, string)
204 7
    with config.set(embed=True):
205 7
        model = panel.get_root(document, comm)
206 7
    embed_state(panel, model, document)
207 7
    _, state = document.roots
208 7
    assert set(state.state) == {'A', 'B', 'C'}
209 7
    for k, v in state.state.items():
210 7
        content = json.loads(v['content'])
211 7
        assert 'events' in content
212 7
        events = content['events']
213 7
        assert len(events) == 1
214 7
        event = events[0]
215 7
        assert event['kind'] == 'ModelChanged'
216 7
        assert event['attr'] == 'text'
217 7
        assert event['model'] == model.children[1].ref
218 7
        assert event['new'] == '<pre>%s</pre>' % k
219

220

221 7
def test_embed_select_str_jslink(document, comm):
222 7
    select = Select(options=['A', 'B', 'C'])
223 7
    string = Str()
224 7
    select.link(string, value='object')
225 7
    panel = Row(select, string)
226 7
    with config.set(embed=True):
227 7
        model = panel.get_root(document, comm)
228 7
    embed_state(panel, model, document)
229 7
    assert len(document.roots) == 1
230 7
    assert model is document.roots[0]
231

232 7
    ref = model.ref['id']
233 7
    cbs = list(model.select({'type': CustomJS}))
234 7
    assert len(cbs) == 2
235 7
    cb1, cb2 = cbs
236 7
    cb1, cb2 = (cb1, cb2) if select._models[ref][0] is cb1.args['source'] else (cb2, cb1)
237 7
    assert cb1.code == """
238
    var value = source['value'];
239
    value = value;
240
    value = JSON.stringify(value).replace(/,/g, ", ").replace(/:/g, ": ");
241
    try {
242
      var property = target.properties['text'];
243
      if (property !== undefined) { property.validate(value); }
244
    } catch(err) {
245
      console.log('WARNING: Could not set text on target, raised error: ' + err);
246
      return;
247
    }
248
    try {
249
      target['text'] = value;
250
    } catch(err) {
251
      console.log(err)
252
    }
253
    """
254

255 7
    assert cb2.code == """
256
    var value = source['text'];
257
    value = value;
258
    value = value;
259
    try {
260
      var property = target.properties['value'];
261
      if (property !== undefined) { property.validate(value); }
262
    } catch(err) {
263
      console.log('WARNING: Could not set value on target, raised error: ' + err);
264
      return;
265
    }
266
    try {
267
      target['value'] = value;
268
    } catch(err) {
269
      console.log(err)
270
    }
271
    """
272

273

274 7
def test_embed_checkbox_str_link(document, comm):
275 7
    checkbox = Checkbox()
276 7
    string = Str()
277 7
    def link(target, event):
278 7
        target.object = event.new
279 7
    checkbox.link(string, callbacks={'value': link})
280 7
    panel = Row(checkbox, string)
281 7
    with config.set(embed=True):
282 7
        model = panel.get_root(document, comm)
283 7
    embed_state(panel, model, document)
284 7
    _, state = document.roots
285 7
    assert set(state.state) == {'false', 'true'}
286 7
    for k, v in state.state.items():
287 7
        content = json.loads(v['content'])
288 7
        assert 'events' in content
289 7
        events = content['events']
290 7
        assert len(events) == 1
291 7
        event = events[0]
292 7
        assert event['kind'] == 'ModelChanged'
293 7
        assert event['attr'] == 'text'
294 7
        assert event['model'] == model.children[1].ref
295 7
        assert event['new'] == '<pre>%s</pre>' % k.title()
296

297

298 7
def test_embed_checkbox_str_jslink(document, comm):
299 7
    checkbox = Checkbox()
300 7
    string = Str()
301 7
    checkbox.link(string, value='object')
302 7
    panel = Row(checkbox, string)
303 7
    with config.set(embed=True):
304 7
        model = panel.get_root(document, comm)
305 7
    embed_state(panel, model, document)
306 7
    assert len(document.roots) == 1
307 7
    assert model is document.roots[0]
308

309 7
    ref = model.ref['id']
310 7
    cbs = list(model.select({'type': CustomJS}))
311 7
    assert len(cbs) == 2
312 7
    cb1, cb2 = cbs
313 7
    cb1, cb2 = (cb1, cb2) if checkbox._models[ref][0] is cb1.args['source'] else (cb2, cb1)
314 7
    assert cb1.code == """
315
    var value = source['active'];
316
    value = value.indexOf(0) >= 0;
317
    value = JSON.stringify(value).replace(/,/g, ", ").replace(/:/g, ": ");
318
    try {
319
      var property = target.properties['text'];
320
      if (property !== undefined) { property.validate(value); }
321
    } catch(err) {
322
      console.log('WARNING: Could not set text on target, raised error: ' + err);
323
      return;
324
    }
325
    try {
326
      target['text'] = value;
327
    } catch(err) {
328
      console.log(err)
329
    }
330
    """
331

332 7
    assert cb2.code == """
333
    var value = source['text'];
334
    value = value;
335
    value = value ? [0] : [];
336
    try {
337
      var property = target.properties['active'];
338
      if (property !== undefined) { property.validate(value); }
339
    } catch(err) {
340
      console.log('WARNING: Could not set active on target, raised error: ' + err);
341
      return;
342
    }
343
    try {
344
      target['active'] = value;
345
    } catch(err) {
346
      console.log(err)
347
    }
348
    """
349

350

351 7
def test_embed_slider_str_link(document, comm):
352 7
    slider = FloatSlider(start=0, end=10)
353 7
    string = Str()
354 7
    def link(target, event):
355 7
        target.object = event.new
356 7
    slider.link(string, callbacks={'value': link})
357 7
    panel = Row(slider, string)
358 7
    with config.set(embed=True):
359 7
        model = panel.get_root(document, comm)
360 7
    embed_state(panel, model, document)
361 7
    _, state = document.roots
362 7
    assert set(state.state) == {0, 1, 2}
363 7
    values = [0, 5, 10]
364 7
    for k, v in state.state.items():
365 7
        content = json.loads(v['content'])
366 7
        assert 'events' in content
367 7
        events = content['events']
368 7
        assert len(events) == 1
369 7
        event = events[0]
370 7
        assert event['kind'] == 'ModelChanged'
371 7
        assert event['attr'] == 'text'
372 7
        assert event['model'] == model.children[1].ref
373 7
        assert event['new'] == '<pre>%.1f</pre>' % values[k]
374

375

376 7
def test_embed_slider_str_jslink(document, comm):
377 7
    slider = FloatSlider(start=0, end=10)
378 7
    string = Str()
379 7
    slider.link(string, value='object')
380 7
    panel = Row(slider, string)
381 7
    with config.set(embed=True):
382 7
        model = panel.get_root(document, comm)
383 7
    embed_state(panel, model, document)
384 7
    assert len(document.roots) == 1
385 7
    assert model is document.roots[0]
386

387 7
    ref = model.ref['id']
388 7
    cbs = list(model.select({'type': CustomJS}))
389 7
    assert len(cbs) == 2
390 7
    cb1, cb2 = cbs
391 7
    cb1, cb2 = (cb1, cb2) if slider._models[ref][0] is cb1.args['source'] else (cb2, cb1)
392 7
    assert cb1.code == """
393
    var value = source['value'];
394
    value = value;
395
    value = JSON.stringify(value).replace(/,/g, ", ").replace(/:/g, ": ");
396
    try {
397
      var property = target.properties['text'];
398
      if (property !== undefined) { property.validate(value); }
399
    } catch(err) {
400
      console.log('WARNING: Could not set text on target, raised error: ' + err);
401
      return;
402
    }
403
    try {
404
      target['text'] = value;
405
    } catch(err) {
406
      console.log(err)
407
    }
408
    """
409

410 7
    assert cb2.code == """
411
    var value = source['text'];
412
    value = value;
413
    value = value;
414
    try {
415
      var property = target.properties['value'];
416
      if (property !== undefined) { property.validate(value); }
417
    } catch(err) {
418
      console.log('WARNING: Could not set value on target, raised error: ' + err);
419
      return;
420
    }
421
    try {
422
      target['value'] = value;
423
    } catch(err) {
424
      console.log(err)
425
    }
426
    """
427

428

429 7
def test_embed_merged_sliders(document, comm):
430 7
    s1 = IntSlider(name='A', start=1, end=10, value=1)
431 7
    t1 = StaticText()
432 7
    s1.param.watch(lambda event: setattr(t1, 'value', event.new), 'value')
433

434 7
    s2 = IntSlider(name='A', start=1, end=10, value=1)
435 7
    t2 = StaticText()
436 7
    s2.param.watch(lambda event: setattr(t2, 'value', event.new), 'value')
437

438 7
    panel = Row(s1, s2, t1, t2)
439 7
    with config.set(embed=True):
440 7
        model = panel.get_root(document, comm)
441 7
    state_model = embed_state(panel, model, document)
442 7
    assert len(document.roots) == 2
443 7
    assert model is document.roots[0]
444

445 7
    cbs = list(model.select({'type': CustomJS}))
446 7
    assert len(cbs) == 5
447

448 7
    ref1, ref2 = model.children[2].ref['id'], model.children[3].ref['id']
449 7
    state0 = json.loads(state_model.state[0]['content'])['events']
450 7
    assert state0 == [
451
        {"attr": "text", "kind": "ModelChanged", "model": {"id": ref1}, "new": "1"},
452
        {"attr": "text", "kind": "ModelChanged", "model": {"id": ref2}, "new": "1"}
453
    ]
454 7
    state1 = json.loads(state_model.state[1]['content'])['events']
455 7
    assert state1 == [
456
        {"attr": "text", "kind": "ModelChanged", "model": {"id": ref1}, "new": "5"},
457
        {"attr": "text", "kind": "ModelChanged", "model": {"id": ref2}, "new": "5"}
458
    ]
459 7
    state2 = json.loads(state_model.state[2]['content'])['events']
460 7
    assert state2 == [
461
        {"attr": "text", "kind": "ModelChanged", "model": {"id": ref1}, "new": "9"},
462
        {"attr": "text", "kind": "ModelChanged", "model": {"id": ref2}, "new": "9"}
463
    ]
464

465

466 7
def test_save_embed_bytesio():
467 7
    checkbox = Checkbox()
468 7
    string = Str()
469 7
    def link(target, event):
470 7
        target.object = event.new
471 7
    checkbox.link(string, callbacks={'value': link})
472 7
    panel = Row(checkbox, string)
473 7
    stringio = StringIO()
474 7
    panel.save(stringio, embed=True)
475 7
    stringio.seek(0)
476 7
    utf = stringio.read()
477 7
    assert "<pre>False</pre>" in utf
478 7
    assert "<pre>True</pre>" in utf
479

480

481 7
def test_save_embed(tmpdir):
482 7
    checkbox = Checkbox()
483 7
    string = Str()
484 7
    checkbox.link(string, value='object')
485 7
    panel = Row(checkbox, string)
486 7
    filename = os.path.join(str(tmpdir), 'test.html')
487 7
    panel.save(filename, embed=True)
488 7
    assert os.path.isfile(filename)
489

490

491 7
def test_save_embed_json(tmpdir):
492 7
    checkbox = Checkbox()
493 7
    string = Str()
494 7
    def link(target, event):
495 7
        target.object = event.new
496 7
    checkbox.link(string, callbacks={'value': link})
497 7
    panel = Row(checkbox, string)
498 7
    filename = os.path.join(str(tmpdir), 'test.html')
499 7
    panel.save(filename, embed=True, embed_json=True,
500
               save_path=str(tmpdir))
501 7
    assert os.path.isfile(filename)
502 7
    paths = glob.glob(os.path.join(str(tmpdir), '*'))
503 7
    paths.remove(filename)
504 7
    assert len(paths) == 1
505 7
    json_files = sorted(glob.glob(os.path.join(paths[0], '*.json')))
506 7
    assert len(json_files) == 2
507

508 7
    for jf, v in zip(json_files, ('False', 'True')):
509 7
        with open(jf) as f:
510 7
            state = json.load(f)
511 7
        assert 'content' in state
512 7
        assert 'events' in state['content']
513 7
        events = json.loads(state['content'])['events']
514 7
        assert len(events) == 1
515 7
        event = events[0]
516 7
        assert event['kind'] == 'ModelChanged'
517 7
        assert event['attr'] == 'text'
518 7
        assert event['new'] == '<pre>%s</pre>' % v

Read our documentation on viewing source code .

Loading