Back to Interpret

stitch

python/stitch/README.md

0.7.826.1 KB
Original Source

stitch

Widget that handles bi-directional communication between user-defined JavaScript and the Jupyter kernel via a sandboxed iframe and postMessage.

It is very difficult to get kernel comms directly working across local and cloud environments without pushing users to install custom Jupyter widgets or extensions for each project. For restricted environments (corporate / medical) this isn't always achievable. stitch alleviates that by acting as general-purpose library where user-defined JavaScript can be rendered in Jupyter without the boilerplate.

Usage

Below is an example of a message being rendered in Jupyter passed from JavaScript and relayed back.

python
import stitch

w = stitch.StitchWidget()
w.srcdoc = """
<html>
<script>
// Ping 'kernelmsg' back to kernel as 'clientmsg'
window.addEventListener("message", function(event) {
  if (event.source === window.parent && event.data.type === "kernelmsg") {
    document.getElementById("msgview").innerHTML = event.data.content;
    window.parent.postMessage({type: "clientmsg", content: event.data.content}, "*");
  }
});

// Handle iframe resizing to fit content
window.addEventListener("load", function(){
  var prevHeight = 0;
  var prevWidth = 0;
  setInterval(function() {
    var body = document.body, html = document.documentElement;
    var height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
    var width = Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth);
    if (height !== prevHeight || prevWidth !== width) {
      msg = {type: 'resize', content: {height: height + 'px', width: width + 'px'}};
      window.parent.postMessage(msg, "*");
      prevHeight = height;
      prevWidth = width;
    }
  }, 100);
});
</script>
<body>
<div style="white-space:nowrap">
MESSAGE: <span id="msgview"></span>
</div>
</body>
</html>
"""
w

Send a kernel message to the client

python
# This will update all rendered widgets within Jupyter (including above)
w.kernelmsg = "Houston, we have a problem."
w

Our example sends pings the kernel message back to client.

python
assert w.clientmsg == "Houston, we have a problem."

stitch uses a custom DOMWidget, so you can monitor changes too.

python
w.observe(lambda x: print(x['new']), 'kernelmsg')
w.kernelmsg = "Wow, a change!"

The StitchWidget used throughout has the following state:

  • srcdoc - HTML to be rendered (in a sandboxed iframe) as the frontend
  • kernelmsg - Message sent via Jupyter kernel
  • clientmsg - Message sent from frontend
  • initial_height - Initial height of the sandboxed iframe
  • initial_width - Initial width of the sandboxed iframe
  • initial_border - Initial border of the sandboxed iframe

Installation

You can install using pip:

bash
pip install stitch

If you are using Jupyter Notebook 5.2 or earlier, you may also need to enable the nbextension:

bash
jupyter nbextension enable --py [--sys-prefix|--user|--system] stitch