Accepting request 1199626 from devel:languages:python:numeric

- 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

OBS-URL: https://build.opensuse.org/request/show/1199626
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python-xarray?expand=0&rev=50
This commit is contained in:
Ana Guerrero 2024-09-09 12:45:45 +00:00 committed by Git OBS Bridge
commit 852099ad70
9 changed files with 468 additions and 907 deletions

View File

@ -1,3 +1,147 @@
-------------------------------------------------------------------
Wed Sep 4 09:11:37 UTC 2024 - Ben Greiner <code@bnavigator.de>
- 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 <code@bnavigator.de>
@ -2019,8 +2163,8 @@ Sun Dec 20 16:09:14 UTC 2020 - Sebastian Wagner <sebix+novell.com@sebix.at>
- 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 <https://github.com/mathause>`_.
- Add GitHub action for running nightly tests against upstream dependencies (:pull:`4583`).
By `Anderson Banihirwe <https://github.com/andersy005>`_.
- Add GitHub action for running nightly tests against upstream dependencies (:pull:`4583`).
By `Anderson Banihirwe <https://github.com/andersy005>`_.
- Ensure all figures are closed properly in plot tests (:pull:`4600`).
By `Yash Saboo <https://github.com/yashsaboo>`_, `Nirupam K N
<https://github.com/Nirupamkn>`_ and `Mathias Hauser
@ -2101,7 +2245,7 @@ Wed Sep 23 06:23:20 UTC 2020 - Sebastian Wagner <sebix+novell.com@sebix.at>
By `Jens Svensmark <https://github.com/jenssss>`_
- Fix incorrect legend labels for :py:meth:`Dataset.plot.scatter` (:issue:`4126`).
By `Peter Hausamann <https://github.com/phausamann>`_.
- 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 <https://github.com/TomAugspurger>`_
- 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 <mcalabkova@suse.com>
- 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 indexs 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 <https://github.com/dcherian`_.
+ xarray.DataArray.roll correctly handles multidimensional arrays.
+ xarray.DataArray.roll correctly handles multidimensional arrays.
(GH2445) By Keisuke Fujii.
+ xarray.plot() now properly accepts a norm argument and does not
+ xarray.plot() now properly accepts a norm argument and does not
override the norms vmin and vmax. (GH2381) By Deepak Cherian.
+ xarray.DataArray.std() now correctly accepts ddof keyword argument.
+ xarray.DataArray.std() now correctly accepts ddof keyword argument.
(GH2240) By Keisuke Fujii.
+ Restore matplotlibs default of plotting dashed negative contours
when a single color is passed to DataArray.contour() e.g.
+ Restore matplotlibs default of plotting dashed negative contours
when a single color is passed to DataArray.contour() e.g.
colors='k'. By Deepak Cherian.
+ Fix a bug that caused some indexing operations on arrays opened
+ Fix a bug that caused some indexing operations on arrays opened
with open_rasterio to error (GH2454). By Stephan Hoyer.
+ Subtracting one CFTimeIndex from another now returns a
pandas.TimedeltaIndex, analogous to the behavior for
+ Subtracting one CFTimeIndex from another now returns a
pandas.TimedeltaIndex, analogous to the behavior for
DatetimeIndexes (GH2484). By Spencer Clark.
+ Adding a TimedeltaIndex to, or subtracting a TimedeltaIndex from
+ Adding a TimedeltaIndex to, or subtracting a TimedeltaIndex from
a CFTimeIndex is now allowed (GH2484). By Spencer Clark.
+ Avoid use of Dasks deprecated get= parameter in tests by Matthew Rocklin.
+ An OverflowError is now accurately raised and caught during the
encoding process if a reference date is used that is so distant that
the dates must be encoded using cftime rather than NumPy (GH2272).
+ An OverflowError is now accurately raised and caught during the
encoding process if a reference date is used that is so distant that
the dates must be encoded using cftime rather than NumPy (GH2272).
By Spencer Clark.
+ Chunked datasets can now roundtrip to Zarr storage continually with
+ Chunked datasets can now roundtrip to Zarr storage continually with
to_zarr and open_zarr (GH2300). By Lily Wang.
-------------------------------------------------------------------
@ -3454,11 +3598,11 @@ Thu Jan 28 13:02:36 UTC 2016 - toddrme2178@gmail.com
This avoids a namespace conflict with the entire field of x-ray science. Renaming
our project seemed like the right thing to do, especially because some
scientists who work with actual x-rays are interested in using this project in
their work. Thanks for your understanding and patience in this transition.
their work. Thanks for your understanding and patience in this transition.
* Breaking changes
- The internal data model used by :py:class:`~xray.DataArray` has been
rewritten to fix several outstanding issues. Internally, ``DataArray``
is now implemented in terms of ``._variable`` and ``._coords``
is now implemented in terms of ``._variable`` and ``._coords``
attributes instead of holding variables in a ``Dataset`` object.
- It is no longer possible to convert a DataArray to a Dataset with
:py:meth:`xray.DataArray.to_dataset` if it is unnamed. This will now
@ -3481,7 +3625,7 @@ Thu Jan 28 13:02:36 UTC 2016 - toddrme2178@gmail.com
- Passing a :py:class:`pandas.DataFrame` or :py:class:`pandas.Panel` to a Dataset constructor
is now permitted.
- New function :py:func:`~xray.broadcast` for explicitly broadcasting
``DataArray`` and ``Dataset`` objects against each other.
``DataArray`` and ``Dataset`` objects against each other.
* Bug fixes
- Fixes for several issues found on ``DataArray`` objects with the same name
as one of their coordinates (see :ref:`v0.7.0.breaking` for more details).

View File

@ -25,11 +25,11 @@
%define psuffix %{nil}
%endif
%define ghversion 2024.05.0
%define ghversion 2024.07.0
%{?sle15_python_module_pythons}
Name: python-xarray%{psuffix}
Version: 2024.5.0
Version: 2024.7.0
Release: 0
Summary: N-D labeled arrays and datasets in Python
License: Apache-2.0
@ -38,10 +38,12 @@ Source: https://github.com/pydata/xarray/archive/refs/tags/v%{ghversion}
# PATCH-FEATURE-UPSTREAM local_dataset.patch gh#pydata/xarray#5377 mcepl@suse.com
# fix xr.tutorial.open_dataset to work with the preloaded cache.
Patch0: local_dataset.patch
# PATCH-FIX-UPSTREAM xarray-pr8854-np2.patch gh#pydata/xarray#8854
Patch1: xarray-pr8854-np2.patch
# PATCH-FIX-UPSTREAM xarray-pr9305-cftime.patch gh#pydata/xarray#9305
Patch2: xarray-pr9305-cftime.patch
# PATCH-FIX-UPSTREAM xarray-pr9321-dasktests.patch gh#pydata/xarray#9321
Patch1: xarray-pr9321-dasktests.patch
# PATCH-FIX-UPSTREAM xarray-pr9356-dasktests.patch gh#pydata/xarray#9356
Patch2: xarray-pr9356-dasktests.patch
# PATCH-FIX-UPSTREAM xarray-pr9403-np2.1-scalar.patch gh#pydata/xarray#9403
Patch3: xarray-pr9403-np2.1-scalar.patch
BuildRequires: %{python_module base >= 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

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:604a801c7bba96524b09b993b159ae998e0987627949b667c884f65895939f11
size 3739324

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3db5160a699a7731fba26b42aef3f175ca3a6adfe5593bebd0b7af90e55d747d
size 3756547

View File

@ -1,772 +0,0 @@
From e066a6c559e9d7f31c359ea95da42d0e45c585ce Mon Sep 17 00:00:00 2001
From: Justus Magin <keewis@posteo.de>
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
<xarray.NamedArray (x: 2)> Size: 16B
- Array([1.5, 2.5], dtype=float64)
+ array([1.5, 2.5])
>>> astype(narr, np.dtype(np.int32))
<xarray.NamedArray (x: 2)> 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)
<xarray.NamedArray (x: 2)> 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)
<xarray.NamedArray (x: 2)> 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)
<xarray.NamedArray (dim_2: 1, x: 2, y: 2)> Size: 32B
- Array([[[1., 2.],
- [3., 4.]]], dtype=float64)
+ array([[[1., 2.],
+ [3., 4.]]])
>>> expand_dims(x, dim="z")
<xarray.NamedArray (z: 1, x: 2, y: 2)> 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("<NA>")
@@ -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)

View File

@ -1,73 +0,0 @@
From cc4daebf1a4a41483c6b60fc57d82d8bc30911e5 Mon Sep 17 00:00:00 2001
From: Mark Harfouche <mark.harfouche@gmail.com>
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 = <xarray.tests.test_plot.TestNcAxisNotInstalled object at 0x78ed1992aa10>
@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 = <class 'FutureWarning'>
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

View File

@ -0,0 +1,118 @@
From 9406c49fb281d9ffbf88bfd46133288bd23649a4 Mon Sep 17 00:00:00 2001
From: Deepak Cherian <deepak@cherian.net>
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 <deepak@cherian.net>
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()

View File

@ -0,0 +1,98 @@
From 70e3f30d5a636f6d847acb2dd0d12cffeb601d41 Mon Sep 17 00:00:00 2001
From: Deepak Cherian <deepak@cherian.net>
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 <deepak@cherian.net>
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

View File

@ -0,0 +1,44 @@
From 17367f3545a48d8b8a18bf8f7054b19351c255dc Mon Sep 17 00:00:00 2001
From: Justus Magin <keewis@posteo.de>
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):