Skip to content

Commit

Permalink
Merge pull request #656 from vidartf/nb6
Browse files Browse the repository at this point in the history
Add notebook 6 server extension support (w/tests)
  • Loading branch information
vidartf committed Apr 22, 2023
2 parents 9fbfd46 + df0353a commit 691b9c8
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 113 deletions.
42 changes: 33 additions & 9 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ jobs:
python -m pip install jupyterlab~=3.0
npm install -g codecov
- name: Use Node.js 14.x
- name: Use Node.js 18.x
uses: actions/setup-node@v1
with:
node-version: 14.x
node-version: 18.x
- name: Get npm cache directory
id: npm-cache-dir
run: |
Expand All @@ -75,11 +75,21 @@ jobs:
CI: true
python:
name: Python
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
max-parallel: 4
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
os: [ubuntu-latest]
include:
- python-version: '3.11'
jupyter_server-version: '<2'
- python-version: '3.11'
jupyter_server-version: '>=2'
- python-version: '3.7'
os: windows-latest
- python-version: '3.11'
os: windows-latest

steps:
- uses: actions/checkout@v2
Expand All @@ -95,16 +105,30 @@ jobs:
${{ runner.os }}-pip-
- name: Install dependencies
run: |
export NODE_OPTIONS="--openssl-legacy-provider"
python -m pip install codecov
python -m pip install --upgrade pip
python -m pip install jupyterlab~=3.0
python -m pip install --upgrade --upgrade-strategy=eager ".[test]"
- name: Test with pytest
python -m pip install jupyter_server${{ matrix.jupyter_server-version }}
- name: Test with pytest (Linux)
if: startsWith(matrix.os, 'ubuntu')
run: |
git config --global user.email CI@fake.com
git config --global user.name "CI"
pushd $(mktemp -d)
tmpdir=$(mktemp -d)
echo "TEST_TMPDIR=$tmpdir" >> $GITHUB_ENV
pushd $tmpdir
py.test -l --cov-report xml --cov=nbdime --pyargs nbdime
codecov
popd
- name: Test with pytest (Windows)
if: startsWith(matrix.os, 'windows')
run: |
git config --global user.email CI@fake.com
git config --global user.name "CI"
$hgconfig = "[ui]`r`nusername = CI <CI@fake.com>"
$hgconfig | Set-Content ($HOME + "\mercurial.ini")
echo "TEST_TMPDIR=." >> $Env:GITHUB_ENV
py.test -l --cov-report xml --cov=nbdime --pyargs nbdime
- uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
directory: ${{ env.TEST_TMPDIR }}
55 changes: 0 additions & 55 deletions appveyor.yml

This file was deleted.

7 changes: 4 additions & 3 deletions nbdime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

from functools import partial
from ._version import __version__

from .diffing import diff, diff_notebooks
from .patching import patch, patch_notebook
from .merging import merge_notebooks, decide_merge, apply_decisions


def load_jupyter_server_extension(nb_server_app):
def _load_jupyter_server_extension(nb_server_app, nb6_entrypoint=False):
# Wrap this here to avoid pulling in webapp in a normal run
from .webapp.nb_server_extension import _load_jupyter_server_extension
_load_jupyter_server_extension(nb_server_app)
_load_jupyter_server_extension(nb_server_app, nb6_entrypoint=nb6_entrypoint)


_load_jupyter_server_extension = load_jupyter_server_extension
load_jupyter_server_extension = partial(_load_jupyter_server_extension, nb6_entrypoint=True)


def _jupyter_server_extension_paths():
Expand Down
21 changes: 13 additions & 8 deletions nbdime/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def git_repo(tmpdir, request, filespath, needs_git, slow):
save_cwd = os.getcwd()
os.chdir(repo)
request.addfinalizer(lambda: os.chdir(save_cwd))
call('git init'.split())
call('git init -b master'.split())

# setup base branch
src = filespath
Expand Down Expand Up @@ -131,7 +131,7 @@ def git_repo2(tmpdir, request, filespath, needs_git, slow):
save_cwd = os.getcwd()
os.chdir(repo)
request.addfinalizer(lambda: os.chdir(save_cwd))
call('git init'.split())
call('git init -b master'.split())

# setup base branch
src = filespath
Expand Down Expand Up @@ -457,14 +457,11 @@ def create_server_extension_config(tmpdir_factory, cmd):
return str(path)


# TODO: Add back 'notebook' as param when NB 7.0 is out ?
@fixture(scope='module', params=('jupyter_server',))
@fixture(scope='module', params=('jupyter_server', 'notebook'))
def server_extension_app(tmpdir_factory, request):
cmd = request.param

if cmd == 'notebook':
token_config_location = 'NotebookApp'
else:
def _get_version(pkg):
v = None
try:
from importlib.metadata import version
Expand All @@ -473,7 +470,15 @@ def server_extension_app(tmpdir_factory, request):
import pkg_resources
v = pkg_resources.get_distribution('jupyter_server').version
from packaging import version
if version.parse(v).major >= 2:
return version.parse(v)

if cmd == 'notebook':
token_config_location = 'NotebookApp'
if _get_version('notebook').major <= 6 and _get_version('jupyter_server').major >= 2:
skip('Do not test with notebook<=6 + jupyter_server>=2')
else:
from packaging import version
if _get_version('jupyter_server').major >= 2:
token_config_location = 'IdentityProvider'
else:
token_config_location = 'ServerApp'
Expand Down
43 changes: 38 additions & 5 deletions nbdime/webapp/nb_server_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,27 @@

from jupyter_server.utils import url_path_join, to_os_path, ensure_async

generic_checkpoint_mixin_types = []
file_checkpoint_mixin_types = []

from jupyter_server.services.contents.checkpoints import GenericCheckpointsMixin
from jupyter_server.services.contents.filecheckpoints import FileCheckpoints
try:
from jupyter_server.services.contents.checkpoints import GenericCheckpointsMixin as jpserver_GenericCheckpointsMixin
from jupyter_server.services.contents.filecheckpoints import FileCheckpoints as jpserver_FileCheckpoints
generic_checkpoint_mixin_types.append(jpserver_GenericCheckpointsMixin)
file_checkpoint_mixin_types.append(jpserver_FileCheckpoints)
except ModuleNotFoundError:
pass

try:
from notebook.services.contents.checkpoints import GenericCheckpointsMixin as nbserver_GenericCheckpointsMixin
from notebook.services.contents.filecheckpoints import FileCheckpoints as nbserver_FileCheckpoints
generic_checkpoint_mixin_types.append(nbserver_GenericCheckpointsMixin)
file_checkpoint_mixin_types.append(nbserver_FileCheckpoints)
except ModuleNotFoundError:
pass

generic_checkpoint_mixin_types = tuple(generic_checkpoint_mixin_types)
file_checkpoint_mixin_types = tuple(file_checkpoint_mixin_types)


from tornado.web import HTTPError, escape, authenticated, gen
Expand Down Expand Up @@ -151,11 +169,11 @@ async def _get_checkpoint_notebooks(self, base):
return remote_nb, remote_nb
self.log.debug('Checkpoints: %r', checkpoints)
checkpoint = checkpoints[0]
if isinstance(cm.checkpoints, GenericCheckpointsMixin):
if isinstance(cm.checkpoints, generic_checkpoint_mixin_types):
checkpoint_model = await ensure_async(
cm.checkpoints.get_notebook_checkpoint(checkpoint, base))
base_nb = checkpoint_model['content']
elif isinstance(cm.checkpoints, FileCheckpoints):
elif isinstance(cm.checkpoints, file_checkpoint_mixin_types):
path = await ensure_async(
cm.checkpoints.checkpoint_path(checkpoint['id'], base))
base_nb = read_notebook(path, on_null='minimal')
Expand Down Expand Up @@ -292,13 +310,28 @@ def post(self):
self.finish(data)


def _load_jupyter_server_extension(nb_server_app):
def _load_jupyter_server_extension(nb_server_app, nb6_entrypoint=False):
"""
Called when the extension is loaded.
Args:
nb_server_app (NotebookWebApplication): handle to the Notebook webserver instance.
"""
if nb6_entrypoint:
# We're using the old notebook 6 extenstion entry point
# In this case, we only support jupyter_server < 2, so fail if >=2
from jupyter_server._version import __version__
try:
from packaging.version import parse, Version
if parse(__version__) >= Version('2.0.0'):
nb_server_app.log.critical(
"You must use Jupyter Server v1 to load nbdime as a classic notebook server extension. "
f"You have v{__version__} installed.\nYou can fix this by executing:\n"
" pip install -U \"jupyter-server<2.0.0\""
)
return
except Exception: # noqa
pass
web_app = nb_server_app.web_app

env = web_app.settings['jinja2_env']
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
"devDependencies": {
"@jupyterlab/buildutils": "^3.0.0",
"lerna": "^4.0.0",
"rimraf": "^2.6.3"
"rimraf": "^5.0.0"
}
}
12 changes: 6 additions & 6 deletions packages/labextension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,25 @@
},
"license": "BSD-3-Clause",
"author": "Project Jupyter",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"files": [
"lib/*.js",
"lib/*.js.map",
"lib/*.d.ts",
"style/*.css",
"schema/*.json"
],
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"scripts": {
"build": "npm run build:lib && npm run build:labextension",
"build:dev": "npm run build:lib && jupyter labextension build --development True .",
"build:labextension": "npm run build:labextension:source && npm run build:labextension:prebuilt",
"build:labextension:source": "rimraf dist && mkdirp dist && cd dist && npm pack ..",
"build:labextension:prebuilt": "rimraf ../../nbdime/labextension && mkdirp ../../nbdime/labextension && jupyter labextension build .",
"build:labextension:source": "rimraf dist && mkdirp dist && cd dist && npm pack ..",
"build:lib": "tsc --build",
"clean": "npm run clean:lib && npm run clean:labextension",
"clean:lib": "rimraf tsconfig.tsbuildinfo lib",
"clean:labextension": "rimraf ../../nbdime/labextension",
"clean:lib": "rimraf tsconfig.tsbuildinfo lib",
"prepublishOnly": "npm run build",
"update": "rimraf node_modules/nbdime && npm install && npm run build",
"watch": "tsc --build --watch"
Expand All @@ -60,8 +60,8 @@
"@jupyterlab/builder": "^3.0.0",
"@jupyterlab/docregistry": "^2 || ^3",
"@lumino/commands": "^1.6.1",
"mkdirp": "^0.5.1",
"rimraf": "^2.6.3",
"mkdirp": "^3.0.0",
"rimraf": "^5.0.0",
"typescript": "^4.9.0"
},
"jupyterlab": {
Expand Down
3 changes: 2 additions & 1 deletion packages/nbdime/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ tsOptions["rootDir"] = null;
tsOptions["inlineSourceMap"] = true;

module.exports = {
testEnvironment: 'jsdom',
automock: false,
moduleNameMapper: {
'\\.(css|less|sass|scss)$': 'identity-obj-proxy',
Expand All @@ -16,7 +17,7 @@ module.exports = {
setupFiles: ['<rootDir>/test/jest-setup-files.js'],
testPathIgnorePatterns: ['/lib/', '/node_modules/'],
testRegex: '/test/src/.*.spec.ts$',
transformIgnorePatterns: ['/node_modules/(?!((@jupyterlab|y-protocols|lib0)/.*))'],
transformIgnorePatterns: ['/node_modules/(?!((@jupyterlab|y-protocols|yjs|@jupyter/ydoc|lib0)/.*))'],
globals: {
'ts-jest': {
tsconfig: tsOptions
Expand Down
15 changes: 8 additions & 7 deletions packages/nbdime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,17 @@
"@babel/preset-env": "^7.5.0",
"@jupyterlab/apputils": "^2 || ^3",
"@lumino/messaging": "^1.2.2",
"@types/jest": "^29.5.0",
"@types/json-stable-stringify": "^1.0.32",
"@types/jest": "^26.0.0",
"@types/node": "^14.14.13",
"@types/node": "^18.15.0",
"@types/sanitizer": "^0.0.28",
"fs-extra": "^8.1.0",
"fs-extra": "^11.1.1",
"identity-obj-proxy": "^3.0.0",
"jest": "^26.0.0",
"jest-fetch-mock": "^1.6.6",
"ts-jest": "^26.0.0",
"rimraf": "^2.6.3",
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"jest-fetch-mock": "^3.0.3",
"rimraf": "^5.0.0",
"ts-jest": "^29.1.0",
"typescript": "^4.9.0"
},
"peerDependencies": {
Expand Down
1 change: 1 addition & 0 deletions packages/nbdime/test/jest-setup-files.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
global.fetch = require('jest-fetch-mock');
global.crypto = require('crypto');

0 comments on commit 691b9c8

Please sign in to comment.