Skip to content

Commit efaa11e

Browse files
DEPR: to_pydatetime return Index[object] (#52459)
* DEPR: to_pydatetime return Index[object] * fix pyarrow case * suppress doctest warning * typo fixup * deprecate for arrow case * suppress warning * call np.asarray * Update pandas/io/sql.py Co-authored-by: Matthew Roeschke <[email protected]> --------- Co-authored-by: Matthew Roeschke <[email protected]>
1 parent 4d6ca9d commit efaa11e

File tree

7 files changed

+48
-5
lines changed

7 files changed

+48
-5
lines changed

Diff for: doc/source/whatsnew/v2.1.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ Deprecations
168168
- Deprecated 'broadcast_axis' keyword in :meth:`Series.align` and :meth:`DataFrame.align`, upcast before calling ``align`` with ``left = DataFrame({col: left for col in right.columns}, index=right.index)`` (:issue:`51856`)
169169
- Deprecated the 'axis' keyword in :meth:`.GroupBy.idxmax`, :meth:`.GroupBy.idxmin`, :meth:`.GroupBy.fillna`, :meth:`.GroupBy.take`, :meth:`.GroupBy.skew`, :meth:`.GroupBy.rank`, :meth:`.GroupBy.cumprod`, :meth:`.GroupBy.cumsum`, :meth:`.GroupBy.cummax`, :meth:`.GroupBy.cummin`, :meth:`.GroupBy.pct_change`, :meth:`GroupBy.diff`, :meth:`.GroupBy.shift`, and :meth:`DataFrameGroupBy.corrwith`; for ``axis=1`` operate on the underlying :class:`DataFrame` instead (:issue:`50405`, :issue:`51046`)
170170
- Deprecated the "fastpath" keyword in :class:`Categorical` constructor, use :meth:`Categorical.from_codes` instead (:issue:`20110`)
171+
- Deprecated behavior of :meth:`Series.dt.to_pydatetime`, in a future version this will return a :class:`Series` containing python ``datetime`` objects instead of an ``ndarray`` of datetimes; this matches the behavior of other :meth:`Series.dt` properties (:issue:`20306`)
171172
- Deprecated passing a dictionary to :meth:`.SeriesGroupBy.agg`; pass a list of aggregations instead (:issue:`50684`)
172173
- Deprecated logical operations (``|``, ``&``, ``^``) between pandas objects and dtype-less sequences (e.g. ``list``, ``tuple``), wrap a sequence in a :class:`Series` or numpy array before operating instead (:issue:`51521`)
173174
- Deprecated the methods :meth:`Series.bool` and :meth:`DataFrame.bool` (:issue:`51749`)

Diff for: pandas/conftest.py

+4
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ def pytest_collection_modifyitems(items, config) -> None:
137137
ignored_doctest_warnings = [
138138
# Docstring divides by zero to show behavior difference
139139
("missing.mask_zero_div_zero", "divide by zero encountered"),
140+
(
141+
"to_pydatetime",
142+
"The behavior of DatetimeProperties.to_pydatetime is deprecated",
143+
),
140144
(
141145
"pandas.core.generic.NDFrame.bool",
142146
"(Series|DataFrame).bool is now deprecated and will be removed "

Diff for: pandas/core/indexes/accessors.py

+21
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
TYPE_CHECKING,
88
cast,
99
)
10+
import warnings
1011

1112
import numpy as np
1213

14+
from pandas.util._exceptions import find_stack_level
15+
1316
from pandas.core.dtypes.common import (
1417
is_datetime64_dtype,
1518
is_integer_dtype,
@@ -214,6 +217,15 @@ def _delegate_method(self, name: str, *args, **kwargs):
214217
return result
215218

216219
def to_pydatetime(self):
220+
# GH#20306
221+
warnings.warn(
222+
f"The behavior of {type(self).__name__}.to_pydatetime is deprecated, "
223+
"in a future version this will return a Series containing python "
224+
"datetime objects instead of an ndarray. To retain the old behavior, "
225+
"call `np.array` on the result",
226+
FutureWarning,
227+
stacklevel=find_stack_level(),
228+
)
217229
return cast(ArrowExtensionArray, self._parent.array)._dt_to_pydatetime()
218230

219231
def isocalendar(self):
@@ -333,6 +345,15 @@ def to_pydatetime(self) -> np.ndarray:
333345
array([datetime.datetime(2018, 3, 10, 0, 0),
334346
datetime.datetime(2018, 3, 10, 0, 0)], dtype=object)
335347
"""
348+
# GH#20306
349+
warnings.warn(
350+
f"The behavior of {type(self).__name__}.to_pydatetime is deprecated, "
351+
"in a future version this will return a Series containing python "
352+
"datetime objects instead of an ndarray. To retain the old behavior, "
353+
"call `np.array` on the result",
354+
FutureWarning,
355+
stacklevel=find_stack_level(),
356+
)
336357
return self._get_values().to_pydatetime()
337358

338359
@property

Diff for: pandas/io/sql.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,13 @@ def insert_data(self) -> tuple[list[str], list[np.ndarray]]:
964964

965965
for i, (_, ser) in enumerate(temp.items()):
966966
if ser.dtype.kind == "M":
967-
d = ser.dt.to_pydatetime()
967+
if isinstance(ser._values, ArrowExtensionArray):
968+
with warnings.catch_warnings():
969+
warnings.filterwarnings("ignore", category=FutureWarning)
970+
# GH#52459 to_pydatetime will return Index[object]
971+
d = np.asarray(ser.dt.to_pydatetime(), dtype=object)
972+
else:
973+
d = ser._values.to_pydatetime()
968974
elif ser.dtype.kind == "m":
969975
vals = ser._values
970976
if isinstance(vals, ArrowExtensionArray):

Diff for: pandas/tests/extension/test_arrow.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -2287,12 +2287,16 @@ def test_dt_to_pydatetime():
22872287
data = [datetime(2022, 1, 1), datetime(2023, 1, 1)]
22882288
ser = pd.Series(data, dtype=ArrowDtype(pa.timestamp("ns")))
22892289

2290-
result = ser.dt.to_pydatetime()
2290+
msg = "The behavior of ArrowTemporalProperties.to_pydatetime is deprecated"
2291+
with tm.assert_produces_warning(FutureWarning, match=msg):
2292+
result = ser.dt.to_pydatetime()
22912293
expected = np.array(data, dtype=object)
22922294
tm.assert_numpy_array_equal(result, expected)
22932295
assert all(type(res) is datetime for res in result)
22942296

2295-
expected = ser.astype("datetime64[ns]").dt.to_pydatetime()
2297+
msg = "The behavior of DatetimeProperties.to_pydatetime is deprecated"
2298+
with tm.assert_produces_warning(FutureWarning, match=msg):
2299+
expected = ser.astype("datetime64[ns]").dt.to_pydatetime()
22962300
tm.assert_numpy_array_equal(result, expected)
22972301

22982302

Diff for: pandas/tests/series/accessors/test_cat_accessor.py

+3
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ def test_dt_accessor_api_for_categorical(self, idx):
203203
if func == "to_period":
204204
# dropping TZ
205205
warnings.simplefilter("ignore", UserWarning)
206+
if func == "to_pydatetime":
207+
# deprecated to return Index[object]
208+
warnings.simplefilter("ignore", FutureWarning)
206209
res = getattr(cat.dt, func)(*args, **kwargs)
207210
exp = getattr(ser.dt, func)(*args, **kwargs)
208211

Diff for: pandas/tests/series/accessors/test_dt_accessor.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ def test_dt_namespace_accessor_datetime64(self, freq):
115115
for prop in ok_for_dt_methods:
116116
getattr(ser.dt, prop)
117117

118-
result = ser.dt.to_pydatetime()
118+
msg = "The behavior of DatetimeProperties.to_pydatetime is deprecated"
119+
with tm.assert_produces_warning(FutureWarning, match=msg):
120+
result = ser.dt.to_pydatetime()
119121
assert isinstance(result, np.ndarray)
120122
assert result.dtype == object
121123

@@ -152,7 +154,9 @@ def test_dt_namespace_accessor_datetime64tz(self):
152154
for prop in ok_for_dt_methods:
153155
getattr(ser.dt, prop)
154156

155-
result = ser.dt.to_pydatetime()
157+
msg = "The behavior of DatetimeProperties.to_pydatetime is deprecated"
158+
with tm.assert_produces_warning(FutureWarning, match=msg):
159+
result = ser.dt.to_pydatetime()
156160
assert isinstance(result, np.ndarray)
157161
assert result.dtype == object
158162

0 commit comments

Comments
 (0)