Skip to content

Commit d08efaf

Browse files
Zac-HDshoyer
authored andcommitted
Shorter repr for attributes (#1322)
* Shorter repr for attributes NetCDF files often have tens of attributes, including multi-paragraph summaries or the full modification history of the file. It's great to have this available in the .attrs, but we can truncate it substantially in the repr! Hopefully this will stop people writing `data.attrs = {}` and discarding metadata in interactive workflows for the sake of cleaner output. * Add test for attribute repr
1 parent 56cec46 commit d08efaf

File tree

6 files changed

+31
-6
lines changed

6 files changed

+31
-6
lines changed

doc/whats-new.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ By `Henry S. Harrison <https://hsharrison.github.io>`_.
4343
Note, the default is ``autoclose=False``, which is consistent with previous
4444
xarray behavior. By `Phillip J. Wolfram <https://github.com/pwolfram>`_.
4545

46+
- The ``repr()`` of ``Dataset`` and ``DataArray`` attributes uses a similar
47+
format to coordinates and variables, with vertically aligned entries
48+
truncated to fit on a single line. Hopefully this will stop people writing
49+
``data.attrs = {}`` and discarding metadata in notebooks for the sake of
50+
cleaner output. The full metadata is still available as ``data.attrs``.
51+
By `Zac Hatfield-Dodds <https://github.com/Zac-HD>`_.
52+
4653
Bug fixes
4754
~~~~~~~~~
4855
- ``rolling`` now keeps its original dimension order (:issue:`1125`).

xarray/core/formatting.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,15 @@ def summarize_coord(name, var, col_width):
253253

254254

255255
def summarize_attr(key, value, col_width=None):
256-
# ignore col_width for now to more clearly distinguish attributes
257-
return u' %s: %s' % (key, maybe_truncate(value))
256+
"""Summary for __repr__ - use ``X.attrs[key]`` for full value."""
257+
# Indent key and add ':', then right-pad if col_width is not None
258+
k_str = u' %s:' % key
259+
if col_width is not None:
260+
k_str = pretty_print(k_str, col_width)
261+
# Replace tabs and newlines, so we print on one line in known width
262+
v_str = unicode_type(value).replace(u'\t', u'\\t').replace(u'\n', u'\\n')
263+
# Finally, truncate to the desired display width
264+
return maybe_truncate(u'%s %s' % (k_str, v_str), OPTIONS['display_width'])
258265

259266

260267
EMPTY_REPR = u' *empty*'

xarray/tests/test_dataarray.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def test_repr(self):
4949
other int64 0
5050
Dimensions without coordinates: time
5151
Attributes:
52-
foo: bar""")
52+
foo: bar""")
5353
self.assertEqual(expected, repr(data_array))
5454

5555
def test_repr_multiindex(self):

xarray/tests/test_dataset.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def test_repr(self):
101101
var2 (dim1, dim2) float64 1.162 -1.097 -2.123 1.04 -0.4034 -0.126 ...
102102
var3 (dim3, dim1) float64 0.5565 -0.2121 0.4563 1.545 -0.2397 0.1433 ...
103103
Attributes:
104-
foo: bar""") % data['dim3'].dtype
104+
foo: bar""") % data['dim3'].dtype
105105
actual = '\n'.join(x.rstrip() for x in repr(data).split('\n'))
106106
print(actual)
107107
self.assertEqual(expected, actual)
@@ -187,7 +187,7 @@ def test_unicode_data(self):
187187
Data variables:
188188
*empty*
189189
Attributes:
190-
å: ∑""" % u'ba®')
190+
å: ∑""" % u'ba®')
191191
actual = unicode_type(data)
192192
self.assertEqual(expected, actual)
193193

xarray/tests/test_formatting.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,17 @@ def test_format_timestamp_out_of_bounds(self):
131131
result = formatting.format_timestamp(date)
132132
self.assertEqual(result, expected)
133133

134+
def test_attribute_repr(self):
135+
short = formatting.summarize_attr(u'key', u'Short string')
136+
long = formatting.summarize_attr(u'key', 100 * u'Very long string ')
137+
newlines = formatting.summarize_attr(u'key', u'\n\n\n')
138+
tabs = formatting.summarize_attr(u'key', u'\t\t\t')
139+
self.assertEqual(short, ' key: Short string')
140+
self.assertLessEqual(len(long), 80)
141+
self.assertTrue(long.endswith(u'...'))
142+
self.assertNotIn(u'\n', newlines)
143+
self.assertNotIn(u'\t', tabs)
144+
134145

135146
def test_set_numpy_options():
136147
original_options = np.get_printoptions()

xarray/tests/test_variable.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ def test_repr(self):
644644
array([[1, 2, 3],
645645
[4, 5, 6]])
646646
Attributes:
647-
foo: bar
647+
foo: bar
648648
""").strip()
649649
self.assertEqual(expected, repr(v))
650650

0 commit comments

Comments
 (0)