Skip to content

Commit 119968b

Browse files
committed
fix: add native_namespace to interchange level of support
1 parent 25df02f commit 119968b

File tree

7 files changed

+94
-0
lines changed

7 files changed

+94
-0
lines changed

narwhals/_duckdb/dataframe.py

+6
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
from typing import TYPE_CHECKING
55
from typing import Any
66

7+
from narwhals.dependencies import get_duckdb
78
from narwhals.utils import parse_version
89

910
if TYPE_CHECKING:
11+
from types import ModuleType
12+
1013
import pandas as pd
1114
import pyarrow as pa
1215
from typing_extensions import Self
@@ -68,6 +71,9 @@ def __init__(self, df: Any, dtypes: DTypes) -> None:
6871
def __narwhals_dataframe__(self) -> Any:
6972
return self
7073

74+
def __native_namespace__(self: Self) -> ModuleType:
75+
return get_duckdb() # type: ignore[no-any-return]
76+
7177
def __getitem__(self, item: str) -> DuckDBInterchangeSeries:
7278
from narwhals._duckdb.series import DuckDBInterchangeSeries
7379

narwhals/_duckdb/series.py

+6
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
from typing import Any
55

66
from narwhals._duckdb.dataframe import map_duckdb_dtype_to_narwhals_dtype
7+
from narwhals.dependencies import get_duckdb
78

89
if TYPE_CHECKING:
10+
from types import ModuleType
11+
912
from narwhals.typing import DTypes
1013

1114

@@ -17,6 +20,9 @@ def __init__(self, df: Any, dtypes: DTypes) -> None:
1720
def __narwhals_series__(self) -> Any:
1821
return self
1922

23+
def __native_namespace__(self) -> ModuleType:
24+
return get_duckdb() # type: ignore[no-any-return]
25+
2026
def __getattr__(self, attr: str) -> Any:
2127
if attr == "dtype":
2228
return map_duckdb_dtype_to_narwhals_dtype(

narwhals/_ibis/dataframe.py

+7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
from typing import TYPE_CHECKING
44
from typing import Any
55

6+
from narwhals.dependencies import get_ibis
7+
68
if TYPE_CHECKING:
9+
from types import ModuleType
10+
711
import pandas as pd
812
import pyarrow as pa
913
from typing_extensions import Self
@@ -59,6 +63,9 @@ def __init__(self, df: Any, dtypes: DTypes) -> None:
5963
def __narwhals_dataframe__(self) -> Any:
6064
return self
6165

66+
def __native_namespace__(self: Self) -> ModuleType:
67+
return get_ibis() # type: ignore[no-any-return]
68+
6269
def __getitem__(self, item: str) -> IbisInterchangeSeries:
6370
from narwhals._ibis.series import IbisInterchangeSeries
6471

narwhals/_ibis/series.py

+6
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
from typing import Any
55

66
from narwhals._ibis.dataframe import map_ibis_dtype_to_narwhals_dtype
7+
from narwhals.dependencies import get_ibis
78

89
if TYPE_CHECKING:
10+
from types import ModuleType
11+
912
from narwhals.typing import DTypes
1013

1114

@@ -17,6 +20,9 @@ def __init__(self, df: Any, dtypes: DTypes) -> None:
1720
def __narwhals_series__(self) -> Any:
1821
return self
1922

23+
def __native_namespace__(self) -> ModuleType:
24+
return get_ibis() # type: ignore[no-any-return]
25+
2026
def __getattr__(self, attr: str) -> Any:
2127
if attr == "dtype":
2228
return map_ibis_dtype_to_narwhals_dtype(

narwhals/_interchange/dataframe.py

+8
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ def __init__(self, df: Any, dtypes: DTypes) -> None:
8282
def __narwhals_dataframe__(self) -> Any:
8383
return self
8484

85+
def __native_namespace__(self: Self) -> NoReturn:
86+
msg = (
87+
"Cannot access native namespace for metadata-only dataframes with unknown backend."
88+
"If you would like to see this kind of object supported in Narwhals, please "
89+
"open a feature request at https://github.com/narwhals-dev/narwhals/issues."
90+
)
91+
raise NotImplementedError(msg)
92+
8593
def __getitem__(self, item: str) -> InterchangeSeries:
8694
from narwhals._interchange.series import InterchangeSeries
8795

narwhals/_interchange/series.py

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import TYPE_CHECKING
44
from typing import Any
5+
from typing import NoReturn
56

67
from narwhals._interchange.dataframe import map_interchange_dtype_to_narwhals_dtype
78

@@ -17,6 +18,14 @@ def __init__(self, df: Any, dtypes: DTypes) -> None:
1718
def __narwhals_series__(self) -> Any:
1819
return self
1920

21+
def __native_namespace__(self) -> NoReturn:
22+
msg = (
23+
"Cannot access native namespace for metadata-only series with unknown backend. "
24+
"If you would like to see this kind of object supported in Narwhals, please "
25+
"open a feature request at https://github.com/narwhals-dev/narwhals/issues."
26+
)
27+
raise NotImplementedError(msg)
28+
2029
def __getattr__(self, attr: str) -> Any:
2130
if attr == "dtype":
2231
return map_interchange_dtype_to_narwhals_dtype(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import duckdb
2+
import polars as pl
3+
import pytest
4+
5+
import narwhals.stable.v1 as nw
6+
7+
data = {"a": [1, 2, 3], "b": [4.5, 6.7, 8.9], "z": ["x", "y", "w"]}
8+
9+
10+
def test_interchange() -> None:
11+
df_pl = pl.DataFrame(data)
12+
df = nw.from_native(df_pl.__dataframe__(), eager_or_interchange_only=True)
13+
series = df["a"]
14+
15+
with pytest.raises(
16+
NotImplementedError,
17+
match="Cannot access native namespace for metadata-only dataframes with unknown backend",
18+
):
19+
df.__native_namespace__()
20+
21+
with pytest.raises(
22+
NotImplementedError,
23+
match="Cannot access native namespace for metadata-only series with unknown backend",
24+
):
25+
series.__native_namespace__()
26+
27+
28+
def test_ibis(
29+
tmpdir: pytest.TempdirFactory,
30+
) -> None: # pragma: no cover
31+
ibis = pytest.importorskip("ibis")
32+
df_pl = pl.DataFrame(data)
33+
34+
filepath = str(tmpdir / "file.parquet") # type: ignore[operator]
35+
df_pl.write_parquet(filepath)
36+
tbl = ibis.read_parquet(filepath)
37+
df = nw.from_native(tbl, eager_or_interchange_only=True)
38+
series = df["a"]
39+
40+
assert df.__native_namespace__() == ibis
41+
assert series.__native_namespace__() == ibis
42+
43+
44+
def test_duckdb() -> None:
45+
df_pl = pl.DataFrame(data) # noqa: F841
46+
47+
rel = duckdb.sql("select * from df_pl")
48+
df = nw.from_native(rel, eager_or_interchange_only=True)
49+
series = df["a"]
50+
51+
assert df.__native_namespace__() == duckdb
52+
assert series.__native_namespace__() == duckdb

0 commit comments

Comments
 (0)