Repository: dask/dask
Pull request #11107 (2024-05-07 17:58:39)

Use nightly ``scikit-image`` in upstream CI build
This fixes the 

```
ERROR dask/array/tests/test_image.py - ValueError: numpy.dtype size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject
```

errors we're currently seeing in the `upstream` build due to scikit-image / NumPy 2.0 compatibility 


Patch:
diff --git a/continuous_integration/scripts/install.sh b/continuous_integration/scripts/install.sh
index 66be2606d..e4ddbf1bd 100644
--- a/continuous_integration/scripts/install.sh
+++ b/continuous_integration/scripts/install.sh
@@ -28,12 +28,13 @@ if [[ ${UPSTREAM_DEV} ]]; then
         git+https://github.com/dask/dask-expr \
         git+https://github.com/dask/fastparquet \
         git+https://github.com/zarr-developers/zarr-python
-    mamba uninstall --force numpy pandas scipy numexpr numba sparse
+    mamba uninstall --force numpy pandas scipy numexpr numba sparse scikit-image
     python -m pip install --no-deps --pre --retries 10 \
         -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple \
         numpy \
         pandas \
-        scipy
+        scipy \
+        scikit-image
 
     # Used when automatically opening an issue when the `upstream` CI build fails
     mamba install pytest-reportlog
diff --git a/dask/array/creation.py b/dask/array/creation.py
index aa32b1a51..37cbb3008 100644
--- a/dask/array/creation.py
+++ b/dask/array/creation.py
@@ -22,7 +22,7 @@ from dask.array.core import (
     normalize_chunks,
     stack,
 )
-from dask.array.numpy_compat import AxisError
+from dask.array.numpy_compat import NUMPY_GE_200, AxisError
 from dask.array.ufunc import greater_equal, rint
 from dask.array.utils import meta_from_array
 from dask.array.wrap import empty, full, ones, zeros
@@ -501,9 +501,10 @@ def meshgrid(*xi, sparse=False, indexing="xy", **kwargs):
         grid = broadcast_arrays(*grid)
 
     if indexing == "xy" and len(xi) > 1:
-        grid[0], grid[1] = grid[1], grid[0]
+        grid = (grid[1], grid[0], *grid[2:])
 
-    return grid
+    out_type = tuple if NUMPY_GE_200 else list
+    return out_type(grid)
 
 
 def indices(dimensions, dtype=int, chunks="auto"):
diff --git a/dask/array/routines.py b/dask/array/routines.py
index fc118fa89..38fafa6da 100644
--- a/dask/array/routines.py
+++ b/dask/array/routines.py
@@ -83,6 +83,8 @@ def atleast_3d(*arys):
     if len(new_arys) == 1:
         return new_arys[0]
     else:
+        if NUMPY_GE_200:
+            new_arys = tuple(new_arys)
         return new_arys
 
 
@@ -101,6 +103,8 @@ def atleast_2d(*arys):
     if len(new_arys) == 1:
         return new_arys[0]
     else:
+        if NUMPY_GE_200:
+            new_arys = tuple(new_arys)
         return new_arys
 
 
@@ -117,6 +121,8 @@ def atleast_1d(*arys):
     if len(new_arys) == 1:
         return new_arys[0]
     else:
+        if NUMPY_GE_200:
+            new_arys = tuple(new_arys)
         return new_arys
 
 


Test patch:
diff --git a/dask/array/tests/test_creation.py b/dask/array/tests/test_creation.py
index 2d338c47b..db11190dd 100644
--- a/dask/array/tests/test_creation.py
+++ b/dask/array/tests/test_creation.py
@@ -381,7 +381,7 @@ def test_meshgrid(shapes, chunks, indexing, sparse):
     r_a = np.meshgrid(*xi_a, indexing=indexing, sparse=sparse)
     r_d = da.meshgrid(*xi_d, indexing=indexing, sparse=sparse)
 
-    assert isinstance(r_d, list)
+    assert type(r_d) is type(r_a)
     assert len(r_a) == len(r_d)
 
     for e_r_a, e_r_d, i in zip(r_a, r_d, do):