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 pytest and handle warnings #6338

Merged
merged 6 commits into from
Apr 1, 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
23 changes: 8 additions & 15 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,28 +39,21 @@ jobs:
- name: Base Setup
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1

- name: Install dependencies
- name: Install the package
run: |
python -m pip install -U jupyter_packaging~=0.10
python -m pip install ".[test]""
jlpm run build:test

- name: Install the package
- name: Unit tests
run: |
python -m pip install .
jlpm run test
pytest -vv || pytest -vv --lf

- name: Integration Tests
jupyter labextension list 2>&1 | grep -ie "@jupyter-notebook/lab-extension.*enabled.*ok" -
jupyter server extension list 2>&1 | grep -ie "notebook.*enabled" -
python -m jupyterlab.browser_check

- name: Lint
run: |
jlpm
jlpm run eslint:check
jlpm run prettier:check

- name: Test
run: |
jlpm run build:test
jlpm run test

install:
needs: [build]
runs-on: ${{ matrix.os }}
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,7 @@ jobs:
run: |
EXIT_STATUS=0
make -C docs/ html SPHINXOPTS="-W" || EXIT_STATUS=$?
pytest --nbval --current-env docs || EXIT_STATUS=$?
# Ignore warnings to work around
# # https://github.com/computationalmodelling/nbval/issues/180
pytest --nbval --current-env -W default docs || EXIT_STATUS=$?
exit $EXIT_STATUS
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ include package.json
include install.json
include ts*.json

recursive-include tests *

graft notebook/labextension
graft notebook/static
graft notebook/templates
Expand Down
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
# |version| and |release|, also used in various other places throughout the
# built documents.
#
_version_py = "../../notebook/_version.py"
_version_py = os.path.join(here, "../../notebook/_version.py")
version_ns = {}
exec(compile(open(_version_py).read(), _version_py, "exec"), version_ns)
# The short X.Y version.
Expand Down
42 changes: 29 additions & 13 deletions notebook/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from notebook_shim.shim import NotebookConfigShimMixin
from tornado import web
from tornado.gen import maybe_future
from traitlets import Bool
from traitlets import Bool, default

from ._version import __version__

Expand Down Expand Up @@ -181,11 +181,6 @@ class JupyterNotebookApp(NotebookConfigShimMixin, LabServerApp):
file_url_prefix = "/notebooks"
load_other_extensions = True
app_dir = app_dir
app_settings_dir = pjoin(app_dir, "settings")
schemas_dir = pjoin(app_dir, "schemas")
themes_dir = pjoin(app_dir, "themes")
user_settings_dir = get_user_settings_dir()
workspaces_dir = get_workspaces_dir()
subcommands = {}

expose_app_in_browser = Bool(
Expand All @@ -206,6 +201,34 @@ class JupyterNotebookApp(NotebookConfigShimMixin, LabServerApp):
"Whether to enable collaborative mode.",
)

@default("static_dir")
def _default_static_dir(self):
return os.path.join(HERE, "static")

@default("templates_dir")
def _default_templates_dir(self):
return os.path.join(HERE, "templates")

@default("app_settings_dir")
def _default_app_settings_dir(self):
return pjoin(app_dir, "settings")

@default("schemas_dir")
def _default_schemas_dir(self):
return pjoin(app_dir, "schemas")

@default("themes_dir")
def _default_themes_dir(self):
return pjoin(app_dir, "themes")

@default("user_settings_dir")
def _default_user_settings_dir(self):
return get_user_settings_dir()

@default("workspaces_dir")
def _default_workspaces_dir(self):
return get_workspaces_dir()

def initialize_handlers(self):
self.handlers.append(
(
Expand All @@ -222,13 +245,6 @@ def initialize_handlers(self):
self.handlers.append(("/terminals/(.*)", TerminalHandler))
super().initialize_handlers()

def initialize_templates(self):
super().initialize_templates()
self.static_dir = os.path.join(HERE, "static")
self.templates_dir = os.path.join(HERE, "templates")
self.static_paths = [self.static_dir]
self.template_paths = [self.templates_dir]

def initialize_settings(self):
super().initialize_settings()

Expand Down
15 changes: 15 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,18 @@ npm = ["jlpm"]

[tool.check-manifest]
ignore = ["app/**", "binder/**", "buildutils/**", "docs/**", "packages/**", "codecov.yml", "*.json", "yarn.lock", "readthedocs.yml", ".bumpversion.cfg", ".*", "lint-staged.config.js", "*.svg", "notebook/labextension/**", "notebook/schemas/**", "notebook/static/**", "notebook/template/**", "ui-tests/**"]

[tool.pytest.ini_options]
addopts = "-raXs --durations 10 --color=yes --doctest-modules"
testpaths = [
"tests/"
]
timeout = 300
# Restore this setting to debug failures
# timeout_method = "thread"
filterwarnings = [
"error",
# Pending release of https://github.com/jupyterlab/jupyterlab_server/pull/259
"ignore:metadata:DeprecationWarning",
"ignore:There is no current event loop:DeprecationWarning",
]
8 changes: 8 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,17 @@ test =
pytest-cov
requests
pytest-tornasync
pytest-timeout
pytest-console-scripts
ipykernel
pre-commit
jupyterlab_server[test]

[options.packages.find]
exclude =
docs.*
tests
tests.*

[options.entry_points]
console_scripts =
Expand Down
130 changes: 130 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import json
import os
import os.path as osp
import shutil
from importlib.resources import path
from os.path import join as pjoin

import pytest

from notebook.app import JupyterNotebookApp

pytest_plugins = ["jupyter_server.pytest_plugin"]


def mkdir(tmp_path, *parts):
path = tmp_path.joinpath(*parts)
if not path.exists():
path.mkdir(parents=True)
return path


app_settings_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, "app_settings"))
user_settings_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, "user_settings"))
schemas_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, "schemas"))
workspaces_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, "workspaces"))
labextensions_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, "labextensions_dir"))


@pytest.fixture
def make_notebook_app(
jp_root_dir,
jp_template_dir,
app_settings_dir,
user_settings_dir,
schemas_dir,
workspaces_dir,
labextensions_dir,
):
def _make_notebook_app(**kwargs):

return JupyterNotebookApp(
static_dir=str(jp_root_dir),
templates_dir=str(jp_template_dir),
app_url="/",
app_settings_dir=str(app_settings_dir),
user_settings_dir=str(user_settings_dir),
schemas_dir=str(schemas_dir),
workspaces_dir=str(workspaces_dir),
extra_labextensions_path=[str(labextensions_dir)],
)

# Create the index files.
index = jp_template_dir.joinpath("index.html")
index.write_text(
"""
<!DOCTYPE html>
<html>
<head>
<title>{{page_config['appName'] | e}}</title>
</head>
<body>
{# Copy so we do not modify the page_config with updates. #}
{% set page_config_full = page_config.copy() %}
{# Set a dummy variable - we just want the side effect of the update. #}
{% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %}
<script id="jupyter-config-data" type="application/json">
{{ page_config_full | tojson }}
</script>
<script src="{{page_config['fullStaticUrl'] | e}}/bundle.js" main="index"></script>
<script type="text/javascript">
/* Remove token from URL. */
(function () {
var parsedUrl = new URL(window.location.href);
if (parsedUrl.searchParams.get('token')) {
parsedUrl.searchParams.delete('token');
window.history.replaceState({ }, '', parsedUrl.href);
}
})();
</script>
</body>
</html>
"""
)

# Copy the schema files.
test_data = str(path("jupyterlab_server", "test_data"))
src = pjoin(test_data, "schemas", "@jupyterlab")
dst = pjoin(str(schemas_dir), "@jupyterlab")
if os.path.exists(dst):
shutil.rmtree(dst)
shutil.copytree(src, dst)

# Create the federated extensions
for name in ["apputils-extension", "codemirror-extension"]:
target_name = name + "-federated"
target = pjoin(str(labextensions_dir), "@jupyterlab", target_name)
src = pjoin(test_data, "schemas", "@jupyterlab", name)
dst = pjoin(target, "schemas", "@jupyterlab", target_name)
if osp.exists(dst):
shutil.rmtree(dst)
shutil.copytree(src, dst)
with open(pjoin(target, "package.orig.json"), "w") as fid:
data = dict(name=target_name, jupyterlab=dict(extension=True))
json.dump(data, fid)

# Copy the overrides file.
src = pjoin(test_data, "app-settings", "overrides.json")
dst = pjoin(str(app_settings_dir), "overrides.json")
if os.path.exists(dst):
os.remove(dst)
shutil.copyfile(src, dst)

# Copy workspaces.
data = pjoin(test_data, "workspaces")
for item in os.listdir(data):
src = pjoin(data, item)
dst = pjoin(str(workspaces_dir), item)
if os.path.exists(dst):
os.remove(dst)
shutil.copy(src, str(workspaces_dir))

return _make_notebook_app


@pytest.fixture
def notebookapp(jp_serverapp, make_notebook_app):
app = make_notebook_app()
app._link_jupyter_server_extension(jp_serverapp)
app.initialize()
return app
22 changes: 22 additions & 0 deletions tests/test_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import pytest


@pytest.fixture
def notebooks(jp_create_notebook, notebookapp):
nbpaths = (
"notebook1.ipynb",
"jlab_test_notebooks/notebook2.ipynb",
"jlab_test_notebooks/level2/notebook3.ipynb",
)
for nb in nbpaths:
jp_create_notebook(nb)
return nbpaths


async def test_notebook_handler(notebooks, jp_fetch):
for nbpath in notebooks:
r = await jp_fetch("/", nbpath)
assert r.code == 200
# Check that the lab template is loaded
html = r.body.decode()
assert "Jupyter Notebook" in html