Browse Source

Include DateY fixes from #109

113_errors
Florian Mounier 11 years ago
parent
commit
58330ff679
  1. 73
      pygal/graph/datey.py
  2. 18
      pygal/graph/xy.py
  3. 9
      pygal/svg.py
  4. 58
      pygal/test/test_date.py
  5. 1
      pygal/test/test_graph.py

73
pygal/graph/datey.py

@ -30,8 +30,12 @@ def jour(n) :
x=(1,20,35,54,345,898) x=(1,20,35,54,345,898)
x=tuple(map(jour,x)) x=tuple(map(jour,x))
x_label=(0,100,200,300,400,500,600,700,800,900,1000)
x_label=map(jour,x_label)
y=(1,3,4,2,3,1) y=(1,3,4,2,3,1)
graph=pygal.DateY(x_label_rotation=20) graph=pygal.DateY(x_label_rotation=20)
graph.x_label_format = "%Y-%m-%d"
graph.x_labels = x_label
graph.add("graph1",list(zip(x,y))+[None,None]) graph.add("graph1",list(zip(x,y))+[None,None])
graph.render_in_browser() graph.render_in_browser()
""" """
@ -75,27 +79,19 @@ class DateY(XY):
for serie in self.all_series: for serie in self.all_series:
serie.values = [(self._tonumber(v[0]), v[1]) for v in serie.values] serie.values = [(self._tonumber(v[0]), v[1]) for v in serie.values]
xvals = [val[0] if self.xvals:
for serie in self.series xmin = min(self.xvals)
for val in serie.values xmax = max(self.xvals)
if val[0] is not None]
yvals = [val[1]
for serie in self.series
for val in serie.values
if val[1] is not None]
if xvals:
xmin = min(xvals)
xmax = max(xvals)
rng = (xmax - xmin) rng = (xmax - xmin)
else: else:
rng = None rng = None
if yvals: if self.yvals:
ymin = min(yvals) ymin = self._min
ymax = max(yvals) ymax = self._max
if self.include_x_axis: if self.include_x_axis:
ymin = min(ymin or 0, 0) ymin = min(self._min or 0, 0)
ymax = max(ymax or 0, 0) ymax = max(self._max or 0, 0)
for serie in self.all_series: for serie in self.all_series:
serie.points = serie.values serie.points = serie.values
@ -106,25 +102,46 @@ class DateY(XY):
serie.interpolated = self._interpolate(vals[0], vals[1]) serie.interpolated = self._interpolate(vals[0], vals[1])
if self.interpolate and rng: if self.interpolate and rng:
xvals = [val[0] self.xvals = [val[0]
for serie in self.all_series for serie in self.all_series
for val in serie.interpolated] for val in serie.interpolated]
yvals = [val[1] self.yvals = [val[1]
for serie in self.all_series for serie in self.all_series
for val in serie.interpolated] for val in serie.interpolated]
if xvals: if self.xvals:
xmin = min(xvals) xmin = min(self.xvals)
xmax = max(xvals) xmax = max(self.xvals)
rng = (xmax - xmin) rng = (xmax - xmin)
else: else:
rng = None rng = None
if rng: # Calculate/prcoess the x_labels
if self.x_labels and all(
map(lambda x: isinstance(
x, (datetime.datetime, datetime.date)), self.x_labels)):
# Process the given x_labels
x_labels_num = []
for label in self.x_labels:
x_labels_num.append(self._tonumber(label))
x_pos = x_labels_num
# Update the xmin/xmax to fit all of the x_labels and the data
xmin = min(xmin, min(x_pos))
xmax = max(xmax, max(x_pos))
self._box.xmin, self._box.xmax = xmin, xmax self._box.xmin, self._box.xmax = xmin, xmax
self._box.ymin, self._box.ymax = ymin, ymax self._box.ymin, self._box.ymax = ymin, ymax
else:
# Automatically generate the x_labels
if rng:
self._box.xmin, self._box.xmax = xmin, xmax
self._box.ymin, self._box.ymax = ymin, ymax
x_pos = compute_scale(
self._box.xmin, self._box.xmax, self.logarithmic,
self.order_min)
x_pos = compute_scale( # Always auto-generate the y labels
self._box.xmin, self._box.xmax, self.logarithmic, self.order_min)
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)

18
pygal/graph/xy.py

@ -44,12 +44,22 @@ class XY(Line):
for val in serie.values for val in serie.values
if val[1] is not None] if val[1] is not None]
@cached_property
def _min(self):
return (self.range[0] if (self.range and self.range[0] is not None)
else (min(self.yvals) if self.yvals else None))
@cached_property
def _max(self):
return (self.range[1] if (self.range and self.range[1] is not None)
else (max(self.yvals) if self.yvals else None))
def _has_data(self): def _has_data(self):
"""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:
@ -60,8 +70,8 @@ class XY(Line):
xrng = None xrng = None
if self.yvals: if self.yvals:
ymin = min(self.yvals) ymin = self._min
ymax = max(self.yvals) ymax = self._max
if self.include_x_axis: if self.include_x_axis:
ymin = min(ymin or 0, 0) ymin = min(ymin or 0, 0)

9
pygal/svg.py

@ -26,7 +26,7 @@ from pygal._compat import to_str, u
import io import io
import os import os
import json import json
from datetime import date from datetime import date, datetime
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
@ -97,7 +97,12 @@ class Svg(object):
"""Add the js to the svg""" """Add the js to the svg"""
common_script = self.node(self.defs, 'script', type='text/javascript') common_script = self.node(self.defs, 'script', type='text/javascript')
common_script.text = " = ".join( common_script.text = " = ".join(
("window.config", json.dumps(self.graph.config.to_dict()))) ("window.config", json.dumps(
self.graph.config.to_dict(),
default=lambda o: (
o.isoformat() if isinstance(o, (datetime, date))
else json.JSONEncoder().default(o))
)))
for js in self.graph.js: for js in self.graph.js:
if '://' in js: if '://' in js:

58
pygal/test/test_date.py

@ -0,0 +1,58 @@
# -*- 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 import DateY
from pygal.test.utils import texts
from datetime import datetime
def test_date():
datey = DateY(truncate_label=1000)
datey.add('dates', [
(datetime(2013, 1, 2), 300),
(datetime(2013, 1, 12), 412),
(datetime(2013, 2, 2), 823),
(datetime(2013, 2, 22), 672)
])
q = datey.render_pyquery()
assert list(
map(lambda t: t.split(' ')[0],
q(".axis.x text").map(texts))) == [
'2013-01-02',
'2013-01-13',
'2013-01-25',
'2013-02-05',
'2013-02-17'
]
datey.x_labels = [
datetime(2013, 1, 1),
datetime(2013, 2, 1),
datetime(2013, 3, 1)
]
q = datey.render_pyquery()
assert list(
map(lambda t: t.split(' ')[0],
q(".axis.x text").map(texts))) == [
'2013-01-01',
'2013-02-01',
'2013-03-01'
]

1
pygal/test/test_graph.py

@ -16,6 +16,7 @@
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>. # along with pygal. If not, see <http://www.gnu.org/licenses/>.
import os import os
import pygal import pygal
import uuid import uuid

Loading…
Cancel
Save