Skip to content

Commit eef3cd5

Browse files
hsperrjreback
authored andcommitted
ENH: repr now shows index name pandas-dev#6482
move tests to generically tests for index generify __unicode__ for Index adjust index display to max_seq_items
1 parent 8b7c22d commit eef3cd5

File tree

8 files changed

+220
-99
lines changed

8 files changed

+220
-99
lines changed

pandas/core/index.py

+62-2
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,68 @@ def __unicode__(self):
392392
Invoked by unicode(df) in py2 only. Yields a Unicode String in both
393393
py2/py3.
394394
"""
395-
prepr = default_pprint(self)
396-
return "%s(%s, dtype='%s')" % (type(self).__name__, prepr, self.dtype)
395+
klass = self.__class__.__name__
396+
data = self._format_data()
397+
attrs = self._format_attrs()
398+
max_seq_items = get_option('display.max_seq_items')
399+
if len(self) > max_seq_items:
400+
space = "\n%s" % (' ' * (len(klass) + 1))
401+
else:
402+
space = " "
403+
404+
prepr = (u(",%s") % space).join([u("%s=%s") % (k, v)
405+
for k, v in attrs])
406+
res = u("%s(%s,%s%s)") % (klass,
407+
data,
408+
space,
409+
prepr)
410+
411+
return res
412+
413+
@property
414+
def _formatter_func(self):
415+
"""
416+
Return the formatted data as a unicode string
417+
"""
418+
return default_pprint
419+
420+
def _format_data(self):
421+
"""
422+
Return the formatted data as a unicode string
423+
"""
424+
425+
max_seq_items = get_option('display.max_seq_items')
426+
formatter = self._formatter_func
427+
n = len(self)
428+
if n == 0:
429+
summary = '[]'
430+
elif n == 1:
431+
first = formatter(self[0])
432+
summary = '[%s]' % first
433+
elif n == 2:
434+
first = formatter(self[0])
435+
last = formatter(self[-1])
436+
summary = '[%s, %s]' % (first, last)
437+
elif n > max_seq_items:
438+
n = min(max_seq_items//2,2)
439+
head = ', '.join([ formatter(x) for x in self[:n] ])
440+
tail = ', '.join([ formatter(x) for x in self[-n:] ])
441+
summary = '[%s, ..., %s]' % (head, tail)
442+
else:
443+
summary = "[%s]" % ', '.join([ formatter(x) for x in self ])
444+
445+
return summary
446+
447+
448+
def _format_attrs(self):
449+
"""
450+
Return a list of tuples of the (attr,formatted_value)
451+
"""
452+
attrs = []
453+
if self.name is not None:
454+
attrs.append(('name',default_pprint(self.name)))
455+
attrs.append(('dtype',"'%s'" % self.dtype))
456+
return attrs
397457

398458
def to_series(self, **kwargs):
399459
"""

pandas/tests/test_index.py

+36-2
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,19 @@ def test_ndarray_compat_properties(self):
120120
idx.nbytes
121121
idx.values.nbytes
122122

123+
def test_repr_roundtrip(self):
124+
125+
idx = self.create_index()
126+
tm.assert_index_equal(eval(repr(idx)),idx)
127+
128+
def test_str(self):
129+
130+
# test the string repr
131+
idx = self.create_index()
132+
idx.name = 'foo'
133+
self.assertTrue("'foo'" in str(idx))
134+
self.assertTrue(idx.__class__.__name__ in str(idx))
135+
123136
def test_wrong_number_names(self):
124137
def testit(ind):
125138
ind.names = ["apple", "banana", "carrot"]
@@ -2474,6 +2487,26 @@ def test_slice_keep_name(self):
24742487

24752488
class DatetimeLike(Base):
24762489

2490+
def test_repr_roundtrip(self):
2491+
raise nose.SkipTest("Short reprs are not supported repr for Datetimelike indexes")
2492+
2493+
def test_str(self):
2494+
2495+
# test the string repr
2496+
idx = self.create_index()
2497+
idx.name = 'foo'
2498+
self.assertTrue("length=%s" % len(idx) in str(idx))
2499+
self.assertTrue("u'foo'" in str(idx))
2500+
self.assertTrue(idx.__class__.__name__ in str(idx))
2501+
2502+
if hasattr(idx,'tz'):
2503+
if idx.tz is not None:
2504+
self.assertTrue("tz='%s'" % idx.tz in str(idx))
2505+
else:
2506+
self.assertTrue("tz=None" in str(idx))
2507+
if hasattr(idx,'freq'):
2508+
self.assertTrue("freq='%s'" % idx.freqstr in str(idx))
2509+
24772510
def test_view(self):
24782511
super(DatetimeLike, self).test_view()
24792512

@@ -4387,8 +4420,9 @@ def test_repr_with_unicode_data(self):
43874420
index = pd.DataFrame(d).set_index(["a", "b"]).index
43884421
self.assertFalse("\\u" in repr(index)) # we don't want unicode-escaped
43894422

4390-
def test_repr_roundtrip(self):
4391-
tm.assert_index_equal(eval(repr(self.index)), self.index)
4423+
def test_str(self):
4424+
# tested elsewhere
4425+
pass
43924426

43934427
def test_unicode_string_with_unicode(self):
43944428
d = {"a": [u("\u05d0"), 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]}

pandas/tseries/base.py

+18-24
Original file line numberDiff line numberDiff line change
@@ -265,30 +265,24 @@ def _formatter_func(self):
265265
"""
266266
return str
267267

268-
def _format_footer(self):
269-
raise AbstractMethodError(self)
270-
271-
def __unicode__(self):
272-
formatter = self._formatter_func
273-
summary = str(self.__class__) + '\n'
274-
275-
n = len(self)
276-
if n == 0:
277-
pass
278-
elif n == 1:
279-
first = formatter(self[0])
280-
summary += '[%s]\n' % first
281-
elif n == 2:
282-
first = formatter(self[0])
283-
last = formatter(self[-1])
284-
summary += '[%s, %s]\n' % (first, last)
285-
else:
286-
first = formatter(self[0])
287-
last = formatter(self[-1])
288-
summary += '[%s, ..., %s]\n' % (first, last)
289-
290-
summary += self._format_footer()
291-
return summary
268+
def _format_attrs(self):
269+
"""
270+
Return a list of tuples of the (attr,formatted_value)
271+
"""
272+
attrs = super(DatetimeIndexOpsMixin, self)._format_attrs()
273+
attrs.append(('length',len(self)))
274+
for attrib in self._attributes:
275+
if attrib == 'freq':
276+
freq = self.freqstr
277+
if freq is not None:
278+
freq = "'%s'" % freq
279+
attrs.append(('freq',freq))
280+
elif attrib == 'tz':
281+
tz = self.tz
282+
if tz is not None:
283+
tz = "'%s'" % tz
284+
attrs.append(('tz',tz))
285+
return attrs
292286

293287
@cache_readonly
294288
def _resolution(self):

pandas/tseries/index.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ def _is_dates_only(self):
597597
def _formatter_func(self):
598598
from pandas.core.format import _get_format_datetime64
599599
formatter = _get_format_datetime64(is_dates_only=self._is_dates_only)
600-
return lambda x: formatter(x, tz=self.tz)
600+
return lambda x: "'%s'" % formatter(x, tz=self.tz)
601601

602602
def __reduce__(self):
603603

@@ -684,10 +684,6 @@ def _format_native_types(self, na_rep=u('NaT'),
684684
def to_datetime(self, dayfirst=False):
685685
return self.copy()
686686

687-
def _format_footer(self):
688-
tagline = 'Length: %d, Freq: %s, Timezone: %s'
689-
return tagline % (len(self), self.freqstr, self.tz)
690-
691687
def astype(self, dtype):
692688
dtype = np.dtype(dtype)
693689

pandas/tseries/period.py

-4
Original file line numberDiff line numberDiff line change
@@ -697,10 +697,6 @@ def __array_finalize__(self, obj):
697697
self.name = getattr(obj, 'name', None)
698698
self._reset_identity()
699699

700-
def _format_footer(self):
701-
tagline = 'Length: %d, Freq: %s'
702-
return tagline % (len(self), self.freqstr)
703-
704700
def take(self, indices, axis=None):
705701
"""
706702
Analogous to ndarray.take

pandas/tseries/tdi.py

-4
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,6 @@ def _formatter_func(self):
274274
from pandas.core.format import _get_format_timedelta64
275275
return _get_format_timedelta64(self, box=True)
276276

277-
def _format_footer(self):
278-
tagline = 'Length: %d, Freq: %s'
279-
return tagline % (len(self), self.freqstr)
280-
281277
def __setstate__(self, state):
282278
"""Necessary for making this object picklable"""
283279
if isinstance(state, dict):

0 commit comments

Comments
 (0)