Skip to content

Commit

Permalink
fix: raise on selectors addition (#1854)
Browse files Browse the repository at this point in the history
  • Loading branch information
FBruzzesi authored Jan 23, 2025
1 parent 23ed049 commit 0f38b77
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 40 deletions.
10 changes: 0 additions & 10 deletions narwhals/_arrow/selectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from typing import TYPE_CHECKING
from typing import Any
from typing import NoReturn
from typing import Sequence

from narwhals._arrow.expr import ArrowExpr
Expand Down Expand Up @@ -178,12 +177,3 @@ def __invert__(self: Self) -> ArrowSelector:
).all()
- self
)

def __rsub__(self: Self, other: Any) -> NoReturn:
raise NotImplementedError

def __rand__(self: Self, other: Any) -> NoReturn:
raise NotImplementedError

def __ror__(self: Self, other: Any) -> NoReturn:
raise NotImplementedError
10 changes: 0 additions & 10 deletions narwhals/_dask/selectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from typing import TYPE_CHECKING
from typing import Any
from typing import NoReturn

from narwhals._dask.expr import DaskExpr
from narwhals.utils import import_dtypes_module
Expand Down Expand Up @@ -186,12 +185,3 @@ def __invert__(self: Self) -> DaskSelector:
).all()
- self
)

def __rsub__(self: Self, other: Any) -> NoReturn:
raise NotImplementedError

def __rand__(self: Self, other: Any) -> NoReturn:
raise NotImplementedError

def __ror__(self: Self, other: Any) -> NoReturn:
raise NotImplementedError
10 changes: 0 additions & 10 deletions narwhals/_pandas_like/selectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from typing import TYPE_CHECKING
from typing import Any
from typing import NoReturn

from narwhals._pandas_like.expr import PandasLikeExpr
from narwhals.utils import import_dtypes_module
Expand Down Expand Up @@ -189,12 +188,3 @@ def __invert__(self: Self) -> PandasSelector:
).all()
- self
)

def __rsub__(self, other: Any) -> NoReturn:
raise NotImplementedError

def __rand__(self, other: Any) -> NoReturn:
raise NotImplementedError

def __ror__(self, other: Any) -> NoReturn:
raise NotImplementedError
29 changes: 28 additions & 1 deletion narwhals/selectors.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
from __future__ import annotations

from typing import TYPE_CHECKING
from typing import Any
from typing import NoReturn

from narwhals.expr import Expr
from narwhals.utils import flatten

if TYPE_CHECKING:
from typing_extensions import Self

class Selector(Expr): ...

class Selector(Expr):
def _to_expr(self: Self) -> Expr:
return Expr(
to_compliant_expr=self._to_compliant_expr,
is_order_dependent=self._is_order_dependent,
changes_length=self._changes_length,
aggregates=self._aggregates,
)

def __add__(self: Self, other: Any) -> Expr: # type: ignore[override]
if isinstance(other, Selector):
msg = "unsupported operand type(s) for op: ('Selector' + 'Selector')"
raise TypeError(msg)
return self._to_expr() + other # type: ignore[no-any-return]

def __rsub__(self: Self, other: Any) -> NoReturn:
raise NotImplementedError

def __rand__(self: Self, other: Any) -> NoReturn:
raise NotImplementedError

def __ror__(self: Self, other: Any) -> NoReturn:
raise NotImplementedError


def by_dtype(*dtypes: Any) -> Expr:
Expand Down
19 changes: 10 additions & 9 deletions tests/selectors_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

import pandas as pd
import pyarrow as pa
import re

import pytest

import narwhals.stable.v1 as nw
Expand Down Expand Up @@ -103,16 +103,17 @@ def test_set_ops(
assert sorted(result) == expected


@pytest.mark.parametrize("invalid_constructor", [pd.DataFrame, pa.table])
def test_set_ops_invalid(
invalid_constructor: Constructor, request: pytest.FixtureRequest
) -> None:
if "duckdb" in str(invalid_constructor):
request.applymarker(pytest.mark.xfail)
df = nw.from_native(invalid_constructor(data))
def test_set_ops_invalid(constructor: Constructor) -> None:
df = nw.from_native(constructor(data))
with pytest.raises((NotImplementedError, ValueError)):
df.select(1 - numeric())
with pytest.raises((NotImplementedError, ValueError)):
df.select(1 | numeric())
with pytest.raises((NotImplementedError, ValueError)):
df.select(1 & numeric())

with pytest.raises(
TypeError,
match=re.escape("unsupported operand type(s) for op: ('Selector' + 'Selector')"),
):
df.select(boolean() + numeric())

0 comments on commit 0f38b77

Please sign in to comment.