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,829 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-repl
|
2
|
+
r"""
|
3
|
+
Display Manager
|
4
|
+
|
5
|
+
This is the heart of the rich output system, the display manager
|
6
|
+
arbitrates between
|
7
|
+
|
8
|
+
* Backend capabilities: what can be displayed
|
9
|
+
|
10
|
+
* Backend preferences: what gives good quality on the backend
|
11
|
+
|
12
|
+
* Sage capabilities: every Sage object can only generate certain
|
13
|
+
representations, and
|
14
|
+
|
15
|
+
* User preferences: typeset vs. plain text vs. ascii art, etc.
|
16
|
+
|
17
|
+
The display manager is a singleton class, Sage always has exactly one
|
18
|
+
instance of it. Use :func:`get_display_manager` to obtain it.
|
19
|
+
|
20
|
+
EXAMPLES::
|
21
|
+
|
22
|
+
sage: from sage.repl.rich_output import get_display_manager
|
23
|
+
sage: dm = get_display_manager(); dm
|
24
|
+
The Sage display manager using the doctest backend
|
25
|
+
"""
|
26
|
+
|
27
|
+
# ****************************************************************************
|
28
|
+
# Copyright (C) 2015 Volker Braun <vbraun.name@gmail.com>
|
29
|
+
#
|
30
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
31
|
+
# as published by the Free Software Foundation; either version 2 of
|
32
|
+
# the License, or (at your option) any later version.
|
33
|
+
# https://www.gnu.org/licenses/
|
34
|
+
# ****************************************************************************
|
35
|
+
|
36
|
+
|
37
|
+
import warnings
|
38
|
+
|
39
|
+
from sage.structure.sage_object import SageObject
|
40
|
+
from sage.repl.rich_output.output_basic import (
|
41
|
+
OutputPlainText, OutputAsciiArt, OutputUnicodeArt, OutputLatex,
|
42
|
+
)
|
43
|
+
from sage.repl.rich_output.output_browser import (
|
44
|
+
OutputHtml,
|
45
|
+
)
|
46
|
+
from sage.repl.rich_output.preferences import DisplayPreferences
|
47
|
+
|
48
|
+
|
49
|
+
class DisplayException(Exception):
|
50
|
+
"""
|
51
|
+
Base exception for all rich output-related exceptions.
|
52
|
+
|
53
|
+
EXAMPLES::
|
54
|
+
|
55
|
+
sage: from sage.repl.rich_output.display_manager import DisplayException
|
56
|
+
sage: raise DisplayException('foo')
|
57
|
+
Traceback (most recent call last):
|
58
|
+
...
|
59
|
+
DisplayException: foo
|
60
|
+
"""
|
61
|
+
pass
|
62
|
+
|
63
|
+
|
64
|
+
class OutputTypeException(DisplayException):
|
65
|
+
"""
|
66
|
+
Wrong Output container.
|
67
|
+
|
68
|
+
The output containers are the subclasses of
|
69
|
+
:class:`~sage.repl.rich_output.output_basic.OutputBase` that
|
70
|
+
contain the entire output. The display backends must create output
|
71
|
+
containers of a suitable type depending on the displayed Python
|
72
|
+
object. This exception indicates that there is a mistake in the
|
73
|
+
backend and it returned the wrong type of output container.
|
74
|
+
|
75
|
+
EXAMPLES::
|
76
|
+
|
77
|
+
sage: from sage.repl.rich_output.display_manager import OutputTypeException
|
78
|
+
sage: raise OutputTypeException('foo')
|
79
|
+
Traceback (most recent call last):
|
80
|
+
...
|
81
|
+
OutputTypeException: foo
|
82
|
+
"""
|
83
|
+
pass
|
84
|
+
|
85
|
+
|
86
|
+
class RichReprWarning(UserWarning):
|
87
|
+
"""
|
88
|
+
Warning that is throws if a call to ``_rich_repr_`` fails.
|
89
|
+
|
90
|
+
If an object implements ``_rich_repr_`` then it must return a
|
91
|
+
value, possibly ``None`` to indicate that no rich output can be
|
92
|
+
generated. But it may not raise an exception as it is very
|
93
|
+
confusing for the user if the displayhook fails.
|
94
|
+
|
95
|
+
EXAMPLES::
|
96
|
+
|
97
|
+
sage: from sage.repl.rich_output.display_manager import RichReprWarning
|
98
|
+
sage: raise RichReprWarning('foo')
|
99
|
+
Traceback (most recent call last):
|
100
|
+
...
|
101
|
+
RichReprWarning: foo
|
102
|
+
"""
|
103
|
+
pass
|
104
|
+
|
105
|
+
|
106
|
+
class restricted_output:
|
107
|
+
|
108
|
+
def __init__(self, display_manager, output_classes):
|
109
|
+
"""
|
110
|
+
Context manager to temporarily restrict the accepted output types.
|
111
|
+
|
112
|
+
In the context, the output is restricted to the output
|
113
|
+
container types listed in ``output_classes``. Additionally,
|
114
|
+
display preferences are changed not to show graphics.
|
115
|
+
|
116
|
+
INPUT:
|
117
|
+
|
118
|
+
- ``display_manager`` -- the display manager
|
119
|
+
|
120
|
+
- ``output_classes`` -- iterable of output container types
|
121
|
+
|
122
|
+
EXAMPLES::
|
123
|
+
|
124
|
+
sage: from sage.repl.rich_output.display_manager import (
|
125
|
+
....: get_display_manager, restricted_output)
|
126
|
+
sage: dm = get_display_manager()
|
127
|
+
sage: restricted_output(dm, [dm.types.OutputPlainText])
|
128
|
+
<sage.repl.rich_output.display_manager.restricted_output object at 0x...>
|
129
|
+
"""
|
130
|
+
self._display_manager = display_manager
|
131
|
+
self._output_classes = frozenset(output_classes)
|
132
|
+
|
133
|
+
def __enter__(self):
|
134
|
+
"""
|
135
|
+
Enter the restricted output context.
|
136
|
+
|
137
|
+
EXAMPLES::
|
138
|
+
|
139
|
+
sage: from sage.repl.rich_output.display_manager import (
|
140
|
+
....: get_display_manager, restricted_output)
|
141
|
+
sage: dm = get_display_manager()
|
142
|
+
sage: len(dm.supported_output()) > 1
|
143
|
+
True
|
144
|
+
sage: with restricted_output(dm, [dm.types.OutputPlainText]):
|
145
|
+
....: dm.supported_output()
|
146
|
+
frozenset({<class 'sage.repl.rich_output.output_basic.OutputPlainText'>})
|
147
|
+
|
148
|
+
sage: dm.preferences.supplemental_plot
|
149
|
+
'never'
|
150
|
+
sage: dm.preferences.supplemental_plot = 'always'
|
151
|
+
sage: with restricted_output(dm, [dm.types.OutputPlainText]):
|
152
|
+
....: dm.preferences
|
153
|
+
Display preferences:
|
154
|
+
* align_latex is not specified
|
155
|
+
* graphics = disable
|
156
|
+
* supplemental_plot = never
|
157
|
+
* text is not specified
|
158
|
+
sage: dm.preferences.supplemental_plot = 'never'
|
159
|
+
"""
|
160
|
+
dm = self._display_manager
|
161
|
+
self._original = dm._supported_output
|
162
|
+
dm._supported_output = self._output_classes
|
163
|
+
self._original_prefs = DisplayPreferences(dm.preferences)
|
164
|
+
dm.preferences.graphics = 'disable'
|
165
|
+
dm.preferences.supplemental_plot = 'never'
|
166
|
+
|
167
|
+
def __exit__(self, exception_type, value, traceback):
|
168
|
+
"""
|
169
|
+
Exit the restricted output context.
|
170
|
+
|
171
|
+
EXAMPLES::
|
172
|
+
|
173
|
+
sage: from sage.repl.rich_output.display_manager import (
|
174
|
+
....: get_display_manager, restricted_output)
|
175
|
+
sage: dm = get_display_manager()
|
176
|
+
sage: with restricted_output(dm, [dm.types.OutputPlainText]):
|
177
|
+
....: assert len(dm.supported_output()) == 1
|
178
|
+
sage: assert len(dm.supported_output()) > 1
|
179
|
+
"""
|
180
|
+
dm = self._display_manager
|
181
|
+
dm._supported_output = self._original
|
182
|
+
dm.preferences.graphics = self._original_prefs.graphics
|
183
|
+
dm.preferences.supplemental_plot = self._original_prefs.supplemental_plot
|
184
|
+
|
185
|
+
|
186
|
+
class DisplayManager(SageObject):
|
187
|
+
|
188
|
+
_instance = None
|
189
|
+
|
190
|
+
def __init__(self):
|
191
|
+
"""
|
192
|
+
The Display Manager.
|
193
|
+
|
194
|
+
Used to decide what kind of rich output is best.
|
195
|
+
|
196
|
+
EXAMPLES::
|
197
|
+
|
198
|
+
sage: from sage.repl.rich_output import get_display_manager
|
199
|
+
sage: get_display_manager()
|
200
|
+
The Sage display manager using the doctest backend
|
201
|
+
"""
|
202
|
+
assert DisplayManager._instance is None
|
203
|
+
DisplayManager._instance = self
|
204
|
+
from sage.repl.rich_output.backend_base import BackendSimple
|
205
|
+
self.switch_backend(BackendSimple())
|
206
|
+
|
207
|
+
@classmethod
|
208
|
+
def get_instance(cls):
|
209
|
+
"""
|
210
|
+
Get the singleton instance.
|
211
|
+
|
212
|
+
This class method is equivalent to
|
213
|
+
:func:`get_display_manager`.
|
214
|
+
|
215
|
+
OUTPUT: the display manager singleton
|
216
|
+
|
217
|
+
EXAMPLES::
|
218
|
+
|
219
|
+
sage: from sage.repl.rich_output.display_manager import DisplayManager
|
220
|
+
sage: DisplayManager.get_instance()
|
221
|
+
The Sage display manager using the doctest backend
|
222
|
+
"""
|
223
|
+
if cls._instance is not None:
|
224
|
+
return cls._instance
|
225
|
+
else:
|
226
|
+
return cls()
|
227
|
+
|
228
|
+
def _repr_(self):
|
229
|
+
"""
|
230
|
+
Return a string representation.
|
231
|
+
|
232
|
+
OUTPUT: string
|
233
|
+
|
234
|
+
EXAMPLES::
|
235
|
+
|
236
|
+
sage: from sage.repl.rich_output import get_display_manager
|
237
|
+
sage: get_display_manager()
|
238
|
+
The Sage display manager using the doctest backend
|
239
|
+
"""
|
240
|
+
s = 'The Sage display manager using the {0} backend'.format(self._backend)
|
241
|
+
return s
|
242
|
+
|
243
|
+
@property
|
244
|
+
def types(self):
|
245
|
+
"""
|
246
|
+
Catalog of all output container types.
|
247
|
+
|
248
|
+
Note that every output type must be registered in
|
249
|
+
:mod:`sage.repl.rich_output.output_catalog`.
|
250
|
+
|
251
|
+
OUTPUT:
|
252
|
+
|
253
|
+
Returns the :mod:`sage.repl.rich_output.output_catalog`
|
254
|
+
module.
|
255
|
+
|
256
|
+
EXAMPLES::
|
257
|
+
|
258
|
+
sage: from sage.repl.rich_output import get_display_manager
|
259
|
+
sage: dm = get_display_manager()
|
260
|
+
sage: dm.types.OutputPlainText
|
261
|
+
<class 'sage.repl.rich_output.output_basic.OutputPlainText'>
|
262
|
+
"""
|
263
|
+
import sage.repl.rich_output.output_catalog
|
264
|
+
return sage.repl.rich_output.output_catalog
|
265
|
+
|
266
|
+
def switch_backend(self, backend, **kwds):
|
267
|
+
"""
|
268
|
+
Switch to a new backend.
|
269
|
+
|
270
|
+
INPUT:
|
271
|
+
|
272
|
+
- ``backend`` -- instance of
|
273
|
+
:class:`~sage.repl.rich_output.backend_base.BackendBase`
|
274
|
+
|
275
|
+
- ``kwds`` -- optional keyword arguments that are passed on to
|
276
|
+
the :meth:`~sage.repl.rich_output.backend_base.BackendBase.install`
|
277
|
+
method
|
278
|
+
|
279
|
+
OUTPUT: the previous backend
|
280
|
+
|
281
|
+
EXAMPLES::
|
282
|
+
|
283
|
+
sage: from sage.repl.rich_output.backend_base import BackendSimple
|
284
|
+
sage: simple = BackendSimple()
|
285
|
+
sage: from sage.repl.rich_output import get_display_manager
|
286
|
+
sage: dm = get_display_manager(); dm
|
287
|
+
The Sage display manager using the doctest backend
|
288
|
+
|
289
|
+
sage: previous = dm.switch_backend(simple)
|
290
|
+
sage: dm
|
291
|
+
The Sage display manager using the simple backend
|
292
|
+
|
293
|
+
Restore the doctest backend::
|
294
|
+
|
295
|
+
sage: dm.switch_backend(previous) is simple
|
296
|
+
True
|
297
|
+
"""
|
298
|
+
from sage.repl.rich_output.backend_base import BackendBase
|
299
|
+
if not isinstance(backend, BackendBase):
|
300
|
+
raise ValueError('backend must be instance of BackendBase class')
|
301
|
+
supported = backend.supported_output()
|
302
|
+
if not any(issubclass(out, OutputPlainText) for out in supported):
|
303
|
+
raise ValueError('every backend must support plain text')
|
304
|
+
try:
|
305
|
+
self._backend.uninstall()
|
306
|
+
except AttributeError:
|
307
|
+
pass # first time we switch
|
308
|
+
# clear caches
|
309
|
+
self._output_promotions = dict()
|
310
|
+
self._supported_output = frozenset(
|
311
|
+
map(self._demote_output_class, backend.supported_output()))
|
312
|
+
# install new backend
|
313
|
+
try:
|
314
|
+
old_backend = self._backend
|
315
|
+
except AttributeError:
|
316
|
+
old_backend = None
|
317
|
+
self._backend = backend
|
318
|
+
self._backend.install(**kwds)
|
319
|
+
self._preferences = DisplayPreferences(self._backend.default_preferences())
|
320
|
+
return old_backend
|
321
|
+
|
322
|
+
@property
|
323
|
+
def preferences(self):
|
324
|
+
"""
|
325
|
+
Return the preferences.
|
326
|
+
|
327
|
+
OUTPUT:
|
328
|
+
|
329
|
+
The display preferences as instance of
|
330
|
+
:class:`~sage.repl.rich_output.preferences.DisplayPreferences`.
|
331
|
+
|
332
|
+
EXAMPLES::
|
333
|
+
|
334
|
+
sage: from sage.repl.rich_output import get_display_manager
|
335
|
+
sage: dm = get_display_manager()
|
336
|
+
sage: dm.preferences
|
337
|
+
Display preferences:
|
338
|
+
* align_latex is not specified
|
339
|
+
* graphics is not specified
|
340
|
+
* supplemental_plot = never
|
341
|
+
* text is not specified
|
342
|
+
"""
|
343
|
+
return self._preferences
|
344
|
+
|
345
|
+
def is_in_terminal(self):
|
346
|
+
"""
|
347
|
+
Test whether the UI is meant to run in a terminal.
|
348
|
+
|
349
|
+
When this method returns ``True``, you can assume that it is
|
350
|
+
possible to use ``raw_input`` or launch external programs that
|
351
|
+
take over the input.
|
352
|
+
|
353
|
+
Otherwise, you should assume that the backend runs remotely or
|
354
|
+
in a pty controlled by another program. Then you should not
|
355
|
+
launch external programs with a (text or graphical) UI.
|
356
|
+
|
357
|
+
This is used to enable/disable interpreter consoles.
|
358
|
+
|
359
|
+
OUTPUT:
|
360
|
+
|
361
|
+
Boolean.
|
362
|
+
"""
|
363
|
+
return self._backend.is_in_terminal()
|
364
|
+
|
365
|
+
def check_backend_class(self, backend_class):
|
366
|
+
"""
|
367
|
+
Check that the current backend is an instance of
|
368
|
+
``backend_class``.
|
369
|
+
|
370
|
+
This is, for example, used by the Sage IPython display
|
371
|
+
formatter to ensure that the IPython backend is in use.
|
372
|
+
|
373
|
+
INPUT:
|
374
|
+
|
375
|
+
- ``backend_class`` -- type of a backend class
|
376
|
+
|
377
|
+
OUTPUT:
|
378
|
+
|
379
|
+
This method returns nothing. A :exc:`RuntimeError` is raised if
|
380
|
+
``backend_class`` is not the type of the current backend.
|
381
|
+
|
382
|
+
EXAMPLES::
|
383
|
+
|
384
|
+
sage: from sage.repl.rich_output.backend_base import BackendSimple
|
385
|
+
sage: from sage.repl.rich_output import get_display_manager
|
386
|
+
sage: dm = get_display_manager()
|
387
|
+
sage: dm.check_backend_class(BackendSimple)
|
388
|
+
Traceback (most recent call last):
|
389
|
+
...
|
390
|
+
RuntimeError: check failed: current backend is invalid
|
391
|
+
"""
|
392
|
+
if not isinstance(self._backend, backend_class):
|
393
|
+
raise RuntimeError('check failed: current backend is invalid')
|
394
|
+
|
395
|
+
def _demote_output_class(self, output_class):
|
396
|
+
"""
|
397
|
+
Helper for :meth:`switch_backend`.
|
398
|
+
|
399
|
+
INPUT:
|
400
|
+
|
401
|
+
- ``output_class`` -- a possibly derived class from one of the
|
402
|
+
output container classes in :meth:`types`
|
403
|
+
|
404
|
+
OUTPUT: the underlying container class that it was derived from
|
405
|
+
|
406
|
+
EXAMPLES::
|
407
|
+
|
408
|
+
sage: from sage.repl.rich_output import get_display_manager
|
409
|
+
sage: dm = get_display_manager()
|
410
|
+
sage: dm._demote_output_class(dm.types.OutputPlainText)
|
411
|
+
<class 'sage.repl.rich_output.output_basic.OutputPlainText'>
|
412
|
+
"""
|
413
|
+
from sage.repl.rich_output.output_basic import OutputBase
|
414
|
+
if not issubclass(output_class, OutputBase):
|
415
|
+
raise OutputTypeException(
|
416
|
+
'invalid output container type: {0} is not subclass of OutputBase'
|
417
|
+
.format(output_class))
|
418
|
+
result = None
|
419
|
+
for type_name in dir(self.types):
|
420
|
+
if type_name.startswith('_'):
|
421
|
+
continue
|
422
|
+
tp = getattr(self.types, type_name)
|
423
|
+
if not issubclass(tp, OutputBase):
|
424
|
+
continue
|
425
|
+
if issubclass(output_class, tp):
|
426
|
+
if result is not None:
|
427
|
+
raise OutputTypeException(
|
428
|
+
'{0} inherits from multiple output classes'
|
429
|
+
.format(output_class))
|
430
|
+
else:
|
431
|
+
self._output_promotions[tp] = output_class
|
432
|
+
result = tp
|
433
|
+
if result is None:
|
434
|
+
raise OutputTypeException(
|
435
|
+
'{0} does not inherit from any known output class'
|
436
|
+
.format(output_class))
|
437
|
+
return result
|
438
|
+
|
439
|
+
def _promote_output(self, output):
|
440
|
+
"""
|
441
|
+
Promote output container to a backend-specific subclass.
|
442
|
+
|
443
|
+
INPUT:
|
444
|
+
|
445
|
+
- ``output`` -- instance of a subclass of
|
446
|
+
:class:`~sage.repl.rich_output.output_basic.OutputBase`. Backend-agnostic
|
447
|
+
output container.
|
448
|
+
|
449
|
+
OUTPUT:
|
450
|
+
|
451
|
+
If the backend returned a subclass of the type of ``output``:
|
452
|
+
promote the class to the subclass and return it. Otherwise,
|
453
|
+
the unchanged output is returned.
|
454
|
+
|
455
|
+
EXAMPLES::
|
456
|
+
|
457
|
+
sage: from sage.repl.rich_output import get_display_manager
|
458
|
+
sage: dm = get_display_manager()
|
459
|
+
sage: out = dm._promote_output(dm.types.OutputPlainText('test'))
|
460
|
+
sage: type(out)
|
461
|
+
<class 'sage.repl.rich_output.output_basic.OutputPlainText'>
|
462
|
+
"""
|
463
|
+
try:
|
464
|
+
specialized_class = self._output_promotions[type(output)]
|
465
|
+
except KeyError:
|
466
|
+
return output
|
467
|
+
output.__class__ = specialized_class
|
468
|
+
return output
|
469
|
+
|
470
|
+
def _preferred_text_formatter(self, obj, plain_text=None, **kwds):
|
471
|
+
r"""
|
472
|
+
Return the preferred textual representation.
|
473
|
+
|
474
|
+
INPUT:
|
475
|
+
|
476
|
+
- ``obj`` -- anything; the objects to format
|
477
|
+
|
478
|
+
- ``plain_text`` -- ``None`` (default) or string. The plain
|
479
|
+
text representation. If specified, this will be used for
|
480
|
+
plain text output.
|
481
|
+
|
482
|
+
OUTPUT:
|
483
|
+
|
484
|
+
One of
|
485
|
+
:class:`~sage.repl.rich_output.output_basic.OutputPlainText`,
|
486
|
+
:class:`~sage.repl.rich_output.output_basic.OutputAsciiArt`,
|
487
|
+
:class:`~sage.repl.rich_output.output_basic.OutputUnicodeArt`,
|
488
|
+
or
|
489
|
+
:class:`~sage.repl.rich_output.output_basic.OutputLatex`
|
490
|
+
containing the preferred textual representation of ``obj``
|
491
|
+
supported by the backend.
|
492
|
+
|
493
|
+
EXAMPLES::
|
494
|
+
|
495
|
+
sage: from sage.repl.rich_output import get_display_manager
|
496
|
+
sage: dm = get_display_manager()
|
497
|
+
sage: dm.preferences.text is None
|
498
|
+
True
|
499
|
+
sage: dm._preferred_text_formatter([1/42])
|
500
|
+
OutputPlainText container
|
501
|
+
|
502
|
+
sage: dm.preferences.text = 'plain'
|
503
|
+
sage: dm._preferred_text_formatter([1/42])
|
504
|
+
OutputPlainText container
|
505
|
+
|
506
|
+
sage: dm.preferences.text = 'ascii_art'
|
507
|
+
sage: dm._preferred_text_formatter([1/42])
|
508
|
+
OutputAsciiArt container
|
509
|
+
|
510
|
+
sage: dm.preferences.text = 'unicode_art'
|
511
|
+
sage: dm._preferred_text_formatter([1/42])
|
512
|
+
OutputUnicodeArt container
|
513
|
+
|
514
|
+
sage: dm.preferences.text = 'latex'
|
515
|
+
sage: dm._preferred_text_formatter([1/42]) # doctest backend does not support html
|
516
|
+
OutputPlainText container
|
517
|
+
|
518
|
+
sage: del dm.preferences.text # reset to default
|
519
|
+
"""
|
520
|
+
want = self.preferences.text
|
521
|
+
supported = self._backend.supported_output()
|
522
|
+
if want == 'ascii_art' and OutputAsciiArt in supported:
|
523
|
+
out = self._backend.ascii_art_formatter(obj, **kwds)
|
524
|
+
if type(out) is not OutputAsciiArt:
|
525
|
+
raise OutputTypeException('backend returned wrong output type, require AsciiArt')
|
526
|
+
return out
|
527
|
+
if want == 'unicode_art' and OutputUnicodeArt in supported:
|
528
|
+
out = self._backend.unicode_art_formatter(obj, **kwds)
|
529
|
+
if type(out) is not OutputUnicodeArt:
|
530
|
+
raise OutputTypeException('backend returned wrong output type, require UnicodeArt')
|
531
|
+
return out
|
532
|
+
if want == 'latex' and OutputHtml in supported:
|
533
|
+
out = self._backend.latex_formatter(obj, **kwds)
|
534
|
+
if type(out) is not OutputHtml:
|
535
|
+
raise OutputTypeException('backend returned wrong output type, require Html')
|
536
|
+
return out
|
537
|
+
if plain_text is not None:
|
538
|
+
if type(plain_text) is not OutputPlainText:
|
539
|
+
raise OutputTypeException('backend returned wrong output type, require PlainText')
|
540
|
+
return plain_text
|
541
|
+
out = self._backend.plain_text_formatter(obj, **kwds)
|
542
|
+
if type(out) is not OutputPlainText:
|
543
|
+
raise OutputTypeException('backend returned wrong output type, require PlainText')
|
544
|
+
return out
|
545
|
+
|
546
|
+
def _call_rich_repr(self, obj, rich_repr_kwds):
|
547
|
+
"""
|
548
|
+
Call the ``_rich_repr_`` method.
|
549
|
+
|
550
|
+
This method calls ``obj._rich_repr_``. If this raises an
|
551
|
+
exception, it is caught and a suitable warning is displayed.
|
552
|
+
|
553
|
+
INPUT:
|
554
|
+
|
555
|
+
- ``obj`` -- anything
|
556
|
+
|
557
|
+
- ``rich_repr_kwds`` -- dictionary; optional keyword arguments
|
558
|
+
that are passed through to ``obj._rich_repr_``
|
559
|
+
|
560
|
+
OUTPUT:
|
561
|
+
|
562
|
+
Whatever ``_rich_repr_`` returned. If it raises an exception,
|
563
|
+
then a :class:`DisplayFormatterWarning` is displayed and
|
564
|
+
``None`` is returned.
|
565
|
+
|
566
|
+
EXAMPLES::
|
567
|
+
|
568
|
+
sage: class Foo(SageObject):
|
569
|
+
....: def _rich_repr_(self, display_manager, **kwds):
|
570
|
+
....: raise ValueError('reason')
|
571
|
+
|
572
|
+
sage: from sage.repl.rich_output import get_display_manager
|
573
|
+
sage: dm = get_display_manager()
|
574
|
+
sage: dm._call_rich_repr(Foo(), {})
|
575
|
+
doctest:...: ...RichReprWarning: Exception in _rich_repr_ while displaying object: reason
|
576
|
+
"""
|
577
|
+
if rich_repr_kwds:
|
578
|
+
# do not ignore errors from invalid options
|
579
|
+
return obj._rich_repr_(self, **rich_repr_kwds)
|
580
|
+
try:
|
581
|
+
return obj._rich_repr_(self)
|
582
|
+
except NotImplementedError:
|
583
|
+
# don't warn on NotImplementedErrors
|
584
|
+
return None
|
585
|
+
except Exception as e:
|
586
|
+
warnings.warn(
|
587
|
+
'Exception in _rich_repr_ while displaying object: {0}'.format(e),
|
588
|
+
RichReprWarning,
|
589
|
+
)
|
590
|
+
|
591
|
+
def _rich_output_formatter(self, obj, rich_repr_kwds):
|
592
|
+
"""
|
593
|
+
Generate appropriate rich output containers.
|
594
|
+
|
595
|
+
INPUT:
|
596
|
+
|
597
|
+
- ``obj`` -- anything
|
598
|
+
|
599
|
+
- ``rich_repr_kwds`` -- dictionary; optional keyword arguments
|
600
|
+
that are passed through to ``obj._rich_repr_``
|
601
|
+
|
602
|
+
OUTPUT:
|
603
|
+
|
604
|
+
A pair of rich output containers. The first is plain text,
|
605
|
+
that is, an instance of
|
606
|
+
:class:`~sage.repl.rich_output.output_basic.OutputPlainText`. The
|
607
|
+
second is the best rich output available, subject to the
|
608
|
+
constraints of the backend.
|
609
|
+
|
610
|
+
EXAMPLES::
|
611
|
+
|
612
|
+
sage: from sage.repl.rich_output import get_display_manager
|
613
|
+
sage: dm = get_display_manager()
|
614
|
+
sage: dm._rich_output_formatter(1/2, dict())
|
615
|
+
(OutputPlainText container, OutputPlainText container)
|
616
|
+
"""
|
617
|
+
rich_output = None
|
618
|
+
plain_text = None
|
619
|
+
has_rich_repr = isinstance(obj, SageObject) and hasattr(obj, '_rich_repr_')
|
620
|
+
if has_rich_repr:
|
621
|
+
rich_output = self._call_rich_repr(obj, rich_repr_kwds)
|
622
|
+
if isinstance(rich_output, OutputPlainText):
|
623
|
+
plain_text = rich_output
|
624
|
+
elif has_rich_repr:
|
625
|
+
with restricted_output(self, [OutputPlainText]):
|
626
|
+
plain_text = self._call_rich_repr(obj, rich_repr_kwds)
|
627
|
+
if plain_text is None:
|
628
|
+
plain_text = self._backend.plain_text_formatter(obj, **rich_repr_kwds)
|
629
|
+
if rich_output is None:
|
630
|
+
rich_output = self._preferred_text_formatter(
|
631
|
+
obj, plain_text=plain_text, **rich_repr_kwds)
|
632
|
+
# promote output container types to backend-specific containers
|
633
|
+
plain_text = self._promote_output(plain_text)
|
634
|
+
rich_output = self._promote_output(rich_output)
|
635
|
+
# check that the output container types are valid for the backend
|
636
|
+
supported = self._backend.supported_output()
|
637
|
+
if type(plain_text) not in supported:
|
638
|
+
raise OutputTypeException(
|
639
|
+
'text output container not supported: {0}'.format(type(plain_text)))
|
640
|
+
if type(rich_output) not in supported:
|
641
|
+
raise OutputTypeException(
|
642
|
+
'output container not supported: {0}'.format(type(rich_output)))
|
643
|
+
return plain_text, rich_output
|
644
|
+
|
645
|
+
def graphics_from_save(self, save_function, save_kwds,
|
646
|
+
file_extension, output_container,
|
647
|
+
figsize=None, dpi=None):
|
648
|
+
r"""
|
649
|
+
Helper to construct graphics.
|
650
|
+
|
651
|
+
This method can be used to simplify the implementation of a
|
652
|
+
``_rich_repr_`` method of a graphics object if there is
|
653
|
+
already a function to save graphics to a file.
|
654
|
+
|
655
|
+
INPUT:
|
656
|
+
|
657
|
+
- ``save_function`` -- callable that can save graphics to a file
|
658
|
+
and accepts options like :meth:`sage.plot.graphics.Graphics.save`
|
659
|
+
|
660
|
+
- ``save_kwds`` -- dictionary; keyword arguments that are
|
661
|
+
passed to the save function
|
662
|
+
|
663
|
+
- ``file_extension`` -- string starting with ``'.'``; the file
|
664
|
+
extension of the graphics file
|
665
|
+
|
666
|
+
- ``output_container`` -- subclass of
|
667
|
+
:class:`sage.repl.rich_output.output_basic.OutputBase`. The
|
668
|
+
output container to use. Must be one of the types in
|
669
|
+
:meth:`supported_output`.
|
670
|
+
|
671
|
+
- ``figsize`` -- pair of integers (optional). The desired graphics
|
672
|
+
size in pixels. Suggested, but need not be respected by the
|
673
|
+
output.
|
674
|
+
|
675
|
+
- ``dpi`` -- integer (optional). The desired resolution in dots
|
676
|
+
per inch. Suggested, but need not be respected by the output.
|
677
|
+
|
678
|
+
OUTPUT: an instance of ``output_container``
|
679
|
+
|
680
|
+
EXAMPLES::
|
681
|
+
|
682
|
+
sage: # needs sage.plot sage.symbolic
|
683
|
+
sage: from sage.repl.rich_output import get_display_manager
|
684
|
+
sage: dm = get_display_manager()
|
685
|
+
sage: plt = plot(sin)
|
686
|
+
sage: out = dm.graphics_from_save(plt.save, dict(), '.png',
|
687
|
+
....: dm.types.OutputImagePng)
|
688
|
+
sage: out
|
689
|
+
OutputImagePng container
|
690
|
+
sage: out.png.get().startswith(b'\x89PNG')
|
691
|
+
True
|
692
|
+
sage: out.png.filename() # random
|
693
|
+
'/home/user/.sage/temp/localhost.localdomain/23903/tmp_pu5woK.png'
|
694
|
+
"""
|
695
|
+
import os
|
696
|
+
if not file_extension.startswith(os.path.extsep):
|
697
|
+
raise ValueError('file_extension must start with a period')
|
698
|
+
if output_container not in self.supported_output():
|
699
|
+
raise OutputTypeException('output_container is not supported by backend')
|
700
|
+
from sage.misc.temporary_file import tmp_filename
|
701
|
+
filename = tmp_filename(ext=file_extension)
|
702
|
+
# Call the save_function with the right arguments
|
703
|
+
kwds = dict(save_kwds)
|
704
|
+
if figsize is not None:
|
705
|
+
kwds['figsize'] = figsize
|
706
|
+
if dpi is not None:
|
707
|
+
kwds['dpi'] = dpi
|
708
|
+
save_function(filename, **kwds)
|
709
|
+
from sage.repl.rich_output.buffer import OutputBuffer
|
710
|
+
buf = OutputBuffer.from_file(filename)
|
711
|
+
return output_container(buf)
|
712
|
+
|
713
|
+
def threejs_scripts(self, online):
|
714
|
+
"""
|
715
|
+
Return Three.js script tag for the current backend.
|
716
|
+
|
717
|
+
INPUT:
|
718
|
+
|
719
|
+
- ``online`` -- boolean determining script usage context
|
720
|
+
|
721
|
+
OUTPUT: string containing script tag
|
722
|
+
|
723
|
+
.. NOTE::
|
724
|
+
|
725
|
+
This base method handles ``online=True`` case only, serving CDN
|
726
|
+
script tag. Location of script for offline usage is
|
727
|
+
backend-specific.
|
728
|
+
|
729
|
+
EXAMPLES::
|
730
|
+
|
731
|
+
sage: from sage.repl.rich_output import get_display_manager
|
732
|
+
sage: get_display_manager().threejs_scripts(online=True) # needs sage.plot
|
733
|
+
'...<script src="https://cdn.jsdelivr.net/gh/sagemath/threejs-sage@...'
|
734
|
+
sage: get_display_manager().threejs_scripts(online=False) # needs sage.plot
|
735
|
+
Traceback (most recent call last):
|
736
|
+
...
|
737
|
+
ValueError: current backend does not support
|
738
|
+
offline threejs graphics
|
739
|
+
"""
|
740
|
+
from sage.features.threejs import Threejs
|
741
|
+
if online:
|
742
|
+
version = Threejs().required_version()
|
743
|
+
return """
|
744
|
+
<script src="https://cdn.jsdelivr.net/gh/sagemath/threejs-sage@{0}/build/three.min.js"></script>
|
745
|
+
""".format(version)
|
746
|
+
try:
|
747
|
+
return self._backend.threejs_offline_scripts()
|
748
|
+
except AttributeError:
|
749
|
+
raise ValueError(
|
750
|
+
'current backend does not support offline threejs graphics')
|
751
|
+
|
752
|
+
def supported_output(self):
|
753
|
+
"""
|
754
|
+
Return the output container classes that can be used.
|
755
|
+
|
756
|
+
OUTPUT:
|
757
|
+
|
758
|
+
Frozen set of subclasses of
|
759
|
+
:class:`~sage.repl.rich_output.output_basic.OutputBase`. If
|
760
|
+
the backend defines derived container classes, this method
|
761
|
+
will always return their base classes.
|
762
|
+
|
763
|
+
EXAMPLES::
|
764
|
+
|
765
|
+
sage: from sage.repl.rich_output import get_display_manager
|
766
|
+
sage: dm = get_display_manager()
|
767
|
+
sage: dm.types.OutputPlainText in dm.supported_output()
|
768
|
+
True
|
769
|
+
sage: type(dm.supported_output())
|
770
|
+
<... 'frozenset'>
|
771
|
+
"""
|
772
|
+
return self._supported_output
|
773
|
+
|
774
|
+
def displayhook(self, obj):
|
775
|
+
"""
|
776
|
+
Implementation of the displayhook.
|
777
|
+
|
778
|
+
Every backend must pass the value of the last statement of a
|
779
|
+
line / cell to this method. See also
|
780
|
+
:meth:`display_immediately` if you want do display rich output
|
781
|
+
while a program is running.
|
782
|
+
|
783
|
+
INPUT:
|
784
|
+
|
785
|
+
- ``obj`` -- anything; the object to be shown
|
786
|
+
|
787
|
+
OUTPUT: whatever the backend's displayhook method returned
|
788
|
+
|
789
|
+
EXAMPLES::
|
790
|
+
|
791
|
+
sage: from sage.repl.rich_output import get_display_manager
|
792
|
+
sage: dm = get_display_manager()
|
793
|
+
sage: dm.displayhook(1/2)
|
794
|
+
1/2
|
795
|
+
"""
|
796
|
+
if obj is None:
|
797
|
+
return
|
798
|
+
self._backend.set_underscore_variable(obj)
|
799
|
+
plain_text, rich_output = self._rich_output_formatter(obj, dict())
|
800
|
+
return self._backend.displayhook(plain_text, rich_output)
|
801
|
+
|
802
|
+
def display_immediately(self, obj, **rich_repr_kwds):
|
803
|
+
"""
|
804
|
+
Show output without going back to the command line prompt.
|
805
|
+
|
806
|
+
This method must be called to create rich output from an
|
807
|
+
object when we are not returning to the command line prompt,
|
808
|
+
for example during program execution. Typically, it is being
|
809
|
+
called by :meth:`sage.plot.graphics.Graphics.show`.
|
810
|
+
|
811
|
+
INPUT:
|
812
|
+
|
813
|
+
- ``obj`` -- anything; the object to be shown
|
814
|
+
|
815
|
+
- ``rich_repr_kwds`` -- optional keyword arguments that are
|
816
|
+
passed through to ``obj._rich_repr_``
|
817
|
+
|
818
|
+
EXAMPLES::
|
819
|
+
|
820
|
+
sage: from sage.repl.rich_output import get_display_manager
|
821
|
+
sage: dm = get_display_manager()
|
822
|
+
sage: dm.display_immediately(1/2)
|
823
|
+
1/2
|
824
|
+
"""
|
825
|
+
plain_text, rich_output = self._rich_output_formatter(obj, rich_repr_kwds)
|
826
|
+
self._backend.display_immediately(plain_text, rich_output)
|
827
|
+
|
828
|
+
|
829
|
+
get_display_manager = DisplayManager.get_instance
|