diff --git a/pandas/core/computation/expr.py b/pandas/core/computation/expr.py index c59952bea8dc0..ec7e4c107edf5 100644 --- a/pandas/core/computation/expr.py +++ b/pandas/core/computation/expr.py @@ -670,19 +670,26 @@ def visit_Call(self, node, side=None, **kwargs): ) return res(*new_args) + elif isinstance(res, np.floor()): + new_args = [self.visit(arg) for arg in node.args] + new_args = str(*new_args) + new_args = [eval(new_args)] + if node.keywords: + raise TypeError( + f'Function "{res.name}" does not support keyword arguments' + ) else: - new_args = [self.visit(arg).value for arg in node.args] - for key in node.keywords: - if not isinstance(key, ast.keyword): - raise ValueError(f"keyword error in function call '{node.func.id}'") + for key in node.keywords: + if not isinstance(key, ast.keyword): + raise ValueError(f"keyword error in function call '{node.func.id}'") - if key.arg: - kwargs[key.arg] = self.visit(key.value).value + if key.arg: + kwargs[key.arg] = self.visit(key.value).value - return self.const_type(res(*new_args, **kwargs), self.env) + return self.const_type(res(*new_args, **kwargs), self.env) def translate_In(self, op): return op diff --git a/pandas/tests/computation/test_eval.py b/pandas/tests/computation/test_eval.py index 08d8d5ca342b7..7059113759759 100644 --- a/pandas/tests/computation/test_eval.py +++ b/pandas/tests/computation/test_eval.py @@ -727,6 +727,10 @@ def test_line_continuation(self): result = pd.eval(exp, engine=self.engine, parser=self.parser) assert result == 12 + def test_floor_expression(self): + assert pd.eval("floor(0.9 + floor(1.2+2.3))") == 3.0 + assert pd.eval("floor(1.2+2.3)") == 3.0 + def test_float_truncation(self): # GH 14241 exp = "1000000000.006"