From 6d4cb2648f229f5684481182fc919c9e37c9c1a5 Mon Sep 17 00:00:00 2001 From: John Mount Date: Sun, 2 Jul 2023 09:11:50 -0600 Subject: [PATCH 01/10] fix JTask compasirion --- pkg/wvpy.egg-info/PKG-INFO | 7 +++---- pkg/wvpy/jtools.py | 19 ++++++++++++------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/pkg/wvpy.egg-info/PKG-INFO b/pkg/wvpy.egg-info/PKG-INFO index d81bf7a..4733bba 100644 --- a/pkg/wvpy.egg-info/PKG-INFO +++ b/pkg/wvpy.egg-info/PKG-INFO @@ -6,6 +6,9 @@ Home-page: https://github.com/WinVector/wvpy Author: John Mount Author-email: jmount@win-vector.com License: License :: OSI Approved :: BSD 3-clause License +Description: + Convert Jupyter notebooks to and from Python files. + Platform: any Classifier: Intended Audience :: Science/Research Classifier: Programming Language :: Python @@ -21,7 +24,3 @@ Classifier: License :: OSI Approved :: BSD License Description-Content-Type: text/markdown Provides-Extra: pdf_export Provides-Extra: code_format -License-File: LICENSE - - -Convert Jupyter notebooks to and from Python files. diff --git a/pkg/wvpy/jtools.py b/pkg/wvpy/jtools.py index e918def..9cd47f8 100644 --- a/pkg/wvpy/jtools.py +++ b/pkg/wvpy/jtools.py @@ -390,6 +390,9 @@ def render_as_html( print(f'\tdone render_as_html "{html_name}" {datetime.datetime.now()}') +_jtask_comparison_attributes = [ + "sheet_name", "output_suffix", "exclude_input", "init_code", "path_prefix"] + @total_ordering class JTask: def __init__( @@ -457,7 +460,7 @@ def __eq__(self, other): return NotImplemented if str(type(self)) != str(type(other)): return False - for v in ["sheet_name", "output_suffix", "exclude_input", "init_code", "path_prefix"]: + for v in _jtask_comparison_attributes: if self[v] != other[v]: return False return True @@ -467,20 +470,22 @@ def __lt__(self, other): return NotImplemented if str(type(self)) < str(type(other)): return True - for v in ["sheet_name", "output_suffix", "exclude_input", "init_code", "path_prefix"]: + for v in _jtask_comparison_attributes: v_self = self[v] v_other = other[v] # can't order compare None to None - if ((v_self is None) or (v_other is None)) and ((v_self is None) != (v_other is None)): - return v_self is None - if self[v] < other[v]: - return True + if ((v_self is None) or (v_other is None)): + if ((v_self is None) != (v_other is None)): + return v_self is None + else: + if self[v] < other[v]: + return True return False def __str__(self) -> str: args_str = ",\n".join([ f" {v}= {repr(self[v])}" - for v in ["sheet_name", "output_suffix", "exclude_input", "init_code", "path_prefix"] + for v in _jtask_comparison_attributes ]) return 'JTask(\n' + args_str + ",\n)" From ae6dfb625e09ac3a470ff5520be64cbd6bcb4bcb Mon Sep 17 00:00:00 2001 From: John Mount Date: Sun, 2 Jul 2023 09:19:19 -0600 Subject: [PATCH 02/10] a bit more subtle on equality check --- pkg/wvpy/jtools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/wvpy/jtools.py b/pkg/wvpy/jtools.py index 9cd47f8..361cdbc 100644 --- a/pkg/wvpy/jtools.py +++ b/pkg/wvpy/jtools.py @@ -457,7 +457,7 @@ def _is_valid_operand(self, other): def __eq__(self, other): if not self._is_valid_operand(other): - return NotImplemented + return False if str(type(self)) != str(type(other)): return False for v in _jtask_comparison_attributes: From 0c4cc880e172fc006deb2e63b0ddba31831eee34 Mon Sep 17 00:00:00 2001 From: John Mount Date: Sun, 2 Jul 2023 09:35:38 -0600 Subject: [PATCH 03/10] rebuild pkg --- pkg/wvpy.egg-info/PKG-INFO | 7 ++++--- pkg/wvpy.egg-info/SOURCES.txt | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/wvpy.egg-info/PKG-INFO b/pkg/wvpy.egg-info/PKG-INFO index 4733bba..d81bf7a 100644 --- a/pkg/wvpy.egg-info/PKG-INFO +++ b/pkg/wvpy.egg-info/PKG-INFO @@ -6,9 +6,6 @@ Home-page: https://github.com/WinVector/wvpy Author: John Mount Author-email: jmount@win-vector.com License: License :: OSI Approved :: BSD 3-clause License -Description: - Convert Jupyter notebooks to and from Python files. - Platform: any Classifier: Intended Audience :: Science/Research Classifier: Programming Language :: Python @@ -24,3 +21,7 @@ Classifier: License :: OSI Approved :: BSD License Description-Content-Type: text/markdown Provides-Extra: pdf_export Provides-Extra: code_format +License-File: LICENSE + + +Convert Jupyter notebooks to and from Python files. diff --git a/pkg/wvpy.egg-info/SOURCES.txt b/pkg/wvpy.egg-info/SOURCES.txt index 54ffef7..49527c3 100644 --- a/pkg/wvpy.egg-info/SOURCES.txt +++ b/pkg/wvpy.egg-info/SOURCES.txt @@ -3,6 +3,7 @@ MANIFEST.in README.txt setup.py Doc/documentation.txt +tests/test_nb_fns.py wvpy/__init__.py wvpy/jtools.py wvpy/pysheet.py From 5c5303377594b484d75711c7eb29bd5ac26d643c Mon Sep 17 00:00:00 2001 From: John Mount Date: Sun, 2 Jul 2023 10:42:48 -0600 Subject: [PATCH 04/10] add sheet_vars and tests work on comparison and string representation of JTasks --- pkg/tests/example_sheet_vars_notebook.ipynb | 53 +++++++++++++++++++++ pkg/tests/test_nb_fns.py | 48 +++++++++++++++++++ pkg/wvpy/jtools.py | 36 ++++++++++++-- 3 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 pkg/tests/example_sheet_vars_notebook.ipynb diff --git a/pkg/tests/example_sheet_vars_notebook.ipynb b/pkg/tests/example_sheet_vars_notebook.ipynb new file mode 100644 index 0000000..2a0c04e --- /dev/null +++ b/pkg/tests/example_sheet_vars_notebook.ipynb @@ -0,0 +1,53 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": true, + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "*text*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "assert sheet_vars['x'] == 7\n", + "\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/pkg/tests/test_nb_fns.py b/pkg/tests/test_nb_fns.py index 9c9c34b..f419711 100644 --- a/pkg/tests/test_nb_fns.py +++ b/pkg/tests/test_nb_fns.py @@ -49,6 +49,41 @@ def test_jupyter_notebook_good(): os.chdir(orig_wd) +def test_jupyter_notebook_sheet_vars_good(): + source_dir = os.path.dirname(os.path.realpath(__file__)) + orig_wd = os.getcwd() + os.chdir(source_dir) + try: + os.remove("example_sheet_vars_notebook.html") + except FileNotFoundError: + pass + render_as_html( + "example_sheet_vars_notebook.ipynb", + sheet_vars={'x': 7}, + ) + os.remove("example_sheet_vars_notebook.html") + # want the raised issue if not present + os.chdir(orig_wd) + + +def test_jupyter_notebook_sheet_vars_bad(): + source_dir = os.path.dirname(os.path.realpath(__file__)) + orig_wd = os.getcwd() + os.chdir(source_dir) + try: + os.remove("example_sheet_vars_notebook.html") + except FileNotFoundError: + pass + with pytest.raises(CellExecutionError): + render_as_html( + "example_sheet_vars_notebook.ipynb", + sheet_vars={'x': 4}, # wrong value! + ) + os.remove("example_sheet_vars_notebook.html") + # want the raised issue if not present + os.chdir(orig_wd) + + def test_jupyter_notebook_bad(): source_dir = os.path.dirname(os.path.realpath(__file__)) orig_wd = os.getcwd() @@ -219,3 +254,16 @@ def test_nb_convert(): res_txt = convert_notebook_code_to_py(nb) assert isinstance(res_txt, str) # TODO: compare to original text + + +def test_JTask_basics(): + t1 = JTask("example_good_notebook.ipynb", strict=False) + s1 = str(t1) + assert isinstance(s1, str) + r1 = t1.__repr__() + assert isinstance(r1, str) + t2 = JTask("example_good_notebook.ipynb", strict=False, sheet_vars={'x': 7}) + s2 = str(t2) + assert isinstance(s2, str) + r2 = t2.__repr__() + assert isinstance(r2, str) diff --git a/pkg/wvpy/jtools.py b/pkg/wvpy/jtools.py index 361cdbc..914530f 100644 --- a/pkg/wvpy/jtools.py +++ b/pkg/wvpy/jtools.py @@ -9,6 +9,8 @@ from nbconvert.preprocessors import ExecutePreprocessor from multiprocessing import Pool import sys +import pickle +import tempfile from typing import Iterable, List, Optional from functools import total_ordering @@ -287,6 +289,7 @@ def render_as_html( timeout:int = 60000, kernel_name: Optional[str] = None, verbose: bool = True, + sheet_vars = None, init_code: Optional[str] = None, exclude_input: bool = False, prompt_strip_regexp: Optional[str] = r'<\s*div\s+class\s*=\s*"jp-OutputPrompt[^<>]*>[^<>]*Out[^<>]*<\s*/div\s*>', @@ -301,7 +304,8 @@ def render_as_html( :param timeout: Maximum time in seconds each notebook cell is allowed to run. passed to nbconvert.preprocessors.ExecutePreprocessor. :param kernel_name: Jupyter kernel to use. passed to nbconvert.preprocessors.ExecutePreprocessor. - :param verbose logical, if True print while running + :param verbose logical, if True print while running + :param sheet_vars: if not None value is de-serialized as a variable named "sheet_vars" :param init_code: Python init code for first cell :param exclude_input: if True, exclude input cells :param prompt_strip_regexp: regexp to strip prompts, only used if exclude_input is True @@ -335,7 +339,19 @@ def render_as_html( nb = convert_py_code_to_notebook(text) else: raise ValueError('{ipynb_exists}: file must end with .py or .ipynb') + tmp_path = None # do the conversion + if sheet_vars is not None: + with tempfile.NamedTemporaryFile(delete=False) as ntf: + tmp_path = ntf.name + pickle.dump(sheet_vars, file=ntf) + if (init_code is None) or (len(init_code) <= 0): + init_code = "" + init_code = f""" +import pickle +with open({tmp_path.__repr__()}, 'rb') as pf: + sheet_vars = pickle.load(pf) +""" + "\n" + init_code if (init_code is not None) and (len(init_code) > 0): assert isinstance(init_code, str) nb = prepend_code_cell_to_notebook( @@ -384,6 +400,11 @@ def render_as_html( caught = ep.caught_exception except Exception as e: caught = e + if tmp_path is not None: + try: + os.remove(tmp_path) + except FileNotFoundError: + pass if caught is not None: raise caught if verbose: @@ -393,6 +414,7 @@ def render_as_html( _jtask_comparison_attributes = [ "sheet_name", "output_suffix", "exclude_input", "init_code", "path_prefix"] + @total_ordering class JTask: def __init__( @@ -401,6 +423,7 @@ def __init__( *, output_suffix: Optional[str] = None, exclude_input: bool = True, + sheet_vars = None, init_code: Optional[str] = None, path_prefix: Optional[str] = None, strict: bool = True, @@ -411,6 +434,7 @@ def __init__( :param sheet_name: name of sheet to run can be .ipynb or .py, and suffix can be omitted. :param output_suffix: optional string to append to rendered HTML file name. :param exclude_input: if True strip input cells out of HTML render. + :param sheet_vars: if not None value is de-serialized as a variable named "sheet_vars" :param init_code: optional code to insert at the top of the Jupyter sheet, used to pass parameters. :param path_prefix: optional prefix to add to sheet_name to find Jupyter source. :param strict: if True check paths path_prefix and path_prefix/sheetname[.py|.ipynb] exist. @@ -435,6 +459,7 @@ def __init__( self.sheet_name = sheet_name self.output_suffix = output_suffix self.exclude_input = exclude_input + self.sheet_vars = sheet_vars self.init_code = init_code self.path_prefix = path_prefix @@ -446,6 +471,7 @@ def render_as_html(self) -> None: path, exclude_input=self.exclude_input, output_suffix=self.output_suffix, + sheet_vars=self.sheet_vars, init_code=self.init_code, ) @@ -463,6 +489,8 @@ def __eq__(self, other): for v in _jtask_comparison_attributes: if self[v] != other[v]: return False + if str(self.sheet_vars) != str(other.sheet_vars): + return False return True def __lt__(self, other): @@ -480,12 +508,14 @@ def __lt__(self, other): else: if self[v] < other[v]: return True + if str(self.sheet_vars) < str(other.sheet_vars): + return True return False def __str__(self) -> str: args_str = ",\n".join([ - f" {v}= {repr(self[v])}" - for v in _jtask_comparison_attributes + f" {v}={repr(self[v])}" + for v in _jtask_comparison_attributes + ["sheet_vars"] ]) return 'JTask(\n' + args_str + ",\n)" From 724266d349862f30454ff2d48a59d7723a7eeb3d Mon Sep 17 00:00:00 2001 From: John Mount Date: Sun, 2 Jul 2023 10:50:46 -0600 Subject: [PATCH 05/10] more spacing and more tests --- pkg/tests/example_sheet_vars_notebook.ipynb | 2 ++ pkg/tests/test_nb_fns.py | 2 ++ pkg/wvpy/jtools.py | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/tests/example_sheet_vars_notebook.ipynb b/pkg/tests/example_sheet_vars_notebook.ipynb index 2a0c04e..7d00285 100644 --- a/pkg/tests/example_sheet_vars_notebook.ipynb +++ b/pkg/tests/example_sheet_vars_notebook.ipynb @@ -25,6 +25,8 @@ "outputs": [], "source": [ "assert sheet_vars['x'] == 7\n", + "assert y == 3\n", + "\n", "\n" ] } diff --git a/pkg/tests/test_nb_fns.py b/pkg/tests/test_nb_fns.py index f419711..cb50beb 100644 --- a/pkg/tests/test_nb_fns.py +++ b/pkg/tests/test_nb_fns.py @@ -60,6 +60,7 @@ def test_jupyter_notebook_sheet_vars_good(): render_as_html( "example_sheet_vars_notebook.ipynb", sheet_vars={'x': 7}, + init_code='y = 3', ) os.remove("example_sheet_vars_notebook.html") # want the raised issue if not present @@ -78,6 +79,7 @@ def test_jupyter_notebook_sheet_vars_bad(): render_as_html( "example_sheet_vars_notebook.ipynb", sheet_vars={'x': 4}, # wrong value! + init_code='y = 3', ) os.remove("example_sheet_vars_notebook.html") # want the raised issue if not present diff --git a/pkg/wvpy/jtools.py b/pkg/wvpy/jtools.py index 914530f..f2b2092 100644 --- a/pkg/wvpy/jtools.py +++ b/pkg/wvpy/jtools.py @@ -351,7 +351,7 @@ def render_as_html( import pickle with open({tmp_path.__repr__()}, 'rb') as pf: sheet_vars = pickle.load(pf) -""" + "\n" + init_code +""" + "\n\n" + init_code if (init_code is not None) and (len(init_code) > 0): assert isinstance(init_code, str) nb = prepend_code_cell_to_notebook( From a66a4d645b66447f8fa9de7a2fc9c6c9e2e7230d Mon Sep 17 00:00:00 2001 From: John Mount Date: Sun, 2 Jul 2023 11:13:28 -0600 Subject: [PATCH 06/10] init code before pickle code (for any user imports) --- pkg/wvpy/jtools.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/wvpy/jtools.py b/pkg/wvpy/jtools.py index f2b2092..fcaf074 100644 --- a/pkg/wvpy/jtools.py +++ b/pkg/wvpy/jtools.py @@ -347,11 +347,12 @@ def render_as_html( pickle.dump(sheet_vars, file=ntf) if (init_code is None) or (len(init_code) <= 0): init_code = "" - init_code = f""" + pickle_code = f""" import pickle with open({tmp_path.__repr__()}, 'rb') as pf: sheet_vars = pickle.load(pf) -""" + "\n\n" + init_code +""" + init_code = init_code + "\n\n" + pickle_code if (init_code is not None) and (len(init_code) > 0): assert isinstance(init_code, str) nb = prepend_code_cell_to_notebook( From fc582227e0c87be3104b3123de61b36f03b1aa32 Mon Sep 17 00:00:00 2001 From: John Mount Date: Sun, 2 Jul 2023 11:53:33 -0600 Subject: [PATCH 07/10] work on sheet vars exmaple --- examples/sheet_vars/driver_sheet.ipynb | 210 + examples/sheet_vars/task_sheet.ipynb | 45 + examples/sheet_vars/task_sheet_g1.html | 15265 +++++++++++++++++++++++ examples/sheet_vars/task_sheet_g1.png | Bin 0 -> 262737 bytes examples/sheet_vars/task_sheet_g2.html | 15265 +++++++++++++++++++++++ examples/sheet_vars/task_sheet_g2.png | Bin 0 -> 262737 bytes 6 files changed, 30785 insertions(+) create mode 100644 examples/sheet_vars/driver_sheet.ipynb create mode 100644 examples/sheet_vars/task_sheet.ipynb create mode 100644 examples/sheet_vars/task_sheet_g1.html create mode 100644 examples/sheet_vars/task_sheet_g1.png create mode 100644 examples/sheet_vars/task_sheet_g2.html create mode 100644 examples/sheet_vars/task_sheet_g2.png diff --git a/examples/sheet_vars/driver_sheet.ipynb b/examples/sheet_vars/driver_sheet.ipynb new file mode 100644 index 0000000..0ef043d --- /dev/null +++ b/examples/sheet_vars/driver_sheet.ipynb @@ -0,0 +1,210 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Example driver sheet." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from pprint import pprint\n", + "from wvpy.jtools import JTask, run_pool\n", + "import imgkit\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "tasks = [\n", + " JTask(\n", + " \"task_sheet.ipynb\",\n", + " output_suffix=\"_g1\",\n", + " sheet_vars = {\n", + " \"file_names\": [\n", + " \"fname_1.txt\",\n", + " \"fname_2.txt\",\n", + " ]},\n", + " ),\n", + " JTask(\n", + " \"task_sheet.ipynb\",\n", + " output_suffix=\"_g2\",\n", + " sheet_vars = {\n", + " \"file_names\": [\n", + " \"fname_3.txt\",\n", + " \"fname_4.txt\",\n", + " ]},\n", + " ),\n", + "]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[JTask(\n", + " sheet_name='task_sheet.ipynb',\n", + " output_suffix='_g1',\n", + " exclude_input=True,\n", + " init_code=None,\n", + " path_prefix=None,\n", + " sheet_vars={'file_names': ['fname_1.txt', 'fname_2.txt']},\n", + "),\n", + " JTask(\n", + " sheet_name='task_sheet.ipynb',\n", + " output_suffix='_g2',\n", + " exclude_input=True,\n", + " init_code=None,\n", + " path_prefix=None,\n", + " sheet_vars={'file_names': ['fname_3.txt', 'fname_4.txt']},\n", + ")]\n" + ] + } + ], + "source": [ + "pprint(tasks)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "start render_as_html \"task_sheet.ipynb\" \"_g1\" 2023-07-02 11:52:33.286698\n", + "start render_as_html \"task_sheet.ipynb\" \"_g2\" 2023-07-02 11:52:33.286955\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "This version of python seems to be incorrectly compiled\n", + "(internal generated filenames are not absolute).\n", + "This may make the debugger miss breakpoints.\n", + "Related bug: http://bugs.python.org/issue1666807\n", + "This version of python seems to be incorrectly compiled\n", + "(internal generated filenames are not absolute).\n", + "This may make the debugger miss breakpoints.\n", + "Related bug: http://bugs.python.org/issue1666807\n", + "This version of python seems to be incorrectly compiled\n", + "(internal generated filenames are not absolute).\n", + "This may make the debugger miss breakpoints.\n", + "Related bug: http://bugs.python.org/issue1666807\n", + "This version of python seems to be incorrectly compiled\n", + "(internal generated filenames are not absolute).\n", + "This may make the debugger miss breakpoints.\n", + "Related bug: http://bugs.python.org/issue1666807\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\tdone render_as_html \"task_sheet_g2.html\" 2023-07-02 11:52:35.467671\n", + "\tdone render_as_html \"task_sheet_g1.html\" 2023-07-02 11:52:35.467699\n" + ] + }, + { + "data": { + "text/plain": [ + "[None, None]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# ignore \n", + "# \"This version of python seems to be incorrectly compiled\"\n", + "# Just MacOS problems\n", + "run_pool(\n", + " tasks,\n", + " njobs=2,\n", + " verbose=False,\n", + " stop_on_error=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading page (1/2)\n", + "Rendering (2/2) \n", + "Done \n", + "Loading page (1/2)\n", + "Rendering (2/2) \n", + "Done \n" + ] + } + ], + "source": [ + "for fname in os.listdir():\n", + " if fname.startswith('task_sheet_') and fname.endswith('.html'):\n", + " imgkit.from_file(fname, fname.removesuffix('.html') + \".png\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "wvpy_dev_env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.3" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/examples/sheet_vars/task_sheet.ipynb b/examples/sheet_vars/task_sheet.ipynb new file mode 100644 index 0000000..0364951 --- /dev/null +++ b/examples/sheet_vars/task_sheet.ipynb @@ -0,0 +1,45 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Example task sheet" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pprint import pprint" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pprint(sheet_vars[\"file_names\"])" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/examples/sheet_vars/task_sheet_g1.html b/examples/sheet_vars/task_sheet_g1.html new file mode 100644 index 0000000..673de54 --- /dev/null +++ b/examples/sheet_vars/task_sheet_g1.html @@ -0,0 +1,15265 @@ + + + + + +Notebook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/sheet_vars/task_sheet_g1.png b/examples/sheet_vars/task_sheet_g1.png new file mode 100644 index 0000000000000000000000000000000000000000..64a31e5eef47c268af35e147a5835776f789352e GIT binary patch literal 262737 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 literal 0 HcmV?d00001 diff --git a/examples/sheet_vars/task_sheet_g2.html b/examples/sheet_vars/task_sheet_g2.html new file mode 100644 index 0000000..4b5d0f8 --- /dev/null +++ b/examples/sheet_vars/task_sheet_g2.html @@ -0,0 +1,15265 @@ + + + + + +Notebook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/sheet_vars/task_sheet_g2.png b/examples/sheet_vars/task_sheet_g2.png new file mode 100644 index 0000000000000000000000000000000000000000..eb47be7b09ac2e7dbc7d1600403764d43d0067cc GIT binary patch literal 262737 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 iq}MwFqVLTN(6j^J&#&BgO(|b_$f Date: Sun, 2 Jul 2023 12:09:22 -0600 Subject: [PATCH 08/10] finish example --- examples/sheet_vars/driver_sheet.ipynb | 49 ++++++----- examples/sheet_vars/task_sheet.ipynb | 31 +++++-- examples/sheet_vars/task_sheet_g1.html | 110 +++++++++++++++++++++++-- examples/sheet_vars/task_sheet_g1.png | Bin 262737 -> 1112177 bytes examples/sheet_vars/task_sheet_g2.html | 49 +++++++++-- examples/sheet_vars/task_sheet_g2.png | Bin 262737 -> 595124 bytes 6 files changed, 190 insertions(+), 49 deletions(-) diff --git a/examples/sheet_vars/driver_sheet.ipynb b/examples/sheet_vars/driver_sheet.ipynb index 0ef043d..d67a4ea 100644 --- a/examples/sheet_vars/driver_sheet.ipynb +++ b/examples/sheet_vars/driver_sheet.ipynb @@ -5,7 +5,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Example driver sheet." + "Example driver sheet.\n", + "\n", + "This can be used to run many jobs in parallel." ] }, { @@ -20,19 +22,14 @@ "import os" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ + "# define tasks, rendering the same Jupyter notebook\n", + "# with different sheet_vars values and ouput suffices.\n", "tasks = [\n", " JTask(\n", " \"task_sheet.ipynb\",\n", @@ -41,7 +38,10 @@ " \"file_names\": [\n", " \"fname_1.txt\",\n", " \"fname_2.txt\",\n", - " ]},\n", + " ],\n", + " \"sheet_group\": \"g1\",\n", + " },\n", + " exclude_input=False,\n", " ),\n", " JTask(\n", " \"task_sheet.ipynb\",\n", @@ -50,7 +50,10 @@ " \"file_names\": [\n", " \"fname_3.txt\",\n", " \"fname_4.txt\",\n", - " ]},\n", + " ],\n", + " \"sheet_group\": \"g2\",\n", + " },\n", + " exclude_input=True,\n", " ),\n", "]\n" ] @@ -67,10 +70,10 @@ "[JTask(\n", " sheet_name='task_sheet.ipynb',\n", " output_suffix='_g1',\n", - " exclude_input=True,\n", + " exclude_input=False,\n", " init_code=None,\n", " path_prefix=None,\n", - " sheet_vars={'file_names': ['fname_1.txt', 'fname_2.txt']},\n", + " sheet_vars={'file_names': ['fname_1.txt', 'fname_2.txt'], 'sheet_group': 'g1'},\n", "),\n", " JTask(\n", " sheet_name='task_sheet.ipynb',\n", @@ -78,12 +81,13 @@ " exclude_input=True,\n", " init_code=None,\n", " path_prefix=None,\n", - " sheet_vars={'file_names': ['fname_3.txt', 'fname_4.txt']},\n", + " sheet_vars={'file_names': ['fname_3.txt', 'fname_4.txt'], 'sheet_group': 'g2'},\n", ")]\n" ] } ], "source": [ + "# print our tasks\n", "pprint(tasks)" ] }, @@ -96,8 +100,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "start render_as_html \"task_sheet.ipynb\" \"_g1\" 2023-07-02 11:52:33.286698\n", - "start render_as_html \"task_sheet.ipynb\" \"_g2\" 2023-07-02 11:52:33.286955\n" + "start render_as_html \"task_sheet.ipynb\" \"_g2\" 2023-07-02 12:08:33.054926\n", + "start render_as_html \"task_sheet.ipynb\" \"_g1\" 2023-07-02 12:08:33.056136\n" ] }, { @@ -126,8 +130,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "\tdone render_as_html \"task_sheet_g2.html\" 2023-07-02 11:52:35.467671\n", - "\tdone render_as_html \"task_sheet_g1.html\" 2023-07-02 11:52:35.467699\n" + "\tdone render_as_html \"task_sheet_g2.html\" 2023-07-02 12:08:35.352744\n", + "\tdone render_as_html \"task_sheet_g1.html\" 2023-07-02 12:08:35.438916\n" ] }, { @@ -142,7 +146,8 @@ } ], "source": [ - "# ignore \n", + "# run the tasks, in parallel\n", + "# ignore warning msgs\n", "# \"This version of python seems to be incorrectly compiled\"\n", "# Just MacOS problems\n", "run_pool(\n", @@ -172,17 +177,11 @@ } ], "source": [ + "# convert HTMLs from renders to PNGs to show\n", "for fname in os.listdir():\n", " if fname.startswith('task_sheet_') and fname.endswith('.html'):\n", " imgkit.from_file(fname, fname.removesuffix('.html') + \".png\")" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/examples/sheet_vars/task_sheet.ipynb b/examples/sheet_vars/task_sheet.ipynb index 0364951..df33015 100644 --- a/examples/sheet_vars/task_sheet.ipynb +++ b/examples/sheet_vars/task_sheet.ipynb @@ -1,18 +1,23 @@ { "cells": [ { - "cell_type": "code", - "execution_count": null, + "attachments": {}, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "Example task sheet.\n", + "\n", + "Example of a single job to run. Values come in through `sheet_vars` and even optional `init_code`." + ] }, { - "attachments": {}, - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ - "Example task sheet" + "from pprint import pprint\n", + "from IPython.display import display, HTML, Markdown" ] }, { @@ -21,7 +26,15 @@ "metadata": {}, "outputs": [], "source": [ - "from pprint import pprint" + "display(HTML(f'File names assigned: {sheet_vars[\"file_names\"]}.'))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The sheet variables are the following." ] }, { @@ -30,7 +43,7 @@ "metadata": {}, "outputs": [], "source": [ - "pprint(sheet_vars[\"file_names\"])" + "pprint(sheet_vars)" ] } ], diff --git a/examples/sheet_vars/task_sheet_g1.html b/examples/sheet_vars/task_sheet_g1.html index 673de54..5898cca 100644 --- a/examples/sheet_vars/task_sheet_g1.html +++ b/examples/sheet_vars/task_sheet_g1.html @@ -15212,25 +15212,119 @@ -