From fe0bf42e6997d0f61df477557f839315d3759964 Mon Sep 17 00:00:00 2001 From: Anton Petnitsky <168552591+Mukller@users.noreply.github.com> Date: Wed, 29 Jul 2026 16:36:42 +0300 Subject: [PATCH 1/4] fix(naturaldelta): catch OverflowError for float('inf') (#333) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `int(float("inf"))` raises `OverflowError`, not `ValueError`, so the existing `except (ValueError, TypeError)` guard misses it. The function docstring states that non-finite floats are returned unchanged, but `float("inf")` and `float("-inf")` raised uncaught `OverflowError` while only `float("nan")` was silently returned. Add `OverflowError` to the except clause so that ±inf are treated the same as nan. Remove the misleading "Raises: OverflowError" note from the docstring since that exception is now caught. --- src/humanize/time.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/humanize/time.py b/src/humanize/time.py index 4a07d52..de16c3e 100644 --- a/src/humanize/time.py +++ b/src/humanize/time.py @@ -117,9 +117,6 @@ def naturaldelta( 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. - Examples: Compare two timestamps in a custom local timezone:: @@ -151,7 +148,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 From e16584ec706ca43479d817cdd4e3f7d2dff43081 Mon Sep 17 00:00:00 2001 From: Anton Petnitsky <168552591+Mukller@users.noreply.github.com> Date: Thu, 30 Jul 2026 21:54:38 +0300 Subject: [PATCH 2/4] fix(naturaldelta): only suppress OverflowError for non-finite floats The previous fix caught all OverflowErrors, which incorrectly swallowed the documented OverflowError for truly too-large finite float values. Use math.isfinite() to distinguish inf/-inf (return unchanged) from a legitimately too-large finite value (re-raise). --- src/humanize/time.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/humanize/time.py b/src/humanize/time.py index de16c3e..3d5ef12 100644 --- a/src/humanize/time.py +++ b/src/humanize/time.py @@ -148,7 +148,14 @@ 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, OverflowError): + except OverflowError: + # int(value) raises OverflowError for non-finite floats (inf/-inf). + # Like NaN they are returned unchanged. A truly too-large *finite* + # float still raises, preserving the documented OverflowError contract. + if not math.isfinite(value): + return str(value) + raise + except (ValueError, TypeError): return str(value) use_months = months From ac55bbb581905fb97baf21cdbdb7858941bd773a Mon Sep 17 00:00:00 2001 From: Anton Petnitsky <168552591+Mukller@users.noreply.github.com> Date: Thu, 30 Jul 2026 21:55:13 +0300 Subject: [PATCH 3/4] test: regression for #333 non-finite float OverflowError in naturaldelta Verify inf/-inf are returned as strings, nan still works, and a truly too-large finite float still raises OverflowError as documented. --- tests/test_time.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test_time.py b/tests/test_time.py index 7699770..78bec9e 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -138,6 +138,25 @@ def test_naturaldelta(test_input: float | dt.timedelta, expected: str) -> None: assert humanize.naturaldelta(-test_input) == expected +def test_naturaldelta_non_finite_floats() -> None: + """Regression for #333: non-finite floats must not raise OverflowError. + + float("inf") and float("-inf") trigger int(value) -> OverflowError inside + timedelta(seconds=value). They should be returned as strings, like float("nan"). + A legitimately too-large *finite* float must still raise OverflowError. + """ + import math + # Non-finite values return the string repr + assert humanize.naturaldelta(float("inf")) == "inf" + assert humanize.naturaldelta(float("-inf")) == "-inf" + # NaN already worked before; confirm it still does + assert humanize.naturaldelta(float("nan")) == "nan" + # A truly too-large finite float must still raise (documented behaviour) + import pytest + with pytest.raises(OverflowError): + humanize.naturaldelta(1e308 * 10) + + @freeze_time(FROZEN_DATE) @pytest.mark.parametrize( "test_input, expected", From ca10a45ba16abfc762464ff2f77203f33fc67692 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 30 Jul 2026 18:55:56 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_time.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_time.py b/tests/test_time.py index 78bec9e..d5856ed 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -145,7 +145,6 @@ def test_naturaldelta_non_finite_floats() -> None: timedelta(seconds=value). They should be returned as strings, like float("nan"). A legitimately too-large *finite* float must still raise OverflowError. """ - import math # Non-finite values return the string repr assert humanize.naturaldelta(float("inf")) == "inf" assert humanize.naturaldelta(float("-inf")) == "-inf" @@ -153,6 +152,7 @@ def test_naturaldelta_non_finite_floats() -> None: assert humanize.naturaldelta(float("nan")) == "nan" # A truly too-large finite float must still raise (documented behaviour) import pytest + with pytest.raises(OverflowError): humanize.naturaldelta(1e308 * 10)