From 650bd3ca36f06712940401cece541a25859e83bb Mon Sep 17 00:00:00 2001 From: Brock Date: Fri, 18 Mar 2022 21:23:52 -0700 Subject: [PATCH 1/4] DEPR: Timedelta.freq --- pandas/_libs/tslibs/timedeltas.pxd | 1 - pandas/_libs/tslibs/timedeltas.pyx | 9 ++++++++- pandas/tests/scalar/timedelta/test_timedelta.py | 9 +++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/pandas/_libs/tslibs/timedeltas.pxd b/pandas/_libs/tslibs/timedeltas.pxd index fed1f2d326819..0da4b614dd379 100644 --- a/pandas/_libs/tslibs/timedeltas.pxd +++ b/pandas/_libs/tslibs/timedeltas.pxd @@ -11,7 +11,6 @@ cdef bint is_any_td_scalar(object obj) cdef class _Timedelta(timedelta): cdef readonly: int64_t value # nanoseconds - object freq # frequency reference bint is_populated # are my components populated int64_t _d, _h, _m, _s, _ms, _us, _ns diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 6b7ebf96633b3..7783888b59d18 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -826,13 +826,20 @@ cdef _to_py_int_float(v): cdef class _Timedelta(timedelta): # cdef readonly: # int64_t value # nanoseconds - # object freq # frequency reference # bint is_populated # are my components populated # int64_t _d, _h, _m, _s, _ms, _us, _ns # higher than np.ndarray and np.matrix __array_priority__ = 100 + @property + def freq(self): + warnings.warn( + "Timedelta.freq is deprecated and will be removed in a future version", + FutureWarning, + stacklevel=1, + ) + def __hash__(_Timedelta self): if self._has_ns(): return hash(self.value) diff --git a/pandas/tests/scalar/timedelta/test_timedelta.py b/pandas/tests/scalar/timedelta/test_timedelta.py index 7a32c932aee77..0bc054e74505f 100644 --- a/pandas/tests/scalar/timedelta/test_timedelta.py +++ b/pandas/tests/scalar/timedelta/test_timedelta.py @@ -659,3 +659,12 @@ def test_timedelta_attribute_precision(): result += td.nanoseconds expected = td.value assert result == expected + + +def test_freq_deprecated(): + td = Timedelta(123456546, unit="ns") + with tm.assert_produces_warning(FutureWarning, match="Timedelta.freq"): + td.freq + + with pytest.raises(AttributeError, match="is not writable"): + td.freq = offsets.Day() From 5aa297ac89168100a4539d22b01ee5b6b7f69aa2 Mon Sep 17 00:00:00 2001 From: Brock Date: Fri, 18 Mar 2022 21:29:08 -0700 Subject: [PATCH 2/4] DEPR: Timedelta.is_populated --- doc/source/whatsnew/v1.5.0.rst | 1 + pandas/_libs/tslibs/timedeltas.pxd | 2 +- pandas/_libs/tslibs/timedeltas.pyx | 17 +++++++++++++---- pandas/tests/scalar/timedelta/test_timedelta.py | 9 +++++++++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 74639cc693cb7..5a21e7cfce2a6 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -342,6 +342,7 @@ Other Deprecations - Deprecated allowing non-keyword arguments in :meth:`ExtensionArray.argsort` (:issue:`46134`) - Deprecated treating all-bool ``object``-dtype columns as bool-like in :meth:`DataFrame.any` and :meth:`DataFrame.all` with ``bool_only=True``, explicitly cast to bool instead (:issue:`46188`) - Deprecated behavior of method :meth:`DataFrame.quantile`, attribute ``numeric_only`` will default False. Including datetime/timedelta columns in the result (:issue:`7308`). +- Deprecated :attr:`Timedelta.freq` and :attr:`Timedelta.is_populated` (:issue:`??`) - .. --------------------------------------------------------------------------- diff --git a/pandas/_libs/tslibs/timedeltas.pxd b/pandas/_libs/tslibs/timedeltas.pxd index 0da4b614dd379..f054a22ed7ad7 100644 --- a/pandas/_libs/tslibs/timedeltas.pxd +++ b/pandas/_libs/tslibs/timedeltas.pxd @@ -11,7 +11,7 @@ cdef bint is_any_td_scalar(object obj) cdef class _Timedelta(timedelta): cdef readonly: int64_t value # nanoseconds - bint is_populated # are my components populated + bint _is_populated # are my components populated int64_t _d, _h, _m, _s, _ms, _us, _ns cpdef timedelta to_pytimedelta(_Timedelta self) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 7783888b59d18..b5c901dfded01 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -826,7 +826,7 @@ cdef _to_py_int_float(v): cdef class _Timedelta(timedelta): # cdef readonly: # int64_t value # nanoseconds - # bint is_populated # are my components populated + # bint _is_populated # are my components populated # int64_t _d, _h, _m, _s, _ms, _us, _ns # higher than np.ndarray and np.matrix @@ -840,6 +840,15 @@ cdef class _Timedelta(timedelta): stacklevel=1, ) + @property + def is_populated(self): + warnings.warn( + "Timedelta.is_populated is deprecated and will be removed in a future version", + FutureWarning, + stacklevel=1, + ) + return self._is_populated + def __hash__(_Timedelta self): if self._has_ns(): return hash(self.value) @@ -888,7 +897,7 @@ cdef class _Timedelta(timedelta): """ compute the components """ - if self.is_populated: + if self._is_populated: return cdef: @@ -905,7 +914,7 @@ cdef class _Timedelta(timedelta): self._seconds = tds.seconds self._microseconds = tds.microseconds - self.is_populated = 1 + self._is_populated = 1 cpdef timedelta to_pytimedelta(_Timedelta self): """ @@ -1396,7 +1405,7 @@ class Timedelta(_Timedelta): # make timedelta happy td_base = _Timedelta.__new__(cls, microseconds=int(value) // 1000) td_base.value = value - td_base.is_populated = 0 + td_base._is_populated = 0 return td_base def __setstate__(self, state): diff --git a/pandas/tests/scalar/timedelta/test_timedelta.py b/pandas/tests/scalar/timedelta/test_timedelta.py index 0bc054e74505f..2d108973706a8 100644 --- a/pandas/tests/scalar/timedelta/test_timedelta.py +++ b/pandas/tests/scalar/timedelta/test_timedelta.py @@ -668,3 +668,12 @@ def test_freq_deprecated(): with pytest.raises(AttributeError, match="is not writable"): td.freq = offsets.Day() + + +def test_is_populated_deprecated(): + td = Timedelta(123456546, unit="ns") + with tm.assert_produces_warning(FutureWarning, match="Timedelta.is_populated"): + td.is_populated + + with pytest.raises(AttributeError, match="is not writable"): + td.is_populated = 1 From 36157f8ce19e69ae9d76ad3e22c588e4edfcd7bc Mon Sep 17 00:00:00 2001 From: Brock Date: Fri, 18 Mar 2022 21:30:21 -0700 Subject: [PATCH 3/4] GH refs --- doc/source/whatsnew/v1.5.0.rst | 2 +- pandas/_libs/tslibs/timedeltas.pyx | 2 ++ pandas/tests/scalar/timedelta/test_timedelta.py | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 5a21e7cfce2a6..20c8dfae0de5e 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -342,7 +342,7 @@ Other Deprecations - Deprecated allowing non-keyword arguments in :meth:`ExtensionArray.argsort` (:issue:`46134`) - Deprecated treating all-bool ``object``-dtype columns as bool-like in :meth:`DataFrame.any` and :meth:`DataFrame.all` with ``bool_only=True``, explicitly cast to bool instead (:issue:`46188`) - Deprecated behavior of method :meth:`DataFrame.quantile`, attribute ``numeric_only`` will default False. Including datetime/timedelta columns in the result (:issue:`7308`). -- Deprecated :attr:`Timedelta.freq` and :attr:`Timedelta.is_populated` (:issue:`??`) +- Deprecated :attr:`Timedelta.freq` and :attr:`Timedelta.is_populated` (:issue:`46430`) - .. --------------------------------------------------------------------------- diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index b5c901dfded01..7aee144076670 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -834,6 +834,7 @@ cdef class _Timedelta(timedelta): @property def freq(self): + # GH#46430 warnings.warn( "Timedelta.freq is deprecated and will be removed in a future version", FutureWarning, @@ -842,6 +843,7 @@ cdef class _Timedelta(timedelta): @property def is_populated(self): + # GH#46430 warnings.warn( "Timedelta.is_populated is deprecated and will be removed in a future version", FutureWarning, diff --git a/pandas/tests/scalar/timedelta/test_timedelta.py b/pandas/tests/scalar/timedelta/test_timedelta.py index 2d108973706a8..1cb859a733a1c 100644 --- a/pandas/tests/scalar/timedelta/test_timedelta.py +++ b/pandas/tests/scalar/timedelta/test_timedelta.py @@ -662,6 +662,7 @@ def test_timedelta_attribute_precision(): def test_freq_deprecated(): + # GH#46430 td = Timedelta(123456546, unit="ns") with tm.assert_produces_warning(FutureWarning, match="Timedelta.freq"): td.freq @@ -671,6 +672,7 @@ def test_freq_deprecated(): def test_is_populated_deprecated(): + # GH#46430 td = Timedelta(123456546, unit="ns") with tm.assert_produces_warning(FutureWarning, match="Timedelta.is_populated"): td.is_populated From c8e9ba8e9a4928bb78a41bf1a4b6fb59f4990172 Mon Sep 17 00:00:00 2001 From: Brock Date: Sat, 19 Mar 2022 11:54:18 -0700 Subject: [PATCH 4/4] annotate, make None explicit --- pandas/_libs/tslibs/timedeltas.pyi | 4 ++++ pandas/_libs/tslibs/timedeltas.pyx | 5 +++-- pandas/tests/scalar/timedelta/test_timedelta.py | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/pandas/_libs/tslibs/timedeltas.pyi b/pandas/_libs/tslibs/timedeltas.pyi index 28c2f7db62158..f4711f728907d 100644 --- a/pandas/_libs/tslibs/timedeltas.pyi +++ b/pandas/_libs/tslibs/timedeltas.pyi @@ -146,3 +146,7 @@ class Timedelta(timedelta): def __hash__(self) -> int: ... def isoformat(self) -> str: ... def to_numpy(self) -> np.timedelta64: ... + @property + def freq(self) -> None: ... + @property + def is_populated(self) -> bool: ... diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 7aee144076670..5df316f86dd02 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -833,16 +833,17 @@ cdef class _Timedelta(timedelta): __array_priority__ = 100 @property - def freq(self): + def freq(self) -> None: # GH#46430 warnings.warn( "Timedelta.freq is deprecated and will be removed in a future version", FutureWarning, stacklevel=1, ) + return None @property - def is_populated(self): + def is_populated(self) -> bool: # GH#46430 warnings.warn( "Timedelta.is_populated is deprecated and will be removed in a future version", diff --git a/pandas/tests/scalar/timedelta/test_timedelta.py b/pandas/tests/scalar/timedelta/test_timedelta.py index 1cb859a733a1c..36520a1983aac 100644 --- a/pandas/tests/scalar/timedelta/test_timedelta.py +++ b/pandas/tests/scalar/timedelta/test_timedelta.py @@ -665,7 +665,9 @@ def test_freq_deprecated(): # GH#46430 td = Timedelta(123456546, unit="ns") with tm.assert_produces_warning(FutureWarning, match="Timedelta.freq"): - td.freq + freq = td.freq + + assert freq is None with pytest.raises(AttributeError, match="is not writable"): td.freq = offsets.Day()