Skip to content

Commit 2895b9b

Browse files
author
root
committed
Fix for issue pandas-dev#28283: Ensure DataFrame.eval calls __finalize__
1 parent 283a2dc commit 2895b9b

File tree

1 file changed

+26
-17
lines changed

1 file changed

+26
-17
lines changed

pandas/core/frame.py

+26-17
Original file line numberDiff line numberDiff line change
@@ -4628,27 +4628,36 @@ def query(self, expr: str, *, inplace: bool = False, **kwargs) -> DataFrame | No
46284628
return result
46294629

46304630
@overload
4631-
def eval(self, expr: str, *, inplace: Literal[False] = ..., **kwargs) -> Any: ...
46324631

4633-
@overload
4634-
def eval(self, expr: str, *, inplace: Literal[True], **kwargs) -> None: ...
4632+
def eval(self, expr: str, *, inplace: bool = False, **kwargs) -> Any | None:
4633+
"""
4634+
Evaluate a string describing operations on DataFrame columns.
46354635
4636-
def eval(self, expr: str, *, inplace: bool = False, **kwargs) -> Any | None:
4637-
"""
4638-
Evaluate a string describing operations on DataFrame columns.
4636+
Operates on columns only, not specific rows or elements. This allows
4637+
`eval` to run arbitrary code, which can make you vulnerable to code
4638+
injection if you pass user input to this function.
46394639
4640-
Operates on columns only, not specific rows or elements. This allows
4641-
`eval` to run arbitrary code, which can make you vulnerable to code
4642-
injection if you pass user input to this function.
4640+
Parameters
4641+
----------
4642+
expr : str
4643+
The expression string to evaluate.
4644+
inplace : bool, default False
4645+
If the expression contains an assignment, whether to perform the
4646+
operation inplace and mutate the existing DataFrame. Otherwise,
4647+
a new DataFrame is returned.
4648+
"""
4649+
from pandas.core.computation.eval import eval as _eval
4650+
4651+
if not isinstance(expr, str):
4652+
msg = f"expr must be a string to be evaluated, {type(expr)} given"
4653+
raise ValueError(msg)
4654+
4655+
# Ensure __finalize__ is called to propagate metadata
4656+
result = super().eval(expr, inplace=inplace, **kwargs)
4657+
if not inplace:
4658+
result = result.__finalize__(self, method="eval")
4659+
return result
46434660

4644-
Parameters
4645-
----------
4646-
expr : str
4647-
The expression string to evaluate.
4648-
inplace : bool, default False
4649-
If the expression contains an assignment, whether to perform the
4650-
operation inplace and mutate the existing DataFrame. Otherwise,
4651-
a new DataFrame is returned.
46524661
**kwargs
46534662
See the documentation for :func:`eval` for complete details
46544663
on the keyword arguments accepted by

0 commit comments

Comments
 (0)