diff --git a/doc/whats-new.rst b/doc/whats-new.rst index cd01f0adaf1..c1bfaba8756 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -59,9 +59,14 @@ Bug fixes By `Kai Mühlbauer `_. - do not cast `_FillValue`/`missing_value` in `CFMaskCoder` if `_Unsigned` is provided (:issue:`8844`, :pull:`8852`). -- Adapt handling of copy keyword argument in scipy backend for numpy >= 2.0dev - (:issue:`8844`, :pull:`8851`). +- Adapt handling of copy keyword argument for numpy >= 2.0dev + (:issue:`8844`, :pull:`8851`, :pull:`8865``). By `Kai Mühlbauer `_. +- import trapz/trapezoid depending on numpy version. + (:issue:`8844`, :pull:`8865`). + By `Kai Mühlbauer `_. + + Documentation ~~~~~~~~~~~~~ diff --git a/xarray/coding/strings.py b/xarray/coding/strings.py index b3b9d8d1041..db95286f6aa 100644 --- a/xarray/coding/strings.py +++ b/xarray/coding/strings.py @@ -15,10 +15,13 @@ unpack_for_encoding, ) from xarray.core import indexing +from xarray.core.utils import module_available from xarray.core.variable import Variable from xarray.namedarray.parallelcompat import get_chunked_array_type from xarray.namedarray.pycompat import is_chunked_array +HAS_NUMPY_2_0 = module_available("numpy", minversion="2.0.0.dev0") + def create_vlen_dtype(element_type): if element_type not in (str, bytes): @@ -156,8 +159,12 @@ def bytes_to_char(arr): def _numpy_bytes_to_char(arr): """Like netCDF4.stringtochar, but faster and more flexible.""" + # adapt handling of copy-kwarg to numpy 2.0 + # see https://github.com/numpy/numpy/issues/25916 + # and https://github.com/numpy/numpy/pull/25922 + copy = None if HAS_NUMPY_2_0 else False # ensure the array is contiguous - arr = np.array(arr, copy=False, order="C", dtype=np.bytes_) + arr = np.array(arr, copy=copy, order="C", dtype=np.bytes_) return arr.reshape(arr.shape + (1,)).view("S1") @@ -199,8 +206,12 @@ def char_to_bytes(arr): def _numpy_char_to_bytes(arr): """Like netCDF4.chartostring, but faster and more flexible.""" + # adapt handling of copy-kwarg to numpy 2.0 + # see https://github.com/numpy/numpy/issues/25916 + # and https://github.com/numpy/numpy/pull/25922 + copy = None if HAS_NUMPY_2_0 else False # based on: http://stackoverflow.com/a/10984878/809705 - arr = np.array(arr, copy=False, order="C") + arr = np.array(arr, copy=copy, order="C") dtype = "S" + str(arr.shape[-1]) return arr.view(dtype).reshape(arr.shape[:-1]) diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 19b7ef7292c..39c404d096b 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -80,6 +80,13 @@ except ImportError: pass +# from numpy version 2.0 trapz is deprecated and renamed to trapezoid +# remove once numpy 2.0 is the oldest supported version +try: + from numpy import trapezoid # type: ignore[attr-defined,unused-ignore] +except ImportError: + from numpy import trapz as trapezoid + sparse_array_type = array_type("sparse") pytestmark = [ @@ -6999,7 +7006,7 @@ def test_integrate(dask) -> None: actual = da.integrate("x") # coordinate that contains x should be dropped. expected_x = xr.DataArray( - np.trapz(da.compute(), da["x"], axis=0), + trapezoid(da.compute(), da["x"], axis=0), dims=["y"], coords={k: v for k, v in da.coords.items() if "x" not in v.dims}, ) @@ -7012,7 +7019,7 @@ def test_integrate(dask) -> None: # along y actual = da.integrate("y") expected_y = xr.DataArray( - np.trapz(da, da["y"], axis=1), + trapezoid(da, da["y"], axis=1), dims=["x"], coords={k: v for k, v in da.coords.items() if "y" not in v.dims}, ) @@ -7093,7 +7100,7 @@ def test_cumulative_integrate(dask) -> None: @pytest.mark.filterwarnings("ignore:Converting non-nanosecond") @pytest.mark.parametrize("dask", [True, False]) @pytest.mark.parametrize("which_datetime", ["np", "cftime"]) -def test_trapz_datetime(dask, which_datetime) -> None: +def test_trapezoid_datetime(dask, which_datetime) -> None: rs = np.random.RandomState(42) if which_datetime == "np": coord = np.array( @@ -7124,7 +7131,7 @@ def test_trapz_datetime(dask, which_datetime) -> None: da = da.chunk({"time": 4}) actual = da.integrate("time", datetime_unit="D") - expected_data = np.trapz( + expected_data = trapezoid( da.compute().data, duck_array_ops.datetime_to_numeric(da["time"].data, datetime_unit="D"), axis=0,