Skip to content

Commit ce1205e

Browse files
authored
REGR: CategoricalIndex(None) (#41612)
1 parent 1c22786 commit ce1205e

File tree

8 files changed

+38
-13
lines changed

8 files changed

+38
-13
lines changed

doc/source/whatsnew/v1.3.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ Build
655655
Deprecations
656656
~~~~~~~~~~~~
657657
- Deprecated allowing scalars to be passed to the :class:`Categorical` constructor (:issue:`38433`)
658+
- Deprecated constructing :class:`CategoricalIndex` without passing list-like data (:issue:`38944`)
658659
- Deprecated allowing subclass-specific keyword arguments in the :class:`Index` constructor, use the specific subclass directly instead (:issue:`14093`, :issue:`21311`, :issue:`22315`, :issue:`26974`)
659660
- Deprecated ``astype`` of datetimelike (``timedelta64[ns]``, ``datetime64[ns]``, ``Datetime64TZDtype``, ``PeriodDtype``) to integer dtypes, use ``values.view(...)`` instead (:issue:`38544`)
660661
- Deprecated :meth:`MultiIndex.is_lexsorted` and :meth:`MultiIndex.lexsort_depth`, use :meth:`MultiIndex.is_monotonic_increasing` instead (:issue:`32259`)

pandas/core/indexes/category.py

+11
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,17 @@ def __new__(
222222

223223
name = maybe_extract_name(name, data, cls)
224224

225+
if data is None:
226+
# GH#38944
227+
warnings.warn(
228+
"Constructing a CategoricalIndex without passing data is "
229+
"deprecated and will raise in a future version. "
230+
"Use CategoricalIndex([], ...) instead",
231+
FutureWarning,
232+
stacklevel=2,
233+
)
234+
data = []
235+
225236
if is_scalar(data):
226237
raise cls._scalar_data_error(data)
227238

pandas/tests/indexes/categorical/test_category.py

+5
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ def test_can_hold_identifiers(self):
3838
key = idx[0]
3939
assert idx._can_hold_identifiers_and_holds_name(key) is True
4040

41+
def test_pickle_compat_construction(self):
42+
# Once the deprecation is enforced, we can use the parent class's test
43+
with tm.assert_produces_warning(FutureWarning, match="without passing data"):
44+
self._index_cls()
45+
4146
def test_insert(self, simple_index):
4247

4348
ci = simple_index

pandas/tests/indexes/categorical/test_constructors.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,17 @@
1111

1212

1313
class TestCategoricalIndexConstructors:
14+
def test_construction_without_data_deprecated(self):
15+
# Once the deprecation is enforced, we can add this case to
16+
# test_construction_disallows_scalar
17+
msg = "without passing data"
18+
with tm.assert_produces_warning(FutureWarning, match=msg):
19+
CategoricalIndex(categories=list("abcd"), ordered=False)
20+
1421
def test_construction_disallows_scalar(self):
1522
msg = "must be called with a collection of some kind"
1623
with pytest.raises(TypeError, match=msg):
17-
CategoricalIndex(categories=list("abcd"), ordered=False)
24+
CategoricalIndex(data=1, categories=list("abcd"), ordered=False)
1825

1926
def test_construction(self):
2027

pandas/tests/indexes/common.py

+11-5
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,17 @@ def create_index(self) -> Index:
4747

4848
def test_pickle_compat_construction(self):
4949
# need an object to create with
50-
msg = (
51-
r"Index\(\.\.\.\) must be called with a collection of some "
52-
r"kind, None was passed|"
53-
r"__new__\(\) missing 1 required positional argument: 'data'|"
54-
r"__new__\(\) takes at least 2 arguments \(1 given\)"
50+
msg = "|".join(
51+
[
52+
r"Index\(\.\.\.\) must be called with a collection of some "
53+
r"kind, None was passed",
54+
r"DatetimeIndex\(\) must be called with a collection of some "
55+
r"kind, None was passed",
56+
r"TimedeltaIndex\(\) must be called with a collection of some "
57+
r"kind, None was passed",
58+
r"__new__\(\) missing 1 required positional argument: 'data'",
59+
r"__new__\(\) takes at least 2 arguments \(1 given\)",
60+
]
5561
)
5662
with pytest.raises(TypeError, match=msg):
5763
self._index_cls()

pandas/tests/indexes/datetimes/test_datetimelike.py

-3
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ def test_format(self, simple_index):
3232
def test_shift(self):
3333
pass # handled in test_ops
3434

35-
def test_pickle_compat_construction(self):
36-
pass
37-
3835
def test_intersection(self):
3936
pass # handled in test_setops
4037

pandas/tests/indexes/period/test_period.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ def simple_index(self) -> Index:
3535
def index(self, request):
3636
return request.param
3737

38+
@pytest.mark.xfail(reason="Goes through a generate_range path")
3839
def test_pickle_compat_construction(self):
39-
pass
40+
super().test_pickle_compat_construction()
4041

4142
@pytest.mark.parametrize("freq", ["D", "M", "A"])
4243
def test_pickle_round_trip(self, freq):

pandas/tests/indexes/timedeltas/test_timedelta.py

-3
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ def test_numeric_compat(self):
4242
def test_shift(self):
4343
pass # this is handled in test_arithmetic.py
4444

45-
def test_pickle_compat_construction(self):
46-
pass
47-
4845
def test_pickle_after_set_freq(self):
4946
tdi = timedelta_range("1 day", periods=4, freq="s")
5047
tdi = tdi._with_freq(None)

0 commit comments

Comments
 (0)