def __init__(self, object, params={}, **kwargs): if signature is None: raise ImportError( 'interact requires either recent Python version ' '(>=3.3 or IPython to inspect function signatures.') super(interactive, self).__init__(object, **params) new_kwargs = self.find_abbreviations(kwargs) # Before we proceed, let's make sure that the user has passed a set of args+kwargs # that will lead to a valid call of the function. This protects against unspecified # and doubly-specified arguments. try: check_argspec(object) except TypeError: # if we can't inspect, we can't validate pass else: getcallargs(object, **{n: v for n, v, _ in new_kwargs}) widgets = self.widgets_from_abbreviations(new_kwargs) if self.manual_update: widgets.append(('manual', Button(name=self.manual_name))) self._widgets = OrderedDict(widgets) self._pane = panel(self.object(**self.kwargs), name=self.name) self._inner_layout = Row(self._pane) widgets = [ widget for _, widget in widgets if isinstance(widget, Widget) ] if 'name' in params: widgets.insert(0, HTML('<h2>%s</h2>' % self.name)) self.widget_box = Column(*widgets) self.layout.objects = [self.widget_box, self._inner_layout] self._link_widgets()
def __init__(self, object, params={}, **kwargs): super(interactive, self).__init__(object, **params) new_kwargs = self.find_abbreviations(kwargs) # Before we proceed, let's make sure that the user has passed a set of args+kwargs # that will lead to a valid call of the function. This protects against unspecified # and doubly-specified arguments. try: check_argspec(object) except TypeError: # if we can't inspect, we can't validate pass else: getcallargs(object, **{n: v for n, v, _ in new_kwargs}) widgets = self.widgets_from_abbreviations(new_kwargs) if self.manual_update: widgets.append(('manual', Button(name=self.manual_name))) self._widgets = OrderedDict(widgets) self._pane = Pane(self.object(**self.kwargs), name=self.name, _temporary=True) self._inner_layout = Row(self._pane) self.widget_box = WidgetBox(*(widget for _, widget in widgets if isinstance(widget, Widget))) self.layout.objects = [self.widget_box, self._inner_layout] self._link_widgets()
def __init__(self, __interact_f, __options={}, **kwargs): VBox.__init__(self, _dom_classes=['widget-interact']) self.result = None self.args = [] self.kwargs = {} self.f = f = __interact_f self.clear_output = kwargs.pop('clear_output', True) self.manual = __options.get("manual", False) self.manual_name = __options.get("manual_name", "Run Interact") self.auto_display = __options.get("auto_display", False) new_kwargs = self.find_abbreviations(kwargs) # Before we proceed, let's make sure that the user has passed a set of args+kwargs # that will lead to a valid call of the function. This protects against unspecified # and doubly-specified arguments. try: check_argspec(f) except TypeError: # if we can't inspect, we can't validate pass else: getcallargs(f, **{n:v for n,v,_ in new_kwargs}) # Now build the widgets from the abbreviations. self.kwargs_widgets = self.widgets_from_abbreviations(new_kwargs) # This has to be done as an assignment, not using self.children.append, # so that traitlets notices the update. We skip any objects (such as fixed) that # are not DOMWidgets. c = [w for w in self.kwargs_widgets if isinstance(w, DOMWidget)] # If we are only to run the function on demand, add a button to request this. if self.manual: self.manual_button = Button(description=self.manual_name) c.append(self.manual_button) self.out = Output() c.append(self.out) self.children = c # Wire up the widgets # If we are doing manual 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 function with the initial parameters if self.manual: self.manual_button.on_click(self.update) # Also register input handlers on text areas, so the user can hit return to # invoke execution. for w in self.kwargs_widgets: if isinstance(w, Text): w.on_submit(self.update) else: for widget in self.kwargs_widgets: widget.observe(self.update, names='value') self.on_displayed(self.update)
def __init__(self, __interact_f, __options={}, **kwargs): VBox.__init__(self, _dom_classes=['widget-interact']) self.result = None self.args = [] self.kwargs = {} self.f = f = __interact_f self.clear_output = kwargs.pop('clear_output', True) self.manual = __options.get("manual", False) self.manual_name = __options.get("manual_name", "Run Interact") self.auto_display = __options.get("auto_display", False) new_kwargs = self.find_abbreviations(kwargs) # Before we proceed, let's make sure that the user has passed a set of args+kwargs # that will lead to a valid call of the function. This protects against unspecified # and doubly-specified arguments. try: check_argspec(f) except TypeError: # if we can't inspect, we can't validate pass else: getcallargs(f, **{n: v for n, v, _ in new_kwargs}) # Now build the widgets from the abbreviations. self.kwargs_widgets = self.widgets_from_abbreviations(new_kwargs) # This has to be done as an assignment, not using self.children.append, # so that traitlets notices the update. We skip any objects (such as fixed) that # are not DOMWidgets. c = [w for w in self.kwargs_widgets if isinstance(w, DOMWidget)] # If we are only to run the function on demand, add a button to request this. if self.manual: self.manual_button = Button(description=self.manual_name) c.append(self.manual_button) self.out = Output() c.append(self.out) self.children = c # Wire up the widgets # If we are doing manual 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 function with the initial parameters if self.manual: self.manual_button.on_click(self.update) # Also register input handlers on text areas, so the user can hit return to # invoke execution. for w in self.kwargs_widgets: if isinstance(w, Text): w.on_submit(self.update) else: for widget in self.kwargs_widgets: widget.observe(self.update, names='value') self.on_displayed(self.update)
def __call__(self, __interact_f=None, **kwargs): """ Make the given function interactive by adding and displaying the corresponding :class:`interactive` widget. Expects the first argument to be a function. Parameters to this function are widget abbreviations passed in as keyword arguments (``**kwargs``). Can be used as a decorator (see examples). Returns ------- f : __interact_f with interactive widget attached to it. Parameters ---------- __interact_f : function The function to which the interactive widgets are tied. The `**kwargs` should match the function signature. Passed to :func:`interactive()` **kwargs : various, optional An interactive widget is created for each keyword argument that is a valid widget abbreviation. Passed to :func:`interactive()` Examples -------- Render an interactive text field that shows the greeting with the passed in text:: # 1. Using interact as a function def greeting(text="World"): print("Hello {}".format(text)) interact(greeting, text="IPython Widgets") # 2. Using interact as a decorator @interact def greeting(text="World"): print("Hello {}".format(text)) # 3. Using interact as a decorator with named parameters @interact(text="IPython Widgets") def greeting(text="World"): print("Hello {}".format(text)) Render an interactive slider widget and prints square of number:: # 1. Using interact as a function def square(num=1): print("{} squared is {}".format(num, num*num)) interact(square, num=5) # 2. Using interact as a decorator @interact def square(num=2): print("{} squared is {}".format(num, num*num)) # 3. Using interact as a decorator with named parameters @interact(num=5) def square(num=2): print("{} squared is {}".format(num, num*num)) """ # If kwargs are given, replace self by a new # _InteractFactory with the updated kwargs if kwargs: params = list(interactive.param) kw = dict(self.kwargs) kw.update({k: v for k, v in kwargs.items() if k not in params}) opts = dict(self.opts, **{k: v for k, v in kwargs.items() if k in params}) self = type(self)(self.cls, opts, kw) f = __interact_f if f is None: # This branch handles the case 3 # @interact(a=30, b=40) # def f(*args, **kwargs): # ... # # Simply return the new factory return self elif 'throttled' in check_argspec(f).args: raise ValueError( 'A function cannot have "throttled" as an argument') # positional arg support in: https://gist.github.com/8851331 # Handle the cases 1 and 2 # 1. interact(f, **kwargs) # 2. @interact # def f(*args, **kwargs): # ... w = self.widget(f) try: f.widget = w except AttributeError: # some things (instancemethods) can't have attributes attached, # so wrap in a lambda f = lambda *args, **kwargs: __interact_f(*args, **kwargs) f.widget = w return w.layout
def interactive(__interact_f, **kwargs): """ Builds a group of interactive widgets tied to a function and places the group into a Box container. Returns ------- container : a Box instance containing multiple widgets Parameters ---------- __interact_f : function The function to which the interactive widgets are tied. The `**kwargs` should match the function signature. **kwargs : various, optional An interactive widget is created for each keyword argument that is a valid widget abbreviation. """ f = __interact_f co = kwargs.pop('clear_output', True) manual = kwargs.pop('__manual', False) kwargs_widgets = [] container = Box(_dom_classes=['widget-interact']) container.result = None container.args = [] container.kwargs = dict() kwargs = kwargs.copy() new_kwargs = _find_abbreviations(f, kwargs) # Before we proceed, let's make sure that the user has passed a set of args+kwargs # that will lead to a valid call of the function. This protects against unspecified # and doubly-specified arguments. try: check_argspec(f) except TypeError: # if we can't inspect, we can't validate pass else: getcallargs(f, **{n: v for n, v, _ in new_kwargs}) # Now build the widgets from the abbreviations. kwargs_widgets.extend(_widgets_from_abbreviations(new_kwargs)) # This has to be done as an assignment, not using container.children.append, # 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 manual: manual_button = Button(description="Run %s" % f.__name__) c.append(manual_button) out = Output() c.append(out) container.children = c # Build the callback def call_f(*args): container.kwargs = {} for widget in kwargs_widgets: value = widget.value container.kwargs[widget._kwarg] = value if manual: manual_button.disabled = True try: with out: if co: clear_output(wait=True) container.result = f(**container.kwargs) if container.result is not None: display(container.result) 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 # Otherwise, it is triggered for every trait change received # On-demand running also suppresses running the function with the initial parameters if manual: manual_button.on_click(call_f) # Also register input handlers on text areas, so the user can hit return to # invoke execution. for w in kwargs_widgets: if isinstance(w, Text): w.on_submit(call_f) else: for widget in kwargs_widgets: widget.observe(call_f, names='value') container.on_displayed( lambda _: call_f(dict(name=None, old=None, new=None))) return container
def interactive(__interact_f, **kwargs): """ Builds a group of interactive widgets tied to a function and places the group into a Box container. Returns ------- container : a Box instance containing multiple widgets Parameters ---------- __interact_f : function The function to which the interactive widgets are tied. The `**kwargs` should match the function signature. **kwargs : various, optional An interactive widget is created for each keyword argument that is a valid widget abbreviation. """ f = __interact_f co = kwargs.pop('clear_output', True) manual = kwargs.pop('__manual', False) kwargs_widgets = [] container = Box(_dom_classes=['widget-interact']) container.result = None container.args = [] container.kwargs = dict() kwargs = kwargs.copy() new_kwargs = _find_abbreviations(f, kwargs) # Before we proceed, let's make sure that the user has passed a set of args+kwargs # that will lead to a valid call of the function. This protects against unspecified # and doubly-specified arguments. try: check_argspec(f) except TypeError: # if we can't inspect, we can't validate pass else: getcallargs(f, **{n:v for n,v,_ in new_kwargs}) # Now build the widgets from the abbreviations. kwargs_widgets.extend(_widgets_from_abbreviations(new_kwargs)) # This has to be done as an assignment, not using container.children.append, # 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 manual: manual_button = Button(description="Run %s" % f.__name__) c.append(manual_button) container.children = c # Build the callback def call_f(*args): 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) if container.result is not None: display(container.result) 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 # Otherwise, it is triggered for every trait change received # On-demand running also suppresses running the function with the initial parameters if manual: manual_button.on_click(call_f) # Also register input handlers on text areas, so the user can hit return to # invoke execution. for w in kwargs_widgets: if isinstance(w, Text): w.on_submit(call_f) else: for widget in kwargs_widgets: widget.observe(call_f, names='value') container.on_displayed(lambda _: call_f(dict(name=None, old=None, new=None))) return container