Skip to content

BUG: Reset an unrepresentable fill_value on a dtype change (#32508) - #32557

Merged
charris merged 3 commits into
numpy:maintenance/2.5.xfrom
charris:backport-32508-32358
Sep 10, 2026
Merged

charris merged 3 commits into
numpy:maintenance/2.5.xfrom
charris:backport-32508-32358

Conversation

@charris

@charris charris commented Sep 9, 2026

Copy link
Copy Markdown
Member

Backport of #32508 and #32358.

PR summary

As discussed in gh-28255. Since #32423, MaskedArray._update_from validates an inherited fill_value against the new dtype and falls back to the default when the cast fails. It decides "fails" by catching an exception, which misses casts that fail through the floating point error state instead.

>>> a = np.ma.arange(9.0)
>>> np.ones_like(a, dtype='int64').fill_value
np.int64(999999)
>>> a.fill_value          # only reads it
np.float64(1e+20)
>>> np.ones_like(a, dtype='int64').fill_value
RuntimeWarning: invalid value encountered in cast
np.int64(-9223372036854775808)

1e20 is not a value the user picked, it is the default fill_value for float64, and reading the attribute stores it as a 0-d array. Casting that stored np.float64(1e20) to int64 does not raise: it sets the invalid flag, warns, and returns an out-of-range integer (INT64_MIN on x86; INT64_MAX on the macOS machine in the issue thread). A Python float 1e20 passed directly goes through the scalar path and raises, which is why fill_value=1e20 at construction already fails cleanly.

This wraps that call in np.errstate(invalid='raise') and adds FloatingPointError to the except clause, so the fallback added in #32423 also runs for this case.

Scope:

Tests: the new test compares against the result when fill_value was never read rather than against a specific number, so it does not depend on the platform or on the default integer width. In gh-28255 I said this would not touch existing tests; running the full numpy/ma suite showed that TestMaskedArrayFunctions.test_where in numpy/ma/tests/test_core.py asserted the RuntimeWarning from exactly this cast (set_fill_value(1e20) followed by astype(int)). It now asserts that the cast emits no warning and that ixm.fill_value is the default for the new dtype. The rest of numpy/ma passes unchanged (run against 2.5.2 with the change applied).

Fixes #28255

First time committer introduction

Not my first PR (#32405 was a whitespace fix), but my first change to numpy.ma. I came to numpy.ma through gh-15601, which I am also preparing a fix for, and found this one while going through open ma issues around the time #32423 was being reviewed.

AI Disclosure

I used Claude throughout: to help investigate the cause, to draft the two-line change, the tests, and the release note from my notes, and to put this description and the code comments into English. I reviewed and applied the changes, and ran the reproducer, the new tests, and the numpy/ma suite myself.

danggeun and others added 3 commits September 9, 2026 10:16
The backport of numpy#32508 brought with it a number of new tests, this
fixes a test failure by adding a needed import.
@charris charris added this to the 2.5.4 release milestone Sep 9, 2026
@charris charris added 00 - Bug 08 - Backport Used to tag backport PRs labels Sep 9, 2026
@charris
charris merged commit 421a366 into numpy:maintenance/2.5.x Sep 10, 2026
84 checks passed
@charris
charris deleted the backport-32508-32358 branch September 10, 2026 01:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

00 - Bug 08 - Backport Used to tag backport PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants