This is an automated email from the ASF dual-hosted git repository.

AlenkaF pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new 65244af1ff GH-49232: [Python] deprecate feather python (#49590)
65244af1ff is described below

commit 65244af1ffb1b7b9b8ae3d46f4768736d9ef9ece
Author: piyushka-ally <[email protected]>
AuthorDate: Wed Jul 1 13:07:16 2026 +0530

    GH-49232: [Python] deprecate feather python (#49590)
    
    ### Rationale for this change
    
    Arrow C++ is deprecating the Feather reader/writer (#49231) so we should 
update the Python functions too. Feather V2 is exactly the Arrow IPC file 
format, making the separate `pyarrow.feather` module redundant. Users should 
migrate to `pyarrow.ipc`.
    
    ### What changes are included in this PR?
    
    - Added `FutureWarning` deprecation warnings to all four public APIs in 
`pyarrow.feather`: `write_feather()`, `read_feather()`, `read_table()`, and 
`FeatherDataset`
    - Extracted `_read_table_internal()` so that `read_feather()` calling 
`read_table()` internally does not produce double warnings
    - Updated `FeatherDataset.read_table()` to use the internal function for 
the same reason
    - Added `.. deprecated:: 24.0.0` directives to all four public API 
docstrings
    - Added module-level `pytestmark` filter in `test_feather.py` to suppress 
warnings in existing tests
    - Added 5 new tests verifying deprecation warnings are emitted correctly 
(including a no-double-warning test)
    - Added `@ pytest.mark.filterwarnings` to 5 test functions in 
`test_dataset.py` that use feather as a utility
    - Updated `feather.rst` with a deprecation notice and migration guide 
(including a note that `pyarrow.ipc` does not compress by default unlike 
`feather.write_feather`)
    - Updated `formats.rst` to mark the Feather API section as deprecated
    
    ### Are these changes tested?
    
    Yes. Five new tests verify that each deprecated function emits exactly one 
`FutureWarning`, and existing tests continue to pass with module/function-level 
warning filters.
    
    ### Are there any user-facing changes?
    
    Yes — calling `pyarrow.feather.write_feather()`, `read_feather()`, 
`read_table()`, or `FeatherDataset()` now emits a `FutureWarning` directing 
users to `pyarrow.ipc` equivalents. Existing functionality is unchanged.
    
    * GitHub Issue: #49232
    
    Lead-authored-by: Piyush Kanti Chanda <[email protected]>
    Co-authored-by: Isaac
    Signed-off-by: AlenkaF <[email protected]>
---
 docs/source/python/api/formats.rst   |   7 ++-
 docs/source/python/feather.rst       |  36 +++++++++++++
 python/pyarrow/feather.py            | 101 +++++++++++++++++++++++++++--------
 python/pyarrow/tests/test_dataset.py |   5 ++
 python/pyarrow/tests/test_feather.py |  48 +++++++++++++++++
 5 files changed, 173 insertions(+), 24 deletions(-)

diff --git a/docs/source/python/api/formats.rst 
b/docs/source/python/api/formats.rst
index 57a5e824fa..0d2cd8975c 100644
--- a/docs/source/python/api/formats.rst
+++ b/docs/source/python/api/formats.rst
@@ -42,11 +42,14 @@ CSV Files
 
 .. _api.feather:
 
-Feather Files
--------------
+Feather Files (Deprecated)
+--------------------------
 
 .. currentmodule:: pyarrow.feather
 
+.. deprecated:: 24.0.0
+   The Feather API is deprecated. Use the :ref:`IPC <ipc>` API instead.
+
 .. autosummary::
    :toctree: ../generated/
 
diff --git a/docs/source/python/feather.rst b/docs/source/python/feather.rst
index 026ea987a2..76520e912b 100644
--- a/docs/source/python/feather.rst
+++ b/docs/source/python/feather.rst
@@ -22,6 +22,10 @@
 Feather File Format
 ===================
 
+.. deprecated:: 24.0.0
+   The ``pyarrow.feather`` module is deprecated. Feather V2 is the Arrow IPC
+   file format. Use :mod:`pyarrow.ipc` instead. See :ref:`ipc` for details.
+
 Feather is a portable file format for storing Arrow tables or data frames (from
 languages like Python or R) that utilizes the :ref:`Arrow IPC format <ipc>`
 internally. Feather was created early in the Arrow project as a proof of
@@ -107,3 +111,35 @@ Writing Version 1 (V1) Files
 For compatibility with libraries without support for Version 2 files, you can
 write the version 1 format by passing ``version=1`` to ``write_feather``. We
 intend to maintain read support for V1 for the foreseeable future.
+
+Migration to IPC
+----------------
+
+Since Feather V2 is the Arrow IPC file format, you can use the
+:mod:`pyarrow.ipc` module as a direct replacement:
+
+.. code-block:: python
+
+   import pyarrow as pa
+   import pyarrow.ipc
+
+   table = pa.table({"col1": [1, 2, 3], "col2": ["a", "b", "c"]})
+
+   # Writing (replaces feather.write_feather)
+   options = pa.ipc.IpcWriteOptions(compression='lz4')
+   with pa.ipc.new_file("data.arrow", table.schema, options=options) as writer:
+       writer.write_table(table)
+
+   # Reading (replaces feather.read_table)
+   with pa.ipc.open_file("data.arrow") as reader:
+       result = reader.read_all()
+
+.. note::
+
+   ``feather.write_feather`` defaults to LZ4 compression, while
+   ``ipc.new_file`` does not compress by default. To preserve the same
+   behavior, pass ``compression='lz4'`` via
+   :class:`~pyarrow.ipc.IpcWriteOptions` as shown above.
+
+For reading multiple files, use the :mod:`pyarrow.dataset` module with
+``format='ipc'`` instead of :class:`~pyarrow.feather.FeatherDataset`.
diff --git a/python/pyarrow/feather.py b/python/pyarrow/feather.py
index 241c27706a..68f708c914 100644
--- a/python/pyarrow/feather.py
+++ b/python/pyarrow/feather.py
@@ -18,6 +18,7 @@
 
 from collections.abc import Sequence
 import os
+import warnings
 
 from pyarrow.pandas_compat import _pandas_api  # noqa
 from pyarrow.lib import (Codec, Table,  # noqa
@@ -31,6 +32,9 @@ class FeatherDataset:
     """
     Encapsulates details of reading a list of Feather files.
 
+    .. deprecated:: 24.0.0
+       Use :func:`pyarrow.dataset.dataset` with ``format='ipc'`` instead.
+
     Parameters
     ----------
     path_or_paths : List[str]
@@ -40,6 +44,12 @@ class FeatherDataset:
     """
 
     def __init__(self, path_or_paths, validate_schema=True):
+        warnings.warn(
+            "pyarrow.feather.FeatherDataset is deprecated as of 24.0.0. "
+            "Use pyarrow.dataset.dataset() with format='ipc' instead.",
+            FutureWarning,
+            stacklevel=2
+        )
         self.paths = path_or_paths
         self.validate_schema = validate_schema
 
@@ -57,12 +67,12 @@ class FeatherDataset:
         pyarrow.Table
             Content of the file as a table (of columns)
         """
-        _fil = read_table(self.paths[0], columns=columns)
+        _fil = _read_table_internal(self.paths[0], columns=columns)
         self._tables = [_fil]
         self.schema = _fil.schema
 
         for path in self.paths[1:]:
-            table = read_table(path, columns=columns)
+            table = _read_table_internal(path, columns=columns)
             if self.validate_schema:
                 self.validate_schemas(path, table)
             self._tables.append(table)
@@ -117,6 +127,11 @@ def write_feather(df, dest, compression=None, 
compression_level=None,
     """
     Write a pandas.DataFrame to Feather format.
 
+    .. deprecated:: 24.0.0
+       Use :func:`pyarrow.ipc.new_file` /
+       :class:`pyarrow.ipc.RecordBatchFileWriter` instead.
+       Feather V2 is the Arrow IPC file format.
+
     Parameters
     ----------
     df : pandas.DataFrame or pyarrow.Table
@@ -137,6 +152,13 @@ def write_feather(df, dest, compression=None, 
compression_level=None,
         Feather file version. Version 2 is the current. Version 1 is the more
         limited legacy format
     """
+    warnings.warn(
+        "pyarrow.feather.write_feather is deprecated as of 24.0.0. "
+        "Use pyarrow.ipc.new_file() / RecordBatchFileWriter instead. "
+        "Feather V2 is the Arrow IPC file format.",
+        FutureWarning,
+        stacklevel=2
+    )
     if _pandas_api.have_pandas:
         if (_pandas_api.has_sparse and
                 isinstance(df, _pandas_api.pd.SparseDataFrame)):
@@ -201,6 +223,11 @@ def read_feather(source, columns=None, use_threads=True,
     Read a pandas.DataFrame from Feather format. To read as pyarrow.Table use
     feather.read_table.
 
+    .. deprecated:: 24.0.0
+       Use :func:`pyarrow.ipc.open_file` /
+       :class:`pyarrow.ipc.RecordBatchFileReader` instead.
+       Feather V2 is the Arrow IPC file format.
+
     Parameters
     ----------
     source : str file path, or file-like object
@@ -222,31 +249,23 @@ def read_feather(source, columns=None, use_threads=True,
     df : pandas.DataFrame
         The contents of the Feather file as a pandas.DataFrame
     """
-    return (read_table(
+    warnings.warn(
+        "pyarrow.feather.read_feather is deprecated as of 24.0.0. "
+        "Use pyarrow.ipc.open_file() / RecordBatchFileReader instead. "
+        "Feather V2 is the Arrow IPC file format.",
+        FutureWarning,
+        stacklevel=2
+    )
+    return (_read_table_internal(
         source, columns=columns, memory_map=memory_map,
         use_threads=use_threads).to_pandas(use_threads=use_threads, **kwargs))
 
 
-def read_table(source, columns=None, memory_map=False, use_threads=True):
+def _read_table_internal(source, columns=None, memory_map=False,
+                         use_threads=True):
     """
-    Read a pyarrow.Table from Feather format
-
-    Parameters
-    ----------
-    source : str file path, or file-like object
-        You can use MemoryMappedFile as source, for explicitly use memory map.
-    columns : sequence, optional
-        Only read a specific set of columns. If not provided, all columns are
-        read.
-    memory_map : boolean, default False
-        Use memory mapping when opening file on disk, when source is a str
-    use_threads : bool, default True
-        Whether to parallelize reading using multiple threads.
-
-    Returns
-    -------
-    table : pyarrow.Table
-        The contents of the Feather file as a pyarrow.Table
+    Internal implementation for reading a Feather file as a pyarrow.Table.
+    Does not emit deprecation warnings.
     """
     reader = _feather.FeatherReader(
         source, use_memory_map=memory_map, use_threads=use_threads)
@@ -277,3 +296,41 @@ def read_table(source, columns=None, memory_map=False, 
use_threads=True):
     else:
         # follow exact order / selection of names
         return table.select(columns)
+
+
+def read_table(source, columns=None, memory_map=False, use_threads=True):
+    """
+    Read a pyarrow.Table from Feather format
+
+    .. deprecated:: 24.0.0
+       Use :func:`pyarrow.ipc.open_file` /
+       :class:`pyarrow.ipc.RecordBatchFileReader` instead.
+       Feather V2 is the Arrow IPC file format.
+
+    Parameters
+    ----------
+    source : str file path, or file-like object
+        You can use MemoryMappedFile as source, for explicitly use memory map.
+    columns : sequence, optional
+        Only read a specific set of columns. If not provided, all columns are
+        read.
+    memory_map : boolean, default False
+        Use memory mapping when opening file on disk, when source is a str
+    use_threads : bool, default True
+        Whether to parallelize reading using multiple threads.
+
+    Returns
+    -------
+    table : pyarrow.Table
+        The contents of the Feather file as a pyarrow.Table
+    """
+    warnings.warn(
+        "pyarrow.feather.read_table is deprecated as of 24.0.0. "
+        "Use pyarrow.ipc.open_file() / RecordBatchFileReader instead. "
+        "Feather V2 is the Arrow IPC file format.",
+        FutureWarning,
+        stacklevel=2
+    )
+    return _read_table_internal(source, columns=columns,
+                                memory_map=memory_map,
+                                use_threads=use_threads)
diff --git a/python/pyarrow/tests/test_dataset.py 
b/python/pyarrow/tests/test_dataset.py
index 0b339f18fd..63c537eae5 100644
--- a/python/pyarrow/tests/test_dataset.py
+++ b/python/pyarrow/tests/test_dataset.py
@@ -1927,6 +1927,7 @@ def 
test_fragments_parquet_subset_with_nested_fields(tempdir):
 
 @pytest.mark.pandas
 @pytest.mark.parquet
[email protected]("ignore:pyarrow.feather:FutureWarning")
 def test_fragments_repr(tempdir, dataset):
     # partitioned parquet dataset
     fragment = list(dataset.get_fragments())[0]
@@ -3699,6 +3700,7 @@ def test_column_names_encoding(tempdir, dataset_reader):
     assert dataset_transcoded.to_table().equals(expected_table)
 
 
[email protected]("ignore:pyarrow.feather:FutureWarning")
 def test_feather_format(tempdir, dataset_reader):
     from pyarrow.feather import write_feather
 
@@ -4080,6 +4082,7 @@ def test_dataset_project_null_column(tempdir, 
dataset_reader):
     assert dataset_reader.to_table(dataset).equals(expected)
 
 
[email protected]("ignore:pyarrow.feather:FutureWarning")
 def test_dataset_project_columns(tempdir, dataset_reader):
     # basic column re-projection with expressions
     from pyarrow import feather
@@ -4431,6 +4434,7 @@ def test_write_dataset_with_dataset(tempdir):
 
 
 @pytest.mark.pandas
[email protected]("ignore:pyarrow.feather:FutureWarning")
 def test_write_dataset_existing_data(tempdir):
     directory = tempdir / 'ds'
     table = pa.table({'b': ['x', 'y', 'z'], 'c': [1, 2, 3]})
@@ -5054,6 +5058,7 @@ def test_write_dataset_arrow_schema_metadata(tempdir):
     assert result["a"].type.tz == "Europe/Brussels"
 
 
[email protected]("ignore:pyarrow.feather:FutureWarning")
 def test_write_dataset_schema_metadata(tempdir):
     # ensure that schema metadata gets written
     from pyarrow import feather
diff --git a/python/pyarrow/tests/test_feather.py 
b/python/pyarrow/tests/test_feather.py
index 054bf920b2..c04cef534e 100644
--- a/python/pyarrow/tests/test_feather.py
+++ b/python/pyarrow/tests/test_feather.py
@@ -19,6 +19,7 @@ import io
 import os
 import sys
 import tempfile
+import warnings
 import pytest
 import hypothesis as h
 import hypothesis.strategies as st
@@ -40,6 +41,12 @@ try:
 except ImportError:
     pass
 
+# Suppress deprecation warnings for existing tests since pyarrow.feather
+# is deprecated as of 24.0.0
+pytestmark = pytest.mark.filterwarnings(
+    "ignore:pyarrow.feather:FutureWarning"
+)
+
 
 @pytest.fixture(scope='module')
 def datadir(base_datadir):
@@ -882,3 +889,44 @@ def 
test_feather_datetime_resolution_arrow_to_pandas(tempdir):
 
     assert expected_0 == result['date'][0]
     assert expected_1 == result['date'][1]
+
+
+# --- Deprecation warning tests ---
+
[email protected]
[email protected]("default:pyarrow.feather:FutureWarning")
+def test_feather_deprecation_warnings(tempdir):
+    table = pa.table({"a": [1, 2, 3]})
+    path = str(tempdir / "test.feather")
+
+    with pytest.warns(FutureWarning, match="write_feather is deprecated"):
+        write_feather(table, path)
+
+    with pytest.warns(FutureWarning, match="read_table is deprecated"):
+        read_table(path)
+
+    with pytest.warns(FutureWarning, match="read_feather is deprecated"):
+        read_feather(path)
+
+
[email protected]("default:pyarrow.feather:FutureWarning")
+def test_feather_dataset_deprecated():
+    with pytest.warns(FutureWarning, match="FeatherDataset is deprecated"):
+        FeatherDataset([])
+
+
[email protected]
[email protected]("default:pyarrow.feather:FutureWarning")
+def test_read_feather_no_double_warning(tempdir):
+    """Verify read_feather emits exactly one FutureWarning, not two."""
+    table = pa.table({"a": [1, 2, 3]})
+    path = str(tempdir / "test.feather")
+    with warnings.catch_warnings():
+        warnings.simplefilter("ignore", FutureWarning)
+        write_feather(table, path)
+    with warnings.catch_warnings(record=True) as w:
+        warnings.simplefilter("always")
+        read_feather(path)
+        future_warnings = [x for x in w if issubclass(x.category,
+                                                      FutureWarning)]
+        assert len(future_warnings) == 1

Reply via email to