From e69d2da25051dacb2adc70042335854330455641 Mon Sep 17 00:00:00 2001 From: Trevor Bergeron Date: Wed, 9 Jul 2025 20:48:05 +0000 Subject: [PATCH 1/3] fix: DataFrame string addition respects order --- bigframes/dataframe.py | 7 +++++-- tests/system/small/test_dataframe.py | 10 ++++++++++ .../bigframes_vendored/pandas/core/frame.py | 14 ++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/bigframes/dataframe.py b/bigframes/dataframe.py index 1884f0beff..4def300ea4 100644 --- a/bigframes/dataframe.py +++ b/bigframes/dataframe.py @@ -1046,14 +1046,17 @@ def radd( ) -> DataFrame: # TODO(swast): Support fill_value parameter. # TODO(swast): Support level parameter with MultiIndex. - return self.add(other, axis=axis) + return self._apply_binop(other, ops.add_op, axis=axis, reverse=True) def __add__(self, other) -> DataFrame: return self.add(other) __add__.__doc__ = inspect.getdoc(vendored_pandas_frame.DataFrame.__add__) - __radd__ = __add__ + def __radd__(self, other): + return self.radd(other) + + __radd__.__doc__ = inspect.getdoc(vendored_pandas_frame.DataFrame.__radd__) def sub( self, diff --git a/tests/system/small/test_dataframe.py b/tests/system/small/test_dataframe.py index 3a1c54302f..67ee54e6e7 100644 --- a/tests/system/small/test_dataframe.py +++ b/tests/system/small/test_dataframe.py @@ -2548,6 +2548,16 @@ def test_scalar_binop(scalars_dfs, op, other_scalar, reverse_operands): assert_pandas_df_equal(bf_result, pd_result) +def test_dataframe_string_radd_const(scalars_dfs): + scalars_df, scalars_pandas_df = scalars_dfs + columns = ["string_col", "string_col"] + + bf_result = ("prefix" + scalars_df[columns]).to_pandas() + pd_result = "prefix" + scalars_pandas_df[columns] + + assert_pandas_df_equal(bf_result, pd_result) + + @pytest.mark.parametrize(("other_scalar"), [1, -2]) def test_mod(scalars_dfs, other_scalar): # Zero case excluded as pandas produces 0 result for Int64 inputs rather than NA/NaN. diff --git a/third_party/bigframes_vendored/pandas/core/frame.py b/third_party/bigframes_vendored/pandas/core/frame.py index 40ab5a7352..3dcff52a66 100644 --- a/third_party/bigframes_vendored/pandas/core/frame.py +++ b/third_party/bigframes_vendored/pandas/core/frame.py @@ -3043,6 +3043,20 @@ def radd(self, other, axis: str | int = "columns") -> DataFrame: """ raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) + def __radd__(self, other, axis: str | int = "columns") -> DataFrame: + """Get addition of other and DataFrame, element-wise (binary operator `+`). + + Equivalent to ``DataFrame.radd(other)``. + + Args: + other (float, int, or Series): + Any single or multiple element data structure, or list-like object. + + Returns: + bigframes.pandas.DataFrame: DataFrame result of the arithmetic operation. + """ + raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) + def sub(self, other, axis: str | int = "columns") -> DataFrame: """Get subtraction of DataFrame and other, element-wise (binary operator `-`). From 557e6bf2f765f4870cd1b430e9f39904ac7d0ac5 Mon Sep 17 00:00:00 2001 From: Trevor Bergeron Date: Wed, 9 Jul 2025 20:53:50 +0000 Subject: [PATCH 2/3] fix types annotations --- bigframes/dataframe.py | 2 +- third_party/bigframes_vendored/pandas/core/frame.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bigframes/dataframe.py b/bigframes/dataframe.py index 4def300ea4..324107680a 100644 --- a/bigframes/dataframe.py +++ b/bigframes/dataframe.py @@ -1053,7 +1053,7 @@ def __add__(self, other) -> DataFrame: __add__.__doc__ = inspect.getdoc(vendored_pandas_frame.DataFrame.__add__) - def __radd__(self, other): + def __radd__(self, other) -> DataFrame: return self.radd(other) __radd__.__doc__ = inspect.getdoc(vendored_pandas_frame.DataFrame.__radd__) diff --git a/third_party/bigframes_vendored/pandas/core/frame.py b/third_party/bigframes_vendored/pandas/core/frame.py index 3dcff52a66..2d737282b7 100644 --- a/third_party/bigframes_vendored/pandas/core/frame.py +++ b/third_party/bigframes_vendored/pandas/core/frame.py @@ -3043,7 +3043,7 @@ def radd(self, other, axis: str | int = "columns") -> DataFrame: """ raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) - def __radd__(self, other, axis: str | int = "columns") -> DataFrame: + def __radd__(self, other) -> DataFrame: """Get addition of other and DataFrame, element-wise (binary operator `+`). Equivalent to ``DataFrame.radd(other)``. From 8025d2d8be1f309414875e8c2adeb46bce4355d5 Mon Sep 17 00:00:00 2001 From: Trevor Bergeron Date: Wed, 9 Jul 2025 21:33:11 +0000 Subject: [PATCH 3/3] skip test on old pandas --- tests/system/small/test_dataframe.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/system/small/test_dataframe.py b/tests/system/small/test_dataframe.py index 67ee54e6e7..3a8ee61ed1 100644 --- a/tests/system/small/test_dataframe.py +++ b/tests/system/small/test_dataframe.py @@ -2549,6 +2549,12 @@ def test_scalar_binop(scalars_dfs, op, other_scalar, reverse_operands): def test_dataframe_string_radd_const(scalars_dfs): + pytest.importorskip( + "pandas", + minversion="2.0.0", + reason="PyArrow string addition requires pandas 2.0+", + ) + scalars_df, scalars_pandas_df = scalars_dfs columns = ["string_col", "string_col"]