diff --git a/geoviews/models/custom_tools.py b/geoviews/models/custom_tools.py index 0ad46dd5..f5d8d541 100644 --- a/geoviews/models/custom_tools.py +++ b/geoviews/models/custom_tools.py @@ -1,8 +1,30 @@ +from functools import cache + +from bokeh import __version__ as bokeh_version from bokeh.core.properties import Any, Dict, Instance, List, String from bokeh.models import ColumnDataSource, PolyDrawTool, PolyEditTool, Tool +from packaging.requirements import Requirement + +from .._warnings import warn + + +class _BokehCheck(Tool): + _bokeh_require_version = "bokeh ==3.6.*" + def __init__(self, *args, **kwargs): + self._check_bokeh_version() + super().__init__(*args, **kwargs) + + @classmethod + @cache + def _check_bokeh_version(cls) -> None: + bokeh_req = Requirement(cls._bokeh_require_version) + if bokeh_req.specifier.contains(bokeh_version): + return + msg = f"{cls.__name__} only official supported with {cls._bokeh_require_version}, you have {bokeh_version} installed." + warn(msg, RuntimeWarning) -class CheckpointTool(Tool): +class CheckpointTool(_BokehCheck, Tool): """ Checkpoints the data on the supplied ColumnDataSources, allowing the RestoreTool to restore the data to a previous state. @@ -11,7 +33,7 @@ class CheckpointTool(Tool): sources = List(Instance(ColumnDataSource)) -class RestoreTool(Tool): +class RestoreTool(_BokehCheck, Tool): """ Restores the data on the supplied ColumnDataSources to a previous checkpoint created by the CheckpointTool @@ -20,7 +42,7 @@ class RestoreTool(Tool): sources = List(Instance(ColumnDataSource)) -class ClearTool(Tool): +class ClearTool(_BokehCheck, Tool): """ Clears the data on the supplied ColumnDataSources. """ @@ -28,7 +50,7 @@ class ClearTool(Tool): sources = List(Instance(ColumnDataSource)) -class PolyVertexEditTool(PolyEditTool): +class PolyVertexEditTool(_BokehCheck, PolyEditTool): node_style = Dict(String, Any, help=""" Custom styling to apply to the intermediate nodes of a patch or line glyph.""") @@ -37,7 +59,7 @@ class PolyVertexEditTool(PolyEditTool): Custom styling to apply to the start and nodes of a patch or line glyph.""") -class PolyVertexDrawTool(PolyDrawTool): +class PolyVertexDrawTool(_BokehCheck, PolyDrawTool): node_style = Dict(String, Any, help=""" Custom styling to apply to the intermediate nodes of a patch or line glyph.""") diff --git a/geoviews/tests/plotting/bokeh/test_models.py b/geoviews/tests/plotting/bokeh/test_models.py new file mode 100644 index 00000000..f8ca7b05 --- /dev/null +++ b/geoviews/tests/plotting/bokeh/test_models.py @@ -0,0 +1,22 @@ +from pathlib import Path + +import pytest + +from geoviews.models.custom_tools import _BokehCheck + + +def test_bokeh_version(): + # Can be removed when minimum Python version is 3.11 + tomllib = pytest.importorskip("tomllib") + + pyproject = Path(__file__).parents[4] / "pyproject.toml" + pyproject.resolve(strict=True) + requires = tomllib.loads(pyproject.read_text())["build-system"]["requires"] + + for req in requires: + if req.startswith("bokeh"): + break + else: + raise ValueError("Bokeh not found in build-system requires") + + assert req == _BokehCheck._bokeh_require_version diff --git a/pyproject.toml b/pyproject.toml index e8c919cd..1cfee9cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["hatchling", "hatch-vcs", 'bokeh ==3.6'] +requires = ["hatchling", "hatch-vcs", 'bokeh ==3.6.*'] build-backend = "hatchling.build" [project] @@ -27,7 +27,7 @@ classifiers = [ ] dependencies = [ - 'bokeh >=3.6.0,<3.7.0', + 'bokeh >=3.6.0', 'cartopy >=0.18.0', 'holoviews >=1.16.0', 'numpy',