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,12 @@
1
+ #!/bin/sh
2
+
3
+ # Compile Fortran code within Sage,
4
+ # see src/sage/misc/inline_fortran.py
5
+
6
+ [ -n "$FC" ] || FC=gfortran
7
+
8
+ if [ "$UNAME" = "Darwin" ]; then
9
+ exec $FC -bundle -undefined dynamic_lookup "$@"
10
+ else
11
+ exec $FC -shared "$@"
12
+ fi
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env bash
2
+
3
+ if [ -z $SAGE_EXTCODE ]; then
4
+ SAGE_EXTCODE=`${0/-ipynb2rst} -c "from sage.env import SAGE_EXTCODE; print(SAGE_EXTCODE)"`
5
+ fi
6
+
7
+ fail () {
8
+ echo "ERROR: ${1}" 1>&2
9
+ exit 1
10
+ }
11
+
12
+ help () {
13
+ cat << EOF
14
+ Usage:
15
+
16
+ sage -ipynb2rst <source> [<destination>]
17
+
18
+ Generates reStructuredText source (.rst) from IPython worksheet (.ipynb).
19
+
20
+ If the destination is not specified, the reStructuredText source is written in
21
+ the standard output.
22
+
23
+ Examples:
24
+
25
+ sage -ipynb2rst file.ipynb file.rst
26
+
27
+ sage -ipynb2rst file.ipynb
28
+
29
+ Options:
30
+ -h, --help show this help message and exit
31
+ EOF
32
+ }
33
+
34
+ if [ "${1}" = '-h' ] || [ "${1}" = '--help' ] ; then help ; exit 0 ; fi
35
+
36
+ case "${#}" in
37
+ (1)
38
+ jupyter nbconvert --to rst --RSTExporter.template_path=[\'$SAGE_EXTCODE/nbconvert/\'] --RSTExporter.template_file='rst_sage.tpl' --NbConvertApp.output_files_dir='.' --output-dir='.' "${1}" || ( echo -e '\n' ; help )
39
+ $SAGE_EXTCODE/nbconvert/postprocess.py "${1/.ipynb/.rst}"
40
+ ;;
41
+ (2)
42
+ jupyter nbconvert --output="${2}" --to rst --RSTExporter.template_path=[\'$SAGE_EXTCODE/nbconvert/\'] --RSTExporter.template_file='rst_sage.tpl' --NbConvertApp.output_files_dir='.' "${1}" || ( echo -e '\n' ; help )
43
+ $SAGE_EXTCODE/nbconvert/postprocess.py "${2}"
44
+ ;;
45
+ (*)
46
+ help ;;
47
+ esac
48
+
49
+ exit 0
50
+
@@ -0,0 +1,16 @@
1
+ #!python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Sage IPython startup script.
5
+ """
6
+
7
+ # Display startup banner. Do this before anything else to give the user
8
+ # early feedback that Sage is starting.
9
+ from sage.misc.banner import banner
10
+ banner()
11
+
12
+ from sage.repl.interpreter import SageTerminalApp
13
+
14
+ app = SageTerminalApp.instance()
15
+ app.initialize()
16
+ app.start()
@@ -0,0 +1,25 @@
1
+ #!/bin/sh
2
+
3
+ # We reuse the gdb pythonstartup script.
4
+ PYTHONSTARTUP=`dirname $0`/sage-ipython
5
+ export PYTHONSTARTUP
6
+ echo $PYTHONSTARTUP
7
+ if [ ! -d "$DOT_SAGE/valgrind" ]; then
8
+ mkdir "$DOT_SAGE/valgrind"
9
+ fi
10
+
11
+ LOG="$DOT_SAGE"/valgrind/sage-massif.%p
12
+ echo "Log file is $LOG"
13
+
14
+ MASSIF_FLAGS="--log-file=$LOG --depth=6 "; export MASSIF_FLAGS
15
+ if [ "$SAGE_MASSIF_FLAGS" ]; then
16
+ echo "Overwriting massif flags with:"
17
+ echo $SAGE_MASSIF_FLAGS
18
+ MASSIF_FLAGS=$SAGE_MASSIF_FLAGS; export MASSIF_FLAGS
19
+ else
20
+ echo "Using default flags:"
21
+ echo $MASSIF_FLAGS
22
+ fi
23
+
24
+ valgrind --tool=massif $MASSIF_FLAGS sage-python -i
25
+
@@ -0,0 +1,267 @@
1
+ #!python
2
+ # -*- coding: utf-8; mode: python -*-
3
+
4
+ import os
5
+ import sys
6
+ import ast
7
+ import argparse
8
+ import logging
9
+ import textwrap
10
+ from contextlib import contextmanager
11
+
12
+ logging.basicConfig()
13
+ logger = logging.getLogger()
14
+
15
+ from sage.misc.banner import banner
16
+
17
+
18
+ _system_jupyter_url = "https://doc.sagemath.org/html/en/installation/launching.html#setting-up-sagemath-as-a-jupyter-kernel-in-an-existing-jupyter-notebook-or-jupyterlab-installation"
19
+
20
+
21
+ class NotebookJupyter():
22
+
23
+ def print_banner(self):
24
+ print('Please wait while the Sage Jupyter Notebook server starts...')
25
+
26
+ @classmethod
27
+ def print_help(cls):
28
+ cls(['help'])
29
+
30
+ def __init__(self, argv):
31
+ self.print_banner()
32
+ try:
33
+ try:
34
+ # notebook 6
35
+ from notebook.notebookapp import main
36
+ except ImportError:
37
+ # notebook 7
38
+ from notebook.app import main
39
+ except ImportError:
40
+ import traceback
41
+ traceback.print_exc()
42
+ print("The Jupyter notebook is not installed (at least not in this Sage installation).")
43
+ print("You can install it by running")
44
+ print(" sage -i notebook")
45
+ print("Alternatively, you can follow the instructions at")
46
+ print(" " + _system_jupyter_url)
47
+ print("to use Sage with an existing Jupyter notebook installation.")
48
+ raise SystemExit(1)
49
+ main(argv)
50
+
51
+
52
+ class NotebookJupyterlab():
53
+ def print_banner(self):
54
+ print('Please wait while the Jupyterlab server starts...')
55
+
56
+ @classmethod
57
+ def print_help(cls):
58
+ cls(['help'])
59
+
60
+ def __init__(self, argv):
61
+ try:
62
+ from jupyterlab.labapp import main
63
+ except ImportError:
64
+ import traceback
65
+ traceback.print_exc()
66
+ print("Jupyterlab is not installed (at least not in this Sage installation).")
67
+ print("You can install it by running")
68
+ print(" sage -i jupyterlab")
69
+ print("Alternatively, you can follow the instructions at")
70
+ print(" " + _system_jupyter_url)
71
+ print("to use Sage with an existing Jupyterlab installation.")
72
+ raise SystemExit(1)
73
+ self.print_banner()
74
+ main(argv)
75
+
76
+
77
+ class SageNBExport(NotebookJupyter):
78
+
79
+ def print_banner(self):
80
+ print('Please wait while the SageNB export server starts...')
81
+
82
+ @classmethod
83
+ def print_help(cls):
84
+ cls(['--help'])
85
+
86
+ def __init__(self, argv):
87
+ if argv:
88
+ SAGENB_EXPORT = 'sagenb-export'
89
+ os.execvp(SAGENB_EXPORT, [SAGENB_EXPORT] + argv)
90
+ argv += [
91
+ "--NotebookApp.nbserver_extensions={'sagenb_export.nbextension':True}",
92
+ "--NotebookApp.default_url='/sagenb'",
93
+ ]
94
+ super(SageNBExport, self).__init__(argv)
95
+
96
+
97
+ description = \
98
+ """
99
+ The Sage notebook launcher is used to start the notebook, and allows
100
+ you to choose between different implementations. Any further command
101
+ line options are passed to the respective notebook.
102
+ """
103
+
104
+ help_help = \
105
+ """
106
+ show this help message and exit. Can be combined with
107
+ "--notebook=[...]" to see notebook-specific options
108
+ """
109
+
110
+ epilog = \
111
+ """
112
+ EXAMPLES:
113
+
114
+ * Run default notebook on port 1234.
115
+
116
+ sage -n default --port=1234
117
+ sage -n --port=1234 # equivalent
118
+
119
+ * Run Jupyter notebook in custom directory:
120
+
121
+ sage --notebook=jupyter --notebook-dir=/home/foo/bar
122
+
123
+ * List available legacy Sage notebooks:
124
+
125
+ sage --notebook=export --list
126
+
127
+ * Export a legacy Sage notebook as a Jupyter notebook:
128
+
129
+ sage --notebook=export --ipynb=Output.ipynb admin:10
130
+ """
131
+
132
+ notebook_launcher = {
133
+ 'default': NotebookJupyter, # change this to change the default
134
+ 'ipython': NotebookJupyter,
135
+ 'jupyter': NotebookJupyter,
136
+ 'jupyterlab': NotebookJupyterlab,
137
+ 'export': SageNBExport,
138
+ }
139
+
140
+ notebook_names = ', '.join(notebook_launcher.keys())
141
+
142
+
143
+ def make_parser():
144
+ """
145
+ The main parser handling the selection of the notebook.
146
+
147
+ Any arguments that are not parsed here are supposed to be handled
148
+ by the notebook implementation.
149
+ """
150
+ parser = argparse.ArgumentParser(
151
+ description=description, epilog=epilog,
152
+ formatter_class=argparse.RawDescriptionHelpFormatter,
153
+ add_help=False)
154
+ parser.add_argument('-h', '--help',
155
+ dest='option_help', action='store_true',
156
+ default=False,
157
+ help=help_help)
158
+ parser.add_argument('--log', dest='log', default=None,
159
+ help='one of [DEBUG, INFO, ERROR, WARNING, CRITICAL]')
160
+ default = None
161
+ for name, launcher in notebook_launcher.items():
162
+ if launcher == notebook_launcher['default'] and name != 'default':
163
+ default = name
164
+ if default is None:
165
+ raise RuntimeError('default launcher is defined but not known under a specific name')
166
+ parser.add_argument('--notebook', # long style
167
+ '-n', # short style
168
+ '-notebook', # wtf style, we can't decide (legacy support)
169
+ dest='notebook', type=str, nargs='?', const='default',
170
+ help='The notebook to run [one of: {0}]. Default is {1}'.format(
171
+ notebook_names, default))
172
+ return parser
173
+
174
+
175
+ def trac_23428_browser_workaround():
176
+ """
177
+ Running 'sage -n" with the Jupyter notebook on Darwin fails to
178
+ open a browser automatically. See :trac:`23428`.
179
+ """
180
+ if sys.platform != 'darwin':
181
+ return
182
+ if not os.environ.get('BROWSER', False):
183
+ os.environ['BROWSER'] = 'open'
184
+
185
+
186
+ @contextmanager
187
+ def sage_doc_server():
188
+ from functools import partial
189
+ from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
190
+ from threading import Thread
191
+ from sage.env import SAGE_DOC, SAGE_DOC_LOCAL_PORT as port
192
+
193
+ server = ThreadingHTTPServer(('127.0.0.1', int(port)),
194
+ partial(SimpleHTTPRequestHandler, directory=SAGE_DOC))
195
+
196
+ if port == '0':
197
+ port = str(server.server_address[1])
198
+ os.environ['SAGE_DOC_LOCAL_PORT'] = port
199
+
200
+ server_thread = Thread(target=server.serve_forever, name="sage_doc_server")
201
+ server_thread.start()
202
+ print(f'Sage doc server started running at http://127.0.0.1:{port}')
203
+
204
+ try:
205
+ yield
206
+ finally:
207
+ server.shutdown()
208
+ server_thread.join()
209
+ print(f'Sage doc server stopped runnning at http://127.0.0.1:{port}')
210
+
211
+
212
+ if __name__ == '__main__':
213
+ parser = make_parser()
214
+ args, unknown = parser.parse_known_args(sys.argv[1:])
215
+ if unknown and unknown[0] == '--':
216
+ unknown = unknown[1:]
217
+ trac_23428_browser_workaround()
218
+ if args.log is not None:
219
+ import logging
220
+ level = getattr(logging, args.log.upper())
221
+ logger.setLevel(level=level)
222
+ logger.info('Main parser got arguments %s', args)
223
+ logger.info('Passing on to notebook implementation: %s', unknown)
224
+
225
+ if args.notebook == "sagenb":
226
+ logger.critical('cannot use the legacy notebook SageNB with Python 3')
227
+ print('The legacy notebook does not work under Python 3; '
228
+ 'use the Jupyter notebook.')
229
+ print('See https://wiki.sagemath.org/Python3-Switch')
230
+ print('Use \"sage --notebook=export\" to export SageNB notebooks '
231
+ 'to Jupyter')
232
+ sys.exit(1)
233
+
234
+ from sage.repl.ipython_kernel.install import SageKernelSpec
235
+ SageKernelSpec.check()
236
+
237
+ try:
238
+ launcher = notebook_launcher[args.notebook]
239
+ except KeyError:
240
+ logger.critical('unknown notebook: %s', args.notebook)
241
+ print('Error, notebook must be one of {0} but got {1}'.
242
+ format(notebook_names, args.notebook))
243
+ sys.exit(1)
244
+
245
+ if args.option_help:
246
+ if args.notebook == 'default':
247
+ parser.print_help()
248
+ else:
249
+ launcher.print_help()
250
+ sys.exit(0)
251
+
252
+ banner()
253
+
254
+ # Start a Sage doc server if the Sage documentation is available locally.
255
+ # See the corresponding code in src/sage/repl/ipython_kernel/kernel.py.
256
+
257
+ from sage.env import SAGE_DOC_SERVER_URL
258
+ from sage.features.sagemath import sagemath_doc_html
259
+
260
+ if SAGE_DOC_SERVER_URL:
261
+ print(f'Sage doc server is running at {SAGE_DOC_SERVER_URL}')
262
+ launcher(unknown)
263
+ elif sagemath_doc_html().is_present():
264
+ with sage_doc_server():
265
+ launcher(unknown)
266
+ else:
267
+ launcher(unknown)
@@ -0,0 +1,25 @@
1
+ #!/bin/sh
2
+
3
+ # We reuse the gdb pythonstartup script.
4
+ PYTHONSTARTUP=`dirname $0`/sage-ipython
5
+ export PYTHONSTARTUP
6
+ echo $PYTHONSTARTUP
7
+ if [ ! -d "$DOT_SAGE/valgrind" ]; then
8
+ mkdir "$DOT_SAGE/valgrind"
9
+ fi
10
+
11
+ LOG="$DOT_SAGE"/valgrind/sage-omega.%p
12
+ echo "Log file is $LOG"
13
+
14
+ OMEGA_FLAGS="--log-file=$LOG "; export OMEGA_FLAGS
15
+ if [ "$SAGE_OMEGA_FLAGS" ]; then
16
+ echo "Overwriting omega flags with:"
17
+ echo $SAGE_OMEGA_FLAGS
18
+ OMEGA_FLAGS=$SAGE_OMEGA_FLAGS; export OMEGA_FLAGS
19
+ else
20
+ echo "Using default flags:"
21
+ echo $OMEGA_FLAGS
22
+ fi
23
+
24
+ valgrind --tool=exp-omega $OMEGA_FLAGS sage-python -i
25
+
@@ -0,0 +1,302 @@
1
+ #!python
2
+ """
3
+ Preparse .sage files and save the result to .sage.py files.
4
+
5
+ AUTHOR:
6
+ -- William Stein (2005): first version
7
+ -- William Stein (2008): fix trac #2391 and document the code.
8
+ -- Dan Drake (2009): fix trac #5052
9
+ -- Dan Drake (2010-12-08): fix trac #10440
10
+ -- Johan S. R. Nielsen (2015-11-06): fix trac #17019
11
+ """
12
+
13
+ import os
14
+ import sys
15
+ import re
16
+
17
+ from sage.repl.preparse import preparse_file
18
+ from sage.misc.temporary_file import atomic_write
19
+
20
+ # The spkg/bin/sage script passes the files to be preparsed as
21
+ # arguments (but remove sys.argv[0]).
22
+ files = sys.argv[1:]
23
+
24
+ # There must be at least 1 file or we display an error/usage message
25
+ # and exit
26
+ if not files:
27
+ print("""Usage: {} <file1.sage> <file2.sage>...
28
+ Creates files file1.sage.py, file2.sage.py ... that are the Sage
29
+ preparsed versions of file1.sage, file2.sage ...
30
+ If a non-autogenerated .sage.py file with the same name exists, you will
31
+ receive an error and the file will not be overwritten.""".format(sys.argv[0]))
32
+ sys.exit(1)
33
+
34
+ # The module-scope variable contains a list of all files we
35
+ # have seen while preparsing a given file. The point of this
36
+ # is that we want to avoid preparsing a file we have already
37
+ # seen, since then infinite loops would result from mutual
38
+ # recursive includes.
39
+ files_so_far = []
40
+
41
+ # This message is inserted in autogenerated files so that the reader
42
+ # will know, and so we know it is safe to overwrite them.
43
+ AUTOGEN_MSG = "# This file was *autogenerated* from the file "
44
+
45
+ # We use this regexp to parse lines with load or attach statements.
46
+ # Here's what it looks for:
47
+ #
48
+ # A (possibly empty) sequence of whitespace at the beginning of the
49
+ # line, saved as a group named 'lws';
50
+ #
51
+ # followed by
52
+ #
53
+ # the word "load" or "attach";
54
+ #
55
+ # followed by
56
+ #
57
+ # a nonempty sequence of whitespace;
58
+ #
59
+ # followed by
60
+ #
61
+ # whatever else is on the line, saved as a group named 'files'.
62
+ #
63
+ # We want to save the leading white space so that we can maintain
64
+ # correct indentation in the preparsed file.
65
+ load_or_attach = re.compile(r"^(?P<lws>\s*)(load|attach)\s+(?P<files>.*)$")
66
+
67
+ def do_preparse(f, files_before=[]):
68
+ """
69
+ Preparse the file f and write the result out to a filename
70
+ with extension .sage.py.
71
+
72
+ INPUT:
73
+
74
+ - ``f`` -- string: the name of a file
75
+ - ``files_before`` -- list of strings of previous filenames loaded (to avoid circular loops)
76
+
77
+ OUTPUT: none (writes a file with extension .sage.py to disk)
78
+ """
79
+ if f in files_so_far:
80
+ return
81
+ files_so_far.append(f)
82
+ if not os.path.exists(f):
83
+ print("{}: File '{}' is missing".format(sys.argv[0], f))
84
+ return
85
+ if f.endswith('.py'):
86
+ return
87
+ if not f.endswith('.sage'):
88
+ print("{}: Unknown file type {}".format(sys.argv[0], f))
89
+ sys.exit(1)
90
+
91
+ fname = f + ".py"
92
+ if os.path.exists(fname):
93
+ with open(fname) as fin:
94
+ if AUTOGEN_MSG not in fin.read():
95
+ print("Refusing to overwrite existing non-autogenerated file {!r}."
96
+ .format(os.path.abspath(fname)))
97
+ print("Please delete or move this file manually.")
98
+ sys.exit(1)
99
+
100
+ # TODO:
101
+ # I am commenting this "intelligence" out, since, e.g., if I change
102
+ # the preparser between versions this can cause problems. This
103
+ # is an optimization that definitely isn't needed at present, since
104
+ # preparsing is so fast.
105
+ # Idea: I could introduce version numbers, though....
106
+ #if os.path.exists(fname) and os.path.getmtime(fname) >= os.path.getmtime(f):
107
+ # return
108
+
109
+ # Finally open the file
110
+ with open(f) as fin:
111
+ F = fin.read()
112
+
113
+ # Check to see if a coding is specified in the .sage file. If it is,
114
+ # then we want to copy it over to the new file and not include it in
115
+ # the preprocessing. If both the first and second line have an
116
+ # encoding declaration, the second line's encoding will get used.
117
+
118
+ lines = F.splitlines()
119
+ coding = ''
120
+ for num, line in enumerate(lines[:2]):
121
+ if re.search(r"coding[:=]\s*([-\w.]+)", line):
122
+ coding = line + '\n'
123
+ F = '\n'.join(lines[:num] + lines[(num+1):])
124
+
125
+ # It is ** critical ** that all the preparser-stuff we put into
126
+ # the file are put after the module docstring, since
127
+ # otherwise the docstring will not be understood by Python.
128
+ i = find_position_right_after_module_docstring(F)
129
+ header, body = F[:i] , F[i:]
130
+ # Preparse the body
131
+ body = preparse_file(body)
132
+
133
+ # Check for "from __future__ import ..." statements. Those
134
+ # statements need to come at the top of the file (after the
135
+ # module-level docstring is okay), so we separate them from the
136
+ # body.
137
+ #
138
+ # Note: this will convert invalid Python to valid, because it will
139
+ # move all "from __future__ import ..." to the top of the file,
140
+ # even if they were not at the top originally.
141
+ future_imports, body = find_future_imports(body)
142
+
143
+ # Check for load/attach commands.
144
+ body = do_load_and_attach(body, f, files_before)
145
+
146
+ # The Sage library include line along with a autogen message
147
+ sage_incl = '%s%s\nfrom sage.all_cmdline import * # import sage library\n'%(AUTOGEN_MSG, f)
148
+
149
+ # Finally, write out the result. We use atomic_write to avoid
150
+ # race conditions (for example, the file will never be half written).
151
+ with atomic_write(fname) as f:
152
+ f.write(coding)
153
+ f.write(header)
154
+ f.write('\n')
155
+ f.write(future_imports)
156
+ f.write('\n')
157
+ f.write(sage_incl)
158
+ f.write('\n')
159
+ f.write(body)
160
+ f.write('\n')
161
+
162
+ def find_position_right_after_module_docstring(G):
163
+ """
164
+ Return first position right after the module docstring of G, if it
165
+ has one. Otherwise return 0.
166
+
167
+ INPUT:
168
+ G -- a string
169
+ OUTPUT:
170
+ an integer -- the index into G so that G[i] is right after
171
+ the module docstring of G, if G has one.
172
+ """
173
+ # The basic idea below is that we look at each line first ignoring
174
+ # all empty lines and commented out lines. Then we check to see
175
+ # if the next line is a docstring. If so, we find where that
176
+ # docstring ends.
177
+ v = G.splitlines()
178
+ i = 0
179
+ while i < len(v):
180
+ s = v[i].strip()
181
+ if s and s[0] != '#':
182
+ break
183
+ i += 1
184
+ if i >= len(v):
185
+ # No module docstring --- entire file is commented out
186
+ return 0
187
+
188
+ # Now v[i] contains the first line of the first statement in the file.
189
+ # Is it a docstring?
190
+ n = v[i].lstrip()
191
+ if not (n[0] in ['"',"'"] or n[0:2] in ['r"',"r'"]):
192
+ # not a docstring
193
+ return 0
194
+
195
+ # First line is the module docstring. Where does it end?
196
+ def pos_after_line(k):
197
+ return sum(len(v[j])+1 for j in range(k+1))
198
+
199
+ n = n.lstrip('r') # strip leading r if there is one
200
+ if n[:3] in ["'''", '"""']:
201
+ quotes = n[:3]
202
+ # possibly multiline
203
+ if quotes in n[3:]:
204
+ return pos_after_line(i)
205
+ j = i+1
206
+ while j < len(v) and quotes not in v[j]:
207
+ j += 1
208
+ return pos_after_line(j)
209
+ else:
210
+ # it must be a single line; so add up the lengths of all lines
211
+ # including this one and return that
212
+ return pos_after_line(i)
213
+
214
+
215
+ def find_future_imports(G):
216
+ """
217
+ Parse a file G as a string, looking for "from __future__ import ...".
218
+
219
+ Return a tuple: (the import statements, the file G with those
220
+ statements removed)
221
+
222
+ INPUT:
223
+ G -- a string; the contents of a file
224
+
225
+ This can only handle "from __future__ import ..." statements which
226
+ are completely on a single line: nothing of the form ::
227
+
228
+ from __future__ import \
229
+ print_function
230
+
231
+ or ::
232
+
233
+ from __future__ import (print_function,
234
+ division)
235
+
236
+ This function will raise an error if it detects lines of these forms.
237
+ """
238
+ import_statements = []
239
+ # "from __future__ import ..." should not be indented.
240
+ m = re.search("^(from __future__ import .*)$", G, re.MULTILINE)
241
+ while m:
242
+ statement = m.group(0)
243
+ # If the import statement ends in a line continuation marker
244
+ # or if it contains a left parenthesis but not a right one,
245
+ # then the statement is not complete, so raise an error. (This
246
+ # is not a perfect check and some bad cases may slip through,
247
+ # like two left parentheses and only one right parenthesis,
248
+ # but they should be rare.)
249
+ if (statement[-1] == '\\' or
250
+ (statement.find('(') > -1 and statement.find(')') == -1)):
251
+ raise NotImplementedError('the Sage preparser can only preparse "from __future__ import ..." statements which are on a single line')
252
+ import_statements.append(statement)
253
+ G = G[:m.start()] + G[m.end():]
254
+ m = re.search("^(from __future__ import .*)$", G, re.MULTILINE)
255
+ return ('\n'.join(import_statements), G)
256
+
257
+
258
+ def do_load_and_attach(G, file, files_before):
259
+ """
260
+ Parse a file G and replace load and attach statements with the
261
+ corresponding execfile() statements.
262
+
263
+ INPUT:
264
+ G -- a string; a file loaded in from disk
265
+ file -- the name of the file that contains the non-preparsed
266
+ version of G.
267
+ files_before -- list of files seen so far (don't recurse into
268
+ infinite loop)
269
+
270
+ OUTPUT:
271
+ string -- result of parsing load/attach statements in G, i.e.
272
+ modified version of G with execfiles.
273
+ """
274
+ s = ''
275
+ for t in G.split('\n'):
276
+ z = load_or_attach.match(t)
277
+ if z:
278
+ files = z.group('files').split()
279
+ lws = z.group('lws')
280
+ for w in files:
281
+ name = w.replace(',', '').replace('"', '').replace("'", "")
282
+ if name in files_before:
283
+ print("WARNING: not loading {} (in {}) again since would cause circular loop"
284
+ .format(name, file))
285
+ continue
286
+ if name.endswith('.sage'):
287
+ do_preparse(name, files_before + [file])
288
+ s += lws + "exec(compile(open({0}.py).read(), {0}.py, \
289
+ 'exec'))\n".format(name)
290
+ elif name.endswith('.py'):
291
+ s += lws + "exec(compile(open({0}).read(), {0}, \
292
+ 'exec'))\n".format(name)
293
+ else:
294
+ s += t + '\n'
295
+ return s
296
+
297
+
298
+ # Here we do the actual work. We iterate over ever
299
+ # file in the input args and create the corresponding
300
+ # output file.
301
+ for f in files:
302
+ do_preparse(f)