Skip to content

BUG: np.take out dtype - #30615

Merged
seberg merged 5 commits into
numpy:mainfrom
himanow:take_out_dtype
Mar 24, 2026
Merged

BUG: np.take out dtype#30615
seberg merged 5 commits into
numpy:mainfrom
himanow:take_out_dtype

Conversation

@himanow

@himanow himanow commented Jan 9, 2026

Copy link
Copy Markdown
Contributor

Description

This PR addresses the issue in np.take where an error was raised when input and output dtypes were different during casting.

Key changes:

  • Allows 'same-kind' casting to proceed in np.take.
  • Emits a DeprecationWarning for other casting types to maintain backward compatibility while signaling future changes.

This is my first contribution to NumPy, so I'm opening this as a draft to ensure the implementation and formatting align with the project's standards. I'd appreciate any feedback on the code or the CI results.

Fixes

Closes #25588

@jorenham

This comment was marked as outdated.

@himanow

himanow commented Jan 11, 2026

Copy link
Copy Markdown
Contributor Author

I rebased my branch onto the latest main, and all CI/CD checks are now passing

@jorenham
jorenham marked this pull request as ready for review January 11, 2026 10:12
Comment thread numpy/_core/tests/test_regression.py Outdated
raise AssertionError("compress with an out which cannot be "
"safely casted should not return "
"successfully")
assert_equal(b, np.array([[1.0], [3.0]]))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you please explain this change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The compress method uses PyArray_TakeFrom internally. Since it no longer raises an error after my changes, I have updated the test to verify that the output values match the expected results.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

OK, I guess this is fine to generalize. We may want to tighten the casting from same-kind at some point, but I don't think we have to worry about it now.

assert_array_equal(a[indices], out)
diffrent_dtype_out = np.zeros_like(indices, dtype=np.uint32)
with pytest.warns(DeprecationWarning):
np.take(a, indices, out=diffrent_dtype_out)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please move this test to test_deprecations and use the pattern used there.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit 0029b81. Could you please check if the implementation and coding style are correct?

"Implicit casting of output to a different kind is "
"deprecated. "
"In a future version, this will result in an error. Please "
"ensure the output has the same-kind type as the input.") <

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please add the comments we usually add to say when the deprecation happened (before it) and also inside the deprecation itself, such as (deprecated NumPy 2.5).

The last sentence feels like unnecessary to me. (I should think once more if we shouldn't just use safe casting, although then one might be tempted to ask for a casting= kwarg.)

@himanow himanow Jan 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit 0029b81. I removed the last sentence.

@@ -311,7 +311,25 @@ PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis,
}
dtype = PyArray_DESCR(self);
Py_INCREF(dtype);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This needs cleaning up, you are inserting code but that code interacts closely with this so you can't insert code between these two lines.
I.e. the dtype reference can be lost on error.

@himanow himanow Jan 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 0029b81. Is it safe to insert code between dtype = PyArray_DESCR(self); and Py_INCREF(dtype);? Also, is the line Py_INCREF(out_dtype); unnecessary or redundant here?

}
}
flags |= NPY_ARRAY_FORCECAST;
obj = (PyArrayObject *)PyArray_FromArray(out, dtype, flags);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is the exact same code as the first branch, except for a flag that is irrelevant in the first branch.

@himanow himanow Jan 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit 0029b81.

@himanow

himanow commented Jan 17, 2026

Copy link
Copy Markdown
Contributor Author

Thank you for the detailed feedback. I have pushed the fixes in the latest commit.

@seberg seberg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks a few nits, mainly the refcount addition is incorrect and I think it would be good to add a test that goes across kind boundaries (if you looked at it the other way).

flags |= NPY_ARRAY_FORCECAST;
}
Py_INCREF(dtype);
Py_INCREF(out_dtype);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This incref isn't necessary here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 6f40af4.

if (DEPRECATE(
"Implicit casting of output to a different kind is "
"deprecated. "
"In a future version, this will result in an error. (Deprecated NumPy 2.5)") <

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you format this a bit prettier? (e.g. start at smaller indent, don't break the line when there is no \n anyway.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 6f40af4.

dtype = PyArray_DESCR(self);
out_dtype = PyArray_DESCR(out);
if (dtype != out_dtype) {
/*Deprecated NumPy 2.5, 2026-01*/

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/*Deprecated NumPy 2.5, 2026-01*/
/* Deprecated NumPy 2.5, 2026-01 */

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

"Updated as suggested."

out_dtype = PyArray_DESCR(out);
if (dtype != out_dtype) {
/*Deprecated NumPy 2.5, 2026-01*/
if (PyArray_CanCastTypeTo(dtype, out_dtype, NPY_SAME_KIND_CASTING) == 0) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Most code uses !PyArray_... for this type of pattern, so I would stick to it here too. (The < 0 is very common for errors.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 6f40af4. I've updated this to follow the !PyArray_... pattern.

Comment thread numpy/_core/tests/test_regression.py Outdated
raise AssertionError("compress with an out which cannot be "
"safely casted should not return "
"successfully")
assert_equal(b, np.array([[1.0], [3.0]]))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

OK, I guess this is fine to generalize. We may want to tighten the casting from same-kind at some point, but I don't think we have to worry about it now.

Comment thread numpy/_core/tests/test_deprecations.py Outdated

self.assert_deprecated(
np.take, args=(a, indices), kwargs={"out": diffrent_dtype_out}
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

different_dtype_out or just shorten (small typo). This is good as is, but while I wrote this args/kwargs, I actually like the pattern we use a lot more to just use a lambda, i.e. passing lambda: np.take(a, indices, out=out) (it even ends up shorter!)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 6f40af4. I've renamed the variable to different_dtype_out. I also switched to the lambda pattern as you suggested—it definitely looks much cleaner and more concise.

Comment thread numpy/_core/tests/test_item_selection.py
@himanow

himanow commented Feb 1, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review. I’ve updated the PR and addressed each comment.

@himanow

himanow commented Feb 23, 2026

Copy link
Copy Markdown
Contributor Author

I have resolved the merge conflicts and rebased the branch onto the latest main.
CI is still in progress, but the PR is ready for further review.
I will keep monitoring the test results. Thank you.

@himanow

himanow commented Mar 15, 2026

Copy link
Copy Markdown
Contributor Author

Hi @seberg , sorry for the ping, but I'm just checking in to see if there's anything else I should update for this PR. I’d appreciate any feedback when you have a moment"

@seberg

seberg commented Mar 17, 2026

Copy link
Copy Markdown
Member

Sorry, I forgot about this. We have conflicts now, and it would make sense to add a very brief (single bullet point is OK) release note for the new deprecation.
But yeah, I think this is good and I can make sure to just do those follow ups myself some time.

@seberg seberg added this to the 2.5.0 Release milestone Mar 17, 2026
@himanow

himanow commented Mar 20, 2026

Copy link
Copy Markdown
Contributor Author

Thank you! I appreciate you taking care of the conflicts and the release note. I look forward to it.

himanow and others added 5 commits March 24, 2026 16:27
Previously, an error was raised when the input and output dtypes were different during casting.
This change allows 'same-kind' casting to proceed while issuing a
DeprecationWarning for other casting types to maintain backward
compatibility while signaling future changes.

Closes numpy#25588
@seberg
seberg merged commit e87d0e0 into numpy:main Mar 24, 2026
79 checks passed
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.

BUG: np.take cast to out argument

3 participants