diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 74639cc693cb7..20c8dfae0de5e 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:`46430`) - .. --------------------------------------------------------------------------- diff --git a/pandas/_libs/tslibs/timedeltas.pxd b/pandas/_libs/tslibs/timedeltas.pxd index fed1f2d326819..f054a22ed7ad7 100644 --- a/pandas/_libs/tslibs/timedeltas.pxd +++ b/pandas/_libs/tslibs/timedeltas.pxd @@ -11,8 +11,7 @@ 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 + 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.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 6b7ebf96633b3..5df316f86dd02 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -826,13 +826,32 @@ 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 + # 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) -> 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) -> bool: + # GH#46430 + 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) @@ -881,7 +900,7 @@ cdef class _Timedelta(timedelta): """ compute the components """ - if self.is_populated: + if self._is_populated: return cdef: @@ -898,7 +917,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): """ @@ -1389,7 +1408,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 7a32c932aee77..36520a1983aac 100644 --- a/pandas/tests/scalar/timedelta/test_timedelta.py +++ b/pandas/tests/scalar/timedelta/test_timedelta.py @@ -659,3 +659,25 @@ def test_timedelta_attribute_precision(): result += td.nanoseconds expected = td.value assert result == expected + + +def test_freq_deprecated(): + # GH#46430 + td = Timedelta(123456546, unit="ns") + with tm.assert_produces_warning(FutureWarning, match="Timedelta.freq"): + freq = td.freq + + assert freq is None + + with pytest.raises(AttributeError, match="is not writable"): + td.freq = offsets.Day() + + +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 + + with pytest.raises(AttributeError, match="is not writable"): + td.is_populated = 1