Skip to content

Commit b92da86

Browse files
authored
chore: Use _compliant.typing aliases in more places (#2336)
1 parent 9b0bc75 commit b92da86

File tree

10 files changed

+76
-66
lines changed

10 files changed

+76
-66
lines changed

narwhals/_arrow/expr.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from typing import TYPE_CHECKING
44
from typing import Any
5-
from typing import Callable
65
from typing import Literal
76
from typing import Sequence
87

@@ -22,6 +21,9 @@
2221

2322
from narwhals._arrow.dataframe import ArrowDataFrame
2423
from narwhals._arrow.namespace import ArrowNamespace
24+
from narwhals._compliant.typing import AliasNames
25+
from narwhals._compliant.typing import EvalNames
26+
from narwhals._compliant.typing import EvalSeries
2527
from narwhals._expression_parsing import ExprMetadata
2628
from narwhals.utils import Version
2729
from narwhals.utils import _FullContext
@@ -32,12 +34,12 @@ class ArrowExpr(EagerExpr["ArrowDataFrame", ArrowSeries]):
3234

3335
def __init__(
3436
self: Self,
35-
call: Callable[[ArrowDataFrame], Sequence[ArrowSeries]],
37+
call: EvalSeries[ArrowDataFrame, ArrowSeries],
3638
*,
3739
depth: int,
3840
function_name: str,
39-
evaluate_output_names: Callable[[ArrowDataFrame], Sequence[str]],
40-
alias_output_names: Callable[[Sequence[str]], Sequence[str]] | None,
41+
evaluate_output_names: EvalNames[ArrowDataFrame],
42+
alias_output_names: AliasNames | None,
4143
backend_version: tuple[int, ...],
4244
version: Version,
4345
call_kwargs: dict[str, Any] | None = None,
@@ -57,7 +59,7 @@ def __init__(
5759
@classmethod
5860
def from_column_names(
5961
cls: type[Self],
60-
evaluate_column_names: Callable[[ArrowDataFrame], Sequence[str]],
62+
evaluate_column_names: EvalNames[ArrowDataFrame],
6163
/,
6264
*,
6365
context: _FullContext,
@@ -139,11 +141,7 @@ def cum_sum(self: Self, *, reverse: bool) -> Self:
139141
def shift(self: Self, n: int) -> Self:
140142
return self._reuse_series("shift", n=n)
141143

142-
def over(
143-
self: Self,
144-
partition_by: Sequence[str],
145-
order_by: Sequence[str] | None,
146-
) -> Self:
144+
def over(self, partition_by: Sequence[str], order_by: Sequence[str] | None) -> Self:
147145
assert self._metadata is not None # noqa: S101
148146
if partition_by and not is_scalar_like(self._metadata.kind):
149147
msg = "Only aggregation or literal operations are supported in grouped `over` context for PyArrow."

narwhals/_compliant/expr.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@
5858
from narwhals._compliant.namespace import CompliantNamespace
5959
from narwhals._compliant.namespace import EagerNamespace
6060
from narwhals._compliant.series import CompliantSeries
61+
from narwhals._compliant.typing import AliasNames
62+
from narwhals._compliant.typing import EvalNames
63+
from narwhals._compliant.typing import EvalSeries
6164
from narwhals._expression_parsing import ExprKind
6265
from narwhals._expression_parsing import ExprMetadata
6366
from narwhals.dtypes import DType
@@ -84,21 +87,19 @@ class CompliantExpr(Protocol38[CompliantFrameT, CompliantSeriesOrNativeExprT_co]
8487
_implementation: Implementation
8588
_backend_version: tuple[int, ...]
8689
_version: Version
87-
_evaluate_output_names: Callable[[CompliantFrameT], Sequence[str]]
88-
_alias_output_names: Callable[[Sequence[str]], Sequence[str]] | None
90+
_evaluate_output_names: EvalNames[CompliantFrameT]
91+
_alias_output_names: AliasNames | None
8992
_metadata: ExprMetadata | None
9093

9194
def __call__(
9295
self, df: CompliantFrameT
9396
) -> Sequence[CompliantSeriesOrNativeExprT_co]: ...
9497
def __narwhals_expr__(self) -> None: ...
95-
def __narwhals_namespace__(
96-
self,
97-
) -> CompliantNamespace[CompliantFrameT, Self]: ...
98+
def __narwhals_namespace__(self) -> CompliantNamespace[CompliantFrameT, Self]: ...
9899
@classmethod
99100
def from_column_names(
100101
cls,
101-
evaluate_column_names: Callable[[CompliantFrameT], Sequence[str]],
102+
evaluate_column_names: EvalNames[CompliantFrameT],
102103
/,
103104
*,
104105
context: _FullContext,
@@ -298,7 +299,7 @@ class DepthTrackingExpr(
298299
@classmethod
299300
def from_column_names(
300301
cls: type[Self],
301-
evaluate_column_names: Callable[[CompliantFrameT], Sequence[str]],
302+
evaluate_column_names: EvalNames[CompliantFrameT],
302303
/,
303304
*,
304305
context: _FullContext,
@@ -330,17 +331,17 @@ class EagerExpr(
330331
DepthTrackingExpr[EagerDataFrameT, EagerSeriesT],
331332
Protocol38[EagerDataFrameT, EagerSeriesT],
332333
):
333-
_call: Callable[[EagerDataFrameT], Sequence[EagerSeriesT]]
334+
_call: EvalSeries[EagerDataFrameT, EagerSeriesT]
334335
_call_kwargs: dict[str, Any]
335336

336337
def __init__(
337338
self: Self,
338-
call: Callable[[EagerDataFrameT], Sequence[EagerSeriesT]],
339+
call: EvalSeries[EagerDataFrameT, EagerSeriesT],
339340
*,
340341
depth: int,
341342
function_name: str,
342-
evaluate_output_names: Callable[[EagerDataFrameT], Sequence[str]],
343-
alias_output_names: Callable[[Sequence[str]], Sequence[str]] | None,
343+
evaluate_output_names: EvalNames[EagerDataFrameT],
344+
alias_output_names: AliasNames | None,
344345
implementation: Implementation,
345346
backend_version: tuple[int, ...],
346347
version: Version,
@@ -358,12 +359,12 @@ def __narwhals_expr__(self) -> None: ...
358359
@classmethod
359360
def _from_callable(
360361
cls,
361-
func: Callable[[EagerDataFrameT], Sequence[EagerSeriesT]],
362+
func: EvalSeries[EagerDataFrameT, EagerSeriesT],
362363
*,
363364
depth: int,
364365
function_name: str,
365-
evaluate_output_names: Callable[[EagerDataFrameT], Sequence[str]],
366-
alias_output_names: Callable[[Sequence[str]], Sequence[str]] | None,
366+
evaluate_output_names: EvalNames[EagerDataFrameT],
367+
alias_output_names: AliasNames | None,
367368
context: _FullContext,
368369
call_kwargs: dict[str, Any] | None = None,
369370
) -> Self:

narwhals/_compliant/typing.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from narwhals._compliant.expr import EagerExpr
1818
from narwhals._compliant.expr import LazyExpr
1919
from narwhals._compliant.expr import NativeExpr
20+
from narwhals._compliant.namespace import CompliantNamespace
2021
from narwhals._compliant.namespace import EagerNamespace
2122
from narwhals._compliant.series import CompliantSeries
2223
from narwhals._compliant.series import EagerSeries
@@ -42,6 +43,7 @@
4243
CompliantDataFrameAny: TypeAlias = "CompliantDataFrame[Any, Any, Any]"
4344
CompliantLazyFrameAny: TypeAlias = "CompliantLazyFrame[Any, Any]"
4445
CompliantFrameAny: TypeAlias = "CompliantDataFrameAny | CompliantLazyFrameAny"
46+
CompliantNamespaceAny: TypeAlias = "CompliantNamespace[Any, Any]"
4547

4648
DepthTrackingExprAny: TypeAlias = "DepthTrackingExpr[Any, Any]"
4749

@@ -110,8 +112,18 @@
110112
LazyExprT_contra = TypeVar("LazyExprT_contra", bound=LazyExprAny, contravariant=True)
111113

112114
AliasNames: TypeAlias = Callable[[Sequence[str]], Sequence[str]]
115+
"""A function aliasing a *sequence* of column names."""
116+
113117
AliasName: TypeAlias = Callable[[str], str]
118+
"""A function aliasing a *single* column name."""
119+
114120
EvalSeries: TypeAlias = Callable[
115121
[CompliantFrameT], Sequence[CompliantSeriesOrNativeExprT]
116122
]
123+
"""A function from a `Frame` to a sequence of `Series`*.
124+
125+
See [underwater unicorn magic](https://narwhals-dev.github.io/narwhals/how_it_works/).
126+
"""
127+
117128
EvalNames: TypeAlias = Callable[[CompliantFrameT], Sequence[str]]
129+
"""A function from a `Frame` to a sequence of columns names *before* any aliasing takes place."""

narwhals/_compliant/when_then.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from typing_extensions import Self
2525
from typing_extensions import TypeAlias
2626

27+
from narwhals._compliant.typing import EvalSeries
2728
from narwhals.utils import Implementation
2829
from narwhals.utils import Version
2930
from narwhals.utils import _FullContext
@@ -82,7 +83,7 @@ def from_expr(cls, condition: ExprT, /, *, context: _FullContext) -> Self:
8283

8384

8485
class CompliantThen(CompliantExpr[FrameT, SeriesT], Protocol38[FrameT, SeriesT, ExprT]):
85-
_call: Callable[[FrameT], Sequence[SeriesT]]
86+
_call: EvalSeries[FrameT, SeriesT]
8687
_when_value: CompliantWhen[FrameT, SeriesT, ExprT]
8788
_function_name: str
8889
_depth: int

narwhals/_dask/expr.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434

3535
from typing_extensions import Self
3636

37+
from narwhals._compliant.typing import EvalNames
38+
from narwhals._compliant.typing import EvalSeries
3739
from narwhals._dask.dataframe import DaskLazyFrame
3840
from narwhals._dask.namespace import DaskNamespace
3941
from narwhals._expression_parsing import ExprMetadata
@@ -50,12 +52,12 @@ class DaskExpr(
5052

5153
def __init__(
5254
self: Self,
53-
call: Callable[[DaskLazyFrame], Sequence[dx.Series]],
55+
call: EvalSeries[DaskLazyFrame, dx.Series],
5456
*,
5557
depth: int,
5658
function_name: str,
57-
evaluate_output_names: Callable[[DaskLazyFrame], Sequence[str]],
58-
alias_output_names: Callable[[Sequence[str]], Sequence[str]] | None,
59+
evaluate_output_names: EvalNames[DaskLazyFrame],
60+
alias_output_names: AliasNames | None,
5961
backend_version: tuple[int, ...],
6062
version: Version,
6163
# Kwargs with metadata which we may need in group-by agg
@@ -101,7 +103,7 @@ def func(df: DaskLazyFrame) -> list[dx.Series]:
101103
@classmethod
102104
def from_column_names(
103105
cls: type[Self],
104-
evaluate_column_names: Callable[[DaskLazyFrame], Sequence[str]],
106+
evaluate_column_names: EvalNames[DaskLazyFrame],
105107
/,
106108
*,
107109
context: _FullContext,

narwhals/_duckdb/expr.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
from typing_extensions import Self
3535

3636
from narwhals._compliant.typing import AliasNames
37+
from narwhals._compliant.typing import EvalNames
38+
from narwhals._compliant.typing import EvalSeries
3739
from narwhals._duckdb.dataframe import DuckDBLazyFrame
3840
from narwhals._duckdb.namespace import DuckDBNamespace
3941
from narwhals._duckdb.typing import WindowFunction
@@ -51,10 +53,10 @@ class DuckDBExpr(LazyExpr["DuckDBLazyFrame", "duckdb.Expression"]):
5153

5254
def __init__(
5355
self: Self,
54-
call: Callable[[DuckDBLazyFrame], Sequence[duckdb.Expression]],
56+
call: EvalSeries[DuckDBLazyFrame, duckdb.Expression],
5557
*,
56-
evaluate_output_names: Callable[[DuckDBLazyFrame], Sequence[str]],
57-
alias_output_names: Callable[[Sequence[str]], Sequence[str]] | None,
58+
evaluate_output_names: EvalNames[DuckDBLazyFrame],
59+
alias_output_names: AliasNames | None,
5860
backend_version: tuple[int, ...],
5961
version: Version,
6062
) -> None:
@@ -168,7 +170,7 @@ def func(df: DuckDBLazyFrame) -> Sequence[duckdb.Expression]:
168170
@classmethod
169171
def from_column_names(
170172
cls: type[Self],
171-
evaluate_column_names: Callable[[DuckDBLazyFrame], Sequence[str]],
173+
evaluate_column_names: EvalNames[DuckDBLazyFrame],
172174
/,
173175
*,
174176
context: _FullContext,
@@ -243,10 +245,7 @@ def _with_alias_output_names(self, func: AliasNames | None, /) -> Self:
243245
version=self._version,
244246
)
245247

246-
def _with_window_function(
247-
self: Self,
248-
window_function: WindowFunction,
249-
) -> Self:
248+
def _with_window_function(self, window_function: WindowFunction) -> Self:
250249
result = self.__class__(
251250
self._call,
252251
evaluate_output_names=self._evaluate_output_names,

narwhals/_expression_parsing.py

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from itertools import chain
99
from typing import TYPE_CHECKING
1010
from typing import Any
11-
from typing import Callable
1211
from typing import Literal
1312
from typing import Sequence
1413
from typing import TypeVar
@@ -29,10 +28,13 @@
2928
from narwhals._compliant import CompliantExprT
3029
from narwhals._compliant import CompliantFrameT
3130
from narwhals._compliant import CompliantNamespace
31+
from narwhals._compliant.typing import AliasNames
32+
from narwhals._compliant.typing import CompliantExprAny
33+
from narwhals._compliant.typing import CompliantFrameAny
34+
from narwhals._compliant.typing import CompliantNamespaceAny
3235
from narwhals._compliant.typing import EagerNamespaceAny
36+
from narwhals._compliant.typing import EvalNames
3337
from narwhals.expr import Expr
34-
from narwhals.typing import CompliantDataFrame
35-
from narwhals.typing import CompliantLazyFrame
3638
from narwhals.typing import IntoExpr
3739
from narwhals.typing import _1DArray
3840

@@ -48,7 +50,7 @@ def is_expr(obj: Any) -> TypeIs[Expr]:
4850

4951
def combine_evaluate_output_names(
5052
*exprs: CompliantExpr[CompliantFrameT, Any],
51-
) -> Callable[[CompliantFrameT], Sequence[str]]:
53+
) -> EvalNames[CompliantFrameT]:
5254
# Follow left-hand-rule for naming. E.g. `nw.sum_horizontal(expr1, expr2)` takes the
5355
# first name of `expr1`.
5456
if not is_compliant_expr(exprs[0]): # pragma: no cover
@@ -61,9 +63,7 @@ def evaluate_output_names(df: CompliantFrameT) -> Sequence[str]:
6163
return evaluate_output_names
6264

6365

64-
def combine_alias_output_names(
65-
*exprs: CompliantExpr[Any, Any],
66-
) -> Callable[[Sequence[str]], Sequence[str]] | None:
66+
def combine_alias_output_names(*exprs: CompliantExprAny) -> AliasNames | None:
6767
# Follow left-hand-rule for naming. E.g. `nw.sum_horizontal(expr1.alias(alias), expr2)` takes the
6868
# aliasing function of `expr1` and apply it to the first output name of `expr1`.
6969
if exprs[0]._alias_output_names is None:
@@ -91,9 +91,7 @@ def extract_compliant(
9191

9292

9393
def evaluate_output_names_and_aliases(
94-
expr: CompliantExpr[Any, Any],
95-
df: CompliantDataFrame[Any, Any, Any] | CompliantLazyFrame[Any, Any],
96-
exclude: Sequence[str],
94+
expr: CompliantExprAny, df: CompliantFrameAny, exclude: Sequence[str]
9795
) -> tuple[Sequence[str], Sequence[str]]:
9896
output_names = expr._evaluate_output_names(df)
9997
if not output_names:
@@ -410,11 +408,8 @@ def infer_kind(obj: IntoExpr | _1DArray | object, *, str_as_lit: bool) -> ExprKi
410408

411409

412410
def apply_n_ary_operation(
413-
plx: CompliantNamespace[Any, Any],
414-
function: Any,
415-
*comparands: IntoExpr,
416-
str_as_lit: bool,
417-
) -> CompliantExpr[Any, Any]:
411+
plx: CompliantNamespaceAny, function: Any, *comparands: IntoExpr, str_as_lit: bool
412+
) -> CompliantExprAny:
418413
compliant_exprs = (
419414
extract_compliant(plx, comparand, str_as_lit=str_as_lit)
420415
for comparand in comparands

narwhals/_pandas_like/expr.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from typing import TYPE_CHECKING
44
from typing import Any
5-
from typing import Callable
65
from typing import Literal
76
from typing import Sequence
87

@@ -16,6 +15,9 @@
1615
if TYPE_CHECKING:
1716
from typing_extensions import Self
1817

18+
from narwhals._compliant.typing import AliasNames
19+
from narwhals._compliant.typing import EvalNames
20+
from narwhals._compliant.typing import EvalSeries
1921
from narwhals._expression_parsing import ExprMetadata
2022
from narwhals._pandas_like.dataframe import PandasLikeDataFrame
2123
from narwhals._pandas_like.namespace import PandasLikeNamespace
@@ -71,12 +73,12 @@ def window_kwargs_to_pandas_equivalent(
7173
class PandasLikeExpr(EagerExpr["PandasLikeDataFrame", PandasLikeSeries]):
7274
def __init__(
7375
self: Self,
74-
call: Callable[[PandasLikeDataFrame], Sequence[PandasLikeSeries]],
76+
call: EvalSeries[PandasLikeDataFrame, PandasLikeSeries],
7577
*,
7678
depth: int,
7779
function_name: str,
78-
evaluate_output_names: Callable[[PandasLikeDataFrame], Sequence[str]],
79-
alias_output_names: Callable[[Sequence[str]], Sequence[str]] | None,
80+
evaluate_output_names: EvalNames[PandasLikeDataFrame],
81+
alias_output_names: AliasNames | None,
8082
implementation: Implementation,
8183
backend_version: tuple[int, ...],
8284
version: Version,
@@ -105,7 +107,7 @@ def __narwhals_expr__(self) -> None: ...
105107
@classmethod
106108
def from_column_names(
107109
cls: type[Self],
108-
evaluate_column_names: Callable[[PandasLikeDataFrame], Sequence[str]],
110+
evaluate_column_names: EvalNames[PandasLikeDataFrame],
109111
/,
110112
*,
111113
context: _FullContext,

0 commit comments

Comments
 (0)