kopia lustrzana https://github.com/jupyterhub/repo2docker
add basic stencila buildpack
rodzic
f7139e8f89
commit
a61d9253a4
|
@ -30,7 +30,7 @@ from . import __version__
|
||||||
from .buildpacks import (
|
from .buildpacks import (
|
||||||
PythonBuildPack, DockerBuildPack, LegacyBinderDockerBuildPack,
|
PythonBuildPack, DockerBuildPack, LegacyBinderDockerBuildPack,
|
||||||
CondaBuildPack, JuliaBuildPack, BaseImage,
|
CondaBuildPack, JuliaBuildPack, BaseImage,
|
||||||
RBuildPack
|
RBuildPack, StencilaBuildPack,
|
||||||
)
|
)
|
||||||
from .utils import (
|
from .utils import (
|
||||||
execute_cmd, ByteSpecification, maybe_cleanup, is_valid_docker_image_name,
|
execute_cmd, ByteSpecification, maybe_cleanup, is_valid_docker_image_name,
|
||||||
|
@ -67,6 +67,7 @@ class Repo2Docker(Application):
|
||||||
DockerBuildPack,
|
DockerBuildPack,
|
||||||
JuliaBuildPack,
|
JuliaBuildPack,
|
||||||
RBuildPack,
|
RBuildPack,
|
||||||
|
StencilaBuildPack,
|
||||||
CondaBuildPack,
|
CondaBuildPack,
|
||||||
PythonBuildPack,
|
PythonBuildPack,
|
||||||
],
|
],
|
||||||
|
|
|
@ -5,3 +5,4 @@ from .julia import JuliaBuildPack
|
||||||
from .docker import DockerBuildPack
|
from .docker import DockerBuildPack
|
||||||
from .legacy import LegacyBinderDockerBuildPack
|
from .legacy import LegacyBinderDockerBuildPack
|
||||||
from .r import RBuildPack
|
from .r import RBuildPack
|
||||||
|
from .stencila import StencilaBuildPack
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
from .stencila import *
|
|
@ -0,0 +1,25 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Stencila Project</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="./node_modules/stencila/dist/stencila.css">
|
||||||
|
<script type="text/javascript" src="./node_modules/stencila/dist/katex/katex.min.js"></script>
|
||||||
|
<script type="text/javascript" src="./node_modules/stencila/dist/lib/plotly.min.js"></script>
|
||||||
|
<script type="text/javascript" src="./node_modules/stencila/dist/lib/substance.js"></script>
|
||||||
|
<script type="text/javascript" src="./node_modules/stencila/dist/lib/texture.js"></script>
|
||||||
|
<script type="text/javascript" src="./node_modules/stencila/dist/lib/stencila-mini.js"></script>
|
||||||
|
<script type="text/javascript" src="./node_modules/stencila/dist/lib/stencila-envcore.min.js"></script>
|
||||||
|
<script type="text/javascript" src="./node_modules/stencila/dist/lib/stencila-libcore.min.js"></script>
|
||||||
|
<script type="text/javascript" src="./node_modules/stencila/dist/stencila.js"></script>
|
||||||
|
<script type="text/javascript" src="./node_modules/stencila/dist/vfs.js"></script>
|
||||||
|
<script type="text/javascript" src="./node_modules/stencila/dist/env.js"></script>
|
||||||
|
<script type="text/javascript" src="./app.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
// Set the URL for the Stencila host based on the current window's URL which on Binder looks like:
|
||||||
|
// https://hub.mybinder.org/user/nokome-jupyter-dar-xufgzr0d/stencila/?token=c1KzGj7XRg-Gyur8rr-U3pQ
|
||||||
|
window.STENCILA_HOSTS = (window.location.origin + window.location.pathname).replace('/stencila/', '/stencila-host')
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
|
@ -0,0 +1,71 @@
|
||||||
|
import pipes
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from nbserverproxy.handlers import SuperviseAndProxyHandler
|
||||||
|
|
||||||
|
# define our proxy handler for proxying the application
|
||||||
|
|
||||||
|
class StencilaProxyHandler(SuperviseAndProxyHandler):
|
||||||
|
|
||||||
|
name = 'stencila'
|
||||||
|
|
||||||
|
def get_env(self):
|
||||||
|
return {
|
||||||
|
'STENCILA_PORT': str(self.port),
|
||||||
|
'STENCILA_ARCHIVE_DIR': self.state['notebook_dir'],
|
||||||
|
'BASE_URL': self.state['base_url'],
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_cmd(self):
|
||||||
|
return [
|
||||||
|
'sh', '-c', 'cd "$STENCILA_DIR"; node stencila.js',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class StencilaHostProxyHandler(SuperviseAndProxyHandler):
|
||||||
|
|
||||||
|
name = 'stencila-host'
|
||||||
|
|
||||||
|
def get_env(self):
|
||||||
|
return {
|
||||||
|
'STENCILA_HOST_PORT': str(self.port)
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_cmd(self):
|
||||||
|
return [
|
||||||
|
'sh', '-c', 'cd "$STENCILA_DIR"; node stencila-host.js',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def add_handlers(app):
|
||||||
|
"""Register the stencila proxy directory"""
|
||||||
|
app.log.info("serving stencila at %s", app.base_url + 'stencila')
|
||||||
|
app.web_app.add_handlers('.*', [
|
||||||
|
(
|
||||||
|
app.base_url + 'stencila/(.*)',
|
||||||
|
StencilaProxyHandler,
|
||||||
|
dict(state=dict(
|
||||||
|
base_url=app.base_url,
|
||||||
|
notebook_dir=app.notebook_dir,
|
||||||
|
)),
|
||||||
|
|
||||||
|
), (
|
||||||
|
app.base_url + 'stencila-host/(.*)',
|
||||||
|
StencilaHostProxyHandler,
|
||||||
|
dict(state=dict(
|
||||||
|
base_url=app.base_url,
|
||||||
|
notebook_dir=app.notebook_dir,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
# fake a module to load the proxy handler as an extension
|
||||||
|
module_name = '_stencilaproxy'
|
||||||
|
import types
|
||||||
|
mod = types.ModuleType(module_name)
|
||||||
|
sys.modules[module_name] = mod
|
||||||
|
mod.load_jupyter_server_extension = add_handlers
|
||||||
|
c.NotebookApp.nbserver_extensions.update({
|
||||||
|
module_name: True,
|
||||||
|
})
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"name": "jupyter-dar",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "javascript dependencies for jupyter-dar",
|
||||||
|
"main": "stencila.js",
|
||||||
|
"dependencies": {
|
||||||
|
"stencila": "0.28.1-preview.2",
|
||||||
|
"stencila-node": "stencila/node#9b619f8f191474dc362934993199642acdf81ae2"
|
||||||
|
},
|
||||||
|
"devDependencies": {},
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/minrk/jupyter-dar.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"jupyter",
|
||||||
|
"dar",
|
||||||
|
"stencila",
|
||||||
|
"texture"
|
||||||
|
],
|
||||||
|
"author": "Min RK, Daniel Nüst",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/minrk/jupyter-dar/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/minrk/jupyter-dar#readme"
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"NotebookApp": {
|
||||||
|
"nbserver_extensions": {
|
||||||
|
"_stencilaproxy": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
const stencila = require("stencila-node");
|
||||||
|
|
||||||
|
// Get the port passed here from the `nbserverproxy.hanglers.SuperviseAndProxyHandler`
|
||||||
|
const port = parseInt(process.env.STENCILA_HOST_PORT || '2000')
|
||||||
|
|
||||||
|
// Run the Stencila execution host without
|
||||||
|
// any authentication (handled by Jupyter)
|
||||||
|
process.env.STENCILA_AUTH = 'false'
|
||||||
|
|
||||||
|
stencila.run({ port })
|
|
@ -0,0 +1,26 @@
|
||||||
|
const path = require("path");
|
||||||
|
const darServer = require("dar-server");
|
||||||
|
const express = require("express");
|
||||||
|
|
||||||
|
const port = parseInt(process.env.STENCILA_PORT || '4000');
|
||||||
|
const archiveDir = process.env.STENCILA_ARCHIVE_DIR || process.env.HOME;
|
||||||
|
const baseUrl = process.env.BASE_URL || "/";
|
||||||
|
const serverUrl = baseUrl + "stencila";
|
||||||
|
const server = express();
|
||||||
|
|
||||||
|
darServer.serve(server, {
|
||||||
|
port: port,
|
||||||
|
serverUrl: serverUrl,
|
||||||
|
rootDir: archiveDir,
|
||||||
|
apiUrl: "/archives"
|
||||||
|
});
|
||||||
|
|
||||||
|
var staticDir = __dirname;
|
||||||
|
|
||||||
|
console.log("Stencila app root: %s", staticDir);
|
||||||
|
console.log("DAR archive path: %s", archiveDir);
|
||||||
|
console.log("DAR public URL: %s", serverUrl);
|
||||||
|
console.log("Serving stencila on :%s", port);
|
||||||
|
|
||||||
|
server.use("/", express.static(staticDir));
|
||||||
|
server.listen(port);
|
|
@ -0,0 +1,120 @@
|
||||||
|
"""
|
||||||
|
Buildpack for stencila editor for DAR document archives
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from ..conda import CondaBuildPack
|
||||||
|
|
||||||
|
|
||||||
|
class StencilaBuildPack(CondaBuildPack):
|
||||||
|
"""Stencila buildpack
|
||||||
|
|
||||||
|
- installs stencila in /opt/stencila
|
||||||
|
- installs nbserverproxy
|
||||||
|
- registers nbserverproxy extension for stencila
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def runtime(self):
|
||||||
|
"""
|
||||||
|
Return contents of runtime.txt if it exists, '' otherwise
|
||||||
|
"""
|
||||||
|
if not hasattr(self, "_runtime"):
|
||||||
|
runtime_path = self.binder_path("runtime.txt")
|
||||||
|
try:
|
||||||
|
with open(runtime_path) as f:
|
||||||
|
self._runtime = f.read().strip()
|
||||||
|
except FileNotFoundError:
|
||||||
|
self._runtime = ""
|
||||||
|
|
||||||
|
return self._runtime
|
||||||
|
|
||||||
|
def detect(self):
|
||||||
|
"""
|
||||||
|
Check if current repo should be built with the stencila
|
||||||
|
|
||||||
|
Currently only checks for 'stencila' in runtime.txt
|
||||||
|
"""
|
||||||
|
return self.runtime.startswith("stencila")
|
||||||
|
|
||||||
|
def get_env(self):
|
||||||
|
"""
|
||||||
|
Return environment variables to be set.
|
||||||
|
|
||||||
|
Sets STENCILA_DIR
|
||||||
|
"""
|
||||||
|
return super().get_env() + [
|
||||||
|
# This is the path where user libraries are installed
|
||||||
|
("STENCILA_DIR", "/opt/stencila")
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_build_script_files(self):
|
||||||
|
"""
|
||||||
|
Dict of files to be copied to the container image for use in building.
|
||||||
|
|
||||||
|
This is copied before the `build_scripts` & `assemble_scripts` are
|
||||||
|
run, so can be executed from either of them.
|
||||||
|
|
||||||
|
It's a dictionary where the key is the source file path in the host
|
||||||
|
system, and the value is the destination file path inside the
|
||||||
|
container image.
|
||||||
|
|
||||||
|
Includes files required for running stencila
|
||||||
|
|
||||||
|
This currently adds a frozen set of Python requirements to the dict
|
||||||
|
of files.
|
||||||
|
|
||||||
|
"""
|
||||||
|
files = super().get_build_script_files()
|
||||||
|
for f in [
|
||||||
|
"index.html",
|
||||||
|
"stencila.js",
|
||||||
|
"stencila-host.js",
|
||||||
|
"package.json",
|
||||||
|
"package-lock.json",
|
||||||
|
]:
|
||||||
|
files["stencila/" + f] = "${STENCILA_DIR}/" + f
|
||||||
|
files[
|
||||||
|
"stencila/jupyter_notebook_config.py"
|
||||||
|
] = "/etc/jupyter/jupyter_notebook_config.py"
|
||||||
|
files[
|
||||||
|
"stencila/stencila-ext.json"
|
||||||
|
] = "/etc/jupyter/jupyter_notebook_config.d/stencila-ext.json"
|
||||||
|
return files
|
||||||
|
|
||||||
|
def get_build_scripts(self):
|
||||||
|
"""
|
||||||
|
Install commands for stencila
|
||||||
|
"""
|
||||||
|
return super().get_build_scripts() + [
|
||||||
|
(
|
||||||
|
"root",
|
||||||
|
r"""
|
||||||
|
mkdir -p ${STENCILA_DIR} && \
|
||||||
|
chown -R ${NB_USER}:${NB_USER} ${STENCILA_DIR}
|
||||||
|
""",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"${NB_USER}",
|
||||||
|
# install nbserverproxy
|
||||||
|
r"""
|
||||||
|
pip install https://github.com/minrk/nbserverproxy/archive/del-starting.tar.gz
|
||||||
|
""",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"${NB_USER}",
|
||||||
|
# install stencila
|
||||||
|
r"""
|
||||||
|
cd ${STENCILA_DIR} && \
|
||||||
|
npm install
|
||||||
|
""",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_assemble_scripts(self):
|
||||||
|
"""Return assembly scripts to run after staging repo contents"""
|
||||||
|
assemble_scripts = super().get_assemble_scripts()
|
||||||
|
return assemble_scripts
|
Ładowanie…
Reference in New Issue