123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- import json
- import os
- import re
- import tempfile
- import shutil
- import traitlets
- from ..widgets import IntSlider, IntText, Text, Widget, jslink, HBox, widget_serialization
- from ..embed import embed_data, embed_snippet, embed_minimal_html, dependency_state
- try:
- from io import StringIO
- except ImportError:
- from StringIO import StringIO
- try:
- # Python 3
- from html.parser import HTMLParser
- except ImportError:
- # Python 2
- from HTMLParser import HTMLParser
- class CaseWidget(Widget):
- """Widget to test dependency traversal"""
- a = traitlets.Instance(Widget, allow_none=True).tag(sync=True, **widget_serialization)
- b = traitlets.Instance(Widget, allow_none=True).tag(sync=True, **widget_serialization)
- _model_name = traitlets.Unicode('CaseWidgetModel').tag(sync=True)
- other = traitlets.Dict().tag(sync=True, **widget_serialization)
- class TestEmbed:
- def teardown(self):
- for w in tuple(Widget.widgets.values()):
- w.close()
- def test_embed_data_simple(self):
- w = IntText(4)
- state = dependency_state(w, drop_defaults=True)
- data = embed_data(views=w, drop_defaults=True, state=state)
- state = data['manager_state']['state']
- views = data['view_specs']
- assert len(state) == 3
- assert len(views) == 1
- model_names = [s['model_name'] for s in state.values()]
- assert 'IntTextModel' in model_names
- def test_cors(self):
- w = IntText(4)
- code = embed_snippet(w)
- # 1 is from the require
- assert len(re.findall(' crossorigin', code)) > 1
- f = StringIO()
- embed_minimal_html(f, w)
- assert len(re.findall(' crossorigin', f.getvalue())) > 1
- code = embed_snippet(w, cors=False, requirejs=False)
- assert ' crossorigin' not in code
- f = StringIO()
- embed_minimal_html(f, w, cors=False, requirejs=False)
- assert ' crossorigin' not in f.getvalue()
- code = embed_snippet(w, cors=False, requirejs=True)
- assert len(re.findall(' crossorigin', code)) == 1 # 1 is from the require, which is ok
- f = StringIO()
- embed_minimal_html(f, w, cors=False, requirejs=True)
- assert len(re.findall(' crossorigin', f.getvalue())) == 1 # 1 is from the require, which is ok
- def test_escape(self):
- w = Text('<script A> <ScRipt> </Script> <!-- --> <b>hi</b>')
- code = embed_snippet(w)
- assert code.find(r'<script A>') == -1
- assert code.find(r'\u003cscript A> \u003cScRipt> \u003c/Script> \u003c!-- --> <b>hi</b>') >= 0
- f = StringIO()
- embed_minimal_html(f, w)
- content = f.getvalue()
- assert content.find(r'<script A>') == -1
- assert content.find(r'\u003cscript A> \u003cScRipt> \u003c/Script> \u003c!-- --> <b>hi</b>') >= 0
- def test_embed_data_two_widgets(self):
- w1 = IntText(4)
- w2 = IntSlider(min=0, max=100)
- jslink((w1, 'value'), (w2, 'value'))
- state = dependency_state([w1, w2], drop_defaults=True)
- data = embed_data(views=[w1, w2], drop_defaults=True, state=state)
- state = data['manager_state']['state']
- views = data['view_specs']
- assert len(state) == 7
- assert len(views) == 2
- model_names = [s['model_name'] for s in state.values()]
- assert 'IntTextModel' in model_names
- assert 'IntSliderModel' in model_names
- def test_embed_data_complex(self):
- w1 = IntText(4)
- w2 = IntSlider(min=0, max=100)
- jslink((w1, 'value'), (w2, 'value'))
- w3 = CaseWidget()
- w3.a = w1
- w4 = CaseWidget()
- w4.a = w3
- w4.other['test'] = w2
- # Add a circular reference:
- w3.b = w4
- # Put it in an HBox
- HBox(children=[w4])
- state = dependency_state(w3)
- assert len(state) == 9
- model_names = [s['model_name'] for s in state.values()]
- assert 'IntTextModel' in model_names
- assert 'IntSliderModel' in model_names
- assert 'CaseWidgetModel' in model_names
- assert 'LinkModel' in model_names
- # Check that HBox is not collected
- assert 'HBoxModel' not in model_names
- # Check that views make sense:
- data = embed_data(views=w3, drop_defaults=True, state=state)
- assert state is data['manager_state']['state']
- views = data['view_specs']
- assert len(views) == 1
- def test_snippet(self):
- class Parser(HTMLParser):
- state = 'initial'
- states = []
- def handle_starttag(self, tag, attrs):
- attrs = dict(attrs)
- if tag == 'script' and attrs.get('type', '') == "application/vnd.jupyter.widget-state+json":
- self.state = 'widget-state'
- self.states.append(self.state)
- elif tag == 'script' and attrs.get('type', '') == "application/vnd.jupyter.widget-view+json":
- self.state = 'widget-view'
- self.states.append(self.state)
- def handle_endtag(self, tag):
- self.state = 'initial'
- def handle_data(self, data):
- if self.state == 'widget-state':
- manager_state = json.loads(data)['state']
- assert len(manager_state) == 3
- self.states.append('check-widget-state')
- elif self.state == 'widget-view':
- view = json.loads(data)
- assert isinstance(view, dict)
- self.states.append('check-widget-view')
- w = IntText(4)
- state = dependency_state(w, drop_defaults=True)
- snippet = embed_snippet(views=w, drop_defaults=True, state=state)
- parser = Parser()
- parser.feed(snippet)
- print(parser.states)
- assert parser.states == ['widget-state', 'check-widget-state', 'widget-view', 'check-widget-view']
- def test_minimal_html_filename(self):
- w = IntText(4)
- tmpd = tempfile.mkdtemp()
- try:
- output = os.path.join(tmpd, 'test.html')
- state = dependency_state(w, drop_defaults=True)
- embed_minimal_html(output, views=w, drop_defaults=True, state=state)
- # Check that the file is written to the intended destination:
- with open(output, 'r') as f:
- content = f.read()
- assert content.splitlines()[0] == '<!DOCTYPE html>'
- finally:
- shutil.rmtree(tmpd)
- def test_minimal_html_filehandle(self):
- w = IntText(4)
- output = StringIO()
- state = dependency_state(w, drop_defaults=True)
- embed_minimal_html(output, views=w, drop_defaults=True, state=state)
- content = output.getvalue()
- assert content.splitlines()[0] == '<!DOCTYPE html>'
|