From 7430ac7b0b239968ec69d9a1493723aaa9ded2e8 Mon Sep 17 00:00:00 2001 From: Florian Mounier Date: Thu, 25 Feb 2016 18:04:50 +0100 Subject: [PATCH] * Fix range option for some Charts (Fix #297 Fix #298) --- demo/moulinrouge/tests.py | 7 +++++++ docs/changelog.rst | 2 ++ pygal/graph/funnel.py | 6 ++++++ pygal/graph/histogram.py | 6 ++++++ pygal/graph/pyramid.py | 16 +++++++++++++--- pygal/graph/stackedbar.py | 14 ++++++++++---- pygal/test/test_config.py | 17 +++++++++++++++++ pygal/view.py | 6 +++--- 8 files changed, 64 insertions(+), 10 deletions(-) diff --git a/demo/moulinrouge/tests.py b/demo/moulinrouge/tests.py index 2e061d7..2c944cc 100644 --- a/demo/moulinrouge/tests.py +++ b/demo/moulinrouge/tests.py @@ -354,6 +354,13 @@ def get_test_routes(app): graph.add('2', [73, -14, 10, None, -58, 32, 91]) return graph.render_response() + @app.route('/test/range/') + def test_range_for(chart): + graph = CHARTS_BY_NAME[chart]() + graph.range = [0, 100] + graph.add('1', [1, 2, 10]) + return graph.render_response() + @app.route('/test/fill_with_none/') def test_fill_with_none(): graph = XY(fill=True) diff --git a/docs/changelog.rst b/docs/changelog.rst index 8482a06..6976ddf 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -10,6 +10,8 @@ Changelog * Add horizontal line charts (thanks @chartique #301) * There is now a `formatter` config option to format values as specified. The formatter callable may or may not take `chart`, `serie` and `index` as argument. The default value formatting is now chart dependent and is value_formatter for most graph but could be a combination of value_formatter and x_value_formatter for dual charts. * The `human_readable` option has been removed. Now you have to use the pygal.formatters.human_readable formatter (value_formatter=human_readable instead of human_readable=True) +* New chart type: SolidGauge (thanks @chartique #295) +* Fix range option for some Charts (#297 #298) 2.1.1 ===== diff --git a/pygal/graph/funnel.py b/pygal/graph/funnel.py index b652539..cf54156 100644 --- a/pygal/graph/funnel.py +++ b/pygal/graph/funnel.py @@ -90,6 +90,12 @@ class Funnel(Graph): self._box.ymin = -val_max self._box.ymax = val_max + if self.range and self.range[0] is not None: + self._box.ymin = self.range[0] + + if self.range and self.range[1] is not None: + self._box.ymax = self.range[1] + def _compute_x_labels(self): self._x_labels = list( zip(self.x_labels and diff --git a/pygal/graph/histogram.py b/pygal/graph/histogram.py index b7dd529..63932e6 100644 --- a/pygal/graph/histogram.py +++ b/pygal/graph/histogram.py @@ -125,3 +125,9 @@ class Histogram(Dual, Bar): self._box.xmin, self._box.xmax = xmin, xmax if yrng: self._box.ymin, self._box.ymax = ymin, ymax + + if self.range and self.range[0] is not None: + self._box.ymin = self.range[0] + + if self.range and self.range[1] is not None: + self._box.ymax = self.range[1] diff --git a/pygal/graph/pyramid.py b/pygal/graph/pyramid.py index a5138c0..b592d6c 100644 --- a/pygal/graph/pyramid.py +++ b/pygal/graph/pyramid.py @@ -54,9 +54,19 @@ class VerticalPyramid(StackedBar): def _compute_box(self, positive_vals, negative_vals): """Compute Y min and max""" - self._box.ymax = max(max(positive_vals or [self.zero]), - max(negative_vals or [self.zero])) - self._box.ymin = - self._box.ymax + max_ = max( + max(positive_vals or [self.zero]), + max(negative_vals or [self.zero])) + + if self.range and self.range[0] is not None: + self._box.ymin = self.range[0] + else: + self._box.ymin = - max_ + + if self.range and self.range[1] is not None: + self._box.ymax = self.range[1] + else: + self._box.ymax = max_ def _pre_compute_secondary(self, positive_vals, negative_vals): """Compute secondary y min and max""" diff --git a/pygal/graph/stackedbar.py b/pygal/graph/stackedbar.py index 13848b0..ec136eb 100644 --- a/pygal/graph/stackedbar.py +++ b/pygal/graph/stackedbar.py @@ -50,10 +50,16 @@ class StackedBar(Bar): def _compute_box(self, positive_vals, negative_vals): """Compute Y min and max""" - self._box.ymin = negative_vals and min( - min(negative_vals), self.zero) or self.zero - self._box.ymax = positive_vals and max( - max(positive_vals), self.zero) or self.zero + if self.range and self.range[0] is not None: + self._box.ymin = self.range[0] + else: + self._box.ymin = negative_vals and min( + min(negative_vals), self.zero) or self.zero + if self.range and self.range[1] is not None: + self._box.ymax = self.range[1] + else: + self._box.ymax = positive_vals and max( + max(positive_vals), self.zero) or self.zero def _compute(self): """Compute y min and max and y scale and set labels""" diff --git a/pygal/test/test_config.py b/pygal/test/test_config.py index 6ac34b6..81ff2b1 100644 --- a/pygal/test/test_config.py +++ b/pygal/test/test_config.py @@ -390,6 +390,23 @@ def test_x_y_title(Chart): assert len(q('.titles .title')) == 3 +def test_range(Chart): + """Test y label major option""" + if Chart in ( + Pie, Treemap, Dot, SolidGauge + ) or issubclass(Chart, BaseMap): + return + chart = Chart() + chart.range = (0, 100) + chart.add('', [1, 2, 10]) + q = chart.render_pyquery() + axis = map(str, range(0, 101, 10)) + if Chart == Radar: + axis = map(str, range(100, -1, -20)) + z = 'x' if getattr(chart, 'horizontal', False) or Chart == Gauge else 'y' + assert [t.text for t in q('.axis.%s .guides text' % z)] == list(axis) + + def test_x_label_major(Chart): """Test x label major option""" if Chart in ( diff --git a/pygal/view.py b/pygal/view.py index 44bc8ca..2a9abc4 100644 --- a/pygal/view.py +++ b/pygal/view.py @@ -79,7 +79,7 @@ class Box(object): @xmin.setter def xmin(self, value): """X minimum setter""" - if value: + if value is not None: self._xmin = value @property @@ -90,7 +90,7 @@ class Box(object): @ymin.setter def ymin(self, value): """Y minimum setter""" - if value: + if value is not None: self._ymin = value @property @@ -101,7 +101,7 @@ class Box(object): @xmax.setter def xmax(self, value): """X maximum setter""" - if value: + if value is not None: self._xmax = value @property