hub/venv/lib/python3.7/site-packages/ipywidgets/tests/test_embed.py

206 lines
6.7 KiB
Python
Raw Normal View History

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>'