Skip to content

Commit f954e05

Browse files
committed
test: A bunch of parsing cov
1 parent 4c39f51 commit f954e05

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

tests/plan/expr_parsing_test.py

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
from narwhals._plan._parse import parse_into_seq_of_expr_ir
1616
from narwhals._plan.expressions import functions as F, operators as ops
1717
from narwhals._plan.expressions.literal import SeriesLiteral
18+
from narwhals._plan.expressions.ranges import IntRange
1819
from narwhals.exceptions import (
1920
ComputeError,
2021
InvalidIntoExprError,
2122
InvalidOperationError,
2223
InvalidOperationError as LengthChangingExprError,
24+
MultiOutputExpressionError,
2325
ShapeError,
2426
)
2527
from tests.plan.utils import assert_expr_ir_equal, re_compile
@@ -127,7 +129,7 @@ def test_valid_windows() -> None:
127129
assert nwp.sum_horizontal(a.diff().abs(), a.cum_sum()).over(order_by="i")
128130

129131

130-
def test_invalid_repeat_agg() -> None:
132+
def test_repeat_agg_invalid() -> None:
131133
with pytest.raises(InvalidOperationError):
132134
nwp.col("a").mean().mean()
133135
with pytest.raises(InvalidOperationError):
@@ -144,7 +146,7 @@ def test_invalid_repeat_agg() -> None:
144146

145147
# NOTE: Previously multiple different errors, but they can be reduced to the same thing
146148
# Once we are scalar, only elementwise is allowed
147-
def test_invalid_agg_non_elementwise() -> None:
149+
def test_agg_non_elementwise_invalid() -> None:
148150
pattern = re.compile(r"cannot use.+rank.+aggregated.+mean", re.IGNORECASE)
149151
with pytest.raises(InvalidOperationError, match=pattern):
150152
nwp.col("a").mean().rank()
@@ -167,7 +169,7 @@ def test_agg_non_elementwise_range_special() -> None:
167169
assert isinstance(e_ir.expr.input[1], ir.Len)
168170

169171

170-
def test_invalid_int_range() -> None:
172+
def test_int_range_invalid() -> None:
171173
pattern = re.compile(r"scalar.+agg", re.IGNORECASE)
172174
with pytest.raises(InvalidOperationError, match=pattern):
173175
nwp.int_range(nwp.col("a"))
@@ -177,16 +179,37 @@ def test_invalid_int_range() -> None:
177179
nwp.int_range(0, nwp.col("a").abs())
178180
with pytest.raises(InvalidOperationError, match=pattern):
179181
nwp.int_range(nwp.col("a") + 1)
182+
with pytest.raises(InvalidOperationError, match=pattern):
183+
nwp.int_range((1 + nwp.col("b")).name.keep())
184+
int_range = IntRange(step=1, dtype=nw.Int64())
185+
with pytest.raises(InvalidOperationError, match=r"at least 2 inputs.+int_range"):
186+
int_range.to_function_expr(ir.col("a"))
187+
188+
189+
@pytest.mark.xfail(
190+
reason="Not implemented `int_range(eager=True)`", raises=NotImplementedError
191+
)
192+
def test_int_range_series() -> None:
193+
assert isinstance(nwp.int_range(50, eager=True), nwp.Series)
180194

181195

182-
# NOTE: Non-`polars`` rule
183-
def test_invalid_over() -> None:
196+
def test_over_invalid() -> None:
197+
with pytest.raises(TypeError, match=r"one of.+partition_by.+or.+order_by"):
198+
nwp.col("a").last().over()
199+
200+
# NOTE: Non-`polars` rule
184201
pattern = re.compile(r"cannot use.+over.+elementwise", re.IGNORECASE)
185202
with pytest.raises(InvalidOperationError, match=pattern):
186203
nwp.col("a").fill_null(3).over("b")
187204

205+
# NOTE: This version isn't elementwise
206+
expr_ir = nwp.col("a").fill_null(strategy="backward").over("b")._ir
207+
assert isinstance(expr_ir, ir.WindowExpr)
208+
assert isinstance(expr_ir.expr, ir.FunctionExpr)
209+
assert isinstance(expr_ir.expr.function, F.FillNullWithStrategy)
210+
188211

189-
def test_nested_over() -> None:
212+
def test_over_nested() -> None:
190213
pattern = re.compile(r"cannot nest.+over", re.IGNORECASE)
191214
with pytest.raises(InvalidOperationError, match=pattern):
192215
nwp.col("a").mean().over("b").over("c")
@@ -196,7 +219,7 @@ def test_nested_over() -> None:
196219

197220
# NOTE: This *can* error in polars, but only if the length **actually changes**
198221
# The rule then breaks down to needing the same length arrays in all parts of the over
199-
def test_filtration_over() -> None:
222+
def test_over_filtration() -> None:
200223
pattern = re.compile(r"cannot use.+over.+change length", re.IGNORECASE)
201224
with pytest.raises(InvalidOperationError, match=pattern):
202225
nwp.col("a").drop_nulls().over("b")
@@ -206,9 +229,9 @@ def test_filtration_over() -> None:
206229
nwp.col("a").diff().drop_nulls().over("b", order_by="i")
207230

208231

209-
def test_invalid_binary_expr_length_changing() -> None:
232+
def test_binary_expr_length_changing_invalid() -> None:
210233
a = nwp.col("a")
211-
b = nwp.col("b")
234+
b = nwp.col("b").exp()
212235

213236
with pytest.raises(LengthChangingExprError):
214237
a.unique() + b.unique()
@@ -247,7 +270,7 @@ def test_binary_expr_length_changing_agg() -> None:
247270
)
248271

249272

250-
def test_invalid_binary_expr_shape() -> None:
273+
def test_binary_expr_shape_invalid() -> None:
251274
pattern = re.compile(
252275
re.escape("Cannot combine length-changing expressions with length-preserving"),
253276
re.IGNORECASE,
@@ -261,6 +284,8 @@ def test_invalid_binary_expr_shape() -> None:
261284
a.map_batches(lambda x: x, is_elementwise=True) * b.gather_every(1, 0)
262285
with pytest.raises(ShapeError, match=pattern):
263286
a / b.drop_nulls()
287+
with pytest.raises(ShapeError, match=pattern):
288+
a.fill_null(1) // b.rolling_mean(5)
264289

265290

266291
@pytest.mark.parametrize("into_iter", [list, tuple, deque, iter, dict.fromkeys, set])
@@ -306,7 +331,7 @@ def test_is_in_series() -> None:
306331
),
307332
],
308333
)
309-
def test_invalid_is_in(other: Any, context: AbstractContextManager[Any]) -> None:
334+
def test_is_in_invalid(other: Any, context: AbstractContextManager[Any]) -> None:
310335
with context:
311336
nwp.col("a").is_in(other)
312337

0 commit comments

Comments
 (0)