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,318 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-repl
|
2
|
+
r"""
|
3
|
+
IPython Displayhook Formatters
|
4
|
+
|
5
|
+
The classes in this module can be used as IPython displayhook
|
6
|
+
formatters. It has two main features, by default the displayhook
|
7
|
+
contains a new facility for displaying lists of matrices in an easier
|
8
|
+
to read format::
|
9
|
+
|
10
|
+
sage: [identity_matrix(i) for i in range(2, 5)] # needs sage.modules
|
11
|
+
[
|
12
|
+
[1 0 0 0]
|
13
|
+
[1 0 0] [0 1 0 0]
|
14
|
+
[1 0] [0 1 0] [0 0 1 0]
|
15
|
+
[0 1], [0 0 1], [0 0 0 1]
|
16
|
+
]
|
17
|
+
|
18
|
+
This facility uses :meth:`_repr_` (and a simple string) to try do a nice read
|
19
|
+
format (see :meth:`sage.structure.parent.Parent._repr_option` for details).
|
20
|
+
|
21
|
+
With this displayhook there exists an other way for displaying object and more
|
22
|
+
generally, all sage expression as an ASCII art object::
|
23
|
+
|
24
|
+
sage: from sage.repl.interpreter import get_test_shell
|
25
|
+
sage: shell = get_test_shell()
|
26
|
+
sage: shell.run_cell('%display ascii_art')
|
27
|
+
sage: shell.run_cell('integral(x^2/pi^x, x)') # needs sage.symbolic
|
28
|
+
-x / 2 2 \
|
29
|
+
-pi *\x *log (pi) + 2*x*log(pi) + 2/
|
30
|
+
--------------------------------------
|
31
|
+
3
|
32
|
+
log (pi)
|
33
|
+
sage: shell.run_cell("i = var('i')") # needs sage.symbolic
|
34
|
+
sage: shell.run_cell('sum(i*x^i, i, 0, 10)') # needs sage.symbolic
|
35
|
+
10 9 8 7 6 5 4 3 2
|
36
|
+
10*x + 9*x + 8*x + 7*x + 6*x + 5*x + 4*x + 3*x + 2*x + x
|
37
|
+
sage: shell.run_cell('StandardTableaux(4).list()') # needs sage.combinat
|
38
|
+
[
|
39
|
+
[ 1 4 1 3
|
40
|
+
[ 1 3 4 1 2 4 1 2 3 1 3 1 2 2 2
|
41
|
+
[ 1 2 3 4, 2 , 3 , 4 , 2 4, 3 4, 3 , 4 ,
|
42
|
+
<BLANKLINE>
|
43
|
+
1 ]
|
44
|
+
1 2 2 ]
|
45
|
+
3 3 ]
|
46
|
+
4 , 4 ]
|
47
|
+
sage: shell.run_cell('%display default')
|
48
|
+
sage: shell.quit()
|
49
|
+
|
50
|
+
This other facility uses a simple
|
51
|
+
:class:`~sage.typeset.ascii_art.AsciiArt` object (see and
|
52
|
+
:meth:`sage.structure.sage_object.SageObject._ascii_art_`). """
|
53
|
+
|
54
|
+
# ****************************************************************************
|
55
|
+
# Copyright (C) 2014 Volker Braun <vbraun.name@gmail.com>
|
56
|
+
#
|
57
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
58
|
+
# as published by the Free Software Foundation; either version 2 of
|
59
|
+
# the License, or (at your option) any later version.
|
60
|
+
# https://www.gnu.org/licenses/
|
61
|
+
# ****************************************************************************
|
62
|
+
|
63
|
+
from io import StringIO
|
64
|
+
|
65
|
+
from IPython.core.formatters import DisplayFormatter, PlainTextFormatter
|
66
|
+
from IPython.utils.py3compat import unicode_to_str
|
67
|
+
from IPython.core.display import DisplayObject
|
68
|
+
|
69
|
+
from ipywidgets import Widget
|
70
|
+
|
71
|
+
from sage.repl.display.pretty_print import SagePrettyPrinter
|
72
|
+
from sage.misc.lazy_import import lazy_import
|
73
|
+
|
74
|
+
IPYTHON_NATIVE_TYPES = (DisplayObject, Widget)
|
75
|
+
|
76
|
+
PLAIN_TEXT = 'text/plain'
|
77
|
+
TEXT_LATEX = 'text/latex'
|
78
|
+
TEXT_HTML = 'text/html'
|
79
|
+
|
80
|
+
lazy_import('matplotlib.figure', 'Figure')
|
81
|
+
|
82
|
+
|
83
|
+
class SageDisplayFormatter(DisplayFormatter):
|
84
|
+
|
85
|
+
def __init__(self, *args, **kwds):
|
86
|
+
"""
|
87
|
+
This is where the Sage rich objects are translated to IPython.
|
88
|
+
|
89
|
+
INPUT/OUTPUT: see the IPython documentation
|
90
|
+
|
91
|
+
EXAMPLES:
|
92
|
+
|
93
|
+
This is part of how Sage works with the IPython output
|
94
|
+
system. It cannot be used in doctests::
|
95
|
+
|
96
|
+
sage: from sage.repl.display.formatter import SageDisplayFormatter
|
97
|
+
sage: fmt = SageDisplayFormatter()
|
98
|
+
Traceback (most recent call last):
|
99
|
+
...
|
100
|
+
RuntimeError: check failed: current backend is invalid
|
101
|
+
"""
|
102
|
+
super().__init__(*args, **kwds)
|
103
|
+
from sage.repl.rich_output.display_manager import get_display_manager
|
104
|
+
self.dm = get_display_manager()
|
105
|
+
from sage.repl.rich_output.backend_ipython import BackendIPython
|
106
|
+
self.dm.check_backend_class(BackendIPython)
|
107
|
+
|
108
|
+
pt_formatter = self.formatters[PLAIN_TEXT]
|
109
|
+
pt_formatter.observe(self._ipython_float_precision_changed,
|
110
|
+
names=['float_precision'])
|
111
|
+
|
112
|
+
def format(self, obj, include=None, exclude=None):
|
113
|
+
r"""
|
114
|
+
Use the Sage rich output instead of IPython.
|
115
|
+
|
116
|
+
INPUT/OUTPUT: see the IPython documentation
|
117
|
+
|
118
|
+
EXAMPLES::
|
119
|
+
|
120
|
+
sage: [identity_matrix(i) for i in range(3,7)] # needs sage.modules
|
121
|
+
[
|
122
|
+
[1 0 0 0 0 0]
|
123
|
+
[1 0 0 0 0] [0 1 0 0 0 0]
|
124
|
+
[1 0 0 0] [0 1 0 0 0] [0 0 1 0 0 0]
|
125
|
+
[1 0 0] [0 1 0 0] [0 0 1 0 0] [0 0 0 1 0 0]
|
126
|
+
[0 1 0] [0 0 1 0] [0 0 0 1 0] [0 0 0 0 1 0]
|
127
|
+
[0 0 1], [0 0 0 1], [0 0 0 0 1], [0 0 0 0 0 1]
|
128
|
+
]
|
129
|
+
sage: from sage.repl.interpreter import get_test_shell
|
130
|
+
sage: shell = get_test_shell()
|
131
|
+
sage: shell.run_cell('%display ascii_art') # indirect doctest
|
132
|
+
sage: shell.run_cell("i = var('i')") # needs sage.symbolic
|
133
|
+
sage: shell.run_cell('sum(i*x^i, i, 0, 10)') # needs sage.symbolic
|
134
|
+
10 9 8 7 6 5 4 3 2
|
135
|
+
10*x + 9*x + 8*x + 7*x + 6*x + 5*x + 4*x + 3*x + 2*x + x
|
136
|
+
sage: shell.run_cell('%display default')
|
137
|
+
sage: shell.quit()
|
138
|
+
|
139
|
+
TESTS::
|
140
|
+
|
141
|
+
sage: import os
|
142
|
+
sage: import importlib.resources
|
143
|
+
sage: import warnings
|
144
|
+
sage: warnings.filterwarnings('ignore', category=DeprecationWarning,
|
145
|
+
....: message=r'path is deprecated\. Use files\(\) instead\.')
|
146
|
+
sage: from sage.repl.rich_output.backend_ipython import BackendIPython
|
147
|
+
sage: backend = BackendIPython()
|
148
|
+
sage: shell = get_test_shell()
|
149
|
+
sage: backend.install(shell=shell)
|
150
|
+
sage: shell.run_cell('get_ipython().display_formatter')
|
151
|
+
<sage.repl.display.formatter.SageDisplayFormatter object at 0x...>
|
152
|
+
sage: shell.run_cell('from IPython.display import Image')
|
153
|
+
sage: with importlib.resources.path(sage.repl.rich_output, 'example.png') as example_png:
|
154
|
+
....: shell.run_cell('ipython_image = Image("{0}")'.format(example_png))
|
155
|
+
sage: shell.run_cell('ipython_image')
|
156
|
+
<IPython.core.display.Image object>
|
157
|
+
sage: shell.run_cell('get_ipython().display_formatter.format(ipython_image)')
|
158
|
+
({'image/png': ...,
|
159
|
+
'text/plain': '<IPython.core.display.Image object>'},
|
160
|
+
{})
|
161
|
+
|
162
|
+
Test that IPython images and widgets still work even in latex output mode::
|
163
|
+
|
164
|
+
sage: shell.run_cell('%display latex') # indirect doctest
|
165
|
+
sage: shell.run_cell('set(get_ipython().display_formatter.format(ipython_image)[0].keys())'
|
166
|
+
....: ' == set(["text/plain", "image/png"])')
|
167
|
+
True
|
168
|
+
|
169
|
+
sage: shell.run_cell('import ipywidgets')
|
170
|
+
sage: shell.run_cell('slider = ipywidgets.IntSlider()')
|
171
|
+
sage: shell.run_cell('get_ipython().display_formatter.format(slider)')
|
172
|
+
...IntSlider(value=0)..., {})
|
173
|
+
|
174
|
+
sage: shell.run_cell('%display default')
|
175
|
+
sage: shell.quit()
|
176
|
+
|
177
|
+
Test that ``__repr__`` is only called once when generating text output::
|
178
|
+
|
179
|
+
sage: class Repper():
|
180
|
+
....: def __repr__(self):
|
181
|
+
....: print('__repr__ called')
|
182
|
+
....: return 'I am repper'
|
183
|
+
sage: Repper()
|
184
|
+
__repr__ called
|
185
|
+
I am repper
|
186
|
+
"""
|
187
|
+
sage_format, sage_metadata = self.dm.displayhook(obj)
|
188
|
+
assert PLAIN_TEXT in sage_format, 'plain text is always present'
|
189
|
+
|
190
|
+
# use Sage rich output for any except those native to IPython, but only
|
191
|
+
# if it is not plain and dull
|
192
|
+
if (not isinstance(obj, IPYTHON_NATIVE_TYPES) and
|
193
|
+
not set(sage_format.keys()).issubset([PLAIN_TEXT]) and
|
194
|
+
not isinstance(obj, Figure)):
|
195
|
+
return sage_format, sage_metadata
|
196
|
+
|
197
|
+
if self.ipython_display_formatter(obj):
|
198
|
+
# object handled itself, don't proceed
|
199
|
+
return {}, {}
|
200
|
+
|
201
|
+
# try IPython display formatter
|
202
|
+
if exclude is not None:
|
203
|
+
exclude = list(exclude) + [PLAIN_TEXT]
|
204
|
+
else:
|
205
|
+
exclude = [PLAIN_TEXT]
|
206
|
+
ipy_format, ipy_metadata = super().format(obj, include=include, exclude=exclude)
|
207
|
+
if not ipy_format:
|
208
|
+
return sage_format, sage_metadata
|
209
|
+
ipy_format[PLAIN_TEXT] = sage_format[PLAIN_TEXT]
|
210
|
+
if PLAIN_TEXT in sage_metadata:
|
211
|
+
ipy_metadata[PLAIN_TEXT] = sage_metadata[PLAIN_TEXT]
|
212
|
+
return ipy_format, ipy_metadata
|
213
|
+
|
214
|
+
@staticmethod
|
215
|
+
def _ipython_float_precision_changed(change):
|
216
|
+
"""
|
217
|
+
Update the current float precision for the display of matrices in Sage.
|
218
|
+
|
219
|
+
This function is called when the IPython ``%precision`` magic is
|
220
|
+
invoked.
|
221
|
+
|
222
|
+
TESTS::
|
223
|
+
|
224
|
+
sage: from sage.repl.interpreter import get_test_shell
|
225
|
+
sage: shell = get_test_shell()
|
226
|
+
sage: shell.run_cell('%precision 4')
|
227
|
+
'%.4f'
|
228
|
+
sage: shell.run_cell('matrix.options.precision') # indirect doctest # needs sage.modules
|
229
|
+
4
|
230
|
+
sage: shell.run_cell('%precision')
|
231
|
+
'%r'
|
232
|
+
sage: shell.run_cell('matrix.options.precision') # indirect doctest # needs sage.modules
|
233
|
+
None
|
234
|
+
"""
|
235
|
+
try:
|
236
|
+
from sage.matrix.constructor import options
|
237
|
+
except ImportError:
|
238
|
+
pass
|
239
|
+
else:
|
240
|
+
s = change.new
|
241
|
+
if not s:
|
242
|
+
# unset the precision
|
243
|
+
options.precision = None
|
244
|
+
else:
|
245
|
+
try:
|
246
|
+
prec = int(s)
|
247
|
+
if prec >= 0:
|
248
|
+
options.precision = prec
|
249
|
+
# otherwise ignore the change
|
250
|
+
except ValueError:
|
251
|
+
pass
|
252
|
+
|
253
|
+
|
254
|
+
class SagePlainTextFormatter(PlainTextFormatter):
|
255
|
+
|
256
|
+
def __init__(self, *args, **kwds):
|
257
|
+
r"""
|
258
|
+
Improved plain text IPython formatter.
|
259
|
+
|
260
|
+
In particular, it correctly print lists of matrices or other
|
261
|
+
objects (see
|
262
|
+
:meth:`sage.structure.parent.Parent._repr_option`).
|
263
|
+
|
264
|
+
.. warning::
|
265
|
+
|
266
|
+
This IPython formatter is NOT used. You could use it to
|
267
|
+
enable Sage formatting in IPython, but Sage uses its own
|
268
|
+
rich output system that is more flexible and supports
|
269
|
+
different backends.
|
270
|
+
|
271
|
+
INPUT/OUTPUT: see the IPython documentation
|
272
|
+
|
273
|
+
EXAMPLES::
|
274
|
+
|
275
|
+
sage: from sage.repl.interpreter import get_test_shell
|
276
|
+
sage: shell = get_test_shell()
|
277
|
+
sage: shell.display_formatter.formatters['text/plain']
|
278
|
+
<IPython.core.formatters.PlainTextFormatter object at 0x...>
|
279
|
+
sage: shell.quit()
|
280
|
+
"""
|
281
|
+
super().__init__(*args, **kwds)
|
282
|
+
|
283
|
+
def __call__(self, obj):
|
284
|
+
r"""
|
285
|
+
Compute the pretty representation of the object.
|
286
|
+
|
287
|
+
Adapted from ``IPython.core.formatters.PlainTextPrettyPrint``.
|
288
|
+
|
289
|
+
INPUT:
|
290
|
+
|
291
|
+
- ``obj`` -- anything
|
292
|
+
|
293
|
+
OUTPUT: string; the plain text representation
|
294
|
+
|
295
|
+
EXAMPLES::
|
296
|
+
|
297
|
+
sage: from sage.repl.display.formatter import SagePlainTextFormatter
|
298
|
+
sage: fmt = SagePlainTextFormatter()
|
299
|
+
sage: fmt
|
300
|
+
<sage.repl.display.formatter.SagePlainTextFormatter object at 0x...>
|
301
|
+
sage: fmt(2)
|
302
|
+
---- calling ipython formatter ----
|
303
|
+
'2'
|
304
|
+
sage: a = identity_matrix(ZZ, 2) # needs sage.modules
|
305
|
+
sage: fmt([a, a]) # needs sage.modules
|
306
|
+
---- calling ipython formatter ----
|
307
|
+
'[\n[1 0] [1 0]\n[0 1], [0 1]\n]'
|
308
|
+
"""
|
309
|
+
from sage.doctest import DOCTEST_MODE
|
310
|
+
if DOCTEST_MODE:
|
311
|
+
# Just to show that this is never executed in any other doctests in the Sage library
|
312
|
+
print('---- calling ipython formatter ----')
|
313
|
+
stream = StringIO()
|
314
|
+
printer = SagePrettyPrinter(
|
315
|
+
stream, self.max_width, unicode_to_str(self.newline))
|
316
|
+
printer.pretty(obj)
|
317
|
+
printer.flush()
|
318
|
+
return stream.getvalue()
|
@@ -0,0 +1,290 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-repl
|
2
|
+
"""
|
3
|
+
HTML Generator for JSmol
|
4
|
+
|
5
|
+
This is all an evil iframe hack to get JSmol to display 3-d graphics
|
6
|
+
while separating JSmol's j2s machinery from your actual web page.
|
7
|
+
|
8
|
+
There are some caveats for how to load JSmol, in particular it cannot
|
9
|
+
just load its code from a ``file://`` uri. To use a html file
|
10
|
+
generated by this module, you need
|
11
|
+
|
12
|
+
* A web server,
|
13
|
+
|
14
|
+
* The JSmol directory tree must be served by your web server,
|
15
|
+
|
16
|
+
* The output of :meth:`JSMolHtml.inner_html` or
|
17
|
+
:meth:`JSMolHtml.outer_html` must be served by the same web server.
|
18
|
+
|
19
|
+
See https://github.com/phetsims/molecule-polarity/issues/6 for a
|
20
|
+
discussion of loading JSMol.
|
21
|
+
"""
|
22
|
+
|
23
|
+
import io
|
24
|
+
import os
|
25
|
+
import zipfile
|
26
|
+
|
27
|
+
from sage.cpython.string import bytes_to_str
|
28
|
+
from sage.structure.sage_object import SageObject
|
29
|
+
from sage.misc.cachefunc import cached_method
|
30
|
+
|
31
|
+
|
32
|
+
INNER_HTML_TEMPLATE = """
|
33
|
+
<html>
|
34
|
+
<head>
|
35
|
+
<style>
|
36
|
+
* {{
|
37
|
+
margin: 0;
|
38
|
+
padding: 0;
|
39
|
+
overflow: hidden;
|
40
|
+
}}
|
41
|
+
body, html {{
|
42
|
+
height: 100%;
|
43
|
+
width: 100%;
|
44
|
+
}}
|
45
|
+
</style>
|
46
|
+
<script type="text/javascript" src="{path_to_jsmol}/JSmol.min.js"></script>
|
47
|
+
</head>
|
48
|
+
<body>
|
49
|
+
<script type="text/javascript">
|
50
|
+
delete Jmol._tracker; // Prevent JSmol from phoning home.
|
51
|
+
var script = {script};
|
52
|
+
var Info = {{
|
53
|
+
width: '{width}',
|
54
|
+
height: '{height}',
|
55
|
+
debug: false,
|
56
|
+
disableInitialConsole: true, // very slow when used with inline mesh
|
57
|
+
color: '#3131ff',
|
58
|
+
addSelectionOptions: false,
|
59
|
+
use: 'HTML5',
|
60
|
+
j2sPath: '{path_to_jsmol}/j2s',
|
61
|
+
script: script,
|
62
|
+
}};
|
63
|
+
var jmolApplet0 = Jmol.getApplet('jmolApplet0', Info);
|
64
|
+
</script>
|
65
|
+
</body>
|
66
|
+
</html>
|
67
|
+
"""
|
68
|
+
|
69
|
+
|
70
|
+
IFRAME_TEMPLATE = """
|
71
|
+
<iframe srcdoc="{escaped_inner_html}"
|
72
|
+
width="{width}"
|
73
|
+
height="{height}"
|
74
|
+
style="border: 0;">
|
75
|
+
</iframe>
|
76
|
+
"""
|
77
|
+
|
78
|
+
|
79
|
+
OUTER_HTML_TEMPLATE = """
|
80
|
+
<html>
|
81
|
+
<head>
|
82
|
+
<title>JSmol 3D Scene</title>
|
83
|
+
</head>
|
84
|
+
</body>
|
85
|
+
{iframe}
|
86
|
+
</body>
|
87
|
+
</html>
|
88
|
+
""".format(iframe=IFRAME_TEMPLATE)
|
89
|
+
|
90
|
+
|
91
|
+
class JSMolHtml(SageObject):
|
92
|
+
|
93
|
+
def __init__(self, jmol, path_to_jsmol=None, width='100%', height='100%'):
|
94
|
+
"""
|
95
|
+
INPUT:
|
96
|
+
|
97
|
+
- ``jmol`` -- 3-d graphics or
|
98
|
+
:class:`sage.repl.rich_output.output_graphics3d.OutputSceneJmol`
|
99
|
+
instance. The 3-d scene to show.
|
100
|
+
|
101
|
+
- ``path_to_jsmol`` -- string (default:
|
102
|
+
``'/nbextensions/jupyter-jsmol/jsmol'``). The path (relative or absolute)
|
103
|
+
where ``JSmol.min.js`` is served on the web server.
|
104
|
+
|
105
|
+
- ``width`` -- integer or string (default:
|
106
|
+
``'100%'``). The width of the JSmol applet using CSS
|
107
|
+
dimensions.
|
108
|
+
|
109
|
+
- ``height`` -- integer or string (default:
|
110
|
+
``'100%'``). The height of the JSmol applet using CSS
|
111
|
+
dimensions.
|
112
|
+
|
113
|
+
EXAMPLES::
|
114
|
+
|
115
|
+
sage: from sage.repl.display.jsmol_iframe import JSMolHtml
|
116
|
+
sage: JSMolHtml(sphere(), width=500, height=300) # needs sage.plot
|
117
|
+
JSmol Window 500x300
|
118
|
+
"""
|
119
|
+
from sage.repl.rich_output.output_graphics3d import OutputSceneJmol
|
120
|
+
if not isinstance(jmol, OutputSceneJmol):
|
121
|
+
jmol = jmol._rich_repr_jmol()
|
122
|
+
self._jmol = jmol
|
123
|
+
self._zip = zipfile.ZipFile(io.BytesIO(self._jmol.scene_zip.get()))
|
124
|
+
if path_to_jsmol is None:
|
125
|
+
self._path = os.path.join('/', 'nbextensions', 'jupyter-jsmol', 'jsmol')
|
126
|
+
else:
|
127
|
+
self._path = path_to_jsmol
|
128
|
+
self._width = width
|
129
|
+
self._height = height
|
130
|
+
|
131
|
+
@cached_method
|
132
|
+
def script(self):
|
133
|
+
r"""
|
134
|
+
Return the JMol script file.
|
135
|
+
|
136
|
+
This method extracts the Jmol script from the Jmol spt file (a
|
137
|
+
zip archive) and inlines meshes.
|
138
|
+
|
139
|
+
OUTPUT: string
|
140
|
+
|
141
|
+
EXAMPLES::
|
142
|
+
|
143
|
+
sage: from sage.repl.display.jsmol_iframe import JSMolHtml
|
144
|
+
sage: from sage.repl.rich_output.output_graphics3d import OutputSceneJmol
|
145
|
+
sage: jsmol = JSMolHtml(OutputSceneJmol.example(), width=500, height=300)
|
146
|
+
sage: jsmol.script()
|
147
|
+
'data "model list"\n10\nempt...aliasdisplay on;\n'
|
148
|
+
"""
|
149
|
+
script = []
|
150
|
+
with self._zip.open('SCRIPT') as SCRIPT:
|
151
|
+
for line in SCRIPT:
|
152
|
+
if line.startswith(b'pmesh'):
|
153
|
+
command, obj, meshfile = line.split(b' ', 3)
|
154
|
+
assert command == b'pmesh'
|
155
|
+
if meshfile not in [b'dots\n', b'mesh\n']:
|
156
|
+
assert (meshfile.startswith(b'"') and
|
157
|
+
meshfile.endswith(b'"\n'))
|
158
|
+
meshfile = bytes_to_str(meshfile[1:-2]) # strip quotes
|
159
|
+
script += [
|
160
|
+
'pmesh {0} inline "'.format(bytes_to_str(obj)),
|
161
|
+
bytes_to_str(self._zip.open(meshfile).read()),
|
162
|
+
'"\n'
|
163
|
+
]
|
164
|
+
continue
|
165
|
+
script += [bytes_to_str(line)]
|
166
|
+
return ''.join(script)
|
167
|
+
|
168
|
+
def js_script(self):
|
169
|
+
r"""
|
170
|
+
The :meth:`script` as Javascript string.
|
171
|
+
|
172
|
+
Since the many shortcomings of Javascript include multi-line
|
173
|
+
strings, this actually returns Javascript code to reassemble
|
174
|
+
the script from a list of strings.
|
175
|
+
|
176
|
+
OUTPUT:
|
177
|
+
|
178
|
+
String. Javascript code that evaluates to :meth:`script` as
|
179
|
+
Javascript string.
|
180
|
+
|
181
|
+
EXAMPLES::
|
182
|
+
|
183
|
+
sage: from sage.repl.display.jsmol_iframe import JSMolHtml
|
184
|
+
sage: from sage.repl.rich_output.output_graphics3d import OutputSceneJmol
|
185
|
+
sage: jsmol = JSMolHtml(OutputSceneJmol.example(), width=500, height=300)
|
186
|
+
sage: print(jsmol.js_script())
|
187
|
+
[
|
188
|
+
'data "model list"',
|
189
|
+
...
|
190
|
+
'isosurface fullylit; pmesh o* fullylit; set antialiasdisplay on;',
|
191
|
+
].join('\n');
|
192
|
+
"""
|
193
|
+
script = [r"["]
|
194
|
+
for line in self.script().splitlines():
|
195
|
+
script += [r" '{0}',".format(line)]
|
196
|
+
script += [r"].join('\n');"]
|
197
|
+
return '\n'.join(script)
|
198
|
+
|
199
|
+
def _repr_(self):
|
200
|
+
"""
|
201
|
+
Return as string representation.
|
202
|
+
|
203
|
+
OUTPUT: string
|
204
|
+
|
205
|
+
EXAMPLES::
|
206
|
+
|
207
|
+
sage: from sage.repl.display.jsmol_iframe import JSMolHtml
|
208
|
+
sage: from sage.repl.rich_output.output_graphics3d import OutputSceneJmol
|
209
|
+
sage: JSMolHtml(OutputSceneJmol.example(), width=500, height=300)._repr_()
|
210
|
+
'JSmol Window 500x300'
|
211
|
+
"""
|
212
|
+
return 'JSmol Window {0}x{1}'.format(self._width, self._height)
|
213
|
+
|
214
|
+
def inner_html(self):
|
215
|
+
"""
|
216
|
+
Return a HTML document containing a JSmol applet.
|
217
|
+
|
218
|
+
EXAMPLES::
|
219
|
+
|
220
|
+
sage: from sage.repl.display.jsmol_iframe import JSMolHtml
|
221
|
+
sage: from sage.repl.rich_output.output_graphics3d import OutputSceneJmol
|
222
|
+
sage: jmol = JSMolHtml(OutputSceneJmol.example(), width=500, height=300)
|
223
|
+
sage: print(jmol.inner_html())
|
224
|
+
<html>
|
225
|
+
<head>
|
226
|
+
<style>
|
227
|
+
* {
|
228
|
+
margin: 0;
|
229
|
+
padding: 0;
|
230
|
+
...
|
231
|
+
</html>
|
232
|
+
"""
|
233
|
+
return INNER_HTML_TEMPLATE.format(
|
234
|
+
script=self.js_script(),
|
235
|
+
width=self._width,
|
236
|
+
height=self._height,
|
237
|
+
path_to_jsmol=self._path,
|
238
|
+
)
|
239
|
+
|
240
|
+
def iframe(self):
|
241
|
+
"""
|
242
|
+
Return HTML iframe.
|
243
|
+
|
244
|
+
OUTPUT: string
|
245
|
+
|
246
|
+
EXAMPLES::
|
247
|
+
|
248
|
+
sage: from sage.repl.display.jsmol_iframe import JSMolHtml
|
249
|
+
sage: from sage.repl.rich_output.output_graphics3d import OutputSceneJmol
|
250
|
+
sage: jmol = JSMolHtml(OutputSceneJmol.example())
|
251
|
+
sage: print(jmol.iframe())
|
252
|
+
<iframe srcdoc="
|
253
|
+
...
|
254
|
+
</iframe>
|
255
|
+
"""
|
256
|
+
escaped_inner_html = self.inner_html().replace('"', '"')
|
257
|
+
return IFRAME_TEMPLATE.format(width=self._width,
|
258
|
+
height=self._height,
|
259
|
+
escaped_inner_html=escaped_inner_html)
|
260
|
+
|
261
|
+
def outer_html(self):
|
262
|
+
"""
|
263
|
+
Return a HTML document containing an iframe with a JSmol applet.
|
264
|
+
|
265
|
+
OUTPUT: string
|
266
|
+
|
267
|
+
EXAMPLES::
|
268
|
+
|
269
|
+
sage: from sage.repl.display.jsmol_iframe import JSMolHtml
|
270
|
+
sage: from sage.repl.rich_output.output_graphics3d import OutputSceneJmol
|
271
|
+
sage: jmol = JSMolHtml(OutputSceneJmol.example(), width=500, height=300)
|
272
|
+
sage: print(jmol.outer_html())
|
273
|
+
<html>
|
274
|
+
<head>
|
275
|
+
<title>JSmol 3D Scene</title>
|
276
|
+
</head>
|
277
|
+
</body>
|
278
|
+
<BLANKLINE>
|
279
|
+
<iframe srcdoc="
|
280
|
+
...
|
281
|
+
</html>
|
282
|
+
"""
|
283
|
+
escaped_inner_html = self.inner_html().replace('"', '"')
|
284
|
+
outer = OUTER_HTML_TEMPLATE.format(
|
285
|
+
script=self.js_script(),
|
286
|
+
width=self._width,
|
287
|
+
height=self._height,
|
288
|
+
escaped_inner_html=escaped_inner_html,
|
289
|
+
)
|
290
|
+
return outer
|