Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Sage's IPython Extension
A Sage extension which adds sage-specific features:
* magics
- ``%crun``
- ``%runfile``
- ``%attach``
- ``%display``
- ``%mode`` (like ``%maxima``, etc.)
- ``%%cython``
- ``%%fortran``
* preparsing of input
* loading Sage library
* running init.sage
* changing prompt to Sage prompt
* Display hook
TESTS:
We test that preparsing is off for ``%runfile``, on for ``%time``::
sage: import os, re sage: from sage.repl.interpreter import get_test_shell sage: from sage.misc.all import tmp_dir sage: shell = get_test_shell() sage: TMP = tmp_dir()
The temporary directory should have a name of the form ``.../12345/...``, to demonstrate that file names are not preparsed when calling ``%runfile`` ::
sage: bool(re.search('/[0-9]+/', TMP)) True sage: tmp = os.path.join(TMP, 'run_cell.py') sage: f = open(tmp, 'w'); _ = f.write('a = 2\n'); f.close() sage: shell.run_cell('%runfile '+tmp) sage: shell.run_cell('a') 2
In contrast, input to the ``%time`` magic command is preparsed::
sage: shell.run_cell('%time 594.factor()') CPU times: user ... Wall time: ... 2 * 3^3 * 11 sage: shell.quit() """
def crun(self, s): r""" Profile C function calls
INPUT:
- ``s`` -- string. Sage command to profile.
EXAMPLES::
sage: from sage.repl.interpreter import get_test_shell sage: shell = get_test_shell() sage: shell.run_cell('%crun sum(1/(1+n^2) for n in range(100))') # optional - gperftools PROFILE: interrupts/evictions/bytes = ... Using local file ... Using local file ... sage: shell.quit() """ import sage.misc.gperftools sage.misc.gperftools.crun(s, evaluator=self.shell.ex)
def runfile(self, s): r""" Execute the code contained in the file ``s``.
This is designed to be used from the command line as ``%runfile /path/to/file``.
- ``s`` -- string. The file to be loaded.
EXAMPLES::
sage: import os sage: from sage.repl.interpreter import get_test_shell sage: from sage.misc.all import tmp_dir sage: shell = get_test_shell() sage: tmp = os.path.join(tmp_dir(), 'run_cell.py') sage: f = open(tmp, 'w'); _ = f.write('a = 2\n'); f.close() sage: shell.run_cell('%runfile '+tmp) sage: shell.run_cell('a') 2 sage: shell.quit() """
def attach(self, s): r""" Attach the code contained in the file ``s``.
This is designed to be used from the command line as ``%attach /path/to/file``.
- ``s`` -- string. The file to be attached
EXAMPLES::
sage: import os sage: from sage.repl.interpreter import get_test_shell sage: shell = get_test_shell() sage: tmp = os.path.normpath(os.path.join(SAGE_TMP, 'run_cell.py')) sage: f = open(tmp, 'w'); _ = f.write('a = 2\n'); f.close() sage: shell.run_cell('%attach ' + tmp) sage: shell.run_cell('a') 2 sage: sleep(1) # filesystem timestamp granularity sage: f = open(tmp, 'w'); _ = f.write('a = 3\n'); f.close()
Note that the doctests are never really at the command prompt, so we call the input hook manually::
sage: shell.run_cell('from sage.repl.attach import reload_attached_files_if_modified') sage: shell.run_cell('reload_attached_files_if_modified()') ### reloading attached file run_cell.py modified at ... ###
sage: shell.run_cell('a') 3 sage: shell.run_cell('detach(%r)'%tmp) sage: shell.run_cell('attached_files()') [] sage: os.remove(tmp) sage: shell.quit() """
def iload(self, args): """ A magic command to interactively load a file as in MAGMA.
- ``args`` -- string. The file to be interactively loaded
.. note::
Currently, this cannot be completely doctested as it relies on :func:`raw_input`.
EXAMPLES::
sage: ip = get_ipython() # not tested: works only in interactive shell sage: ip.magic_iload('/dev/null') # not tested: works only in interactive shell Interactively loading "/dev/null" # not tested: works only in interactive shell """ content = self.shell.find_user_code(args).splitlines()
# we create a stack so e.g. having an iload inside of an iload # will process the inner iload and then resume the outer iload orig_readline = self.shell.pre_readline
def pre_readline(): if self.shell.rl_next_input is None: self.shell.rl_next_input = content.pop(0) self.shell.rl_do_indent = False orig_readline() if not content: # restore original hook self.shell.readline_startup_hook(orig_readline) self.shell.pre_readline = orig_readline
self.shell.readline_startup_hook(pre_readline) self.shell.pre_readline = pre_readline
print('Interactively loading "%s"'%args)
def display(self, args): r""" A magic command to switch between simple display and ASCII art display.
- ``args`` -- string. See :meth:`sage.misc.display_hook.DisplayHookBase.set_display` for allowed values. If the mode is ``ascii_art``, it can optionally be followed by a width.
How to use: if you want activate the ASCII art mod::
sage: from sage.repl.interpreter import get_test_shell sage: shell = get_test_shell() sage: shell.run_cell('%display ascii_art')
That means you don't have to use :func:`ascii_art` to get an ASCII art output::
sage: shell.run_cell("i = var('i')") sage: shell.run_cell('sum(i^2*x^i, i, 0, 10)') 10 9 8 7 6 5 4 3 2 100*x + 81*x + 64*x + 49*x + 36*x + 25*x + 16*x + 9*x + 4*x + x
Then when you want return in 'textual mode'::
sage: shell.run_cell('%display text plain') sage: shell.run_cell('%display plain') # shortcut for "text plain" sage: shell.run_cell('sum(i^2*x^i, i, 0, 10)') 100*x^10 + 81*x^9 + 64*x^8 + 49*x^7 + 36*x^6 + 25*x^5 + 16*x^4 + 9*x^3 + 4*x^2 + x
Sometime you could have to use a special output width and you could specify it::
sage: shell.run_cell('%display ascii_art') sage: shell.run_cell('StandardTableaux(4).list()') [ [ 1 4 [ 1 3 4 1 2 4 1 2 3 1 3 1 2 2 [ 1 2 3 4, 2 , 3 , 4 , 2 4, 3 4, 3 , <BLANKLINE> 1 ] 1 3 1 2 2 ] 2 3 3 ] 4 , 4 , 4 ] sage: shell.run_cell('%display ascii_art 50') sage: shell.run_cell('StandardTableaux(4).list()') [ [ [ 1 3 4 1 2 4 1 2 3 [ 1 2 3 4, 2 , 3 , 4 , <BLANKLINE> 1 ] 1 4 1 3 1 2 2 ] 1 3 1 2 2 2 3 3 ] 2 4, 3 4, 3 , 4 , 4 , 4 ]
As yet another option, typeset mode. This is used in the emacs interface::
sage: shell.run_cell('%display text latex') sage: shell.run_cell('1/2') \newcommand{\Bold}[1]{\mathbf{#1}}\frac{1}{2}
Switch back::
sage: shell.run_cell('%display default')
Switch graphics to default to vector or raster graphics file formats::
sage: shell.run_cell('%display graphics vector')
TESTS::
sage: shell.run_cell('%display invalid_mode') value must be unset (None) or one of ('plain', 'ascii_art', 'unicode_art', 'latex'), got invalid_mode sage: shell.quit() """ print(dm.preferences) return # deprecated values dm.preferences.text = 'latex' except ValueError: max_width = 0 raise ValueError( "max width must be a positive integer") # Unset all # Normal argument handling # "%display text" => get current value print(getattr(dm.preferences, arg0)) else: # "%display text latex" => set new value delattr(dm.preferences, arg0) else: except ValueError as err: print(err) # do not show traceback # If all else fails: assume text else:
def cython(self, line, cell): """ Cython cell magic
This is syntactic sugar on the :func:`~sage.misc.cython.cython_compile` function.
INPUT:
- ``line`` -- ignored.
- ``cell`` -- string. The Cython source code to process.
OUTPUT:
None. The Cython code is compiled and loaded.
EXAMPLES::
sage: from sage.repl.interpreter import get_test_shell sage: shell = get_test_shell() sage: shell.run_cell(''' ....: %%cython ....: def f(): ....: print('test') ....: ''') ....: shell.run_cell('f()') """
def fortran(self, line, cell): """ Fortran cell magic.
This is syntactic sugar on the :func:`~sage.misc.inline_fortran.fortran` function.
INPUT:
- ``line`` -- ignored.
- ``cell`` -- string. The Cython source code to process.
OUTPUT:
None. The Fortran code is compiled and loaded.
EXAMPLES::
sage: from sage.repl.interpreter import get_test_shell sage: shell = get_test_shell() sage: shell.run_cell(''' ....: %%fortran ....: C FILE: FIB1.F ....: SUBROUTINE FIB(A,N) ....: C ....: C CALCULATE FIRST N FIBONACCI NUMBERS ....: C ....: INTEGER N ....: REAL*8 A(N) ....: DO I=1,N ....: IF (I.EQ.1) THEN ....: A(I) = 0.0D0 ....: ELSEIF (I.EQ.2) THEN ....: A(I) = 1.0D0 ....: ELSE ....: A(I) = A(I-1) + A(I-2) ....: ENDIF ....: ENDDO ....: END ....: C END FILE FIB1.F ....: ''') sage: fib <fortran object> sage: from numpy import array sage: a = array(range(10), dtype=float) sage: fib(a, 10) sage: a array([ 0., 1., 1., 2., 3., 5., 8., 13., 21., 34.]) """
""" Initialize the Sage plugin. """
""" Register magics for each of the Sage interfaces """
""" Set the exit hook to cleanly exit Sage. """ import sage.all sage.all.quit_sage(self.shell.verbose_quit)
def all_globals(): """ Return a Python module containing all globals which should be made available to the user.
EXAMPLES::
sage: from sage.repl.ipython_extension import SageCustomizations sage: SageCustomizations.all_globals() <module 'sage.all_cmdline' ...> """
""" Set up Sage command-line environment """ # import outside of cell so we don't get a traceback
""" Run Sage's initial startup file. """ self.shell.run_cell(f.read(), store_history=False)
# Ideally, these would just be methods of the Inspector class # that we could override; however, IPython looks them up in # the global :class:`IPython.core.oinspect` module namespace. # Thus, we have to monkey-patch.
""" Set up transforms (like the preparser). """ SagePromptTransformer)
def all_globals(): """ Return a Python module containing all globals which should be made available to the user when running the Jupyter notebook.
EXAMPLES::
sage: from sage.repl.ipython_extension import SageJupyterCustomizations sage: SageJupyterCustomizations.all_globals() <module 'sage.repl.ipython_kernel.all_jupyter' ...> """
# from http://stackoverflow.com/questions/4103773/efficient-way-of-having-a-function-only-execute-once-in-a-loop """ Runs a function (successfully) only once.
The running can be reset by setting the ``has_run`` attribute to False
TESTS::
sage: from sage.repl.ipython_extension import run_once sage: @run_once ....: def foo(work): ....: if work: ....: return 'foo worked' ....: raise RuntimeError("foo didn't work") sage: foo(False) Traceback (most recent call last): ... RuntimeError: foo didn't work sage: foo(True) 'foo worked' sage: foo(False) sage: foo(True) """ def wrapper(*args, **kwargs):
def load_ipython_extension(ip): """ Load the extension in IPython. """ # this modifies ip |