I am working on a static code analyzer. Given the python file defining classes and methods, I'd like to construct a Signature object for all functions.
For instance, given the following function:
def method_with_args(self, param_a: str, param_b: int = 123) -> str:
"""
Method with arguments and a return value.
Args:
param_a (str): A string parameter.
param_b (int): An integer parameter.
Returns:
str: Concatenation of param1 and string representation of param2.
"""
return param_a + str(param_b)
I want to get something like:
<Signature (self, param_a: str, param_b: int = 123) -> str>
I know I can achieve this using inspect, however, I do not want to import the analyzed code, and this must be done statically.
Is there a straightforward way to do this?
You can use Python's ast module to treat the code as text and parse it into an abstract syntax tree:
import ast
s = '''
def method_with_args(self, param_a: str, param_b: int = 123) -> str:
"""
Method with arguments and a return value.
Args:
param_a (str): A string parameter.
param_b (int): An integer parameter.
Returns:
str: Concatenation of param1 and string representation of param2.
"""
return param_a + str(param_b)
'''
tree = ast.parse(s)
Then you can iterate over the nodes in the tree and look for classes, methods, functions or whatever else you are interested in and inspect its contents to construct a signature:
for node in tree.body:
if isinstance(node, ast.FunctionDef):
print([x.arg for x in node.args.args])
print([x.arg for x in node.args.kwonlyargs])
print(node.args.vararg)
print(node.args.kwarg)
...