Skip to content

Commit

Permalink
Release 4.0.0 (#154)
Browse files Browse the repository at this point in the history
* Support for bokeh 3.1.0 (>2.0.0) (#153)

* Fix range args with value None

* Pass range start / end only if not None

* Fix font value for bokeh>=2.3

* Undo pinning bokeh to <2.3.0

* Workaround for select(CategoricalColorMapper) bug
- bug in bokeh>=3.0.0
- bokeh/bokeh#13015

* - Drop python 3.6 and 3.7 from tox testing
- Update version to 4.0.0

* Try to add python 3.11

* Remove 3.11

* Update requirements

* Updated dev requirements

* Reformat and change back flake8 version

* Re-ran example notebook

---------

Co-authored-by: Quoc Duong Bui <35042166+vanHekthor@users.noreply.github.com>
  • Loading branch information
iampelle and vanHekthor committed Mar 23, 2023
1 parent 59df367 commit b518f1b
Show file tree
Hide file tree
Showing 22 changed files with 2,839 additions and 4,249 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
strategy:
max-parallel: 5
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]
python-version: ["3.8", "3.9", "3.10"]

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Before you submit a pull request, check that it meets these guidelines:
2. If the pull request adds functionality, the docs should be updated. Put
your new functionality into a function with a docstring, and add the
feature to the list in README.rst.
3. The pull request should work for Python 3.6. Check
3. The pull request should work for Python 3.8, 3.9 and 3.10. Check
https://github.com/spotify/chartify/actions
and make sure that the tests pass for all supported Python versions.

Expand Down
5 changes: 5 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
History
=======

4.0.0 (2023-03-23)
------------------

* Dropped support for python 3.6 and 3.7

3.1.0 (2023-03-22)
------------------

Expand Down
7 changes: 4 additions & 3 deletions chartify/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# flake8: noqa
"""Top-level package for chartify."""
from chartify._core.chart import Chart
from chartify._core.radar_chart import RadarChart
Expand All @@ -21,8 +22,8 @@
from chartify import examples

__author__ = """Chris Halpert"""
__email__ = 'chalpert@spotify.com'
__version__ = '3.1.0'
__email__ = "chalpert@spotify.com"
__version__ = "4.0.0"

_IPYTHON_INSTANCE = False

Expand All @@ -44,7 +45,7 @@ def set_display_settings():
if curstate().notebook_type is None:
# Inline resources uses bokeh.js from the local version.
# This enables offline usage.
output_notebook(Resources('inline'), hide_banner=True)
output_notebook(Resources("inline"), hide_banner=True)


set_display_settings()
Expand Down
140 changes: 64 additions & 76 deletions chartify/_core/axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@


class YAxisMixin:

def __init__(self):
self._y_axis_index = 0
self._y_range = self._chart.figure.y_range
Expand Down Expand Up @@ -59,12 +58,9 @@ def hide_yaxis(self):
removed with .axes.set_yaxis_label("")
"""
self._chart.figure.yaxis[self._y_axis_index].axis_line_alpha = 0
self._chart.figure.yaxis[
self._y_axis_index].major_tick_line_color = None
self._chart.figure.yaxis[
self._y_axis_index].minor_tick_line_color = None
self._chart.figure.yaxis[
self._y_axis_index].major_label_text_color = None
self._chart.figure.yaxis[self._y_axis_index].major_tick_line_color = None
self._chart.figure.yaxis[self._y_axis_index].minor_tick_line_color = None
self._chart.figure.yaxis[self._y_axis_index].major_label_text_color = None
return self._chart


Expand All @@ -78,23 +74,21 @@ def __init__(self, chart):

@classmethod
def _get_axis_class(cls, x_axis_type, y_axis_type):
if x_axis_type == 'categorical' and y_axis_type == 'categorical':
if x_axis_type == "categorical" and y_axis_type == "categorical":
return CategoricalXYAxes
elif x_axis_type == 'categorical':
elif x_axis_type == "categorical":
return NumericalYAxis
elif y_axis_type == 'categorical':
elif y_axis_type == "categorical":
return NumericalXAxis
elif x_axis_type == 'datetime':
elif x_axis_type == "datetime":
return DatetimeXNumericalYAxes
return NumericalXYAxes

@property
def _vertical(self):
if self._chart._x_axis_type == 'density':
if self._chart._x_axis_type == "density":
return False
elif isinstance(self, (NumericalYAxis,
NumericalXYAxes,
DatetimeXNumericalYAxes)):
elif isinstance(self, (NumericalYAxis, NumericalXYAxes, DatetimeXNumericalYAxes)):
return True
else:
return False
Expand All @@ -103,44 +97,42 @@ def _initialize_defaults(self):
xaxis_label = """ch.axes.set_xaxis_label('label (units)')"""
yaxis_label = """ch.axes.set_yaxis_label('label (units)')"""
if self._chart._blank_labels:
xaxis_label = ''
yaxis_label = ''
xaxis_label = ""
yaxis_label = ""
self.set_xaxis_label(xaxis_label)
self.set_yaxis_label(yaxis_label)

@staticmethod
def _convert_major_orientation_labels(orientation):
"""Map the user inputted orientation values to the values expected by
bokeh for major labels."""
if orientation == 'vertical':
if orientation == "vertical":
orientation = pi / 180 * 90
elif orientation == 'diagonal':
elif orientation == "diagonal":
orientation = pi / 180 * 45
elif orientation != 'horizontal':
raise ValueError(
'Orientation must be `horizontal`, `vertical`, or `diagonal`.')
elif orientation != "horizontal":
raise ValueError("Orientation must be `horizontal`, `vertical`, or `diagonal`.")
return orientation

def _convert_subgroup_orientation_labels(self, orientation):
"""Map the user inputted orientation values to the values expected by
bokeh for group labels."""

if self._vertical:
horizontal_value = 'parallel'
horizontal_value = "parallel"
vertical_value = pi / 180 * 90
else:
horizontal_value = 'normal'
vertical_value = 'parallel'
horizontal_value = "normal"
vertical_value = "parallel"

if orientation == 'horizontal':
if orientation == "horizontal":
orientation = horizontal_value
elif orientation == 'vertical':
elif orientation == "vertical":
orientation = vertical_value
elif orientation == 'diagonal':
elif orientation == "diagonal":
orientation = pi / 180 * 45
else:
raise ValueError(
'Orientation must be `horizontal`, `vertical`, or `diagonal`.')
raise ValueError("Orientation must be `horizontal`, `vertical`, or `diagonal`.")
return orientation

@property
Expand Down Expand Up @@ -180,7 +172,7 @@ def hide_xaxis(self):

return self._chart

def set_xaxis_tick_orientation(self, orientation='horizontal'):
def set_xaxis_tick_orientation(self, orientation="horizontal"):
"""Change the orientation or the x axis tick labels.
Args:
Expand All @@ -194,7 +186,7 @@ def set_xaxis_tick_orientation(self, orientation='horizontal'):
orientation = [orientation] * 3

level_1 = orientation[0]
level_2 = orientation[1] if len(orientation) > 1 else 'horizontal'
level_2 = orientation[1] if len(orientation) > 1 else "horizontal"
level_3 = orientation[2] if len(orientation) > 2 else level_2

level_1 = self._convert_major_orientation_labels(level_1)
Expand All @@ -204,11 +196,11 @@ def set_xaxis_tick_orientation(self, orientation='horizontal'):
self._chart.figure.xaxis.major_label_orientation = level_1

xaxis = self._chart.figure.xaxis[0]
has_subgroup_label = getattr(xaxis, 'subgroup_label_orientation', None)
has_subgroup_label = getattr(xaxis, "subgroup_label_orientation", None)
if has_subgroup_label is not None:
self._chart.figure.xaxis.subgroup_label_orientation = level_2

has_group_label = getattr(xaxis, 'group_label_orientation', None)
has_group_label = getattr(xaxis, "group_label_orientation", None)
if has_group_label is not None:
self._chart.figure.xaxis.group_label_orientation = level_3
return self._chart
Expand All @@ -225,8 +217,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):
Expand Down Expand Up @@ -270,14 +264,11 @@ def set_xaxis_tick_format(self, num_format):
Returns:
Current chart object
"""
self._chart.figure.xaxis[0].formatter = (
bokeh.models.NumeralTickFormatter(format=num_format)
)
self._chart.figure.xaxis[0].formatter = bokeh.models.NumeralTickFormatter(format=num_format)
return self._chart


class NumericalYMixin:

def set_yaxis_range(self, start=None, end=None):
"""Set y-axis range.
Expand All @@ -288,8 +279,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):
Expand All @@ -301,8 +294,7 @@ def set_yaxis_tick_values(self, values):
Returns:
Current chart object
"""
self._chart.figure.yaxis[
self._y_axis_index].ticker = FixedTicker(ticks=values)
self._chart.figure.yaxis[self._y_axis_index].ticker = FixedTicker(ticks=values)
return self._chart

def set_yaxis_tick_format(self, num_format):
Expand Down Expand Up @@ -334,8 +326,7 @@ def set_yaxis_tick_format(self, num_format):
Returns:
Current chart object
"""
self._chart.figure.yaxis[self._y_axis_index].formatter = (
bokeh.models.NumeralTickFormatter(format=num_format))
self._chart.figure.yaxis[self._y_axis_index].formatter = bokeh.models.NumeralTickFormatter(format=num_format)
return self._chart


Expand Down Expand Up @@ -420,7 +411,7 @@ def hide_yaxis(self):
pass
return self._chart

def set_yaxis_tick_orientation(self, orientation='horizontal'):
def set_yaxis_tick_orientation(self, orientation="horizontal"):
"""Change the orientation or the y axis tick labels.
Args:
Expand All @@ -434,7 +425,7 @@ def set_yaxis_tick_orientation(self, orientation='horizontal'):
orientation = [orientation] * 3

level_1 = orientation[0]
level_2 = orientation[1] if len(orientation) > 1 else 'horizontal'
level_2 = orientation[1] if len(orientation) > 1 else "horizontal"
level_3 = orientation[2] if len(orientation) > 2 else level_2

level_1 = self._convert_major_orientation_labels(level_1)
Expand All @@ -454,15 +445,14 @@ class DatetimeXMixin:
def _convert_timestamp_list_to_epoch_ms(ts_list):
return list(
map(
lambda x: (
(pd.to_datetime(x) - pd.Timestamp("1970-01-01"))
// pd.Timedelta('1ms')),
ts_list))
lambda x: ((pd.to_datetime(x) - pd.Timestamp("1970-01-01")) // pd.Timedelta("1ms")),
ts_list,
)
)

@staticmethod
def _convert_timestamp_to_epoch_ms(timestamp):
return (pd.to_datetime(timestamp) -
pd.Timestamp("1970-01-01")) // pd.Timedelta('1ms')
return (pd.to_datetime(timestamp) - pd.Timestamp("1970-01-01")) // pd.Timedelta("1ms")

def set_xaxis_range(self, start=None, end=None):
"""Set x-axis range.
Expand Down Expand Up @@ -541,17 +531,17 @@ def set_xaxis_tick_format(self, date_format):
Returns:
Current chart object
"""
self._chart.figure.xaxis[
0].formatter = bokeh.models.DatetimeTickFormatter(
milliseconds=[date_format],
seconds=[date_format],
minsec=[date_format],
minutes=[date_format],
hourmin=[date_format],
hours=[date_format],
days=[date_format],
months=[date_format],
years=[date_format])
self._chart.figure.xaxis[0].formatter = bokeh.models.DatetimeTickFormatter(
milliseconds=[date_format],
seconds=[date_format],
minsec=[date_format],
minutes=[date_format],
hourmin=[date_format],
hours=[date_format],
days=[date_format],
months=[date_format],
years=[date_format],
)
return self._chart


Expand All @@ -560,15 +550,15 @@ class NumericalXAxis(BaseAxes, NumericalXMixin, CategoricalYMixin):

def __init__(self, chart):
super(NumericalXAxis, self).__init__(chart)
self._chart.style._apply_settings('categorical_yaxis')
self._chart.style._apply_settings("categorical_yaxis")


class NumericalYAxis(BaseAxes, CategoricalXMixin, NumericalYMixin):
"""Axis class for numerical Y and categorical X axes"""

def __init__(self, chart):
super(NumericalYAxis, self).__init__(chart)
self._chart.style._apply_settings('categorical_xaxis')
self._chart.style._apply_settings("categorical_xaxis")


class NumericalXYAxes(BaseAxes, NumericalXMixin, NumericalYMixin):
Expand All @@ -584,27 +574,25 @@ class CategoricalXYAxes(BaseAxes, CategoricalXMixin, CategoricalYMixin):

def __init__(self, chart):
super(CategoricalXYAxes, self).__init__(chart)
self._chart.style._apply_settings('categorical_xyaxis')
self._chart.style._apply_settings("categorical_xyaxis")


class SecondYNumericalAxis(YAxisMixin, NumericalYMixin):
"""Axis class for second Y numerical axes."""

def __init__(self, chart):
self._chart = chart
self._y_range_name = 'second_y'
self._chart.figure.extra_y_ranges = {
self._y_range_name: DataRange1d(bounds='auto')
}
self._y_range_name = "second_y"
self._chart.figure.extra_y_ranges = {self._y_range_name: DataRange1d(bounds="auto")}
# Add the appropriate axis type to the figure.
axis_class = LinearAxis
if self._chart._second_y_axis_type == 'log':
if self._chart._second_y_axis_type == "log":
axis_class = LogAxis
self._chart.figure.add_layout(
axis_class(y_range_name=self._y_range_name), 'right')
self._chart.figure.add_layout(axis_class(y_range_name=self._y_range_name), "right")

self._y_axis_index = 1
self._y_range = self._chart.figure.extra_y_ranges[self._y_range_name]
self._chart.style._apply_settings('second_y_axis')
self._chart.style._apply_settings("second_y_axis")


class SecondAxis:
Expand Down

0 comments on commit b518f1b

Please sign in to comment.