pydata / sparse

Sparse multi-dimensional arrays for the PyData ecosystem
https://sparse.pydata.org
BSD 3-Clause "New" or "Revised" License
581 stars 123 forks source link

``RecursionError`` using `numpy.real`/`numpy.imag` on ``sparse.COO`` array #682

Closed jrbourbeau closed 2 months ago

jrbourbeau commented 2 months ago

Describe the bug The Dask test suite turned up a RecursionError with the recent 0.15.2 release

To Reproduce

Here's an MRE:

import sparse
import numpy as np

x = np.random.random((100, 100, 100))
s = sparse.COO(x)
result = np.real(s)
print(f"{result = }")

Expected behavior

With the 0.15.1 release the above snippet outputs (expected)

result = <COO: shape=(100, 100, 100), dtype=float64, nnz=1000000, fill_value=0.0>

but with the 0.15.2 release we get this error

Traceback (most recent call last):
  File "/Users/james/projects/dask/dask/test.py", line 6, in <module>
    result = np.real(s)
             ^^^^^^^^^^
  File "/Users/james/mambaforge/envs/dask-py312/lib/python3.12/site-packages/sparse/_sparse_array.py", line 283, in __array_function__
    return sparse_func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/james/mambaforge/envs/dask-py312/lib/python3.12/site-packages/sparse/_sparse_array.py", line 283, in __array_function__
    return sparse_func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/james/mambaforge/envs/dask-py312/lib/python3.12/site-packages/sparse/_sparse_array.py", line 283, in __array_function__
    return sparse_func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  [Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded
jrbourbeau commented 2 months ago

Looks like there was a change in how np.real is handled in __array_function__ dispatching. Previously we had (with the 0.15.1 release)

In [1]: import sparse

In [2]: import numpy as np

In [3]: sparse.real is np.real
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[3], line 1
----> 1 sparse.real is np.real

AttributeError: module 'sparse' has no attribute 'real'

Now we have (with the latest 0.15.2 release)

In [1]: import sparse

In [2]: import numpy as np

In [3]: sparse.real is np.real
Out[3]: True

which seems to be why we're getting the infinite recursion

hameerabbasi commented 2 months ago

Thanks for the report. I think I missed a commit or two when cherry picking.

hameerabbasi commented 2 months ago

This was fixed by https://github.com/pydata/sparse/commit/32d9f80a22b2c0ac0fd017cf3bd226140221a1ec. 0.15.3 is up on PyPI, and will soon also be on conda-forge.

jrbourbeau commented 2 months ago

Thanks @hameerabbasi