From 74f419185b7ebbbcc04e99e2b9ae90f89ac0edb1 Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 07:20:54 -0700 Subject: [PATCH 01/15] Initial version of pure python conversion script --- examples/makejnb.py | 71 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/examples/makejnb.py b/examples/makejnb.py index 0d7a715f3..0090d0a1d 100755 --- a/examples/makejnb.py +++ b/examples/makejnb.py @@ -15,12 +15,81 @@ import nbformat from nbconvert.preprocessors import ExecutePreprocessor +from py2jn.tools import py_string_to_notebook, write_notebook + try: import ray except ImportError: raise RuntimeError("The ray package is required to run this script") + +def py_file_to_string(src): + """Preprocess example script file and return result as a string.""" + + with open(src, "r") as srcfile: + # Drop header comment + for line in srcfile: + if line[0] != "#": + break # assume first non-comment line is a newline that can be dropped + # Insert notebook plot config after last import + lines = [] + import_seen = False + for line in srcfile: + line = re.sub('^r"""', '"""', line) # remove r from r""" + line = re.sub(":cite:`([^`]+)`", r'', line) # fix cite format + if import_seen: + # Once an import statement has been seen, break on encountering a line that + # is neither an import statement not a newline + if not re.match(r"(^import|^from|^\n$)", line): + lines.append(line) + break + else: + # Set flag indicating that an import statement has been seen once one has + # been encountered + if re.match("^(import|from)", line): + import_seen = True + lines.append(line) + # Backtrack through list of lines to find last import statement + n = 1 + for line in lines[-2::-1]: + if re.match("^(import|from)", line): + break + else: + n += 1 + # Insert notebook plotting config directly after last import statement + lines.insert(-n, "plot.config_notebook_plotting()\n") + + # Process remainder of source file + for line in srcfile: + if re.match("^input", line): # end processing when input statement encountered + break + line = re.sub('^r"""', '"""', line) # remove r from r""" + line = re.sub(":cite:\`([^`]+)\`", r'', line) # fix cite format + lines.append(line) + + # Backtrack through list of lines to remove trailing newlines + n = 0 + for line in lines[::-1]: + if re.match("^\n$", line): + n += 1 + else: + break + lines = lines[0:-n] + + return "".join(lines) + + +def script_to_notebook(src, dst): + """Convert a Python example script into a Jupyter notebook.""" + + str = py_file_to_string(src) + nb = py_string_to_notebook(str) + write_notebook(nb, dst) + + + + if sys.argv[1:]: # Script names specified on command line scriptnames = [os.path.basename(s) for s in sys.argv[1:]] @@ -49,7 +118,7 @@ nb = Path("notebooks") / (s.stem + ".ipynb") if not nb.is_file() or s.stat().st_mtime > nb.stat().st_mtime: # Make notebook file - os.popen(f"./pytojnb.sh {s} {nb}") + script_to_notebook(s, nb) # Add it to the list for execution notebooks.append(nb) if sys.argv[1:]: From b25f7816016b4756d172aa353288aab73549d6ed Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 12:03:37 -0700 Subject: [PATCH 02/15] Improve script capabilities --- examples/makejnb.py | 91 ++++++++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 30 deletions(-) diff --git a/examples/makejnb.py b/examples/makejnb.py index 0090d0a1d..25fccb0cb 100755 --- a/examples/makejnb.py +++ b/examples/makejnb.py @@ -4,17 +4,19 @@ # create/update and execute any Jupyter notebooks that are out # of date with respect to their source Python scripts. If script # names specified on command line, process them instead. -# Run as -# python makejnb.py [script_name_1 [script_name_2 [...]]] +# Run +# python makejnb.py -h +# for usage details. +import argparse import os import re import sys from pathlib import Path +from timeit import default_timer as timer import nbformat from nbconvert.preprocessors import ExecutePreprocessor - from py2jn.tools import py_string_to_notebook, write_notebook try: @@ -23,7 +25,6 @@ raise RuntimeError("The ray package is required to run this script") - def py_file_to_string(src): """Preprocess example script file and return result as a string.""" @@ -88,11 +89,38 @@ def script_to_notebook(src, dst): write_notebook(nb, dst) +def execute_notebook(fname): + """Execute the specified notebook file.""" + + with open(fname) as f: + nb = nbformat.read(f, as_version=4) + ep = ExecutePreprocessor() + try: + t0 = timer() + out = ep.preprocess(nb) + t1 = timer() + with open(fname, "w", encoding="utf-8") as f: + nbformat.write(nb, f) + except CellExecutionError: + raise Exception(f"Error executing the notebook {fname}") + print(f"{fname} done in {t1 - t0} s") + + + +argparser = argparse.ArgumentParser( + description="Convert Python example scripts to Jupyter notebooks." +) +argparser.add_argument("--no-exec", action="store_true", + help="Create/update notebooks but don't execute them") +argparser.add_argument("--no-ray", action="store_true", + help="Execute notebooks serially, without the use of ray parallelization") +argparser.add_argument("filename", nargs="*", help="Optional Python example script filenames") +args = argparser.parse_args() -if sys.argv[1:]: +if args.filename: # Script names specified on command line - scriptnames = [os.path.basename(s) for s in sys.argv[1:]] + scriptnames = [os.path.basename(s) for s in args.filename] else: # Read script names from index file scriptnames = [] @@ -109,6 +137,8 @@ def script_to_notebook(src, dst): # Construct script paths scripts = [Path("scripts") / Path(s) for s in scriptnames] +# Display status information +print(f"Processing scripts {','.join(scriptnames)}") # Construct list of notebooks that are out of date with respect to the corresponding # script, or that have not yet been constructed from the corresponding script, and @@ -121,36 +151,37 @@ def script_to_notebook(src, dst): script_to_notebook(s, nb) # Add it to the list for execution notebooks.append(nb) -if sys.argv[1:]: +if args.filename: # If scripts specified on command line, add all corresonding notebooks to the # list for execution notebooks = [Path("notebooks") / (s.stem + ".ipynb") for s in scripts] -ray.init() -nproc = len(notebooks) -ngpu = 0 -ar = ray.available_resources() -ncpu = max(int(ar["CPU"]) // nproc, 1) -if "GPU" in ar: - ngpu = max(int(ar["GPU"]) // nproc, 1) -print(f"Running on {ncpu} CPUs and {ngpu} GPUs per process") +# Run relevant notebooks if no excecution flag not specified +if not args.no_exec: -# Function to execute each notebook with one GPU -@ray.remote(num_cpus=ncpu, num_gpus=ngpu) -def run_nb(fname): - with open(fname) as f: - nb = nbformat.read(f, as_version=4) + # Execute notebooks serially if not requested to avoid use of ray + if args.no_ray: - ep = ExecutePreprocessor() - try: - out = ep.preprocess(nb) - with open(fname, "w", encoding="utf-8") as f: - nbformat.write(nb, f) - except CellExecutionError: - raise Exception(f"Error executing the notebook {fname}") - print(f"{fname} done") + for nbfile in notebooks: + execute_notebook(nbfile) + + # Execute notebooks in parallel using ray + else: + ray.init() + + nproc = len(notebooks) + ngpu = 0 + ar = ray.available_resources() + ncpu = max(int(ar["CPU"]) // nproc, 1) + if "GPU" in ar: + ngpu = max(int(ar["GPU"]) // nproc, 1) + print(f"Running on {ncpu} CPUs and {ngpu} GPUs per process") + # Function to execute each notebook with available resources suitably divided + @ray.remote(num_cpus=ncpu, num_gpus=ngpu) + def ray_run_nb(fname): + execute_notebook(fname) -# run all; blocking -ray.get([run_nb.remote(_) for _ in notebooks]) + # Execute relevant notebooks in parallel + ray.get([ray_run_nb.remote(nbfile) for nbfile in notebooks]) From c11bfbcfb9ecb00868fb5b79c27678290a0e161e Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 12:04:19 -0700 Subject: [PATCH 03/15] Manually run black --- examples/makejnb.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/makejnb.py b/examples/makejnb.py index 25fccb0cb..5f9e14a3f 100755 --- a/examples/makejnb.py +++ b/examples/makejnb.py @@ -106,14 +106,17 @@ def execute_notebook(fname): print(f"{fname} done in {t1 - t0} s") - argparser = argparse.ArgumentParser( description="Convert Python example scripts to Jupyter notebooks." ) -argparser.add_argument("--no-exec", action="store_true", - help="Create/update notebooks but don't execute them") -argparser.add_argument("--no-ray", action="store_true", - help="Execute notebooks serially, without the use of ray parallelization") +argparser.add_argument( + "--no-exec", action="store_true", help="Create/update notebooks but don't execute them" +) +argparser.add_argument( + "--no-ray", + action="store_true", + help="Execute notebooks serially, without the use of ray parallelization", +) argparser.add_argument("filename", nargs="*", help="Optional Python example script filenames") args = argparser.parse_args() From 8f5aa879153843b9acfd1fb9eed43863d2ec2919 Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 12:12:59 -0700 Subject: [PATCH 04/15] Minor improvement --- examples/makejnb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/makejnb.py b/examples/makejnb.py index 5f9e14a3f..eca33a753 100755 --- a/examples/makejnb.py +++ b/examples/makejnb.py @@ -103,7 +103,7 @@ def execute_notebook(fname): nbformat.write(nb, f) except CellExecutionError: raise Exception(f"Error executing the notebook {fname}") - print(f"{fname} done in {t1 - t0} s") + print(f"{fname} done in {(t1 - t0):.1e} s") argparser = argparse.ArgumentParser( From ea3a92d3b7c4ca231f61ae532538f5f7cb40ee7c Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 12:26:29 -0700 Subject: [PATCH 05/15] Improve control flow logic --- examples/makejnb.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/examples/makejnb.py b/examples/makejnb.py index eca33a753..d25a0fa7d 100755 --- a/examples/makejnb.py +++ b/examples/makejnb.py @@ -141,23 +141,21 @@ def execute_notebook(fname): scripts = [Path("scripts") / Path(s) for s in scriptnames] # Display status information -print(f"Processing scripts {','.join(scriptnames)}") +print(f"Processing scripts {', '.join(scriptnames)}") -# Construct list of notebooks that are out of date with respect to the corresponding -# script, or that have not yet been constructed from the corresponding script, and -# construct/update each of them +# Convert scripts to corresponding notebooks and create list of new/modified notebooks. notebooks = [] for s in scripts: nb = Path("notebooks") / (s.stem + ".ipynb") - if not nb.is_file() or s.stat().st_mtime > nb.stat().st_mtime: + # If scripts specified on command line, convert all of them. Otherwise, only + # convert scripts that have a newer timestamp than their corresponding notebooks, + # or that have not previously been converted (i.e. corresponding notebook file + # does not exist). + if args.filename or not nb.is_file() or s.stat().st_mtime > nb.stat().st_mtime: # Make notebook file script_to_notebook(s, nb) # Add it to the list for execution notebooks.append(nb) -if args.filename: - # If scripts specified on command line, add all corresonding notebooks to the - # list for execution - notebooks = [Path("notebooks") / (s.stem + ".ipynb") for s in scripts] # Run relevant notebooks if no excecution flag not specified From 183791b26800b901c31b75c4f3c34385454a90fa Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 12:28:17 -0700 Subject: [PATCH 06/15] Typo fix --- examples/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Makefile b/examples/Makefile index 2b9571f25..4ec03d164 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,4 +1,4 @@ -# Makefile for Jypyter notebooks +# Makefile for Jupyter notebooks # To rebuild the notebooks without executing them, do # make [target] fast From 2d904fd0daf94d30374c81f73c009b4505048e24 Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 12:29:45 -0700 Subject: [PATCH 07/15] Update notes on tools in examples directory --- examples/README.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/examples/README.rst b/examples/README.rst index 69cf9f3fa..42f5c72d9 100644 --- a/examples/README.rst +++ b/examples/README.rst @@ -46,11 +46,5 @@ A number of files in this directory assist in the mangement of the usage example `makeindex.py `_ Auto-generate the docs example index ``docs/source/examples.rst`` from the example scripts index ``scripts/index.rst``. -`Makefile `_ - A makefile allowing use of the command ``make`` to update auto-generated Jupyter notebooks. Run as ``make no-execute=true`` to update the notebooks without executing them. Use of `makejnb.py` rather than this makefile is recommended. - -`pytojnb.sh `_ - Low-level python to Jupyter notebook conversion script. Used by both the makefile and `makejnb.py `_. - `scriptcheck.sh `_ Run all example scripts with a reduced number of iterations as a rapid check that they are functioning correctly. From 885f38933378b71870861377ce7b717767ca7d02 Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 12:30:05 -0700 Subject: [PATCH 08/15] Remove Makefile --- examples/Makefile | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 examples/Makefile diff --git a/examples/Makefile b/examples/Makefile deleted file mode 100644 index 4ec03d164..000000000 --- a/examples/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# Makefile for Jupyter notebooks -# To rebuild the notebooks without executing them, do -# make [target] fast - -SRCPTH = scripts -DSTPTH = notebooks -SRC = $(SRCPTH)/*.py -SRCBASE = $(shell echo $(SRC) | xargs -n 1 basename) -DSTBASE = $(SRCBASE:%.py=%.ipynb) -DST = $(shell echo $(DSTBASE) | xargs -n 1 printf "notebooks/%s ") - -.PHONY: all fast -.SUFFIXES: .py .ipynb - -all: $(DST) -fast: $(DST) - -$(DSTPTH)/%.ipynb: $(SRCPTH)/%.py -ifneq (,$(findstring fast,$(MAKECMDGOALS))) # source: https://www.gnu.org/software/make/manual/html_node/Testing-Flags.html and https://www.gnu.org/software/make/manual/html_node/Goals.html - ./pytojnb $< $@ -else - ./pytojnb $< $@ - jupyter nbconvert --to=notebook --output $(shell basename $@) --execute $@ -endif From 252568f746b88f6be28af71db00e79c38e2b0c4d Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 13:16:42 -0700 Subject: [PATCH 09/15] Fix some bugs --- examples/makejnb.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/makejnb.py b/examples/makejnb.py index d25a0fa7d..53eb5d4a8 100755 --- a/examples/makejnb.py +++ b/examples/makejnb.py @@ -38,11 +38,14 @@ def py_file_to_string(src): import_seen = False for line in srcfile: line = re.sub('^r"""', '"""', line) # remove r from r""" - line = re.sub(":cite:`([^`]+)`", r'', line) # fix cite format + line = re.sub(":cite:`([^`]+)`", r'', line) # fix cite format if import_seen: # Once an import statement has been seen, break on encountering a line that - # is neither an import statement not a newline - if not re.match(r"(^import|^from|^\n$)", line): + # is neither an import statement nor a newline, nor a component of an import + # statement extended over multiple lines, nor components of a try/except + # construction (note that handling of these final two cases is probably not + # very robust). + if not re.match(r"(^import|^from|^\n$|^\W+[^\W]|^\)$|^try:$|^except)", line): lines.append(line) break else: From 6ac0de6e41818051c94004804f1c9c24b2771679 Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 13:19:04 -0700 Subject: [PATCH 10/15] Remove bash script to notebook converter --- examples/pytojnb.sh | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100755 examples/pytojnb.sh diff --git a/examples/pytojnb.sh b/examples/pytojnb.sh deleted file mode 100755 index 784a47469..000000000 --- a/examples/pytojnb.sh +++ /dev/null @@ -1,30 +0,0 @@ -#! /bin/bash - -# Convert a Python script into a Jupyter notebook -# Run as -# pytojnb.sh - -src=$1 -dst=$2 - -tmp=$(mktemp /tmp/pytojnb.XXXXXX) -trap "rm -f $tmp" 0 2 3 15 - -# sed usage from: -# https://stackoverflow.com/questions/37909388 - -# Remove trailing input -sed '${/^input(/d;}' $src > $tmp -# Remove header comment -sed -i '1,/^$/d' $tmp -# Remove r from r""" -sed -i 's/^r"""$/"""/' $tmp -# Insert notebook plot config after last import -sed -E -i '/^(from|import)[^\n]*/,$!b;//{x;//p;g};//!H;$!d;x;s//&\nplot.config_notebook_plotting()/' $tmp -# Convert citations to nbsphinx-recognized format -sed -E -i 's/:cite:`([^`]+)`//g' $tmp - -# Convert modified script to notebook -python -m py2jn $tmp $dst - -exit 0 From 2f91069f80015e4cd916e4c204b8d79d81920f6f Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 16:49:03 -0700 Subject: [PATCH 11/15] Rename notebook build script --- examples/README.rst | 8 ++++---- examples/{makejnb.py => makenotebooks.py} | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename examples/{makejnb.py => makenotebooks.py} (99%) diff --git a/examples/README.rst b/examples/README.rst index 42f5c72d9..54766aa72 100644 --- a/examples/README.rst +++ b/examples/README.rst @@ -16,14 +16,14 @@ The procedure for adding a adding a new notebook to the documentation is: 2. Run ``makeindex.py`` to update the example scripts README file, the notebook index file, and the examples index in the docs. -3. Run ``makejnb.py`` to build the new notebook, as well as any other notebooks that are out of date with respect to their source scripts, as determined by the respective file timestamps. +3. Run ``makenotebooks.py`` to build the new notebook, as well as any other notebooks that are out of date with respect to their source scripts, as determined by the respective file timestamps. 4. Add and commit the new script, the ``scripts/index.rst`` script index file, the auto-generated ``scripts/README.rst`` file and ``docs/source/examples.rst`` index file, and the new or updated notebooks and the auto-generated ``notebooks/index.ipynb`` file in the notebooks directory (following the submodule handling procedure as described in the developer docs). The procedure for rebuilding notebook(s) after the source file(s) have been modified is: -1. Run ``makejnb.py`` to build the new notebook, as well as any other notebooks that are out of date with respect to their source scripts, as determined by the respective file timestamps. Note that timestamps for files retrieved from version control may not be meaningful for this purpose. In such cases, ``touch`` the relevant source scripts to force updating on the next run of ``makejnb.py``. +1. Run ``makenotebooks.py`` to build the new notebook, as well as any other notebooks that are out of date with respect to their source scripts, as determined by the respective file timestamps. Note that timestamps for files retrieved from version control may not be meaningful for this purpose. In such cases, ``touch`` the relevant source scripts to force updating on the next run of ``makenotebooks.py``. 2. Add and commit the modified script(s), and the updated notebooks (following the submodule handling procedure as described in the developer docs). @@ -40,8 +40,8 @@ A number of files in this directory assist in the mangement of the usage example `notebooks_requirements.txt `_ Requirements file (as used by ``pip``) listing additional dependencies for building the Jupyter notebooks from the usage example scripts. -`makejnb.py `_ - An alternative to the makefile for updating the auto-generated Jupyter notebooks. Notebooks are executed in parallel using the ``ray`` package. +`makenotebooks.py `_ + Auto-generate Jupyter notebooks from the example scripts. `makeindex.py `_ Auto-generate the docs example index ``docs/source/examples.rst`` from the example scripts index ``scripts/index.rst``. diff --git a/examples/makejnb.py b/examples/makenotebooks.py similarity index 99% rename from examples/makejnb.py rename to examples/makenotebooks.py index 53eb5d4a8..6e5a97c84 100755 --- a/examples/makejnb.py +++ b/examples/makenotebooks.py @@ -5,7 +5,7 @@ # of date with respect to their source Python scripts. If script # names specified on command line, process them instead. # Run -# python makejnb.py -h +# python makenotebooks.py -h # for usage details. import argparse From 00677b05f7c959d49049178e3e184767c5a2b85a Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 17:05:41 -0700 Subject: [PATCH 12/15] Add flag indicating processing of all scripts --- examples/makenotebooks.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/examples/makenotebooks.py b/examples/makenotebooks.py index 6e5a97c84..960ebb226 100755 --- a/examples/makenotebooks.py +++ b/examples/makenotebooks.py @@ -112,6 +112,12 @@ def execute_notebook(fname): argparser = argparse.ArgumentParser( description="Convert Python example scripts to Jupyter notebooks." ) +argparser.add_argument( + "--all", + action="store_true", + help="Process all notebooks, without checking timestamps. " + "Has no effect when files to process are explicitly specified.", +) argparser.add_argument( "--no-exec", action="store_true", help="Create/update notebooks but don't execute them" ) @@ -150,11 +156,11 @@ def execute_notebook(fname): notebooks = [] for s in scripts: nb = Path("notebooks") / (s.stem + ".ipynb") - # If scripts specified on command line, convert all of them. Otherwise, only - # convert scripts that have a newer timestamp than their corresponding notebooks, - # or that have not previously been converted (i.e. corresponding notebook file - # does not exist). - if args.filename or not nb.is_file() or s.stat().st_mtime > nb.stat().st_mtime: + # If scripts specified on command line or --all flag specified, convert all scripts. + # Otherwise, only convert scripts that have a newer timestamp than their corresponding + # notebooks, or that have not previously been converted (i.e. corresponding notebook + # file does not exist). + if args.all or args.filename or not nb.is_file() or s.stat().st_mtime > nb.stat().st_mtime: # Make notebook file script_to_notebook(s, nb) # Add it to the list for execution From 74e5a4d8d7226201d4c6a41c2d3370d7a2c1d031 Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Thu, 18 Nov 2021 17:09:22 -0700 Subject: [PATCH 13/15] Better handling of check for ray presence --- examples/makenotebooks.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/makenotebooks.py b/examples/makenotebooks.py index 960ebb226..b367a57d9 100755 --- a/examples/makenotebooks.py +++ b/examples/makenotebooks.py @@ -21,8 +21,9 @@ try: import ray + have_ray = True except ImportError: - raise RuntimeError("The ray package is required to run this script") + have_ray = False def py_file_to_string(src): @@ -129,6 +130,10 @@ def execute_notebook(fname): argparser.add_argument("filename", nargs="*", help="Optional Python example script filenames") args = argparser.parse_args() +# Raise error if ray needed but not present +if not have_ray and not args.no_ray: + raise RuntimeError("The ray package is required to run this script") + if args.filename: # Script names specified on command line From e7b2b4b207ed6ff44c30e6e7388fab583cccc337 Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Sat, 20 Nov 2021 05:18:59 -0700 Subject: [PATCH 14/15] Minor change to avoid black reformatting --- examples/makenotebooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/makenotebooks.py b/examples/makenotebooks.py index b367a57d9..8ff009ebd 100755 --- a/examples/makenotebooks.py +++ b/examples/makenotebooks.py @@ -19,9 +19,9 @@ from nbconvert.preprocessors import ExecutePreprocessor from py2jn.tools import py_string_to_notebook, write_notebook +have_ray = True try: import ray - have_ray = True except ImportError: have_ray = False From 53dc8626c962100e21e8a835be29aaa5a6bec6a1 Mon Sep 17 00:00:00 2001 From: Brendt Wohlberg Date: Mon, 22 Nov 2021 13:29:55 -0700 Subject: [PATCH 15/15] Fix list of selected scripts --- examples/makenotebooks.py | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/examples/makenotebooks.py b/examples/makenotebooks.py index 8ff009ebd..b64fa6e3d 100755 --- a/examples/makenotebooks.py +++ b/examples/makenotebooks.py @@ -151,26 +151,36 @@ def execute_notebook(fname): # Ensure list entries are unique scriptnames = list(set(scriptnames)) -# Construct script paths -scripts = [Path("scripts") / Path(s) for s in scriptnames] - -# Display status information -print(f"Processing scripts {', '.join(scriptnames)}") - -# Convert scripts to corresponding notebooks and create list of new/modified notebooks. +# Creat list of selected scripts and corresponding notebooks. +scripts = [] notebooks = [] -for s in scripts: - nb = Path("notebooks") / (s.stem + ".ipynb") +for s in scriptnames: + sb = Path(s).stem + spath = Path("scripts") / Path(sb + ".py") + npath = Path("notebooks") / Path(sb + ".ipynb") # If scripts specified on command line or --all flag specified, convert all scripts. # Otherwise, only convert scripts that have a newer timestamp than their corresponding # notebooks, or that have not previously been converted (i.e. corresponding notebook # file does not exist). - if args.all or args.filename or not nb.is_file() or s.stat().st_mtime > nb.stat().st_mtime: - # Make notebook file - script_to_notebook(s, nb) - # Add it to the list for execution - notebooks.append(nb) + if ( + args.all + or args.filename + or not npath.is_file() + or spath.stat().st_mtime > npath.stat().st_mtime + ): + # Add to the list of selected scripts + scripts.append(spath) + # Add to the list of selected notebooks + notebooks.append(npath) + +# Display status information +print(f"Processing scripts {', '.join([os.path.basename(s) for s in scriptnames])}") +# Convert selected scripts to corresponding notebooks and create list of new/modified notebooks. +for spath in scripts: + npath = Path("notebooks") / Path(spath.stem + ".ipynb") + # Make notebook file + script_to_notebook(spath, npath) # Run relevant notebooks if no excecution flag not specified if not args.no_exec: