Commits

Jason R. Coombs committed 9f16e9e

Fixed failing test case in Pie.add_data. Tests now pass on Python 3

  • Participants
  • Parent commits e13f628

Comments (0)

Files changed (1)

File svg/charts/pie.py

 import math
-from operator import add
+import itertools
 from lxml import etree
 from svg.charts.graph import Graph
 
 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,
 	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
 	"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"
 	"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
 
 	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"
 		return ['']
 
 	def keys(self):
-		total = reduce(add, self.data)
+		total = sum(self.data)
 		percent_scale = 100.0 / total
 		def key(field, value):
 			result = [field]
 				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
 		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
 		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)
 				"%(percent_greater_fifty)s,1,",
 				"%(x_end)s %(y_end)s Z"))
 			path = path % vars()
-			
+
 			wedge = etree.SubElement(
 				self.foreground,
 				'path',
 					'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,
 					# 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:
 				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)
 					}
 				)
 				label_node.text = label
-			
+
 			prev_percent += percent
 
 	def round(self, val, to):