Repository: modin-project/modin

Issue:
Doing hasattr(df, 'sparse') leads to exception
### System information
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**:

Ubuntu 20.04

- **Modin version** (`modin.__version__`):

0.7.3+107.g888cdf1

- **Python version**:

Python 3.8.2

- **Code we can use to reproduce**:

```python
import modin.pandas as pd

df = pd.DataFrame(
    {
        "col1": [0, 1, 2, 3],
        "col2": [4, 5, 6, 7],
    }
)

if not hasattr(df, 'sparse'):
    print("No sparse")
else:
    print("sparse")
```

<!--
You can obtain the Modin version with

python -c "import modin; print(modin.__version__)"
-->

### Describe the problem
<!-- Describe the problem clearly here. -->

The above is a fragment is scikit-learn code. Executing `hasattr` on dataframe results in this method call and leads to an exception.

### Source code / logs
<!-- Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached. Try to provide a reproducible test case that is the bare minimum necessary to generate the problem. -->



Discussion:

Resolving patch:
diff --git a/modin/pandas/dataframe.py b/modin/pandas/dataframe.py
--- a/modin/pandas/dataframe.py
+++ b/modin/pandas/dataframe.py
@@ -1813,8 +1813,8 @@ def set_index(
             return frame
 
     @property
-    def sparse(self, data=None):
-        return self._default_to_pandas(pandas.DataFrame.sparse, data=data)
+    def sparse(self):
+        return self._default_to_pandas(pandas.DataFrame.sparse)
 
     def squeeze(self, axis=None):
         axis = self._get_axis_number(axis) if axis is not None else None
diff --git a/modin/pandas/series.py b/modin/pandas/series.py
--- a/modin/pandas/series.py
+++ b/modin/pandas/series.py
@@ -1092,8 +1092,8 @@ def sort_values(
         )
 
     @property
-    def sparse(self, data=None):
-        return self._default_to_pandas(pandas.Series.sparse, data=data)
+    def sparse(self):
+        return self._default_to_pandas(pandas.Series.sparse)
 
     def squeeze(self, axis=None):
         if axis is not None:


Test patch:
diff --git a/modin/pandas/test/test_dataframe.py b/modin/pandas/test/test_dataframe.py
--- a/modin/pandas/test/test_dataframe.py
+++ b/modin/pandas/test/test_dataframe.py
@@ -2776,6 +2776,19 @@ def test___setstate__(self):
             except TypeError:
                 pass
 
+    @pytest.mark.parametrize("data", test_data_values, ids=test_data_keys)
+    def test_hasattr_sparse(self, data):
+        modin_df = pd.DataFrame(data)
+        pandas_df = pandas.DataFrame(data)
+        try:
+            pandas_result = hasattr(pandas_df, "sparse")
+        except Exception as e:
+            with pytest.raises(type(e)):
+                hasattr(modin_df, "sparse")
+        else:
+            modin_result = hasattr(modin_df, "sparse")
+            assert modin_result == pandas_result
+
 
 class TestDataFrameReduction_A:
     @pytest.mark.parametrize("data", test_data_values, ids=test_data_keys)
diff --git a/modin/pandas/test/test_series.py b/modin/pandas/test/test_series.py
--- a/modin/pandas/test/test_series.py
+++ b/modin/pandas/test/test_series.py
@@ -3785,3 +3785,16 @@ def test_encode(data, encoding_type):
     else:
         modin_result = modin_series.str.encode(encoding=encoding_type)
         df_equals(modin_result, pandas_result)
+
+
+@pytest.mark.parametrize("data", test_string_data_values, ids=test_string_data_keys)
+def test_hasattr_sparse(data):
+    modin_series, pandas_series = create_test_series(data)
+    try:
+        pandas_result = hasattr(pandas_series, "sparse")
+    except Exception as e:
+        with pytest.raises(type(e)):
+            hasattr(modin_series, "sparse")
+    else:
+        modin_result = hasattr(modin_series, "sparse")
+        assert modin_result == pandas_result