From d9a04c0eed0f742f46229058822ec2662e80cd24 Mon Sep 17 00:00:00 2001 From: Marco Edward Gorelli Date: Mon, 20 Jan 2025 07:02:19 +0000 Subject: [PATCH] feat: Deprecate Expr.arg_true (but keep Series.arg_true, and keep both available in stable.v1) (#1827) --- narwhals/expr.py | 49 ++++---------------------- narwhals/stable/v1/__init__.py | 10 ++++++ tests/expr_and_series/arg_true_test.py | 16 ++++----- 3 files changed, 24 insertions(+), 51 deletions(-) diff --git a/narwhals/expr.py b/narwhals/expr.py index 69c2e7dcc..4d17552af 100644 --- a/narwhals/expr.py +++ b/narwhals/expr.py @@ -2206,50 +2206,13 @@ def arg_true(self) -> Self: 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 941f16377..76dee2e49 100644 --- a/narwhals/stable/v1/__init__.py +++ b/narwhals/stable/v1/__init__.py @@ -920,6 +920,16 @@ def sort(self, *, descending: bool = False, nulls_last: bool = False) -> Self: 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, diff --git a/tests/expr_and_series/arg_true_test.py b/tests/expr_and_series/arg_true_test.py index 6db10dab6..ec7d1d883 100644 --- a/tests/expr_and_series/arg_true_test.py +++ b/tests/expr_and_series/arg_true_test.py @@ -2,21 +2,21 @@ 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)