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

Add more coverage #1069

Merged
merged 15 commits into from
Nov 17, 2022
59 changes: 18 additions & 41 deletions .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,34 +37,20 @@ jobs:
sudo apt-get update
sudo apt-get install texlive-plain-generic inkscape texlive-xetex
sudo apt-get install xvfb x11-utils libxkbcommon-x11-0 pandoc
- name: Run the tests
- name: Run the tests on posix
if: ${{ !startsWith(matrix.python-version, 'pypy') && !startsWith(matrix.os, 'windows') }}
run: hatch run cov:test -W default || hatch run test:test -W default --lf
- name: Run the tests on pypy and windows
if: ${{ startsWith(matrix.python-version, 'pypy') || startsWith(matrix.os, 'windows') }}
run: hatch run test:test -W default || hatch run test:test -W default --lf
run: hatch run cov:test --cov-fail-under 75 || hatch run test:test --lf
- name: Run the tests on pypy
if: ${{ startsWith(matrix.python-version, 'pypy') }}
run: hatch run test:test || hatch run test:test --lf
- name: Run the tests on windows
if: ${{ startsWith(matrix.python-version, 'windows') }}
run: hatch run cov:nowarn -s || hatch run cov:nowarn --lf
- name: Coverage
run: |
pip install codecov
codecov

client8:
runs-on: ${{ matrix.os }}
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.10"]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Base Setup
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- run: |
pip install -U pre jupyter_client
hatch run test:test || hatch run test:test --lf

pre-commit:
name: pre-commit
runs-on: ubuntu-latest
Expand Down Expand Up @@ -102,38 +88,30 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Base Setup
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
with:
python_version: "3.8"
- name: Install miniumum versions
uses: jupyterlab/maintainer-tools/.github/actions/install-minimums@v1
- uses: jupyterlab/maintainer-tools/.github/actions/install-minimums@v1
with:
only_create_file: 1
- name: Run the unit tests
run: |
pytest -vv -W default || pytest -vv -W default --lf
export PIP_CONSTRAINT="./contraints_file.txt"
hatch run test:nowarn || hatch run test:nowarn --lf

test_prereleases:
name: Test Prereleases
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Base Setup
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- uses: actions/checkout@v3
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
with:
python_version: "3.11"
- name: Install the Python dependencies
run: |
pip install --no-deps .
pip install --pre --upgrade ".[test]"
- name: List installed packages
run: |
pip freeze
pip check
- name: Run the tests
run: |
pytest -vv -W default || pytest -vv -W default --lf
export PIP_PRE=1
hatch run test:nowarn || hatch run test:nowarn --lf

make_sdist:
name: Make SDist
Expand Down Expand Up @@ -173,7 +151,6 @@ jobs:
- test_docs
- test_minimum_versions
- test_prereleases
- client8
- check_links
- test_sdist
runs-on: ubuntu-latest
Expand Down
5 changes: 1 addition & 4 deletions jupyter_server/files/handlers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Serve files directly from the ContentsManager."""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import json
import mimetypes
from base64 import decodebytes
from typing import List
Expand All @@ -15,7 +14,7 @@
AUTH_RESOURCE = "contents"


class FilesHandler(JupyterHandler):
class FilesHandler(JupyterHandler, web.StaticFileHandler):
"""serve files via ContentsManager

Normally used when ContentsManager is not a FileContentsManager.
Expand Down Expand Up @@ -85,8 +84,6 @@ async def get(self, path, include_body=True):
if model["format"] == "base64":
b64_bytes = model["content"].encode("ascii")
self.write(decodebytes(b64_bytes))
elif model["format"] == "json":
self.write(json.dumps(model["content"]))
else:
self.write(model["content"])
self.flush()
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ dependencies = ["coverage", "pytest-cov"]
[tool.hatch.envs.cov.env-vars]
ARGS = "-vv --cov jupyter_server --cov-branch --cov-report term-missing:skip-covered"
[tool.hatch.envs.cov.scripts]
test = "python -m pytest $ARGS --cov-fail-under 75 {args}"
test = "python -m pytest $ARGS {args}"
nwarn = "python -m pytest $ARGS -W default {args}"
integration = "python -m pytest $ARGS --integration_tests=true {args}"

[tool.hatch.version]
Expand Down
22 changes: 22 additions & 0 deletions tests/extension/test_serverextension.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@

from jupyter_server.config_manager import BaseJSONConfigManager
from jupyter_server.extension.serverextension import (
DisableServerExtensionApp,
ListServerExtensionsApp,
ServerExtensionApp,
ToggleServerExtensionApp,
_get_config_dir,
toggle_server_extension_python,
)
Expand Down Expand Up @@ -112,3 +116,21 @@ def test_load_ordered(jp_serverapp, jp_server_config):
assert jp_serverapp.mockII is True, "Mock II should have been loaded"
assert jp_serverapp.mockI is True, "Mock I should have been loaded"
assert jp_serverapp.mock_shared == "II", "Mock II should be loaded after Mock I"


def test_server_extension_apps(jp_env_config_path, jp_extension_environ):
app = ToggleServerExtensionApp()
app.extra_args = "mock1"
app.start()

app = DisableServerExtensionApp()
app.extra_args = "mock1"
app.start()

app = ListServerExtensionsApp()
app.start()


def test_server_extension_app():
app = ServerExtensionApp()
app.launch_instance(["list"])
22 changes: 21 additions & 1 deletion tests/extension/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import logging
import warnings

import pytest

from jupyter_server.extension.utils import validate_extension
from jupyter_server.extension.utils import get_loader, get_metadata, validate_extension
from tests.extension.mockextensions import mockext_sys

# Use ServerApps environment because it monkeypatches
# jupyter_core.paths and provides a config directory
Expand All @@ -17,3 +21,19 @@ def test_validate_extension():
assert validate_extension("tests.extension.mockextensions.mockext_user")
# enabled at Python
assert validate_extension("tests.extension.mockextensions.mockext_py")


def test_get_loader():
get_loader(mockext_sys)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
assert get_loader(object()) is None


def test_get_metadata():
_, ext_points = get_metadata("tests.extension.mockextensions.mockext_sys")
assert len(ext_points)
_, ext_points = get_metadata("tests", logger=logging.getLogger())
point = ext_points[0]
assert point["module"] == "tests"
assert point["name"] == "tests"
21 changes: 20 additions & 1 deletion tests/test_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
from .utils import expected_http_error


@pytest.fixture(
params=[
"jupyter_server.files.handlers.FilesHandler",
"jupyter_server.base.handlers.AuthenticatedFileHandler",
]
)
def jp_argv(request):
return ["--ContentsManager.files_handler_class=" + request.param]


@pytest.fixture(
params=[
[False, ["å b"]],
Expand All @@ -33,6 +43,15 @@ async def fetch_expect_404(jp_fetch, *path_parts):
assert expected_http_error(e, 404), [path_parts, e]


async def test_file_types(jp_fetch, jp_root_dir):
path = Path(jp_root_dir, "test")
path.mkdir(parents=True, exist_ok=True)
foos = ["foo.tar.gz", "foo.bz", "foo.foo"]
for foo in foos:
(path / foo).write_text(foo)
await fetch_expect_200(jp_fetch, "test", foo)


async def test_hidden_files(jp_fetch, jp_serverapp, jp_root_dir, maybe_hidden):
is_hidden, path_parts = maybe_hidden
path = Path(jp_root_dir, *path_parts)
Expand Down Expand Up @@ -85,7 +104,7 @@ async def test_contents_manager(jp_fetch, jp_serverapp, jp_root_dir):

r = await jp_fetch("files/test.txt", method="GET")
assert r.code == 200
assert r.headers["content-type"] == "text/plain; charset=UTF-8"
assert "text/plain" in r.headers["content-type"]
assert r.body.decode() == "foobar"


Expand Down
5 changes: 4 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import socket
import subprocess
import sys
import uuid
import warnings
from pathlib import Path
from unittest.mock import patch
Expand Down Expand Up @@ -116,7 +117,9 @@ async def foo():
@pytest.mark.skipif(os.name != "posix", reason="Requires unix sockets")
def test_unix_socket_in_use(tmp_path):
root_tmp_dir = Path("/tmp").resolve()
server_address = os.path.join(root_tmp_dir, os.path.basename(tmp_path))
server_address = os.path.join(root_tmp_dir, uuid.uuid4().hex)
if os.path.exists(server_address):
os.remove(server_address)
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind(server_address)
sock.listen(0)
Expand Down