Skip to content

Commit eb6f368

Browse files
Liam3851jorisvandenbossche
authored andcommitted
BUG: Fix Index construction when given empty generator (#21470). (#21481)
(cherry picked from commit 076635a)
1 parent 76551c2 commit eb6f368

File tree

4 files changed

+21
-16
lines changed

4 files changed

+21
-16
lines changed

doc/source/whatsnew/v0.23.2.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ Bug Fixes
4949

5050
**Conversion**
5151

52+
- Bug in constructing :class:`Index` with an iterator or generator (:issue:`21470`)
5253
- Bug in :meth:`Series.nlargest` for signed and unsigned integer dtypes when the minimum value is present (:issue:`21426`)
53-
-
54+
5455

5556
**Indexing**
5657

pandas/core/arrays/categorical.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import numpy as np
44
from warnings import warn
55
import textwrap
6-
import types
76

87
from pandas import compat
98
from pandas.compat import u, lzip
@@ -28,7 +27,7 @@
2827
is_categorical,
2928
is_categorical_dtype,
3029
is_list_like, is_sequence,
31-
is_scalar,
30+
is_scalar, is_iterator,
3231
is_dict_like)
3332

3433
from pandas.core.algorithms import factorize, take_1d, unique1d, take
@@ -2473,7 +2472,7 @@ def _convert_to_list_like(list_like):
24732472
if isinstance(list_like, list):
24742473
return list_like
24752474
if (is_sequence(list_like) or isinstance(list_like, tuple) or
2476-
isinstance(list_like, types.GeneratorType)):
2475+
is_iterator(list_like)):
24772476
return list(list_like)
24782477
elif is_scalar(list_like):
24792478
return [list_like]

pandas/core/indexes/base.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -436,12 +436,14 @@ def __new__(cls, data=None, dtype=None, copy=False, name=None,
436436
elif data is None or is_scalar(data):
437437
cls._scalar_data_error(data)
438438
else:
439-
if tupleize_cols and is_list_like(data) and data:
439+
if tupleize_cols and is_list_like(data):
440+
# GH21470: convert iterable to list before determining if empty
440441
if is_iterator(data):
441442
data = list(data)
442-
# we must be all tuples, otherwise don't construct
443-
# 10697
444-
if all(isinstance(e, tuple) for e in data):
443+
444+
if data and all(isinstance(e, tuple) for e in data):
445+
# we must be all tuples, otherwise don't construct
446+
# 10697
445447
from .multi import MultiIndex
446448
return MultiIndex.from_tuples(
447449
data, names=name or kwargs.get('names'))

pandas/tests/indexes/test_base.py

+11-8
Original file line numberDiff line numberDiff line change
@@ -419,21 +419,24 @@ def test_constructor_dtypes_timedelta(self, attr, klass):
419419
result = klass(list(values), dtype=dtype)
420420
tm.assert_index_equal(result, index)
421421

422-
def test_constructor_empty_gen(self):
423-
skip_index_keys = ["repeats", "periodIndex", "rangeIndex",
424-
"tuples"]
425-
for key, index in self.generate_index_types(skip_index_keys):
426-
empty = index.__class__([])
427-
assert isinstance(empty, index.__class__)
428-
assert not len(empty)
422+
@pytest.mark.parametrize("value", [[], iter([]), (x for x in [])])
423+
@pytest.mark.parametrize("klass",
424+
[Index, Float64Index, Int64Index, UInt64Index,
425+
CategoricalIndex, DatetimeIndex, TimedeltaIndex])
426+
def test_constructor_empty(self, value, klass):
427+
empty = klass(value)
428+
assert isinstance(empty, klass)
429+
assert not len(empty)
429430

430431
@pytest.mark.parametrize("empty,klass", [
431432
(PeriodIndex([], freq='B'), PeriodIndex),
433+
(PeriodIndex(iter([]), freq='B'), PeriodIndex),
434+
(PeriodIndex((x for x in []), freq='B'), PeriodIndex),
432435
(RangeIndex(step=1), pd.RangeIndex),
433436
(MultiIndex(levels=[[1, 2], ['blue', 'red']],
434437
labels=[[], []]), MultiIndex)
435438
])
436-
def test_constructor_empty(self, empty, klass):
439+
def test_constructor_empty_special(self, empty, klass):
437440
assert isinstance(empty, klass)
438441
assert not len(empty)
439442

0 commit comments

Comments
 (0)