Skip to content

Commit 4397220

Browse files
authored
chore: Deprecate native_namespace in favour of backend in from_arrow (#2219)
* chore: Deprecate `native_namespace` in favour of `backend` in `from_arrow` - Related issue #1888 * fix: avoid `DeprecationWarning` in `v1` * ignore duplicate coverage https://github.com/narwhals-dev/narwhals/actions/runs/13873969274/job/38823975995?pr=2219
1 parent 636fe40 commit 4397220

File tree

3 files changed

+61
-17
lines changed

3 files changed

+61
-17
lines changed

narwhals/functions.py

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -593,15 +593,32 @@ def _from_numpy_impl(
593593
return from_native(native_frame, eager_only=True)
594594

595595

596+
@deprecate_native_namespace(warn_version="1.31.0", required=True)
596597
def from_arrow(
597-
native_frame: ArrowStreamExportable, *, native_namespace: ModuleType
598-
) -> DataFrame[Any]:
598+
native_frame: ArrowStreamExportable,
599+
*,
600+
backend: ModuleType | Implementation | str | None = None,
601+
native_namespace: ModuleType | None = None, # noqa: ARG001
602+
) -> DataFrame[Any]: # pragma: no cover
599603
"""Construct a DataFrame from an object which supports the PyCapsule Interface.
600604
601605
Arguments:
602606
native_frame: Object which implements `__arrow_c_stream__`.
607+
backend: specifies which eager backend instantiate to.
608+
609+
`backend` can be specified in various ways:
610+
611+
- As `Implementation.<BACKEND>` with `BACKEND` being `PANDAS`, `PYARROW`,
612+
`POLARS`, `MODIN` or `CUDF`.
613+
- As a string: `"pandas"`, `"pyarrow"`, `"polars"`, `"modin"` or `"cudf"`.
614+
- Directly as a module `pandas`, `pyarrow`, `polars`, `modin` or `cudf`.
603615
native_namespace: The native library to use for DataFrame creation.
604616
617+
**Deprecated** (v1.31.0):
618+
Please use `backend` instead. Note that `native_namespace` is still available
619+
(and won't emit a deprecation warning) if you use `narwhals.stable.v1`,
620+
see [perfect backwards compatibility policy](../backcompat.md/).
621+
605622
Returns:
606623
A new DataFrame.
607624
@@ -611,7 +628,7 @@ def from_arrow(
611628
>>> import narwhals as nw
612629
>>>
613630
>>> df_native = pd.DataFrame({"a": [1, 2], "b": [4.2, 5.1]})
614-
>>> nw.from_arrow(df_native, native_namespace=pl)
631+
>>> nw.from_arrow(df_native, backend="polars")
615632
┌──────────────────┐
616633
|Narwhals DataFrame|
617634
|------------------|
@@ -626,13 +643,22 @@ def from_arrow(
626643
| └─────┴─────┘ |
627644
└──────────────────┘
628645
"""
629-
if not hasattr(native_frame, "__arrow_c_stream__"):
630-
msg = f"Given object of type {type(native_frame)} does not support PyCapsule interface"
646+
backend = cast("ModuleType | Implementation | str", backend)
647+
return _from_arrow_impl(native_frame, backend=backend)
648+
649+
650+
def _from_arrow_impl(
651+
data: ArrowStreamExportable, *, backend: ModuleType | Implementation | str
652+
) -> DataFrame[Any]:
653+
if not hasattr(data, "__arrow_c_stream__"):
654+
msg = f"Given object of type {type(data)} does not support PyCapsule interface"
631655
raise TypeError(msg)
632-
implementation = Implementation.from_native_namespace(native_namespace)
656+
657+
implementation = Implementation.from_backend(backend)
658+
native_namespace = implementation.to_native_namespace()
633659

634660
if implementation.is_polars() and parse_version(native_namespace) >= (1, 3):
635-
native_frame = native_namespace.DataFrame(native_frame)
661+
native_frame = native_namespace.DataFrame(data)
636662
elif implementation in {
637663
Implementation.PANDAS,
638664
Implementation.MODIN,
@@ -650,7 +676,7 @@ def from_arrow(
650676
msg = f"PyArrow>=14.0.0 is required for `from_arrow` for object of type {native_namespace}"
651677
raise ModuleNotFoundError(msg) from None
652678

653-
tbl = pa.table(native_frame)
679+
tbl = pa.table(data)
654680
if implementation is Implementation.PANDAS:
655681
native_frame = tbl.to_pandas()
656682
elif implementation is Implementation.MODIN: # pragma: no cover
@@ -665,12 +691,12 @@ def from_arrow(
665691
msg = "congratulations, you entered unrecheable code - please report a bug"
666692
raise AssertionError(msg)
667693
elif implementation is Implementation.PYARROW:
668-
native_frame = native_namespace.table(native_frame)
694+
native_frame = native_namespace.table(data)
669695
else: # pragma: no cover
670696
try:
671697
# implementation is UNKNOWN, Narwhals extension using this feature should
672698
# implement PyCapsule support
673-
native_frame = native_namespace.DataFrame(native_frame)
699+
native_frame = native_namespace.DataFrame(data)
674700
except AttributeError as e:
675701
msg = "Unknown namespace is expected to implement `DataFrame` class which accepts object which supports PyCapsule Interface."
676702
raise AttributeError(msg) from e

narwhals/stable/v1/__init__.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323
from narwhals.expr import Expr as NwExpr
2424
from narwhals.functions import Then as NwThen
2525
from narwhals.functions import When as NwWhen
26+
from narwhals.functions import _from_arrow_impl
2627
from narwhals.functions import _from_dict_impl
2728
from narwhals.functions import _from_numpy_impl
2829
from narwhals.functions import _new_series_impl
2930
from narwhals.functions import _read_csv_impl
3031
from narwhals.functions import _read_parquet_impl
3132
from narwhals.functions import _scan_csv_impl
3233
from narwhals.functions import _scan_parquet_impl
33-
from narwhals.functions import from_arrow as nw_from_arrow
3434
from narwhals.functions import get_level
3535
from narwhals.functions import show_versions
3636
from narwhals.functions import when as nw_when
@@ -2218,20 +2218,38 @@ def new_series(
22182218
)
22192219

22202220

2221+
@deprecate_native_namespace(required=True)
22212222
def from_arrow(
2222-
native_frame: ArrowStreamExportable, *, native_namespace: ModuleType
2223+
native_frame: ArrowStreamExportable,
2224+
*,
2225+
backend: ModuleType | Implementation | str | None = None,
2226+
native_namespace: ModuleType | None = None, # noqa: ARG001
22232227
) -> DataFrame[Any]:
22242228
"""Construct a DataFrame from an object which supports the PyCapsule Interface.
22252229
22262230
Arguments:
22272231
native_frame: Object which implements `__arrow_c_stream__`.
2232+
backend: specifies which eager backend instantiate to.
2233+
2234+
`backend` can be specified in various ways:
2235+
2236+
- As `Implementation.<BACKEND>` with `BACKEND` being `PANDAS`, `PYARROW`,
2237+
`POLARS`, `MODIN` or `CUDF`.
2238+
- As a string: `"pandas"`, `"pyarrow"`, `"polars"`, `"modin"` or `"cudf"`.
2239+
- Directly as a module `pandas`, `pyarrow`, `polars`, `modin` or `cudf`.
22282240
native_namespace: The native library to use for DataFrame creation.
22292241
2242+
**Deprecated** (v1.31.0):
2243+
Please use `backend` instead. Note that `native_namespace` is still available
2244+
(and won't emit a deprecation warning) if you use `narwhals.stable.v1`,
2245+
see [perfect backwards compatibility policy](../backcompat.md/).
2246+
22302247
Returns:
22312248
A new DataFrame.
22322249
"""
2250+
backend = cast("ModuleType | Implementation | str", backend)
22332251
return _stableify( # type: ignore[no-any-return]
2234-
nw_from_arrow(native_frame, native_namespace=native_namespace)
2252+
_from_arrow_impl(native_frame, backend=backend)
22352253
)
22362254

22372255

tests/from_pycapsule_test.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
@pytest.mark.xfail(PYARROW_VERSION < (14,), reason="too old")
1616
def test_from_arrow_to_arrow() -> None:
1717
df = nw.from_native(pl.DataFrame({"ab": [1, 2, 3], "ba": [4, 5, 6]}), eager_only=True)
18-
result = nw.from_arrow(df, native_namespace=pa)
18+
result = nw.from_arrow(df, backend=pa)
1919
assert isinstance(result.to_native(), pa.Table)
2020
expected = {"ab": [1, 2, 3], "ba": [4, 5, 6]}
2121
assert_equal_data(result, expected)
@@ -26,7 +26,7 @@ def test_from_arrow_to_polars(monkeypatch: pytest.MonkeyPatch) -> None:
2626
tbl = pa.table({"ab": [1, 2, 3], "ba": [4, 5, 6]})
2727
monkeypatch.delitem(sys.modules, "pandas")
2828
df = nw.from_native(tbl, eager_only=True)
29-
result = nw.from_arrow(df, native_namespace=pl)
29+
result = nw.from_arrow(df, backend=pl)
3030
assert isinstance(result.to_native(), pl.DataFrame)
3131
expected = {"ab": [1, 2, 3], "ba": [4, 5, 6]}
3232
assert_equal_data(result, expected)
@@ -36,12 +36,12 @@ def test_from_arrow_to_polars(monkeypatch: pytest.MonkeyPatch) -> None:
3636
@pytest.mark.xfail(PYARROW_VERSION < (14,), reason="too old")
3737
def test_from_arrow_to_pandas() -> None:
3838
df = nw.from_native(pa.table({"ab": [1, 2, 3], "ba": [4, 5, 6]}), eager_only=True)
39-
result = nw.from_arrow(df, native_namespace=pd)
39+
result = nw.from_arrow(df, backend=pd)
4040
assert isinstance(result.to_native(), pd.DataFrame)
4141
expected = {"ab": [1, 2, 3], "ba": [4, 5, 6]}
4242
assert_equal_data(result, expected)
4343

4444

4545
def test_from_arrow_invalid() -> None:
4646
with pytest.raises(TypeError, match="PyCapsule"):
47-
nw.from_arrow({"a": [1]}, native_namespace=pa) # type: ignore[arg-type]
47+
nw.from_arrow({"a": [1]}, backend=pa) # type: ignore[arg-type]

0 commit comments

Comments
 (0)