Skip to content

Commit

Permalink
Remove DateY and replace it by real XY datetime, date, time and timed…
Browse files Browse the repository at this point in the history
…elta support. Introduce new XY configuration options: `xrange`, `x_value_formatter`.
  • Loading branch information
paradoxxxzero committed Feb 16, 2015
1 parent a1acaac commit a5f94eb
Show file tree
Hide file tree
Showing 17 changed files with 360 additions and 210 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
V 1.6.3 UNRELEASED
V 2.0.0 UNRELEASED
Remove DateY and replace it by real XY datetime, date, time and timedelta support.
Introduce new XY configuration options: `xrange`, `x_value_formatter`
Rework the ghost mechanism to come back to a more object oriented behavior (WIP)

V 1.6.3
Add show_x_labels option to remove them and the x axis.
Set print_values to False by default.
Fix secondary serie text values when None in data. (#192)
Expand Down
52 changes: 50 additions & 2 deletions demo/moulinrouge/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from pygal import (
Bar, Gauge, Pyramid, Funnel, Dot, StackedBar, StackedLine, XY,
CHARTS_BY_NAME, Config, Line, DateY, Worldmap, Histogram, Box,
FrenchMap_Departments, FrenchMap_Regions, Pie, Treemap)
FrenchMap_Departments, FrenchMap_Regions, Pie, Treemap, TimeLine, DateLine)
from pygal.style import styles, Style, RotateStyle
from pygal.colors import rotate
from pygal.graph.frenchmap import DEPARTMENTS, REGIONS
Expand Down Expand Up @@ -58,7 +58,7 @@ def test_bar_links():

@app.route('/test/xy_links')
def test_xy_links():
xy = XY(style=styles['neon'])
xy = XY(style=styles['neon'], interpolate='cubic')
xy.add('1234', [
{'value': (10, 5),
'label': 'Ten',
Expand Down Expand Up @@ -219,6 +219,12 @@ def test_no_data_for(chart):
graph.title = '123456789 ' * 30
return graph.render_response()

@app.route('/test/xy_single')
def test_xy_single():
graph = XY(interpolate='cubic')
graph.add('Single', [(1, 1)])
return graph.render_response()

@app.route('/test/datey_single')
def test_datey_single():
graph = DateY(interpolate='cubic')
Expand Down Expand Up @@ -371,6 +377,19 @@ class LolConfig(Config):
stacked.add('2', [4, 5, 6])
return stacked.render_response()

@app.route('/test/dateline')
def test_dateline():
from datetime import date
datey = DateLine(show_dots=False)
datey.add('1', [
(datetime(2013, 1, 2), 300),
(datetime(2013, 1, 12), 412),
(datetime(2013, 2, 2), 823),
(datetime(2013, 2, 22), 672)
])
datey.x_label_rotation = 25
return datey.render_response()

@app.route('/test/datey')
def test_datey():
from datetime import datetime
Expand All @@ -384,6 +403,35 @@ def test_datey():
datey.x_label_rotation = 25
return datey.render_response()

@app.route('/test/datexy')
def test_datexy():
from datetime import datetime, date, timedelta
datey = DateY()
datey.add('1', [
(datetime(2011, 12, 21), 10),
(datetime(2014, 4, 8), 12),
(datetime(2010, 2, 28), 2)
])
datey.add('2', map(
lambda t: (date.today() + timedelta(days=t[0]), t[1]),
[(12, 4), (219, 8), (928, 6)]))
datey.x_label_rotation = 25
return datey.render_response()

@app.route('/test/timexy')
def test_timexy():
from datetime import time
datey = TimeLine()
datey.add('1', [
(time(1, 12, 29), 2),
(time(21, 2, 29), 10),
(time(12, 30, 59), 7)
])
datey.add('2',
[(time(12, 12, 12), 4), (time(), 8), (time(23, 59, 59), 6)])
datey.x_label_rotation = 25
return datey.render_response()

@app.route('/test/worldmap')
def test_worldmap():
wmap = Worldmap(style=choice(list(styles.values())))
Expand Down
12 changes: 12 additions & 0 deletions pygal/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
import sys
from collections import Iterable
import time


if sys.version_info[0] == 3:
Expand Down Expand Up @@ -60,3 +61,14 @@ def total_seconds(td):
(td.days * 86400 + td.seconds) * 10 ** 6 + td.microseconds
) / 10 ** 6
return td.total_seconds()


def to_timestamp(x):
if hasattr(x, 'timestamp'):
return x.timestamp()
else:
if hasattr(x, 'utctimetuple'):
t = x.utctimetuple()
else:
t = x.timetuple()
return time.mktime(t)
13 changes: 0 additions & 13 deletions pygal/adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
Value adapters to use when a chart doesn't accept all value types
"""
import datetime
from numbers import Number
from decimal import Decimal


Expand All @@ -43,17 +41,6 @@ def none_to_zero(x):
return x or 0


def date(x):
# Make int work for date graphs by counting days number from now
if isinstance(x, Number):
try:
d = datetime.date.today() + datetime.timedelta(days=x)
return datetime.datetime.combine(d, datetime.time(0, 0, 0))
except OverflowError:
return None
return x


def decimal_to_float(x):
if isinstance(x, Decimal):
return float(x)
Expand Down
12 changes: 11 additions & 1 deletion pygal/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ class Config(CommonConfig):

stack_from_top = Key(
False, bool, "Look", "Stack from top to zero, this makes the stacked "
"data match the legend order")
"data match the legend order")

spacing = Key(
10, int, "Look",
Expand Down Expand Up @@ -336,6 +336,11 @@ class Config(CommonConfig):
False, bool, "Value", "Display values in human readable format",
"(ie: 12.4M)")

x_value_formatter = Key(
None, type(lambda: 1), "Value",
"A function to convert abscissa numeric value to strings "
"(used in XY and Date charts)")

value_formatter = Key(
None, type(lambda: 1), "Value",
"A function to convert numeric value to strings")
Expand Down Expand Up @@ -367,6 +372,11 @@ class Config(CommonConfig):
None, list, "Value", "Explicitly specify min and max of values",
"(ie: (0, 100))", int)

xrange = Key(
None, list, "Value", "Explicitly specify min and max of x values "
"(used in XY and Date charts)",
"(ie: (0, 100))", int)

include_x_axis = Key(
False, bool, "Value", "Always include x axis")

Expand Down
15 changes: 13 additions & 2 deletions pygal/ghost.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,20 @@ class ChartCollection(object):
pass


REAL_CHARTS = {}
REAL_CHARTS = {
'DateY': 'pygal.graph.time.DateY',
'DateTimeLine': 'pygal.graph.time.DateTimeLine',
'DateLine': 'pygal.graph.time.DateLine',
'TimeLine': 'pygal.graph.time.TimeLine',
'TimeDeltaLine': 'pygal.graph.time.TimeDeltaLine'
}

for NAME in CHARTS_NAMES:
mod_name = 'pygal.graph.%s' % NAME.lower()
if NAME in REAL_CHARTS:
mod_name = 'pygal.graph.time'
else:
mod_name = 'pygal.graph.%s' % NAME.lower()

__import__(mod_name)
mod = sys.modules[mod_name]
chart = getattr(mod, NAME)
Expand Down
8 changes: 6 additions & 2 deletions pygal/graph/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@
'VerticalPyramid',
'Dot',
'Gauge',
'DateY',
'Worldmap',
'SupranationalWorldmap',
'Histogram',
'Box',
'FrenchMap',
'Treemap'
'Treemap',
'DateY',
'DateTimeLine',
'DateLine',
'TimeLine',
'TimeDeltaLine'
]
8 changes: 8 additions & 0 deletions pygal/graph/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,21 @@ def __init__(self, config, series, secondary_series, uuid, xml_filters):
for serie in self.series for val in serie.safe_values]))

self.zero = min(positive_values or (1,)) or 1
if self._len < 3:
self.interpolate = None
self._draw()
self.svg.pre_render()

@property
def all_series(self):
return self.series + self.secondary_series

@property
def _x_format(self):
"""Return the value formatter for this graph"""
return self.config.x_value_formatter or (
humanize if self.human_readable else str)

@property
def _format(self):
"""Return the value formatter for this graph"""
Expand Down
5 changes: 5 additions & 0 deletions pygal/graph/box.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ def _plot(self):
for serie in self.series:
self._boxf(serie)

@property
def _len(self):
"""Len is always 5 here"""
return 5

def _boxf(self, serie):
"""
For a specific series, draw the box plot.
Expand Down
Loading

0 comments on commit a5f94eb

Please sign in to comment.