I’m writing a Jupyter Extension Application that can be started with
jupyter myapp, but I’m not sure how I can run it on Binder.
I found a page that explains how to use some popular interfaces, which seems to come down to “it’s automatically available” for stuff such as classic notebooks or RStudio.
Then I looked over the documentation which mentions the
start file, but that needs to end in
exec so it seems you can’t just launch you own UI there.
Then I looked over some examples.
I found this example on how to enable extensions for JupyterLab, but I think that’s not what I need as mine is its own app, not an extension to lab: GitHub - binder-examples/jupyter-extension: Enabling jupyter extensions for use in Binder
Then I looked at the Bokeh example, but that seems to use a whole proxy setup. GitHub - binder-examples/bokeh
So now I’m not sure if for a Jupyter server extension app, it will just automatically work, I need to run some magic command to enable my extension app, or I need to proxy it.
I hit my two links per post limit. Here is the page on server extension apps: Server Extensions — Jupyter Server 1.14.0.dev0 documentation
And the docs about configuring the UI I saw: Configure the user interface — Binder 0.1b documentation
I suspect you have a port that it is served on. If that is the case if you install the Jupyter server proxy along with it in your repo, you can use the proxy port in the URL to open the correct page. At least that is what has been my experience in the past, like what is discussed in this thread.
I think once you know it works, you can somehow customize the server proxy for your app and use URLs that handle the port behind the scenes to make appropriate entrypoints but I haven’t done any of that myself yet. I believe it is covered in the Jupyter server proxy documentation.
Hm so when you run lab and nteract and classic notebooks, are nteract and classic notebooks just an extension to lab? Basically that’s exactly what I want to do.
I guess I could rewrite my app as a lab extension rather than its own app. Basically my app is JupyterLab, static pages, and a Bokeh app.
The main reason that outside Binder I want it to be an app is so that it has a nice entrypoint and the homepage is my app rather than /lab.
Somehow nteract is an extension that can be loaded into jupyterlab, yet also has its own entrypoint. How do I do just that?
Starting up a fresh cookiecutter it, will offer to build all of the boilerplate for a serverextension with a REST API.
_load_jupyter_server_extension, an extension can change the
ExtensionApplication.default_url and even have access to the underlying
As for bokeh: while I don’t have any examples of it, I don’t see why one wouldn’t be able to run some bokeh handlers on the same loop as jupyter server. Likely one could subclass
bokeh.server.Server and add in some special sauce to reuse the existing loop.
No, JupyterLab and the classic notebooks running via MyBinder aren’t extensions to each other as far as I know. I cannot comment on nteract.
The extension being talked with how to provide entrypoints without the
proxy/1315/-type stuff being necessary in the URL when you want to switch to your app is a server extension. Not a JupyterLab extension. It’s an extension to Jupyter Server which is described here as:
Jupyter Server is the backend—the core services, APIs, and REST endpoints—to Jupyter web applications. Jupyter Server is a replacement for the Tornado Web Server in Jupyter Notebook. Jupyter web applications should move to using Jupyter Server.
Okay so I followed the steps for distributing a server extension, and now if I install my package locally it shows up as an enabled server extension, and is available. I’ve also managed to enable the server proxy extension and use that together with a Bokeh server running on the Jupyter server IOLoop. So locally everything works perfectly now.
But on binder nothing works at all. The JSON file and Python module got installed and are importable, but listing the server extensions warns that it’s not importable. Huh?!
jovyan@jupyter-nyancad-2dpyttoresque-2dtemplates-2ddqyto6zs:~$ jupyter serverextension list
config dir: /srv/conda/envs/notebook/etc/jupyter
jupyter_resource_usage 0.6.1 OK
jupyterlab 3.2.5 OK
nteract_on_jupyter 2.1.3 OK
X is pyttoresque importable?
Python 3.7.12 | packaged by conda-forge | (default, Oct 26 2021, 06:08:53)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyttoresque
jovyan@jupyter-nyancad-2dpyttoresque-2dtemplates-2ddqyto6zs:~$ cat /srv/conda/envs/notebook/etc/jupyter/jupyter_server_config.d/jupyter-server-proxy-jupyterserverextension.json
jovyan@jupyter-nyancad-2dpyttoresque-2dtemplates-2ddqyto6zs:~$ cat /srv/conda/envs/notebook/etc/jupyter/jupyter_server_config.d/pyttoresque.json
My template repo: GitHub - NyanCAD/Pyttoresque-templates: Notebook templates for Pyttoresque simulations
My extension: GitHub - NyanCAD/Pyttoresque
Perhaps you’ve run aground on the transition between
jupyter lab (which you are running locally) and
jupyter notebook which is what binder runs.
The nickle fix on this is to deploy files to all of
etc/jupyter/jupyter_(notebook|server)_config.d, a la this extension.
Confusingly, these are reported by
jupyter server extension list (which your pacakging should be impacting) and
jupyter serverextension list (which you are assessing) for
Note that, correctly packaged, you shouldn’t even need your
postBuild but it is definitely useful in this case for listing things…
As to why your package is not importable… no idea. Since you have proxy installed, you could actually fire up a second instance of
jupyter notebook --debug from a terminal and watch the log spoor there…
Ah! It’s working! In addition to that I also needed to add this compat mechanism, which was the cause of the import error: Server Extensions — Jupyter Server 1.14.0.dev0 documentation
Now there are just a few minor nits to pick.
Currently I can only access Bokeh via the proxy URL. I tried to use
server_document but it gets confused about the URLs and tries to load stuff from the wrong place. Not the end of the world.
I’m currently starting Bokeh in
ExtensionApp.initialize_handlers which feels a bit improper. Most importantly, it seems that with the notebook server this gets called before starting the server, which means
io_loop is not yet set. I think in practice it doesn’t matter since they both use the default singleton IOLoop instance.
I noticed that jupyter-proxy-server adds launcher icons to JupyterLab if you configure it correctly. I should try to figure out how to do that for my app so there is an easy way to open it from JupyterLab.
jupyter-proxy-server adds launcher icons to JupyterLab
Welp… if you don’t need proxy, and your stuff can run (well) in-loop, then you might just need a very simple (e.g. close to one-liner
activate) launcher extension… but that would bring along the whole nodejs shooting match. Otherwise, yeah, proxy is pretty good for getting stuff up and going, and the new request rewriting stuff is great.