Browse Source

Clean code + fix test

pull/78/head
Florian Mounier 11 years ago
parent
commit
66041bdb54
  1. 1
      pygal/config.py
  2. 2
      pygal/graph/base.py
  3. 58
      pygal/graph/graph.py
  4. 4
      pygal/graph/histogram.py
  5. 3
      pygal/graph/horizontalbar.py
  6. 4
      pygal/graph/xy.py
  7. 5
      pygal/test/test_donut.py
  8. 72
      pygal/test/test_graph.py
  9. 8
      pygal/view.py

1
pygal/config.py

@ -176,7 +176,6 @@ class Config(object):
inner_radius = Key( inner_radius = Key(
0, float, "Look", "Piechart inner radius (donut), must be <.9") 0, float, "Look", "Piechart inner radius (donut), must be <.9")
############ Label ############ ############ Label ############
x_labels = Key( x_labels = Key(
None, list, "Label", None, list, "Label",

2
pygal/graph/base.py

@ -243,7 +243,7 @@ class BaseGraph(object):
"""Check if there is any data""" """Check if there is any data"""
return sum( return sum(
map(len, map(lambda s: s.safe_values, self.series))) != 0 and ( map(len, map(lambda s: s.safe_values, self.series))) != 0 and (
sum(map(abs, self._values)) != 0) sum(map(abs, self._values)) != 0)
def render(self, is_unicode=False): def render(self, is_unicode=False):
"""Render the graph, and return the svg string""" """Render the graph, and return the svg string"""

58
pygal/graph/graph.py

@ -132,7 +132,7 @@ class Graph(BaseGraph):
last_label_position = self.view.x(self._x_labels[-1][1]) last_label_position = self.view.x(self._x_labels[-1][1])
available_space = ( available_space = (
last_label_position - first_label_position) / ( last_label_position - first_label_position) / (
len(self._x_labels) - 1) len(self._x_labels) - 1)
truncation = reverse_text_len( truncation = reverse_text_len(
available_space, self.label_font_size) available_space, self.label_font_size)
truncation = max(truncation, 1) truncation = max(truncation, 1)
@ -179,15 +179,13 @@ class Graph(BaseGraph):
y=y, y=y,
class_='major' if major else '' class_='major' if major else ''
) )
if isinstance(label, dict): if isinstance(label, dict):
text.text = truncate(label['title'], truncation) label = label['title']
else:
text.text = truncate(label, truncation) text.text = truncate(label, truncation)
if text.text != label: if text.text != label:
if isinstance(label, dict): self.svg.node(guides, 'title').text = label
self.svg.node(guides, 'title').text = label['title']
else:
self.svg.node(guides, 'title').text = label
if self.x_label_rotation: if self.x_label_rotation:
text.attrib['transform'] = "rotate(%d %f %f)" % ( text.attrib['transform'] = "rotate(%d %f %f)" % (
self.x_label_rotation, x, y) self.x_label_rotation, x, y)
@ -252,10 +250,11 @@ class Graph(BaseGraph):
y=y + .35 * self.label_font_size, y=y + .35 * self.label_font_size,
class_='major' if major else '' class_='major' if major else ''
) )
if isinstance(label, dict): if isinstance(label, dict):
text.text = label['title'] label = label['title']
else: text.text = label
text.text = label
if self.y_label_rotation: if self.y_label_rotation:
text.attrib['transform'] = "rotate(%d %f %f)" % ( text.attrib['transform'] = "rotate(%d %f %f)" % (
self.y_label_rotation, x, y) self.y_label_rotation, x, y)
@ -359,31 +358,22 @@ class Graph(BaseGraph):
height=self.legend_box_size, height=self.legend_box_size,
class_="color-%d reactive" % (global_serie_number % 16) class_="color-%d reactive" % (global_serie_number % 16)
) )
if isinstance(title, dict): if isinstance(title, dict):
truncated = truncate(title['title'], truncation) node = decorate(self.svg, legend, title)
a = decorate(self.svg, legend, title) title = title['title']
self.svg.node(
a, 'text',
x=col * x_step + self.legend_box_size + 5,
y=1.5 * row * h
+ .5 * h
+ .3 * self.legend_font_size
).text = truncated
#as <a> is decorated with title I do not think we need title here
if truncated != title['title']:
self.svg.node(legend, 'title').text = title['title']
else: else:
truncated = truncate(title, truncation) node = legend
# Serious magical numbers here
self.svg.node( truncated = truncate(title, truncation)
legend, 'text', self.svg.node(
x=col * x_step + self.legend_box_size + 5, node, 'text',
y=1.5 * row * h x=col * x_step + self.legend_box_size + 5,
+ .5 * h y=1.5 * row * h + .5 * h + .3 * self.legend_font_size
+ .3 * self.legend_font_size ).text = truncated
).text = truncated
if truncated != title: if truncated != title:
self.svg.node(legend, 'title').text = title self.svg.node(legend, 'title').text = title
def _title(self): def _title(self):
"""Make the title""" """Make the title"""

4
pygal/graph/histogram.py

@ -67,8 +67,8 @@ class Histogram(Graph):
"""Check if there is any data""" """Check if there is any data"""
return sum( return sum(
map(len, map(lambda s: s.safe_values, self.series))) != 0 and any(( map(len, map(lambda s: s.safe_values, self.series))) != 0 and any((
sum(map(abs, self.xvals)) != 0, sum(map(abs, self.xvals)) != 0,
sum(map(abs, self.yvals)) != 0)) sum(map(abs, self.yvals)) != 0))
def _bar(self, parent, x0, x1, y, index, i, zero, secondary=False): def _bar(self, parent, x0, x1, y, index, i, zero, secondary=False):
x, y = self.view((x0, y)) x, y = self.view((x0, y))

3
pygal/graph/horizontalbar.py

@ -23,6 +23,7 @@ Horizontal bar graph
from pygal.graph.horizontal import HorizontalGraph from pygal.graph.horizontal import HorizontalGraph
from pygal.graph.bar import Bar from pygal.graph.bar import Bar
class HorizontalBar(HorizontalGraph, Bar): class HorizontalBar(HorizontalGraph, Bar):
"""Horizontal Bar graph""" """Horizontal Bar graph"""
@ -31,5 +32,5 @@ class HorizontalBar(HorizontalGraph, Bar):
num = len(self.series) - index - 1 num = len(self.series) - index - 1
self.bar(self._serie(num), serie, index) self.bar(self._serie(num), serie, index)
for index, serie in enumerate(self.secondary_series[::-1]): for index, serie in enumerate(self.secondary_series[::-1]):
num = len(self.secondary_series) + len(self.series) - index -1 num = len(self.secondary_series) + len(self.series) - index - 1
self.bar(self._serie(num), serie, index + len(self.series), True) self.bar(self._serie(num), serie, index + len(self.series), True)

4
pygal/graph/xy.py

@ -48,8 +48,8 @@ class XY(Line):
"""Check if there is any data""" """Check if there is any data"""
return sum( return sum(
map(len, map(lambda s: s.safe_values, self.series))) != 0 and any(( map(len, map(lambda s: s.safe_values, self.series))) != 0 and any((
sum(map(abs, self.xvals)) != 0, sum(map(abs, self.xvals)) != 0,
sum(map(abs, self.yvals)) != 0)) sum(map(abs, self.yvals)) != 0))
def _compute(self): def _compute(self):
if self.xvals: if self.xvals:

5
pygal/test/test_donut.py

@ -20,6 +20,7 @@ import os
import uuid import uuid
from pygal import Pie from pygal import Pie
def test_donut(): def test_donut():
file_name = '/tmp/test_graph-%s.svg' % uuid.uuid4() file_name = '/tmp/test_graph-%s.svg' % uuid.uuid4()
if os.path.exists(file_name): if os.path.exists(file_name):
@ -36,6 +37,7 @@ def test_donut():
assert 'pygal' in f.read() assert 'pygal' in f.read()
os.remove(file_name) os.remove(file_name)
def test_multiseries_donut(): def test_multiseries_donut():
#this just demos that the multiseries pie does not respect the inner_radius #this just demos that the multiseries pie does not respect the inner_radius
file_name = '/tmp/test_graph-%s.svg' % uuid.uuid4() file_name = '/tmp/test_graph-%s.svg' % uuid.uuid4()
@ -52,6 +54,3 @@ def test_multiseries_donut():
with open(file_name) as f: with open(file_name) as f:
assert 'pygal' in f.read() assert 'pygal' in f.read()
os.remove(file_name) os.remove(file_name)

72
pygal/test/test_graph.py

@ -150,7 +150,7 @@ def test_values_by_dict(Chart):
chart1 = Chart(no_prefix=True) chart1 = Chart(no_prefix=True)
chart2 = Chart(no_prefix=True) chart2 = Chart(no_prefix=True)
if Chart != pygal.Worldmap: if not issubclass(Chart, pygal.Worldmap):
chart1.add('A', {'red': 10, 'green': 12, 'blue': 14}) chart1.add('A', {'red': 10, 'green': 12, 'blue': 14})
chart1.add('B', {'green': 11, 'red': 7}) chart1.add('B', {'green': 11, 'red': 7})
chart1.add('C', {'blue': 7}) chart1.add('C', {'blue': 7})
@ -242,7 +242,7 @@ def test_unicode_labels_decode(Chart):
'label': 'unicode <3' 'label': 'unicode <3'
}]) }])
chart.x_labels = [u('&œ'), u('¿?'), u('††††††††'), 'unicode <3'] chart.x_labels = [u('&œ'), u('¿?'), u('††††††††'), 'unicode <3']
q = chart.render_pyquery() chart.render_pyquery()
def test_unicode_labels_python2(Chart): def test_unicode_labels_python2(Chart):
@ -264,7 +264,7 @@ def test_unicode_labels_python2(Chart):
'label': eval("'unicode <3'") 'label': eval("'unicode <3'")
}]) }])
chart.x_labels = eval("[u'&œ', u'¿?', u'††††††††', 'unicode <3']") chart.x_labels = eval("[u'&œ', u'¿?', u'††††††††', 'unicode <3']")
q = chart.render_pyquery() chart.render_pyquery()
def test_unicode_labels_python3(Chart): def test_unicode_labels_python3(Chart):
@ -286,47 +286,55 @@ def test_unicode_labels_python3(Chart):
'label': eval("b'unicode <3'") 'label': eval("b'unicode <3'")
}]) }])
chart.x_labels = eval("['&œ', '¿?', '††††††††', 'unicode <3']") chart.x_labels = eval("['&œ', '¿?', '††††††††', 'unicode <3']")
q = chart.render_pyquery() chart.render_pyquery()
def test_labels_with_links(Chart): def test_labels_with_links(Chart):
chart = Chart() chart = Chart()
#link on chart and label # link on chart and label
chart.add({'title':'Red','xlink': chart.add({
{'href': 'http://en.wikipedia.org/wiki/Red'}}, 'title': 'Red', 'xlink': {'href': 'http://en.wikipedia.org/wiki/Red'}
[{ }, [{
'value': 2, 'value': 2,
'label': 'This is red', 'label': 'This is red',
'xlink': {'href': 'http://en.wikipedia.org/wiki/Red'}}]) 'xlink': {'href': 'http://en.wikipedia.org/wiki/Red'}}])
#link on chart only
# link on chart only
chart.add('Green', [{ chart.add('Green', [{
'value': 4, 'value': 4,
'label': 'This is green', 'label': 'This is green',
'xlink': { 'xlink': {
'href': 'http://en.wikipedia.org/wiki/Green', 'href': 'http://en.wikipedia.org/wiki/Green',
'target': '_top'} 'target': '_top'}}])
}])
#link on label only opens in new tab # link on label only opens in new tab
chart.add({'title': 'Yellow', 'xlink': { chart.add({'title': 'Yellow', 'xlink': {
'href': 'http://en.wikipedia.org/wiki/Yellow', 'href': 'http://en.wikipedia.org/wiki/Yellow',
'target': '_blank'}}, 7) 'target': '_blank'}}, 7)
#link on chart only
# link on chart only
chart.add('Blue', [{ chart.add('Blue', [{
'value': 5, 'value': 5,
'xlink': { 'xlink': {
'href': 'http://en.wikipedia.org/wiki/Blue', 'href': 'http://en.wikipedia.org/wiki/Blue',
'target': '_blank'} 'target': '_blank'}}])
}])
#link on label and chart with diffrent behaviours # link on label and chart with diffrent behaviours
chart.add({'title': 'Violet', chart.add({
'xlink': 'http://en.wikipedia.org/wiki/Violet_(color)'}, 'title': 'Violet',
[{ 'xlink': 'http://en.wikipedia.org/wiki/Violet_(color)'
'value': 3, }, [{
'label': 'This is violet', 'value': 3,
'xlink': { 'label': 'This is violet',
'xlink': {
'href': 'http://en.wikipedia.org/wiki/Violet_(color)', 'href': 'http://en.wikipedia.org/wiki/Violet_(color)',
'target': '_self'} 'target': '_self'}}])
}])
q = chart.render_pyquery() q = chart.render_pyquery()
links = q('a') links = q('a')
assert(len(links) == 8) # 7 links and 1 tooltip
if issubclass(chart.cls, pygal.graph.worldmap.Worldmap):
# No country is found in this case so:
assert len(links) == 4 # 3 links and 1 tooltip
else:
assert len(links) == 8 # 7 links and 1 tooltip

8
pygal/view.py

@ -214,7 +214,7 @@ class PolarLogView(View):
return super(PolarLogView, self).__call__((0, 0)) return super(PolarLogView, self).__call__((0, 0))
rho = (self.box._rmax - self.box._rmin) * ( rho = (self.box._rmax - self.box._rmin) * (
log10(rho) - self.log10_rmin) / ( log10(rho) - self.log10_rmin) / (
self.log10_rmax - self.log10_rmin) self.log10_rmax - self.log10_rmin)
return super(PolarLogView, self).__call__( return super(PolarLogView, self).__call__(
(rho * cos(theta), rho * sin(theta))) (rho * cos(theta), rho * sin(theta)))
@ -242,7 +242,7 @@ class PolarThetaView(View):
start = 3 * pi / 2 + aperture / 2 start = 3 * pi / 2 + aperture / 2
theta = start + (2 * pi - aperture) * ( theta = start + (2 * pi - aperture) * (
theta - self.box._tmin) / ( theta - self.box._tmin) / (
self.box._tmax - self.box._tmin) self.box._tmax - self.box._tmin)
return super(PolarThetaView, self).__call__( return super(PolarThetaView, self).__call__(
(rho * cos(theta), rho * sin(theta))) (rho * cos(theta), rho * sin(theta)))
@ -269,7 +269,7 @@ class PolarThetaLogView(View):
return super(PolarThetaLogView, self).__call__((0, 0)) return super(PolarThetaLogView, self).__call__((0, 0))
theta = self.box._tmin + (self.box._tmax - self.box._tmin) * ( theta = self.box._tmin + (self.box._tmax - self.box._tmin) * (
log10(theta) - self.log10_tmin) / ( log10(theta) - self.log10_tmin) / (
self.log10_tmax - self.log10_tmin) self.log10_tmax - self.log10_tmin)
aperture = pi / 3 aperture = pi / 3
if theta > self.box._tmax: if theta > self.box._tmax:
theta = (3 * pi - aperture / 2) / 2 theta = (3 * pi - aperture / 2) / 2
@ -279,7 +279,7 @@ class PolarThetaLogView(View):
start = 3 * pi / 2 + aperture / 2 start = 3 * pi / 2 + aperture / 2
theta = start + (2 * pi - aperture) * ( theta = start + (2 * pi - aperture) * (
theta - self.box._tmin) / ( theta - self.box._tmin) / (
self.box._tmax - self.box._tmin) self.box._tmax - self.box._tmin)
return super(PolarThetaLogView, self).__call__( return super(PolarThetaLogView, self).__call__(
(rho * cos(theta), rho * sin(theta))) (rho * cos(theta), rho * sin(theta)))

Loading…
Cancel
Save