passagemath-repl 10.4.62__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.4.62.data/scripts/sage-cachegrind +25 -0
  2. passagemath_repl-10.4.62.data/scripts/sage-callgrind +16 -0
  3. passagemath_repl-10.4.62.data/scripts/sage-cleaner +230 -0
  4. passagemath_repl-10.4.62.data/scripts/sage-coverage +327 -0
  5. passagemath_repl-10.4.62.data/scripts/sage-eval +14 -0
  6. passagemath_repl-10.4.62.data/scripts/sage-fixdoctests +708 -0
  7. passagemath_repl-10.4.62.data/scripts/sage-inline-fortran +12 -0
  8. passagemath_repl-10.4.62.data/scripts/sage-ipynb2rst +50 -0
  9. passagemath_repl-10.4.62.data/scripts/sage-ipython +16 -0
  10. passagemath_repl-10.4.62.data/scripts/sage-massif +25 -0
  11. passagemath_repl-10.4.62.data/scripts/sage-notebook +267 -0
  12. passagemath_repl-10.4.62.data/scripts/sage-omega +25 -0
  13. passagemath_repl-10.4.62.data/scripts/sage-preparse +302 -0
  14. passagemath_repl-10.4.62.data/scripts/sage-run +27 -0
  15. passagemath_repl-10.4.62.data/scripts/sage-run-cython +10 -0
  16. passagemath_repl-10.4.62.data/scripts/sage-runtests +9 -0
  17. passagemath_repl-10.4.62.data/scripts/sage-startuptime.py +163 -0
  18. passagemath_repl-10.4.62.data/scripts/sage-valgrind +34 -0
  19. passagemath_repl-10.4.62.dist-info/METADATA +77 -0
  20. passagemath_repl-10.4.62.dist-info/RECORD +162 -0
  21. passagemath_repl-10.4.62.dist-info/WHEEL +5 -0
  22. passagemath_repl-10.4.62.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 +131 -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 +246 -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/__init__.py +1 -0
  143. sage/tests/all.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 +1923 -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 +790 -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,301 @@
1
+ # sage_setup: distribution = sagemath-repl
2
+ """
3
+ Installing the SageMath Jupyter Kernel and Extensions
4
+
5
+ Kernels have to register themselves with Jupyter so that they appear
6
+ in the Jupyter notebook's kernel drop-down. This is done by
7
+ :class:`SageKernelSpec`.
8
+
9
+ .. NOTE::
10
+
11
+ The doctests in this module run in a temporary directory as the involved
12
+ directories might be different during runs of the tests and actual
13
+ installation and because we might be lacking write permission to places
14
+ such as ``/usr/share``.
15
+ """
16
+
17
+ import errno
18
+ import os
19
+ import warnings
20
+
21
+ from sage.env import (
22
+ SAGE_DOC,
23
+ SAGE_EXTCODE,
24
+ SAGE_VENV,
25
+ SAGE_VERSION,
26
+ )
27
+
28
+
29
+ class SageKernelSpec:
30
+
31
+ def __init__(self, prefix=None):
32
+ """
33
+ Utility to manage SageMath kernels and extensions.
34
+
35
+ INPUT:
36
+
37
+ - ``prefix`` -- (default: ``sys.prefix``)
38
+ directory for the installation prefix
39
+
40
+ EXAMPLES::
41
+
42
+ sage: from sage.repl.ipython_kernel.install import SageKernelSpec
43
+ sage: prefix = tmp_dir()
44
+ sage: spec = SageKernelSpec(prefix=prefix)
45
+ sage: spec._display_name # random output
46
+ 'SageMath 6.9'
47
+ sage: spec.kernel_dir == SageKernelSpec(prefix=prefix).kernel_dir
48
+ True
49
+ """
50
+ self._display_name = 'SageMath {0}'.format(SAGE_VERSION)
51
+ if prefix is None:
52
+ from sys import prefix
53
+ jupyter_dir = os.path.join(prefix, "share", "jupyter")
54
+ self.nbextensions_dir = os.path.join(jupyter_dir, "nbextensions")
55
+ self.kernel_dir = os.path.join(jupyter_dir, "kernels", self.identifier())
56
+ self._mkdirs()
57
+
58
+ def _mkdirs(self):
59
+ """
60
+ Create necessary parent directories.
61
+
62
+ EXAMPLES::
63
+
64
+ sage: from sage.repl.ipython_kernel.install import SageKernelSpec
65
+ sage: spec = SageKernelSpec(prefix=tmp_dir())
66
+ sage: spec._mkdirs()
67
+ sage: os.path.isdir(spec.nbextensions_dir)
68
+ True
69
+ """
70
+ def mkdir_p(path):
71
+ try:
72
+ os.makedirs(path)
73
+ except OSError:
74
+ if not os.path.isdir(path):
75
+ raise
76
+ mkdir_p(self.nbextensions_dir)
77
+ mkdir_p(self.kernel_dir)
78
+
79
+ @classmethod
80
+ def identifier(cls):
81
+ """
82
+ Internal identifier for the SageMath kernel.
83
+
84
+ OUTPUT: the string ``'sagemath'``
85
+
86
+ EXAMPLES::
87
+
88
+ sage: from sage.repl.ipython_kernel.install import SageKernelSpec
89
+ sage: SageKernelSpec.identifier()
90
+ 'sagemath'
91
+ """
92
+ return 'sagemath'
93
+
94
+ def symlink(self, src, dst):
95
+ """
96
+ Symlink ``src`` to ``dst``.
97
+
98
+ This is not an atomic operation.
99
+
100
+ Already-existing symlinks will be deleted, already existing
101
+ non-empty directories will be kept.
102
+
103
+ EXAMPLES::
104
+
105
+ sage: from sage.repl.ipython_kernel.install import SageKernelSpec
106
+ sage: spec = SageKernelSpec(prefix=tmp_dir())
107
+ sage: path = tmp_dir()
108
+ sage: spec.symlink(os.path.join(path, 'a'), os.path.join(path, 'b'))
109
+ sage: os.listdir(path)
110
+ ['b']
111
+ """
112
+ try:
113
+ os.remove(dst)
114
+ except OSError as err:
115
+ if err.errno == errno.EEXIST:
116
+ return
117
+ os.symlink(src, dst)
118
+
119
+ def use_local_threejs(self):
120
+ """
121
+ Symlink threejs to the Jupyter notebook.
122
+
123
+ EXAMPLES::
124
+
125
+ sage: # needs threejs
126
+ sage: from sage.repl.ipython_kernel.install import SageKernelSpec
127
+ sage: spec = SageKernelSpec(prefix=tmp_dir())
128
+ sage: spec.use_local_threejs()
129
+ sage: threejs = os.path.join(spec.nbextensions_dir, 'threejs-sage')
130
+ sage: os.path.isdir(threejs)
131
+ True
132
+ """
133
+ from sage.features.threejs import Threejs
134
+ if not Threejs().is_present():
135
+ return
136
+ src = os.path.dirname(os.path.dirname(Threejs().absolute_filename()))
137
+ dst = os.path.join(self.nbextensions_dir, 'threejs-sage')
138
+ self.symlink(src, dst)
139
+
140
+ def _kernel_cmd(self):
141
+ """
142
+ Helper to construct the SageMath kernel command.
143
+
144
+ OUTPUT: list of strings; the command to start a new SageMath kernel
145
+
146
+ EXAMPLES::
147
+
148
+ sage: from sage.repl.ipython_kernel.install import SageKernelSpec
149
+ sage: spec = SageKernelSpec(prefix=tmp_dir())
150
+ sage: spec._kernel_cmd()
151
+ ['/.../sage',
152
+ '--python',
153
+ '-m',
154
+ 'sage.repl.ipython_kernel',
155
+ '-f',
156
+ '{connection_file}']
157
+ """
158
+ return [
159
+ os.path.join(SAGE_VENV, 'bin', 'sage'),
160
+ '--python',
161
+ '-m', 'sage.repl.ipython_kernel',
162
+ '-f', '{connection_file}',
163
+ ]
164
+
165
+ def kernel_spec(self):
166
+ """
167
+ Return the kernel spec as Python dictionary.
168
+
169
+ OUTPUT: a dictionary; see the Jupyter documentation for details
170
+
171
+ EXAMPLES::
172
+
173
+ sage: from sage.repl.ipython_kernel.install import SageKernelSpec
174
+ sage: spec = SageKernelSpec(prefix=tmp_dir())
175
+ sage: spec.kernel_spec()
176
+ {'argv': ..., 'display_name': 'SageMath ...', 'language': 'sage'}
177
+ """
178
+ return dict(
179
+ argv=self._kernel_cmd(),
180
+ display_name=self._display_name,
181
+ language='sage',
182
+ )
183
+
184
+ def _install_spec(self):
185
+ """
186
+ Install the SageMath Jupyter kernel.
187
+
188
+ EXAMPLES::
189
+
190
+ sage: from sage.repl.ipython_kernel.install import SageKernelSpec
191
+ sage: spec = SageKernelSpec(prefix=tmp_dir())
192
+ sage: spec._install_spec()
193
+ """
194
+ jsonfile = os.path.join(self.kernel_dir, "kernel.json")
195
+ import json
196
+ with open(jsonfile, 'w') as f:
197
+ json.dump(self.kernel_spec(), f)
198
+
199
+ def _symlink_resources(self):
200
+ """
201
+ Symlink miscellaneous resources.
202
+
203
+ This method symlinks additional resources (like the SageMath
204
+ documentation) into the SageMath kernel directory. This is
205
+ necessary to make the help links in the notebook work.
206
+
207
+ EXAMPLES::
208
+
209
+ sage: from sage.repl.ipython_kernel.install import SageKernelSpec
210
+ sage: spec = SageKernelSpec(prefix=tmp_dir())
211
+ sage: spec._install_spec()
212
+ sage: spec._symlink_resources()
213
+ """
214
+ path = os.path.join(SAGE_EXTCODE, 'notebook-ipython')
215
+ for filename in os.listdir(path):
216
+ self.symlink(
217
+ os.path.join(path, filename),
218
+ os.path.join(self.kernel_dir, filename)
219
+ )
220
+ self.symlink(
221
+ SAGE_DOC,
222
+ os.path.join(self.kernel_dir, 'doc')
223
+ )
224
+
225
+ @classmethod
226
+ def update(cls, *args, **kwds):
227
+ """
228
+ Configure the Jupyter notebook for the SageMath kernel.
229
+
230
+ This method does everything necessary to use the SageMath kernel,
231
+ you should never need to call any of the other methods
232
+ directly.
233
+
234
+ EXAMPLES::
235
+
236
+ sage: from sage.repl.ipython_kernel.install import SageKernelSpec
237
+ sage: SageKernelSpec.update(prefix=tmp_dir())
238
+ """
239
+ instance = cls(*args, **kwds)
240
+ instance.use_local_threejs()
241
+ instance._install_spec()
242
+ instance._symlink_resources()
243
+
244
+ @classmethod
245
+ def check(cls):
246
+ """
247
+ Check that the SageMath kernel can be discovered by its name (sagemath).
248
+
249
+ This method issues a warning if it cannot -- either because it is not installed,
250
+ or it is shadowed by a different kernel of this name, or Jupyter is
251
+ misconfigured in a different way.
252
+
253
+ EXAMPLES::
254
+
255
+ sage: from sage.repl.ipython_kernel.install import SageKernelSpec
256
+ sage: SageKernelSpec.check() # random
257
+ """
258
+ from jupyter_client.kernelspec import NoSuchKernel, get_kernel_spec
259
+ ident = cls.identifier()
260
+ try:
261
+ spec = get_kernel_spec(ident)
262
+ except NoSuchKernel:
263
+ warnings.warn(f'no kernel named {ident} is accessible; '
264
+ 'check your Jupyter configuration '
265
+ '(see https://docs.jupyter.org/en/latest/use/jupyter-directories.html)')
266
+ else:
267
+ from pathlib import Path
268
+ if Path(spec.argv[0]).resolve() != Path(os.path.join(SAGE_VENV, 'bin', 'sage')).resolve():
269
+ warnings.warn(f'the kernel named {ident} does not seem to correspond to this '
270
+ 'installation of SageMath; check your Jupyter configuration '
271
+ '(see https://docs.jupyter.org/en/latest/use/jupyter-directories.html)')
272
+
273
+
274
+ def have_prerequisites(debug=True):
275
+ """
276
+ Check that we have all prerequisites to run the Jupyter notebook.
277
+
278
+ In particular, the Jupyter notebook requires OpenSSL whether or
279
+ not you are using https. See :issue:`17318`.
280
+
281
+ INPUT:
282
+
283
+ - ``debug`` -- boolean (default: ``True``); whether to print debug
284
+ information in case that prerequisites are missing
285
+
286
+ OUTPUT: boolean
287
+
288
+ EXAMPLES::
289
+
290
+ sage: from sage.repl.ipython_kernel.install import have_prerequisites
291
+ sage: have_prerequisites(debug=False) in [True, False]
292
+ True
293
+ """
294
+ try:
295
+ from notebook.notebookapp import NotebookApp
296
+ return True
297
+ except ImportError:
298
+ if debug:
299
+ import traceback
300
+ traceback.print_exc()
301
+ return False
@@ -0,0 +1,278 @@
1
+ # sage_setup: distribution = sagemath-repl
2
+ r"""
3
+ Interacts for the Sage Jupyter notebook
4
+
5
+ This is mostly the same as the stock ``ipywidgets.interact``, but with
6
+ some customizations for Sage.
7
+
8
+ TESTS:
9
+
10
+ We need to setup a proper test environment for widgets::
11
+
12
+ sage: from ipywidgets.widgets.tests.utils import setup_test_comm
13
+ sage: setup_test_comm()
14
+
15
+ EXAMPLES::
16
+
17
+ sage: from sage.repl.ipython_kernel.interact import interact
18
+ sage: @interact
19
+ ....: def f(x=(0, 10)):
20
+ ....: pass
21
+ ...Interactive function <function f at ...> with 1 widget
22
+ x: IntSlider(value=5, description='x', max=10)
23
+ sage: f.widget.children
24
+ (IntSlider(value=5, description='x', max=10), Output())
25
+ """
26
+
27
+ # ****************************************************************************
28
+ # Copyright (C) 2017 Jeroen Demeyer <jdemeyer@cage.ugent.be>
29
+ #
30
+ # This program is free software: you can redistribute it and/or modify
31
+ # it under the terms of the GNU General Public License as published by
32
+ # the Free Software Foundation, either version 2 of the License, or
33
+ # (at your option) any later version.
34
+ # https://www.gnu.org/licenses/
35
+ # ****************************************************************************
36
+
37
+ from collections import OrderedDict
38
+ from collections.abc import Iterable, Iterator
39
+
40
+ from ipywidgets.widgets import SelectionSlider, ValueWidget, ToggleButtons
41
+ from ipywidgets.widgets.interaction import interactive, signature
42
+
43
+ import sage.rings.abc
44
+
45
+ from sage.misc.lazy_import import lazy_import
46
+ from sage.repl.ipython_kernel.widgets import EvalText, SageColorPicker
47
+ from sage.structure.element import Matrix, parent
48
+
49
+ lazy_import("sage.plot.colors", "Color")
50
+
51
+
52
+ class sage_interactive(interactive):
53
+ """
54
+ Wrapper around the ipywidgets interactive which handles some SageNB
55
+ specifics.
56
+
57
+ EXAMPLES::
58
+
59
+ sage: from sage.repl.ipython_kernel.interact import sage_interactive
60
+ sage: def myfunc(x=10, y='hello', z=None): pass
61
+ sage: sage_interactive(myfunc, x=(0,100), z=["one", "two", "three"])
62
+ ...Interactive function <function myfunc at ...> with 3 widgets
63
+ x: IntSlider(value=10, description='x')
64
+ y: Text(value='hello', description='y')
65
+ z: Dropdown(description='z', options=('one', 'two', 'three'), value=None)
66
+ """
67
+ def __init__(self, *args, **kwds):
68
+ """
69
+ See :class:`ipywidgets.widgets.interaction.interactive`.
70
+
71
+ TESTS::
72
+
73
+ sage: from sage.repl.ipython_kernel.interact import sage_interactive
74
+ sage: def myfunc(): pass
75
+ sage: sage_interactive(myfunc, dict(manual=True))
76
+ Manual interactive function <function myfunc ...> with 0 widgets
77
+
78
+ ::
79
+
80
+ sage: def myfunc(auto_update=False): pass
81
+ sage: sage_interactive(myfunc)
82
+ ...Manual interactive function <function myfunc ...> with 0 widgets
83
+ sage: def myfunc(auto_update=None): pass
84
+ sage: sage_interactive(myfunc)
85
+ ...Interactive function <function myfunc ...> with 0 widgets
86
+ """
87
+ # Use *args to avoid name clash with keyword arguments
88
+ if len(args) < 2:
89
+ f = args[0]
90
+ options = {}
91
+ else:
92
+ (f, options) = args
93
+ options = options.copy()
94
+
95
+ # Check for auto_update in signature
96
+ sig = signature(f)
97
+ params = OrderedDict(sig.parameters)
98
+ try:
99
+ p_auto_update = params.pop("auto_update")
100
+ except KeyError:
101
+ pass
102
+ else:
103
+ options["manual"] = (p_auto_update.default is False)
104
+
105
+ self.__signature = sig.replace(parameters=params.values())
106
+ super().__init__(f, options, **kwds)
107
+ if self.manual:
108
+ # In Sage, manual interacts are always run once
109
+ self.on_widget_constructed(self.update)
110
+ else:
111
+ # In automatic mode, clicking on a ToggleButtons button
112
+ # should also run the interact
113
+ for widget in self.kwargs_widgets:
114
+ if isinstance(widget, ToggleButtons):
115
+ widget.on_msg(self.update)
116
+
117
+ def __repr__(self):
118
+ """
119
+ Textual representation of this interactive function.
120
+
121
+ EXAMPLES::
122
+
123
+ sage: from sage.repl.ipython_kernel.interact import sage_interactive
124
+ sage: def myfunc(): pass
125
+ sage: sage_interactive(myfunc)
126
+ ...Interactive function <function myfunc ...> with 0 widgets
127
+ """
128
+ s = "Manual interactive" if self.manual else "Interactive"
129
+ widgets = [w for w in self.children if isinstance(w, ValueWidget)]
130
+ n = len(widgets)
131
+ s += " function %r with %s widget%s" % (self.f, n,
132
+ "s" if n != 1 else "")
133
+ for w in widgets:
134
+ s += "\n %s: %s" % (w._kwarg, w)
135
+ return s
136
+
137
+ def signature(self):
138
+ """
139
+ Return the fixed signature of the interactive function (after
140
+ a possible ``auto_update`` parameter was removed).
141
+
142
+ EXAMPLES::
143
+
144
+ sage: from sage.repl.ipython_kernel.interact import sage_interactive
145
+ sage: def myfunc(x=[1,2,3], auto_update=False): pass
146
+ sage: sage_interactive(myfunc).signature().parameters
147
+ ...mappingproxy({'x': <Parameter "x=[1, 2, 3]">})
148
+ """
149
+ return self.__signature
150
+
151
+ @classmethod # Behaves like a staticmethod, but we need super()
152
+ def widget_from_single_value(cls, abbrev, *args, **kwds):
153
+ """
154
+ Convert a single value (i.e. a non-iterable) to a widget.
155
+
156
+ This supports the Sage :class:`Color` and ``Matrix`` classes.
157
+ Any unknown type is changed to a string for evaluating.
158
+ This is meant to support symbolic expressions like ``sin(x)``.
159
+
160
+ EXAMPLES::
161
+
162
+ sage: from sage.repl.ipython_kernel.interact import sage_interactive
163
+ sage: sage_interactive.widget_from_single_value("sin(x)")
164
+ ...Text(value='sin(x)')
165
+ sage: sage_interactive.widget_from_single_value(sin(x)) # needs sage.symbolic
166
+ ...EvalText(value='sin(x)')
167
+ sage: sage_interactive.widget_from_single_value(matrix([[1, 2], [3, 4]])) # needs sage.modules
168
+ ...Grid(value=[[1, 2], [3, 4]], children=(Label(value=''), VBox(children=(EvalText(value='1', layout=Layout(max_width='5em')), EvalText(value='3', layout=Layout(max_width='5em')))), VBox(children=(EvalText(value='2', layout=Layout(max_width='5em')), EvalText(value='4', layout=Layout(max_width='5em'))))))
169
+ sage: from sage.plot.colors import Color # needs sage.plot
170
+ sage: sage_interactive.widget_from_single_value(Color('cornflowerblue')) # needs sage.plot
171
+ ...SageColorPicker(value='#6495ed')
172
+ """
173
+ # Support Sage matrices and colors
174
+ if isinstance(abbrev, Matrix):
175
+ from .widgets_sagenb import input_grid
176
+
177
+ return input_grid(abbrev.nrows(), abbrev.ncols(),
178
+ default=abbrev.list(), to_value=abbrev.parent())
179
+
180
+ try:
181
+ from sage.plot.colors import Color
182
+ except ImportError:
183
+ pass
184
+ else:
185
+ if isinstance(abbrev, Color):
186
+ return SageColorPicker(value=abbrev.html_color())
187
+ # Get widget from IPython if possible
188
+ widget = super().widget_from_single_value(abbrev, *args, **kwds)
189
+ if widget is not None or isinstance(abbrev, Iterable):
190
+ return widget
191
+ # If IPython didn't construct a widget and the abbrev is not an
192
+ # iterable, return an EvalText widget
193
+ return EvalText(value=str(abbrev))
194
+
195
+ @classmethod # Behaves like a staticmethod, but we need super()
196
+ def widget_from_tuple(cls, abbrev, *args, **kwds):
197
+ """
198
+ Convert a tuple to a widget.
199
+
200
+ This supports two SageNB extensions: ``(description, abbrev)``
201
+ if ``description`` is a string and ``(default, abbrev)`` if
202
+ ``abbrev`` is not a single value.
203
+
204
+ Symbolic expressions are changed to a floating-point number.
205
+
206
+ EXAMPLES::
207
+
208
+ sage: from sage.repl.ipython_kernel.interact import sage_interactive
209
+ sage: sage_interactive.widget_from_tuple( (0, 10) )
210
+ ...IntSlider(value=5, max=10)
211
+ sage: sage_interactive.widget_from_tuple( ("number", (0, 10)) )
212
+ ...IntSlider(value=5, description='number', max=10)
213
+ sage: sage_interactive.widget_from_tuple( (3, (0, 10)) )
214
+ ...IntSlider(value=3, max=10)
215
+ sage: sage_interactive.widget_from_tuple((2, [('one', 1), ('two', 2), ('three', 3)]))
216
+ ...Dropdown(index=1, options=(('one', 1), ('two', 2), ('three', 3)), value=2)
217
+ sage: sage_interactive.widget_from_tuple( (sqrt(2), pi) ) # needs sage.symbolic
218
+ ...FloatSlider(value=2.277903107981444, max=3.141592653589793, min=1.4142135623730951)
219
+
220
+ TESTS:
221
+
222
+ Symbolic subrings::
223
+
224
+ sage: SCR = SR.subring(no_variables=True) # needs sage.symbolic
225
+ sage: sage_interactive.widget_from_tuple( (SCR(sqrt(2)), SCR(pi)) ) # needs sage.symbolic
226
+ ...FloatSlider(value=2.277903107981444, max=3.141592653589793, min=1.4142135623730951)
227
+ """
228
+ # Support (description, abbrev)
229
+ if len(abbrev) == 2 and isinstance(abbrev[0], str):
230
+ widget = cls.widget_from_abbrev(abbrev[1])
231
+ widget.description = abbrev[0]
232
+ return widget
233
+ # Support (default, abbrev)
234
+ if len(abbrev) == 2 and isinstance(abbrev[1], Iterable):
235
+ widget = cls.widget_from_abbrev(abbrev[1])
236
+ widget.value = abbrev[0]
237
+ return widget
238
+ # Numerically evaluate symbolic expressions
239
+
240
+ def n(x):
241
+ if isinstance(parent(x), sage.rings.abc.SymbolicRing):
242
+ return x.numerical_approx()
243
+ else:
244
+ return x
245
+ abbrev = tuple(n(x) for x in abbrev)
246
+ return super().widget_from_tuple(abbrev, *args, **kwds)
247
+
248
+ @classmethod # Behaves like a staticmethod, but we need super()
249
+ def widget_from_iterable(cls, abbrev, *args, **kwds):
250
+ """
251
+ Convert an unspecified iterable to a widget.
252
+
253
+ This behaves like in ipywidgets, except that an iterator (like
254
+ a generator object) becomes a ``SelectionSlider``.
255
+
256
+ EXAMPLES::
257
+
258
+ sage: from sage.repl.ipython_kernel.interact import sage_interactive
259
+ sage: sage_interactive.widget_from_iterable([1..5])
260
+ ...Dropdown(options=(1, 2, 3, 4, 5), value=1)
261
+ sage: sage_interactive.widget_from_iterable(iter([1..5]))
262
+ ...SelectionSlider(options=(1, 2, 3, 4, 5), value=1)
263
+ sage: sage_interactive.widget_from_iterable((1..5))
264
+ ...SelectionSlider(options=(1, 2, 3, 4, 5), value=1)
265
+ sage: sage_interactive.widget_from_iterable(x for x in [1..5])
266
+ ...SelectionSlider(options=(1, 2, 3, 4, 5), value=1)
267
+ sage: def gen():
268
+ ....: yield 1; yield 2; yield 3; yield 4; yield 5
269
+ sage: sage_interactive.widget_from_iterable(gen())
270
+ ...SelectionSlider(options=(1, 2, 3, 4, 5), value=1)
271
+ """
272
+ if isinstance(abbrev, Iterator):
273
+ return SelectionSlider(options=list(abbrev))
274
+ return super().widget_from_iterable(abbrev, *args, **kwds)
275
+
276
+
277
+ # @interact decorator
278
+ interact = sage_interactive.factory()