Repository: narwhals-dev/narwhals
Pull request #536 (2024-07-16 07:14:28)

feat: `ArrowExprCatNamespace`
## 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 
- [x] Documented the changes

## If you have comments or can explain your changes, please do so below.

It was not discussed, I hope I am not missing something 


Patch:
diff --git a/narwhals/_arrow/expr.py b/narwhals/_arrow/expr.py
index bf3cc7de..bf4578a9 100644
--- a/narwhals/_arrow/expr.py
+++ b/narwhals/_arrow/expr.py
@@ -203,6 +203,22 @@ class ArrowExpr:
     def str(self) -> ArrowExprStringNamespace:
         return ArrowExprStringNamespace(self)
 
+    @property
+    def cat(self) -> ArrowExprCatNamespace:
+        return ArrowExprCatNamespace(self)
+
+
+class ArrowExprCatNamespace:
+    def __init__(self, expr: ArrowExpr) -> None:
+        self._expr = expr
+
+    def get_categories(self) -> ArrowExpr:
+        return reuse_series_namespace_implementation(
+            self._expr,
+            "cat",
+            "get_categories",
+        )
+
 
 class ArrowExprDateTimeNamespace:
     def __init__(self, expr: ArrowExpr) -> None:


Test patch:
diff --git a/.github/workflows/downstream_tests.yml b/.github/workflows/downstream_tests.yml
index 9a587f02..3ae02c65 100644
--- a/.github/workflows/downstream_tests.yml
+++ b/.github/workflows/downstream_tests.yml
@@ -76,7 +76,7 @@ jobs:
       - name: install-scikit-lego-dev
         run: |
             cd scikit-lego
-            pip install -e ".[dev, test]"
+            pip install -e ".[test]"
       - name: install-narwhals-dev
         run: |
             pip uninstall narwhals -y
diff --git a/tests/expr/cat/get_categories_test.py b/tests/expr/cat/get_categories_test.py
index a4d51c73..ed163a3d 100644
--- a/tests/expr/cat/get_categories_test.py
+++ b/tests/expr/cat/get_categories_test.py
@@ -6,24 +6,27 @@ import pyarrow as pa
 import pytest
 
 import narwhals.stable.v1 as nw
+from narwhals.utils import parse_version
 from tests.utils import compare_dicts
 
 data = {"a": ["one", "two", "two"]}
 
 
 def test_get_categories(request: Any, constructor: Any) -> None:
-    if "pyarrow_table" in str(constructor):
+    if "pyarrow_table" in str(constructor) and parse_version(
+        pa.__version__
+    ) < parse_version("15.0.0"):
         request.applymarker(pytest.mark.xfail)
 
     df = nw.from_native(constructor(data), eager_only=True)
     df = df.select(nw.col("a").cast(nw.Categorical))
-
-    result = df.select(nw.col("a").cat.get_categories())
     expected = {"a": ["one", "two"]}
-    compare_dicts(result, expected)
 
-    result = df.select(df["a"].cat.get_categories())
-    compare_dicts(result, expected)
+    result_expr = df.select(nw.col("a").cat.get_categories())
+    compare_dicts(result_expr, expected)
+
+    result_series = df["a"].cat.get_categories().to_list()
+    assert set(result_series) == set(expected["a"])
 
 
 def test_get_categories_pyarrow() -> None:
@@ -33,6 +36,10 @@ def test_get_categories_pyarrow() -> None:
         {"a": pa.array(["a", "b", None, "d"], pa.dictionary(pa.int64(), pa.utf8()))}
     )
     df = nw.from_native(table, eager_only=True)
-    result = df["a"].cat.get_categories().to_list()
-    expected = ["a", "b", "d"]
-    assert result == expected
+    expected = {"a": ["a", "b", "d"]}
+
+    result_expr = df.select(nw.col("a").cat.get_categories())
+    compare_dicts(result_expr, expected)
+
+    result_series = df["a"].cat.get_categories().to_list()
+    assert result_series == expected["a"]