diff --git a/chartify/_core/axes.py b/chartify/_core/axes.py index 62001de..77c9b06 100644 --- a/chartify/_core/axes.py +++ b/chartify/_core/axes.py @@ -225,8 +225,10 @@ def set_xaxis_range(self, start=None, end=None): Returns: Current chart object """ - self._chart.figure.x_range.end = end - self._chart.figure.x_range.start = start + if end is not None: + self._chart.figure.x_range.end = end + if start is not None: + self._chart.figure.x_range.start = start return self._chart def set_xaxis_tick_values(self, values): @@ -288,8 +290,10 @@ def set_yaxis_range(self, start=None, end=None): Returns: Current chart object """ - self._y_range.end = end - self._y_range.start = start + if end is not None: + self._y_range.end = end + if start is not None: + self._y_range.start = start return self._chart def set_yaxis_tick_values(self, values): diff --git a/chartify/_core/chart.py b/chartify/_core/chart.py index 506bd3b..817d7a8 100644 --- a/chartify/_core/chart.py +++ b/chartify/_core/chart.py @@ -154,24 +154,23 @@ def __repr__(self): y_axis_type=self._y_axis_type) def _initialize_figure(self, x_axis_type, y_axis_type): - x_range, y_range = None, None + range_args = {} if x_axis_type == 'categorical': - x_range = [] + range_args['x_range'] = [] x_axis_type = 'auto' if y_axis_type == 'categorical': - y_range = [] + range_args['y_range'] = [] y_axis_type = 'auto' if x_axis_type == 'density': x_axis_type = 'linear' if y_axis_type == 'density': y_axis_type = 'linear' figure = bokeh.plotting.figure( - x_range=x_range, - y_range=y_range, + **range_args, y_axis_type=y_axis_type, x_axis_type=x_axis_type, - plot_width=self.style.plot_width, - plot_height=self.style.plot_height, + width=self.style.plot_width, + height=self.style.plot_height, tools='save', # toolbar_location='right', active_drag=None) diff --git a/chartify/_core/style.py b/chartify/_core/style.py index f9c6031..d97ac03 100644 --- a/chartify/_core/style.py +++ b/chartify/_core/style.py @@ -23,10 +23,13 @@ import yaml import bokeh +from bokeh.core.properties import value as bokeh_value from chartify._core import colors from chartify._core.options import options +from packaging import version + class BasePalette: """Base class for color palettes.""" @@ -288,7 +291,7 @@ def __init__(self, chart, layout): 'subtitle_text_font': 'helvetica' }, 'text_callout_and_plot': { - 'font': 'helvetica', + 'font': self._font_value('helvetica'), }, 'interval_plot': { 'space_between_bars': .25, @@ -331,6 +334,14 @@ def __init__(self, chart, layout): except FileNotFoundError: pass + @staticmethod + def _font_value(text_font): + # https://github.com/bokeh/bokeh/issues/11044 + if version.parse(bokeh.__version__) < version.parse("2.3"): + return text_font + else: # >= 2.3 + return bokeh_value(text_font) + def _set_width_and_height(self, layout='slide_100%'): """Set plot width and height based on the layout""" self.plot_width = 960 diff --git a/requirements.txt b/requirements.txt index 4c62703..0cb18cd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ Pillow>=8.4.0 # Avoid selenium bug: # https://github.com/SeleniumHQ/selenium/issues/5296 selenium>=3.7.0,<=3.8.0 -bokeh>=2.0.0,<2.3.0 +bokeh>=2.0.0 scipy>=1.0.0,<2.0.0 ipykernel>=5.0 ipython>=7.0 diff --git a/tests/test_plots.py b/tests/test_plots.py index f5b469c..6b97004 100644 --- a/tests/test_plots.py +++ b/tests/test_plots.py @@ -21,6 +21,8 @@ import numpy as np import bokeh +from packaging import version + def chart_data(chart_object, series_name): """Retrieve data from chart object based on series name. @@ -438,10 +440,20 @@ def test_bar_color_column(self): categorical_columns='category2', numeric_column='number', color_column='category2') + + if version.parse(bokeh.__version__) < version.parse("3.0"): + assert (np.array_equal( + chart_color_mapper(ch).factors, ['1', '2', '3'])) + assert (np.array_equal(chart_color_mapper(ch).palette, + ['#1f77b4', '#ff7f0e', '#2ca02c'])) + return + + vbar_glyph = ch.figure.renderers[0].glyph assert (np.array_equal( - chart_color_mapper(ch).factors, ['1', '2', '3'])) - assert (np.array_equal( - chart_color_mapper(ch).palette, ['#1f77b4', '#ff7f0e', '#2ca02c'])) + vbar_glyph.fill_color.transform.factors, ['1', '2', '3'])) + assert (np.array_equal(vbar_glyph.fill_color.transform.palette, + ['#1f77b4', '#ff7f0e', '#2ca02c'])) + assert vbar_glyph.line_color == 'white' def test_lollipop_color_column(self): sliced_data = self.data[self.data['category1'] == 'a'] @@ -451,10 +463,30 @@ def test_lollipop_color_column(self): categorical_columns='category2', numeric_column='number', color_column='category2') + + if version.parse(bokeh.__version__) < version.parse("3.0"): + assert (np.array_equal( + chart_color_mapper(ch).factors, ['1', '2', '3'])) + assert (np.array_equal(chart_color_mapper(ch).palette, + ['#1f77b4', '#ff7f0e', '#2ca02c'])) + return + + segment_glyph = ch.figure.renderers[0].glyph + circle_glyph = ch.figure.renderers[1].glyph + # check segment colors + assert (np.array_equal( + segment_glyph.line_color.transform.factors, ['1', '2', '3'])) + assert (np.array_equal(segment_glyph.line_color.transform.palette, + ['#1f77b4', '#ff7f0e', '#2ca02c'])) + # check circle colors assert (np.array_equal( - chart_color_mapper(ch).factors, ['1', '2', '3'])) + circle_glyph.line_color.transform.factors, ['1', '2', '3'])) + assert (np.array_equal(circle_glyph.line_color.transform.palette, + ['#1f77b4', '#ff7f0e', '#2ca02c'])) assert (np.array_equal( - chart_color_mapper(ch).palette, ['#1f77b4', '#ff7f0e', '#2ca02c'])) + circle_glyph.fill_color.transform.factors, ['1', '2', '3'])) + assert (np.array_equal(circle_glyph.fill_color.transform.palette, + ['#1f77b4', '#ff7f0e', '#2ca02c'])) def test_bar_parallel_color_column(self): ch = chartify.Chart(x_axis_type='categorical')