-
-
Save BradyHu/f4dc997d4b53f9b23e1120940fb8f0d1 to your computer and use it in GitHub Desktop.
#! /usr/bin python3 | |
# -*- coding:utf-8 -*- | |
""" | |
Add mypy type-checking ability to jupyter/ipython. | |
Save this script to your ipython profile's startup directory. | |
IPython's directories can be found via `ipython locate [profile]` to find the current ipython directory and ipython profile directory, respectively. | |
For example, this file could exist on a path like this on mac: | |
/Users/yourusername/.ipython/profile_default/startup/typecheck.py | |
where /Users/yourusername/.ipython/profile_default/ is the ipython directory for the default profile. | |
and the jupyter/ipython shell will do typecheck automatically. | |
""" | |
import re | |
from IPython import get_ipython | |
mypy_cells = '' | |
mypy_shell = get_ipython() | |
mypy_tmp_func = mypy_shell.run_cell | |
mypy_typecheck=True | |
def mypy_tmp(cell,*args,**kwargs): | |
if mypy_typecheck: | |
from mypy import api | |
global mypy_cells | |
mypy_cells_length = len(mypy_cells.split('\n'))-1 | |
mypy_cells+=(cell+'\n') | |
mypy_result = api.run(['-c', mypy_cells]) | |
if mypy_result[0]: | |
for line in mypy_result[0].strip().split('\n'): | |
l,n,r = re.compile('(<[a-z]+>:)(\d+)(.*?)$').findall(line)[0] | |
if int(n)>mypy_cells_length: | |
n = str(int(n)-mypy_cells_length) | |
print("".join([l,n,r])) | |
if mypy_result[1]: | |
print(mypy_result[1]) | |
return mypy_tmp_func(cell,*args,**kwargs) | |
mypy_shell.run_cell = mypy_tmp |
... works for a single run-through but not optimal for interactive use: mypy_cells keeps growing. Should be tracking cell modifications and deletions. Another question is - which cells should be re-evaluated by mypy to create the context for the current cell? All cells in the notebook? Perhaps not; maybe all cells with a magic marker.
The standard operating mechanism for a jupyter notebook is that the context for evaluating the current cell is precisely evaluating all previous cells in the order in which they were evaluated. Clearly any type-checking must use the same semantics.
I'm working on a facility based on this, to have some interactive use. It is internal for now, but I'll share it when I can.
Thanks for the initial gist btw!
We've made it into an iPython extension, which can be found here: https://pypi.org/project/nb-mypy/
... works for a single run-through but not optimal for interactive use: mypy_cells keeps growing. Should be tracking cell modifications and deletions. Another question is - which cells should be re-evaluated by mypy to create the context for the current cell? All cells in the notebook? Perhaps not; maybe all cells with a magic marker. This functionality could be folded into a jupyter extension.