From 27fdbfdff8460be471daab7c6ffc76f3eff6cab5 Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Wed, 24 Apr 2024 14:34:12 +0200 Subject: [PATCH 1/4] fixed #58403 --- .../tseries/frequencies/test_inference.py | 23 +++++++++++++++++ pandas/tseries/frequencies.py | 25 +++++++------------ 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/pandas/tests/tseries/frequencies/test_inference.py b/pandas/tests/tseries/frequencies/test_inference.py index edfc1973a2bd9..a91a9a9aea3ba 100644 --- a/pandas/tests/tseries/frequencies/test_inference.py +++ b/pandas/tests/tseries/frequencies/test_inference.py @@ -554,3 +554,26 @@ def test_infer_freq_non_nano_tzaware(tz_aware_fixture): res = frequencies.infer_freq(dta) assert res == "B" + + +@pytest.mark.parametrize( + ("data", "expected"), + [ + (["2022-01-01T10:00:00", "2022-01-01T10:00:30", "2022-01-01T10:01:00"], "30s"), + (["2022-01-01T10:00:00", "2022-01-01T10:00:37", "2022-01-01T10:01:00"], None), + (["2022-01-01T10:00:00", "2022-01-01T10:00:01", "2022-01-01T10:00:02"], "s"), + ( + [ + "2022-01-01T10:00:00", + "2022-01-01T10:00:01", + "2022-01-01T10:00:02", + "2022-01-01T10:00:04", + ], + None, + ), + ], +) +@pytest.mark.parametrize("cls", [Index, Series]) +def test_infer_freq_pyarrow(data, expected, cls): + obj = cls(data).astype("timestamp[s][pyarrow]") + assert frequencies.infer_freq(obj) == expected diff --git a/pandas/tseries/frequencies.py b/pandas/tseries/frequencies.py index 534bee5fede44..10d5506466186 100644 --- a/pandas/tseries/frequencies.py +++ b/pandas/tseries/frequencies.py @@ -33,10 +33,7 @@ from pandas.util._decorators import cache_readonly from pandas.core.dtypes.common import is_numeric_dtype -from pandas.core.dtypes.dtypes import ( - DatetimeTZDtype, - PeriodDtype, -) +from pandas.core.dtypes.dtypes import PeriodDtype from pandas.core.dtypes.generic import ( ABCIndex, ABCSeries, @@ -112,20 +109,16 @@ def infer_freq( >>> pd.infer_freq(idx) 'D' """ + from pandas.api.types import is_datetime64_any_dtype from pandas.core.api import DatetimeIndex - if isinstance(index, ABCSeries): - values = index._values - if not ( - lib.is_np_dtype(values.dtype, "mM") - or isinstance(values.dtype, DatetimeTZDtype) - or values.dtype == object - ): - raise TypeError( - "cannot infer freq from a non-convertible dtype " - f"on a Series of {index.dtype}" - ) - index = values + if isinstance(index, ABCSeries) and not ( + is_datetime64_any_dtype(index) or index.dtype == object + ): + raise TypeError( + "cannot infer freq from a non-convertible dtype " + f"on a Series of {index.dtype}" + ) inferer: _FrequencyInferer From 75cf5bceeab7492a2e7b05cc2264c2133fc872b1 Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Wed, 24 Apr 2024 14:37:36 +0200 Subject: [PATCH 2/4] added whatsnew entry --- doc/source/whatsnew/v3.0.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 781b3b2282a87..ad96818b6b300 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -362,6 +362,7 @@ Datetimelike - Bug in :class:`Timestamp` constructor failing to raise when ``tz=None`` is explicitly specified in conjunction with timezone-aware ``tzinfo`` or data (:issue:`48688`) - Bug in :func:`date_range` where the last valid timestamp would sometimes not be produced (:issue:`56134`) - Bug in :func:`date_range` where using a negative frequency value would not include all points between the start and end values (:issue:`56382`) +- Bug in :func:`infer_freq` prevented application to :class:`Series` of with ``pyarrow`` dtype. (:issue:`58403`) - Bug in :func:`tseries.api.guess_datetime_format` would fail to infer time format when "%Y" == "%H%M" (:issue:`57452`) - Bug in setting scalar values with mismatched resolution into arrays with non-nanosecond ``datetime64``, ``timedelta64`` or :class:`DatetimeTZDtype` incorrectly truncating those scalars (:issue:`56410`) From abe76ea33d8495b262f4a8113083ab50d0dad7bf Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Wed, 24 Apr 2024 15:19:18 +0200 Subject: [PATCH 3/4] skip tests if pyarrow not installed --- pandas/tests/tseries/frequencies/test_inference.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pandas/tests/tseries/frequencies/test_inference.py b/pandas/tests/tseries/frequencies/test_inference.py index a91a9a9aea3ba..2306669f86e92 100644 --- a/pandas/tests/tseries/frequencies/test_inference.py +++ b/pandas/tests/tseries/frequencies/test_inference.py @@ -2,6 +2,7 @@ datetime, timedelta, ) +import importlib import numpy as np import pytest @@ -556,6 +557,9 @@ def test_infer_freq_non_nano_tzaware(tz_aware_fixture): assert res == "B" +@pytest.mark.skipif( + importlib.util.find_spec("pyarrow") is None, reason="pyarrow not installed" +) @pytest.mark.parametrize( ("data", "expected"), [ From 63151946fcfde4726322019dff60da09916e3095 Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Wed, 24 Apr 2024 19:04:34 +0200 Subject: [PATCH 4/4] used pytest.importorskip --- pandas/tests/tseries/frequencies/test_inference.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pandas/tests/tseries/frequencies/test_inference.py b/pandas/tests/tseries/frequencies/test_inference.py index 2306669f86e92..05bfdff808d37 100644 --- a/pandas/tests/tseries/frequencies/test_inference.py +++ b/pandas/tests/tseries/frequencies/test_inference.py @@ -2,7 +2,6 @@ datetime, timedelta, ) -import importlib import numpy as np import pytest @@ -557,9 +556,6 @@ def test_infer_freq_non_nano_tzaware(tz_aware_fixture): assert res == "B" -@pytest.mark.skipif( - importlib.util.find_spec("pyarrow") is None, reason="pyarrow not installed" -) @pytest.mark.parametrize( ("data", "expected"), [ @@ -579,5 +575,6 @@ def test_infer_freq_non_nano_tzaware(tz_aware_fixture): ) @pytest.mark.parametrize("cls", [Index, Series]) def test_infer_freq_pyarrow(data, expected, cls): + pytest.importorskip("pyarrow") obj = cls(data).astype("timestamp[s][pyarrow]") assert frequencies.infer_freq(obj) == expected