Skip to content

Commit

Permalink
len_chars too
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcoGorelli committed Jan 9, 2025
1 parent 20eb53b commit df1386e
Show file tree
Hide file tree
Showing 8 changed files with 24 additions and 13 deletions.
2 changes: 1 addition & 1 deletion narwhals/_arrow/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ def join(
self: Self,
other: Self,
*,
how: Literal["left", "inner", "outer", "cross", "anti", "semi"],
how: Literal["left", "inner", "cross", "anti", "semi"],
left_on: str | list[str] | None,
right_on: str | list[str] | None,
suffix: str,
Expand Down
2 changes: 1 addition & 1 deletion narwhals/_dask/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def join(
self: Self,
other: Self,
*,
how: Literal["left", "inner", "outer", "cross", "anti", "semi"] = "inner",
how: Literal["left", "inner", "cross", "anti", "semi"] = "inner",
left_on: str | list[str] | None,
right_on: str | list[str] | None,
suffix: str,
Expand Down
6 changes: 1 addition & 5 deletions narwhals/_duckdb/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def join(
self: Self,
other: Self,
*,
how: Literal["left", "inner", "outer", "cross", "anti", "semi"] = "inner",
how: Literal["left", "inner", "cross", "anti", "semi"] = "inner",
left_on: str | list[str] | None,
right_on: str | list[str] | None,
suffix: str,
Expand All @@ -226,10 +226,6 @@ def join(
right_on = [right_on]
original_alias = self._native_frame.alias

if how not in ("inner", "left", "semi", "cross"):
msg = "Only inner and left join is implemented for DuckDB"
raise NotImplementedError(msg)

if how == "cross":
if self._backend_version < (1, 1, 4):
msg = f"DuckDB>=1.1.4 is required for cross-join, found version: {self._backend_version}"
Expand Down
18 changes: 18 additions & 0 deletions narwhals/_duckdb/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,15 @@ def min(self) -> Self:
lambda _input: FunctionExpression("min", _input), "min", returns_scalar=True
)

def null_count(self) -> Self:
from duckdb import FunctionExpression

return self._from_call(
lambda _input: FunctionExpression("sum", _input.isnull().cast("int")),
"null_count",
returns_scalar=True,
)

def is_null(self) -> Self:
return self._from_call(
lambda _input: _input.isnull(), "is_null", returns_scalar=self._returns_scalar
Expand Down Expand Up @@ -619,6 +628,15 @@ def func(_input: duckdb.Expression) -> duckdb.Expression:
func, "slice", returns_scalar=self._compliant_expr._returns_scalar
)

def len_chars(self) -> DuckDBExpr:
from duckdb import FunctionExpression

return self._compliant_expr._from_call(
lambda _input: FunctionExpression("length", _input),
"len_chars",
returns_scalar=self._compliant_expr._returns_scalar,
)

def to_lowercase(self) -> DuckDBExpr:
from duckdb import FunctionExpression

Expand Down
2 changes: 1 addition & 1 deletion narwhals/_pandas_like/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ def join(
self,
other: Self,
*,
how: Literal["left", "inner", "outer", "cross", "anti", "semi"] = "inner",
how: Literal["left", "inner", "cross", "anti", "semi"] = "inner",
left_on: str | list[str] | None,
right_on: str | list[str] | None,
suffix: str,
Expand Down
2 changes: 1 addition & 1 deletion tests/expr_and_series/null_count_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
def test_null_count_expr(
constructor: Constructor, request: pytest.FixtureRequest
) -> None:
if ("pyspark" in str(constructor)) or "duckdb" in str(constructor):
if "pyspark" in str(constructor):
request.applymarker(pytest.mark.xfail)
df = nw.from_native(constructor(data))
result = df.select(nw.all().null_count())
Expand Down
2 changes: 1 addition & 1 deletion tests/expr_and_series/str/len_chars_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


def test_str_len_chars(constructor: Constructor, request: pytest.FixtureRequest) -> None:
if ("pyspark" in str(constructor)) or "duckdb" in str(constructor):
if "pyspark" in str(constructor):
request.applymarker(pytest.mark.xfail)
df = nw.from_native(constructor(data))
result = df.select(nw.col("a").str.len_chars())
Expand Down
3 changes: 0 additions & 3 deletions tests/frame/join_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,7 @@ def test_anti_join(
join_key: list[str],
filter_expr: nw.Expr,
expected: dict[str, list[Any]],
request: pytest.FixtureRequest,
) -> None:
if "duckdb" in str(constructor):
request.applymarker(pytest.mark.xfail)
data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8, 9]}
df = nw.from_native(constructor(data))
other = df.filter(filter_expr)
Expand Down

0 comments on commit df1386e

Please sign in to comment.