Skip to content

BUG: MultiIndex.isin raising TypeError on iterator elements - #66540

Open
guptaishaan wants to merge 1 commit into
pandas-dev:mainfrom
guptaishaan:fix-66514
Open

BUG: MultiIndex.isin raising TypeError on iterator elements#66540
guptaishaan wants to merge 1 commit into
pandas-dev:mainfrom
guptaishaan:fix-66514

Conversation

@guptaishaan

Copy link
Copy Markdown

Fixes #66514

The MultiIndex.isin validation loop added for GH#20252 / GH#26622 calls len(value)
on anything is_list_like accepts, but that includes iterators, which have no
__len__. Elements that are iterators used to reach MultiIndex.from_tuples, which
handled them; now they raise TypeError: object of type 'list_iterator' has no len()
first.

Fix: materialize iterator elements with tuple(...) before the loop, so they can be
length-checked and are still intact when from_tuples consumes them. is_iterator
was already imported in the module.

Verified on Linux, CPython 3.13, numpy 2.4, built from this branch with meson-python:

  • Reproduced first on the nightly named in the issue (3.1.0.dev0+1420.g7986b42596),
    whose multi.py is byte-identical to current main.
  • mi.isin({iter([3])}) now returns [False False True], the same as released 3.0.3.
  • New tests fail on main with the reported TypeError and pass with the patch.
  • pandas/tests/indexes/ (16517 passed), every -k isin test in the repo (471
    passed), and the multi.py doctests all pass. ruff check and ruff format clean.

One side effect worth flagging. Replacing values with a list changes which branch of
from_tuples handles an ndarray argument, so mi.isin(np.array([[1, "a"], [3, "c"]]))
now behaves like the equivalent list of rows instead of raising ValueError: Buffer has wrong number of dimensions. Only inputs that previously raised are affected, nothing
that returned a result changes. Happy to add an if any(is_iterator(v) for v in values): guard if you would rather keep that error path.

No whatsnew entry: the regression is unreleased, it arrived with the 3.1.0 entry for
GH#20252 / GH#26622.

Not verified: full test suite, mypy/pyright, non-ruff pre-commit hooks.

Thanks to @loicdiridollou for the report and the minimal reproducer.

The validation loop added for GH#20252 / GH#26622 calls len(value) on
anything is_list_like accepts, but that includes iterators, which have no
__len__. Elements that are iterators used to reach MultiIndex.from_tuples,
which handled them; now they raise "object of type 'list_iterator' has no
len()" first.

Materialize iterator elements with tuple() before the loop, so they can be
length-checked and are still intact when from_tuples consumes them.

Side effect: values is now always a list at that point, so an ndarray
argument goes through to_object_array_tuples rather than
tuples_to_object_array. 2-D ndarray arguments, which previously raised a
buffer error, now behave like the equivalent list of rows. No input that
previously returned a result changes.

Closes pandas-dev#66514
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: object of type 'list_iterator' has no len()

1 participant