jupyter-widgets / ipywidgets

Interactive Widgets for the Jupyter Notebook
https://ipywidgets.readthedocs.io
BSD 3-Clause "New" or "Revised" License
3.14k stars 948 forks source link

Base ipywidgets on Ypy/Yjs #3695

Open davidbrochart opened 1 year ago

davidbrochart commented 1 year ago

Problem

ipywidgets are currently collaborative in the sense that a change to a widget made in a frontend will propagate to every other frontend, but no conflict resolution in the change is done. For instance, we can imagine a widget implementing a text editor and two frontends inserting a different character at the same position simultaneously, that would result in one frontend having "ab" and the other "ba".

Proposed Solution

We should use CRDTs for synchronizing widgets, as we do in JupyterLab document collaboration. I have started ypywidgets and added support for it in jpterm.

https://user-images.githubusercontent.com/4711805/216942588-8c1325ef-1896-495a-a2c7-a39b0db5c9d8.mp4

bollwyvl commented 1 year ago

While I'm bullish on CRDTs at the interface, I'm lukewarm on adopting y-based stuff as the one true widgets implementation, as it adds a fairly non-trivial dependency and build chain.

Getting the above demo running in a jupyterlite/pyodide-based site would go a long way towards alleviating that specific concern.

Getting past "can i install it", such a change (which would certainly be a major release), then there would be the issues of:

davidbrochart commented 1 year ago

I would argue that the dependency/build chain issue will have to be solved anyway, otherwise JupyterLite will be stuck with JupyterLab<4.0 forever.

bollwyvl commented 1 year ago

JupyterLite will be stuck with JupyterLab<4.0

Will be stuck without RTC. Widgets will work well before then.

maartenbreddels commented 1 year ago

I am not sure about this change, but at the same time, quite interested in it!

I am not sure ipywidgets is the layer where this problem should be tackled. I think this should be the responsibility of the application layer (like the state management layer). I am not convinced having true collaborative widgets is a common use case. Having multiple frontends supported is great (such that changing a slider in 1 frontend will echo to the other), and we already have that working now in ipywidgets 8. But I do not think the situations where multiple people are in the same kernel playing with the same widget is a very common use case.

Happy to discuss this further, and happy to change my mind, but reluctant to change the relatively simple model we have now.

davidbrochart commented 1 year ago

I think CRDTs do a better job at delta-updates than we do. For instance if one element of a list has changed, then only that value change is emitted, instead of the whole list as in our current implementation. I also think that we will soon face the situation where the kernel is just another client modifying a shared document. For instance, we can imagine a JupyterLab (collaborative) notebook, and a kernel linting it as you type. Or a kernel programmatically modifying a JupyterCAD widget that could also be opened as a shared document (without a kernel) in a browser on another machine (@trungleduc is experimenting with this). The advantages of making JupyterLab shared documents and Jupyter widgets use the same infrastructure become obvious in that case.

bollwyvl commented 1 year ago

These are interesting cases, to be sure.

But before invalidating the entire existing widget ecosystem, this could be demonstrated by integrating along with those existing things. A ypy-traittypes package, similar to traittypes that gave folk the ability to use y-backed stuff for their specific cases would indeed be helpful.

class CadThinger(Widget):
    cad_file: whatever = YpyFileTrait(schema=however_you_get_this).tag(sync=true, **y_serialization)

CadThinger(cad_file=however_you_get_this)

If this cracks open another comm_id with its own comm_target, that doesn't mess with the existing one, can be serialized to a notebook's metadata, etc. then everything is great. If you can't install that package, you can't use widgets that use those traits.