Browse Source

Same code for python 2.7 and 3.3

pull/35/head
Florian Mounier 12 years ago
parent
commit
c27bd13739
  1. 17
      pygal/_compat.py
  2. 2
      pygal/adapters.py
  3. 6
      pygal/graph/bar.py
  4. 4
      pygal/graph/base.py
  5. 2
      pygal/graph/datey.py
  6. 7
      pygal/graph/dot.py
  7. 7
      pygal/graph/funnel.py
  8. 2
      pygal/graph/gauge.py
  9. 10
      pygal/graph/graph.py
  10. 8
      pygal/graph/line.py
  11. 4
      pygal/graph/radar.py
  12. 10
      pygal/graph/stackedbar.py
  13. 2
      pygal/graph/stackedline.py
  14. 6
      pygal/graph/verticalpyramid.py
  15. 5
      pygal/graph/worldmap.py
  16. 8
      pygal/graph/xy.py
  17. 2
      pygal/interpolate.py
  18. 2
      pygal/serie.py
  19. 10
      pygal/svg.py
  20. 8
      pygal/test/test_config.py
  21. 2
      pygal/test/test_graph.py
  22. 27
      pygal/util.py
  23. 1
      setup.py

17
pygal/compat.py → pygal/_compat.py

@ -18,6 +18,23 @@
# along with pygal. If not, see <http://www.gnu.org/licenses/>. # along with pygal. If not, see <http://www.gnu.org/licenses/>.
import sys import sys
try:
from urllib.parse import urlparse
except ImportError:
from urlparse import urlparse
def to_str(string):
if sys.version_info[0] == 3:
base = (str, bytes)
coerce = str
else:
base = basestring
coerce = unicode
if not isinstance(string, base):
return coerce(string)
return string
def total_seconds(td): def total_seconds(td):
if sys.version_info[:2] == (2, 6): if sys.version_info[:2] == (2, 6):

2
pygal/adapters.py

@ -51,7 +51,7 @@ def int_to_country(x):
except: except:
return x return x
if x >= 0 and x < len(COUNTRIES): if x >= 0 and x < len(COUNTRIES):
return COUNTRIES.keys()[x] return list(COUNTRIES.keys())[x]
return x return x

6
pygal/graph/bar.py

@ -100,9 +100,9 @@ class Bar(Graph):
self._box.ymin, self._box.ymax, self.logarithmic, self.order_min self._box.ymin, self._box.ymax, self.logarithmic, self.order_min
) if not self.y_labels else map(float, self.y_labels) ) if not self.y_labels else map(float, self.y_labels)
self._x_labels = self.x_labels and zip(self.x_labels, [ self._x_labels = self.x_labels and list(zip(self.x_labels, [
(i + .5) / self._len for i in range(self._len)]) (i + .5) / self._len for i in range(self._len)]))
self._y_labels = zip(map(self._format, y_pos), y_pos) self._y_labels = list(zip(map(self._format, y_pos), y_pos))
def _compute_secondary(self): def _compute_secondary(self):
if self.secondary_series: if self.secondary_series:

4
pygal/graph/base.py

@ -58,10 +58,10 @@ class BaseGraph(object):
else: else:
get = lambda x: x get = lambda x: x
positive_values = filter( positive_values = list(filter(
lambda x: x > 0, lambda x: x > 0,
[get(val) [get(val)
for serie in self.series for val in serie.safe_values]) for serie in self.series for val in serie.safe_values]))
self.zero = min(positive_values) if positive_values else 0 self.zero = min(positive_values) if positive_values else 0
self._draw() self._draw()

2
pygal/graph/datey.py

@ -36,10 +36,10 @@ graph.add("graph1",list(zip(x,y))+[None,None])
graph.render_in_browser() graph.render_in_browser()
""" """
from pygal._compat import total_seconds
from pygal.adapters import date from pygal.adapters import date
from pygal.util import compute_scale from pygal.util import compute_scale
from pygal.graph.xy import XY from pygal.graph.xy import XY
from pygal.compat import total_seconds
import datetime import datetime

7
pygal/graph/dot.py

@ -39,7 +39,7 @@ class Dot(Graph):
def dot(self, serie_node, serie, r_max): def dot(self, serie_node, serie, r_max):
"""Draw a dot line""" """Draw a dot line"""
view_values = map(self.view, serie.points) view_values = list(map(self.view, serie.points))
for i, value in safe_enumerate(serie.values): for i, value in safe_enumerate(serie.values):
x, y = view_values[i] x, y = view_values[i]
size = r_max * value size = r_max * value
@ -69,8 +69,9 @@ class Dot(Graph):
(x_pos[i], y_pos[j]) (x_pos[i], y_pos[j])
for i in range(x_len)] for i in range(x_len)]
self._x_labels = self.x_labels and zip(self.x_labels, x_pos) self._x_labels = self.x_labels and list(zip(self.x_labels, x_pos))
self._y_labels = zip(self.y_labels or cut(self.series, 'title'), y_pos) self._y_labels = list(zip(
self.y_labels or cut(self.series, 'title'), y_pos))
def _plot(self): def _plot(self):
r_max = min( r_max = min(

7
pygal/graph/funnel.py

@ -87,9 +87,10 @@ class Funnel(Graph):
self._box.ymin, self._box.ymax, self.logarithmic, self.order_min self._box.ymin, self._box.ymax, self.logarithmic, self.order_min
) if not self.y_labels else map(float, self.y_labels) ) if not self.y_labels else map(float, self.y_labels)
self._x_labels = zip(cut(self.series, 'title'), self._x_labels = list(
map(lambda x: x - 1 / (2 * self._order), x_pos)) zip(cut(self.series, 'title'),
self._y_labels = zip(map(self._format, y_pos), y_pos) map(lambda x: x - 1 / (2 * self._order), x_pos)))
self._y_labels = list(zip(map(self._format, y_pos), y_pos))
def _plot(self): def _plot(self):
for index, serie in enumerate(self.series): for index, serie in enumerate(self.series):

2
pygal/graph/gauge.py

@ -112,7 +112,7 @@ class Gauge(Graph):
x_pos = compute_scale( x_pos = compute_scale(
self.min_, self.max_, self.logarithmic, self.order_min self.min_, self.max_, self.logarithmic, self.order_min
) )
self._x_labels = zip(map(self._format, x_pos), x_pos) self._x_labels = list(zip(map(self._format, x_pos), x_pos))
def _plot(self): def _plot(self):
for index, serie in enumerate(self.series): for index, serie in enumerate(self.series):

10
pygal/graph/graph.py

@ -28,7 +28,7 @@ from pygal.view import View, LogView, XYLogView
from pygal.util import ( 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)
from math import isnan, pi, sqrt, ceil, cos from math import isnan, pi, sqrt, ceil, cos
from itertools import repeat, izip, chain from itertools import repeat, chain
class Graph(BaseGraph): class Graph(BaseGraph):
@ -296,13 +296,13 @@ class Graph(BaseGraph):
# l - label # l - label
# tf - whether it is secondary label # tf - whether it is secondary label
gen = enumerate(enumerate(chain( gen = enumerate(enumerate(chain(
izip(self._legends, repeat(False)), zip(self._legends, repeat(False)),
izip(self._secondary_legends, repeat(True))))) zip(self._secondary_legends, repeat(True)))))
secondary_legends = legends # svg node is the same secondary_legends = legends # svg node is the same
else: else:
gen = enumerate(chain( gen = enumerate(chain(
enumerate(izip(self._legends, repeat(False))), enumerate(zip(self._legends, repeat(False))),
enumerate(izip(self._secondary_legends, repeat(True))))) enumerate(zip(self._secondary_legends, repeat(True)))))
# draw secondary axis on right # draw secondary axis on right
x = self.margin.left + self.view.width + 10 x = self.margin.left + self.view.width + 10

8
pygal/graph/line.py

@ -65,7 +65,7 @@ class Line(Graph):
for x, y in serie.points] for x, y in serie.points]
else: else:
points = serie.points points = serie.points
view_values = map(self.view, points) view_values = list(map(self.view, points))
if self.show_dots: if self.show_dots:
for i, (x, y) in enumerate(view_values): for i, (x, y) in enumerate(view_values):
if None in (x, y): if None in (x, y):
@ -95,7 +95,7 @@ class Line(Graph):
if self.stroke: if self.stroke:
if self.interpolate: if self.interpolate:
view_values = map(self.view, serie.interpolated) view_values = list(map(self.view, serie.interpolated))
if self.fill: if self.fill:
view_values = self._fill(view_values) view_values = self._fill(view_values)
self.svg.line( self.svg.line(
@ -111,7 +111,7 @@ class Line(Graph):
self._points(x_pos) self._points(x_pos)
if self.x_labels: if self.x_labels:
self._x_labels = zip(self.x_labels, x_pos) self._x_labels = list(zip(self.x_labels, x_pos))
else: else:
self._x_labels = None self._x_labels = None
@ -127,7 +127,7 @@ class Line(Graph):
self._box.ymin, self._box.ymax, self.logarithmic, self.order_min self._box.ymin, self._box.ymax, self.logarithmic, self.order_min
) if not self.y_labels else map(float, self.y_labels) ) if not self.y_labels else map(float, self.y_labels)
self._y_labels = zip(map(self._format, y_pos), y_pos) self._y_labels = list(zip(map(self._format, y_pos), y_pos))
def _plot(self): def _plot(self):
for index, serie in enumerate(self.series): for index, serie in enumerate(self.series):

4
pygal/graph/radar.py

@ -166,8 +166,8 @@ class Radar(Line):
max_scale=8 max_scale=8
) if not self.y_labels else map(int, self.y_labels) ) if not self.y_labels else map(int, self.y_labels)
self._x_labels = self.x_labels and zip(self.x_labels, x_pos) self._x_labels = self.x_labels and list(zip(self.x_labels, x_pos))
self._y_labels = zip(map(self._format, y_pos), y_pos) self._y_labels = list(zip(map(self._format, y_pos), y_pos))
self.x_pos = x_pos self.x_pos = x_pos
self._self_close = True self._self_close = True

10
pygal/graph/stackedbar.py

@ -55,8 +55,8 @@ class StackedBar(Bar):
self._compute_box(positive_vals, negative_vals) self._compute_box(positive_vals, negative_vals)
if self.logarithmic: if self.logarithmic:
positive_vals = filter(lambda x: x > 0, positive_vals) positive_vals = list(filter(lambda x: x > 0, positive_vals))
negative_vals = filter(lambda x: x > 0, negative_vals) negative_vals = list(filter(lambda x: x > 0, negative_vals))
positive_vals = positive_vals or [self.zero] positive_vals = positive_vals or [self.zero]
negative_vals = negative_vals or [self.zero] negative_vals = negative_vals or [self.zero]
@ -71,9 +71,9 @@ class StackedBar(Bar):
) if not self.y_labels else map(float, self.y_labels) ) if not self.y_labels else map(float, self.y_labels)
self._x_ranges = zip(x_pos, x_pos[1:]) self._x_ranges = zip(x_pos, x_pos[1:])
self._x_labels = self.x_labels and zip(self.x_labels, [ self._x_labels = self.x_labels and list(zip(self.x_labels, [
sum(x_range) / 2 for x_range in self._x_ranges]) sum(x_range) / 2 for x_range in self._x_ranges]))
self._y_labels = zip(map(self._format, y_pos), y_pos) self._y_labels = list(zip(map(self._format, y_pos), y_pos))
self.negative_cumulation = [0] * self._len self.negative_cumulation = [0] * self._len
self.positive_cumulation = [0] * self._len self.positive_cumulation = [0] * self._len

2
pygal/graph/stackedline.py

@ -46,7 +46,7 @@ class StackedLine(Line):
for series_group in (self.series, self.secondary_series): for series_group in (self.series, self.secondary_series):
accumulation = [0] * self._len accumulation = [0] * self._len
for serie in series_group: for serie in series_group:
accumulation = map(sum, zip(accumulation, serie.values)) accumulation = list(map(sum, zip(accumulation, serie.values)))
serie.points = [ serie.points = [
(x_pos[i], v) (x_pos[i], v)
for i, v in enumerate(accumulation)] for i, v in enumerate(accumulation)]

6
pygal/graph/verticalpyramid.py

@ -43,11 +43,11 @@ class VerticalPyramid(StackedBar):
negative_vals = zip(*[serie.safe_values negative_vals = zip(*[serie.safe_values
for index, serie in enumerate(series) for index, serie in enumerate(series)
if not index % 2]) if not index % 2])
return positive_vals, negative_vals return list(positive_vals), list(negative_vals)
def _compute_box(self, positive_vals, negative_vals): def _compute_box(self, positive_vals, negative_vals):
positive_sum = map(sum, positive_vals) or [self.zero] positive_sum = list(map(sum, positive_vals)) or [self.zero]
negative_sum = map(sum, negative_vals) or [self.zero] negative_sum = list(map(sum, negative_vals)) or [self.zero]
self._box.ymax = max(max(positive_sum), max(negative_sum)) self._box.ymax = max(max(positive_sum), max(negative_sum))
self._box.ymin = - self._box.ymax self._box.ymin = - self._box.ymax

5
pygal/graph/worldmap.py

@ -38,7 +38,7 @@ with open(os.path.join(
class Worldmap(Graph): class Worldmap(Graph):
"""Worldmap graph""" """Worldmap graph"""
_dual = True _dual = True
x_labels = COUNTRIES.keys() x_labels = list(COUNTRIES.keys())
country_names = COUNTRIES country_names = COUNTRIES
_adapters = [int_to_country] _adapters = [int_to_country]
@ -63,7 +63,8 @@ class Worldmap(Graph):
map.set('height', str(self.view.height)) map.set('height', str(self.view.height))
for i, serie in enumerate(self.series): for i, serie in enumerate(self.series):
safe_vals = filter(lambda x: x is not None, cut(serie.values, 1)) safe_vals = list(filter(
lambda x: x is not None, cut(serie.values, 1)))
if not safe_vals: if not safe_vals:
continue continue
min_ = min(safe_vals) min_ = min(safe_vals)

8
pygal/graph/xy.py

@ -72,9 +72,9 @@ class XY(Line):
for serie in self.all_series: for serie in self.all_series:
serie.points = serie.values serie.points = serie.values
if self.interpolate and xrng: if self.interpolate and xrng:
vals = zip(*sorted( vals = list(zip(*sorted(
filter(lambda t: None not in t, filter(lambda t: None not in t,
serie.points), key=lambda x: x[0])) serie.points), key=lambda x: x[0])))
serie.interpolated = self._interpolate( serie.interpolated = self._interpolate(
vals[1], vals[0], xy=True, xy_xmin=xmin, xy_rng=xrng) vals[1], vals[0], xy=True, xy_xmin=xmin, xy_rng=xrng)
@ -102,5 +102,5 @@ class XY(Line):
y_pos = compute_scale( y_pos = compute_scale(
self._box.ymin, self._box.ymax, self.logarithmic, self.order_min) self._box.ymin, self._box.ymax, self.logarithmic, self.order_min)
self._x_labels = zip(map(self._format, x_pos), x_pos) self._x_labels = list(zip(map(self._format, x_pos), x_pos))
self._y_labels = zip(map(self._format, y_pos), y_pos) self._y_labels = list(zip(map(self._format, y_pos), y_pos))

2
pygal/interpolate.py

@ -39,7 +39,7 @@ def interpolation(x, y, kind):
if len(y) < len(x): if len(y) < len(x):
x = x[:len(y)] x = x[:len(y)]
pack = zip(*filter(lambda t: None not in t, zip(x, y))) pack = list(zip(*filter(lambda t: None not in t, zip(x, y))))
if len(pack) == 0: if len(pack) == 0:
return ident return ident
x, y = pack x, y = pack

2
pygal/serie.py

@ -32,7 +32,7 @@ class Serie(object):
@cached_property @cached_property
def safe_values(self): def safe_values(self):
return filter(lambda x: x is not None, self.values) return list(filter(lambda x: x is not None, self.values))
class Label(object): class Label(object):

10
pygal/svg.py

@ -22,6 +22,7 @@ Svg helper
""" """
from __future__ import division from __future__ import division
from pygal._compat import urlparse, to_str
import io import io
import os import os
import json import json
@ -29,7 +30,6 @@ from datetime import date
from numbers import Number from numbers import Number
from lxml import etree from lxml import etree
from math import cos, sin, pi from math import cos, sin, pi
from urlparse import urlparse
from pygal.util import template, coord_format, minify_css from pygal.util import template, coord_format, minify_css
from pygal import __version__ from pygal import __version__
@ -109,12 +109,12 @@ class Svg(object):
if in_attrib_and_number(pos): if in_attrib_and_number(pos):
attrib[pos] = attrib[pos] - attrib[dim] attrib[pos] = attrib[pos] - attrib[dim]
for key, value in attrib.items(): for key, value in dict(attrib).items():
if value is None: if value is None:
del attrib[key] del attrib[key]
elif not isinstance(value, basestring):
attrib[key] = str(value) attrib[key] = to_str(value)
elif key.endswith('_'): if key.endswith('_'):
attrib[key.rstrip('_')] = attrib[key] attrib[key.rstrip('_')] = attrib[key]
del attrib[key] del attrib[key]
elif key == 'href': elif key == 'href':

8
pygal/test/test_config.py

@ -190,12 +190,12 @@ def test_human_readable():
line = Line() line = Line()
line.add('_', [10 ** 4, 10 ** 5, 23 * 10 ** 4]) line.add('_', [10 ** 4, 10 ** 5, 23 * 10 ** 4])
q = line.render_pyquery() q = line.render_pyquery()
assert q(".axis.y text").map(texts) == map( assert q(".axis.y text").map(texts) == list(map(
str, map(float, range(20000, 240000, 20000))) str, map(float, range(20000, 240000, 20000))))
line.human_readable = True line.human_readable = True
q = line.render_pyquery() q = line.render_pyquery()
assert q(".axis.y text").map(texts) == map( assert q(".axis.y text").map(texts) == list(map(
lambda x: '%dk' % x, range(20, 240, 20)) lambda x: '%dk' % x, range(20, 240, 20)))
def test_show_legend(): def test_show_legend():

2
pygal/test/test_graph.py

@ -66,7 +66,7 @@ def test_metadata(Chart):
chart = Chart() chart = Chart()
v = range(7) v = range(7)
if Chart == pygal.XY: if Chart == pygal.XY:
v = map(lambda x: (x, x + 1), v) v = list(map(lambda x: (x, x + 1), v))
chart.add('Serie with metadata', [ chart.add('Serie with metadata', [
v[0], v[0],

27
pygal/util.py

@ -21,10 +21,12 @@ Various utils
""" """
from __future__ import division from __future__ import division
from pygal._compat import to_str
import re import re
from decimal import Decimal from decimal import Decimal
from math import floor, pi, log, log10, ceil from math import floor, pi, log, log10, ceil
from itertools import cycle from itertools import cycle
from functools import reduce
from pygal.adapters import not_zero, positive from pygal.adapters import not_zero, positive
ORDERS = u"yzafpnµm kMGTPEZY" ORDERS = u"yzafpnµm kMGTPEZY"
@ -78,7 +80,7 @@ def cut(list_, index=0):
cut_ = lambda x: x[index] cut_ = lambda x: x[index]
else: else:
cut_ = lambda x: getattr(x, index) cut_ = lambda x: getattr(x, index)
return map(cut_, list_) return list(map(cut_, list_))
def rad(degrees): def rad(degrees):
@ -213,10 +215,7 @@ def decorate(svg, node, metadata):
if key == 'xlink' and isinstance(value, dict): if key == 'xlink' and isinstance(value, dict):
value = value.get('href', value) value = value.get('href', value)
if value: if value:
if isinstance(value, unicode): svg.node(node, 'desc', class_=key).text = to_str(value)
svg.node(node, 'desc', class_=key).text = value
else:
svg.node(node, 'desc', class_=key).text = str(value)
return node return node
@ -225,7 +224,7 @@ def cycle_fill(short_list, max_len):
short_list = list(short_list) short_list = list(short_list)
list_cycle = cycle(short_list) list_cycle = cycle(short_list)
while len(short_list) < max_len: while len(short_list) < max_len:
short_list.append(list_cycle.next()) short_list.append(next(list_cycle))
return short_list return short_list
@ -305,6 +304,9 @@ def prepare_values(raw, config, cls):
if config.zero == 0 and issubclass(cls, Worldmap): if config.zero == 0 and issubclass(cls, Worldmap):
config.zero = 1 config.zero = 1
for key in ('x_labels', 'y_labels'):
if getattr(config, key):
setattr(config, key, list(getattr(config, key)))
if not raw: if not raw:
return return
@ -316,6 +318,12 @@ def prepare_values(raw, config, cls):
adapters = adapters + [positive, not_zero] adapters = adapters + [positive, not_zero]
adapter = reduce(compose, adapters) if not config.strict else ident adapter = reduce(compose, adapters) if not config.strict else ident
series = [] series = []
raw = [(
title,
list(raw_values) if not isinstance(raw_values, dict) else raw_values
) for title, raw_values in raw]
width = max([len(values) for _, values in raw] + width = max([len(values) for _, values in raw] +
[len(config.x_labels or [])]) [len(config.x_labels or [])])
@ -324,15 +332,14 @@ def prepare_values(raw, config, cls):
values = [] values = []
if isinstance(raw_values, dict): if isinstance(raw_values, dict):
if issubclass(cls, Worldmap): if issubclass(cls, Worldmap):
raw_values = raw_values.items() raw_values = list(raw_values.items())
else: else:
value_list = [None] * width value_list = [None] * width
for k, v in raw_values.items(): for k, v in raw_values.items():
if k in config.x_labels: if k in config.x_labels:
value_list[config.x_labels.index(k)] = v value_list[config.x_labels.index(k)] = v
raw_values = value_list raw_values = value_list
else:
raw_values = list(raw_values)
for index, raw_value in enumerate( for index, raw_value in enumerate(
raw_values + ( raw_values + (
(width - len(raw_values)) * [None] # aligning values (width - len(raw_values)) * [None] # aligning values
@ -351,7 +358,7 @@ def prepare_values(raw, config, cls):
if issubclass(cls, DateY) or issubclass(cls, Worldmap): if issubclass(cls, DateY) or issubclass(cls, Worldmap):
value = (adapter(value[0]), value[1]) value = (adapter(value[0]), value[1])
else: else:
value = map(adapter, value) value = list(map(adapter, value))
else: else:
value = adapter(value) value = adapter(value)

1
setup.py

@ -42,7 +42,6 @@ setup(
tests_require=["pytest", "pyquery", "flask", "cairosvg"], tests_require=["pytest", "pyquery", "flask", "cairosvg"],
package_data={'pygal': ['css/*', 'graph/worldmap.svg']}, package_data={'pygal': ['css/*', 'graph/worldmap.svg']},
install_requires=['lxml'], install_requires=['lxml'],
use_2to3=True,
classifiers=[ classifiers=[
"Development Status :: 4 - Beta", "Development Status :: 4 - Beta",
"Environment :: Console", "Environment :: Console",

Loading…
Cancel
Save