Repository: mne-tools/mne-python

Issue:
Annotations repr too long
I don't like that the `repr` for an `Annotations` object exceeds 79 characters. For example, the following repr has 94 characters:

```
<Annotations  |  30 segments : T0 (15), T2 (7), T1 (8), orig_time : 2009-08-12 16:15:00+00:00>
```

It would be nice if the maximum character length of this (and any other) repr was 79, otherwise these get hard to read because of line breaks.

In the specific case of `Annotations`, I would remove the `orig_time` information because I don't think this is important enough to show in the repr.


Discussion:
maybe just give time as "Time: 2009-08-12" to omit too precise info?

>

> maybe just give time as "Time: 2009-08-12" to omit too precise info?

I don't think this is that important. I'd rather use the available characters to show more annotations.
we have some repr that are multilines I think

Yes, for example `info`. We also have some reprs that definitely exceed 79 characters (not just `Annotations`).
If there are a lot of different annotation labels, you can't guarantee they'll all fit even if you remove time completely. Will you truncate then? Or change to a summary message like "30 segments, 21 labels"?

(BTW I agree that the time is not that important to include in the repr here)
do what you think is best. I don't have strong feelings here.

>


Resolving patch:
diff --git a/mne/annotations.py b/mne/annotations.py
--- a/mne/annotations.py
+++ b/mne/annotations.py
@@ -9,6 +9,7 @@
 from itertools import takewhile
 import collections
 import warnings
+from textwrap import shorten
 import numpy as np
 
 from .utils import (_pl, check_fname, _validate_type, verbose, warn, logger,
@@ -205,15 +206,11 @@ def __eq__(self, other):
     def __repr__(self):
         """Show the representation."""
         counter = collections.Counter(self.description)
-        kinds = ['%s (%s)' % k for k in counter.items()]
-        kinds = ', '.join(kinds[:3]) + ('' if len(kinds) <= 3 else '...')
+        kinds = ', '.join(['%s (%s)' % k for k in sorted(counter.items())])
         kinds = (': ' if len(kinds) > 0 else '') + kinds
-        if self.orig_time is None:
-            orig = 'orig_time : None'
-        else:
-            orig = 'orig_time : %s' % self.orig_time
-        return ('<Annotations  |  %s segment%s %s, %s>'
-                % (len(self.onset), _pl(len(self.onset)), kinds, orig))
+        s = ('Annotations  |  %s segment%s%s' %
+             (len(self.onset), _pl(len(self.onset)), kinds))
+        return '<' + shorten(s, width=77, placeholder=' ...') + '>'
 
     def __len__(self):
         """Return the number of annotations."""


Test patch:
diff --git a/mne/tests/test_annotations.py b/mne/tests/test_annotations.py
--- a/mne/tests/test_annotations.py
+++ b/mne/tests/test_annotations.py
@@ -1189,4 +1189,21 @@ def test_annotations_from_events():
     assert len(annots) == events[events[:, 2] <= 3].shape[0]
 
 
+def test_repr():
+    """Test repr of Annotations."""
+
+    # short annotation repr (< 79 characters)
+    r = repr(Annotations(range(3), [0] * 3, list("abc")))
+    assert r == '<Annotations | 3 segments: a (1), b (1), c (1)>'
+
+    # long annotation repr (> 79 characters, will be shortened)
+    r = repr(Annotations(range(14), [0] * 14, list("abcdefghijklmn")))
+    assert r == ('<Annotations | 14 segments: a (1), b (1), c (1), d (1), '
+                 'e (1), f (1), g ...>')
+
+    # empty Annotations
+    r = repr(Annotations([], [], []))
+    assert r == '<Annotations | 0 segments>'
+
+
 run_tests_if_main()