Repository: pydata/sparse

Issue:
sparse.COO does not support np.shape
scipy.sparse array support np.shape, but sparse.COO does not.

```python
In [1]: import sparse                                                           

In [2]: import numpy as np                                                      

In [3]: import scipy.sparse                                                     

In [4]: x = sparse.random((3, 4, 5))                                            

In [5]: x.shape                                                                 
Out[5]: (3, 4, 5)

In [6]: np.shape(x)                                                             
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-b17f5597101a> in <module>
----> 1 np.shape(x)

<__array_function__ internals> in shape(*args, **kwargs)

TypeError: no implementation found for 'numpy.shape' on types that implement __array_function__: [<class 'sparse._coo.core.COO'>]

In [7]: y = scipy.sparse.random(3, 4)                                           

In [8]: np.shape(y)                                                             
Out[8]: (3, 4)

```

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/pydata/sparse/pull/309?src=pr&el=h1) Report
> Merging [#309](https://codecov.io/gh/pydata/sparse/pull/309?src=pr&el=desc) into [master](https://codecov.io/gh/pydata/sparse/commit/9e1213aa34f1e4bcf1994b0be6a895060b9fce6f?src=pr&el=desc) will **decrease** coverage by `0.02%`.
> The diff coverage is `75%`.


```diff
@@            Coverage Diff             @@
##           master     #309      +/-   ##
==========================================
- Coverage    93.5%   93.47%   -0.03%     
==========================================
  Files          17       17              
  Lines        2140     2146       +6     
==========================================
+ Hits         2001     2006       +5     
- Misses        139      140       +1
```




Patch:
diff --git a/sparse/_sparse_array.py b/sparse/_sparse_array.py
index 4418b2e..0737fe4 100644
--- a/sparse/_sparse_array.py
+++ b/sparse/_sparse_array.py
@@ -229,6 +229,7 @@ class SparseArray:
     def __array_function__(self, func, types, args, kwargs):
         import sparse as module
 
+        sparse_func = None
         try:
             submodules = getattr(func, "__module__", "numpy").split(".")[1:]
             for submodule in submodules:
@@ -242,9 +243,19 @@ class SparseArray:
         try:
             sparse_func = getattr(type(self), func.__name__)
         except AttributeError:
-            return NotImplemented
+            pass
 
-        if not isinstance(sparse_func, Callable):
-            return getattr(self, func.__name__)
+        if (
+            not isinstance(sparse_func, Callable)
+            and len(args) == 1
+            and len(kwargs) == 0
+        ):
+            try:
+                return getattr(self, func.__name__)
+            except AttributeError:
+                pass
+
+        if sparse_func is None:
+            return NotImplemented
 
         return sparse_func(*args, **kwargs)


Test patch:
diff --git a/sparse/tests/test_array_function.py b/sparse/tests/test_array_function.py
index a0ee724..b31d4fa 100644
--- a/sparse/tests/test_array_function.py
+++ b/sparse/tests/test_array_function.py
@@ -66,3 +66,12 @@ def test_ternary(func, arg_order):
     args = [(x, y)[i] for i in arg_order]
     yy = func(*args)
     assert_eq(xx, yy)
+
+
+@pytest.mark.parametrize("func", [np.shape, np.size, np.ndim])
+def test_property(func):
+    y = sparse.random((50, 50), density=0.25)
+    x = y.todense()
+    xx = func(x)
+    yy = func(y)
+    assert xx == yy