Repository: narwhals-dev/narwhals
Pull request #1331 (2024-11-06 20:25:09)

docs: add "returns" documentation to functions.py
## What type of PR is this? (check all applicable)

- [ ] 💾 Refactor
- [ ] ✨ Feature
- [ ] 🐛 Bug Fix
- [ ] 🔧 Optimization
- [x] 📝 Documentation
- [ ] ✅ Test
- [ ] 🐳 Other

## Related issues 

- Related issue #1293
- Closes #

## Checklist

- [x] Code follows style guide (ruff)
- [ ] Tests added 
- [ ] Documented the changes

## If you have comments or can explain your changes, please do so below.
I wasn't sure if more documentation should be added to the function `get_level` (see [here](https://github.com/narwhals-dev/narwhals/blob/main/narwhals/functions.py#L596)). It's public but it's not really part of the "core functionality".



Patch:
diff --git a/README.md b/README.md
index 0f1f904f..9308af7c 100644
--- a/README.md
+++ b/README.md
@@ -121,6 +121,9 @@ to this list!
 
 Narwhals has been featured in several talks, podcasts, and blog posts:
 
+- [The Real Python Podcast](https://www.youtube.com/watch?v=w5DFZbFYzCM)
+  Narwhals: Expanding DataFrame Compatibility Between Libraries
+
 - [Talk Python to me Podcast](https://youtu.be/FSH7BZ0tuE0)
   Ahoy, Narwhals are bridging the data science APIs
 
diff --git a/narwhals/_arrow/dataframe.py b/narwhals/_arrow/dataframe.py
index ac845853..a357bdeb 100644
--- a/narwhals/_arrow/dataframe.py
+++ b/narwhals/_arrow/dataframe.py
@@ -621,7 +621,7 @@ class ArrowDataFrame:
     ) -> Self:
         """
         NOTE:
-            The param `maintain_order` is only here for compatibility with the polars API
+            The param `maintain_order` is only here for compatibility with the Polars API
             and has no effect on the output.
         """
         import numpy as np  # ignore-banned-import
diff --git a/narwhals/_arrow/expr.py b/narwhals/_arrow/expr.py
index 35e936d7..7b2af578 100644
--- a/narwhals/_arrow/expr.py
+++ b/narwhals/_arrow/expr.py
@@ -317,8 +317,8 @@ class ArrowExpr:
     def is_last_distinct(self: Self) -> Self:
         return reuse_series_implementation(self, "is_last_distinct")
 
-    def unique(self: Self) -> Self:
-        return reuse_series_implementation(self, "unique")
+    def unique(self: Self, *, maintain_order: bool = False) -> Self:
+        return reuse_series_implementation(self, "unique", maintain_order=maintain_order)
 
     def sort(self: Self, *, descending: bool = False, nulls_last: bool = False) -> Self:
         return reuse_series_implementation(
diff --git a/narwhals/_arrow/series.py b/narwhals/_arrow/series.py
index 70009df4..d63a92aa 100644
--- a/narwhals/_arrow/series.py
+++ b/narwhals/_arrow/series.py
@@ -645,7 +645,12 @@ class ArrowSeries:
         else:
             return pc.all(pc.less_equal(ser[:-1], ser[1:]))  # type: ignore[no-any-return]
 
-    def unique(self: Self) -> ArrowSeries:
+    def unique(self: Self, *, maintain_order: bool = False) -> ArrowSeries:
+        """
+        NOTE:
+            The param `maintain_order` is only here for compatibility with the Polars API
+            and has no effect on the output.
+        """
         import pyarrow.compute as pc  # ignore-banned-import()
 
         return self._from_native_series(pc.unique(self._native_series))
diff --git a/narwhals/_dask/dataframe.py b/narwhals/_dask/dataframe.py
index 150b0177..cf5c8eae 100644
--- a/narwhals/_dask/dataframe.py
+++ b/narwhals/_dask/dataframe.py
@@ -187,7 +187,7 @@ class DaskLazyFrame:
     ) -> Self:
         """
         NOTE:
-            The param `maintain_order` is only here for compatibility with the polars API
+            The param `maintain_order` is only here for compatibility with the Polars API
             and has no effect on the output.
         """
         subset = flatten(subset) if subset else None
diff --git a/narwhals/_pandas_like/dataframe.py b/narwhals/_pandas_like/dataframe.py
index 5eab8b08..df298ffc 100644
--- a/narwhals/_pandas_like/dataframe.py
+++ b/narwhals/_pandas_like/dataframe.py
@@ -296,7 +296,7 @@ class PandasLikeDataFrame:
     ) -> Iterator[list[tuple[Any, ...]]] | Iterator[list[dict[str, Any]]]:
         """
         NOTE:
-            The param ``buffer_size`` is only here for compatibility with the polars API
+            The param ``buffer_size`` is only here for compatibility with the Polars API
             and has no effect on the output.
         """
         if not named:
@@ -656,7 +656,7 @@ class PandasLikeDataFrame:
     ) -> Self:
         """
         NOTE:
-            The param `maintain_order` is only here for compatibility with the polars API
+            The param `maintain_order` is only here for compatibility with the Polars API
             and has no effect on the output.
         """
         mapped_keep = {"none": False, "any": "first"}.get(keep, keep)
diff --git a/narwhals/_pandas_like/expr.py b/narwhals/_pandas_like/expr.py
index a58597ee..fb9e577b 100644
--- a/narwhals/_pandas_like/expr.py
+++ b/narwhals/_pandas_like/expr.py
@@ -282,8 +282,8 @@ class PandasLikeExpr:
     def cum_sum(self) -> Self:
         return reuse_series_implementation(self, "cum_sum")
 
-    def unique(self) -> Self:
-        return reuse_series_implementation(self, "unique")
+    def unique(self, *, maintain_order: bool = False) -> Self:
+        return reuse_series_implementation(self, "unique", maintain_order=maintain_order)
 
     def diff(self) -> Self:
         return reuse_series_implementation(self, "diff")
diff --git a/narwhals/_pandas_like/series.py b/narwhals/_pandas_like/series.py
index 078e857b..7bc916b5 100644
--- a/narwhals/_pandas_like/series.py
+++ b/narwhals/_pandas_like/series.py
@@ -471,7 +471,12 @@ class PandasLikeSeries:
     def cum_sum(self) -> PandasLikeSeries:
         return self._from_native_series(self._native_series.cumsum())
 
-    def unique(self) -> PandasLikeSeries:
+    def unique(self, *, maintain_order: bool = False) -> PandasLikeSeries:
+        """
+        NOTE:
+            The param `maintain_order` is only here for compatibility with the Polars API
+            and has no effect on the output.
+        """
         return self._from_native_series(
             self._native_series.__class__(
                 self._native_series.unique(), name=self._native_series.name
diff --git a/narwhals/dataframe.py b/narwhals/dataframe.py
index bf8bb5c9..bb163b28 100644
--- a/narwhals/dataframe.py
+++ b/narwhals/dataframe.py
@@ -1722,9 +1722,9 @@ class DataFrame(BaseFrame[DataFrameT]):
                 * 'none': Don't keep duplicate rows.
                 * 'first': Keep first unique row.
                 * 'last': Keep last unique row.
-            maintain_order: Keep the same order as the original DataFrame. This is more
+            maintain_order: Keep the same order as the original DataFrame. This may be more
                 expensive to compute. Settings this to `True` blocks the possibility
-                to run on the streaming engine for polars.
+                to run on the streaming engine for Polars.
 
         Examples:
             >>> import pandas as pd
@@ -3568,9 +3568,9 @@ class LazyFrame(BaseFrame[FrameT]):
                 * 'none': Don't keep duplicate rows.
                 * 'first': Keep first unique row.
                 * 'last': Keep last unique row.
-            maintain_order: Keep the same order as the original DataFrame. This is more
+            maintain_order: Keep the same order as the original DataFrame. This may be more
                 expensive to compute. Settings this to `True` blocks the possibility
-                to run on the streaming engine for polars.
+                to run on the streaming engine for Polars.
 
         Returns:
             LazyFrame: LazyFrame with unique rows.
diff --git a/narwhals/expr.py b/narwhals/expr.py
index 2f986760..f1d9a193 100644
--- a/narwhals/expr.py
+++ b/narwhals/expr.py
@@ -707,9 +707,14 @@ class Expr:
         """
         return self.__class__(lambda plx: self._call(plx).n_unique())
 
-    def unique(self) -> Self:
+    def unique(self, *, maintain_order: bool = False) -> Self:
         """
-        Return unique values
+        Return unique values of this expression.
+
+        Arguments:
+            maintain_order: Keep the same order as the original expression. This may be more
+                expensive to compute. Settings this to `True` blocks the possibility
+                to run on the streaming engine for Polars.
 
         Examples:
             >>> import polars as pl
@@ -724,7 +729,7 @@ class Expr:
 
             >>> @nw.narwhalify
             ... def func(df):
-            ...     return df.select(nw.col("a", "b").unique())
+            ...     return df.select(nw.col("a", "b").unique(maintain_order=True))
 
             We can then pass any supported library such as Pandas, Polars, or PyArrow to `func`:
 
@@ -752,7 +757,9 @@ class Expr:
             a: [[1,3,5]]
             b: [[2,4,6]]
         """
-        return self.__class__(lambda plx: self._call(plx).unique())
+        return self.__class__(
+            lambda plx: self._call(plx).unique(maintain_order=maintain_order)
+        )
 
     def abs(self) -> Self:
         """
diff --git a/narwhals/functions.py b/narwhals/functions.py
index 20efa7b4..3fd2025a 100644
--- a/narwhals/functions.py
+++ b/narwhals/functions.py
@@ -173,6 +173,9 @@ def new_series(
             may auto-infer it from `values`.
         native_namespace: The native library to use for DataFrame creation.
 
+    Returns:
+        A new Series
+
     Examples:
         >>> import pandas as pd
         >>> import polars as pl
@@ -291,6 +294,9 @@ def from_dict(
         native_namespace: The native library to use for DataFrame creation. Only
             necessary if inputs are not Narwhals Series.
 
+    Returns:
+        A new DataFrame
+
     Examples:
         >>> import pandas as pd
         >>> import polars as pl
@@ -431,6 +437,9 @@ def from_arrow(
         native_frame: Object which implements `__arrow_c_stream__`.
         native_namespace: The native library to use for DataFrame creation.
 
+    Returns:
+        A new DataFrame
+
     Examples:
         >>> import pandas as pd
         >>> import polars as pl
diff --git a/narwhals/series.py b/narwhals/series.py
index dac5c6d7..424c82b4 100644
--- a/narwhals/series.py
+++ b/narwhals/series.py
@@ -1005,9 +1005,14 @@ class Series:
         """
         return self._from_compliant_series(self._compliant_series.cum_sum())
 
-    def unique(self) -> Self:
+    def unique(self, *, maintain_order: bool = False) -> Self:
         """
-        Returns unique values
+        Returns unique values of the series.
+
+        Arguments:
+            maintain_order: Keep the same order as the original series. This may be more
+                expensive to compute. Settings this to `True` blocks the possibility
+                to run on the streaming engine for Polars.
 
         Examples:
             >>> import pandas as pd
@@ -1021,7 +1026,7 @@ class Series:
 
             >>> @nw.narwhalify
             ... def func(s):
-            ...     return s.unique()
+            ...     return s.unique(maintain_order=True)
 
             We can then pass either pandas or Polars to `func`:
 
@@ -1039,7 +1044,9 @@ class Series:
                6
             ]
         """
-        return self._from_compliant_series(self._compliant_series.unique())
+        return self._from_compliant_series(
+            self._compliant_series.unique(maintain_order=maintain_order)
+        )
 
     def diff(self) -> Self:
         """
diff --git a/narwhals/stable/v1/__init__.py b/narwhals/stable/v1/__init__.py
index e11cc687..8e217f08 100644
--- a/narwhals/stable/v1/__init__.py
+++ b/narwhals/stable/v1/__init__.py
@@ -2323,6 +2323,9 @@ def new_series(
             may auto-infer it from `values`.
         native_namespace: The native library to use for DataFrame creation.
 
+    Returns:
+        A new Series
+
     Examples:
         >>> import pandas as pd
         >>> import polars as pl
@@ -2376,6 +2379,9 @@ def from_arrow(
         native_frame: Object which implements `__arrow_c_stream__`.
         native_namespace: The native library to use for DataFrame creation.
 
+    Returns:
+        A new DataFrame
+
     Examples:
         >>> import pandas as pd
         >>> import polars as pl
@@ -2431,6 +2437,9 @@ def from_dict(
         native_namespace: The native library to use for DataFrame creation. Only
             necessary if inputs are not Narwhals Series.
 
+    Returns:
+        A new DataFrame
+
     Examples:
         >>> import pandas as pd
         >>> import polars as pl


Test patch:
diff --git a/tests/expr_and_series/unique_test.py b/tests/expr_and_series/unique_test.py
index acef3f60..62d2e63a 100644
--- a/tests/expr_and_series/unique_test.py
+++ b/tests/expr_and_series/unique_test.py
@@ -8,6 +8,7 @@ from tests.utils import ConstructorEager
 from tests.utils import assert_equal_data
 
 data = {"a": [1, 1, 2]}
+data_str = {"a": ["x", "x", "y"]}
 
 
 def test_unique_expr(constructor: Constructor, request: pytest.FixtureRequest) -> None:
@@ -20,7 +21,7 @@ def test_unique_expr(constructor: Constructor, request: pytest.FixtureRequest) -
 
 
 def test_unique_series(constructor_eager: ConstructorEager) -> None:
-    series = nw.from_native(constructor_eager(data), eager_only=True)["a"]
-    result = series.unique()
-    expected = {"a": [1, 2]}
+    series = nw.from_native(constructor_eager(data_str), eager_only=True)["a"]
+    result = series.unique(maintain_order=True)
+    expected = {"a": ["x", "y"]}
     assert_equal_data({"a": result}, expected)