Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-nbclient for openSUSE:Factory checked in at 2024-04-02 16:40:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-nbclient (Old) and /work/SRC/openSUSE:Factory/.python-nbclient.new.1905 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-nbclient" Tue Apr 2 16:40:40 2024 rev:32 rq:1163579 version:0.10.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-nbclient/python-nbclient.changes 2024-03-07 18:32:38.616158912 +0100 +++ /work/SRC/openSUSE:Factory/.python-nbclient.new.1905/python-nbclient.changes 2024-04-02 16:41:14.858655535 +0200 @@ -1,0 +2,7 @@ +Fri Mar 29 18:45:22 UTC 2024 - Ben Greiner <c...@bnavigator.de> + +- Update to 0.10.0 + * Optionally write out executed notebook in jupyter-execute #307 + (@wpk-nist-gov) + +------------------------------------------------------------------- Old: ---- nbclient-0.9.0.tar.gz New: ---- nbclient-0.10.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-nbclient.spec ++++++ --- /var/tmp/diff_new_pack.aMSITW/_old 2024-04-02 16:41:15.402675583 +0200 +++ /var/tmp/diff_new_pack.aMSITW/_new 2024-04-02 16:41:15.402675583 +0200 @@ -32,7 +32,7 @@ %endif Name: python-nbclient%{psuffix} -Version: 0.9.0 +Version: 0.10.0 Release: 0 Summary: A client library for executing notebooks License: BSD-3-Clause @@ -62,7 +62,7 @@ BuildRequires: %{python_module ipywidgets} BuildRequires: %{python_module nbclient = %{version}} BuildRequires: %{python_module nbconvert >= 7} -BuildRequires: %{python_module pytest >= 7} +BuildRequires: %{python_module pytest >= 7 with %python-pytest < 8} BuildRequires: %{python_module pytest-asyncio} BuildRequires: %{python_module testpath} BuildRequires: %{python_module xmltodict} ++++++ nbclient-0.9.0.tar.gz -> nbclient-0.10.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/PKG-INFO new/nbclient-0.10.0/PKG-INFO --- old/nbclient-0.9.0/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: nbclient -Version: 0.9.0 +Version: 0.10.0 Summary: A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor. Project-URL: Documentation, https://nbclient.readthedocs.io Project-URL: Funding, https://numfocus.org/ @@ -74,7 +74,7 @@ Requires-Dist: nbconvert>=7.0.0; extra == 'test' Requires-Dist: pytest-asyncio; extra == 'test' Requires-Dist: pytest-cov>=4.0; extra == 'test' -Requires-Dist: pytest>=7.0; extra == 'test' +Requires-Dist: pytest<8,>=7.0; extra == 'test' Requires-Dist: testpath; extra == 'test' Requires-Dist: xmltodict; extra == 'test' Description-Content-Type: text/markdown diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/nbclient/_version.py new/nbclient-0.10.0/nbclient/_version.py --- old/nbclient-0.9.0/nbclient/_version.py 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/nbclient/_version.py 2020-02-02 01:00:00.000000000 +0100 @@ -2,7 +2,7 @@ import re from typing import List, Union -__version__ = "0.9.0" +__version__ = "0.10.0" # Build up version_info tuple for backwards compatibility pattern = r"(?P<major>\d+).(?P<minor>\d+).(?P<patch>\d+)(?P<rest>.*)" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/nbclient/cli.py new/nbclient-0.10.0/nbclient/cli.py --- old/nbclient-0.9.0/nbclient/cli.py 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/nbclient/cli.py 2020-02-02 01:00:00.000000000 +0100 @@ -2,9 +2,9 @@ from __future__ import annotations import logging -import pathlib import sys import typing +from pathlib import Path from textwrap import dedent import nbformat @@ -22,6 +22,7 @@ "timeout": "NbClientApp.timeout", "startup_timeout": "NbClientApp.startup_timeout", "kernel_name": "NbClientApp.kernel_name", + "output": "NbClientApp.output_base", } nbclient_flags: dict[str, typing.Any] = { @@ -33,6 +34,14 @@ }, "Errors are ignored and execution is continued until the end of the notebook.", ), + "inplace": ( + { + "NbClientApp": { + "inplace": True, + }, + }, + "Overwrite input notebook with executed results.", + ), } @@ -98,6 +107,29 @@ """ ), ).tag(config=True) + inplace = Bool( + False, + help=dedent( + """ + Default is execute notebook without writing the newly executed notebook. + If this flag is provided, the newly generated notebook will + overwrite the input notebook. + """ + ), + ).tag(config=True) + output_base = Unicode( + None, + allow_none=True, + help=dedent( + """ + Write executed notebook to this file base name. + Supports pattern replacements ``'{notebook_name}'``, + the name of the input notebook file without extension. + Note that output is always relative to the parent directory of the + input notebook. + """ + ), + ).tag(config=True) @default("log_level") def _log_level_default(self) -> int: @@ -115,6 +147,15 @@ if not self.notebooks: sys.exit(-1) + # If output, must have single notebook + if len(self.notebooks) > 1 and self.output_base is not None: + if "{notebook_name}" not in self.output_base: + msg = ( + "If passing multiple notebooks with `--output=output` option, " + "output string must contain {notebook_name}" + ) + raise ValueError(msg) + # Loop and run them one by one for path in self.notebooks: self.run_notebook(path) @@ -136,16 +177,27 @@ # Log it self.log.info(f"Executing {notebook_path}") - name = notebook_path.replace(".ipynb", "") + input_path = Path(notebook_path).with_suffix(".ipynb") # Get its parent directory so we can add it to the $PATH - path = pathlib.Path(notebook_path).parent.absolute() + path = input_path.parent.absolute() - # Set the input file paths - input_path = f"{name}.ipynb" + # Optional output of executed notebook + if self.inplace: + output_path = input_path + elif self.output_base: + output_path = input_path.parent.joinpath( + self.output_base.format(notebook_name=input_path.with_suffix("").name) + ).with_suffix(".ipynb") + else: + output_path = None + + if output_path and not output_path.parent.is_dir(): + msg = f"Cannot write to directory={output_path.parent} that does not exist" + raise ValueError(msg) # Open up the notebook we're going to run - with open(input_path) as f: + with input_path.open() as f: nb = nbformat.read(f, as_version=4) # Configure nbclient to run the notebook @@ -162,5 +214,10 @@ # Run it client.execute() + # Save it + if output_path: + self.log.info(f"Save executed results to {output_path}") + nbformat.write(nb, output_path) + main = NbClientApp.launch_instance diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/nbclient/client.py new/nbclient-0.10.0/nbclient/client.py --- old/nbclient-0.9.0/nbclient/client.py 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/nbclient/client.py 2020-02-02 01:00:00.000000000 +0100 @@ -1206,7 +1206,7 @@ data = content["data"] if self.store_widget_state and "state" in data: # ignore custom msg'es self.widget_state.setdefault(content["comm_id"], {}).update(data["state"]) - if "buffer_paths" in data and data["buffer_paths"]: + if data.get("buffer_paths"): comm_id = content["comm_id"] if comm_id not in self.widget_buffers: self.widget_buffers[comm_id] = {} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/pyproject.toml new/nbclient-0.10.0/pyproject.toml --- old/nbclient-0.9.0/pyproject.toml 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/pyproject.toml 2020-02-02 01:00:00.000000000 +0100 @@ -50,7 +50,7 @@ "nbconvert>=7.0.0", "pytest-asyncio", "pytest-cov>=4.0", - "pytest>=7.0", + "pytest>=7.0,<8", "testpath", "xmltodict", ] @@ -109,7 +109,10 @@ detached = true dependencies = ["pre-commit"] [tool.hatch.envs.lint.scripts] -build = "pre-commit run --all-files ruff" +build = [ + "pre-commit run --all-files ruff", + "pre-commit run --all-files ruff-format" +] [tool.hatch.envs.typing] dependencies = [ "pre-commit"] @@ -163,7 +166,6 @@ files = "nbclient" python_version = "3.8" strict = true -show_error_codes = true enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] warn_unreachable = true @@ -176,7 +178,6 @@ ignore_missing_imports = true [tool.ruff] -target-version = "py38" line-length = 100 [tool.ruff.lint] @@ -197,6 +198,7 @@ # S101 Use of `assert` detected "tests/*" = ["S101"] "nbclient/client.py" = ["S101"] +"*.ipynb" = ["B", "E402", "T201", "F821", "A001", "E722", "S110", "RUF001"] [tool.interrogate] ignore-init-module=true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/tests/files/Autokill.ipynb new/nbclient-0.10.0/tests/files/Autokill.ipynb --- old/nbclient-0.9.0/tests/files/Autokill.ipynb 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/tests/files/Autokill.ipynb 2020-02-02 01:00:00.000000000 +0100 @@ -8,6 +8,7 @@ "source": [ "import os\n", "import signal\n", + "\n", "pid = os.getpid()\n", "os.kill(pid, signal.SIGTERM)" ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' "old/nbclient-0.9.0/tests/files/Check History in Memory.ipynb" "new/nbclient-0.10.0/tests/files/Check History in Memory.ipynb" --- "old/nbclient-0.9.0/tests/files/Check History in Memory.ipynb" 2020-02-02 01:00:00.000000000 +0100 +++ "new/nbclient-0.10.0/tests/files/Check History in Memory.ipynb" 2020-02-02 01:00:00.000000000 +0100 @@ -18,7 +18,7 @@ "outputs": [], "source": [ "ip = get_ipython()\n", - "assert ip.history_manager.hist_file == ':memory:'" + "assert ip.history_manager.hist_file == \":memory:\"" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' "old/nbclient-0.9.0/tests/files/Clear Output.ipynb" "new/nbclient-0.10.0/tests/files/Clear Output.ipynb" --- "old/nbclient-0.9.0/tests/files/Clear Output.ipynb" 2020-02-02 01:00:00.000000000 +0100 +++ "new/nbclient-0.10.0/tests/files/Clear Output.ipynb" 2020-02-02 01:00:00.000000000 +0100 @@ -6,7 +6,6 @@ "metadata": {}, "outputs": [], "source": [ - "from __future__ import print_function\n", "from IPython.display import clear_output" ] }, @@ -53,7 +52,7 @@ } ], "source": [ - "print(\"Hello world\", end='')\n", + "print(\"Hello world\", end=\"\")\n", "clear_output(wait=True) # no output after this" ] }, @@ -71,9 +70,9 @@ } ], "source": [ - "print(\"Hello\", end='')\n", + "print(\"Hello\", end=\"\")\n", "clear_output(wait=True) # here we have new output after wait=True\n", - "print(\"world\", end='')" + "print(\"world\", end=\"\")" ] }, { @@ -120,7 +119,7 @@ "metadata": {}, "outputs": [], "source": [ - "handle1.update('world')" + "handle1.update(\"world\")" ] }, { @@ -169,7 +168,7 @@ "source": [ "handle4 = display(\"Hello\", display_id=\"id4\")\n", "clear_output(wait=True)\n", - "print('world', end='')" + "print(\"world\", end=\"\")" ] }, { @@ -178,7 +177,7 @@ "metadata": {}, "outputs": [], "source": [ - "handle4.update('Hello world') # it is cleared, so it should not show up in the above cell" + "handle4.update(\"Hello world\") # it is cleared, so it should not show up in the above cell" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/tests/files/Error.ipynb new/nbclient-0.10.0/tests/files/Error.ipynb --- old/nbclient-0.9.0/tests/files/Error.ipynb 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/tests/files/Error.ipynb 2020-02-02 01:00:00.000000000 +0100 @@ -19,7 +19,7 @@ } ], "source": [ - "0/0" + "0 / 0" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' "old/nbclient-0.9.0/tests/files/Inline Image.ipynb" "new/nbclient-0.10.0/tests/files/Inline Image.ipynb" --- "old/nbclient-0.9.0/tests/files/Inline Image.ipynb" 2020-02-02 01:00:00.000000000 +0100 +++ "new/nbclient-0.10.0/tests/files/Inline Image.ipynb" 2020-02-02 01:00:00.000000000 +0100 @@ -186,7 +186,7 @@ } ], "source": [ - "Image('python.png')" + "Image(\"python.png\")" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/tests/files/Interrupt.ipynb new/nbclient-0.10.0/tests/files/Interrupt.ipynb --- old/nbclient-0.9.0/tests/files/Interrupt.ipynb 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/tests/files/Interrupt.ipynb 2020-02-02 01:00:00.000000000 +0100 @@ -1,49 +1,49 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "ename": "KeyboardInterrupt", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m<ipython-input-1-31d18a52bf41>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mwhile\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;32mcontinue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mKeyboardInterrupt\u001b[0m: " - ] - } - ], - "source": [ - "while True: continue" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "done\n" - ] - } - ], - "source": [ - "print(\"done\")" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 0 -} + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-1-31d18a52bf41>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mwhile\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;32mcontinue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "while True: continue" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "done\n" + ] + } + ], + "source": [ + "print(\"done\")" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 0 + } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/tests/files/JupyterWidgets.ipynb new/nbclient-0.10.0/tests/files/JupyterWidgets.ipynb --- old/nbclient-0.9.0/tests/files/JupyterWidgets.ipynb 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/tests/files/JupyterWidgets.ipynb 2020-02-02 01:00:00.000000000 +0100 @@ -22,7 +22,8 @@ ], "source": [ "import ipywidgets\n", - "label = ipywidgets.Label('Hello World')\n", + "\n", + "label = ipywidgets.Label(\"Hello World\")\n", "display(label)" ] }, @@ -33,7 +34,7 @@ "outputs": [], "source": [ "# it should also handle custom msg'es\n", - "label.send({'msg': 'Hello'})" + "label.send({\"msg\": \"Hello\"})" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' "old/nbclient-0.9.0/tests/files/Other Comms.ipynb" "new/nbclient-0.10.0/tests/files/Other Comms.ipynb" --- "old/nbclient-0.9.0/tests/files/Other Comms.ipynb" 2020-02-02 01:00:00.000000000 +0100 +++ "new/nbclient-0.10.0/tests/files/Other Comms.ipynb" 2020-02-02 01:00:00.000000000 +0100 @@ -25,7 +25,7 @@ }, "outputs": [], "source": [ - "comm = create_comm('this-comm-tests-a-missing-handler', data={'id': 'foo'})" + "comm = create_comm(\"this-comm-tests-a-missing-handler\", data={\"id\": \"foo\"})" ] }, { @@ -39,7 +39,7 @@ }, "outputs": [], "source": [ - "comm.send(data={'id': 'bar'})" + "comm.send(data={\"id\": \"bar\"})" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/tests/files/Output.ipynb new/nbclient-0.10.0/tests/files/Output.ipynb --- old/nbclient-0.9.0/tests/files/Output.ipynb 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/tests/files/Output.ipynb 2020-02-02 01:00:00.000000000 +0100 @@ -23,6 +23,7 @@ "source": [ "import ipywidgets as widgets\n", "from IPython.display import clear_output\n", + "\n", "output1 = widgets.Output()\n", "output1" ] @@ -78,6 +79,7 @@ ], "source": [ "import ipywidgets as widgets\n", + "\n", "output2 = widgets.Output()\n", "output2" ] @@ -124,6 +126,7 @@ ], "source": [ "import ipywidgets as widgets\n", + "\n", "output3 = widgets.Output()\n", "output3" ] @@ -171,6 +174,7 @@ ], "source": [ "import ipywidgets as widgets\n", + "\n", "output4 = widgets.Output()\n", "output4" ] @@ -217,6 +221,7 @@ ], "source": [ "import ipywidgets as widgets\n", + "\n", "output5 = widgets.Output()\n", "output5" ] @@ -229,7 +234,7 @@ "source": [ "print(\"hi5\")\n", "with output5:\n", - " display(\"hello world\") # this is not a stream but plain text\n", + " display(\"hello world\") # this is not a stream but plain text\n", "clear_output()" ] }, @@ -255,6 +260,7 @@ ], "source": [ "import ipywidgets as widgets\n", + "\n", "output_outer = widgets.Output()\n", "output_inner = widgets.Output()\n", "output_inner" @@ -291,10 +297,10 @@ "outputs": [], "source": [ "with output_inner:\n", - " print('in inner')\n", + " print(\"in inner\")\n", " with output_outer:\n", - " print('in outer')\n", - " print('also in inner')" + " print(\"in outer\")\n", + " print(\"also in inner\")" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' "old/nbclient-0.9.0/tests/files/Parallel Execute A.ipynb" "new/nbclient-0.10.0/tests/files/Parallel Execute A.ipynb" --- "old/nbclient-0.9.0/tests/files/Parallel Execute A.ipynb" 2020-02-02 01:00:00.000000000 +0100 +++ "new/nbclient-0.10.0/tests/files/Parallel Execute A.ipynb" 2020-02-02 01:00:00.000000000 +0100 @@ -20,7 +20,6 @@ "source": [ "import os\n", "import os.path\n", - "import tempfile\n", "import time" ] }, @@ -31,11 +30,11 @@ "outputs": [], "source": [ "# the variable this_notebook is injectected in a cell above by the test framework.\n", - "this_notebook = 'A'\n", - "other_notebook = 'B'\n", - "directory = os.environ['NBEXECUTE_TEST_PARALLEL_TMPDIR']\n", - "with open(os.path.join(directory, 'test_file_{}.txt'.format(this_notebook)), 'w') as f:\n", - " f.write('Hello from {}'.format(this_notebook))" + "this_notebook = \"A\"\n", + "other_notebook = \"B\"\n", + "directory = os.environ[\"NBEXECUTE_TEST_PARALLEL_TMPDIR\"]\n", + "with open(os.path.join(directory, f\"test_file_{this_notebook}.txt\"), \"w\") as f:\n", + " f.write(f\"Hello from {this_notebook}\")" ] }, { @@ -47,16 +46,16 @@ "start = time.time()\n", "timeout = 5\n", "end = start + timeout\n", - "target_file = os.path.join(directory, 'test_file_{}.txt'.format(other_notebook))\n", + "target_file = os.path.join(directory, f\"test_file_{other_notebook}.txt\")\n", "while time.time() < end:\n", " time.sleep(0.1)\n", " if os.path.exists(target_file):\n", - " with open(target_file, 'r') as f:\n", + " with open(target_file) as f:\n", " text = f.read()\n", - " if text == 'Hello from {}'.format(other_notebook):\n", + " if text == f\"Hello from {other_notebook}\":\n", " break\n", "else:\n", - " assert False, \"Timed out â didn't get a message from {}\".format(other_notebook)" + " assert False, f\"Timed out â didn't get a message from {other_notebook}\"" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' "old/nbclient-0.9.0/tests/files/Parallel Execute B.ipynb" "new/nbclient-0.10.0/tests/files/Parallel Execute B.ipynb" --- "old/nbclient-0.9.0/tests/files/Parallel Execute B.ipynb" 2020-02-02 01:00:00.000000000 +0100 +++ "new/nbclient-0.10.0/tests/files/Parallel Execute B.ipynb" 2020-02-02 01:00:00.000000000 +0100 @@ -20,7 +20,6 @@ "source": [ "import os\n", "import os.path\n", - "import tempfile\n", "import time" ] }, @@ -31,11 +30,11 @@ "outputs": [], "source": [ "# the variable this_notebook is injectected in a cell above by the test framework.\n", - "this_notebook = 'B'\n", - "other_notebook = 'A'\n", - "directory = os.environ['NBEXECUTE_TEST_PARALLEL_TMPDIR']\n", - "with open(os.path.join(directory, 'test_file_{}.txt'.format(this_notebook)), 'w') as f:\n", - " f.write('Hello from {}'.format(this_notebook))" + "this_notebook = \"B\"\n", + "other_notebook = \"A\"\n", + "directory = os.environ[\"NBEXECUTE_TEST_PARALLEL_TMPDIR\"]\n", + "with open(os.path.join(directory, f\"test_file_{this_notebook}.txt\"), \"w\") as f:\n", + " f.write(f\"Hello from {this_notebook}\")" ] }, { @@ -47,16 +46,16 @@ "start = time.time()\n", "timeout = 5\n", "end = start + timeout\n", - "target_file = os.path.join(directory, 'test_file_{}.txt'.format(other_notebook))\n", + "target_file = os.path.join(directory, f\"test_file_{other_notebook}.txt\")\n", "while time.time() < end:\n", " time.sleep(0.1)\n", " if os.path.exists(target_file):\n", - " with open(target_file, 'r') as f:\n", + " with open(target_file) as f:\n", " text = f.read()\n", - " if text == 'Hello from {}'.format(other_notebook):\n", + " if text == f\"Hello from {other_notebook}\":\n", " break\n", "else:\n", - " assert False, \"Timed out â didn't get a message from {}\".format(other_notebook)" + " assert False, f\"Timed out â didn't get a message from {other_notebook}\"" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/tests/files/SVG.ipynb new/nbclient-0.10.0/tests/files/SVG.ipynb --- old/nbclient-0.9.0/tests/files/SVG.ipynb 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/tests/files/SVG.ipynb 2020-02-02 01:00:00.000000000 +0100 @@ -35,10 +35,12 @@ } ], "source": [ - "SVG(data='''\n", + "SVG(\n", + " data=\"\"\"\n", "<svg height=\"100\" width=\"100\">\n", " <circle cx=\"50\" cy=\"50\" r=\"40\" stroke=\"black\" stroke-width=\"2\" fill=\"red\" />\n", - "</svg>''')" + "</svg>\"\"\"\n", + ")" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' "old/nbclient-0.9.0/tests/files/Skip Exceptions with Cell Tags.ipynb" "new/nbclient-0.10.0/tests/files/Skip Exceptions with Cell Tags.ipynb" --- "old/nbclient-0.9.0/tests/files/Skip Exceptions with Cell Tags.ipynb" 2020-02-02 01:00:00.000000000 +0100 +++ "new/nbclient-0.10.0/tests/files/Skip Exceptions with Cell Tags.ipynb" 2020-02-02 01:00:00.000000000 +0100 @@ -1,92 +1,92 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "tags": [ - "raises-exception" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "hello\n" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "tags": [ + "raises-exception" + ] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "hello\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "errorred\n" + ] + }, + { + "ename": "Exception", + "evalue": "message", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[1], line 5\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124merrorred\u001b[39m\u001b[38;5;124m\"\u001b[39m, file\u001b[38;5;241m=\u001b[39msys\u001b[38;5;241m.\u001b[39mstderr)\n\u001b[1;32m 4\u001b[0m \u001b[38;5;66;03m# üñîçøâé\u001b[39;00m\n\u001b[0;32m----> 5\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmessage\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[0;31mException\u001b[0m: message" + ] + } + ], + "source": [ + "import sys\n", + "print(\"hello\")\n", + "print(\"errorred\", file=sys.stderr)\n", + "# üñîçøâé\n", + "raise Exception(\"message\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ok\n" + ] + } + ], + "source": [ + "print('ok')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.9" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "errorred\n" - ] - }, - { - "ename": "Exception", - "evalue": "message", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[1], line 5\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124merrorred\u001b[39m\u001b[38;5;124m\"\u001b[39m, file\u001b[38;5;241m=\u001b[39msys\u001b[38;5;241m.\u001b[39mstderr)\n\u001b[1;32m 4\u001b[0m \u001b[38;5;66;03m# üñîçøâé\u001b[39;00m\n\u001b[0;32m----> 5\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmessage\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "\u001b[0;31mException\u001b[0m: message" - ] - } - ], - "source": [ - "import sys\n", - "print(\"hello\")\n", - "print(\"errorred\", file=sys.stderr)\n", - "# üñîçøâé\n", - "raise Exception(\"message\")" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ok\n" - ] - } - ], - "source": [ - "print('ok')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.10.9" - }, - "widgets": { - "application/vnd.jupyter.widget-state+json": { - "state": {}, - "version_major": 2, - "version_minor": 0 + "nbformat": 4, + "nbformat_minor": 4 } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' "old/nbclient-0.9.0/tests/files/Skip Exceptions.ipynb" "new/nbclient-0.10.0/tests/files/Skip Exceptions.ipynb" --- "old/nbclient-0.9.0/tests/files/Skip Exceptions.ipynb" 2020-02-02 01:00:00.000000000 +0100 +++ "new/nbclient-0.10.0/tests/files/Skip Exceptions.ipynb" 2020-02-02 01:00:00.000000000 +0100 @@ -40,7 +40,7 @@ } ], "source": [ - "print('ok')" + "print(\"ok\")" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' "old/nbclient-0.9.0/tests/files/Skip Execution with Cell Tag.ipynb" "new/nbclient-0.10.0/tests/files/Skip Execution with Cell Tag.ipynb" --- "old/nbclient-0.9.0/tests/files/Skip Execution with Cell Tag.ipynb" 2020-02-02 01:00:00.000000000 +0100 +++ "new/nbclient-0.10.0/tests/files/Skip Execution with Cell Tag.ipynb" 2020-02-02 01:00:00.000000000 +0100 @@ -3,32 +3,32 @@ { "cell_type": "code", "execution_count": null, - "source": [ - "print(\"a long running cell\")" - ], - "outputs": [], "metadata": { "tags": [ "skip-execution" ] - } + }, + "outputs": [], + "source": [ + "print(\"a long running cell\")" + ] }, { "cell_type": "code", "execution_count": 1, - "source": [ - "print('ok')" - ], + "metadata": {}, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "ok\n" ] } ], - "metadata": {} + "source": [ + "print(\"ok\")" + ] } ], "metadata": {}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/tests/files/Sleep1s.ipynb new/nbclient-0.10.0/tests/files/Sleep1s.ipynb --- old/nbclient-0.9.0/tests/files/Sleep1s.ipynb 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/tests/files/Sleep1s.ipynb 2020-02-02 01:00:00.000000000 +0100 @@ -6,8 +6,8 @@ "metadata": {}, "outputs": [], "source": [ - "import time\n", - "import datetime" + "import datetime\n", + "import time" ] }, { @@ -27,8 +27,8 @@ "metadata": {}, "outputs": [], "source": [ - "time_format = '%Y-%m-%dT%H:%M:%S.%fZ'\n", - "print(t0.strftime(time_format), end='')" + "time_format = \"%Y-%m-%dT%H:%M:%S.%fZ\"\n", + "print(t0.strftime(time_format), end=\"\")" ] }, { @@ -37,7 +37,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(t1.strftime(time_format), end='')" + "print(t1.strftime(time_format), end=\"\")" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/tests/files/Unicode.ipynb new/nbclient-0.10.0/tests/files/Unicode.ipynb --- old/nbclient-0.9.0/tests/files/Unicode.ipynb 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/tests/files/Unicode.ipynb 2020-02-02 01:00:00.000000000 +0100 @@ -11,12 +11,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "\u2603\n" + "â\n" ] } ], "source": [ - "print('\u2603')" + "print(\"â\")" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/tests/files/UnicodePy3.ipynb new/nbclient-0.10.0/tests/files/UnicodePy3.ipynb --- old/nbclient-0.9.0/tests/files/UnicodePy3.ipynb 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/tests/files/UnicodePy3.ipynb 2020-02-02 01:00:00.000000000 +0100 @@ -11,12 +11,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "\u2603\n" + "â\n" ] } ], "source": [ - "print('\u2603')" + "print(\"â\")" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/tests/files/update-display-id.ipynb new/nbclient-0.10.0/tests/files/update-display-id.ipynb --- old/nbclient-0.9.0/tests/files/update-display-id.ipynb 2020-02-02 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/tests/files/update-display-id.ipynb 2020-02-02 01:00:00.000000000 +0100 @@ -12,18 +12,19 @@ "\n", "from IPython.display import display\n", "\n", + "\n", "def display_with_id(obj, display_id, update=False, execute_result=False):\n", " iopub = ip.kernel.iopub_socket\n", " session = get_ipython().kernel.session\n", " data, md = ip.display_formatter.format(obj)\n", - " transient = {'display_id': str(display_id)}\n", - " content = {'data': data, 'metadata': md, 'transient': transient}\n", + " transient = {\"display_id\": str(display_id)}\n", + " content = {\"data\": data, \"metadata\": md, \"transient\": transient}\n", " if execute_result:\n", - " msg_type = 'execute_result'\n", - " content['execution_count'] = ip.execution_count\n", + " msg_type = \"execute_result\"\n", + " content[\"execution_count\"] = ip.execution_count\n", " else:\n", - " msg_type = 'update_display_data' if update else 'display_data'\n", - " session.send(iopub, msg_type, content, parent=ip.parent_header)\n" + " msg_type = \"update_display_data\" if update else \"display_data\"\n", + " session.send(iopub, msg_type, content, parent=ip.parent_header)" ] }, { @@ -60,9 +61,9 @@ } ], "source": [ - "display('above')\n", - "display_with_id(1, 'here')\n", - "display('below')" + "display(\"above\")\n", + "display_with_id(1, \"here\")\n", + "display(\"below\")" ] }, { @@ -99,9 +100,9 @@ } ], "source": [ - "display_with_id(2, 'here')\n", - "display_with_id(3, 'there')\n", - "display_with_id(4, 'here')" + "display_with_id(2, \"here\")\n", + "display_with_id(3, \"there\")\n", + "display_with_id(4, \"here\")" ] }, { @@ -120,8 +121,8 @@ } ], "source": [ - "display_with_id(5, 'there')\n", - "display_with_id(6, 'there', update=True)" + "display_with_id(5, \"there\")\n", + "display_with_id(6, \"there\", update=True)" ] }, { @@ -150,9 +151,9 @@ } ], "source": [ - "display_with_id(7, 'here')\n", - "display_with_id(8, 'here', update=True)\n", - "display_with_id(9, 'result', execute_result=True)" + "display_with_id(7, \"here\")\n", + "display_with_id(8, \"here\", update=True)\n", + "display_with_id(9, \"result\", execute_result=True)" ] }, { @@ -163,7 +164,7 @@ }, "outputs": [], "source": [ - "display_with_id(10, 'result', update=True)" + "display_with_id(10, \"result\", update=True)" ] } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbclient-0.9.0/tests/test_cli.py new/nbclient-0.10.0/tests/test_cli.py --- old/nbclient-0.9.0/tests/test_cli.py 1970-01-01 01:00:00.000000000 +0100 +++ new/nbclient-0.10.0/tests/test_cli.py 2020-02-02 01:00:00.000000000 +0100 @@ -0,0 +1,178 @@ +from pathlib import Path +from subprocess import CalledProcessError, check_output +from unittest.mock import call, mock_open, patch + +import pytest + +from nbclient.cli import NbClientApp + +current_dir = Path(__file__).parent.absolute() + + +@pytest.fixture() +def jupyterapp(): + with patch("nbclient.cli.JupyterApp.initialize") as mocked: + yield mocked + + +@pytest.fixture() +def client(): + with patch("nbclient.cli.NotebookClient", autospec=True) as mocked: + yield mocked + + +@pytest.fixture() +def writer(): + with patch("nbformat.write", autospec=True) as mocked: + yield mocked + + +@pytest.fixture() +def reader(): + with patch("nbformat.read", autospec=True, return_value="nb") as mocked: + yield mocked + + +@pytest.fixture() +def path_open(): + opener = mock_open() + + def mocked_open(self, *args, **kwargs): + return opener(self, *args, **kwargs) + + with patch("nbclient.cli.Path.open", mocked_open): + yield opener + + +@pytest.mark.parametrize( + "input_names", [("Other Comms",), ("Other Comms.ipynb",), ("Other Comms", "HelloWorld.ipynb")] +) +@pytest.mark.parametrize("relative", [False, True]) +@pytest.mark.parametrize("inplace", [False, True]) +def test_mult(input_names, relative, inplace, jupyterapp, client, reader, writer, path_open): + paths = [current_dir / "files" / name for name in input_names] + if relative: + paths = [p.relative_to(Path.cwd()) for p in paths] + + c = NbClientApp(notebooks=[str(p) for p in paths], kernel_name="python3", inplace=inplace) + c.initialize() + + # add suffix if needed + paths = [p.with_suffix(".ipynb") for p in paths] + + assert path_open.mock_calls[::3] == [call(p) for p in paths] + assert reader.call_count == len(paths) + # assert reader.mock_calls == [call(p, as_version=4) for p in paths] + + expected = [] + for p in paths: + expected.extend( + [ + call( + "nb", + timeout=c.timeout, + startup_timeout=c.startup_timeout, + skip_cells_with_tag=c.skip_cells_with_tag, + allow_errors=c.allow_errors, + kernel_name=c.kernel_name, + resources={"metadata": {"path": p.parent.absolute()}}, + ), + call().execute(), + ] + ) + + assert client.mock_calls == expected + + if inplace: + assert writer.mock_calls == [call("nb", p) for p in paths] + else: + writer.assert_not_called() + + +@pytest.mark.parametrize( + "input_names", [("Other Comms",), ("Other Comms.ipynb",), ("Other Comms", "HelloWorld.ipynb")] +) +@pytest.mark.parametrize("relative", [False, True]) +@pytest.mark.parametrize("output_base", ["thing", "thing.ipynb", "{notebook_name}-new.ipynb"]) +def test_output(input_names, relative, output_base, jupyterapp, client, reader, writer, path_open): + paths = [current_dir / "files" / name for name in input_names] + if relative: + paths = [p.relative_to(Path.cwd()) for p in paths] + + c = NbClientApp( + notebooks=[str(p) for p in paths], kernel_name="python3", output_base=output_base + ) + + if len(paths) != 1 and "{notebook_name}" not in output_base: + with pytest.raises(ValueError) as e: + c.initialize() + assert "If passing multiple" in str(e.value) + return + + c.initialize() + + # add suffix if needed + paths = [p.with_suffix(".ipynb") for p in paths] + + assert path_open.mock_calls[::3] == [call(p) for p in paths] + assert reader.call_count == len(paths) + + expected = [] + for p in paths: + expected.extend( + [ + call( + "nb", + timeout=c.timeout, + startup_timeout=c.startup_timeout, + skip_cells_with_tag=c.skip_cells_with_tag, + allow_errors=c.allow_errors, + kernel_name=c.kernel_name, + resources={"metadata": {"path": p.parent.absolute()}}, + ), + call().execute(), + ] + ) + + assert client.mock_calls == expected + + assert writer.mock_calls == [ + call( + "nb", + (p.parent / output_base.format(notebook_name=p.with_suffix("").name)).with_suffix( + ".ipynb" + ), + ) + for p in paths + ] + + +def test_bad_output_dir(jupyterapp, client, reader, writer, path_open): + input_names = ["Other Comms"] + output_base = "thing/thing" + + paths = [current_dir / "files" / name for name in input_names] + + c = NbClientApp( + notebooks=[str(p) for p in paths], kernel_name="python3", output_base=output_base + ) + + with pytest.raises(ValueError) as e: + c.initialize() + + assert "Cannot write to directory" in str(e.value) + + +# simple runner from command line +def test_cli_simple(): + path = current_dir / "files" / "Other Comms" + + with pytest.raises(CalledProcessError): + check_output(["jupyter-execute", "--output", "thing/thing", str(path)]) # noqa: S603, S607 + + +def test_no_notebooks(jupyterapp): + c = NbClientApp(notebooks=[], kernel_name="python3") + + with pytest.raises(SystemExit): + c.initialize()