Repository: modin-project/modin

Issue:
`Series.values` works wrong when `Series.dtype=ExtensionDtype`
Initially found in https://github.com/modin-project/modin/pull/5469#discussion_r1052494972. 


Discussion:

Resolving patch:
diff --git a/modin/pandas/base.py b/modin/pandas/base.py
--- a/modin/pandas/base.py
+++ b/modin/pandas/base.py
@@ -476,7 +476,11 @@ def _default_to_pandas(self, op, *args, **kwargs):
             # it is a DataFrame, Series, etc.) as a pandas object. The outer `getattr`
             # will get the operation (`op`) from the pandas version of the class and run
             # it on the object after we have converted it to pandas.
-            result = getattr(self._pandas_class, op)(pandas_obj, *args, **kwargs)
+            attr = getattr(self._pandas_class, op)
+            if isinstance(attr, property):
+                result = getattr(pandas_obj, op)
+            else:
+                result = attr(pandas_obj, *args, **kwargs)
         else:
             ErrorMessage.catch_bugs_and_request_email(
                 failure_condition=True,
diff --git a/modin/pandas/series.py b/modin/pandas/series.py
--- a/modin/pandas/series.py
+++ b/modin/pandas/series.py
@@ -486,6 +486,11 @@ def values(self):  # noqa: RT01, D200
         """
         import modin.pandas as pd
 
+        if isinstance(
+            self.dtype, pandas.core.dtypes.dtypes.ExtensionDtype
+        ) and not isinstance(self.dtype, pd.CategoricalDtype):
+            return self._default_to_pandas("values")
+
         data = self.to_numpy()
         if isinstance(self.dtype, pd.CategoricalDtype):
             data = pd.Categorical(data, dtype=self.dtype)


Test patch:
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
@@ -3624,6 +3624,16 @@ def test_values_non_numeric():
     df_equals(modin_series.values, pandas_series.values)
 
 
+def test_values_ea():
+    data = pandas.arrays.SparseArray(np.arange(10, dtype="int64"))
+    modin_series, pandas_series = create_test_series(data)
+    modin_values = modin_series.values
+    pandas_values = pandas_series.values
+
+    assert modin_values.dtype == pandas_values.dtype
+    df_equals(modin_values, pandas_values)
+
+
 @pytest.mark.parametrize("data", test_data_values, ids=test_data_keys)
 @pytest.mark.parametrize(
     "skipna", bool_arg_values, ids=arg_keys("skipna", bool_arg_keys)
diff --git a/modin/pandas/test/utils.py b/modin/pandas/test/utils.py
--- a/modin/pandas/test/utils.py
+++ b/modin/pandas/test/utils.py
@@ -640,7 +640,12 @@ def df_equals(df1, df2):
         assert_index_equal(df1, df2)
     elif isinstance(df1, pandas.Series) and isinstance(df2, pandas.Series):
         assert_series_equal(df1, df2, check_dtype=False, check_series_type=False)
-    elif isinstance(df1, pandas.Categorical) and isinstance(df2, pandas.Categorical):
+    elif (
+        hasattr(df1, "dtype")
+        and hasattr(df2, "dtype")
+        and isinstance(df1.dtype, pandas.core.dtypes.dtypes.ExtensionDtype)
+        and isinstance(df2.dtype, pandas.core.dtypes.dtypes.ExtensionDtype)
+    ):
         assert_extension_array_equal(df1, df2)
     elif isinstance(df1, groupby_types) and isinstance(df2, groupby_types):
         for g1, g2 in zip(df1, df2):