Skip to content

Commit c5ada4a

Browse files
committed
refactor: Deduplicate most Into* typing
`v1` is different for the frame cases #3016 (comment)
1 parent d1f45bb commit c5ada4a

File tree

4 files changed

+125
-216
lines changed

4 files changed

+125
-216
lines changed

narwhals/_native.py

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from collections.abc import Callable, Collection, Iterable, Sized
4-
from typing import TYPE_CHECKING, Any, Protocol, TypeVar, cast
4+
from typing import TYPE_CHECKING, Any, Protocol, TypeVar, Union, cast
55

66
from narwhals.dependencies import (
77
get_cudf,
@@ -30,6 +30,14 @@
3030
_Guard: TypeAlias = "Callable[[Any], TypeIs[T]]"
3131

3232
__all__ = [
33+
"IntoDataFrame",
34+
"IntoDataFrameT",
35+
"IntoFrame",
36+
"IntoFrameT",
37+
"IntoLazyFrame",
38+
"IntoLazyFrameT",
39+
"IntoSeries",
40+
"IntoSeriesT",
3341
"NativeAny",
3442
"NativeArrow",
3543
"NativeCuDF",
@@ -169,6 +177,94 @@ def dropDuplicatesWithinWatermark(self, *arg: Any, **kwargs: Any) -> Any: ... #
169177
NativeUnknown: TypeAlias = "NativeDataFrame | NativeSeries | NativeLazyFrame"
170178
NativeAny: TypeAlias = "NativeKnown | NativeUnknown"
171179

180+
IntoDataFrame: TypeAlias = NativeDataFrame
181+
"""Anything which can be converted to a Narwhals DataFrame.
182+
183+
Use this if your function accepts a narwhalifiable object but doesn't care about its backend.
184+
185+
Examples:
186+
>>> import narwhals as nw
187+
>>> from narwhals.typing import IntoDataFrame
188+
>>> def agnostic_shape(df_native: IntoDataFrame) -> tuple[int, int]:
189+
... df = nw.from_native(df_native, eager_only=True)
190+
... return df.shape
191+
"""
192+
193+
IntoLazyFrame: TypeAlias = Union[NativeLazyFrame, NativeIbis]
194+
195+
IntoFrame: TypeAlias = Union[IntoDataFrame, IntoLazyFrame]
196+
"""Anything which can be converted to a Narwhals DataFrame or LazyFrame.
197+
198+
Use this if your function can accept an object which can be converted to either
199+
`nw.DataFrame` or `nw.LazyFrame` and it doesn't care about its backend.
200+
201+
Examples:
202+
>>> import narwhals as nw
203+
>>> from narwhals.typing import IntoFrame
204+
>>> def agnostic_columns(df_native: IntoFrame) -> list[str]:
205+
... df = nw.from_native(df_native)
206+
... return df.collect_schema().names()
207+
"""
208+
209+
IntoSeries: TypeAlias = NativeSeries
210+
"""Anything which can be converted to a Narwhals Series.
211+
212+
Use this if your function can accept an object which can be converted to `nw.Series`
213+
and it doesn't care about its backend.
214+
215+
Examples:
216+
>>> from typing import Any
217+
>>> import narwhals as nw
218+
>>> from narwhals.typing import IntoSeries
219+
>>> def agnostic_to_list(s_native: IntoSeries) -> list[Any]:
220+
... s = nw.from_native(s_native)
221+
... return s.to_list()
222+
"""
223+
224+
IntoFrameT = TypeVar("IntoFrameT", bound=IntoFrame)
225+
"""TypeVar bound to object convertible to Narwhals DataFrame or Narwhals LazyFrame.
226+
227+
Use this if your function accepts an object which is convertible to `nw.DataFrame`
228+
or `nw.LazyFrame` and returns an object of the same type.
229+
230+
Examples:
231+
>>> import narwhals as nw
232+
>>> from narwhals.typing import IntoFrameT
233+
>>> def agnostic_func(df_native: IntoFrameT) -> IntoFrameT:
234+
... df = nw.from_native(df_native)
235+
... return df.with_columns(c=nw.col("a") + 1).to_native()
236+
"""
237+
238+
IntoDataFrameT = TypeVar("IntoDataFrameT", bound=IntoDataFrame)
239+
"""TypeVar bound to object convertible to Narwhals DataFrame.
240+
241+
Use this if your function accepts an object which can be converted to `nw.DataFrame`
242+
and returns an object of the same class.
243+
244+
Examples:
245+
>>> import narwhals as nw
246+
>>> from narwhals.typing import IntoDataFrameT
247+
>>> def agnostic_func(df_native: IntoDataFrameT) -> IntoDataFrameT:
248+
... df = nw.from_native(df_native, eager_only=True)
249+
... return df.with_columns(c=df["a"] + 1).to_native()
250+
"""
251+
252+
IntoLazyFrameT = TypeVar("IntoLazyFrameT", bound=IntoLazyFrame)
253+
254+
IntoSeriesT = TypeVar("IntoSeriesT", bound=IntoSeries)
255+
"""TypeVar bound to object convertible to Narwhals Series.
256+
257+
Use this if your function accepts an object which can be converted to `nw.Series`
258+
and returns an object of the same class.
259+
260+
Examples:
261+
>>> import narwhals as nw
262+
>>> from narwhals.typing import IntoSeriesT
263+
>>> def agnostic_abs(s_native: IntoSeriesT) -> IntoSeriesT:
264+
... s = nw.from_native(s_native, series_only=True)
265+
... return s.abs().to_native()
266+
"""
267+
172268

173269
def is_native_polars(obj: Any) -> TypeIs[NativePolars]:
174270
return (pl := get_polars()) is not None and isinstance(

narwhals/stable/v1/typing.py

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
from typing import TYPE_CHECKING, Any, Protocol, TypeVar, Union
44

5+
from narwhals._native import IntoSeries, IntoSeriesT
6+
57
if TYPE_CHECKING:
68
from typing_extensions import TypeAlias
79

8-
from narwhals._native import NativeDataFrame, NativeLazyFrame, NativeSeries
10+
from narwhals._native import NativeDataFrame, NativeLazyFrame
911
from narwhals.stable.v1 import DataFrame, Expr, LazyFrame, Series
1012

1113
class DataFrameLike(Protocol):
@@ -22,7 +24,6 @@ def __dataframe__(self, *args: Any, **kwargs: Any) -> Any: ...
2224
`nw.Expr`, e.g. `df.select('a')`.
2325
"""
2426

25-
2627
IntoDataFrame: TypeAlias = Union["NativeDataFrame", "DataFrameLike"]
2728
"""Anything which can be converted to a Narwhals DataFrame.
2829
@@ -37,7 +38,6 @@ def __dataframe__(self, *args: Any, **kwargs: Any) -> Any: ...
3738
"""
3839

3940
IntoLazyFrame: TypeAlias = "NativeLazyFrame"
40-
4141
IntoFrame: TypeAlias = Union["IntoDataFrame", "IntoLazyFrame"]
4242
"""Anything which can be converted to a Narwhals DataFrame or LazyFrame.
4343
@@ -66,21 +66,6 @@ def __dataframe__(self, *args: Any, **kwargs: Any) -> Any: ...
6666
... return df.columns
6767
"""
6868

69-
IntoSeries: TypeAlias = "NativeSeries"
70-
"""Anything which can be converted to a Narwhals Series.
71-
72-
Use this if your function can accept an object which can be converted to `nw.Series`
73-
and it doesn't care about its backend.
74-
75-
Examples:
76-
>>> from typing import Any
77-
>>> import narwhals as nw
78-
>>> from narwhals.typing import IntoSeries
79-
>>> def agnostic_to_list(s_native: IntoSeries) -> list[Any]:
80-
... s = nw.from_native(s_native)
81-
... return s.to_list()
82-
"""
83-
8469
IntoFrameT = TypeVar("IntoFrameT", bound="IntoFrame")
8570
"""TypeVar bound to object convertible to Narwhals DataFrame or Narwhals LazyFrame.
8671
@@ -110,7 +95,6 @@ def __dataframe__(self, *args: Any, **kwargs: Any) -> Any: ...
11095
"""
11196

11297
IntoLazyFrameT = TypeVar("IntoLazyFrameT", bound="IntoLazyFrame")
113-
11498
FrameT = TypeVar("FrameT", "DataFrame[Any]", "LazyFrame[Any]")
11599
"""TypeVar bound to Narwhals DataFrame or Narwhals LazyFrame.
116100
@@ -139,20 +123,6 @@ def __dataframe__(self, *args: Any, **kwargs: Any) -> Any: ...
139123
... return df.with_columns(c=df["a"] + 1)
140124
"""
141125

142-
IntoSeriesT = TypeVar("IntoSeriesT", bound="IntoSeries")
143-
"""TypeVar bound to object convertible to Narwhals Series.
144-
145-
Use this if your function accepts an object which can be converted to `nw.Series`
146-
and returns an object of the same class.
147-
148-
Examples:
149-
>>> import narwhals as nw
150-
>>> from narwhals.typing import IntoSeriesT
151-
>>> def agnostic_abs(s_native: IntoSeriesT) -> IntoSeriesT:
152-
... s = nw.from_native(s_native, series_only=True)
153-
... return s.abs().to_native()
154-
"""
155-
156126

157127
__all__ = [
158128
"DataFrameT",

narwhals/stable/v2/typing.py

Lines changed: 13 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,20 @@
22

33
from typing import TYPE_CHECKING, Any, TypeVar, Union
44

5+
from narwhals._native import (
6+
IntoDataFrame,
7+
IntoDataFrameT,
8+
IntoFrame,
9+
IntoFrameT,
10+
IntoLazyFrame,
11+
IntoLazyFrameT,
12+
IntoSeries,
13+
IntoSeriesT,
14+
)
15+
516
if TYPE_CHECKING:
617
from typing_extensions import TypeAlias
718

8-
from narwhals._native import NativeDataFrame, NativeLazyFrame, NativeSeries
919
from narwhals.stable.v2 import DataFrame, Expr, LazyFrame, Series
1020

1121

@@ -19,35 +29,6 @@
1929
`nw.Expr`, e.g. `df.select('a')`.
2030
"""
2131

22-
IntoDataFrame: TypeAlias = "NativeDataFrame"
23-
"""Anything which can be converted to a Narwhals DataFrame.
24-
25-
Use this if your function accepts a narwhalifiable object but doesn't care about its backend.
26-
27-
Examples:
28-
>>> import narwhals as nw
29-
>>> from narwhals.typing import IntoDataFrame
30-
>>> def agnostic_shape(df_native: IntoDataFrame) -> tuple[int, int]:
31-
... df = nw.from_native(df_native, eager_only=True)
32-
... return df.shape
33-
"""
34-
35-
IntoLazyFrame: TypeAlias = "NativeLazyFrame"
36-
37-
IntoFrame: TypeAlias = Union["IntoDataFrame", "IntoLazyFrame"]
38-
"""Anything which can be converted to a Narwhals DataFrame or LazyFrame.
39-
40-
Use this if your function can accept an object which can be converted to either
41-
`nw.DataFrame` or `nw.LazyFrame` and it doesn't care about its backend.
42-
43-
Examples:
44-
>>> import narwhals as nw
45-
>>> from narwhals.typing import IntoFrame
46-
>>> def agnostic_columns(df_native: IntoFrame) -> list[str]:
47-
... df = nw.from_native(df_native)
48-
... return df.collect_schema().names()
49-
"""
50-
5132
Frame: TypeAlias = Union["DataFrame[Any]", "LazyFrame[Any]"]
5233
"""Narwhals DataFrame or Narwhals LazyFrame.
5334
@@ -62,49 +43,6 @@
6243
... return df.columns
6344
"""
6445

65-
IntoSeries: TypeAlias = "NativeSeries"
66-
"""Anything which can be converted to a Narwhals Series.
67-
68-
Use this if your function can accept an object which can be converted to `nw.Series`
69-
and it doesn't care about its backend.
70-
71-
Examples:
72-
>>> from typing import Any
73-
>>> import narwhals as nw
74-
>>> from narwhals.typing import IntoSeries
75-
>>> def agnostic_to_list(s_native: IntoSeries) -> list[Any]:
76-
... s = nw.from_native(s_native)
77-
... return s.to_list()
78-
"""
79-
80-
IntoFrameT = TypeVar("IntoFrameT", bound="IntoFrame")
81-
"""TypeVar bound to object convertible to Narwhals DataFrame or Narwhals LazyFrame.
82-
83-
Use this if your function accepts an object which is convertible to `nw.DataFrame`
84-
or `nw.LazyFrame` and returns an object of the same type.
85-
86-
Examples:
87-
>>> import narwhals as nw
88-
>>> from narwhals.typing import IntoFrameT
89-
>>> def agnostic_func(df_native: IntoFrameT) -> IntoFrameT:
90-
... df = nw.from_native(df_native)
91-
... return df.with_columns(c=nw.col("a") + 1).to_native()
92-
"""
93-
94-
IntoDataFrameT = TypeVar("IntoDataFrameT", bound="IntoDataFrame")
95-
"""TypeVar bound to object convertible to Narwhals DataFrame.
96-
97-
Use this if your function accepts an object which can be converted to `nw.DataFrame`
98-
and returns an object of the same class.
99-
100-
Examples:
101-
>>> import narwhals as nw
102-
>>> from narwhals.typing import IntoDataFrameT
103-
>>> def agnostic_func(df_native: IntoDataFrameT) -> IntoDataFrameT:
104-
... df = nw.from_native(df_native, eager_only=True)
105-
... return df.with_columns(c=df["a"] + 1).to_native()
106-
"""
107-
10846
FrameT = TypeVar("FrameT", "DataFrame[Any]", "LazyFrame[Any]")
10947
"""TypeVar bound to Narwhals DataFrame or Narwhals LazyFrame.
11048
@@ -133,20 +71,6 @@
13371
... return df.with_columns(c=df["a"] + 1)
13472
"""
13573

136-
IntoSeriesT = TypeVar("IntoSeriesT", bound="IntoSeries")
137-
"""TypeVar bound to object convertible to Narwhals Series.
138-
139-
Use this if your function accepts an object which can be converted to `nw.Series`
140-
and returns an object of the same class.
141-
142-
Examples:
143-
>>> import narwhals as nw
144-
>>> from narwhals.typing import IntoSeriesT
145-
>>> def agnostic_abs(s_native: IntoSeriesT) -> IntoSeriesT:
146-
... s = nw.from_native(s_native, series_only=True)
147-
... return s.abs().to_native()
148-
"""
149-
15074

15175
__all__ = [
15276
"DataFrameT",
@@ -157,6 +81,8 @@
15781
"IntoExpr",
15882
"IntoFrame",
15983
"IntoFrameT",
84+
"IntoLazyFrame",
85+
"IntoLazyFrameT",
16086
"IntoSeries",
16187
"IntoSeriesT",
16288
]

0 commit comments

Comments
 (0)