Sage’s IPython Modifications

This module contains all of Sage’s customizations to the IPython interpreter. These changes consist of the following major components:

SageTerminalApp

This is the main application object. It is used by the $SAGE_LOCAL/bin/sage-ipython script to start the Sage command-line. It’s primary purpose is to

  • Initialize the SageTerminalInteractiveShell.

  • Provide default configuration options for the shell, and its subcomponents. These work with (and can be overridden by) IPython’s configuration system.

  • Load the Sage ipython extension (which does things like preparsing, add magics, etc.).

  • Provide a custom SageCrashHandler to give the user instructions on how to report the crash to the Sage support mailing list.

SageInteractiveShell

The SageInteractiveShell object is the object responsible for accepting input from the user and evaluating it. From the command-line, this object can be retrieved by running:

sage: shell = get_ipython()   # not tested
>>> from sage.all import *
>>> shell = get_ipython()   # not tested
shell = get_ipython()   # not tested

Any input is preprocessed and evaluated inside the shell.run_cell method. If the command line processing does not do what you want it to do, you can step through it in the debugger:

sage: %debug shell.run_cell('?')        # not tested
>>> from sage.all import *
>>> %debug shell.run_cell('?')        # not tested
%debug shell.run_cell('?')        # not tested

The SageInteractiveShell provides the following customizations:

  • Modify the libraries before calling system commands. See system_raw().

SageTerminalInteractiveShell

The SageTerminalInteractiveShell is a close relative of SageInteractiveShell that is specialized for running in a terminal. In particular, running commands like !ls will directly write to stdout. Technically, the system attribute will point to system_raw instead of system_piped.

Interface Shell

The function interface_shell_embed() takes a Interface object and returns an embeddable IPython shell which can be used to directly interact with that shell. The bulk of this functionality is provided through InterfaceShellTransformer.

class sage.repl.interpreter.InterfaceShellTransformer(**kwargs: Any)[source]

Bases: PrefilterTransformer

Initialize this class. All of the arguments get passed to PrefilterTransformer.__init__().

temporary_objects

a list of hold onto interface objects and keep them from being garbage collected

preparse_imports_from_sage(line)[source]

Finds occurrences of strings such as sage(object) in line, converts object to shell.interface, and replaces those strings with their identifier in the new system. This also works with strings such as maxima(object) if shell.interface is maxima.

  • line – string; the line to transform

EXAMPLES:

sage: # needs sage.symbolic
sage: from sage.repl.interpreter import interface_shell_embed, InterfaceShellTransformer
sage: shell = interface_shell_embed(maxima)
sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config,
....:     prefilter_manager=shell.prefilter_manager)
sage: ift.shell.ex('a = 3')
sage: ift.preparse_imports_from_sage('2 + sage(a)')
'2 + sage0 '
sage: maxima.eval('sage0')
'3'
sage: ift.preparse_imports_from_sage('2 + maxima(a)') # maxima calls set_seed on startup which is why 'sage0' will becomes 'sage4' and not just 'sage1'
'2 +  sage4 '
sage: ift.preparse_imports_from_sage('2 + gap(a)')
'2 + gap(a)'
>>> from sage.all import *
>>> # needs sage.symbolic
>>> from sage.repl.interpreter import interface_shell_embed, InterfaceShellTransformer
>>> shell = interface_shell_embed(maxima)
>>> ift = InterfaceShellTransformer(shell=shell, config=shell.config,
...     prefilter_manager=shell.prefilter_manager)
>>> ift.shell.ex('a = 3')
>>> ift.preparse_imports_from_sage('2 + sage(a)')
'2 + sage0 '
>>> maxima.eval('sage0')
'3'
>>> ift.preparse_imports_from_sage('2 + maxima(a)') # maxima calls set_seed on startup which is why 'sage0' will becomes 'sage4' and not just 'sage1'
'2 +  sage4 '
>>> ift.preparse_imports_from_sage('2 + gap(a)')
'2 + gap(a)'
# needs sage.symbolic
from sage.repl.interpreter import interface_shell_embed, InterfaceShellTransformer
shell = interface_shell_embed(maxima)
ift = InterfaceShellTransformer(shell=shell, config=shell.config,
    prefilter_manager=shell.prefilter_manager)
ift.shell.ex('a = 3')
ift.preparse_imports_from_sage('2 + sage(a)')
maxima.eval('sage0')
ift.preparse_imports_from_sage('2 + maxima(a)') # maxima calls set_seed on startup which is why 'sage0' will becomes 'sage4' and not just 'sage1'
ift.preparse_imports_from_sage('2 + gap(a)')

Since Issue #28439, this also works with more complicated expressions containing nested parentheses:

sage: # needs sage.libs.gap sage.symbolic
sage: shell = interface_shell_embed(gap)
sage: shell.user_ns = locals()
sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config,
....:     prefilter_manager=shell.prefilter_manager)
sage: line = '2 + sage((1+2)*gap(-(5-3)^2).sage()) - gap(1+(2-1))'
sage: line = ift.preparse_imports_from_sage(line)
sage: gap.eval(line)
'-12'
>>> from sage.all import *
>>> # needs sage.libs.gap sage.symbolic
>>> shell = interface_shell_embed(gap)
>>> shell.user_ns = locals()
>>> ift = InterfaceShellTransformer(shell=shell, config=shell.config,
...     prefilter_manager=shell.prefilter_manager)
>>> line = '2 + sage((1+2)*gap(-(5-3)^2).sage()) - gap(1+(2-1))'
>>> line = ift.preparse_imports_from_sage(line)
>>> gap.eval(line)
'-12'
# needs sage.libs.gap sage.symbolic
shell = interface_shell_embed(gap)
shell.user_ns = locals()
ift = InterfaceShellTransformer(shell=shell, config=shell.config,
    prefilter_manager=shell.prefilter_manager)
line = '2 + sage((1+2)*gap(-(5-3)^2).sage()) - gap(1+(2-1))'
line = ift.preparse_imports_from_sage(line)
gap.eval(line)
priority = 50
transform(line, continue_prompt)[source]

Evaluates line in shell.interface and returns a string representing the result of that evaluation.

  • line – string; the line to be transformed and evaluated

  • continue_prompt – boolean; whether this line is a continuation in a sequence of multiline input

EXAMPLES:

sage: # needs sage.symbolic
sage: from sage.repl.interpreter import interface_shell_embed, InterfaceShellTransformer
sage: shell = interface_shell_embed(maxima)
sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config,
....:     prefilter_manager=shell.prefilter_manager)
sage: ift.transform('2+2', False)   # note: output contains triple quotation marks
'sage.repl.interpreter.logstr(r"""4""")'
sage: ift.shell.ex('a = 4')
sage: ift.transform(r'sage(a)+4', False)
'sage.repl.interpreter.logstr(r"""8""")'
sage: ift.temporary_objects
set()
sage: shell = interface_shell_embed(gap)                                    # needs sage.libs.gap
sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config,     # needs sage.libs.gap
....:     prefilter_manager=shell.prefilter_manager)
sage: ift.transform('2+2', False)
'sage.repl.interpreter.logstr(r"""4""")'
>>> from sage.all import *
>>> # needs sage.symbolic
>>> from sage.repl.interpreter import interface_shell_embed, InterfaceShellTransformer
>>> shell = interface_shell_embed(maxima)
>>> ift = InterfaceShellTransformer(shell=shell, config=shell.config,
...     prefilter_manager=shell.prefilter_manager)
>>> ift.transform('2+2', False)   # note: output contains triple quotation marks
'sage.repl.interpreter.logstr(r"""4""")'
>>> ift.shell.ex('a = 4')
>>> ift.transform(r'sage(a)+4', False)
'sage.repl.interpreter.logstr(r"""8""")'
>>> ift.temporary_objects
set()
>>> shell = interface_shell_embed(gap)                                    # needs sage.libs.gap
>>> ift = InterfaceShellTransformer(shell=shell, config=shell.config,     # needs sage.libs.gap
...     prefilter_manager=shell.prefilter_manager)
>>> ift.transform('2+2', False)
'sage.repl.interpreter.logstr(r"""4""")'
# needs sage.symbolic
from sage.repl.interpreter import interface_shell_embed, InterfaceShellTransformer
shell = interface_shell_embed(maxima)
ift = InterfaceShellTransformer(shell=shell, config=shell.config,
    prefilter_manager=shell.prefilter_manager)
ift.transform('2+2', False)   # note: output contains triple quotation marks
ift.shell.ex('a = 4')
ift.transform(r'sage(a)+4', False)
ift.temporary_objects
shell = interface_shell_embed(gap)                                    # needs sage.libs.gap
ift = InterfaceShellTransformer(shell=shell, config=shell.config,     # needs sage.libs.gap
    prefilter_manager=shell.prefilter_manager)
ift.transform('2+2', False)
class sage.repl.interpreter.SageCrashHandler(app)[source]

Bases: IPAppCrashHandler

A custom CrashHandler which gives the user instructions on how to post the problem to sage-support.

EXAMPLES:

sage: from sage.repl.interpreter import SageTerminalApp, SageCrashHandler
sage: app = SageTerminalApp.instance()
sage: sch = SageCrashHandler(app); sch
<sage.repl.interpreter.SageCrashHandler object at 0x...>
sage: sorted(sch.info.items())
[('app_name', 'Sage'),
 ('bug_tracker', 'https://github.com/sagemath/sage/issues'),
 ('contact_email', 'sage-support@googlegroups.com'),
 ('contact_name', 'sage-support'),
 ('crash_report_fname', 'Crash_report_Sage.txt')]
>>> from sage.all import *
>>> from sage.repl.interpreter import SageTerminalApp, SageCrashHandler
>>> app = SageTerminalApp.instance()
>>> sch = SageCrashHandler(app); sch
<sage.repl.interpreter.SageCrashHandler object at 0x...>
>>> sorted(sch.info.items())
[('app_name', 'Sage'),
 ('bug_tracker', 'https://github.com/sagemath/sage/issues'),
 ('contact_email', 'sage-support@googlegroups.com'),
 ('contact_name', 'sage-support'),
 ('crash_report_fname', 'Crash_report_Sage.txt')]
from sage.repl.interpreter import SageTerminalApp, SageCrashHandler
app = SageTerminalApp.instance()
sch = SageCrashHandler(app); sch
sorted(sch.info.items())
class sage.repl.interpreter.SageNotebookInteractiveShell(**kwargs: Any)[source]

Bases: SageShellOverride, InteractiveShell

IPython Shell for the Sage IPython Notebook.

The doctests are not tested since they would change the current rich output backend away from the doctest rich output backend.

EXAMPLES:

sage: from sage.repl.interpreter import SageNotebookInteractiveShell
sage: SageNotebookInteractiveShell()   # not tested
<sage.repl.interpreter.SageNotebookInteractiveShell object at 0x...>
>>> from sage.all import *
>>> from sage.repl.interpreter import SageNotebookInteractiveShell
>>> SageNotebookInteractiveShell()   # not tested
<sage.repl.interpreter.SageNotebookInteractiveShell object at 0x...>
from sage.repl.interpreter import SageNotebookInteractiveShell
SageNotebookInteractiveShell()   # not tested
init_display_formatter()[source]

Switch to the Sage IPython notebook rich output backend.

EXAMPLES:

sage: from sage.repl.interpreter import SageNotebookInteractiveShell
sage: SageNotebookInteractiveShell().init_display_formatter()   # not tested
>>> from sage.all import *
>>> from sage.repl.interpreter import SageNotebookInteractiveShell
>>> SageNotebookInteractiveShell().init_display_formatter()   # not tested
from sage.repl.interpreter import SageNotebookInteractiveShell
SageNotebookInteractiveShell().init_display_formatter()   # not tested
sage.repl.interpreter.SagePreparseTransformer(lines)[source]

EXAMPLES:

sage: from sage.repl.interpreter import SagePreparseTransformer
sage: spt = SagePreparseTransformer
sage: spt(['1+1r+2.3^2.3r\n'])
["Integer(1)+1+RealNumber('2.3')**2.3\n"]
sage: preparser(False)
sage: spt(['2.3^2\n'])
['2.3^2\n']
>>> from sage.all import *
>>> from sage.repl.interpreter import SagePreparseTransformer
>>> spt = SagePreparseTransformer
>>> spt(['1+1r+2.3^2.3r\n'])
["Integer(1)+1+RealNumber('2.3')**2.3\n"]
>>> preparser(False)
>>> spt(['2.3^2\n'])
['2.3^2\n']
from sage.repl.interpreter import SagePreparseTransformer
spt = SagePreparseTransformer
spt(['1+1r+2.3^2.3r\n'])
preparser(False)
spt(['2.3^2\n'])

Note

IPython may call this function more than once for the same input lines. So when debugging the preparser, print outs may be duplicated. If using IPython >= 7.17, try: sage.repl.interpreter.SagePreparseTransformer.has_side_effects = True

class sage.repl.interpreter.SageShellOverride[source]

Bases: object

Mixin to override methods in IPython’s [Terminal]InteractiveShell classes.

show_usage()[source]

Print the basic Sage usage.

This method ends up being called when you enter ? and nothing else on the command line.

EXAMPLES:

sage: from sage.repl.interpreter import get_test_shell
sage: shell = get_test_shell()
sage: shell.run_cell('?')
Welcome to Sage ...
sage: shell.quit()
>>> from sage.all import *
>>> from sage.repl.interpreter import get_test_shell
>>> shell = get_test_shell()
>>> shell.run_cell('?')
Welcome to Sage ...
>>> shell.quit()
from sage.repl.interpreter import get_test_shell
shell = get_test_shell()
shell.run_cell('?')
shell.quit()
system_raw(cmd)[source]

Run a system command.

EXAMPLES:

sage: from sage.repl.interpreter import get_test_shell
sage: shell = get_test_shell()
sage: shell.system_raw('false')
sage: shell.user_ns['_exit_code'] > 0
True
sage: shell.system_raw('true')
sage: shell.user_ns['_exit_code']
0
sage: shell.system_raw('R --version')   # optional - r
R version ...
sage: shell.user_ns['_exit_code']       # optional - r
0
sage: shell.quit()
>>> from sage.all import *
>>> from sage.repl.interpreter import get_test_shell
>>> shell = get_test_shell()
>>> shell.system_raw('false')
>>> shell.user_ns['_exit_code'] > Integer(0)
True
>>> shell.system_raw('true')
>>> shell.user_ns['_exit_code']
0
>>> shell.system_raw('R --version')   # optional - r
R version ...
>>> shell.user_ns['_exit_code']       # optional - r
0
>>> shell.quit()
from sage.repl.interpreter import get_test_shell
shell = get_test_shell()
shell.system_raw('false')
shell.user_ns['_exit_code'] > 0
shell.system_raw('true')
shell.user_ns['_exit_code']
shell.system_raw('R --version')   # optional - r
shell.user_ns['_exit_code']       # optional - r
shell.quit()
class sage.repl.interpreter.SageTerminalApp(**kwargs: Any)[source]

Bases: TerminalIPythonApp

crash_handler_class[source]

alias of SageCrashHandler

init_shell()[source]

Initialize the SageInteractiveShell instance.

Note

This code is based on TerminalIPythonApp.init_shell().

EXAMPLES:

sage: from sage.repl.interpreter import SageTerminalApp
sage: app = SageTerminalApp.instance()
sage: app.shell
<sage.repl.interpreter.SageTestShell object at 0x...>
>>> from sage.all import *
>>> from sage.repl.interpreter import SageTerminalApp
>>> app = SageTerminalApp.instance()
>>> app.shell
<sage.repl.interpreter.SageTestShell object at 0x...>
from sage.repl.interpreter import SageTerminalApp
app = SageTerminalApp.instance()
app.shell
load_config_file(*args, **kwds)[source]

Merges a config file with the default sage config.

Note

This code is based on Application.update_config().

name: str | Unicode[str, str | bytes] = 'Sage'
shell_class[source]

Type of the shell

test_shell[source]

Whether the shell is a test shell

class sage.repl.interpreter.SageTerminalInteractiveShell(**kwargs: Any)[source]

Bases: SageShellOverride, TerminalInteractiveShell

IPython Shell for the Sage IPython Commandline Interface.

The doctests are not tested since they would change the current rich output backend away from the doctest rich output backend.

EXAMPLES:

sage: from sage.repl.interpreter import SageTerminalInteractiveShell
sage: SageTerminalInteractiveShell()   # not tested
<sage.repl.interpreter.SageNotebookInteractiveShell object at 0x...>
>>> from sage.all import *
>>> from sage.repl.interpreter import SageTerminalInteractiveShell
>>> SageTerminalInteractiveShell()   # not tested
<sage.repl.interpreter.SageNotebookInteractiveShell object at 0x...>
from sage.repl.interpreter import SageTerminalInteractiveShell
SageTerminalInteractiveShell()   # not tested
init_display_formatter()[source]

Switch to the Sage IPython commandline rich output backend.

EXAMPLES:

sage: from sage.repl.interpreter import SageTerminalInteractiveShell
sage: SageTerminalInteractiveShell().init_display_formatter()   # not tested
>>> from sage.all import *
>>> from sage.repl.interpreter import SageTerminalInteractiveShell
>>> SageTerminalInteractiveShell().init_display_formatter()   # not tested
from sage.repl.interpreter import SageTerminalInteractiveShell
SageTerminalInteractiveShell().init_display_formatter()   # not tested
prompt_for_code()[source]
class sage.repl.interpreter.SageTestShell(**kwargs: Any)[source]

Bases: SageShellOverride, TerminalInteractiveShell

Test Shell.

Care must be taken in these doctests to quit the test shell in order to switch back the rich output display backend to the doctest backend.

EXAMPLES:

sage: from sage.repl.interpreter import get_test_shell
sage: shell = get_test_shell();  shell
<sage.repl.interpreter.SageTestShell object at 0x...>
sage: shell.quit()
>>> from sage.all import *
>>> from sage.repl.interpreter import get_test_shell
>>> shell = get_test_shell();  shell
<sage.repl.interpreter.SageTestShell object at 0x...>
>>> shell.quit()
from sage.repl.interpreter import get_test_shell
shell = get_test_shell();  shell
shell.quit()
init_display_formatter()[source]

Switch to the Sage IPython commandline rich output backend.

EXAMPLES:

sage: from sage.repl.interpreter import get_test_shell
sage: shell = get_test_shell();  shell
<sage.repl.interpreter.SageTestShell object at 0x...>
sage: shell.quit()
sage: shell.init_display_formatter()
sage: shell.quit()
>>> from sage.all import *
>>> from sage.repl.interpreter import get_test_shell
>>> shell = get_test_shell();  shell
<sage.repl.interpreter.SageTestShell object at 0x...>
>>> shell.quit()
>>> shell.init_display_formatter()
>>> shell.quit()
from sage.repl.interpreter import get_test_shell
shell = get_test_shell();  shell
shell.quit()
shell.init_display_formatter()
shell.quit()
quit()[source]

Quit the test shell.

To make the test shell as realistic as possible, we switch to the BackendIPythonCommandline display backend. This method restores the previous display backend, which is the BackendDoctest during doctests.

EXAMPLES:

sage: from sage.repl.interpreter import get_test_shell
sage: from sage.repl.rich_output import get_display_manager
sage: get_display_manager()
The Sage display manager using the doctest backend

sage: shell = get_test_shell()
sage: get_display_manager()
The Sage display manager using the IPython command line backend

sage: shell.quit()
sage: get_display_manager()
The Sage display manager using the doctest backend
>>> from sage.all import *
>>> from sage.repl.interpreter import get_test_shell
>>> from sage.repl.rich_output import get_display_manager
>>> get_display_manager()
The Sage display manager using the doctest backend

>>> shell = get_test_shell()
>>> get_display_manager()
The Sage display manager using the IPython command line backend

>>> shell.quit()
>>> get_display_manager()
The Sage display manager using the doctest backend
from sage.repl.interpreter import get_test_shell
from sage.repl.rich_output import get_display_manager
get_display_manager()
shell = get_test_shell()
get_display_manager()
shell.quit()
get_display_manager()
run_cell(*args, **kwds)[source]

Run IPython cell.

Starting with IPython-3.0, this returns an success/failure information. Since it is more convenient for doctests, we ignore it.

EXAMPLES:

sage: from sage.repl.interpreter import get_test_shell
sage: shell = get_test_shell()
sage: rc = shell.run_cell('2^50')
1125899906842624
sage: rc is None
True
sage: shell.quit()
>>> from sage.all import *
>>> from sage.repl.interpreter import get_test_shell
>>> shell = get_test_shell()
>>> rc = shell.run_cell('2^50')
1125899906842624
>>> rc is None
True
>>> shell.quit()
from sage.repl.interpreter import get_test_shell
shell = get_test_shell()
rc = shell.run_cell('2^50')
rc is None
shell.quit()
sage.repl.interpreter.get_test_shell()[source]

Return a IPython shell that can be used in testing the functions in this module.

OUTPUT: an IPython shell

EXAMPLES:

sage: from sage.repl.interpreter import get_test_shell
sage: shell = get_test_shell(); shell
<sage.repl.interpreter.SageTestShell object at 0x...>
sage: shell.parent.shell_class
<class 'sage.repl.interpreter.SageTestShell'>
sage: shell.parent.test_shell
True
sage: shell.quit()
>>> from sage.all import *
>>> from sage.repl.interpreter import get_test_shell
>>> shell = get_test_shell(); shell
<sage.repl.interpreter.SageTestShell object at 0x...>
>>> shell.parent.shell_class
<class 'sage.repl.interpreter.SageTestShell'>
>>> shell.parent.test_shell
True
>>> shell.quit()
from sage.repl.interpreter import get_test_shell
shell = get_test_shell(); shell
shell.parent.shell_class
shell.parent.test_shell
shell.quit()
sage.repl.interpreter.interface_shell_embed(interface)[source]

Return an IPython shell which uses a Sage interface on the backend to perform the evaluations. It uses InterfaceShellTransformer to transform the input into the appropriate interface.eval(...) input.

INPUT:

  • interface – a Sage PExpect interface instance

EXAMPLES:

sage: from sage.repl.interpreter import interface_shell_embed
sage: shell = interface_shell_embed(gap)                                        # needs sage.libs.gap
sage: shell.run_cell('List( [1..10], IsPrime )')                                # needs sage.libs.gap
[ false, true, true, false, true, false, true, false, false, false ]
<ExecutionResult object at ..., execution_count=None error_before_exec=None error_in_exec=None ...result=[ false, true, true, false, true, false, true, false, false, false ]>
>>> from sage.all import *
>>> from sage.repl.interpreter import interface_shell_embed
>>> shell = interface_shell_embed(gap)                                        # needs sage.libs.gap
>>> shell.run_cell('List( [1..10], IsPrime )')                                # needs sage.libs.gap
[ false, true, true, false, true, false, true, false, false, false ]
<ExecutionResult object at ..., execution_count=None error_before_exec=None error_in_exec=None ...result=[ false, true, true, false, true, false, true, false, false, false ]>
from sage.repl.interpreter import interface_shell_embed
shell = interface_shell_embed(gap)                                        # needs sage.libs.gap
shell.run_cell('List( [1..10], IsPrime )')                                # needs sage.libs.gap
class sage.repl.interpreter.logstr[source]

Bases: str

For use by :meth`~InterfaceShellTransformer.transform`. This provides a _latex_ method which is just the string wrapped in a \verb environment.

sage.repl.interpreter.preparser(on=True)[source]

Turn on or off the Sage preparser.

  • on – boolean; whether to turn on preparsing

EXAMPLES:

sage: 2/3
2/3
sage: preparser(False)
sage: 2/3  # not tested since doctests are always preparsed
0
sage: preparser(True)
sage: 2^3
8
>>> from sage.all import *
>>> Integer(2)/Integer(3)
2/3
>>> preparser(False)
>>> Integer(2)/Integer(3)  # not tested since doctests are always preparsed
0
>>> preparser(True)
>>> Integer(2)**Integer(3)
8
2/3
preparser(False)
2/3  # not tested since doctests are always preparsed
preparser(True)
2^3