Browse Source

Improving coverture and robustness

pull/130/head
Florian Mounier 11 years ago
parent
commit
d7e9953d9a
  1. 15
      demo/moulinrouge/tests.py
  2. 14
      pygal/ghost.py
  3. 19
      pygal/graph/bar.py
  4. 2
      pygal/graph/graph.py
  5. 4
      pygal/graph/stackedbar.py
  6. 4
      pygal/graph/verticalpyramid.py
  7. 31
      pygal/test/test_config.py
  8. 6
      pygal/test/test_date.py
  9. 38
      pygal/test/test_graph.py
  10. 16
      pygal/test/test_line.py
  11. 28
      pygal/test/test_view.py
  12. 4
      pygal/view.py
  13. 1
      tox.ini

15
demo/moulinrouge/tests.py

@ -266,7 +266,6 @@ def get_test_routes(app):
hist.add('2', [(2, 2, 8)])
return hist.render_response()
@app.route('/test/ylabels')
def test_ylabels():
chart = Line()
@ -275,7 +274,6 @@ def get_test_routes(app):
chart.add('line', [.0002, .0005, .00035])
return chart.render_response()
@app.route('/test/secondary/<chart>')
def test_secondary_for(chart):
chart = CHARTS_BY_NAME[chart](fill=True)
@ -463,4 +461,15 @@ def get_test_routes(app):
return pie.render_response()
return filter(lambda x: x.startswith('test'), locals())
@app.route('/test/legend_at_bottom/<chart>')
def test_legend_at_bottom_for(chart):
graph = CHARTS_BY_NAME[chart]()
graph.add('1', [1, 3, 12, 3, 4, None, 9])
graph.add('2', [7, -4, 10, None, 8, 3, 1])
graph.add('3', [7, -14, -10, None, 8, 3, 1])
graph.add('4', [7, 4, -10, None, 8, 3, 1])
graph.x_labels = ('a', 'b', 'c', 'd', 'e', 'f', 'g')
graph.legend_at_bottom = True
return graph.render_response()
return list(filter(lambda x: x.startswith('test'), locals()))

14
pygal/ghost.py

@ -88,9 +88,9 @@ class Ghost(object):
def make_series(self, series):
return prepare_values(series, self.config, self.cls)
def make_instance(self, overrides={}):
def make_instance(self, overrides=None):
self.config(**self.__dict__)
self.config.__dict__.update(overrides)
self.config.__dict__.update(overrides or {})
series = self.make_series(self.raw_series)
secondary_series = self.make_series(self.raw_series2)
self._last__inst = self.cls(
@ -99,8 +99,10 @@ class Ghost(object):
return self._last__inst
# Rendering
def render(self, is_unicode=False):
return self.make_instance().render(is_unicode=is_unicode)
def render(self, is_unicode=False, **kwargs):
return (self
.make_instance(overrides=kwargs)
.render(is_unicode=is_unicode))
def render_tree(self):
return self.make_instance().render_tree()
@ -171,6 +173,10 @@ class Ghost(object):
spark_options.update(kwargs)
return self.make_instance(spark_options).render()
def _repr_svg_(self):
"""Display svg in IPython notebook"""
return self.render(disable_xml_declaration=True)
def _repr_png_(self):
"""Display png in IPython notebook"""
return self.render_to_png()

19
pygal/graph/bar.py

@ -37,18 +37,17 @@ class Bar(Graph):
super(Bar, self).__init__(*args, **kwargs)
def _bar(self, parent, x, y, index, i, zero,
shift=True, secondary=False, rounded=False):
secondary=False, rounded=False):
width = (self.view.x(1) - self.view.x(0)) / self._len
x, y = self.view((x, y))
series_margin = width * self._series_margin
x += series_margin
width -= 2 * series_margin
if shift:
width /= self._order
x += index * width
serie_margin = width * self._serie_margin
x += serie_margin
width -= 2 * serie_margin
width /= self._order
x += index * width
serie_margin = width * self._serie_margin
x += serie_margin
width -= 2 * serie_margin
height = self.view.y(zero) - y
r = rounded * 1 if rounded else 0
self.svg.transposable_node(
@ -115,12 +114,10 @@ class Bar(Graph):
min_0_ratio = (self.zero - self._box.ymin) / self._box.height or 1
max_0_ratio = (self._box.ymax - self.zero) / self._box.height or 1
new_ymax = (self.zero - ymin) * (1 / min_0_ratio - 1)
new_ymin = -(ymax - self.zero) * (1 / max_0_ratio - 1)
if ymax > self._box.ymax:
ymin = new_ymin
ymin = -(ymax - self.zero) * (1 / max_0_ratio - 1)
else:
ymax = new_ymax
ymax = (self.zero - ymin) * (1 / min_0_ratio - 1)
left_range = abs(self._box.ymax - self._box.ymin)
right_range = abs(ymax - ymin) or 1

2
pygal/graph/graph.py

@ -518,7 +518,7 @@ class Graph(BaseGraph):
steps = len(y_pos)
left_range = abs(y_pos[-1] - y_pos[0])
right_range = abs(ymax - ymin) or 1
scale = right_range / (steps - 1)
scale = right_range / ((steps - 1) or 1)
self._y_2nd_labels = [(self._format(ymin + i * scale), pos)
for i, pos in enumerate(y_pos)]

4
pygal/graph/stackedbar.py

@ -80,6 +80,8 @@ class StackedBar(Bar):
if self.secondary_series:
positive_vals, negative_vals = self._get_separated_values(True)
positive_vals = positive_vals or [self.zero]
negative_vals = negative_vals or [self.zero]
self.secondary_negative_cumulation = [0] * self._len
self.secondary_positive_cumulation = [0] * self._len
self._pre_compute_secondary(positive_vals, negative_vals)
@ -91,7 +93,7 @@ class StackedBar(Bar):
max(positive_vals), self.zero)) or self.zero
def _bar(self, parent, x, y, index, i, zero,
shift=False, secondary=False, rounded=False):
secondary=False, rounded=False):
if secondary:
cumulation = (self.secondary_negative_cumulation
if y < self.zero else

4
pygal/graph/verticalpyramid.py

@ -57,8 +57,8 @@ class VerticalPyramid(StackedBar):
self._secondary_min = - self._secondary_max
def _bar(self, parent, x, y, index, i, zero,
shift=True, secondary=False, rounded=False):
secondary=False, rounded=False):
if index % 2:
y = -y
return super(VerticalPyramid, self)._bar(
parent, x, y, index, i, zero, False, secondary, rounded)
parent, x, y, index, i, zero, secondary, rounded)

31
pygal/test/test_config.py

@ -323,3 +323,34 @@ def test_inline_css(Chart):
def test_meta_config():
from pygal.config import CONFIG_ITEMS
assert all(c.name != 'Unbound' for c in CONFIG_ITEMS)
def test_label_rotation(Chart):
chart = Chart(x_label_rotation=28)
chart.add('1', [4, -5, 123, 59, 38])
chart.add('2', [89, 0, 8, .12, 8])
chart.x_labels = ['one', 'twoooooooooooooooooooooo', 'three', '4']
q = chart.render_pyquery()
if Chart in (Line, Bar):
assert len(q('.guides text[transform^="rotate(28"]')) == 4
def test_legend_at_bottom(Chart):
chart = Chart(legend_at_bottom=True)
chart.add('1', [4, -5, 123, 59, 38])
chart.add('2', [89, 0, 8, .12, 8])
chart.x_labels = ['one', 'twoooooooooooooooooooooo', 'three', '4']
lab = chart.render()
chart.legend_at_bottom = False
assert lab != chart.render()
def test_x_y_title(Chart):
chart = Chart(title='I Am A Title',
x_title="I am a x title",
y_title="I am a y title")
chart.add('1', [4, -5, 123, 59, 38])
chart.add('2', [89, 0, 8, .12, 8])
chart.x_labels = ['one', 'twoooooooooooooooooooooo', 'three', '4']
q = chart.render_pyquery()
assert len(q('.titles .title')) == 3

6
pygal/test/test_date.py

@ -56,3 +56,9 @@ def test_date():
'2013-02-01',
'2013-03-01'
]
def test_date_overflow():
datey = DateY(truncate_label=1000)
datey.add('dates', [1, 2, -1000000, 5, 100000000])
assert datey.render_pyquery()

38
pygal/test/test_graph.py

@ -21,12 +21,18 @@ import os
import pygal
import uuid
import sys
import pytest
from pygal import i18n
from pygal.graph.frenchmap import DEPARTMENTS, REGIONS
from pygal.util import cut
from pygal._compat import u
from pygal.test import pytest_generate_tests, make_data
try:
import cairosvg
except ImportError:
cairosvg = None
def test_multi_render(Chart, datas):
chart = Chart()
@ -49,12 +55,8 @@ def test_render_to_file(Chart, datas):
os.remove(file_name)
@pytest.mark.skipif(not cairosvg, reason="CairoSVG not installed")
def test_render_to_png(Chart, datas):
try:
import cairosvg
except ImportError:
return
file_name = '/tmp/test_graph-%s.png' % uuid.uuid4()
if os.path.exists(file_name):
os.remove(file_name)
@ -62,8 +64,10 @@ def test_render_to_png(Chart, datas):
chart = Chart()
chart = make_data(chart, datas)
chart.render_to_png(file_name)
png = chart._repr_png_()
with open(file_name, 'rb') as f:
assert f.read()
assert png == f.read()
os.remove(file_name)
@ -353,3 +357,25 @@ def test_labels_with_links(Chart):
assert len(links) == 4 # 3 links and 1 tooltip
else:
assert len(links) == 8 # 7 links and 1 tooltip
def test_sparkline(Chart, datas):
chart = Chart()
chart = make_data(chart, datas)
assert chart.render_sparkline()
def test_secondary(Chart):
chart = Chart()
rng = [83, .12, -34, 59]
chart.add('First serie', rng)
chart.add('Secondary serie',
map(lambda x: x * 2, rng),
secondary=True)
assert chart.render_pyquery()
def test_ipython_notebook(Chart, datas):
chart = Chart()
chart = make_data(chart, datas)
assert chart._repr_svg_()

16
pygal/test/test_line.py

@ -100,3 +100,19 @@ def test_only_major_dots():
line.x_labels = map(str, range(12))
q = line.render_pyquery()
assert len(q(".dots")) == 4
def test_line_secondary():
line = Line()
rng = [8, 12, 23, 73, 39, 57]
line.add('First serie', rng)
line.add('Secondary serie',
map(lambda x: x * 2, rng),
secondary=True)
line.title = "One serie"
q = line.render_pyquery()
assert len(q(".axis.x")) == 0
assert len(q(".axis.y")) == 1
assert len(q(".plot .series path")) == 2
assert len(q(".x.axis .guides")) == 0
assert len(q(".y.axis .guides")) == 7

28
pygal/test/test_view.py

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# This file is part of pygal
#
# A python svg graph plotting library
# Copyright © 2012-2014 Kozea
#
# This library is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This library is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
from pygal.test import pytest_generate_tests, make_data
def test_all_logarithmic(Chart):
print(repr(Chart))
chart = Chart(logarithmic=True)
chart.add('1', [1, 30, 8, 199, -23])
chart.add('2', [87, 42, .9, 189, 81])
assert chart.render()

4
pygal/view.py

@ -255,8 +255,8 @@ class PolarThetaLogView(View):
if not hasattr(box, '_tmin') or not hasattr(box, '_tmax'):
raise Exception(
'Box must be set with set_polar_box for polar charts')
self.log10_tmax = log10(self.box._tmax)
self.log10_tmin = log10(self.box._tmin)
self.log10_tmax = log10(self.box._tmax) if self.box._tmax > 0 else 0
self.log10_tmin = log10(self.box._tmin) if self.box._tmin > 0 else 0
def __call__(self, rhotheta):
"""Project rho and theta"""

1
tox.ini

@ -7,6 +7,7 @@ deps =
pytest
pytest-cov
pyquery
cairosvg
commands =
py.test [] --cov pygal pygal/test

Loading…
Cancel
Save