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
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
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
.- Parameters:
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)'
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'
- priority = 50#
- transform(line, continue_prompt)[source]#
Evaluates line in
shell.interface
and returns a string representing the result of that evaluation.- Parameters:
line (string) – the line to be transformed and evaluated
continue_prompt (bool) – is this line 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""")'
- 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', '[email protected]'), ('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', '[email protected]'), ('contact_name', 'sage-support'), ('crash_report_fname', 'Crash_report_Sage.txt')]
- 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...>
- 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
- 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']
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()
- 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()
- 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...>
- 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...>
- 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
- 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()
- 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()
- 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
- 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()
- 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()
- sage.repl.interpreter.interface_shell_embed(interface)[source]#
Returns 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 ]>
- 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.
- Parameters:
on (bool) – if True turn on preparsing; if False, turn it off.
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