From 46a8dc70ad3c296c922ee025c68e52f81805930e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 31 Jul 2011 11:45:44 -0400 Subject: [PATCH] Fixed failing test case in Pie.add_data. Tests now pass on Python 3 --- svg/charts/pie.py | 80 ++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/svg/charts/pie.py b/svg/charts/pie.py index 7e4cd32..2958043 100644 --- a/svg/charts/pie.py +++ b/svg/charts/pie.py @@ -1,5 +1,5 @@ import math -from operator import add +import itertools from lxml import etree from svg.charts.graph import Graph @@ -14,15 +14,15 @@ RADIANS = math.pi/180 class Pie(Graph): """ A presentation-quality SVG pie graph - + Synopsis ======== - + from svg.charts.pie import Pie fields = ['Jan', 'Feb', 'Mar'] - + data_sales_02 = [12, 45, 21] - + graph = Pie(dict( height = 500, width = 300, @@ -30,7 +30,7 @@ class Pie(Graph): graph.add_data({'data': data_sales_02, 'title': 'Sales 2002'}) print "Content-type" image/svg+xml\r\n\r\n' print graph.burn() - + Description =========== This object aims to allow you to easily create high quality @@ -44,14 +44,14 @@ class Pie(Graph): "if true, displays a drop shadow for the chart" show_shadow = True "Sets the offset of the shadow from the pie chart" - shadow_offset = 10 + shadow_offset = 10 show_data_labels = False - "If true, display the actual field values in the data labels" + "If true, display the actual field values in the data labels" show_actual_values = False "If true, display the percentage value of each pie wedge in the data labels" show_percent = True - + "If true, display the labels in the key" show_key_data_labels = True "If true, display the actual value of the field in the key" @@ -59,13 +59,13 @@ class Pie(Graph): "If true, display the percentage value of the wedges in the key" show_key_percent = False - "If true, explode the pie (put space between the wedges)" + "If true, explode the pie (put space between the wedges)" expanded = False "If true, expand the largest pie wedge" expand_greatest = False "The amount of space between expanded wedges" expand_gap = 10 - + show_x_labels = False show_y_labels = False @@ -77,22 +77,38 @@ class Pie(Graph): def add_data(self, data_descriptor): """ Add a data set to the graph - + >>> graph.add_data({data:[1,2,3,4]}) # doctest: +SKIP - + Note that a 'title' key is ignored. - + Multiple calls to add_data will sum the elements, and the pie will display the aggregated data. e.g. - + >>> graph.add_data({data:[1,2,3,4]}) # doctest: +SKIP >>> graph.add_data({data:[2,3,5,7]}) # doctest: +SKIP - + is the same as: - - graph.add_data({data:[3,5,8,11]}) # doctest: +SKIP + + >>> graph.add_data({data:[3,5,8,11]}) # doctest: +SKIP + + If data is added of with differing lengths, the corresponding + values will be assumed to be zero. + + >>> graph.add_data({data:[1,2,3,4]}) # doctest: +SKIP + >>> graph.add_data({data:[5,7]}) # doctest: +SKIP + + is the same as: + + >>> graph.add_data({data:[5,7]}) # doctest: +SKIP + >>> graph.add_data({data:[1,2,3,4]}) # doctest: +SKIP + + and + + >>> graph.add_data({data:[6,9,3,4]}) # doctest: +SKIP """ - self.data = map(robust_add, self.data, data_descriptor['data']) + pairs = itertools.izip_longest(self.data, data_descriptor['data']) + self.data = list(itertools.starmap(robust_add, pairs)) def add_defs(self, defs): "Add svg definitions" @@ -123,7 +139,7 @@ class Pie(Graph): return [''] def keys(self): - total = reduce(add, self.data) + total = sum(self.data) percent_scale = 100.0 / total def key(field, value): result = [field] @@ -133,13 +149,13 @@ class Pie(Graph): result.append(percent) return ' '.join(result) return map(key, self.fields, self.data) - + def draw_data(self): self.graph = etree.SubElement(self.root, 'g') background = etree.SubElement(self.graph, 'g') # midground is somewhere between the background and the foreground midground = etree.SubElement(self.graph, 'g') - + is_expanded = (self.expanded or self.expand_greatest) diameter = min(self.graph_width, self.graph_height) # the following assumes int(True)==1 and int(False)==0 @@ -157,7 +173,7 @@ class Pie(Graph): wedge_text_pad = 5 wedge_text_pad = 20 * int(self.show_percent) * int(self.show_data_labels) - total = reduce(add, self.data) + total = sum(self.data) max_value = max(self.data) percent_scale = 100.0 / total @@ -166,7 +182,7 @@ class Pie(Graph): rad_mult = 3.6 * RADIANS for index, (field, value) in enumerate(zip(self.fields, self.data)): percent = percent_scale * value - + radians = prev_percent * rad_mult x_start = radius+(math.sin(radians) * radius) y_start = radius-(math.cos(radians) * radius) @@ -182,7 +198,7 @@ class Pie(Graph): "%(percent_greater_fifty)s,1,", "%(x_end)s %(y_end)s Z")) path = path % vars() - + wedge = etree.SubElement( self.foreground, 'path', @@ -191,13 +207,13 @@ class Pie(Graph): 'class': 'fill%s' % (index+1), } ) - + translate = None tx = 0 ty = 0 half_percent = prev_percent + percent / 2 radians = half_percent * rad_mult - + if self.show_shadow: shadow = etree.SubElement( background, @@ -215,20 +231,20 @@ class Pie(Graph): # consider getting the style from the stylesheet style="fill:#fff; stroke:none;", ) - + if self.expanded or (self.expand_greatest and value == max_value): tx = (math.sin(radians) * self.expand_gap) ty = -(math.cos(radians) * self.expand_gap) translate = "translate(%(tx)s %(ty)s)" % vars() wedge.set('transform', translate) clear.set('transform', translate) - + if self.show_shadow: shadow_tx = self.shadow_offset + tx shadow_ty = self.shadow_offset + ty translate = 'translate(%(shadow_tx)s %(shadow_ty)s)' % vars() shadow.set('transform', translate) - + if self.show_data_labels and value != 0: label = [] if self.show_key_data_labels: @@ -243,7 +259,7 @@ class Pie(Graph): mcr = math.cos(radians) tx = radius + (msr * radius) ty = radius -(mcr * radius) - + if self.expanded or (self.expand_greatest and value == max_value): tx += (msr * self.expand_gap) ty -= (mcr * self.expand_gap) @@ -270,7 +286,7 @@ class Pie(Graph): } ) label_node.text = label - + prev_percent += percent def round(self, val, to):