Skip to content

Commit 1edf7b6

Browse files
committed
Refine int checks (a bit annoyingly).
1 parent 86662bf commit 1edf7b6

2 files changed

Lines changed: 17 additions & 2 deletions

File tree

numpy/_core/src/multiarray/descriptor.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2553,13 +2553,21 @@ arraydescr_new(PyTypeObject *subtype,
25532553
/*
25542554
* In the future, reject non Python (or NumPy) boolean, including integers to avoid any
25552555
* possibility of thinking that an integer alignment makes sense here.
2556+
* We omit the case of `oalign == 0` and `ocopy == 1` if there are exact ints.
2557+
* This can fail, in which case res is -1 and we enter the deprecation path.
25562558
*/
2559+
int res = 0;
2560+
int overflow;
25572561
if (!PyBool_Check(oalign) && !PyArray_IsScalar(oalign, Bool) && !(
25582562
// Some old pickles use 0, 1 exactly, assume no user passes it
25592563
// (It may also be possible to use `copyreg` instead.)
2560-
PyLong_CheckExact(oalign) && PyLong_AsLong(oalign) == 0 &&
2561-
ocopy != NULL && PyLong_CheckExact(ocopy) && PyLong_AsLong(ocopy) == 1)) {
2564+
PyLong_CheckExact(oalign) && (res = PyLong_IsZero(oalign)) == 1 &&
2565+
ocopy != NULL && PyLong_CheckExact(ocopy) &&
2566+
(res = PyLong_AsLongAndOverflow(ocopy, &overflow)) == 1)) {
25622567
/* Deprecated 2025-07-01: NumPy 2.4 */
2568+
if (res == -1 && PyErr_Occurred()) {
2569+
return NULL; // Should actually be impossible (as inputs are `long`)
2570+
}
25632571
if (PyErr_WarnFormat(npy_static_pydata.VisibleDeprecationWarning, 1,
25642572
"dtype(): align should be passed as Python or NumPy boolean but got `align=%.100R`. "
25652573
"Did you mean to pass a tuple to create a subarray type? (Deprecated NumPy 2.4)",

numpy/_core/tests/test_deprecations.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,11 +280,18 @@ def test_deprecated(self):
280280
# alignment, or pass them accidentally as a subarray shape (meaning to pass
281281
# a tuple).
282282
self.assert_deprecated(lambda: np.dtype("f8", align=3))
283+
self.assert_deprecated(lambda: np.dtype("f8", align=0, copy=10**100))
284+
self.assert_deprecated(lambda: np.dtype("f8", align=10**100, copy=0))
285+
# Subclasses of ints don't hit the below pickle code path:
286+
self.assert_deprecated(
287+
lambda: np.dtype("f8", align=np.long(0), copy=np.long(1)))
283288

284289
@pytest.mark.parametrize("align", [True, False, np.True_, np.False_])
285290
def test_not_deprecated(self, align):
286291
# if the user passes a bool, it is accepted.
287292
self.assert_not_deprecated(lambda: np.dtype("f8", align=align))
293+
# The following specific case is used by old pickles:
294+
self.assert_not_deprecated(lambda: np.dtype("f8", align=0, copy=1))
288295

289296

290297
class TestFlatiterIndexing0dBoolIndex(_DeprecationTestCase):

0 commit comments

Comments
 (0)