From c7b46363019aac68b44829cebc33c97a2d4475e8 Mon Sep 17 00:00:00 2001 From: Manush Prajwal Date: Sun, 9 Aug 2026 12:07:53 +0530 Subject: [PATCH 1/3] fix: catch OverflowError for non-finite floats in time functions naturaldelta(), naturaltime(), and precisedelta() all raised an uncaught OverflowError for float('inf') / float('-inf') instead of returning the value unchanged, unlike every other numeric humanize function (which already treat non-finite input this way) and unlike how these same functions already handle float('nan'). The root cause is that int()/round() raise OverflowError (not ValueError or TypeError) for infinite floats, and that exception wasn't in the except clauses guarding the timedelta conversion in naturaldelta() and the shared _date_and_delta() helper used by naturaltime() and precisedelta(). Fixes #333. --- src/humanize/time.py | 12 +++++------- tests/test_time.py | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/humanize/time.py b/src/humanize/time.py index 4a07d528..37f930dc 100644 --- a/src/humanize/time.py +++ b/src/humanize/time.py @@ -89,7 +89,7 @@ def _date_and_delta( value = value if precise else round(value) delta = dt.timedelta(seconds=value) date = now - delta - except (ValueError, TypeError): + except (ValueError, TypeError, OverflowError): return None, value return date, _abs_timedelta(delta) @@ -114,11 +114,9 @@ def naturaldelta( Returns: str (str or `value`): A natural representation of the amount of time elapsed unless `value` is not datetime.timedelta or cannot be - converted to int (cannot be float due to 'inf' or 'nan'). - In that case, a `value` is returned unchanged. - - Raises: - OverflowError: If `value` is too large to convert to datetime.timedelta. + converted to int (cannot be float due to 'inf' or 'nan', or too + large to fit in a `datetime.timedelta`). In that case, `value` is + returned unchanged (via `str()`). Examples: Compare two timestamps in a custom local timezone:: @@ -151,7 +149,7 @@ def naturaldelta( int(value) # Explicitly don't support string such as "NaN" or "inf" value = float(value) delta = dt.timedelta(seconds=value) - except (ValueError, TypeError): + except (ValueError, TypeError, OverflowError): return str(value) use_months = months diff --git a/tests/test_time.py b/tests/test_time.py index 76997704..033a4e55 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -837,6 +837,45 @@ def test_time_unit() -> None: _ = years < "foo" +@pytest.mark.parametrize( + "value, expected", + [ + (float("inf"), "inf"), + (float("-inf"), "-inf"), + (float("nan"), "nan"), + ], +) +def test_naturaldelta_non_finite(value: float, expected: str) -> None: + # Regression test for #333: non-finite floats used to raise an uncaught + # OverflowError (or, for nan, were only handled when passed as a string) + # instead of being returned unchanged like other non-numeric input. + assert humanize.naturaldelta(value) == expected + + +@pytest.mark.parametrize( + "value, expected", + [ + (float("inf"), "inf"), + (float("-inf"), "-inf"), + (float("nan"), "nan"), + ], +) +def test_naturaltime_non_finite(value: float, expected: str) -> None: + assert humanize.naturaltime(value) == expected + + +@pytest.mark.parametrize( + "value, expected", + [ + (float("inf"), "inf"), + (float("-inf"), "-inf"), + (float("nan"), "nan"), + ], +) +def test_precisedelta_non_finite(value: float, expected: str) -> None: + assert humanize.precisedelta(value) == expected + + @pytest.mark.parametrize( "fmt, value, expected", [ From eaba1b076c4c9ad88c55e82294bacf651d61f94d Mon Sep 17 00:00:00 2001 From: Manushprajwal <160592047+Manushprajwal7@users.noreply.github.com> Date: Sun, 23 Aug 2026 17:01:17 +0530 Subject: [PATCH 2/3] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/humanize/time.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/humanize/time.py b/src/humanize/time.py index 37f930dc..31fce53c 100644 --- a/src/humanize/time.py +++ b/src/humanize/time.py @@ -146,7 +146,7 @@ def naturaldelta( delta = value else: try: - int(value) # Explicitly don't support string such as "NaN" or "inf" + int(value) # Force numeric types; strings like "NaN"/"inf" are returned unchanged value = float(value) delta = dt.timedelta(seconds=value) except (ValueError, TypeError, OverflowError): From 631796984b4e6e07140978e2716474696ec603ab Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 11:31:59 +0000 Subject: [PATCH 3/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/humanize/time.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/humanize/time.py b/src/humanize/time.py index 31fce53c..c7b1de22 100644 --- a/src/humanize/time.py +++ b/src/humanize/time.py @@ -146,7 +146,9 @@ def naturaldelta( delta = value else: try: - int(value) # Force numeric types; strings like "NaN"/"inf" are returned unchanged + int( + value + ) # Force numeric types; strings like "NaN"/"inf" are returned unchanged value = float(value) delta = dt.timedelta(seconds=value) except (ValueError, TypeError, OverflowError):