Bokeh 1.3.0 Released

23 July 2019 / Bryan Van de Ven

We are pleased to announce the release of Bokeh 1.3!

This point release contains some new features. Highlights include:

  • Long asked-for FileInput widget is added. #6096
  • A brand new DataCube widget affords groups and aggregations of tabular data. #8100
  • The TextInput widget now has a new per-keystroke capability. #8676
  • Bug fixes to DataTable and DatePicker. #8015, #8921, #8923, #8934
  • A new User’s Guide section discussing securing Bokeh Server applications. #8919
  • Can now set source.data directly from DataFrames #9052

For full details, see the CHANGELOG and Release Notes. Additionally, examples for each release are uploaded to CDN. Click here to download.

If you are using Anaconda, Bokeh can most easily be installed by executing the command conda install -c bokeh bokeh . Otherwise, use pip install bokeh.


Before getting to the release itself, a few project announcements:

First, the next release will be the last release to support Python 2. After that, starting with Bokeh 2.0, Python 3.5 will be the minimum supported Python version. We will publish a blog post soon outlining all expected Bokeh 2.0 changes.

Earlier this month, Bokeh passed 10k stars on GitHub and is about to pass 10k followers on Twitter. Thanks to everyone for your support and interest!

The Bokeh project has assumed direct control over the CDN that publishes BokehJS resources. This includes making a new base URL of cdn.bokeh.org the primary location going forward. All existing links to cdn.pydata.org will continue to function indefinitely, but users are encouraged to use the new URL starting immediately.

As a reminder, the Bokeh project has recently launched two new sites:

Both these sites are great resources for new and old users, please use and share them often!

We have also created a Project Bokeh page on LinkedIn. Anyone who has contributed to Bokeh may now list Bokeh on their own profile. There is not much content there yet, but we hope to ramp things up in the coming months.

As part of all this increased emphasis on outreach, we have had a sharp new logotype produced:

Please feel free to use this anytime you are sharing or writing about Bokeh.

Finally, the July Fundraiser is still ongoing! Although we have just recently met our original goal of 1000 USD, every bit helps offset operational costs (e.g. to keep the CDN running), so please donate if you can, or help spread the word:

Click to Donate to the Bokeh Project

THANK YOU to everyone who donates to Bokeh! We will make a wrap-up blog post about the July fundraising experience in the near future.

Now, on to new features!


New File Input Widget

Another old issue falls! With some inspiration from an existing Holoviews implementation, #6096 File Open Dialog was added. Some follow-on work by new contributor jbeanland helped improve and refine the initial version. Choose a file below, and watch the results update:

The FileInput can be configured with the standard HTML "accept" attribute, and reports back the base filename, mime type, and base64-encoded file contents:

file_input = FileInput(accept=".csv,.json,.txt")

callback = CustomJS(args=dict(para=para, file_input=file_input), code="""
    para.text = "<p><b>filename:</b> " + file_input.filename  + \
                "<p><b>number of lines:</b> " + atob(file_input.value).split('\\n').length
""")

file_input.js_on_change('value', callback)

 

Data Cube Widget for Aggregation

Recent new contrubutor jburgy really knocked it out of the park with sizeable PR to implement #8100 Option to collapse DataRable rows. The final result was actually an entirely new widget, DataCube. Consider that you are starting with data like this:

source = ColumnDataSource(data=dict(
    d0=['A', 'E', 'E', 'E', 'J', 'L', 'M'],
    d1=['B', 'D', 'D', 'H', 'K', 'L', 'N'],
    d2=['C', 'F', 'G', 'H', 'K', 'L', 'O'],
    px=[10,  20,  30,  40,  50,  60,  70 ],
))

Then the DataCube can produce a table with nested groupings or sub-groupings that you specify. It can evenly automatically aggregate those groups if you choose. Here is a DataCube based on the data above:

 

 

The code for the above example looks like this:

target = ColumnDataSource(data=dict(row_indices=[], labels=[]))

formatter = StringFormatter(font_style='bold')

columns = [
    TableColumn(field='d2', title='Name', width=40, sortable=False, formatter=formatter),
    TableColumn(field='px', title='Price', width=40, sortable=False),
]

grouping = [
    GroupingInfo(getter='d0', aggregators=[SumAggregator(field_='px')]),
    GroupingInfo(getter='d1', aggregators=[SumAggregator(field_='px')])
]

cube = DataCube(source=source, columns=columns, grouping=grouping, target=target)

 

Hover Highlight for Stacked Glyphs

The previous release saw the addition of some really useful new methods for stacking aligned areas. But a feature was missing: they did not work with a hover highlight! That deficiency has been corrected and now stacked areas can be hovered just like any other glyph:

p.varea_stack(names, x='index', source=df, color=brewer['Oranges'][N],
              hover_alpha=1.0, hover_color=brewer['Blues'][N])

 

Fine-Grained Text Input

Last, but not least, another new contributor russellburdt dropped in to add some additional capability to the existing TextInput widget. Now not only can you get the value when a user hits <enter>, you can also get value_input which is updated on every keystroke:


Many thanks to all the new contributors to helped make this great release!

As always, anyone interested in helping out should drop by the Dev Chat Channel and say hello!

Thanks,

Bryan Van de Ven