--- doc/src/gotchas.rst.orig 2015-09-03 14:34:00.000000000 -0600 +++ doc/src/gotchas.rst 2015-11-21 15:24:18.475852154 -0700 @@ -148,7 +148,7 @@ See the Python docs for more information If you define a circular relationship, you will get a -:exc:`RuntimeError`. +:exc:`RecursionError`. >>> def a(): ... return b() @@ -169,7 +169,7 @@ If you define a circular relationship, y File "<...>", line 2, in a return b() ... - RuntimeError: maximum recursion depth exceeded + RecursionError: maximum recursion depth exceeded .. note:: --- sympy/concrete/expr_with_limits.py.orig 2015-09-03 14:34:00.000000000 -0600 +++ sympy/concrete/expr_with_limits.py 2015-11-21 15:26:31.337139532 -0700 @@ -25,12 +25,12 @@ def _process_limits(*symbols): limits = [] orientation = 1 for V in symbols: - if isinstance(V, Symbol): + if isinstance(V, Symbol) or getattr(V, '_diff_wrt', False): limits.append(Tuple(V)) continue elif is_sequence(V, Tuple): V = sympify(flatten(V)) - if V[0].is_Symbol: + if V[0].is_Symbol or getattr(V[0], '_diff_wrt', False): newsymbol = V[0] if len(V) == 2 and isinstance(V[1], Interval): V[1:] = [V[1].start, V[1].end] --- sympy/parsing/sympy_parser.py.orig 2015-09-03 14:34:00.000000000 -0600 +++ sympy/parsing/sympy_parser.py 2015-11-21 15:28:46.742218940 -0700 @@ -568,6 +568,8 @@ def lambda_notation(tokens, local_dict, if tokNum == OP and tokVal == ':': tokVal = ',' flag = True + if not flag and tokNum == OP and tokVal in ['*', '**']: + raise TokenError("Starred arguments in lambda not supported") if flag: result.insert(-1, (tokNum, tokVal)) else: --- sympy/physics/vector/frame.py.orig 2015-09-03 14:34:00.000000000 -0600 +++ sympy/physics/vector/frame.py 2015-11-21 15:30:46.308575762 -0700 @@ -45,7 +45,11 @@ class CoordinateSym(Symbol): """ def __new__(cls, name, frame, index): - obj = super(CoordinateSym, cls).__new__(cls, name) + # We can't use the cached Symbol.__new__ because this class depends on + # frame and index, which are not passed to Symbol.__xnew__. + assumptions = {} + super(CoordinateSym, cls)._sanitize(assumptions, cls) + obj = super(CoordinateSym, cls).__xnew__(cls, name, **assumptions) _check_frame(frame) if index not in range(0, 3): raise ValueError("Invalid index specified") --- sympy/printing/pretty/pretty.py.orig 2015-09-03 14:34:00.000000000 -0600 +++ sympy/printing/pretty/pretty.py 2015-11-21 15:35:28.750796441 -0700 @@ -761,82 +761,77 @@ class PrettyPrinter(Printer): if not self._use_unicode: raise NotImplementedError("ASCII pretty printing of BasisDependent is not implemented") - class Fake(object): - baseline = 0 - # slf to distinguish from self from _print_BasisDependent - def render(slf, *args, **kwargs): - if expr == expr.zero: - return expr.zero._pretty_form - o1 = [] - vectstrs = [] - if isinstance(expr, Vector): - items = expr.separate().items() + if expr == expr.zero: + return prettyForm(expr.zero._pretty_form) + o1 = [] + vectstrs = [] + if isinstance(expr, Vector): + items = expr.separate().items() + else: + items = [(0, expr)] + for system, vect in items: + inneritems = list(vect.components.items()) + inneritems.sort(key = lambda x: x[0].__str__()) + for k, v in inneritems: + #if the coef of the basis vector is 1 + #we skip the 1 + if v == 1: + o1.append(u("") + + k._pretty_form) + #Same for -1 + elif v == -1: + o1.append(u("(-1) ") + + k._pretty_form) + #For a general expr else: - items = [(0, expr)] - for system, vect in items: - inneritems = list(vect.components.items()) - inneritems.sort(key = lambda x: x[0].__str__()) - for k, v in inneritems: - #if the coef of the basis vector is 1 - #we skip the 1 - if v == 1: - o1.append(u("") + - k._pretty_form) - #Same for -1 - elif v == -1: - o1.append(u("(-1) ") + - k._pretty_form) - #For a general expr - else: - #We always wrap the measure numbers in - #parentheses - arg_str = self._print( - v).parens()[0] + #We always wrap the measure numbers in + #parentheses + arg_str = self._print( + v).parens()[0] - o1.append(arg_str + ' ' + k._pretty_form) - vectstrs.append(k._pretty_form) + o1.append(arg_str + ' ' + k._pretty_form) + vectstrs.append(k._pretty_form) - #outstr = u("").join(o1) - if o1[0].startswith(u(" + ")): - o1[0] = o1[0][3:] - elif o1[0].startswith(" "): - o1[0] = o1[0][1:] - #Fixing the newlines - lengths = [] - strs = [''] - for i, partstr in enumerate(o1): - # XXX: What is this hack? - if '\n' in partstr: - tempstr = partstr - tempstr = tempstr.replace(vectstrs[i], '') - tempstr = tempstr.replace(u('\u239e'), - u('\u239e') - + ' ' + vectstrs[i]) - o1[i] = tempstr - o1 = [x.split('\n') for x in o1] - n_newlines = max([len(x) for x in o1]) - for parts in o1: - lengths.append(len(parts[0])) - for j in range(n_newlines): - if j+1 <= len(parts): - if j >= len(strs): - strs.append(' ' * (sum(lengths[:-1]) + - 3*(len(lengths)-1))) - if j == 0: - strs[0] += parts[0] + ' + ' - else: - strs[j] += parts[j] + ' '*(lengths[-1] - - len(parts[j])+ - 3) - else: - if j >= len(strs): - strs.append(' ' * (sum(lengths[:-1]) + - 3*(len(lengths)-1))) - strs[j] += ' '*(lengths[-1]+3) + #outstr = u("").join(o1) + if o1[0].startswith(u(" + ")): + o1[0] = o1[0][3:] + elif o1[0].startswith(" "): + o1[0] = o1[0][1:] + #Fixing the newlines + lengths = [] + strs = [''] + for i, partstr in enumerate(o1): + # XXX: What is this hack? + if '\n' in partstr: + tempstr = partstr + tempstr = tempstr.replace(vectstrs[i], '') + tempstr = tempstr.replace(u('\N{RIGHT PARENTHESIS UPPER HOOK}'), + u('\N{RIGHT PARENTHESIS UPPER HOOK}') + + ' ' + vectstrs[i]) + o1[i] = tempstr + o1 = [x.split('\n') for x in o1] + n_newlines = max([len(x) for x in o1]) + for parts in o1: + lengths.append(len(parts[0])) + for j in range(n_newlines): + if j+1 <= len(parts): + if j >= len(strs): + strs.append(' ' * (sum(lengths[:-1]) + + 3*(len(lengths)-1))) + if j == 0: + strs[0] += parts[0] + ' + ' + else: + strs[j] += parts[j] + ' '*(lengths[-1] - + len(parts[j])+ + 3) + else: + if j >= len(strs): + strs.append(' ' * (sum(lengths[:-1]) + + 3*(len(lengths)-1))) + strs[j] += ' '*(lengths[-1]+3) - return u('\n').join([s[:-3] for s in strs]) - return Fake() + return prettyForm(u('\n').join([s[:-3] for s in strs])) def _print_Piecewise(self, pexpr): --- sympy/printing/pretty/stringpict.py.orig 2015-09-03 14:34:00.000000000 -0600 +++ sympy/printing/pretty/stringpict.py 2015-11-21 15:36:01.748135163 -0700 @@ -29,6 +29,7 @@ class stringPict(object): """Initialize from string. Multiline strings are centered. """ + self.s = s #picture is a string that just can be printed self.picture = stringPict.equalLengths(s.splitlines()) #baseline is the line number of the "base line" --- sympy/printing/pretty/tests/test_pretty.py.orig 2015-09-03 14:34:00.000000000 -0600 +++ sympy/printing/pretty/tests/test_pretty.py 2015-11-21 15:37:58.227740936 -0700 @@ -14,6 +14,8 @@ from sympy.functions import (Abs, Chi, C lowergamma, meijerg, sin, sqrt, subfactorial, tan, uppergamma, elliptic_k, elliptic_f, elliptic_e, elliptic_pi) +from sympy.matrices import Adjoint, Inverse, MatrixSymbol, Transpose + from sympy.printing.pretty import pretty as xpretty from sympy.printing.pretty import pprint @@ -2478,7 +2480,6 @@ u("""\ def test_Adjoint(): - from sympy.matrices import Adjoint, Inverse, MatrixSymbol, Transpose X = MatrixSymbol('X', 2, 2) Y = MatrixSymbol('Y', 2, 2) assert pretty(Adjoint(X)) == " +\nX " @@ -2511,6 +2512,26 @@ def test_Adjoint(): u(" T\n⎛ †⎞ \n⎝X ⎠ ") +def test_MatrixExpressions(): + n = Symbol('n', integer=True) + X = MatrixSymbol('X', n, n) + + assert pretty(X) == upretty(X) == "X" + + Y = X[1:2:3, 4:5:6] + + ascii_str = ucode_str = "X[1:3, 4:6]" + + assert pretty(Y) == ascii_str + assert upretty(Y) == ucode_str + + Z = X[1:10:2] + + ascii_str = ucode_str = "X[1:10:2, :n]" + + assert pretty(Z) == ascii_str + assert upretty(Z) == ucode_str + def test_pretty_piecewise(): expr = Piecewise((x, x < 1), (x**2, True)) ascii_str = \ --- sympy/vector/coordsysrect.py.orig 2015-09-03 14:34:00.000000000 -0600 +++ sympy/vector/coordsysrect.py 2015-11-21 15:44:01.012479961 -0700 @@ -436,6 +436,12 @@ class CoordSysCartesian(Basic): final_matrix = orienters.rotation_matrix(self) else: final_matrix = orienters.rotation_matrix() + # TODO: trigsimp is needed here so that the matrix becomes + # canonical (scalar_map also calls trigsimp; without this, you can + # end up with the same CoordinateSystem that compares differently + # due to a differently formatted matrix). However, this is + # probably not so good for performance. + final_matrix = trigsimp(final_matrix) else: final_matrix = Matrix(eye(3)) for orienter in orienters: --- sympy/vector/deloperator.py.orig 2015-09-03 14:34:00.000000000 -0600 +++ sympy/vector/deloperator.py 2015-11-21 15:44:44.065004287 -0700 @@ -3,6 +3,7 @@ from sympy.core.function import Derivati from sympy.vector.vector import Vector from sympy.vector.functions import express from sympy.vector.coordsysrect import CoordSysCartesian +from sympy.vector.scalar import BaseScalar from sympy.core import S @@ -171,6 +172,6 @@ def _diff_conditional(expr, base_scalar) """ new_expr = express(expr, base_scalar.system, variables = True) - if base_scalar in new_expr.atoms(): + if base_scalar in new_expr.atoms(BaseScalar): return Derivative(new_expr, base_scalar) return S(0) --- sympy/vector/functions.py.orig 2015-09-03 14:34:00.000000000 -0600 +++ sympy/vector/functions.py 2015-11-21 15:46:08.050224073 -0700 @@ -69,9 +69,8 @@ def express(expr, system, system2=None, #If variables attribute is True, substitute #the coordinate variables in the Vector system_list = [] - for x in expr.atoms(): - if (isinstance(x, (BaseScalar, BaseVector)) - and x.system != system): + for x in expr.atoms(BaseScalar, BaseVector): + if x.system != system: system_list.append(x.system) system_list = set(system_list) subs_dict = {} @@ -113,8 +112,8 @@ def express(expr, system, system2=None, system_set = set([]) expr = sympify(expr) #Subsitute all the coordinate variables - for x in expr.atoms(): - if isinstance(x, BaseScalar)and x.system != system: + for x in expr.atoms(BaseScalar): + if x.system != system: system_set.add(x.system) subs_dict = {} for f in system_set: --- sympy/vector/point.py.orig 2015-09-03 14:34:00.000000000 -0600 +++ sympy/vector/point.py 2015-11-21 15:47:51.025910739 -0700 @@ -15,11 +15,11 @@ class Point(Basic): def __new__(cls, name, position=Vector.zero, parent_point=None): #Check the args first if not isinstance(position, Vector): - raise TypeError("position should be a Vector instance") + raise TypeError("position should be an instance of Vector, not %s" % type(position)) if (not isinstance(parent_point, Point) and parent_point is not None): - raise TypeError("parent_point should be a Point instance") - #Create an object + raise TypeError("parent_point should be an instance of Point, not %s" % type(parent_point)) + # Super class construction if parent_point is None: arg_parent = Symbol('default') arg_self = Symbol(name) --- sympy/vector/tests/test_field_functions.py.orig 2015-09-03 14:34:00.000000000 -0600 +++ sympy/vector/tests/test_field_functions.py 2015-11-21 15:55:13.935154218 -0700 @@ -219,4 +219,4 @@ def test_scalar_potential_difference(): (P.x*cos(q) - P.y*sin(q))**2) assert (scalar_potential_difference(grad_field, P, P.origin, genericpointP).simplify() == - potential_diff_P) + potential_diff_P.simplify())