From 0f43d43abe8fb4f59b29fa8efe2393dbb9ad4ee4 Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Mon, 11 Nov 2024 10:21:58 -0300 Subject: [PATCH] * Add align attribute in `stack`, `top` and `bottom` methods. * `top`, `bottom`, `left` and `right` produce `stringPict` objects * adding `superscript` and `subscript` methods --- .mailmap | 1 + sympy/printing/pretty/pretty.py | 524 ++++++++++++++-------------- sympy/printing/pretty/stringpict.py | 238 ++++++++----- 3 files changed, 406 insertions(+), 357 deletions(-) diff --git a/.mailmap b/.mailmap index 2920418cc191..494121e8c068 100644 --- a/.mailmap +++ b/.mailmap @@ -825,6 +825,7 @@ João Moura Juan Barbosa Juan Felipe Osorio Juan Luis Cano Rodríguez +Juan Mauricio Matera Juha Remes Julien Palard Julien Rioux diff --git a/sympy/printing/pretty/pretty.py b/sympy/printing/pretty/pretty.py index b945f009119b..9793195f22bc 100644 --- a/sympy/printing/pretty/pretty.py +++ b/sympy/printing/pretty/pretty.py @@ -73,8 +73,8 @@ def _print_basestring(self, e): return prettyForm(e) def _print_atan2(self, e): - pform = prettyForm(*self._print_seq(e.args).parens()) - pform = prettyForm(*pform.left('atan2')) + pform = self._print_seq(e.args).parens() + pform = pform.left('atan2') return pform def _print_Symbol(self, e, bold_name=False): @@ -96,58 +96,58 @@ def _print_Cross(self, e): vec1 = e._expr1 vec2 = e._expr2 pform = self._print(vec2) - pform = prettyForm(*pform.left('(')) - pform = prettyForm(*pform.right(')')) - pform = prettyForm(*pform.left(self._print(U('MULTIPLICATION SIGN')))) - pform = prettyForm(*pform.left(')')) - pform = prettyForm(*pform.left(self._print(vec1))) - pform = prettyForm(*pform.left('(')) + pform = pform.left('(') + pform = pform.right(')') + pform = pform.left(self._print(U('MULTIPLICATION SIGN'))) + pform = pform.left(')') + pform = pform.left(self._print(vec1)) + pform = pform.left('(') return pform def _print_Curl(self, e): vec = e._expr pform = self._print(vec) - pform = prettyForm(*pform.left('(')) - pform = prettyForm(*pform.right(')')) - pform = prettyForm(*pform.left(self._print(U('MULTIPLICATION SIGN')))) - pform = prettyForm(*pform.left(self._print(U('NABLA')))) + pform = pform.left('(') + pform = pform.right(')') + pform = pform.left(self._print(U('MULTIPLICATION SIGN'))) + pform = pform.left(self._print(U('NABLA'))) return pform def _print_Divergence(self, e): vec = e._expr pform = self._print(vec) - pform = prettyForm(*pform.left('(')) - pform = prettyForm(*pform.right(')')) - pform = prettyForm(*pform.left(self._print(U('DOT OPERATOR')))) - pform = prettyForm(*pform.left(self._print(U('NABLA')))) + pform = pform.left('(') + pform = pform.right(')') + pform = pform.left(self._print(U('DOT OPERATOR'))) + pform = pform.left(self._print(U('NABLA'))) return pform def _print_Dot(self, e): vec1 = e._expr1 vec2 = e._expr2 pform = self._print(vec2) - pform = prettyForm(*pform.left('(')) - pform = prettyForm(*pform.right(')')) - pform = prettyForm(*pform.left(self._print(U('DOT OPERATOR')))) - pform = prettyForm(*pform.left(')')) - pform = prettyForm(*pform.left(self._print(vec1))) - pform = prettyForm(*pform.left('(')) + pform = pform.left('(') + pform = pform.right(')') + pform = pform.left(self._print(U('DOT OPERATOR'))) + pform = pform.left(')') + pform = pform.left(self._print(vec1)) + pform = pform.left('(') return pform def _print_Gradient(self, e): func = e._expr pform = self._print(func) - pform = prettyForm(*pform.left('(')) - pform = prettyForm(*pform.right(')')) - pform = prettyForm(*pform.left(self._print(U('NABLA')))) + pform = pform.left('(') + pform = pform.right(')') + pform = pform.left(self._print(U('NABLA'))) return pform def _print_Laplacian(self, e): func = e._expr pform = self._print(func) - pform = prettyForm(*pform.left('(')) - pform = prettyForm(*pform.right(')')) - pform = prettyForm(*pform.left(self._print(U('INCREMENT')))) + pform = pform.left('(') + pform = pform.right(')') + pform = pform.left(self._print(U('INCREMENT'))) return pform def _print_Atom(self, e): @@ -181,8 +181,8 @@ def _print_subfactorial(self, e): pform = self._print(x) # Add parentheses if needed if not ((x.is_Integer and x.is_nonnegative) or x.is_Symbol): - pform = prettyForm(*pform.parens()) - pform = prettyForm(*pform.left('!')) + pform = pform.parens() + pform = pform.left('!') return pform def _print_factorial(self, e): @@ -190,8 +190,8 @@ def _print_factorial(self, e): pform = self._print(x) # Add parentheses if needed if not ((x.is_Integer and x.is_nonnegative) or x.is_Symbol): - pform = prettyForm(*pform.parens()) - pform = prettyForm(*pform.right('!')) + pform = pform.parens() + pform = pform.right('!') return pform def _print_factorial2(self, e): @@ -199,8 +199,8 @@ def _print_factorial2(self, e): pform = self._print(x) # Add parentheses if needed if not ((x.is_Integer and x.is_nonnegative) or x.is_Symbol): - pform = prettyForm(*pform.parens()) - pform = prettyForm(*pform.right('!!')) + pform = pform.parens() + pform = pform.right('!!') return pform def _print_binomial(self, e): @@ -211,9 +211,9 @@ def _print_binomial(self, e): bar = ' '*max(n_pform.width(), k_pform.width()) - pform = prettyForm(*k_pform.above(bar)) - pform = prettyForm(*pform.above(n_pform)) - pform = prettyForm(*pform.parens('(', ')')) + pform = k_pform.above(bar) + pform = pform.above(n_pform) + pform = pform.parens('(', ')') pform.baseline = (pform.baseline + 1)//2 @@ -238,9 +238,9 @@ def _print_Not(self, e): return self._print_Implies(arg, altchar=pretty_atom('NotArrow')) if arg.is_Boolean and not arg.is_Not: - pform = prettyForm(*pform.parens()) + pform = pform.parens() - return prettyForm(*pform.left(pretty_atom('Not'))) + return pform.left(pretty_atom('Not')) else: return self._print_Function(e) @@ -252,16 +252,16 @@ def __print_Boolean(self, e, char, sort=True): pform = self._print(arg) if arg.is_Boolean and not arg.is_Not: - pform = prettyForm(*pform.parens()) + pform = pform.parens() for arg in args[1:]: pform_arg = self._print(arg) if arg.is_Boolean and not arg.is_Not: - pform_arg = prettyForm(*pform_arg.parens()) + pform_arg = pform_arg.parens() - pform = prettyForm(*pform.right(' %s ' % char)) - pform = prettyForm(*pform.right(pform_arg)) + pform = pform.right(' %s ' % char) + pform = pform.right(pform_arg) return pform @@ -313,13 +313,13 @@ def _print_conjugate(self, e): def _print_Abs(self, e): pform = self._print(e.args[0]) - pform = prettyForm(*pform.parens('|', '|')) + pform = pform.parens('|', '|') return pform def _print_floor(self, e): if self._use_unicode: pform = self._print(e.args[0]) - pform = prettyForm(*pform.parens('lfloor', 'rfloor')) + pform = pform.parens('lfloor', 'rfloor') return pform else: return self._print_Function(e) @@ -327,7 +327,7 @@ def _print_floor(self, e): def _print_ceiling(self, e): if self._use_unicode: pform = self._print(e.args[0]) - pform = prettyForm(*pform.parens('lceil', 'rceil')) + pform = pform.parens('lceil', 'rceil') return pform else: return self._print_Function(e) @@ -342,7 +342,7 @@ def _print_Derivative(self, deriv): for sym, num in reversed(deriv.variable_count): s = self._print(sym) - ds = prettyForm(*s.left(deriv_symbol)) + ds = s.left(deriv_symbol) count_total_deriv += num if (not num.is_Integer) or (num > 1): @@ -351,18 +351,18 @@ def _print_Derivative(self, deriv): if x is None: x = ds else: - x = prettyForm(*x.right(' ')) - x = prettyForm(*x.right(ds)) + x = x.right(' ') + x = x.right(ds) - f = prettyForm( - binding=prettyForm.FUNC, *self._print(deriv.expr).parens()) + f = self._print(deriv.expr).parens() + f.binding=prettyForm.FUNC pform = prettyForm(deriv_symbol) if (count_total_deriv > 1) != False: pform = pform**prettyForm(str(count_total_deriv)) - pform = prettyForm(*pform.below(stringPict.LINE, x)) + pform = pform.below(stringPict.LINE, x) pform.baseline = pform.baseline + 1 pform = prettyForm(*stringPict.next(pform, f)) pform.binding = prettyForm.MUL @@ -374,18 +374,18 @@ def _print_Cycle(self, dc): # for Empty Cycle if dc == Cycle(): cyc = stringPict('') - return prettyForm(*cyc.parens()) + return cyc.parens() dc_list = Permutation(dc.list()).cyclic_form # for Identity Cycle if dc_list == []: cyc = self._print(dc.size - 1) - return prettyForm(*cyc.parens()) + return cyc.parens() cyc = stringPict('') for i in dc_list: l = self._print(str(tuple(i)).replace(',', '')) - cyc = prettyForm(*cyc.right(l)) + cyc = cyc.right(l) return cyc def _print_Permutation(self, expr): @@ -416,13 +416,13 @@ def _print_Permutation(self, expr): for u, l in zip(upper, lower): s1 = self._print(u) s2 = self._print(l) - col = prettyForm(*s1.below(s2)) + col = s1.below(s2) if first: first = False else: - col = prettyForm(*col.left(" ")) - result = prettyForm(*result.right(col)) - return prettyForm(*result.parens()) + col = col.left(" ") + result = result.right(col) + return result.parens() def _print_Integral(self, integral): @@ -433,7 +433,7 @@ def _print_Integral(self, integral): prettyF = self._print(f) # XXX generalize parens if f.is_Add: - prettyF = prettyForm(*prettyF.parens()) + prettyF = prettyF.parens() # dx dy dz ... arg = prettyF @@ -441,9 +441,9 @@ def _print_Integral(self, integral): prettyArg = self._print(x[0]) # XXX qparens (parens if needs-parens) if prettyArg.width() > 1: - prettyArg = prettyForm(*prettyArg.parens()) + prettyArg = prettyArg.parens() - arg = prettyForm(*arg.right(' d', prettyArg)) + arg = arg.right(' d', prettyArg) # \int \int \int ... firstterm = True @@ -479,24 +479,24 @@ def _print_Integral(self, integral): # Add spacing so that endpoint can more easily be # identified with the correct integral sign spc = max(1, 3 - prettyB.width()) - prettyB = prettyForm(*prettyB.left(' ' * spc)) + prettyB = prettyB.left(' ' * spc) spc = max(1, 4 - prettyA.width()) - prettyA = prettyForm(*prettyA.right(' ' * spc)) + prettyA = prettyA.right(' ' * spc) - pform = prettyForm(*pform.above(prettyB)) - pform = prettyForm(*pform.below(prettyA)) + pform = pform.above(prettyB) + pform = pform.below(prettyA) if not ascii_mode: # XXX hack - pform = prettyForm(*pform.right(' ')) + pform = pform.right(' ') if firstterm: s = pform # first term firstterm = False else: - s = prettyForm(*s.left(pform)) + s = s.left(pform) - pform = prettyForm(*arg.left(s)) + pform = arg.left(s) pform.binding = prettyForm.MUL return pform @@ -536,8 +536,8 @@ def _print_Product(self, expr): if first: sign_height = pretty_sign.height() - pretty_sign = prettyForm(*pretty_sign.above(pretty_upper)) - pretty_sign = prettyForm(*pretty_sign.below(pretty_lower)) + pretty_sign = pretty_sign.above(pretty_upper) + pretty_sign = pretty_sign.below(pretty_lower) if first: pretty_func.baseline = 0 @@ -546,9 +546,9 @@ def _print_Product(self, expr): height = pretty_sign.height() padding = stringPict('') padding = prettyForm(*padding.stack(*[' ']*(height - 1))) - pretty_sign = prettyForm(*pretty_sign.right(padding)) + pretty_sign = pretty_sign.right(padding) - pretty_func = prettyForm(*pretty_sign.right(pretty_func)) + pretty_func = pretty_sign.right(pretty_func) pretty_func.baseline = max_upper + sign_height//2 pretty_func.binding = prettyForm.MUL @@ -616,7 +616,7 @@ def adjust(s, wid=None, how='<^>'): prettyF = self._print(f) if f.is_Add: # add parens - prettyF = prettyForm(*prettyF.parens()) + prettyF = prettyF.parens() H = prettyF.height() + 2 @@ -639,8 +639,8 @@ def adjust(s, wid=None, how='<^>'): if first: sign_height = prettySign.height() - prettySign = prettyForm(*prettySign.above(prettyUpper)) - prettySign = prettyForm(*prettySign.below(prettyLower)) + prettySign = prettySign.above(prettyUpper) + prettySign = prettySign.below(prettyLower) if first: # change F baseline so it centers on the sign @@ -651,9 +651,9 @@ def adjust(s, wid=None, how='<^>'): # put padding to the right pad = stringPict('') pad = prettyForm(*pad.stack(*[' ']*h)) - prettySign = prettyForm(*prettySign.right(pad)) + prettySign = prettySign.right(pad) # put the present prettyF to the right - prettyF = prettyForm(*prettySign.right(prettyF)) + prettyF = prettySign.right(prettyF) # adjust baseline of ascii mode sigma with an odd height so that it is # exactly through the center @@ -668,15 +668,15 @@ def _print_Limit(self, l): E = self._print(e) if precedence(e) <= PRECEDENCE["Mul"]: - E = prettyForm(*E.parens('(', ')')) + E = E.parens('(', ')') Lim = prettyForm('lim') LimArg = self._print(z) if self._use_unicode: - LimArg = prettyForm(*LimArg.right(f"{xobj('-', 1)}{pretty_atom('Arrow')}")) + LimArg = LimArg.right(f"{xobj('-', 1)}{pretty_atom('Arrow')}") else: - LimArg = prettyForm(*LimArg.right('->')) - LimArg = prettyForm(*LimArg.right(self._print(z0))) + LimArg = LimArg.right('->') + LimArg = LimArg.right(self._print(z0)) if str(dir) == '+-' or z0 in (S.Infinity, S.NegativeInfinity): dir = "" @@ -684,10 +684,11 @@ def _print_Limit(self, l): if self._use_unicode: dir = pretty_atom('SuperscriptPlus') if str(dir) == "+" else pretty_atom('SuperscriptMinus') - LimArg = prettyForm(*LimArg.right(self._print(dir))) + LimArg = LimArg.right(self._print(dir)) - Lim = prettyForm(*Lim.below(LimArg)) - Lim = prettyForm(*Lim.right(E), binding=prettyForm.MUL) + Lim = Lim.below(LimArg) + Lim = Lim.right(E) + Lim.binding=prettyForm.MUL return Lim @@ -729,8 +730,8 @@ def _print_matrix_contents(self, e): # XXX this is not good in all cases -- maybe introduce vbaseline? left, right = center_pad(s.width(), maxw[j]) - s = prettyForm(*s.right(right)) - s = prettyForm(*s.left(left)) + s = s.right(right) + s = s.left(left) # we don't need vcenter cells -- this is automatically done in # a pretty way because when their baselines are taking into @@ -740,8 +741,8 @@ def _print_matrix_contents(self, e): D_row = s # first box in a row continue - D_row = prettyForm(*D_row.right(' '*hsep)) # h-spacer - D_row = prettyForm(*D_row.right(s)) + D_row = D_row.right(' '*hsep) # h-spacer + D_row = D_row.right(s) if D is None: D = D_row # first row in a picture @@ -749,9 +750,9 @@ def _print_matrix_contents(self, e): # v-spacer for _ in range(vsep): - D = prettyForm(*D.below(' ')) + D = D.below(' ') - D = prettyForm(*D.below(D_row)) + D = D.below(D_row) if D is None: D = prettyForm('') # Empty Matrix @@ -761,7 +762,7 @@ def _print_matrix_contents(self, e): def _print_MatrixBase(self, e, lparens='[', rparens=']'): D = self._print_matrix_contents(e) D.baseline = D.height()//2 - D = prettyForm(*D.parens(lparens, rparens)) + D = D.parens(lparens, rparens) return D def _print_Determinant(self, e): @@ -772,7 +773,7 @@ def _print_Determinant(self, e): return self._print_MatrixBase(mat.blocks, lparens='|', rparens='|') D = self._print(mat) D.baseline = D.height()//2 - return prettyForm(*D.parens('|', '|')) + return D.parens('|', '|') else: return self._print_MatrixBase(mat, lparens='|', rparens='|') @@ -796,9 +797,9 @@ def _print_WedgeProduct(self, expr): def _print_Trace(self, e): D = self._print(e.arg) - D = prettyForm(*D.parens('(',')')) + D = D.parens('(',')') D.baseline = D.height()//2 - D = prettyForm(*D.left('\n'*(0) + 'tr')) + D = D.left('\n'*(0) + 'tr') return D @@ -810,7 +811,7 @@ def _print_MatrixElement(self, expr): Symbol(expr.parent.name + '_%d%d' % (expr.i, expr.j))) else: prettyFunc = self._print(expr.parent) - prettyFunc = prettyForm(*prettyFunc.parens()) + prettyFunc = prettyFunc.parens() prettyIndices = self._print_seq((expr.i, expr.j), delimiter=', ' ).parens(left='[', right=']')[0] pform = prettyForm(binding=prettyForm.FUNC, @@ -828,7 +829,7 @@ def _print_MatrixSlice(self, m): from sympy.matrices import MatrixSymbol prettyFunc = self._print(m.parent) if not isinstance(m.parent, MatrixSymbol): - prettyFunc = prettyForm(*prettyFunc.parens()) + prettyFunc = prettyFunc.parens() def ppslice(x, dim): x = list(x) if x[2] == 1: @@ -837,7 +838,7 @@ def ppslice(x, dim): x[0] = '' if x[1] == dim: x[1] = '' - return prettyForm(*self._print_seq(x, delimiter=':')) + return self._print_seq(x, delimiter=':') prettyArgs = self._print_seq((ppslice(m.rowslice, m.parent.rows), ppslice(m.colslice, m.parent.cols)), delimiter=', ').parens(left='[', right=']')[0] @@ -856,7 +857,7 @@ def _print_Transpose(self, expr): from sympy.matrices import MatrixSymbol, BlockMatrix if (not isinstance(mat, MatrixSymbol) and not isinstance(mat, BlockMatrix) and mat.is_MatrixExpr): - pform = prettyForm(*pform.parens()) + pform = pform.parens() pform = pform**(prettyForm('T')) return pform @@ -870,7 +871,7 @@ def _print_Adjoint(self, expr): from sympy.matrices import MatrixSymbol, BlockMatrix if (not isinstance(mat, MatrixSymbol) and not isinstance(mat, BlockMatrix) and mat.is_MatrixExpr): - pform = prettyForm(*pform.parens()) + pform = pform.parens() pform = pform**dag return pform @@ -888,7 +889,7 @@ def _print_MatAdd(self, expr): else: coeff = item.as_coeff_mmul()[0] if S(coeff).could_extract_minus_sign(): - s = prettyForm(*stringPict.next(s, ' ')) + s = stringPict.next(s, ' ') pform = self._print(item) else: s = prettyForm(*stringPict.next(s, ' + ')) @@ -904,7 +905,7 @@ def _print_MatMul(self, expr): for i, a in enumerate(args): if (isinstance(a, (Add, MatAdd, HadamardProduct, KroneckerProduct)) and len(expr.args) > 1): - args[i] = prettyForm(*self._print(a).parens()) + args[i] = self._print(a).parens() else: args[i] = self._print(a) @@ -939,7 +940,7 @@ def _print_MatPow(self, expr): pform = self._print(expr.base) from sympy.matrices import MatrixSymbol if not isinstance(expr.base, MatrixSymbol) and expr.base.is_MatrixExpr: - pform = prettyForm(*pform.parens()) + pform = pform.parens() pform = pform**(self._print(expr.exp)) return pform @@ -963,7 +964,7 @@ def _print_HadamardPower(self, expr): pretty_base = self._print(expr.base) pretty_exp = self._print(expr.exp) if precedence(expr.exp) < PRECEDENCE["Mul"]: - pretty_exp = prettyForm(*pretty_exp.parens()) + pretty_exp = pretty_exp.parens() pretty_circ_exp = prettyForm( binding=prettyForm.LINE, *stringPict.next(circ, pretty_exp) @@ -982,7 +983,7 @@ def _print_KroneckerProduct(self, expr): def _print_FunctionMatrix(self, X): D = self._print(X.lamda.expr) - D = prettyForm(*D.parens('[', ']')) + D = D.parens('[', ']') return D def _print_TransferFunction(self, expr): @@ -996,7 +997,7 @@ def _print_TransferFunction(self, expr): def _print_Series(self, expr): args = list(expr.args) for i, a in enumerate(expr.args): - args[i] = prettyForm(*self._print(a).parens()) + args[i] = self._print(a).parens() return prettyForm.__mul__(*args) def _print_MIMOSeries(self, expr): @@ -1007,7 +1008,7 @@ def _print_MIMOSeries(self, expr): if (isinstance(a, MIMOParallel) and len(expr.args) > 1): expression = self._print(a) expression.baseline = expression.height()//2 - pretty_args.append(prettyForm(*expression.parens())) + pretty_args.append(expression.parens()) else: expression = self._print(a) expression.baseline = expression.height()//2 @@ -1086,11 +1087,11 @@ def _print_MIMOFeedback(self, expr): inv_mat = self._print(MIMOSeries(expr.sys2, expr.sys1)) plant = self._print(expr.sys1) _feedback = prettyForm(*stringPict.next(inv_mat)) - _feedback = prettyForm(*stringPict.right("I + ", _feedback)) if expr.sign == -1 \ - else prettyForm(*stringPict.right("I - ", _feedback)) - _feedback = prettyForm(*stringPict.parens(_feedback)) + _feedback = stringPict.right(prettyForm("I + "), _feedback) if expr.sign == -1 \ + else stringPict.right(prettyForm("I - "), _feedback) + _feedback = stringPict.parens(_feedback) _feedback.baseline = 0 - _feedback = prettyForm(*stringPict.right(_feedback, '-1 ')) + _feedback = stringPict.right(_feedback, stringPict('-1 ')) _feedback.baseline = _feedback.height()//2 _feedback = prettyForm.__mul__(_feedback, prettyForm(" ")) if isinstance(expr.sys1, TransferFunctionMatrix): @@ -1102,7 +1103,7 @@ def _print_TransferFunctionMatrix(self, expr): mat = self._print(expr._expr_mat) mat.baseline = mat.height() - 1 subscript = greek_unicode['tau'] if self._use_unicode else r'{t}' - mat = prettyForm(*mat.right(subscript)) + mat = mat.right(subscript) return mat def _print_StateSpace(self, expr): @@ -1271,17 +1272,17 @@ def _printer_tensor_indices(self, name, indices, index_map={}): else: prev_map = False if index.is_up: - top = stringPict(*top.right(indpic)) - center = stringPict(*center.right(" "*indpic.width())) - bot = stringPict(*bot.right(" "*indpic.width())) + top = top.right(indpic) + center = center.right(" "*indpic.width()) + bot = bot.right(" "*indpic.width()) else: - bot = stringPict(*bot.right(indpic)) - center = stringPict(*center.right(" "*indpic.width())) - top = stringPict(*top.right(" "*indpic.width())) + bot = bot.right(indpic) + center = center.right(" "*indpic.width()) + top = top.right(" "*indpic.width()) last_valence = index.is_up - pict = prettyForm(*center.above(top)) - pict = prettyForm(*pict.below(bot)) + pict = center.above(top) + pict = pict.below(bot) return pict def _print_Tensor(self, expr): @@ -1298,19 +1299,19 @@ def _print_TensorElement(self, expr): def _print_TensMul(self, expr): sign, args = expr._get_args_for_traditional_printer() args = [ - prettyForm(*self._print(i).parens()) if + self._print(i).parens() if precedence_traditional(i) < PRECEDENCE["Mul"] else self._print(i) for i in args ] pform = prettyForm.__mul__(*args) if sign: - return prettyForm(*pform.left(sign)) + return pform.left(sign) else: return pform def _print_TensAdd(self, expr): args = [ - prettyForm(*self._print(i).parens()) if + self._print(i).parens() if precedence_traditional(i) < PRECEDENCE["Mul"] else self._print(i) for i in expr.args ] @@ -1331,23 +1332,23 @@ def _print_PartialDerivative(self, deriv): for variable in reversed(deriv.variables): s = self._print(variable) - ds = prettyForm(*s.left(deriv_symbol)) + ds = s.left(deriv_symbol) if x is None: x = ds else: - x = prettyForm(*x.right(' ')) - x = prettyForm(*x.right(ds)) + x = x.right(' ') + x = x.right(ds) - f = prettyForm( - binding=prettyForm.FUNC, *self._print(deriv.expr).parens()) + f= self._print(deriv.expr).parens() + f.binding = prettyForm.FUNC pform = prettyForm(deriv_symbol) if len(deriv.variables) > 1: pform = pform**self._print(len(deriv.variables)) - pform = prettyForm(*pform.below(stringPict.LINE, x)) + pform = pform.below(stringPict.LINE, x) pform.baseline = pform.baseline + 1 pform = prettyForm(*stringPict.next(pform, f)) pform.binding = prettyForm.MUL @@ -1362,8 +1363,7 @@ def _print_Piecewise(self, pexpr): if ec.cond == True: P[n, 1] = prettyForm('otherwise') else: - P[n, 1] = prettyForm( - *prettyForm('for ').right(self._print(ec.cond))) + P[n, 1] = prettyForm('for ').right(self._print(ec.cond)) hsep = 2 vsep = 1 len_args = len(pexpr.args) @@ -1386,26 +1386,26 @@ def _print_Piecewise(self, pexpr): wleft = wdelta // 2 wright = wdelta - wleft - p = prettyForm(*p.right(' '*wright)) - p = prettyForm(*p.left(' '*wleft)) + p = p.right(' '*wright) + p = p.left(' '*wleft) if D_row is None: D_row = p continue - D_row = prettyForm(*D_row.right(' '*hsep)) # h-spacer - D_row = prettyForm(*D_row.right(p)) + D_row = D_row.right(' '*hsep) # h-spacer + D_row = D_row.right(p) if D is None: D = D_row # first row in a picture continue # v-spacer for _ in range(vsep): - D = prettyForm(*D.below(' ')) + D = D.below(' ') - D = prettyForm(*D.below(D_row)) + D = D.below(D_row) - D = prettyForm(*D.parens('{', '')) + D = D.parens('{', '') D.baseline = D.height()//2 D.binding = prettyForm.OPEN return D @@ -1422,8 +1422,8 @@ def _hprint_vec(self, v): if D is None: D = p else: - D = prettyForm(*D.right(', ')) - D = prettyForm(*D.right(p)) + D = D.right(', ') + D = D.right(p) if D is None: D = stringPict(' ') @@ -1453,21 +1453,21 @@ def _print_hyper(self, e): if D is None: D = D_row # first row in a picture else: - D = prettyForm(*D.below(' ')) - D = prettyForm(*D.below(D_row)) + D = D.below(' ') + D = D.below(D_row) # make sure that the argument `z' is centred vertically D.baseline = D.height()//2 # insert horizontal separator - P = prettyForm(*P.left(' ')) - D = prettyForm(*D.right(' ')) + P = P.left(' ') + D = D.right(' ') # insert separating `|` D = self._hprint_vseparator(D, P) # add parens - D = prettyForm(*D.parens('(', ')')) + D = D.parens('(', ')') # create the F symbol above = D.height()//2 - 1 @@ -1478,11 +1478,11 @@ def _print_hyper(self, e): baseline=above + sz) add = (sz + 1)//2 - F = prettyForm(*F.left(self._print(len(e.ap)))) - F = prettyForm(*F.right(self._print(len(e.bq)))) + F = F.left(self._print(len(e.ap))) + F = F.right(self._print(len(e.bq))) F.baseline = above + add - D = prettyForm(*F.right(' ', D)) + D = F.right(' ', D) return D @@ -1508,27 +1508,27 @@ def _print_meijerg(self, e): s = vp[(j, i)] left = (maxw - s.width()) // 2 right = maxw - left - s.width() - s = prettyForm(*s.left(' ' * left)) - s = prettyForm(*s.right(' ' * right)) + s = s.left(' ' * left) + s = s.right(' ' * right) vp[(j, i)] = s - D1 = prettyForm(*vp[(0, 0)].right(' ', vp[(0, 1)])) - D1 = prettyForm(*D1.below(' ')) - D2 = prettyForm(*vp[(1, 0)].right(' ', vp[(1, 1)])) - D = prettyForm(*D1.below(D2)) + D1 = vp[(0, 0)].right(' ', vp[(0, 1)]) + D1 = D1.below(' ') + D2 = vp[(1, 0)].right(' ', vp[(1, 1)]) + D = D1.below(D2) # make sure that the argument `z' is centred vertically D.baseline = D.height()//2 # insert horizontal separator - P = prettyForm(*P.left(' ')) - D = prettyForm(*D.right(' ')) + P = P.left(' ') + D = D.right(' ') # insert separating `|` D = self._hprint_vseparator(D, P) # add parens - D = prettyForm(*D.parens('(', ')')) + D = D.parens('(', ')') # create the G symbol above = D.height()//2 - 1 @@ -1548,25 +1548,25 @@ def adjust(p1, p2): if diff == 0: return p1, p2 elif diff > 0: - return p1, prettyForm(*p2.left(' '*diff)) + return p1, p2.left(' '*diff) else: - return prettyForm(*p1.left(' '*-diff)), p2 + return p1.left(' '*-diff), p2 pp, pm = adjust(pp, pm) pq, pn = adjust(pq, pn) - pu = prettyForm(*pm.right(', ', pn)) - pl = prettyForm(*pp.right(', ', pq)) + pu = pm.right(', ', pn) + pl = pp.right(', ', pq) ht = F.baseline - above - 2 if ht > 0: - pu = prettyForm(*pu.below('\n'*ht)) - p = prettyForm(*pu.below(pl)) + pu = pu.below('\n'*ht) + p = pu.below(pl) F.baseline = above - F = prettyForm(*F.right(p)) + F = F.right(p) F.baseline = above + add - D = prettyForm(*F.right(' ', D)) + D = F.right(' ', D) return D @@ -1609,7 +1609,7 @@ def _helper_print_function(self, func, args, sort=False, func_name=None, if func_name: prettyFunc = self._print(Symbol(func_name)) else: - prettyFunc = prettyForm(*self._print(func).parens()) + prettyFunc = self._print(func).parens() if elementwise: if self._use_unicode: @@ -1622,8 +1622,8 @@ def _helper_print_function(self, func, args, sort=False, func_name=None, *stringPict.next(prettyFunc, circ) ) - prettyArgs = prettyForm(*self._print_seq(args, delimiter=delimiter).parens( - left=left, right=right)) + prettyArgs = self._print_seq(args, delimiter=delimiter).parens( + left=left, right=right) pform = prettyForm( binding=prettyForm.FUNC, *stringPict.next(prettyFunc, prettyArgs)) @@ -1687,8 +1687,8 @@ def _print_dirichlet_eta(self, e): def _print_Heaviside(self, e): func_name = greek_unicode['theta'] if self._use_unicode else 'Heaviside' if e.args[1] is S.Half: - pform = prettyForm(*self._print(e.args[0]).parens()) - pform = prettyForm(*pform.left(func_name)) + pform = self._print(e.args[0]).parens() + pform = pform.left(func_name) return pform else: return self._print_Function(e, func_name=func_name) @@ -1743,21 +1743,21 @@ def _print_Order(self, expr): pform = self._print(expr.expr) if (expr.point and any(p != S.Zero for p in expr.point)) or \ len(expr.variables) > 1: - pform = prettyForm(*pform.right("; ")) + pform = pform.right("; ") if len(expr.variables) > 1: - pform = prettyForm(*pform.right(self._print(expr.variables))) + pform = pform.right(self._print(expr.variables)) elif len(expr.variables): - pform = prettyForm(*pform.right(self._print(expr.variables[0]))) + pform = pform.right(self._print(expr.variables[0])) if self._use_unicode: - pform = prettyForm(*pform.right(f" {pretty_atom('Arrow')} ")) + pform = pform.right(f" {pretty_atom('Arrow')} ") else: - pform = prettyForm(*pform.right(" -> ")) + pform = pform.right(" -> ") if len(expr.point) > 1: - pform = prettyForm(*pform.right(self._print(expr.point))) + pform = pform.right(self._print(expr.point)) else: - pform = prettyForm(*pform.right(self._print(expr.point[0]))) - pform = prettyForm(*pform.parens()) - pform = prettyForm(*pform.left("O")) + pform = pform.right(self._print(expr.point[0])) + pform = pform.parens() + pform = pform.left("O") return pform def _print_SingularityFunction(self, e): @@ -1765,8 +1765,8 @@ def _print_SingularityFunction(self, e): shift = self._print(e.args[0]-e.args[1]) n = self._print(e.args[2]) base = prettyForm("<") - base = prettyForm(*base.right(shift)) - base = prettyForm(*base.right(">")) + base = base.right(shift) + base = base.right(">") pform = base**n return pform else: @@ -1804,16 +1804,16 @@ def _print_DiracDelta(self, e): if len(e.args) == 2: a = prettyForm(greek_unicode['delta']) b = self._print(e.args[1]) - b = prettyForm(*b.parens()) + b = b.parens() c = self._print(e.args[0]) - c = prettyForm(*c.parens()) + c = c.parens() pform = a**b - pform = prettyForm(*pform.right(' ')) - pform = prettyForm(*pform.right(c)) + pform = pform.right(' ') + pform = pform.right(c) return pform pform = self._print(e.args[0]) - pform = prettyForm(*pform.parens()) - pform = prettyForm(*pform.left(greek_unicode['delta'])) + pform = pform.parens() + pform = pform.left(greek_unicode['delta']) return pform else: return self._print_Function(e) @@ -1828,7 +1828,7 @@ def _print_Chi(self, e): # This needs a special case since otherwise it comes out as greek # letter chi... prettyFunc = prettyForm("Chi") - prettyArgs = prettyForm(*self._print_seq(e.args).parens()) + prettyArgs = self._print_seq(e.args).parens() pform = prettyForm( binding=prettyForm.FUNC, *stringPict.next(prettyFunc, prettyArgs)) @@ -1846,22 +1846,22 @@ def _print_elliptic_e(self, e): else: pforma1 = self._print(e.args[1]) pform = self._hprint_vseparator(pforma0, pforma1) - pform = prettyForm(*pform.parens()) - pform = prettyForm(*pform.left('E')) + pform = pform.parens() + pform = pform.left('E') return pform def _print_elliptic_k(self, e): pform = self._print(e.args[0]) - pform = prettyForm(*pform.parens()) - pform = prettyForm(*pform.left('K')) + pform = pform.parens() + pform = pform.left('K') return pform def _print_elliptic_f(self, e): pforma0 = self._print(e.args[0]) pforma1 = self._print(e.args[1]) pform = self._hprint_vseparator(pforma0, pforma1) - pform = prettyForm(*pform.parens()) - pform = prettyForm(*pform.left('F')) + pform = pform.parens() + pform = pform.left('F') return pform def _print_elliptic_pi(self, e): @@ -1873,10 +1873,10 @@ def _print_elliptic_pi(self, e): else: pforma2 = self._print(e.args[2]) pforma = self._hprint_vseparator(pforma1, pforma2, ifascii_nougly=False) - pforma = prettyForm(*pforma.left('; ')) - pform = prettyForm(*pforma.left(pforma0)) - pform = prettyForm(*pform.parens()) - pform = prettyForm(*pform.left(name)) + pforma = pforma.left('; ') + pform = pforma.left(pforma0) + pform = pform.parens() + pform = pform.left(name) return pform def _print_GoldenRatio(self, expr): @@ -1895,9 +1895,9 @@ def _print_Catalan(self, expr): def _print_Mod(self, expr): pform = self._print(expr.args[0]) if pform.binding > prettyForm.MUL: - pform = prettyForm(*pform.parens()) - pform = prettyForm(*pform.right(' mod ')) - pform = prettyForm(*pform.right(self._print(expr.args[1]))) + pform = pform.parens() + pform = pform.right(' mod ') + pform = pform.right(self._print(expr.args[1])) pform.binding = prettyForm.OPEN return pform @@ -1918,7 +1918,7 @@ def pretty_negative(pform, index): if (pform.binding > prettyForm.NEG or pform.binding == prettyForm.ADD): - p = stringPict(*pform.parens()) + p = pform.parens() else: p = pform p = stringPict.next(pform_neg, p) @@ -1942,7 +1942,7 @@ def pretty_negative(pform, index): pform = self._print(-term) pforms.append(pretty_negative(pform, i)) elif term.is_Relational: - pforms.append(prettyForm(*self._print(term).parens())) + pforms.append(self._print(term).parens()) else: pforms.append(self._print(term)) @@ -2042,7 +2042,7 @@ def _print_nth_root(self, base, root): and root == 2 and bpretty.height() == 1 and (bpretty.width() == 1 or (base.is_Integer and base.is_nonnegative))): - return prettyForm(*bpretty.left(nth_root[2])) + return bpretty.left(nth_root[2]) # Construct root sign, start with the \/ shape _zZ = xobj('/', 1) @@ -2068,14 +2068,14 @@ def _print_nth_root(self, base, root): # Put baseline just below lowest line: next to exp diagonal.baseline = linelength - 1 # Make the root symbol - rootsign = prettyForm(*rootsign.right(diagonal)) + rootsign = rootsign.right(diagonal) # Det the baseline to match contents to fix the height # but if the height of bpretty is one, the rootsign must be one higher rootsign.baseline = max(1, bpretty.baseline) #build result s = prettyForm(hobj('_', 2 + bpretty.width())) - s = prettyForm(*bpretty.above(s)) - s = prettyForm(*s.left(rootsign)) + s = bpretty.above(s) + s = s.left(rootsign) return s def _print_Pow(self, power): @@ -2092,7 +2092,7 @@ def _print_Pow(self, power): return prettyForm("1")/self._print(Pow(b, -e, evaluate=False)) if b.is_Relational: - return prettyForm(*self._print(b).parens()).__pow__(self._print(e)) + return self._print(b).parens().__pow__(self._print(e)) return self._print(b)**self._print(e) @@ -2273,7 +2273,7 @@ def _print_ConditionSet(self, ts): cond = self._print(ts.condition) if self._use_unicode: cond = self._print(cond) - cond = prettyForm(*cond.parens()) + cond = cond.parens() if ts.base_set is S.UniversalSet: return self._hprint_vseparator(variables, cond, left="{", @@ -2322,9 +2322,9 @@ def _print_FormalPowerSeries(self, s): return self._print_Add(s.infinite) def _print_SetExpr(self, se): - pretty_set = prettyForm(*self._print(se.set).parens()) + pretty_set = self._print(se.set).parens() pretty_name = self._print(Symbol("SetExpr")) - return prettyForm(*pretty_name.right(pretty_set)) + return pretty_name.right(pretty_set) def _print_SeqFormula(self, s): if self._use_unicode: @@ -2358,7 +2358,7 @@ def _print_seq(self, seq, left=None, right=None, delimiter=', ', for item in seq: pform = self._print(item) if parenthesize(item): - pform = prettyForm(*pform.parens()) + pform = pform.parens() if pforms: pforms.append(delimiter) pforms.append(pform) @@ -2368,7 +2368,7 @@ def _print_seq(self, seq, left=None, right=None, delimiter=', ', else: s = prettyForm(*stringPict.next(*pforms)) - s = prettyForm(*s.parens(left, right, ifascii_nougly=ifascii_nougly)) + s = s.parens(left, right, ifascii_nougly=ifascii_nougly) return s def join(self, delimiter, args): @@ -2378,8 +2378,8 @@ def join(self, delimiter, args): if pform is None: pform = arg else: - pform = prettyForm(*pform.right(delimiter)) - pform = prettyForm(*pform.right(arg)) + pform = pform.right(delimiter) + pform = pform.right(arg) if pform is None: return prettyForm("") @@ -2392,7 +2392,7 @@ def _print_list(self, l): def _print_tuple(self, t): if len(t) == 1: ptuple = prettyForm(*stringPict.next(self._print(t[0]), ',')) - return prettyForm(*ptuple.parens('(', ')', ifascii_nougly=True)) + return ptuple.parens('(', ')', ifascii_nougly=True) else: return self._print_seq(t, '(', ')') @@ -2420,7 +2420,7 @@ def _print_set(self, s): return prettyForm('set()') items = sorted(s, key=default_sort_key) pretty = self._print_seq(items) - pretty = prettyForm(*pretty.parens('{', '}', ifascii_nougly=True)) + pretty = pretty.parens('{', '}', ifascii_nougly=True) return pretty def _print_frozenset(self, s): @@ -2428,8 +2428,8 @@ def _print_frozenset(self, s): return prettyForm('frozenset()') items = sorted(s, key=default_sort_key) pretty = self._print_seq(items) - pretty = prettyForm(*pretty.parens('{', '}', ifascii_nougly=True)) - pretty = prettyForm(*pretty.parens('(', ')', ifascii_nougly=True)) + pretty = pretty.parens('{', '}', ifascii_nougly=True) + pretty = pretty.parens('(', ')', ifascii_nougly=True) pretty = prettyForm(*stringPict.next(type(s).__name__, pretty)) return pretty @@ -2462,8 +2462,8 @@ def _print_AlgebraicNumber(self, expr): def _print_ComplexRootOf(self, expr): args = [self._print_Add(expr.expr, order='lex'), expr.index] - pform = prettyForm(*self._print_seq(args).parens()) - pform = prettyForm(*pform.left('CRootOf')) + pform = self._print_seq(args).parens() + pform = pform.left('CRootOf') return pform def _print_RootSum(self, expr): @@ -2472,8 +2472,8 @@ def _print_RootSum(self, expr): if expr.fun is not S.IdentityFunction: args.append(self._print(expr.fun)) - pform = prettyForm(*self._print_seq(args).parens()) - pform = prettyForm(*pform.left('RootSum')) + pform = self._print_seq(args).parens() + pform = pform.left('RootSum') return pform @@ -2523,11 +2523,11 @@ def _print_PolynomialRing(self, expr): args = list(expr.symbols) if not expr.order.is_default: - order = prettyForm(*prettyForm("order=").right(self._print(expr.order))) + order = prettyForm("order=").right(self._print(expr.order)) args.append(order) pform = self._print_seq(args, '[', ']') - pform = prettyForm(*pform.left(self._print(expr.domain))) + pform = pform.left(self._print(expr.domain)) return pform @@ -2535,11 +2535,11 @@ def _print_FractionField(self, expr): args = list(expr.symbols) if not expr.order.is_default: - order = prettyForm(*prettyForm("order=").right(self._print(expr.order))) + order = prettyForm("order=").right(self._print(expr.order)) args.append(order) pform = self._print_seq(args, '(', ')') - pform = prettyForm(*pform.left(self._print(expr.domain))) + pform = pform.left(self._print(expr.domain)) return pform @@ -2548,42 +2548,40 @@ def _print_PolynomialRingBase(self, expr): if str(expr.order) != str(expr.default_order): g = g + ("order=" + str(expr.order),) pform = self._print_seq(g, '[', ']') - pform = prettyForm(*pform.left(self._print(expr.domain))) + pform = pform.left(self._print(expr.domain)) return pform def _print_GroebnerBasis(self, basis): exprs = [ self._print_Add(arg, order=basis.order) for arg in basis.exprs ] - exprs = prettyForm(*self.join(", ", exprs).parens(left="[", right="]")) + exprs = self.join(", ", exprs).parens(left="[", right="]") gens = [ self._print(gen) for gen in basis.gens ] - domain = prettyForm( - *prettyForm("domain=").right(self._print(basis.domain))) - order = prettyForm( - *prettyForm("order=").right(self._print(basis.order))) + domain = prettyForm("domain=").right(self._print(basis.domain)) + order = prettyForm("order=").right(self._print(basis.order)) pform = self.join(", ", [exprs] + gens + [domain, order]) - pform = prettyForm(*pform.parens()) - pform = prettyForm(*pform.left(basis.__class__.__name__)) + pform = pform.parens() + pform = pform.left(basis.__class__.__name__) return pform def _print_Subs(self, e): pform = self._print(e.expr) - pform = prettyForm(*pform.parens()) + pform = pform.parens() h = pform.height() if pform.height() > 1 else 2 rvert = stringPict(vobj('|', h), baseline=pform.baseline) - pform = prettyForm(*pform.right(rvert)) + pform = pform.right(rvert) b = pform.baseline pform.baseline = pform.height() - 1 - pform = prettyForm(*pform.right(self._print_seq([ + pform = pform.right(self._print_seq([ self._print_seq((self._print(v[0]), xsym('=='), self._print(v[1])), - delimiter='') for v in zip(e.variables, e.point) ]))) + delimiter='') for v in zip(e.variables, e.point) ])) pform.baseline = b return pform @@ -2594,14 +2592,14 @@ def _print_number_function(self, e, name): pform = prettyForm(name) arg = self._print(e.args[0]) pform_arg = prettyForm(" "*arg.width()) - pform_arg = prettyForm(*pform_arg.below(arg)) - pform = prettyForm(*pform.right(pform_arg)) + pform_arg = pform_arg.below(arg) + pform = pform.right(pform_arg) if len(e.args) == 1: return pform m, x = e.args # TODO: copy-pasted from _print_Function: can we do better? prettyFunc = pform - prettyArgs = prettyForm(*self._print_seq([x]).parens()) + prettyArgs = self._print_seq([x]).parens() pform = prettyForm( binding=prettyForm.FUNC, *stringPict.next(prettyFunc, prettyArgs)) pform.prettyFunc = prettyFunc @@ -2636,31 +2634,31 @@ def _print_stieltjes(self, e): def _print_KroneckerDelta(self, e): pform = self._print(e.args[0]) - pform = prettyForm(*pform.right(prettyForm(','))) - pform = prettyForm(*pform.right(self._print(e.args[1]))) + pform = pform.right(prettyForm(',')) + pform = pform.right(self._print(e.args[1])) if self._use_unicode: a = stringPict(pretty_symbol('delta')) else: a = stringPict('d') b = pform - top = stringPict(*b.left(' '*a.width())) - bot = stringPict(*a.right(' '*b.width())) + top = b.left(' '*a.width()) + bot = a.right(' '*b.width()) return prettyForm(binding=prettyForm.POW, *bot.below(top)) def _print_RandomDomain(self, d): if hasattr(d, 'as_boolean'): pform = self._print('Domain: ') - pform = prettyForm(*pform.right(self._print(d.as_boolean()))) + pform = pform.right(self._print(d.as_boolean())) return pform elif hasattr(d, 'set'): pform = self._print('Domain: ') - pform = prettyForm(*pform.right(self._print(d.symbols))) - pform = prettyForm(*pform.right(self._print(' in '))) - pform = prettyForm(*pform.right(self._print(d.set))) + pform = pform.right(self._print(d.symbols)) + pform = pform.right(self._print(' in ')) + pform = pform.right(self._print(d.set)) return pform elif hasattr(d, 'symbols'): pform = self._print('Domain on ') - pform = prettyForm(*pform.right(self._print(d.symbols))) + pform = pform.right(self._print(d.symbols)) return pform else: return self._print(None) @@ -2769,8 +2767,8 @@ def _print_QuotientModule(self, M): def _print_MatrixHomomorphism(self, h): matrix = self._print(h._sympy_matrix()) matrix.baseline = matrix.height() // 2 - pform = prettyForm(*matrix.right(' : ', self._print(h.domain), - ' %s> ' % hobj('-', 2), self._print(h.codomain))) + pform = matrix.right(' : ', self._print(h.domain), + ' %s> ' % hobj('-', 2), self._print(h.codomain)) return pform def _print_Manifold(self, manifold): @@ -2801,32 +2799,32 @@ def _print_Differential(self, diff): return self._print(d + ' ' + pretty_symbol(string)) else: pform = self._print(field) - pform = prettyForm(*pform.parens()) - return prettyForm(*pform.left(d)) + pform = pform.parens() + return pform.left(d) def _print_Tr(self, p): #TODO: Handle indices pform = self._print(p.args[0]) - pform = prettyForm(*pform.left('%s(' % (p.__class__.__name__))) - pform = prettyForm(*pform.right(')')) + pform = pform.left('%s(' % (p.__class__.__name__)) + pform = pform.right(')') return pform def _print_primenu(self, e): pform = self._print(e.args[0]) - pform = prettyForm(*pform.parens()) + pform = pform.parens() if self._use_unicode: - pform = prettyForm(*pform.left(greek_unicode['nu'])) + pform = pform.left(greek_unicode['nu']) else: - pform = prettyForm(*pform.left('nu')) + pform = pform.left('nu') return pform def _print_primeomega(self, e): pform = self._print(e.args[0]) - pform = prettyForm(*pform.parens()) + pform = pform.parens() if self._use_unicode: - pform = prettyForm(*pform.left(greek_unicode['Omega'])) + pform = pform.left(greek_unicode['Omega']) else: - pform = prettyForm(*pform.left('Omega')) + pform = pform.left('Omega') return pform def _print_Quantity(self, e): diff --git a/sympy/printing/pretty/stringpict.py b/sympy/printing/pretty/stringpict.py index b6055f09c83b..4670aa95e177 100644 --- a/sympy/printing/pretty/stringpict.py +++ b/sympy/printing/pretty/stringpict.py @@ -8,8 +8,7 @@ - minor fixes and changes (mostly to prettyForm) TODO: - - Allow left/center/right alignment options for above/below and - top/center/bottom alignment options for left/right + - top/center/bottom alignment options for left/right """ import shutil @@ -19,10 +18,12 @@ _GLOBAL_WRAP_LINE = None + class stringPict: """An ASCII picture. The pictures are represented as a list of equal length strings. """ + #special value for stringPict.below LINE = 'line' @@ -39,7 +40,7 @@ def __init__(self, s, baseline=0): @staticmethod def equalLengths(lines): - # empty lines + #empty lines if not lines: return [''] @@ -68,20 +69,19 @@ def next(*args): #make a list of pictures, with equal height and baseline newBaseline = max(obj.baseline for obj in objects) - newHeightBelowBaseline = max( - obj.height() - obj.baseline - for obj in objects) + newHeightBelowBaseline = max(obj.height() - obj.baseline for obj in objects) newHeight = newBaseline + newHeightBelowBaseline pictures = [] for obj in objects: - oneEmptyLine = [' '*obj.width()] + oneEmptyLine = [' ' * obj.width()] basePadding = newBaseline - obj.baseline totalPadding = newHeight - obj.height() pictures.append( - oneEmptyLine * basePadding + - obj.picture + - oneEmptyLine * (totalPadding - basePadding)) + oneEmptyLine * basePadding + + obj.picture + + oneEmptyLine * (totalPadding - basePadding) + ) result = [''.join(lines) for lines in zip(*pictures)] return '\n'.join(result), newBaseline @@ -95,27 +95,28 @@ def right(self, *args): ======== >>> from sympy.printing.pretty.stringpict import stringPict - >>> print(stringPict("10").right(" + ",stringPict("1\r-\r2",1))[0]) + >>> print(stringPict("10").right(" + ",stringPict("1\r-\r2",1))) 1 10 + - 2 """ - return stringPict.next(self, *args) + return self.__class__(*stringPict.next(self, *args)) def left(self, *args): """Put pictures (left to right) at left. Returns string, baseline arguments for stringPict. """ - return stringPict.next(*(args + (self,))) + return self.__class__(*stringPict.next(*(args + (self,)))) @staticmethod - def stack(*args): + def stack(*args, align="c"): """Put pictures on top of each other, from top to bottom. Returns string, baseline arguments for stringPict. The baseline is the baseline of the second picture. - Everything is centered. + By default, everything is centered. If `align` is set to + 'l' ('r') the elements are aligned to the left (right) margin. Baseline is the baseline of the second picture. Strings are allowed. The special value stringPict.LINE is a row of '-' extended to the width. @@ -128,10 +129,7 @@ def stack(*args): objects.append(arg) #compute new width - newWidth = max( - obj.width() - for obj in objects - if obj is not stringPict.LINE) + newWidth = max(obj.width() for obj in objects if obj is not stringPict.LINE) lineObj = stringPict(hobj('-', newWidth)) @@ -141,11 +139,31 @@ def stack(*args): objects[i] = lineObj #stack the pictures, and center the result - newPicture = [center(line, newWidth) for obj in objects for line in obj.picture] + if align == "c": + newPicture = [ + center(line, newWidth) for obj in objects for line in obj.picture + ] + elif align == "l": + newPicture = [ + line + (newWidth - len(line)) * ' ' + for obj in objects + for line in obj.picture + ] + elif align == "r": + newPicture = [ + (newWidth - len(line)) * ' ' + line + for obj in objects + for line in obj.picture + ] + else: + raise ValueError( + f"the align parameter must be one of 'l'(left), 'r'(right) or 'c' (center). Got {align}." + ) + newBaseline = objects[0].height() + objects[1].baseline - return '\n'.join(newPicture), newBaseline + return "\n".join(newPicture), newBaseline - def below(self, *args): + def below(self, *args, align="c"): """Put pictures under this picture. Returns string, baseline arguments for stringPict. Baseline is baseline of top picture @@ -155,25 +173,40 @@ def below(self, *args): >>> from sympy.printing.pretty.stringpict import stringPict >>> print(stringPict("x+3").below( - ... stringPict.LINE, '3')[0]) #doctest: +NORMALIZE_WHITESPACE + ... stringPict.LINE, '3')) #doctest: +NORMALIZE_WHITESPACE x+3 --- 3 + The optional argument `align` controls the alignment. + The default value is `'c'`. For `align='l'`, + the text is left aligned: + + >>> print(stringPict("Humpty Dumpty").below( + ... stringPict("falls off the wall..."), align="l")) + Humpty Dumpty + falls off the wall... + + and for `align='r'`, the elements are right aligned: + >>> print(stringPict("Humpty Dumpty").below( + ... stringPict("falls off the wall..."), align="r")) + Humpty Dumpty + falls off the wall... + """ - s, baseline = stringPict.stack(self, *args) - return s, self.baseline + s, baseline = stringPict.stack(self, *args, align=align) + return self.__class__(s, self.baseline) - def above(self, *args): + def above(self, *args, align="c"): """Put pictures above this picture. Returns string, baseline arguments for stringPict. Baseline is baseline of bottom picture. """ - string, baseline = stringPict.stack(*(args + (self,))) + string, baseline = stringPict.stack(*(args + (self,)), align=align) baseline = len(string.splitlines()) - self.height() + self.baseline - return string, baseline + return self.__class__(string, baseline) - def parens(self, left='(', right=')', ifascii_nougly=False): + def parens(self, left="(", right=")", ifascii_nougly=False): """Put parentheses around self. Returns string, baseline arguments for stringPict. @@ -192,25 +225,21 @@ def parens(self, left='(', right=')', ifascii_nougly=False): if left: lparen = stringPict(vobj(left, h), baseline=b) - res = stringPict(*lparen.right(self)) + res = lparen.right(self) if right: rparen = stringPict(vobj(right, h), baseline=b) - res = stringPict(*res.right(rparen)) + res = res.right(rparen) - return ('\n'.join(res.picture), res.baseline) + return self.__class__("\n".join(res.picture), res.baseline) def leftslash(self): - """Precede object by a slash of the proper size. - """ + """Precede object by a slash of the proper size.""" # XXX not used anywhere ? - height = max( - self.baseline, - self.height() - 1 - self.baseline)*2 + 1 + height = max(self.baseline, self.height() - 1 - self.baseline) * 2 + 1 slash = '\n'.join( - ' '*(height - i - 1) + xobj('/', 1) + ' '*i - for i in range(height) + ' ' * (height - i - 1) + xobj('/', 1) + ' ' * i for i in range(height) ) - return self.left(stringPict(slash, height//2)) + return self.left(stringPict(slash, height // 2)) def root(self, n=None): """Produce a nice root symbol. @@ -219,13 +248,10 @@ def root(self, n=None): # XXX not used anywhere # XXX duplicate of root drawing in pretty.py #put line over expression - result = self.above('_'*self.width()) + result = self.above('_' * self.width()) #construct right half of root symbol height = self.height() - slash = '\n'.join( - ' ' * (height - i - 1) + '/' + ' ' * i - for i in range(height) - ) + slash = '\n'.join(' ' * (height - i - 1) + '/' + ' ' * i for i in range(height)) slash = stringPict(slash, height - 1) #left half of root symbol if height > 2: @@ -234,7 +260,7 @@ def root(self, n=None): downline = stringPict('\\') #put n on top, as low as possible if n is not None and n.width() > downline.width(): - downline = downline.left(' '*(n.width() - downline.width())) + downline = downline.left(' ' * (n.width() - downline.width())) downline = downline.above(n) #build root symbol root = downline.right(slash) @@ -246,7 +272,7 @@ def root(self, n=None): root.baseline = result.baseline - result.height() + root.height() return result.left(root) - def render(self, * args, **kwargs): + def render(self, *args, **kwargs): """Return the string form of self. Unless the argument line_break is set to False, it will @@ -257,7 +283,7 @@ def render(self, * args, **kwargs): kwargs["wrap_line"] = _GLOBAL_WRAP_LINE if kwargs["wrap_line"] is False: - return "\n".join(self.picture) + return '\n'.join(self.picture) if kwargs["num_columns"] is not None: # Read the argument num_columns if it is not None @@ -293,10 +319,10 @@ def render(self, * args, **kwargs): overflow_first = "" if kwargs["use_unicode"] or pretty_use_unicode(): overflow_start = "\N{RIGHTWARDS ARROW WITH HOOK} " - overflow_end = " \N{RIGHTWARDS ARROW WITH HOOK}" + overflow_end = " \N{RIGHTWARDS ARROW WITH HOOK}" else: overflow_start = "> " - overflow_end = " >" + overflow_end = " >" def chunks(line): """Yields consecutive chunks of line_width ncols""" @@ -317,14 +343,33 @@ def chunks(line): pictures = zip(*map(chunks, self.picture)) # Join lines of each screen into sub-pictures - pictures = ["\n".join(picture) for picture in pictures] + pictures = ['\n'.join(picture) for picture in pictures] - # Add spacers between sub-pictures + #Add spacers between sub-pictures return "\n\n".join(pictures) - def terminal_width(self): - """Return the terminal width if possible, otherwise return 0. + def subindex(self, index): + """ + Add a `sub index`. """ + width_self = self.width() + width_index = index.width() + extended_self = self.right(width_index * stringPict(' ')) + index = index.left(width_self * stringPict(' ')) + return extended_self.bellow(index) + + def superindex(self, index): + """ + Add a `super index`. + """ + width_self = self.width() + width_index = index.width() + extended_self = self.right(width_index * stringPict(' ')) + index = index.left(width_self * stringPict(' ')) + return extended_self.above(index) + + def terminal_width(self): + """Return the terminal width if possible, otherwise return 0.""" size = shutil.get_terminal_size(fallback=(0, 0)) return size.columns @@ -369,6 +414,7 @@ class prettyForm(stringPict): OPEN this is an open object: parenthesize if added, multiplied, or powered (example: Piecewise) """ + ATOM, FUNC, DIV, POW, MUL, ADD, NEG, OPEN = range(8) def __init__(self, s, baseline=0, binding=0, unicode=None): @@ -404,12 +450,12 @@ def __add__(self, *others): """ arg = self if arg.binding > prettyForm.NEG: - arg = stringPict(*arg.parens()) + arg = arg.parens() result = [arg] for arg in others: - #add parentheses for weak binders + # add parentheses for weak binders if arg.binding > prettyForm.NEG: - arg = stringPict(*arg.parens()) + arg = arg.parens() #use existing minus sign if available if arg.binding != prettyForm.NEG: result.append(' + ') @@ -417,51 +463,47 @@ def __add__(self, *others): return prettyForm(binding=prettyForm.ADD, *stringPict.next(*result)) def __truediv__(self, den, slashed=False): - """Make a pretty division; stacked or slashed. - """ + """Make a pretty division; stacked or slashed.""" if slashed: raise NotImplementedError("Can't do slashed fraction yet") num = self if num.binding == prettyForm.DIV: - num = stringPict(*num.parens()) + num = num.parens() if den.binding == prettyForm.DIV: - den = stringPict(*den.parens()) + den = den.parens() - if num.binding==prettyForm.NEG: - num = num.right(" ")[0] + if num.binding == prettyForm.NEG: + num = num.right(' ') - return prettyForm(binding=prettyForm.DIV, *stringPict.stack( - num, - stringPict.LINE, - den)) + return prettyForm( + binding=prettyForm.DIV, *stringPict.stack(num, stringPict.LINE, den) + ) def __mul__(self, *others): """Make a pretty multiplication. Parentheses are needed around +, - and neg. """ - quantity = { - 'degree': "\N{DEGREE SIGN}" - } + quantity = {"degree": "\N{DEGREE SIGN}"} if len(others) == 0: - return self # We aren't actually multiplying... So nothing to do here. + return self #We aren't actually multiplying... So nothing to do here. - # add parens on args that need them + #add parens on args that need them arg = self if arg.binding > prettyForm.MUL and arg.binding != prettyForm.NEG: - arg = stringPict(*arg.parens()) + arg = arg.parens() result = [arg] for arg in others: if arg.picture[0] not in quantity.values(): result.append(xsym('*')) #add parentheses for weak binders if arg.binding > prettyForm.MUL and arg.binding != prettyForm.NEG: - arg = stringPict(*arg.parens()) + arg = arg.parens() result.append(arg) len_res = len(result) for i in range(len_res): - if i < len_res - 1 and result[i] == '-1' and result[i + 1] == xsym('*'): + if i < len_res - 1 and result[i] == "-1" and result[i + 1] == xsym('*'): # substitute -1 by -, like in -1*x -> -x result.pop(i) result.pop(i) @@ -482,21 +524,21 @@ def __repr__(self): return "prettyForm(%r,%d,%d)" % ( '\n'.join(self.picture), self.baseline, - self.binding) + self.binding, + ) def __pow__(self, b): - """Make a pretty power. - """ + """Make a pretty power.""" a = self use_inline_func_form = False if b.binding == prettyForm.POW: - b = stringPict(*b.parens()) + b = b.parens() if a.binding > prettyForm.FUNC: - a = stringPict(*a.parens()) + a = a.parens() elif a.binding == prettyForm.FUNC: # heuristic for when to use inline power if b.height() > 1: - a = stringPict(*a.parens()) + a = a.parens() else: use_inline_func_form = True @@ -504,34 +546,42 @@ def __pow__(self, b): # 2 # sin + + (x) b.baseline = a.prettyFunc.baseline + b.height() - func = stringPict(*a.prettyFunc.right(b)) - return prettyForm(*func.right(a.prettyArgs)) + func = a.prettyFunc.right(b) + return func.right(a.prettyArgs) else: # 2 <-- top # (x+y) <-- bot - top = stringPict(*b.left(' '*a.width())) - bot = stringPict(*a.right(' '*b.width())) + top = b.left(' ' * a.width()) + bot = a.right(' ' * b.width()) - return prettyForm(binding=prettyForm.POW, *bot.above(top)) + result = bot.above(top) + result.binding = prettyForm.POW + return result simpleFunctions = ["sin", "cos", "tan"] @staticmethod def apply(function, *args): - """Functions of one or more variables. - """ + """Functions of one or more variables.""" if function in prettyForm.simpleFunctions: #simple function: use only space if possible - assert len( - args) == 1, "Simple function %s must have 1 argument" % function + assert len(args) == 1, "Simple function %s must have 1 argument" % function arg = args[0].__pretty__() if arg.binding <= prettyForm.DIV: #optimization: no parentheses necessary - return prettyForm(binding=prettyForm.FUNC, *arg.left(function + ' ')) + result = arg.left(function + ' ') + result.binding = prettyForm.FUNC + return result argumentList = [] for arg in args: argumentList.append(',') argumentList.append(arg.__pretty__()) - argumentList = stringPict(*stringPict.next(*argumentList[1:])) - argumentList = stringPict(*argumentList.parens()) - return prettyForm(binding=prettyForm.ATOM, *argumentList.left(function)) + if argumentList: + first_arg, *rest = argumentList + argument_pict = first_arg.right(*rest) + else: + argument_pict = stringPict("") + argument_pict = argument_pict.parens() + func_pict = argument_pict.left(function) + func_pict.binding = prettyForm.ATOM + return func_pict