Skip to content

Several number functions raise OverflowError on integers larger than a float #419

Description

@itzzdev09

Summary

Most functions in humanize.number convert the input with float() before trying int(), purely to test for NaN/infinity. For an integer larger than the float range that conversion raises OverflowError, which escapes the except (TypeError, ValueError) clause and propagates to the caller — even though the value is a perfectly ordinary Python int.

Reproduction

>>> import humanize
>>> humanize.apnumber(10**400)
OverflowError: int too large to convert to float
>>> humanize.fractional(10**400)
OverflowError: int too large to convert to float

Scope

Passing 10**400 + 123 on main:

function as int as str
ordinal OverflowError +Inf
intcomma correct +Inf
intword OverflowError +Inf
apnumber OverflowError +Inf
fractional OverflowError +Inf
scientific OverflowError +Inf
clamp OverflowError TypeError
metric OverflowError TypeError

The +Inf results are the same root cause seen from the string side: float("1" + "0"*400) returns inf rather than raising, so a finite integer is reported as infinite.

Why these are bugs rather than out-of-contract input

apnumber documents the fallback explicitly:

This always returns a string unless the value was not int-able, then str(value) is returned.

10**400 is int-able — it is already an int — so by the documented contract it must return a string. ordinal carries the same wording. The others follow the same except ...: return str(value) shape, so graceful degradation is clearly the intent throughout; OverflowError simply isn't in the tuple.

clamp and metric annotate value: float, so arguably a large int is outside their contract — I've listed them for completeness rather than as a claim.

Related work already in flight

So apnumber, fractional and scientific are the ones not currently covered by an open PR. I'll put up a PR for apnumber and fractional, where the correct result is unambiguous.

scientific is worth separating: falling back to str(value) there would return 401 digits from a function whose purpose is compact notation, so it probably wants Decimal-based formatting (1.00 x 10⁴⁰⁰) rather than a fallback. Happy to follow up with that if the approach sounds right.

Verified on main at 392aef7, Python 3.12.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions