Sage Input Formatting#

This module provides the function sage_input() that takes an arbitrary sage value and produces a sequence of commands that, if typed at the sage: prompt, will recreate the value. If this is not implemented for a particular value, then an exception is raised instead. This might be useful in understanding a part of Sage, or for debugging. For instance, if you have a value produced in a complicated way in the middle of a debugging session, you could use sage_input() to find a simple way to produce the same value. We attempt to produce commands that are readable and idiomatic.:

sage: sage_input(3)
3
sage: sage_input((polygen(RR) + RR(pi))^2, verify=True)                             # needs sage.symbolic
# Verified
R.<x> = RR[]
x^2 + 6.2831853071795862*x + 9.869604401089358

With verify=True, sage_input() also verifies the results, by calling sage_eval() on the result and verifying that it is equal to the input.:

sage: sage_input(GF(2)(1), verify=True)
# Verified
GF(2)(1)

We can generate code that works without the preparser, with preparse=False; or we can generate code that will work whether or not the preparser is enabled, with preparse=None. Generating code with preparse=False may be useful to see how to create a certain value in a Python or Cython source file.:

sage: sage_input(5, verify=True)
# Verified
5
sage: sage_input(5, preparse=False)
ZZ(5)
sage: sage_input(5, preparse=None)
ZZ(5)
sage: sage_input(5r, verify=True)
# Verified
5r
sage: sage_input(5r, preparse=False)
5
sage: sage_input(5r, preparse=None)
int(5)

Adding sage_input() support to your own classes is straightforward. You need to add a _sage_input_() method which returns a SageInputExpression (henceforth abbreviated as SIE) which will reconstruct this instance of your class.

A _sage_input_ method takes two parameters, conventionally named sib and coerced. The first argument is a SageInputBuilder; it has methods to build SIEs. The second argument, coerced, is a boolean. This is only useful if your class is a subclass of Element (although it is always present). If coerced is False, then your method must generate an expression which will evaluate to a value of the correct type with the correct parent. If coerced is True, then your method may generate an expression of a type that has a canonical coercion to your type; and if coerced is 2, then your method may generate an expression of a type that has a conversion to your type.

Let’s work through some examples. We’ll build a sequence of functions that would be acceptable as _sage_input_ methods for the Rational class.

Here’s the first and simplest version.:

sage: def qq_sage_input_v1(self, sib, coerced):
....:     return sib(self.numerator())/sib(self.denominator())

We see that given a SageInputBuilder sib, you can construct a SIE for a value v simply with sib(v), and you can construct a SIE for a quotient with the division operator. Of course, the other operators also work, and so do function calls, method calls, subscripts, etc.

We’ll test with the following code, which you don’t need to understand. (It produces a list of 8 results, showing the formatted versions of -5/7 and 3, with the preparser either enabled or disabled and either with or without an automatic coercion to QQ.):

sage: from sage.misc.sage_input import SageInputBuilder
sage: def test_qq_formatter(fmt):
....:     results = []
....:     for v in [-5/7, QQ(3)]:
....:         for pp in [False, True]:
....:             for coerced in [False, True]:
....:                 sib = SageInputBuilder(preparse=pp)
....:                 results.append(sib.result(fmt(v, sib, coerced)))
....:     return results

sage: test_qq_formatter(qq_sage_input_v1)
[-ZZ(5)/ZZ(7), -ZZ(5)/ZZ(7), -5/7, -5/7, ZZ(3)/ZZ(1), ZZ(3)/ZZ(1), 3/1, 3/1]

Let’s try for some shorter, perhaps nicer-looking output. We’ll start by getting rid of the ZZ in the denominators; even without the preparser, -ZZ(5)/7 == -ZZ(5)/ZZ(7).:

sage: def qq_sage_input_v2(self, sib, coerced):
....:     return sib(self.numerator())/sib.int(self.denominator())

The int method on SageInputBuilder returns a SIE for an integer that is always represented in the simple way, without coercions. (So, depending on the preparser mode, it might read in as an Integer or an int.):

sage: test_qq_formatter(qq_sage_input_v2)
[-ZZ(5)/7, -ZZ(5)/7, -5/7, -5/7, ZZ(3)/1, ZZ(3)/1, 3/1, 3/1]

Next let us get rid of the divisions by 1. These are more complicated, since if we are not careful we will get results in \(\ZZ\) instead of \(\QQ\):

sage: def qq_sage_input_v3(self, sib, coerced):
....:     if self.denominator() == 1:
....:         if coerced:
....:             return sib.int(self.numerator())
....:         else:
....:             return sib.name('QQ')(sib.int(self.numerator()))
....:     return sib(self.numerator())/sib.int(self.denominator())

We see that the method{name} method gives an SIE representing a sage constant or function.:

sage: test_qq_formatter(qq_sage_input_v3)
[-ZZ(5)/7, -ZZ(5)/7, -5/7, -5/7, QQ(3), 3, QQ(3), 3]

This is the prettiest output we’re going to get, but let’s make one further refinement. Other _sage_input_ methods, like the one for polynomials, analyze the structure of SIEs; they work better (give prettier output) if negations are at the outside. If the above code were used for rationals, then sage_input(polygen(QQ) - 2/3) would produce x + (-2/3); if we change to the following code, then we would get x - 2/3 instead.:

sage: def qq_sage_input_v4(self, sib, coerced):
....:     num = self.numerator()
....:     neg = (num < 0)
....:     if neg: num = -num
....:     if self.denominator() == 1:
....:         if coerced:
....:             v = sib.int(num)
....:         else:
....:             v = sib.name('QQ')(sib.int(num))
....:     else:
....:         v = sib(num)/sib.int(self.denominator())
....:     if neg: v = -v
....:     return v

sage: test_qq_formatter(qq_sage_input_v4)
[-ZZ(5)/7, -ZZ(5)/7, -5/7, -5/7, QQ(3), 3, QQ(3), 3]

AUTHORS:

  • Carl Witty (2008-04): new file

  • Vincent Delecroix (2015-02): documentation formatting

class sage.misc.sage_input.SIE_assign(sib, lhs, rhs)#

Bases: SageInputExpression

This class represents an assignment command.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.assign(sib.name('foo').x, sib.name('pi'))
{assign: {getattr: {atomic:foo}.x} {atomic:pi}}
class sage.misc.sage_input.SIE_binary(sib, op, lhs, rhs)#

Bases: SageInputExpression

This class represents an arithmetic expression with a binary operator and its two arguments, in a sage_input() expression tree.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib(3)+5
{binop:+ {atomic:3} {atomic:5}}
class sage.misc.sage_input.SIE_call(sib, func, args, kwargs)#

Bases: SageInputExpression

This class represents a function-call node in a sage_input() expression tree.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sie = sib.name('GF')
sage: sie(49)
{call: {atomic:GF}({atomic:49})}
class sage.misc.sage_input.SIE_dict(sib, entries)#

Bases: SageInputExpression

This class represents a dict node in a sage_input() expression tree.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.dict([('TeX', RR(pi)), ('Metafont', RR(e))])                          # needs sage.symbolic
{dict: {{atomic:'TeX'}:{call: {atomic:RR}({atomic:3.1415926535897931})},
        {atomic:'Metafont'}:{call: {atomic:RR}({atomic:2.7182818284590451})}}}
sage: sib.dict({-40:-40, 0:32, 100:212})
{dict: {{unop:- {atomic:40}}:{unop:- {atomic:40}},
        {atomic:0}:{atomic:32}, {atomic:100}:{atomic:212}}}
class sage.misc.sage_input.SIE_gen(sib, parent, name)#

Bases: SageInputExpression

This class represents a named generator of a parent with named generators.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.gen(ZZ['x'])
{gen:x {constr_parent: {subscr: {atomic:ZZ}[{atomic:'x'}]} with gens: ('x',)}}
class sage.misc.sage_input.SIE_gens_constructor(sib, constr, gen_names, gens_syntax=None)#

Bases: SageInputExpression

This class represents an expression that can create a sage parent with named generators, optionally using the sage preparser generators syntax (like K.<x> = QQ[]).

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: qq = sib.name('QQ')
sage: sib.parent_with_gens("some parent", qq['x'],
....:                      ('x',), 'QQx',
....:                      gens_syntax=sib.empty_subscript(qq))
{constr_parent: {subscr: {atomic:QQ}[{atomic:'x'}]} with gens: ('x',)}
class sage.misc.sage_input.SIE_getattr(sib, obj, attr)#

Bases: SageInputExpression

This class represents a getattr node in a sage_input() expression tree.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sie = sib.name('CC').gen()
sage: sie
{call: {getattr: {atomic:CC}.gen}()}
class sage.misc.sage_input.SIE_import_name(sib, module, name, alt_name=None)#

Bases: SageInputExpression

This class represents a name which has been imported from a module.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.import_name('sage.rings.integer', 'make_integer')
{import:sage.rings.integer/make_integer}
sage: sib.import_name('sage.foo', 'happy', 'sad')
{import:sage.foo/happy as sad}
class sage.misc.sage_input.SIE_literal(sib)#

Bases: SageInputExpression

An abstract base class for literals (basically, values which consist of a single token).

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder, SIE_literal

sage: sib = SageInputBuilder()
sage: sie = sib(3)
sage: sie
{atomic:3}
sage: isinstance(sie, SIE_literal)
True
class sage.misc.sage_input.SIE_literal_stringrep(sib, n)#

Bases: SIE_literal

Values in this class are leaves in a sage_input() expression tree. Typically they represent a single token, and consist of the string representation of that token. They are used for integer, floating-point, and string literals, and for name expressions.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder, SIE_literal_stringrep

sage: sib = SageInputBuilder()
sage: isinstance(sib(3), SIE_literal_stringrep)
True
sage: isinstance(sib(3.14159, True), SIE_literal_stringrep)                     # needs sage.rings.real_mpfr
True
sage: isinstance(sib.name('pi'), SIE_literal_stringrep)
True
sage: isinstance(sib(False), SIE_literal_stringrep)
True
sage: sib(False)
{atomic:False}
class sage.misc.sage_input.SIE_subscript(sib, coll, key)#

Bases: SageInputExpression

This class represents a subscript node in a sage_input() expression tree.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sie = sib.name('QQ')['x,y']
sage: sie
{subscr: {atomic:QQ}[{atomic:'x,y'}]}
class sage.misc.sage_input.SIE_tuple(sib, values, is_list)#

Bases: SageInputExpression

This class represents a tuple or list node in a sage_input() expression tree.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib((1, 'howdy'))
{tuple: ({atomic:1}, {atomic:'howdy'})}
sage: sib(["lists"])
{list: ({atomic:'lists'})}
class sage.misc.sage_input.SIE_unary(sib, op, operand)#

Bases: SageInputExpression

This class represents an arithmetic expression with a unary operator and its argument, in a sage_input() expression tree.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: -sib(256)
{unop:- {atomic:256}}
class sage.misc.sage_input.SageInputAnswer(cmds, expr, locals=None)#

Bases: tuple

This class inherits from tuple, so it acts like a tuple when passed to sage_eval(); but it prints as a sequence of commands.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputAnswer
sage: v = SageInputAnswer('x = 22\n', 'x/7'); v
x = 22
x/7
sage: isinstance(v, tuple)
True
sage: v[0]
'x = 22\n'
sage: v[1]
'x/7'
sage: len(v)
2
sage: v = SageInputAnswer('', 'sin(3.14)', {'sin': math.sin}); v
LOCALS:
  sin: <built-in function sin>
sin(3.14)
sage: v[0]
''
sage: v[1]
'sin(3.14)'
sage: v[2]
{'sin': <built-in function sin>}
class sage.misc.sage_input.SageInputBuilder(allow_locals=False, preparse=True)#

Bases: object

An instance of this class is passed to _sage_input_ methods. It keeps track of the current state of the _sage_input_ process, and contains many utility methods for building SageInputExpression objects.

In normal use, instances of SageInputBuilder are created internally by sage_input(), but it may be useful to create an instance directly for testing or doctesting.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

We can create a SageInputBuilder, use it to create some SageInputExpression s, and get a result. (As mentioned above, this is only useful for testing or doctesting; normally you would just use sage_input().):

sage: sib = SageInputBuilder()
sage: sib.result((sib(3) + sib(4)) * (sib(5) + sib(6)))
(3 + 4)*(5 + 6)
assign(e, val)#

Constructs a command that performs the assignment e=val.

Can only be used as an argument to the command method.

INPUT:

  • e, val – SageInputExpression

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: circular = sib([None])
sage: sib.command(circular, sib.assign(circular[0], circular))
sage: sib.result(circular)
si = [None]
si[0] = si
si
cache(x, sie, name)#

INPUT:

Enters x and sie in a cache, so that subsequent calls self(x) will directly return sie. Also, marks the requested name of this sie to be name.

This should almost always be called as part of the method{_sage_input_} method of a parent. It may also be called on values of an arbitrary type, which may be useful if the values are both large and likely to be used multiple times in a single expression.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sie42 = sib(GF(101)(42))
sage: sib.cache(GF(101)(42), sie42, 'the_ultimate_answer')
sage: sib.result(sib(GF(101)(42)) + sib(GF(101)(42)))
the_ultimate_answer = GF(101)(42)
the_ultimate_answer + the_ultimate_answer

Note that we don’t assign the result to a variable if the value is only used once.:

sage: sib = SageInputBuilder()
sage: sie42 = sib(GF(101)(42))
sage: sib.cache(GF(101)(42), sie42, 'the_ultimate_answer')
sage: sib.result(sib(GF(101)(42)) + sib(GF(101)(43)))
GF_101 = GF(101)
GF_101(42) + GF_101(43)
command(v, cmd)#

INPUT:

  • v, cmd – SageInputExpression

Attaches a command to v, which will be executed before v is used. Multiple commands will be executed in the order added.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: incr_list = sib([])
sage: sib.command(incr_list, incr_list.append(1))
sage: sib.command(incr_list, incr_list.extend([2, 3]))
sage: sib.result(incr_list)
si = []
si.append(1)
si.extend([2, 3])
si
dict(entries)#

Given a dictionary, or a list of (key, value) pairs, produces a SageInputExpression representing the dictionary.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.result(sib.dict({1:1, 2:5/2, 3:100/3}))
{1:1, 2:5/2, 3:100/3}
sage: sib.result(sib.dict([('hello', 'sunshine'), ('goodbye', 'rain')]))
{'hello':'sunshine', 'goodbye':'rain'}
empty_subscript(parent)#

Given a SageInputExpression representing foo, produces a SageInputExpression representing foo[]. Since this is not legal Python syntax, it is useful only for producing the sage generator syntax for a polynomial ring.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.result(sib.empty_subscript(sib(2) + sib(3)))
(2 + 3)[]

The following calls this method indirectly.:

sage: sage_input(polygen(ZZ['y']))
R.<x> = ZZ['y'][]
x
float_str(n)#

Given a string representing a floating-point number, produces a SageInputExpression that formats as that string.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.result(sib.float_str(repr(RR(e))))                                # needs sage.symbolic
2.71828182845905
gen(parent, n=0)#

Given a parent, returns a SageInputExpression for the \(n\)-th (default 0) generator of the parent.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.result(sib.gen(ZZ['y']))
R.<y> = ZZ[]
y
getattr(sie, attr)#

Given a SageInputExpression representing foo and an attribute name bar, produce a SageInputExpression representing foo.bar. Normally, you could just use attribute-access syntax, but that doesn’t work if bar is some attribute that bypasses __getattr__ (such as if bar is ‘__getattr__’ itself).

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.getattr(ZZ, '__getattr__')
{getattr: {atomic:ZZ}.__getattr__}
sage: sib.getattr(sib.name('foo'), '__new__')
{getattr: {atomic:foo}.__new__}
id_cache(x, sie, name)#

INPUT:

Enters x and sie in a cache, so that subsequent calls self(x) will directly return sie. Also, marks the requested name of this sie to be name. Differs from the method{cache} method in that the cache is keyed by id(x) instead of by x.

This may be called on values of an arbitrary type, which may be useful if the values are both large and likely to be used multiple times in a single expression; it should be preferred to method{cache} if equality on the values is difficult or impossible to compute.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: x = polygen(ZZ)
sage: sib = SageInputBuilder()
sage: my_42 = 42*x
sage: sie42 = sib(my_42)
sage: sib.id_cache(my_42, sie42, 'the_ultimate_answer')
sage: sib.result(sib(my_42) + sib(my_42))
R.<x> = ZZ[]
the_ultimate_answer = 42*x
the_ultimate_answer + the_ultimate_answer

Since id_cache keys off of object identity (“is”), the following does not trigger the cache.:

sage: sib.result(sib(42*x) + sib(42*x))
42*x + 42*x

Note that we don’t assign the result to a variable if the value is only used once.:

sage: sib = SageInputBuilder()
sage: my_42 = 42*x
sage: sie42 = sib(my_42)
sage: sib.id_cache(my_42, sie42, 'the_ultimate_answer')
sage: sib.result(sib(my_42) + sib(43*x))
R.<x> = ZZ[]
42*x + 43*x
import_name(module, name, alt_name=None)#

INPUT:

  • module, name, alt_name – strings

Creates an expression that will import a name from a module and then use that name.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: v1 = sib.import_name('sage.foo.bar', 'baz')
sage: v2 = sib.import_name('sage.foo.bar', 'ZZ', 'not_the_real_ZZ')
sage: sib.result(v1+v2)
from sage.foo.bar import baz
from sage.foo.bar import ZZ as not_the_real_ZZ
baz + not_the_real_ZZ

We adjust the names if there is a conflict.:

sage: sib = SageInputBuilder()
sage: v1 = sib.import_name('sage.foo', 'poly')
sage: v2 = sib.import_name('sage.bar', 'poly')
sage: sib.result(v1+v2)
from sage.foo import poly as poly1
from sage.bar import poly as poly2
poly1 + poly2
int(n)#

Return a raw SIE from the integer n

As it is raw, it may read back as a Sage Integer or a Python int, depending on its size and whether the preparser is enabled.

INPUT:

  • n – a Sage Integer or a Python int

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.result(sib.int(-3^50))
-717897987691852588770249

sage: sib = SageInputBuilder()
sage: sib.result(sib.int(-42r))
-42
name(n)#

Given a string representing a Python name, produces a SageInputExpression for that name.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.result(sib.name('pi') + sib.name('e'))
pi + e
parent_with_gens(parent, sie, gen_names, name, gens_syntax=None)#

This method is used for parents with generators, to manage the sage preparser generator syntax (like K.<x> = QQ[]).

The method{_sage_input_} method of a parent class with generators should construct a SageInputExpression for the parent, and then call this method with the parent itself, the constructed SIE, a sequence containing the names of the generators, and (optionally) another SIE to use if the sage generator syntax is used; typically this will be the same as the first SIE except omitting a names parameter.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder


sage: def test_setup(use_gens=True, preparse=True):
....:     sib = SageInputBuilder(preparse=preparse)
....:     gen_names=('foo', 'bar')
....:     parent = "some parent"
....:     normal_sie = sib.name('make_a_parent')(names=gen_names)
....:     if use_gens:
....:         gens_sie = sib.name('make_a_parent')()
....:     else:
....:         gens_sie = None
....:     name = 'the_thing'
....:     result = sib.parent_with_gens(parent, normal_sie,
....:                                   gen_names, name,
....:                                   gens_syntax=gens_sie)
....:     return sib, result

sage: sib, par_sie = test_setup()
sage: sib.result(par_sie)
make_a_parent(names=('foo', 'bar'))

sage: sib, par_sie = test_setup()
sage: sib.result(sib(3) * sib.gen("some parent", 0))
the_thing.<foo,bar> = make_a_parent()
3*foo

sage: sib, par_sie = test_setup(preparse=False)
sage: sib.result(par_sie)
make_a_parent(names=('foo', 'bar'))

sage: sib, par_sie = test_setup(preparse=False)
sage: sib.result(sib(3) * sib.gen("some parent", 0))
the_thing = make_a_parent(names=('foo', 'bar'))
foo,bar = the_thing.gens()
ZZ(3)*foo

sage: sib, par_sie = test_setup(use_gens=False)
sage: sib.result(par_sie)
make_a_parent(names=('foo', 'bar'))

sage: sib, par_sie = test_setup(use_gens=False)
sage: sib.result(sib(3) * sib.gen("some parent", 0))
the_thing = make_a_parent(names=('foo', 'bar'))
foo,bar = the_thing.gens()
3*foo

sage: sib, par_sie = test_setup()
sage: sib.result(par_sie - sib.gen("some parent", 1))
the_thing.<foo,bar> = make_a_parent()
the_thing - bar
preparse()#

Checks the preparse status.

It returns True if the preparser will be enabled, False if it will be disabled, and None if the result must work whether or not the preparser is enabled.

For example, this is useful in the method{_sage_input_} methods of Integer and RealNumber; but most method{_sage_input_} methods will not need to examine this.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder
sage: SageInputBuilder().preparse()
True
sage: SageInputBuilder(preparse=False).preparse()
False
prod(factors, simplify=False)#

Given a sequence, returns a SageInputExpression for the product of the elements.

With simplify=True, performs some simplifications first. If any element is formatted as a string '0', then that element is returned directly. If any element is formatted as a string '1', then it is removed from the sequence (unless it is the only element in the sequence). And any negations are removed from the elements and moved to the outside of the product.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.result(sib.prod([-1, 0, 1, -2]))
-1*0*1*-2

sage: sib = SageInputBuilder()
sage: sib.result(sib.prod([-1, 0, 1, 2], simplify=True))
0

sage: sib = SageInputBuilder()
sage: sib.result(sib.prod([-1, 2, -3, -4], simplify=True))
-2*3*4

sage: sib = SageInputBuilder()
sage: sib.result(sib.prod([-1, 1, -1, -1], simplify=True))
-1

sage: sib = SageInputBuilder()
sage: sib.result(sib.prod([1, 1, 1], simplify=True))
1
result(e)#

Given a SageInputExpression constructed using self, returns a tuple of a list of commands and an expression (and possibly a dictionary of local variables) suitable for sage_eval().

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: r = sib.result(sib(6) * sib(7)); r
6*7
sage: tuple(r)
('', '6*7')
share(sie)#

Mark the given expression as sharable, so that it will be replaced by a variable if it occurs multiple times in the expression. (Most non-single-token expressions are already sharable.)

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

Without explicitly using .share(), string literals are not shared:

sage: sib = SageInputBuilder()
sage: e = sib('hello')
sage: sib.result(sib((e, e)))
('hello', 'hello')

See the difference if we use .share():

sage: sib = SageInputBuilder()
sage: e = sib('hello')
sage: sib.share(e)
sage: sib.result(sib((e, e)))
si = 'hello'
(si, si)
sum(terms, simplify=False)#

Given a sequence, returns a SageInputExpression for the product of the elements.

With simplify=True, performs some simplifications first. If any element is formatted as a string '0', then it is removed from the sequence (unless it is the only element in the sequence); and any instances of a + -b are changed to a - b.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: sib.result(sib.sum([-1, 0, 1, 0, -1]))
-1 + 0 + 1 + 0 + -1

sage: sib = SageInputBuilder()
sage: sib.result(sib.sum([-1, 0, 1, 0, -1], simplify=True))
-1 + 1 - 1

sage: sib = SageInputBuilder()
sage: sib.result(sib.sum([0, 0, 0], simplify=True))
0
use_variable(sie, name)#

Marks the SageInputExpression sie to use a variable even if it is only referenced once. (If sie is the final top-level expression, though, it will not use a variable.)

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder

sage: sib = SageInputBuilder()
sage: e = sib.name('MatrixSpace')(ZZ, 10, 10)
sage: sib.use_variable(e, 'MS')
sage: sib.result(e.zero_matrix())
MS = MatrixSpace(ZZ, 10, 10)
MS.zero_matrix()

Without the call to use_variable, we get this instead:

sage: sib = SageInputBuilder()
sage: e = sib.name('MatrixSpace')(ZZ, 10, 10)
sage: sib.result(e.zero_matrix())
MatrixSpace(ZZ, 10, 10).zero_matrix()

And even with the call to use_variable, we don’t use a variable here:

sage: sib = SageInputBuilder()
sage: e = sib.name('MatrixSpace')(ZZ, 10, 10)
sage: sib.use_variable(e, 'MS')
sage: sib.result(e)
MatrixSpace(ZZ, 10, 10)
class sage.misc.sage_input.SageInputExpression(sib)#

Bases: object

Subclasses of this class represent expressions for sage_input(). sage classes should define a method{_sage_input_} method, which will return an instance of SageInputExpression, created using methods of SageInputBuilder.

To the extent possible, operations on SageInputExpression objects construct a new SageInputExpression representing that operation. That is, if a is a SageInputExpression, then a + b constructs a SageInputExpression representing this sum. This also works for attribute access, function calls, subscripts, etc. Since arbitrary attribute accesses might be used to construct a new attribute-access expression, all internal attributes and methods have names that begin with _sie_ to reduce the chance of collisions.

It is expected that instances of this class will not be directly created outside this module; instead, instances will be created using methods of SageInputBuilder and SageInputExpression.

Values of type SageInputExpression print in a fairly ugly way, that reveals the internal structure of the expression tree.

class sage.misc.sage_input.SageInputFormatter#

Bases: object

An instance of this class is used to keep track of variable names and a sequence of generated commands during the sage_input() formatting process.

format(e, prec)#

Format a Sage input expression into a string.

INPUT:

First, we check to see if e should be replaced by a variable. If so, we generate the command to assign the variable, and return the name of the variable.

Otherwise, we format the expression by calling its method{_sie_format} method, and add parentheses if necessary.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter

sage: sib = SageInputBuilder()
sage: sif = SageInputFormatter()
sage: sie = sib(GF(5))

Here we cheat by calling method{_sie_prepare} twice, to make it use a variable.:

sage: sie._sie_prepare(sif)
sage: sie._sie_prepare(sif)
sage: sif._commands
''
sage: sif.format(sie, 0)
'GF_5'
sage: sif._commands
'GF_5 = GF(5)\n'

We demonstrate the use of commands, by showing how to construct code that will produce a random matrix:

sage: sib = SageInputBuilder()
sage: sif = SageInputFormatter()
sage: sie = sib.name('matrix')(sib.name('ZZ'), 10, 10)
sage: sib.command(sie, sie.randomize())
sage: sie._sie_prepare(sif)
sage: sif._commands
''
sage: sif.format(sie, 0)
'si'
sage: sif._commands
'si = matrix(ZZ, 10, 10)\nsi.randomize()\n'
get_name(name)#

Return a name corresponding to a given requested name. If only one request for a name is received, then we will use the requested name; otherwise, we will add numbers to the end of the name to make it unique.

If the input name is None, then it is treated as a name of 'si'.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputFormatter

sage: sif = SageInputFormatter()
sage: names = ('x', 'x', 'y', 'z')
sage: for n in names: sif.register_name(n)
sage: for n in names: sif.get_name(n)
'x1'
'x2'
'y'
'z'
register_name(name)#

Register that some value would like to use a given name. If only one request for a name is received, then we will use the requested name; otherwise, we will add numbers to the end of the name to make it unique.

If the input name is None, then it is treated as a name of 'si'.

EXAMPLES:

sage: from sage.misc.sage_input import SageInputFormatter

sage: sif = SageInputFormatter()
sage: sif._names, sif._dup_names
(set(), {})
sage: sif.register_name('x')
sage: sif.register_name('y')
sage: sif._names, sif._dup_names
({'x', 'y'}, {})
sage: sif.register_name('x')
sage: sif._names, sif._dup_names
({'x', 'y'}, {'x': 0})
sage.misc.sage_input.sage_input(x, preparse=True, verify=False, allow_locals=False)#

Return a sequence of commands that can be used to rebuild the object x.

INPUT:

  • x - the value we want to find an input form for

  • preparse - (default True) Whether to generate code that requires the preparser. With True, generated code requires the preparser. With False, generated code requires that the preparser not be used. With None, generated code will work whether or not the preparser is used.

  • verify - (default False) If True, then the answer will be evaluated with sage_eval(), and an exception will be raised if the result is not equal to the original value. (In fact, for verify=True, sage_input() is effectively run three times, with preparse set to True, False, and None, and all three results are checked.) This is particularly useful for doctests.

  • allow_locals - (default False) If True, then values that sage_input() cannot handle are returned in a dictionary, and the returned code assumes that this dictionary is passed as the locals parameter of sage_eval(). (Otherwise, if sage_input() cannot handle a value, an exception is raised.)

EXAMPLES:

sage: sage_input(GF(2)(1))
GF(2)(1)
sage: sage_input((GF(2)(0), GF(2)(1)), verify=True)
# Verified
GF_2 = GF(2)
(GF_2(0), GF_2(1))

When the preparser is enabled, we use the sage generator syntax.:

sage: K.<x> = GF(5)[]
sage: sage_input(x^3 + 2*x, verify=True)
# Verified
R.<x> = GF(5)[]
x^3 + 2*x
sage: sage_input(x^3 + 2*x, preparse=False)
R = GF(5)['x']
x = R.gen()
x**3 + 2*x

The result of sage_input() is actually a pair of strings with a special __repr__ method to print nicely.:

sage: # needs sage.rings.real_mpfr sage.symbolic
sage: r = sage_input(RealField(20)(pi), verify=True)
sage: r
# Verified
RealField(20)(3.1415939)
sage: isinstance(r, tuple)
True
sage: len(r)
2
sage: tuple(r)
('# Verified\n', 'RealField(20)(3.1415939)')

We cannot find an input form for a function.:

sage: sage_input((3, lambda x: x))
Traceback (most recent call last):
...
ValueError: cannot convert <function <lambda> at 0x...> to sage_input form

But we can have sage_input() continue anyway, and return an input form for the rest of the expression, with allow_locals=True.:

sage: r = sage_input((3, lambda x: x), verify=True, allow_locals=True)
sage: r
LOCALS:
    _sil1: <function <lambda> at 0x...>
# Verified
(3, _sil1)
sage: tuple(r)
('# Verified\n', '(3, _sil1)', {'_sil1': <function <lambda> at 0x...>})
sage.misc.sage_input.verify_same(a, b)#

Verify that two Sage values are the same. This is an extended equality test; it checks that the values are equal and that their parents are equal. (For values which are not Elements, the types are checked instead.)

If the values are the same, we return None; otherwise, we raise an exception.

EXAMPLES:

sage: from sage.misc.sage_input import verify_same
sage: verify_same(1, 1)
sage: verify_same(1, 2)
Traceback (most recent call last):
...
AssertionError: Expected 1 == 2
sage: verify_same(1, 1r)
Traceback (most recent call last):
...
AttributeError: 'int' object has no attribute 'parent'...
sage: verify_same(1r, 1)
Traceback (most recent call last):
...
    assert(type(a) == type(b))
AssertionError
sage: verify_same(5, GF(7)(5))
Traceback (most recent call last):
...
    assert(a.parent() == b.parent())
AssertionError
sage.misc.sage_input.verify_si_answer(x, answer, preparse)#

Verify that evaluating answer gives a value equal to x (with the same parent/type). If preparse is True or False, then we evaluate answer with the preparser enabled or disabled, respectively; if preparse is None, then we evaluate answer both with the preparser enabled and disabled and check both results.

On success, we return None; on failure, we raise an exception.

INPUT:

  • x - an arbitrary Sage value

  • answer - a string, or a SageInputAnswer

  • preparseTrue, False, or None

EXAMPLES:

sage: from sage.misc.sage_input import verify_si_answer
sage: verify_si_answer(1, '1', True)
sage: verify_si_answer(1, '1', False)
Traceback (most recent call last):
...
AttributeError: 'int' object has no attribute 'parent'...
sage: verify_si_answer(1, 'ZZ(1)', None)