Base Class for Backends#

The display backends are the commandline, the IPython notebook, the Emacs sage mode, the Sage doctester, …. All of these have different capabilities for what they can display.

To implement a new display backend, you need to subclass BackendBase. All backend-specific handling of rich output should be in displayhook() and display_immediately(). See BackendSimple for an absolutely minimal example of a functioning backend.

You declare the types of rich output that your backend can handle in supported_output(). There are two ways to then display specific output types in your own backend.

You can also mix both ways of implementing different rich output types.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendSimple
sage: backend = BackendSimple()
sage: plain_text = backend.plain_text_formatter(list(range(10)));  plain_text
OutputPlainText container
sage: backend.displayhook(plain_text, plain_text)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendSimple
>>> backend = BackendSimple()
>>> plain_text = backend.plain_text_formatter(list(range(Integer(10))));  plain_text
OutputPlainText container
>>> backend.displayhook(plain_text, plain_text)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
class sage.repl.rich_output.backend_base.BackendBase[source]#

Bases: SageObject

ascii_art_formatter(obj, **kwds)[source]#

Hook to override how ascii art is being formatted.

INPUT:

  • obj – anything.

  • **kwds – optional keyword arguments to control the formatting. Supported are:

    • concatenate – boolean (default: False). If True, the argument obj must be iterable and its entries will be concatenated. There is a single whitespace between entries.

OUTPUT:

Instance of OutputAsciiArt containing the ascii art string representation of the object.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: out = backend.ascii_art_formatter(list(range(30)))
sage: out
OutputAsciiArt container
sage: out.ascii_art
buffer containing 114 bytes
sage: print(out.ascii_art.get_str())
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,

 22, 23, 24, 25, 26, 27, 28, 29 ]
sage: backend.ascii_art_formatter([1,2,3], concatenate=False).ascii_art.get_str()
'[ 1, 2, 3 ]'
sage: backend.ascii_art_formatter([1,2,3], concatenate=True).ascii_art.get_str()
'1 2 3'
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> out = backend.ascii_art_formatter(list(range(Integer(30))))
>>> out
OutputAsciiArt container
>>> out.ascii_art
buffer containing 114 bytes
>>> print(out.ascii_art.get_str())
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
<BLANKLINE>
 22, 23, 24, 25, 26, 27, 28, 29 ]
>>> backend.ascii_art_formatter([Integer(1),Integer(2),Integer(3)], concatenate=False).ascii_art.get_str()
'[ 1, 2, 3 ]'
>>> backend.ascii_art_formatter([Integer(1),Integer(2),Integer(3)], concatenate=True).ascii_art.get_str()
'1 2 3'
default_preferences()[source]#

Return the backend’s display preferences

Override this method to change the default preferences when using your backend.

OUTPUT:

Instance of DisplayPreferences.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: backend.default_preferences()
Display preferences:
* align_latex is not specified
* graphics is not specified
* supplemental_plot is not specified
* text is not specified
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> backend.default_preferences()
Display preferences:
* align_latex is not specified
* graphics is not specified
* supplemental_plot is not specified
* text is not specified
display_immediately(plain_text, rich_output)[source]#

Show output without going back to the command line prompt.

This method is similar to the rich output displayhook(), except that it can be invoked at any time. Typically, it ends up being called by sage.plot.graphics.Graphics.show().

Derived classes must implement this method.

INPUT:

Same as displayhook().

OUTPUT:

This method may return something so you can implement displayhook() by calling this method. However, when called by the display manager any potential return value is discarded: There is no way to return anything without returning to the command prompt.

EXAMPLES:

sage: from sage.repl.rich_output.output_basic import OutputPlainText
sage: plain_text = OutputPlainText.example()
sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: backend.display_immediately(plain_text, plain_text)
Traceback (most recent call last):
...
NotImplementedError: derived classes must implement this method
>>> from sage.all import *
>>> from sage.repl.rich_output.output_basic import OutputPlainText
>>> plain_text = OutputPlainText.example()
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> backend.display_immediately(plain_text, plain_text)
Traceback (most recent call last):
...
NotImplementedError: derived classes must implement this method
displayhook(plain_text, rich_output)[source]#

Backend implementation of the displayhook

The value of the last statement on a REPL input line or notebook cell are usually handed to the Python displayhook and shown on screen. By overriding this method you define how your backend handles output. The difference to the usual displayhook is that Sage already converted the value to the most suitable rich output container.

Derived classes must implement this method.

INPUT:

  • plain_text – instance of OutputPlainText. The plain text version of the output.

  • rich_output – instance of an output container class (subclass of OutputBase). Guaranteed to be one of the output containers returned from supported_output(), possibly the same as plain_text.

OUTPUT:

This method may return something, which is then returned from the display manager’s displayhook() method.

EXAMPLES:

sage: from sage.repl.rich_output.output_basic import OutputPlainText
sage: plain_text = OutputPlainText.example()
sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: backend.displayhook(plain_text, plain_text)
Traceback (most recent call last):
...
NotImplementedError: derived classes must implement this method
>>> from sage.all import *
>>> from sage.repl.rich_output.output_basic import OutputPlainText
>>> plain_text = OutputPlainText.example()
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> backend.displayhook(plain_text, plain_text)
Traceback (most recent call last):
...
NotImplementedError: derived classes must implement this method
get_display_manager()[source]#

Return the display manager singleton

This is a convenience method to access the display manager singleton.

OUTPUT:

The unique DisplayManager instance.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: backend.get_display_manager()
The Sage display manager using the doctest backend
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> backend.get_display_manager()
The Sage display manager using the doctest backend
install(**kwds)[source]#

Hook that will be called once before the backend is used for the first time.

The default implementation does nothing.

INPUT:

  • kwds – optional keyword arguments that are passed through by the switch_backend() method.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: backend.install()
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> backend.install()
is_in_terminal()[source]#

Test whether the UI is meant to run in a terminal

See sage.repl.rich_output.display_manager.DisplayManager.is_in_terminal() for details.

OUTPUT:

Defaults to False.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: backend.is_in_terminal()
False
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> backend.is_in_terminal()
False
latex_formatter(obj, **kwds)[source]#

Hook to override how latex is being formatted.

INPUT:

  • obj – anything.

  • **kwds – optional keyword arguments to control the formatting. Supported are:

    • concatenate – boolean (default: False). If True, the argument obj must be iterable and its entries will be concatenated. There is a single whitespace between entries.

OUTPUT:

Instance of OutputHtml containing the latex string representation of the object.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: out = backend.latex_formatter(1/2)
sage: out
OutputHtml container
sage: out.html
buffer containing 42 bytes
sage: out.html.get_str()
'<html>\\(\\displaystyle \\frac{1}{2}\\)</html>'

sage: # needs sage.symbolic
sage: out = backend.latex_formatter([1/2, x, 3/4, ZZ], concatenate=False)
sage: out.html.get_str()
'<html>\\(\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\frac{1}{2}, x, \\frac{3}{4}, \\Bold{Z}\\right]\\)</html>'
sage: out = backend.latex_formatter([1/2, x, 3/4, ZZ], concatenate=True)
sage: out.html.get_str()
'<html>\\(\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\frac{1}{2} x \\frac{3}{4} \\Bold{Z}\\)</html>'
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> out = backend.latex_formatter(Integer(1)/Integer(2))
>>> out
OutputHtml container
>>> out.html
buffer containing 42 bytes
>>> out.html.get_str()
'<html>\\(\\displaystyle \\frac{1}{2}\\)</html>'

>>> # needs sage.symbolic
>>> out = backend.latex_formatter([Integer(1)/Integer(2), x, Integer(3)/Integer(4), ZZ], concatenate=False)
>>> out.html.get_str()
'<html>\\(\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\frac{1}{2}, x, \\frac{3}{4}, \\Bold{Z}\\right]\\)</html>'
>>> out = backend.latex_formatter([Integer(1)/Integer(2), x, Integer(3)/Integer(4), ZZ], concatenate=True)
>>> out.html.get_str()
'<html>\\(\\displaystyle \\newcommand{\\Bold}[1]{\\mathbf{#1}}\\frac{1}{2} x \\frac{3}{4} \\Bold{Z}\\)</html>'
max_width()[source]#

Return the number of characters that fit into one output line

OUTPUT:

Integer.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: backend.max_width()
79
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> backend.max_width()
79
newline()[source]#

Return the newline string.

OUTPUT:

String for starting a new line of output.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: backend.newline()
'\n'
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> backend.newline()
'\n'
plain_text_formatter(obj, **kwds)[source]#

Hook to override how plain text is being formatted.

If the object does not have a _rich_repr_ method, or if it does not return a rich output object (OutputBase), then this method is used to generate plain text output.

INPUT:

  • obj – anything.

  • **kwds – optional keyword arguments to control the formatting. Supported are:

    • concatenate – boolean (default: False). If True, the argument obj must be iterable and its entries will be concatenated. There is a single whitespace between entries.

OUTPUT:

Instance of OutputPlainText containing the string representation of the object.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: out = backend.plain_text_formatter(list(range(30)))
sage: out
OutputPlainText container
sage: out.text
buffer containing 139 bytes
sage: out.text.get_str()
'[0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6,\n 7,\n 8,\n 9,\n
10,\n 11,\n 12,\n 13,\n 14,\n 15,\n 16,\n 17,\n 18,\n
19,\n 20,\n 21,\n 22,\n 23,\n 24,\n 25,\n 26,\n 27,\n
28,\n 29]'

sage: out = backend.plain_text_formatter(list(range(20)), concatenate=True)
sage: out.text.get_str()
'0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19'
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> out = backend.plain_text_formatter(list(range(Integer(30))))
>>> out
OutputPlainText container
>>> out.text
buffer containing 139 bytes
>>> out.text.get_str()
'[0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6,\n 7,\n 8,\n 9,\n
10,\n 11,\n 12,\n 13,\n 14,\n 15,\n 16,\n 17,\n 18,\n
19,\n 20,\n 21,\n 22,\n 23,\n 24,\n 25,\n 26,\n 27,\n
28,\n 29]'

>>> out = backend.plain_text_formatter(list(range(Integer(20))), concatenate=True)
>>> out.text.get_str()
'0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19'
set_underscore_variable(obj)[source]#

Set the _ builtin variable.

By default, this sets the special _ variable. Backends that organize the history differently (e.g. IPython) can override this method.

INPUT:

  • obj – result of the most recent evaluation.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: backend.set_underscore_variable(123)
sage: _
123

sage: 'foo'
'foo'
sage: _     # indirect doctest
'foo'
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> backend.set_underscore_variable(Integer(123))
>>> _
123

>>> 'foo'
'foo'
>>> _     # indirect doctest
'foo'
supported_output()[source]#

Return the outputs that are supported by the backend.

Subclasses must implement this method.

OUTPUT:

Iterable of output container classes, that is, subclass of OutputBase). May be a list/tuple/set/frozenset. The order is ignored. Only used internally by the display manager.

You may return backend-specific subclasses of existing output containers. This allows you to attach backend-specific functionality to the output container.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: backend.supported_output()
Traceback (most recent call last):
...
NotImplementedError: derived classes must implement this method
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> backend.supported_output()
Traceback (most recent call last):
...
NotImplementedError: derived classes must implement this method
unicode_art_formatter(obj, **kwds)[source]#

Hook to override how unicode art is being formatted.

INPUT:

  • obj – anything.

  • **kwds – optional keyword arguments to control the formatting. Supported are:

    • concatenate – boolean (default: False). If True, the argument obj must be iterable and its entries will be concatenated. There is a single whitespace between entries.

OUTPUT:

Instance of OutputUnicodeArt containing the unicode art string representation of the object.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: out = backend.unicode_art_formatter(list(range(30)))
sage: out
OutputUnicodeArt container
sage: out.unicode_art
buffer containing 114 bytes
sage: print(out.unicode_art.get_str())
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,

22, 23, 24, 25, 26, 27, 28, 29 ]

sage: backend.unicode_art_formatter([1,2,3], concatenate=False).unicode_art.get_str()
'[ 1, 2, 3 ]'
sage: backend.unicode_art_formatter([1,2,3], concatenate=True).unicode_art.get_str()
'1 2 3'
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> out = backend.unicode_art_formatter(list(range(Integer(30))))
>>> out
OutputUnicodeArt container
>>> out.unicode_art
buffer containing 114 bytes
>>> print(out.unicode_art.get_str())
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
<BLANKLINE>
22, 23, 24, 25, 26, 27, 28, 29 ]

>>> backend.unicode_art_formatter([Integer(1),Integer(2),Integer(3)], concatenate=False).unicode_art.get_str()
'[ 1, 2, 3 ]'
>>> backend.unicode_art_formatter([Integer(1),Integer(2),Integer(3)], concatenate=True).unicode_art.get_str()
'1 2 3'
uninstall()[source]#

Hook that will be called once right before the backend is removed.

The default implementation does nothing.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendBase
sage: backend = BackendBase()
sage: backend.uninstall()
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendBase
>>> backend = BackendBase()
>>> backend.uninstall()
class sage.repl.rich_output.backend_base.BackendSimple[source]#

Bases: BackendBase

Simple Backend

This backend only supports plain text.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendSimple
sage: BackendSimple()
simple
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendSimple
>>> BackendSimple()
simple
display_immediately(plain_text, rich_output)[source]#

Show output without going back to the command line prompt.

INPUT:

Same as displayhook().

OUTPUT:

This backend returns nothing, it just prints to stdout.

EXAMPLES:

sage: from sage.repl.rich_output.output_basic import OutputPlainText
sage: plain_text = OutputPlainText.example()
sage: from sage.repl.rich_output.backend_base import BackendSimple
sage: backend = BackendSimple()
sage: backend.display_immediately(plain_text, plain_text)
Example plain text output
>>> from sage.all import *
>>> from sage.repl.rich_output.output_basic import OutputPlainText
>>> plain_text = OutputPlainText.example()
>>> from sage.repl.rich_output.backend_base import BackendSimple
>>> backend = BackendSimple()
>>> backend.display_immediately(plain_text, plain_text)
Example plain text output
supported_output()[source]#

Return the outputs that are supported by the backend.

OUTPUT:

Iterable of output container classes, that is, subclass of OutputBase). This backend only supports the plain text output container.

EXAMPLES:

sage: from sage.repl.rich_output.backend_base import BackendSimple
sage: backend = BackendSimple()
sage: backend.supported_output()
{<class 'sage.repl.rich_output.output_basic.OutputPlainText'>}
>>> from sage.all import *
>>> from sage.repl.rich_output.backend_base import BackendSimple
>>> backend = BackendSimple()
>>> backend.supported_output()
{<class 'sage.repl.rich_output.output_basic.OutputPlainText'>}