From b6deb07fbfed9310a4be9394255f92536ff46d96 Mon Sep 17 00:00:00 2001 From: Pey Lian Lim <2090236+pllim@users.noreply.github.com> Date: Mon, 28 Aug 2023 21:03:32 -0400 Subject: [PATCH] NumPy 2.0 also moved function_base Handle warning in test_bounds_gauss2d_lsq that is flaky and we do not really care for, so just ignore it. --- astropy/modeling/tests/test_constraints.py | 21 ++++-------- .../units/quantity_helper/function_helpers.py | 2 +- astropy/utils/masked/core.py | 15 +++++++-- astropy/utils/masked/function_helpers.py | 33 ++++++++++++++----- 4 files changed, 43 insertions(+), 28 deletions(-) diff --git a/astropy/modeling/tests/test_constraints.py b/astropy/modeling/tests/test_constraints.py index 2ddcf37d607..fd7699cee4b 100644 --- a/astropy/modeling/tests/test_constraints.py +++ b/astropy/modeling/tests/test_constraints.py @@ -15,7 +15,6 @@ from astropy.modeling.core import Fittable1DModel from astropy.modeling.parameters import Parameter from astropy.utils import minversion -from astropy.utils.compat.numpycompat import NUMPY_LT_2_0 from astropy.utils.compat.optional_deps import HAS_SCIPY from astropy.utils.exceptions import AstropyUserWarning @@ -184,6 +183,7 @@ def test_bounds_slsqp(self): assert intercept + 10**-5 >= bounds["intercept"][0] assert intercept - 10**-5 <= bounds["intercept"][1] + @pytest.mark.filterwarnings("ignore:The fit may be unsuccessful") @pytest.mark.parametrize("fitter", fitters) def test_bounds_gauss2d_lsq(self, fitter): fitter = fitter() @@ -204,21 +204,12 @@ def test_bounds_gauss2d_lsq(self, fitter): theta=0.5, bounds=bounds, ) - if isinstance(fitter, (fitting.LevMarLSQFitter, fitting.DogBoxLSQFitter)): - with pytest.warns(AstropyUserWarning, match="The fit may be unsuccessful"): - model = fitter(gauss, X, Y, self.data) + if isinstance(fitter, fitting.TRFLSQFitter): + ctx = np.errstate(invalid="ignore", divide="ignore") else: - ctx2 = nullcontext() - if isinstance(fitter, fitting.TRFLSQFitter): - ctx = np.errstate(invalid="ignore", divide="ignore") - if not NUMPY_LT_2_0 or not SCIPY_LT_1_11_2: - ctx2 = pytest.warns( - AstropyUserWarning, match="The fit may be unsuccessful" - ) - else: - ctx = nullcontext() - with ctx, ctx2: - model = fitter(gauss, X, Y, self.data) + ctx = nullcontext() + with ctx: + model = fitter(gauss, X, Y, self.data) x_mean = model.x_mean.value y_mean = model.y_mean.value x_stddev = model.x_stddev.value diff --git a/astropy/units/quantity_helper/function_helpers.py b/astropy/units/quantity_helper/function_helpers.py index 3919ec8b778..b36d023d327 100644 --- a/astropy/units/quantity_helper/function_helpers.py +++ b/astropy/units/quantity_helper/function_helpers.py @@ -442,7 +442,7 @@ def select(condlist, choicelist, default=0): def piecewise(x, condlist, funclist, *args, **kw): from astropy.units import Quantity - # Copied implementation from numpy.lib.function_base.piecewise, + # Copied implementation from numpy.lib._function_base_impl.piecewise, # taking care of units of function outputs. n2 = len(funclist) # undocumented: single condition is promoted to a list of one condition diff --git a/astropy/utils/masked/core.py b/astropy/utils/masked/core.py index e9a30cec583..51c7feecc20 100644 --- a/astropy/utils/masked/core.py +++ b/astropy/utils/masked/core.py @@ -19,6 +19,7 @@ import numpy as np +from astropy.utils.compat import NUMPY_LT_2_0 from astropy.utils.data_info import ParentDtypeInfo from astropy.utils.shapes import NDArrayShapeMethods @@ -759,9 +760,17 @@ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): else: # Parse signature with private numpy function. Note it # cannot handle spaces in tuples, so remove those. - in_sig, out_sig = np.lib.function_base._parse_gufunc_signature( - ufunc.signature.replace(" ", "") - ) + if NUMPY_LT_2_0: + in_sig, out_sig = np.lib.function_base._parse_gufunc_signature( + ufunc.signature.replace(" ", "") + ) + else: + ( + in_sig, + out_sig, + ) = np.lib._function_base_impl._parse_gufunc_signature( + ufunc.signature.replace(" ", "") + ) axis = kwargs.get("axis", -1) keepdims = kwargs.get("keepdims", False) in_masks = [] diff --git a/astropy/utils/masked/function_helpers.py b/astropy/utils/masked/function_helpers.py index ce6ef0285f1..d13bde30634 100644 --- a/astropy/utils/masked/function_helpers.py +++ b/astropy/utils/masked/function_helpers.py @@ -93,7 +93,7 @@ np.isclose, np.allclose, np.flatnonzero, np.argwhere, # np.core.shape_base np.atleast_1d, np.atleast_2d, np.atleast_3d, np.stack, np.hstack, np.vstack, - # np.lib.function_base + # np.lib._function_base_impl np.average, np.diff, np.extract, np.meshgrid, np.trapz, np.gradient, # np.lib.index_tricks np.diag_indices_from, np.triu_indices_from, np.tril_indices_from, @@ -108,7 +108,7 @@ np.real_if_close, np.common_type, # np.lib.ufunclike np.fix, np.isneginf, np.isposinf, - # np.lib.function_base + # np.lib._function_base_impl np.angle, np.i0, } # fmt: skip IGNORED_FUNCTIONS = { @@ -121,7 +121,7 @@ IGNORED_FUNCTIONS |= { np.pad, np.searchsorted, np.digitize, np.is_busday, np.busday_count, np.busday_offset, - # numpy.lib.function_base + # numpy.lib._function_base_impl np.cov, np.corrcoef, np.trim_zeros, # numpy.core.numeric np.correlate, np.convolve, @@ -439,7 +439,7 @@ def msort(a): @dispatched_function def sort_complex(a): - # Just a copy of function_base.sort_complex, to avoid the asarray. + # Just a copy of np.lib._function_base_impl.sort_complex, to avoid the asarray. b = a.copy() b.sort() if not issubclass(b.dtype.type, np.complexfloating): # pragma: no cover @@ -595,11 +595,15 @@ def median(a, axis=None, out=None, **kwargs): ) return (r.reshape(k) if keepdims else r) if out is None else out - else: + elif NUMPY_LT_2_0: return np.lib.function_base._ureduce( a, func=_masked_median, axis=axis, out=out, **kwargs ) + return np.lib._function_base_impl._ureduce( + a, func=_masked_median, axis=axis, out=out, **kwargs + ) + def _masked_quantile_1d(a, q, **kwargs): """ @@ -608,7 +612,12 @@ def _masked_quantile_1d(a, q, **kwargs): """ unmasked = a.unmasked[~a.mask] if unmasked.size: - result = np.lib.function_base._quantile_unchecked(unmasked, q, **kwargs) + if NUMPY_LT_2_0: + result = np.lib.function_base._quantile_unchecked(unmasked, q, **kwargs) + else: + result = np.lib._function_base_impl._quantile_unchecked( + unmasked, q, **kwargs + ) return a.from_unmasked(result) else: return a.from_unmasked(np.zeros_like(a.unmasked, shape=q.shape), True) @@ -641,7 +650,9 @@ def quantile(a, q, axis=None, out=None, **kwargs): a = Masked(a) q = np.asanyarray(q) - if not np.lib.function_base._quantile_is_valid(q): + if (NUMPY_LT_2_0 and not np.lib.function_base._quantile_is_valid(q)) or ( + not NUMPY_LT_2_0 and not np.lib._function_base_impl._quantile_is_valid(q) + ): raise ValueError("Quantiles must be in the range [0, 1]") if NUMPY_LT_1_24: @@ -650,11 +661,15 @@ def quantile(a, q, axis=None, out=None, **kwargs): a, func=_masked_quantile, q=q, axis=axis, out=out, **kwargs ) return (r.reshape(q.shape + k) if keepdims else r) if out is None else out - else: + elif NUMPY_LT_2_0: return np.lib.function_base._ureduce( a, func=_masked_quantile, q=q, axis=axis, out=out, **kwargs ) + return np.lib._function_base_impl._ureduce( + a, func=_masked_quantile, q=q, axis=axis, out=out, **kwargs + ) + @dispatched_function def percentile(a, q, *args, **kwargs): @@ -761,7 +776,7 @@ def piecewise(x, condlist, funclist, *args, **kw): Any masks in ``condlist`` are ignored. """ - # Copied implementation from numpy.lib.function_base.piecewise, + # Copied implementation from numpy.lib._function_base_impl.piecewise, # just to ensure output is Masked. n2 = len(funclist) # undocumented: single condition is promoted to a list of one condition