Skip to content

Commit 694e69a

Browse files
authored
Infinite loop if this lambda is parsed in Jupyter (#111)
* Found bug if a "word" wasn't at the end of the line, which was a bit of a dumb bug and a bit embarassing that none of my tests had covered it. Fixes #110
1 parent b76eed7 commit 694e69a

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

func_adl/util_ast.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def function_call(function_name: str, args: List[ast.AST]) -> ast.Call:
6464

6565

6666
def lambda_unwrap(lam: ast.AST) -> ast.Lambda:
67-
"""Given an AST of a lambda node, return the lambda node. If it is burried in a module, then
67+
"""Given an AST of a lambda node, return the lambda node. If it is buried in a module, then
6868
unwrap it first Python, when it parses an module, returns the lambda wrapped in a `Module` AST
6969
node. This gets rid of it, but is also flexible.
7070
@@ -557,7 +557,7 @@ def previous_word(self) -> Optional[str]:
557557
carrot = self._carrot
558558
while line_no >= 0:
559559
while carrot >= 0:
560-
m = re.match(r".*\W(\w+)\s*$", self._lines[line_no][:carrot])
560+
m = re.match(r".*\b(\w+)\b[\s|\W]*$", self._lines[line_no][:carrot])
561561
if m:
562562
return m.group(1)
563563
line_no -= 1

tests/test_util_ast.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,42 @@ def do_it(self, x: Callable):
612612
assert "20" in ast.dump(found[0])
613613

614614

615+
def test_parse_multiline_lambda_blank_lines_no_infinite_loop():
616+
"Make sure we can properly parse a multi-line lambda - using parens as delimiters"
617+
618+
found = []
619+
620+
class my_obj:
621+
def Where(self, x: Callable):
622+
found.append(parse_as_ast(x))
623+
return self
624+
625+
def Select(self, x: Callable):
626+
found.append(parse_as_ast(x))
627+
return self
628+
629+
def AsAwkwardArray(self, stuff: str):
630+
return self
631+
632+
def value(self):
633+
return self
634+
635+
jets_pflow_name = "hi"
636+
ds_dijet = my_obj()
637+
638+
# fmt: off
639+
jets_pflow = (
640+
ds_dijet.Select(lambda e: e.Jets(uncalibrated_collection=jets_pflow_name))
641+
.Select(lambda e: e.Where(lambda j: (j.pt() / 1000) > 30))
642+
.Select(lambda e: e.Select(lambda j: (j.pt() / 1000)))
643+
.AsAwkwardArray("JetPt")
644+
.value()
645+
)
646+
# fmt: on
647+
assert jets_pflow is not None # Just to keep flake8 happy without adding a noqa above.
648+
assert "uncalibrated_collection" in ast.dump(found[0])
649+
650+
615651
def test_parse_multiline_lambda_ok_with_one_as_arg():
616652
"Make sure we can properly parse a multi-line lambda - but now with argument"
617653

0 commit comments

Comments
 (0)