Skip to content

Commit a279634

Browse files
authored
chore: Add CompliantDataFrame.native (#2249)
* chore: Add `CompliantDataFrame.native` -> `NativeFrame` Related: - #2232 - #2230 - #2130 * chore: Coverage for `PolarsDataFrame.native` * refactor: remove already imported imports * chore: Coverage for `ArrowDataFrame.native` * chore: Cov for `PandasLikeDataFrame.native` * refactor: Clean up `ArrowDataFrame` * unbreak `ArrowDataFrame.with_columns` and write an essay
1 parent 8c255d2 commit a279634

File tree

12 files changed

+235
-245
lines changed

12 files changed

+235
-245
lines changed

narwhals/_arrow/dataframe.py

Lines changed: 71 additions & 83 deletions
Large diffs are not rendered by default.

narwhals/_compliant/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from narwhals._compliant.typing import EagerDataFrameT
2424
from narwhals._compliant.typing import EagerSeriesT
2525
from narwhals._compliant.typing import IntoCompliantExpr
26+
from narwhals._compliant.typing import NativeFrameT_co
2627

2728
__all__ = [
2829
"CompliantDataFrame",
@@ -48,4 +49,5 @@
4849
"IntoCompliantExpr",
4950
"LazyExpr",
5051
"LazySelectorNamespace",
52+
"NativeFrameT_co",
5153
]

narwhals/_compliant/dataframe.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@
4444
T = TypeVar("T")
4545

4646

47-
class CompliantDataFrame(Sized, Protocol[CompliantSeriesT, CompliantExprT_contra]):
47+
class CompliantDataFrame(
48+
_StoresNative[NativeFrameT_co],
49+
Sized,
50+
Protocol[CompliantSeriesT, CompliantExprT_contra, NativeFrameT_co],
51+
):
52+
_native_frame: Any
53+
4854
def __narwhals_dataframe__(self) -> Self: ...
4955
def __narwhals_namespace__(self) -> Any: ...
5056
def __array__(self, dtype: Any, *, copy: bool | None) -> _2DArray: ...
@@ -60,6 +66,10 @@ def aggregate(self, *exprs: CompliantExprT_contra) -> Self:
6066
"""
6167
return self.select(*exprs)
6268

69+
@property
70+
def native(self) -> NativeFrameT_co:
71+
return self._native_frame # type: ignore[no-any-return]
72+
6373
@property
6474
def columns(self) -> Sequence[str]: ...
6575
@property
@@ -69,7 +79,7 @@ def shape(self) -> tuple[int, int]: ...
6979
def clone(self) -> Self: ...
7080
def collect(
7181
self, backend: Implementation | None, **kwargs: Any
72-
) -> CompliantDataFrame[Any, Any]: ...
82+
) -> CompliantDataFrame[Any, Any, Any]: ...
7383
def collect_schema(self) -> Mapping[str, DType]: ...
7484
def drop(self, columns: Sequence[str], *, strict: bool) -> Self: ...
7585
def drop_nulls(self, subset: Sequence[str] | None) -> Self: ...
@@ -195,7 +205,7 @@ def schema(self) -> Mapping[str, DType]: ...
195205
def _iter_columns(self) -> Iterator[Any]: ...
196206
def collect(
197207
self, backend: Implementation | None, **kwargs: Any
198-
) -> CompliantDataFrame[Any, Any]: ...
208+
) -> CompliantDataFrame[Any, Any, Any]: ...
199209
def collect_schema(self) -> Mapping[str, DType]: ...
200210
def drop(self, columns: Sequence[str], *, strict: bool) -> Self: ...
201211
def drop_nulls(self, subset: Sequence[str] | None) -> Self: ...
@@ -252,7 +262,7 @@ def with_row_index(self, name: str) -> Self: ...
252262

253263

254264
class EagerDataFrame(
255-
CompliantDataFrame[EagerSeriesT, EagerExprT_contra],
265+
CompliantDataFrame[EagerSeriesT, EagerExprT_contra, NativeFrameT_co],
256266
CompliantLazyFrame[EagerExprT_contra, NativeFrameT_co],
257267
Protocol[EagerSeriesT, EagerExprT_contra, NativeFrameT_co],
258268
):

narwhals/_compliant/selectors.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@
6666
SeriesT = TypeVar("SeriesT", bound="CompliantSeries")
6767
ExprT = TypeVar("ExprT", bound="NativeExpr")
6868
FrameT = TypeVar(
69-
"FrameT", bound="CompliantDataFrame[Any, Any] | CompliantLazyFrame[Any, Any]"
69+
"FrameT", bound="CompliantDataFrame[Any, Any, Any] | CompliantLazyFrame[Any, Any]"
7070
)
71-
DataFrameT = TypeVar("DataFrameT", bound="CompliantDataFrame[Any, Any]")
71+
DataFrameT = TypeVar("DataFrameT", bound="CompliantDataFrame[Any, Any, Any]")
7272
LazyFrameT = TypeVar("LazyFrameT", bound="CompliantLazyFrame[Any, Any]")
7373
SelectorOrExpr: TypeAlias = (
7474
"CompliantSelector[FrameT, SeriesOrExprT] | CompliantExpr[FrameT, SeriesOrExprT]"
@@ -311,7 +311,7 @@ def __repr__(self: Self) -> str: # pragma: no cover
311311

312312

313313
def _eval_lhs_rhs(
314-
df: CompliantDataFrame[Any, Any] | CompliantLazyFrame[Any, Any],
314+
df: CompliantDataFrame[Any, Any, Any] | CompliantLazyFrame[Any, Any],
315315
lhs: CompliantExpr[Any, Any],
316316
rhs: CompliantExpr[Any, Any],
317317
) -> tuple[Sequence[str], Sequence[str]]:

narwhals/_compliant/typing.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"CompliantLazyFrameT",
2929
"CompliantSeriesT",
3030
"IntoCompliantExpr",
31+
"NativeFrameT_co",
3132
]
3233
NativeExprT_co = TypeVar("NativeExprT_co", bound="NativeExpr", covariant=True)
3334
CompliantSeriesT = TypeVar("CompliantSeriesT", bound="CompliantSeries")
@@ -36,12 +37,14 @@
3637
bound="CompliantSeries | NativeExpr",
3738
covariant=True,
3839
)
39-
4040
NativeFrameT_co = TypeVar("NativeFrameT_co", bound="NativeFrame", covariant=True)
4141
CompliantFrameT = TypeVar(
42-
"CompliantFrameT", bound="CompliantDataFrame[Any, Any] | CompliantLazyFrame[Any, Any]"
42+
"CompliantFrameT",
43+
bound="CompliantDataFrame[Any, Any, Any] | CompliantLazyFrame[Any, Any]",
44+
)
45+
CompliantDataFrameT = TypeVar(
46+
"CompliantDataFrameT", bound="CompliantDataFrame[Any, Any, Any]"
4347
)
44-
CompliantDataFrameT = TypeVar("CompliantDataFrameT", bound="CompliantDataFrame[Any, Any]")
4548
CompliantLazyFrameT = TypeVar("CompliantLazyFrameT", bound="CompliantLazyFrame[Any, Any]")
4649
IntoCompliantExpr: TypeAlias = "CompliantExpr[CompliantFrameT, CompliantSeriesOrNativeExprT_co] | CompliantSeriesOrNativeExprT_co"
4750
CompliantExprT = TypeVar("CompliantExprT", bound="CompliantExpr[Any, Any]")

narwhals/_dask/dataframe.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def collect(
9595
self: Self,
9696
backend: Implementation | None,
9797
**kwargs: Any,
98-
) -> CompliantDataFrame[Any, Any]:
98+
) -> CompliantDataFrame[Any, Any, Any]:
9999
result = self._native_frame.compute(**kwargs)
100100

101101
if backend is None or backend is Implementation.PANDAS:

narwhals/_duckdb/dataframe.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def collect(
9494
self: Self,
9595
backend: ModuleType | Implementation | str | None,
9696
**kwargs: Any,
97-
) -> CompliantDataFrame[Any, Any]:
97+
) -> CompliantDataFrame[Any, Any, Any]:
9898
if backend is None or backend is Implementation.PYARROW:
9999
import pyarrow as pa # ignore-banned-import
100100

narwhals/_expression_parsing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def extract_compliant(
109109

110110
def evaluate_output_names_and_aliases(
111111
expr: CompliantExpr[Any, Any],
112-
df: CompliantDataFrame[Any, Any] | CompliantLazyFrame[Any, Any],
112+
df: CompliantDataFrame[Any, Any, Any] | CompliantLazyFrame[Any, Any],
113113
exclude: Sequence[str],
114114
) -> tuple[Sequence[str], Sequence[str]]:
115115
output_names = expr._evaluate_output_names(df)

0 commit comments

Comments
 (0)