passagemath-repl 10.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. passagemath_repl-10.5.1.data/scripts/sage-cachegrind +25 -0
  2. passagemath_repl-10.5.1.data/scripts/sage-callgrind +16 -0
  3. passagemath_repl-10.5.1.data/scripts/sage-cleaner +230 -0
  4. passagemath_repl-10.5.1.data/scripts/sage-coverage +327 -0
  5. passagemath_repl-10.5.1.data/scripts/sage-eval +14 -0
  6. passagemath_repl-10.5.1.data/scripts/sage-fixdoctests +710 -0
  7. passagemath_repl-10.5.1.data/scripts/sage-inline-fortran +12 -0
  8. passagemath_repl-10.5.1.data/scripts/sage-ipynb2rst +50 -0
  9. passagemath_repl-10.5.1.data/scripts/sage-ipython +16 -0
  10. passagemath_repl-10.5.1.data/scripts/sage-massif +25 -0
  11. passagemath_repl-10.5.1.data/scripts/sage-notebook +267 -0
  12. passagemath_repl-10.5.1.data/scripts/sage-omega +25 -0
  13. passagemath_repl-10.5.1.data/scripts/sage-preparse +302 -0
  14. passagemath_repl-10.5.1.data/scripts/sage-run +27 -0
  15. passagemath_repl-10.5.1.data/scripts/sage-run-cython +10 -0
  16. passagemath_repl-10.5.1.data/scripts/sage-runtests +9 -0
  17. passagemath_repl-10.5.1.data/scripts/sage-startuptime.py +163 -0
  18. passagemath_repl-10.5.1.data/scripts/sage-valgrind +34 -0
  19. passagemath_repl-10.5.1.dist-info/METADATA +77 -0
  20. passagemath_repl-10.5.1.dist-info/RECORD +162 -0
  21. passagemath_repl-10.5.1.dist-info/WHEEL +5 -0
  22. passagemath_repl-10.5.1.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 +134 -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 +249 -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/all.py +0 -0
  143. sage/tests/all__sagemath_repl.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 +1925 -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 +796 -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,361 @@
1
+ # sage_setup: distribution = sagemath-repl
2
+ # sage.doctest: needs sage.symbolic
3
+ """
4
+ C Function Profiler Using Google Perftools
5
+
6
+ Note that the profiler samples 100x per second by default. In
7
+ particular, you cannot profile anything shorter than 10ms. You can
8
+ adjust the rate with the ``CPUPROFILE_FREQUENCY`` environment variable
9
+ if you want to change it.
10
+
11
+ EXAMPLES::
12
+
13
+ sage: from sage.misc.gperftools import Profiler, run_100ms
14
+ sage: prof = Profiler()
15
+ sage: prof.start() # optional - gperftools
16
+ sage: run_100ms()
17
+ sage: prof.stop() # optional - gperftools
18
+ PROFILE: interrupts/evictions/bytes = ...
19
+
20
+ REFERENCE:
21
+
22
+ Uses the `Google performance analysis tools
23
+ <https://github.com/gperftools/gperftools>`_. Note that they are not
24
+ included in Sage, you have to install them yourself on your system.
25
+
26
+ AUTHORS:
27
+
28
+ - Volker Braun (2014-03-31): initial version
29
+ """
30
+
31
+ # ****************************************************************************
32
+ # Copyright (C) 2014 Volker Braun <vbraun.name@gmail.com>
33
+ #
34
+ # Distributed under the terms of the GNU General Public License (GPL)
35
+ #
36
+ # https://www.gnu.org/licenses/
37
+ # ****************************************************************************
38
+
39
+ import sys
40
+ import ctypes
41
+ import time
42
+ from sage.structure.sage_object import SageObject
43
+ from sage.misc.cachefunc import cached_method
44
+ from sage.misc.compat import find_library
45
+ from sage.cpython.string import bytes_to_str
46
+
47
+
48
+ libc = None
49
+ libprofiler = None
50
+
51
+
52
+ class Profiler(SageObject):
53
+
54
+ def __init__(self, filename=None):
55
+ """
56
+ Interface to the gperftools profiler.
57
+
58
+ INPUT:
59
+
60
+ - ``filename`` -- string or ``None`` (default). The file name
61
+ to log to. By default, a new temporary file is created.
62
+
63
+ EXAMPLES::
64
+
65
+ sage: from sage.misc.gperftools import Profiler
66
+ sage: Profiler()
67
+ Profiler logging to ...
68
+ """
69
+ if filename is None:
70
+ from sage.misc.temporary_file import tmp_filename
71
+ self._filename = tmp_filename(ext='.perf')
72
+ else:
73
+ self._filename = filename
74
+
75
+ def filename(self):
76
+ """
77
+ Return the file name.
78
+
79
+ OUTPUT: string
80
+
81
+ EXAMPLES::
82
+
83
+ sage: from sage.misc.gperftools import Profiler
84
+ sage: prof = Profiler()
85
+ sage: prof.filename()
86
+ '.../tmp_....perf'
87
+ """
88
+ return self._filename
89
+
90
+ def _repr_(self):
91
+ """
92
+ Return string representation.
93
+
94
+ OUTPUT: string
95
+
96
+ EXAMPLES::
97
+
98
+ sage: from sage.misc.gperftools import Profiler
99
+ sage: Profiler()
100
+ Profiler logging to .../tmp....perf
101
+ """
102
+ return 'Profiler logging to {0}'.format(self.filename())
103
+
104
+ def _libprofiler(self):
105
+ """
106
+ Return libprofiler.
107
+
108
+ OUTPUT: a ctypes shared library handle
109
+
110
+ EXAMPLES::
111
+
112
+ sage: from sage.misc.gperftools import Profiler
113
+ sage: Profiler()._libprofiler() # optional - gperftools
114
+ <CDLL 'libprofiler...', handle ... at ...>
115
+ """
116
+ global libprofiler
117
+ if libprofiler is not None:
118
+ return libprofiler
119
+ import ctypes.util
120
+ name = ctypes.util.find_library('profiler')
121
+ if name:
122
+ libprofiler = ctypes.CDLL(name)
123
+ return libprofiler
124
+ else:
125
+ raise ImportError('failed to open libprofiler, make sure gperftools is installed')
126
+
127
+ def start(self):
128
+ """
129
+ Start profiling.
130
+
131
+ EXAMPLES::
132
+
133
+ sage: from sage.misc.gperftools import Profiler, run_100ms
134
+ sage: prof = Profiler()
135
+ sage: prof.start() # optional - gperftools
136
+ sage: run_100ms()
137
+ sage: prof.stop() # optional - gperftools
138
+ PROFILE: interrupts/evictions/bytes = ...
139
+ """
140
+ from signal import SIGPROF, SIG_DFL
141
+ from cysignals.pysignals import setossignal
142
+ self._previous_sigprof_handler = setossignal(SIGPROF, SIG_DFL)
143
+ profiler = self._libprofiler()
144
+ self._t_start = time.time()
145
+ rc = profiler.ProfilerStart(str.encode(self.filename()))
146
+ if rc < 0:
147
+ raise ValueError('profiler failed to start')
148
+
149
+ def stop(self):
150
+ """
151
+ Stop the CPU profiler.
152
+
153
+ EXAMPLES::
154
+
155
+ sage: from sage.misc.gperftools import Profiler, run_100ms
156
+ sage: prof = Profiler()
157
+ sage: prof.start() # optional - gperftools
158
+ sage: run_100ms()
159
+ sage: prof.stop() # optional - gperftools
160
+ PROFILE: interrupts/evictions/bytes = ...
161
+ """
162
+ profiler = self._libprofiler()
163
+ profiler.ProfilerStop()
164
+ self._t_stop = time.time()
165
+ if (self._t_stop - self._t_start) < 0.1:
166
+ from warnings import warn
167
+ warn('not enough samples, total runtime was '
168
+ 'less than 100ms', RuntimeWarning)
169
+
170
+ @cached_method
171
+ def _pprof(self):
172
+ """
173
+ Return the name of the ``pprof`` binary.
174
+
175
+ OUTPUT:
176
+
177
+ String. The name of the gperftools ``pprof`` utility. A
178
+ :exc:`OSError` is raised if it cannot be found.
179
+
180
+ EXAMPLES::
181
+
182
+ sage: from sage.misc.gperftools import Profiler
183
+ sage: prof = Profiler()
184
+ sage: try:
185
+ ....: pp = prof._pprof()
186
+ ....: assert isinstance(pp, str)
187
+ ....: except OSError:
188
+ ....: pass # not installed
189
+ """
190
+ potential_names = ['google-pprof', 'pprof']
191
+ from subprocess import check_output, CalledProcessError, STDOUT
192
+ for name in potential_names:
193
+ try:
194
+ version = check_output([name, '--version'], stderr=STDOUT)
195
+ except (CalledProcessError, OSError):
196
+ continue
197
+ version = bytes_to_str(version)
198
+ if 'gperftools' not in version:
199
+ from warnings import warn
200
+ warn('the "{0}" utility does not appear to be the gperftools profiler'
201
+ .format(name), RuntimeWarning)
202
+ continue
203
+ return name
204
+ raise OSError('unable to run pprof, please install gperftools')
205
+
206
+ def _executable(self):
207
+ """
208
+ Return the name of the Sage Python interpreter.
209
+
210
+ OUTPUT: string
211
+
212
+ EXAMPLES::
213
+
214
+ sage: from sage.misc.gperftools import Profiler
215
+ sage: prof = Profiler()
216
+ sage: prof._executable()
217
+ '.../python...'
218
+ """
219
+ return sys.executable
220
+
221
+ def _call_pprof(self, *args, **kwds):
222
+ """
223
+ Run the pprof binary.
224
+
225
+ INPUT:
226
+
227
+ - ``args`` -- list of strings; the arguments to ``pprof``
228
+
229
+ - ``kwds`` -- keyword arguments passed to ``subprocess.check_call``
230
+
231
+ EXAMPLES::
232
+
233
+ sage: from sage.misc.gperftools import Profiler
234
+ sage: prof = Profiler()
235
+ sage: prof._call_pprof('--help') # optional - gperftools
236
+ Usage:
237
+ pprof [options] <program> <profiles>
238
+ ...
239
+ """
240
+ from subprocess import check_call
241
+ check_call([self._pprof()] + list(args), **kwds)
242
+
243
+ def top(self, cumulative=True):
244
+ """
245
+ Print text report.
246
+
247
+ OUTPUT: nothing; a textual report is printed to stdout
248
+
249
+ EXAMPLES::
250
+
251
+ sage: from sage.misc.gperftools import Profiler
252
+ sage: prof = Profiler()
253
+ sage: prof.start() # optional - gperftools
254
+ sage: # do something
255
+ sage: prof.stop() # optional - gperftools
256
+ PROFILE: interrupts/evictions/bytes = ...
257
+ sage: prof.top() # optional - gperftools
258
+ Using local file ...
259
+ Using local file ...
260
+ """
261
+ args = []
262
+ if cumulative:
263
+ args += ['--cum']
264
+ args += ['--text', self._executable(), self.filename()]
265
+ self._call_pprof(*args)
266
+
267
+ def save(self, filename, cumulative=True, verbose=True):
268
+ """
269
+ Save report to disk.
270
+
271
+ INPUT:
272
+
273
+ - ``filename`` -- string; the filename to save at. Must end
274
+ with one of ``.dot``, ``.ps``, ``.pdf``, ``.svg``, ``.gif``,
275
+ or ``.txt`` to specify the output file format.
276
+
277
+ - ``cumulative`` -- boolean (default: ``True``); whether to return
278
+ cumulative timings
279
+
280
+ - ``verbose`` -- boolean (default: ``True``); whether to print
281
+ informational messages
282
+
283
+ EXAMPLES::
284
+
285
+ sage: from sage.misc.gperftools import Profiler, run_100ms
286
+ sage: prof = Profiler()
287
+ sage: prof.start() # optional - gperftools
288
+ sage: run_100ms() # optional - gperftools
289
+ sage: prof.stop() # optional - gperftools
290
+ PROFILE: interrupts/evictions/bytes = ...
291
+ sage: f = tmp_filename(ext='.txt') # optional - gperftools
292
+ sage: prof.save(f, verbose=False) # optional - gperftools
293
+ """
294
+ args = []
295
+ if cumulative:
296
+ args += ['--cum']
297
+ if filename.endswith('.dot'):
298
+ args += ['--dot']
299
+ elif filename.endswith('.ps'):
300
+ args += ['--ps']
301
+ elif filename.endswith('.pdf'):
302
+ args += ['--pdf']
303
+ elif filename.endswith('.svg'):
304
+ args += ['--svg']
305
+ elif filename.endswith('.txt'):
306
+ args += ['--text']
307
+ elif filename.endswith('.gif'):
308
+ args += ['--gif']
309
+ else:
310
+ raise ValueError('unknown extension')
311
+ args += [self._executable(), self.filename()]
312
+ stderr = sys.stdout if verbose else False
313
+ with open(filename, 'wb') as outfile:
314
+ self._call_pprof(*args, stdout=outfile, stderr=stderr)
315
+
316
+
317
+ def crun(s, evaluator):
318
+ """
319
+ Profile single statement.
320
+
321
+ - ``s`` -- string; Sage code to profile
322
+
323
+ - ``evaluator`` -- callable to evaluate
324
+
325
+ EXAMPLES::
326
+
327
+ sage: import sage.misc.gperftools as gperf
328
+ sage: ev = lambda ex:eval(ex, globals(), locals())
329
+ sage: gperf.crun('gperf.run_100ms()', evaluator=ev) # optional - gperftools
330
+ PROFILE: interrupts/evictions/bytes = ...
331
+ Using local file ...
332
+ Using local file ...
333
+ """
334
+ prof = Profiler()
335
+ from sage.repl.preparse import preparse
336
+ py_s = preparse(s)
337
+ prof.start()
338
+ try:
339
+ evaluator(py_s)
340
+ finally:
341
+ prof.stop()
342
+ prof.top()
343
+
344
+
345
+ def run_100ms():
346
+ """
347
+ Used for doctesting.
348
+
349
+ A function that performs some computation for more than (but not
350
+ that much more than) 100ms.
351
+
352
+ EXAMPLES::
353
+
354
+ sage: from sage.misc.gperftools import run_100ms
355
+ sage: run_100ms()
356
+ """
357
+ t0 = time.time() # start
358
+ t1 = t0 + 0.1 # end
359
+ from sage.symbolic.ring import SR
360
+ while time.time() < t1:
361
+ sum(1 / (1 + SR(n) ** 2) for n in range(100))
@@ -0,0 +1,212 @@
1
+ # sage_setup: distribution = sagemath-repl
2
+ """
3
+ Fortran compiler
4
+ """
5
+
6
+ import importlib
7
+ import os
8
+ import shutil
9
+ import subprocess
10
+ import sys
11
+
12
+ from sage.misc.temporary_file import tmp_dir
13
+
14
+
15
+ def _import_module_from_path(name, path=None):
16
+ """
17
+ Import the module named ``name`` by searching the given path entries (or
18
+ `sys.path` by default).
19
+
20
+ Returns a fully executed module object without inserting that module into
21
+ `sys.modules`.
22
+
23
+ EXAMPLES::
24
+
25
+ sage: from sage.misc.inline_fortran import _import_module_from_path
26
+ sage: modname = '___test__import_module_from_path'
27
+ sage: tmpdir = tmp_dir()
28
+ sage: filename = os.path.join(tmpdir, modname + '.py')
29
+ sage: with open(filename, 'w') as fobj:
30
+ ....: _ = fobj.write('foo = "bar"')
31
+ sage: mod = _import_module_from_path(modname)
32
+ Traceback (most recent call last):
33
+ ...
34
+ ImportError: No module named ___test__import_module_from_path
35
+ sage: mod = _import_module_from_path('DoEsNoTeXiSt', path=[tmpdir])
36
+ Traceback (most recent call last):
37
+ ...
38
+ ImportError: No module named DoEsNoTeXiSt
39
+ sage: mod = _import_module_from_path(modname, path=[tmpdir])
40
+ sage: mod.foo
41
+ 'bar'
42
+ """
43
+
44
+ if path is None:
45
+ path = sys.path
46
+
47
+ return _import_module_from_path_impl(name, path)
48
+
49
+
50
+ def _import_module_from_path_impl(name, path):
51
+ """Implement ``_import_module_from_path`` for Python 3.4+."""
52
+
53
+ # This is remarkably tricky to do right, considering that the new
54
+ # importlib is supposed to make direct interaction with the import
55
+ # system easier. I blame the ModuleSpec stuff...
56
+ finder = importlib.machinery.PathFinder()
57
+ spec = finder.find_spec(name, path=path)
58
+ if spec is None:
59
+ raise ImportError('No module named {}'.format(name))
60
+ mod = importlib.util.module_from_spec(spec)
61
+ spec.loader.exec_module(mod)
62
+ return mod
63
+
64
+
65
+ class InlineFortran:
66
+ def __init__(self, globals=None):
67
+ # globals=None means: use user globals from REPL
68
+ self.globs = globals
69
+ self.library_paths = []
70
+ self.libraries = []
71
+ self.verbose = False
72
+
73
+ def __repr__(self):
74
+ return "Interface to Fortran compiler"
75
+
76
+ def __call__(self, *args, **kwds):
77
+ return self.eval(*args, **kwds)
78
+
79
+ def eval(self, x, globals=None, locals=None):
80
+ """
81
+ Compile fortran code ``x`` and adds the functions in it to ``globals``.
82
+
83
+ INPUT:
84
+
85
+ - ``x`` -- fortran code
86
+
87
+ - ``globals`` -- dictionary to which to add the functions from the
88
+ fortran module
89
+
90
+ - ``locals`` -- ignored
91
+
92
+ EXAMPLES::
93
+
94
+ sage: # needs numpy
95
+ sage: code = '''
96
+ ....: C FILE: FIB1.F
97
+ ....: SUBROUTINE FIB(A,N)
98
+ ....: C
99
+ ....: C CALCULATE FIRST N FIBONACCI NUMBERS
100
+ ....: C
101
+ ....: INTEGER N
102
+ ....: REAL*8 A(N)
103
+ ....: DO I=1,N
104
+ ....: IF (I.EQ.1) THEN
105
+ ....: A(I) = 0.0D0
106
+ ....: ELSEIF (I.EQ.2) THEN
107
+ ....: A(I) = 1.0D0
108
+ ....: ELSE
109
+ ....: A(I) = A(I-1) + A(I-2)
110
+ ....: ENDIF
111
+ ....: ENDDO
112
+ ....: END
113
+ ....: C END FILE FIB1.F
114
+ ....: '''
115
+ sage: fortran(code, globals())
116
+ sage: import numpy
117
+ sage: a = numpy.array(range(10), dtype=float)
118
+ sage: fib(a, 10)
119
+ sage: a
120
+ array([ 0., 1., 1., 2., 3., 5., 8., 13., 21., 34.])
121
+
122
+ TESTS::
123
+
124
+ sage: os.chdir(DOT_SAGE)
125
+ sage: fortran.eval("SYNTAX ERROR !@#$")
126
+ Traceback (most recent call last):
127
+ ...
128
+ RuntimeError: failed to compile Fortran code:...
129
+ sage: os.getcwd() == os.path.realpath(DOT_SAGE)
130
+ True
131
+ """
132
+ if globals is None:
133
+ globals = self.globs
134
+ if globals is None:
135
+ from sage.repl.user_globals import get_globals
136
+ globals = get_globals()
137
+
138
+ # Create everything in a temporary directory
139
+ mytmpdir = tmp_dir()
140
+
141
+ try:
142
+ old_cwd = os.getcwd()
143
+ os.chdir(mytmpdir)
144
+
145
+ name = "fortran_module" # Python module name
146
+ # if the first line has !f90 as a comment, gfortran will
147
+ # treat it as Fortran 90 code
148
+ if x.startswith('!f90'):
149
+ fortran_file = name + '.f90'
150
+ else:
151
+ fortran_file = name + '.f'
152
+
153
+ s_lib_path = ['-L' + p for p in self.library_paths]
154
+ s_lib = ['-l' + l for l in self.libraries]
155
+
156
+ with open(fortran_file, 'w') as fobj:
157
+ fobj.write(x)
158
+
159
+ # This is basically the same as what f2py.compile() does, but we
160
+ # do it manually here in order to customize running the subprocess
161
+ # a bit more (in particular to capture stderr)
162
+ cmd = [sys.executable, '-c', 'import numpy.f2py; numpy.f2py.main()']
163
+
164
+ # What follows are the arguments to f2py itself (appended later
165
+ # just for logical separation)
166
+ cmd += ['-c', '-m', name, fortran_file, '--quiet',
167
+ '--f77exec=sage-inline-fortran',
168
+ '--f90exec=sage-inline-fortran'] + s_lib_path + s_lib
169
+
170
+ try:
171
+ out = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
172
+ except subprocess.CalledProcessError as exc:
173
+ raise RuntimeError(
174
+ "failed to compile Fortran code:\n{}".format(exc.output))
175
+
176
+ # Note that f2py() doesn't raise an exception if it fails.
177
+ # In that case, the import below will fail.
178
+ try:
179
+ mod = _import_module_from_path(name, [mytmpdir])
180
+ except ImportError as exc:
181
+ # Failed to import the module; include any output from building
182
+ # the module (even though it was ostensibly successful) in case
183
+ # it might help
184
+ msg = "failed to load compiled Fortran code: {}".format(exc)
185
+ if out:
186
+ msg += '\n' + out
187
+ raise RuntimeError(msg)
188
+
189
+ if self.verbose:
190
+ print(out)
191
+ finally:
192
+ os.chdir(old_cwd)
193
+
194
+ try:
195
+ shutil.rmtree(mytmpdir)
196
+ except OSError:
197
+ # This can fail for example over NFS
198
+ pass
199
+
200
+ for k, x in mod.__dict__.items():
201
+ if k[0] != '_':
202
+ globals[k] = x
203
+
204
+ def add_library(self, s):
205
+ self.libraries.append(s)
206
+
207
+ def add_library_path(self, s):
208
+ self.library_paths.append(s)
209
+
210
+
211
+ # An instance
212
+ fortran = InlineFortran()
sage/misc/messaging.py ADDED
@@ -0,0 +1,86 @@
1
+ # sage_setup: distribution = sagemath-repl
2
+ """
3
+ Message delivery
4
+
5
+ Various interfaces to messaging services. Currently:
6
+
7
+ - ``pushover`` -- a platform for sending and receiving push notifications
8
+
9
+ is supported.
10
+
11
+ AUTHORS:
12
+
13
+ - Martin Albrecht (2012) - initial implementation
14
+ """
15
+
16
+ import http.client as httplib
17
+ from urllib.parse import urlencode
18
+ from ssl import create_default_context as default_context
19
+
20
+ pushover_defaults = {"token": "Eql67F14ohOZJ0AtEBJJU7FiLAk8wK"}
21
+
22
+
23
+ def pushover(message, **kwds):
24
+ """
25
+ Send a push notification with ``message`` to ``user`` using https://pushover.net/.
26
+
27
+ Pushover is a platform for sending and receiving push notifications. On the server side, it
28
+ provides an HTTP API for queueing messages to deliver to devices. On the device side, iOS and
29
+ Android clients receive those push notifications, show them to the user, and store them for
30
+ offline viewing.
31
+
32
+ An account on https://pushover.net is required and the Pushover app must be installed on your
33
+ phone for this function to be able to deliver messages to you.
34
+
35
+ INPUT:
36
+
37
+ - ``message`` -- your message
38
+
39
+ - ``user`` -- the user key (not e-mail address) of your user (or you), viewable when logged
40
+ into the Pushover dashboard. (default: ``None``)
41
+
42
+ - ``device`` -- your user's device identifier to send the message directly to that device,
43
+ rather than all of the user's devices (default: ``None``)
44
+
45
+ - ``title`` -- your message's title, otherwise uses your app's name (default: ``None``)
46
+
47
+ - ``url`` -- a supplementary URL to show with your message (default: ``None``)
48
+
49
+ - ``url_title`` -- a title for your supplementary URL (default: ``None``)
50
+
51
+ - ``priority`` -- set to 1 to display as high-priority and bypass quiet hours, or -1 to always
52
+ send as a quiet notification (default: ``0``)
53
+
54
+ - ``timestamp`` -- set to a unix timestamp to have your message show with a particular time,
55
+ rather than now (default: ``None``)
56
+
57
+ - ``sound`` -- set to the name of one of the sounds supported by device clients to override the
58
+ user's default sound choice (default: ``None``)
59
+
60
+ - ``token`` -- your application's API token (default: Sage's default App token)
61
+
62
+ EXAMPLES::
63
+
64
+ sage: import sage.misc.messaging
65
+ sage: sage.misc.messaging.pushover("Hi, how are you?", user="XXX") # not tested
66
+
67
+ To set default values populate ``pushover_defaults``::
68
+
69
+ sage: sage.misc.messaging.pushover_defaults["user"] = "USER_TOKEN"
70
+ sage: sage.misc.messaging.pushover("Hi, how are you?") # not tested
71
+
72
+ .. NOTE::
73
+
74
+ You may want to populate ``sage.misc.messaging.pushover_defaults`` with default values such
75
+ as the default user in ``$HOME/.sage/init.sage``.
76
+ """
77
+ request = {"message": message}
78
+ request.update(pushover_defaults)
79
+ request.update(kwds)
80
+
81
+ conn = httplib.HTTPSConnection("api.pushover.net:443",
82
+ context=default_context())
83
+ conn.request("POST", "/1/messages.json",
84
+ urlencode(request),
85
+ {"Content-type": "application/x-www-form-urlencoded"})
86
+ return conn.getresponse().status == 200
sage/misc/pager.py ADDED
@@ -0,0 +1,21 @@
1
+ # sage_setup: distribution = sagemath-repl
2
+ """
3
+ Pager for showing strings
4
+
5
+ Currently we just use the IPython pager.
6
+ If we want to use something else, we can just change this function.
7
+
8
+ Any code in sage that uses a pager should use this pager.
9
+ """
10
+ # ---------------------------------------------------------------------------
11
+ # Copyright (C) 2006 William Stein <wstein@gmail.com>
12
+ #
13
+ # Distributed under the terms of the GNU General Public License (GPL)
14
+ #
15
+ # https://www.gnu.org/licenses/
16
+ # ---------------------------------------------------------------------------
17
+
18
+
19
+ def pager():
20
+ import IPython.core.page
21
+ return IPython.core.page.page