Working Interactively with NotebookApp

[ ]:
from uuid import uuid4
import logging
from IPython.display import HTML, IFrame, SVG
from notebook.notebookapp import NotebookApp, web
from notebook.base.handlers import IPythonHandler
import ipywidgets as W
from tornado.httpclient import AsyncHTTPClient
[ ]:
PORT = 9999
TOKEN = str(uuid4())
[ ]:
app = NotebookApp()

The Magic Moment

[ ]:
app.initialize(["--port", f"{PORT}", f"--NotebookApp.token={TOKEN}"])




You're going to want to collapse that output.

It’s actually a little anticlimactic: once initialized, the app is already listening, as the IOLoop is already running, and the server is already listening on PORT

[ ]:
SVG(app.contents_manager.get("example.svg")["content"])

A little bit about logging

We’ll explore more here later. Extracted from this issue.

[ ]:
class LogViewer(logging.Handler):
    def __init__(self, output_widget, *args, **kwargs):
        logging.Handler.__init__(self, *args)
        for key, value in kwargs.items():
            if f"{key}" == "format":
                self.setFormatter(value)
        self.output_widget = output_widget

    def emit(self, record):
        w = self.output_widget
        msg = self.format(record)
        w.outputs = (dict(name="stdout", output_type="stream", text=f"{msg}\n"),) + w.outputs
[ ]:
output = W.Output()
app.log.addHandler(LogViewer(output))
output

Dynamically Adding a (Dyanmic) Handler

[ ]:
bar = W.IntSlider(99, description="bar")
bar
[ ]:
class Bar(IPythonHandler):
    re = r"^/foo/?$"
    @web.authenticated
    def get(self):
        self.finish("🍻" * bar.value)
app.web_app.add_handlers('.*', [[Bar.re, Bar]])

Use the right client

[ ]:
fetch = AsyncHTTPClient().fetch

Using a synchronous client, like vanilla requests, or the !curl magic, will deadlock your kernel (and app!).

[ ]:
(
    await fetch(f"http://localhost:{PORT}/foo/?token={TOKEN}")
).body.decode("utf-8")
[ ]:
bar.value = 1
[ ]:
(
    await fetch(f"http://localhost:{PORT}/foo/?token={TOKEN}")
).body.decode("utf-8")