Remove type hints in Python source programmatically

后端 未结 3 812
孤城傲影
孤城傲影 2020-12-29 07:21

I have some source code written for Python 3.5 that I want to make executable under Python 3.4. The only feature from 3.5 that I use which is not available in 3.4 are type h

3条回答
  •  太阳男子
    2020-12-29 07:58

    OK, I got it :D

    Use Python's builtin ast module to parse the source code and then the excellent astunparse library to generate source code from the parsed ast again. Then all that's left is to remove the type annotations:

    import ast
    import astunparse
    
    source="""
    import typing
    from typing import Dict, T, Callable
    from typing import List
    
    def foo(bar: Dict[T, List[T]],
            baz: Callable[[T], int] = lambda x: (x+3)/7,
            **kwargs) -> List[T]:
        pass
    """
    
    class TypeHintRemover(ast.NodeTransformer):
    
        def visit_FunctionDef(self, node):
            # remove the return type defintion
            node.returns = None
            # remove all argument annotations
            if node.args.args:
                for arg in node.args.args:
                    arg.annotation = None
            return node
    
        def visit_Import(self, node):
            node.names = [n for n in node.names if n.name != 'typing']
            return node if node.names else None
    
        def visit_ImportFrom(self, node):
            return node if node.module != 'typing' else None
    
    # parse the source code into an AST
    parsed_source = ast.parse(source)
    # remove all type annotations, function return type definitions
    # and import statements from 'typing'
    transformed = TypeHintRemover().visit(parsed_source)
    # convert the AST back to source code
    print(astunparse.unparse(transformed))
    

    The TypeHintRemover visits all Nodes in the AST and removes all type hints within function arguments, the return type definitions of each function and all import statements that refer to the 'typing' module.

    The result is:

    def foo(bar, baz=(lambda x: ((x + 3) / 7)), **kwargs):
        pass
    

提交回复
热议问题