2

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.

5
  • 2
    Why are you parsing Python with regular expressions? Commented Jun 26, 2015 at 15:19
  • Your chances might be better just scanning one line after the other and memorizing the last class definition you encountered. Also, what about nested classes, or methods, or methods with nested classes? Commented Jun 26, 2015 at 15:30
  • I want to analyze the code base. Is there another tool that I can parse Python with? Commented Jun 26, 2015 at 15:31
  • Not used it myself, but docs.python.org/2/library/parser.html might be worth a look, or the ast(docs.python.org/2/library/ast.html) module. Commented Jun 26, 2015 at 15:33
  • @tobias_k yea I'll try that. Good point about the nested classes - in that case I would want just the closest level class. If the method is in a method which is in a class, I would want that class. Commented Jun 26, 2015 at 15:37

3 Answers 3

5

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
Sign up to request clarification or add additional context in comments.

3 Comments

This doesn't serve OPs purpose, he wants to return a class that contains a certain function call
@PruthviRaj It's not complete, but it certainly works better than using regex.
@mescalinum , +1 this is perfect :)
1

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()

4 Comments

Now try to use this to find a method named get_class() or similar.
@tobias_k , I agree this approach might not be better but I did what OP has asked for
He did not ask for this specifically, just wanted to point out that the regex appraoch (not just yours, but generally) is not really up to the job. That's just one example of when it will fail.
yeah I see the approach by mescalinium is better :) , Thank you
0

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

1 Comment

This will return all classes, but what if I want only the class with function bar2()?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.