Farthing: generate type annotations for Python source code by running it
Farthing will run arbitrary Python code while tracing the argument and return types of all functions within a given file or directory. Farthing can then automatically add type annotations based on the types of the values it saw during the execution run. This might be useful if you want to add static types to existing Python code, or for exploring codebases where you're not sure what type a value has.
For instance, the following code:
def factorial(n): result = 1 for i in range(2, n + 1): result *= i return result
can be automatically transformed into:
def factorial(n: int) -> int: result = 1 for i in range(2, n + 1): result *= i return result
by running Farthing against the following test file:
from nose.tools import assert_equal import fact def test_fib(): test_cases = [ (0, 1), (1, 1), (2, 2), (3, 6), (4, 24), (5, 120), ] for index, value in test_cases: yield _check_fact, index, value def _check_fact(index, value): assert_equal(value, fact.factorial(index))
Farthing can be called from the command line. The first argument should be the file or directory that should have type annotations added to it. The other arguments should be the Python script to run with any arguments. For instance:
farthing demo/fact.py _virtualenv/bin/nosetests demo/tests.py
To run the demo, you can just run
demo.sh. To explain what it actually does:
make bootstrapto set up the virtualenv with dependencies.
. _virtualenv/bin/activateto enter the virtualenv.
farthing demo/fact.py _virtualenv/bin/nosetests demo/tests.pyto run
_virtualenv/bin/nosetests demo/tests.pyand add annotations to
demo/fact.pybased on the types of actual values used in the execution run.
At the moment, Farthing is just a quick prototype, so currently has the following limitations:
- Annotations are added just using the name of the type, which may not be available in the current scope.
- Type annotations cannot be added to the Python script being run.
I'd be interested to see any projects along similar lines, so if you know of any, I'd be grateful if you let me know.
- Type various iterables (e.g. the return value from
dict.keys()) as iterables.
- Check typing of methods.
- Support user-defined generics (with markup).
- Allow additional directories and files to be traced without being annotated.