Skip to content

Raise NumOutOfRangeError from tenfn instead of leaking IndexError (#242) - #271

Open
chiliec wants to merge 1 commit into
jaraco:mainfrom
chiliec:fix/issue-242-numoutofrange-in-tenfn
Open

chiliec wants to merge 1 commit into
jaraco:mainfrom
chiliec:fix/issue-242-numoutofrange-in-tenfn

Conversation

@chiliec

@chiliec chiliec commented Aug 27, 2026

Copy link
Copy Markdown

Fixes #242.

Problem

number_to_words documents (and imports/advertises) NumOutOfRangeError for out-of-range inputs, but for numbers requiring a magnitude index beyond the largest scale word it leaks an uncaught IndexError instead:

import inflect
p = inflect.engine()
p.number_to_words(10**40)
# Expected: NumOutOfRangeError
# Actual:   IndexError: list index out of range  (from tenfn)

10**36 raises NumOutOfRangeError correctly; 10**40 and above do not.

Root cause

millfn performs the bounds check and raises NumOutOfRangeError:

def millfn(self, ind: int = 0) -> str:
    if ind > len(mill) - 1:
        raise NumOutOfRangeError
    return mill[ind]

Every scale-word lookup goes through it — except the teen branch of tenfn (tens == 1), which indexed the table directly:

return f"{teen[units]}{mill[mindex]}"   # unchecked

so an out-of-range mindex raised IndexError from that line rather than the documented error.

Fix

Route the lookup through millfn, matching every other path:

return f"{teen[units]}{self.millfn(mindex)}"

Tests

  • test_tenfn: the teen branch now raises NumOutOfRangeError for an out-of-range magnitude.
  • test_issue_242: number_to_words(10**36 / 10**40 / 10**100) all raise NumOutOfRangeError, and number_to_words(10**33) still returns "one decillion".

Adds a newsfragments/242.bugfix.rst.

Verification (local, Python 3.11)

  • RED→GREEN: with the fix reverted, both new tests fail with IndexError at the tenfn line; with the fix they pass.
  • Full suite: pytest — 215 passed, 16 xfailed, no regressions.
  • ruff introduces no new findings on the changed line.

tenfn's teen branch (tens == 1) indexed the mill table directly with
mill[mindex] rather than through millfn, which performs the range check.
For numbers requiring a magnitude index beyond the largest scale word
(roughly 10**37 and above), this leaked an uncaught IndexError instead of
the documented NumOutOfRangeError that number_to_words advertises.

Route the lookup through millfn so the teen branch raises the same
documented error as every other path.

Adds a regression test at both the tenfn and number_to_words levels, plus
a news fragment.

Fixes jaraco#242.

@CAOShurong CAOShurong left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Verified independently (no run, no claim). I cloned the repo and checked out the PR head 3db76f5d (3db76f5dbfe1526fbc0cb05b251b3abc3b9b5d77).

Root cause matches the PR description exactly: the teen branch of tenfn indexed mill[mindex] directly instead of routing through millfn() (which is the only path that raises the documented NumOutOfRangeError). So inputs whose magnitude index exceeds len(mill) - 1 leaked an uncaught IndexError instead of the advertised error type.

Reproduction (RED on base 262a247d):

  • inflect.engine().number_to_words(10**40) raises IndexError: list index out of range at inflect/__init__.py:3699 (the mill[mindex] line).
  • New tests/test_numwords.py::test_issue_242 FAILS on base with that same IndexError.

GREEN at the PR head:

  • git checkout 3db76f5dtests/test_numwords.py::test_issue_242 and the tests/test_pwd.py tenfn assertion both pass.
  • Full suite via uv run --with pytest --with more-itertools python -m pytest tests/: 172 passed, 16 xfailed, no regressions (the new test_issue_242 + test_pwd additions included).

The fix is a 1-line change that routes the lookup through self.millfn(mindex), consistent with every other scale-word path, and it adds a newsfragments/242.bugfix.rst changelog entry. Small, correct, and well-tested. Approved.

(AI assistance used to collect verification evidence; the fix and tests are the author's.)

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.

number_to_words leaks IndexError instead of NumOutOfRangeError for huge inputs

2 participants