Skip to content

Commit b518f1b

Browse files
iampelle0verhead
andauthored
Release 4.0.0 (#154)
* 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>
1 parent 59df367 commit b518f1b

22 files changed

+2839
-4249
lines changed

.github/workflows/tox.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ on: [push, pull_request]
44

55
jobs:
66
build:
7-
runs-on: ubuntu-20.04
7+
runs-on: ubuntu-latest
88
strategy:
99
max-parallel: 5
1010
matrix:
11-
python-version: [3.6, 3.7, 3.8, 3.9]
11+
python-version: ["3.8", "3.9", "3.10"]
1212

1313
steps:
1414
- uses: actions/checkout@v3

CONTRIBUTING.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ Before you submit a pull request, check that it meets these guidelines:
106106
2. If the pull request adds functionality, the docs should be updated. Put
107107
your new functionality into a function with a docstring, and add the
108108
feature to the list in README.rst.
109-
3. The pull request should work for Python 3.6. Check
109+
3. The pull request should work for Python 3.8, 3.9 and 3.10. Check
110110
https://github.com/spotify/chartify/actions
111111
and make sure that the tests pass for all supported Python versions.
112112

HISTORY.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
History
33
=======
44

5+
4.0.0 (2023-03-23)
6+
------------------
7+
8+
* Dropped support for python 3.6 and 3.7
9+
510
3.1.0 (2023-03-22)
611
------------------
712

chartify/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
16+
# flake8: noqa
1617
"""Top-level package for chartify."""
1718
from chartify._core.chart import Chart
1819
from chartify._core.radar_chart import RadarChart
@@ -21,8 +22,8 @@
2122
from chartify import examples
2223

2324
__author__ = """Chris Halpert"""
24-
__email__ = 'chalpert@spotify.com'
25-
__version__ = '3.1.0'
25+
__email__ = "chalpert@spotify.com"
26+
__version__ = "4.0.0"
2627

2728
_IPYTHON_INSTANCE = False
2829

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

4950

5051
set_display_settings()

chartify/_core/axes.py

Lines changed: 64 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727

2828
class YAxisMixin:
29-
3029
def __init__(self):
3130
self._y_axis_index = 0
3231
self._y_range = self._chart.figure.y_range
@@ -59,12 +58,9 @@ def hide_yaxis(self):
5958
removed with .axes.set_yaxis_label("")
6059
"""
6160
self._chart.figure.yaxis[self._y_axis_index].axis_line_alpha = 0
62-
self._chart.figure.yaxis[
63-
self._y_axis_index].major_tick_line_color = None
64-
self._chart.figure.yaxis[
65-
self._y_axis_index].minor_tick_line_color = None
66-
self._chart.figure.yaxis[
67-
self._y_axis_index].major_label_text_color = None
61+
self._chart.figure.yaxis[self._y_axis_index].major_tick_line_color = None
62+
self._chart.figure.yaxis[self._y_axis_index].minor_tick_line_color = None
63+
self._chart.figure.yaxis[self._y_axis_index].major_label_text_color = None
6864
return self._chart
6965

7066

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

7975
@classmethod
8076
def _get_axis_class(cls, x_axis_type, y_axis_type):
81-
if x_axis_type == 'categorical' and y_axis_type == 'categorical':
77+
if x_axis_type == "categorical" and y_axis_type == "categorical":
8278
return CategoricalXYAxes
83-
elif x_axis_type == 'categorical':
79+
elif x_axis_type == "categorical":
8480
return NumericalYAxis
85-
elif y_axis_type == 'categorical':
81+
elif y_axis_type == "categorical":
8682
return NumericalXAxis
87-
elif x_axis_type == 'datetime':
83+
elif x_axis_type == "datetime":
8884
return DatetimeXNumericalYAxes
8985
return NumericalXYAxes
9086

9187
@property
9288
def _vertical(self):
93-
if self._chart._x_axis_type == 'density':
89+
if self._chart._x_axis_type == "density":
9490
return False
95-
elif isinstance(self, (NumericalYAxis,
96-
NumericalXYAxes,
97-
DatetimeXNumericalYAxes)):
91+
elif isinstance(self, (NumericalYAxis, NumericalXYAxes, DatetimeXNumericalYAxes)):
9892
return True
9993
else:
10094
return False
@@ -103,44 +97,42 @@ def _initialize_defaults(self):
10397
xaxis_label = """ch.axes.set_xaxis_label('label (units)')"""
10498
yaxis_label = """ch.axes.set_yaxis_label('label (units)')"""
10599
if self._chart._blank_labels:
106-
xaxis_label = ''
107-
yaxis_label = ''
100+
xaxis_label = ""
101+
yaxis_label = ""
108102
self.set_xaxis_label(xaxis_label)
109103
self.set_yaxis_label(yaxis_label)
110104

111105
@staticmethod
112106
def _convert_major_orientation_labels(orientation):
113107
"""Map the user inputted orientation values to the values expected by
114108
bokeh for major labels."""
115-
if orientation == 'vertical':
109+
if orientation == "vertical":
116110
orientation = pi / 180 * 90
117-
elif orientation == 'diagonal':
111+
elif orientation == "diagonal":
118112
orientation = pi / 180 * 45
119-
elif orientation != 'horizontal':
120-
raise ValueError(
121-
'Orientation must be `horizontal`, `vertical`, or `diagonal`.')
113+
elif orientation != "horizontal":
114+
raise ValueError("Orientation must be `horizontal`, `vertical`, or `diagonal`.")
122115
return orientation
123116

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

128121
if self._vertical:
129-
horizontal_value = 'parallel'
122+
horizontal_value = "parallel"
130123
vertical_value = pi / 180 * 90
131124
else:
132-
horizontal_value = 'normal'
133-
vertical_value = 'parallel'
125+
horizontal_value = "normal"
126+
vertical_value = "parallel"
134127

135-
if orientation == 'horizontal':
128+
if orientation == "horizontal":
136129
orientation = horizontal_value
137-
elif orientation == 'vertical':
130+
elif orientation == "vertical":
138131
orientation = vertical_value
139-
elif orientation == 'diagonal':
132+
elif orientation == "diagonal":
140133
orientation = pi / 180 * 45
141134
else:
142-
raise ValueError(
143-
'Orientation must be `horizontal`, `vertical`, or `diagonal`.')
135+
raise ValueError("Orientation must be `horizontal`, `vertical`, or `diagonal`.")
144136
return orientation
145137

146138
@property
@@ -180,7 +172,7 @@ def hide_xaxis(self):
180172

181173
return self._chart
182174

183-
def set_xaxis_tick_orientation(self, orientation='horizontal'):
175+
def set_xaxis_tick_orientation(self, orientation="horizontal"):
184176
"""Change the orientation or the x axis tick labels.
185177
186178
Args:
@@ -194,7 +186,7 @@ def set_xaxis_tick_orientation(self, orientation='horizontal'):
194186
orientation = [orientation] * 3
195187

196188
level_1 = orientation[0]
197-
level_2 = orientation[1] if len(orientation) > 1 else 'horizontal'
189+
level_2 = orientation[1] if len(orientation) > 1 else "horizontal"
198190
level_3 = orientation[2] if len(orientation) > 2 else level_2
199191

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

206198
xaxis = self._chart.figure.xaxis[0]
207-
has_subgroup_label = getattr(xaxis, 'subgroup_label_orientation', None)
199+
has_subgroup_label = getattr(xaxis, "subgroup_label_orientation", None)
208200
if has_subgroup_label is not None:
209201
self._chart.figure.xaxis.subgroup_label_orientation = level_2
210202

211-
has_group_label = getattr(xaxis, 'group_label_orientation', None)
203+
has_group_label = getattr(xaxis, "group_label_orientation", None)
212204
if has_group_label is not None:
213205
self._chart.figure.xaxis.group_label_orientation = level_3
214206
return self._chart
@@ -225,8 +217,10 @@ def set_xaxis_range(self, start=None, end=None):
225217
Returns:
226218
Current chart object
227219
"""
228-
self._chart.figure.x_range.end = end
229-
self._chart.figure.x_range.start = start
220+
if end is not None:
221+
self._chart.figure.x_range.end = end
222+
if start is not None:
223+
self._chart.figure.x_range.start = start
230224
return self._chart
231225

232226
def set_xaxis_tick_values(self, values):
@@ -270,14 +264,11 @@ def set_xaxis_tick_format(self, num_format):
270264
Returns:
271265
Current chart object
272266
"""
273-
self._chart.figure.xaxis[0].formatter = (
274-
bokeh.models.NumeralTickFormatter(format=num_format)
275-
)
267+
self._chart.figure.xaxis[0].formatter = bokeh.models.NumeralTickFormatter(format=num_format)
276268
return self._chart
277269

278270

279271
class NumericalYMixin:
280-
281272
def set_yaxis_range(self, start=None, end=None):
282273
"""Set y-axis range.
283274
@@ -288,8 +279,10 @@ def set_yaxis_range(self, start=None, end=None):
288279
Returns:
289280
Current chart object
290281
"""
291-
self._y_range.end = end
292-
self._y_range.start = start
282+
if end is not None:
283+
self._y_range.end = end
284+
if start is not None:
285+
self._y_range.start = start
293286
return self._chart
294287

295288
def set_yaxis_tick_values(self, values):
@@ -301,8 +294,7 @@ def set_yaxis_tick_values(self, values):
301294
Returns:
302295
Current chart object
303296
"""
304-
self._chart.figure.yaxis[
305-
self._y_axis_index].ticker = FixedTicker(ticks=values)
297+
self._chart.figure.yaxis[self._y_axis_index].ticker = FixedTicker(ticks=values)
306298
return self._chart
307299

308300
def set_yaxis_tick_format(self, num_format):
@@ -334,8 +326,7 @@ def set_yaxis_tick_format(self, num_format):
334326
Returns:
335327
Current chart object
336328
"""
337-
self._chart.figure.yaxis[self._y_axis_index].formatter = (
338-
bokeh.models.NumeralTickFormatter(format=num_format))
329+
self._chart.figure.yaxis[self._y_axis_index].formatter = bokeh.models.NumeralTickFormatter(format=num_format)
339330
return self._chart
340331

341332

@@ -420,7 +411,7 @@ def hide_yaxis(self):
420411
pass
421412
return self._chart
422413

423-
def set_yaxis_tick_orientation(self, orientation='horizontal'):
414+
def set_yaxis_tick_orientation(self, orientation="horizontal"):
424415
"""Change the orientation or the y axis tick labels.
425416
426417
Args:
@@ -434,7 +425,7 @@ def set_yaxis_tick_orientation(self, orientation='horizontal'):
434425
orientation = [orientation] * 3
435426

436427
level_1 = orientation[0]
437-
level_2 = orientation[1] if len(orientation) > 1 else 'horizontal'
428+
level_2 = orientation[1] if len(orientation) > 1 else "horizontal"
438429
level_3 = orientation[2] if len(orientation) > 2 else level_2
439430

440431
level_1 = self._convert_major_orientation_labels(level_1)
@@ -454,15 +445,14 @@ class DatetimeXMixin:
454445
def _convert_timestamp_list_to_epoch_ms(ts_list):
455446
return list(
456447
map(
457-
lambda x: (
458-
(pd.to_datetime(x) - pd.Timestamp("1970-01-01"))
459-
// pd.Timedelta('1ms')),
460-
ts_list))
448+
lambda x: ((pd.to_datetime(x) - pd.Timestamp("1970-01-01")) // pd.Timedelta("1ms")),
449+
ts_list,
450+
)
451+
)
461452

462453
@staticmethod
463454
def _convert_timestamp_to_epoch_ms(timestamp):
464-
return (pd.to_datetime(timestamp) -
465-
pd.Timestamp("1970-01-01")) // pd.Timedelta('1ms')
455+
return (pd.to_datetime(timestamp) - pd.Timestamp("1970-01-01")) // pd.Timedelta("1ms")
466456

467457
def set_xaxis_range(self, start=None, end=None):
468458
"""Set x-axis range.
@@ -541,17 +531,17 @@ def set_xaxis_tick_format(self, date_format):
541531
Returns:
542532
Current chart object
543533
"""
544-
self._chart.figure.xaxis[
545-
0].formatter = bokeh.models.DatetimeTickFormatter(
546-
milliseconds=[date_format],
547-
seconds=[date_format],
548-
minsec=[date_format],
549-
minutes=[date_format],
550-
hourmin=[date_format],
551-
hours=[date_format],
552-
days=[date_format],
553-
months=[date_format],
554-
years=[date_format])
534+
self._chart.figure.xaxis[0].formatter = bokeh.models.DatetimeTickFormatter(
535+
milliseconds=[date_format],
536+
seconds=[date_format],
537+
minsec=[date_format],
538+
minutes=[date_format],
539+
hourmin=[date_format],
540+
hours=[date_format],
541+
days=[date_format],
542+
months=[date_format],
543+
years=[date_format],
544+
)
555545
return self._chart
556546

557547

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

561551
def __init__(self, chart):
562552
super(NumericalXAxis, self).__init__(chart)
563-
self._chart.style._apply_settings('categorical_yaxis')
553+
self._chart.style._apply_settings("categorical_yaxis")
564554

565555

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

569559
def __init__(self, chart):
570560
super(NumericalYAxis, self).__init__(chart)
571-
self._chart.style._apply_settings('categorical_xaxis')
561+
self._chart.style._apply_settings("categorical_xaxis")
572562

573563

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

585575
def __init__(self, chart):
586576
super(CategoricalXYAxes, self).__init__(chart)
587-
self._chart.style._apply_settings('categorical_xyaxis')
577+
self._chart.style._apply_settings("categorical_xyaxis")
588578

589579

590580
class SecondYNumericalAxis(YAxisMixin, NumericalYMixin):
591581
"""Axis class for second Y numerical axes."""
582+
592583
def __init__(self, chart):
593584
self._chart = chart
594-
self._y_range_name = 'second_y'
595-
self._chart.figure.extra_y_ranges = {
596-
self._y_range_name: DataRange1d(bounds='auto')
597-
}
585+
self._y_range_name = "second_y"
586+
self._chart.figure.extra_y_ranges = {self._y_range_name: DataRange1d(bounds="auto")}
598587
# Add the appropriate axis type to the figure.
599588
axis_class = LinearAxis
600-
if self._chart._second_y_axis_type == 'log':
589+
if self._chart._second_y_axis_type == "log":
601590
axis_class = LogAxis
602-
self._chart.figure.add_layout(
603-
axis_class(y_range_name=self._y_range_name), 'right')
591+
self._chart.figure.add_layout(axis_class(y_range_name=self._y_range_name), "right")
604592

605593
self._y_axis_index = 1
606594
self._y_range = self._chart.figure.extra_y_ranges[self._y_range_name]
607-
self._chart.style._apply_settings('second_y_axis')
595+
self._chart.style._apply_settings("second_y_axis")
608596

609597

610598
class SecondAxis:

0 commit comments

Comments
 (0)