Skip to content

Commit 4bea299

Browse files
authored
DEPR: maybe_promote with pydate (#49487)
* DEPR: maybe_promote with pydate * fix whatsnew
1 parent 91e1fdc commit 4bea299

File tree

4 files changed

+20
-49
lines changed

4 files changed

+20
-49
lines changed

doc/source/whatsnew/v2.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ Removal of prior version deprecations/changes
423423
- Changed behavior of empty data passed into :class:`Series`; the default dtype will be ``object`` instead of ``float64`` (:issue:`29405`)
424424
- Changed the behavior of :meth:`DatetimeIndex.union`, :meth:`DatetimeIndex.intersection`, and :meth:`DatetimeIndex.symmetric_difference` with mismatched timezones to convert to UTC instead of casting to object dtype (:issue:`39328`)
425425
- Changed the behavior of :func:`to_datetime` with argument "now" with ``utc=False`` to match ``Timestamp("now")`` (:issue:`18705`)
426+
- Changed the behavior of :meth:`Index.reindex`, :meth:`Series.reindex`, and :meth:`DataFrame.reindex` with a ``datetime64`` dtype and a ``datetime.date`` object for ``fill_value``; these are no longer considered equivalent to ``datetime.datetime`` objects so the reindex casts to object dtype (:issue:`39767`)
426427
- Changed behavior of :meth:`SparseArray.astype` when given a dtype that is not explicitly ``SparseDtype``, cast to the exact requested dtype rather than silently using a ``SparseDtype`` instead (:issue:`34457`)
427428
- Changed behavior of :meth:`Index.ravel` to return a view on the original :class:`Index` instead of a ``np.ndarray`` (:issue:`36900`)
428429
- Changed behavior of :meth:`Index.to_frame` with explicit ``name=None`` to use ``None`` for the column name instead of the index's name or default ``0`` (:issue:`45523`)

pandas/core/dtypes/cast.py

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from __future__ import annotations
66

77
from datetime import (
8-
date,
98
datetime,
109
timedelta,
1110
)
@@ -615,41 +614,14 @@ def _maybe_promote(dtype: np.dtype, fill_value=np.nan):
615614
if inferred == dtype:
616615
return dtype, fv
617616

618-
# TODO(2.0): once this deprecation is enforced, this whole case
619-
# becomes equivalent to:
620-
# dta = DatetimeArray._from_sequence([], dtype="M8[ns]")
621-
# try:
622-
# fv = dta._validate_setitem_value(fill_value)
623-
# return dta.dtype, fv
624-
# except (ValueError, TypeError):
625-
# return _dtype_obj, fill_value
626-
if isinstance(fill_value, date) and not isinstance(fill_value, datetime):
627-
# deprecate casting of date object to match infer_dtype_from_scalar
628-
# and DatetimeArray._validate_setitem_value
629-
try:
630-
fv = Timestamp(fill_value).to_datetime64()
631-
except OutOfBoundsDatetime:
632-
pass
633-
else:
634-
warnings.warn(
635-
"Using a `date` object for fill_value with `datetime64[ns]` "
636-
"dtype is deprecated. In a future version, this will be cast "
637-
"to object dtype. Pass `fill_value=Timestamp(date_obj)` instead.",
638-
FutureWarning,
639-
stacklevel=find_stack_level(),
640-
)
641-
return dtype, fv
642-
elif isinstance(fill_value, str):
643-
try:
644-
# explicitly wrap in str to convert np.str_
645-
fv = Timestamp(str(fill_value))
646-
except (ValueError, TypeError):
647-
pass
648-
else:
649-
if isna(fv) or fv.tz is None:
650-
return dtype, fv.asm8
617+
from pandas.core.arrays import DatetimeArray
651618

652-
return np.dtype("object"), fill_value
619+
dta = DatetimeArray._from_sequence([], dtype="M8[ns]")
620+
try:
621+
fv = dta._validate_setitem_value(fill_value)
622+
return dta.dtype, fv
623+
except (ValueError, TypeError):
624+
return _dtype_obj, fill_value
653625

654626
elif issubclass(dtype.type, np.timedelta64):
655627
inferred, fv = infer_dtype_from_scalar(fill_value, pandas_dtype=True)

pandas/tests/dtypes/cast/test_promote.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
from pandas.core.dtypes.missing import isna
2626

2727
import pandas as pd
28-
import pandas._testing as tm
2928

3029

3130
@pytest.fixture(
@@ -403,15 +402,12 @@ def test_maybe_promote_any_with_datetime64(any_numpy_dtype_reduced, fill_value):
403402
expected_dtype = np.dtype(object)
404403
exp_val_for_scalar = fill_value
405404

406-
warn = None
407-
msg = "Using a `date` object for fill_value"
408405
if type(fill_value) is datetime.date and dtype.kind == "M":
409-
# Casting date to dt64 is deprecated
410-
warn = FutureWarning
406+
# Casting date to dt64 is deprecated, in 2.0 enforced to cast to object
407+
expected_dtype = np.dtype(object)
408+
exp_val_for_scalar = fill_value
411409

412-
with tm.assert_produces_warning(warn, match=msg):
413-
# stacklevel is chosen to make sense when called from higher-level functions
414-
_check_promote(dtype, fill_value, expected_dtype, exp_val_for_scalar)
410+
_check_promote(dtype, fill_value, expected_dtype, exp_val_for_scalar)
415411

416412

417413
@pytest.mark.parametrize(

pandas/tests/frame/methods/test_reindex.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,30 +136,32 @@ def test_reindex_copies(self):
136136

137137
@td.skip_array_manager_not_yet_implemented
138138
def test_reindex_date_fill_value(self):
139-
# passing date to dt64 is deprecated
139+
# passing date to dt64 is deprecated; enforced in 2.0 to cast to object
140140
arr = date_range("2016-01-01", periods=6).values.reshape(3, 2)
141141
df = DataFrame(arr, columns=["A", "B"], index=range(3))
142142

143143
ts = df.iloc[0, 0]
144144
fv = ts.date()
145145

146-
with tm.assert_produces_warning(FutureWarning):
147-
res = df.reindex(index=range(4), columns=["A", "B", "C"], fill_value=fv)
146+
res = df.reindex(index=range(4), columns=["A", "B", "C"], fill_value=fv)
148147

149148
expected = DataFrame(
150-
{"A": df["A"].tolist() + [ts], "B": df["B"].tolist() + [ts], "C": [ts] * 4}
149+
{"A": df["A"].tolist() + [fv], "B": df["B"].tolist() + [fv], "C": [fv] * 4},
150+
dtype=object,
151151
)
152152
tm.assert_frame_equal(res, expected)
153153

154154
# only reindexing rows
155-
with tm.assert_produces_warning(FutureWarning):
156-
res = df.reindex(index=range(4), fill_value=fv)
155+
res = df.reindex(index=range(4), fill_value=fv)
157156
tm.assert_frame_equal(res, expected[["A", "B"]])
158157

159158
# same with a datetime-castable str
160159
res = df.reindex(
161160
index=range(4), columns=["A", "B", "C"], fill_value="2016-01-01"
162161
)
162+
expected = DataFrame(
163+
{"A": df["A"].tolist() + [ts], "B": df["B"].tolist() + [ts], "C": [ts] * 4},
164+
)
163165
tm.assert_frame_equal(res, expected)
164166

165167
def test_reindex_with_multi_index(self):

0 commit comments

Comments
 (0)