Python: Making a function signature *without* inspect

67 views Asked by At

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?

1

There are 1 answers

0
Robert Haas On BEST ANSWER

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