Repository: astropy/astropy

Issue:
# BUG: incoming deprecation warnings from numpy 2.5 (dev): direct mutations to array shape attributes are deprecated

xref: https://github.com/numpy/numpy/pull/29536

this PR (just merged) breaks about 150 tests throughout astropy. Some deprecations are more easily handled than others, so I'll start with the easy ones to reduce the number of failures so we can streamline the discussion where it's really needed.

upstream reports/PRs:
- https://github.com/brandon-rhodes/python-jplephem/issues/63
- https://github.com/brandon-rhodes/python-jplephem/pull/64

linked PRs:
- #19127 
- #19128 
- #19129 
- #19130 
- #19131 
- #19132 
- #19152
- #19158
- #19182 
- #19184
- #19187

Implementation patch:
diff --git a/astropy/utils/masked/function_helpers.py b/astropy/utils/masked/function_helpers.py
index 7cdec60111e3..08e5ad856be7 100644
--- a/astropy/utils/masked/function_helpers.py
+++ b/astropy/utils/masked/function_helpers.py
@@ -17,7 +17,7 @@
 from numpy.lib._function_base_impl import _quantile_is_valid, _ureduce
 
 from astropy.units.quantity_helper.function_helpers import FunctionAssigner
-from astropy.utils.compat import NUMPY_LT_2_1, NUMPY_LT_2_2, NUMPY_LT_2_4
+from astropy.utils.compat import NUMPY_LT_2_1, NUMPY_LT_2_2, NUMPY_LT_2_4, NUMPY_LT_2_5
 
 # This module should not really be imported, but we define __all__
 # such that sphinx can typeset the functions with docstrings.
@@ -1427,7 +1427,10 @@ def in1d(ar1, ar2, assume_unique=False, invert=False, *, kind=None):
 def isin(element, test_elements, assume_unique=False, invert=False, *, kind=None):
     element = np.asanyarray(element)
     result = _in1d(element, test_elements, assume_unique, invert, kind=kind)
-    result.shape = element.shape
+    if NUMPY_LT_2_5:
+        result.shape = element.shape
+    else:
+        result._set_shape(element.shape)
     return result, _copy_of_mask(element), None
 
 


Test patch:
diff --git a/astropy/utils/masked/tests/test_masked.py b/astropy/utils/masked/tests/test_masked.py
index 4cd7ca309980..c9dc2c5c5bc7 100644
--- a/astropy/utils/masked/tests/test_masked.py
+++ b/astropy/utils/masked/tests/test_masked.py
@@ -14,7 +14,7 @@
 from astropy import units as u
 from astropy.coordinates import Longitude
 from astropy.units import Quantity
-from astropy.utils.compat import NUMPY_LT_2_2, NUMPY_LT_2_3
+from astropy.utils.compat import NUMPY_LT_2_1, NUMPY_LT_2_2, NUMPY_LT_2_3
 from astropy.utils.compat.optional_deps import HAS_PLT
 from astropy.utils.masked import Masked, MaskedNDArray
 
@@ -304,8 +304,11 @@ def test_viewing(self):
 
     def test_viewing_independent_shape(self):
         mms = Masked(self.a, mask=self.m)
-        mms2 = mms.view()
-        mms2.shape = mms2.shape[::-1]
+        if NUMPY_LT_2_1:
+            mms2 = mms.view()
+            mms2.shape = mms2.shape[::-1]
+        else:
+            mms2 = np.reshape(mms, mms.shape[::-1], copy=False)
         assert mms2.shape == mms.shape[::-1]
         assert mms2.mask.shape == mms.shape[::-1]
         # This should not affect the original array!
@@ -563,14 +566,21 @@ def test_reshape(self):
         assert_array_equal(ma_reshape.mask, expected_mask)
 
     def test_shape_setting(self):
-        ma_reshape = self.ma.copy()
-        ma_reshape.shape = (6,)
+        if NUMPY_LT_2_1:
+            ma_reshape = self.ma.copy()
+            ma_reshape.shape = (6,)
+        else:
+            ma_reshape = np.reshape(self.ma, (6,), copy=True)
+
         expected_data = self.a.reshape((6,))
         expected_mask = self.mask_a.reshape((6,))
         assert ma_reshape.shape == expected_data.shape
         assert_array_equal(ma_reshape.unmasked, expected_data)
         assert_array_equal(ma_reshape.mask, expected_mask)
 
+    @pytest.mark.filterwarnings(
+        "default:Setting the shape on a NumPy array has been deprecated in NumPy 2.5:DeprecationWarning"
+    )
     def test_shape_setting_failure(self):
         ma = self.ma.copy()
         with pytest.raises(ValueError, match="cannot reshape"):