flexxui / flexx

Write desktop and web apps in pure Python
http://flexx.readthedocs.io
BSD 2-Clause "Simplified" License
3.25k stars 258 forks source link

Running in Jupyter notebook / lab / other #253

Open almarklein opened 7 years ago

almarklein commented 7 years ago

The purpose of this issue is to get an idea of what's needed for Flexx to run inside environments like the notebook, JupyterLab, and other. What special measures does Flexx need to take, and what does Flexx need to know. Some things are already in place, but there are some loose ends.

Flexx needs to be made aware of certain aspects of the environment that it runs in. Sometimes its ok if the user provides this information (e.g. via app.init_notebook()), but the more we can automate, the better. If the server is aware of something, its easy to make the client aware too. The reverse is less true (the server might need the information before a connection is made).

I split this up aspects related to notebooks and Phosphor.

General

Since Flexx is embedded as part of an existing web page/app, there is no concept of a "Flexx app", and therefore must make use of the default session. E.g. app.init_notebook() takes care of this.

Notebooks

Notebooks can run in:

What Flexx needs to be able to detect:

Phosphor

If Flexx is loaded in an environment that already uses Phosphor, Flexx should probably use that version. This is a problem we're now facing with integrating Flexx with JLab, but could be an issue in general, especially if Phosphor gets more widely adopted.

For the JavaScript, Flexx ships its own phosphor-all.js in an AMD module. In one way or another, we can make Flexx make use of the available library instead of its own. For the CSS, Flexx ships its own phosphor-al.js (i.e. phosphor/styles/base.css). Fortunately, we can set this style DOM element to disabled if we know that Phosphor is already loaded.

How to determine if Phosphor is already loaded:

How to let Flexx reach the Phosphor lib:

Versioning: JLab uses a semver to determine compatibility. If what Flexx needs is not compatible with what JLab has, there will be an error.

Multiple Flexx "instances"

272

In JLab you can run multiple notebooks at the same time. Also, eventually we might have some plugins in JLab based on Flexx, while a user can use Flexx in a notebook. As it is now, things will break hard when this happens. Module names, class definitions, and instance id's...

Korijn commented 7 years ago

You could mirror the matplotlib approach? By default matplotlib just opens in new windows, even from a notebook, unless you apply the %matplotlib notebook magic to a notebook cell.

almarklein commented 7 years ago

Yeah, I guess that's equivalent to calling app.init_notebook(). But from that point on, there are still plenty of difficulties :)

Korijn commented 7 years ago
  • Client needs to know whether its running in an exported notebook. We now try to detect this by looking for the presence of window.IPython.foo.bar and window.jupyter.lab. This seems fragile though.

You could create an endpoint on the server to test if it's available. The client can then try to connect to it, assuming that it's in an exported notebook if the connection fails and app.init_notebook() was called.

If Flexx is loaded in an environment that already uses Phosphor, Flexx should probably use that version.

You have to make sure it's a supported version though; otherwise you have to fall back to the vendored copy of Phosphor.

How to determine if Phosphor is already loaded:

Industry best practices recommend feature detection; just try to make use of the library, and if you can't, assume it's not loaded.

Multiple Flexx "instances"

Make flexx.app instance-based rather than a global. :) That could tie in with #238

almarklein commented 7 years ago

Found a solution for detecting whether the notebook is exported by setting a flag that does not end up in the exported html.

Industry best practices recommend feature detection; just try to make use of [Phosphor], and if you can't, assume it's not loaded.

But how? Phosphor might be packaged with WebPack, an AMD module, a global ... and if its in WebPack, there is no way to load it unless there is a hook.

Multiple Flexx "instances"

Make flexx.app instance-based rather than a global. :) That could tie in with #238

Flexx can already serve multiple apps and sessions from the same process. What I mean here is one client that is connected to multiple Flexx servers. The problem is the global window.flexx.

Korijn commented 7 years ago

But how? Phosphor might be packaged with WebPack, an AMD module, a global ... and if its in WebPack, there is no way to load it unless there is a hook.

Touché, I am still more used to the old school world of script tags on a .html file...

Flexx can already severe multiple apps and sessions from the same process. What I mean here is one client that is connected to multiple Flexx servers. The problem is the global window.flexx.

Right, so the client needs to be aware of multiple servers... that'll get hairy very quickly.