Sage’s IPython Modifications¶
This module contains all of Sage’s customizations to the IPython interpreter. These changes consist of the following major components:
SageInteractiveShell
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
See also
- preparse_imports_from_sage(line)[source]¶
Finds occurrences of strings such as
sage(object)
in line, convertsobject
toshell.interface
, and replaces those strings with their identifier in the new system. This also works with strings such asmaxima(object)
ifshell.interface
ismaxima
.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 evaluatedcontinue_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
- 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
- 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 theBackendDoctest
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 appropriateinterface.eval(...)
input.INPUT:
interface
– a SagePExpect
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