diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index bc52ba55ff..d772228b58 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -58,7 +58,7 @@ jobs: with: name: unit_test_suite python-version: ${{ matrix.python-version }} - channels: pyviz/label/dev,bokeh,conda-forge,nodefaults + channels: pyviz/label/dev,bokeh/label/dev,conda-forge,nodefaults # Remove when Python 3.11 is well supported on latest conda/conda-forge. conda-update: ${{ matrix.python-version == '3.11' && 'false' || 'true' }} nodejs: true @@ -80,7 +80,7 @@ jobs: - name: Install bokeh 3.0 compatibility packages run: | conda activate test-environment - conda uninstall holoviews jupyter_bokeh --force -y --offline + conda uninstall holoviews jupyter_bokeh --force -y --offline || echo "packages already removed" pip install "git+https://github.com/holoviz/holoviews.git@bokeh3.0" pip install "git+https://github.com/bokeh/jupyter_bokeh.git" - name: doit env_capture diff --git a/panel/__init__.py b/panel/__init__.py index 52342d2552..3cfb1f868c 100644 --- a/panel/__init__.py +++ b/panel/__init__.py @@ -63,7 +63,7 @@ Accordion, Card, Column, FlexBox, GridBox, GridSpec, Row, Spacer, Tabs, WidgetBox, ) -from .pane import Pane, panel # noqa +from .pane import panel # noqa from .param import Param # noqa from .template import Template # noqa from .widgets import indicators, widget # noqa @@ -76,7 +76,6 @@ "FlexBox", "GridBox", "GridSpec", - "Pane", # deprecated "Param", "Row", "Spacer", diff --git a/panel/models/vtk.py b/panel/models/vtk.py index 5a4792f59c..1e89c6e22a 100644 --- a/panel/models/vtk.py +++ b/panel/models/vtk.py @@ -5,7 +5,7 @@ from bokeh.core.has_props import abstract from bokeh.core.properties import ( Any, Bool, Dict, Enum, Float, Instance, Int, List, Nullable, Override, - PositiveInt, String, + Positive, String, ) from bokeh.models import ColorMapper, Model @@ -25,7 +25,7 @@ class VTKAxes(Model): digits = Int(default=1) - fontsize = PositiveInt(default=12) + fontsize = Positive(Int, default=12) grid_opacity = Float(default=0.1) diff --git a/panel/package-lock.json b/panel/package-lock.json index 942ea00bfb..7bae9c2fef 100644 --- a/panel/package-lock.json +++ b/panel/package-lock.json @@ -9,7 +9,7 @@ "version": "0.14.2", "license": "BSD-3-Clause", "dependencies": { - "@bokeh/bokehjs": "^3.0.0", + "@bokeh/bokehjs": "^3.1.0-dev.1", "@luma.gl/constants": "^8.0.3", "@types/debounce": "^1.2.0", "@types/gl-matrix": "^2.4.5", @@ -25,9 +25,9 @@ } }, "node_modules/@bokeh/bokehjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-3.0.0.tgz", - "integrity": "sha512-QJRmGEbIiKEC0EK+oXDoTk3ix/ZgayBgfmSjlmR0v7LpJDMCg9fs86vgVPMUBRl6wnbgY3Kae0T9k3wviRfgkw==", + "version": "3.1.0-dev.1", + "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-3.1.0-dev.1.tgz", + "integrity": "sha512-EBXGvaGoV5TBBBDfNEDpd/AY/fYj67GhWHv7EqDCOH9d3eRFM7Bn1cbc7QnxE2umJRlUmu5Q3fbq6BlM220h+A==", "engines": { "node": ">=16.0", "npm": ">=8.0" @@ -96,9 +96,9 @@ }, "dependencies": { "@bokeh/bokehjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-3.0.0.tgz", - "integrity": "sha512-QJRmGEbIiKEC0EK+oXDoTk3ix/ZgayBgfmSjlmR0v7LpJDMCg9fs86vgVPMUBRl6wnbgY3Kae0T9k3wviRfgkw==" + "version": "3.1.0-dev.1", + "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-3.1.0-dev.1.tgz", + "integrity": "sha512-EBXGvaGoV5TBBBDfNEDpd/AY/fYj67GhWHv7EqDCOH9d3eRFM7Bn1cbc7QnxE2umJRlUmu5Q3fbq6BlM220h+A==" }, "@luma.gl/constants": { "version": "8.1.0" diff --git a/panel/package.json b/panel/package.json index d7ff11ff79..a48f6f13f6 100644 --- a/panel/package.json +++ b/panel/package.json @@ -8,7 +8,7 @@ "url": "https://github.com/holoviz/panel.git" }, "dependencies": { - "@bokeh/bokehjs": "^3.0.0", + "@bokeh/bokehjs": "^3.1.0-dev.1", "@luma.gl/constants": "^8.0.3", "@types/debounce": "^1.2.0", "@types/gl-matrix": "^2.4.5", diff --git a/panel/pane/__init__.py b/panel/pane/__init__.py index c5792580f5..3e8d699230 100644 --- a/panel/pane/__init__.py +++ b/panel/pane/__init__.py @@ -32,7 +32,7 @@ https://panel.holoviz.org/getting_started/index.html """ from .alert import Alert # noqa -from .base import Pane, PaneBase, panel # noqa +from .base import PaneBase, panel # noqa from .deckgl import DeckGL # noqa from .echarts import ECharts # noqa from .equation import LaTeX # noqa @@ -75,7 +75,6 @@ "LaTeX", "Markdown", "Matplotlib", - "Pane", "PaneBase", "panel", "PDF", diff --git a/panel/pane/base.py b/panel/pane/base.py index 8029a0045a..98abce63d5 100644 --- a/panel/pane/base.py +++ b/panel/pane/base.py @@ -24,7 +24,6 @@ from ..models import ReactiveHTML as _BkReactiveHTML from ..reactive import Reactive from ..util import param_reprs -from ..util.warnings import deprecated from ..viewable import ( Layoutable, ServableMixin, Viewable, Viewer, ) @@ -35,16 +34,6 @@ from pyviz_comms import Comm -def Pane(obj: Any, **kwargs) -> 'PaneBase': - """ - Converts any object to a Pane if a matching Pane class exists. - """ - deprecated("1.0", "panel.Pane", "panel.panel") - if isinstance(obj, Viewable): - return obj - return PaneBase.get_pane_type(obj, **kwargs)(obj, **kwargs) - - def panel(obj: Any, **kwargs) -> Viewable: """ Creates a panel from any supplied object by wrapping it in a pane diff --git a/panel/pane/holoviews.py b/panel/pane/holoviews.py index ffe74211f4..047a3e1255 100644 --- a/panel/pane/holoviews.py +++ b/panel/pane/holoviews.py @@ -24,7 +24,7 @@ ) from ..viewable import Layoutable, Viewable from ..widgets import Player -from .base import Pane, PaneBase, RerenderError +from .base import PaneBase, RerenderError, panel from .plot import Bokeh, Matplotlib from .plotly import Plotly @@ -397,7 +397,7 @@ def _get_model( return model def _get_pane(self, backend, state, **kwargs): - pane_type = self._panes.get(backend, Pane) + pane_type = self._panes.get(backend, panel) if isinstance(pane_type, type): if issubclass(pane_type, Matplotlib): kwargs['tight'] = True diff --git a/panel/pane/markup.py b/panel/pane/markup.py index 544df070b0..9cedf50a4c 100644 --- a/panel/pane/markup.py +++ b/panel/pane/markup.py @@ -14,7 +14,8 @@ import param from ..models import HTML as _BkHTML, JSON as _BkJSON -from ..util import escape, style_to_styles +from ..util import escape +from ..util.warnings import deprecated from ..viewable import Layoutable from .base import PaneBase @@ -43,7 +44,10 @@ class DivPaneBase(PaneBase): __abstract = True def __init__(self, object=None, **params): - params = style_to_styles(params) + if "style" in params: + # In Bokeh 3 'style' was changed to 'styles'. + params["styles"] = params.pop("style") + deprecated("1.1", "style", "styles") super().__init__(object=object, **params) def _get_properties(self): diff --git a/panel/pane/perspective.py b/panel/pane/perspective.py index 8f622296ad..eb1968f177 100644 --- a/panel/pane/perspective.py +++ b/panel/pane/perspective.py @@ -16,7 +16,6 @@ from ..reactive import ReactiveData from ..util import lazy_load -from ..util.warnings import deprecated from ..viewable import Viewable from .base import PaneBase @@ -281,16 +280,10 @@ class Perspective(PaneBase, ReactiveData): columns = param.List(default=None, doc=""" A list of source columns to show as columns. For example ["x", "y"]""") - computed_columns = param.List(default=None, precedence=-1, doc=""" - Deprecated alias for expressions.""") - expressions = param.List(default=None, doc=""" A list of expressions computing new columns from existing columns. For example [""x"+"index""]""") - column_pivots = param.List(None, precedence=-1, doc=""" - Deprecated alias of split_by.""") - split_by = param.List(None, doc=""" A list of source columns to pivot by. For example ["x", "y"]""") @@ -306,9 +299,6 @@ class Perspective(PaneBase, ReactiveData): group_by = param.List(default=None, doc=""" A list of source columns to group by. For example ["x", "y"]""") - row_pivots = param.List(default=None, precedence=-1, doc=""" - Deprecated alias of group_by.""") - selectable = param.Boolean(default=True, allow_None=True, doc=""" Whether items are selectable.""") @@ -334,9 +324,6 @@ class Perspective(PaneBase, ReactiveData): _rerender_params: ClassVar[List[str]] = ['object'] _rename: ClassVar[Mapping[str, str | None]] = { - 'computed_columns': None, - 'row_pivots': None, - 'column_pivots': None, 'selection': None, } @@ -348,12 +335,6 @@ class Perspective(PaneBase, ReactiveData): 'row_pivots': 'group_by' } - def __init__(self, object=None, **params): - super().__init__(object=object, **params) - self.param.watch(self._deprecated_warning, ['computed_columns', 'column_pivots', 'row_pivots']) - ps = [deprecation for deprecation in self._deprecations if deprecation in params] - self.param.trigger(*ps) - @classmethod def applies(cls, object): if isinstance(object, dict) and all(isinstance(v, (list, np.ndarray)) for v in object.values()): @@ -385,14 +366,6 @@ def _get_data(self): "converted to strings.") return df, {str(k): v for k, v in data.items()} - def _deprecated_warning(self, *events): - updates = {} - for event in events: - renamed = self._deprecations[event.name] - deprecated("1.0", event.name, renamed) - updates[renamed] = event.new - self.param.update(**updates) - def _filter_properties(self, properties): ignored = list(Viewable.param) return [p for p in properties if p not in ignored] @@ -462,12 +435,6 @@ def _process_property_change(self, msg): if prop not in msg: continue msg[prop] = [self._as_digit(col) for col in msg[prop]] - if prop == 'group_by': - msg['row_pivots'] = msg['group_by'] - if prop == 'split_by': - msg['column_pivots'] = msg['split_by'] - if 'expressions' in msg: - msg['computed_columns'] = msg['expressions'] if msg.get('sort'): msg['sort'] = [[self._as_digit(col), *args] for col, *args in msg['sort']] if msg.get('filters'): diff --git a/panel/tests/pane/test_deckgl.py b/panel/tests/pane/test_deckgl.py index f3980e530c..981270c941 100644 --- a/panel/tests/pane/test_deckgl.py +++ b/panel/tests/pane/test_deckgl.py @@ -9,7 +9,7 @@ pydeck_available = pytest.mark.skipif(pydeck is None, reason="requires pydeck") from panel.models.deckgl import DeckGLPlot -from panel.pane import DeckGL, Pane, PaneBase +from panel.pane import DeckGL, PaneBase, panel @pydeck_available @@ -21,7 +21,7 @@ def test_get_pydeck_pane_type_from_deck(): @pydeck_available def test_pydeck_pane_deck(document, comm): deck = pydeck.Deck(tooltip=True, api_keys={'mapbox': 'ABC'}) - pane = Pane(deck) + pane = panel(deck) # Create pane model = pane.get_root(document, comm=comm) diff --git a/panel/tests/pane/test_holoviews.py b/panel/tests/pane/test_holoviews.py index 580b644baf..083b2525a3 100644 --- a/panel/tests/pane/test_holoviews.py +++ b/panel/tests/pane/test_holoviews.py @@ -1,4 +1,5 @@ import datetime as dt +import warnings from collections import OrderedDict @@ -29,6 +30,7 @@ from panel.layout import Column, FlexBox, Row from panel.pane import HoloViews, PaneBase, panel from panel.tests.util import hv_available, mpl_available +from panel.util.warnings import PanelDeprecationWarning from panel.widgets import ( Checkbox, DiscreteSlider, FloatSlider, Select, ) @@ -671,11 +673,25 @@ def test_holoviews_link_within_pane(document, comm): assert range_tool.x_range == p2.x_range +@hv_available +def test_holoviews_property_override_old_method(document, comm): + c1 = hv.Curve([]) + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", PanelDeprecationWarning) + pane = pn.panel(c1, backend='bokeh', background='red', + css_classes=['test_class']) + model = pane.get_root(document, comm=comm) + + assert model.styles["background"] == 'red' + assert model.css_classes == ['test_class'] + @hv_available def test_holoviews_property_override(document, comm): c1 = hv.Curve([]) - pane = pn.panel(c1, backend='bokeh', background='red', + pane = pn.panel(c1, backend='bokeh', + styles={'background': 'red'}, css_classes=['test_class']) model = pane.get_root(document, comm=comm) diff --git a/panel/tests/pane/test_perspective.py b/panel/tests/pane/test_perspective.py index 708bc6b267..26f0c21480 100644 --- a/panel/tests/pane/test_perspective.py +++ b/panel/tests/pane/test_perspective.py @@ -13,7 +13,7 @@ def test_perspective_int_cols(document, comm): psp = Perspective( data, columns=[0], aggregates={0: 'mean'}, sort=[[0, 'desc']], - row_pivots=[0], column_pivots=[0], filters=[[0, '==', 'None']] + group_by=[0], split_by=[0], filters=[[0, '==', 'None']] ) model = psp.get_root(document, comm) @@ -37,8 +37,8 @@ def test_perspective_int_cols(document, comm): }) assert psp2.columns == [0] - assert psp2.row_pivots == [0] - assert psp2.column_pivots == [0] + assert psp2.group_by == [0] + assert psp2.split_by == [0] assert psp2.aggregates == {0: 'mean'} assert psp2.sort == [[0, 'desc']] assert psp2.filters == [[0, '==', 'None']] diff --git a/panel/tests/widgets/test_debugger.py b/panel/tests/widgets/test_debugger.py index dd5df4c8ec..0da8d1e72a 100644 --- a/panel/tests/widgets/test_debugger.py +++ b/panel/tests/widgets/test_debugger.py @@ -1,9 +1,12 @@ """This module contains tests of the Debugger""" import logging +import pytest + import panel as pn +@pytest.mark.xdist_group("debugger") def test_debugger_constructor(): debugger = pn.widgets.Debugger() @@ -17,6 +20,7 @@ def test_debugger_constructor(): assert repr(debugger).startswith("Debugger(") +@pytest.mark.xdist_group("debugger") def test_debugger_logging(): logger = logging.getLogger('panel.callbacks') debugger = pn.widgets.Debugger() @@ -36,6 +40,7 @@ def test_debugger_logging(): #TODO: test if debugger.terminal.output is cleared by JS callback. +@pytest.mark.xdist_group("debugger") def test_debugger_logging_info(): logger = logging.getLogger('panel.callbacks') debugger = pn.widgets.Debugger(level=logging.DEBUG) diff --git a/panel/tests/widgets/test_indicators.py b/panel/tests/widgets/test_indicators.py index 4c1ee57ef7..da743c9fee 100644 --- a/panel/tests/widgets/test_indicators.py +++ b/panel/tests/widgets/test_indicators.py @@ -104,7 +104,7 @@ def test_gauge_bounds(): def test_tqdm_color(): tqdm = Tqdm() - tqdm.text_pane.style={'color': 'green'} + tqdm.text_pane.styles={'color': 'green'} for _ in tqdm(range(0,2)): pass - assert tqdm.text_pane.style["color"]=="green" + assert tqdm.text_pane.styles["color"]=="green" diff --git a/panel/util/__init__.py b/panel/util/__init__.py index 62971a048e..70a8cf02cc 100644 --- a/panel/util/__init__.py +++ b/panel/util/__init__.py @@ -13,7 +13,6 @@ import re import sys import urllib.parse as urlparse -import warnings from collections import OrderedDict, defaultdict from collections.abc import MutableMapping, MutableSequence @@ -381,41 +380,3 @@ def base_version(version: str) -> str: return match.group() else: return version - - -def style_to_styles(params): - """ - In Bokeh 3.0.0 'style' was changed to 'styles'. - This small function will change it and emit a warning. - - """ - if "style" in params: - params["styles"] = params.pop("style") - msg = "The parameter 'style' is deprecated please use 'styles' instead of." - deprecation_warning(msg) - - return params - - -def deprecation_warning(msg, warning=FutureWarning): - # Finding the first stacklevel outside panel and param - # Inspired by: pandas.util._exceptions.find_stack_level - import param - - import panel as pn - - pkg_dir = os.path.dirname(pn.__file__) - test_dir = os.path.join(pkg_dir, "tests") - param_dir = os.path.dirname(param.__file__) - - frame = inspect.currentframe() - stacklevel = 1 - while frame: - fname = inspect.getfile(frame) - if (fname.startswith(pkg_dir) or fname.startswith(param_dir)) and not fname.startswith(test_dir): - frame = frame.f_back - stacklevel += 1 - else: - break - - warnings.warn(msg, warning, stacklevel=stacklevel) diff --git a/panel/viewable.py b/panel/viewable.py index e7bab59dfb..c2b1c4daa2 100644 --- a/panel/viewable.py +++ b/panel/viewable.py @@ -607,17 +607,13 @@ def _update_loading(self, *_) -> None: stop_loading_spinner(self) def _set_background(self, *_) -> None: - if self.background == self.styles.get("background", None): + if self.background == self.styles.get("background", None) or self.background is None: return # Warning - prev = f'{type(self).name}(background="{self.background}")' - new = f'{type(self).name}(styles={{"background": "{self.background}"}}' - deprecation_warning( - f"{prev!r} is deprecated and will stop working, " - f"use {new!r} instead of." - ) - + prev = f'{type(self).name}(background={self.background!r})' + new = f'{type(self).name}(styles={{"background": {self.background!r}}}' + deprecated("1.1", prev, new) self.styles["background"] = self.background self.param.trigger("styles") diff --git a/panel/widgets/indicators.py b/panel/widgets/indicators.py index c87ddc7237..948bb21ded 100644 --- a/panel/widgets/indicators.py +++ b/panel/widgets/indicators.py @@ -1123,7 +1123,7 @@ def __init__(self, *args, **kwargs): def display(self, msg=None, pos=None, bar_style=None): super().display(msg, pos) styles = self._indicator.text_pane.styles or {} - if "color" not in style: + if "color" not in styles: color = self.colour or 'black' self._indicator.text_pane.styles = dict(styles, color=color) if self.total is not None and self.n is not None: diff --git a/pyproject.toml b/pyproject.toml index ef83d59e93..7d8324dee4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ requires = [ "param >=1.9.2", "pyct >=0.4.4", - "setuptools >=42", + "setuptools >=42,<66", # upper pin can be removed after Holoviews support Bokeh 3.0 "bokeh >=3.1.0.dev1,<3.2.0", "pyviz_comms >=0.7.4", "requests", diff --git a/setup.py b/setup.py index 109938d0a5..cd9f8e1726 100644 --- a/setup.py +++ b/setup.py @@ -103,7 +103,7 @@ def run(self): ########## dependencies ########## install_requires = [ - 'bokeh >=3.0,<3.1', + 'bokeh >=3.1.0.dev1', 'param >=1.12.0', 'pyviz_comms >=0.7.4', 'markdown', @@ -218,7 +218,7 @@ def run(self): 'setuptools >=42', 'requests', 'packaging', - 'bokeh >=3.1.0.dev1,<3.2', + 'bokeh >=3.1.0.dev1', 'pyviz_comms >=0.7.4', 'bleach', 'tqdm >=4.48.0',