DEP: Correct dtype in `__array_finalize__` if _set_dtype=None by seberg · Pull Request #31293 · numpy/numpy · GitHub
Skip to content

DEP: Correct dtype in __array_finalize__ if _set_dtype=None - #31293

Merged
seberg merged 4 commits into
numpy:mainfrom
seberg:no-array-finalize-dtype
Apr 21, 2026
Merged

seberg merged 4 commits into
numpy:mainfrom
seberg:no-array-finalize-dtype

Conversation

@seberg

@seberg seberg commented Apr 21, 2026

Copy link
Copy Markdown
Member

This avoids using the correct dtype in array_finalize unless _set_dtype = None is set on the class.
We also use this new path to make record arrays follow the main class deprecation correctly.

This means that recarray does live in the future.

CC @mhvk, hopefully the last iteration (unless the larger view change works out)...

(no AI tool use)

Closes gh-31281

seberg added 2 commits April 21, 2026 12:20
This avoids using the correct dtype in __array_finalize__ *unless*
`_set_dtype = None` is set on the class.
We also use this new path to make record arrays follow the main
class deprecation correctly.

This means that `recarray` does live in the future.
@seberg

seberg commented Apr 21, 2026

Copy link
Copy Markdown
Member Author

Comment thread numpy/_core/records.py Outdated

def __array_finalize__(self, obj):
if self.dtype.type is not record and self.dtype.names is not None:
if issubclass(self.dtype.type, nt.void) and self.dtype.names is not None:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is the logic used in __setattr__, basically the same I guess, but thought I'd just copy paste it.

@seberg seberg Apr 21, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

EDIT: Actually, no, I'll just undo this to avoid creating a new dtype here if it isn't necessary. After that dtype.type is always record, so that check should be enough.

Made it to have both checks. The second one is needed for some ridiculous tests to pass, but the original one is definitely OK as a fast-path.

@seberg
seberg force-pushed the no-array-finalize-dtype branch from ddec556 to 6895cbc Compare April 21, 2026 11:03

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This does seem a good path forward! My comments are minimal, mostly about comments, so will approve now.

p.s. I may still follow up with changing the dims & strides beforehand.

* Set ``_set_dtype = None`` in which case ``arr.view(dtype=new_dtype)``
will call ``__array_finalize__`` with the new dtype, ensuring that
any validation ``__array_finalize__`` will run is done.
* Define ``_set_dtype`` as a function (calling ``ndarray._set_dtype()``

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How about, "Of, for a quick fix to avoid DeprecationWarning, define ..."

Comment thread numpy/_core/src/multiarray/convert.c Outdated
* setter): create subclass view first, use the setter, but
* emit a deprecation asking to implement _set_dtype instead.
* 3. Otherwise (including plain ndarray): create an ndarray base
* 3. If _set_dtype is None (or base-class): create an ndarray base

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think "or base-class" is incorrect, otherwise how would one ever get to path 4?

Comment thread numpy/_core/src/multiarray/convert.c Outdated
* 3. If _set_dtype is None (or base-class): create an ndarray base
* view, set dtype internally, then create the subclass view
* if needed. __array_finalize__ sees the final dtype+shape.
* 4. Otherwise, call `__array_finalize__` with old dtype and forcibly

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe you meant to write it here, like If _set_dtype is NULL or base-class: ...

Comment thread numpy/_core/src/multiarray/convert.c Outdated
* with correct dtype+shape, this will call `__array_finalize__`
* with the final dtype+shape.
*/
if (use_dtype_in_finalize && subtype != &PyArray_Type) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

use_dtype_in_finalize can only be set if it is a subclass, so second part can be omitted.

@seberg
seberg merged commit 388bd75 into numpy:main Apr 21, 2026
86 checks passed
@seberg
seberg deleted the no-array-finalize-dtype branch April 21, 2026 14:57
@mhvk

mhvk commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

MaanasArora pushed a commit to MaanasArora/numpy that referenced this pull request May 7, 2026
…31293)

This avoids using the correct dtype in array_finalize unless _set_dtype = None is set on the class.
We also use this new path to make record arrays follow the main class deprecation correctly.

This means that recarray does live in the future.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: a regression from gh-31234 seen in astropy (broadcasting error while creating views of a Masked array)

3 participants