From af9d9cb0615a797cba60502f8218e6644169818c Mon Sep 17 00:00:00 2001 From: Brock Date: Wed, 16 Jul 2025 13:38:08 -0700 Subject: [PATCH] BUG: Timedelta with invalid keyword --- doc/source/whatsnew/v3.0.0.rst | 1 + pandas/_libs/tslibs/timedeltas.pyx | 24 ++++++++++++++---------- pandas/tests/tslibs/test_timedeltas.py | 4 ++++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index f2650a64d2c59..fdc851399c13c 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -717,6 +717,7 @@ Datetimelike Timedelta ^^^^^^^^^ - Accuracy improvement in :meth:`Timedelta.to_pytimedelta` to round microseconds consistently for large nanosecond based Timedelta (:issue:`57841`) +- Bug in :class:`Timedelta` constructor failing to raise when passed an invalid keyword (:issue:`53801`) - Bug in :meth:`DataFrame.cumsum` which was raising ``IndexError`` if dtype is ``timedelta64[ns]`` (:issue:`57956`) Timezones diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 222a6070016e0..6c76e05471577 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -2006,6 +2006,20 @@ class Timedelta(_Timedelta): "milliseconds", "microseconds", "nanoseconds"} def __new__(cls, object value=_no_input, unit=None, **kwargs): + unsupported_kwargs = set(kwargs) + unsupported_kwargs.difference_update(cls._req_any_kwargs_new) + if unsupported_kwargs or ( + value is _no_input and + not cls._req_any_kwargs_new.intersection(kwargs) + ): + raise ValueError( + # GH#53801 + "cannot construct a Timedelta from the passed arguments, " + "allowed keywords are " + "[weeks, days, hours, minutes, seconds, " + "milliseconds, microseconds, nanoseconds]" + ) + if value is _no_input: if not len(kwargs): raise ValueError("cannot construct a Timedelta without a " @@ -2014,16 +2028,6 @@ class Timedelta(_Timedelta): kwargs = {key: _to_py_int_float(kwargs[key]) for key in kwargs} - unsupported_kwargs = set(kwargs) - unsupported_kwargs.difference_update(cls._req_any_kwargs_new) - if unsupported_kwargs or not cls._req_any_kwargs_new.intersection(kwargs): - raise ValueError( - "cannot construct a Timedelta from the passed arguments, " - "allowed keywords are " - "[weeks, days, hours, minutes, seconds, " - "milliseconds, microseconds, nanoseconds]" - ) - # GH43764, convert any input to nanoseconds first and then # create the timedelta. This ensures that any potential # nanosecond contributions from kwargs parsed as floats diff --git a/pandas/tests/tslibs/test_timedeltas.py b/pandas/tests/tslibs/test_timedeltas.py index 4784a6d0d600d..8e27acdd7af75 100644 --- a/pandas/tests/tslibs/test_timedeltas.py +++ b/pandas/tests/tslibs/test_timedeltas.py @@ -104,6 +104,10 @@ def test_kwarg_assertion(kwargs): with pytest.raises(ValueError, match=re.escape(err_message)): Timedelta(**kwargs) + with pytest.raises(ValueError, match=re.escape(err_message)): + # GH#53801 'unit' misspelled as 'units' + Timedelta(1, units="hours") + class TestArrayToTimedelta64: def test_array_to_timedelta64_string_with_unit_2d_raises(self):