Skip to content

Commit c7ac553

Browse files
committed
Fix GH15342 - Multiline Eval broken for local variables after first line
Also fixes the code which attempted to ignore any blank lines in the multiline expression.
1 parent 542c916 commit c7ac553

File tree

3 files changed

+19
-3
lines changed

3 files changed

+19
-3
lines changed

doc/source/whatsnew/v0.20.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -516,3 +516,4 @@ Bug Fixes
516516

517517
- Bug in ``DataFrame.boxplot`` where ``fontsize`` was not applied to the tick labels on both axes (:issue:`15108`)
518518
- Bug in ``Series.replace`` and ``DataFrame.replace`` which failed on empty replacement dicts (:issue:`15289`)
519+
- Bug in ``.eval()`` which caused multiline evals to fail with local variables not on the first line (:issue:`15342`)

pandas/computation/eval.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ def eval(expr, parser='pandas', engine=None, truediv=True,
236236
first_expr = True
237237
if isinstance(expr, string_types):
238238
_check_expression(expr)
239-
exprs = [e for e in expr.splitlines() if e != '']
239+
exprs = [e.strip() for e in expr.splitlines() if e.strip() != '']
240240
else:
241241
exprs = [expr]
242242
multi_line = len(exprs) > 1
@@ -254,8 +254,7 @@ def eval(expr, parser='pandas', engine=None, truediv=True,
254254
_check_for_locals(expr, level, parser)
255255

256256
# get our (possibly passed-in) scope
257-
level += 1
258-
env = _ensure_scope(level, global_dict=global_dict,
257+
env = _ensure_scope(level + 1, global_dict=global_dict,
259258
local_dict=local_dict, resolvers=resolvers,
260259
target=target)
261260

pandas/computation/tests/test_eval.py

+16
Original file line numberDiff line numberDiff line change
@@ -1411,6 +1411,22 @@ def test_multi_line_expression_not_inplace(self):
14111411
e = a + 2""", inplace=False)
14121412
assert_frame_equal(expected, df)
14131413

1414+
def test_multi_line_expression_local_variable(self):
1415+
# GH 15342
1416+
tm.skip_if_no_ne('numexpr')
1417+
df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})
1418+
expected = df.copy()
1419+
1420+
local_var = 7
1421+
expected['c'] = expected['a'] * local_var
1422+
expected['d'] = expected['c'] + local_var
1423+
ans = df.eval("""
1424+
c = a * @local_var
1425+
d = c + @local_var
1426+
""", inplace=True)
1427+
assert_frame_equal(expected, df)
1428+
self.assertIsNone(ans)
1429+
14141430
def test_assignment_in_query(self):
14151431
# GH 8664
14161432
df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})

0 commit comments

Comments
 (0)