Repository: dask/dask

Issue:
BUG: dask.array.maximum can trigger eager evaluation
The failure case seems to be `maximum(scalar, dask_array)`:
```
In [1]: import dask.array as da

In [2]: x = da.ones((3,), chunks=(3,))

In [3]: da.maximum(0, x)
Out[3]: array([ 1.,  1.,  1.])

In [4]: da.maximum(x, 0)
Out[4]: dask.array<maximum..., shape=(3,), dtype=float64, chunksize=(3,)>

In [5]: 0 + x
Out[5]: dask.array<add-5f9..., shape=(3,), dtype=float64, chunksize=(3,)>
```

Pretty sure this was introduced by https://github.com/dask/dask/pull/1669

This is causing the xarray test suite to fail: https://github.com/pydata/xarray/issues/1090

CC @sinhrks

Discussion:

Patch:
diff --git a/dask/array/ufunc.py b/dask/array/ufunc.py
index c107a2880..90ac357bb 100644
--- a/dask/array/ufunc.py
+++ b/dask/array/ufunc.py
@@ -17,15 +17,16 @@ def __array_wrap__(numpy_ufunc, x, *args, **kwargs):
 def wrap_elemwise(numpy_ufunc, array_wrap=False):
     """ Wrap up numpy function into dask.array """
 
-    def wrapped(x, *args, **kwargs):
-        if hasattr(x, '_elemwise'):
+    def wrapped(*args, **kwargs):
+        dsk = [arg for arg in args if hasattr(arg, '_elemwise')]
+        if len(dsk) > 0:
             if array_wrap:
-                return x._elemwise(__array_wrap__, numpy_ufunc,
-                                   x, *args, **kwargs)
+                return dsk[0]._elemwise(__array_wrap__, numpy_ufunc,
+                                        *args, **kwargs)
             else:
-                return x._elemwise(numpy_ufunc, x, *args, **kwargs)
+                return dsk[0]._elemwise(numpy_ufunc, *args, **kwargs)
         else:
-            return numpy_ufunc(x, *args, **kwargs)
+            return numpy_ufunc(*args, **kwargs)
 
     # functools.wraps cannot wrap ufunc in Python 2.x
     wrapped.__name__ = numpy_ufunc.__name__


Test patch:
diff --git a/dask/array/tests/test_ufunc.py b/dask/array/tests/test_ufunc.py
index 229c3e8c6..ac85d2cd4 100644
--- a/dask/array/tests/test_ufunc.py
+++ b/dask/array/tests/test_ufunc.py
@@ -75,6 +75,19 @@ def test_ufunc_2args(ufunc):
     assert isinstance(dafunc(arr1, arr2), np.ndarray)
     assert_eq(dafunc(arr1, arr2), npfunc(arr1, arr2))
 
+    # with scalar
+    assert isinstance(dafunc(darr1, 10), da.Array)
+    assert_eq(dafunc(darr1, 10), npfunc(arr1, 10))
+
+    assert isinstance(dafunc(10, darr1), da.Array)
+    assert_eq(dafunc(10, darr1), npfunc(10, arr1))
+
+    assert isinstance(dafunc(arr1, 10), np.ndarray)
+    assert_eq(dafunc(arr1, 10), npfunc(arr1, 10))
+
+    assert isinstance(dafunc(10, arr1), np.ndarray)
+    assert_eq(dafunc(10, arr1), npfunc(10, arr1))
+
 
 @pytest.mark.parametrize('ufunc', ['isreal', 'iscomplex', 'real', 'imag'])
 def test_complex(ufunc):