Reputation: 358
I am trying to find the class name where a function name is called.
E.g. suppose I have:
class foo1(object):
bar1()
class foo2(object):
bar2()
class foo3(object):
bar3()
If I am searching for bar2() I want to receive:
class foo2(object):
bar2()
I tried regex class[\s\S]*bar2\(\)(?!class)
with the idea being that I would negative lookahead for another appearance of class. Unfortunately it looks like the [\s\S] is already matching everything: https://regex101.com/r/kZ7eE5/1
Is there a way to match if "class" appears only one time while matching on all other chars (including new line and tab)?
Also alternatives that do not require regex would be accepted.
Upvotes: 2
Views: 2072
Reputation: 18940
The RE approach can be error prone (the expressive power of Python language is more that those of the regular languages recognized by REs).
Use Python's ast
module to parse Python code:
code = '''
class foo1(object):
bar1()
class foo2(object):
bar2()
class foo3(object):
bar3()
'''
>>> import ast
>>> tree = ast.parse(code)
>>> for i in tree.body:
... if isinstance(i, ast.ClassDef):
... print('class: %s' % i.name)
...
class: foo1
class: foo2
class: foo3
>>>
and you can do many other things, check the docs at https://greentreesnakes.readthedocs.org/en/latest/
Edit: a more complete example:
>>> for i in tree.body:
... if isinstance(i, ast.ClassDef):
... for j in i.body:
... if isinstance(j, ast.Expr):
... print('found a call to function %s in class %s' % (j.value.func.id, i.name))
...
found a call to function bar1 in class foo1
found a call to function bar2 in class foo2
found a call to function bar3 in class foo3
Upvotes: 5
Reputation: 3036
The following code prints the class that contains the method call that is stored in function
variable .Here's what you need to do :
import re
data = """
class foo1(object):
bar1()
class foo2(object):
bar2()
class foo3(object):
bar3()
"""
classes = re.findall('(class[\s\S]*?)(?=class|$)',data)
function = "bar2()"
for x in classes:
if function in x:
matched_class = x
break
print(matched_class)
Output:
class foo2(object):
bar2()
Upvotes: 1
Reputation: 2553
The reason [\s\S]*
matches everything is because you are telling is to match either any space character (\s
) or any non-space character (\S
) any number of times. You can just match space with space in regex. Usually. There are exceptions, but python demands this form, so it should be fine.
You can use
^class ([\w]+)\([^)]+\):
Demo: https://regex101.com/r/aB9pX4/2
Upvotes: 0