Skip to content

Commit 076635a

Browse files
Liam3851jreback
authored andcommitted
BUG: Fix Index construction when given empty generator (#21470). (#21481)
1 parent d5a1232 commit 076635a

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
@@ -52,8 +52,9 @@ Bug Fixes
5252

5353
**Conversion**
5454

55+
- Bug in constructing :class:`Index` with an iterator or generator (:issue:`21470`)
5556
- Bug in :meth:`Series.nlargest` for signed and unsigned integer dtypes when the minimum value is present (:issue:`21426`)
56-
-
57+
5758

5859
**Indexing**
5960

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
@@ -2483,7 +2482,7 @@ def _convert_to_list_like(list_like):
24832482
if isinstance(list_like, list):
24842483
return list_like
24852484
if (is_sequence(list_like) or isinstance(list_like, tuple) or
2486-
isinstance(list_like, types.GeneratorType)):
2485+
is_iterator(list_like)):
24872486
return list(list_like)
24882487
elif is_scalar(list_like):
24892488
return [list_like]

pandas/core/indexes/base.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -428,12 +428,14 @@ def __new__(cls, data=None, dtype=None, copy=False, name=None,
428428
elif data is None or is_scalar(data):
429429
cls._scalar_data_error(data)
430430
else:
431-
if tupleize_cols and is_list_like(data) and data:
431+
if tupleize_cols and is_list_like(data):
432+
# GH21470: convert iterable to list before determining if empty
432433
if is_iterator(data):
433434
data = list(data)
434-
# we must be all tuples, otherwise don't construct
435-
# 10697
436-
if all(isinstance(e, tuple) for e in data):
435+
436+
if data and all(isinstance(e, tuple) for e in data):
437+
# we must be all tuples, otherwise don't construct
438+
# 10697
437439
from .multi import MultiIndex
438440
return MultiIndex.from_tuples(
439441
data, names=name or kwargs.get('names'))

pandas/tests/indexes/test_base.py

+11-8
Original file line numberDiff line numberDiff line change
@@ -445,21 +445,24 @@ def test_constructor_dtypes_timedelta(self, attr, klass):
445445
result = klass(list(values), dtype=dtype)
446446
tm.assert_index_equal(result, index)
447447

448-
def test_constructor_empty_gen(self):
449-
skip_index_keys = ["repeats", "periodIndex", "rangeIndex",
450-
"tuples"]
451-
for key, index in self.generate_index_types(skip_index_keys):
452-
empty = index.__class__([])
453-
assert isinstance(empty, index.__class__)
454-
assert not len(empty)
448+
@pytest.mark.parametrize("value", [[], iter([]), (x for x in [])])
449+
@pytest.mark.parametrize("klass",
450+
[Index, Float64Index, Int64Index, UInt64Index,
451+
CategoricalIndex, DatetimeIndex, TimedeltaIndex])
452+
def test_constructor_empty(self, value, klass):
453+
empty = klass(value)
454+
assert isinstance(empty, klass)
455+
assert not len(empty)
455456

456457
@pytest.mark.parametrize("empty,klass", [
457458
(PeriodIndex([], freq='B'), PeriodIndex),
459+
(PeriodIndex(iter([]), freq='B'), PeriodIndex),
460+
(PeriodIndex((x for x in []), freq='B'), PeriodIndex),
458461
(RangeIndex(step=1), pd.RangeIndex),
459462
(MultiIndex(levels=[[1, 2], ['blue', 'red']],
460463
labels=[[], []]), MultiIndex)
461464
])
462-
def test_constructor_empty(self, empty, klass):
465+
def test_constructor_empty_special(self, empty, klass):
463466
assert isinstance(empty, klass)
464467
assert not len(empty)
465468

0 commit comments

Comments
 (0)