[sagemath] 01/01: Undo trac #21267 (SageNB interacts for Jupyter).
Tobias Hansen
thansen at moszumanska.debian.org
Sun Mar 26 18:23:17 UTC 2017
This is an automated email from the git hooks/post-receive script.
thansen pushed a commit to branch master
in repository sagemath.
commit 044cd0ba0311e06fb806d078826076a1ea592fb8
Author: Tobias Hansen <thansen at debian.org>
Date: Sun Mar 26 14:47:49 2017 +0100
Undo trac #21267 (SageNB interacts for Jupyter).
---
debian/changelog | 2 +
...o-trac-21267-sagenb-interacts-for-jupyter.patch | 1400 ++++++++++++++++++++
debian/patches/series | 1 +
3 files changed, 1403 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index 9ae6417..cdad511 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -16,6 +16,8 @@ sagemath (7.6-1) UNRELEASED; urgency=medium
- u0-use-local-threejs.patch
- u0-version-pari-2.9.patch
- u0-version-pynac-0.7.4.patch
+ * New patches:
+ - dt-undo-trac-21267-sagenb-interacts-for-jupyter.patch
-- Tobias Hansen <thansen at debian.org> Sat, 18 Mar 2017 12:00:06 +0000
diff --git a/debian/patches/dt-undo-trac-21267-sagenb-interacts-for-jupyter.patch b/debian/patches/dt-undo-trac-21267-sagenb-interacts-for-jupyter.patch
new file mode 100644
index 0000000..21aaa69
--- /dev/null
+++ b/debian/patches/dt-undo-trac-21267-sagenb-interacts-for-jupyter.patch
@@ -0,0 +1,1400 @@
+From 30955d2ec72338cc7b13c17922389bb58c8f278c Mon Sep 17 00:00:00 2001
+From: Jeroen Demeyer <jdemeyer at cage.ugent.be>
+Date: Mon, 19 Sep 2016 14:27:28 +0200
+Subject: Port SageNB interacts to Jupyter
+
+---
+ build/make/deps | 2 +-
+ src/doc/en/reference/repl/index.rst | 3 +
+ src/sage/repl/ipython_extension.py | 36 +-
+ src/sage/repl/ipython_kernel/all_jupyter.py | 9 +
+ src/sage/repl/ipython_kernel/interact.py | 242 ++++++++++
+ src/sage/repl/ipython_kernel/kernel.py | 22 +-
+ src/sage/repl/ipython_kernel/widgets.py | 407 +++++++++++++++++
+ src/sage/repl/ipython_kernel/widgets_sagenb.py | 584 +++++++++++++++++++++++++
+ 8 files changed, 1299 insertions(+), 6 deletions(-)
+ create mode 100644 src/sage/repl/ipython_kernel/all_jupyter.py
+ create mode 100644 src/sage/repl/ipython_kernel/interact.py
+ create mode 100644 src/sage/repl/ipython_kernel/widgets.py
+ create mode 100644 src/sage/repl/ipython_kernel/widgets_sagenb.py
+
+--- a/sage/build/make/deps
++++ b/sage/build/make/deps
+@@ -201,7 +201,7 @@
+ | $(SAGERUNTIME) $(inst_maxima) $(inst_networkx) $(inst_scipy) \
+ $(inst_matplotlib) $(inst_pillow) $(inst_mathjax) $(inst_mpmath) \
+ $(inst_ipykernel) $(inst_jupyter_client) $(inst_conway_polynomials) \
+- $(inst_tachyon) $(inst_jmol) $(inst_thebe) $(inst_ipywidgets)
++ $(inst_tachyon) $(inst_jmol) $(inst_thebe)
+
+ doc: doc-html
+
+--- a/sage/src/doc/en/reference/repl/index.rst
++++ b/sage/src/doc/en/reference/repl/index.rst
+@@ -92,9 +92,6 @@
+ sage/repl/interpreter
+ sage/repl/ipython_extension
+ sage/repl/interface_magic
+- sage/repl/ipython_kernel/interact
+- sage/repl/ipython_kernel/widgets
+- sage/repl/ipython_kernel/widgets_sagenb
+ sage/repl/ipython_kernel/install
+ sage/repl/ipython_kernel/kernel
+ sage/repl/ipython_tests
+--- a/sage/src/sage/repl/ipython_extension.py
++++ b/sage/src/sage/repl/ipython_extension.py
+@@ -400,28 +400,14 @@
+ import atexit
+ atexit.register(quit)
+
+- @staticmethod
+- def all_globals():
+- """
+- Return a Python module containing all globals which should be
+- made available to the user.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_extension import SageCustomizations
+- sage: SageCustomizations.all_globals()
+- <module 'sage.all_cmdline' ...>
+- """
+- from sage import all_cmdline
+- return all_cmdline
+-
+ def init_environment(self):
+ """
+ Set up Sage command-line environment
+ """
+ # import outside of cell so we don't get a traceback
++ from sage import all_cmdline
+ from sage.repl.user_globals import initialize_globals
+- initialize_globals(self.all_globals(), self.shell.user_ns)
++ initialize_globals(all_cmdline, self.shell.user_ns)
+ self.run_init()
+
+ def run_init(self):
+@@ -456,24 +442,6 @@
+ s.physical_line_transforms.insert(1, SagePromptTransformer())
+ s.python_line_transforms.append(SagePreparseTransformer())
+
+-
+-class SageJupyterCustomizations(SageCustomizations):
+- @staticmethod
+- def all_globals():
+- """
+- Return a Python module containing all globals which should be
+- made available to the user when running the Jupyter notebook.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_extension import SageJupyterCustomizations
+- sage: SageJupyterCustomizations.all_globals()
+- <module 'sage.repl.ipython_kernel.all_jupyter' ...>
+- """
+- from .ipython_kernel import all_jupyter
+- return all_jupyter
+-
+-
+ # from http://stackoverflow.com/questions/4103773/efficient-way-of-having-a-function-only-execute-once-in-a-loop
+ from functools import wraps
+ def run_once(func):
+--- a/sage/src/sage/repl/ipython_kernel/all_jupyter.py
++++ /dev/null
+@@ -1,9 +0,0 @@
+-"""
+-All imports for Jupyter
+-"""
+-
+-from sage.all_cmdline import *
+-
+-from .widgets_sagenb import (input_box, text_control, slider,
+- range_slider, checkbox, selector, input_grid, color_selector)
+-from .interact import interact
+--- a/sage/src/sage/repl/ipython_kernel/interact.py
++++ /dev/null
+@@ -1,242 +0,0 @@
+-r"""
+-Interacts for the Sage Jupyter notebook
+-
+-This is mostly the same as the stock ``ipywidgets.interact``, but with
+-some customizations for Sage.
+-
+-TESTS:
+-
+-We need to setup a proper test environment for widgets::
+-
+- sage: from ipywidgets.widgets.tests import setup_test_comm
+- sage: setup_test_comm()
+-
+-EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.interact import interact
+- sage: @interact
+- ....: def f(x=(0,10)):
+- ....: pass
+- Interactive function <function f ...> with 1 widget
+- x: IntSlider(value=5, min=0, max=10, step=1, description=u'x')
+- sage: f.widget.children
+- (IntSlider(value=5, min=0, max=10, step=1, description=u'x'), Output())
+-"""
+-
+-#*****************************************************************************
+-# Copyright (C) 2017 Jeroen Demeyer <jdemeyer at cage.ugent.be>
+-#
+-# This program is free software: you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation, either version 2 of the License, or
+-# (at your option) any later version.
+-# http://www.gnu.org/licenses/
+-#*****************************************************************************
+-
+-from ipywidgets.widgets import SelectionSlider, ValueWidget
+-from ipywidgets.widgets.interaction import interactive, signature, ValueWidget
+-from copy import copy
+-from collections import Iterable, Iterator
+-from .widgets import EvalText, SageColorPicker
+-from sage.structure.element import parent
+-from sage.symbolic.ring import SR
+-from sage.plot.colors import Color
+-
+-
+-class sage_interactive(interactive):
+- """
+- Wrapper around the ipywidgets interactive which handles some SageNB
+- specifics.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.interact import sage_interactive
+- sage: def myfunc(x=10, y="hello", z=None): pass
+- sage: sage_interactive(myfunc, x=(0,100), z=["one", "two", "three"])
+- Interactive function <function myfunc ...> with 3 widgets
+- x: IntSlider(value=10, min=0, max=100, step=1, description=u'x')
+- y: Text(value=u'hello', description=u'y')
+- z: Dropdown(value='one', options=['one', 'two', 'three'], description=u'z')
+- """
+- def __init__(*args, **kwds):
+- """
+- See :class:`ipywidgets.widgets.interaction.interactive`
+-
+- TESTS::
+-
+- sage: from sage.repl.ipython_kernel.interact import sage_interactive
+- sage: def myfunc(): pass
+- sage: sage_interactive(myfunc, dict(manual=True))
+- Manual interactive function <function myfunc ...> with 0 widgets
+-
+- ::
+-
+- sage: def myfunc(auto_update=False): pass
+- sage: sage_interactive(myfunc)
+- Manual interactive function <function myfunc ...> with 0 widgets
+- sage: def myfunc(auto_update=None): pass
+- sage: sage_interactive(myfunc)
+- Interactive function <function myfunc ...> with 0 widgets
+- """
+- # Use *args to avoid name clash with keyword arguments
+- if len(args) < 3:
+- (self, f) = args
+- options = {}
+- else:
+- (self, f, options) = args
+- options = options.copy()
+-
+- # Check for auto_update in signature
+- sig = signature(f)
+- params = copy(sig.parameters)
+- try:
+- p_auto_update = params.pop("auto_update")
+- except KeyError:
+- pass
+- else:
+- options["manual"] = (p_auto_update.default is False)
+-
+- self.__signature = sig.replace(parameters=params.values())
+- super(sage_interactive, self).__init__(f, options, **kwds)
+- if self.manual:
+- # In Sage, manual interacts are always run once
+- self.on_displayed(self.update)
+-
+- def __repr__(self):
+- """
+- Textual representation of this interactive function.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.interact import sage_interactive
+- sage: def myfunc(): pass
+- sage: sage_interactive(myfunc)
+- Interactive function <function myfunc ...> with 0 widgets
+- """
+- s = "Manual interactive" if self.manual else "Interactive"
+- widgets = [w for w in self.children if isinstance(w, ValueWidget)]
+- n = len(widgets)
+- s += " function %r with %s widget%s" % (
+- self.f, n, "s" if n != 1 else "")
+- for w in widgets:
+- s += "\n %s: %s" % (w._kwarg, w)
+- return s
+-
+- def signature(self):
+- """
+- Return the fixed signature of the interactive function (after
+- a possible ``auto_update`` parameter was removed).
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.interact import sage_interactive
+- sage: def myfunc(x=[1,2,3], auto_update=False): pass
+- sage: sage_interactive(myfunc).signature().parameters
+- OrderedDict([('x', <Parameter ... 'x'>)])
+- """
+- return self.__signature
+-
+- @classmethod # Behaves like a staticmethod, but we need super()
+- def widget_from_single_value(cls, abbrev, *args, **kwds):
+- """
+- Convert a single value (i.e. a non-iterable) to a widget.
+-
+- This supports the Sage :class:`Color` class. Any unknown type
+- is changed to a string for evaluating. This is meant to support
+- symbolic expressions like ``sin(x)``.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.interact import sage_interactive
+- sage: sage_interactive.widget_from_single_value("sin(x)")
+- Text(value=u'sin(x)')
+- sage: sage_interactive.widget_from_single_value(sin(x))
+- EvalText(value=u'sin(x)')
+- sage: from sage.plot.colors import Color
+- sage: sage_interactive.widget_from_single_value(Color('cornflowerblue'))
+- SageColorPicker(value='#6495ed')
+- """
+- # Support Sage Colors
+- if isinstance(abbrev, Color):
+- return SageColorPicker(value=abbrev.html_color())
+- # Get widget from IPython if possible
+- widget = super(sage_interactive, cls).widget_from_single_value(abbrev, *args, **kwds)
+- if widget is not None or isinstance(abbrev, Iterable):
+- return widget
+- # If IPython didn't construct a widget and the abbrev is not an
+- # iterable, return an EvalText widget
+- return EvalText(value=str(abbrev))
+-
+- @classmethod # Behaves like a staticmethod, but we need super()
+- def widget_from_tuple(cls, abbrev, *args, **kwds):
+- """
+- Convert a tuple to a widget.
+-
+- This supports two SageNB extensions: ``(description, abbrev)``
+- if ``description`` is a string and ``(default, abbrev)`` if
+- ``abbrev`` is not a single value.
+-
+- Symbolic expressions are changed to a floating-point number.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.interact import sage_interactive
+- sage: sage_interactive.widget_from_tuple( (0, 10) )
+- IntSlider(value=5, min=0, max=10, step=1)
+- sage: sage_interactive.widget_from_tuple( (3, (0, 10)) )
+- IntSlider(value=3, min=0, max=10, step=1)
+- sage: sage_interactive.widget_from_tuple( (2, dict(one=1, two=2, three=3)) )
+- Dropdown(value=2, options={'three': 3, 'two': 2, 'one': 1})
+- sage: sage_interactive.widget_from_tuple( (sqrt(2), pi) )
+- FloatSlider(value=2.277903107981444, min=1.4142135623730951, max=3.141592653589793, step=0.1)
+- """
+- # Support (description, abbrev)
+- if len(abbrev) == 2 and isinstance(abbrev[0], str):
+- widget = cls.widget_from_abbrev(abbrev[1])
+- widget.descriprion = abbrev[0]
+- return widget
+- # Support (default, abbrev)
+- if len(abbrev) == 2 and isinstance(abbrev[1], Iterable):
+- widget = cls.widget_from_abbrev(abbrev[1])
+- widget.value = abbrev[0]
+- return widget
+- # Numerically evaluate symbolic expressions
+- def n(x):
+- if parent(x) is SR:
+- return x.numerical_approx()
+- else:
+- return x
+- abbrev = tuple(n(x) for x in abbrev)
+- return super(sage_interactive, cls).widget_from_tuple(abbrev, *args, **kwds)
+-
+- @classmethod # Behaves like a staticmethod, but we need super()
+- def widget_from_iterable(cls, abbrev, *args, **kwds):
+- """
+- Convert an unspecified iterable to a widget.
+-
+- This behaves like in ipywidgets, except that an iterator (like
+- a generator object) becomes a ``SelectionSlider``.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.interact import sage_interactive
+- sage: sage_interactive.widget_from_iterable([1..5])
+- Dropdown(value=1, options=[1, 2, 3, 4, 5])
+- sage: sage_interactive.widget_from_iterable(iter([1..5]))
+- SelectionSlider(value=1, options=[1, 2, 3, 4, 5])
+- sage: sage_interactive.widget_from_iterable((1..5))
+- SelectionSlider(value=1, options=[1, 2, 3, 4, 5])
+- sage: sage_interactive.widget_from_iterable(x for x in [1..5])
+- SelectionSlider(value=1, options=[1, 2, 3, 4, 5])
+- sage: def gen():
+- ....: yield 1; yield 2; yield 3; yield 4; yield 5
+- sage: sage_interactive.widget_from_iterable(gen())
+- SelectionSlider(value=1, options=[1, 2, 3, 4, 5])
+- """
+- if isinstance(abbrev, Iterator):
+- return SelectionSlider(options=list(abbrev))
+- return super(sage_interactive, cls).widget_from_iterable(abbrev, *args, **kwds)
+-
+-
+-# @interact decorator
+-interact = sage_interactive.factory()
+--- a/sage/src/sage/repl/ipython_kernel/kernel.py
++++ b/sage/src/sage/repl/ipython_kernel/kernel.py
+@@ -19,9 +19,9 @@
+ from ipykernel.zmqshell import ZMQInteractiveShell
+ from traitlets import Type
+
+-from sage.env import SAGE_VERSION
++from sage.env import SAGE_VERSION, SAGE_EXTCODE, SAGE_DOC
+ from sage.repl.interpreter import SageNotebookInteractiveShell
+-from sage.repl.ipython_extension import SageJupyterCustomizations
++from sage.repl.ipython_extension import SageCustomizations
+
+ class SageZMQInteractiveShell(SageNotebookInteractiveShell, ZMQInteractiveShell):
+ pass
+@@ -48,7 +48,7 @@
+ <sage.repl.ipython_kernel.kernel.SageKernel object at 0x...>
+ """
+ super(SageKernel, self).__init__(**kwds)
+- SageJupyterCustomizations(self.shell)
++ SageCustomizations(self.shell)
+
+ @property
+ def banner(self):
+@@ -166,21 +166,5 @@
+ ]
+
+ def pre_handler_hook(self):
+- """
+- Restore the signal handlers to their default values at Sage
+- startup, saving the old handler at the ``saved_sigint_handler``
+- attribute. This is needed because Jupyter needs to change the
+- ``SIGINT`` handler.
+-
+- See :trac:`19135`.
+-
+- TESTS::
+-
+- sage: from sage.repl.ipython_kernel.kernel import SageKernel
+- sage: k = SageKernel.__new__(SageKernel)
+- sage: k.pre_handler_hook()
+- sage: k.saved_sigint_handler
+- <built-in function python_check_interrupt>
+- """
+ from cysignals import init_cysignals
+ self.saved_sigint_handler = init_cysignals()
+--- a/sage/src/sage/repl/ipython_kernel/widgets.py
++++ /dev/null
+@@ -1,407 +0,0 @@
+-r"""
+-Widgets to be used for the Sage Jupyter notebook
+-
+-These are all based on widgets from ``ipywidgets``, changing or
+-combining existing widgets.
+-
+-TESTS:
+-
+-We need to setup a proper test environment for widgets::
+-
+- sage: from ipywidgets.widgets.tests import setup_test_comm
+- sage: setup_test_comm()
+-"""
+-
+-#*****************************************************************************
+-# Copyright (C) 2017 Jeroen Demeyer <jdemeyer at cage.ugent.be>
+-#
+-# This program is free software: you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation, either version 2 of the License, or
+-# (at your option) any later version.
+-# http://www.gnu.org/licenses/
+-#*****************************************************************************
+-
+-from ipywidgets.widgets import (IntSlider, IntRangeSlider, FloatSlider,
+- FloatRangeSlider, Text, Textarea, ColorPicker,
+- Label, HBox, VBox, ValueWidget)
+-from traitlets import List, Unicode, link
+-
+-from sage.misc.sage_eval import sage_eval
+-from sage.repl.user_globals import get_globals
+-from sage.plot.colors import Color
+-
+-
+-class TransformWidget(object):
+- """
+- A mixin class for a widget to transform the bare widget value for
+- use in interactive functions.
+-
+- INPUT:
+-
+- - ``transform`` -- a one-argument function which transforms the
+- value of the widget for use by an interactive function.
+-
+- - other arguments are passed to the base class
+-
+- EXAMPLES::
+-
+- sage: from ipywidgets import ToggleButtons
+- sage: from sage.repl.ipython_kernel.widgets import TransformWidget
+- sage: class TransformToggleButtons(TransformWidget, ToggleButtons): pass
+- sage: w = TransformToggleButtons(options=["pi", "e"], transform=lambda x: x+x)
+- sage: w
+- TransformToggleButtons(value='pi', options=['pi', 'e'])
+- sage: w.get_interact_value()
+- 'pipi'
+- """
+- def __init__(self, *args, **kwds):
+- """
+- Construct a :class:`TransformWidget`.
+-
+- TESTS::
+-
+- sage: from sage.repl.ipython_kernel.widgets import TransformWidget
+- sage: w = TransformWidget(transform=dict)
+- sage: w._TransformWidget__transform
+- <type 'dict'>
+- """
+- self.__transform = kwds.pop("transform", None)
+- return super(TransformWidget, self).__init__(*args, **kwds)
+-
+- def get_value(self):
+- """
+- Return ``self.value``.
+-
+- This is meant to be overridden by sub-classes to change the
+- input of the transform function.
+-
+- EXAMPLES::
+-
+- sage: from ipywidgets import ColorPicker
+- sage: from sage.repl.ipython_kernel.widgets import TransformWidget
+- sage: class TransformColorPicker(TransformWidget, ColorPicker): pass
+- sage: TransformColorPicker(value="red").get_value()
+- 'red'
+- """
+- return self.value
+-
+- def get_interact_value(self):
+- """
+- Return the transformed value of this widget, by calling
+- the ``transform`` function.
+-
+- EXAMPLES:
+-
+- sage: from ipywidgets import Checkbox
+- sage: from sage.repl.ipython_kernel.widgets import TransformWidget
+- sage: class TransformCheckbox(TransformWidget, Checkbox): pass
+- sage: w = TransformCheckbox(value=True, transform=int); w
+- TransformCheckbox(value=True)
+- sage: w.get_interact_value()
+- 1
+- """
+- v = self.get_value()
+- f = self.__transform
+- if f is None:
+- return v
+- else:
+- return f(v)
+-
+-
+-class EvalWidget(TransformWidget):
+- """
+- A mixin class for a widget to evaluate (using :func:`sage_eval`) the
+- widget value and possibly transform it like :class:`TransformWidget`.
+-
+- EXAMPLES::
+-
+- sage: from ipywidgets import ToggleButtons
+- sage: from sage.repl.ipython_kernel.widgets import EvalWidget
+- sage: class EvalToggleButtons(EvalWidget, ToggleButtons): pass
+- sage: w = EvalToggleButtons(options=["pi", "e"], transform=lambda x: x+x)
+- sage: w
+- EvalToggleButtons(value='pi', options=['pi', 'e'])
+- sage: w.get_interact_value()
+- 2*pi
+- """
+- def get_value(self):
+- """
+- Evaluate the bare widget value using :func:`sage_eval`.
+-
+- EXAMPLES:
+-
+- sage: from ipywidgets import Dropdown
+- sage: from sage.repl.ipython_kernel.widgets import EvalWidget
+- sage: class EvalDropdown(EvalWidget, Dropdown): pass
+- sage: w = EvalDropdown(options=["the_answer"], transform=RR)
+- sage: w
+- EvalDropdown(value='the_answer', options=['the_answer'])
+- sage: the_answer = 42
+- sage: w.get_value()
+- 42
+- sage: w.get_interact_value()
+- 42.0000000000000
+- """
+- return sage_eval(self.value, get_globals())
+-
+-
+-class TransformIntSlider(TransformWidget, IntSlider):
+- """
+- An :class:`ipywidgets.IntSlider` widget with an optional
+- transformation.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.widgets import TransformIntSlider
+- sage: w = TransformIntSlider(min=0, max=100, value=7, transform=lambda x: x^2)
+- sage: w
+- TransformIntSlider(value=7, min=0, max=100, step=1)
+- sage: w.get_interact_value()
+- 49
+- """
+- pass
+-
+-
+-class TransformFloatSlider(TransformWidget, FloatSlider):
+- """
+- A :class:`ipywidgets.FloatSlider` widget with an optional
+- transformation.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.widgets import TransformFloatSlider
+- sage: w = TransformFloatSlider(min=0, max=100, value=7, transform=lambda x: sqrt(x))
+- sage: w
+- TransformFloatSlider(value=7.0, min=0.0, max=100.0, step=0.1)
+- sage: w.get_interact_value()
+- 2.6457513110645907
+- """
+- pass
+-
+-
+-class TransformIntRangeSlider(TransformWidget, IntRangeSlider):
+- """
+- An :class:`ipywidgets.IntRangeSlider` widget with an optional
+- transformation.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.widgets import TransformIntRangeSlider
+- sage: w = TransformIntRangeSlider(min=0, max=100, value=(7,9), transform=lambda x: x[1]-x[0])
+- sage: w
+- TransformIntRangeSlider(value=(7, 9), min=0, max=100, step=1)
+- sage: w.get_interact_value()
+- 2
+- """
+- pass
+-
+-
+-class TransformFloatRangeSlider(TransformWidget, FloatRangeSlider):
+- """
+- An :class:`ipywidgets.FloatRangeSlider` widget with an optional
+- transformation.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.widgets import TransformFloatRangeSlider
+- sage: w = TransformFloatRangeSlider(min=0, max=100, value=(7,9), transform=lambda x: x[1]-x[0])
+- sage: w
+- TransformFloatRangeSlider(value=(7.0, 9.0), min=0.0, max=100.0, step=1.0)
+- sage: w.get_interact_value()
+- 2.0
+- """
+- pass
+-
+-
+-class TransformText(TransformWidget, Text):
+- """
+- A :class:`ipywidgets.Text` widget with an optional
+- transformation.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.widgets import TransformText
+- sage: w = TransformText(value="hello", transform=lambda x: x+x)
+- sage: w
+- TransformText(value=u'hello')
+- sage: w.get_interact_value()
+- u'hellohello'
+- """
+- pass
+-
+-
+-class TransformTextarea(TransformWidget, Textarea):
+- """
+- A :class:`ipywidgets.Textarea` widget with an optional
+- transformation.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.widgets import TransformTextarea
+- sage: w = TransformTextarea(value="hello", transform=lambda x: x+x)
+- sage: w
+- TransformTextarea(value=u'hello')
+- sage: w.get_interact_value()
+- u'hellohello'
+- """
+- pass
+-
+-
+-class EvalText(EvalWidget, Text):
+- """
+- A :class:`ipywidgets.Text` widget which evaluates (using
+- :func:`sage_eval`) its contents and applies an optional transformation.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.widgets import EvalText
+- sage: w = EvalText(value="pi", transform=lambda x: x^2)
+- sage: w
+- EvalText(value=u'pi')
+- sage: w.get_interact_value()
+- pi^2
+- """
+- pass
+-
+-
+-class EvalTextarea(EvalWidget, Textarea):
+- """
+- A :class:`ipywidgets.Textarea` widget which evaluates (using
+- :func:`sage_eval`) its contents and applies an optional transformation.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.widgets import EvalTextarea
+- sage: w = EvalTextarea(value="pi", transform=lambda x: x^2)
+- sage: w
+- EvalTextarea(value=u'pi')
+- sage: w.get_interact_value()
+- pi^2
+- """
+- pass
+-
+-
+-class SageColorPicker(ColorPicker):
+- """
+- A color picker widget return a Sage :class:`Color`.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.widgets import SageColorPicker
+- sage: SageColorPicker()
+- SageColorPicker(value='black')
+- """
+- def get_interact_value(self):
+- """
+- Return a Sage :class:`Color` corresponding to the value of this
+- widget.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.widgets import SageColorPicker
+- sage: SageColorPicker().get_interact_value()
+- RGB color (0.0, 0.0, 0.0)
+- """
+- return Color(self.value)
+-
+-
+-class Grid(TransformWidget, HBox, ValueWidget):
+- """
+- A square grid of widgets whose value is a list of lists of the
+- values of the individual widgets.
+-
+- This is usually created using the :func:`input_grid` function.
+-
+- EXAMPLES::
+-
+- sage: from ipywidgets import Text
+- sage: from sage.repl.ipython_kernel.widgets import Grid
+- sage: w = Grid(2, 2, lambda i,j: Text(value="%s,%s"%(i,j)))
+- sage: w
+- Grid(value=[[u'0,0', u'0,1'], [u'1,0', u'1,1']], children=(Label(value=u''), VBox(children=(Text(value=u'0,0'), Text(value=u'1,0'))), VBox(children=(Text(value=u'0,1'), Text(value=u'1,1')))))
+- sage: w.get_interact_value()
+- [[u'0,0', u'0,1'], [u'1,0', u'1,1']]
+- """
+- value = List()
+- description = Unicode()
+-
+- def __init__(self, nrows, ncols, make_widget, description=u"", transform=None):
+- """
+- Create a :class:`Grid` widget.
+-
+- INPUT:
+-
+- - ``nrows``, ``ncols`` -- number of rows and columns in the grid
+-
+- - ``make_widget`` -- a function of two arguments ``(i,j)``
+- returning the widget to be placed at position ``(i,j)``.
+-
+- - ``description`` -- an optional label.
+-
+- - ``transform`` -- an optional transformation, see :class:`TransformWidget`.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.widgets import Grid, EvalText
+- sage: w = Grid(2, 2, lambda i,j: EvalText(str(j+4*i)),
+- ....: description="2x2 matrix", transform=matrix)
+- sage: w
+- Grid(value=[[0, 1], [4, 5]], description=u'2x2 matrix', children=(Label(value=u'2x2 matrix'), VBox(children=(EvalText(value=u'0'), EvalText(value=u'4'))), VBox(children=(EvalText(value=u'1'), EvalText(value=u'5')))))
+- sage: w.get_interact_value()
+- [0 1]
+- [4 5]
+-
+- TESTS::
+-
+- sage: w = Grid(0, 1, lambda i,j: EvalText())
+- Traceback (most recent call last):
+- ...
+- ValueError: Grid requires a positive number of rows and columns
+- """
+- if nrows < 1 or ncols < 1:
+- raise ValueError("Grid requires a positive number of rows and columns")
+- super(Grid, self).__init__(transform=transform)
+-
+- label = Label(description)
+- link((label, "value"), (self, "description"))
+-
+- self.cols = []
+- for j in range(ncols):
+- col = VBox()
+- widgets = []
+- for i in range(nrows):
+- w = make_widget(i, j)
+- w.observe(self._update, names="value")
+- widgets.append(w)
+- col.children = widgets
+- self.cols.append(col)
+- self.children = [label] + self.cols
+- self._update()
+-
+- def _update(self, *args):
+- """
+- Compute the ``value`` of the grid.
+-
+- Thanks to traitlets magic, this is automatically called
+- whenever one of the child widgets changes.
+-
+- EXAMPLES::
+-
+- sage: from ipywidgets import Text
+- sage: from sage.repl.ipython_kernel.widgets import Grid
+- sage: w = Grid(2, 2, lambda i,j: Text(value="%s,%s"%(i,j)))
+- sage: w._update()
+- sage: w.value
+- [[u'0,0', u'0,1'], [u'1,0', u'1,1']]
+- sage: w.cols[0].children[0].value = "abc"
+- sage: w.value
+- [[u'abc', u'0,1'], [u'1,0', u'1,1']]
+- """
+- v = [[]]
+- for col in self.cols:
+- for i in range(len(col.children)):
+- if i >= len(v):
+- v.append([])
+- v[i].append(col.children[i].get_interact_value())
+- self.value = v
+--- a/sage/src/sage/repl/ipython_kernel/widgets_sagenb.py
++++ /dev/null
+@@ -1,584 +0,0 @@
+-r"""
+-Functions to construct widgets, based on the old SageNB interface.
+-
+-These should ensure mostly backwards compatibility with SageNB.
+-
+-TESTS:
+-
+-We need to setup a proper test environment for widgets::
+-
+- sage: from ipywidgets.widgets.tests import setup_test_comm
+- sage: setup_test_comm()
+-
+-EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.widgets_sagenb import text_control
+- sage: text_control("Hello World!")
+- HTML(value=u'Hello World!')
+-"""
+-
+-#*****************************************************************************
+-# Copyright (C) 2017 Jeroen Demeyer <jdemeyer at cage.ugent.be>
+-#
+-# This program is free software: you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation, either version 2 of the License, or
+-# (at your option) any later version.
+-# http://www.gnu.org/licenses/
+-#*****************************************************************************
+-
+-from ipywidgets.widgets import (IntSlider, IntRangeSlider, FloatSlider,
+- FloatRangeSlider, SelectionSlider,
+- Checkbox, ToggleButtons, Dropdown, HTML)
+-from .widgets import (TransformText, TransformTextarea,
+- TransformIntSlider, TransformIntRangeSlider,
+- TransformFloatSlider, TransformFloatRangeSlider,
+- EvalText, EvalTextarea, SageColorPicker, Grid)
+-from ipywidgets.widgets.interaction import _get_min_max_value
+-from collections import Iterable, Sequence
+-from numbers import Integral, Rational, Real
+-
+-from sage.structure.all import parent
+-from sage.arith.srange import srange
+-from sage.plot.colors import Color
+-from sage.misc.six import u
+-from sage.symbolic.ring import SR
+-from sage.rings.all import RR
+-
+-
+-# The SageNB text_control widget does exactly the same as the
+-# ipywidgets.HTML widget
+-text_control = HTML
+-
+-
+-def input_box(default=None, label=None, type=None, width=80, height=1):
+- """
+- A textbox widget.
+-
+- INPUT:
+-
+- - ``default`` -- initial value
+-
+- - ``label`` -- optional label
+-
+- - ``type`` -- function of one variable or ``None``. if ``type`` is
+- ``str``, the value of this widget for interactive functions is
+- just the text as ``str``. Otherwise, the text is evaluated using
+- :func:`sage_eval`, ``type`` is called on it and the result is used
+- as value. Except if ``type`` is ``None``, then the evaluated text
+- is used as value.
+-
+- - ``width`` -- width of the box
+-
+- - ``height`` -- if ``height > 1``, create a textarea instead of a
+- single-line textbox.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.all_jupyter import input_box
+-
+- The most basic usage is when ``type=str``::
+-
+- sage: w = input_box("4+5", type=str, label="enter a string")
+- sage: w
+- TransformText(value=u'4+5', description=u'enter a string')
+- sage: w.get_interact_value()
+- '4+5'
+-
+- Without ``type``, the text is evaluated::
+-
+- sage: w = input_box("4+5")
+- sage: w
+- EvalText(value=u'4+5')
+- sage: w.get_interact_value()
+- 9
+-
+- With a different ``type``, the text is evaluated and ``type`` is
+- called on it:
+-
+- sage: w = input_box("4+5", type=float)
+- sage: w
+- EvalText(value=u'4+5')
+- sage: w.get_interact_value()
+- 9.0
+-
+- Despite the keyword name, ``type`` does not need to be a type::
+-
+- sage: w = input_box("4+5", type=sqrt)
+- sage: w
+- EvalText(value=u'4+5')
+- sage: w.get_interact_value()
+- 3
+-
+- When ``height > 1``, a textarea is returned::
+-
+- sage: w = input_box("4+5", width=100, height=1)
+- sage: w
+- EvalText(value=u'4+5')
+- sage: w = input_box("4+5", width=100, height=5)
+- sage: w
+- EvalTextarea(value=u'4+5')
+-
+- TESTS::
+-
+- sage: w = input_box(type=Color)
+- Traceback (most recent call last):
+- ...
+- NotImplementedError: type=Color is not supported
+- """
+- kwds = {}
+- if type is str:
+- kwds["transform"] = str # Convert unicode to str
+- if height > 1:
+- cls = TransformTextarea
+- else:
+- cls = TransformText
+- elif type is Color:
+- # This is special-cased by SageNB (with a non-trivial
+- # implementation!), but it doesn't seem to be used in practice
+- # because we have a SageColorPicker widget.
+- raise NotImplementedError("type=Color is not supported")
+- else:
+- kwds["transform"] = type
+- if height > 1:
+- cls = EvalTextarea
+- else:
+- cls = EvalText
+- if default is not None:
+- kwds["value"] = str(default)
+- if label is not None:
+- kwds["description"] = u(label)
+- w = cls(**kwds)
+- w.layout.max_width = str(width+1) + "em"
+- return w
+-
+-
+-def slider(vmin, vmax=None, step_size=None, default=None, label=None, display_value=True, _range=False):
+- """
+- A slider widget.
+-
+- INPUT:
+-
+- For a numeric slider (select a value from a range):
+-
+- - ``vmin``, ``vmax`` -- minimum and maximum value
+-
+- - ``step_size`` -- the step size
+-
+- For a selection slider (select a value from a list of values):
+-
+- - ``vmin`` -- a list of possible values for the slider
+-
+- For all sliders:
+-
+- - ``default`` -- initial value
+-
+- - ``label`` -- optional label
+-
+- - ``display_value`` -- (boolean) if ``True``, display the current
+- value.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.all_jupyter import slider
+- sage: slider(5, label="slide me")
+- TransformIntSlider(value=5, min=5, max=100, step=1, description=u'slide me')
+- sage: slider(5, 20)
+- TransformIntSlider(value=5, min=5, max=20, step=1)
+- sage: slider(5, 20, 0.5)
+- TransformFloatSlider(value=5.0, min=5.0, max=20.0, step=0.5)
+- sage: slider(5, 20, default=12)
+- TransformIntSlider(value=12, min=5, max=20, step=1)
+-
+- The parent of the inputs determines the parent of the value::
+-
+- sage: w = slider(5); w
+- TransformIntSlider(value=5, min=5, max=100, step=1)
+- sage: parent(w.get_interact_value())
+- Integer Ring
+- sage: w = slider(int(5)); w
+- IntSlider(value=5, min=5, max=100, step=1)
+- sage: parent(w.get_interact_value())
+- <type 'int'>
+- sage: w = slider(5, 20, step_size=RDF("0.1")); w
+- TransformFloatSlider(value=5.0, min=5.0, max=20.0, step=0.1)
+- sage: parent(w.get_interact_value())
+- Real Double Field
+- sage: w = slider(5, 20, step_size=10/3); w
+- SelectionSlider(value=35/3, options=[5, 25/3, 35/3, 15, 55/3])
+- sage: parent(w.get_interact_value())
+- Rational Field
+-
+- Symbolic input is evaluated numerically::
+-
+- sage: w = slider(e, pi); w
+- TransformFloatSlider(value=2.718281828459045, min=2.718281828459045, max=3.141592653589793, step=0.1)
+- sage: parent(w.get_interact_value())
+- Real Field with 53 bits of precision
+-
+- For a selection slider, the default is adjusted to one of the
+- possible values::
+-
+- sage: slider(range(10), default=17/10)
+- SelectionSlider(value=2, options=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+-
+- TESTS::
+-
+- sage: slider(range(5), range(5))
+- Traceback (most recent call last):
+- ...
+- TypeError: unexpected argument 'vmax' for a selection slider
+- sage: slider(range(5), step_size=2)
+- Traceback (most recent call last):
+- ...
+- TypeError: unexpected argument 'step_size' for a selection slider
+- sage: slider(5).readout
+- True
+- sage: slider(5, display_value=False).readout
+- False
+- """
+- kwds = {"readout": display_value}
+- if label:
+- kwds["description"] = u(label)
+-
+- # If vmin is iterable, return a SelectionSlider
+- if isinstance(vmin, Iterable):
+- if vmax is not None:
+- raise TypeError("unexpected argument 'vmax' for a selection slider")
+- if step_size is not None:
+- raise TypeError("unexpected argument 'step_size' for a selection slider")
+- if _range:
+- # https://github.com/ipython/ipywidgets/issues/760
+- raise NotImplementedError("range_slider does not support a list of values")
+- options = list(vmin)
+- # Find default in options
+- def err(v):
+- if v is default:
+- return (-1, 0)
+- try:
+- if v == default:
+- return (0, 0)
+- return (0, abs(v - default))
+- except Exception:
+- return (1, 0)
+- kwds["options"] = options
+- if default is not None:
+- kwds["value"] = min(options, key=err)
+- return SelectionSlider(**kwds)
+-
+- if default is not None:
+- kwds["value"] = default
+-
+- # Sum all input numbers to figure out type/parent
+- p = parent(sum(x for x in (vmin, vmax, step_size) if x is not None))
+-
+- # Change SR to RR
+- if p is SR:
+- p = RR
+-
+- # Convert all inputs to the common parent
+- if vmin is not None:
+- vmin = p(vmin)
+- if vmax is not None:
+- vmax = p(vmax)
+- if step_size is not None:
+- step_size = p(step_size)
+-
+- def tuple_elements_p(t):
+- "Convert all entries of the tuple `t` to `p`"
+- return tuple(p(x) for x in t)
+-
+- zero = p()
+- if isinstance(zero, Integral):
+- if p is int:
+- if _range:
+- cls = IntRangeSlider
+- else:
+- cls = IntSlider
+- else:
+- if _range:
+- kwds["transform"] = tuple_elements_p
+- cls = TransformIntRangeSlider
+- else:
+- kwds["transform"] = p
+- cls = TransformIntSlider
+- elif isinstance(zero, Rational):
+- # Rational => implement as SelectionSlider
+- if _range:
+- # https://github.com/ipython/ipywidgets/issues/760
+- raise NotImplementedError("range_slider does not support rational numbers")
+- vmin, vmax, value = _get_min_max_value(vmin, vmax, default, step_size)
+- kwds["value"] = value
+- kwds["options"] = srange(vmin, vmax, step_size, include_endpoint=True)
+- return SelectionSlider(**kwds)
+- elif isinstance(zero, Real):
+- if p is float:
+- if _range:
+- cls = FloatRangeSlider
+- else:
+- cls = FloatSlider
+- else:
+- if _range:
+- kwds["transform"] = tuple_elements_p
+- cls = TransformFloatRangeSlider
+- else:
+- kwds["transform"] = p
+- cls = TransformFloatSlider
+- else:
+- raise TypeError("unknown parent {!r} for slider".format(p))
+-
+- kwds["min"] = vmin
+- if vmax is not None:
+- kwds["max"] = vmax
+- if step_size is not None:
+- kwds["step"] = step_size
+- return cls(**kwds)
+-
+-
+-def range_slider(*args, **kwds):
+- """
+- A slider widget to select a range of values.
+-
+- INPUT:
+-
+- - ``vmin``, ``vmax`` -- minimum and maximum value
+-
+- - ``step_size`` -- the step size
+-
+- - ``default`` -- initial value, given as a 2-tuple
+-
+- - ``label`` -- optional label
+-
+- - ``display_value`` -- (boolean) if ``True``, display the current
+- value.
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.all_jupyter import range_slider
+- sage: range_slider(5, label="slide me")
+- TransformIntRangeSlider(value=(28, 76), min=5, max=100, step=1, description=u'slide me')
+- sage: range_slider(5, 20)
+- TransformIntRangeSlider(value=(8, 16), min=5, max=20, step=1)
+- sage: range_slider(5, 20, 0.5)
+- TransformFloatRangeSlider(value=(8.75, 16.25), min=5.0, max=20.0, step=0.5)
+- sage: range_slider(5, 20, default=(12,15))
+- TransformIntRangeSlider(value=(12, 15), min=5, max=20, step=1)
+-
+- The parent of the inputs determines the parent of the value::
+-
+- sage: w = range_slider(5); w
+- TransformIntRangeSlider(value=(28, 76), min=5, max=100, step=1)
+- sage: [parent(x) for x in w.get_interact_value()]
+- [Integer Ring, Integer Ring]
+- sage: w = range_slider(int(5)); w
+- IntRangeSlider(value=(28, 76), min=5, max=100, step=1)
+- sage: [parent(x) for x in w.get_interact_value()]
+- [<type 'int'>, <type 'int'>]
+- sage: w = range_slider(5, 20, step_size=RDF("0.1")); w
+- TransformFloatRangeSlider(value=(8.75, 16.25), min=5.0, max=20.0, step=0.1)
+- sage: [parent(x) for x in w.get_interact_value()]
+- [Real Double Field, Real Double Field]
+-
+- Unfortunately, rational numbers are not supported::
+-
+- sage: w = range_slider(5, 20, step_size=10/3); w
+- Traceback (most recent call last):
+- ...
+- NotImplementedError: range_slider does not support rational numbers
+-
+- TESTS::
+-
+- sage: range_slider(range(5))
+- Traceback (most recent call last):
+- ...
+- NotImplementedError: range_slider does not support a list of values
+- """
+- kwds["_range"] = True
+- return slider(*args, **kwds)
+-
+-
+-def checkbox(default=True, label=None):
+- """
+- A checkbox widget.
+-
+- INPUT:
+-
+- - ``default`` -- (boolean) initial value
+-
+- - ``label`` -- optional label
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.all_jupyter import checkbox
+- sage: checkbox(label="toggle me")
+- Checkbox(value=True, description=u'toggle me')
+- sage: checkbox(default=0)
+- Checkbox(value=False)
+- """
+- kwds = {"value": bool(default)}
+- if label is not None:
+- kwds["description"] = u(label)
+- return Checkbox(**kwds)
+-
+-
+-def selector(values, label=None, default=None, nrows=None, ncols=None, width=None, buttons=False):
+- """
+- A widget to select a value from a given list of values.
+-
+- This is rendered as a dropdown box (if ``buttons`` is False) or
+- as a list of buttons (if ``buttons`` is True).
+-
+- INPUT:
+-
+- - ``values`` -- a list of values to choose from (see examples below
+- for the accepted formats for this)
+-
+- - ``label`` -- optional label
+-
+- - ``default`` -- initial value
+-
+- - ``buttons`` -- (boolean) if True, display buttons instead of a
+- dropdown box
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.all_jupyter import selector
+- sage: selector(range(5), label="choose one")
+- Dropdown(value=0, options=[0, 1, 2, 3, 4], description=u'choose one')
+- sage: selector(range(5), buttons=True, default=4)
+- ToggleButtons(value=4, options=[0, 1, 2, 3, 4])
+-
+- Apart from a simple list, ``values`` can be given as a list of
+- 2-tuples ``(value, label)``::
+-
+- sage: selector([(1,"one"), (2,"two"), (3,"three")])
+- Dropdown(value=1, options=[('one', 1), ('two', 2), ('three', 3)])
+- sage: selector([(1,"one"), (2,"two"), (3,"three")], buttons=True)
+- ToggleButtons(value=1, options=[('one', 1), ('two', 2), ('three', 3)])
+-
+- A dict of ``label:value`` pairs is also allowed. Since a ``dict``
+- is not ordered, it is better to use an :class:`OrderedDict`::
+-
+- sage: from collections import OrderedDict
+- sage: selector(OrderedDict(one=1, two=2, three=3))
+- Dropdown(value=1, options=OrderedDict([('one', 1), ('three', 3), ('two', 2)]))
+- sage: selector(OrderedDict(one=1, two=2, three=3), buttons=True)
+- ToggleButtons(value=1, options=OrderedDict([('one', 1), ('three', 3), ('two', 2)]))
+-
+- The values can be any kind of object:
+-
+- sage: selector([sin(x^2), GF(29), EllipticCurve('37a1')])
+- Dropdown(value=sin(x^2), options=[sin(x^2), Finite Field of size 29, Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field])
+- """
+- if isinstance(values, Sequence):
+- values = list(values)
+- if values:
+- v0 = values[0]
+- if isinstance(v0, tuple) and len(v0) == 2:
+- # Change [(val0, lbl0), ...] to [(lbl0, val0), ...]
+- values = [(str(lbl), val) for (val, lbl) in values]
+- kwds = {"options": values}
+- if buttons:
+- cls = ToggleButtons
+- elif nrows is not None or ncols is not None:
+- # For compatibility with SageNB, these keywords are recognized
+- # but their value is ignored
+- cls = ToggleButtons
+- else:
+- cls = Dropdown
+- if default is not None:
+- kwds["value"] = default
+- if label is not None:
+- kwds["description"] = u(label)
+- return cls(**kwds)
+-
+-
+-def input_grid(nrows, ncols, default=None, label=None, to_value=None, width=4):
+- """
+- A widget consisting of a grid (matrix) of textboxes.
+-
+- The values entered in the textboxes are evaluated (using
+- :func:`sage_eval`). These are stored as a list of lists on the
+- ``value`` attribute. The value of this widget for an interactive
+- function is the result of calling ``to_value`` on this list of
+- lists.
+-
+- INPUT:
+-
+- - ``nrows``, ``ncols`` -- number of rows and columns in the grid
+-
+- - ``default`` -- initial value (given as a list of lists, a single
+- constant value or a flat list)
+-
+- - ``label`` -- optional label
+-
+- - ``to_value`` -- function to be called to get the value for
+- interactive functions
+-
+- - ``width`` -- width of each textbox
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.all_jupyter import input_grid
+- sage: input_grid(2, 2, default=42, label="answers")
+- Grid(value=[[42, 42], [42, 42]], description=u'answers', children=(Label(value=u'answers'), VBox(children=(EvalText(value=u'42'), EvalText(value=u'42'))), VBox(children=(EvalText(value=u'42'), EvalText(value=u'42')))))
+- sage: w = input_grid(2, 2, default=[[cos(x), sin(x)], [-sin(x), cos(x)]], to_value=matrix); w
+- Grid(value=[[cos(x), sin(x)], [-sin(x), cos(x)]], children=(Label(value=u''), VBox(children=(EvalText(value=u'cos(x)'), EvalText(value=u'-sin(x)'))), VBox(children=(EvalText(value=u'sin(x)'), EvalText(value=u'cos(x)')))))
+- sage: w.get_interact_value()
+- [ cos(x) sin(x)]
+- [-sin(x) cos(x)]
+- sage: w = input_grid(2, 2, default=[1, x, x^2, x^3], to_value=lambda x: x[1][1]); w
+- Grid(value=[[1, x], [x^2, x^3]], children=(Label(value=u''), VBox(children=(EvalText(value=u'1'), EvalText(value=u'x^2'))), VBox(children=(EvalText(value=u'x'), EvalText(value=u'x^3')))))
+- sage: w.get_interact_value()
+- x^3
+- """
+- kwds = {"transform": to_value}
+- if label is not None:
+- kwds["description"] = u(label)
+-
+- # Parse default
+- if not isinstance(default, list):
+- # Single value
+- default = [[default] * ncols] * nrows
+- if all(isinstance(elt, list) for elt in default):
+- # List of lists
+- pass
+- else:
+- # Flat list
+- default = [[default[i * ncols + j] for j in range(ncols)] for i in range(nrows)]
+-
+- def make_widget(i, j):
+- return input_box(str(default[i][j]), width=width)
+-
+- grid = Grid(nrows, ncols, make_widget, **kwds)
+- return grid
+-
+-
+-def color_selector(default=(0, 0, 1), label=None, widget=None, hide_box=False):
+- """
+- A widget for choosing a color.
+-
+- INPUT:
+-
+- - ``default`` -- initial value
+-
+- - ``label`` -- optional label
+-
+- - ``hide_box`` -- (boolean) if True, do not show the textbox
+-
+- EXAMPLES::
+-
+- sage: from sage.repl.ipython_kernel.all_jupyter import color_selector
+- sage: w = color_selector("orange", label="color me"); w
+- SageColorPicker(value='#ffa500', description=u'color me')
+- sage: w.get_interact_value()
+- RGB color (1.0, 0.6470588235294118, 0.0)
+- sage: color_selector(Color(0.1, 0.2, 0.3))
+- SageColorPicker(value='#19334c')
+- """
+- # widget argument is silently ignored
+- kwds = {"value": Color(default).html_color(),
+- "concise": hide_box}
+- if label is not None:
+- kwds["description"] = u(label)
+- return SageColorPicker(**kwds)
diff --git a/debian/patches/series b/debian/patches/series
index 62e1ce5..63672f0 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -70,3 +70,4 @@ dt-version-glpk-4.60-extra-hacky-fixes.patch
dt-r-no-readline.patch
dt-more-fix-test-cases.patch
dt-work-around-doc-common-conf.patch
+dt-undo-trac-21267-sagenb-interacts-for-jupyter.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/sagemath.git
More information about the debian-science-commits
mailing list