Add 'on_demand' option to interact() so that long-running functions can be started only when explicitly requested

pull/37/head
Gordon Ball 12 years ago
parent c9961b44b6
commit 4752b83feb

@ -23,7 +23,7 @@ from inspect import getcallargs
from IPython.core.getipython import get_ipython
from IPython.html.widgets import (Widget, TextWidget,
FloatSliderWidget, IntSliderWidget, CheckboxWidget, DropdownWidget,
ContainerWidget, DOMWidget)
ContainerWidget, DOMWidget, ButtonWidget)
from IPython.display import display, clear_output
from IPython.utils.py3compat import string_types, unicode_type
from IPython.utils.traitlets import HasTraits, Any, Unicode
@ -114,7 +114,7 @@ def _widget_from_abbrev(abbrev, default=empty):
"""Build a Widget instance given an abbreviation or Widget."""
if isinstance(abbrev, Widget) or isinstance(abbrev, fixed):
return abbrev
widget = _widget_abbrev(abbrev)
if default is not empty and isinstance(abbrev, (list, tuple, dict)):
# if it's not a single-value abbreviation,
@ -175,6 +175,7 @@ def interactive(__interact_f, **kwargs):
"""Build a group of widgets to interact with a function."""
f = __interact_f
co = kwargs.pop('clear_output', True)
on_demand = kwargs.pop('on_demand', False)
kwargs_widgets = []
container = ContainerWidget()
container.result = None
@ -194,10 +195,15 @@ def interactive(__interact_f, **kwargs):
# so that traitlets notices the update. We skip any objects (such as fixed) that
# are not DOMWidgets.
c = [w for w in kwargs_widgets if isinstance(w, DOMWidget)]
# If we are only to run the function on demand, add a button to request this
if on_demand:
on_demand_button = ButtonWidget(description="Run %s" % f.__name__)
c.append(on_demand_button)
container.children = c
# Build the callback
def call_f(name, old, new):
def call_f(name=None, old=None, new=None):
container.kwargs = {}
for widget in kwargs_widgets:
value = widget.value
@ -214,16 +220,22 @@ def interactive(__interact_f, **kwargs):
ip.showtraceback()
# Wire up the widgets
for widget in kwargs_widgets:
widget.on_trait_change(call_f, 'value')
# If we are doing on demand running, the callback is only triggered by the button
# Otherwise, it is triggered for every trait change received
# On-demand running also suppresses running the fucntion with the initial parameters
if on_demand:
on_demand_button.on_click(call_f)
else:
for widget in kwargs_widgets:
widget.on_trait_change(call_f, 'value')
container.on_displayed(lambda _: call_f(None, None, None))
container.on_displayed(lambda _: call_f(None, None, None))
return container
def interact(__interact_f=None, **kwargs):
"""interact(f, **kwargs)
Interact with a function using widgets."""
# positional arg support in: https://gist.github.com/8851331
if __interact_f is not None:

Loading…
Cancel
Save