nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: narwhals-dev/narwhals
Pull request #176 (2024-05-16 14:45:16)

Concat should preserve laziness
closes https://github.com/narwhals-dev/narwhals/issues/39


Patch:
diff --git a/narwhals/functions.py b/narwhals/functions.py
index 44263413..3a4dd607 100644
--- a/narwhals/functions.py
+++ b/narwhals/functions.py
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING
 from typing import Iterable
 from typing import Literal
 
+from narwhals.utils import validate_laziness
 from narwhals.utils import validate_same_library
 
 if TYPE_CHECKING:
@@ -24,6 +25,7 @@ def concat(
         raise ValueError("No items to concatenate")
     items = list(items)
     validate_same_library(items)
+    validate_laziness(items)
     first_item = items[0]
     plx = first_item.__narwhals_namespace__()
     return first_item.__class__(
diff --git a/narwhals/utils.py b/narwhals/utils.py
index 06f93b1b..a17b6cf4 100644
--- a/narwhals/utils.py
+++ b/narwhals/utils.py
@@ -85,6 +85,19 @@ def validate_same_library(items: Iterable[Any]) -> None:
     raise NotImplementedError("Cross-library comparisons aren't supported")
 
 
+def validate_laziness(items: Iterable[Any]) -> None:
+    from narwhals.dataframe import DataFrame
+    from narwhals.dataframe import LazyFrame
+
+    if all(isinstance(item, DataFrame) for item in items) or (
+        all(isinstance(item, LazyFrame) for item in items)
+    ):
+        return
+    raise NotImplementedError(
+        "The items to concatenate should either all be eager, or all lazy"
+    )
+
+
 def maybe_align_index(lhs: T, rhs: Series | BaseFrame) -> T:
     """
     Align `lhs` to the Index of `rhs, if they're both pandas-like.


Test patch:
diff --git a/tests/test_invalid.py b/tests/test_invalid.py
index f8f8ebce..301bf7ed 100644
--- a/tests/test_invalid.py
+++ b/tests/test_invalid.py
@@ -14,3 +14,12 @@ def test_native_vs_non_native() -> None:
     df = pl.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
     with pytest.raises(TypeError, match="Perhaps you forgot"):
         nw.from_native(df).filter(s > 1)
+
+
+def test_validate_laziness() -> None:
+    df = pl.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
+    with pytest.raises(
+        NotImplementedError,
+        match=("The items to concatenate should either all be eager, or all lazy"),
+    ):
+        nw.concat([nw.DataFrame(df), nw.LazyFrame(df)])
Repository: narwhals-dev/narwhals
Pull request #330 (2024-06-22 09:46:23)

fix: group-by(...).agg(nw.col(...).len()) was raising unnecessarily
<!--
# Thanks for contributing a pull request! 
## Please make sure you see our contribution guidelines: https://github.com/narwhals-dev/narwhals/blob/main/CONTRIBUTING.md
-->

## What type of PR is this? (check all applicable)

- [ ] 💾 Refactor
- [ ] ✨ Feature
- [x] 🐛 Bug Fix
- [ ] 🔧 Optimization
- [ ] 📝 Documentation
- [ ] ✅ Test
- [ ] 🐳 Other

## Related issues 

- Related issue # 
- Closes  #326 

## Checklist

- [ ] Code follows style guide (ruff)
- [ ] Tests added 
- [ ] Documented the changes

## If you have comments or can explain your changes, please do so below.




Patch:
diff --git a/narwhals/_pandas_like/group_by.py b/narwhals/_pandas_like/group_by.py
index a5c57a85..203b6f84 100644
--- a/narwhals/_pandas_like/group_by.py
+++ b/narwhals/_pandas_like/group_by.py
@@ -118,9 +118,12 @@ def agg_pandas(  # noqa: PLR0913
             assert expr._depth == 1
             assert expr._root_names is not None
             assert expr._output_names is not None
+            function_name = remove_prefix(expr._function_name, "col->")
+            function_name = POLARS_TO_PANDAS_AGGREGATIONS.get(
+                function_name, function_name
+            )
             for root_name, output_name in zip(expr._root_names, expr._output_names):
-                name = remove_prefix(expr._function_name, "col->")
-                simple_aggregations[output_name] = (root_name, name)
+                simple_aggregations[output_name] = (root_name, function_name)
 
         aggs = collections.defaultdict(list)
         name_mapping = {}


Test patch:
diff --git a/tests/group_by_test.py b/tests/group_by_test.py
index ec0b85ef..52cf96df 100644
--- a/tests/group_by_test.py
+++ b/tests/group_by_test.py
@@ -35,3 +35,12 @@ def test_group_by_iter(constructor: Any) -> None:
     for key, _df in df.group_by(["a", "b"]):
         keys.append(key)
     assert sorted(keys) == sorted(expected_keys)
+
+
+@pytest.mark.parametrize("constructor", [pd.DataFrame, pl.DataFrame])
+def test_group_by_len(constructor: Any) -> None:
+    result = (
+        nw.from_native(constructor(data)).group_by("a").agg(nw.col("b").len()).sort("a")
+    )
+    expected = {"a": [1, 3], "b": [2, 1]}
+    compare_dicts(result, expected)
Repository: narwhals-dev/narwhals
Pull request #361 (2024-06-30 15:15:50)

feat: add is_pandas_dataframe
<!--
# Thanks for contributing a pull request! 
## Please make sure you see our contribution guidelines: https://github.com/narwhals-dev/narwhals/blob/main/CONTRIBUTING.md
-->

## What type of PR is this? (check all applicable)

- [ ] 💾 Refactor
- [ ] ✨ Feature
- [ ] 🐛 Bug Fix
- [ ] 🔧 Optimization
- [ ] 📝 Documentation
- [ ] ✅ Test
- [ ] 🐳 Other

## Related issues 

- Related issue # 
- Closes #

## Checklist

- [ ] Code follows style guide (ruff)
- [ ] Tests added 
- [ ] Documented the changes

## If you have comments or can explain your changes, please do so below.




Patch:
diff --git a/docs/api-reference/dependencies.md b/docs/api-reference/dependencies.md
index 79002ba6..72541875 100644
--- a/docs/api-reference/dependencies.md
+++ b/docs/api-reference/dependencies.md
@@ -9,5 +9,6 @@
         - get_modin
         - get_cudf
         - get_pyarrow
+        - is_pandas_dataframe
       show_source: false
       show_bases: false
diff --git a/narwhals/dependencies.py b/narwhals/dependencies.py
index 7d5b9752..64c43d8e 100644
--- a/narwhals/dependencies.py
+++ b/narwhals/dependencies.py
@@ -45,3 +45,22 @@ def get_pyarrow_compute() -> Any:  # pragma: no cover
 def get_numpy() -> Any:
     """Get numpy module (if already imported - else return None)."""
     return sys.modules.get("numpy", None)
+
+
+def is_pandas_dataframe(df: Any) -> bool:
+    """Check whether `df` is a pandas DataFrame without importing pandas."""
+    if (pd := get_pandas()) is not None and isinstance(df, pd.DataFrame):
+        return True
+    return False
+
+
+__all__ = [
+    "get_polars",
+    "get_pandas",
+    "get_modin",
+    "get_cudf",
+    "get_pyarrow",
+    "get_pyarrow_compute",
+    "get_numpy",
+    "is_pandas_dataframe",
+]


Test patch:
diff --git a/tests/dependencies/__init__.py b/tests/dependencies/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dependencies/is_pandas_dataframe_test.py b/tests/dependencies/is_pandas_dataframe_test.py
new file mode 100644
index 00000000..a8ffaa73
--- /dev/null
+++ b/tests/dependencies/is_pandas_dataframe_test.py
@@ -0,0 +1,9 @@
+import pandas as pd
+import polars as pl
+
+from narwhals.dependencies import is_pandas_dataframe
+
+
+def test_is_pandas_dataframe() -> None:
+    assert is_pandas_dataframe(pd.DataFrame())
+    assert not is_pandas_dataframe(pl.DataFrame())
Repository: narwhals-dev/narwhals
Pull request #503 (2024-07-12 20:12:20)

feat: pyarrow `sum_horizontal`
## 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 0a7d3453..25852327 100644
--- a/narwhals/_arrow/namespace.py
+++ b/narwhals/_arrow/namespace.py
@@ -125,3 +125,12 @@ class ArrowNamespace:
             lambda x, y: x & y,
             parse_into_exprs(*exprs, namespace=self),
         )  # pragma: no cover
+
+    def sum_horizontal(self, *exprs: IntoArrowExpr) -> ArrowExpr:
+        return reduce(
+            lambda x, y: x + y,
+            parse_into_exprs(
+                *exprs,
+                namespace=self,
+            ),
+        )


Test patch:
diff --git a/tests/expr/sum_horizontal_test.py b/tests/expr/sum_horizontal_test.py
index 3c4600bb..64e74308 100644
--- a/tests/expr/sum_horizontal_test.py
+++ b/tests/expr/sum_horizontal_test.py
@@ -1,32 +1,20 @@
 from typing import Any
 
+import pytest
+
 import narwhals.stable.v1 as nw
 from tests.utils import compare_dicts
 
 
-def test_sumh(constructor: Any) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
-    df = nw.from_native(constructor(data), eager_only=True)
-    result = df.with_columns(horizonal_sum=nw.sum_horizontal(nw.col("a"), nw.col("b")))
-    result_native = nw.to_native(result)
-    expected = {
-        "a": [1, 3, 2],
-        "b": [4, 4, 6],
-        "z": [7.0, 8.0, 9.0],
-        "horizonal_sum": [5, 7, 8],
-    }
-    compare_dicts(result_native, expected)
-
-
-def test_sumh_literal(constructor: Any) -> None:
+@pytest.mark.parametrize("col_expr", [nw.col("a"), "a"])
+def test_sumh(constructor_with_pyarrow: Any, col_expr: Any) -> None:
     data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
-    df = nw.from_native(constructor(data), eager_only=True)
-    result = df.with_columns(horizonal_sum=nw.sum_horizontal("a", nw.col("b")))
-    result_native = nw.to_native(result)
+    df = nw.from_native(constructor_with_pyarrow(data), eager_only=True)
+    result = df.with_columns(horizontal_sum=nw.sum_horizontal(col_expr, nw.col("b")))
     expected = {
         "a": [1, 3, 2],
         "b": [4, 4, 6],
         "z": [7.0, 8.0, 9.0],
-        "horizonal_sum": [5, 7, 8],
+        "horizontal_sum": [5, 7, 8],
     }
-    compare_dicts(result_native, expected)
+    compare_dicts(result, expected)
Repository: narwhals-dev/narwhals
Pull request #538 (2024-07-16 15:46:55)

feat: add len to pyarrow series and expr
## What type of PR is this? (check all applicable)

- [ ] 💾 Refactor
- [x] ✨ Feature
- [ ] 🐛 Bug Fix
- [ ] 🔧 Optimization
- [ ] 📝 Documentation
- [ ] ✅ Test
- [ ] 🐳 Other

## Related issues 

- Related issue # #372 
- 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.
nox is giving failed nightly version




Patch:
diff --git a/narwhals/_arrow/expr.py b/narwhals/_arrow/expr.py
index bf4578a9..ced6556d 100644
--- a/narwhals/_arrow/expr.py
+++ b/narwhals/_arrow/expr.py
@@ -128,6 +128,9 @@ class ArrowExpr:
     def __invert__(self) -> Self:
         return reuse_series_implementation(self, "__invert__")
 
+    def len(self) -> Self:
+        return reuse_series_implementation(self, "len", returns_scalar=True)
+
     def filter(self, *predicates: Any) -> Self:
         from narwhals._arrow.namespace import ArrowNamespace
 
diff --git a/narwhals/_arrow/series.py b/narwhals/_arrow/series.py
index b0f2b6ae..19598bb8 100644
--- a/narwhals/_arrow/series.py
+++ b/narwhals/_arrow/series.py
@@ -143,6 +143,9 @@ class ArrowSeries:
         pc = get_pyarrow_compute()
         return self._from_native_series(pc.invert(self._native_series))
 
+    def len(self) -> int:
+        return len(self._native_series)
+
     def filter(self, other: Any) -> Self:
         other = validate_column_comparand(other)
         return self._from_native_series(self._native_series.filter(other))
diff --git a/utils/check_backend_completeness.py b/utils/check_backend_completeness.py
index f412fc5e..b9f07418 100644
--- a/utils/check_backend_completeness.py
+++ b/utils/check_backend_completeness.py
@@ -27,7 +27,6 @@ MISSING = [
     "Series.is_last_distinct",
     "Series.is_sorted",
     "Series.is_unique",
-    "Series.len",
     "Series.n_unique",
     "Series.quantile",
     "Series.round",


Test patch:
diff --git a/tests/expr/len_test.py b/tests/expr/len_test.py
index 55735d96..7ec1505c 100644
--- a/tests/expr/len_test.py
+++ b/tests/expr/len_test.py
@@ -1,7 +1,5 @@
 from typing import Any
 
-import pytest
-
 import narwhals.stable.v1 as nw
 from tests.utils import compare_dicts
 
@@ -9,13 +7,11 @@ data = {"a": list("xyz"), "b": [1, 2, 1]}
 expected = {"a1": [2], "a2": [1]}
 
 
-def test_len(request: Any, constructor: Any) -> None:
-    if "pyarrow_table" in str(constructor):
-        request.applymarker(pytest.mark.xfail)
+def test_len(constructor: Any) -> None:
     df_raw = constructor(data)
     df = nw.from_native(df_raw).select(
         nw.col("a").filter(nw.col("b") == 1).len().alias("a1"),
         nw.col("a").filter(nw.col("b") == 2).len().alias("a2"),
     )
 
-    compare_dicts(nw.to_native(df), expected)
+    compare_dicts(df, expected)