Skip to content

Commit

Permalink
feat: add support for script files, Python and Julia (py|jl)
Browse files Browse the repository at this point in the history
  • Loading branch information
maartenbreddels committed Jul 29, 2019
1 parent 4c34b43 commit 6d8039e
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 5 deletions.
5 changes: 3 additions & 2 deletions .travis.yml
Expand Up @@ -18,13 +18,14 @@ before_install:
- conda config --set always_yes yes --set changeps1 no
- conda update -q conda
- conda info -a
- conda create -q -n test-environment -c conda-forge python=$PYTHON_VERSION jupyter_server==0.1.0 jupyterlab_pygments==0.1.0 pytest==3.10.1 nbconvert=5.5 pytest-cov nodejs flake8 ipywidgets matplotlib
- conda create -q -n test-environment -c conda-forge python=$PYTHON_VERSION jupyter_server==0.1.0 jupyterlab_pygments==0.1.0 pytest==3.10.1 nbconvert=5.5 pytest-cov nodejs flake8 ipywidgets matplotlib julia
- source activate test-environment
- julia -e 'using Pkg; Pkg.add("IJulia")'
install:
- pip install ".[test]"
- cd tests/test_template; pip install .; cd ../../;
before_script:
- flake8 voila tests setup.py
script:
- VOILA_TEST_DEBUG=1 py.test tests/ --async-test-timeout=20
- VOILA_TEST_DEBUG=1 VOILA_TEST_JULIA=1 py.test tests/ --async-test-timeout=20
- voila --help # Making sure we can run `voila --help`
33 changes: 31 additions & 2 deletions tests/app/serve_directory_test.py
@@ -1,15 +1,44 @@
# test serving a notebook
# test serving a notebook or python/julia file
import os
import pytest

TEST_JULIA = os.environ.get('VOILA_TEST_JULIA', '') == '1'


@pytest.fixture
def voila_args(notebook_directory, voila_args_extra):
return ['--VoilaTest.root_dir=%r' % notebook_directory, '--VoilaTest.log_level=DEBUG'] + voila_args_extra


@pytest.mark.gen_test
def test_hello_world(http_client, print_notebook_url):
def test_print(http_client, print_notebook_url):
print(print_notebook_url)
response = yield http_client.fetch(print_notebook_url)
assert response.code == 200
assert 'Hi Voila' in response.body.decode('utf-8')


@pytest.mark.gen_test
def test_print_py(http_client, print_notebook_url):
print(print_notebook_url)
response = yield http_client.fetch(print_notebook_url.replace('ipynb', 'py'))
assert response.code == 200
assert 'Hi Voila' in response.body.decode('utf-8')


@pytest.mark.skipif(not TEST_JULIA, reason='testing julia is slow and requires external dependencies')
@pytest.mark.gen_test
def test_print_julia(http_client, print_notebook_url):
print(print_notebook_url)
response = yield http_client.fetch(print_notebook_url.replace('ipynb', 'jl'))
assert response.code == 200
assert 'Hi Voila, from Julia' in response.body.decode('utf-8')


@pytest.mark.skipif(not TEST_JULIA, reason='testing julia is slow and requires external dependencies')
@pytest.mark.gen_test
def test_print_julia_notebook(http_client, print_notebook_url):
print(print_notebook_url)
response = yield http_client.fetch(print_notebook_url.replace('.ipynb', '_julia.ipynb'))
assert response.code == 200
assert 'Hi Voila, from Julia' in response.body.decode('utf-8')
15 changes: 15 additions & 0 deletions tests/notebooks/print.jl
@@ -0,0 +1,15 @@
# ---
# jupyter:
# jupytext:
# text_representation:
# extension: .jl
# format_name: light
# format_version: '1.4'
# jupytext_version: 1.2.1
# kernelspec:
# display_name: Julia 1.0.3
# language: julia
# name: julia-1.0
# ---

print("Hi Voila, from Julia")
15 changes: 15 additions & 0 deletions tests/notebooks/print.py
@@ -0,0 +1,15 @@
# ---
# jupyter:
# jupytext:
# text_representation:
# extension: .py
# format_name: light
# format_version: '1.4'
# jupytext_version: 1.2.1
# kernelspec:
# display_name: Python 3
# language: python
# name: python
# ---

print('Hi Voila!')
28 changes: 28 additions & 0 deletions tests/notebooks/print_julia.ipynb
@@ -0,0 +1,28 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"Hi Voila, from Julia!\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 1.0.3",
"language": "julia",
"name": "julia-1.0"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "1.0.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
23 changes: 23 additions & 0 deletions voila/handler.py
Expand Up @@ -102,6 +102,12 @@ def load_notebook(self, path):
notebook = model['content']
notebook = yield self.fix_notebook(notebook)
raise tornado.gen.Return(notebook) # TODO py2: replace by return
elif model['mimetype'] == 'text/x-python' or model.get('path', '').endswith('.py'):
notebook = yield self.create_notebook(model, language='python')
raise tornado.gen.Return(notebook) # TODO py2: replace by return
elif model.get('path', '').endswith('.jl'):
notebook = yield self.create_notebook(model, language='julia')
raise tornado.gen.Return(notebook) # TODO py2: replace by return
else:
raise tornado.web.HTTPError(500, 'file not supported')

Expand Down Expand Up @@ -130,6 +136,23 @@ def fix_notebook(self, notebook):
notebook.metadata.kernelspec.language = all_kernel_specs[kernel_name]['spec']['language']
raise tornado.gen.Return(notebook) # TODO py2: replace by return

@tornado.gen.coroutine
def create_notebook(self, model, language):
all_kernel_specs = yield tornado.gen.maybe_future(self.kernel_spec_manager.get_all_specs())
kernel_name = yield self.find_kernel_name_for_language(language, kernel_specs=all_kernel_specs)
spec = all_kernel_specs[kernel_name]
nb = nbformat.v4.new_notebook(
metadata={
'kernelspec': {
'display_name': spec['spec']['display_name'],
'language': spec['spec']['language'],
'name': kernel_name
}
},
cells=[nbformat.v4.new_code_cell(model['content'])],
)
return nb

@tornado.gen.coroutine
def find_kernel_name_for_language(self, kernel_language, kernel_specs=None):
"""Finds a best matching kernel name given a kernel languages.
Expand Down
2 changes: 1 addition & 1 deletion voila/paths.py
Expand Up @@ -16,7 +16,7 @@
# if the directory above us contains the following paths, it means we are installed in dev mode (pip install -e .)
DEV_MODE = os.path.exists(os.path.join(ROOT, '../setup.py')) and os.path.exists(os.path.join(ROOT, '../share'))

notebook_path_regex = r'(.*\.ipynb)'
notebook_path_regex = r'(.*\.(?:ipynb|py|jl))'


def collect_template_paths(
Expand Down

0 comments on commit 6d8039e

Please sign in to comment.