Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Align version check #6413

Merged
merged 5 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

system = platform.system()
py_version = sys.version_info[:2]
PD2 = Version(pd.__version__) >= Version("2.0")
PANDAS_GE_2_0_0 = Version(pd.__version__).release >= (2, 0, 0)

# Having "OMP_NUM_THREADS"=1, set as an environment variable, can be needed
# to avoid crashing when running tests with pytest-xdist on Windows.
Expand All @@ -30,7 +30,7 @@

# 2023-07-14 with following error:
# ValueError: Buffer dtype mismatch, expected 'const int64_t' but got 'int'
if PD2 and system == "Windows":
if PANDAS_GE_2_0_0 and system == "Windows":
collect_ignore_glob += [
"gallery/demos/bokeh/point_draw_triangulate.ipynb",
"reference/elements/*/TriMesh.ipynb",
Expand All @@ -45,7 +45,7 @@
]

# First available in Bokeh 3.2.0
if Version(bokeh.__version__) < Version("3.2.0"):
if Version(bokeh.__version__).release < (3, 2, 0):
collect_ignore_glob += [
"reference/elements/bokeh/HLines.ipynb",
"reference/elements/bokeh/HSpans.ipynb",
Expand Down
2 changes: 1 addition & 1 deletion holoviews/core/data/dask.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def groupby(cls, dataset, dimensions, container_type, group_type, **kwargs):
for coord in indices:
if any(isinstance(c, float) and np.isnan(c) for c in coord):
continue
if len(coord) == 1 and not util.PANDAS_GE_220:
if len(coord) == 1 and not util.PANDAS_GE_2_2_0:
coord = coord[0]
group = group_type(groupby.get_group(coord), **group_kwargs)
data.append((coord, group))
Expand Down
53 changes: 18 additions & 35 deletions holoviews/core/data/ibis.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,18 @@
import sys
from collections.abc import Iterable
from functools import lru_cache

import numpy as np
from packaging.version import Version

from .. import util
from ..element import Element
from ..ndmapping import NdMapping, item_check, sorted_context
from .interface import DataError, Interface
from .util import cached


@lru_cache
def ibis_version():
import ibis
return Version(ibis.__version__)


@lru_cache
def ibis4():
return ibis_version() >= Version("4.0")


@lru_cache
def ibis5():
return ibis_version() >= Version("5.0")

@lru_cache
def ibis9_5():
return ibis_version() >= Version("9.5")
IBIS_VERSION = util._no_import_version("ibis-framework")
IBIS_GE_4_0_0 = IBIS_VERSION >= (4, 0, 0)
IBIS_GE_5_0_0 = IBIS_VERSION >= (5, 0, 0)
IBIS_GE_9_5_0 = IBIS_VERSION >= (9, 5, 0)


class IbisInterface(Interface):
Expand Down Expand Up @@ -120,7 +103,7 @@ def persist(cls, dataset):
@cached
def length(self, dataset):
# Get the length by counting the length of an empty query.
if ibis4():
if IBIS_GE_4_0_0:
return dataset.data.count().execute()
else:
return dataset.data[[]].count().execute()
Expand All @@ -129,7 +112,7 @@ def length(self, dataset):
@cached
def nonzero(cls, dataset):
# Make an empty query to see if a row is returned.
if ibis4():
if IBIS_GE_4_0_0:
return bool(len(dataset.data.head(1).execute()))
else:
return bool(len(dataset.data[[]].head(1).execute()))
Expand Down Expand Up @@ -163,7 +146,7 @@ def values(
dimension = dataset.get_dimension(dimension, strict=True)
data = dataset.data[dimension.name]
if (
ibis_version() > Version("3")
IBIS_VERSION > (3, 0, 0)
and isinstance(data, ibis.expr.types.AnyColumn)
and not expanded
):
Expand All @@ -178,12 +161,12 @@ def histogram(cls, expr, bins, density=True, weights=None):
bins = [int(v) if bins.dtype.kind in 'iu' else float(v) for v in bins]
binned = expr.bucket(bins).name('bucket')
hist = np.zeros(len(bins)-1)
if ibis4():
if IBIS_GE_4_0_0:
hist_bins = binned.value_counts().order_by('bucket').execute()
else:
# sort_by will be removed in Ibis 5.0
hist_bins = binned.value_counts().sort_by('bucket').execute()
metric_name = 'bucket_count' if ibis5() else 'count'
metric_name = 'bucket_count' if IBIS_GE_5_0_0 else 'count'
for b, v in zip(hist_bins['bucket'], hist_bins[metric_name]):
if np.isnan(b):
continue
Expand Down Expand Up @@ -212,11 +195,11 @@ def dtype(cls, dataset, dimension):
def sort(cls, dataset, by=None, reverse=False):
if by is None:
by = []
if ibis_version() >= Version("6.0"):
if IBIS_VERSION >= (6, 0, 0):
import ibis
order = ibis.desc if reverse else ibis.asc
return dataset.data.order_by([order(dataset.get_dimension(x).name) for x in by])
elif ibis4():
elif IBIS_GE_4_0_0:
# Tuple syntax will be removed in Ibis 7.0:
# https://github.com/ibis-project/ibis/pull/6082
return dataset.data.order_by([(dataset.get_dimension(x).name, not reverse) for x in by])
Expand Down Expand Up @@ -245,7 +228,7 @@ def _index_ibis_table(cls, data):
if "hv_row_id__" in data.columns:
return data

if ibis4():
if IBIS_GE_4_0_0:
return data.mutate(hv_row_id__=ibis.row_number())
elif cls.is_rowid_zero_indexed(data):
return data.mutate(hv_row_id__=data.rowid())
Expand Down Expand Up @@ -290,7 +273,7 @@ def iloc(cls, dataset, index):
rows = [rows]
data = data.filter([data.hv_row_id__.isin(rows)])

if ibis4():
if IBIS_GE_4_0_0:
return data.drop("hv_row_id__")
else:
# Passing a sequence of fields to `drop` will be removed in Ibis 5.0
Expand All @@ -302,7 +285,7 @@ def unpack_scalar(cls, dataset, data):
Given a dataset object and data in the appropriate format for
the interface, return a simple scalar.
"""
if ibis4():
if IBIS_GE_4_0_0:
count = data.count().execute()
else:
count = data[[]].count().execute()
Expand All @@ -326,7 +309,7 @@ def groupby(cls, dataset, dimensions, container_type, group_type, **kwargs):
group_by = [d.name for d in index_dims]

# execute a query against the table to find the unique groups.
if ibis4():
if IBIS_GE_4_0_0:
groups = dataset.data.group_by(group_by).aggregate().execute()
else:
# groupby will be removed in Ibis 5.0
Expand Down Expand Up @@ -392,7 +375,7 @@ def select(cls, dataset, selection_mask=None, **selection):
data["hv_row_id__"].isin(list(map(int, selection_mask)))
)

if ibis4():
if IBIS_GE_4_0_0:
data = data.drop("hv_row_id__")
else:
# Passing a sequence of fields to `drop` will be removed in Ibis 5.0
Expand Down Expand Up @@ -462,7 +445,7 @@ def sample(cls, dataset, samples=None):
if all(util.isscalar(s) or len(s) == 1 for s in samples):
items = [s[0] if isinstance(s, tuple) else s for s in samples]
subset = data[dims[0].name].isin(items)
return data.filter(subset) if ibis9_5() else data[subset]
return data.filter(subset) if IBIS_GE_9_5_0 else data[subset]

predicates = None
for sample in samples:
Expand Down Expand Up @@ -508,7 +491,7 @@ def aggregate(cls, dataset, dimensions, function, **kwargs):
}.get(function, function)

if len(dimensions):
if ibis4():
if IBIS_GE_4_0_0:
selection = new.group_by(columns)
else:
# groupby will be removed in Ibis 5.0
Expand Down
9 changes: 4 additions & 5 deletions holoviews/core/data/pandas.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import numpy as np
import pandas as pd
from packaging.version import Version
from pandas.api.types import is_numeric_dtype

from .. import util
from ..dimension import Dimension, dimension_name
from ..element import Element
from ..ndmapping import NdMapping, item_check, sorted_context
from ..util import PANDAS_GE_210
from ..util import PANDAS_GE_2_1_0
from .interface import DataError, Interface
from .util import finite_range

Expand Down Expand Up @@ -251,14 +250,14 @@ def groupby(cls, dataset, dimensions, container_type, group_type, **kwargs):
group_kwargs['dataset'] = dataset.dataset

group_by = [d.name for d in index_dims]
if len(group_by) == 1 and util.pandas_version >= Version("1.5.0"):
if len(group_by) == 1 and util.PANDAS_VERSION >= (1, 5, 0):
# Because of this deprecation warning from pandas 1.5.0:
# In a future version of pandas, a length 1 tuple will be returned
# when iterating over a groupby with a grouper equal to a list of length 1.
# Don't supply a list with a single grouper to avoid this warning.
group_by = group_by[0]
groupby_kwargs = {"sort": False}
if PANDAS_GE_210:
if PANDAS_GE_2_1_0:
groupby_kwargs["observed"] = False
data = [(k, group_type(v, **group_kwargs)) for k, v in
dataset.data.groupby(group_by, **groupby_kwargs)]
Expand Down Expand Up @@ -296,7 +295,7 @@ def aggregate(cls, dataset, dimensions, function, **kwargs):
if is_numeric_dtype(d) and c not in cols
]
groupby_kwargs = {"sort": False}
if PANDAS_GE_210:
if PANDAS_GE_2_1_0:
groupby_kwargs["observed"] = False
grouped = reindexed.groupby(cols, **groupby_kwargs)
df = grouped[numeric_cols].aggregate(fn, **kwargs).reset_index()
Expand Down
21 changes: 15 additions & 6 deletions holoviews/core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from collections import defaultdict, namedtuple
from contextlib import contextmanager
from functools import partial
from importlib.metadata import PackageNotFoundError, version
from threading import Event, Thread
from types import FunctionType

Expand All @@ -38,13 +39,13 @@
get_keywords = operator.attrgetter('varkw')

# Versions
numpy_version = Version(Version(np.__version__).base_version)
param_version = Version(param.__version__)
pandas_version = Version(pd.__version__)
NUMPY_VERSION = Version(np.__version__).release
PARAM_VERSION = Version(param.__version__).release
PANDAS_VERSION = Version(pd.__version__).release

NUMPY_GE_200 = numpy_version >= Version("2")
PANDAS_GE_210 = pandas_version >= Version("2.1")
PANDAS_GE_220 = pandas_version >= Version("2.2")
NUMPY_GE_2_0_0 = NUMPY_VERSION >= (2, 0, 0)
PANDAS_GE_2_1_0 = PANDAS_VERSION >= (2, 1, 0)
PANDAS_GE_2_2_0 = PANDAS_VERSION >= (2, 2, 0)

# Types
generator_types = (zip, range, types.GeneratorType)
Expand Down Expand Up @@ -115,6 +116,14 @@ def __init__(self, msg, version=None, min_version=None, **kwargs):
super().__init__(msg, **kwargs)


def _no_import_version(name) -> tuple[int, int, int]:
""" Get version number without importing the library """
try:
return Version(version(name)).release
except PackageNotFoundError:
return (0, 0, 0)


class Config(param.ParameterizedFunction):
"""
Set of boolean configuration values to change HoloViews' global
Expand Down
4 changes: 2 additions & 2 deletions holoviews/element/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from ..core.operation import Operation
from ..core.sheetcoords import Slice
from ..core.util import (
PANDAS_GE_210,
PANDAS_GE_2_1_0,
cartesian_product,
datetime_types,
is_cyclic,
Expand Down Expand Up @@ -202,7 +202,7 @@ def _aggregate_dataset(self, obj):
def _aggregate_dataset_pandas(self, obj):
index_cols = [d.name for d in obj.kdims]
groupby_kwargs = {"sort": False}
if PANDAS_GE_210:
if PANDAS_GE_2_1_0:
groupby_kwargs["observed"] = False
df = obj.data.set_index(index_cols).groupby(index_cols, **groupby_kwargs).first()
label = 'unique' if len(df) == len(obj) else 'non-unique'
Expand Down
10 changes: 5 additions & 5 deletions holoviews/operation/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ def _process(self, element, key=None):
if self.p.filled:
vdims = [vdims[0].clone(range=crange)]

if Version(contourpy_version) >= Version('1.2'):
if Version(contourpy_version).release >= (1, 2, 0):
line_type = LineType.ChunkCombinedNan
else:
line_type = LineType.ChunkCombinedOffset
Expand Down Expand Up @@ -821,7 +821,7 @@ def _process(self, element, key=None, groupby=False):
is_cupy = is_cupy_array(data)
if is_cupy:
import cupy
full_cupy_support = Version(cupy.__version__) > Version('8.0')
full_cupy_support = Version(cupy.__version__).release > (8, 0, 0)
if not full_cupy_support and (normed or self.p.weight_dimension):
data = cupy.asnumpy(data)
is_cupy = False
Expand All @@ -830,17 +830,17 @@ def _process(self, element, key=None, groupby=False):

# Mask data
if is_ibis_expr(data):
from ..core.data.ibis import ibis5, ibis9_5
from ..core.data.ibis import IBIS_GE_5_0_0, IBIS_GE_9_5_0

mask = data.notnull()
if self.p.nonzero:
mask = mask & (data != 0)
if ibis5():
if IBIS_GE_5_0_0:
data = data.as_table()
else:
# to_projection removed in ibis 5.0.0
data = data.to_projection()
data = data.filter(mask) if ibis9_5() else data[mask]
data = data.filter(mask) if IBIS_GE_9_5_0 else data[mask]
no_data = not len(data.head(1).execute())
data = data[dim.name]
else:
Expand Down
2 changes: 1 addition & 1 deletion holoviews/plotting/bokeh/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
from .stats import BivariatePlot, BoxWhiskerPlot, DistributionPlot, ViolinPlot
from .tabular import TablePlot
from .tiles import TilePlot
from .util import bokeh_version # noqa (API import)
from .util import BOKEH_VERSION # noqa (API import)

Store.renderers['bokeh'] = BokehRenderer.instance()

Expand Down
4 changes: 2 additions & 2 deletions holoviews/plotting/bokeh/annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
line_properties,
text_properties,
)
from .util import bokeh32, date_to_integer
from .util import BOKEH_GE_3_2_0, date_to_integer

arrow_start = {'<->': NormalHead, '<|-|>': NormalHead}
arrow_end = {'->': NormalHead, '-[': TeeHead, '-|>': NormalHead,
Expand All @@ -39,7 +39,7 @@ class _SyntheticAnnotationPlot(ColorbarPlot):
_allow_implicit_categories = False

def __init__(self, element, **kwargs):
if not bokeh32:
if not BOKEH_GE_3_2_0:
name = type(getattr(element, "last", element)).__name__
msg = f'{name} element requires Bokeh >=3.2'
raise ImportError(msg)
Expand Down
4 changes: 2 additions & 2 deletions holoviews/plotting/bokeh/callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
Tap,
)
from ...util.warnings import warn
from .util import bokeh33, convert_timestamp
from .util import BOKEH_GE_3_3_0, convert_timestamp


class Callback:
Expand Down Expand Up @@ -1569,7 +1569,7 @@ def initialize(self, plot_id=None):
renderer = self._path_initialize()
if stream.styles:
self._create_style_callback(cds, renderer.glyph)
if bokeh33:
if BOKEH_GE_3_3_0:
# First version with Quad support
box_tool = BoxEditTool(renderers=[renderer], **kwargs)
self.plot.state.tools.append(box_tool)
Expand Down
Loading