Repository: narwhals-dev/narwhals
Pull request #1830 (2025-01-19 15:31:25)

chore: rename time zone tests
## What type of PR is this? (check all applicable)

- [ ] 💾 Refactor
- [x] ✨ Feature
- [ ] 🐛 Bug Fix
- [ ] 🔧 Optimization
- [ ] 📝 Documentation
- [ ] ✅ Test
- [ ] 🐳 Other

## Checklist

- [x] Code follows style guide (ruff)
- [x] Tests added
- [ ] Documented the changes



Patch:
diff --git a/narwhals/_arrow/namespace.py b/narwhals/_arrow/namespace.py
index 70d372a5..e1ad9550 100644
--- a/narwhals/_arrow/namespace.py
+++ b/narwhals/_arrow/namespace.py
@@ -441,7 +441,7 @@ class ArrowWhen:
         except TypeError:
             # `self._then_value` is a scalar and can't be converted to an expression
             value_series = plx._create_series_from_scalar(
-                self._then_value, reference_series=condition
+                self._then_value, reference_series=condition.alias("literal")
             )
 
         condition_native, value_series_native = broadcast_series(
diff --git a/narwhals/_dask/namespace.py b/narwhals/_dask/namespace.py
index 936b9abb..485163a0 100644
--- a/narwhals/_dask/namespace.py
+++ b/narwhals/_dask/namespace.py
@@ -411,8 +411,8 @@ class DaskWhen:
 
         if is_scalar:
             _df = condition.to_frame("a")
-            _df["tmp"] = value_sequence[0]
-            value_series = _df["tmp"]
+            _df["literal"] = value_sequence[0]
+            value_series = _df["literal"]
         else:
             value_series = value_sequence
 
diff --git a/narwhals/_duckdb/namespace.py b/narwhals/_duckdb/namespace.py
index c91d11d3..c516336c 100644
--- a/narwhals/_duckdb/namespace.py
+++ b/narwhals/_duckdb/namespace.py
@@ -248,22 +248,27 @@ class DuckDBWhen:
             value = parse_into_expr(self._then_value, namespace=plx)(df)[0]
         except TypeError:
             # `self._otherwise_value` is a scalar and can't be converted to an expression
-            value = ConstantExpression(self._then_value)
+            value = ConstantExpression(self._then_value).alias("literal")
         value = cast("duckdb.Expression", value)
+        value_name = get_column_name(df, value)
 
         if self._otherwise_value is None:
-            return [CaseExpression(condition=condition, value=value)]
+            return [CaseExpression(condition=condition, value=value).alias(value_name)]
         try:
             otherwise_expr = parse_into_expr(self._otherwise_value, namespace=plx)
         except TypeError:
             # `self._otherwise_value` is a scalar and can't be converted to an expression
             return [
-                CaseExpression(condition=condition, value=value).otherwise(
-                    ConstantExpression(self._otherwise_value)
-                )
+                CaseExpression(condition=condition, value=value)
+                .otherwise(ConstantExpression(self._otherwise_value))
+                .alias(value_name)
             ]
         otherwise = otherwise_expr(df)[0]
-        return [CaseExpression(condition=condition, value=value).otherwise(otherwise)]
+        return [
+            CaseExpression(condition=condition, value=value)
+            .otherwise(otherwise)
+            .alias(value_name)
+        ]
 
     def then(self, value: DuckDBExpr | Any) -> DuckDBThen:
         self._then_value = value
diff --git a/narwhals/_pandas_like/namespace.py b/narwhals/_pandas_like/namespace.py
index 4265a340..84efef83 100644
--- a/narwhals/_pandas_like/namespace.py
+++ b/narwhals/_pandas_like/namespace.py
@@ -467,13 +467,12 @@ class PandasWhen:
         except TypeError:
             # `self._then_value` is a scalar and can't be converted to an expression
             value_series = plx._create_series_from_scalar(
-                self._then_value, reference_series=condition
+                self._then_value, reference_series=condition.alias("literal")
             )
 
         condition_native, value_series_native = broadcast_align_and_extract_native(
             condition, value_series
         )
-
         if self._otherwise_value is None:
             return [
                 value_series._from_native_series(
diff --git a/narwhals/_pandas_like/utils.py b/narwhals/_pandas_like/utils.py
index 159a9f1c..28b7a903 100644
--- a/narwhals/_pandas_like/utils.py
+++ b/narwhals/_pandas_like/utils.py
@@ -128,7 +128,7 @@ def broadcast_align_and_extract_native(
             s = rhs._native_series
             return (
                 lhs._native_series,
-                s.__class__(s.iloc[0], index=lhs_index, dtype=s.dtype),
+                s.__class__(s.iloc[0], index=lhs_index, dtype=s.dtype, name=rhs.name),
             )
         if lhs.len() == 1:
             # broadcast
diff --git a/narwhals/_spark_like/expr_dt.py b/narwhals/_spark_like/expr_dt.py
index 4c31d6b6..a007c744 100644
--- a/narwhals/_spark_like/expr_dt.py
+++ b/narwhals/_spark_like/expr_dt.py
@@ -44,7 +44,7 @@ class SparkLikeExprDateTimeNamespace:
         from pyspark.sql import functions as F  # noqa: N812
 
         return self._compliant_expr._from_call(
-            F.dayofmonth,
+            F.day,
             "day",
             returns_scalar=self._compliant_expr._returns_scalar,
         )
diff --git a/narwhals/expr.py b/narwhals/expr.py
index 69c2e7dc..4d17552a 100644
--- a/narwhals/expr.py
+++ b/narwhals/expr.py
@@ -2206,50 +2206,13 @@ class Expr:
 
         Returns:
             A new expression.
-
-        Examples:
-            >>> import pandas as pd
-            >>> import polars as pl
-            >>> import pyarrow as pa
-            >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {"a": [1, None, None, 2]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a library agnostic function:
-
-            >>> def agnostic_arg_true(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(nw.col("a").is_null().arg_true()).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_arg_true`:
-
-            >>> agnostic_arg_true(df_pd)
-               a
-            1  1
-            2  2
-
-            >>> agnostic_arg_true(df_pl)
-            shape: (2, 1)
-            ┌─────┐
-            │ a   │
-            │ --- │
-            │ u32 │
-            ╞═════╡
-            │ 1   │
-            │ 2   │
-            └─────┘
-
-            >>> agnostic_arg_true(df_pa)
-            pyarrow.Table
-            a: int64
-            ----
-            a: [[1,2]]
         """
+        msg = (
+            "`Expr.arg_true` is deprecated and will be removed in a future version.\n\n"
+            "Note: this will remain available in `narwhals.stable.v1`.\n"
+            "See https://narwhals-dev.github.io/narwhals/backcompat/ for more information.\n"
+        )
+        issue_deprecation_warning(msg, _version="1.23.0")
         return self.__class__(
             lambda plx: self._to_compliant_expr(plx).arg_true(), is_order_dependent=True
         )
diff --git a/narwhals/stable/v1/__init__.py b/narwhals/stable/v1/__init__.py
index 941f1637..76dee2e4 100644
--- a/narwhals/stable/v1/__init__.py
+++ b/narwhals/stable/v1/__init__.py
@@ -920,6 +920,16 @@ class Expr(NwExpr):
             is_order_dependent=True,
         )
 
+    def arg_true(self) -> Self:
+        """Find elements where boolean expression is True.
+
+        Returns:
+            A new expression.
+        """
+        return self.__class__(
+            lambda plx: self._to_compliant_expr(plx).arg_true(), is_order_dependent=True
+        )
+
     def sample(
         self: Self,
         n: int | None = None,


Test patch:
diff --git a/tests/expr_and_series/arg_true_test.py b/tests/expr_and_series/arg_true_test.py
index 6db10dab..ec7d1d88 100644
--- a/tests/expr_and_series/arg_true_test.py
+++ b/tests/expr_and_series/arg_true_test.py
@@ -2,21 +2,21 @@ from __future__ import annotations
 
 import pytest
 
-import narwhals.stable.v1 as nw
+import narwhals as nw
+import narwhals.stable.v1 as nw_v1
 from tests.utils import ConstructorEager
 from tests.utils import assert_equal_data
 
 
-def test_arg_true(
-    constructor_eager: ConstructorEager, request: pytest.FixtureRequest
-) -> None:
-    if "dask" in str(constructor_eager):
-        request.applymarker(pytest.mark.xfail)
-    df = nw.from_native(constructor_eager({"a": [1, None, None, 3]}))
-    result = df.select(nw.col("a").is_null().arg_true())
+def test_arg_true(constructor_eager: ConstructorEager) -> None:
+    df = nw_v1.from_native(constructor_eager({"a": [1, None, None, 3]}))
+    result = df.select(nw_v1.col("a").is_null().arg_true())
     expected = {"a": [1, 2]}
     assert_equal_data(result, expected)
 
+    with pytest.deprecated_call():
+        df.select(nw.col("a").is_null().arg_true())
+
 
 def test_arg_true_series(constructor_eager: ConstructorEager) -> None:
     df = nw.from_native(constructor_eager({"a": [1, None, None, 3]}), eager_only=True)
diff --git a/tests/expr_and_series/convert_time_zone_test.py b/tests/expr_and_series/dt/convert_time_zone_test.py
similarity index 100%
rename from tests/expr_and_series/convert_time_zone_test.py
rename to tests/expr_and_series/dt/convert_time_zone_test.py
diff --git a/tests/expr_and_series/replace_time_zone_test.py b/tests/expr_and_series/dt/replace_time_zone_test.py
similarity index 100%
rename from tests/expr_and_series/replace_time_zone_test.py
rename to tests/expr_and_series/dt/replace_time_zone_test.py
diff --git a/tests/expr_and_series/when_test.py b/tests/expr_and_series/when_test.py
index 4f768db0..140626e4 100644
--- a/tests/expr_and_series/when_test.py
+++ b/tests/expr_and_series/when_test.py
@@ -24,6 +24,11 @@ def test_when(constructor: Constructor) -> None:
         "a_when": [3, None, None],
     }
     assert_equal_data(result, expected)
+    result = df.select(nw.when(nw.col("a") == 1).then(value=3))
+    expected = {
+        "literal": [3, None, None],
+    }
+    assert_equal_data(result, expected)
 
 
 def test_when_otherwise(constructor: Constructor) -> None:
@@ -121,22 +126,14 @@ def test_otherwise_expression(constructor: Constructor) -> None:
     assert_equal_data(result, expected)
 
 
-def test_when_then_otherwise_into_expr(
-    constructor: Constructor, request: pytest.FixtureRequest
-) -> None:
-    if "duckdb" in str(constructor):
-        request.applymarker(pytest.mark.xfail)
+def test_when_then_otherwise_into_expr(constructor: Constructor) -> None:
     df = nw.from_native(constructor(data))
     result = df.select(nw.when(nw.col("a") > 1).then("c").otherwise("e"))
     expected = {"c": [7, 5, 6]}
     assert_equal_data(result, expected)
 
 
-def test_when_then_otherwise_lit_str(
-    constructor: Constructor, request: pytest.FixtureRequest
-) -> None:
-    if "duckdb" in str(constructor):
-        request.applymarker(pytest.mark.xfail)
+def test_when_then_otherwise_lit_str(constructor: Constructor) -> None:
     df = nw.from_native(constructor(data))
     result = df.select(nw.when(nw.col("a") > 1).then(nw.col("b")).otherwise(nw.lit("z")))
     expected = {"b": ["z", "b", "c"]}