Repository: m-rossi/jupyter-docx-bundler (language: python)

Issue:
Incompatibility to Jupyter notebook version 7
**Describe the bug**
Jupyter notebook [version 7] got released. Major issue seem `jupyter bundlerextension` is no longer working/needed, but is used for conda installation.


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c596f4b..ef8b6d9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -49,7 +49,7 @@ jobs:
       fail-fast: false
       matrix:
         os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
-        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
+        python-version: ['3.8', '3.9', '3.10', '3.11']
     steps:
       - uses: actions/checkout@v2
       - uses: conda-incubator/setup-miniconda@v2
@@ -82,7 +82,6 @@ jobs:
           activate-environment: test
           auto-update-conda: true
           miniforge-variant: Mambaforge
-          python-version: ${{ matrix.python-version }}
       - name: Install dependencies
         run: mamba install --yes --quiet --file requirements.txt --file requirements_test.txt pandoc=${{ matrix.pandoc-version }}
       - name: Execute pytest
@@ -90,7 +89,7 @@ jobs:
 
   conda-build:
     needs: [pytest, pytest-pandoc-versions]
-    name: conda-build (Python ${{ matrix.python-version }}, ${{ matrix.os }})
+    name: conda-build (${{ matrix.os }})
     runs-on: ${{ matrix.os }}
     defaults:
       run:
@@ -99,7 +98,6 @@ jobs:
       fail-fast: false
       matrix:
         os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
-        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
     steps:
       - uses: actions/checkout@v2
         with:
@@ -113,10 +111,10 @@ jobs:
       - name: Install conda-build
         run: mamba install --yes --quiet conda-build boa
       - name: Execute conda-build
-        run: conda mambabuild --output-folder conda-bld --python ${{ matrix.python-version }} conda.recipe
+        run: conda mambabuild --output-folder conda-bld conda.recipe
       - uses: actions/upload-artifact@v2
         with:
-          name: python-${{ matrix.python-version }}-${{ matrix.os }}
+          name: python-${{ matrix.os }}
           path: conda-bld/*/*.tar.bz2
 
   pypi-packages:
diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml
index 251f7da..a9965c4 100644
--- a/conda.recipe/meta.yaml
+++ b/conda.recipe/meta.yaml
@@ -11,28 +11,27 @@ source:
   path: ..
 
 build:
-  skip: True  # [py<36]
   script: "{{ PYTHON }} -m pip install . --no-deps -vv"
+  noarch: python
 
 requirements:
   host:
     - pip
-    - python
+    - python >=3.8
     - setuptools >=61.0
     - setuptools-scm >=6.2
   run:
-    - importlib_resources  # [py<39]
+    - importlib-resources
     - lxml
     - nbconvert >=7.0
-    - notebook >=5.0
+    - notebook >=7.0
     - pandas
     - pandoc >=2.11,<3
     - pandocfilters
     - pypandoc >=1.4
-    - python
+    - python >=3.8
     - requests
     - tabulate
-    - tornado
 
 test:
   imports:
diff --git a/conda.recipe/post-link.bat b/conda.recipe/post-link.bat
deleted file mode 100644
index 59cc143..0000000
--- a/conda.recipe/post-link.bat
+++ /dev/null
@@ -1,4 +0,0 @@
-@echo off
-(
-  "%PREFIX%\Scripts\jupyter-bundlerextension.exe" enable --py jupyter_docx_bundler --sys-prefix
-) >>"%PREFIX%\.messages.txt" 2>&1
\ No newline at end of file
diff --git a/conda.recipe/post-link.sh b/conda.recipe/post-link.sh
deleted file mode 100644
index 72e30fc..0000000
--- a/conda.recipe/post-link.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/env bash
-{
-  "${PREFIX}/bin/jupyter-bundlerextension" enable --py jupyter_docx_bundler --sys-prefix
-} >>"$PREFIX/.messages.txt" 2>&1
diff --git a/conda.recipe/pre-unlink.bat b/conda.recipe/pre-unlink.bat
deleted file mode 100644
index 9d143ba..0000000
--- a/conda.recipe/pre-unlink.bat
+++ /dev/null
@@ -1,4 +0,0 @@
-@echo off
-(
-  "%PREFIX%\Scripts\jupyter-bundlerextension" disable --py jupyter_docx_bundler  --sys-prefix
-) >>"%PREFIX%\.messages.txt" 2>&1
\ No newline at end of file
diff --git a/conda.recipe/pre-unlink.sh b/conda.recipe/pre-unlink.sh
deleted file mode 100644
index 598079c..0000000
--- a/conda.recipe/pre-unlink.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env bash
-{
-  "${PREFIX}/bin/jupyter-bundlerextension" disable --py jupyter_docx_bundler --sys-prefix
-} >>"$PREFIX/.messages.txt" 2>&1
-
diff --git a/jupyter_docx_bundler/__init__.py b/jupyter_docx_bundler/__init__.py
index 604773c..29ea10f 100644
--- a/jupyter_docx_bundler/__init__.py
+++ b/jupyter_docx_bundler/__init__.py
@@ -1,67 +1,8 @@
-import os
-from pathlib import Path
-
 from nbconvert.exporters import Exporter
-from tornado import gen
 
 from . import converters
 
 
-def _jupyter_bundlerextension_paths():
-    """ Declare bundler extensions provided by this package."""
-
-    return [
-        {
-            # unique bundler name
-            'name': 'docx_bundler',
-            # module containing bundle function
-            'module_name': 'jupyter_docx_bundler',
-            # human-redable menu item label
-            'label': 'Office Open XML (.docx)',
-            # group under 'deploy' or 'download' menu
-            'group': 'download',
-        }
-    ]  # pragma: no cover
-
-
-@gen.coroutine
-def bundle(handler, model):
-    """ Create a compressed tarball containing the notebook document.
-
-    Parameters
-    ----------
-
-    handler : tornado.web.RequestHandler
-        Handler that serviced the bundle request
-    model : dict
-        Notebook model from the configured ContentManager
-    """
-
-    # prepare notebook
-    if Path(model['path']).is_absolute():
-        notebook_path = Path(model['path']).parent
-    else:
-        notebook_path = (Path.cwd() / model['path']).parent
-    notebook_filename = os.path.basename(model['name'])
-    notebook_name = os.path.splitext(notebook_filename)[0]
-
-    # Set headers to trigger browser download
-    handler.set_header(
-        'Content-Disposition', f'attachment; filename="{os.path.basename(notebook_name)}.docx"',
-    )
-    handler.set_header(
-        'Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
-    )
-
-    # send content to handler
-    yield handler.write(
-        converters.notebookcontent_to_docxbytes(model['content'], notebook_filename, notebook_path)
-    )
-
-    # Return the buffer value as the response
-    handler.finish()
-
-
 class DocxExporter(Exporter):
     """Convert a notebook to docx
     This is the API which nbconvert calls.
diff --git a/pyproject.toml b/pyproject.toml
index e2d2704..8ad16ea 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -21,8 +21,6 @@ classifiers = [
     "License :: OSI Approved :: MIT License",
     "Operating System :: OS Independent",
     "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.6",
-    "Programming Language :: Python :: 3.7",
     "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
@@ -32,13 +30,12 @@ dependencies = [
     'importlib-resources; python_version<"3.9"',
     "lxml",
     "nbconvert>=7.0",
-    "notebook>=5.0",
+    "notebook>=7.0",
     "pandas",
     "pandocfilters",
     "pypandoc>=1.4",
     "requests",
     "tabulate",
-    "tornado",
 ]
 
 [project.entry-points."nbconvert.exporters"]
diff --git a/requirements.txt b/requirements.txt
index 6a4b194..1008276 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
 importlib_resources
 lxml
 nbconvert >= 7.0
-notebook >= 5.0
+notebook >= 7.0
 pandas
 pandocfilters
 pypandoc >= 1.4
@@ -9,4 +9,3 @@ requests
 setuptools >= 38.6.0
 setuptools-scm
 tabulate
-tornado


Test patch:
diff --git a/conda.recipe/run_test.py b/conda.recipe/run_test.py
index cf6b42d..10aec2a 100644
--- a/conda.recipe/run_test.py
+++ b/conda.recipe/run_test.py
@@ -1,25 +1,6 @@
-import os
 import sys
 
 from nbconvert import nbconvertapp
-from notebook.config_manager import BaseJSONConfigManager
-from jupyter_core.paths import jupyter_config_path
-
-
-# Check if bundler extension is enabled
-bundler_enabled = False
-config_dirs = [os.path.join(p, 'nbconfig') for p in jupyter_config_path()]
-for config_dir in config_dirs:
-    cm = BaseJSONConfigManager(config_dir=config_dir)
-    data = cm.get('notebook')
-    if 'bundlerextensions' in data:
-        for bundler_id, info in data['bundlerextensions'].items():
-            label = info.get('label')
-            module = info.get('module_name')
-            if module == 'jupyter_docx_bundler':
-                bundler_enabled = True
-if not bundler_enabled:
-    sys.exit('jupyter-dox-bundler not enabled.')
 
 
 # Check if nbconvert lists docx as available format
diff --git a/jupyter_docx_bundler/tests/test_bundler.py b/jupyter_docx_bundler/tests/test_bundler.py
index ab7ed17..91a1759 100644
--- a/jupyter_docx_bundler/tests/test_bundler.py
+++ b/jupyter_docx_bundler/tests/test_bundler.py
@@ -1,43 +1,7 @@
-from pathlib import Path
 import os
 
-from mock import patch
 from nbconvert import nbconvertapp
 import nbformat
-from nbformat import write
-from nbformat.v4 import (
-    new_notebook,
-    new_markdown_cell,
-    new_code_cell,
-    new_output,
-)
-from notebook.tests.launchnotebook import NotebookTestBase
-
-
-class BundleAPITest(NotebookTestBase):
-    @classmethod
-    def setup_class(cls):
-        super(BundleAPITest, cls).setup_class()
-        nbdir = Path(cls.notebook_dir)
-
-        nb = new_notebook()
-
-        nb.cells.append(new_markdown_cell(u'Created by test'))
-        cc1 = new_code_cell(source=u'print(2*6)')
-        cc1.outputs.append(new_output(output_type='stream', text=u'12'))
-        nb.cells.append(cc1)
-
-        with open(nbdir / 'testnb.ipynb', 'w', encoding='utf-8') as f:
-            write(nb, f, version=4)
-
-    def test_bundler_invoke(self):
-        with patch('notebook.bundler.handlers.BundlerHandler.get_bundler') as mock:
-            mock.return_value = {'module_name': 'jupyter_docx_bundler'}
-            resp = self.request(
-                'GET', 'bundle/testnb.ipynb', params={'bundler': 'jupyter_docx_bundler'}
-            )
-            mock.assert_called_with('jupyter_docx_bundler')
-        self.assertEqual(resp.status_code, 200)
 
 
 def test_jupyter_nbconvert_cli(tmpdir, download_notebook):
diff --git a/jupyter_docx_bundler/tests/test_converters.py b/jupyter_docx_bundler/tests/test_converters.py
index d363484..077b73f 100644
--- a/jupyter_docx_bundler/tests/test_converters.py
+++ b/jupyter_docx_bundler/tests/test_converters.py
@@ -37,7 +37,7 @@ def test_image_conversion(tmpdir, images_notebook):
 
     # compare number of extracted media with generated media
     media = list(Path(tmpdir / 'media').glob('**/*.*'))
-    assert images_notebook['metadata']['image_count'] == len(media),\
+    assert images_notebook['metadata']['image_count'] == len(media), \
         'Number of generated images does not match in docx-document.'
 
 
@@ -168,8 +168,8 @@ def test_pandas_html_table(tmpdir, pandas_html_table_notebook):
     df = pd.DataFrame(json.loads(pandas_html_table_notebook['metadata']['table']))
     # because of the intermediate conversion to json-string, the int-datatype is lost
     try:
-        df.index = df.index.astype('int')
-    except TypeError:
+        df.index = df.index.astype(int)
+    except ValueError:
         pass
 
     # adujst column names to those we can extract from the markdown format later