Skip to content

Commit 6c66272

Browse files
authored
fix: is_in was raising when used with empty list (#2031)
1 parent 2b58ee7 commit 6c66272

File tree

7 files changed

+18
-11
lines changed

7 files changed

+18
-11
lines changed

.github/workflows/downstream_tests.yml

+2
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ jobs:
8383
run: |
8484
cd marimo
8585
. .venv/bin/activate
86+
# temporary to get CI green
87+
uv pip install "panel<1.6.1"
8688
uv pip install -e ".[dev]"
8789
which python
8890
- name: install-narwhals-dev

narwhals/_arrow/series.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -545,10 +545,8 @@ def tail(self: Self, n: int) -> Self:
545545
return self._from_native_series(ser.slice(abs(n)))
546546

547547
def is_in(self: Self, other: Any) -> Self:
548-
if isinstance(other, list) and isinstance(other[0], self.__class__):
549-
# We can't use `broadcast_and_align` because we don't want to align here.
550-
# `other` is just a sequence that all rows from `self` are checked against.
551-
value_set = other[0]._native_series
548+
if isinstance(other, pa.ChunkedArray):
549+
value_set: ArrowChunkedArray | ArrowArray = other
552550
else:
553551
value_set = pa.array(other)
554552
ser = self._native_series

narwhals/_duckdb/expr.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,9 @@ def is_finite(self: Self) -> Self:
494494

495495
def is_in(self: Self, other: Sequence[Any]) -> Self:
496496
return self._from_call(
497-
lambda _input: _input.isin(*[lit(x) for x in other]),
497+
lambda _input: lit(False) # noqa: FBT003
498+
if not other
499+
else _input.isin(*[lit(x) for x in other]),
498500
"is_in",
499501
expr_kind=self._expr_kind,
500502
)

narwhals/_pandas_like/series.py

-4
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,6 @@ def is_between(
300300

301301
def is_in(self: Self, other: Any) -> PandasLikeSeries:
302302
ser = self._native_series
303-
if isinstance(other, list) and isinstance(other[0], self.__class__):
304-
# We can't use `broadcast_and_align` because we don't want to align here.
305-
# `other` is just a sequence that all rows from `self` are checked against.
306-
other = other[0]._native_series
307303
res = ser.isin(other)
308304
return self._from_native_series(res)
309305

narwhals/expr.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from narwhals.expr_list import ExprListNamespace
2121
from narwhals.expr_name import ExprNameNamespace
2222
from narwhals.expr_str import ExprStringNamespace
23+
from narwhals.translate import to_native
2324
from narwhals.utils import _validate_rolling_arguments
2425
from narwhals.utils import flatten
2526
from narwhals.utils import issue_deprecation_warning
@@ -1254,7 +1255,7 @@ def is_in(self: Self, other: Any) -> Self:
12541255
if isinstance(other, Iterable) and not isinstance(other, (str, bytes)):
12551256
return self.__class__(
12561257
lambda plx: self._to_compliant_expr(plx).is_in(
1257-
extract_compliant(plx, other, strings_are_column_names=False)
1258+
to_native(other, pass_through=True)
12581259
),
12591260
self._metadata,
12601261
)

narwhals/series.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ def is_in(self: Self, other: Any) -> Self:
805805
]
806806
"""
807807
return self._from_compliant_series(
808-
self._compliant_series.is_in(self._extract_native(other))
808+
self._compliant_series.is_in(to_native(other, pass_through=True))
809809
)
810810

811811
def arg_true(self: Self) -> Self:

tests/expr_and_series/is_in_test.py

+8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ def test_expr_is_in(constructor: Constructor) -> None:
1818
assert_equal_data(result, expected)
1919

2020

21+
def test_expr_is_in_empty_list(constructor: Constructor) -> None:
22+
df = nw.from_native(constructor(data))
23+
result = df.select(nw.col("a").is_in([]))
24+
expected = {"a": [False, False, False, False]}
25+
26+
assert_equal_data(result, expected)
27+
28+
2129
def test_ser_is_in(constructor_eager: ConstructorEager) -> None:
2230
ser = nw.from_native(constructor_eager(data), eager_only=True)["a"]
2331
result = {"a": ser.is_in([4, 5])}

0 commit comments

Comments
 (0)