Skip to content

Commit 08a8640

Browse files
committed
[roottest] Use nbconvert as a library in nbdiff.py
Using nbconvert as a Python library is less fragile, because otherwise there is ambiguity how the command line util should be called (the name changed over the versions as it migrated from ipython to jupyter).
1 parent 62d931d commit 08a8640

File tree

1 file changed

+32
-31
lines changed

1 file changed

+32
-31
lines changed

roottest/python/JupyROOT/nbdiff.py

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,10 @@
22
import json
33
import os
44
import shutil
5-
import subprocess
65
import sys
76
import tempfile
87

98
nbExtension = ".ipynb"
10-
convCmdTmpl = (
11-
"%s nbconvert "
12-
"--to notebook "
13-
"--ExecutePreprocessor.kernel_name=%s "
14-
"--ExecutePreprocessor.enabled=True "
15-
"--ExecutePreprocessor.timeout=3600 "
16-
"--ExecutePreprocessor.startup_timeout=180 "
17-
"%s "
18-
"--output %s"
19-
)
20-
pythonInterpName = "python3"
219

2210
rootKernelFileContent = (
2311
"""{
@@ -32,7 +20,7 @@
3220
]
3321
}
3422
"""
35-
% pythonInterpName
23+
% sys.executable
3624
)
3725

3826

@@ -149,34 +137,49 @@ def addEtcToEnvironment(inNBDirName):
149137
return ipythondir
150138

151139

152-
def getInterpreterName():
153-
"""Find if the 'jupyter' executable is available on the platform. If
154-
yes, return its name else return 'ipython'
155-
"""
156-
ret = subprocess.call("type jupyter", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
157-
return "jupyter" if ret == 0 else "i%s" % pythonInterpName
158-
159-
160140
def getKernelName(inNBName):
161141
with open(inNBName) as f:
162142
nbj = json.load(f)
163143
if nbj["metadata"]["kernelspec"]["language"] == "python":
164-
return pythonInterpName
144+
return "python3"
165145
else: # we support only Python and C++
166146
return "root"
167147

168148

169-
def canReproduceNotebook(inNBName, kernelName, needsCompare):
149+
def canReproduceNotebook(inNBName, needsCompare):
150+
from nbconvert import NotebookExporter
151+
from nbconvert.preprocessors import ExecutePreprocessor
152+
import nbformat
153+
170154
tmpDir = addEtcToEnvironment(os.path.dirname(inNBName))
171155
outNBName = inNBName.replace(nbExtension, "_out" + nbExtension)
172-
interpName = getInterpreterName()
173-
convCmd = convCmdTmpl % (interpName, kernelName, inNBName, outNBName)
174-
exitStatus = os.system(convCmd) # we use system to inherit the environment in os.environ
175-
shutil.rmtree(tmpDir)
156+
157+
# Load input notebook
158+
with open(inNBName, "r", encoding="utf-8") as f:
159+
nb = nbformat.read(f, as_version=4)
160+
161+
# Configure execution
162+
ep = ExecutePreprocessor(
163+
kernel_name=getKernelName(inNBName),
164+
timeout=3600,
165+
startup_timeout=180,
166+
allow_errors=False,
167+
)
168+
169+
# Run the notebook
170+
ep.preprocess(nb, {"metadata": {"path": os.path.dirname(inNBName)}})
171+
172+
# Export executed notebook
173+
with open(outNBName, "w", encoding="utf-8") as f:
174+
nbformat.write(nb, f)
175+
176+
# Compare or return success
176177
if needsCompare:
177178
return compareNotebooks(inNBName, outNBName)
178179
else:
179-
return exitStatus
180+
return 0 # success
181+
182+
shutil.rmtree(tmpDir)
180183

181184

182185
def isInputNotebookFileName(filename):
@@ -206,7 +209,5 @@ def isInputNotebookFileName(filename):
206209
except:
207210
raise ImportError("Cannot import jupyter")
208211

209-
kernelName = getKernelName(nbFileName)
210-
211-
retCode = canReproduceNotebook(nbFileName, kernelName, needsCompare)
212+
retCode = canReproduceNotebook(nbFileName, needsCompare)
212213
sys.exit(retCode)

0 commit comments

Comments
 (0)