Skip to content

Commit a82307f

Browse files
authored
BUG: Fix AttributeError in pd.eval for method calls on binary operations (#61198)
BUG: Fix AttributeError in pd.eval for method calls on binary operations (#61175)
1 parent b69a2ae commit a82307f

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

doc/source/whatsnew/v3.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,7 @@ Other
825825
- Bug in :class:`DataFrame` when passing a ``dict`` with a NA scalar and ``columns`` that would always return ``np.nan`` (:issue:`57205`)
826826
- Bug in :class:`Series` ignoring errors when trying to convert :class:`Series` input data to the given ``dtype`` (:issue:`60728`)
827827
- Bug in :func:`eval` on :class:`ExtensionArray` on including division ``/`` failed with a ``TypeError``. (:issue:`58748`)
828+
- Bug in :func:`eval` where method calls on binary operations like ``(x + y).dropna()`` would raise ``AttributeError: 'BinOp' object has no attribute 'value'`` (:issue:`61175`)
828829
- Bug in :func:`eval` where the names of the :class:`Series` were not preserved when using ``engine="numexpr"``. (:issue:`10239`)
829830
- Bug in :func:`eval` with ``engine="numexpr"`` returning unexpected result for float division. (:issue:`59736`)
830831
- Bug in :func:`to_numeric` raising ``TypeError`` when ``arg`` is a :class:`Timedelta` or :class:`Timestamp` scalar. (:issue:`59944`)

pandas/core/computation/expr.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,11 @@ def visit_Attribute(self, node, **kwargs):
644644
ctx = node.ctx
645645
if isinstance(ctx, ast.Load):
646646
# resolve the value
647-
resolved = self.visit(value).value
647+
visited_value = self.visit(value)
648+
if hasattr(visited_value, "value"):
649+
resolved = visited_value.value
650+
else:
651+
resolved = visited_value(self.env)
648652
try:
649653
v = getattr(resolved, attr)
650654
name = self.env.add_tmp(v)

pandas/tests/computation/test_eval.py

+21
Original file line numberDiff line numberDiff line change
@@ -2006,3 +2006,24 @@ def test_eval_float_div_numexpr():
20062006
result = pd.eval("1 / 2", engine="numexpr")
20072007
expected = 0.5
20082008
assert result == expected
2009+
2010+
2011+
def test_method_calls_on_binop():
2012+
# GH 61175
2013+
x = Series([1, 2, 3, 5])
2014+
y = Series([2, 3, 4])
2015+
2016+
# Method call on binary operation result
2017+
result = pd.eval("(x + y).dropna()")
2018+
expected = (x + y).dropna()
2019+
tm.assert_series_equal(result, expected)
2020+
2021+
# Test with other binary operations
2022+
result = pd.eval("(x * y).dropna()")
2023+
expected = (x * y).dropna()
2024+
tm.assert_series_equal(result, expected)
2025+
2026+
# Test with method chaining
2027+
result = pd.eval("(x + y).dropna().reset_index(drop=True)")
2028+
expected = (x + y).dropna().reset_index(drop=True)
2029+
tm.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)