From 26c5cbcd91b4b3f3761b82c93f1e6d79ebcec2c0 Mon Sep 17 00:00:00 2001 From: raisadz <34237447+raisadz@users.noreply.github.com> Date: Sun, 26 Jan 2025 10:54:56 +0000 Subject: [PATCH] feat: raise if expression changes length in `.over()` (#1867) --- narwhals/expr.py | 4 ++++ tests/expr_and_series/over_test.py | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/narwhals/expr.py b/narwhals/expr.py index 5fbb4336d..ea912807a 100644 --- a/narwhals/expr.py +++ b/narwhals/expr.py @@ -13,6 +13,7 @@ from narwhals._expression_parsing import operation_changes_length from narwhals._expression_parsing import operation_is_order_dependent from narwhals.dtypes import _validate_dtype +from narwhals.exceptions import LengthChangingExprError from narwhals.expr_cat import ExprCatNamespace from narwhals.expr_dt import ExprDateTimeNamespace from narwhals.expr_list import ExprListNamespace @@ -2702,6 +2703,9 @@ def over(self: Self, *keys: str | Iterable[str]) -> Self: │ 3 ┆ 2 ┆ 3 │ └─────┴─────┴─────┘ """ + if self._changes_length: + msg = "`.over()` can not be used for expressions which change length." + raise LengthChangingExprError(msg) return self.__class__( lambda plx: self._to_compliant_expr(plx).over(flatten(keys)), self._is_order_dependent, diff --git a/tests/expr_and_series/over_test.py b/tests/expr_and_series/over_test.py index 2ccbe070d..ee8a14806 100644 --- a/tests/expr_and_series/over_test.py +++ b/tests/expr_and_series/over_test.py @@ -1,9 +1,12 @@ from __future__ import annotations +import re + import pandas as pd import pytest import narwhals.stable.v1 as nw +from narwhals.exceptions import LengthChangingExprError from tests.utils import PANDAS_VERSION from tests.utils import Constructor from tests.utils import ConstructorEager @@ -207,3 +210,13 @@ def test_over_cum_reverse() -> None: match=r"Cumulative operation with `reverse=True` is not supported", ): nw.from_native(df).select(nw.col("b").cum_max(reverse=True).over("a")) + + +def test_over_raise_len_change(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) + + with pytest.raises( + LengthChangingExprError, + match=re.escape("`.over()` can not be used for expressions which change length."), + ): + nw.from_native(df).select(nw.col("b").drop_nulls().over("a"))