Browse Source

Merge remote-tracking branch 'cleder/master' into donut_label_with_links

pull/78/head
Florian Mounier 11 years ago
parent
commit
61441a2490
  1. 4
      pygal/config.py
  2. 53
      pygal/graph/graph.py
  3. 9
      pygal/graph/horizontalbar.py
  4. 2
      pygal/graph/pie.py
  5. 57
      pygal/test/test_donut.py
  6. 43
      pygal/test/test_graph.py
  7. 8
      pygal/util.py
  8. 18
      setup.py

4
pygal/config.py

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

53
pygal/graph/graph.py

@ -26,7 +26,7 @@ from pygal.interpolate import INTERPOLATIONS
from pygal.graph.base import BaseGraph
from pygal.view import View, LogView, XYLogView
from pygal.util import (
is_major, truncate, reverse_text_len, get_texts_box, cut, rad)
is_major, truncate, reverse_text_len, get_texts_box, cut, rad, decorate)
from math import sqrt, ceil, cos
from itertools import repeat, chain
@ -179,9 +179,15 @@ class Graph(BaseGraph):
y=y,
class_='major' if major else ''
)
text.text = truncate(label, truncation)
if isinstance(label, dict):
text.text = truncate(label['title'], truncation)
else:
text.text = truncate(label, truncation)
if text.text != label:
self.svg.node(guides, 'title').text = label
if isinstance(label, dict):
self.svg.node(guides, 'title').text = label['title']
else:
self.svg.node(guides, 'title').text = label
if self.x_label_rotation:
text.attrib['transform'] = "rotate(%d %f %f)" % (
self.x_label_rotation, x, y)
@ -246,7 +252,10 @@ class Graph(BaseGraph):
y=y + .35 * self.label_font_size,
class_='major' if major else ''
)
text.text = label
if isinstance(label, dict):
text.text = label['title']
else:
text.text = label
if self.y_label_rotation:
text.attrib['transform'] = "rotate(%d %f %f)" % (
self.y_label_rotation, x, y)
@ -350,17 +359,31 @@ class Graph(BaseGraph):
height=self.legend_box_size,
class_="color-%d reactive" % (global_serie_number % 16)
)
truncated = truncate(title, truncation)
# Serious magical numbers here
self.svg.node(
legend, 'text',
x=col * x_step + self.legend_box_size + 5,
y=1.5 * row * h
+ .5 * h
+ .3 * self.legend_font_size
).text = truncated
if truncated != title:
self.svg.node(legend, 'title').text = title
if isinstance(title, dict):
truncated = truncate(title['title'], truncation)
a = decorate(self.svg, legend, 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:
truncated = truncate(title, truncation)
# Serious magical numbers here
self.svg.node(
legend, 'text',
x=col * x_step + self.legend_box_size + 5,
y=1.5 * row * h
+ .5 * h
+ .3 * self.legend_font_size
).text = truncated
if truncated != title:
self.svg.node(legend, 'title').text = title
def _title(self):
"""Make the title"""

9
pygal/graph/horizontalbar.py

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

2
pygal/graph/pie.py

@ -59,7 +59,7 @@ class Pie(Graph):
big_radius = radius
else:
big_radius = radius * .9
small_radius = 0
small_radius = radius * self.config.inner_radius
self.svg.slice(
serie_node, slice_, big_radius, small_radius,

57
pygal/test/test_donut.py

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
# This file is part of pygal
#
# A python svg graph plotting library
# Copyright © 2012-2013 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/>.
import os
import uuid
from pygal import Pie
def test_donut():
file_name = '/tmp/test_graph-%s.svg' % uuid.uuid4()
if os.path.exists(file_name):
os.remove(file_name)
chart = Pie(inner_radius=.3, pretty_print=True)
chart.title = 'Browser usage in February 2012 (in %)'
chart.add('IE', 19.5)
chart.add('Firefox', 36.6)
chart.add('Chrome', 36.3)
chart.add('Safari', 4.5)
chart.add('Opera', 2.3)
chart.render_to_file(file_name)
with open(file_name) as f:
assert 'pygal' in f.read()
os.remove(file_name)
def test_multiseries_donut():
#this just demos that the multiseries pie does not respect the inner_radius
file_name = '/tmp/test_graph-%s.svg' % uuid.uuid4()
if os.path.exists(file_name):
os.remove(file_name)
chart = Pie(inner_radius=.3, pretty_print=True)
chart.title = 'Browser usage by version in February 2012 (in %)'
chart.add('IE', [5.7, 10.2, 2.6, 1])
chart.add('Firefox', [.6, 16.8, 7.4, 2.2, 1.2, 1, 1, 1.1, 4.3, 1])
chart.add('Chrome', [.3, .9, 17.1, 15.3, .6, .5, 1.6])
chart.add('Safari', [4.4, .1])
chart.add('Opera', [.1, 1.6, .1, .5])
chart.render_to_file(file_name)
with open(file_name) as f:
assert 'pygal' in f.read()
os.remove(file_name)

43
pygal/test/test_graph.py

@ -284,3 +284,46 @@ def test_unicode_labels_python3(Chart):
}])
chart.x_labels = eval("['&œ', '¿?', '††††††††', 'unicode <3']")
q = chart.render_pyquery()
def test_labels_with_links(Chart):
chart = Chart()
#link on chart and label
chart.add({'title':'Red','xlink':
{'href': 'http://en.wikipedia.org/wiki/Red'}},
[{
'value': 2,
'label': 'This is red',
'xlink': {'href': 'http://en.wikipedia.org/wiki/Red'}}])
#link on chart only
chart.add('Green', [{
'value': 4,
'label': 'This is green',
'xlink': {
'href': 'http://en.wikipedia.org/wiki/Green',
'target': '_top'}
}])
#link on label only opens in new tab
chart.add({'title': 'Yellow', 'xlink': {
'href': 'http://en.wikipedia.org/wiki/Yellow',
'target': '_blank'}}, 7)
#link on chart only
chart.add('Blue', [{
'value': 5,
'xlink': {
'href': 'http://en.wikipedia.org/wiki/Blue',
'target': '_blank'}
}])
#link on label and chart with diffrent behaviours
chart.add({'title': 'Violet',
'xlink': 'http://en.wikipedia.org/wiki/Violet_(color)'},
[{
'value': 3,
'label': 'This is violet',
'xlink': {
'href': 'http://en.wikipedia.org/wiki/Violet_(color)',
'target': '_self'}
}])
q = chart.render_pyquery()
links = q('a')
assert(len(links) == 8) # 7 links and 1 tooltip

8
pygal/util.py

@ -197,7 +197,13 @@ def get_text_box(text, fs):
def get_texts_box(texts, fs):
"""Approximation of multiple texts bounds"""
max_len = max(map(len, texts))
def get_text_title(texts):
for text in texts:
if isinstance(text, dict):
yield text['title']
else:
yield text
max_len = max(map(len, get_text_title(texts)))
return (fs, text_len(max_len, fs))

18
setup.py

@ -17,9 +17,24 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
import os
import os, sys
import re
from setuptools import setup, find_packages
from setuptools.command.test import test as TestCommand
class PyTest(TestCommand):
def finalize_options(self):
TestCommand.finalize_options(self)
self.test_args = []
self.test_suite = True
def run_tests(self):
#import here, cause outside the eggs aren't loaded
import pytest
errno = pytest.main(self.test_args)
sys.exit(errno)
ROOT = os.path.dirname(__file__)
with open(os.path.join(ROOT, 'pygal', '__init__.py')) as fd:
@ -40,6 +55,7 @@ setup(
keywords=[
"svg", "chart", "graph", "diagram", "plot", "histogram", "kiviat"],
tests_require=["pytest", "pyquery", "flask", "cairosvg"],
cmdclass = {'test': PyTest},
package_data={'pygal': ['css/*', 'graph/worldmap.svg']},
install_requires=['lxml'],
classifiers=[

Loading…
Cancel
Save