From bd29887ff469b86fa4992dc15d0989bc741d7b08 Mon Sep 17 00:00:00 2001 From: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> Date: Wed, 26 Apr 2023 17:33:08 -0700 Subject: [PATCH 1/5] ERR: Raise a better error message with to_pydatetime and ArrowDtype(pa.date) --- doc/source/whatsnew/v2.0.2.rst | 2 +- pandas/core/arrays/arrow/array.py | 4 ++++ pandas/tests/extension/test_arrow.py | 11 +++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v2.0.2.rst b/doc/source/whatsnew/v2.0.2.rst index f6b0b4086cb39..79011df1b2522 100644 --- a/doc/source/whatsnew/v2.0.2.rst +++ b/doc/source/whatsnew/v2.0.2.rst @@ -30,7 +30,7 @@ Bug fixes Other ~~~~~ -- +- Raised a better error message when calling :func:`Series.dt.to_pydatetime` with :class:`ArrowDtype` with ``pyarrow.date32`` or ``pyarrow.date64`` type (:issue:`52812`) .. --------------------------------------------------------------------------- .. _whatsnew_202.contributors: diff --git a/pandas/core/arrays/arrow/array.py b/pandas/core/arrays/arrow/array.py index a7f2ef85c2a9d..da02c474d2254 100644 --- a/pandas/core/arrays/arrow/array.py +++ b/pandas/core/arrays/arrow/array.py @@ -2367,6 +2367,10 @@ def _dt_month_name(self, locale: str | None = None): return type(self)(pc.strftime(self._pa_array, format="%B", locale=locale)) def _dt_to_pydatetime(self): + if pa.types.is_date(self.dtype.pyarrow_dtype): + raise ValueError( + f"to_pydatetime cannot be called with {self.dtype.pyarrow_dtype} type." + ) data = self._pa_array.to_pylist() if self._dtype.pyarrow_dtype.unit == "ns": data = [None if ts is None else ts.to_pydatetime(warn=False) for ts in data] diff --git a/pandas/tests/extension/test_arrow.py b/pandas/tests/extension/test_arrow.py index 4caa982fa7b64..034af51d0a80d 100644 --- a/pandas/tests/extension/test_arrow.py +++ b/pandas/tests/extension/test_arrow.py @@ -2615,6 +2615,17 @@ def test_dt_to_pydatetime(): tm.assert_numpy_array_equal(result, expected) +@pytest.mark.parametrize("date_type", [32, 64]) +def test_dt_to_pydatetime_date_error(date_type): + # GH 52812 + ser = pd.Series( + [datetime.date(2022, 12, 31)], + dtype=ArrowDtype(getattr(pa, f"date{date_type}")()), + ) + with pytest.raises(ValueError, match="to_pydatetime cannot be called with"): + ser.dt.to_pydatetime() + + def test_dt_tz_localize_unsupported_tz_options(): ser = pd.Series( [datetime(year=2023, month=1, day=2, hour=3), None], From e434a42dcb7851509a418208d725623269c5aa85 Mon Sep 17 00:00:00 2001 From: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> Date: Wed, 26 Apr 2023 19:18:01 -0700 Subject: [PATCH 2/5] Update pandas/tests/extension/test_arrow.py --- pandas/tests/extension/test_arrow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/extension/test_arrow.py b/pandas/tests/extension/test_arrow.py index 034af51d0a80d..f2524681a8a65 100644 --- a/pandas/tests/extension/test_arrow.py +++ b/pandas/tests/extension/test_arrow.py @@ -2619,7 +2619,7 @@ def test_dt_to_pydatetime(): def test_dt_to_pydatetime_date_error(date_type): # GH 52812 ser = pd.Series( - [datetime.date(2022, 12, 31)], + [date(2022, 12, 31)], dtype=ArrowDtype(getattr(pa, f"date{date_type}")()), ) with pytest.raises(ValueError, match="to_pydatetime cannot be called with"): From bfc3cb1e2bb4748d71a9bf76bb46e1ab69395a4e Mon Sep 17 00:00:00 2001 From: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> Date: Thu, 27 Apr 2023 08:53:10 -0700 Subject: [PATCH 3/5] Add warning --- pandas/tests/extension/test_arrow.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pandas/tests/extension/test_arrow.py b/pandas/tests/extension/test_arrow.py index f2524681a8a65..70afe5694061e 100644 --- a/pandas/tests/extension/test_arrow.py +++ b/pandas/tests/extension/test_arrow.py @@ -2622,8 +2622,10 @@ def test_dt_to_pydatetime_date_error(date_type): [date(2022, 12, 31)], dtype=ArrowDtype(getattr(pa, f"date{date_type}")()), ) - with pytest.raises(ValueError, match="to_pydatetime cannot be called with"): - ser.dt.to_pydatetime() + msg = "The behavior of DatetimeProperties.to_pydatetime is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + with pytest.raises(ValueError, match="to_pydatetime cannot be called with"): + ser.dt.to_pydatetime() def test_dt_tz_localize_unsupported_tz_options(): From ba3ca0222f78570467081014c0783734ba099ea2 Mon Sep 17 00:00:00 2001 From: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> Date: Thu, 27 Apr 2023 09:46:00 -0700 Subject: [PATCH 4/5] fix error message --- pandas/tests/extension/test_arrow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/extension/test_arrow.py b/pandas/tests/extension/test_arrow.py index 70afe5694061e..e4115e235cd6b 100644 --- a/pandas/tests/extension/test_arrow.py +++ b/pandas/tests/extension/test_arrow.py @@ -2622,7 +2622,7 @@ def test_dt_to_pydatetime_date_error(date_type): [date(2022, 12, 31)], dtype=ArrowDtype(getattr(pa, f"date{date_type}")()), ) - msg = "The behavior of DatetimeProperties.to_pydatetime is deprecated" + msg = "The behavior of ArrowTemporalProperties.to_pydatetime is deprecated" with tm.assert_produces_warning(FutureWarning, match=msg): with pytest.raises(ValueError, match="to_pydatetime cannot be called with"): ser.dt.to_pydatetime() From 350b89d8f809028e2ba3b926131a8f2897139bbe Mon Sep 17 00:00:00 2001 From: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> Date: Fri, 28 Apr 2023 10:46:09 -0700 Subject: [PATCH 5/5] Suggest to convert to pyarrow timestamp type first --- pandas/core/arrays/arrow/array.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/core/arrays/arrow/array.py b/pandas/core/arrays/arrow/array.py index b51e1ac8d7d36..8d76b0910814c 100644 --- a/pandas/core/arrays/arrow/array.py +++ b/pandas/core/arrays/arrow/array.py @@ -2346,7 +2346,8 @@ def _dt_month_name(self, locale: str | None = None): def _dt_to_pydatetime(self): if pa.types.is_date(self.dtype.pyarrow_dtype): raise ValueError( - f"to_pydatetime cannot be called with {self.dtype.pyarrow_dtype} type." + f"to_pydatetime cannot be called with {self.dtype.pyarrow_dtype} type. " + "Convert to pyarrow timestamp type." ) data = self._pa_array.to_pylist() if self._dtype.pyarrow_dtype.unit == "ns":