Repository: modin-project/modin

Issue:
Query compiler method to_dataframe should be named to_interchange or similar
The name `to_dataframe()` does not reflect the method's purpose, which is to produce a dataframe interchange protocol object.

Discussion:

Patch:
diff --git a/modin/core/dataframe/pandas/dataframe/dataframe.py b/modin/core/dataframe/pandas/dataframe/dataframe.py
index 5456f28f..043de08f 100644
--- a/modin/core/dataframe/pandas/dataframe/dataframe.py
+++ b/modin/core/dataframe/pandas/dataframe/dataframe.py
@@ -4807,7 +4807,7 @@ class PandasDataframe(
         )
 
     @classmethod
-    def from_dataframe(cls, df: ProtocolDataframe) -> PandasDataframe:
+    def from_interchange_dataframe(cls, df: ProtocolDataframe) -> PandasDataframe:
         """
         Convert a DataFrame implementing the dataframe exchange protocol to a Core Modin Dataframe.
 
diff --git a/modin/core/execution/dispatching/factories/dispatcher.py b/modin/core/execution/dispatching/factories/dispatcher.py
index 0bbe84af..b7a0bb4b 100644
--- a/modin/core/execution/dispatching/factories/dispatcher.py
+++ b/modin/core/execution/dispatching/factories/dispatcher.py
@@ -177,9 +177,9 @@ class FactoryDispatcher(object):
         return cls.get_factory()._from_non_pandas(*args, **kwargs)
 
     @classmethod
-    @_inherit_docstrings(factories.BaseFactory._from_dataframe)
-    def from_dataframe(cls, *args, **kwargs):
-        return cls.get_factory()._from_dataframe(*args, **kwargs)
+    @_inherit_docstrings(factories.BaseFactory._from_interchange_dataframe)
+    def from_interchange_dataframe(cls, *args, **kwargs):
+        return cls.get_factory()._from_interchange_dataframe(*args, **kwargs)
 
     @classmethod
     @_inherit_docstrings(factories.BaseFactory._from_ray)
diff --git a/modin/core/execution/dispatching/factories/factories.py b/modin/core/execution/dispatching/factories/factories.py
index deda5113..ba6d1eef 100644
--- a/modin/core/execution/dispatching/factories/factories.py
+++ b/modin/core/execution/dispatching/factories/factories.py
@@ -200,10 +200,10 @@ class BaseFactory(object):
         _doc_io_method_template,
         source="a DataFrame object supporting exchange protocol `__dataframe__()`",
         params=_doc_io_method_all_params,
-        method="io.from_dataframe",
+        method="io.from_interchange_dataframe",
     )
-    def _from_dataframe(cls, *args, **kwargs):
-        return cls.io_cls.from_dataframe(*args, **kwargs)
+    def _from_interchange_dataframe(cls, *args, **kwargs):
+        return cls.io_cls.from_interchange_dataframe(*args, **kwargs)
 
     @classmethod
     @doc(
diff --git a/modin/core/io/io.py b/modin/core/io/io.py
index cb7647e2..42d0cbdb 100644
--- a/modin/core/io/io.py
+++ b/modin/core/io/io.py
@@ -100,7 +100,7 @@ class BaseIO:
         return cls.query_compiler_cls.from_arrow(at, cls.frame_cls)
 
     @classmethod
-    def from_dataframe(cls, df):
+    def from_interchange_dataframe(cls, df):
         """
         Create a Modin QueryCompiler from a DataFrame supporting the DataFrame exchange protocol `__dataframe__()`.
 
@@ -114,7 +114,7 @@ class BaseIO:
         BaseQueryCompiler
             QueryCompiler containing data from the DataFrame.
         """
-        return cls.query_compiler_cls.from_dataframe(df, cls.frame_cls)
+        return cls.query_compiler_cls.from_interchange_dataframe(df, cls.frame_cls)
 
     @classmethod
     def from_ray(cls, ray_obj):
diff --git a/modin/core/storage_formats/base/query_compiler.py b/modin/core/storage_formats/base/query_compiler.py
index dc7f2fce..1b4284a1 100644
--- a/modin/core/storage_formats/base/query_compiler.py
+++ b/modin/core/storage_formats/base/query_compiler.py
@@ -45,6 +45,9 @@ from modin.core.dataframe.algebra.default2pandas import (
     StrDefault,
     StructDefault,
 )
+from modin.core.dataframe.base.interchange.dataframe_protocol.dataframe import (
+    ProtocolDataframe,
+)
 from modin.error_message import ErrorMessage
 from modin.logging import ClassLogger
 from modin.logging.config import LogLevel
@@ -472,7 +475,9 @@ class BaseQueryCompiler(
     # Dataframe exchange protocol
 
     @abc.abstractmethod
-    def to_dataframe(self, nan_as_null: bool = False, allow_copy: bool = True):
+    def to_interchange_dataframe(
+        self, nan_as_null: bool = False, allow_copy: bool = True
+    ) -> ProtocolDataframe:
         """
         Get a DataFrame exchange protocol object representing data of the Modin DataFrame.
 
@@ -501,13 +506,13 @@ class BaseQueryCompiler(
 
     @classmethod
     @abc.abstractmethod
-    def from_dataframe(cls, df, data_cls):
+    def from_interchange_dataframe(cls, df: ProtocolDataframe, data_cls):
         """
         Build QueryCompiler from a DataFrame object supporting the dataframe exchange protocol `__dataframe__()`.
 
         Parameters
         ----------
-        df : DataFrame
+        df : ProtocolDataframe
             The DataFrame object supporting the dataframe exchange protocol.
         data_cls : type
             :py:class:`~modin.core.dataframe.pandas.dataframe.dataframe.PandasDataframe` class
diff --git a/modin/core/storage_formats/pandas/native_query_compiler.py b/modin/core/storage_formats/pandas/native_query_compiler.py
index 12f9da6e..7660c05f 100644
--- a/modin/core/storage_formats/pandas/native_query_compiler.py
+++ b/modin/core/storage_formats/pandas/native_query_compiler.py
@@ -24,6 +24,9 @@ import numpy as np
 import pandas
 from pandas.core.dtypes.common import is_list_like, is_scalar
 
+from modin.core.dataframe.base.interchange.dataframe_protocol.dataframe import (
+    ProtocolDataframe,
+)
 from modin.core.storage_formats.base.query_compiler import BaseQueryCompiler
 from modin.core.storage_formats.pandas.query_compiler_caster import QueryCompilerCaster
 from modin.utils import (
@@ -1236,13 +1239,15 @@ class NativeQueryCompiler(BaseQueryCompiler, QueryCompilerCaster):
 
     # Dataframe exchange protocol
 
-    def to_dataframe(self, nan_as_null: bool = False, allow_copy: bool = True):
+    def to_interchange_dataframe(
+        self, nan_as_null: bool = False, allow_copy: bool = True
+    ):
         return self._modin_frame.__dataframe__(
             nan_as_null=nan_as_null, allow_copy=allow_copy
         )
 
     @classmethod
-    def from_dataframe(cls, df, data_cls):
+    def from_interchange_dataframe(cls, df: ProtocolDataframe, data_cls):
         return cls(pandas.api.interchange.from_dataframe(df))
 
     # END Dataframe exchange protocol
diff --git a/modin/core/storage_formats/pandas/query_compiler.py b/modin/core/storage_formats/pandas/query_compiler.py
index b62f2aa4..656b636d 100644
--- a/modin/core/storage_formats/pandas/query_compiler.py
+++ b/modin/core/storage_formats/pandas/query_compiler.py
@@ -59,6 +59,9 @@ from modin.core.dataframe.algebra.default2pandas.groupby import (
     GroupByDefault,
     SeriesGroupByDefault,
 )
+from modin.core.dataframe.base.interchange.dataframe_protocol.dataframe import (
+    ProtocolDataframe,
+)
 from modin.core.dataframe.pandas.metadata import (
     DtypesDescriptor,
     ModinDtypes,
@@ -381,14 +384,16 @@ class PandasQueryCompiler(BaseQueryCompiler, QueryCompilerCaster):
 
     # Dataframe exchange protocol
 
-    def to_dataframe(self, nan_as_null: bool = False, allow_copy: bool = True):
+    def to_interchange_dataframe(
+        self, nan_as_null: bool = False, allow_copy: bool = True
+    ):
         return self._modin_frame.__dataframe__(
             nan_as_null=nan_as_null, allow_copy=allow_copy
         )
 
     @classmethod
-    def from_dataframe(cls, df, data_cls):
-        return cls(data_cls.from_dataframe(df))
+    def from_interchange_dataframe(cls, df: ProtocolDataframe, data_cls):
+        return cls(data_cls.from_interchange_dataframe(df))
 
     # END Dataframe exchange protocol
 
diff --git a/modin/pandas/dataframe.py b/modin/pandas/dataframe.py
index 4f47c937..b85a2f6c 100644
--- a/modin/pandas/dataframe.py
+++ b/modin/pandas/dataframe.py
@@ -2917,7 +2917,7 @@ class DataFrame(BasePandasDataset):
         ProtocolDataframe
             A dataframe object following the dataframe protocol specification.
         """
-        return self._query_compiler.to_dataframe(
+        return self._query_compiler.to_interchange_dataframe(
             nan_as_null=nan_as_null, allow_copy=allow_copy
         )
 
diff --git a/modin/pandas/io.py b/modin/pandas/io.py
index 508d1b2a..ecd53935 100644
--- a/modin/pandas/io.py
+++ b/modin/pandas/io.py
@@ -65,6 +65,9 @@ from pandas.io.parsers import TextFileReader
 from pandas.io.parsers.readers import _c_parser_defaults
 
 from modin.config import ModinNumpy
+from modin.core.dataframe.base.interchange.dataframe_protocol.dataframe import (
+    ProtocolDataframe,
+)
 from modin.error_message import ErrorMessage
 from modin.logging import ClassLogger, enable_logging
 from modin.utils import (
@@ -1013,16 +1016,16 @@ def from_arrow(at) -> DataFrame:
     return ModinObjects.DataFrame(query_compiler=FactoryDispatcher.from_arrow(at))
 
 
-def from_dataframe(df) -> DataFrame:
+def from_dataframe(df: ProtocolDataframe) -> DataFrame:
     """
-    Convert a DataFrame implementing the dataframe exchange protocol to a Modin DataFrame.
+    Convert a DataFrame implementing the dataframe interchange protocol to a Modin DataFrame.
 
     See more about the protocol in https://data-apis.org/dataframe-protocol/latest/index.html.
 
     Parameters
     ----------
-    df : DataFrame
-        The DataFrame object supporting the dataframe exchange protocol.
+    df : ProtocolDataframe
+        An object supporting the dataframe interchange protocol.
 
     Returns
     -------
@@ -1031,7 +1034,9 @@ def from_dataframe(df) -> DataFrame:
     """
     from modin.core.execution.dispatching.factories.dispatcher import FactoryDispatcher
 
-    return ModinObjects.DataFrame(query_compiler=FactoryDispatcher.from_dataframe(df))
+    return ModinObjects.DataFrame(
+        query_compiler=FactoryDispatcher.from_interchange_dataframe(df)
+    )
 
 
 def from_ray(ray_obj) -> DataFrame:


Test patch:
diff --git a/modin/conftest.py b/modin/conftest.py
index a025b978..9a126883 100644
--- a/modin/conftest.py
+++ b/modin/conftest.py
@@ -183,13 +183,15 @@ class TestQC(BaseQueryCompiler):
     def free(self):
         pass
 
-    def to_dataframe(self, nan_as_null: bool = False, allow_copy: bool = True):
+    def to_interchange_dataframe(
+        self, nan_as_null: bool = False, allow_copy: bool = True
+    ):
         raise NotImplementedError(
             "The selected execution does not implement the DataFrame exchange protocol."
         )
 
     @classmethod
-    def from_dataframe(cls, df, data_cls):
+    def from_interchange_dataframe(cls, df, data_cls):
         raise NotImplementedError(
             "The selected execution does not implement the DataFrame exchange protocol."
         )
diff --git a/modin/tests/interchange/dataframe_protocol/base/test_sanity.py b/modin/tests/interchange/dataframe_protocol/base/test_sanity.py
index 4d96250e..ddd8fcfb 100644
--- a/modin/tests/interchange/dataframe_protocol/base/test_sanity.py
+++ b/modin/tests/interchange/dataframe_protocol/base/test_sanity.py
@@ -38,8 +38,8 @@ def test_basic_io(get_unique_base_execution):
         raise TestPassed
 
     query_compiler_cls = get_unique_base_execution
-    query_compiler_cls.from_dataframe = dummy_io_method
-    query_compiler_cls.to_dataframe = dummy_io_method
+    query_compiler_cls.from_interchange_dataframe = dummy_io_method
+    query_compiler_cls.to_interchange_dataframe = dummy_io_method
 
     from modin.pandas.io import from_dataframe
 
diff --git a/modin/tests/test_executions_api.py b/modin/tests/test_executions_api.py
index f1cd6352..cde0d7f3 100644
--- a/modin/tests/test_executions_api.py
+++ b/modin/tests/test_executions_api.py
@@ -29,8 +29,8 @@ def test_base_abstract_methods():
         "from_pandas",
         "from_arrow",
         "default_to_pandas",
-        "from_dataframe",
-        "to_dataframe",
+        "from_interchange_dataframe",
+        "to_interchange_dataframe",
     ]
 
     not_implemented_methods = BASE_EXECUTION.__abstractmethods__.difference(