passagemath-repl 10.4.62__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_repl-10.4.62.data/scripts/sage-cachegrind +25 -0
- passagemath_repl-10.4.62.data/scripts/sage-callgrind +16 -0
- passagemath_repl-10.4.62.data/scripts/sage-cleaner +230 -0
- passagemath_repl-10.4.62.data/scripts/sage-coverage +327 -0
- passagemath_repl-10.4.62.data/scripts/sage-eval +14 -0
- passagemath_repl-10.4.62.data/scripts/sage-fixdoctests +708 -0
- passagemath_repl-10.4.62.data/scripts/sage-inline-fortran +12 -0
- passagemath_repl-10.4.62.data/scripts/sage-ipynb2rst +50 -0
- passagemath_repl-10.4.62.data/scripts/sage-ipython +16 -0
- passagemath_repl-10.4.62.data/scripts/sage-massif +25 -0
- passagemath_repl-10.4.62.data/scripts/sage-notebook +267 -0
- passagemath_repl-10.4.62.data/scripts/sage-omega +25 -0
- passagemath_repl-10.4.62.data/scripts/sage-preparse +302 -0
- passagemath_repl-10.4.62.data/scripts/sage-run +27 -0
- passagemath_repl-10.4.62.data/scripts/sage-run-cython +10 -0
- passagemath_repl-10.4.62.data/scripts/sage-runtests +9 -0
- passagemath_repl-10.4.62.data/scripts/sage-startuptime.py +163 -0
- passagemath_repl-10.4.62.data/scripts/sage-valgrind +34 -0
- passagemath_repl-10.4.62.dist-info/METADATA +77 -0
- passagemath_repl-10.4.62.dist-info/RECORD +162 -0
- passagemath_repl-10.4.62.dist-info/WHEEL +5 -0
- passagemath_repl-10.4.62.dist-info/top_level.txt +1 -0
- sage/all__sagemath_repl.py +119 -0
- sage/doctest/__init__.py +4 -0
- sage/doctest/__main__.py +236 -0
- sage/doctest/all.py +4 -0
- sage/doctest/check_tolerance.py +261 -0
- sage/doctest/control.py +1727 -0
- sage/doctest/external.py +534 -0
- sage/doctest/fixtures.py +383 -0
- sage/doctest/forker.py +2665 -0
- sage/doctest/marked_output.py +102 -0
- sage/doctest/parsing.py +1708 -0
- sage/doctest/parsing_test.py +79 -0
- sage/doctest/reporting.py +733 -0
- sage/doctest/rif_tol.py +124 -0
- sage/doctest/sources.py +1657 -0
- sage/doctest/test.py +584 -0
- sage/doctest/tests/1second.rst +4 -0
- sage/doctest/tests/99seconds.rst +4 -0
- sage/doctest/tests/abort.rst +5 -0
- sage/doctest/tests/atexit.rst +7 -0
- sage/doctest/tests/fail_and_die.rst +6 -0
- sage/doctest/tests/initial.rst +15 -0
- sage/doctest/tests/interrupt.rst +7 -0
- sage/doctest/tests/interrupt_diehard.rst +14 -0
- sage/doctest/tests/keyboardinterrupt.rst +11 -0
- sage/doctest/tests/longtime.rst +5 -0
- sage/doctest/tests/nodoctest +5 -0
- sage/doctest/tests/random_seed.rst +4 -0
- sage/doctest/tests/show_skipped.rst +18 -0
- sage/doctest/tests/sig_on.rst +9 -0
- sage/doctest/tests/simple_failure.rst +8 -0
- sage/doctest/tests/sleep_and_raise.rst +106 -0
- sage/doctest/tests/tolerance.rst +31 -0
- sage/doctest/util.py +750 -0
- sage/interfaces/cleaner.py +48 -0
- sage/interfaces/quit.py +163 -0
- sage/misc/all__sagemath_repl.py +51 -0
- sage/misc/banner.py +235 -0
- sage/misc/benchmark.py +221 -0
- sage/misc/classgraph.py +131 -0
- sage/misc/copying.py +22 -0
- sage/misc/cython.py +694 -0
- sage/misc/dev_tools.py +745 -0
- sage/misc/edit_module.py +304 -0
- sage/misc/explain_pickle.py +3079 -0
- sage/misc/gperftools.py +361 -0
- sage/misc/inline_fortran.py +212 -0
- sage/misc/messaging.py +86 -0
- sage/misc/pager.py +21 -0
- sage/misc/profiler.py +179 -0
- sage/misc/python.py +70 -0
- sage/misc/remote_file.py +53 -0
- sage/misc/sage_eval.py +246 -0
- sage/misc/sage_input.py +3621 -0
- sage/misc/sagedoc.py +1742 -0
- sage/misc/sh.py +38 -0
- sage/misc/trace.py +90 -0
- sage/repl/__init__.py +16 -0
- sage/repl/all.py +15 -0
- sage/repl/attach.py +625 -0
- sage/repl/configuration.py +186 -0
- sage/repl/display/__init__.py +1 -0
- sage/repl/display/fancy_repr.py +354 -0
- sage/repl/display/formatter.py +318 -0
- sage/repl/display/jsmol_iframe.py +290 -0
- sage/repl/display/pretty_print.py +153 -0
- sage/repl/display/util.py +163 -0
- sage/repl/image.py +302 -0
- sage/repl/inputhook.py +91 -0
- sage/repl/interface_magic.py +298 -0
- sage/repl/interpreter.py +854 -0
- sage/repl/ipython_extension.py +593 -0
- sage/repl/ipython_kernel/__init__.py +1 -0
- sage/repl/ipython_kernel/__main__.py +4 -0
- sage/repl/ipython_kernel/all_jupyter.py +10 -0
- sage/repl/ipython_kernel/install.py +301 -0
- sage/repl/ipython_kernel/interact.py +278 -0
- sage/repl/ipython_kernel/kernel.py +217 -0
- sage/repl/ipython_kernel/widgets.py +466 -0
- sage/repl/ipython_kernel/widgets_sagenb.py +587 -0
- sage/repl/ipython_tests.py +163 -0
- sage/repl/load.py +326 -0
- sage/repl/preparse.py +2218 -0
- sage/repl/prompts.py +90 -0
- sage/repl/rich_output/__init__.py +4 -0
- sage/repl/rich_output/backend_base.py +648 -0
- sage/repl/rich_output/backend_doctest.py +316 -0
- sage/repl/rich_output/backend_emacs.py +151 -0
- sage/repl/rich_output/backend_ipython.py +596 -0
- sage/repl/rich_output/buffer.py +311 -0
- sage/repl/rich_output/display_manager.py +829 -0
- sage/repl/rich_output/example.avi +0 -0
- sage/repl/rich_output/example.canvas3d +1 -0
- sage/repl/rich_output/example.dvi +0 -0
- sage/repl/rich_output/example.flv +0 -0
- sage/repl/rich_output/example.gif +0 -0
- sage/repl/rich_output/example.jpg +0 -0
- sage/repl/rich_output/example.mkv +0 -0
- sage/repl/rich_output/example.mov +0 -0
- sage/repl/rich_output/example.mp4 +0 -0
- sage/repl/rich_output/example.ogv +0 -0
- sage/repl/rich_output/example.pdf +0 -0
- sage/repl/rich_output/example.png +0 -0
- sage/repl/rich_output/example.svg +54 -0
- sage/repl/rich_output/example.webm +0 -0
- sage/repl/rich_output/example.wmv +0 -0
- sage/repl/rich_output/example_jmol.spt.zip +0 -0
- sage/repl/rich_output/example_wavefront_scene.mtl +7 -0
- sage/repl/rich_output/example_wavefront_scene.obj +17 -0
- sage/repl/rich_output/output_basic.py +391 -0
- sage/repl/rich_output/output_browser.py +103 -0
- sage/repl/rich_output/output_catalog.py +54 -0
- sage/repl/rich_output/output_graphics.py +320 -0
- sage/repl/rich_output/output_graphics3d.py +345 -0
- sage/repl/rich_output/output_video.py +231 -0
- sage/repl/rich_output/preferences.py +432 -0
- sage/repl/rich_output/pretty_print.py +339 -0
- sage/repl/rich_output/test_backend.py +201 -0
- sage/repl/user_globals.py +214 -0
- sage/tests/__init__.py +1 -0
- sage/tests/all.py +3 -0
- sage/tests/article_heuberger_krenn_kropf_fsm-in-sage.py +630 -0
- sage/tests/arxiv_0812_2725.py +351 -0
- sage/tests/benchmark.py +1923 -0
- sage/tests/book_schilling_zabrocki_kschur_primer.py +795 -0
- sage/tests/book_stein_ent.py +651 -0
- sage/tests/book_stein_modform.py +558 -0
- sage/tests/cmdline.py +790 -0
- sage/tests/combinatorial_hopf_algebras.py +52 -0
- sage/tests/finite_poset.py +623 -0
- sage/tests/functools_partial_src.py +27 -0
- sage/tests/gosper-sum.py +218 -0
- sage/tests/lazy_imports.py +28 -0
- sage/tests/modular_group_cohomology.py +80 -0
- sage/tests/numpy.py +21 -0
- sage/tests/parigp.py +76 -0
- sage/tests/startup.py +27 -0
- sage/tests/symbolic-series.py +76 -0
- sage/tests/sympy.py +16 -0
- sage/tests/test_deprecation.py +31 -0
@@ -0,0 +1,163 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-repl
|
2
|
+
'''
|
3
|
+
Tests for the IPython integration
|
4
|
+
|
5
|
+
First, test the pinfo magic for Python code. This is what IPython
|
6
|
+
calls when you ask for the single-questionmark help, like `foo?` ::
|
7
|
+
|
8
|
+
sage: from sage.repl.interpreter import get_test_shell
|
9
|
+
sage: shell = get_test_shell()
|
10
|
+
sage: shell.run_cell(u'from sage.repl.ipython_tests import dummy')
|
11
|
+
sage: shell.run_cell(u'%pinfo dummy')
|
12
|
+
Signature: dummy(argument, optional=None)
|
13
|
+
Docstring:
|
14
|
+
Dummy Docstring Title.
|
15
|
+
<BLANKLINE>
|
16
|
+
Dummy docstring explanation.
|
17
|
+
<BLANKLINE>
|
18
|
+
INPUT:
|
19
|
+
<BLANKLINE>
|
20
|
+
... "argument" -- anything; dummy argument
|
21
|
+
<BLANKLINE>
|
22
|
+
... "optional" -- anything (optional); dummy optional
|
23
|
+
<BLANKLINE>
|
24
|
+
EXAMPLES...
|
25
|
+
<BLANKLINE>
|
26
|
+
...
|
27
|
+
Init docstring: ...ee help(type(...)) for...signature...
|
28
|
+
File: .../sage/repl/ipython_tests.py
|
29
|
+
Type: function
|
30
|
+
|
31
|
+
Next, test the pinfo magic for Cython code::
|
32
|
+
|
33
|
+
sage: from sage.repl.interpreter import get_test_shell
|
34
|
+
sage: shell = get_test_shell()
|
35
|
+
sage: shell.run_cell(u'from sage.tests.stl_vector import stl_int_vector')
|
36
|
+
sage: shell.run_cell(u'%pinfo stl_int_vector')
|
37
|
+
...
|
38
|
+
Example class wrapping an STL vector.
|
39
|
+
<BLANKLINE>
|
40
|
+
EXAMPLES...
|
41
|
+
<BLANKLINE>
|
42
|
+
...
|
43
|
+
Init docstring: ...ee help(type(...)) for...signature...
|
44
|
+
File: .../sage/tests/stl_vector.pyx
|
45
|
+
Type: type
|
46
|
+
...
|
47
|
+
|
48
|
+
Next, test the ``pinfo`` magic for ``R`` interface code, see :issue:`26906`::
|
49
|
+
|
50
|
+
sage: from sage.repl.interpreter import get_test_shell # optional - rpy2
|
51
|
+
sage: shell = get_test_shell() # optional - rpy2
|
52
|
+
sage: shell.run_cell(u'%pinfo r.lm') # optional - rpy2
|
53
|
+
Signature: r.lm(...*args, **kwds)
|
54
|
+
...
|
55
|
+
String form: lm
|
56
|
+
File: .../sage/interfaces/r.py
|
57
|
+
Docstring:...
|
58
|
+
title
|
59
|
+
*****
|
60
|
+
<BLANKLINE>
|
61
|
+
Fitting Linear Models
|
62
|
+
...
|
63
|
+
|
64
|
+
Next, test the pinfo2 magic for Python code. This is what IPython
|
65
|
+
calls when you ask for the double-questionmark help, like `foo??` ::
|
66
|
+
|
67
|
+
sage: from sage.repl.interpreter import get_test_shell
|
68
|
+
sage: shell = get_test_shell()
|
69
|
+
sage: shell.run_cell(u'from sage.repl.ipython_tests import dummy')
|
70
|
+
sage: shell.run_cell(u'%pinfo2 dummy')
|
71
|
+
Signature: dummy(argument, optional=None)
|
72
|
+
...
|
73
|
+
Source:
|
74
|
+
def dummy(argument, optional=None):
|
75
|
+
"""
|
76
|
+
Dummy Docstring Title.
|
77
|
+
<BLANKLINE>
|
78
|
+
Dummy docstring explanation.
|
79
|
+
<BLANKLINE>
|
80
|
+
INPUT:
|
81
|
+
<BLANKLINE>
|
82
|
+
- ``argument`` -- anything; dummy argument
|
83
|
+
<BLANKLINE>
|
84
|
+
- ``optional`` -- anything (optional); dummy optional
|
85
|
+
<BLANKLINE>
|
86
|
+
EXAMPLES::
|
87
|
+
<BLANKLINE>
|
88
|
+
...
|
89
|
+
"""
|
90
|
+
return 'Source code would be here'
|
91
|
+
File: .../sage/repl/ipython_tests.py
|
92
|
+
Type: function
|
93
|
+
|
94
|
+
Next, test the pinfo2 magic for Cython code::
|
95
|
+
|
96
|
+
sage: from sage.repl.interpreter import get_test_shell
|
97
|
+
sage: shell = get_test_shell()
|
98
|
+
sage: shell.run_cell(u'from sage.tests.stl_vector import stl_int_vector')
|
99
|
+
sage: shell.run_cell(u'%pinfo2 stl_int_vector')
|
100
|
+
...
|
101
|
+
cdef class stl_int_vector(SageObject):
|
102
|
+
"""
|
103
|
+
Example class wrapping an STL vector.
|
104
|
+
<BLANKLINE>
|
105
|
+
EXAMPLES::
|
106
|
+
<BLANKLINE>
|
107
|
+
...
|
108
|
+
"""
|
109
|
+
<BLANKLINE>
|
110
|
+
cdef vector[int] *data
|
111
|
+
cdef string *name
|
112
|
+
<BLANKLINE>
|
113
|
+
def __cinit__(self):
|
114
|
+
"""
|
115
|
+
The Cython constructor.
|
116
|
+
<BLANKLINE>
|
117
|
+
EXAMPLES::
|
118
|
+
<BLANKLINE>
|
119
|
+
...
|
120
|
+
File: .../sage/tests/stl_vector.pyx
|
121
|
+
Type: type
|
122
|
+
...
|
123
|
+
|
124
|
+
Next, test the ``pinfo2`` magic for ``R`` interface code, see :issue:`26906`::
|
125
|
+
|
126
|
+
sage: from sage.repl.interpreter import get_test_shell # optional - rpy2
|
127
|
+
sage: shell = get_test_shell() # optional - rpy2
|
128
|
+
sage: shell.run_cell(u'%pinfo2 r.lm') # optional - rpy2
|
129
|
+
Signature: r.lm(...*args, **kwds)
|
130
|
+
...
|
131
|
+
String form: lm
|
132
|
+
File: .../sage/interfaces/r.py
|
133
|
+
Source:
|
134
|
+
function (formula, data, subset, weights, na.action, method = "qr",
|
135
|
+
...
|
136
|
+
|
137
|
+
Test that there are no warnings being ignored internally::
|
138
|
+
|
139
|
+
sage: import warnings
|
140
|
+
sage: warnings.simplefilter('error'); get_test_shell()
|
141
|
+
<sage.repl.interpreter.SageTestShell object at 0x...>
|
142
|
+
'''
|
143
|
+
|
144
|
+
|
145
|
+
def dummy(argument, optional=None):
|
146
|
+
"""
|
147
|
+
Dummy Docstring Title.
|
148
|
+
|
149
|
+
Dummy docstring explanation.
|
150
|
+
|
151
|
+
INPUT:
|
152
|
+
|
153
|
+
- ``argument`` -- anything; dummy argument
|
154
|
+
|
155
|
+
- ``optional`` -- anything (optional); dummy optional
|
156
|
+
|
157
|
+
EXAMPLES::
|
158
|
+
|
159
|
+
sage: from sage.repl.ipython_tests import dummy
|
160
|
+
sage: dummy(1)
|
161
|
+
'Source code would be here'
|
162
|
+
"""
|
163
|
+
return 'Source code would be here'
|
sage/repl/load.py
ADDED
@@ -0,0 +1,326 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-repl
|
2
|
+
"""
|
3
|
+
Load Python, Sage, Cython, Fortran and Magma files in Sage
|
4
|
+
"""
|
5
|
+
# ****************************************************************************
|
6
|
+
# Copyright (C) 2006 William Stein <wstein@gmail.com>
|
7
|
+
#
|
8
|
+
# This program is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 2 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
# https://www.gnu.org/licenses/
|
13
|
+
# ****************************************************************************
|
14
|
+
import base64
|
15
|
+
from pathlib import Path
|
16
|
+
|
17
|
+
from sage.cpython.string import str_to_bytes, bytes_to_str, FS_ENCODING
|
18
|
+
|
19
|
+
|
20
|
+
def is_loadable_filename(filename):
|
21
|
+
"""
|
22
|
+
Return whether a file can be loaded into Sage.
|
23
|
+
|
24
|
+
This checks only whether its name ends in one of the supported
|
25
|
+
extensions ``.py``, ``.pyx``, ``.sage``, ``.spyx``, ``.f``,
|
26
|
+
``.f90`` and ``.m``.
|
27
|
+
|
28
|
+
.. NOTE:: :func:`load` assumes that `.m` signifies a Magma file.
|
29
|
+
|
30
|
+
INPUT:
|
31
|
+
|
32
|
+
- ``filename`` -- string or :class:`Path` object
|
33
|
+
|
34
|
+
OUTPUT: boolean
|
35
|
+
|
36
|
+
EXAMPLES::
|
37
|
+
|
38
|
+
sage: sage.repl.load.is_loadable_filename('foo.bar')
|
39
|
+
False
|
40
|
+
sage: sage.repl.load.is_loadable_filename('foo.c')
|
41
|
+
False
|
42
|
+
sage: sage.repl.load.is_loadable_filename('foo.sage')
|
43
|
+
True
|
44
|
+
sage: sage.repl.load.is_loadable_filename('FOO.F90')
|
45
|
+
True
|
46
|
+
sage: sage.repl.load.is_loadable_filename('foo.m')
|
47
|
+
True
|
48
|
+
|
49
|
+
sage: from pathlib import Path
|
50
|
+
sage: sage.repl.load.is_loadable_filename(Path('foo.py'))
|
51
|
+
True
|
52
|
+
"""
|
53
|
+
ext = Path(filename).suffix.lower()
|
54
|
+
return ext in ('.py', '.pyx', '.sage', '.spyx', '.f', '.f90', '.m')
|
55
|
+
|
56
|
+
|
57
|
+
def load_cython(name):
|
58
|
+
"""
|
59
|
+
Helper function to load a Cython file.
|
60
|
+
|
61
|
+
INPUT:
|
62
|
+
|
63
|
+
- ``name`` -- filename of the Cython file
|
64
|
+
|
65
|
+
OUTPUT:
|
66
|
+
|
67
|
+
- A string with Python code to import the names from the compiled
|
68
|
+
module.
|
69
|
+
"""
|
70
|
+
from sage.misc.cython import cython
|
71
|
+
mod, dir = cython(str(name), compile_message=True, use_cache=True)
|
72
|
+
import sys
|
73
|
+
sys.path.append(dir)
|
74
|
+
return f'from {mod} import *'
|
75
|
+
|
76
|
+
|
77
|
+
def load(filename, globals, attach=False):
|
78
|
+
r"""
|
79
|
+
Execute a file in the scope given by ``globals``. If the name starts with
|
80
|
+
``http://`` or ``https://``, it is treated as a URL and downloaded.
|
81
|
+
|
82
|
+
.. NOTE::
|
83
|
+
|
84
|
+
For Cython files, the situation is more complicated --
|
85
|
+
the module is first compiled to a temporary module ``t`` and
|
86
|
+
executed via::
|
87
|
+
|
88
|
+
from t import *
|
89
|
+
|
90
|
+
INPUT:
|
91
|
+
|
92
|
+
- ``filename`` -- string (denoting a filename or URL) or a :class:`Path` object
|
93
|
+
|
94
|
+
- ``globals`` -- string:object dictionary; the context in which
|
95
|
+
to execute the file contents
|
96
|
+
|
97
|
+
- ``attach`` -- boolean (default: ``False``); whether to add the
|
98
|
+
file to the list of attached files
|
99
|
+
|
100
|
+
Loading an executable Sage script from the command prompt will run whatever
|
101
|
+
code is inside an
|
102
|
+
|
103
|
+
if __name__ == "__main__":
|
104
|
+
|
105
|
+
section, as the condition on ``__name__`` will hold true (code run from the
|
106
|
+
command prompt is considered to be running in the ``__main__`` module.)
|
107
|
+
|
108
|
+
EXAMPLES:
|
109
|
+
|
110
|
+
Note that ``.py`` files are *not* preparsed::
|
111
|
+
|
112
|
+
sage: t = tmp_filename(ext='.py')
|
113
|
+
sage: with open(t, 'w') as f:
|
114
|
+
....: _ = f.write("print(('hi', 2^3)); z = -2^7")
|
115
|
+
sage: z = 1
|
116
|
+
sage: sage.repl.load.load(t, globals())
|
117
|
+
('hi', 1)
|
118
|
+
sage: z
|
119
|
+
-7
|
120
|
+
|
121
|
+
A ``.sage`` file *is* preparsed::
|
122
|
+
|
123
|
+
sage: t = tmp_filename(ext='.sage')
|
124
|
+
sage: with open(t, 'w') as f:
|
125
|
+
....: _ = f.write("print(('hi', 2^3)); z = -2^7")
|
126
|
+
sage: z = 1
|
127
|
+
sage: sage.repl.load.load(t, globals())
|
128
|
+
('hi', 8)
|
129
|
+
sage: z
|
130
|
+
-128
|
131
|
+
|
132
|
+
Cython files are *not* preparsed::
|
133
|
+
|
134
|
+
sage: t = tmp_filename(ext='.pyx')
|
135
|
+
sage: with open(t, 'w') as f:
|
136
|
+
....: _ = f.write("print(('hi', 2^3)); z = -2^7")
|
137
|
+
sage: z = 1
|
138
|
+
sage: sage.repl.load.load(t, globals()) # needs sage.misc.cython
|
139
|
+
Compiling ...
|
140
|
+
('hi', 1)
|
141
|
+
sage: z
|
142
|
+
-7
|
143
|
+
|
144
|
+
If the file is not a Cython, Python, or Sage file, a :exc:`ValueError`
|
145
|
+
is raised::
|
146
|
+
|
147
|
+
sage: sage.repl.load.load(tmp_filename(ext='.foo'), globals())
|
148
|
+
Traceback (most recent call last):
|
149
|
+
...
|
150
|
+
ValueError: unknown file extension '.foo' for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)
|
151
|
+
|
152
|
+
We load a file given at a remote URL (not tested for security reasons)::
|
153
|
+
|
154
|
+
sage: sage.repl.load.load('https://www.sagemath.org/files/loadtest.py', globals()) # not tested
|
155
|
+
hi from the net
|
156
|
+
5
|
157
|
+
|
158
|
+
We can load files using secure http (https)::
|
159
|
+
|
160
|
+
sage: sage.repl.load.load('https://raw.githubusercontent.com/sagemath/sage-patchbot/3.0.0/sage_patchbot/util.py', globals()) # optional - internet
|
161
|
+
|
162
|
+
We attach a file::
|
163
|
+
|
164
|
+
sage: t = tmp_filename(ext='.py')
|
165
|
+
sage: with open(t, 'w') as f:
|
166
|
+
....: _ = f.write("print('hello world')")
|
167
|
+
sage: sage.repl.load.load(t, globals(), attach=True)
|
168
|
+
hello world
|
169
|
+
sage: t in attached_files()
|
170
|
+
True
|
171
|
+
|
172
|
+
You cannot attach remote URLs (yet)::
|
173
|
+
|
174
|
+
sage: sage.repl.load.load('https://www.sagemath.org/files/loadtest.py', globals(), attach=True) # optional - internet
|
175
|
+
Traceback (most recent call last):
|
176
|
+
...
|
177
|
+
NotImplementedError: you cannot attach a URL
|
178
|
+
|
179
|
+
The default search path for loading and attaching files is the
|
180
|
+
current working directory, i.e., ``'.'``. But you can modify the
|
181
|
+
path with :func:`load_attach_path`::
|
182
|
+
|
183
|
+
sage: import tempfile
|
184
|
+
sage: sage.repl.attach.reset(); reset_load_attach_path()
|
185
|
+
sage: load_attach_path()
|
186
|
+
[PosixPath('.')]
|
187
|
+
sage: with tempfile.TemporaryDirectory() as t_dir:
|
188
|
+
....: fname = 'test.py'
|
189
|
+
....: fullpath = os.path.join(t_dir, fname)
|
190
|
+
....: with open(fullpath, 'w') as f:
|
191
|
+
....: _ = f.write("print(37 * 3)")
|
192
|
+
....: load_attach_path(t_dir, replace=True)
|
193
|
+
....: attach(fname)
|
194
|
+
111
|
195
|
+
sage: sage.repl.attach.reset(); reset_load_attach_path() # clean up
|
196
|
+
|
197
|
+
or by setting the environment variable ``SAGE_LOAD_ATTACH_PATH``
|
198
|
+
to a colon-separated list before starting Sage::
|
199
|
+
|
200
|
+
$ export SAGE_LOAD_ATTACH_PATH="/path/to/my/library:/path/to/utils"
|
201
|
+
$ sage
|
202
|
+
sage: load_attach_path() # not tested
|
203
|
+
['.', '/path/to/my/library', '/path/to/utils']
|
204
|
+
|
205
|
+
TESTS:
|
206
|
+
|
207
|
+
Make sure that load handles filenames with spaces in the name or path::
|
208
|
+
|
209
|
+
sage: t = tmp_filename(ext=' b.sage')
|
210
|
+
sage: with open(t, 'w') as f:
|
211
|
+
....: _ = f.write("print(2)")
|
212
|
+
sage: sage.repl.load.load(t, globals())
|
213
|
+
2
|
214
|
+
|
215
|
+
Non-existing files with spaces give correct messages::
|
216
|
+
|
217
|
+
sage: sage.repl.load.load("this file should not exist", globals())
|
218
|
+
Traceback (most recent call last):
|
219
|
+
...
|
220
|
+
OSError: did not find file 'this file should not exist' to load or attach
|
221
|
+
"""
|
222
|
+
if attach:
|
223
|
+
from sage.repl.attach import add_attached_file
|
224
|
+
|
225
|
+
if isinstance(filename, bytes):
|
226
|
+
# For Python 3 in particular, convert bytes filenames to str since the
|
227
|
+
# rest of this functions operate on filename as a str
|
228
|
+
filename = bytes_to_str(filename, FS_ENCODING, 'surrogateescape')
|
229
|
+
|
230
|
+
if isinstance(filename, str) and filename.lower().startswith(('http://', 'https://')):
|
231
|
+
if attach:
|
232
|
+
# But see https://en.wikipedia.org/wiki/HTTP_ETag for how
|
233
|
+
# we will do this.
|
234
|
+
# https://diveintopython3.net/http-web-services.html#etags
|
235
|
+
raise NotImplementedError("you cannot attach a URL")
|
236
|
+
from sage.misc.remote_file import get_remote_file
|
237
|
+
filename = get_remote_file(filename, verbose=False)
|
238
|
+
|
239
|
+
filename = Path(filename).expanduser()
|
240
|
+
|
241
|
+
from sage.repl.attach import load_attach_path
|
242
|
+
for path in load_attach_path():
|
243
|
+
fpath = (path / filename).expanduser()
|
244
|
+
if fpath.is_file():
|
245
|
+
break
|
246
|
+
else:
|
247
|
+
raise OSError('did not find file %r to load or attach' % str(filename))
|
248
|
+
|
249
|
+
ext = fpath.suffix.lower()
|
250
|
+
if ext == '.py':
|
251
|
+
if attach:
|
252
|
+
add_attached_file(fpath)
|
253
|
+
with fpath.open() as f:
|
254
|
+
code = compile(f.read(), fpath, 'exec')
|
255
|
+
exec(code, globals)
|
256
|
+
elif ext == '.sage':
|
257
|
+
from sage.repl.attach import load_attach_mode
|
258
|
+
from sage.repl.preparse import preparse_file_named, preparse_file
|
259
|
+
load_debug_mode, attach_debug_mode = load_attach_mode()
|
260
|
+
if (attach and attach_debug_mode) or ((not attach) and load_debug_mode):
|
261
|
+
# Preparse to a file to enable tracebacks with
|
262
|
+
# code snippets. Use preparse_file_named to make
|
263
|
+
# the file name appear in the traceback as well.
|
264
|
+
# See Issue 11812.
|
265
|
+
if attach:
|
266
|
+
add_attached_file(fpath)
|
267
|
+
parsed_file = preparse_file_named(fpath)
|
268
|
+
with parsed_file.open() as f:
|
269
|
+
code = compile(f.read(), parsed_file, 'exec')
|
270
|
+
exec(code, globals)
|
271
|
+
else:
|
272
|
+
# Preparse in memory only for speed.
|
273
|
+
if attach:
|
274
|
+
add_attached_file(fpath)
|
275
|
+
with fpath.open() as f:
|
276
|
+
exec(preparse_file(f.read()) + "\n", globals)
|
277
|
+
elif ext in ['.spyx', '.pyx']:
|
278
|
+
if attach:
|
279
|
+
add_attached_file(fpath)
|
280
|
+
exec(load_cython(fpath), globals)
|
281
|
+
elif ext in ['.f', '.f90']:
|
282
|
+
from sage.misc.inline_fortran import fortran
|
283
|
+
with fpath.open() as f:
|
284
|
+
fortran(f.read(), globals)
|
285
|
+
elif ext == '.m':
|
286
|
+
# Assume magma for now, though maybe .m is used by maple and
|
287
|
+
# mathematica too, and we should really analyze the file
|
288
|
+
# further.
|
289
|
+
s = globals['magma'].load(fpath)
|
290
|
+
i = s.find('\n')
|
291
|
+
print(s[i + 1:])
|
292
|
+
else:
|
293
|
+
raise ValueError('unknown file extension %r for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)' % ext)
|
294
|
+
|
295
|
+
|
296
|
+
def load_wrap(filename, attach=False):
|
297
|
+
"""
|
298
|
+
Encode a load or attach command as valid Python code.
|
299
|
+
|
300
|
+
INPUT:
|
301
|
+
|
302
|
+
- ``filename`` -- string or :class:`Path` object; the argument
|
303
|
+
to the load or attach command
|
304
|
+
|
305
|
+
- ``attach`` -- boolean (default: ``False``); whether to attach
|
306
|
+
``filename``, instead of loading it
|
307
|
+
|
308
|
+
OUTPUT: string
|
309
|
+
|
310
|
+
EXAMPLES::
|
311
|
+
|
312
|
+
sage: sage.repl.load.load_wrap('foo.py', True)
|
313
|
+
'sage.repl.load.load(sage.repl.load.base64.b64decode("Zm9vLnB5"),globals(),True)'
|
314
|
+
sage: sage.repl.load.load_wrap('foo.sage')
|
315
|
+
'sage.repl.load.load(sage.repl.load.base64.b64decode("Zm9vLnNhZ2U="),globals(),False)'
|
316
|
+
sage: m = sage.repl.load.base64.b64decode("Zm9vLnNhZ2U=")
|
317
|
+
sage: m == b'foo.sage'
|
318
|
+
True
|
319
|
+
"""
|
320
|
+
if isinstance(filename, Path):
|
321
|
+
filename = str(filename)
|
322
|
+
# Note: In Python 3, b64encode only accepts bytes, and returns bytes.
|
323
|
+
b64 = base64.b64encode(str_to_bytes(filename, FS_ENCODING,
|
324
|
+
"surrogateescape"))
|
325
|
+
txt = 'sage.repl.load.load(sage.repl.load.base64.b64decode("{}"),globals(),{})'
|
326
|
+
return txt.format(bytes_to_str(b64, 'ascii'), attach)
|