Skip to content

Commit 6127198

Browse files
committed
Merge branch 'master' into pytest_fixture_updates
2 parents 0d67d5d + ae6ae6a commit 6127198

File tree

13 files changed

+94
-38
lines changed

13 files changed

+94
-38
lines changed

.github/workflows/main.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ jobs:
2424
- name: Install the Python dependencies
2525
run: |
2626
pip install -e .[test]
27-
- name: ipykernel fix on windows 3.8
28-
if: matrix.os == 'windows-latest' && matrix.python-version == '3.8'
29-
run: |
30-
pip install --upgrade git+https://github.com/ipython/ipykernel.git
3127
- name: Run the tests
3228
run: |
3329
pytest

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ src
3333
*.swp
3434
*.map
3535
.idea/
36+
.vscode/
3637
Read the Docs
3738
config.rst
3839

appveyor.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ install:
3434
- cmd: conda create -y -q -n test-env-%CONDA_PY% python=%CONDA_PY_SPEC% pip pyzmq tornado jupyter_client nbformat nbconvert nose
3535
- cmd: conda activate test-env-%CONDA_PY%
3636
- cmd: pip install -e .[test]
37-
# FIXME: Use patch for python 3.8, windows issues (https://github.com/ipython/ipykernel/pull/456) - remove once released
38-
- IF %CONDA_PY% == 38 pip install --upgrade git+https://github.com/ipython/ipykernel.git
3937

4038
test_script:
4139
- pytest -s -v

jupyter_server/extension/application.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ class method. This method can be set as a entry_point in
154154
help="Name of extension."
155155
)
156156

157+
@default('extension_name')
157158
def _extension_name_default(self):
158159
try:
159160
return self.name
@@ -163,8 +164,8 @@ def _extension_name_default(self):
163164
INVALID_EXTENSION_NAME_CHARS = [' ', '.', '+', '/']
164165

165166
@validate('extension_name')
166-
def _validate_extension_name(self, value):
167-
#value = self.extension_name
167+
def _validate_extension_name(self, proposal):
168+
value = proposal['value']
168169
if isinstance(value, str):
169170
# Validate that extension_name doesn't contain any invalid characters.
170171
for c in ExtensionApp.INVALID_EXTENSION_NAME_CHARS:
@@ -351,6 +352,7 @@ def _prepare_templates(self):
351352
self.settings.update({
352353
"{}_template_paths".format(self.extension_name): self.template_paths
353354
})
355+
self.initialize_templates()
354356

355357
@staticmethod
356358
def initialize_server(argv=[], load_other_extensions=True, **kwargs):

jupyter_server/pytest_plugin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ def mkdir(tmp_path, *parts):
5353
config_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, "config"))
5454
runtime_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, "runtime"))
5555
root_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, "root_dir"))
56+
template_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, "templates"))
5657
system_jupyter_path = pytest.fixture(
5758
lambda tmp_path: mkdir(tmp_path, "share", "jupyter")
5859
)

jupyter_server/services/api/api.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,14 +441,19 @@ paths:
441441
tags:
442442
- kernels
443443
parameters:
444-
- name: name
444+
- name: options
445445
in: body
446-
description: Kernel spec name (defaults to default kernel spec for server)
447446
schema:
448447
type: object
448+
required:
449+
- name
449450
properties:
450451
name:
451452
type: string
453+
description: Kernel spec name (defaults to default kernel spec for server)
454+
path:
455+
type: string
456+
description: API path from root to the cwd of the kernel
452457
responses:
453458
201:
454459
description: Kernel started

jupyter_server/services/kernels/handlers.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ def post(self):
4545
else:
4646
model.setdefault('name', km.default_kernel_name)
4747

48-
kernel_id = yield maybe_future(km.start_kernel(kernel_name=model['name']))
48+
kernel_id = yield maybe_future(km.start_kernel(kernel_name=model['name'],
49+
path=model.get('path')))
4950
model = yield maybe_future(km.kernel_model(kernel_id))
5051
location = url_path_join(self.base_url, 'api', 'kernels', url_escape(kernel_id))
5152
self.set_header('Location', location)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
],
9393
extras_require = {
9494
'test': ['nose', 'coverage', 'requests', 'nose_warnings_filters',
95-
'pytest', 'pytest-cov', 'pytest-tornasync', 'pytest-console-scripts'],
95+
'pytest==5.3.2', 'pytest-cov', 'pytest-tornasync', 'pytest-console-scripts'],
9696
'test:sys_platform == "win32"': ['nose-exclude'],
9797
},
9898
python_requires = '>=3.5',

tests/extension/conftest.py

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
from jupyter_core import paths
77
from jupyter_server.extension import serverextension
88
from jupyter_server.extension.serverextension import _get_config_dir
9-
from jupyter_server.extension.application import ExtensionApp
10-
from jupyter_server.extension.handler import ExtensionHandler
9+
from jupyter_server.extension.application import ExtensionApp, ExtensionAppJinjaMixin
10+
from jupyter_server.extension.handler import ExtensionHandler, ExtensionHandlerJinjaMixin
1111

1212
# ----------------- Mock Extension App ----------------------
1313

@@ -17,14 +17,21 @@ def get(self):
1717
self.finish(self.config.mock_trait)
1818

1919

20-
class MockExtensionApp(ExtensionApp):
20+
class MockExtensionTemplateHandler(ExtensionHandlerJinjaMixin, ExtensionHandler):
21+
22+
def get(self):
23+
self.write(self.render_template("index.html"))
24+
25+
26+
class MockExtensionApp(ExtensionAppJinjaMixin, ExtensionApp):
2127
extension_name = 'mockextension'
2228
mock_trait = Unicode('mock trait', config=True)
2329

2430
loaded = False
2531

2632
def initialize_handlers(self):
2733
self.handlers.append(('/mock', MockExtensionHandler))
34+
self.handlers.append(('/mock_template', MockExtensionTemplateHandler))
2835
self.loaded = True
2936

3037
@staticmethod
@@ -33,6 +40,36 @@ def _jupyter_server_extension_paths():
3340
'module': '_mockdestination/index'
3441
}]
3542

43+
@pytest.fixture
44+
def make_mock_extension_app(template_dir):
45+
def _make_mock_extension_app(**kwargs):
46+
kwargs.setdefault('template_paths', [str(template_dir)])
47+
return MockExtensionApp(**kwargs)
48+
49+
# TODO Should the index template creation be only be done only once?
50+
index = template_dir.joinpath("index.html")
51+
index.write_text("""
52+
<!DOCTYPE HTML>
53+
<html>
54+
<head>
55+
<meta charset="utf-8">
56+
<title>{% block title %}Jupyter Server 1{% endblock %}</title>
57+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
58+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
59+
{% block meta %}
60+
{% endblock %}
61+
</head>
62+
<body>
63+
<div id="site">
64+
{% block site %}
65+
{% endblock site %}
66+
</div>
67+
{% block after_site %}
68+
{% endblock after_site %}
69+
</body>
70+
</html>""")
71+
return _make_mock_extension_app
72+
3673

3774
@pytest.fixture
3875
def config_file(config_dir):
@@ -43,21 +80,21 @@ def config_file(config_dir):
4380

4481

4582
@pytest.fixture
46-
def extended_serverapp(serverapp):
83+
def extended_serverapp(serverapp, make_mock_extension_app):
4784
""""""
48-
m = MockExtensionApp()
85+
m = make_mock_extension_app()
4986
m.initialize(serverapp)
5087
return m
5188

5289

5390
@pytest.fixture
54-
def inject_mock_extension(environ, extension_environ):
91+
def inject_mock_extension(environ, extension_environ, make_mock_extension_app):
5592
"""Fixture that can be used to inject a mock Jupyter Server extension into the tests namespace.
5693
5794
Usage: inject_mock_extension({'extension_name': ExtensionClass})
5895
"""
5996
def ext(modulename="mockextension"):
60-
sys.modules[modulename] = e = MockExtensionApp()
97+
sys.modules[modulename] = e = make_mock_extension_app()
6198
return e
6299

63100
return ext

tests/extension/test_app.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,17 @@
33
from jupyter_server.serverapp import ServerApp
44
from jupyter_server.extension.application import ExtensionApp
55

6-
from .conftest import MockExtensionApp
76

8-
9-
def test_instance_creation():
10-
mock_extension = MockExtensionApp()
7+
def test_instance_creation(make_mock_extension_app, template_dir):
8+
mock_extension = make_mock_extension_app()
119
assert mock_extension.static_paths == []
12-
assert mock_extension.template_paths == []
10+
assert mock_extension.template_paths == [str(template_dir)]
1311
assert mock_extension.settings == {}
14-
assert mock_extension.handlers == []
12+
assert mock_extension.handlers == []
1513

1614

17-
def test_initialize(serverapp):
18-
mock_extension = MockExtensionApp()
15+
def test_initialize(serverapp, make_mock_extension_app):
16+
mock_extension = make_mock_extension_app()
1917
mock_extension.initialize(serverapp)
2018
# Check that settings and handlers were added to the mock extension.
2119
assert isinstance(mock_extension.serverapp, ServerApp)
@@ -35,24 +33,24 @@ def test_initialize(serverapp):
3533
'trait_name,trait_value',
3634
traits
3735
)
38-
def test_instance_creation_with_instance_args(trait_name, trait_value):
36+
def test_instance_creation_with_instance_args(trait_name, trait_value, make_mock_extension_app):
3937
kwarg = {}
4038
kwarg.setdefault(trait_name, trait_value)
41-
mock_extension = MockExtensionApp(**kwarg)
39+
mock_extension = make_mock_extension_app(**kwarg)
4240
assert getattr(mock_extension, trait_name) == trait_value
4341

4442

4543
@pytest.mark.parametrize(
4644
'trait_name,trait_value',
4745
traits
4846
)
49-
def test_instance_creation_with_argv(serverapp, trait_name, trait_value):
47+
def test_instance_creation_with_argv(serverapp, trait_name, trait_value, make_mock_extension_app):
5048
kwarg = {}
5149
kwarg.setdefault(trait_name, trait_value)
5250
argv = [
5351
'--MockExtensionApp.{name}={value}'.format(name=trait_name, value=trait_value)
5452
]
55-
mock_extension = MockExtensionApp()
53+
mock_extension = make_mock_extension_app()
5654
mock_extension.initialize(serverapp, argv=argv)
5755
assert getattr(mock_extension, trait_name) == trait_value
5856

0 commit comments

Comments
 (0)