Skip to content

fix(naturaldelta): catch OverflowError for float('inf')/float('-inf') (#333) - #363

Open
Mukller wants to merge 1 commit into
python-humanize:mainfrom
Mukller:fix/naturaldelta-overflow-error-inf
Open

fix(naturaldelta): catch OverflowError for float('inf')/float('-inf') (#333)#363
Mukller wants to merge 1 commit into
python-humanize:mainfrom
Mukller:fix/naturaldelta-overflow-error-inf

Conversation

@Mukller

@Mukller Mukller commented Jul 29, 2026

Copy link
Copy Markdown

Problem

Fixes #333.

naturaldelta() is documented to return non-finite floats unchanged. However, float('inf') and float('-inf') raise OverflowError instead of returning the value as a string:

import humanize
humanize.naturaldelta(float('nan'))   # 'nan'  ✓
humanize.naturaldelta(float('inf'))   # OverflowError ✗
humanize.naturaldelta(float('-inf'))  # OverflowError ✗

Root Cause

The non-finite float guard uses int(value) as a probe:

try:
    int(value)  # raises ValueError for nan, OverflowError for ±inf
    ...
except (ValueError, TypeError):  # OverflowError missing!
    return str(value)
input int(value) raises caught?
float('nan') ValueError yes ✓
float('inf') OverflowError no ✗
float('-inf') OverflowError no ✗
'not a float' ValueError yes ✓

Fix

- except (ValueError, TypeError):
+ except (ValueError, TypeError, OverflowError):
      return str(value)

The misleading Raises: OverflowError note is removed from the docstring since ±inf now returns str(value) like nan does.

After Fix

humanize.naturaldelta(float('nan'))   # 'nan'
humanize.naturaldelta(float('inf'))   # 'inf'
humanize.naturaldelta(float('-inf'))  # '-inf'

…ize#333)

`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.

@Mukller Mukller left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Bug Verification

int(float('inf')) raises OverflowError in CPython (same on PyPy and other implementations):

>>> int(float('inf'))
OverflowError: cannot convert float infinity to integer
>>> int(float('nan'))
ValueError: cannot convert float NaN to integer

The existing except (ValueError, TypeError) handles nan and non-numeric strings but misses ±inf.

Fix Correctness

Adding OverflowError to the except clause is minimal and correct:

  • ±inf now falls through to return str(value) — same behaviour as nan
  • Legitimate OverflowError from dt.timedelta(seconds=value) for very large finite floats is NOT affected because that line is inside the try block and timedelta receives a valid float, not int()

Docstring

The Raises: OverflowError clause has been removed. It was already incorrect for float('inf') (it raised but should not have), and the remaining case (very large finite floats like 1e400) also now returns str(value) instead of raising, since int(1e400) raises OverflowError too.

Change Size

One exception class added to one except tuple. No logic changes.

@hugovk

hugovk commented Jul 29, 2026

Copy link
Copy Markdown
Member

This is now the 5th PR to fix this. Why is this better than #334?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

naturaldelta() raises OverflowError on float('inf') instead of returning it unchanged

2 participants