algebra_with_sympy.preparser

 1def algebra_with_sympy_preparser(lines):
 2    """
 3    In IPython compatible environments (Jupyter, IPython, etc...) this supports
 4    a special compact input method for equations.
 5
 6    The syntax supported is `equation_name =@ equation.lhs = equation.rhs`,
 7    where `equation_name` is a valid Python name that can be used to refer to
 8    the equation later. `equation.lhs` is the left-hand side of the equation
 9    and `equation.rhs` is the right-hand side of the equation. Each side of the
10    equation must parse into a valid Sympy expression.
11
12    **Note**: This does not support line continuation. Long equations should be
13    built by combining expressions using names short enough to do this on one
14    line. The alternative is to use `equation_name = Eqn(long ...
15    expressions ... with ... multiple ... lines)`.
16
17    **Note**: If the `equation_name` is omitted the equation will be formed,
18    but it will not be assigned to a name that can be used to refer to it
19    later. You may be able to access it through one of the special IPython
20    underscore names. This is not recommended.
21
22    **THIS FUNCTION IS USED BY THE IPYTHON ENVIRONMENT TO PREPARSE THE INPUT
23    BEFORE IT IS PASSED TO THE PYTHON INTERPRETER. IT IS NOT MEANT TO BE USED
24    DIRECTLY BY A USER**
25    """
26    new_lines = []
27    if isinstance(lines,str):
28        lines = [lines]
29    for k in lines:
30        if '=@' in k:
31            drop_comments = k.split('#')
32            to_rephrase = ''
33            if len(drop_comments) > 2:
34                for i in range(len(drop_comments)-1):
35                    to_rephrase += drop_comments[i]
36            else:
37                to_rephrase = drop_comments[0]
38            linesplit = to_rephrase.split('=@')
39            eqsplit = linesplit[1].split('=')
40            if len(eqsplit)!=2:
41                raise ValueError('The two sides of the equation must be' \
42                                 ' separated by an \"=\" sign when using' \
43                                 ' the \"=@\" special input method.')
44            templine =''
45            if eqsplit[0]!='' and eqsplit[1]!='':
46                if eqsplit[1].endswith('\n'):
47                    eqsplit[1] = eqsplit[1][:-1]
48                if linesplit[0]!='':
49                    templine = str(linesplit[0])+'= Eqn('+str(eqsplit[0])+',' \
50                        ''+str(eqsplit[1])+')\n'
51                else:
52                    templine = 'Eqn('+str(eqsplit[0])+','+str(eqsplit[1])+')\n'
53            new_lines.append(templine)
54        else:
55            new_lines.append(k)
56    return new_lines
57
58
59def integers_as_exact(lines):
60    """This preparser uses `sympy.interactive.session.int_to_Integer` to
61    convert numbers without decimal points into sympy integers so that math
62    on them will be exact rather than defaulting to floating point. **This
63    should not be called directly by the user. It is plugged into the
64    IPython preparsing sequence when the feature is requested.** The default for
65    Algebra_with_sympy is to use this preparser. This can be turned on and
66    off using the Algebra_with_sympy functions:
67    * `set_integers_as_exact()`
68    * `unset_integers_as_exact()`
69    """
70    from sympy.interactive.session import int_to_Integer
71    string = ''
72    for k in lines:
73        string += k + '\n'
74    string = string[:-1] # remove the last '\n'
75    return int_to_Integer(string)
76
77from IPython import get_ipython
78if get_ipython():
79    if hasattr(get_ipython(),'input_transformers_cleanup'):
80        get_ipython().input_transformers_post.\
81            append(algebra_with_sympy_preparser)
82    else:
83        import warnings
84        warnings.warn('Compact equation input unavailable.\nYou will have ' \
85                      'to use the form "eq1 = Eqn(lhs,rhs)" instead of ' \
86                      '"eq1=@lhs=rhs".\nIt appears you are running an ' \
87                      'outdated version of IPython.\nTo fix, update IPython ' \
88                      'using "pip install -U IPython".')
def algebra_with_sympy_preparser(lines):
 2def algebra_with_sympy_preparser(lines):
 3    """
 4    In IPython compatible environments (Jupyter, IPython, etc...) this supports
 5    a special compact input method for equations.
 6
 7    The syntax supported is `equation_name =@ equation.lhs = equation.rhs`,
 8    where `equation_name` is a valid Python name that can be used to refer to
 9    the equation later. `equation.lhs` is the left-hand side of the equation
10    and `equation.rhs` is the right-hand side of the equation. Each side of the
11    equation must parse into a valid Sympy expression.
12
13    **Note**: This does not support line continuation. Long equations should be
14    built by combining expressions using names short enough to do this on one
15    line. The alternative is to use `equation_name = Eqn(long ...
16    expressions ... with ... multiple ... lines)`.
17
18    **Note**: If the `equation_name` is omitted the equation will be formed,
19    but it will not be assigned to a name that can be used to refer to it
20    later. You may be able to access it through one of the special IPython
21    underscore names. This is not recommended.
22
23    **THIS FUNCTION IS USED BY THE IPYTHON ENVIRONMENT TO PREPARSE THE INPUT
24    BEFORE IT IS PASSED TO THE PYTHON INTERPRETER. IT IS NOT MEANT TO BE USED
25    DIRECTLY BY A USER**
26    """
27    new_lines = []
28    if isinstance(lines,str):
29        lines = [lines]
30    for k in lines:
31        if '=@' in k:
32            drop_comments = k.split('#')
33            to_rephrase = ''
34            if len(drop_comments) > 2:
35                for i in range(len(drop_comments)-1):
36                    to_rephrase += drop_comments[i]
37            else:
38                to_rephrase = drop_comments[0]
39            linesplit = to_rephrase.split('=@')
40            eqsplit = linesplit[1].split('=')
41            if len(eqsplit)!=2:
42                raise ValueError('The two sides of the equation must be' \
43                                 ' separated by an \"=\" sign when using' \
44                                 ' the \"=@\" special input method.')
45            templine =''
46            if eqsplit[0]!='' and eqsplit[1]!='':
47                if eqsplit[1].endswith('\n'):
48                    eqsplit[1] = eqsplit[1][:-1]
49                if linesplit[0]!='':
50                    templine = str(linesplit[0])+'= Eqn('+str(eqsplit[0])+',' \
51                        ''+str(eqsplit[1])+')\n'
52                else:
53                    templine = 'Eqn('+str(eqsplit[0])+','+str(eqsplit[1])+')\n'
54            new_lines.append(templine)
55        else:
56            new_lines.append(k)
57    return new_lines

In IPython compatible environments (Jupyter, IPython, etc...) this supports a special compact input method for equations.

The syntax supported is equation_name =@ equation.lhs = equation.rhs, where equation_name is a valid Python name that can be used to refer to the equation later. equation.lhs is the left-hand side of the equation and equation.rhs is the right-hand side of the equation. Each side of the equation must parse into a valid Sympy expression.

Note: This does not support line continuation. Long equations should be built by combining expressions using names short enough to do this on one line. The alternative is to use equation_name = Eqn(long ... expressions ... with ... multiple ... lines).

Note: If the equation_name is omitted the equation will be formed, but it will not be assigned to a name that can be used to refer to it later. You may be able to access it through one of the special IPython underscore names. This is not recommended.

THIS FUNCTION IS USED BY THE IPYTHON ENVIRONMENT TO PREPARSE THE INPUT BEFORE IT IS PASSED TO THE PYTHON INTERPRETER. IT IS NOT MEANT TO BE USED DIRECTLY BY A USER

def integers_as_exact(lines):
60def integers_as_exact(lines):
61    """This preparser uses `sympy.interactive.session.int_to_Integer` to
62    convert numbers without decimal points into sympy integers so that math
63    on them will be exact rather than defaulting to floating point. **This
64    should not be called directly by the user. It is plugged into the
65    IPython preparsing sequence when the feature is requested.** The default for
66    Algebra_with_sympy is to use this preparser. This can be turned on and
67    off using the Algebra_with_sympy functions:
68    * `set_integers_as_exact()`
69    * `unset_integers_as_exact()`
70    """
71    from sympy.interactive.session import int_to_Integer
72    string = ''
73    for k in lines:
74        string += k + '\n'
75    string = string[:-1] # remove the last '\n'
76    return int_to_Integer(string)

This preparser uses sympy.interactive.session.int_to_Integer to convert numbers without decimal points into sympy integers so that math on them will be exact rather than defaulting to floating point. This should not be called directly by the user. It is plugged into the IPython preparsing sequence when the feature is requested. The default for Algebra_with_sympy is to use this preparser. This can be turned on and off using the Algebra_with_sympy functions:

  • set_integers_as_exact()
  • unset_integers_as_exact()