Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Depend on jupyter-server only, compatibility with jupyter server >= 2, notebook < 7 #240

Merged
merged 6 commits into from
Jul 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
jupyter-packaging>=0.10
nbclassic
notebook>=5.5,<7
packaging
pytest
pytest-cov
16 changes: 14 additions & 2 deletions nbgitpuller/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from .version import __version__ # noqa
from .handlers import SyncHandler, UIHandler, LegacyInteractRedirectHandler, LegacyGitSyncRedirectHandler
from .pull import GitPuller # noqa
from notebook.utils import url_path_join
from jupyter_server.utils import url_path_join
from tornado.web import StaticFileHandler
import os

Expand Down Expand Up @@ -33,6 +32,19 @@ def _load_jupyter_server_extension(app):
- notebook: https://jupyter-notebook.readthedocs.io/en/stable/examples/Notebook/Distributing%20Jupyter%20Extensions%20as%20Python%20Packages.html#Example---Server-extension
- jupyter_server: https://jupyter-server.readthedocs.io/en/latest/developers/extensions.html
"""
# identify base handler by app class
# must do this before importing from .handlers
from ._compat import get_base_handler

get_base_handler(app)

from .handlers import (
SyncHandler,
UIHandler,
LegacyInteractRedirectHandler,
LegacyGitSyncRedirectHandler,
)

web_app = app.web_app
base_url = url_path_join(web_app.settings['base_url'], 'git-pull')
handlers = [
Expand Down
40 changes: 40 additions & 0 deletions nbgitpuller/_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""Import base Handler classes from Jupyter Server or Notebook

Must be called before importing .handlers to ensure the correct base classes
"""
import warnings

_JupyterHandler = None


def get_base_handler(app=None):
"""Get the base JupyterHandler class to use

Inferred from app class (either jupyter_server or notebook app)
"""
global _JupyterHandler
if _JupyterHandler is not None:
return _JupyterHandler
if app is None:
warnings.warn(
"Guessing base JupyterHandler class. Specify an app to ensure the right JupyterHandler is used.",
stacklevel=2,
)
from jupyter_server.base.handlers import JupyterHandler
return JupyterHandler

top_modules = {cls.__module__.split(".", 1)[0] for cls in app.__class__.mro()}
if "jupyter_server" in top_modules:
from jupyter_server.base.handlers import JupyterHandler

_JupyterHandler = JupyterHandler
return _JupyterHandler
if "notebook" in top_modules:
from notebook.base.handlers import IPythonHandler

_JupyterHandler = IPythonHandler
return _JupyterHandler

warnings.warn(f"Failed to detect base JupyterHandler class for {app}.", stacklevel=2)
from jupyter_server.base.handlers import JupyterHandler
return JupyterHandler
12 changes: 7 additions & 5 deletions nbgitpuller/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import traceback
import urllib.parse

from notebook.base.handlers import IPythonHandler
import threading
import json
import os
Expand All @@ -11,14 +10,17 @@

from .pull import GitPuller
from .version import __version__
from ._compat import get_base_handler

JupyterHandler = get_base_handler()


jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(
os.path.join(os.path.dirname(__file__), 'templates')
),
)

class SyncHandler(IPythonHandler):
class SyncHandler(JupyterHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

Expand Down Expand Up @@ -132,7 +134,7 @@ def pull():
self.git_lock.release()


class UIHandler(IPythonHandler):
class UIHandler(JupyterHandler):
@web.authenticated
async def get(self):
app_env = os.getenv('NBGITPULLER_APP', default='notebook')
Expand Down Expand Up @@ -169,7 +171,7 @@ async def get(self):
await self.flush()


class LegacyGitSyncRedirectHandler(IPythonHandler):
class LegacyGitSyncRedirectHandler(JupyterHandler):
"""
The /git-pull endpoint was previously exposed /git-sync.

Expand All @@ -185,7 +187,7 @@ async def get(self):
self.redirect(new_url)


class LegacyInteractRedirectHandler(IPythonHandler):
class LegacyInteractRedirectHandler(JupyterHandler):
"""
The /git-pull endpoint was previously exposed /interact.

Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
author='Peter Veerman, YuviPanda',
author_email='[email protected]',
cmdclass=cmdclass,
description='Notebook Extension to do one-way synchronization of git repositories',
description='Jupyter Extension to do one-way synchronization of git repositories',
long_description=open('README.md').read(),
long_description_content_type='text/markdown',
packages=find_packages(),
include_package_data=True,
platforms='any',
install_requires=['notebook>=5.5.0', 'jupyter_server>=1.10.1', 'tornado'],
install_requires=['jupyter_server>=1.10.1', 'tornado'],
data_files=[
('etc/jupyter/jupyter_server_config.d', ['nbgitpuller/etc/jupyter_server_config.d/nbgitpuller.json']),
('etc/jupyter/jupyter_notebook_config.d', ['nbgitpuller/etc/jupyter_notebook_config.d/nbgitpuller.json'])
Expand Down
17 changes: 17 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,23 @@ def test_clone_default(jupyterdir, jupyter_server):
assert os.path.isdir(os.path.join(target_path, '.git'))


def test_clone_auth(jupyterdir, jupyter_server):
"""
Tests use of 'repo' and 'branch' parameters.
"""
with Remote() as remote, Pusher(remote) as pusher:
pusher.push_file('README.md', 'Testing some content')
print(f'path: {remote.path}')
params = {
'repo': remote.path,
'branch': 'master',
'token': 'wrong',
}
r = request_api(params)
# no token, redirect to login
assert r.code == 302


def test_clone_targetpath(jupyterdir, jupyter_server):
"""
Tests use of 'targetpath' parameter.
Expand Down