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()

Reply via email to