Repository: sympy/sympy
Pull request: update pretty printer for physics vector
<!-- Your title above should be a short description of what
was changed. Do not include the issue number in the title. -->

#### References to other Issues or PRs
<!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
format, e.g. "Fixes #1234". See
https://github.com/blog/1506-closing-issues-via-pull-requests .-->
"Fixes #15583".

#### Brief description of what is fixed or changed
pretty printer is not working and throw an error for tuple of physics
so i change pretty printer function .

#### Other comments


#### Release Notes

<!-- Write the release notes for this release below. See
https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more information
on how to write release notes. The bot will check your release notes
automatically to see if they are formatted correctly. -->

<!-- BEGIN RELEASE NOTES -->
- printing
  - pretty printer 
<!-- END RELEASE NOTES -->


Problem statement:
Tuple of Physics Unit Vectors Errors on Rendering in Jupyter Notebook
```python
import sympy as sm
sm.init_printing()
import sympy.physics.mechanics as me
N = me.ReferenceFrame('N')
N.x, N.y, N.z
```

```
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~/miniconda3/envs/resonance-dev/lib/python3.6/site-packages/IPython/core/formatters.py in __call__(self, obj)
    700                 type_pprinters=self.type_printers,
    701                 deferred_pprinters=self.deferred_printers)
--> 702             printer.pretty(obj)
    703             printer.flush()
    704             return stream.getvalue()

~/miniconda3/envs/resonance-dev/lib/python3.6/site-packages/IPython/lib/pretty.py in pretty(self, obj)
    383                 if cls in self.type_pprinters:
    384                     # printer registered in self.type_pprinters
--> 385                     return self.type_pprinters[cls](obj, self, cycle)
    386                 else:
    387                     # deferred printer

~/miniconda3/envs/resonance-dev/lib/python3.6/site-packages/sympy/interactive/printing.py in _print_plain(arg, p, cycle)
     66         """caller for pretty, for use in IPython 0.11"""
     67         if _can_print_latex(arg):
---> 68             p.text(stringify_func(arg))
     69         else:
     70             p.text(IPython.lib.pretty.pretty(arg))

~/miniconda3/envs/resonance-dev/lib/python3.6/site-packages/sympy/printing/pretty/pretty.py in pretty(expr, **settings)
   2339 
   2340     try:
-> 2341         return pp.doprint(expr)
   2342     finally:
   2343         pretty_use_unicode(uflag)

~/miniconda3/envs/resonance-dev/lib/python3.6/site-packages/sympy/printing/pretty/pretty.py in doprint(self, expr)
     60 
     61     def doprint(self, expr):
---> 62         return self._print(expr).render(**self._settings)
     63 
     64     # empty op so _print(stringPict) returns the same

~/miniconda3/envs/resonance-dev/lib/python3.6/site-packages/sympy/printing/printer.py in _print(self, expr, **kwargs)
    285                 printmethod = '_print_' + cls.__name__
    286                 if hasattr(self, printmethod):
--> 287                     return getattr(self, printmethod)(expr, **kwargs)
    288             # Unknown object, fall back to the emptyPrinter.
    289             return self.emptyPrinter(expr)

~/miniconda3/envs/resonance-dev/lib/python3.6/site-packages/sympy/printing/pretty/pretty.py in _print_tuple(self, t)
   1914             return prettyForm(*ptuple.parens('(', ')', ifascii_nougly=True))
   1915         else:
-> 1916             return self._print_seq(t, '(', ')')
   1917 
   1918     def _print_Tuple(self, expr):

~/miniconda3/envs/resonance-dev/lib/python3.6/site-packages/sympy/printing/pretty/pretty.py in _print_seq(self, seq, left, right, delimiter, parenthesize)
   1882                 s = pform
   1883             else:
-> 1884                 s = prettyForm(*stringPict.next(s, delimiter))
   1885                 s = prettyForm(*stringPict.next(s, pform))
   1886 

~/miniconda3/envs/resonance-dev/lib/python3.6/site-packages/sympy/printing/pretty/stringpict.py in next(*args)
     67 
     68         #make a list of pictures, with equal height and baseline
---> 69         newBaseline = max(obj.baseline for obj in objects)
     70         newHeightBelowBaseline = max(
     71             obj.height() - obj.baseline

~/miniconda3/envs/resonance-dev/lib/python3.6/site-packages/sympy/printing/pretty/stringpict.py in <genexpr>(.0)
     67 
     68         #make a list of pictures, with equal height and baseline
---> 69         newBaseline = max(obj.baseline for obj in objects)
     70         newHeightBelowBaseline = max(
     71             obj.height() - obj.baseline

AttributeError: 'Fake' object has no attribute 'baseline'

```

Hints from issue discussion:
@moorepants  i would like to work on this issue can you tell me more about this.
The pretty printer seems to fail for the physics vectors.

Commit message: update pretty printer for physics vector

Patch to review:
diff --git a/sympy/printing/pretty/pretty.py b/sympy/printing/pretty/pretty.py
index a696db126202..26c93f8751e5 100644
--- a/sympy/printing/pretty/pretty.py
+++ b/sympy/printing/pretty/pretty.py
@@ -1977,21 +1977,37 @@ def _print_SeqFormula(self, s):
     def _print_seq(self, seq, left=None, right=None, delimiter=', ',
             parenthesize=lambda x: False):
         s = None
+        try:
+            for item in seq:
+                pform = self._print(item)
+
+                if parenthesize(item):
+                    pform = prettyForm(*pform.parens())
+                if s is None:
+                    # first element
+                    s = pform
+                else:
+                    s = prettyForm(*stringPict.next(s, delimiter))
+                    s = prettyForm(*stringPict.next(s, pform))
 
-        for item in seq:
-            pform = self._print(item)
-
-            if parenthesize(item):
-                pform = prettyForm(*pform.parens())
             if s is None:
-                # first element
-                s = pform
-            else:
-                s = prettyForm(*stringPict.next(s, delimiter))
-                s = prettyForm(*stringPict.next(s, pform))
+                s = stringPict('')
 
-        if s is None:
-            s = stringPict('')
+        except AttributeError:
+            s = None
+            for item in seq:
+                pform = self.doprint(item)
+                if parenthesize(item):
+                    pform = prettyForm(*pform.parens())
+                if s is None:
+                    # first element
+                    s = pform
+                else :
+                    s = prettyForm(*stringPict.next(s, delimiter))
+                    s = prettyForm(*stringPict.next(s, pform))
+
+            if s is None:
+                s = stringPict('')
 
         s = prettyForm(*s.parens(left, right, ifascii_nougly=True))
         return s
diff --git a/sympy/printing/pretty/tests/test_pretty.py b/sympy/printing/pretty/tests/test_pretty.py
index d413887f400e..cf9457a4a6a0 100644
--- a/sympy/printing/pretty/tests/test_pretty.py
+++ b/sympy/printing/pretty/tests/test_pretty.py
@@ -6483,3 +6483,11 @@ def test_issue_15560():
     e = pretty(a*(KroneckerProduct(a, a)))
     result = 'a*(a x a)'
     assert e == result
+
+def test_issue_15583():
+    from  sympy.physics import mechanics
+
+    N = mechanics.ReferenceFrame('N')
+    result = '(n_x, n_y, n_z)'
+    e = pretty((N.x, N.y, N.z))
+    assert e == result


Code review comments:
diff_hunk: @@ -6483,3 +6483,11 @@ def test_issue_15560():
     e = pretty(a*(KroneckerProduct(a, a)))
     result = 'a*(a x a)'
     assert e == result
+
+def test_issue_15583():
+    from  sympy.physics import mechanics
path: sympy/printing/pretty/tests/test_pretty.py
text: @user1:
This should go at the top of the file with all imports.

@author:
ok ,i will do this.