Skip to content

Commit

Permalink
Add dev_tools/check_notebooks.py (#244)
Browse files Browse the repository at this point in the history
* Add dev_tools/check_notebooks.py

Change-Id: I578c7a45d1946d89b8de1ca15d3353ccc8578f76

* docs

Change-Id: I07c189f27b2c7c2adcf184e56437abab2e8eafe8

* nbfmt

Change-Id: I4308d149b9f088f565c68aad304ad6ee420e976b
  • Loading branch information
mpharrigan authored Dec 15, 2021
1 parent 6cf7bc2 commit dc52158
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 0 deletions.
1 change: 1 addition & 0 deletions dev_tools/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
notebook_envs
109 changes: 109 additions & 0 deletions dev_tools/check_notebooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import os
import shutil
import time
from multiprocessing import Pool
from subprocess import run as _run, CalledProcessError

BASE_PACKAGES = [
# for running the notebooks
"jupyter",
# assumed to be part of colab
"seaborn~=0.11.1",
]


def _check_notebook(notebook_fn: str, notebook_id: str, stdout, stderr):
"""Helper function to actually do the work in `check_notebook`.
`check_notebook` has all the context managers and exception handling,
which would otherwise result in highly indented code.
Args:
notebook_fn: The notebook filename
notebook_id: A unique string id for the notebook that does not include `/`
stdout: A file-like object to redirect stdout
stderr: A file-like object to redirect stderr
"""
print(f'Starting {notebook_id}')

def run(*args, **kwargs):
return _run(*args, check=True, stdout=stdout, stderr=stderr, **kwargs)

# 1. create venv
venv_dir = os.path.abspath(f'./notebook_envs/{notebook_id}')
run(['python', '-m', 'venv', '--clear', venv_dir])

# 2. basic colab-like environment
pip = f'{venv_dir}/bin/pip'
run([pip, 'install'] + BASE_PACKAGES)

# 3. execute
jupyter = f'{venv_dir}/bin/jupyter'
env = os.environ.copy()
env['PATH'] = f'{venv_dir}/bin:{env["PATH"]}'
run([jupyter, 'nbconvert', '--to', 'html', '--execute', notebook_fn], cwd='../', env=env)

# 4. clean up
shutil.rmtree(venv_dir)


def check_notebook(notebook_fn: str):
"""Check a notebook.
1. Create a venv just for that notebook
2. Verify the notebook executes without error (and that it installs its own dependencies!)
3. Clean up venv dir
A scratch directory dev_tools/notebook_envs will be created containing tvenv as well as
stdout and stderr logs for each notebook. Each of these files and directories will be
named according to the "notebook_id", which is `notebook_fn.replace('/', '-')`.
The executed notebook will be rendered to html alongside its original .ipynb file for
spot-checking.
Args:
notebook_fn: The filename of the notebook relative to the repo root.
"""
notebook_id = notebook_fn.replace('/', '-')
start = time.perf_counter()
with open(f'./notebook_envs/{notebook_id}.stdout', 'w') as stdout, \
open(f'./notebook_envs/{notebook_id}.stderr', 'w') as stderr:
try:
_check_notebook(notebook_fn, notebook_id, stdout, stderr)
except CalledProcessError:
print('ERROR!', notebook_id)
end = time.perf_counter()
print(f'{notebook_id} {end - start:.1f}s')


NOTEBOOKS = [
'docs/otoc/otoc_example.ipynb',
'docs/guide/data_analysis.ipynb',
'docs/guide/data_collection.ipynb',
'docs/qaoa/example_problems.ipynb',
'docs/qaoa/precomputed_analysis.ipynb',
'docs/qaoa/hardware_grid_circuits.ipynb',
'docs/qaoa/optimization_analysis.ipynb',
'docs/qaoa/tasks.ipynb',
'docs/qaoa/landscape_analysis.ipynb',
'docs/qaoa/routing_with_tket.ipynb',
'docs/quantum_chess/concepts.ipynb',
# 'docs/quantum_chess/quantum_chess_rest_api.ipynb', # runs a server, never finishes.
# 'docs/quantum_chess/quantum_chess_client.ipynb', # uses the server, requires modification.
'docs/hfvqe/molecular_data.ipynb',
'docs/hfvqe/quickstart.ipynb',
'docs/fermi_hubbard/publication_results.ipynb',
'docs/fermi_hubbard/experiment_example.ipynb',
]


def main():
os.chdir(os.path.dirname(__file__))
os.makedirs('./notebook_envs', exist_ok=True)
with Pool(4) as pool:
results = pool.map(check_notebook, NOTEBOOKS)
print(results)


if __name__ == '__main__':
main()
25 changes: 25 additions & 0 deletions docs/qaoa/optimization_analysis.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,31 @@
"</table>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "314b4703b85b"
},
"source": [
"## Setup\n",
"\n",
"Install the ReCirq package:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ca9285a3a162"
},
"outputs": [],
"source": [
"try:\n",
" import recirq\n",
"except ImportError:\n",
" !pip install -q git+https://github.com/quantumlib/ReCirq sympy~=1.6"
]
},
{
"cell_type": "markdown",
"metadata": {
Expand Down

0 comments on commit dc52158

Please sign in to comment.