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.
- passagemath_repl-10.4.62.data/scripts/sage-cachegrind +25 -0
- passagemath_repl-10.4.62.data/scripts/sage-callgrind +16 -0
- passagemath_repl-10.4.62.data/scripts/sage-cleaner +230 -0
- passagemath_repl-10.4.62.data/scripts/sage-coverage +327 -0
- passagemath_repl-10.4.62.data/scripts/sage-eval +14 -0
- passagemath_repl-10.4.62.data/scripts/sage-fixdoctests +708 -0
- passagemath_repl-10.4.62.data/scripts/sage-inline-fortran +12 -0
- passagemath_repl-10.4.62.data/scripts/sage-ipynb2rst +50 -0
- passagemath_repl-10.4.62.data/scripts/sage-ipython +16 -0
- passagemath_repl-10.4.62.data/scripts/sage-massif +25 -0
- passagemath_repl-10.4.62.data/scripts/sage-notebook +267 -0
- passagemath_repl-10.4.62.data/scripts/sage-omega +25 -0
- passagemath_repl-10.4.62.data/scripts/sage-preparse +302 -0
- passagemath_repl-10.4.62.data/scripts/sage-run +27 -0
- passagemath_repl-10.4.62.data/scripts/sage-run-cython +10 -0
- passagemath_repl-10.4.62.data/scripts/sage-runtests +9 -0
- passagemath_repl-10.4.62.data/scripts/sage-startuptime.py +163 -0
- passagemath_repl-10.4.62.data/scripts/sage-valgrind +34 -0
- passagemath_repl-10.4.62.dist-info/METADATA +77 -0
- passagemath_repl-10.4.62.dist-info/RECORD +162 -0
- passagemath_repl-10.4.62.dist-info/WHEEL +5 -0
- passagemath_repl-10.4.62.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 +131 -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 +246 -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/__init__.py +1 -0
- sage/tests/all.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 +1923 -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 +790 -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,217 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-repl
|
2
|
+
"""
|
3
|
+
The Sage ZMQ Kernel
|
4
|
+
|
5
|
+
Version of the Jupyter kernel when running Sage inside the Jupyter
|
6
|
+
notebook or remote Jupyter sessions.
|
7
|
+
"""
|
8
|
+
|
9
|
+
# ***************************************************************************
|
10
|
+
# Copyright (C) 2015 Volker Braun <vbraun.name@gmail.com>
|
11
|
+
#
|
12
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
13
|
+
# as published by the Free Software Foundation; either version 2 of
|
14
|
+
# the License, or (at your option) any later version.
|
15
|
+
# https://www.gnu.org/licenses/
|
16
|
+
# ***************************************************************************
|
17
|
+
|
18
|
+
import sys
|
19
|
+
import warnings
|
20
|
+
with warnings.catch_warnings():
|
21
|
+
# When upstream pydevd (as opposed to the bundled version) is used
|
22
|
+
# with debugpy, a PEP 420 warning is emitted. Debugpy and/or
|
23
|
+
# pydevd will eventually work around this, but as of September
|
24
|
+
# 2023, hiding the warning gives us more flexibility in the
|
25
|
+
# versions of those packages that we can accept.
|
26
|
+
warnings.filterwarnings("ignore",
|
27
|
+
message=r".*pkg_resources\.declare_namespace",
|
28
|
+
category=DeprecationWarning)
|
29
|
+
from ipykernel.ipkernel import IPythonKernel
|
30
|
+
|
31
|
+
from ipykernel.zmqshell import ZMQInteractiveShell
|
32
|
+
from traitlets import Type
|
33
|
+
|
34
|
+
from sage.env import SAGE_VERSION
|
35
|
+
from sage.repl.interpreter import SageNotebookInteractiveShell
|
36
|
+
from sage.repl.ipython_extension import SageJupyterCustomizations
|
37
|
+
|
38
|
+
|
39
|
+
class SageZMQInteractiveShell(SageNotebookInteractiveShell, ZMQInteractiveShell):
|
40
|
+
pass
|
41
|
+
|
42
|
+
|
43
|
+
class SageKernel(IPythonKernel):
|
44
|
+
implementation = 'sage'
|
45
|
+
implementation_version = SAGE_VERSION
|
46
|
+
|
47
|
+
shell_class = Type(SageZMQInteractiveShell)
|
48
|
+
|
49
|
+
def __init__(self, **kwds):
|
50
|
+
"""
|
51
|
+
The Sage Jupyter Kernel.
|
52
|
+
|
53
|
+
INPUT:
|
54
|
+
|
55
|
+
See the Jupyter documentation.
|
56
|
+
|
57
|
+
EXAMPLES::
|
58
|
+
|
59
|
+
sage: from sage.repl.ipython_kernel.kernel import SageKernel
|
60
|
+
sage: SageKernel.__new__(SageKernel)
|
61
|
+
<sage.repl.ipython_kernel.kernel.SageKernel object at 0x...>
|
62
|
+
"""
|
63
|
+
super().__init__(**kwds)
|
64
|
+
SageJupyterCustomizations(self.shell)
|
65
|
+
|
66
|
+
@property
|
67
|
+
def banner(self):
|
68
|
+
r"""
|
69
|
+
The Sage Banner.
|
70
|
+
|
71
|
+
The value of this property is displayed in the Jupyter
|
72
|
+
notebook.
|
73
|
+
|
74
|
+
OUTPUT: string
|
75
|
+
|
76
|
+
EXAMPLES::
|
77
|
+
|
78
|
+
sage: from sage.repl.ipython_kernel.kernel import SageKernel
|
79
|
+
sage: sk = SageKernel.__new__(SageKernel)
|
80
|
+
sage: print(sk.banner)
|
81
|
+
┌... version...
|
82
|
+
"""
|
83
|
+
from sage.misc.banner import banner_text
|
84
|
+
return banner_text()
|
85
|
+
|
86
|
+
@property
|
87
|
+
def help_links(self):
|
88
|
+
r"""
|
89
|
+
Help in the Jupyter Notebook.
|
90
|
+
|
91
|
+
OUTPUT: see the Jupyter documentation
|
92
|
+
|
93
|
+
EXAMPLES::
|
94
|
+
|
95
|
+
sage: from sage.repl.ipython_kernel.kernel import SageKernel
|
96
|
+
sage: sk = SageKernel.__new__(SageKernel)
|
97
|
+
sage: sk.help_links
|
98
|
+
[{'text': 'Sage Documentation',
|
99
|
+
'url': '.../html/en/index.html'},
|
100
|
+
...]
|
101
|
+
"""
|
102
|
+
# A Sage doc server starts when Jupyter notebook launches if the Sage
|
103
|
+
# documentation is available locally. See the corresponding code in
|
104
|
+
# src/bin/sage-notebook.
|
105
|
+
|
106
|
+
from sage.env import SAGE_DOC_SERVER_URL
|
107
|
+
from sage.env import SAGE_DOC_LOCAL_PORT as port
|
108
|
+
from sage.features.sagemath import sagemath_doc_html
|
109
|
+
|
110
|
+
if SAGE_DOC_SERVER_URL:
|
111
|
+
def doc_url(path):
|
112
|
+
return f'{SAGE_DOC_SERVER_URL}/{path}'
|
113
|
+
elif sagemath_doc_html().is_present() and int(port):
|
114
|
+
def doc_url(path):
|
115
|
+
return f'http://127.0.0.1:{port}/{path}'
|
116
|
+
else:
|
117
|
+
def doc_url(path):
|
118
|
+
return f'https://doc.sagemath.org/{path}'
|
119
|
+
|
120
|
+
return [
|
121
|
+
{
|
122
|
+
'text': 'Sage Documentation',
|
123
|
+
'url': doc_url('html/en/index.html'),
|
124
|
+
},
|
125
|
+
{
|
126
|
+
'text': 'A Tour of Sage',
|
127
|
+
'url': doc_url('html/en/a_tour_of_sage/index.html'),
|
128
|
+
},
|
129
|
+
{
|
130
|
+
'text': 'Tutorial',
|
131
|
+
'url': doc_url('html/en/tutorial/index.html'),
|
132
|
+
},
|
133
|
+
{
|
134
|
+
'text': 'Thematic Tutorials',
|
135
|
+
'url': doc_url('html/en/thematic_tutorials/index.html'),
|
136
|
+
},
|
137
|
+
{
|
138
|
+
'text': 'PREP Tutorials',
|
139
|
+
'url': doc_url('html/en/prep/index.html'),
|
140
|
+
},
|
141
|
+
{
|
142
|
+
'text': 'Constructions',
|
143
|
+
'url': doc_url('html/en/constructions/index.html'),
|
144
|
+
},
|
145
|
+
{
|
146
|
+
'text': 'FAQ',
|
147
|
+
'url': doc_url('html/en/faq/index.html'),
|
148
|
+
},
|
149
|
+
{
|
150
|
+
'text': 'Reference Manual',
|
151
|
+
'url': doc_url('html/en/reference/index.html'),
|
152
|
+
},
|
153
|
+
{
|
154
|
+
'text': "Installation Guide",
|
155
|
+
'url': doc_url('html/en/installation/index.html'),
|
156
|
+
},
|
157
|
+
{
|
158
|
+
'text': "Developer Guide",
|
159
|
+
'url': doc_url('html/en/developer/index.html'),
|
160
|
+
},
|
161
|
+
{
|
162
|
+
'text': "Python",
|
163
|
+
'url': "http://docs.python.org/%i.%i" % sys.version_info[:2],
|
164
|
+
},
|
165
|
+
{
|
166
|
+
'text': "IPython",
|
167
|
+
'url': "http://ipython.org/documentation.html",
|
168
|
+
},
|
169
|
+
{
|
170
|
+
'text': 'Singular',
|
171
|
+
'url': 'http://www.singular.uni-kl.de/Manual/latest/index.htm',
|
172
|
+
},
|
173
|
+
{
|
174
|
+
'text': 'GAP',
|
175
|
+
'url': 'http://gap-system.org/Manuals/doc/ref/chap0.html',
|
176
|
+
},
|
177
|
+
{
|
178
|
+
'text': "NumPy",
|
179
|
+
'url': "http://docs.scipy.org/doc/numpy/reference/",
|
180
|
+
},
|
181
|
+
{
|
182
|
+
'text': "SciPy",
|
183
|
+
'url': "http://docs.scipy.org/doc/scipy/reference/",
|
184
|
+
},
|
185
|
+
{
|
186
|
+
'text': "SymPy",
|
187
|
+
'url': 'http://docs.sympy.org/latest/index.html',
|
188
|
+
},
|
189
|
+
{
|
190
|
+
'text': "Matplotlib",
|
191
|
+
'url': "https://matplotlib.org/contents.html",
|
192
|
+
},
|
193
|
+
{
|
194
|
+
'text': "Markdown",
|
195
|
+
'url': "http://help.github.com/articles/github-flavored-markdown",
|
196
|
+
},
|
197
|
+
]
|
198
|
+
|
199
|
+
def pre_handler_hook(self):
|
200
|
+
"""
|
201
|
+
Restore the signal handlers to their default values at Sage
|
202
|
+
startup, saving the old handler at the ``saved_sigint_handler``
|
203
|
+
attribute. This is needed because Jupyter needs to change the
|
204
|
+
``SIGINT`` handler.
|
205
|
+
|
206
|
+
See :issue:`19135`.
|
207
|
+
|
208
|
+
TESTS::
|
209
|
+
|
210
|
+
sage: from sage.repl.ipython_kernel.kernel import SageKernel
|
211
|
+
sage: k = SageKernel.__new__(SageKernel)
|
212
|
+
sage: k.pre_handler_hook()
|
213
|
+
sage: k.saved_sigint_handler
|
214
|
+
<cyfunction python_check_interrupt at ...>
|
215
|
+
"""
|
216
|
+
from cysignals import init_cysignals
|
217
|
+
self.saved_sigint_handler = init_cysignals()
|
@@ -0,0 +1,466 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-repl
|
2
|
+
r"""
|
3
|
+
Widgets to be used for the Sage Jupyter notebook
|
4
|
+
|
5
|
+
These are all based on widgets from ``ipywidgets``, changing or
|
6
|
+
combining existing widgets.
|
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
|
+
|
16
|
+
# ****************************************************************************
|
17
|
+
# Copyright (C) 2017 Jeroen Demeyer <jdemeyer@cage.ugent.be>
|
18
|
+
#
|
19
|
+
# This program is free software: you can redistribute it and/or modify
|
20
|
+
# it under the terms of the GNU General Public License as published by
|
21
|
+
# the Free Software Foundation, either version 2 of the License, or
|
22
|
+
# (at your option) any later version.
|
23
|
+
# http://www.gnu.org/licenses/
|
24
|
+
# ****************************************************************************
|
25
|
+
|
26
|
+
|
27
|
+
from ipywidgets.widgets import (IntSlider, IntRangeSlider,
|
28
|
+
FloatSlider, FloatRangeSlider, Text,
|
29
|
+
Textarea, ColorPicker, HTMLMath, Label,
|
30
|
+
HBox, VBox, ValueWidget)
|
31
|
+
from traitlets import List, Unicode, link
|
32
|
+
|
33
|
+
from sage.misc.sage_eval import sage_eval
|
34
|
+
from sage.repl.user_globals import get_globals
|
35
|
+
from sage.misc.lazy_import import lazy_import
|
36
|
+
lazy_import("sage.plot.colors", "Color")
|
37
|
+
|
38
|
+
|
39
|
+
class HTMLText(HTMLMath):
|
40
|
+
"""
|
41
|
+
An HTML widget whose ``description`` is always empty.
|
42
|
+
|
43
|
+
This is used to display arbitrary HTML text in interacts without
|
44
|
+
a label. The :func:`text_control` function from SageNB is an alias
|
45
|
+
of :class:`HTMLText`.
|
46
|
+
|
47
|
+
EXAMPLES::
|
48
|
+
|
49
|
+
sage: from sage.repl.ipython_kernel.widgets import HTMLText
|
50
|
+
sage: w = HTMLText("Hello")
|
51
|
+
sage: w.description
|
52
|
+
''
|
53
|
+
sage: w.description = "text"
|
54
|
+
sage: w.description
|
55
|
+
''
|
56
|
+
"""
|
57
|
+
@property
|
58
|
+
def description(self):
|
59
|
+
"""
|
60
|
+
Always return empty string.
|
61
|
+
|
62
|
+
EXAMPLES::
|
63
|
+
|
64
|
+
sage: from sage.repl.ipython_kernel.widgets import HTMLText
|
65
|
+
sage: w = HTMLText("Hello")
|
66
|
+
sage: w.description
|
67
|
+
''
|
68
|
+
"""
|
69
|
+
return ''
|
70
|
+
|
71
|
+
@description.setter
|
72
|
+
def description(self, value):
|
73
|
+
"""
|
74
|
+
Do not set anything.
|
75
|
+
|
76
|
+
EXAMPLES::
|
77
|
+
|
78
|
+
sage: from sage.repl.ipython_kernel.widgets import HTMLText
|
79
|
+
sage: w = HTMLText("Hello")
|
80
|
+
sage: w.description = "text"
|
81
|
+
sage: w.description
|
82
|
+
''
|
83
|
+
"""
|
84
|
+
pass
|
85
|
+
|
86
|
+
|
87
|
+
class TransformWidget:
|
88
|
+
"""
|
89
|
+
A mixin class for a widget to transform the bare widget value for
|
90
|
+
use in interactive functions.
|
91
|
+
|
92
|
+
INPUT:
|
93
|
+
|
94
|
+
- ``transform`` -- a one-argument function which transforms the
|
95
|
+
value of the widget for use by an interactive function
|
96
|
+
|
97
|
+
- other arguments are passed to the base class
|
98
|
+
|
99
|
+
EXAMPLES::
|
100
|
+
|
101
|
+
sage: from ipywidgets import ToggleButtons
|
102
|
+
sage: from sage.repl.ipython_kernel.widgets import TransformWidget
|
103
|
+
sage: class TransformToggleButtons(TransformWidget, ToggleButtons): pass
|
104
|
+
sage: w = TransformToggleButtons(options=["pi", "e"], transform=lambda x: x + x)
|
105
|
+
sage: w
|
106
|
+
TransformToggleButtons(options=('pi', 'e'), value='pi')
|
107
|
+
sage: w.get_interact_value()
|
108
|
+
'pipi'
|
109
|
+
"""
|
110
|
+
def __init__(self, *args, **kwds):
|
111
|
+
"""
|
112
|
+
Construct a :class:`TransformWidget`.
|
113
|
+
|
114
|
+
TESTS::
|
115
|
+
|
116
|
+
sage: from sage.repl.ipython_kernel.widgets import TransformWidget
|
117
|
+
sage: w = TransformWidget(transform=dict)
|
118
|
+
sage: w._TransformWidget__transform
|
119
|
+
<... 'dict'>
|
120
|
+
"""
|
121
|
+
self.__transform = kwds.pop("transform", None)
|
122
|
+
return super().__init__(*args, **kwds)
|
123
|
+
|
124
|
+
def get_value(self):
|
125
|
+
"""
|
126
|
+
Return ``self.value``.
|
127
|
+
|
128
|
+
This is meant to be overridden by sub-classes to change the
|
129
|
+
input of the transform function.
|
130
|
+
|
131
|
+
EXAMPLES::
|
132
|
+
|
133
|
+
sage: from ipywidgets import ColorPicker
|
134
|
+
sage: from sage.repl.ipython_kernel.widgets import TransformWidget
|
135
|
+
sage: class TransformColorPicker(TransformWidget, ColorPicker): pass
|
136
|
+
sage: TransformColorPicker(value='red').get_value()
|
137
|
+
'red'
|
138
|
+
"""
|
139
|
+
return self.value
|
140
|
+
|
141
|
+
def get_interact_value(self):
|
142
|
+
"""
|
143
|
+
Return the transformed value of this widget, by calling
|
144
|
+
the ``transform`` function.
|
145
|
+
|
146
|
+
EXAMPLES::
|
147
|
+
|
148
|
+
sage: from ipywidgets import Checkbox
|
149
|
+
sage: from sage.repl.ipython_kernel.widgets import TransformWidget
|
150
|
+
sage: class TransformCheckbox(TransformWidget, Checkbox): pass
|
151
|
+
sage: w = TransformCheckbox(value=True, transform=int); w
|
152
|
+
TransformCheckbox(value=True)
|
153
|
+
sage: w.get_interact_value()
|
154
|
+
1
|
155
|
+
"""
|
156
|
+
v = self.get_value()
|
157
|
+
f = self.__transform
|
158
|
+
if f is None:
|
159
|
+
return v
|
160
|
+
else:
|
161
|
+
return f(v)
|
162
|
+
|
163
|
+
|
164
|
+
class EvalWidget(TransformWidget):
|
165
|
+
"""
|
166
|
+
A mixin class for a widget to evaluate (using :func:`sage_eval`) the
|
167
|
+
widget value and possibly transform it like :class:`TransformWidget`.
|
168
|
+
|
169
|
+
EXAMPLES::
|
170
|
+
|
171
|
+
sage: from ipywidgets import ToggleButtons
|
172
|
+
sage: from sage.repl.ipython_kernel.widgets import EvalWidget
|
173
|
+
sage: class EvalToggleButtons(EvalWidget, ToggleButtons): pass
|
174
|
+
sage: w = EvalToggleButtons(options=["pi", "e"], transform=lambda x: x+x)
|
175
|
+
sage: w
|
176
|
+
EvalToggleButtons(options=('pi', 'e'), value='pi')
|
177
|
+
sage: w.get_interact_value() # needs sage.symbolic
|
178
|
+
2*pi
|
179
|
+
"""
|
180
|
+
def get_value(self):
|
181
|
+
"""
|
182
|
+
Evaluate the bare widget value using :func:`sage_eval`.
|
183
|
+
|
184
|
+
EXAMPLES::
|
185
|
+
|
186
|
+
sage: from ipywidgets import Dropdown
|
187
|
+
sage: from sage.repl.ipython_kernel.widgets import EvalWidget
|
188
|
+
sage: class EvalDropdown(EvalWidget, Dropdown): pass
|
189
|
+
sage: w = EvalDropdown(options=["the_answer"], transform=RR)
|
190
|
+
sage: w
|
191
|
+
EvalDropdown(options=('the_answer',), value='the_answer')
|
192
|
+
sage: the_answer = 42
|
193
|
+
sage: w.get_value()
|
194
|
+
42
|
195
|
+
sage: w.get_interact_value()
|
196
|
+
42.0000000000000
|
197
|
+
"""
|
198
|
+
return sage_eval(self.value, get_globals())
|
199
|
+
|
200
|
+
|
201
|
+
class TransformIntSlider(TransformWidget, IntSlider):
|
202
|
+
"""
|
203
|
+
An :class:`ipywidgets.IntSlider` widget with an optional
|
204
|
+
transformation.
|
205
|
+
|
206
|
+
EXAMPLES::
|
207
|
+
|
208
|
+
sage: from sage.repl.ipython_kernel.widgets import TransformIntSlider
|
209
|
+
sage: w = TransformIntSlider(min=0, max=100, value=7, transform=lambda x: x^2)
|
210
|
+
sage: w
|
211
|
+
TransformIntSlider(value=7)
|
212
|
+
sage: w.get_interact_value()
|
213
|
+
49
|
214
|
+
"""
|
215
|
+
pass
|
216
|
+
|
217
|
+
|
218
|
+
class TransformFloatSlider(TransformWidget, FloatSlider):
|
219
|
+
"""
|
220
|
+
A :class:`ipywidgets.FloatSlider` widget with an optional
|
221
|
+
transformation.
|
222
|
+
|
223
|
+
EXAMPLES::
|
224
|
+
|
225
|
+
sage: from sage.repl.ipython_kernel.widgets import TransformFloatSlider
|
226
|
+
sage: w = TransformFloatSlider(min=0, max=100, value=7, transform=lambda x: sqrt(x))
|
227
|
+
sage: w
|
228
|
+
TransformFloatSlider(value=7.0)
|
229
|
+
sage: w.get_interact_value() # needs sage.symbolic
|
230
|
+
2.6457513110645907
|
231
|
+
"""
|
232
|
+
pass
|
233
|
+
|
234
|
+
|
235
|
+
class TransformIntRangeSlider(TransformWidget, IntRangeSlider):
|
236
|
+
"""
|
237
|
+
An :class:`ipywidgets.IntRangeSlider` widget with an optional
|
238
|
+
transformation.
|
239
|
+
|
240
|
+
EXAMPLES::
|
241
|
+
|
242
|
+
sage: from sage.repl.ipython_kernel.widgets import TransformIntRangeSlider
|
243
|
+
sage: w = TransformIntRangeSlider(min=0, max=100, value=(7, 9),
|
244
|
+
....: transform=lambda x: x[1] - x[0])
|
245
|
+
sage: w
|
246
|
+
TransformIntRangeSlider(value=(7, 9))
|
247
|
+
sage: w.get_interact_value()
|
248
|
+
2
|
249
|
+
"""
|
250
|
+
pass
|
251
|
+
|
252
|
+
|
253
|
+
class TransformFloatRangeSlider(TransformWidget, FloatRangeSlider):
|
254
|
+
"""
|
255
|
+
An :class:`ipywidgets.FloatRangeSlider` widget with an optional
|
256
|
+
transformation.
|
257
|
+
|
258
|
+
EXAMPLES::
|
259
|
+
|
260
|
+
sage: from sage.repl.ipython_kernel.widgets import TransformFloatRangeSlider
|
261
|
+
sage: w = TransformFloatRangeSlider(min=0, max=100, value=(7, 9),
|
262
|
+
....: transform=lambda x: x[1] - x[0])
|
263
|
+
sage: w
|
264
|
+
TransformFloatRangeSlider(value=(7.0, 9.0))
|
265
|
+
sage: w.get_interact_value()
|
266
|
+
2.0
|
267
|
+
"""
|
268
|
+
pass
|
269
|
+
|
270
|
+
|
271
|
+
class TransformText(TransformWidget, Text):
|
272
|
+
"""
|
273
|
+
A :class:`ipywidgets.Text` widget with an optional
|
274
|
+
transformation.
|
275
|
+
|
276
|
+
EXAMPLES::
|
277
|
+
|
278
|
+
sage: from sage.repl.ipython_kernel.widgets import TransformText
|
279
|
+
sage: w = TransformText(value='hello', transform=lambda x: x + x)
|
280
|
+
sage: w
|
281
|
+
TransformText(value='hello')
|
282
|
+
sage: w.get_interact_value()
|
283
|
+
'hellohello'
|
284
|
+
"""
|
285
|
+
pass
|
286
|
+
|
287
|
+
|
288
|
+
class TransformTextarea(TransformWidget, Textarea):
|
289
|
+
"""
|
290
|
+
A :class:`ipywidgets.Textarea` widget with an optional
|
291
|
+
transformation.
|
292
|
+
|
293
|
+
EXAMPLES::
|
294
|
+
|
295
|
+
sage: from sage.repl.ipython_kernel.widgets import TransformTextarea
|
296
|
+
sage: w = TransformTextarea(value='hello', transform=lambda x: x + x)
|
297
|
+
sage: w
|
298
|
+
TransformTextarea(value='hello')
|
299
|
+
sage: w.get_interact_value()
|
300
|
+
'hellohello'
|
301
|
+
"""
|
302
|
+
pass
|
303
|
+
|
304
|
+
|
305
|
+
class EvalText(EvalWidget, Text):
|
306
|
+
"""
|
307
|
+
A :class:`ipywidgets.Text` widget which evaluates (using
|
308
|
+
:func:`sage_eval`) its contents and applies an optional transformation.
|
309
|
+
|
310
|
+
EXAMPLES::
|
311
|
+
|
312
|
+
sage: from sage.repl.ipython_kernel.widgets import EvalText
|
313
|
+
sage: w = EvalText(value='pi', transform=lambda x: x^2)
|
314
|
+
sage: w
|
315
|
+
EvalText(value='pi')
|
316
|
+
sage: w.get_interact_value() # needs sage.symbolic
|
317
|
+
pi^2
|
318
|
+
"""
|
319
|
+
pass
|
320
|
+
|
321
|
+
|
322
|
+
class EvalTextarea(EvalWidget, Textarea):
|
323
|
+
"""
|
324
|
+
A :class:`ipywidgets.Textarea` widget which evaluates (using
|
325
|
+
:func:`sage_eval`) its contents and applies an optional transformation.
|
326
|
+
|
327
|
+
EXAMPLES::
|
328
|
+
|
329
|
+
sage: from sage.repl.ipython_kernel.widgets import EvalTextarea
|
330
|
+
sage: w = EvalTextarea(value='pi', transform=lambda x: x^2)
|
331
|
+
sage: w
|
332
|
+
EvalTextarea(value='pi')
|
333
|
+
sage: w.get_interact_value() # needs sage.symbolic
|
334
|
+
pi^2
|
335
|
+
"""
|
336
|
+
pass
|
337
|
+
|
338
|
+
|
339
|
+
class SageColorPicker(ColorPicker):
|
340
|
+
"""
|
341
|
+
A color picker widget returning a Sage :class:`Color`.
|
342
|
+
|
343
|
+
EXAMPLES::
|
344
|
+
|
345
|
+
sage: from sage.repl.ipython_kernel.widgets import SageColorPicker
|
346
|
+
sage: SageColorPicker()
|
347
|
+
SageColorPicker(value='black')
|
348
|
+
"""
|
349
|
+
def get_interact_value(self):
|
350
|
+
"""
|
351
|
+
Return a Sage :class:`Color` corresponding to the value of this
|
352
|
+
widget.
|
353
|
+
|
354
|
+
EXAMPLES::
|
355
|
+
|
356
|
+
sage: from sage.repl.ipython_kernel.widgets import SageColorPicker
|
357
|
+
sage: SageColorPicker().get_interact_value() # needs sage.plot
|
358
|
+
RGB color (0.0, 0.0, 0.0)
|
359
|
+
"""
|
360
|
+
return Color(self.value)
|
361
|
+
|
362
|
+
|
363
|
+
class Grid(TransformWidget, HBox, ValueWidget):
|
364
|
+
"""
|
365
|
+
A square grid of widgets whose value is a list of lists of the
|
366
|
+
values of the individual widgets.
|
367
|
+
|
368
|
+
This is usually created using the :func:`input_grid` function.
|
369
|
+
|
370
|
+
EXAMPLES::
|
371
|
+
|
372
|
+
sage: from ipywidgets import Text
|
373
|
+
sage: from sage.repl.ipython_kernel.widgets import Grid
|
374
|
+
sage: w = Grid(2, 2, lambda i,j: Text(value="%s,%s"%(i,j)))
|
375
|
+
sage: w
|
376
|
+
Grid(value=[['0,0', '0,1'], ['1,0', '1,1']],
|
377
|
+
children=(Label(value=''),
|
378
|
+
VBox(children=(Text(value='0,0'), Text(value='1,0'))),
|
379
|
+
VBox(children=(Text(value='0,1'), Text(value='1,1')))))
|
380
|
+
sage: w.get_interact_value()
|
381
|
+
[['0,0', '0,1'], ['1,0', '1,1']]
|
382
|
+
"""
|
383
|
+
value = List()
|
384
|
+
description = Unicode()
|
385
|
+
|
386
|
+
def __init__(self, nrows, ncols, make_widget, description="", transform=None):
|
387
|
+
"""
|
388
|
+
Create a :class:`Grid` widget.
|
389
|
+
|
390
|
+
INPUT:
|
391
|
+
|
392
|
+
- ``nrows``, ``ncols`` -- number of rows and columns in the grid
|
393
|
+
|
394
|
+
- ``make_widget`` -- a function of two arguments ``(i,j)``
|
395
|
+
returning the widget to be placed at position ``(i,j)``
|
396
|
+
|
397
|
+
- ``description`` -- an optional label
|
398
|
+
|
399
|
+
- ``transform`` -- an optional transformation, see :class:`TransformWidget`
|
400
|
+
|
401
|
+
EXAMPLES::
|
402
|
+
|
403
|
+
sage: from sage.repl.ipython_kernel.widgets import Grid, EvalText
|
404
|
+
sage: w = Grid(2, 2, lambda i,j: EvalText(str(j+4*i)), # needs sage.modules
|
405
|
+
....: description="2x2 matrix", transform=matrix); w
|
406
|
+
Grid(value=[[0, 1], [4, 5]],
|
407
|
+
children=(Label(value='2x2 matrix'),
|
408
|
+
VBox(children=(EvalText(value='0'), EvalText(value='4'))),
|
409
|
+
VBox(children=(EvalText(value='1'), EvalText(value='5')))))
|
410
|
+
sage: w.get_interact_value() # needs sage.modules
|
411
|
+
[0 1]
|
412
|
+
[4 5]
|
413
|
+
|
414
|
+
TESTS::
|
415
|
+
|
416
|
+
sage: w = Grid(0, 1, lambda i,j: EvalText())
|
417
|
+
Traceback (most recent call last):
|
418
|
+
...
|
419
|
+
ValueError: Grid requires a positive number of rows and columns
|
420
|
+
"""
|
421
|
+
if nrows < 1 or ncols < 1:
|
422
|
+
raise ValueError("Grid requires a positive number of rows and columns")
|
423
|
+
super().__init__(transform=transform)
|
424
|
+
|
425
|
+
label = Label(description)
|
426
|
+
link((label, "value"), (self, "description"))
|
427
|
+
|
428
|
+
self.cols = []
|
429
|
+
for j in range(ncols):
|
430
|
+
col = VBox()
|
431
|
+
widgets = []
|
432
|
+
for i in range(nrows):
|
433
|
+
w = make_widget(i, j)
|
434
|
+
w.observe(self._update, names='value')
|
435
|
+
widgets.append(w)
|
436
|
+
col.children = widgets
|
437
|
+
self.cols.append(col)
|
438
|
+
self.children = [label] + self.cols
|
439
|
+
self._update()
|
440
|
+
|
441
|
+
def _update(self, *args):
|
442
|
+
"""
|
443
|
+
Compute the ``value`` of the grid.
|
444
|
+
|
445
|
+
Thanks to traitlets magic, this is automatically called
|
446
|
+
whenever one of the child widgets changes.
|
447
|
+
|
448
|
+
EXAMPLES::
|
449
|
+
|
450
|
+
sage: from ipywidgets import Text
|
451
|
+
sage: from sage.repl.ipython_kernel.widgets import Grid
|
452
|
+
sage: w = Grid(2, 2, lambda i,j: Text(value="%s,%s"%(i,j)))
|
453
|
+
sage: w._update()
|
454
|
+
sage: w.value
|
455
|
+
[['0,0', '0,1'], ['1,0', '1,1']]
|
456
|
+
sage: w.cols[0].children[0].value = "abc"
|
457
|
+
sage: w.value
|
458
|
+
[['abc', '0,1'], ['1,0', '1,1']]
|
459
|
+
"""
|
460
|
+
v = [[]]
|
461
|
+
for col in self.cols:
|
462
|
+
for i in range(len(col.children)):
|
463
|
+
if i >= len(v):
|
464
|
+
v.append([])
|
465
|
+
v[i].append(col.children[i].get_interact_value())
|
466
|
+
self.value = v
|