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.
Files changed (162) hide show
  1. passagemath_repl-10.5.1.data/scripts/sage-cachegrind +25 -0
  2. passagemath_repl-10.5.1.data/scripts/sage-callgrind +16 -0
  3. passagemath_repl-10.5.1.data/scripts/sage-cleaner +230 -0
  4. passagemath_repl-10.5.1.data/scripts/sage-coverage +327 -0
  5. passagemath_repl-10.5.1.data/scripts/sage-eval +14 -0
  6. passagemath_repl-10.5.1.data/scripts/sage-fixdoctests +710 -0
  7. passagemath_repl-10.5.1.data/scripts/sage-inline-fortran +12 -0
  8. passagemath_repl-10.5.1.data/scripts/sage-ipynb2rst +50 -0
  9. passagemath_repl-10.5.1.data/scripts/sage-ipython +16 -0
  10. passagemath_repl-10.5.1.data/scripts/sage-massif +25 -0
  11. passagemath_repl-10.5.1.data/scripts/sage-notebook +267 -0
  12. passagemath_repl-10.5.1.data/scripts/sage-omega +25 -0
  13. passagemath_repl-10.5.1.data/scripts/sage-preparse +302 -0
  14. passagemath_repl-10.5.1.data/scripts/sage-run +27 -0
  15. passagemath_repl-10.5.1.data/scripts/sage-run-cython +10 -0
  16. passagemath_repl-10.5.1.data/scripts/sage-runtests +9 -0
  17. passagemath_repl-10.5.1.data/scripts/sage-startuptime.py +163 -0
  18. passagemath_repl-10.5.1.data/scripts/sage-valgrind +34 -0
  19. passagemath_repl-10.5.1.dist-info/METADATA +77 -0
  20. passagemath_repl-10.5.1.dist-info/RECORD +162 -0
  21. passagemath_repl-10.5.1.dist-info/WHEEL +5 -0
  22. passagemath_repl-10.5.1.dist-info/top_level.txt +1 -0
  23. sage/all__sagemath_repl.py +119 -0
  24. sage/doctest/__init__.py +4 -0
  25. sage/doctest/__main__.py +236 -0
  26. sage/doctest/all.py +4 -0
  27. sage/doctest/check_tolerance.py +261 -0
  28. sage/doctest/control.py +1727 -0
  29. sage/doctest/external.py +534 -0
  30. sage/doctest/fixtures.py +383 -0
  31. sage/doctest/forker.py +2665 -0
  32. sage/doctest/marked_output.py +102 -0
  33. sage/doctest/parsing.py +1708 -0
  34. sage/doctest/parsing_test.py +79 -0
  35. sage/doctest/reporting.py +733 -0
  36. sage/doctest/rif_tol.py +124 -0
  37. sage/doctest/sources.py +1657 -0
  38. sage/doctest/test.py +584 -0
  39. sage/doctest/tests/1second.rst +4 -0
  40. sage/doctest/tests/99seconds.rst +4 -0
  41. sage/doctest/tests/abort.rst +5 -0
  42. sage/doctest/tests/atexit.rst +7 -0
  43. sage/doctest/tests/fail_and_die.rst +6 -0
  44. sage/doctest/tests/initial.rst +15 -0
  45. sage/doctest/tests/interrupt.rst +7 -0
  46. sage/doctest/tests/interrupt_diehard.rst +14 -0
  47. sage/doctest/tests/keyboardinterrupt.rst +11 -0
  48. sage/doctest/tests/longtime.rst +5 -0
  49. sage/doctest/tests/nodoctest +5 -0
  50. sage/doctest/tests/random_seed.rst +4 -0
  51. sage/doctest/tests/show_skipped.rst +18 -0
  52. sage/doctest/tests/sig_on.rst +9 -0
  53. sage/doctest/tests/simple_failure.rst +8 -0
  54. sage/doctest/tests/sleep_and_raise.rst +106 -0
  55. sage/doctest/tests/tolerance.rst +31 -0
  56. sage/doctest/util.py +750 -0
  57. sage/interfaces/cleaner.py +48 -0
  58. sage/interfaces/quit.py +163 -0
  59. sage/misc/all__sagemath_repl.py +51 -0
  60. sage/misc/banner.py +235 -0
  61. sage/misc/benchmark.py +221 -0
  62. sage/misc/classgraph.py +134 -0
  63. sage/misc/copying.py +22 -0
  64. sage/misc/cython.py +694 -0
  65. sage/misc/dev_tools.py +745 -0
  66. sage/misc/edit_module.py +304 -0
  67. sage/misc/explain_pickle.py +3079 -0
  68. sage/misc/gperftools.py +361 -0
  69. sage/misc/inline_fortran.py +212 -0
  70. sage/misc/messaging.py +86 -0
  71. sage/misc/pager.py +21 -0
  72. sage/misc/profiler.py +179 -0
  73. sage/misc/python.py +70 -0
  74. sage/misc/remote_file.py +53 -0
  75. sage/misc/sage_eval.py +249 -0
  76. sage/misc/sage_input.py +3621 -0
  77. sage/misc/sagedoc.py +1742 -0
  78. sage/misc/sh.py +38 -0
  79. sage/misc/trace.py +90 -0
  80. sage/repl/__init__.py +16 -0
  81. sage/repl/all.py +15 -0
  82. sage/repl/attach.py +625 -0
  83. sage/repl/configuration.py +186 -0
  84. sage/repl/display/__init__.py +1 -0
  85. sage/repl/display/fancy_repr.py +354 -0
  86. sage/repl/display/formatter.py +318 -0
  87. sage/repl/display/jsmol_iframe.py +290 -0
  88. sage/repl/display/pretty_print.py +153 -0
  89. sage/repl/display/util.py +163 -0
  90. sage/repl/image.py +302 -0
  91. sage/repl/inputhook.py +91 -0
  92. sage/repl/interface_magic.py +298 -0
  93. sage/repl/interpreter.py +854 -0
  94. sage/repl/ipython_extension.py +593 -0
  95. sage/repl/ipython_kernel/__init__.py +1 -0
  96. sage/repl/ipython_kernel/__main__.py +4 -0
  97. sage/repl/ipython_kernel/all_jupyter.py +10 -0
  98. sage/repl/ipython_kernel/install.py +301 -0
  99. sage/repl/ipython_kernel/interact.py +278 -0
  100. sage/repl/ipython_kernel/kernel.py +217 -0
  101. sage/repl/ipython_kernel/widgets.py +466 -0
  102. sage/repl/ipython_kernel/widgets_sagenb.py +587 -0
  103. sage/repl/ipython_tests.py +163 -0
  104. sage/repl/load.py +326 -0
  105. sage/repl/preparse.py +2218 -0
  106. sage/repl/prompts.py +90 -0
  107. sage/repl/rich_output/__init__.py +4 -0
  108. sage/repl/rich_output/backend_base.py +648 -0
  109. sage/repl/rich_output/backend_doctest.py +316 -0
  110. sage/repl/rich_output/backend_emacs.py +151 -0
  111. sage/repl/rich_output/backend_ipython.py +596 -0
  112. sage/repl/rich_output/buffer.py +311 -0
  113. sage/repl/rich_output/display_manager.py +829 -0
  114. sage/repl/rich_output/example.avi +0 -0
  115. sage/repl/rich_output/example.canvas3d +1 -0
  116. sage/repl/rich_output/example.dvi +0 -0
  117. sage/repl/rich_output/example.flv +0 -0
  118. sage/repl/rich_output/example.gif +0 -0
  119. sage/repl/rich_output/example.jpg +0 -0
  120. sage/repl/rich_output/example.mkv +0 -0
  121. sage/repl/rich_output/example.mov +0 -0
  122. sage/repl/rich_output/example.mp4 +0 -0
  123. sage/repl/rich_output/example.ogv +0 -0
  124. sage/repl/rich_output/example.pdf +0 -0
  125. sage/repl/rich_output/example.png +0 -0
  126. sage/repl/rich_output/example.svg +54 -0
  127. sage/repl/rich_output/example.webm +0 -0
  128. sage/repl/rich_output/example.wmv +0 -0
  129. sage/repl/rich_output/example_jmol.spt.zip +0 -0
  130. sage/repl/rich_output/example_wavefront_scene.mtl +7 -0
  131. sage/repl/rich_output/example_wavefront_scene.obj +17 -0
  132. sage/repl/rich_output/output_basic.py +391 -0
  133. sage/repl/rich_output/output_browser.py +103 -0
  134. sage/repl/rich_output/output_catalog.py +54 -0
  135. sage/repl/rich_output/output_graphics.py +320 -0
  136. sage/repl/rich_output/output_graphics3d.py +345 -0
  137. sage/repl/rich_output/output_video.py +231 -0
  138. sage/repl/rich_output/preferences.py +432 -0
  139. sage/repl/rich_output/pretty_print.py +339 -0
  140. sage/repl/rich_output/test_backend.py +201 -0
  141. sage/repl/user_globals.py +214 -0
  142. sage/tests/all.py +0 -0
  143. sage/tests/all__sagemath_repl.py +3 -0
  144. sage/tests/article_heuberger_krenn_kropf_fsm-in-sage.py +630 -0
  145. sage/tests/arxiv_0812_2725.py +351 -0
  146. sage/tests/benchmark.py +1925 -0
  147. sage/tests/book_schilling_zabrocki_kschur_primer.py +795 -0
  148. sage/tests/book_stein_ent.py +651 -0
  149. sage/tests/book_stein_modform.py +558 -0
  150. sage/tests/cmdline.py +796 -0
  151. sage/tests/combinatorial_hopf_algebras.py +52 -0
  152. sage/tests/finite_poset.py +623 -0
  153. sage/tests/functools_partial_src.py +27 -0
  154. sage/tests/gosper-sum.py +218 -0
  155. sage/tests/lazy_imports.py +28 -0
  156. sage/tests/modular_group_cohomology.py +80 -0
  157. sage/tests/numpy.py +21 -0
  158. sage/tests/parigp.py +76 -0
  159. sage/tests/startup.py +27 -0
  160. sage/tests/symbolic-series.py +76 -0
  161. sage/tests/sympy.py +16 -0
  162. 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)