Skip to content

BUG: Fix Index.__repr__ when display.max_seq_items = 1 #38443

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Dec 28, 2020
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.3.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ MultiIndex
I/O
^^^

- Bug in :meth:`Index.__repr__` when ``display.max_seq_items=1`` (:issue:`38415`)
- Bug in :func:`read_csv` interpreting ``NA`` value as comment, when ``NA`` does contain the comment string fixed for ``engine="python"`` (:issue:`34002`)
- Bug in :func:`read_csv` raising ``IndexError`` with multiple header columns and ``index_col`` specified when file has no data rows (:issue:`38292`)
- Bug in :func:`read_csv` not accepting ``usecols`` with different length than ``names`` for ``engine="python"`` (:issue:`16469`)
Expand Down
6 changes: 5 additions & 1 deletion pandas/io/formats/printing.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,11 @@ def best_len(values: List[str]) -> int:
summary = f"[{first}, {last}]{close}"
else:

if n > max_seq_items:
if max_seq_items == 1:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you also cover in a test the max_seq_items == 0 case (I think we have this but maybe not). Also pls confirm that we have a test for n == max_seq_items.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we don't have a test for n == max_seq_items. Will cover these in my tests.

Just wanted to confirm that this is the relevant location for adding these?

def test_repr(self, idx):
result = idx[:1].__repr__()
expected = """\
MultiIndex([('foo', 'one')],
names=['first', 'second'])"""
assert result == expected
result = idx.__repr__()
expected = """\
MultiIndex([('foo', 'one'),
('foo', 'two'),
('bar', 'one'),
('baz', 'two'),
('qux', 'one'),
('qux', 'two')],
names=['first', 'second'])"""
assert result == expected
with pd.option_context("display.max_seq_items", 5):
result = idx.__repr__()
expected = """\
MultiIndex([('foo', 'one'),
('foo', 'two'),
...
('qux', 'one'),
('qux', 'two')],
names=['first', 'second'], length=6)"""
assert result == expected

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah there plus some generic Index ones (look in pandas/tests/indexes/); you may have to grep around a bit

e.g.

~/pandas-dev$ grep -r max_seq_items pandas/tests/
pandas/tests/io/formats/test_format.py:        with option_context("display.max_seq_items", 2000):
pandas/tests/io/formats/test_format.py:        with option_context("display.max_seq_items", 5):
pandas/tests/groupby/test_groupby.py:    "max_seq_items, expected",
pandas/tests/groupby/test_groupby.py:def test_groups_repr_truncates(max_seq_items, expected):
pandas/tests/groupby/test_groupby.py:    with pd.option_context("display.max_seq_items", max_seq_items):
pandas/tests/indexes/multi/test_formats.py:    with pd.option_context("display.max_seq_items", None):
pandas/tests/indexes/multi/test_formats.py:        with pd.option_context("display.max_seq_items", 5):
pandas/tests/indexes/common.py:        with pd.option_context("display.max_seq_items", None):
pandas/tests/indexes/base_class/test_formats.py:        with cf.option_context("display.max_seq_items", 10):

i think pandas/tests/indexes/base_class/test_formats.py: with cf.option_context("display.max_seq_items", 10):
has a number of tests as well

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have a case of max_seq_items==0 ? (I think this is a valid value), < 0 is restricted i am pretty sure?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we do. Max_seq_items ==0 implies unlimited if I'm not mistaken

# If max_seq_items=1 show only last element
head = []
tail = [formatter(x) for x in obj[-1:]]
elif n > max_seq_items:
n = min(max_seq_items // 2, 10)
head = [formatter(x) for x in obj[:n]]
tail = [formatter(x) for x in obj[-n:]]
Expand Down
1 change: 1 addition & 0 deletions pandas/tests/groupby/test_groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -2058,6 +2058,7 @@ def test_groupby_list_level():
[
(5, "{0: [0], 1: [1], 2: [2], 3: [3], 4: [4]}"),
(4, "{0: [0], 1: [1], 2: [2], 3: [3], ...}"),
(1, "{0: [0], ...}"),
],
)
def test_groups_repr_truncates(max_seq_items, expected):
Expand Down
23 changes: 23 additions & 0 deletions pandas/tests/indexes/multi/test_formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,20 @@ def test_unicode_repr_issues(self):
# NumPy bug
# repr(index.get_level_values(1))

def test_repr_max_seq_items_equal_to_n(self, idx):
# display.max_seq_items == n
with pd.option_context("display.max_seq_items", 6):
result = idx.__repr__()
expected = """\
MultiIndex([('foo', 'one'),
('foo', 'two'),
('bar', 'one'),
('baz', 'two'),
('qux', 'one'),
('qux', 'two')],
names=['first', 'second'])"""
assert result == expected

def test_repr(self, idx):
result = idx[:1].__repr__()
expected = """\
Expand Down Expand Up @@ -118,6 +132,15 @@ def test_repr(self, idx):
names=['first', 'second'], length=6)"""
assert result == expected

# display.max_seq_items == 1
with pd.option_context("display.max_seq_items", 1):
result = idx.__repr__()
expected = """\
MultiIndex([...
('qux', 'two')],
names=['first', ...], length=6)"""
assert result == expected

def test_rjust(self, narrow_multi_index):
mi = narrow_multi_index
result = mi[:1].__repr__()
Expand Down
3 changes: 3 additions & 0 deletions pandas/tests/io/formats/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@ def test_repr_obeys_max_seq_limit(self):
with option_context("display.max_seq_items", 5):
assert len(printing.pprint_thing(list(range(1000)))) < 100

with option_context("display.max_seq_items", 1):
assert len(printing.pprint_thing(list(range(1000)))) < 9

def test_repr_set(self):
assert printing.pprint_thing({1}) == "{1}"

Expand Down