Skip to content

Commit

Permalink
Implement bokeh3 compatible layout (#1076)
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr authored Jun 5, 2023
1 parent d9bd81a commit d336e11
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 1 deletion.
50 changes: 49 additions & 1 deletion hvplot/interactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@

from .converter import HoloViewsConverter
from .util import (
_flatten, is_tabular, is_xarray, is_xarray_dataarray,
_flatten, bokeh3, is_tabular, is_xarray, is_xarray_dataarray,
_convert_col_names_to_str,
)

Expand Down Expand Up @@ -709,6 +709,11 @@ def layout(self, **kwargs):
to the center and widget location specified in the
interactive call.
"""
if bokeh3:
return self._layout_bk3(**kwargs)
return self._layout_bk2(**kwargs)

def _layout_bk2(self, **kwargs):
widget_box = self.widgets()
panel = self.output()
loc = self._loc
Expand Down Expand Up @@ -751,6 +756,49 @@ def layout(self, **kwargs):
components = [Column(panel, widgets)]
return Row(*components, **kwargs)

def _layout_bk3(self, **kwargs):
widget_box = self.widgets()
panel = self.output()
loc = self._loc
center = self._center
alignments = {
'left': (Row, ('start', 'center'), True),
'right': (Row, ('end', 'center'), False),
'top': (Column, ('center', 'start'), True),
'bottom': (Column, ('center', 'end'), False),
'top_left': (Column, 'start', True),
'top_right': (Column, ('end', 'start'), True),
'bottom_left': (Column, ('start', 'end'), False),
'bottom_right': (Column, 'end', False),
'left_top': (Row, 'start', True),
'left_bottom': (Row, ('start', 'end'), True),
'right_top': (Row, ('end', 'start'), False),
'right_bottom': (Row, 'end', False)
}
layout, align, widget_first = alignments[loc]
widget_box.align = align
if not len(widget_box):
if center:
components = [HSpacer(), panel, HSpacer()]
else:
components = [panel]
return Row(*components, **kwargs)

items = (widget_box, panel) if widget_first else (panel, widget_box)
sizing_mode = kwargs.get('sizing_mode')
if not center:
if layout is Row:
components = list(items)
else:
components = [layout(*items, sizing_mode=sizing_mode)]
elif layout is Column:
components = [HSpacer(), layout(*items, sizing_mode=sizing_mode), HSpacer()]
elif loc.startswith('left'):
components = [widget_box, HSpacer(), panel, HSpacer()]
else:
components = [HSpacer(), panel, HSpacer(), widget_box]
return Row(*components, **kwargs)

def holoviews(self):
"""
Returns a HoloViews object to render the output of this
Expand Down
27 changes: 27 additions & 0 deletions hvplot/tests/testinteractive.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
from hvplot import bind
from hvplot.interactive import Interactive
from hvplot.xarray import XArrayInteractive
from hvplot.util import bokeh3

is_bokeh2 = pytest.mark.skipif(bokeh3, reason="requires bokeh 2.x")
is_bokeh3 = pytest.mark.skipif(not bokeh3, reason="requires bokeh 3.x")


@pytest.fixture(scope='module')
Expand Down Expand Up @@ -1247,6 +1251,7 @@ def test_interactive_pandas_layout_default_no_widgets_kwargs(df):
assert layout.width == 200


@is_bokeh2
def test_interactive_pandas_layout_default_with_widgets(df):
w = pn.widgets.IntSlider(value=2, start=1, end=5)
dfi = Interactive(df)
Expand All @@ -1270,6 +1275,27 @@ def test_interactive_pandas_layout_default_with_widgets(df):
assert isinstance(layout[0][0][1], pn.layout.HSpacer)


@is_bokeh3
def test_interactive_pandas_layout_default_with_widgets_bk3(df):
w = pn.widgets.IntSlider(value=2, start=1, end=5)
dfi = Interactive(df)
dfi = dfi.head(w)

assert dfi._center is False
assert dfi._loc == 'top_left'

layout = dfi.layout()

assert isinstance(layout, pn.Row)
assert len(layout) == 1
assert isinstance(layout[0], pn.Column)
assert len(layout[0]) == 2
assert isinstance(layout[0][0], pn.Column)
assert isinstance(layout[0][1], pn.pane.PaneBase)
assert len(layout[0][0]) == 1
assert isinstance(layout[0][0][0], pn.widgets.IntSlider)

@is_bokeh2
def test_interactive_pandas_layout_center_with_widgets(df):
w = pn.widgets.IntSlider(value=2, start=1, end=5)
dfi = df.interactive(center=True)
Expand Down Expand Up @@ -1298,6 +1324,7 @@ def test_interactive_pandas_layout_center_with_widgets(df):
assert isinstance(layout[1][1][2], pn.layout.HSpacer)


@is_bokeh2
def test_interactive_pandas_layout_loc_with_widgets(df):
w = pn.widgets.IntSlider(value=2, start=1, end=5)
dfi = df.interactive(loc='top_right')
Expand Down
3 changes: 3 additions & 0 deletions hvplot/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from packaging.version import Version
from types import FunctionType

import bokeh
import numpy as np
import pandas as pd
import param
Expand All @@ -21,6 +22,8 @@
panel_available = False

hv_version = Version(hv.__version__)
bokeh_version = Version(bokeh.__version__)
bokeh3 = bokeh_version >= Version("3.0")


def with_hv_extension(func, extension='bokeh', logo=False):
Expand Down

0 comments on commit d336e11

Please sign in to comment.