passagemath-repl 10.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_repl-10.5.1.data/scripts/sage-cachegrind +25 -0
- passagemath_repl-10.5.1.data/scripts/sage-callgrind +16 -0
- passagemath_repl-10.5.1.data/scripts/sage-cleaner +230 -0
- passagemath_repl-10.5.1.data/scripts/sage-coverage +327 -0
- passagemath_repl-10.5.1.data/scripts/sage-eval +14 -0
- passagemath_repl-10.5.1.data/scripts/sage-fixdoctests +710 -0
- passagemath_repl-10.5.1.data/scripts/sage-inline-fortran +12 -0
- passagemath_repl-10.5.1.data/scripts/sage-ipynb2rst +50 -0
- passagemath_repl-10.5.1.data/scripts/sage-ipython +16 -0
- passagemath_repl-10.5.1.data/scripts/sage-massif +25 -0
- passagemath_repl-10.5.1.data/scripts/sage-notebook +267 -0
- passagemath_repl-10.5.1.data/scripts/sage-omega +25 -0
- passagemath_repl-10.5.1.data/scripts/sage-preparse +302 -0
- passagemath_repl-10.5.1.data/scripts/sage-run +27 -0
- passagemath_repl-10.5.1.data/scripts/sage-run-cython +10 -0
- passagemath_repl-10.5.1.data/scripts/sage-runtests +9 -0
- passagemath_repl-10.5.1.data/scripts/sage-startuptime.py +163 -0
- passagemath_repl-10.5.1.data/scripts/sage-valgrind +34 -0
- passagemath_repl-10.5.1.dist-info/METADATA +77 -0
- passagemath_repl-10.5.1.dist-info/RECORD +162 -0
- passagemath_repl-10.5.1.dist-info/WHEEL +5 -0
- passagemath_repl-10.5.1.dist-info/top_level.txt +1 -0
- sage/all__sagemath_repl.py +119 -0
- sage/doctest/__init__.py +4 -0
- sage/doctest/__main__.py +236 -0
- sage/doctest/all.py +4 -0
- sage/doctest/check_tolerance.py +261 -0
- sage/doctest/control.py +1727 -0
- sage/doctest/external.py +534 -0
- sage/doctest/fixtures.py +383 -0
- sage/doctest/forker.py +2665 -0
- sage/doctest/marked_output.py +102 -0
- sage/doctest/parsing.py +1708 -0
- sage/doctest/parsing_test.py +79 -0
- sage/doctest/reporting.py +733 -0
- sage/doctest/rif_tol.py +124 -0
- sage/doctest/sources.py +1657 -0
- sage/doctest/test.py +584 -0
- sage/doctest/tests/1second.rst +4 -0
- sage/doctest/tests/99seconds.rst +4 -0
- sage/doctest/tests/abort.rst +5 -0
- sage/doctest/tests/atexit.rst +7 -0
- sage/doctest/tests/fail_and_die.rst +6 -0
- sage/doctest/tests/initial.rst +15 -0
- sage/doctest/tests/interrupt.rst +7 -0
- sage/doctest/tests/interrupt_diehard.rst +14 -0
- sage/doctest/tests/keyboardinterrupt.rst +11 -0
- sage/doctest/tests/longtime.rst +5 -0
- sage/doctest/tests/nodoctest +5 -0
- sage/doctest/tests/random_seed.rst +4 -0
- sage/doctest/tests/show_skipped.rst +18 -0
- sage/doctest/tests/sig_on.rst +9 -0
- sage/doctest/tests/simple_failure.rst +8 -0
- sage/doctest/tests/sleep_and_raise.rst +106 -0
- sage/doctest/tests/tolerance.rst +31 -0
- sage/doctest/util.py +750 -0
- sage/interfaces/cleaner.py +48 -0
- sage/interfaces/quit.py +163 -0
- sage/misc/all__sagemath_repl.py +51 -0
- sage/misc/banner.py +235 -0
- sage/misc/benchmark.py +221 -0
- sage/misc/classgraph.py +134 -0
- sage/misc/copying.py +22 -0
- sage/misc/cython.py +694 -0
- sage/misc/dev_tools.py +745 -0
- sage/misc/edit_module.py +304 -0
- sage/misc/explain_pickle.py +3079 -0
- sage/misc/gperftools.py +361 -0
- sage/misc/inline_fortran.py +212 -0
- sage/misc/messaging.py +86 -0
- sage/misc/pager.py +21 -0
- sage/misc/profiler.py +179 -0
- sage/misc/python.py +70 -0
- sage/misc/remote_file.py +53 -0
- sage/misc/sage_eval.py +249 -0
- sage/misc/sage_input.py +3621 -0
- sage/misc/sagedoc.py +1742 -0
- sage/misc/sh.py +38 -0
- sage/misc/trace.py +90 -0
- sage/repl/__init__.py +16 -0
- sage/repl/all.py +15 -0
- sage/repl/attach.py +625 -0
- sage/repl/configuration.py +186 -0
- sage/repl/display/__init__.py +1 -0
- sage/repl/display/fancy_repr.py +354 -0
- sage/repl/display/formatter.py +318 -0
- sage/repl/display/jsmol_iframe.py +290 -0
- sage/repl/display/pretty_print.py +153 -0
- sage/repl/display/util.py +163 -0
- sage/repl/image.py +302 -0
- sage/repl/inputhook.py +91 -0
- sage/repl/interface_magic.py +298 -0
- sage/repl/interpreter.py +854 -0
- sage/repl/ipython_extension.py +593 -0
- sage/repl/ipython_kernel/__init__.py +1 -0
- sage/repl/ipython_kernel/__main__.py +4 -0
- sage/repl/ipython_kernel/all_jupyter.py +10 -0
- sage/repl/ipython_kernel/install.py +301 -0
- sage/repl/ipython_kernel/interact.py +278 -0
- sage/repl/ipython_kernel/kernel.py +217 -0
- sage/repl/ipython_kernel/widgets.py +466 -0
- sage/repl/ipython_kernel/widgets_sagenb.py +587 -0
- sage/repl/ipython_tests.py +163 -0
- sage/repl/load.py +326 -0
- sage/repl/preparse.py +2218 -0
- sage/repl/prompts.py +90 -0
- sage/repl/rich_output/__init__.py +4 -0
- sage/repl/rich_output/backend_base.py +648 -0
- sage/repl/rich_output/backend_doctest.py +316 -0
- sage/repl/rich_output/backend_emacs.py +151 -0
- sage/repl/rich_output/backend_ipython.py +596 -0
- sage/repl/rich_output/buffer.py +311 -0
- sage/repl/rich_output/display_manager.py +829 -0
- sage/repl/rich_output/example.avi +0 -0
- sage/repl/rich_output/example.canvas3d +1 -0
- sage/repl/rich_output/example.dvi +0 -0
- sage/repl/rich_output/example.flv +0 -0
- sage/repl/rich_output/example.gif +0 -0
- sage/repl/rich_output/example.jpg +0 -0
- sage/repl/rich_output/example.mkv +0 -0
- sage/repl/rich_output/example.mov +0 -0
- sage/repl/rich_output/example.mp4 +0 -0
- sage/repl/rich_output/example.ogv +0 -0
- sage/repl/rich_output/example.pdf +0 -0
- sage/repl/rich_output/example.png +0 -0
- sage/repl/rich_output/example.svg +54 -0
- sage/repl/rich_output/example.webm +0 -0
- sage/repl/rich_output/example.wmv +0 -0
- sage/repl/rich_output/example_jmol.spt.zip +0 -0
- sage/repl/rich_output/example_wavefront_scene.mtl +7 -0
- sage/repl/rich_output/example_wavefront_scene.obj +17 -0
- sage/repl/rich_output/output_basic.py +391 -0
- sage/repl/rich_output/output_browser.py +103 -0
- sage/repl/rich_output/output_catalog.py +54 -0
- sage/repl/rich_output/output_graphics.py +320 -0
- sage/repl/rich_output/output_graphics3d.py +345 -0
- sage/repl/rich_output/output_video.py +231 -0
- sage/repl/rich_output/preferences.py +432 -0
- sage/repl/rich_output/pretty_print.py +339 -0
- sage/repl/rich_output/test_backend.py +201 -0
- sage/repl/user_globals.py +214 -0
- sage/tests/all.py +0 -0
- sage/tests/all__sagemath_repl.py +3 -0
- sage/tests/article_heuberger_krenn_kropf_fsm-in-sage.py +630 -0
- sage/tests/arxiv_0812_2725.py +351 -0
- sage/tests/benchmark.py +1925 -0
- sage/tests/book_schilling_zabrocki_kschur_primer.py +795 -0
- sage/tests/book_stein_ent.py +651 -0
- sage/tests/book_stein_modform.py +558 -0
- sage/tests/cmdline.py +796 -0
- sage/tests/combinatorial_hopf_algebras.py +52 -0
- sage/tests/finite_poset.py +623 -0
- sage/tests/functools_partial_src.py +27 -0
- sage/tests/gosper-sum.py +218 -0
- sage/tests/lazy_imports.py +28 -0
- sage/tests/modular_group_cohomology.py +80 -0
- sage/tests/numpy.py +21 -0
- sage/tests/parigp.py +76 -0
- sage/tests/startup.py +27 -0
- sage/tests/symbolic-series.py +76 -0
- sage/tests/sympy.py +16 -0
- sage/tests/test_deprecation.py +31 -0
@@ -0,0 +1,587 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-repl
|
2
|
+
r"""
|
3
|
+
Functions to construct widgets, based on the old SageNB interface.
|
4
|
+
|
5
|
+
These should ensure mostly backwards compatibility with SageNB.
|
6
|
+
|
7
|
+
TESTS:
|
8
|
+
|
9
|
+
We need to setup a proper test environment for widgets::
|
10
|
+
|
11
|
+
sage: from ipywidgets.widgets.tests.utils import setup_test_comm
|
12
|
+
sage: setup_test_comm()
|
13
|
+
|
14
|
+
EXAMPLES::
|
15
|
+
|
16
|
+
sage: from sage.repl.ipython_kernel.widgets_sagenb import text_control
|
17
|
+
sage: text_control("Hello World!")
|
18
|
+
HTMLText(value='Hello World!')
|
19
|
+
"""
|
20
|
+
|
21
|
+
# ****************************************************************************
|
22
|
+
# Copyright (C) 2017 Jeroen Demeyer <jdemeyer@cage.ugent.be>
|
23
|
+
#
|
24
|
+
# This program is free software: you can redistribute it and/or modify
|
25
|
+
# it under the terms of the GNU General Public License as published by
|
26
|
+
# the Free Software Foundation, either version 2 of the License, or
|
27
|
+
# (at your option) any later version.
|
28
|
+
# https://www.gnu.org/licenses/
|
29
|
+
# ****************************************************************************
|
30
|
+
|
31
|
+
from ipywidgets.widgets import (IntSlider, IntRangeSlider, FloatSlider,
|
32
|
+
FloatRangeSlider, SelectionSlider,
|
33
|
+
Checkbox, ToggleButtons, Dropdown)
|
34
|
+
from .widgets import (TransformText, TransformTextarea,
|
35
|
+
TransformIntSlider, TransformIntRangeSlider,
|
36
|
+
TransformFloatSlider, TransformFloatRangeSlider,
|
37
|
+
EvalText, EvalTextarea, SageColorPicker, Grid)
|
38
|
+
from ipywidgets.widgets.interaction import _get_min_max_value
|
39
|
+
from collections.abc import Iterable, Sequence
|
40
|
+
from numbers import Integral, Rational, Real
|
41
|
+
|
42
|
+
from sage.structure.all import parent
|
43
|
+
from sage.arith.srange import srange
|
44
|
+
import sage.rings.abc
|
45
|
+
|
46
|
+
from .widgets import HTMLText as text_control
|
47
|
+
|
48
|
+
Color = None
|
49
|
+
|
50
|
+
|
51
|
+
def input_box(default=None, label=None, type=None, width=80, height=1):
|
52
|
+
"""
|
53
|
+
A textbox widget.
|
54
|
+
|
55
|
+
INPUT:
|
56
|
+
|
57
|
+
- ``default`` -- initial value
|
58
|
+
|
59
|
+
- ``label`` -- (optional)
|
60
|
+
|
61
|
+
- ``type`` -- function of one variable or ``None``. if ``type`` is
|
62
|
+
``str``, the value of this widget for interactive functions is
|
63
|
+
just the text as ``str``. Otherwise, the text is evaluated using
|
64
|
+
:func:`sage_eval`, ``type`` is called on it and the result is used
|
65
|
+
as value. Except if ``type`` is ``None``, then the evaluated text
|
66
|
+
is used as value.
|
67
|
+
|
68
|
+
- ``width`` -- width of the box
|
69
|
+
|
70
|
+
- ``height`` -- if ``height > 1``, create a textarea instead of a
|
71
|
+
single-line textbox
|
72
|
+
|
73
|
+
EXAMPLES::
|
74
|
+
|
75
|
+
sage: from sage.repl.ipython_kernel.all_jupyter import input_box
|
76
|
+
|
77
|
+
The most basic usage is when ``type=str``::
|
78
|
+
|
79
|
+
sage: w = input_box("4+5", type=str, label="enter a string")
|
80
|
+
sage: w
|
81
|
+
TransformText(value='4+5', description='enter a string', layout=Layout(max_width='81em'))
|
82
|
+
sage: w.get_interact_value()
|
83
|
+
'4+5'
|
84
|
+
|
85
|
+
Without ``type``, the text is evaluated::
|
86
|
+
|
87
|
+
sage: w = input_box("4+5")
|
88
|
+
sage: w
|
89
|
+
EvalText(value='4+5', layout=Layout(max_width='81em'))
|
90
|
+
sage: w.get_interact_value()
|
91
|
+
9
|
92
|
+
|
93
|
+
With a different ``type``, the text is evaluated and ``type`` is
|
94
|
+
called on it::
|
95
|
+
|
96
|
+
sage: w = input_box("4+5", type=float)
|
97
|
+
sage: w
|
98
|
+
EvalText(value='4+5', layout=Layout(max_width='81em'))
|
99
|
+
sage: w.get_interact_value()
|
100
|
+
9.0
|
101
|
+
|
102
|
+
Despite the keyword name, ``type`` does not need to be a type::
|
103
|
+
|
104
|
+
sage: w = input_box("4+5", type=sqrt)
|
105
|
+
sage: w
|
106
|
+
EvalText(value='4+5', layout=Layout(max_width='81em'))
|
107
|
+
sage: w.get_interact_value()
|
108
|
+
3
|
109
|
+
|
110
|
+
When ``height > 1``, a textarea is returned::
|
111
|
+
|
112
|
+
sage: w = input_box("4+5", width=100, height=1)
|
113
|
+
sage: w
|
114
|
+
EvalText(value='4+5', layout=Layout(max_width='101em'))
|
115
|
+
sage: w = input_box("4+5", width=100, height=5)
|
116
|
+
sage: w
|
117
|
+
EvalTextarea(value='4+5', layout=Layout(max_width='101em'))
|
118
|
+
|
119
|
+
TESTS::
|
120
|
+
|
121
|
+
sage: w = input_box(type=Color)
|
122
|
+
Traceback (most recent call last):
|
123
|
+
...
|
124
|
+
NotImplementedError: type=Color is not supported
|
125
|
+
"""
|
126
|
+
kwds = {}
|
127
|
+
if type is str:
|
128
|
+
kwds["transform"] = str # Convert unicode to str
|
129
|
+
if height > 1:
|
130
|
+
cls = TransformTextarea
|
131
|
+
else:
|
132
|
+
cls = TransformText
|
133
|
+
else:
|
134
|
+
global Color
|
135
|
+
if Color is None:
|
136
|
+
try:
|
137
|
+
from sage.plot.colors import Color
|
138
|
+
except ImportError:
|
139
|
+
pass
|
140
|
+
if type is Color:
|
141
|
+
# This is special-cased by SageNB (with a non-trivial
|
142
|
+
# implementation!), but it doesn't seem to be used in practice
|
143
|
+
# because we have a SageColorPicker widget.
|
144
|
+
raise NotImplementedError("type=Color is not supported")
|
145
|
+
|
146
|
+
kwds["transform"] = type
|
147
|
+
if height > 1:
|
148
|
+
cls = EvalTextarea
|
149
|
+
else:
|
150
|
+
cls = EvalText
|
151
|
+
if default is not None:
|
152
|
+
kwds["value"] = str(default)
|
153
|
+
if label is not None:
|
154
|
+
kwds["description"] = label
|
155
|
+
w = cls(**kwds)
|
156
|
+
w.layout.max_width = str(width + 1) + "em"
|
157
|
+
return w
|
158
|
+
|
159
|
+
|
160
|
+
def slider(vmin, vmax=None, step_size=None, default=None, label=None, display_value=True, _range=False):
|
161
|
+
"""
|
162
|
+
A slider widget.
|
163
|
+
|
164
|
+
INPUT:
|
165
|
+
|
166
|
+
For a numeric slider (select a value from a range):
|
167
|
+
|
168
|
+
- ``vmin``, ``vmax`` -- minimum and maximum value
|
169
|
+
|
170
|
+
- ``step_size`` -- the step size
|
171
|
+
|
172
|
+
For a selection slider (select a value from a list of values):
|
173
|
+
|
174
|
+
- ``vmin`` -- list of possible values for the slider
|
175
|
+
|
176
|
+
For all sliders:
|
177
|
+
|
178
|
+
- ``default`` -- initial value
|
179
|
+
|
180
|
+
- ``label`` -- (optional)
|
181
|
+
|
182
|
+
- ``display_value`` -- boolean; if ``True``, display the current value
|
183
|
+
|
184
|
+
EXAMPLES::
|
185
|
+
|
186
|
+
sage: from sage.repl.ipython_kernel.all_jupyter import slider
|
187
|
+
sage: slider(5, label="slide me")
|
188
|
+
TransformIntSlider(value=5, description='slide me', min=5)
|
189
|
+
sage: slider(5, 20)
|
190
|
+
TransformIntSlider(value=5, max=20, min=5)
|
191
|
+
sage: slider(5, 20, 0.5)
|
192
|
+
TransformFloatSlider(value=5.0, max=20.0, min=5.0, step=0.5)
|
193
|
+
sage: slider(5, 20, default=12)
|
194
|
+
TransformIntSlider(value=12, max=20, min=5)
|
195
|
+
|
196
|
+
The parent of the inputs determines the parent of the value::
|
197
|
+
|
198
|
+
sage: w = slider(5); w
|
199
|
+
TransformIntSlider(value=5, min=5)
|
200
|
+
sage: parent(w.get_interact_value())
|
201
|
+
Integer Ring
|
202
|
+
sage: w = slider(int(5)); w
|
203
|
+
IntSlider(value=5, min=5)
|
204
|
+
sage: parent(w.get_interact_value())
|
205
|
+
<... 'int'>
|
206
|
+
sage: w = slider(5, 20, step_size=RDF("0.1")); w
|
207
|
+
TransformFloatSlider(value=5.0, max=20.0, min=5.0)
|
208
|
+
sage: parent(w.get_interact_value())
|
209
|
+
Real Double Field
|
210
|
+
sage: w = slider(5, 20, step_size=10/3); w
|
211
|
+
SelectionSlider(index=2, options=(5, 25/3, 35/3, 15, 55/3), value=35/3)
|
212
|
+
sage: parent(w.get_interact_value())
|
213
|
+
Rational Field
|
214
|
+
|
215
|
+
Symbolic input is evaluated numerically::
|
216
|
+
|
217
|
+
sage: w = slider(e, pi); w
|
218
|
+
TransformFloatSlider(value=2.718281828459045, max=3.141592653589793, min=2.718281828459045)
|
219
|
+
sage: parent(w.get_interact_value())
|
220
|
+
Real Field with 53 bits of precision
|
221
|
+
|
222
|
+
For a selection slider, the default is adjusted to one of the
|
223
|
+
possible values::
|
224
|
+
|
225
|
+
sage: slider(range(10), default=17/10)
|
226
|
+
SelectionSlider(index=2, options=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), value=2)
|
227
|
+
|
228
|
+
TESTS::
|
229
|
+
|
230
|
+
sage: slider(range(5), range(5))
|
231
|
+
Traceback (most recent call last):
|
232
|
+
...
|
233
|
+
TypeError: unexpected argument 'vmax' for a selection slider
|
234
|
+
sage: slider(range(5), step_size=2)
|
235
|
+
Traceback (most recent call last):
|
236
|
+
...
|
237
|
+
TypeError: unexpected argument 'step_size' for a selection slider
|
238
|
+
sage: slider(5).readout
|
239
|
+
True
|
240
|
+
sage: slider(5, display_value=False).readout
|
241
|
+
False
|
242
|
+
|
243
|
+
Symbolic subrings work like ``SR``::
|
244
|
+
|
245
|
+
sage: SCR = SR.subring(no_variables=True)
|
246
|
+
sage: w = slider(SCR(e), SCR(pi)); w
|
247
|
+
TransformFloatSlider(value=2.718281828459045, max=3.141592653589793, min=2.718281828459045)
|
248
|
+
sage: parent(w.get_interact_value())
|
249
|
+
Real Field with 53 bits of precision
|
250
|
+
"""
|
251
|
+
kwds = {"readout": display_value}
|
252
|
+
if label:
|
253
|
+
kwds["description"] = label
|
254
|
+
|
255
|
+
# If vmin is iterable, return a SelectionSlider
|
256
|
+
if isinstance(vmin, Iterable):
|
257
|
+
if vmax is not None:
|
258
|
+
raise TypeError("unexpected argument 'vmax' for a selection slider")
|
259
|
+
if step_size is not None:
|
260
|
+
raise TypeError("unexpected argument 'step_size' for a selection slider")
|
261
|
+
if _range:
|
262
|
+
# https://github.com/ipython/ipywidgets/issues/760
|
263
|
+
raise NotImplementedError("range_slider does not support a list of values")
|
264
|
+
options = list(vmin)
|
265
|
+
# Find default in options
|
266
|
+
|
267
|
+
def err(v):
|
268
|
+
if v is default:
|
269
|
+
return (-1, 0)
|
270
|
+
try:
|
271
|
+
if v == default:
|
272
|
+
return (0, 0)
|
273
|
+
return (0, abs(v - default))
|
274
|
+
except Exception:
|
275
|
+
return (1, 0)
|
276
|
+
kwds["options"] = options
|
277
|
+
if default is not None:
|
278
|
+
kwds["value"] = min(options, key=err)
|
279
|
+
return SelectionSlider(**kwds)
|
280
|
+
|
281
|
+
if default is not None:
|
282
|
+
kwds["value"] = default
|
283
|
+
|
284
|
+
# Sum all input numbers to figure out type/parent
|
285
|
+
p = parent(sum(x for x in (vmin, vmax, step_size) if x is not None))
|
286
|
+
|
287
|
+
# Change SR to RR
|
288
|
+
if isinstance(p, sage.rings.abc.SymbolicRing):
|
289
|
+
from sage.rings.real_mpfr import RR
|
290
|
+
p = RR
|
291
|
+
|
292
|
+
# Convert all inputs to the common parent
|
293
|
+
if vmin is not None:
|
294
|
+
vmin = p(vmin)
|
295
|
+
if vmax is not None:
|
296
|
+
vmax = p(vmax)
|
297
|
+
if step_size is not None:
|
298
|
+
step_size = p(step_size)
|
299
|
+
|
300
|
+
def tuple_elements_p(t):
|
301
|
+
"Convert all entries of the tuple `t` to `p`"
|
302
|
+
return tuple(p(x) for x in t)
|
303
|
+
|
304
|
+
zero = p()
|
305
|
+
if isinstance(zero, Integral):
|
306
|
+
if p is int:
|
307
|
+
if _range:
|
308
|
+
cls = IntRangeSlider
|
309
|
+
else:
|
310
|
+
cls = IntSlider
|
311
|
+
else:
|
312
|
+
if _range:
|
313
|
+
kwds["transform"] = tuple_elements_p
|
314
|
+
cls = TransformIntRangeSlider
|
315
|
+
else:
|
316
|
+
kwds["transform"] = p
|
317
|
+
cls = TransformIntSlider
|
318
|
+
elif isinstance(zero, Rational):
|
319
|
+
# Rational => implement as SelectionSlider
|
320
|
+
if _range:
|
321
|
+
# https://github.com/ipython/ipywidgets/issues/760
|
322
|
+
raise NotImplementedError("range_slider does not support rational numbers")
|
323
|
+
vmin, vmax, value = _get_min_max_value(vmin, vmax, default, step_size)
|
324
|
+
kwds["value"] = value
|
325
|
+
kwds["options"] = srange(vmin, vmax, step_size, include_endpoint=True)
|
326
|
+
return SelectionSlider(**kwds)
|
327
|
+
elif isinstance(zero, Real):
|
328
|
+
if p is float:
|
329
|
+
if _range:
|
330
|
+
cls = FloatRangeSlider
|
331
|
+
else:
|
332
|
+
cls = FloatSlider
|
333
|
+
else:
|
334
|
+
if _range:
|
335
|
+
kwds["transform"] = tuple_elements_p
|
336
|
+
cls = TransformFloatRangeSlider
|
337
|
+
else:
|
338
|
+
kwds["transform"] = p
|
339
|
+
cls = TransformFloatSlider
|
340
|
+
else:
|
341
|
+
raise TypeError("unknown parent {!r} for slider".format(p))
|
342
|
+
|
343
|
+
kwds["min"] = vmin
|
344
|
+
if vmax is not None:
|
345
|
+
kwds["max"] = vmax
|
346
|
+
if step_size is not None:
|
347
|
+
kwds["step"] = step_size
|
348
|
+
return cls(**kwds)
|
349
|
+
|
350
|
+
|
351
|
+
def range_slider(*args, **kwds):
|
352
|
+
"""
|
353
|
+
A slider widget to select a range of values.
|
354
|
+
|
355
|
+
INPUT:
|
356
|
+
|
357
|
+
- ``vmin``, ``vmax`` -- minimum and maximum value
|
358
|
+
|
359
|
+
- ``step_size`` -- the step size
|
360
|
+
|
361
|
+
- ``default`` -- initial value, given as a 2-tuple
|
362
|
+
|
363
|
+
- ``label`` -- (optional)
|
364
|
+
|
365
|
+
- ``display_value`` -- boolean; if ``True``, display the current value
|
366
|
+
|
367
|
+
EXAMPLES::
|
368
|
+
|
369
|
+
sage: from sage.repl.ipython_kernel.all_jupyter import range_slider
|
370
|
+
sage: range_slider(5, label="slide me")
|
371
|
+
TransformIntRangeSlider(value=(28, 76), description='slide me', min=5)
|
372
|
+
sage: range_slider(5, 20)
|
373
|
+
TransformIntRangeSlider(value=(8, 16), max=20, min=5)
|
374
|
+
sage: range_slider(5, 20, 0.5)
|
375
|
+
TransformFloatRangeSlider(value=(8.75, 16.25), max=20.0, min=5.0, step=0.5)
|
376
|
+
sage: range_slider(5, 20, default=(12,15))
|
377
|
+
TransformIntRangeSlider(value=(12, 15), max=20, min=5)
|
378
|
+
|
379
|
+
The parent of the inputs determines the parent of the value::
|
380
|
+
|
381
|
+
sage: w = range_slider(5); w
|
382
|
+
TransformIntRangeSlider(value=(28, 76), min=5)
|
383
|
+
sage: [parent(x) for x in w.get_interact_value()]
|
384
|
+
[Integer Ring, Integer Ring]
|
385
|
+
sage: w = range_slider(int(5)); w
|
386
|
+
IntRangeSlider(value=(28, 76), min=5)
|
387
|
+
sage: [parent(x) for x in w.get_interact_value()]
|
388
|
+
[<... 'int'>, <... 'int'>]
|
389
|
+
sage: w = range_slider(5, 20, step_size=RDF("0.1")); w
|
390
|
+
TransformFloatRangeSlider(value=(8.75, 16.25), max=20.0, min=5.0)
|
391
|
+
sage: [parent(x) for x in w.get_interact_value()]
|
392
|
+
[Real Double Field, Real Double Field]
|
393
|
+
|
394
|
+
Unfortunately, rational numbers are not supported::
|
395
|
+
|
396
|
+
sage: w = range_slider(5, 20, step_size=10/3); w
|
397
|
+
Traceback (most recent call last):
|
398
|
+
...
|
399
|
+
NotImplementedError: range_slider does not support rational numbers
|
400
|
+
|
401
|
+
TESTS::
|
402
|
+
|
403
|
+
sage: range_slider(range(5))
|
404
|
+
Traceback (most recent call last):
|
405
|
+
...
|
406
|
+
NotImplementedError: range_slider does not support a list of values
|
407
|
+
"""
|
408
|
+
kwds["_range"] = True
|
409
|
+
return slider(*args, **kwds)
|
410
|
+
|
411
|
+
|
412
|
+
def checkbox(default=True, label=None):
|
413
|
+
"""
|
414
|
+
A checkbox widget.
|
415
|
+
|
416
|
+
INPUT:
|
417
|
+
|
418
|
+
- ``default`` -- boolean; initial value
|
419
|
+
|
420
|
+
- ``label`` -- (optional)
|
421
|
+
|
422
|
+
EXAMPLES::
|
423
|
+
|
424
|
+
sage: from sage.repl.ipython_kernel.all_jupyter import checkbox
|
425
|
+
sage: checkbox(label="toggle me")
|
426
|
+
Checkbox(value=True, description='toggle me')
|
427
|
+
sage: checkbox(default=0)
|
428
|
+
Checkbox(value=False)
|
429
|
+
"""
|
430
|
+
kwds = {"value": bool(default)}
|
431
|
+
if label is not None:
|
432
|
+
kwds["description"] = label
|
433
|
+
return Checkbox(**kwds)
|
434
|
+
|
435
|
+
|
436
|
+
def selector(values, label=None, default=None, nrows=None, ncols=None, width=None, buttons=False):
|
437
|
+
"""
|
438
|
+
A widget to select a value from a given list of values.
|
439
|
+
|
440
|
+
This is rendered as a dropdown box (if ``buttons`` is False) or
|
441
|
+
as a list of buttons (if ``buttons`` is True).
|
442
|
+
|
443
|
+
INPUT:
|
444
|
+
|
445
|
+
- ``values`` -- list of values to choose from (see examples below
|
446
|
+
for the accepted formats for this)
|
447
|
+
|
448
|
+
- ``label`` -- (optional)
|
449
|
+
|
450
|
+
- ``default`` -- initial value
|
451
|
+
|
452
|
+
- ``buttons`` -- boolean; if ``True``, display buttons instead of a
|
453
|
+
dropdown box
|
454
|
+
|
455
|
+
EXAMPLES::
|
456
|
+
|
457
|
+
sage: from sage.repl.ipython_kernel.all_jupyter import selector
|
458
|
+
sage: selector(range(5), label="choose one")
|
459
|
+
Dropdown(description='choose one', options=(0, 1, 2, 3, 4), value=0)
|
460
|
+
sage: selector(range(5), buttons=True, default=4)
|
461
|
+
ToggleButtons(index=4, options=(0, 1, 2, 3, 4), value=4)
|
462
|
+
|
463
|
+
Apart from a simple list, ``values`` can be given as a list of
|
464
|
+
2-tuples ``(value, label)``::
|
465
|
+
|
466
|
+
sage: selector([(1,"one"), (2,"two"), (3,"three")])
|
467
|
+
Dropdown(options=(('one', 1), ('two', 2), ('three', 3)), value=1)
|
468
|
+
sage: selector([(1,"one"), (2,"two"), (3,"three")], buttons=True)
|
469
|
+
ToggleButtons(options=(('one', 1), ('two', 2), ('three', 3)), value=1)
|
470
|
+
|
471
|
+
The values can be any kind of object::
|
472
|
+
|
473
|
+
sage: selector([sin(x^2), GF(29), EllipticCurve('37a1')])
|
474
|
+
Dropdown(options=(sin(x^2), Finite Field of size 29, Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field), value=sin(x^2))
|
475
|
+
"""
|
476
|
+
if isinstance(values, Sequence):
|
477
|
+
values = list(values)
|
478
|
+
if values:
|
479
|
+
v0 = values[0]
|
480
|
+
if isinstance(v0, tuple) and len(v0) == 2:
|
481
|
+
# Change [(val0, lbl0), ...] to [(lbl0, val0), ...]
|
482
|
+
values = [(str(lbl), val) for (val, lbl) in values]
|
483
|
+
kwds = {"options": values}
|
484
|
+
if buttons:
|
485
|
+
cls = ToggleButtons
|
486
|
+
elif nrows is not None or ncols is not None:
|
487
|
+
# For compatibility with SageNB, these keywords are recognized
|
488
|
+
# but their value is ignored
|
489
|
+
cls = ToggleButtons
|
490
|
+
else:
|
491
|
+
cls = Dropdown
|
492
|
+
if default is not None:
|
493
|
+
kwds["value"] = default
|
494
|
+
if label is not None:
|
495
|
+
kwds["description"] = label
|
496
|
+
return cls(**kwds)
|
497
|
+
|
498
|
+
|
499
|
+
def input_grid(nrows, ncols, default=None, label=None, to_value=None, width=4):
|
500
|
+
"""
|
501
|
+
A widget consisting of a grid (matrix) of textboxes.
|
502
|
+
|
503
|
+
The values entered in the textboxes are evaluated (using
|
504
|
+
:func:`sage_eval`). These are stored as a list of lists on the
|
505
|
+
``value`` attribute. The value of this widget for an interactive
|
506
|
+
function is the result of calling ``to_value`` on this list of
|
507
|
+
lists.
|
508
|
+
|
509
|
+
INPUT:
|
510
|
+
|
511
|
+
- ``nrows``, ``ncols`` -- number of rows and columns in the grid
|
512
|
+
|
513
|
+
- ``default`` -- initial value (given as a list of lists, a single
|
514
|
+
constant value or a flat list)
|
515
|
+
|
516
|
+
- ``label`` -- (optional)
|
517
|
+
|
518
|
+
- ``to_value`` -- function to be called to get the value for
|
519
|
+
interactive functions
|
520
|
+
|
521
|
+
- ``width`` -- width of each textbox
|
522
|
+
|
523
|
+
EXAMPLES::
|
524
|
+
|
525
|
+
sage: from sage.repl.ipython_kernel.all_jupyter import input_grid
|
526
|
+
sage: input_grid(2, 2, default=42, label='answers')
|
527
|
+
Grid(value=[[42, 42], [42, 42]], children=(Label(value='answers'), VBox(children=(EvalText(value='42', layout=Layout(max_width='5em')), EvalText(value='42', layout=Layout(max_width='5em')))), VBox(children=(EvalText(value='42', layout=Layout(max_width='5em')), EvalText(value='42', layout=Layout(max_width='5em'))))))
|
528
|
+
sage: w = input_grid(2, 2, default=[[cos(x), sin(x)], [-sin(x), cos(x)]], to_value=matrix); w
|
529
|
+
Grid(value=[[cos(x), sin(x)], [-sin(x), cos(x)]], children=(Label(value=''), VBox(children=(EvalText(value='cos(x)', layout=Layout(max_width='5em')), EvalText(value='-sin(x)', layout=Layout(max_width='5em')))), VBox(children=(EvalText(value='sin(x)', layout=Layout(max_width='5em')), EvalText(value='cos(x)', layout=Layout(max_width='5em'))))))
|
530
|
+
sage: w.get_interact_value()
|
531
|
+
[ cos(x) sin(x)]
|
532
|
+
[-sin(x) cos(x)]
|
533
|
+
sage: w = input_grid(2, 2, default=[1, x, x^2, x^3], to_value=lambda x: x[1][1]); w
|
534
|
+
Grid(value=[[1, x], [x^2, x^3]], children=(Label(value=''), VBox(children=(EvalText(value='1', layout=Layout(max_width='5em')), EvalText(value='x^2', layout=Layout(max_width='5em')))), VBox(children=(EvalText(value='x', layout=Layout(max_width='5em')), EvalText(value='x^3', layout=Layout(max_width='5em'))))))
|
535
|
+
sage: w.get_interact_value()
|
536
|
+
x^3
|
537
|
+
"""
|
538
|
+
kwds = {"transform": to_value}
|
539
|
+
if label is not None:
|
540
|
+
kwds["description"] = label
|
541
|
+
|
542
|
+
# Parse default
|
543
|
+
if not isinstance(default, list):
|
544
|
+
# Single value
|
545
|
+
default = [[default] * ncols] * nrows
|
546
|
+
if all(isinstance(elt, list) for elt in default):
|
547
|
+
# List of lists
|
548
|
+
pass
|
549
|
+
else:
|
550
|
+
# Flat list
|
551
|
+
default = [[default[i * ncols + j] for j in range(ncols)] for i in range(nrows)]
|
552
|
+
|
553
|
+
def make_widget(i, j):
|
554
|
+
return input_box(str(default[i][j]), width=width)
|
555
|
+
|
556
|
+
grid = Grid(nrows, ncols, make_widget, **kwds)
|
557
|
+
return grid
|
558
|
+
|
559
|
+
|
560
|
+
def color_selector(default=(0, 0, 1), label=None, widget=None, hide_box=False):
|
561
|
+
"""
|
562
|
+
A widget for choosing a color.
|
563
|
+
|
564
|
+
INPUT:
|
565
|
+
|
566
|
+
- ``default`` -- initial value
|
567
|
+
|
568
|
+
- ``label`` -- (optional)
|
569
|
+
|
570
|
+
- ``hide_box`` -- boolean; if ``True``, do not show the textbox
|
571
|
+
|
572
|
+
EXAMPLES::
|
573
|
+
|
574
|
+
sage: from sage.repl.ipython_kernel.all_jupyter import color_selector
|
575
|
+
sage: w = color_selector("orange", label="color me"); w
|
576
|
+
SageColorPicker(value='#ffa500', description='color me')
|
577
|
+
sage: w.get_interact_value()
|
578
|
+
RGB color (1.0, 0.6470588235294118, 0.0)
|
579
|
+
sage: color_selector(Color(0.1, 0.2, 0.3))
|
580
|
+
SageColorPicker(value='#19334c')
|
581
|
+
"""
|
582
|
+
# widget argument is silently ignored
|
583
|
+
kwds = {"value": Color(default).html_color(),
|
584
|
+
"concise": hide_box}
|
585
|
+
if label is not None:
|
586
|
+
kwds["description"] = label
|
587
|
+
return SageColorPicker(**kwds)
|