mirror of
https://github.com/jupyter/notebook.git
synced 2024-12-21 04:10:17 +08:00
Merge pull request #7554 from jdfreder/interact-fix
Use Output widget with Interact
This commit is contained in:
commit
1a4aac0de0
@ -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)
|
||||
Box, Button, DOMWidget, Output)
|
||||
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,29 +204,34 @@ 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):
|
||||
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:
|
||||
with output:
|
||||
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 = False
|
||||
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
|
||||
|
||||
# Wire up the widgets
|
||||
# If we are doing manual running, the callback is only triggered by the button
|
||||
|
@ -80,7 +80,8 @@ def check_widgets(container, **to_check):
|
||||
# build a widget dictionary, so it matches
|
||||
widgets = {}
|
||||
for w in container.children:
|
||||
widgets[w.description] = w
|
||||
if hasattr(w, 'description'):
|
||||
widgets[w.description] = w
|
||||
|
||||
for key, d in to_check.items():
|
||||
nt.assert_in(key, widgets)
|
||||
@ -138,7 +139,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), 1)
|
||||
nt.assert_equal(len(c.children), 2)
|
||||
w = c.children[0]
|
||||
check_widget(w,
|
||||
cls=widgets.IntSlider,
|
||||
@ -157,7 +158,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), 2)
|
||||
nt.assert_equal(len(c.children), 3)
|
||||
d = dict(
|
||||
cls=widgets.IntSlider,
|
||||
min=min,
|
||||
@ -174,7 +175,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), 2)
|
||||
nt.assert_equal(len(c.children), 3)
|
||||
d = dict(
|
||||
cls=widgets.IntSlider,
|
||||
min=min,
|
||||
@ -191,7 +192,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), 2)
|
||||
nt.assert_equal(len(c.children), 3)
|
||||
d = dict(
|
||||
cls=widgets.FloatSlider,
|
||||
min=min,
|
||||
@ -210,7 +211,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), 2)
|
||||
nt.assert_equal(len(c.children), 3)
|
||||
d = dict(
|
||||
cls=widgets.FloatSlider,
|
||||
min=min,
|
||||
@ -224,7 +225,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), 2)
|
||||
nt.assert_equal(len(c.children), 3)
|
||||
d = dict(
|
||||
cls=widgets.Dropdown,
|
||||
value=first,
|
||||
@ -471,7 +472,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), 1)
|
||||
nt.assert_equal(len(c.children), 2)
|
||||
w = c.children[0]
|
||||
check_widget(w,
|
||||
cls=widgets.Text,
|
||||
|
@ -34,43 +34,53 @@ 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."""
|
||||
self._flush()
|
||||
kernel = get_ipython().kernel
|
||||
session = kernel.session
|
||||
send = session.send
|
||||
self._original_send = send
|
||||
self._session = session
|
||||
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):
|
||||
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)
|
||||
# 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)
|
||||
# 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
|
||||
session.send = send_hook
|
||||
|
||||
def __exit__(self, exception_type, exception_value, traceback):
|
||||
"""Called upon exiting output widget context manager."""
|
||||
self._flush()
|
||||
self._session.send = self._original_send
|
||||
if self._kernel is not None:
|
||||
self._flush()
|
||||
self._session.send = self._original_send
|
||||
|
||||
def _flush(self):
|
||||
"""Flush stdout and stderr buffers."""
|
||||
|
Loading…
Reference in New Issue
Block a user