@@ -341,16 +341,11 @@ array_nbytes_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
341341 * (contiguous or fortran) with compatible dimensions The shape and strides
342342 * will be adjusted in that case as well.
343343 */
344- static int
345- array_descr_set (PyArrayObject * self , PyObject * arg , void * NPY_UNUSED ( ignored ) )
344+ NPY_NO_EXPORT int
345+ array_descr_set_internal (PyArrayObject * self , PyObject * arg )
346346{
347347 PyArray_Descr * newtype = NULL ;
348-
349- if (arg == NULL ) {
350- PyErr_SetString (PyExc_AttributeError ,
351- "Cannot delete array dtype" );
352- return -1 ;
353- }
348+ assert (arg );
354349
355350 if (!(PyArray_DescrConverter (arg , & newtype )) ||
356351 newtype == NULL ) {
@@ -496,6 +491,43 @@ array_descr_set(PyArrayObject *self, PyObject *arg, void *NPY_UNUSED(ignored))
496491 return -1 ;
497492}
498493
494+ static int
495+ non_unique_reference (PyObject * lhs )
496+ {
497+ // Return 1 if we have a guaranteed non-unique reference
498+ // When 0 is returned, the object can be unique or non-unique
499+ #if defined(PYPY_VERSION )
500+ // on pypy we cannot use reference counting
501+ return 0 ;
502+ #endif
503+ return Py_REFCNT (lhs ) > 1 ;
504+ }
505+
506+ static int
507+ array_descr_set (PyArrayObject * self , PyObject * arg )
508+ {
509+ if (arg == NULL ) {
510+ PyErr_SetString (PyExc_AttributeError ,
511+ "Cannot delete array dtype" );
512+ return -1 ;
513+ }
514+
515+ if (non_unique_reference ((PyObject * )self )) {
516+ // this will not emit deprecation warnings for all cases, but for most it will
517+ // we skip unique references, so that we will not get a deprecation warning
518+ // when array.view(new_dtype) is called
519+ /* DEPRECATED 2026-02-06, NumPy 2.5 */
520+ int ret = PyErr_WarnEx (PyExc_DeprecationWarning ,
521+ "Setting the dtype on a NumPy array has been deprecated in NumPy 2.4.\n"
522+ "Instead of changing the dtype on an array x, create a new array with x.view(new_dtype)" ,
523+ 1 );
524+ if (ret ) {
525+ return -1 ;
526+ }
527+ }
528+ return array_descr_set_internal (self , arg );
529+ }
530+
499531static PyObject *
500532array_struct_get (PyArrayObject * self , void * NPY_UNUSED (ignored ))
501533{
0 commit comments