Giter Site home page Giter Site logo

bokeh / ipywidgets_bokeh Goto Github PK

View Code? Open in Web Editor NEW
19.0 17.0 9.0 797 KB

Allows embedding of Jupyter widgets in Bokeh applications.

License: BSD 3-Clause "New" or "Revised" License

Python 29.50% TypeScript 49.81% JavaScript 18.29% Shell 2.40%

ipywidgets_bokeh's Introduction

ipywidgets_bokeh

Support for using ipywidgets within Bokeh. Ipywidgets are normally used in Jupyter notebooks, but this project allows them to be embedded into a Bokeh application so that they can be used alongside and with Bokeh-based plots and Bokeh widgets. See the separate jupyter_bokeh library for support for using Bokeh plots and widgets in Jupyter and ipywidgets (the opposite case from what ipywidgets_bokeh supports).

ipywidgets_bokeh's People

Contributors

bryevdv avatar dependabot[bot] avatar govinda18 avatar jbednar avatar mattpap avatar ndmlny-cs avatar ndmlny-qs avatar peytondmurray avatar philippjfr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ipywidgets_bokeh's Issues

priorities roadmap

Below are issues grouped by similar topics. @philippjfr my priorities are heavily weighted to enhancing the development experience so that I can hunt new bugs, create features, fix previous bugs, and make releases.

@dharhas I'm seeing more issues around logging behavior and the lack of notifications when websockets messages are never received, or when a kernel dies because no websocket message is received. Creating the necessary fallback mechanisms would help development, and user reports on issues they may face.

We can use this issue to discuss direction, and how to make it easier for contributing and debugging.

Development experience

Examples/integrating other tools

Upgrades

Bug fixes (may be fixed by package upgrades above)

lost interaction between ipywidgets when wrapped into bokeh

When wrapping interconnected ipywidgets (e.g.: an IPyWidget.IntSlider with a ipyleaflet.Map.zoom) into an ipywidgets_bokeh, we lost the interaction between widgets.

Attempt to reproduce the issue:

from ipywidgets_bokeh import IPyWidget
import ipywidgets as widgets

from bokeh.layouts import row
from bokeh.plotting import curdoc
from ipyleaflet import Map, basemaps
from ipywidgets import jslink

m = Map(center=(46.01, 6.16), zoom=12, basemap=basemaps.Stamen.Terrain)
zoom_slider = widgets.IntSlider(description='Zoom level:', min=0, max=15, value=7)
jslink((zoom_slider, 'value'), (m, 'zoom'))

slider_wrapper = IPyWidget(widget=zoom_slider, width=600, height=400)
map_wrapper = IPyWidget(widget=m, width=600, height=400)


doc = curdoc()
doc.add_root(row(slider_wrapper, map_wrapper))

In the code above, the zoom slider should be connected with the zoom level into the ipywidgets map canvas.

Wrong widget protocol version

Panel: 0.12.1
Ipywidgets: 7.6.3
IPysheet: 0.4.4
IPykernel: 5.5.5
jupyter-bokeh: 3.0.2
ipywidgets-bokeh: 1.0.2

When navigating from "tab" 1 to "tab 2" in the app below I get.

ipywidgets_bokeh.js:95 Wrong widget protocol version: received protocol version '', but was expecting major version '2'

wrong-protocol.mp4
import ipysheet
import ipywidgets as ipw
import panel as pn

pn.extension("ipywidgets", sizing_mode="stretch_width")

def ipywidgets_example():
    return ipw.DatePicker(description='Date')

def ipysheet_example():
    slider = pn.widgets.FloatSlider(value=10, start=0, end=100)
    sheet = ipysheet.sheet()
    cell = ipysheet.cell(2,2, 10., read_only=True, background_color="whitesmoke")

    @pn.depends(slider, watch=True)
    def calculate(a):
        cell.value = a
        print("update", cell.value)

    return pn.Column(slider, sheet)

components = {
    "IPYSHEET": ipysheet_example(),
    "IPYWIDGETS": ipywidgets_example(),
}

def show(component):
    component = components[component]
    return component

select = pn.widgets.RadioButtonGroup(options=list(components.keys()))
show = pn.bind(show, component=select)

pn.template.FastListTemplate(
    main=[pn.Column(select,show)],
).servable()

Additional Context

Related to holoviz/panel#2633

Support binary messages

The ipyvolume_camera.py in the examples folder doesn't work correctly. the ipyvolume figure doesn't update after data change. It seems that ipywidgets uses binary messages to send array data, and ipywidgets_bokeh doesn't support binary messages yet.

Update dependencies

There are a few PRs from dependabot;

Making this issue to resolve the above PRs, and to ensure that the example in the repo runs given the new dependency versions.

UI cluttered while tring to use this library

Using the following code:

import panel as pn
from ipywidgets_bokeh import IPyWidget
from ipywidgets import FloatSlider
pn.extension()
angle = FloatSlider(min=0, max=360, value=0, step=1, description="Angle")
wrapper = IPyWidget(widget=angle, width=800, height=800)
pn.Row(wrapper)

resolved most times in the following UI clutter:
image

Ipygrid not working

Ipygrid is a really powerful table/ grid that would nice to be able to use with Panel. But unfortunately it does not work. Instead it raises an error.

image

Panel: 0.12.6
IpyKernel: 6.5.0
IpyWidgets_bokeh: 1.2.1
ipydatagrid: 1.1.7
bokeh: 2.4.2

Error: Could not create a view for model id 1e70e7bde1404f8e951efc9553a0289f
    y ipywidgets_bokeh.js:2
    promise callback*I</e.prototype.create_view/e.state_change< ipywidgets_bokeh.js:2
    promise callback*I</e.prototype.create_view ipywidgets_bokeh.js:2
    create_child_view ipywidgets_bokeh.js:2
    updateProcessor cellrenderer.ts:172
    initializeRenderer cellrenderer.ts:109
    render cellrenderer.ts:73
    render cellrenderer.ts:304
    state_change ipywidgets_bokeh.js:2
    promise callback*I</e.prototype.create_view/e.state_change< ipywidgets_bokeh.js:2
    promise callback*I</e.prototype.create_view ipywidgets_bokeh.js:2
    create_child_view ipywidgets_bokeh.js:2
    updateRenderers datagrid.ts:533
    render datagrid.ts:485
    state_change ipywidgets_bokeh.js:2
    promise callback*I</e.prototype.create_view/e.state_change< ipywidgets_bokeh.js:2
    promise callback*I</e.prototype.create_view ipywidgets_bokeh.js:2
    display_model ipywidgets_bokeh.js:2
    render ipywidgets_bokeh.js:2
    _render ipywidgets_bokeh.js:2
    render ipywidgets_bokeh.js:2
    render bokeh.min.js:496
    build bokeh.min.js:496
    renderTo bokeh.min.js:496
    f bokeh.min.js:584
    add_document_standalone bokeh.min.js:584
    add_document_from_session bokeh.min.js:586
    w bokeh.min.js:163
    embed_items bokeh.min.js:163
    embed_document script3:80
    fn script3:84
    fn script3:100
    safely bokeh.min.js:595
    fn script3:74
    EventListener.handleEvent* script3:104
    <anonymous> script3:105
from ipydatagrid import DataGrid
import panel as pn
import pandas as pd
from urllib.request import urlopen
import json

pn.extension("ipywidgets", sizing_mode="stretch_width")

def get_widget():

    url = "https://raw.githubusercontent.com/bloomberg/ipydatagrid/main/examples/cars.json"
    response = urlopen(url)
    json_data = response.read().decode('utf-8', 'replace')
    data = json.loads(json_data)

    df = (
        pd.DataFrame(data["data"])
        .drop("index", axis=1)
    )

    datagrid = DataGrid(df, selection_mode="cell")

    return datagrid

widget = get_widget()
component = pn.pane.IPyWidget(widget, height=500, width=500, sizing_mode="fixed")
pn.Column(
    "# IpyDatagrid",
    component,
    "is not shown",
).servable()

Run panel serve file.py --show to show investigate the error in the browser.

Crossposts: holoviz/panel#2641, https://github.com/bloomberg/ipydatagrid/issues/265d

Improve dev experience with custom ipywidgets

Currently, ipywidgets_bokeh fetches the js it needs to render the frontend of a widget from a configurable CDN that defaults to unpkg. This is fine if the ipywidget is published and easily available from somewhere, but if a user is developing a widget locally, they have to intercept the web requests made by ipywidgets_bokeh and serve the appropriate bundle. It isn't at all obvious for someone who isn't extremely comfortable with both ipywidgets and ipywidgets_bokeh why this needs to be done and what they need to do to get around it.

This issue is meant to start a discussion around what can be done to make the barrier to entry smaller here.

Ipywidget bokeh messes up jupyter lab css

Ipywidget bokeh does not seem to work well with jupyter lab's css. Whenever it is loaded on the page with lab's css, it messes up the css of the lab. Here is a simple reproducer:

import panel as pn
import ipywidgets_bokeh
import ipywidgets as w
pn.extension()
pn.Row(ipywidgets_bokeh.IPyWidget(widget=w.HTML("asd")))

image

Note that the above is just for a reproducer. My use case requires me to load some javascript extensions I need dynamically on the page. For now, a workaround for me is to to not load it when I am in an ipynb environment.

Not working with mapwidget.cesium: Class null not found in module @jupyter-widgets/[email protected]

I was trying out if Panel could work with mapwidget.cesium. But unfortunately it raised the exception

Class null not found in module @jupyter-widgets/[email protected]      ipywidgets_bokeh.js?v=59296d23d623ce0adf7675d22156e83b1248c8508135a65dd8a9e38c497e94a8:8 

image

Reproducible Example

pip install panel==0.14.1 ipywidgets-bokeh==1.3.0 mapwidget==0.1.2

Other versions: ipywidgets-8.0.5 jupyterlab-widgets-3.0.6 widgetsnbextension-4.0.6 anywidget-0.2.0

import os
import mapwidget.cesium as mapwidget
import panel as pn

pn.extension("ipywidgets")

try:
    token = os.environ['CESIUM_TOKEN']
except KeyError as ex:
    raise EnvironmentError(
        "CESIUM_TOKEN environment variable not set. "
        "Sign up for free and get a free Cesium token here https://ion.cesium.com/signup/"
        ) from ex

cesium_map = mapwidget.Map(center=[40.70605, -74.01177], altitude=600, height='600px', token=token)
pn.panel(cesium_map).servable()
panel serve mapwidget_app.py

Open: http://localhost:5006/mapwidget_app

panel and ipyleaflet errors (Wrong widgets protocol, Comm is already created)

Minimal example

import panel as pn
from ipyleaflet import Map, CircleMarker, MarkerCluster
from ipywidgets import Layout
pn.extension('ipywidgets')

mapcenter = [40.7, -74]
m =  Map(center=mapcenter, layout=Layout(width='400px', height='300px'))
points = []
for k in range(5):
    points.append(CircleMarker(location=[40.7 + 0.01, -74]))
cluster = MarkerCluster(markers=points)
m.add(cluster)

move = pn.widgets.FloatSlider(start=-74., end=-73.95, step=0.01)

@pn.depends(move)
def view_map(move):
    global cluster
    newcent = [40.7, move]
    m.center = newcent
    newmarks = []
    for k in range(5):
        newmarks.append(CircleMarker(location=[40.7 + 0.01, move]))
    cluster.markers = newmarks
    return m

only when executed via panel serve (testing this example in jupyter notebook is OK). After interaction with move slider, the map (initially shown properly) disappears and in development console there are multiple error messages of type:
Wrong widget protocol version: received protocol version '', but was expecting major version '2'
Uncaught (in promise) Error: Comm is already created
(thrown by ipywidgets_bokeh)

This happens with modules versions:
ipyleaflet: 0.18.1, 0.17.4
bokeh: 3.3.3
ipywidgets_bokeh: 1.5.0
panel: 1.3.6, 1.3.1
pyviz_comms: 2.3.2, 3.1.0
(tested in several conda or pip installed virtual environments)

Consolidate `.gitignore` files

Currently there are two .gitignore files.

  • .gitignore
  • ipywidgets_bokeh/.gitignore

I don't see a good reason to keep both, and will help with #75

version value

@mattpap or @philippjfr do you have a preferred way for updating version information? Currently the DEVGUIDE.md shows the following.

Update package version

File Entry Content
ipywidgets_bokeh/__init__.py __version__ 1.0.0dev2
ipywidgets_bokeh/kernel.py implementation_version 1.0.0dev2
ipywidgets_bokeh/package.json version 1.0.0-dev.2
setup.py version 1.0.0dev2

This is a lot of spots where one needs to update this info. I can make something that models the preferred way of propagating this info into all the requisite spots. Just point me to what you want and I'll make a PR for it.

Panel Matplotlib pane fails when interactive=True

I was directed to file an issue here from https://discourse.holoviz.org/t/matplotlib-pane-throwing-attributeerror-when-interactive-true/2911

The minimal app:

import panel as pn
from matplotlib import pyplot as plt

fig, ax = plt.subplots()
ax.plot([0,1,2], [2,2,4])
pn.pane.plot.Matplotlib(fig, interactive=True).show()

works when

    - ipykernel<6  
    - ipympl==0.7.0  
    - panel<=0.12.1  

But I have discovered that even with these versions, the app crashes when the page is reloaded.
If I run it via docker, the panes displays correctly the first time the app spins up, but subsequent sessions will display horizontally squished panes:

Capture

where the first session dies with trace:

HTTPServerRequest(protocol='http', host='localhost:58471', method='GET', uri='/', version='HTTP/1.1', remote_ip='::1')
Traceback (most recent call last):
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\traitlets\traitlets.py", line 537, in get
    value = obj._trait_values[self.name]
KeyError: 'layout'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\tornado\web.py", line 1704, in _execute
    result = await result
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\panel\io\server.py", line 206, in get
    session = await self.get_session()
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\bokeh\server\views\session_handler.py", line 120, in get_session
    session = await self.application_context.create_session_if_needed(session_id, self.request, token)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\bokeh\server\contexts.py", line 218, in create_session_if_needed
    self._application.initialize_document(doc)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\panel\io\server.py", line 172, in initialize_document
    super().initialize_document(doc)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\bokeh\application\application.py", line 171, in initialize_document
    h.modify_document(doc)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\bokeh\application\handlers\function.py", line 132, in modify_document
    self._func(doc)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\panel\io\server.py", line 81, in _eval_panel
    doc = as_panel(panel)._modify_doc(server_id, title, doc, location)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\panel\viewable.py", line 244, in _modify_doc
    return self.server_doc(doc, title, location)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\panel\viewable.py", line 794, in server_doc
    model = self.get_root(doc)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\panel\pane\base.py", line 265, in get_root
    root = self._get_model(doc, comm=comm)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\panel\pane\plot.py", line 192, in _get_model
    manager = self._get_widget(self.object)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\panel\pane\plot.py", line 178, in _get_widget
    canvas = Canvas(fig)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipympl\backend_nbagg.py", line 163, in __init__
    DOMWidget.__init__(self, *args, **kwargs)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipywidgets\widgets\widget.py", line 415, in __init__
    self.open()
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipywidgets\widgets\widget.py", line 428, in open
    state, buffer_paths, buffers = _remove_buffers(self.get_state())
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipywidgets\widgets\widget.py", line 518, in get_state
    value = to_json(getattr(self, k), self)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\traitlets\traitlets.py", line 577, in __get__
    return self.get(obj, cls)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\traitlets\traitlets.py", line 540, in get
    default = obj.trait_defaults(self.name)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\traitlets\traitlets.py", line 1580, in trait_defaults
    return self._get_trait_default_generator(names[0])(self)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\traitlets\traitlets.py", line 513, in default
    return self.make_dynamic_default()
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipywidgets\widgets\trait_types.py", line 168, in make_dynamic_default
    return self.klass(*(self.default_args or ()),
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipywidgets\widgets\widget.py", line 415, in __init__
    self.open()
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipywidgets\widgets\widget.py", line 438, in open
    self.comm = Comm(**args)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipykernel\comm\comm.py", line 57, in __init__
    self.open(data=data, metadata=metadata, buffers=buffers)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipykernel\comm\comm.py", line 91, in open
    self._publish_msg('comm_open',
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipykernel\comm\comm.py", line 66, in _publish_msg
    self.kernel.session.send(self.kernel.iopub_socket, msg_type,
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipywidgets_bokeh\kernel.py", line 80, in send
    self._trigger_change(event)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipywidgets_bokeh\kernel.py", line 103, in _trigger_change
    self.document.callbacks.trigger_on_change(event)
AttributeError: 'Document' object has no attribute 'callbacks'

failure to import

from ipywidgets_bokeh import IPyWidget
---------------------------------------------------------------------------
MultipleInstanceError                     Traceback (most recent call last)
<ipython-input-1-260606c01c5a> in <module>
----> 1 from ipywidgets_bokeh import IPyWidget

~/dev/ipywidgets_bokeh/ipywidgets_bokeh/__init__.py in <module>
----> 1 from .ipy_widget import IPyWidget

~/dev/ipywidgets_bokeh/ipywidgets_bokeh/ipy_widget.py in <module>
     11 from ipywidgets import embed, Widget
     12 
---> 13 from .kernel import kernel
     14 
     15 class IPyWidget(HTMLBox):

~/dev/ipywidgets_bokeh/ipywidgets_bokeh/kernel.py in <module>
     74             self.shell_handlers[msg_type] = getattr(self.comm_manager, msg_type)
     75 
---> 76 kernel = BokehKernel.instance()

~/opt/anaconda3/lib/python3.7/site-packages/traitlets/config/configurable.py in instance(cls, *args, **kwargs)
    421             raise MultipleInstanceError(
    422                 'Multiple incompatible subclass instances of '
--> 423                 '%s are being created.' % cls.__name__
    424             )
    425 

MultipleInstanceError: Multiple incompatible subclass instances of BokehKernel are being created.

with release as well as latest

ipywidgets_bokeh not loading ipython

When instantiating a MatplotlibPane in Panel, I get an attribute error.

import panel as pn
from matplotlib import pyplot as plt

fig, ax = plt.subplots()
ax.plot([0,1,2], [2,2,4])
pn.pane.plot.Matplotlib(fig, interactive=True).show()

Raises

...
  File "/home/jovyan/conda-envs/pmat/lib/python3.9/site-packages/panel/pane/plot.py", line 170, in _get_widget
    from ipympl.backend_nbagg import FigureManager, Canvas, is_interactive
  File "/home/jovyan/conda-envs/pmat/lib/python3.9/site-packages/ipympl/__init__.py", line 27, in <module>
    matplotlib.use('module://ipympl.backend_nbagg')
  File "/home/jovyan/conda-envs/pmat/lib/python3.9/site-packages/matplotlib/__init__.py", line 1080, in use
    plt.switch_backend(name)
  File "/home/jovyan/conda-envs/pmat/lib/python3.9/site-packages/matplotlib/pyplot.py", line 277, in switch_backend
    class backend_mod(matplotlib.backend_bases._Backend):
  File "/home/jovyan/conda-envs/pmat/lib/python3.9/site-packages/matplotlib/pyplot.py", line 278, in backend_mod
    locals().update(vars(importlib.import_module(backend_name)))
  File "/home/jovyan/conda-envs/pmat/lib/python3.9/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "/home/jovyan/conda-envs/pmat/lib/python3.9/site-packages/ipympl/backend_nbagg.py", line 431, in <module>
    ip.events.register('post_execute', flush_figures)
AttributeError: 'NoneType' object has no attribute 'events'

I have tried implementing the pull request suggested in https://discourse.holoviz.org/t/matplotlib-pane-throwing-attributeerror-when-interactive-true/2911/6

but then I get errors:

ERROR:fake:Invalid Message
Traceback (most recent call last):
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\ipykernel\kernelbase.py", line 312, in dispatch_shell
    msg = self.session.deserialize(msg, content=True, copy=False)
  File "C:\Users\nchvg\Miniconda3\envs\optisoil-engineering-tools\lib\site-packages\jupyter_client\session.py", line 1048, in deserialize
    raise ValueError("Duplicate Signature: %r" % signature)
ValueError: Duplicate Signature: b'9b25b08aacbdc8c77ef9f91368742482787dd5afe83a7a6872bb7f3e1366b335'

Here is my env:

bokeh                     2.4.0            py38haa244fe_0    conda-forge
ipykernel                 6.4.1            py38h595d716_0    conda-forge
ipympl                    0.8.0              pyhd8ed1ab_0    conda-forge
ipython                   7.28.0           py38h595d716_0    conda-forge
ipython_genutils          0.2.0                      py_1    conda-forge
ipywidgets                7.6.5              pyhd8ed1ab_0    conda-forge
ipywidgets-bokeh          1.2.1                    pypi_0    pypi
jupyter_client            7.0.6              pyhd8ed1ab_0    conda-forge
jupyter_core              4.8.1            py38haa244fe_0    conda-forge
jupyterlab_pygments       0.1.2              pyh9f0ad1d_0    conda-forge
jupyterlab_widgets        1.0.2              pyhd8ed1ab_0    conda-forge

bokeh-2.4.0 (server) fails to render ipywidgets

Trying to run the ipyleaflet_tiles.py I got the following error:

  File "/home/epinux/.local/lib/python3.9/site-packages/ipywidgets_bokeh/kernel.py", line 67, in send
    self._trigger_change(event)
  File "/home/epinux/.local/lib/python3.9/site-packages/ipywidgets_bokeh/kernel.py", line 83, in _trigger_change
    self.document._trigger_on_change(event)
AttributeError: 'Document' object has no attribute '_trigger_on_change'

full log: https://gist.github.com/epifanio/7f930b959684fe71f73c75bc65488f1c

The same code works running bokeh 2.3.2, I tried to upgrade [ipywidgets, ipywidgets_bokeh] to the latest releases, but the error persists.

Using nglview ipywidget

I'd like to use the nglview widget in a bokeh application.

I'm using bokeh 2.0.2 (bokeh channel) and ipywidgets 1.0.0 (bokeh channel)

from bokeh.plotting import curdoc
from bokeh.layouts import column

from ipywidgets_bokeh import IPyWidget
import nglview

view = nglview.show_pdbid("3pqr")
wrapper = IPyWidget(widget=view, width=800, height=800)

layout = column(wrapper)

doc = curdoc()
doc.add_root(layout)

If i run this with bokeh serve I get the following error in the browser console:

TypeError: "buffers is undefined"
    widgets 2.7.5/dist/index.js:116602
    _handleCommMsg http://localhost:5006/static/extensions/ipywidgets_bokeh/ipywidgets_bokeh.js:69
    _handleMessage http://localhost:5006/static/extensions/ipywidgets_bokeh/ipywidgets_bokeh.js:69

See also holoviz/panel#1307

v1.0.2 Release

@mattpap Any chance we could release my latest changes here? Also it looks like 1.0.1 was never tagged.

Only one widget gets displayed with ipyvuetify - Error: Comm is already created

panel==0.12.1
ipywidgets==7.6.3
ipywidgets-bokeh==1.0.2
ipykernel==5.5.5
ipyvue==1.5.0
ipyvuetify==1.8.1
jupyterlab==3.0.0

Description

When creating a pn.Row or pn.GridSpec with multiple ipyvuetify widgets, only one of them gets displayed.
The same thing happens for example when trying to display the same ipywidgets.Button twice - the same error is thrown.

Minimal steps to reproduce

In jupyter lab:

import ipyvuetify as v
import panel as pn

pn.extension()

button1 = v.Btn(class_="ma-4", children=["B1"])
button2 = v.Btn(class_="ma-4", children=["B2"])

row = pn.Row(button1, button2)
pn.panel(row).show()

Console output

This error gets thrown when this happens:

Uncaught (in promise) Error: Comm is already created
    at m.createComm (ipywidgets_bokeh.js:69)
    at au._create_comm (ipywidgets_bokeh.js:95)
    at ipywidgets_bokeh.js:95
    at Array.map (<anonymous>)
    at ipywidgets_bokeh.js:95
    at async au.render (ipywidgets_bokeh.js:95)
    at async lu._render (ipywidgets_bokeh.js:95)

HTML produced

<div class="bk" style="position: relative; display: block; left: 0px; top: 0px; width: 117px; height: 78px; margin: 0px;">
    <div class="bk" style="position: absolute; left: 5px; top: 5px; width: 97px; height: 68px; display: block;">
        <div class="lm-Widget p-Widget">
            <div class="vuetify-styles">
                <div data-app="true" class="v-application v-application--is-ltr theme--light" id="app">
                    <div class="v-application--wrap">
                        <button type="button" class="v-btn v-btn--contained theme--light v-size--default ma-4">
                            <span class="v-btn__content">B1</span></button></div></div></div></div></div>
    <div class="bk" style="position: absolute; left: 112px; top: 5px; width: 0px; height: 68px; display: block;"></div>
</div>

The last div class="bk" is where the second button is supposed to be, but as you can see it's empty.

not working with VegaFusionWidget: Error: [object ArrayBuffer] is not serializable

Panel: 0.12.6 vegafusion-jupyter: 0.0.2 vega-datasets 0.9.0 ipywidgets-bokeh 1.2.1

I'm trying to use the VegaFusionWidget ipywidget with Panel. See vega/vegafusion#62. But its raising the error below.

pip install panel vegafusion-jupyter vega-datasets ipywidgets_bokeh
import panel as pn
import altair as alt
from vega_datasets import data

pn.extension("ipywidgets", template="fast")

from vegafusion_jupyter import VegaFusionWidget

ACCENT = "#1f77b4"
PALETTE = [ACCENT, "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"]

if not "panel-vegafusion" in pn.state.cache:
    seattle_weather = pn.state.cache["panel-vegafusion"]=data.seattle_weather()
else:
    seattle_weather = pn.state.cache["panel-vegafusion"]

def get_chart(seattle_weather):
    brush = alt.selection(type='interval', encodings=['x'])

    bars = alt.Chart().mark_bar().encode(
        x='month(date):O',
        y='mean(precipitation):Q',
        opacity=alt.condition(brush, alt.OpacityValue(1), alt.OpacityValue(0.7)),
    ).add_selection(
        brush
    )

    line = alt.Chart().mark_rule(color='firebrick').encode(
        y='mean(precipitation):Q',
        size=alt.SizeValue(3)
    ).transform_filter(
        brush
    )

    return alt.layer(bars, line, data=seattle_weather)

chart = get_chart(seattle_weather)
vchart = VegaFusionWidget(chart)
pn.pane.IPyWidget(vchart).servable()

pn.state.template.param.update(
    site="Vegafusion", title="Interactive Big Data Apps with Crossfiltering",
    accent_base_color=ACCENT, header_background=ACCENT
)
$ panel serve 'panel_vegafusion_app.py'
2022-01-28 01:59:38,588 Starting Bokeh server version 2.4.2 (running on Tornado 6.1)
2022-01-28 01:59:38,596 User authentication hooks NOT provided (default user enabled)
2022-01-28 01:59:38,601 Bokeh app running at: http://localhost:5006/panel_vegafusion_app
2022-01-28 01:59:38,602 Starting Bokeh server with process id: 18208

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000029ABB811820>
msg_type comm_open
content {'data': {'state': {'_model_module': '@jupyter-widgets/base', '_model_module_version': '1.2.0', '_model_name': 'LayoutModel', '_view_count': None, '_view_module': '@jupyter-widgets/base', '_view_module_version': '1.2.0', '_view_name': 'LayoutView', 'align_content': None, 'align_items': None, 'align_self': None, 'border': None, 'bottom': None, 'display': None, 'flex': None, 'flex_flow': None, 'grid_area': None, 'grid_auto_columns': None, 'grid_auto_flow': None, 'grid_auto_rows': None, 'grid_column': None, 'grid_gap': None, 'grid_row': None, 'grid_template_areas': None, 'grid_template_columns': None, 'grid_template_rows': None, 'height': None, 'justify_content': None, 'justify_items': None, 'left': None, 'margin': None, 'max_height': None, 'max_width': None, 'min_height': None, 'min_width': None, 'object_fit': None, 
'object_position': None, 'order': None, 'overflow': None, 'overflow_x': None, 'overflow_y': None, 'padding': None, 'right': None, 'top': None, 'visibility': None, 'width': None}, 'buffer_paths': []}, 'comm_id': 'b6744b8551fd4011b0546411cdaf1ba7', 'target_name': 'jupyter.widget', 'target_module': None}
parent {}
header None
metadata {'version': '2.0.0'}
data {"header": {"msg_id": "e1061adc-4bea603cc82aeb2970e4f28d_18208_0", "msg_type": "comm_open", "username": "username", "session": "e1061adc-4bea603cc82aeb2970e4f28d", "date": "2022-01-28T00:59:45.793502Z", "version": "5.3"}, "msg_id": "e1061adc-4bea603cc82aeb2970e4f28d_18208_0", "msg_type": "comm_open", "parent_header": {}, "content": {"data": {"state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": 
null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, 
"height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null}, "buffer_paths": []}, "comm_id": "b6744b8551fd4011b0546411cdaf1ba7", "target_name": "jupyter.widget", "target_module": null}, "metadata": {"version": "2.0.0"}, "channel": "iopub"}       

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000029ABB811820>
msg_type comm_open
content {'data': {'state': {'_dom_classes': (), '_model_module': 'vegafusion-jupyter', '_model_module_version': '^0.0.2', '_model_name': 'VegaFusionModel', '_view_count': None, '_view_module': 'vegafusion-jupyter', '_view_module_version': '^0.0.2', '_view_name': 'VegaFusionView', 'client_vega_spec': None, 'comm_plan': None, 'debounce_max_wait': 60.0, 'debounce_wait': 30.0, 'download_source_link': None, 'full_vega_spec': None, 'layout': 'IPY_MODEL_b6744b8551fd4011b0546411cdaf1ba7', 'server_vega_spec': None, 'spec': '{\n  "config": {\n    "view": {\n  
    "continuousWidth": 400,\n      "continuousHeight": 300\n    }\n  },\n  "layer": [\n    {\n      "mark": "bar",\n      "encoding": {\n  
      "opacity": {\n          "condition": {\n            "value": 1,\n            "selection": "selector001"\n          },\n          "value": 0.7\n        },\n        "x": {\n          "field": "date",\n          "timeUnit": "month",\n          "type": "ordinal"\n        },\n        "y": {\n          "aggregate": "mean",\n          "field": "precipitation",\n          "type": "quantitative"\n        }\n      },\n      "selection": {\n        "selector001": {\n          "type": "interval",\n          "encodings": [\n            "x"\n          ]\n   
     }\n      }\n    },\n    {\n      "mark": {\n        "type": "rule",\n        "color": "firebrick"\n      },\n      "encoding": {\n    
    "size": {\n          "value": 3\n        },\n        "y": {\n          "aggregate": "mean",\n          "field": "precipitation",\n     
     "type": "quantitative"\n        }\n      },\n      "transform": [\n        {\n          "filter": {\n            "selection": "selector001"\n          }\n        }\n      ]\n    }\n  ],\n  "data": {\n    "url": "_vegafusion_data/vegafusion-7bd7f9dd903be78e727c1b52e745f4f17d1212dd.feather"\n  },\n  "$schema": "https://vega.github.io/schema/vega-lite/v4.17.0.json"\n}', 'verbose': False}, 'buffer_paths': []}, 'comm_id': '0582b62fd2c64638b4821fd5d8c4040d', 'target_name': 'jupyter.widget', 'target_module': None}
parent {}
header None
metadata {'version': '2.0.0'}
data {"header": {"msg_id": "e1061adc-4bea603cc82aeb2970e4f28d_18208_1", "msg_type": "comm_open", "username": "username", "session": "e1061adc-4bea603cc82aeb2970e4f28d", "date": "2022-01-28T00:59:45.799505Z", "version": "5.3"}, "msg_id": "e1061adc-4bea603cc82aeb2970e4f28d_18208_1", "msg_type": "comm_open", "parent_header": {}, "content": {"data": {"state": {"_dom_classes": [], "_model_module": "vegafusion-jupyter", "_model_module_version": "^0.0.2", "_model_name": "VegaFusionModel", "_view_count": null, "_view_module": "vegafusion-jupyter", "_view_module_version": "^0.0.2", "_view_name": "VegaFusionView", "client_vega_spec": null, "comm_plan": null, "debounce_max_wait": 60.0, "debounce_wait": 30.0, "download_source_link": null, "full_vega_spec": null, "layout": "IPY_MODEL_b6744b8551fd4011b0546411cdaf1ba7", "server_vega_spec": null, "spec": "{\n  \"config\": {\n    \"view\": {\n      \"continuousWidth\": 400,\n      \"continuousHeight\": 300\n    }\n  },\n  \"layer\": [\n    {\n      \"mark\": \"bar\",\n      \"encoding\": {\n        \"opacity\": {\n          \"condition\": {\n            \"value\": 1,\n            \"selection\": \"selector001\"\n          },\n          \"value\": 0.7\n        },\n        \"x\": {\n          \"field\": \"date\",\n          \"timeUnit\": \"month\",\n          \"type\": \"ordinal\"\n        },\n        \"y\": {\n          \"aggregate\": \"mean\",\n          \"field\": \"precipitation\",\n          \"type\": \"quantitative\"\n        }\n      },\n      \"selection\": {\n     
   \"selector001\": {\n          \"type\": \"interval\",\n          \"encodings\": [\n            \"x\"\n          ]\n        }\n      }\n 
   },\n    {\n      \"mark\": {\n        \"type\": \"rule\",\n        \"color\": \"firebrick\"\n      },\n      \"encoding\": {\n        \"size\": {\n          \"value\": 3\n        },\n        \"y\": {\n          \"aggregate\": \"mean\",\n          \"field\": \"precipitation\",\n          \"type\": \"quantitative\"\n        }\n      },\n      \"transform\": [\n        {\n          \"filter\": {\n            \"selection\": \"selector001\"\n          }\n        }\n      ]\n    }\n  ],\n  \"data\": {\n    \"url\": \"_vegafusion_data/vegafusion-7bd7f9dd903be78e727c1b52e745f4f17d1212dd.feather\"\n  },\n  \"$schema\": \"https://vega.github.io/schema/vega-lite/v4.17.0.json\"\n}", "verbose": false}, "buffer_paths": []}, "comm_id": "0582b62fd2c64638b4821fd5d8c4040d", "target_name": "jupyter.widget", "target_module": null}, "metadata": {"version": "2.0.0"}, "channel": "iopub"}
2022-01-28 01:59:46,288 WebSocket connection opened
2022-01-28 01:59:46,289 ServerConnection created

image

594.index.js:1 
        
       panicked at 'send_request function call failed: JsValue(Error: [object ArrayBuffer] is not serializable
Error: [object ArrayBuffer] is not serializable
    at f.to_serializable (http://localhost:5006/static/js/bokeh.min.js?v=b3e0592a1e90448fa40dcddd5cd5217dcd6b3c7dd368020f6a8e4be4fdd1adbdeb2824eb75ab4f5120c80dc7684f8ff2aa2f8b00d6f393108c96d2f6f2cf0297:195:1391)
    at l.[serialize] (http://localhost:5006/static/js/bokeh.min.js?v=b3e0592a1e90448fa40dcddd5cd5217dcd6b3c7dd368020f6a8e4be4fdd1adbdeb2824eb75ab4f5120c80dc7684f8ff2aa2f8b00d6f393108c96d2f6f2cf0297:200:458)
    at f.to_serializable (http://localhost:5006/static/js/bokeh.min.js?v=b3e0592a1e90448fa40dcddd5cd5217dcd6b3c7dd368020f6a8e4be4fdd1adbdeb2824eb75ab4f5120c80dc7684f8ff2aa2f8b00d6f393108c96d2f6f2cf0297:195:1042)
    at f.to_serializable (http://localhost:5006/static/js/bokeh.min.js?v=b3e0592a1e90448fa40dcddd5cd5217dcd6b3c7dd368020f6a8e4be4fdd1adbdeb2824eb75ab4f5120c80dc7684f8ff2aa2f8b00d6f393108c96d2f6f2cf0297:195:1169)
    at E.create_json_patch (http://localhost:5006/static/js/bokeh.min.js?v=b3e0592a1e90448fa40dcddd5cd5217dcd6b3c7dd368020f6a8e4be4fdd1adbdeb2824eb75ab4f5120c80dc7684f8ff2aa2f8b00d6f393108c96d2f6f2cf0297:165:9308)
    at r._document_changed (http://localhost:5006/static/js/bokeh.min.js?v=b3e0592a1e90448fa40dcddd5cd5217dcd6b3c7dd368020f6a8e4be4fdd1adbdeb2824eb75ab4f5120c80dc7684f8ff2aa2f8b00d6f393108c96d2f6f2cf0297:590:850)
    at _document_listener (http://localhost:5006/static/js/bokeh.min.js?v=b3e0592a1e90448fa40dcddd5cd5217dcd6b3c7dd368020f6a8e4be4fdd1adbdeb2824eb75ab4f5120c80dc7684f8ff2aa2f8b00d6f393108c96d2f6f2cf0297:590:162)
    at E._trigger_on_change (http://localhost:5006/static/js/bokeh.min.js?v=b3e0592a1e90448fa40dcddd5cd5217dcd6b3c7dd368020f6a8e4be4fdd1adbdeb2824eb75ab4f5120c80dc7684f8ff2aa2f8b00d6f393108c96d2f6f2cf0297:165:4698)
    at gg.bk_send (http://localhost:5006/static/extensions/ipywidgets_bokeh/ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2745297)
    at e.send (http://localhost:5006/static/extensions/ipywidgets_bokeh/ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2743285))', vegafusion-wasm/src/lib.rs:330:14

Stack:

Error
    at Object.G (https://unpkg.com/[email protected]/dist/594.index.js:1:7607)
    at __wbg_new_693216e109162396 (https://unpkg.com/vegafusion-jupyter@%5E0.0.2/dist/index.js:1:22417)
    at https://unpkg.com/[email protected]/dist/d0048f4ff7544ce1ea76.module.wasm:wasm-function[2561]:0x3d8a32
    at https://unpkg.com/[email protected]/dist/d0048f4ff7544ce1ea76.module.wasm:wasm-function[5005]:0x4491e5
    at https://unpkg.com/[email protected]/dist/d0048f4ff7544ce1ea76.module.wasm:wasm-function[3646]:0x42ed5b
    at https://unpkg.com/[email protected]/dist/d0048f4ff7544ce1ea76.module.wasm:wasm-function[3935]:0x43bbbf
    at https://unpkg.com/[email protected]/dist/d0048f4ff7544ce1ea76.module.wasm:wasm-function[4371]:0x445b30
    at https://unpkg.com/[email protected]/dist/d0048f4ff7544ce1ea76.module.wasm:wasm-function[4417]:0x4463d7
    at https://unpkg.com/[email protected]/dist/d0048f4ff7544ce1ea76.module.wasm:wasm-function[3974]:0x43ceec
    at https://unpkg.com/[email protected]/dist/d0048f4ff7544ce1ea76.module.wasm:wasm-function[1422]:0x33ce35


nn @ 594.index.js:1
ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2 
        
       Error: Could not create a view for model id 0582b62fd2c64638b4821fd5d8c4040d
    at ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2087124
(anonymous) @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2 
        
       Error: Could not create view
    at ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2087124
    at async gg.render (ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2744026)
    at async _g._render (ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2744950)
(anonymous) @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
2d0048f4ff7544ce1ea76.module.wasm:0x42ed91 
        
       Uncaught (in promise) RuntimeError: unreachable
    at d0048f4ff7544ce1ea76.module.wasm:0x42ed91
    at d0048f4ff7544ce1ea76.module.wasm:0x43bbbf
    at d0048f4ff7544ce1ea76.module.wasm:0x445b30
    at d0048f4ff7544ce1ea76.module.wasm:0x4463d7
    at d0048f4ff7544ce1ea76.module.wasm:0x43ceec
    at d0048f4ff7544ce1ea76.module.wasm:0x33ce35
    at d0048f4ff7544ce1ea76.module.wasm:0x1714ab
    at d0048f4ff7544ce1ea76.module.wasm:0x43abec
    at d.J [as render_vegafusion] (594.index.js:1:4972)
    at d.value_changed (index.js:1:14547)

Describe how to debug ipywidgets_bokeh together with an Ipywidgets widgets.

I can only do very primitive debugging as in https://github.com/martinRenou/ipycanvas/issues/236 which means that I cannot really find cause of errors like in #44.

I would like some documentation that shows how I could configure and debug an example like the below. To find the cause of the above error. Otherwise I would depend on someone from this project or the specific Ipywidgets project to identify the cause and fix it.

# pip install ipycanvas panel ipywidgets_bokeh
import panel as pn
from ipycanvas import Canvas

pn.extension('ipywidgets')

canvas = Canvas(width=200, height=200)

# Cubic curves example
button = pn.widgets.Button(name="run")
@pn.depends(button.param.clicks, watch=True)
def draw(clicks):
    print("draw begin")
    canvas.begin_path()
    canvas.move_to(75, 40)
    canvas.bezier_curve_to(75, 37, 70, 25, 50, 25)
    canvas.fill()
    print("draw end")

pn.Column(
    button,
    pn.panel(canvas, height=200, width=200)
).servable()

IpyCanvas raising errors

Panel: 0.12.6 Bokeh: 2.4.2 ipywidgets_bokeh: 1.2.1 ipycanvas: 0.10.2 ipykernel: 6.6.0

Raises expected a string or ArrayBuffer, got object.

image

# pip install ipycanvas panel ipywidgets_bokeh
import panel as pn
from ipycanvas import Canvas

pn.extension('ipywidgets')

canvas = Canvas(width=200, height=200)

# Cubic curves example
def draw():
    canvas.begin_path()
    canvas.move_to(75, 40)
    canvas.bezier_curve_to(75, 37, 70, 25, 50, 25)
    canvas.bezier_curve_to(20, 25, 20, 62.5, 20, 62.5)
    canvas.bezier_curve_to(20, 80, 40, 102, 75, 120)
    canvas.bezier_curve_to(110, 102, 130, 80, 130, 62.5)
    canvas.bezier_curve_to(130, 62.5, 130, 25, 100, 25)
    canvas.bezier_curve_to(85, 25, 75, 37, 75, 40)
    canvas.fill()
    print("drawn")

pn.state.onload(draw)

pn.panel(canvas, height=200, width=200).servable()

Ipywidgets not getting rendered in Panel accordion

Ipywidgets don't get rendered when using inside a Panel accordion.

Panel version : 1.2.4
Bokeh version : 3.3.0

Reproducer :

import panel as pn
import ipywidgets as ipw
pn.extension()
basic_view_btn = ipw.Button(description="Click me")
accordion = pn.Accordion(
    ('Button', pn.Row(basic_view_btn)),
    ('Panel Button', pn.Row(pn.widgets.Button(name='hello')))
)
accordion.servable()

Output :
image

Console Error :
image

Controller widget not working

Dear team,

I'm trying to serve the Ipywidget for Gamepad control through Panel (v11.3) using the ipywidgets_bokeh wrapper in order to get gamepad input back to the backend server. The mechanism works fine for other widgets like sliders etc.

I have the impression there is an initialization problem (this widget is dynamic as it defines its buttons and axes on first use) and I suspect an issue with serialization/deserialization. Instead of Button or Axes objects with numbers the backend gets similar IPY_MODEL_xxxxx inputs that are ok for the controller object as such. The widget is fully functional and displaying/reacting on the frontend.

I've had a look at the py and js files, but without an expert developer eye there is just too many stuff happening there for me to find the possible issue.

Does any of you have a clue on what may be going wrong and how to correct it?

Kind regards

Wim

RangeSlider not displaying correctly

I've been trying to incorporate the range sliders from ipywidgets into my bokeh plot since the default bokeh widgets don't allow for user to type precise values. The example file uses a FloatSlider which has no issues with bokeh plots. For some reason the IntRangeSlider and the FloatRangeSlider don't work the same way.

Reproducible example below

from bokeh.io import output_notebook, show

from ipywidgets_bokeh import IPyWidget

import ipywidgets as ipw

output_notebook()

test_slider = ipw.IntRangeSlider(value=[5,7], min=0, max=10)
wrapper = IPyWidget(widget=test_slider)

#display(test_slider)
# shows a range slider populated between 5 and 7

show(wrapper)
#shows a slider with the knob fixed at the left displaying a value of NaN

An image of the returned slider.
image

In the browser console, it is outputting the following error when I try and interact with the widget. Strangely enough it allows me to click on the NaN value and type values. Once I type something, it begins to behave like a normal slider (no range).

VM279:302 Uncaught TypeError: Cannot read property 'toggleClass' of undefined
    at e.<computed>.<computed>._toggleClass (eval at <anonymous> (output_binary.js?vrz=colab-20210413-060132-RC00_368166360:1), <anonymous>:302:5975)
    at e.<computed>.<computed>._addClass (eval at <anonymous> (output_binary.js?vrz=colab-20210413-060132-RC00_368166360:1), <anonymous>:302:5784)
    at e.<computed>.<computed>._mouseCapture (eval at <anonymous> (output_binary.js?vrz=colab-20210413-060132-RC00_368166360:1), <anonymous>:315:2729)
    at e.<computed>.<computed>.eval [as _mouseCapture] (eval at <anonymous> (output_binary.js?vrz=colab-20210413-060132-RC00_368166360:1), <anonymous>:302:1025)
    at e.<computed>.<computed>._mouseDown (eval at <anonymous> (output_binary.js?vrz=colab-20210413-060132-RC00_368166360:1), <anonymous>:323:1076)
    at e.<computed>.<computed>.eval [as _mouseDown] (eval at <anonymous> (output_binary.js?vrz=colab-20210413-060132-RC00_368166360:1), <anonymous>:302:1025)
    at HTMLDivElement.eval (eval at <anonymous> (output_binary.js?vrz=colab-20210413-060132-RC00_368166360:1), <anonymous>:323:362)
    at HTMLDivElement.dispatch (eval at <anonymous> (output_binary.js?vrz=colab-20210413-060132-RC00_368166360:1), <anonymous>:287:39280)
    at HTMLDivElement.g.handle (eval at <anonymous> (output_binary.js?vrz=colab-20210413-060132-RC00_368166360:1), <anonymous>:287:37275)

I'm not very familiar with JavaScript so I'm not sure how to go about addressing this. Any help is appreciated. Thanks!

Not working with geemap

geemap enables users to use Google Earth Engine in Python Notebooks. See https://github.com/giswqs/geemap. I would like to be able to use geemap with Panel but I cannot as it raises errors in the browser console and the terminal.

I don't know if the issue is on ipywidgets_bokeh side or geemaps, so I've crossposted here gee-community/geemap#1101.

Reproducible example

pip install geemap==0.13.10 ipywidgets_bokeh==1.2.1 panel==0.13.1

Then panel serve script.py --autoreload --show where script.py contains

import geemap

map = geemap.Map(center=[40,-100], zoom=4)

import panel as pn

pn.extension("ipywidgets", template="fast")
pn.state.template.param.update(
  site="Awesome Panel", title="Panel + Geemap - Google Earth Engine Data Apps"
)

pn.panel(map).servable()

Then I see the errors

ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2 
        
       Error: Could not create a view for model id b97b1de12b934e639c9b914f53f0985f
    at ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2087124
(anonymous) @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
Promise.catch (async)
(anonymous) @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
Promise.then (async)
e.create_view @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
t.create_child_view @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
add_control_model @ Map.js:194
e.update @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
(anonymous) @ Map.js:233
Promise.then (async)
render_leaflet @ Map.js:231
Promise.then (async)
render @ Map.js:227
(anonymous) @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
Promise.then (async)
(anonymous) @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
Promise.then (async)
e.create_view @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
e.display_model @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
render @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
await in render (async)
_render @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
render @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
render @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:496
build @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:496
renderTo @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:496
f @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:584
await in f (async)
t.add_document_standalone @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:584
await in t.add_document_standalone (async)
t.add_document_from_session @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:586
await in t.add_document_from_session (async)
w @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:163
t.embed_items @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:163
await in t.embed_items (async)
embed_document @ script?theme=dark:286
(anonymous) @ script?theme=dark:289
(anonymous) @ script?theme=dark:305
o.safely @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:595
fn @ script?theme=dark:281
ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2 
        
       Error: Could not create child view
    at ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2087124
    at async Promise.all (:5006/index 0)
(anonymous) @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
Promise.catch (async)
t.create_child_view @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
add_control_model @ Map.js:194
e.update @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
(anonymous) @ Map.js:233
Promise.then (async)
render_leaflet @ Map.js:231
Promise.then (async)
render @ Map.js:227
(anonymous) @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
Promise.then (async)
(anonymous) @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
Promise.then (async)
e.create_view @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
e.display_model @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
render @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
await in render (async)
_render @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
render @ ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2
render @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:496
build @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:496
renderTo @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:496
f @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:584
await in f (async)
t.add_document_standalone @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:584
await in t.add_document_standalone (async)
t.add_document_from_session @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:586
await in t.add_document_from_session (async)
w @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:163
t.embed_items @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:163
await in t.embed_items (async)
embed_document @ script?theme=dark:286
(anonymous) @ script?theme=dark:289
(anonymous) @ script?theme=dark:305
o.safely @ bokeh.min.js?v=3c61e952b808bb7e346ce828a565a5f23aaf7708d034fa9d0906403813355d45bb4e8d8b0b23a93f032c76831d4f0221846f28699c7f5147caa62e0d31668314:595
fn @ script?theme=dark:281
ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2 
        
       Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'indexOf')
    at ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2459037
    at gg.Bl [as loader] (ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2459166)
    at ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2741052
    at new Promise (<anonymous>)
    at gg.loadClass (ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2740898)
    at ipywidgets_bokeh.js?v=206620a657f1ccc8af72b866fdcef20e641c48f39ce27f338ce8313949c63e53:2:2091629

image

and in the terminal

$ panel serve 'script.py' --autoreload --show
2022-06-12 11:07:23,557 Starting Bokeh server version 2.4.3 (running on Tornado 6.1)
2022-06-12 11:07:23,559 User authentication hooks NOT provided (default user enabled)
2022-06-12 11:07:23,560 Bokeh app running at: http://localhost:5006/script
2022-06-12 11:07:23,561 Starting Bokeh server with process id: 32072
2022-06-12 11:07:27,280 WebSocket connection opened
2022-06-12 11:07:27,281 ServerConnection created
2022-06-12 11:07:27,305 WebSocket connection opened
2022-06-12 11:07:27,306 ServerConnection created
2022-06-12 11:07:28,329 No such comm: 32d8eaaf587145428eaf87cde1e9eda1
2022-06-12 11:07:28,591 No such comm: 32d8eaaf587145428eaf87cde1e9eda1
2022-06-12 11:07:28,597 No such comm: 32d8eaaf587145428eaf87cde1e9eda1
2022-06-12 11:07:29,826 No such comm: 32d8eaaf587145428eaf87cde1e9eda1
2022-06-12 11:07:29,926 No such comm: 32d8eaaf587145428eaf87cde1e9eda1
2022-06-12 11:07:29,931 No such comm: 32d8eaaf587145428eaf87cde1e9eda1

Adding bokeh view information to ipywidget model

Given that bokeh (2.x) CSS layout engine needs a layout invalidation using view.invalidate_layout, it might be the case that an ipywidget needs to call the invalidate_layout method.

For example, if the view creation uses react rendering (react-widget-cookiecutter), it might be the case that the rendering inside the div is done after the component is mounted causing bokeh to mess up the layout.

It will be helpful to attach the bokeh view to the DOMWidgetModel so that a custom widget can use the bokeh view methods if need be when used in a bokeh environment.

Not working with anywidget: Class null not found in module @jupyter-widgets/[email protected]

anywidget is a new way of developing ipywidgets with a claim for being easier and more modern. For example mapwidget is built on top of anywidget.

I reported in #88 that mapwidget.cesium is not working with ipywidgets-bokeh and Panel. So I thought I would try out a basic anywidget example. And I can see that it raises the same issue.

Reproducible Example

pip install panel==0.14.4 ipywidgets-bokeh==1.3.0 anywidget==0.2.0

script.py

import anywidget
import traitlets

import panel as pn

pn.extension("ipywidgets")

class CounterWidget(anywidget.AnyWidget):
    _esm = """
    export function render(view) {
      let getCount = () => view.model.get("count");
      let button = document.createElement("button");
      button.classList.add("counter-button");
      button.innerHTML = `count is ${getCount()}`;
      button.addEventListener("click", () => {
        view.model.set("count", getCount() + 1);
        view.model.save_changes();
      });
      view.model.on("change:count", () => {
        button.innerHTML = `count is ${getCount()}`;
      });
      view.el.appendChild(button);
    }
    """
    _css="""
    .counter-button { background-color: #ea580c; }
    .counter-button:hover { background-color: #9a3412; }
    """
    count = traitlets.Int(0).tag(sync=True)

counter = CounterWidget()
pn.panel(counter).servable()
panel serve script.py

Open http://localhost:5006/script and see the exception in the browser console.

image

Class null not found in module @jupyter-widgets/[email protected]

issues handling bokeh message protocol

Not sure what is the cause, but after a rebuild of a working bokeh+ipywidgets docker environment - I am having the following error while running an ipyleaflet widget within a bokeh application:

bokeh_1  | 2021-07-15 14:47:20,754 error handling message
bokeh_1  |  message: Message 'PATCH-DOC' content: {'events': [{'kind': 'MessageSent', 'msg_type': 'ipywidgets_bokeh', 'msg_data': '{"buffers":[],"channel":"shell","content":{"comm_id":"5f6fb61e7c174d2d84b73bfafdd35ec3","data":{"method":"custom","content":{"event":"interaction","type":"mouseout","coordinates":[52.198611636156976,360.1245832443238]}}},"header":{"date":"2021-07-15T14:47:20.752Z","msg_id":"6068335f-bf37-4df8-896c-7e9a04bf3bf3","msg_type":"comm_msg","session":"86e52fc5-b439-4ddf-beb9-6ade95961403","username":"","version":"5.2"},"metadata":{},"parent_header":{}}'}], 'references': []} 
bokeh_1  |  error: TypeError('dispatch_shell() takes 2 positional arguments but 3 were given')
bokeh_1  | Traceback (most recent call last):
bokeh_1  |   File "/opt/venv/lib/python3.9/site-packages/bokeh/server/protocol_handler.py", line 90, in handle
bokeh_1  |     work = await handler(message, connection)
bokeh_1  |   File "/opt/venv/lib/python3.9/site-packages/bokeh/server/session.py", line 67, in _needs_document_lock_wrapper
bokeh_1  |     result = func(self, *args, **kwargs)
bokeh_1  |   File "/opt/venv/lib/python3.9/site-packages/bokeh/server/session.py", line 261, in _handle_patch
bokeh_1  |     message.apply_to_document(self.document, self)
bokeh_1  |   File "/opt/venv/lib/python3.9/site-packages/bokeh/protocol/messages/patch_doc.py", line 100, in apply_to_document
bokeh_1  |     doc._with_self_as_curdoc(lambda: doc.apply_json_patch(self.content, setter))
bokeh_1  |   File "/opt/venv/lib/python3.9/site-packages/bokeh/document/document.py", line 1198, in _with_self_as_curdoc
bokeh_1  |     return f()
bokeh_1  |   File "/opt/venv/lib/python3.9/site-packages/bokeh/protocol/messages/patch_doc.py", line 100, in <lambda>
bokeh_1  |     doc._with_self_as_curdoc(lambda: doc.apply_json_patch(self.content, setter))
bokeh_1  |   File "/opt/venv/lib/python3.9/site-packages/bokeh/document/document.py", line 398, in apply_json_patch
bokeh_1  |     self._trigger_on_message(event_json["msg_type"], event_json["msg_data"])
bokeh_1  |   File "/opt/venv/lib/python3.9/site-packages/bokeh/document/document.py", line 687, in _trigger_on_message
bokeh_1  |     cb(msg_data)
bokeh_1  |   File "/opt/venv/lib/python3.9/site-packages/ipywidgets_bokeh/kernel.py", line 75, in receive
bokeh_1  |     self.parent.dispatch_shell(stream, msg_list)
bokeh_1  | TypeError: dispatch_shell() takes 2 positional arguments but 3 were given
bokeh_1  | 2021-07-15 14:47:29,177 [pid 6] 1 clients connected

The log above is printed out from the shell where the docker environament is running, and it is printed when the mouse is hovering the map widget. I noticed it while attempting to capture the cursor position on the map-canvas.

To reproduce the error I used the following code /app/main.py:

from ipyleaflet import Map
from bokeh.plotting import curdoc
from ipywidgets_bokeh import IPyWidget
from bokeh.layouts import row, layout

curdoc_element = curdoc()

center = (52.204793, 360.121558)
m = Map(center=center, zoom=15)

wrap_map = IPyWidget(widget=m)
layout = row([wrap_map], height_policy='fit', sizing_mode='scale_both')
curdoc_element.add_root(layout)

below a dockerfile to reproduce the environment I am using

FROM python:3.9-slim-buster

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y apt-utils  build-essential
RUN apt-get install -y libproj-dev libgeos-dev proj-bin proj-data git

# Install dependencies:
COPY requirements.txt .
RUN pip install -U pip

RUN pip install ipyleaflet \
                bokeh \
                ipywidgets_bokeh

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

EXPOSE 7000

ENV ORIGIN="0.0.0.0:7000" PORT="7000" PREFIX="" LOG_LEVEL="debug"

ENTRYPOINT ["./entrypoint.sh"]

My Entry point looks like this:

bokeh serve --port ${PORT} --address 0.0.0.0 --allow-websocket-origin '*' ${PREFIX_PARAM} --log-level debug /app

Where app contains the python code (main.py)

Continue Bokeh 3.0 update

PR #51 began the work necessary for updating to Bokeh 3.0. @Hoxbro points out in PR #77 that we did not fully complete the updates required for Bokeh 3.0.

  • bump Bokeh versions
  • fix breaking changes from Bokeh 3.0 update

Wrong widget protocol version thrown when using an ipywidget in a callback

Hi,

I'm using panel and ipywidgets together, and whenever I do something related to ipywidgets from a callback function triggered by a panel widget, I've got this error : Wrong widget protocol version: received protocol version '', but was expecting major version '2' in the browser console

Expected behavior : No error

Simple program to reproduce :

import panel, ipywidgets

ipywidget = ipywidgets.Label(value="IPYWIDGET")
button = panel.widgets.Button(name='Actualiser')
test_box = ipywidgets.Box([])

def callback(value):
    something_happening_with_ipywidget = ipywidgets.Box([])

button.param.watch(callback, ['value'], onlychanged=True)

panel.Row(ipywidget, button).servable()

The error triggers only if I click the button, so it's not ipywidgets.Box([]) that's the cause of the error

I'm posting this here because it's thrown by ipywidgets_bokeh

PS : if I do not display any ipywidgets widget or if I don't do anything ipywidgets related in the callback, the error isn't thrown

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.