diff --git a/python-xarray.changes b/python-xarray.changes index b3513b0..d2f654d 100644 --- a/python-xarray.changes +++ b/python-xarray.changes @@ -1,3 +1,147 @@ +------------------------------------------------------------------- +Wed Sep 4 09:11:37 UTC 2024 - Ben Greiner + +- Update to 2024.7.0 + * Add test for rechunking to a size string by @dcherian in #9117 + * Update docstring in api.py for open_mfdataset(), clarifying + "chunks" argument by @arthur-e in #9121 + * Grouper refactor by @dcherian in #9122 + * adjust repr tests to account for different platforms (#9127) by + @mgorny in #9128 + * Support duplicate dimensions in .chunk by @mraspaud in #9099 + * Update zendoo badge link by @max-sixty in #9133 + * Split out distributed writes in zarr docs by @max-sixty in + #9132 + * Improve to_zarr docs by @max-sixty in #9139 + * groupby: remove some internal use of IndexVariable by @dcherian + in #9123 + * Improve zarr chunks docs by @max-sixty in #9140 + * Include numbagg in type checks by @max-sixty in #9159 + * Remove mypy exclusions for a couple more libraries by + @max-sixty in #9160 + * Add test for #9155 by @max-sixty in #9161 + * switch to datetime unit "D" by @keewis in #9170 + * Slightly improve DataTree repr by @shoyer in #9064 + * Fix example code formatting for CachingFileManager by @djhoese + in #9178 + * Change np.core.defchararray to np.char (#9165) by @pont-us in + #9166 + * temporarily remove pydap from CI by @keewis in #9183 + * also pin numpy in the all-but-dask CI by @keewis in #9184 + * promote floating-point numeric datetimes to 64-bit before + decoding by @keewis in #9182 + * "source" encoding for datasets opened from fsspec objects by + @keewis in #8923 + * properly diff objects with arrays as attributes on variables by + @keewis in #9169 + * Allow str in static typing of reindex, ffill etc. by @headtr1ck + in #9194 + * Fix dark-theme in html[data-theme=dark]-tags by @prisae in + #9200 + * Add open_datatree benchmark by @aladinor in #9158 + * use a composite strategy to generate the dataframe with a + tz-aware datetime column by @keewis in #9174 + * Hierarchical coordinates in DataTree by @shoyer in #9063 + * avoid converting custom indexes to pandas indexes when + formatting coordinate diffs by @keewis in #9157 + * Fix reductions for np.complex_ dtypes with numbagg by + @max-sixty in #9210 + * Consolidate some numbagg tests by @max-sixty in #9211 + * Use numpy 2.0-compat np.complex64 dtype in test by @max-sixty + in #9217 + * Fix two bugs in DataTree.update() by @shoyer in #9214 + * Only use necessary dims when creating temporary dataarray by + @Illviljan in #9206 + * Cleanup test_coding_times.py by @Illviljan in #9223 + * Use reshape and ravel from duck_array_ops in coding/times.py by + @Illviljan in #9225 + * Use duckarray assertions in test_coding_times by @Illviljan in + #9226 + * Fix time indexing regression in convert_calendar by @hmaarrfk + in #9192 + * numpy 2 compatibility in the netcdf4 and h5netcdf backends by + @keewis in #9136 + * numpy 2 compatibility in the iris code paths by @keewis in + #9156 + * switch the documentation to run with numpy>=2 by @keewis in + #9177 + * exclude the bots from the release notes by @keewis in #9235 + * Add a .drop_attrs method by @max-sixty in #8258 + * Allow mypy to run in vscode by @max-sixty in #9239 + * Fix typing for test_plot.py by @Illviljan in #9234 + * Added a space to the documentation by @ChrisCleaner in #9247 + * Per-variable specification of boolean parameters in + open_dataset by @Ostheer in #9218 + * Enable pandas type checking by @headtr1ck in #9213 + * fix typing of fallback isdtype method by @headtr1ck in #9250 + * Grouper, Resampler as public api by @dcherian in #8840 + * Update dropna docstring by @TomNicholas in #9257 + * Delete base and loffset parameters to resample by @dcherian in + #9233 + * groupby, resample: Deprecate some positional args by @dcherian + in #9236 + * Add encode_cf_datetime benchmark by @spencerkclark in #9262 + * Update signature for _arrayfunction.array by @Illviljan in + #9237 + * Fix copybutton for multi line examples in double digit ipython + cells by @mosc9575 in #9264 + * add backend intro and how-to diagram by @JessicaS11 in #9175 + * Restore ability to specify _FillValue as Python native integers + by @djhoese in #9258 + * Adding open_datatree backend-specific keyword arguments by + @aladinor in #9199 + * Change .groupby fastpath to work for monotonic increasing and + decreasing by @JoelJaeschke in #7427 + * Fully deprecate squeeze kwarg to groupby by @dcherian in #9280 + * Support rechunking to a frequency. by @dcherian in #9109 + * automate extracting the contributors by @keewis in #9288 + * Allow importing from xarray.groupers by @dcherian in #9289 +- Release 2024.06.0 + * TEST: Fix numbagg or bottlekneck skip by @hmaarrfk in #9034 + * Use ME in test_plot instead of M by @hmaarrfk in #9035 + * (fix): equality check against singleton PandasExtensionArray by + @ilan-gold in #9032 + * array api-related upstream-dev failures by @keewis in #8854 + * User-guide - pandas : Add alternative to + xarray.Dataset.from_dataframe by @loco-philippe in #9020 + * Clarify matmul does xarray.dot by @mthramann in #9060 + * Run tests on changes to root dotfiles by @max-sixty in #9062 + * Speed up netCDF4, h5netcdf backends by @dcherian in #9067 + * citation / orcid by @keewis in #9082 + * fixes for the pint tests by @keewis in #8983 + * Address latest pandas-related upstream test failures by + @spencerkclark in #9081 + * Add scottyhq to CITATION.cff by @scottyhq in #9089 + * Fix Typo in Bfill benchmark by @Ockenfuss in #9087 + * add link to CF conventions on packed data in + doc/user-guide/io.rst by @kmuehlbauer in #9045 + * add order for polynomial interpolation, fixes #8762 by + @nkarasiak in #9079 + * Fix upcasting with python builtin numbers and numpy 2 by + @djhoese in #8946 + * Add Eni to CITATION.cff by @eni-awowale in #9095 + * add Jessica to citation by @JessicaS11 in #9096 + * (fix): don't handle time-dtypes as extension arrays in + from_dataframe by @ilan-gold in #9042 + * Micro optimizations to improve indexing by @hmaarrfk in #9002 + * DAS-2067 - Migrate datatree io.py and common.py by + @owenlittlejohns in #9011 + * open_datatree performance improvement on NetCDF, H5, and Zarr + files by @aladinor in #9014 + * Adds Matt Savoie to CITATION.cff by @flamingbear in #9103 + * skip the pandas datetime roundtrip test with pandas=3.0 by + @keewis in #9104 + * Add user survey announcement to docs by @jhamman in #9101 + * add remaining core-dev citations by @keewis in #9110 + * Undo custom padding-top. by @dcherian in #9107 +- Drop xarray-pr8854-np2.patch +- Drop xarray-pr9305-cftime.patch + * was actually gh#pydata/xarray#9035 +- Add xarray-pr9321-dasktests.patch gh#pydata/xarray#9321 +- Add xarray-pr9356-dasktests.patch gh#pydata/xarray#9356 +- Add xarray-pr9403-np2.1-scalar.patch gh#pydata/xarray#9403 +- Remove obsolete versions from extra requirements + ------------------------------------------------------------------- Wed Jun 5 15:00:43 UTC 2024 - Ben Greiner @@ -2019,8 +2163,8 @@ Sun Dec 20 16:09:14 UTC 2020 - Sebastian Wagner - Replace the internal use of ``pd.Index.__or__`` and ``pd.Index.__and__`` with ``pd.Index.union`` and ``pd.Index.intersection`` as they will stop working as set operations in the future (:issue:`4565`). By `Mathias Hauser `_. - - Add GitHub action for running nightly tests against upstream dependencies (:pull:`4583`). - By `Anderson Banihirwe `_. + - Add GitHub action for running nightly tests against upstream dependencies (:pull:`4583`). + By `Anderson Banihirwe `_. - Ensure all figures are closed properly in plot tests (:pull:`4600`). By `Yash Saboo `_, `Nirupam K N `_ and `Mathias Hauser @@ -2101,7 +2245,7 @@ Wed Sep 23 06:23:20 UTC 2020 - Sebastian Wagner By `Jens Svensmark `_ - Fix incorrect legend labels for :py:meth:`Dataset.plot.scatter` (:issue:`4126`). By `Peter Hausamann `_. - - Fix ``dask.optimize`` on ``DataArray`` producing an invalid Dask task graph (:issue:`3698`) + - Fix ``dask.optimize`` on ``DataArray`` producing an invalid Dask task graph (:issue:`3698`) By `Tom Augspurger `_ - Fix ``pip install .`` when no ``.git`` directory exists; namely when the xarray source directory has been rsync'ed by PyCharm Professional for a remote deployment over SSH. @@ -3039,64 +3183,64 @@ Tue Nov 13 14:30:03 UTC 2018 - Marketa Calabkova - update to version 0.11.0 * Enhancements - + xarray.DataArray.plot.line() can now accept multidimensional - coordinate variables as input. hue must be a dimension name + + xarray.DataArray.plot.line() can now accept multidimensional + coordinate variables as input. hue must be a dimension name in this case. (GH2407) By Deepak Cherian. + Added support for Python 3.7. (GH2271). By Joe Hamman. - + Added support for plotting data with pandas.Interval coordinates, + + Added support for plotting data with pandas.Interval coordinates, such as those created by groupby_bins() By Maximilian Maahn. - + Added shift() for shifting the values of a CFTimeIndex by a + + Added shift() for shifting the values of a CFTimeIndex by a specified frequency. (GH2244). By Spencer Clark. - + Added support for using cftime.datetime coordinates with - differentiate(), differentiate(), interp(), and interp(). + + Added support for using cftime.datetime coordinates with + differentiate(), differentiate(), interp(), and interp(). By Spencer Clark - + There is now a global option to either always keep or always - discard dataset and dataarray attrs upon operations. The option - is set with xarray.set_options(keep_attrs=True), and the default + + There is now a global option to either always keep or always + discard dataset and dataarray attrs upon operations. The option + is set with xarray.set_options(keep_attrs=True), and the default is to use the old behaviour. By Tom Nicholas. - + Added a new backend for the GRIB file format based on ECMWF - cfgrib python driver and ecCodes C-library. (GH2475) By + + Added a new backend for the GRIB file format based on ECMWF + cfgrib python driver and ecCodes C-library. (GH2475) By Alessandro Amici, sponsored by ECMWF. - + Resample now supports a dictionary mapping from dimension to - frequency as its first argument, e.g., - data.resample({'time': '1D'}).mean(). This is consistent with - other xarray functions that accept either dictionaries or + + Resample now supports a dictionary mapping from dimension to + frequency as its first argument, e.g., + data.resample({'time': '1D'}).mean(). This is consistent with + other xarray functions that accept either dictionaries or keyword arguments. By Stephan Hoyer. - + The preferred way to access tutorial data is now to load it - lazily with xarray.tutorial.open_dataset(). - xarray.tutorial.load_dataset() calls Dataset.load() prior to - returning (and is now deprecated). This was changed in order + + The preferred way to access tutorial data is now to load it + lazily with xarray.tutorial.open_dataset(). + xarray.tutorial.load_dataset() calls Dataset.load() prior to + returning (and is now deprecated). This was changed in order to facilitate using tutorial datasets with dask. By Joe Hamman. - * Bugfixes - + FacetGrid now properly uses the cbar_kwargs keyword argument. + * Bugfixes + + FacetGrid now properly uses the cbar_kwargs keyword argument. (GH1504, GH1717) By Deepak Cherian. - + Addition and subtraction operators used with a CFTimeIndex now + + Addition and subtraction operators used with a CFTimeIndex now preserve the index’s type. (GH2244). By Spencer Clark. - + We now properly handle arrays of datetime.datetime and - datetime.timedelta provided as coordinates. (GH2512) By + + We now properly handle arrays of datetime.datetime and + datetime.timedelta provided as coordinates. (GH2512) By `Deepak Cherian = 3.9} BuildRequires: %{python_module pip} BuildRequires: %{python_module setuptools_scm} @@ -72,12 +74,12 @@ The dataset is an in-memory representation of a netCDF file. %package accel # for minimum versions, check ci/requirements/min-all-deps.yml Summary: The python xarray[accel] extra -Requires: python-Bottleneck >= 1.3 +Requires: python-Bottleneck Requires: python-opt-einsum Requires: python-scipy Requires: python-xarray = %{version} # not available yet -Recommends: python-flox >= 0.7 +Recommends: python-flox Recommends: python-numbagg %description accel @@ -117,21 +119,21 @@ Except pre-commit, Use `pip-%{python_bin_suffix} --user install pre-commit` to i %package io Summary: The python xarray[io] extra -Requires: python-cftime >= 1.6 +Requires: python-cftime Requires: python-fsspec -Requires: python-h5netcdf >= 1.1 -Requires: python-netCDF4 >= 1.6 +Requires: python-h5netcdf +Requires: python-netCDF4 Requires: python-pooch -Requires: python-scipy >= 1.10 +Requires: python-scipy Requires: python-xarray = %{version} -Requires: python-zarr >= 2.13 +Requires: python-zarr %description io The [io] extra for xarray, N-D labeled arrays and datasets in Python %package parallel Summary: The python xarray[parallel] extra -Requires: python-dask-complete >= 2022.12 +Requires: python-dask-complete Requires: python-xarray = %{version} %description parallel @@ -139,8 +141,8 @@ The [parallel] extra for xarray, N-D labeled arrays and datasets in Python %package viz Summary: The python xarray[viz] extra -Requires: python-matplotlib >= 3.6 -Requires: python-seaborn >= 0.12 +Requires: python-matplotlib +Requires: python-seaborn Requires: python-xarray = %{version} # Not available yet Recommends: python-nc-time-axis diff --git a/xarray-2024.05.0-gh.tar.gz b/xarray-2024.05.0-gh.tar.gz deleted file mode 100644 index 3a84c02..0000000 --- a/xarray-2024.05.0-gh.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:604a801c7bba96524b09b993b159ae998e0987627949b667c884f65895939f11 -size 3739324 diff --git a/xarray-2024.07.0-gh.tar.gz b/xarray-2024.07.0-gh.tar.gz new file mode 100644 index 0000000..f9fc877 --- /dev/null +++ b/xarray-2024.07.0-gh.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3db5160a699a7731fba26b42aef3f175ca3a6adfe5593bebd0b7af90e55d747d +size 3756547 diff --git a/xarray-pr8854-np2.patch b/xarray-pr8854-np2.patch deleted file mode 100644 index 665b6e8..0000000 --- a/xarray-pr8854-np2.patch +++ /dev/null @@ -1,772 +0,0 @@ -From e066a6c559e9d7f31c359ea95da42d0e45c585ce Mon Sep 17 00:00:00 2001 -From: Justus Magin -Date: Tue, 19 Mar 2024 11:32:32 +0100 -Subject: [PATCH 01/65] replace the use of `numpy.array_api` with - `array_api_strict` - -This would make it a dependency of `namedarray`, and not allow -behavior that is allowed but not required by the array API standard. Otherwise we can: -- use the main `numpy` namespace -- use `array_api_compat` (would also be a new dependency) to allow -optional behavior ---- - xarray/namedarray/_array_api.py | 9 --------- - 1 file changed, 9 deletions(-) - -Index: xarray-2024.05.0/xarray/namedarray/_array_api.py -=================================================================== ---- xarray-2024.05.0.orig/xarray/namedarray/_array_api.py -+++ xarray-2024.05.0/xarray/namedarray/_array_api.py -@@ -1,6 +1,5 @@ - from __future__ import annotations - --import warnings - from types import ModuleType - from typing import Any - -@@ -21,14 +20,6 @@ from xarray.namedarray._typing import ( - ) - from xarray.namedarray.core import NamedArray - --with warnings.catch_warnings(): -- warnings.filterwarnings( -- "ignore", -- r"The numpy.array_api submodule is still experimental", -- category=UserWarning, -- ) -- import numpy.array_api as nxp # noqa: F401 -- - - def _get_data_namespace(x: NamedArray[Any, Any]) -> ModuleType: - if isinstance(x._data, _arrayapi): -@@ -68,13 +59,13 @@ def astype( - - Examples - -------- -- >>> narr = NamedArray(("x",), nxp.asarray([1.5, 2.5])) -+ >>> narr = NamedArray(("x",), np.asarray([1.5, 2.5])) - >>> narr - Size: 16B -- Array([1.5, 2.5], dtype=float64) -+ array([1.5, 2.5]) - >>> astype(narr, np.dtype(np.int32)) - Size: 8B -- Array([1, 2], dtype=int32) -+ array([1, 2], dtype=int32) - """ - if isinstance(x._data, _arrayapi): - xp = x._data.__array_namespace__() -@@ -109,7 +100,7 @@ def imag( - - Examples - -------- -- >>> narr = NamedArray(("x",), np.asarray([1.0 + 2j, 2 + 4j])) # TODO: Use nxp -+ >>> narr = NamedArray(("x",), np.asarray([1.0 + 2j, 2 + 4j])) - >>> imag(narr) - Size: 16B - array([2., 4.]) -@@ -141,7 +132,7 @@ def real( - - Examples - -------- -- >>> narr = NamedArray(("x",), np.asarray([1.0 + 2j, 2 + 4j])) # TODO: Use nxp -+ >>> narr = NamedArray(("x",), np.asarray([1.0 + 2j, 2 + 4j])) - >>> real(narr) - Size: 16B - array([1., 2.]) -@@ -179,15 +170,15 @@ def expand_dims( - - Examples - -------- -- >>> x = NamedArray(("x", "y"), nxp.asarray([[1.0, 2.0], [3.0, 4.0]])) -+ >>> x = NamedArray(("x", "y"), np.asarray([[1.0, 2.0], [3.0, 4.0]])) - >>> expand_dims(x) - Size: 32B -- Array([[[1., 2.], -- [3., 4.]]], dtype=float64) -+ array([[[1., 2.], -+ [3., 4.]]]) - >>> expand_dims(x, dim="z") - Size: 32B -- Array([[[1., 2.], -- [3., 4.]]], dtype=float64) -+ array([[[1., 2.], -+ [3., 4.]]]) - """ - xp = _get_data_namespace(x) - dims = x.dims -Index: xarray-2024.05.0/xarray/tests/__init__.py -=================================================================== ---- xarray-2024.05.0.orig/xarray/tests/__init__.py -+++ xarray-2024.05.0/xarray/tests/__init__.py -@@ -147,9 +147,10 @@ has_numbagg_or_bottleneck = has_numbagg - requires_numbagg_or_bottleneck = pytest.mark.skipif( - not has_scipy_or_netCDF4, reason="requires scipy or netCDF4" - ) --has_numpy_array_api, requires_numpy_array_api = _importorskip("numpy", "1.26.0") - has_numpy_2, requires_numpy_2 = _importorskip("numpy", "2.0.0") - -+has_array_api_strict, requires_array_api_strict = _importorskip("array_api_strict") -+ - - def _importorskip_h5netcdf_ros3(): - try: -Index: xarray-2024.05.0/xarray/tests/test_array_api.py -=================================================================== ---- xarray-2024.05.0.orig/xarray/tests/test_array_api.py -+++ xarray-2024.05.0/xarray/tests/test_array_api.py -@@ -6,20 +6,9 @@ import xarray as xr - from xarray.testing import assert_equal - - np = pytest.importorskip("numpy", minversion="1.22") -+xp = pytest.importorskip("array_api_strict") - --try: -- import warnings -- -- with warnings.catch_warnings(): -- warnings.simplefilter("ignore") -- -- import numpy.array_api as xp -- from numpy.array_api._array_object import Array --except ImportError: -- # for `numpy>=2.0` -- xp = pytest.importorskip("array_api_strict") -- -- from array_api_strict._array_object import Array # type: ignore[no-redef] -+from array_api_strict._array_object import Array # isort:skip # type: ignore[no-redef] - - - @pytest.fixture -@@ -65,8 +54,8 @@ def test_aggregation_skipna(arrays) -> N - def test_astype(arrays) -> None: - np_arr, xp_arr = arrays - expected = np_arr.astype(np.int64) -- actual = xp_arr.astype(np.int64) -- assert actual.dtype == np.int64 -+ actual = xp_arr.astype(xp.int64) -+ assert actual.dtype == xp.int64 - assert isinstance(actual.data, Array) - assert_equal(actual, expected) - -@@ -118,8 +107,10 @@ def test_indexing(arrays: tuple[xr.DataA - - def test_properties(arrays: tuple[xr.DataArray, xr.DataArray]) -> None: - np_arr, xp_arr = arrays -- assert np_arr.nbytes == np_arr.data.nbytes -- assert xp_arr.nbytes == np_arr.data.nbytes -+ -+ expected = np_arr.data.nbytes -+ assert np_arr.nbytes == expected -+ assert xp_arr.nbytes == expected - - - def test_reorganizing_operation(arrays: tuple[xr.DataArray, xr.DataArray]) -> None: -Index: xarray-2024.05.0/xarray/tests/test_namedarray.py -=================================================================== ---- xarray-2024.05.0.orig/xarray/tests/test_namedarray.py -+++ xarray-2024.05.0/xarray/tests/test_namedarray.py -@@ -1,7 +1,6 @@ - from __future__ import annotations - - import copy --import warnings - from abc import abstractmethod - from collections.abc import Mapping - from typing import TYPE_CHECKING, Any, Generic, cast, overload -@@ -79,6 +78,17 @@ class CustomArrayIndexable( - return np - - -+def check_duck_array_typevar(a: duckarray[Any, _DType]) -> duckarray[Any, _DType]: -+ # Mypy checks a is valid: -+ b: duckarray[Any, _DType] = a -+ -+ # Runtime check if valid: -+ if isinstance(b, _arrayfunction_or_api): -+ return b -+ else: -+ raise TypeError(f"a ({type(a)}) is not a valid _arrayfunction or _arrayapi") -+ -+ - class NamedArraySubclassobjects: - @pytest.fixture - def target(self, data: np.ndarray[Any, Any]) -> Any: -@@ -328,48 +338,27 @@ class TestNamedArray(NamedArraySubclasso - named_array.dims = new_dims - assert named_array.dims == tuple(new_dims) - -- def test_duck_array_class( -- self, -- ) -> None: -- def test_duck_array_typevar( -- a: duckarray[Any, _DType], -- ) -> duckarray[Any, _DType]: -- # Mypy checks a is valid: -- b: duckarray[Any, _DType] = a -- -- # Runtime check if valid: -- if isinstance(b, _arrayfunction_or_api): -- return b -- else: -- raise TypeError( -- f"a ({type(a)}) is not a valid _arrayfunction or _arrayapi" -- ) -- -+ def test_duck_array_class(self) -> None: - numpy_a: NDArray[np.int64] - numpy_a = np.array([2.1, 4], dtype=np.dtype(np.int64)) -- test_duck_array_typevar(numpy_a) -+ check_duck_array_typevar(numpy_a) - - masked_a: np.ma.MaskedArray[Any, np.dtype[np.int64]] - masked_a = np.ma.asarray([2.1, 4], dtype=np.dtype(np.int64)) # type: ignore[no-untyped-call] -- test_duck_array_typevar(masked_a) -+ check_duck_array_typevar(masked_a) - - custom_a: CustomArrayIndexable[Any, np.dtype[np.int64]] - custom_a = CustomArrayIndexable(numpy_a) -- test_duck_array_typevar(custom_a) -+ check_duck_array_typevar(custom_a) - -+ def test_duck_array_class_array_api(self) -> None: - # Test numpy's array api: -- with warnings.catch_warnings(): -- warnings.filterwarnings( -- "ignore", -- r"The numpy.array_api submodule is still experimental", -- category=UserWarning, -- ) -- import numpy.array_api as nxp -+ nxp = pytest.importorskip("array_api_strict", minversion="1.0") - - # TODO: nxp doesn't use dtype typevars, so can only use Any for the moment: - arrayapi_a: duckarray[Any, Any] # duckarray[Any, np.dtype[np.int64]] -- arrayapi_a = nxp.asarray([2.1, 4], dtype=np.dtype(np.int64)) -- test_duck_array_typevar(arrayapi_a) -+ arrayapi_a = nxp.asarray([2.1, 4], dtype=nxp.int64) -+ check_duck_array_typevar(arrayapi_a) - - def test_new_namedarray(self) -> None: - dtype_float = np.dtype(np.float32) -Index: xarray-2024.05.0/xarray/tests/test_strategies.py -=================================================================== ---- xarray-2024.05.0.orig/xarray/tests/test_strategies.py -+++ xarray-2024.05.0/xarray/tests/test_strategies.py -@@ -1,6 +1,9 @@ -+import warnings -+ - import numpy as np - import numpy.testing as npt - import pytest -+from packaging.version import Version - - pytest.importorskip("hypothesis") - # isort: split -@@ -19,7 +22,6 @@ from xarray.testing.strategies import ( - unique_subset_of, - variables, - ) --from xarray.tests import requires_numpy_array_api - - ALLOWED_ATTRS_VALUES_TYPES = (int, bool, str, np.ndarray) - -@@ -199,7 +201,6 @@ class TestVariablesStrategy: - ) - ) - -- @requires_numpy_array_api - @given(st.data()) - def test_make_strategies_namespace(self, data): - """ -@@ -208,16 +209,24 @@ class TestVariablesStrategy: - We still want to generate dtypes not in the array API by default, but this checks we don't accidentally override - the user's choice of dtypes with non-API-compliant ones. - """ -- from numpy import ( -- array_api as np_array_api, # requires numpy>=1.26.0, and we expect a UserWarning to be raised -- ) -+ if Version(np.__version__) >= Version("2.0.0.dev0"): -+ nxp = np -+ else: -+ # requires numpy>=1.26.0, and we expect a UserWarning to be raised -+ with warnings.catch_warnings(): -+ warnings.filterwarnings( -+ "ignore", category=UserWarning, message=".+See NEP 47." -+ ) -+ from numpy import ( # type: ignore[no-redef,unused-ignore] -+ array_api as nxp, -+ ) - -- np_array_api_st = make_strategies_namespace(np_array_api) -+ nxp_st = make_strategies_namespace(nxp) - - data.draw( - variables( -- array_strategy_fn=np_array_api_st.arrays, -- dtype=np_array_api_st.scalar_dtypes(), -+ array_strategy_fn=nxp_st.arrays, -+ dtype=nxp_st.scalar_dtypes(), - ) - ) - -Index: xarray-2024.05.0/xarray/core/duck_array_ops.py -=================================================================== ---- xarray-2024.05.0.orig/xarray/core/duck_array_ops.py -+++ xarray-2024.05.0/xarray/core/duck_array_ops.py -@@ -142,17 +142,25 @@ around.__doc__ = str.replace( - - def isnull(data): - data = asarray(data) -- scalar_type = data.dtype.type -- if issubclass(scalar_type, (np.datetime64, np.timedelta64)): -+ -+ xp = get_array_namespace(data) -+ scalar_type = data.dtype -+ if dtypes.is_datetime_like(scalar_type): - # datetime types use NaT for null - # note: must check timedelta64 before integers, because currently - # timedelta64 inherits from np.integer - return isnat(data) -- elif issubclass(scalar_type, np.inexact): -+ elif dtypes.isdtype(scalar_type, ("real floating", "complex floating"), xp=xp): - # float types use NaN for null - xp = get_array_namespace(data) - return xp.isnan(data) -- elif issubclass(scalar_type, (np.bool_, np.integer, np.character, np.void)): -+ elif dtypes.isdtype(scalar_type, ("bool", "integral"), xp=xp) or ( -+ isinstance(scalar_type, np.dtype) -+ and ( -+ np.issubdtype(scalar_type, np.character) -+ or np.issubdtype(scalar_type, np.void) -+ ) -+ ): - # these types cannot represent missing values - return full_like(data, dtype=bool, fill_value=False) - else: -@@ -406,13 +414,22 @@ def _create_nan_agg_method(name, coerce_ - if invariant_0d and axis == (): - return values - -- values = asarray(values) -+ xp = get_array_namespace(values) -+ values = asarray(values, xp=xp) - -- if coerce_strings and values.dtype.kind in "SU": -+ if coerce_strings and dtypes.is_string(values.dtype): - values = astype(values, object) - - func = None -- if skipna or (skipna is None and values.dtype.kind in "cfO"): -+ if skipna or ( -+ skipna is None -+ and ( -+ dtypes.isdtype( -+ values.dtype, ("complex floating", "real floating"), xp=xp -+ ) -+ or dtypes.is_object(values.dtype) -+ ) -+ ): - nanname = "nan" + name - func = getattr(nanops, nanname) - else: -@@ -477,8 +494,8 @@ def _datetime_nanmin(array): - - numpy nanmin() don't work on datetime64 (all versions at the moment of writing) - - dask min() does not work on datetime64 (all versions at the moment of writing) - """ -- assert array.dtype.kind in "mM" - dtype = array.dtype -+ assert dtypes.is_datetime_like(dtype) - # (NaT).astype(float) does not produce NaN... - array = where(pandas_isnull(array), np.nan, array.astype(float)) - array = min(array, skipna=True) -@@ -515,7 +532,7 @@ def datetime_to_numeric(array, offset=No - """ - # Set offset to minimum if not given - if offset is None: -- if array.dtype.kind in "Mm": -+ if dtypes.is_datetime_like(array.dtype): - offset = _datetime_nanmin(array) - else: - offset = min(array) -@@ -527,7 +544,7 @@ def datetime_to_numeric(array, offset=No - # This map_blocks call is for backwards compatibility. - # dask == 2021.04.1 does not support subtracting object arrays - # which is required for cftime -- if is_duck_dask_array(array) and np.issubdtype(array.dtype, object): -+ if is_duck_dask_array(array) and dtypes.is_object(array.dtype): - array = array.map_blocks(lambda a, b: a - b, offset, meta=array._meta) - else: - array = array - offset -@@ -537,11 +554,11 @@ def datetime_to_numeric(array, offset=No - array = np.array(array) - - # Convert timedelta objects to float by first converting to microseconds. -- if array.dtype.kind in "O": -+ if dtypes.is_object(array.dtype): - return py_timedelta_to_float(array, datetime_unit or "ns").astype(dtype) - - # Convert np.NaT to np.nan -- elif array.dtype.kind in "mM": -+ elif dtypes.is_datetime_like(array.dtype): - # Convert to specified timedelta units. - if datetime_unit: - array = array / np.timedelta64(1, datetime_unit) -@@ -641,7 +658,7 @@ def mean(array, axis=None, skipna=None, - from xarray.core.common import _contains_cftime_datetimes - - array = asarray(array) -- if array.dtype.kind in "Mm": -+ if dtypes.is_datetime_like(array.dtype): - offset = _datetime_nanmin(array) - - # xarray always uses np.datetime64[ns] for np.datetime64 data -@@ -689,7 +706,9 @@ def cumsum(array, axis=None, **kwargs): - - def first(values, axis, skipna=None): - """Return the first non-NA elements in this array along the given axis""" -- if (skipna or skipna is None) and values.dtype.kind not in "iSU": -+ if (skipna or skipna is None) and not ( -+ dtypes.isdtype(values.dtype, "signed integer") or dtypes.is_string(values.dtype) -+ ): - # only bother for dtypes that can hold NaN - if is_chunked_array(values): - return chunked_nanfirst(values, axis) -@@ -700,7 +719,9 @@ def first(values, axis, skipna=None): - - def last(values, axis, skipna=None): - """Return the last non-NA elements in this array along the given axis""" -- if (skipna or skipna is None) and values.dtype.kind not in "iSU": -+ if (skipna or skipna is None) and not ( -+ dtypes.isdtype(values.dtype, "signed integer") or dtypes.is_string(values.dtype) -+ ): - # only bother for dtypes that can hold NaN - if is_chunked_array(values): - return chunked_nanlast(values, axis) -Index: xarray-2024.05.0/xarray/core/dtypes.py -=================================================================== ---- xarray-2024.05.0.orig/xarray/core/dtypes.py -+++ xarray-2024.05.0/xarray/core/dtypes.py -@@ -4,8 +4,9 @@ import functools - from typing import Any - - import numpy as np -+from pandas.api.types import is_extension_array_dtype - --from xarray.core import utils -+from xarray.core import npcompat, utils - - # Use as a sentinel value to indicate a dtype appropriate NA value. - NA = utils.ReprObject("") -@@ -60,22 +61,22 @@ def maybe_promote(dtype: np.dtype) -> tu - # N.B. these casting rules should match pandas - dtype_: np.typing.DTypeLike - fill_value: Any -- if np.issubdtype(dtype, np.floating): -+ if isdtype(dtype, "real floating"): - dtype_ = dtype - fill_value = np.nan -- elif np.issubdtype(dtype, np.timedelta64): -+ elif isinstance(dtype, np.dtype) and np.issubdtype(dtype, np.timedelta64): - # See https://github.com/numpy/numpy/issues/10685 - # np.timedelta64 is a subclass of np.integer - # Check np.timedelta64 before np.integer - fill_value = np.timedelta64("NaT") - dtype_ = dtype -- elif np.issubdtype(dtype, np.integer): -+ elif isdtype(dtype, "integral"): - dtype_ = np.float32 if dtype.itemsize <= 2 else np.float64 - fill_value = np.nan -- elif np.issubdtype(dtype, np.complexfloating): -+ elif isdtype(dtype, "complex floating"): - dtype_ = dtype - fill_value = np.nan + np.nan * 1j -- elif np.issubdtype(dtype, np.datetime64): -+ elif isinstance(dtype, np.dtype) and np.issubdtype(dtype, np.datetime64): - dtype_ = dtype - fill_value = np.datetime64("NaT") - else: -@@ -118,16 +119,16 @@ def get_pos_infinity(dtype, max_for_int= - ------- - fill_value : positive infinity value corresponding to this dtype. - """ -- if issubclass(dtype.type, np.floating): -+ if isdtype(dtype, "real floating"): - return np.inf - -- if issubclass(dtype.type, np.integer): -+ if isdtype(dtype, "integral"): - if max_for_int: - return np.iinfo(dtype).max - else: - return np.inf - -- if issubclass(dtype.type, np.complexfloating): -+ if isdtype(dtype, "complex floating"): - return np.inf + 1j * np.inf - - return INF -@@ -146,24 +147,66 @@ def get_neg_infinity(dtype, min_for_int= - ------- - fill_value : positive infinity value corresponding to this dtype. - """ -- if issubclass(dtype.type, np.floating): -+ if isdtype(dtype, "real floating"): - return -np.inf - -- if issubclass(dtype.type, np.integer): -+ if isdtype(dtype, "integral"): - if min_for_int: - return np.iinfo(dtype).min - else: - return -np.inf - -- if issubclass(dtype.type, np.complexfloating): -+ if isdtype(dtype, "complex floating"): - return -np.inf - 1j * np.inf - - return NINF - - --def is_datetime_like(dtype): -+def is_datetime_like(dtype) -> bool: - """Check if a dtype is a subclass of the numpy datetime types""" -- return np.issubdtype(dtype, np.datetime64) or np.issubdtype(dtype, np.timedelta64) -+ return _is_numpy_subdtype(dtype, (np.datetime64, np.timedelta64)) -+ -+ -+def is_object(dtype) -> bool: -+ """Check if a dtype is object""" -+ return _is_numpy_subdtype(dtype, object) -+ -+ -+def is_string(dtype) -> bool: -+ """Check if a dtype is a string dtype""" -+ return _is_numpy_subdtype(dtype, (np.str_, np.character)) -+ -+ -+def _is_numpy_subdtype(dtype, kind) -> bool: -+ if not isinstance(dtype, np.dtype): -+ return False -+ -+ kinds = kind if isinstance(kind, tuple) else (kind,) -+ return any(np.issubdtype(dtype, kind) for kind in kinds) -+ -+ -+def isdtype(dtype, kind: str | tuple[str, ...], xp=None) -> bool: -+ """Compatibility wrapper for isdtype() from the array API standard. -+ -+ Unlike xp.isdtype(), kind must be a string. -+ """ -+ # TODO(shoyer): remove this wrapper when Xarray requires -+ # numpy>=2 and pandas extensions arrays are implemented in -+ # Xarray via the array API -+ if not isinstance(kind, str) and not ( -+ isinstance(kind, tuple) and all(isinstance(k, str) for k in kind) -+ ): -+ raise TypeError(f"kind must be a string or a tuple of strings: {repr(kind)}") -+ -+ if isinstance(dtype, np.dtype): -+ return npcompat.isdtype(dtype, kind) -+ elif is_extension_array_dtype(dtype): -+ # we never want to match pandas extension array dtypes -+ return False -+ else: -+ if xp is None: -+ xp = np -+ return xp.isdtype(dtype, kind) - - - def result_type( -@@ -184,12 +227,26 @@ def result_type( - ------- - numpy.dtype for the result. - """ -- types = {np.result_type(t).type for t in arrays_and_dtypes} -+ from xarray.core.duck_array_ops import get_array_namespace -+ -+ # TODO(shoyer): consider moving this logic into get_array_namespace() -+ # or another helper function. -+ namespaces = {get_array_namespace(t) for t in arrays_and_dtypes} -+ non_numpy = namespaces - {np} -+ if non_numpy: -+ [xp] = non_numpy -+ else: -+ xp = np -+ -+ types = {xp.result_type(t) for t in arrays_and_dtypes} - -- for left, right in PROMOTE_TO_OBJECT: -- if any(issubclass(t, left) for t in types) and any( -- issubclass(t, right) for t in types -- ): -- return np.dtype(object) -+ if any(isinstance(t, np.dtype) for t in types): -+ # only check if there's numpy dtypes – the array API does not -+ # define the types we're checking for -+ for left, right in PROMOTE_TO_OBJECT: -+ if any(np.issubdtype(t, left) for t in types) and any( -+ np.issubdtype(t, right) for t in types -+ ): -+ return xp.dtype(object) - -- return np.result_type(*arrays_and_dtypes) -+ return xp.result_type(*arrays_and_dtypes) -Index: xarray-2024.05.0/xarray/namedarray/core.py -=================================================================== ---- xarray-2024.05.0.orig/xarray/namedarray/core.py -+++ xarray-2024.05.0/xarray/namedarray/core.py -@@ -470,10 +470,28 @@ class NamedArray(NamedArrayAggregations, - If the underlying data array does not include ``nbytes``, estimates - the bytes consumed based on the ``size`` and ``dtype``. - """ -+ from xarray.namedarray._array_api import _get_data_namespace -+ - if hasattr(self._data, "nbytes"): - return self._data.nbytes # type: ignore[no-any-return] -+ -+ if hasattr(self.dtype, "itemsize"): -+ itemsize = self.dtype.itemsize -+ elif isinstance(self._data, _arrayapi): -+ xp = _get_data_namespace(self) -+ -+ if xp.isdtype(self.dtype, "bool"): -+ itemsize = 1 -+ elif xp.isdtype(self.dtype, "integral"): -+ itemsize = xp.iinfo(self.dtype).bits // 8 -+ else: -+ itemsize = xp.finfo(self.dtype).bits // 8 - else: -- return self.size * self.dtype.itemsize -+ raise TypeError( -+ "cannot compute the number of bytes (no array API nor nbytes / itemsize)" -+ ) -+ -+ return self.size * itemsize - - @property - def dims(self) -> _Dims: -Index: xarray-2024.05.0/xarray/tests/test_dtypes.py -=================================================================== ---- xarray-2024.05.0.orig/xarray/tests/test_dtypes.py -+++ xarray-2024.05.0/xarray/tests/test_dtypes.py -@@ -4,6 +4,18 @@ import numpy as np - import pytest - - from xarray.core import dtypes -+from xarray.tests import requires_array_api_strict -+ -+try: -+ import array_api_strict -+except ImportError: -+ -+ class DummyArrayAPINamespace: -+ bool = None -+ int32 = None -+ float64 = None -+ -+ array_api_strict = DummyArrayAPINamespace - - - @pytest.mark.parametrize( -@@ -58,7 +70,6 @@ def test_inf(obj) -> None: - @pytest.mark.parametrize( - "kind, expected", - [ -- ("a", (np.dtype("O"), "nan")), # dtype('S') - ("b", (np.float32, "nan")), # dtype('int8') - ("B", (np.float32, "nan")), # dtype('uint8') - ("c", (np.dtype("O"), "nan")), # dtype('S1') -@@ -98,3 +109,54 @@ def test_nat_types_membership() -> None: - assert np.datetime64("NaT").dtype in dtypes.NAT_TYPES - assert np.timedelta64("NaT").dtype in dtypes.NAT_TYPES - assert np.float64 not in dtypes.NAT_TYPES -+ -+ -+@pytest.mark.parametrize( -+ ["dtype", "kinds", "xp", "expected"], -+ ( -+ (np.dtype("int32"), "integral", np, True), -+ (np.dtype("float16"), "real floating", np, True), -+ (np.dtype("complex128"), "complex floating", np, True), -+ (np.dtype("U"), "numeric", np, False), -+ pytest.param( -+ array_api_strict.int32, -+ "integral", -+ array_api_strict, -+ True, -+ marks=requires_array_api_strict, -+ id="array_api-int", -+ ), -+ pytest.param( -+ array_api_strict.float64, -+ "real floating", -+ array_api_strict, -+ True, -+ marks=requires_array_api_strict, -+ id="array_api-float", -+ ), -+ pytest.param( -+ array_api_strict.bool, -+ "numeric", -+ array_api_strict, -+ False, -+ marks=requires_array_api_strict, -+ id="array_api-bool", -+ ), -+ ), -+) -+def test_isdtype(dtype, kinds, xp, expected) -> None: -+ actual = dtypes.isdtype(dtype, kinds, xp=xp) -+ assert actual == expected -+ -+ -+@pytest.mark.parametrize( -+ ["dtype", "kinds", "xp", "error", "pattern"], -+ ( -+ (np.dtype("int32"), "foo", np, (TypeError, ValueError), "kind"), -+ (np.dtype("int32"), np.signedinteger, np, TypeError, "kind"), -+ (np.dtype("float16"), 1, np, TypeError, "kind"), -+ ), -+) -+def test_isdtype_error(dtype, kinds, xp, error, pattern): -+ with pytest.raises(error, match=pattern): -+ dtypes.isdtype(dtype, kinds, xp=xp) -Index: xarray-2024.05.0/xarray/core/npcompat.py -=================================================================== ---- xarray-2024.05.0.orig/xarray/core/npcompat.py -+++ xarray-2024.05.0/xarray/core/npcompat.py -@@ -28,3 +28,33 @@ - # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ -+try: -+ # requires numpy>=2.0 -+ from numpy import isdtype # type: ignore[attr-defined,unused-ignore] -+except ImportError: -+ import numpy as np -+ -+ dtype_kinds = { -+ "bool": np.bool_, -+ "signed integer": np.signedinteger, -+ "unsigned integer": np.unsignedinteger, -+ "integral": np.integer, -+ "real floating": np.floating, -+ "complex floating": np.complexfloating, -+ "numeric": np.number, -+ } -+ -+ def isdtype(dtype, kind): -+ kinds = kind if isinstance(kind, tuple) else (kind,) -+ -+ unknown_dtypes = [kind for kind in kinds if kind not in dtype_kinds] -+ if unknown_dtypes: -+ raise ValueError(f"unknown dtype kinds: {unknown_dtypes}") -+ -+ # verified the dtypes already, no need to check again -+ translated_kinds = [dtype_kinds[kind] for kind in kinds] -+ if isinstance(dtype, np.generic): -+ return any(isinstance(dtype, kind) for kind in translated_kinds) -+ else: -+ return any(np.issubdtype(dtype, kind) for kind in translated_kinds) diff --git a/xarray-pr9305-cftime.patch b/xarray-pr9305-cftime.patch deleted file mode 100644 index e771467..0000000 --- a/xarray-pr9305-cftime.patch +++ /dev/null @@ -1,73 +0,0 @@ -From cc4daebf1a4a41483c6b60fc57d82d8bc30911e5 Mon Sep 17 00:00:00 2001 -From: Mark Harfouche -Date: Sat, 18 May 2024 12:54:03 -0400 -Subject: [PATCH] Use ME in test_plot instead of M - -``` -pytest xarray/tests/test_plot.py::TestNcAxisNotInstalled::test_ncaxis_notinstalled_line_plot -``` - -would return the following error - -``` -xarray/tests/test_plot.py E [100%] - -======================================= ERRORS ======================================= -____ ERROR at setup of TestNcAxisNotInstalled.test_ncaxis_notinstalled_line_plot _____ - -self = - - @pytest.fixture(autouse=True) - def setUp(self) -> None: - """ - Create a DataArray with a time-axis that contains cftime.datetime - objects. - """ - month = np.arange(1, 13, 1) - data = np.sin(2 * np.pi * month / 12.0) - darray = DataArray(data, dims=["time"]) -> darray.coords["time"] = xr.cftime_range( - start="2017", periods=12, freq="1M", calendar="noleap" - ) - -/home/mark/git/xarray/xarray/tests/test_plot.py:3004: -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ -/home/mark/git/xarray/xarray/coding/cftime_offsets.py:1129: in cftime_range - offset = to_offset(freq) -/home/mark/git/xarray/xarray/coding/cftime_offsets.py:767: in to_offset - _emit_freq_deprecation_warning(freq) -/home/mark/git/xarray/xarray/coding/cftime_offsets.py:751: in _emit_freq_deprecation_warning - emit_user_level_warning(message, FutureWarning) -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - -message = "'M' is deprecated and will be removed in a future version. Please use 'ME' instead of 'M'." -category = - - def emit_user_level_warning(message, category=None) -> None: - """Emit a warning at the user level by inspecting the stack trace.""" - stacklevel = find_stack_level() -> return warnings.warn(message, category=category, stacklevel=stacklevel) -E FutureWarning: 'M' is deprecated and will be removed in a future version. Please use 'ME' instead of 'M'. - -/home/mark/git/xarray/xarray/core/utils.py:1112: FutureWarning -============================== short test summary info =============================== -ERROR xarray/tests/test_plot.py::TestNcAxisNotInstalled::test_ncaxis_notinstalled_line_plot - FutureWarning: 'M' is deprecated and will be removed in a future version. Please ... -================================== 1 error in 0.64s ================================== -``` ---- - xarray/tests/test_plot.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py -index e636be5589f..27f4ded5646 100644 ---- a/xarray/tests/test_plot.py -+++ b/xarray/tests/test_plot.py -@@ -3002,7 +3002,7 @@ def setUp(self) -> None: - data = np.sin(2 * np.pi * month / 12.0) - darray = DataArray(data, dims=["time"]) - darray.coords["time"] = xr.cftime_range( -- start="2017", periods=12, freq="1M", calendar="noleap" -+ start="2017", periods=12, freq="1ME", calendar="noleap" - ) - - self.darray = darray diff --git a/xarray-pr9321-dasktests.patch b/xarray-pr9321-dasktests.patch new file mode 100644 index 0000000..af35c35 --- /dev/null +++ b/xarray-pr9321-dasktests.patch @@ -0,0 +1,118 @@ +From 9406c49fb281d9ffbf88bfd46133288bd23649a4 Mon Sep 17 00:00:00 2001 +From: Deepak Cherian +Date: Tue, 6 Aug 2024 22:21:29 -0600 +Subject: [PATCH 1/2] Fix some dask tests + +--- + xarray/tests/test_dask.py | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/xarray/tests/test_dask.py b/xarray/tests/test_dask.py +index 20491eca91a..1ef759b3d6a 100644 +--- a/xarray/tests/test_dask.py ++++ b/xarray/tests/test_dask.py +@@ -640,8 +640,10 @@ def counting_get(*args, **kwargs): + + def test_duplicate_dims(self): + data = np.random.normal(size=(4, 4)) +- arr = DataArray(data, dims=("x", "x")) +- chunked_array = arr.chunk({"x": 2}) ++ with pytest.warns(UserWarning, match="Duplicate dimension"): ++ arr = DataArray(data, dims=("x", "x")) ++ with pytest.warns(UserWarning, match="Duplicate dimension"): ++ chunked_array = arr.chunk({"x": 2}) + assert chunked_array.chunks == ((2, 2), (2, 2)) + assert chunked_array.chunksizes == {"x": (2, 2)} + +@@ -1364,7 +1366,8 @@ def test_map_blocks_ds_transformations(func, map_ds): + @pytest.mark.parametrize("obj", [make_da(), make_ds()]) + def test_map_blocks_da_ds_with_template(obj): + func = lambda x: x.isel(x=[1]) +- template = obj.isel(x=[1, 5, 9]) ++ # a simple .isel(x=[1, 5, 9]) puts all those in a single chunk. ++ template = xr.concat([obj.isel(x=[i]) for i in [1, 5, 9]], dim="x") + with raise_if_dask_computes(): + actual = xr.map_blocks(func, obj, template=template) + assert_identical(actual, template) +@@ -1395,15 +1398,16 @@ def test_map_blocks_roundtrip_string_index(): + + def test_map_blocks_template_convert_object(): + da = make_da() ++ ds = da.to_dataset() ++ + func = lambda x: x.to_dataset().isel(x=[1]) +- template = da.to_dataset().isel(x=[1, 5, 9]) ++ template = xr.concat([da.to_dataset().isel(x=[i]) for i in [1, 5, 9]], dim="x") + with raise_if_dask_computes(): + actual = xr.map_blocks(func, da, template=template) + assert_identical(actual, template) + +- ds = da.to_dataset() + func = lambda x: x.to_dataarray().isel(x=[1]) +- template = ds.to_dataarray().isel(x=[1, 5, 9]) ++ template = xr.concat([ds.to_dataarray().isel(x=[i]) for i in [1, 5, 9]], dim="x") + with raise_if_dask_computes(): + actual = xr.map_blocks(func, ds, template=template) + assert_identical(actual, template) +@@ -1429,7 +1433,7 @@ def test_map_blocks_errors_bad_template(obj): + xr.map_blocks( + lambda a: a.isel(x=[1]).assign_coords(x=[120]), # assign bad index values + obj, +- template=obj.isel(x=[1, 5, 9]), ++ template=xr.concat([obj.isel(x=[i]) for i in [1, 5, 9]], dim="x"), + ).compute() + + + +From 6fa200e542fe18b99a86a53126c10639192ea5e1 Mon Sep 17 00:00:00 2001 +From: Deepak Cherian +Date: Tue, 6 Aug 2024 22:29:24 -0600 +Subject: [PATCH 2/2] Cleanup + +--- + xarray/tests/test_variable.py | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/xarray/tests/test_variable.py b/xarray/tests/test_variable.py +index 3f3f1756e45..ff6522c00eb 100644 +--- a/xarray/tests/test_variable.py ++++ b/xarray/tests/test_variable.py +@@ -318,12 +318,11 @@ def test_datetime64_valid_range(self): + with pytest.raises(pderror, match=r"Out of bounds nanosecond"): + self.cls(["t"], [data]) + +- @pytest.mark.xfail(reason="pandas issue 36615") + @pytest.mark.filterwarnings("ignore:Converting non-nanosecond") + def test_timedelta64_valid_range(self): + data = np.timedelta64("200000", "D") + pderror = pd.errors.OutOfBoundsTimedelta +- with pytest.raises(pderror, match=r"Out of bounds nanosecond"): ++ with pytest.raises(pderror, match=r"Cannot convert"): + self.cls(["t"], [data]) + + def test_pandas_data(self): +@@ -2301,20 +2300,20 @@ def test_chunk(self): + assert blocked.chunks == ((3,), (3, 1)) + assert blocked.data.name != first_dask_name + +- @pytest.mark.xfail ++ @pytest.mark.skip + def test_0d_object_array_with_list(self): + super().test_0d_object_array_with_list() + +- @pytest.mark.xfail ++ @pytest.mark.skip + def test_array_interface(self): + # dask array does not have `argsort` + super().test_array_interface() + +- @pytest.mark.xfail ++ @pytest.mark.skip + def test_copy_index(self): + super().test_copy_index() + +- @pytest.mark.xfail ++ @pytest.mark.skip + @pytest.mark.filterwarnings("ignore:elementwise comparison failed.*:FutureWarning") + def test_eq_all_dtypes(self): + super().test_eq_all_dtypes() diff --git a/xarray-pr9356-dasktests.patch b/xarray-pr9356-dasktests.patch new file mode 100644 index 0000000..f60bd70 --- /dev/null +++ b/xarray-pr9356-dasktests.patch @@ -0,0 +1,98 @@ +From 70e3f30d5a636f6d847acb2dd0d12cffeb601d41 Mon Sep 17 00:00:00 2001 +From: Deepak Cherian +Date: Tue, 13 Aug 2024 19:47:10 -0600 +Subject: [PATCH 1/2] xfail np.cross tests + +xref #9327 +--- + xarray/core/computation.py | 6 +++--- + xarray/tests/test_computation.py | 12 ++++++++---- + 2 files changed, 11 insertions(+), 7 deletions(-) + +diff --git a/xarray/core/computation.py b/xarray/core/computation.py +index 5d21d0836b9..bb7122e82de 100644 +--- a/xarray/core/computation.py ++++ b/xarray/core/computation.py +@@ -23,7 +23,7 @@ + from xarray.core.merge import merge_attrs, merge_coordinates_without_align + from xarray.core.options import OPTIONS, _get_keep_attrs + from xarray.core.types import Dims, T_DataArray +-from xarray.core.utils import is_dict_like, is_duck_dask_array, is_scalar, parse_dims ++from xarray.core.utils import is_dict_like, is_scalar, parse_dims + from xarray.core.variable import Variable + from xarray.namedarray.parallelcompat import get_chunked_array_type + from xarray.namedarray.pycompat import is_chunked_array +@@ -1693,11 +1693,11 @@ def cross( + if a.sizes[dim] < b.sizes[dim]: + a = a.pad({dim: (0, 1)}, constant_values=0) + # TODO: Should pad or apply_ufunc handle correct chunking? +- a = a.chunk({dim: -1}) if is_duck_dask_array(a.data) else a ++ a = a.chunk({dim: -1}) if is_chunked_array(a.data) else a + else: + b = b.pad({dim: (0, 1)}, constant_values=0) + # TODO: Should pad or apply_ufunc handle correct chunking? +- b = b.chunk({dim: -1}) if is_duck_dask_array(b.data) else b ++ b = b.chunk({dim: -1}) if is_chunked_array(b.data) else b + else: + raise ValueError( + f"{dim!r} on {'a' if a.sizes[dim] == 1 else 'b'} is incompatible:" +diff --git a/xarray/tests/test_computation.py b/xarray/tests/test_computation.py +index 8b480b02472..e974b8b1ac8 100644 +--- a/xarray/tests/test_computation.py ++++ b/xarray/tests/test_computation.py +@@ -2547,7 +2547,8 @@ def test_polyfit_polyval_integration( + "cartesian", + 1, + ], +- [ # Test 1 sized arrays with coords: ++ # Test 1 sized arrays with coords: ++ pytest.param( + xr.DataArray( + np.array([1]), + dims=["cartesian"], +@@ -2562,8 +2563,10 @@ def test_polyfit_polyval_integration( + np.array([4, 5, 6]), + "cartesian", + -1, +- ], +- [ # Test filling in between with coords: ++ marks=(pytest.mark.xfail(),), ++ ), ++ # Test filling in between with coords: ++ pytest.param( + xr.DataArray( + [1, 2], + dims=["cartesian"], +@@ -2578,7 +2581,8 @@ def test_polyfit_polyval_integration( + np.array([4, 5, 6]), + "cartesian", + -1, +- ], ++ marks=(pytest.mark.xfail(),), ++ ), + ], + ) + def test_cross(a, b, ae, be, dim: str, axis: int, use_dask: bool) -> None: + +From deb9e3266ca163575b200960c14c87fc999dcfc6 Mon Sep 17 00:00:00 2001 +From: Deepak Cherian +Date: Tue, 13 Aug 2024 19:49:56 -0600 +Subject: [PATCH 2/2] Force numpy>=2 + +--- + ci/requirements/environment.yml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ci/requirements/environment.yml b/ci/requirements/environment.yml +index ef02a3e7f23..40ef4a7fc74 100644 +--- a/ci/requirements/environment.yml ++++ b/ci/requirements/environment.yml +@@ -26,7 +26,7 @@ dependencies: + - numba + - numbagg + - numexpr +- - numpy ++ - numpy>=2 + - opt_einsum + - packaging + - pandas diff --git a/xarray-pr9403-np2.1-scalar.patch b/xarray-pr9403-np2.1-scalar.patch new file mode 100644 index 0000000..ace2d5e --- /dev/null +++ b/xarray-pr9403-np2.1-scalar.patch @@ -0,0 +1,44 @@ +From 17367f3545a48d8b8a18bf8f7054b19351c255dc Mon Sep 17 00:00:00 2001 +From: Justus Magin +Date: Tue, 27 Aug 2024 15:18:32 +0200 +Subject: [PATCH 1/3] also call `np.asarray` on numpy scalars + +--- + xarray/core/variable.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: xarray-2024.07.0/xarray/core/variable.py +=================================================================== +--- xarray-2024.07.0.orig/xarray/core/variable.py ++++ xarray-2024.07.0/xarray/core/variable.py +@@ -309,7 +309,7 @@ def as_compatible_data( + else: + data = np.asarray(data) + +- if not isinstance(data, np.ndarray) and ( ++ if not isinstance(data, np.ndarray | np.generic) and ( + hasattr(data, "__array_function__") or hasattr(data, "__array_namespace__") + ): + return cast("T_DuckArray", data) +Index: xarray-2024.07.0/xarray/tests/test_variable.py +=================================================================== +--- xarray-2024.07.0.orig/xarray/tests/test_variable.py ++++ xarray-2024.07.0/xarray/tests/test_variable.py +@@ -2585,10 +2585,15 @@ class TestAsCompatibleData(Generic[T_Duc + assert source_ndarray(x) is source_ndarray(as_compatible_data(x)) + + def test_converted_types(self): +- for input_array in [[[0, 1, 2]], pd.DataFrame([[0, 1, 2]])]: ++ for input_array in [ ++ [[0, 1, 2]], ++ pd.DataFrame([[0, 1, 2]]), ++ np.float64(1.4), ++ np.str_("abc"), ++ ]: + actual = as_compatible_data(input_array) + assert_array_equal(np.asarray(input_array), actual) +- assert np.ndarray == type(actual) ++ assert np.ndarray is type(actual) + assert np.asarray(input_array).dtype == actual.dtype + + def test_masked_array(self):