diff --git a/demo/moulinrouge/tests.py b/demo/moulinrouge/tests.py index ddd1d61..667ef2a 100644 --- a/demo/moulinrouge/tests.py +++ b/demo/moulinrouge/tests.py @@ -6,7 +6,10 @@ from pygal.style import styles def get_test_routes(app): - lnk = lambda v, l=None: {'value': v, 'xlink': 'javascript:alert("Test %s")' % v, 'label': l} + lnk = lambda v, l=None: { + 'value': v, + 'xlink': 'javascript:alert("Test %s")' % v, + 'label': l} @app.route('/test/unsorted') def test_unsorted(): diff --git a/pygal/graph/verticalpyramid.py b/pygal/graph/verticalpyramid.py index cd2c71f..ede8a95 100644 --- a/pygal/graph/verticalpyramid.py +++ b/pygal/graph/verticalpyramid.py @@ -43,7 +43,7 @@ class VerticalPyramid(Bar): for index, serie in enumerate(self.series) if not index % 2]) positive_sum = map(sum, positive_vals) or [0] - negative_sum = map(sum, negative_vals) + negative_sum = map(sum, negative_vals) or [0] self._box.ymax = max(max(positive_sum), max(negative_sum)) self._box.ymin = - self._box.ymax diff --git a/pygal/svg.py b/pygal/svg.py index c40b9a1..a5748ab 100644 --- a/pygal/svg.py +++ b/pygal/svg.py @@ -120,12 +120,15 @@ class Svg(object): def line(self, node, coords, close=False, **kwargs): """Draw a svg line""" - if len(coords) < 2: + line_len = len(coords) + if line_len < 2: return root = 'M%s L%s Z' if close else 'M%s L%s' origin_index = 0 - while None in coords[origin_index]: + while origin_index < line_len and None in coords[origin_index]: origin_index += 1 + if origin_index == line_len: + return origin = coord_format(coords[origin_index]) line = ' '.join([coord_format(c) for c in coords[origin_index + 1:] diff --git a/pygal/test/test_graph.py b/pygal/test/test_graph.py index 88309e9..509bd20 100644 --- a/pygal/test/test_graph.py +++ b/pygal/test/test_graph.py @@ -85,3 +85,40 @@ def test_metadata(Chart): 'Three', 'http://4.example.com/', 'Five', 'http://7.example.com/', 'Seven'): assert md in cut(q('desc'), 'text') + + +def test_empty_lists(Chart): + chart = Chart() + chart.add('A', [1, 2]) + chart.add('B', []) + chart.x_labels = ('red', 'green', 'blue') + q = chart.render_pyquery() + assert len(q(".legend")) == 2 + + chart = Chart() + chart.add('A', [None, None]) + chart.add('B', [None, 4, 4]) + chart.x_labels = ('red', 'green', 'blue') + q = chart.render_pyquery() + assert len(q(".legend")) == 2 + + +def test_values_by_dict(Chart): + chart = Chart() + chart.add('A', {'red': 10, 'green': 12, 'blue': 14}) + chart.add('B', {'green': 11, 'red': 7}) + chart.add('C', {'blue': 7}) + chart.add('D', {}) + chart.add('E', {'blue': 2, 'red': 13}) + chart.x_labels = ('red', 'green', 'blue') + chart1 = chart.render() + + chart = Chart() + chart.add('A', [10, 12, 14]) + chart.add('B', [7, 11]) + chart.add('C', [None, None, 7]) + chart.add('D', []) + chart.add('E', [13, None, 2]) + chart.x_labels = ('red', 'green', 'blue') + chart2 = chart.render() + assert chart1 == chart2 diff --git a/pygal/util.py b/pygal/util.py index 8641a00..46929de 100644 --- a/pygal/util.py +++ b/pygal/util.py @@ -29,12 +29,6 @@ from pygal.adapters import not_zero, positive ORDERS = u"yzafpnµm kMGTPEZY" -def get_value(val): - if isinstance(val, dict): - return val['value'] - return val - - def float_format(number): """Format a float to a precision of 3, without zeroes or dots""" return ("%.3f" % number).rstrip('0').rstrip('.') @@ -307,10 +301,17 @@ def prepare_values(raw, config, cls): adapters = [not_zero, positive] + adapters adapter = reduce(compose, adapters) series = [] - width = max([len(values) for _, values in raw]) + width = max([len(values) for _, values in raw] + + [len(config.x_labels or [])]) for title, raw_values in raw: metadata = {} values = [] + if isinstance(raw_values, dict): + value_list = [None] * width + for k, v in raw_values.items(): + if k in config.x_labels: + value_list[config.x_labels.index(k)] = v + raw_values = value_list for index, raw_value in enumerate( raw_values + ( (width - len(raw_values)) * [None] # aligning values