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 hints, so I'd like to write a script to remove those entirely.
This seemed easy enough at first glance and I decided to write some regexes to do this, but then I thought about a few edge cases and I wasn't sure how to solve the problem for a more complex function like this:
def foo(bar: Dict[T, List[T]],
baz: Callable[[T], int] = lambda x: (x+3)/7,
**kwargs) -> List[T]:
Basically, I'd have to parse the whole thing and rebuild the argument list without type annotations. How would I even approach this?
You can subclass
lib2to3.refactor.RefactoringTool
to refactor the code using a fixer that is a subclass oflib2to3.fixer_base.BaseFix
with a pattern that looks for either a typed argument, a function declaration with an annotated returning value, or a simple statement that imports or imports fromtyping
, and atransform
method that removes the indices of the annotations from the child nodes or replaces the statement node with an empty node:so that:
outputs:
Demo: https://repl.it/@blhsing/BurlywoodFeistyTrials
As a bonus,
lib2to3
also preserves all comments and white spaces after the transformation. You can find the definition of the Python grammar inGrammar.txt
of thelib2to3
module.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:
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: