passagemath-repl 10.4.62__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. passagemath_repl-10.4.62.data/scripts/sage-cachegrind +25 -0
  2. passagemath_repl-10.4.62.data/scripts/sage-callgrind +16 -0
  3. passagemath_repl-10.4.62.data/scripts/sage-cleaner +230 -0
  4. passagemath_repl-10.4.62.data/scripts/sage-coverage +327 -0
  5. passagemath_repl-10.4.62.data/scripts/sage-eval +14 -0
  6. passagemath_repl-10.4.62.data/scripts/sage-fixdoctests +708 -0
  7. passagemath_repl-10.4.62.data/scripts/sage-inline-fortran +12 -0
  8. passagemath_repl-10.4.62.data/scripts/sage-ipynb2rst +50 -0
  9. passagemath_repl-10.4.62.data/scripts/sage-ipython +16 -0
  10. passagemath_repl-10.4.62.data/scripts/sage-massif +25 -0
  11. passagemath_repl-10.4.62.data/scripts/sage-notebook +267 -0
  12. passagemath_repl-10.4.62.data/scripts/sage-omega +25 -0
  13. passagemath_repl-10.4.62.data/scripts/sage-preparse +302 -0
  14. passagemath_repl-10.4.62.data/scripts/sage-run +27 -0
  15. passagemath_repl-10.4.62.data/scripts/sage-run-cython +10 -0
  16. passagemath_repl-10.4.62.data/scripts/sage-runtests +9 -0
  17. passagemath_repl-10.4.62.data/scripts/sage-startuptime.py +163 -0
  18. passagemath_repl-10.4.62.data/scripts/sage-valgrind +34 -0
  19. passagemath_repl-10.4.62.dist-info/METADATA +77 -0
  20. passagemath_repl-10.4.62.dist-info/RECORD +162 -0
  21. passagemath_repl-10.4.62.dist-info/WHEEL +5 -0
  22. passagemath_repl-10.4.62.dist-info/top_level.txt +1 -0
  23. sage/all__sagemath_repl.py +119 -0
  24. sage/doctest/__init__.py +4 -0
  25. sage/doctest/__main__.py +236 -0
  26. sage/doctest/all.py +4 -0
  27. sage/doctest/check_tolerance.py +261 -0
  28. sage/doctest/control.py +1727 -0
  29. sage/doctest/external.py +534 -0
  30. sage/doctest/fixtures.py +383 -0
  31. sage/doctest/forker.py +2665 -0
  32. sage/doctest/marked_output.py +102 -0
  33. sage/doctest/parsing.py +1708 -0
  34. sage/doctest/parsing_test.py +79 -0
  35. sage/doctest/reporting.py +733 -0
  36. sage/doctest/rif_tol.py +124 -0
  37. sage/doctest/sources.py +1657 -0
  38. sage/doctest/test.py +584 -0
  39. sage/doctest/tests/1second.rst +4 -0
  40. sage/doctest/tests/99seconds.rst +4 -0
  41. sage/doctest/tests/abort.rst +5 -0
  42. sage/doctest/tests/atexit.rst +7 -0
  43. sage/doctest/tests/fail_and_die.rst +6 -0
  44. sage/doctest/tests/initial.rst +15 -0
  45. sage/doctest/tests/interrupt.rst +7 -0
  46. sage/doctest/tests/interrupt_diehard.rst +14 -0
  47. sage/doctest/tests/keyboardinterrupt.rst +11 -0
  48. sage/doctest/tests/longtime.rst +5 -0
  49. sage/doctest/tests/nodoctest +5 -0
  50. sage/doctest/tests/random_seed.rst +4 -0
  51. sage/doctest/tests/show_skipped.rst +18 -0
  52. sage/doctest/tests/sig_on.rst +9 -0
  53. sage/doctest/tests/simple_failure.rst +8 -0
  54. sage/doctest/tests/sleep_and_raise.rst +106 -0
  55. sage/doctest/tests/tolerance.rst +31 -0
  56. sage/doctest/util.py +750 -0
  57. sage/interfaces/cleaner.py +48 -0
  58. sage/interfaces/quit.py +163 -0
  59. sage/misc/all__sagemath_repl.py +51 -0
  60. sage/misc/banner.py +235 -0
  61. sage/misc/benchmark.py +221 -0
  62. sage/misc/classgraph.py +131 -0
  63. sage/misc/copying.py +22 -0
  64. sage/misc/cython.py +694 -0
  65. sage/misc/dev_tools.py +745 -0
  66. sage/misc/edit_module.py +304 -0
  67. sage/misc/explain_pickle.py +3079 -0
  68. sage/misc/gperftools.py +361 -0
  69. sage/misc/inline_fortran.py +212 -0
  70. sage/misc/messaging.py +86 -0
  71. sage/misc/pager.py +21 -0
  72. sage/misc/profiler.py +179 -0
  73. sage/misc/python.py +70 -0
  74. sage/misc/remote_file.py +53 -0
  75. sage/misc/sage_eval.py +246 -0
  76. sage/misc/sage_input.py +3621 -0
  77. sage/misc/sagedoc.py +1742 -0
  78. sage/misc/sh.py +38 -0
  79. sage/misc/trace.py +90 -0
  80. sage/repl/__init__.py +16 -0
  81. sage/repl/all.py +15 -0
  82. sage/repl/attach.py +625 -0
  83. sage/repl/configuration.py +186 -0
  84. sage/repl/display/__init__.py +1 -0
  85. sage/repl/display/fancy_repr.py +354 -0
  86. sage/repl/display/formatter.py +318 -0
  87. sage/repl/display/jsmol_iframe.py +290 -0
  88. sage/repl/display/pretty_print.py +153 -0
  89. sage/repl/display/util.py +163 -0
  90. sage/repl/image.py +302 -0
  91. sage/repl/inputhook.py +91 -0
  92. sage/repl/interface_magic.py +298 -0
  93. sage/repl/interpreter.py +854 -0
  94. sage/repl/ipython_extension.py +593 -0
  95. sage/repl/ipython_kernel/__init__.py +1 -0
  96. sage/repl/ipython_kernel/__main__.py +4 -0
  97. sage/repl/ipython_kernel/all_jupyter.py +10 -0
  98. sage/repl/ipython_kernel/install.py +301 -0
  99. sage/repl/ipython_kernel/interact.py +278 -0
  100. sage/repl/ipython_kernel/kernel.py +217 -0
  101. sage/repl/ipython_kernel/widgets.py +466 -0
  102. sage/repl/ipython_kernel/widgets_sagenb.py +587 -0
  103. sage/repl/ipython_tests.py +163 -0
  104. sage/repl/load.py +326 -0
  105. sage/repl/preparse.py +2218 -0
  106. sage/repl/prompts.py +90 -0
  107. sage/repl/rich_output/__init__.py +4 -0
  108. sage/repl/rich_output/backend_base.py +648 -0
  109. sage/repl/rich_output/backend_doctest.py +316 -0
  110. sage/repl/rich_output/backend_emacs.py +151 -0
  111. sage/repl/rich_output/backend_ipython.py +596 -0
  112. sage/repl/rich_output/buffer.py +311 -0
  113. sage/repl/rich_output/display_manager.py +829 -0
  114. sage/repl/rich_output/example.avi +0 -0
  115. sage/repl/rich_output/example.canvas3d +1 -0
  116. sage/repl/rich_output/example.dvi +0 -0
  117. sage/repl/rich_output/example.flv +0 -0
  118. sage/repl/rich_output/example.gif +0 -0
  119. sage/repl/rich_output/example.jpg +0 -0
  120. sage/repl/rich_output/example.mkv +0 -0
  121. sage/repl/rich_output/example.mov +0 -0
  122. sage/repl/rich_output/example.mp4 +0 -0
  123. sage/repl/rich_output/example.ogv +0 -0
  124. sage/repl/rich_output/example.pdf +0 -0
  125. sage/repl/rich_output/example.png +0 -0
  126. sage/repl/rich_output/example.svg +54 -0
  127. sage/repl/rich_output/example.webm +0 -0
  128. sage/repl/rich_output/example.wmv +0 -0
  129. sage/repl/rich_output/example_jmol.spt.zip +0 -0
  130. sage/repl/rich_output/example_wavefront_scene.mtl +7 -0
  131. sage/repl/rich_output/example_wavefront_scene.obj +17 -0
  132. sage/repl/rich_output/output_basic.py +391 -0
  133. sage/repl/rich_output/output_browser.py +103 -0
  134. sage/repl/rich_output/output_catalog.py +54 -0
  135. sage/repl/rich_output/output_graphics.py +320 -0
  136. sage/repl/rich_output/output_graphics3d.py +345 -0
  137. sage/repl/rich_output/output_video.py +231 -0
  138. sage/repl/rich_output/preferences.py +432 -0
  139. sage/repl/rich_output/pretty_print.py +339 -0
  140. sage/repl/rich_output/test_backend.py +201 -0
  141. sage/repl/user_globals.py +214 -0
  142. sage/tests/__init__.py +1 -0
  143. sage/tests/all.py +3 -0
  144. sage/tests/article_heuberger_krenn_kropf_fsm-in-sage.py +630 -0
  145. sage/tests/arxiv_0812_2725.py +351 -0
  146. sage/tests/benchmark.py +1923 -0
  147. sage/tests/book_schilling_zabrocki_kschur_primer.py +795 -0
  148. sage/tests/book_stein_ent.py +651 -0
  149. sage/tests/book_stein_modform.py +558 -0
  150. sage/tests/cmdline.py +790 -0
  151. sage/tests/combinatorial_hopf_algebras.py +52 -0
  152. sage/tests/finite_poset.py +623 -0
  153. sage/tests/functools_partial_src.py +27 -0
  154. sage/tests/gosper-sum.py +218 -0
  155. sage/tests/lazy_imports.py +28 -0
  156. sage/tests/modular_group_cohomology.py +80 -0
  157. sage/tests/numpy.py +21 -0
  158. sage/tests/parigp.py +76 -0
  159. sage/tests/startup.py +27 -0
  160. sage/tests/symbolic-series.py +76 -0
  161. sage/tests/sympy.py +16 -0
  162. sage/tests/test_deprecation.py +31 -0
@@ -0,0 +1,854 @@
1
+ # sage_setup: distribution = sagemath-repl
2
+ r"""
3
+ Sage's IPython Modifications
4
+
5
+ This module contains all of Sage's customizations to the IPython
6
+ interpreter. These changes consist of the following major components:
7
+
8
+ - :class:`SageTerminalApp`
9
+ - :class:`SageInteractiveShell`
10
+ - :class:`SageTerminalInteractiveShell`
11
+ - :func:`interface_shell_embed`
12
+
13
+ SageTerminalApp
14
+ ---------------
15
+
16
+ This is the main application object. It is used by the
17
+ ``$SAGE_LOCAL/bin/sage-ipython`` script to start the Sage
18
+ command-line. It's primary purpose is to
19
+
20
+ - Initialize the :class:`SageTerminalInteractiveShell`.
21
+
22
+ - Provide default configuration options for the shell, and its
23
+ subcomponents. These work with (and can be overridden by)
24
+ IPython's configuration system.
25
+
26
+ - Load the Sage ipython extension (which does things like preparsing,
27
+ add magics, etc.).
28
+
29
+ - Provide a custom :class:`SageCrashHandler` to give the user
30
+ instructions on how to report the crash to the Sage support
31
+ mailing list.
32
+
33
+ SageInteractiveShell
34
+ --------------------
35
+
36
+ The :class:`SageInteractiveShell` object is the object responsible for
37
+ accepting input from the user and evaluating it. From the command-line,
38
+ this object can be retrieved by running::
39
+
40
+ sage: shell = get_ipython() # not tested
41
+
42
+ Any input is preprocessed and evaluated inside the ``shell.run_cell``
43
+ method. If the command line processing does not do what you want it to
44
+ do, you can step through it in the debugger::
45
+
46
+ sage: %debug shell.run_cell('?') # not tested
47
+
48
+ The :class:`SageInteractiveShell` provides the following
49
+ customizations:
50
+
51
+ - Modify the libraries before calling system commands. See
52
+ :meth:`~SageInteractiveShell.system_raw`.
53
+
54
+ SageTerminalInteractiveShell
55
+ ----------------------------
56
+
57
+ The :class:`SageTerminalInteractiveShell` is a close relative of
58
+ :class:`SageInteractiveShell` that is specialized for running in a
59
+ terminal. In particular, running commands like ``!ls`` will directly
60
+ write to stdout. Technically, the ``system`` attribute will point to
61
+ ``system_raw`` instead of ``system_piped``.
62
+
63
+ Interface Shell
64
+ ---------------
65
+
66
+ The function :func:`interface_shell_embed` takes a
67
+ :class:`~sage.interfaces.interface.Interface` object and returns an
68
+ embeddable IPython shell which can be used to directly interact with
69
+ that shell. The bulk of this functionality is provided through
70
+ :class:`InterfaceShellTransformer`.
71
+
72
+ TESTS:
73
+
74
+ Check that Cython source code appears in tracebacks::
75
+
76
+ sage: from sage.repl.interpreter import get_test_shell
77
+ sage: shell = get_test_shell()
78
+ sage: print("dummy line"); shell.run_cell('1/0') # known bug (meson doesn't include the Cython source code) # see #25320 for the reason of the `...` and the dummy line in this test
79
+ dummy line
80
+ ...
81
+ ZeroDivisionError...Traceback (most recent call last)
82
+ ...
83
+ ----> 1 Integer(1)/Integer(0)
84
+ ...
85
+ ...integer.pyx... in sage.rings.integer.Integer...div...
86
+ ...
87
+ -> ... raise ZeroDivisionError("rational division by zero")
88
+ ....: x = <Rational> Rational.__new__(Rational)
89
+ ....: mpq_div_zz(x.value, ....value, (<Integer>right).value)
90
+ <BLANKLINE>
91
+ ZeroDivisionError: rational division by zero
92
+ sage: shell.quit()
93
+
94
+ Test prompt transformer::
95
+
96
+ sage: from sage.repl.interpreter import SagePromptTransformer
97
+ sage: spt = SagePromptTransformer
98
+ sage: spt(["sage: 2 + 2"])
99
+ ['2 + 2']
100
+ sage: spt([''])
101
+ ['']
102
+ sage: spt(["....: 2+2"])
103
+ ['2+2']
104
+
105
+ This should strip multiple prompts: see :issue:`16297`::
106
+
107
+ sage: spt(["sage: sage: 2+2"])
108
+ ['2+2']
109
+ sage: spt([" sage: ....: 2+2"])
110
+ ['2+2']
111
+
112
+ The prompt contains a trailing space. Extra spaces between the
113
+ last prompt and the remainder should not be stripped::
114
+
115
+ sage: spt([" sage: ....: 2+2"])
116
+ [' 2+2']
117
+
118
+ We test that the input transformer is enabled on the Sage command
119
+ line::
120
+
121
+ sage: from sage.repl.interpreter import get_test_shell
122
+ sage: shell = get_test_shell()
123
+ sage: shell.run_cell('sage: a = 123') # single line
124
+ sage: shell.run_cell('sage: a = [\n... 123]') # old-style multi-line
125
+ sage: shell.run_cell('sage: a = [\n....: 123]') # new-style multi-line
126
+
127
+ We test that :issue:`16196` is resolved::
128
+
129
+ sage: shell.run_cell(' sage: 1+1')
130
+ 2
131
+ sage: shell.quit()
132
+ """
133
+
134
+ # ****************************************************************************
135
+ # Copyright (C) 2004-2012 William Stein <wstein@gmail.com>
136
+ #
137
+ # This program is free software: you can redistribute it and/or modify
138
+ # it under the terms of the GNU General Public License as published by
139
+ # the Free Software Foundation, either version 2 of the License, or
140
+ # (at your option) any later version.
141
+ # https://www.gnu.org/licenses/
142
+ # ****************************************************************************
143
+ import re
144
+ from traitlets import Bool, Type
145
+
146
+ from sage.repl.preparse import preparse, containing_block
147
+ from sage.repl.prompts import InterfacePrompts
148
+ from sage.repl.configuration import sage_ipython_config, SAGE_EXTENSION
149
+
150
+ from IPython.core.interactiveshell import InteractiveShell
151
+ from IPython.terminal.interactiveshell import TerminalInteractiveShell
152
+ from IPython.core.inputtransformer2 import PromptStripper
153
+ from IPython.core.prefilter import PrefilterTransformer
154
+ from IPython.terminal.embed import InteractiveShellEmbed
155
+ from IPython.terminal.ipapp import TerminalIPythonApp, IPAppCrashHandler
156
+ from IPython.core.crashhandler import CrashHandler
157
+
158
+ from ctypes import pythonapi, c_int, c_void_p
159
+ # The following functions are part of the stable ABI since python 3.2
160
+ # See: https://docs.python.org/3/c-api/sys.html#c.PyOS_getsig
161
+
162
+ # PyOS_sighandler_t PyOS_getsig(int i)
163
+ pythonapi.PyOS_getsig.restype = c_void_p
164
+ pythonapi.PyOS_getsig.argtypes = c_int,
165
+
166
+ # PyOS_sighandler_t PyOS_setsig(int i, PyOS_sighandler_t h)
167
+ pythonapi.PyOS_setsig.restype = c_void_p
168
+ pythonapi.PyOS_setsig.argtypes = c_int, c_void_p,
169
+
170
+
171
+ # TODO: This global variable _do_preparse should be associated with an
172
+ # IPython InteractiveShell as opposed to a global variable in this
173
+ # module.
174
+ _do_preparse = True
175
+
176
+
177
+ def preparser(on=True):
178
+ """
179
+ Turn on or off the Sage preparser.
180
+
181
+ - ``on`` -- boolean; whether to turn on preparsing
182
+
183
+ EXAMPLES::
184
+
185
+ sage: 2/3
186
+ 2/3
187
+ sage: preparser(False)
188
+ sage: 2/3 # not tested since doctests are always preparsed
189
+ 0
190
+ sage: preparser(True)
191
+ sage: 2^3
192
+ 8
193
+ """
194
+ global _do_preparse
195
+ _do_preparse = on is True
196
+
197
+
198
+ ##############################
199
+ # Sage[Terminal]InteractiveShell
200
+ ##############################
201
+ class SageShellOverride:
202
+ """
203
+ Mixin to override methods in IPython's [Terminal]InteractiveShell
204
+ classes.
205
+ """
206
+
207
+ def show_usage(self):
208
+ """
209
+ Print the basic Sage usage.
210
+
211
+ This method ends up being called when you enter ``?`` and
212
+ nothing else on the command line.
213
+
214
+ EXAMPLES::
215
+
216
+ sage: from sage.repl.interpreter import get_test_shell
217
+ sage: shell = get_test_shell()
218
+ sage: shell.run_cell('?')
219
+ Welcome to Sage ...
220
+ sage: shell.quit()
221
+ """
222
+ from sage.misc.sagedoc import help
223
+ help()
224
+
225
+ def system_raw(self, cmd):
226
+ """
227
+ Run a system command.
228
+
229
+ EXAMPLES::
230
+
231
+ sage: from sage.repl.interpreter import get_test_shell
232
+ sage: shell = get_test_shell()
233
+ sage: shell.system_raw('false')
234
+ sage: shell.user_ns['_exit_code'] > 0
235
+ True
236
+ sage: shell.system_raw('true')
237
+ sage: shell.user_ns['_exit_code']
238
+ 0
239
+ sage: shell.system_raw('R --version') # optional - r
240
+ R version ...
241
+ sage: shell.user_ns['_exit_code'] # optional - r
242
+ 0
243
+ sage: shell.quit()
244
+ """
245
+ return super().system_raw(cmd)
246
+
247
+
248
+ class SageNotebookInteractiveShell(SageShellOverride, InteractiveShell):
249
+ """
250
+ IPython Shell for the Sage IPython Notebook.
251
+
252
+ The doctests are not tested since they would change the current
253
+ rich output backend away from the doctest rich output backend.
254
+
255
+ EXAMPLES::
256
+
257
+ sage: from sage.repl.interpreter import SageNotebookInteractiveShell
258
+ sage: SageNotebookInteractiveShell() # not tested
259
+ <sage.repl.interpreter.SageNotebookInteractiveShell object at 0x...>
260
+ """
261
+
262
+ def init_display_formatter(self):
263
+ """
264
+ Switch to the Sage IPython notebook rich output backend.
265
+
266
+ EXAMPLES::
267
+
268
+ sage: from sage.repl.interpreter import SageNotebookInteractiveShell
269
+ sage: SageNotebookInteractiveShell().init_display_formatter() # not tested
270
+ """
271
+ from sage.repl.rich_output.backend_ipython import BackendIPythonNotebook
272
+ backend = BackendIPythonNotebook()
273
+ backend.get_display_manager().switch_backend(backend, shell=self)
274
+
275
+
276
+ class SageTerminalInteractiveShell(SageShellOverride, TerminalInteractiveShell):
277
+ """
278
+ IPython Shell for the Sage IPython Commandline Interface.
279
+
280
+ The doctests are not tested since they would change the current
281
+ rich output backend away from the doctest rich output backend.
282
+
283
+ EXAMPLES::
284
+
285
+ sage: from sage.repl.interpreter import SageTerminalInteractiveShell
286
+ sage: SageTerminalInteractiveShell() # not tested
287
+ <sage.repl.interpreter.SageNotebookInteractiveShell object at 0x...>
288
+ """
289
+
290
+ def init_display_formatter(self):
291
+ """
292
+ Switch to the Sage IPython commandline rich output backend.
293
+
294
+ EXAMPLES::
295
+
296
+ sage: from sage.repl.interpreter import SageTerminalInteractiveShell
297
+ sage: SageTerminalInteractiveShell().init_display_formatter() # not tested
298
+ """
299
+ from sage.repl.rich_output.backend_ipython import BackendIPythonCommandline
300
+ backend = BackendIPythonCommandline()
301
+ backend.get_display_manager().switch_backend(backend, shell=self)
302
+
303
+ def prompt_for_code(self):
304
+ # save sigint handlers (python and os level)
305
+ # https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1576
306
+ # https://github.com/sagemath/sage/issues/33428
307
+ # https://github.com/sagemath/sage/pull/35251
308
+ import signal
309
+ sigint = signal.getsignal(signal.SIGINT)
310
+ sigint_os = pythonapi.PyOS_getsig(signal.SIGINT)
311
+ text = TerminalInteractiveShell.prompt_for_code(self)
312
+ signal.signal(signal.SIGINT, sigint)
313
+ pythonapi.PyOS_setsig(signal.SIGINT, sigint_os)
314
+ return text
315
+
316
+
317
+ class SageTestShell(SageShellOverride, TerminalInteractiveShell):
318
+ """
319
+ Test Shell.
320
+
321
+ Care must be taken in these doctests to quit the test shell in
322
+ order to switch back the rich output display backend to the
323
+ doctest backend.
324
+
325
+ EXAMPLES::
326
+
327
+ sage: from sage.repl.interpreter import get_test_shell
328
+ sage: shell = get_test_shell(); shell
329
+ <sage.repl.interpreter.SageTestShell object at 0x...>
330
+ sage: shell.quit()
331
+ """
332
+
333
+ def init_display_formatter(self):
334
+ """
335
+ Switch to the Sage IPython commandline rich output backend.
336
+
337
+ EXAMPLES::
338
+
339
+ sage: from sage.repl.interpreter import get_test_shell
340
+ sage: shell = get_test_shell(); shell
341
+ <sage.repl.interpreter.SageTestShell object at 0x...>
342
+ sage: shell.quit()
343
+ sage: shell.init_display_formatter()
344
+ sage: shell.quit()
345
+ """
346
+ from sage.repl.rich_output.backend_ipython import BackendIPythonCommandline
347
+ self._ipython_backend = backend = BackendIPythonCommandline()
348
+ self._display_manager = backend.get_display_manager()
349
+ self._doctest_backend = self._display_manager.switch_backend(backend, shell=self)
350
+
351
+ def quit(self):
352
+ """
353
+ Quit the test shell.
354
+
355
+ To make the test shell as realistic as possible, we switch to
356
+ the
357
+ :class:`~sage.repl.rich_output.backend_ipython.BackendIPythonCommandline`
358
+ display backend. This method restores the previous display
359
+ backend, which is the
360
+ :class:`~sage.repl.rich_output.backend_doctest.BackendDoctest`
361
+ during doctests.
362
+
363
+ EXAMPLES::
364
+
365
+ sage: from sage.repl.interpreter import get_test_shell
366
+ sage: from sage.repl.rich_output import get_display_manager
367
+ sage: get_display_manager()
368
+ The Sage display manager using the doctest backend
369
+
370
+ sage: shell = get_test_shell()
371
+ sage: get_display_manager()
372
+ The Sage display manager using the IPython command line backend
373
+
374
+ sage: shell.quit()
375
+ sage: get_display_manager()
376
+ The Sage display manager using the doctest backend
377
+ """
378
+ self._display_manager.switch_backend(self._doctest_backend)
379
+
380
+ def _restart(self):
381
+ """
382
+ Restart the test shell (after :meth:`quit`).
383
+
384
+ EXAMPLES::
385
+
386
+ sage: from sage.repl.interpreter import get_test_shell
387
+ sage: shell = get_test_shell()
388
+ sage: shell.quit()
389
+ sage: shell._restart()
390
+ sage: shell.quit()
391
+ sage: from sage.repl.rich_output import get_display_manager
392
+ sage: get_display_manager()
393
+ The Sage display manager using the doctest backend
394
+ """
395
+ self._display_manager.switch_backend(self._ipython_backend, shell=self)
396
+
397
+ def run_cell(self, *args, **kwds):
398
+ """
399
+ Run IPython cell.
400
+
401
+ Starting with IPython-3.0, this returns an success/failure
402
+ information. Since it is more convenient for doctests, we
403
+ ignore it.
404
+
405
+ EXAMPLES::
406
+
407
+ sage: from sage.repl.interpreter import get_test_shell
408
+ sage: shell = get_test_shell()
409
+ sage: rc = shell.run_cell('2^50')
410
+ 1125899906842624
411
+ sage: rc is None
412
+ True
413
+ sage: shell.quit()
414
+ """
415
+ super().run_cell(*args, **kwds)
416
+
417
+
418
+ ###################################################################
419
+ # Transformers used in the SageInputSplitter
420
+ ###################################################################
421
+
422
+
423
+ def SagePreparseTransformer(lines):
424
+ r"""
425
+ EXAMPLES::
426
+
427
+ sage: from sage.repl.interpreter import SagePreparseTransformer
428
+ sage: spt = SagePreparseTransformer
429
+ sage: spt(['1+1r+2.3^2.3r\n'])
430
+ ["Integer(1)+1+RealNumber('2.3')**2.3\n"]
431
+ sage: preparser(False)
432
+ sage: spt(['2.3^2\n'])
433
+ ['2.3^2\n']
434
+
435
+ TESTS:
436
+
437
+ Check that syntax errors in the preparser do not crash IPython,
438
+ see :issue:`14961`. ::
439
+
440
+ sage: preparser(True)
441
+ sage: bad_syntax = "R.<t> = QQ{]"
442
+ sage: preparse(bad_syntax)
443
+ Traceback (most recent call last):
444
+ ...
445
+ SyntaxError: mismatched ']'
446
+ sage: from sage.repl.interpreter import get_test_shell
447
+ sage: shell = get_test_shell()
448
+ sage: shell.run_cell(bad_syntax)
449
+ File...<string>...
450
+ SyntaxError: mismatched ']'
451
+ <BLANKLINE>
452
+ sage: shell.quit()
453
+
454
+ Make sure the quote state is carried over across subsequent lines in order
455
+ to avoid interfering with multi-line strings, see :issue:`30417`. ::
456
+
457
+ sage: SagePreparseTransformer(["'''\n", 'abc-1-2\n', "'''\n"])
458
+ ["'''\n", 'abc-1-2\n', "'''\n"]
459
+ sage: # instead of ["'''\n", 'abc-Integer(1)-Integer(2)\n', "'''\n"]
460
+
461
+ .. NOTE::
462
+
463
+ IPython may call this function more than once for the same input lines.
464
+ So when debugging the preparser, print outs may be duplicated. If using
465
+ IPython >= 7.17, try:
466
+ ``sage.repl.interpreter.SagePreparseTransformer.has_side_effects = True``
467
+ """
468
+ if _do_preparse:
469
+ # IPython ensures the input lines end with a newline, and it expects
470
+ # the same of the output lines.
471
+ lines = preparse(''.join(lines)).splitlines(keepends=True)
472
+ return lines
473
+
474
+
475
+ SagePromptTransformer = PromptStripper(prompt_re=re.compile(r'^(\s*(:?sage: |\.\.\.\.: ))+'))
476
+
477
+
478
+ ###################
479
+ # Interface shell #
480
+ ###################
481
+
482
+ class logstr(str):
483
+ """
484
+ For use by :meth`~InterfaceShellTransformer.transform`.
485
+ This provides a ``_latex_`` method which is just the string
486
+ wrapped in a ``\\verb`` environment.
487
+ """
488
+ def __repr__(self):
489
+ """
490
+ EXAMPLES::
491
+ sage: from sage.repl.interpreter import logstr
492
+ sage: logstr("ABC")
493
+ ABC
494
+ """
495
+ return self
496
+
497
+ def _latex_(self):
498
+ r"""
499
+ EXAMPLES::
500
+ sage: from sage.repl.interpreter import logstr
501
+ sage: logstr("A")
502
+ A
503
+ sage: latex(logstr("A"))
504
+ \verb#A#
505
+ sage: latex(logstr("A#B"))
506
+ \verb@A#B@
507
+ """
508
+ # return "\\begin{verbatim}%s\\end{verbatim}"%self
509
+ if '#' not in self:
510
+ delim = '#'
511
+ elif '@' not in self:
512
+ delim = '@'
513
+ elif '~' not in self:
514
+ delim = '~'
515
+ return r"""\verb%s%s%s""" % (delim, self.replace('\n\n', '\n').replace('\n', '; '), delim)
516
+
517
+
518
+ class InterfaceShellTransformer(PrefilterTransformer):
519
+ priority = 50
520
+
521
+ def __init__(self, *args, **kwds):
522
+ """
523
+ Initialize this class. All of the arguments get passed to
524
+ :meth:`PrefilterTransformer.__init__`.
525
+
526
+ .. attribute:: temporary_objects
527
+
528
+ a list of hold onto interface objects and keep them from being
529
+ garbage collected
530
+
531
+ .. SEEALSO:: :func:`interface_shell_embed`
532
+
533
+ TESTS::
534
+
535
+ sage: # needs sage.symbolic
536
+ sage: from sage.repl.interpreter import interface_shell_embed
537
+ sage: shell = interface_shell_embed(maxima)
538
+ sage: ift = shell.prefilter_manager.transformers[0]
539
+ sage: ift.temporary_objects
540
+ set()
541
+ sage: ift._sage_import_re.findall('sage(a) + maxima(b)')
542
+ ['sage(', 'maxima(']
543
+ """
544
+ super().__init__(*args, **kwds)
545
+ self.temporary_objects = set()
546
+ self._sage_import_re = re.compile(r'(?:sage|%s)\('
547
+ % self.shell.interface.name())
548
+
549
+ def preparse_imports_from_sage(self, line):
550
+ """
551
+ Finds occurrences of strings such as ``sage(object)`` in
552
+ *line*, converts ``object`` to :attr:`shell.interface`,
553
+ and replaces those strings with their identifier in the new
554
+ system. This also works with strings such as
555
+ ``maxima(object)`` if :attr:`shell.interface` is
556
+ ``maxima``.
557
+
558
+ - ``line`` -- string; the line to transform
559
+
560
+ EXAMPLES::
561
+
562
+ sage: # needs sage.symbolic
563
+ sage: from sage.repl.interpreter import interface_shell_embed, InterfaceShellTransformer
564
+ sage: shell = interface_shell_embed(maxima)
565
+ sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config,
566
+ ....: prefilter_manager=shell.prefilter_manager)
567
+ sage: ift.shell.ex('a = 3')
568
+ sage: ift.preparse_imports_from_sage('2 + sage(a)')
569
+ '2 + sage0 '
570
+ sage: maxima.eval('sage0')
571
+ '3'
572
+ sage: ift.preparse_imports_from_sage('2 + maxima(a)') # maxima calls set_seed on startup which is why 'sage0' will becomes 'sage4' and not just 'sage1'
573
+ '2 + sage4 '
574
+ sage: ift.preparse_imports_from_sage('2 + gap(a)')
575
+ '2 + gap(a)'
576
+
577
+ Since :issue:`28439`, this also works with more complicated expressions
578
+ containing nested parentheses::
579
+
580
+ sage: # needs sage.libs.gap sage.symbolic
581
+ sage: shell = interface_shell_embed(gap)
582
+ sage: shell.user_ns = locals()
583
+ sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config,
584
+ ....: prefilter_manager=shell.prefilter_manager)
585
+ sage: line = '2 + sage((1+2)*gap(-(5-3)^2).sage()) - gap(1+(2-1))'
586
+ sage: line = ift.preparse_imports_from_sage(line)
587
+ sage: gap.eval(line)
588
+ '-12'
589
+ """
590
+ new_line = []
591
+ pos = 0
592
+ while True:
593
+ m = self._sage_import_re.search(line, pos)
594
+ if not m:
595
+ new_line.append(line[pos:])
596
+ break
597
+ expr_start, expr_end = containing_block(line, m.end() - 1,
598
+ delimiters=['()'])
599
+ expr = preparse(line[expr_start + 1:expr_end - 1])
600
+ result = self.shell.interface(eval(expr, self.shell.user_ns))
601
+ self.temporary_objects.add(result)
602
+ new_line += [line[pos:m.start()], result.name()]
603
+ pos = expr_end
604
+ return ' '.join(new_line)
605
+
606
+ def transform(self, line, continue_prompt):
607
+ r'''
608
+ Evaluates *line* in :attr:`shell.interface` and returns a
609
+ string representing the result of that evaluation.
610
+
611
+ - ``line`` -- string; the line to be transformed *and evaluated*
612
+ - ``continue_prompt`` -- boolean; whether this line is a continuation in a
613
+ sequence of multiline input
614
+
615
+ EXAMPLES::
616
+
617
+ sage: # needs sage.symbolic
618
+ sage: from sage.repl.interpreter import interface_shell_embed, InterfaceShellTransformer
619
+ sage: shell = interface_shell_embed(maxima)
620
+ sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config,
621
+ ....: prefilter_manager=shell.prefilter_manager)
622
+ sage: ift.transform('2+2', False) # note: output contains triple quotation marks
623
+ 'sage.repl.interpreter.logstr(r"""4""")'
624
+ sage: ift.shell.ex('a = 4')
625
+ sage: ift.transform(r'sage(a)+4', False)
626
+ 'sage.repl.interpreter.logstr(r"""8""")'
627
+ sage: ift.temporary_objects
628
+ set()
629
+ sage: shell = interface_shell_embed(gap) # needs sage.libs.gap
630
+ sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, # needs sage.libs.gap
631
+ ....: prefilter_manager=shell.prefilter_manager)
632
+ sage: ift.transform('2+2', False)
633
+ 'sage.repl.interpreter.logstr(r"""4""")'
634
+
635
+ TESTS:
636
+
637
+ Check that whitespace is not stripped and that special characters are
638
+ escaped (:issue:`28439`)::
639
+
640
+ sage: shell = interface_shell_embed(gap) # needs sage.libs.gap sage.symbolic
641
+ sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, # needs sage.libs.gap sage.symbolic
642
+ ....: prefilter_manager=shell.prefilter_manager)
643
+ sage: ift.transform(r'Print(" -\n\\\\- ");', False) # needs sage.symbolic
644
+ 'sage.repl.interpreter.logstr(r""" -\n\\\\-""")'
645
+
646
+ sage: # optional - macaulay2
647
+ sage: shell = interface_shell_embed(macaulay2)
648
+ sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config,
649
+ ....: prefilter_manager=shell.prefilter_manager)
650
+ sage: ift.transform('net(ZZ^2)', False)
651
+ 'sage.repl.interpreter.logstr(r""" 2\nZZ""")'
652
+ '''
653
+ line = self.preparse_imports_from_sage(line)
654
+
655
+ try:
656
+ t = self.shell.interface.eval(line)
657
+ finally:
658
+ # Once we've evaluated the lines, we can clear the
659
+ # temporary objects
660
+ self.temporary_objects = set()
661
+ # We do not strip whitespace from t here as the individual interface is
662
+ # responsible for that
663
+ return 'sage.repl.interpreter.logstr(r"""%s""")' % t
664
+
665
+
666
+ def interface_shell_embed(interface):
667
+ """
668
+ Return an IPython shell which uses a Sage interface on the
669
+ backend to perform the evaluations. It uses
670
+ :class:`InterfaceShellTransformer` to transform the input into the
671
+ appropriate ``interface.eval(...)`` input.
672
+
673
+ INPUT:
674
+
675
+ - ``interface`` -- a Sage ``PExpect`` interface instance
676
+
677
+ EXAMPLES::
678
+
679
+ sage: from sage.repl.interpreter import interface_shell_embed
680
+ sage: shell = interface_shell_embed(gap) # needs sage.libs.gap
681
+ sage: shell.run_cell('List( [1..10], IsPrime )') # needs sage.libs.gap
682
+ [ false, true, true, false, true, false, true, false, false, false ]
683
+ <ExecutionResult object at ..., execution_count=None error_before_exec=None error_in_exec=None ...result=[ false, true, true, false, true, false, true, false, false, false ]>
684
+ """
685
+ cfg = sage_ipython_config.copy()
686
+ ipshell = InteractiveShellEmbed(config=cfg,
687
+ banner1='\n --> Switching to %s <--\n\n' % interface,
688
+ exit_msg='\n --> Exiting back to Sage <--\n')
689
+ ipshell.interface = interface
690
+ ipshell.prompts = InterfacePrompts(interface.name())
691
+
692
+ while ipshell.prefilter_manager.transformers:
693
+ ipshell.prefilter_manager.transformers.pop()
694
+ while ipshell.prefilter_manager.checkers:
695
+ ipshell.prefilter_manager.checkers.pop()
696
+ ipshell.ex('import sage.misc.all')
697
+
698
+ InterfaceShellTransformer(shell=ipshell,
699
+ prefilter_manager=ipshell.prefilter_manager,
700
+ config=cfg)
701
+ return ipshell
702
+
703
+
704
+ def get_test_shell():
705
+ """
706
+ Return a IPython shell that can be used in testing the functions
707
+ in this module.
708
+
709
+ OUTPUT: an IPython shell
710
+
711
+ EXAMPLES::
712
+
713
+ sage: from sage.repl.interpreter import get_test_shell
714
+ sage: shell = get_test_shell(); shell
715
+ <sage.repl.interpreter.SageTestShell object at 0x...>
716
+ sage: shell.parent.shell_class
717
+ <class 'sage.repl.interpreter.SageTestShell'>
718
+ sage: shell.parent.test_shell
719
+ True
720
+ sage: shell.quit()
721
+
722
+ TESTS:
723
+
724
+ Check that :issue:`14070` has been resolved::
725
+
726
+ sage: from sage.tests.cmdline import test_executable
727
+ sage: cmd = 'from sage.repl.interpreter import get_test_shell; shell = get_test_shell()'
728
+ sage: (out, err, ret) = test_executable(["sage", "-c", cmd])
729
+ sage: out + err
730
+ ''
731
+ """
732
+ config = sage_ipython_config.default()
733
+ config.TerminalIPythonApp.test_shell = True
734
+ config.TerminalIPythonApp.shell_class = SageTestShell
735
+ app = SageTerminalApp.instance(config=config)
736
+ if app.shell is None:
737
+ app.initialize(argv=[])
738
+ else:
739
+ try:
740
+ app.shell._restart()
741
+ except AttributeError:
742
+ pass
743
+ # No quit noise
744
+ app.shell.verbose_quit = False
745
+ return app.shell
746
+
747
+
748
+ #######################
749
+ # IPython TerminalApp #
750
+ #######################
751
+
752
+ class SageCrashHandler(IPAppCrashHandler):
753
+ def __init__(self, app):
754
+ """
755
+ A custom :class:`CrashHandler` which gives the user
756
+ instructions on how to post the problem to sage-support.
757
+
758
+ EXAMPLES::
759
+
760
+ sage: from sage.repl.interpreter import SageTerminalApp, SageCrashHandler
761
+ sage: app = SageTerminalApp.instance()
762
+ sage: sch = SageCrashHandler(app); sch
763
+ <sage.repl.interpreter.SageCrashHandler object at 0x...>
764
+ sage: sorted(sch.info.items())
765
+ [('app_name', 'Sage'),
766
+ ('bug_tracker', 'https://github.com/sagemath/sage/issues'),
767
+ ('contact_email', 'sage-support@googlegroups.com'),
768
+ ('contact_name', 'sage-support'),
769
+ ('crash_report_fname', 'Crash_report_Sage.txt')]
770
+ """
771
+ contact_name = 'sage-support'
772
+ contact_email = 'sage-support@googlegroups.com'
773
+ bug_tracker = 'https://github.com/sagemath/sage/issues'
774
+ CrashHandler.__init__(self,
775
+ app, contact_name, contact_email, bug_tracker, show_crash_traceback=True)
776
+ self.crash_report_fname = 'Sage_crash_report.txt'
777
+
778
+
779
+ class SageTerminalApp(TerminalIPythonApp):
780
+ name = 'Sage'
781
+ crash_handler_class = SageCrashHandler
782
+
783
+ test_shell = Bool(False, help='Whether the shell is a test shell')
784
+ test_shell.tag(config=True)
785
+ shell_class = Type(InteractiveShell, help='Type of the shell')
786
+ shell_class.tag(config=True)
787
+
788
+ def load_config_file(self, *args, **kwds):
789
+ r"""
790
+ Merges a config file with the default sage config.
791
+
792
+ .. NOTE::
793
+
794
+ This code is based on :meth:`Application.update_config`.
795
+
796
+ TESTS:
797
+
798
+ Test that :issue:`15972` has been fixed::
799
+
800
+ sage: import tempfile
801
+ sage: from sage.repl.interpreter import SageTerminalApp
802
+ sage: from IPython.paths import get_ipython_dir
803
+ sage: with tempfile.TemporaryDirectory() as d:
804
+ ....: IPYTHONDIR = get_ipython_dir()
805
+ ....: os.environ['IPYTHONDIR'] = d
806
+ ....: SageTerminalApp().load_config_file()
807
+ ....: os.environ['IPYTHONDIR'] = IPYTHONDIR
808
+ """
809
+ super().load_config_file(*args, **kwds)
810
+ newconfig = sage_ipython_config.default()
811
+ # merge in the config loaded from file
812
+ newconfig.merge(self.config)
813
+ self.config = newconfig
814
+
815
+ def init_shell(self):
816
+ r"""
817
+ Initialize the :class:`SageInteractiveShell` instance.
818
+
819
+ .. NOTE::
820
+
821
+ This code is based on
822
+ :meth:`TerminalIPythonApp.init_shell`.
823
+
824
+ EXAMPLES::
825
+
826
+ sage: from sage.repl.interpreter import SageTerminalApp
827
+ sage: app = SageTerminalApp.instance()
828
+ sage: app.shell
829
+ <sage.repl.interpreter.SageTestShell object at 0x...>
830
+ """
831
+ # Shell initialization
832
+ self.shell = self.shell_class.instance(
833
+ parent=self,
834
+ config=self.config,
835
+ profile_dir=self.profile_dir,
836
+ ipython_dir=self.ipython_dir)
837
+ self.shell.configurables.append(self)
838
+ self.shell.has_sage_extensions = SAGE_EXTENSION in self.extensions
839
+
840
+ # Load the %lprun extension if available
841
+ try:
842
+ import line_profiler
843
+ assert line_profiler # silence pyflakes
844
+ except ImportError:
845
+ pass
846
+ else:
847
+ self.extensions.append('line_profiler')
848
+
849
+ if self.shell.has_sage_extensions:
850
+ self.extensions.remove(SAGE_EXTENSION)
851
+
852
+ # load sage extension here to get a crash if
853
+ # something is wrong with the sage library
854
+ self.shell.extension_manager.load_extension(SAGE_EXTENSION)