diff --git a/IPython/html/widgets/interaction.py b/IPython/html/widgets/interaction.py index 366a8fe..76d63f5 100644 --- a/IPython/html/widgets/interaction.py +++ b/IPython/html/widgets/interaction.py @@ -14,7 +14,7 @@ from inspect import getcallargs from IPython.core.getipython import get_ipython from IPython.html.widgets import (Widget, Text, FloatSlider, IntSlider, Checkbox, Dropdown, - Box, Button, DOMWidget, Output) + Box, Button, DOMWidget) from IPython.display import display, clear_output from IPython.utils.py3compat import string_types, unicode_type from IPython.utils.traitlets import HasTraits, Any, Unicode @@ -204,34 +204,29 @@ def interactive(__interact_f, **kwargs): if manual: manual_button = Button(description="Run %s" % f.__name__) c.append(manual_button) - - # Use an output widget to capture the output of interact. - output = Output() - c.append(output) container.children = c # Build the callback def call_f(name=None, old=None, new=None): - with output: - container.kwargs = {} - for widget in kwargs_widgets: - value = widget.value - container.kwargs[widget._kwarg] = value - if co: - clear_output(wait=True) + container.kwargs = {} + for widget in kwargs_widgets: + value = widget.value + container.kwargs[widget._kwarg] = value + if co: + clear_output(wait=True) + if manual: + manual_button.disabled = True + try: + container.result = f(**container.kwargs) + except Exception as e: + ip = get_ipython() + if ip is None: + container.log.warn("Exception in interact callback: %s", e, exc_info=True) + else: + ip.showtraceback() + finally: if manual: - manual_button.disabled = True - try: - container.result = f(**container.kwargs) - except Exception as e: - ip = get_ipython() - if ip is None: - container.log.warn("Exception in interact callback: %s", e, exc_info=True) - else: - ip.showtraceback() - finally: - if manual: - manual_button.disabled = False + manual_button.disabled = False # Wire up the widgets # If we are doing manual running, the callback is only triggered by the button diff --git a/IPython/html/widgets/tests/test_interaction.py b/IPython/html/widgets/tests/test_interaction.py index f1b0133..d209fd3 100644 --- a/IPython/html/widgets/tests/test_interaction.py +++ b/IPython/html/widgets/tests/test_interaction.py @@ -80,8 +80,7 @@ def check_widgets(container, **to_check): # build a widget dictionary, so it matches widgets = {} for w in container.children: - if hasattr(w, 'description'): - widgets[w.description] = w + widgets[w.description] = w for key, d in to_check.items(): nt.assert_in(key, widgets) @@ -139,7 +138,7 @@ def test_single_value_float(): def test_single_value_int(): for a in (1, 5, -3): c = interactive(f, a=a) - nt.assert_equal(len(c.children), 2) + nt.assert_equal(len(c.children), 1) w = c.children[0] check_widget(w, cls=widgets.IntSlider, @@ -158,7 +157,7 @@ def test_list_tuple_2_int(): c = interactive(f, tup=(1,-1)) for min, max in [ (0,1), (1,10), (1,2), (-5,5), (-20,-19) ]: c = interactive(f, tup=(min, max), lis=[min, max]) - nt.assert_equal(len(c.children), 3) + nt.assert_equal(len(c.children), 2) d = dict( cls=widgets.IntSlider, min=min, @@ -175,7 +174,7 @@ def test_list_tuple_3_int(): c = interactive(f, tup=(1,2,-1)) for min, max, step in [ (0,2,1), (1,10,2), (1,100,2), (-5,5,4), (-100,-20,4) ]: c = interactive(f, tup=(min, max, step), lis=[min, max, step]) - nt.assert_equal(len(c.children), 3) + nt.assert_equal(len(c.children), 2) d = dict( cls=widgets.IntSlider, min=min, @@ -192,7 +191,7 @@ def test_list_tuple_2_float(): c = interactive(f, tup=(0.5,-0.5)) for min, max in [ (0.5, 1.5), (1.1,10.2), (1,2.2), (-5.,5), (-20,-19.) ]: c = interactive(f, tup=(min, max), lis=[min, max]) - nt.assert_equal(len(c.children), 3) + nt.assert_equal(len(c.children), 2) d = dict( cls=widgets.FloatSlider, min=min, @@ -211,7 +210,7 @@ def test_list_tuple_3_float(): c = interactive(f, tup=(1,2.,-1.)) for min, max, step in [ (0.,2,1), (1,10.,2), (1,100,2.), (-5.,5.,4), (-100,-20.,4.) ]: c = interactive(f, tup=(min, max, step), lis=[min, max, step]) - nt.assert_equal(len(c.children), 3) + nt.assert_equal(len(c.children), 2) d = dict( cls=widgets.FloatSlider, min=min, @@ -225,7 +224,7 @@ def test_list_tuple_str(): values = ['hello', 'there', 'guy'] first = values[0] c = interactive(f, tup=tuple(values), lis=list(values)) - nt.assert_equal(len(c.children), 3) + nt.assert_equal(len(c.children), 2) d = dict( cls=widgets.Dropdown, value=first, @@ -472,7 +471,7 @@ def test_call_decorated_kwargs_on_trait_change(): def test_fixed(): c = interactive(f, a=widgets.fixed(5), b='text') - nt.assert_equal(len(c.children), 2) + nt.assert_equal(len(c.children), 1) w = c.children[0] check_widget(w, cls=widgets.Text, diff --git a/IPython/html/widgets/widget_output.py b/IPython/html/widgets/widget_output.py index 578df58..771ecb7 100644 --- a/IPython/html/widgets/widget_output.py +++ b/IPython/html/widgets/widget_output.py @@ -34,53 +34,43 @@ class Output(DOMWidget): print('prints to output widget')""" _view_name = Unicode('OutputView', sync=True) - def __init__(self, *args, **kwargs): - super(Output, self).__init__(*args, **kwargs) - from IPython import get_ipython - ip = get_ipython() - if ip is not None and hasattr(ip, 'kernel'): - self._kernel = ip.kernel - else: - self._kernel = None - def clear_output(self, *pargs, **kwargs): with self: clear_output(*pargs, **kwargs) def __enter__(self): """Called upon entering output widget context manager.""" - if self._kernel is not None: - self._flush() - session = self._kernel.session - send = session.send - self._original_send = send - self._session = session - - def send_hook(stream, msg_or_type, content=None, parent=None, ident=None, - buffers=None, track=False, header=None, metadata=None): - - # Handle both prebuild messages and unbuilt messages. - if isinstance(msg_or_type, (Message, dict)): - msg_type = msg_or_type['msg_type'] - msg = dict(msg_or_type) - else: - msg_type = msg_or_type - msg = session.msg(msg_type, content=content, parent=parent, - header=header, metadata=metadata) - - # If this is a message type that we want to forward, forward it. - if stream is self._kernel.iopub_socket and msg_type in ['clear_output', 'stream', 'display_data']: - self.send(msg) - else: - send(stream, msg, ident=ident, buffers=buffers, track=track) - - session.send = send_hook + self._flush() + kernel = get_ipython().kernel + session = kernel.session + send = session.send + self._original_send = send + self._session = session + + def send_hook(stream, msg_or_type, content=None, parent=None, ident=None, + buffers=None, track=False, header=None, metadata=None): + + # Handle both prebuild messages and unbuilt messages. + if isinstance(msg_or_type, (Message, dict)): + msg_type = msg_or_type['msg_type'] + msg = dict(msg_or_type) + else: + msg_type = msg_or_type + msg = session.msg(msg_type, content=content, parent=parent, + header=header, metadata=metadata) + + # If this is a message type that we want to forward, forward it. + if stream is kernel.iopub_socket and msg_type in ['clear_output', 'stream', 'display_data']: + self.send(msg) + else: + send(stream, msg, ident=ident, buffers=buffers, track=track) + + session.send = send_hook def __exit__(self, exception_type, exception_value, traceback): """Called upon exiting output widget context manager.""" - if self._kernel is not None: - self._flush() - self._session.send = self._original_send + self._flush() + self._session.send = self._original_send def _flush(self): """Flush stdout and stderr buffers."""