Skip to content

Commit 8a9b0f5

Browse files
authored
DEPR: enforce deprecation of DTI/TDI unused keywords (#58003)
* DEPR: enforce deprecation of DTI/TDI unused keywords * update docstring * un-xfail (i think) code check
1 parent 09fd5e0 commit 8a9b0f5

File tree

7 files changed

+23
-135
lines changed

7 files changed

+23
-135
lines changed

ci/code_checks.sh

-1
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
504504
-i "pandas.Timedelta.to_timedelta64 SA01" \
505505
-i "pandas.Timedelta.total_seconds SA01" \
506506
-i "pandas.Timedelta.view SA01" \
507-
-i "pandas.TimedeltaIndex PR01" \
508507
-i "pandas.TimedeltaIndex.as_unit RT03,SA01" \
509508
-i "pandas.TimedeltaIndex.ceil SA01" \
510509
-i "pandas.TimedeltaIndex.components SA01" \

doc/source/whatsnew/v3.0.0.rst

+2
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ Removal of prior version deprecations/changes
197197
- :meth:`SeriesGroupBy.agg` no longer pins the name of the group to the input passed to the provided ``func`` (:issue:`51703`)
198198
- All arguments except ``name`` in :meth:`Index.rename` are now keyword only (:issue:`56493`)
199199
- All arguments except the first ``path``-like argument in IO writers are now keyword only (:issue:`54229`)
200+
- Removed the "closed" and "normalize" keywords in :meth:`DatetimeIndex.__new__` (:issue:`52628`)
201+
- Removed the "closed" and "unit" keywords in :meth:`TimedeltaIndex.__new__` (:issue:`52628`, :issue:`55499`)
200202
- All arguments in :meth:`Index.sort_values` are now keyword only (:issue:`56493`)
201203
- All arguments in :meth:`Series.to_dict` are now keyword only (:issue:`56493`)
202204
- Changed the default value of ``observed`` in :meth:`DataFrame.groupby` and :meth:`Series.groupby` to ``True`` (:issue:`51811`)

pandas/core/indexes/datetimes.py

-31
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
cache_readonly,
2929
doc,
3030
)
31-
from pandas.util._exceptions import find_stack_level
3231

3332
from pandas.core.dtypes.common import is_scalar
3433
from pandas.core.dtypes.dtypes import DatetimeTZDtype
@@ -150,17 +149,6 @@ class DatetimeIndex(DatetimeTimedeltaMixin):
150149
inferred frequency upon creation.
151150
tz : pytz.timezone or dateutil.tz.tzfile or datetime.tzinfo or str
152151
Set the Timezone of the data.
153-
normalize : bool, default False
154-
Normalize start/end dates to midnight before generating date range.
155-
156-
.. deprecated:: 2.1.0
157-
158-
closed : {'left', 'right'}, optional
159-
Set whether to include `start` and `end` that are on the
160-
boundary. The default includes boundary points on either end.
161-
162-
.. deprecated:: 2.1.0
163-
164152
ambiguous : 'infer', bool-ndarray, 'NaT', default 'raise'
165153
When clocks moved backward due to DST, ambiguous times may arise.
166154
For example in Central European Time (UTC+01), when going from 03:00
@@ -322,32 +310,13 @@ def __new__(
322310
data=None,
323311
freq: Frequency | lib.NoDefault = lib.no_default,
324312
tz=lib.no_default,
325-
normalize: bool | lib.NoDefault = lib.no_default,
326-
closed=lib.no_default,
327313
ambiguous: TimeAmbiguous = "raise",
328314
dayfirst: bool = False,
329315
yearfirst: bool = False,
330316
dtype: Dtype | None = None,
331317
copy: bool = False,
332318
name: Hashable | None = None,
333319
) -> Self:
334-
if closed is not lib.no_default:
335-
# GH#52628
336-
warnings.warn(
337-
f"The 'closed' keyword in {cls.__name__} construction is "
338-
"deprecated and will be removed in a future version.",
339-
FutureWarning,
340-
stacklevel=find_stack_level(),
341-
)
342-
if normalize is not lib.no_default:
343-
# GH#52628
344-
warnings.warn(
345-
f"The 'normalize' keyword in {cls.__name__} construction is "
346-
"deprecated and will be removed in a future version.",
347-
FutureWarning,
348-
stacklevel=find_stack_level(),
349-
)
350-
351320
if is_scalar(data):
352321
cls._raise_scalar_data_error(data)
353322

pandas/core/indexes/timedeltas.py

+1-34
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from __future__ import annotations
44

55
from typing import TYPE_CHECKING
6-
import warnings
76

87
from pandas._libs import (
98
index as libindex,
@@ -14,8 +13,6 @@
1413
Timedelta,
1514
to_offset,
1615
)
17-
from pandas._libs.tslibs.timedeltas import disallow_ambiguous_unit
18-
from pandas.util._exceptions import find_stack_level
1916

2017
from pandas.core.dtypes.common import (
2118
is_scalar,
@@ -63,12 +60,6 @@ class TimedeltaIndex(DatetimeTimedeltaMixin):
6360
----------
6461
data : array-like (1-dimensional), optional
6562
Optional timedelta-like data to construct index with.
66-
unit : {'D', 'h', 'm', 's', 'ms', 'us', 'ns'}, optional
67-
The unit of ``data``.
68-
69-
.. deprecated:: 2.2.0
70-
Use ``pd.to_timedelta`` instead.
71-
7263
freq : str or pandas offset object, optional
7364
One of pandas date offset strings or corresponding objects. The string
7465
``'infer'`` can be passed in order to set the frequency of the index as
@@ -151,40 +142,16 @@ def _resolution_obj(self) -> Resolution | None: # type: ignore[override]
151142
def __new__(
152143
cls,
153144
data=None,
154-
unit=lib.no_default,
155145
freq=lib.no_default,
156-
closed=lib.no_default,
157146
dtype=None,
158147
copy: bool = False,
159148
name=None,
160149
):
161-
if closed is not lib.no_default:
162-
# GH#52628
163-
warnings.warn(
164-
f"The 'closed' keyword in {cls.__name__} construction is "
165-
"deprecated and will be removed in a future version.",
166-
FutureWarning,
167-
stacklevel=find_stack_level(),
168-
)
169-
170-
if unit is not lib.no_default:
171-
# GH#55499
172-
warnings.warn(
173-
f"The 'unit' keyword in {cls.__name__} construction is "
174-
"deprecated and will be removed in a future version. "
175-
"Use pd.to_timedelta instead.",
176-
FutureWarning,
177-
stacklevel=find_stack_level(),
178-
)
179-
else:
180-
unit = None
181-
182150
name = maybe_extract_name(name, data, cls)
183151

184152
if is_scalar(data):
185153
cls._raise_scalar_data_error(data)
186154

187-
disallow_ambiguous_unit(unit)
188155
if dtype is not None:
189156
dtype = pandas_dtype(dtype)
190157

@@ -211,7 +178,7 @@ def __new__(
211178
# - Cases checked above all return/raise before reaching here - #
212179

213180
tdarr = TimedeltaArray._from_sequence_not_strict(
214-
data, freq=freq, unit=unit, dtype=dtype, copy=copy
181+
data, freq=freq, unit=None, dtype=dtype, copy=copy
215182
)
216183
refs = None
217184
if not copy and isinstance(data, (ABCSeries, Index)):

pandas/tests/indexes/datetimes/test_constructors.py

-12
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,6 @@
3535

3636

3737
class TestDatetimeIndex:
38-
def test_closed_deprecated(self):
39-
# GH#52628
40-
msg = "The 'closed' keyword"
41-
with tm.assert_produces_warning(FutureWarning, match=msg):
42-
DatetimeIndex([], closed=True)
43-
44-
def test_normalize_deprecated(self):
45-
# GH#52628
46-
msg = "The 'normalize' keyword"
47-
with tm.assert_produces_warning(FutureWarning, match=msg):
48-
DatetimeIndex([], normalize=True)
49-
5038
def test_from_dt64_unsupported_unit(self):
5139
# GH#49292
5240
val = np.datetime64(1, "D")

pandas/tests/indexes/timedeltas/test_constructors.py

-33
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,6 @@
1515

1616

1717
class TestTimedeltaIndex:
18-
def test_closed_deprecated(self):
19-
# GH#52628
20-
msg = "The 'closed' keyword"
21-
with tm.assert_produces_warning(FutureWarning, match=msg):
22-
TimedeltaIndex([], closed=True)
23-
2418
def test_array_of_dt64_nat_raises(self):
2519
# GH#39462
2620
nat = np.datetime64("NaT", "ns")
@@ -36,14 +30,6 @@ def test_array_of_dt64_nat_raises(self):
3630
with pytest.raises(TypeError, match=msg):
3731
to_timedelta(arr)
3832

39-
@pytest.mark.parametrize("unit", ["Y", "y", "M"])
40-
def test_unit_m_y_raises(self, unit):
41-
msg = "Units 'M', 'Y', and 'y' are no longer supported"
42-
depr_msg = "The 'unit' keyword in TimedeltaIndex construction is deprecated"
43-
with pytest.raises(ValueError, match=msg):
44-
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
45-
TimedeltaIndex([1, 3, 7], unit)
46-
4733
def test_int64_nocopy(self):
4834
# GH#23539 check that a copy isn't made when we pass int64 data
4935
# and copy=False
@@ -138,9 +124,6 @@ def test_construction_base_constructor(self):
138124
tm.assert_index_equal(pd.Index(arr), TimedeltaIndex(arr))
139125
tm.assert_index_equal(pd.Index(np.array(arr)), TimedeltaIndex(np.array(arr)))
140126

141-
@pytest.mark.filterwarnings(
142-
"ignore:The 'unit' keyword in TimedeltaIndex construction:FutureWarning"
143-
)
144127
def test_constructor(self):
145128
expected = TimedeltaIndex(
146129
[
@@ -162,22 +145,6 @@ def test_constructor(self):
162145
)
163146
tm.assert_index_equal(result, expected)
164147

165-
expected = TimedeltaIndex(
166-
["0 days 00:00:00", "0 days 00:00:01", "0 days 00:00:02"]
167-
)
168-
result = TimedeltaIndex(range(3), unit="s")
169-
tm.assert_index_equal(result, expected)
170-
expected = TimedeltaIndex(
171-
["0 days 00:00:00", "0 days 00:00:05", "0 days 00:00:09"]
172-
)
173-
result = TimedeltaIndex([0, 5, 9], unit="s")
174-
tm.assert_index_equal(result, expected)
175-
expected = TimedeltaIndex(
176-
["0 days 00:00:00.400", "0 days 00:00:00.450", "0 days 00:00:01.200"]
177-
)
178-
result = TimedeltaIndex([400, 450, 1200], unit="ms")
179-
tm.assert_index_equal(result, expected)
180-
181148
def test_constructor_iso(self):
182149
# GH #21877
183150
expected = timedelta_range("1s", periods=9, freq="s")

pandas/tests/scalar/timedelta/test_constructors.py

+20-24
Original file line numberDiff line numberDiff line change
@@ -126,30 +126,26 @@ def test_unit_parser(self, unit, np_unit, wrapper):
126126
)
127127
# TODO(2.0): the desired output dtype may have non-nano resolution
128128

129-
msg = "The 'unit' keyword in TimedeltaIndex construction is deprecated"
130-
with tm.assert_produces_warning(FutureWarning, match=msg):
131-
result = to_timedelta(wrapper(range(5)), unit=unit)
132-
tm.assert_index_equal(result, expected)
133-
result = TimedeltaIndex(wrapper(range(5)), unit=unit)
134-
tm.assert_index_equal(result, expected)
135-
136-
str_repr = [f"{x}{unit}" for x in np.arange(5)]
137-
result = to_timedelta(wrapper(str_repr))
138-
tm.assert_index_equal(result, expected)
139-
result = to_timedelta(wrapper(str_repr))
140-
tm.assert_index_equal(result, expected)
141-
142-
# scalar
143-
expected = Timedelta(np.timedelta64(2, np_unit).astype("timedelta64[ns]"))
144-
result = to_timedelta(2, unit=unit)
145-
assert result == expected
146-
result = Timedelta(2, unit=unit)
147-
assert result == expected
148-
149-
result = to_timedelta(f"2{unit}")
150-
assert result == expected
151-
result = Timedelta(f"2{unit}")
152-
assert result == expected
129+
result = to_timedelta(wrapper(range(5)), unit=unit)
130+
tm.assert_index_equal(result, expected)
131+
132+
str_repr = [f"{x}{unit}" for x in np.arange(5)]
133+
result = to_timedelta(wrapper(str_repr))
134+
tm.assert_index_equal(result, expected)
135+
result = to_timedelta(wrapper(str_repr))
136+
tm.assert_index_equal(result, expected)
137+
138+
# scalar
139+
expected = Timedelta(np.timedelta64(2, np_unit).astype("timedelta64[ns]"))
140+
result = to_timedelta(2, unit=unit)
141+
assert result == expected
142+
result = Timedelta(2, unit=unit)
143+
assert result == expected
144+
145+
result = to_timedelta(f"2{unit}")
146+
assert result == expected
147+
result = Timedelta(f"2{unit}")
148+
assert result == expected
153149

154150
@pytest.mark.parametrize("unit", ["T", "t", "L", "l", "U", "u", "N", "n"])
155151
def test_unit_T_L_N_U_raises(self, unit):

0 commit comments

Comments
 (0)