diff --git a/narwhals/_pandas_like/series.py b/narwhals/_pandas_like/series.py index 33dad2ac6..39ffd4c2d 100644 --- a/narwhals/_pandas_like/series.py +++ b/narwhals/_pandas_like/series.py @@ -15,6 +15,7 @@ if TYPE_CHECKING: from typing_extensions import Self + from narwhals._pandas_like.namespace import PandasNamespace from narwhals.dtypes import DType @@ -45,6 +46,11 @@ def __init__( else: # pragma: no cover pass + def __narwhals_namespace__(self) -> PandasNamespace: + from narwhals._pandas_like.namespace import PandasNamespace + + return PandasNamespace(self._implementation) + def __narwhals_series__(self) -> Self: return self diff --git a/narwhals/series.py b/narwhals/series.py index 31a622bc7..bb5898817 100644 --- a/narwhals/series.py +++ b/narwhals/series.py @@ -37,16 +37,10 @@ def __init__( raise TypeError(msg) # pragma: no cover def _extract_native(self, arg: Any) -> Any: - from narwhals.expression import Expr + from narwhals.series import Series - if not self._is_polars: - return arg if isinstance(arg, Series): return arg._series - if isinstance(arg, Expr): - import polars as pl - - return arg._call(pl) return arg def _from_series(self, series: Any) -> Self: @@ -118,6 +112,9 @@ def n_unique(self) -> int: def unique(self) -> Self: return self._from_series(self._series.unique()) + def sort(self) -> Self: + return self._from_series(self._series.sort()) + def zip_with(self, mask: Self, other: Self) -> Self: return self._from_series( self._series.zip_with(self._extract_native(mask), self._extract_native(other)) @@ -147,7 +144,7 @@ def std(self) -> Any: return self._series.std() def __gt__(self, other: Any) -> Series: - return self._series.__gt__(self._extract_native(other)) # type: ignore[no-any-return] + return self._from_series(self._series.__gt__(self._extract_native(other))) def __lt__(self, other: Any) -> Series: - return self._series.__lt__(self._extract_native(other)) # type: ignore[no-any-return] + return self._from_series(self._series.__lt__(self._extract_native(other))) diff --git a/tests/test_common.py b/tests/test_common.py index 53922191e..a570e5303 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -496,3 +496,16 @@ def test_any_all(df_raw: Any) -> None: result = nw.to_native(df.select((nw.all() > 1).any())) expected = {"a": [True], "b": [True], "z": [True]} compare_dicts(result, expected) + + +def test_invalid() -> None: + df = nw.LazyFrame(df_pandas) + with pytest.raises(ValueError, match="Multi-output"): + df.select(nw.all() + nw.all()) + + +@pytest.mark.parametrize("df_raw", [df_pandas]) +def test_reindex(df_raw: Any) -> None: + df = nw.DataFrame(df_raw) + with pytest.raises(RuntimeError, match="implicit index alignment"): + df.select("a", df["b"].sort()) diff --git a/tests/test_series.py b/tests/test_series.py index 9f4d1c3f9..7ced67eed 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -29,6 +29,19 @@ def test_is_in(df_raw: Any) -> None: assert result[2] +@pytest.mark.parametrize("df_raw", [df_pandas, df_polars]) +def test_gt(df_raw: Any) -> None: + s = nw.Series(df_raw["a"]) + result = nw.to_native(s > s) # noqa: PLR0124 + assert not result[0] + assert not result[1] + assert not result[2] + result = nw.to_native(s > 1) + assert not result[0] + assert result[1] + assert result[2] + + @pytest.mark.parametrize("df_raw", [df_pandas, df_lazy]) def test_dtype(df_raw: Any) -> None: result = nw.LazyFrame(df_raw).collect()["a"].dtype