Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Run 2to3 on IPython notebooks
#!/usr/bin/env python3
"""
To run: python3 nb2to3.py notebook-or-directory
"""
# Authors: Thomas Kluyver, Fernando Perez
# See: https://gist.github.com/takluyver/c8839593c615bb2f6e80
import argparse
import pathlib
from nbformat import read, write
import lib2to3
from lib2to3.refactor import RefactoringTool, get_fixers_from_package
def refactor_notebook_inplace(rt, path):
def refactor_cell(src):
#print('\n***SRC***\n', src)
try:
tree = rt.refactor_string(src+'\n', str(path) + '/cell-%d' % i)
except (lib2to3.pgen2.parse.ParseError,
lib2to3.pgen2.tokenize.TokenError):
return src
else:
return str(tree)[:-1]
print("Refactoring:", path)
nb = read(str(path), as_version=4)
# Run 2to3 on code
for i, cell in enumerate(nb.cells, start=1):
if cell.cell_type == 'code':
if cell.execution_count in (' ', '*'):
cell.execution_count = None
if cell.source.startswith('%%'):
# For cell magics, try to refactor the body, in case it's
# valid python
head, source = cell.source.split('\n', 1)
cell.source = head + '\n' + refactor_cell(source)
else:
cell.source = refactor_cell(cell.source)
# Update notebook metadata
nb.metadata.kernelspec = {
'display_name': 'Python 3',
'name': 'python3',
'language': 'python',
}
if 'language_info' in nb.metadata:
nb.metadata.language_info.codemirror_mode = {
'name': 'ipython',
'version': 3,
}
nb.metadata.language_info.pygments_lexer = 'ipython3'
nb.metadata.language_info.pop('version', None)
write(nb, str(path))
def main(argv=None):
ap = argparse.ArgumentParser()
ap.add_argument('path', type=pathlib.Path,
help="Notebook or directory containing notebooks")
options = ap.parse_args(argv)
avail_fixes = set(get_fixers_from_package('lib2to3.fixes'))
rt = RefactoringTool(avail_fixes)
if options.path.is_dir():
for nb_path in options.path.rglob('*.ipynb'):
refactor_notebook_inplace(rt, nb_path)
else:
refactor_notebook_inplace(rt, options.path)
if __name__ == '__main__':
main()
@drevicko

This comment has been minimized.

Copy link

@drevicko drevicko commented Aug 9, 2017

Traceback (most recent call last):
  File "2to3_nb.py", line 80, in <module>
    main()
  File "2to3_nb.py", line 75, in main
    refactor_notebook_inplace(rt, nb_path)
  File "2to3_nb.py", line 41, in refactor_notebook_inplace
    head, source = cell.source.split('\n', 1)
ValueError: not enough values to unpack (expected 2, got 1)

I think the offending bit of the ipynb file is this:

   "source": [
    "%%timeit p={\"$push\":{'events':event}}"
   ]

Catching the exception and ignoring looks to solve it (:

@EWouters

This comment has been minimized.

Copy link

@EWouters EWouters commented Apr 11, 2018

I used this to make an extension for Jupyter Notebooks that can convert cells (or whole notebooks) from python 2 to 3 with the click of a button. It has been added to jupyter_contrib_nbextensions. I mentioned your contribution in the readme.

Find it here.

@urkh

This comment has been minimized.

Copy link

@urkh urkh commented Jan 2, 2019

Thanks. Very useful for me.

@nyck33

This comment has been minimized.

Copy link

@nyck33 nyck33 commented Mar 6, 2020

Great docs but where is the simplied, "pip install this", "conda install this" and you're good to go instructions?

@takluyver

This comment has been minimized.

Copy link
Owner Author

@takluyver takluyver commented Mar 6, 2020

Since @EWouters turned this script into an nbextension, you can refer to the jupyter-contrib-nbextensions docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment