Skip to content

Commit

Permalink
feat: add DuckDB list.len method (#1850)
Browse files Browse the repository at this point in the history
* feat: add DuckDB `list.len` method

* change back constructors append
  • Loading branch information
raisadz authored Jan 22, 2025
1 parent d9ebf9f commit 07e8024
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 7 deletions.
5 changes: 5 additions & 0 deletions narwhals/_duckdb/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from duckdb import FunctionExpression

from narwhals._duckdb.expr_dt import DuckDBExprDateTimeNamespace
from narwhals._duckdb.expr_list import DuckDBExprListNamespace
from narwhals._duckdb.expr_name import DuckDBExprNameNamespace
from narwhals._duckdb.expr_str import DuckDBExprStringNamespace
from narwhals._duckdb.utils import binary_operation_returns_scalar
Expand Down Expand Up @@ -571,3 +572,7 @@ def dt(self: Self) -> DuckDBExprDateTimeNamespace:
@property
def name(self: Self) -> DuckDBExprNameNamespace:
return DuckDBExprNameNamespace(self)

@property
def list(self: Self) -> DuckDBExprListNamespace:
return DuckDBExprListNamespace(self)
20 changes: 20 additions & 0 deletions narwhals/_duckdb/expr_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from duckdb import FunctionExpression

if TYPE_CHECKING:
from narwhals._duckdb.expr import DuckDBExpr


class DuckDBExprListNamespace:
def __init__(self, expr: DuckDBExpr) -> None:
self._compliant_expr = expr

def len(self) -> DuckDBExpr:
return self._compliant_expr._from_call(
lambda _input: FunctionExpression("len", _input),
"len",
returns_scalar=self._compliant_expr._returns_scalar,
)
4 changes: 2 additions & 2 deletions narwhals/_duckdb/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,8 @@ def narwhals_to_native_dtype(dtype: DType | type[DType], version: Version) -> st
if isinstance_or_issubclass(dtype, dtypes.Date): # pragma: no cover
return "DATE"
if isinstance_or_issubclass(dtype, dtypes.List):
msg = "todo"
raise NotImplementedError(msg)
inner = narwhals_to_native_dtype(dtype.inner, version) # type: ignore[union-attr]
return f"{inner}[]"
if isinstance_or_issubclass(dtype, dtypes.Struct): # pragma: no cover
msg = "todo"
raise NotImplementedError(msg)
Expand Down
6 changes: 1 addition & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,13 +242,9 @@ def pytest_generate_tests(metafunc: pytest.Metafunc) -> None:
)
elif "constructor" in metafunc.fixturenames:
if (
any(
x in str(metafunc.module)
for x in ("list", "unpivot", "from_dict", "from_numpy")
)
any(x in str(metafunc.module) for x in ("unpivot", "from_dict", "from_numpy"))
and LAZY_CONSTRUCTORS["duckdb"] in constructors
):
# TODO(unassigned): list and name namespaces still need implementing for duckdb
constructors.remove(LAZY_CONSTRUCTORS["duckdb"])
constructors_ids.remove("duckdb")
metafunc.parametrize("constructor", constructors, ids=constructors_ids)

0 comments on commit 07e8024

Please sign in to comment.