Skip to content

Refactor terminals into an ExtensionApp #2

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

Merged
merged 11 commits into from
Apr 2, 2022
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
72 changes: 0 additions & 72 deletions .github/workflows/codeql-analysis.yml

This file was deleted.

50 changes: 33 additions & 17 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ on:
push:
branches: ["main"]
pull_request:

schedule:
- cron: "0 8 * * *"

Expand Down Expand Up @@ -33,15 +34,18 @@ jobs:

test:
runs-on: ${{ matrix.os }}
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
python-version: ["3.7", "3.8", "3.9", "3.10", "pypy-3.7"]
exclude:
- os: "windows-latest"
python-version: "pypy-3.7"
- os: "macos-latest"
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.7", "3.10"]
include:
- os: windows-latest
python-version: "3.9"
- os: ubuntu-latest
python-version: "pypy-3.8"
- os: macos-latest
python-version: "3.8"
steps:
- name: Checkout
Expand All @@ -51,28 +55,40 @@ jobs:
- name: Install the Python dependencies
run: |
pip install -e ".[test]" codecov
- name: Point at Jupyter Server branch with terminals removed.
run: |
pip install -U git+https://github.com/Zsailer/jupyter_server.git@jupyter_server_terminals
- name: List installed packages
run: |
pip freeze
pip check
- name: Run the tests with Coverage
if: ${{ !startsWith(matrix.python-version, 'pypy') && !startsWith(runner.os, 'Windows') }}
run: |
pytest -vv jupyter_server_terminals --cov jupyter_server_terminals --cov-branch --cov-report term-missing:skip-covered
python -m pytest -vv --cov jupyter_server_terminals --cov-branch --cov-report term-missing:skip-covered
- name: Run the tests on pypy and Windows
if: ${{ startsWith(matrix.python-version, 'pypy') || startsWith(runner.os, 'Windows') }}
run: |
pytest -vv jupyter_server_terminals
python -m pytest -vv
- name: Coverage
if: ${{ !startsWith(matrix.python-version, 'pypy') && !startsWith(runner.os, 'Windows') }}
run: |
codecov
- name: Test full install
if: ${{ !startsWith(matrix.python-version, 'pypy') && !startsWith(runner.os, 'Windows') }}
run: |
python -m venv test_install
./test_install/bin/python -m pip install -U pip
./test_install/bin/python -m pip install ".[test]"
pushd test_install
./bin/pytest --pyargs jupyter_server_terminals
popd

make_sdist:
name: Make SDist
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- uses: jupyterlab/maintainer-tools/.github/actions/make-sdist@v1

# test_sdist:
# runs-on: ubuntu-latest
# needs: [make_sdist]
# name: Install from SDist and Test
# timeout-minutes: 15
# steps:
# - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
# - uses: jupyterlab/maintainer-tools/.github/actions/test-sdist@v1
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
repos:
- repo: https://github.com/asottile/reorder_python_imports
rev: v1.9.0
rev: v3.0.1
hooks:
- id: reorder-python-imports
- repo: https://github.com/psf/black
rev: 20.8b1
rev: 22.3.0
hooks:
- id: black
args: ["--line-length", "100"]
- repo: https://gitlab.com/pycqa/flake8
rev: "3.8.4"
rev: "3.9.2"
hooks:
- id: flake8
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
rev: v4.1.0
hooks:
- id: end-of-file-fixer
- id: check-case-conflict
Expand Down
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ include CONTRIBUTING.rst
include README.md
include RELEASE.md
include CHANGELOG.md
include pyproject.toml

# include everything in package_data
recursive-include jupyter_server_terminals *

recursive-include tests *

# Documentation
graft docs
exclude docs/\#*
Expand Down
7 changes: 7 additions & 0 deletions jupyter-config/jupyter_server_terminals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"ServerApp": {
"jpserver_extensions": {
"jupyter_server_terminals": true
}
}
}
50 changes: 6 additions & 44 deletions jupyter_server_terminals/__init__.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,10 @@
import os
import sys
from shutil import which
from .app import TerminalsExtensionApp

from jupyter_server.utils import url_path_join as ujoin

from . import api_handlers
from .handlers import TermSocket
from .terminalmanager import TerminalManager

version_info = (0, 1, 0, ".dev", "0")
__version__ = ".".join(map(str, version_info[:3])) + "".join(version_info[3:])


def initialize(webapp, root_dir, connection_url, settings):
if os.name == "nt":
default_shell = "powershell.exe"
else:
default_shell = which("sh")
shell_override = settings.get("shell_command")
shell = [os.environ.get("SHELL") or default_shell] if shell_override is None else shell_override
# When the notebook server is not running in a terminal (e.g. when
# it's launched by a JupyterHub spawner), it's likely that the user
# environment hasn't been fully set up. In that case, run a login
# shell to automatically source /etc/profile and the like, unless
# the user has specifically set a preferred shell command.
if os.name != "nt" and shell_override is None and not sys.stdout.isatty():
shell.append("-l")
terminal_manager = webapp.settings["terminal_manager"] = TerminalManager(
shell_command=shell,
extra_env={
"JUPYTER_SERVER_ROOT": root_dir,
"JUPYTER_SERVER_URL": connection_url,
def _jupyter_server_extension_points(): # pragma: no cover
return [
{
"module": "jupyter_server_terminals.app",
"app": TerminalsExtensionApp,
},
parent=webapp.settings["serverapp"],
)
terminal_manager.log = webapp.settings["serverapp"].log
base_url = webapp.settings["base_url"]
handlers = [
(
ujoin(base_url, r"/terminals/websocket/(\w+)"),
TermSocket,
{"term_manager": terminal_manager},
),
(ujoin(base_url, r"/api/terminals"), api_handlers.TerminalRootHandler),
(ujoin(base_url, r"/api/terminals/(\w+)"), api_handlers.TerminalHandler),
]
webapp.add_handlers(".*$", handlers)
1 change: 1 addition & 0 deletions jupyter_server_terminals/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "0.1.0.dev0"
18 changes: 15 additions & 3 deletions jupyter_server_terminals/api_handlers.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import json

from jupyter_server.base.handlers import APIHandler
from tornado import web

from .base import TerminalsMixin

class TerminalRootHandler(APIHandler):
try:
from jupyter_server.base.handlers import APIHandler
except ModuleNotFoundError:
raise ModuleNotFoundError("Jupyter Server must be installed to use this extension.")


class TerminalRootHandler(TerminalsMixin, APIHandler):
@web.authenticated
def get(self):
models = self.terminal_manager.list()
Expand All @@ -19,7 +25,7 @@ def post(self):
self.finish(json.dumps(model))


class TerminalHandler(APIHandler):
class TerminalHandler(TerminalsMixin, APIHandler):
SUPPORTED_METHODS = ("GET", "DELETE")

@web.authenticated
Expand All @@ -32,3 +38,9 @@ async def delete(self, name):
await self.terminal_manager.terminate(name, force=True)
self.set_status(204)
self.finish()


default_handlers = [
(r"/api/terminals", TerminalRootHandler),
(r"/api/terminals/(\w+)", TerminalHandler),
]
Loading