User interaction without bokeh widgets?

Here is how you can do it without using a Bokeh server. Make sure the data you want to update is in a ColumnDataSource you explicitly create, and make sure to set a name property on the CDS (can be whatever you want):

from bokeh.io import show
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure

x = [1, 2, 3, 4, 5]
y = [6, 7, 6, 4, 5]

source = ColumnDataSource(data=dict(x=x, y=y), name="MY_SOURCE")

p = figure(plot_width=300, plot_height=300)
p.line('x', 'y', source=source)
show(p)

That produces this:

Now in yout JavaScript event handlers, you can access the global Bokeh.index and use it to obtain the CDS you named, and update it:

The Bokeh.index is a “dict” that maps ids to Bokeh views, each of which has a model that corresponds the the Python side Bokeh object. In this case, the single Figure that was shown. The models also have a select_one method that lets you search for children objects by name (i.e. "MY_SOURCE" in this case). Once you have that data source, you can update it by re-assigning to source.data and the plot will update (you have to make a real assignment, if you update the data arrays “in place” then BokehJS won’t be able to pick up the change automatically).

If you have multiple plots/layouts on the same page you will have potentially need to look through all of the views in Bokeh.index to find what you are looking for. This is all a bit clunky which is why it has not been demonstrated widely.

Note: the JavaScript objects look fairly obfuscated because BokehJS is “minified” by default, to save space. For testing, you can set the environment variable BOKEH_MINIFIED=no and you will see much more human-readable output in the console.