Skip to content

ENH: mark fixed-width string to StringDType casts as safe - #32095

Merged
ngoldbaum merged 4 commits into
numpy:mainfrom
ngoldbaum:fixed-width-T-casts
Aug 28, 2026
Merged

ngoldbaum merged 4 commits into
numpy:mainfrom
ngoldbaum:fixed-width-T-casts

Conversation

@ngoldbaum

@ngoldbaum ngoldbaum commented Jul 24, 2026 •

Copy link
Copy Markdown
Member

PR summary

Towards fixing #32031.

This is one half of what #32031 proposes. The implementation ended up allowing me to delete a bunch of code, since the function I'm changing was the only customer of an old helper function that I inlined. I also made the void and bytes casts share the same loop, although I'm not touching void cast safety here.

AI Disclosure

I used an AI model to help debug the change.

@ngoldbaum ngoldbaum added 01 - Enhancement 56 - Needs Release Note. Needs an entry in doc/release/upcoming_changes component: numpy.strings String dtypes and functions and removed 56 - Needs Release Note. Needs an entry in doc/release/upcoming_changes labels Jul 24, 2026

@MaanasArora MaanasArora 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.

Thanks, just a few typos an AI agent found but looks good to me! Largely seems straightforward as a new function + merge. I don't know too much about RAII, but seemed fine from a brief look, and the early returns are nice :)

Approving, I think both #32097 and this are ready!

@@ -0,0 +1,12 @@
Casting and validation changes for fixed-width to variable-width string conversions
-----------------------------------------------------------------------------------
* Casts from fixed-width `numpy.bytes_` and `nummpy.str_` arrays to

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.

Suggested change
* Casts from fixed-width `numpy.bytes_` and `nummpy.str_` arrays to
* Casts from fixed-width `numpy.bytes_` and `numpy.str_` arrays to

* Casts from fixed-width `numpy.bytes_` and `nummpy.str_` arrays to
`numpy.dtypes.StringDType` are now considered `"safe"` rather than
`"same-kind"`.
* These cast from `numpy.bytes_` to `numpy.dtypes.StringDType` now validates the

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.

Suggested change
* These cast from `numpy.bytes_` to `numpy.dtypes.StringDType` now validates the
* These casts from `numpy.bytes_` to `numpy.dtypes.StringDType` now validate the

@ngoldbaum ngoldbaum added this to the 2.6.0 Release milestone Aug 24, 2026

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

Looks very nice! I have one question/suggestion about the error handling, the other comment is just that, a comment and not-directly-relevant query.

PyObject *decoded = PyUnicode_Decode(bad, bad_size, "utf-8",
"strict");
PyMem_RawFree(bad);
if (decoded != NULL) {

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.

Shouldn't one always have decoded == NULL? I.e., does the existence of this branch mean the above succeeded? Isn't that weird enough to give a RuntimeError instead, asking to report?

@ngoldbaum ngoldbaum Aug 28, 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.

This is mostly here defensively and indeed it shouldn't be possible to get here if NumPy's UTF-8 validation is working correctly.

I asked an AI to come up with a scenario that triggers this, and it turns out that you can actually add error handlers for python's UTF-8 validation: https://docs.python.org/3/library/codecs.html#codecs.register_error. If someone added their own error handler (why??) it's possible this error could happen.

We could also get here if there's a multithreaded race to wrote to a np.bytes_ array while a simultaneous cast to StringDType is running.

Both of those aren't a NumPy bug and it would be confusing if the error was written like it has to be.

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.

Ah, I see, but then my suggestion of a RuntimeError saying something weird happened is probably more appropriate. Interesting that it is possible at all...

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.

Fair enough. I just made it a RuntimeError.

npy_gil_error(PyExc_TypeError,
"Invalid UTF-8 bytes found, cannot convert to UTF-8");
goto fail;
np::raii::NpyStringAcquireAllocator alloc(descr);

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 guess there has been a change here that I missed! Is this new way of dealing with the allocator used everywhere, or are you just changing as you touch relevant code?

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.

@WarrenWeckesser added it late last year. I think it makes sense to use it in C++ files like this one.

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

OK, as that was my only remaining comment, now all OK. Feel free to merge once the tests have run.

@ngoldbaum
ngoldbaum merged commit 8a53c5b into numpy:main Aug 28, 2026
90 checks passed
@ngoldbaum

Copy link
Copy Markdown
Member Author

Thanks all, I really appreciate the help and advice you both have been giving me for the StringDType improvements I've been doing this summer.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants