To understand that multiple lines of code are actually a single line of python code, you'll need something that understands python.
In python, you can get at the compiler from code. The "compile" command can take text and return a code object, or throw an error if the code is not syntactically correct:
try:
compile(candidate_code, 'fake filename', 'exec')
# got here? candidate_code compiles
except:
# got here? candidate_code doesn't compile
Compiling is completely tolerant of missing definitions for symbols. However, it doesn't like to see extra indentation.
Using this, we can step through the lines of code, looking for multiline statements (groups of lines that successfully compile) and testing any that do compile for the target string. We have to keep compiling all lines up to the current line (otherwise if your statement is indented, it wont compile) and keep track of how many lines we are actually testing (using numcandidatelines). An alternate approach might be simply to detect and strip off extra indentation.
def findPythonLines(aContainsStr, lines):
numcandidatelines = 0
for index, line in enumerate(lines):
numcandidatelines += 1
try:
candidate_code = "\n".join(lines[:index+1])
candidate_statement = "\n".join(lines[index+1-numcandidatelines: index+1])
compile(candidate_code, 'fake filename', 'exec') # or 'exec'
# if we get here, this is a new possible result
if aContainsStr in candidate_statement:
return candidate_statement
else:
# no dice. Well, we need to look for the next candidate
numcandidatelines = 0
except:
pass
return None
# say input.txt contains the following:
# x = 10
#
# while (x
# > 0):
# g()
#
# y = f(Name='MANHOLE', Values=[ 1, 2, ],
# var='LV')
#
# x -= 1
with open ("input.txt", "r") as myfile:
full_code_lines=myfile.readlines()
print "result: %s" % findPythonLines("'LV'", full_code_lines)
# prints out the following:
#
# result:
# y = f(Name='MANHOLE', Values=[ 1, 2, ],
# var='LV')