def test_clear(self) -> None: d = document.Document() assert not d.roots assert d.title == document.DEFAULT_TITLE d.add_root(AnotherModelInTestDocument()) d.add_root(AnotherModelInTestDocument()) d.title = "Foo" assert len(d.roots) == 2 assert d.title == "Foo" d.clear() assert not d.roots assert not d._all_models assert d.title == "Foo" # do not reset title
def test_get_model_by_id(self) -> None: d = document.Document() assert not d.roots assert len(d._all_models) == 0 m = SomeModelInTestDocument() m2 = AnotherModelInTestDocument() m.child = m2 d.add_root(m) assert len(d.roots) == 1 assert len(d._all_models) == 2 assert d.get_model_by_id(m.id) == m assert d.get_model_by_id(m2.id) == m2 assert d.get_model_by_id("not a valid ID") is None
def test_serialization_one_model(self) -> None: d = document.Document() assert not d.roots assert len(d._all_models) == 0 root1 = SomeModelInTestDocument() d.add_root(root1) d.title = "Foo" json = d.to_json_string() copy = document.Document.from_json_string(json) assert len(copy.roots) == 1 assert copy.title == "Foo"
def test_patch_spec_property(self) -> None: d = document.Document() assert not d.roots assert len(d.models) == 0 root1 = ModelWithSpecInTestDocument(foo=42) d.add_root(root1) assert len(d.roots) == 1 def patch_test(new_value): serializable_new = root1.lookup('foo').property.to_serializable(root1, 'foo', new_value) event1 = ModelChangedEvent(d, root1, 'foo', root1.foo, new_value, serializable_new) patch1, buffers = process_document_events([event1]) d.apply_json_patch_string(patch1) if isinstance(new_value, dict): return root1.lookup('foo').serializable_value(root1) else: return root1.foo assert patch_test(57) == 57 assert 'data' == root1.foo_units assert patch_test(dict(value=58)) == dict(value=58) assert 'data' == root1.foo_units assert patch_test(dict(value=58, units='screen')) == dict(value=58, units='screen') assert 'screen' == root1.foo_units assert patch_test(dict(value=59, units='screen')) == dict(value=59, units='screen') assert 'screen' == root1.foo_units assert patch_test(dict(value=59, units='data')) == dict(value=59) assert 'data' == root1.foo_units assert patch_test(dict(value=60, units='data')) == dict(value=60) assert 'data' == root1.foo_units assert patch_test(dict(value=60, units='data')) == dict(value=60) assert 'data' == root1.foo_units assert patch_test(61) == 61 assert 'data' == root1.foo_units root1.foo = "a_string" # so "woot" gets set as a string assert patch_test("woot") == "woot" assert 'data' == root1.foo_units assert patch_test(dict(field="woot2")) == dict(field="woot2") assert 'data' == root1.foo_units assert patch_test(dict(field="woot2", units='screen')) == dict(field="woot2", units='screen') assert 'screen' == root1.foo_units assert patch_test(dict(field="woot3")) == dict(field="woot3", units="screen") assert 'screen' == root1.foo_units assert patch_test(dict(value=70)) == dict(value=70, units="screen") assert 'screen' == root1.foo_units root1.foo = 123 # so 71 gets set as a number assert patch_test(71) == 71 assert 'screen' == root1.foo_units
def test_get_model_by_name(self) -> None: d = document.Document() assert not d.roots assert len(d._all_models) == 0 m = SomeModelInTestDocument(name="foo") m2 = AnotherModelInTestDocument(name="bar") m.child = m2 d.add_root(m) assert len(d.roots) == 1 assert len(d._all_models) == 2 assert len(d._all_models_by_name._dict) == 2 assert d.get_model_by_name(m.name) == m assert d.get_model_by_name(m2.name) == m2 assert d.get_model_by_name("not a valid name") is None
def test_model_callback_gets_curdoc(self) -> None: d = document.Document() m = AnotherModelInTestDocument(bar=42) d.add_root(m) assert curdoc() is not d curdoc_from_cb = [] def cb(attr, old, new): curdoc_from_cb.append(curdoc()) m.on_change('bar', cb) m.bar = 43 assert len(curdoc_from_cb) == 1 assert curdoc_from_cb[0] is d
def test_basic(self): d = document.Document() assert not d.roots class FakeMod(object): __name__ = 'junkjunkjunk' mod = FakeMod() import sys assert 'junkjunkjunk' not in sys.modules sys.modules['junkjunkjunk'] = mod d._modules.append(mod) assert 'junkjunkjunk' in sys.modules d.delete_modules() assert 'junkjunkjunk' not in sys.modules assert d._modules is None
def test_select(self) -> None: # we aren't trying to replace test_query here, only test # our wrappers around it, so no need to try every kind of # query d = document.Document() root1 = SomeModelInTestDocument(foo=42, name='a') child1 = SomeModelInTestDocument(foo=43, name='b') root2 = SomeModelInTestDocument(foo=44, name='c') root3 = SomeModelInTestDocument(foo=44, name='d') child3 = SomeModelInTestDocument(foo=45, name='c') root1.child = child1 root3.child = child3 d.add_root(root1) d.add_root(root2) d.add_root(root3) # select() assert set([root1]) == set(d.select(dict(foo=42))) assert set([root1]) == set(d.select(dict(name='a'))) assert set([root2, child3]) == set(d.select(dict(name='c'))) assert set() == set(d.select(dict(name='nope'))) # select() on object assert set() == set(root3.select(dict(name='a'))) assert set([child3]) == set(root3.select(dict(name='c'))) # select_one() assert root3 == d.select_one(dict(name='d')) assert None == d.select_one(dict(name='nope')) got_error = False try: d.select_one(dict(name='c')) except ValueError as e: got_error = True assert 'Found more than one' in repr(e) assert got_error # select_one() on object assert None == root3.select_one(dict(name='a')) assert child3 == root3.select_one(dict(name='c')) # set_select() d.set_select(dict(foo=44), dict(name='c')) assert set([root2, child3, root3]) == set(d.select(dict(name='c'))) # set_select() on object root3.set_select(dict(name='c'), dict(foo=57)) assert set([child3, root3]) == set(d.select(dict(foo=57))) assert set([child3, root3]) == set(root3.select(dict(foo=57)))
def test_cannot_get_model_with_duplicate_name(self) -> None: d = document.Document() m = SomeModelInTestDocument(name="foo") m2 = SomeModelInTestDocument(name="foo") d.add_root(m) d.add_root(m2) got_error = False try: d.get_model_by_name("foo") except ValueError as e: got_error = True assert 'Found more than one' in repr(e) assert got_error d.remove_root(m) assert d.get_model_by_name("foo") == m2
def test_select() -> None: # we aren't trying to replace test_query here, only test # our wrappers around it, so no need to try every kind of # query d = document.Document() root1 = SomeModel(a=42, name='a') root2 = SomeModel(a=43, name='c') root3 = SomeModel(a=44, name='d') root4 = SomeModel(a=45, name='d') d.add_root(root1) d.add_root(root2) d.add_root(root3) d.add_root(root4) # select() assert {root1} == set(root1.select(dict(a=42))) assert {root1} == set(root1.select(dict(name="a"))) assert {root2} == set(root2.select(dict(name="c"))) assert set() == set(root1.select(dict(name="nope"))) # select() on object assert set() == set(root3.select(dict(name='a'))) assert {root3} == set(root3.select(dict(a=44))) # select_one() assert root3 == root3.select_one(dict(name='d')) assert None == root1.select_one(dict(name='nope')) with pytest.raises(ValueError) as e: d.select_one(dict(name='d')) assert 'Found more than one' in repr(e) # select_one() on object assert None == root3.select_one(dict(name='a')) assert None == root3.select_one(dict(name='c')) # set_select() root1.set_select(dict(a=42), dict(name="c", a=44)) assert {root1} == set(root1.select(dict(name="c"))) assert {root1} == set(root1.select(dict(a=44))) # set_select() on object root3.set_select(dict(name='d'), dict(a=57)) assert {root3} == set(root3.select(dict(a=57))) # set_select() on class root2.set_select(SomeModel, dict(name='new_name')) assert {root2} == set(root2.select(dict(name="new_name")))
def test_roots_preserves_insertion_order(self) -> None: d = document.Document() assert not d.roots roots = [ AnotherModelInTestDocument(), AnotherModelInTestDocument(), AnotherModelInTestDocument(), ] for r in roots: d.add_root(r) assert len(d.roots) == 3 assert type(d.roots) is list roots_iter = iter(d.roots) assert next(roots_iter) is roots[0] assert next(roots_iter) is roots[1] assert next(roots_iter) is roots[2]
def test_scatter(self): from bokeh.io.doc import set_curdoc from bokeh.plotting import figure import numpy as np d = document.Document() set_curdoc(d) assert not d.roots assert len(d._all_models) == 0 p1 = figure(tools=[]) N = 10 x = np.linspace(0, 4 * np.pi, N) y = np.sin(x) p1.scatter(x, y, color="#FF00FF", nonselection_fill_color="#FFFF00", nonselection_fill_alpha=1) # figure does not automatically add itself to the document d.add_root(p1) assert len(d.roots) == 1
def test_notification_of_title(self): d = document.Document() assert not d.roots assert d.title == document.DEFAULT_TITLE events = [] def listener(event): events.append(event) d.on_change(listener) d.title = "Foo" assert d.title == "Foo" assert len(events) == 1 assert isinstance(events[0], TitleChangedEvent) assert events[0].document is d assert events[0].title == "Foo"
def test_all_models(self) -> None: d = document.Document() assert not d.roots assert len(d._all_models) == 0 m = SomeModelInTestDocument() m2 = AnotherModelInTestDocument() m.child = m2 d.add_root(m) assert len(d.roots) == 1 assert len(d._all_models) == 2 m.child = None assert len(d._all_models) == 1 m.child = m2 assert len(d._all_models) == 2 d.remove_root(m) assert len(d._all_models) == 0
def test_change_notification_removal(self): d = document.Document() assert not d.roots m = AnotherModelInTestDocument() d.add_root(m) assert len(d.roots) == 1 assert m.bar == 1 events = [] def listener(event): events.append(event) d.on_change(listener) m.bar = 42 assert len(events) == 1 assert events[0].new == 42 d.remove_on_change(listener) m.bar = 43 assert len(events) == 1
def test_rehold(self, first, second, caplog): d = document.Document() with caplog.at_level(logging.WARN): d.hold(first) assert caplog.text == "" assert len(caplog.records) == 0 d.hold(first) assert caplog.text == "" assert len(caplog.records) == 0 d.hold(second) assert caplog.text.strip().endswith("hold already active with '%s', ignoring '%s'" % (first, second)) assert len(caplog.records) == 1 d.unhold() d.hold(second) assert len(caplog.records) == 1
def test_event_handles_new_callbacks_in_event_callback(self): from bokeh.models import Button d = document.Document() button1 = Button(label="1") button2 = Button(label="2") def clicked_1(): button2.on_click(clicked_2) d.add_root(button2) def clicked_2(): pass button1.on_click(clicked_1) d.add_root(button1) event_json = json.dumps({"event_name":"button_click","event_values":{"model_id":button1.id}}) try: d.apply_json_event(event_json) except RuntimeError: pytest.fail("apply_json_event probably did not copy models before modifying")
def test_patch_reference_property(self) -> None: d = document.Document() assert not d.roots assert len(d._all_models) == 0 root1 = SomeModelInTestDocument(foo=42) root2 = SomeModelInTestDocument(foo=43) child1 = SomeModelInTestDocument(foo=44) child2 = SomeModelInTestDocument(foo=45) child3 = SomeModelInTestDocument(foo=46, child=child2) root1.child = child1 root2.child = child1 d.add_root(root1) d.add_root(root2) assert len(d.roots) == 2 assert child1.id in d._all_models assert child2.id not in d._all_models assert child3.id not in d._all_models event1 = ModelChangedEvent(d, root1, 'child', root1.child, child3, child3) patch1, buffers = process_document_events([event1]) d.apply_json_patch_string(patch1) assert root1.child.id == child3.id assert root1.child.child.id == child2.id assert child1.id in d._all_models assert child2.id in d._all_models assert child3.id in d._all_models # put it back how it was before event2 = ModelChangedEvent(d, root1, 'child', root1.child, child1, child1) patch2, buffers = process_document_events([event2]) d.apply_json_patch_string(patch2) assert root1.child.id == child1.id assert root1.child.child is None assert child1.id in d._all_models assert child2.id not in d._all_models assert child3.id not in d._all_models
def test_add_partial_callback(self): from functools import partial d = document.Document() events = [] def listener(event): events.append(event) d.on_change(listener) assert len(d.session_callbacks) == 0 assert not events def _cb(): pass cb = partial(_cb) callback_obj = d.add_timeout_callback(cb, 1) assert len(d.session_callbacks) == len(events) == 1 assert isinstance(events[0], SessionCallbackAdded) assert callback_obj == d.session_callbacks[0] == events[0].callback assert callback_obj.timeout == 1
def test_patch_reference_property(self) -> None: d = document.Document() assert not d.roots assert len(d.models) == 0 root1 = SomeModelInTestDocument(foo=42) root2 = SomeModelInTestDocument(foo=43) child1 = SomeModelInTestDocument(foo=44) child2 = SomeModelInTestDocument(foo=45) child3 = SomeModelInTestDocument(foo=46, child=child2) root1.child = child1 root2.child = child1 d.add_root(root1) d.add_root(root2) assert len(d.roots) == 2 assert child1.id in d.models assert child2.id not in d.models assert child3.id not in d.models event1 = ModelChangedEvent(d, root1, 'child', child3) patch1 = patch_doc.create([event1]).content d.apply_json_patch(patch1) assert root1.child.id == child3.id assert root1.child.child.id == child2.id assert child1.id in d.models assert child2.id in d.models assert child3.id in d.models # put it back how it was before event2 = ModelChangedEvent(d, root1, 'child', child1) patch2 = patch_doc.create([event2]).content d.apply_json_patch(patch2) assert root1.child.id == child1.id assert root1.child.child is None assert child1.id in d.models assert child2.id not in d.models assert child3.id not in d.models
def test_patch_two_properties_at_once(self): d = document.Document() assert not d.roots assert len(d._all_models) == 0 root1 = SomeModelInTestDocument(foo=42) child1 = SomeModelInTestDocument(foo=43) root1.child = child1 d.add_root(root1) assert len(d.roots) == 1 assert root1.child == child1 assert root1.foo == 42 assert root1.child.foo == 43 child2 = SomeModelInTestDocument(foo=44) event1 = ModelChangedEvent(d, root1, 'foo', root1.foo, 57, 57) event2 = ModelChangedEvent(d, root1, 'child', root1.child, child2, child2) patch1, buffers = process_document_events([event1, event2]) d.apply_json_patch_string(patch1) assert root1.foo == 57 assert root1.child.foo == 44
def test_patch_two_properties_at_once(self) -> None: d = document.Document() assert not d.roots assert len(d.models) == 0 root1 = SomeModelInTestDocument(foo=42) child1 = SomeModelInTestDocument(foo=43) root1.child = child1 d.add_root(root1) assert len(d.roots) == 1 assert root1.child == child1 assert root1.foo == 42 assert root1.child.foo == 43 child2 = SomeModelInTestDocument(foo=44) event1 = ModelChangedEvent(d, root1, 'foo', 57) event2 = ModelChangedEvent(d, root1, 'child', child2) patch1 = patch_doc.create([event1, event2]).content d.apply_json_patch(patch1) assert root1.foo == 57 assert root1.child.foo == 44
def test_add_remove_next_tick_callback(self): d = document.Document() events = [] def listener(event): events.append(event) d.on_change(listener) assert len(d.session_callbacks) == 0 assert not events def cb(): pass callback_obj = d.add_next_tick_callback(cb) assert len(d.session_callbacks) == len(events) == 1 assert isinstance(events[0], SessionCallbackAdded) assert callback_obj == d.session_callbacks[0] == events[0].callback d.remove_next_tick_callback(callback_obj) assert len(d.session_callbacks) == 0 assert len(events) == 2 assert isinstance(events[0], SessionCallbackAdded) assert isinstance(events[1], SessionCallbackRemoved)
def test_patch_integer_property(self) -> None: d = document.Document() assert not d.roots assert len(d._all_models) == 0 root1 = SomeModelInTestDocument(foo=42) root2 = SomeModelInTestDocument(foo=43) child1 = SomeModelInTestDocument(foo=44) root1.child = child1 root2.child = child1 d.add_root(root1) d.add_root(root2) assert len(d.roots) == 2 event1 = ModelChangedEvent(d, root1, 'foo', root1.foo, 57, 57) patch1, buffers = process_document_events([event1]) d.apply_json_patch_string(patch1) assert root1.foo == 57 event2 = ModelChangedEvent(d, child1, 'foo', child1.foo, 67, 67) patch2, buffers = process_document_events([event2]) d.apply_json_patch_string(patch2) assert child1.foo == 67
def test_extra_referrer_error(self, caplog): d = document.Document() assert not d.roots class FakeMod(object): __name__ = 'junkjunkjunk' mod = FakeMod() import sys assert 'junkjunkjunk' not in sys.modules sys.modules['junkjunkjunk'] = mod d._modules.append(mod) assert 'junkjunkjunk' in sys.modules # add an extra referrer for delete_modules to complain about extra.append(mod) import gc assert len(gc.get_referrers(mod)) == 4 with caplog.at_level(logging.ERROR): d.delete_modules() assert "Module %r has extra unexpected referrers! This could indicate a serious memory leak. Extra referrers:" % mod in caplog.text assert len(caplog.records) == 1 assert 'junkjunkjunk' not in sys.modules assert d._modules is None
def test_patch_integer_property(self) -> None: d = document.Document() assert not d.roots assert len(d.models) == 0 root1 = SomeModelInTestDocument(foo=42) root2 = SomeModelInTestDocument(foo=43) child1 = SomeModelInTestDocument(foo=44) root1.child = child1 root2.child = child1 d.add_root(root1) d.add_root(root2) assert len(d.roots) == 2 event1 = ModelChangedEvent(d, root1, 'foo', 57) patch1 = patch_doc.create([event1]).content d.apply_json_patch(patch1) assert root1.foo == 57 event2 = ModelChangedEvent(d, child1, 'foo', 67) patch2 = patch_doc.create([event2]).content d.apply_json_patch(patch2) assert child1.foo == 67
def test_serialization_has_version(self) -> None: from bokeh import __version__ d = document.Document() json = d.to_json() assert json['version'] == __version__
def test_hold_bad_policy(self) -> None: d = document.Document() with pytest.raises(ValueError): d.hold("junk")
def test_set_title(self) -> None: d = document.Document() assert d.title == document.DEFAULT_TITLE d.title = "Foo" assert d.title == "Foo"
def test_add_roots(self) -> None: d = document.Document() assert not d.roots d.add_root(AnotherModelInTestDocument()) assert len(d.roots) == 1 assert next(iter(d.roots)).document == d