Code Monkey home page Code Monkey logo

nbstencilaproxy's Introduction

Jupyter + Stencila = nbstencilaproxy

Jupyter + Dar file format compatibility exploration for running Stencila editor on Binder

PyPI version

Demo

Click on the button below to launch an online Jupyter instance on mybinder.org based on this repository:

Binder

Open an the example Dar project by clicking on "New > Stencila Session":

About

This project is part of the eLife Innovation Sprint 2018 and Mozilla Global Sprint 2018 (see mozilla/global-sprint#317)

The projects core module is a Python package, nbstencilaproxy, which is available on PyPI. It is based on nbserverproxy to run the services and the UI required to edit Stencila documents in the browser. The concept is inspired by nbrsessionproxy.

nbstencilaproxy includes the following components:

  • a JavaScript package for installing and running Stencila (client/UI and services) in a Jupyter container
  • extension for the Jupyter UI to add a "New Stencila Session" button

Team

How does it work?

The building blocks

Binder relies on repo2docker create a runtime environment from source code repositories. repo2docker was extended as part of this project to detect Dar documents using the file manifest.xml, which is contained in all Dars. If a manifest.xml is found, then repo2docker installs nbstencilaproxy into the image (see code) and creates environment variables (STENCILA_ARCHIVE_DIR and STENCILA_ARCHIVE) to configure a single Dar document to be viewed in the Stencila UI.

The installation consists of the following steps and components:

  1. Install Stencila for Python from GitHub and register the package (thanks to the registration, the Stencila Host can find and connect these runtimes)
  2. Install nbstencilaproxy itself, including a JavaScript module (see below for description of the npm; see setup.py for installation of the npm package as part of the Python module)
  3. Install and enable the nbstencilaproxy Jupyter notebook server extension, which serves the Stencila UI and services via proxies (see nbstencilaproxy/handlers.py)
  4. Install and enable the nbstencilaproxy Jupyter notebook extension, which adds a menu item into the Jupyter UI to open Stencila (see nbstencilaproxy/static/tree.js)

JavaScript module within nbstencilaproxy

The PyPI module includes a small npm package with JavaScript code, which serves the following purposes:

  • pulls in Stencila' JavaScript depenencies, namely stencila and stencila-host (see package.json)
  • includes code to run the dar-server and a static file server for the app using the files from the the module stencilas directory dist (see the file stencila.js for details)
  • run a stencila-host on the port provided by nbserverproxy (see stencila-host.js)

This gives us control of the paths and let's us get rid of complex development features (e.g. substance-bundler).

The package includes stencila-node as a dependency. It provides the JupyterContext as well as a NodeContext (for executing Javascript) and a SqliteContext (for executing SQL).

We also made our own version of app.js, getting rid of the virtual file storage stuff (vfs), defaulting storage to fs (file system), because that is what is needed for Jupyter - we do not need to host any examples. In the same line, we built own index.html (based on example.html) and serve that, which allows us to directly render a Dar document instead of a listing of examples and instruction and to use app.js.

Relevant path configurations comprise (a) the local storage path and (b) the URLs used by the client, accessing the dar-server through nbserverproxy.

Connecting Stencila to Jupyter kernels

Stencila has "execution contexts" (the equivalent of Jupyter's "kernels") for R, Python, SQL, JavaScript (Node.js), and Mini (Stencila's own simple language). Execution contexts differ from kernels in a number of ways including local execution and dependency analysis of cells. Both of these are necessary for the reactive, functional execution model of Stencila Articles and Sheets.

It is possible to install these execution contexts in the Docker image, and is done so for R However, Stencila also has a JupyterContext which acts as a bridge between Stencila's API and Jupyter kernels. Since the base image for BinderHub already has a Jupyter kernel for Python installed, it can always be used. This does mean however, that some of the reactive aspects of the Stencila UI won't work as expected. Also the JupyterContext is not well developed or tested.

Install locally

If you have a local Jupyter instance, you can install the package directly:

pip install nbstencilaproxy

Enable the extensions for all users on the system:

jupyter serverextension enable  --py --sys-prefix nbstencilaproxy
jupyter nbextension     install --py --sys-prefix nbstencilaproxy
jupyter nbextension     enable  --py --sys-prefix nbstencilaproxy

Run locally with repo2docker

You can run the latest release of nbstencilaproxy as part of repo2docker.

# install repo2docker: https://repo2docker.readthedocs.io/en/latest/usage.html#running-repo2docker-locally

# run repo2docker for a repository with Dar directories, e.g. archive/ in this repository (add '--no-build' option to only inspect Dockerfile)
repo2docker --debug ./archive
  • Login by visiting the tokenized URL displayed e.g. http://localhost:8888/?token=99a7bc13...
  • Click on the "New > Stencila Session" button on the Jupyter start page, opening the py-jupyter example, or
  • Open one of the included examples by appending the following parameters to the URL:

Development

Updating Stencila

The following places use/install Stencila components in specific versions:

  • repo2docker/buildpacks/base.py installs github.com/stencila/py
  • repo2docker/buildpacks/r.py installs github.com/stencila/r
  • nbstencilaproxy/package.json installs stencila-node and stencila from npm

Using local nbstencilaproxy in repo2docker

This is quite tricky to do, but useful to test the whole stack of tools. It could be possible to copy the local files into the container, but a more practical approach is to temporarily telling repo2docker to install nbstencilaproxy from ones own fork.

In repo2docker/buildpacks/base.py find the line with

${NB_PYTHON_PREFIX}/bin/pip install --no-cache nbstencilaproxy==0.1.1 && \

which installs nbstencilaproxy from PyPI. Replace it with the following line (using your username for <user>)

${NB_PYTHON_PREFIX}/bin/pip install https://github.com/<user>/nbstencilaproxy/archive/master.tar.gz && \

License

BSD 3-Clause License

nbstencilaproxy's People

Contributors

minrk avatar nuest avatar dependabot[bot] avatar bluerezz avatar ryanlovett avatar

Stargazers

GAURAV avatar John Blischak avatar Giuliano avatar Tony Naggs (Twitter: @xa329) avatar Naomi Penfold avatar Josh Mize avatar Tod Robbins avatar Michael Aufreiter avatar  avatar Ben Marwick avatar Ertuğrul Erata avatar Carol Willing avatar

Watchers

Michael Aufreiter avatar  avatar James Cloos avatar  avatar robin avatar Naomi Penfold avatar  avatar  avatar

nbstencilaproxy's Issues

Sprint wrap-up blog post

I'd like to write a little wrap-up blog post with the stuff started at the sprint, probably not including the ideas going beyond that (discussed on Gitter during sprint), with the following content (feedback welcome)

TASKS

Blog post content

Draft: #12 (comment)

Publication & post-publication

It would be cool if the article could be cross-posted:

[Suggestion] Automatically convert .ipynb and .Rmd files in the user's repo to Dar

There are converters in https://github.com/stencila/convert which allow for conversion to/from various formats including Dar. For Articles (i.e. text documents) it uses Pandoc 2.1.3 (which has both a JATS reader and writer in it and happens to be the version of Pandoc in the Docker image already!)

npm install stencila/convert -g
cd dir
stencila-convert import .

where dir is the directory where the .ipynb or .Rmd file resides.

Fix serving static files through nbserverproxy

The dar-server does not know it is running behind a proxy so static files, e.g. fig1.jpg from the kitchen-sink example is attempted to be loaded at http://localhost:56159/archives/kitchen-sink/assets/fig1.jpg when looking at https://hub.mybinder.org/user/minrk-jupyter-dar-xrbh2i94/stencila/?token=qSWGGevBRg6ZCqkUP167Fg

dar-server seems to process the URLs here: https://github.com/substance/dar-server/blob/d45e17f40a68305f5077dcf0aa7491e21d39f0f2/src/serve.js#L46

[Suggestion] Change urlpath to just "stencila"

At the moment, the launch binder URL points to /stencila/ (which looks like %2Fstencila%2F in the URL bar).

For consistency (e.g. rstudio), I would suggest using just stencila without the leading and trailing slashes.

Probably related to #1.

RContext cannot be started

When manually POSTing (replace token!) to stencila-host for a new RContext, we get an error message:

 curl -X POST http://localhost:8888/stencila-host/RContext?token=4d7c2e8f0bc840019e1d3acfd268748398b6d8697366128f
Internal error: TypeError: Cannot read property 'servers' of undefined
    at Promise.resolve.then.then (/opt/stencila/node_modules/stencila-node/lib/host/Host.js:330:35)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

To replicate run

docker build --tag jupyter-dar-r .
docker run -p 8888:8888 jupyter-dar-r

using the branch rcontext of this repo and open Jupyter using the link in the console. Then start a new terminal for Jupyter and manually fix the manifest file created by stencila/r to use spawn instead of run property, resuting in

image

Then kill all processes of node stencila-host.js (there are several).

Running the span command manually does return a manifest that looks OK, but in Host.js that JSON does not seem to be parsed at all (manifest.servers gives Cannot read property 'servers' of undefined).

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.