Repository: numpy/numpy

Issue:
legacy 1.13 printing edge case: missing superfluous comma after ellipsis
I think this is the last quirk that we found when running the scikit-learn doctests. After this one you will hopefully not hear from me for a while ;-). We have only one doctest affected by this and we can work around this easily by using `repr` instead of `print` or using doctest ellipsis.

This edge case does break the `legacy='1.13'` promise so I thought I would let you know and then you can decide whether you want to fix it (i.e. match the buggy behaviour with `legacy='1.13'`)  or not. I would completely understand if you just decided to close this issue

```py
import numpy as np

try:
    np.set_printoptions(legacy='1.13')
except TypeError:
    pass

print(np.arange(10000))
```

Output numpy dev:
```
[   0    1    2 ... 9997 9998 9999]
```

Ouput on 1.13.3 (note the additional comma after the ellipsis):
```
[   0    1    2 ..., 9997 9998 9999]
```


Discussion:
Yep, this was issue #9777/PR #9815, which was before we settled on the `legacy` API, I think.

It's pretty straightforward to fix this, so I'm inclined to say we should, even if it was a bugfix.
@ahaldane @eric-wieser Has this been fixed?
No, this is still outstanding

Resolving patch:
diff --git a/numpy/core/arrayprint.py b/numpy/core/arrayprint.py
--- a/numpy/core/arrayprint.py
+++ b/numpy/core/arrayprint.py
@@ -443,8 +443,8 @@ def _array2string(a, options, separator=' ', prefix=""):
     next_line_prefix += " "*len(prefix)
 
     lst = _formatArray(a, format_function, a.ndim, options['linewidth'],
-                       next_line_prefix, separator,
-                       options['edgeitems'], summary_insert)[:-1]
+                       next_line_prefix, separator, options['edgeitems'],
+                       summary_insert, options['legacy'])[:-1]
     return lst
 
 
@@ -617,8 +617,8 @@ def _extendLine(s, line, word, max_line_len, next_line_prefix):
     return s, line
 
 
-def _formatArray(a, format_function, rank, max_line_len,
-                 next_line_prefix, separator, edge_items, summary_insert):
+def _formatArray(a, format_function, rank, max_line_len, next_line_prefix,
+                 separator, edge_items, summary_insert, legacy):
     """formatArray is designed for two modes of operation:
 
     1. Full output
@@ -633,6 +633,8 @@ def _formatArray(a, format_function, rank, max_line_len,
         leading_items = edge_items
         trailing_items = edge_items
         summary_insert1 = summary_insert + separator
+        if legacy == '1.13':
+            summary_insert1 = summary_insert + ', '
     else:
         leading_items = 0
         trailing_items = len(a)
@@ -646,7 +648,8 @@ def _formatArray(a, format_function, rank, max_line_len,
             s, line = _extendLine(s, line, word, max_line_len, next_line_prefix)
 
         if summary_insert1:
-            s, line = _extendLine(s, line, summary_insert1, max_line_len, next_line_prefix)
+            s, line = _extendLine(s, line, summary_insert1, max_line_len,
+                                  next_line_prefix)
 
         for i in range(trailing_items, 1, -1):
             word = format_function(a[-i]) + separator
@@ -664,7 +667,7 @@ def _formatArray(a, format_function, rank, max_line_len,
                 s += next_line_prefix
             s += _formatArray(a[i], format_function, rank-1, max_line_len,
                               " " + next_line_prefix, separator, edge_items,
-                              summary_insert)
+                              summary_insert, legacy)
             s = s.rstrip() + sep.rstrip() + '\n'*max(rank-1, 1)
 
         if summary_insert1:
@@ -675,13 +678,13 @@ def _formatArray(a, format_function, rank, max_line_len,
                 s += next_line_prefix
             s += _formatArray(a[-i], format_function, rank-1, max_line_len,
                               " " + next_line_prefix, separator, edge_items,
-                              summary_insert)
+                              summary_insert, legacy)
             s = s.rstrip() + sep.rstrip() + '\n'*max(rank-1, 1)
         if leading_items or trailing_items > 1:
             s += next_line_prefix
         s += _formatArray(a[-1], format_function, rank-1, max_line_len,
                           " " + next_line_prefix, separator, edge_items,
-                          summary_insert).rstrip()+']\n'
+                          summary_insert, legacy).rstrip()+']\n'
     return s
 
 


Test patch:
diff --git a/numpy/core/tests/test_arrayprint.py b/numpy/core/tests/test_arrayprint.py
--- a/numpy/core/tests/test_arrayprint.py
+++ b/numpy/core/tests/test_arrayprint.py
@@ -487,6 +487,13 @@ def test_legacy_mode_scalars(self):
                      '1.1234567891234568')
         assert_equal(str(np.complex128(complex(1, np.nan))), '(1+nanj)')
 
+    def test_legacy_stray_comma(self):
+        np.set_printoptions(legacy='1.13')
+        assert_equal(str(np.arange(10000)), '[   0    1    2 ..., 9997 9998 9999]')
+
+        np.set_printoptions(legacy=False)
+        assert_equal(str(np.arange(10000)), '[   0    1    2 ... 9997 9998 9999]')
+
     def test_dtype_linewidth_wrapping(self):
         np.set_printoptions(linewidth=75)
         assert_equal(repr(np.arange(10,20., dtype='f4')),
diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py
--- a/numpy/ma/tests/test_core.py
+++ b/numpy/ma/tests/test_core.py
@@ -571,8 +571,8 @@ def test_str_repr_legacy(self):
             a[1:50] = np.ma.masked
             assert_equal(
                 repr(a),
-                'masked_array(data = [0 -- -- ... 1997 1998 1999],\n'
-                '             mask = [False  True  True ... False False False],\n'
+                'masked_array(data = [0 -- -- ..., 1997 1998 1999],\n'
+                '             mask = [False  True  True ..., False False False],\n'
                 '       fill_value = 999999)\n'
             )
         finally: