diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index c04de6fd071b7..bb10d421913a8 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -749,6 +749,7 @@ Indexing - Bug in :meth:`MultiIndex.insert` when a new value inserted to a datetime-like level gets cast to ``NaT`` and fails indexing (:issue:`60388`) - Bug in printing :attr:`Index.names` and :attr:`MultiIndex.levels` would not escape single quotes (:issue:`60190`) - Bug in reindexing of :class:`DataFrame` with :class:`PeriodDtype` columns in case of consolidated block (:issue:`60980`, :issue:`60273`) +- Bug in creating :class:`Index` with one item being a ``list`` among others thar aren't (should raise ValueError) (:issue:`60925`) Missing ^^^^^^^ diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 4e1ea07907cdb..26b36bfb92804 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -567,6 +567,13 @@ def __new__( # Ensure we get 1-D array of tuples instead of 2D array. data = com.asarray_tuplesafe(data, dtype=_dtype_obj) + #60925 should raise when one of index's items is a list and others are not + if (any(isinstance(el, list) for el in data) and + not all(isinstance(el, list) for el in data)): + raise ValueError( + "Index names must all be hashable, or all lists to make MultiIndex" + ) + try: arr = sanitize_array(data, None, dtype=dtype, copy=copy) except ValueError as err: diff --git a/pandas/tests/frame/test_repr.py b/pandas/tests/frame/test_repr.py index 73628424725e5..c9a0f09579b6d 100644 --- a/pandas/tests/frame/test_repr.py +++ b/pandas/tests/frame/test_repr.py @@ -71,9 +71,12 @@ def test_assign_index_sequences(self): repr(df) # this travels an improper code path + # #60925 should raise when one of index's items is a list and others are not index[0] = ["faz", "boo"] - df.index = index - repr(df) + msg = "Index names must all be hashable, or all lists to make MultiIndex" + with pytest.raises(ValueError, match=msg): + df.index = index + repr(df) def test_repr_with_mi_nat(self): df = DataFrame({"X": [1, 2]}, index=[[NaT, Timestamp("20130101")], ["a", "b"]]) diff --git a/pandas/tests/indexes/test_index_new.py b/pandas/tests/indexes/test_index_new.py index dd228e6b713b5..5e4bd3c0af7ab 100644 --- a/pandas/tests/indexes/test_index_new.py +++ b/pandas/tests/indexes/test_index_new.py @@ -188,6 +188,17 @@ def test_constructor_datetimes_mixed_tzs(self): expected = Index([dt1, dt2], dtype=object) tm.assert_index_equal(result, expected) + def test_constructor_list_between_elems(self): + # #60925 should raise when one of index's items is a list and others are not + msg = "Index names must all be hashable, or all lists to make MultiIndex" + + data = ['a', ['b', 'c'], ['b', 'c']] + with pytest.raises(ValueError, match=msg): + Index(data) + + data = [['b', 'c'], ('b', 'c')] + with pytest.raises(ValueError, match=msg): + Index(data) class TestDtypeEnforced: # check we don't silently ignore the dtype keyword