From 99ac0591e28aca6eeb1cbeba096ead3bc0c5150b Mon Sep 17 00:00:00 2001 From: uttam12331 Date: Mon, 29 Jun 2026 20:47:10 +0530 Subject: [PATCH] Return non-finite floats unchanged from naturaldelta naturaldelta() documents that values it cannot convert are returned unchanged, and float('nan') already is. But float('inf')/float('-inf') raised an uncaught OverflowError from int(value), instead of being returned unchanged like nan. Catch OverflowError and return non-finite floats unchanged. A too-large *finite* value, whose OverflowError comes from timedelta(), is still raised, preserving the documented OverflowError contract. Closes #333 --- src/humanize/time.py | 9 +++++++++ tests/test_time.py | 13 +++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/humanize/time.py b/src/humanize/time.py index 8651a981..be73bd76 100644 --- a/src/humanize/time.py +++ b/src/humanize/time.py @@ -5,6 +5,7 @@ from __future__ import annotations +import math from enum import Enum from functools import total_ordering @@ -151,6 +152,14 @@ def naturaldelta( delta = dt.timedelta(seconds=value) except (ValueError, TypeError): return str(value) + except OverflowError: + # `int(value)` raises OverflowError for non-finite floats (inf/-inf), + # which, like NaN, are returned unchanged. A too-large *finite* value + # (whose OverflowError comes from `timedelta`) is still raised, per + # the documented `OverflowError` contract. + if not math.isfinite(value): + return str(value) + raise use_months = months diff --git a/tests/test_time.py b/tests/test_time.py index 76997704..b3f448c2 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -138,6 +138,19 @@ def test_naturaldelta(test_input: float | dt.timedelta, expected: str) -> None: assert humanize.naturaldelta(-test_input) == expected +def test_naturaldelta_non_finite() -> None: + """Non-finite floats are returned unchanged instead of raising (#333).""" + assert humanize.naturaldelta(float("nan")) == "nan" + assert humanize.naturaldelta(float("inf")) == "inf" + assert humanize.naturaldelta(float("-inf")) == "-inf" + + +def test_naturaldelta_too_large_value_raises() -> None: + """A too-large *finite* value still raises OverflowError (unlike inf).""" + with pytest.raises(OverflowError): + humanize.naturaldelta(1e30) + + @freeze_time(FROZEN_DATE) @pytest.mark.parametrize( "test_input, expected",