Skip to content

Commit

Permalink
Add ghost containers
Browse files Browse the repository at this point in the history
  • Loading branch information
paradoxxxzero committed Sep 13, 2012
1 parent 05b4974 commit 56a876e
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 107 deletions.
43 changes: 12 additions & 31 deletions pygal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,37 +21,18 @@
"""

__version__ = '0.10.3'

__version__ = '0.11.0'
import sys
from pygal.config import Config
from pygal.graph.bar import Bar
from pygal.graph.dot import Dot
from pygal.graph.funnel import Funnel
from pygal.graph.gauge import Gauge
from pygal.graph.horizontal import HorizontalBar
from pygal.graph.horizontal import HorizontalStackedBar
from pygal.graph.line import Line
from pygal.graph.pie import Pie
from pygal.graph.pyramid import Pyramid
from pygal.graph.radar import Radar
from pygal.graph.stackedbar import StackedBar
from pygal.graph.stackedline import StackedLine
from pygal.graph.xy import XY
from pygal.ghost import Ghost
from pygal.graph import CHARTS_NAMES

CHARTS = []

for NAME in CHARTS_NAMES:
_CHART = type(NAME, (Ghost,), {})
CHARTS.append(_CHART)
setattr(sys.modules[__name__], NAME, _CHART)


#: List of all chart types
CHARTS = [
Bar,
Dot,
Funnel,
Gauge,
HorizontalBar,
HorizontalStackedBar,
Line,
Pie,
Pyramid,
Radar,
StackedBar,
StackedLine,
XY
]
__all__ = CHARTS_NAMES + [Config.__name__, 'CHARTS']
13 changes: 9 additions & 4 deletions pygal/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,16 @@ def __init__(self, **kwargs):
"""Can be instanciated with config kwargs"""
self.css = list(self.css)
self.js = list(self.js)
self.__dict__.update(kwargs)
self._update(kwargs)

def __call__(self, **kwargs):
"""Can be updated with kwargs"""
self.__dict__.update(kwargs)
self._update(kwargs)

def _update(self, kwargs):
self.__dict__.update(
dict([(k, v) for (k, v) in kwargs.items()
if not k.startswith('_') and k in dir(self)]))

def font_sizes(self, with_unit=True):
"""Getter for all font size configs"""
Expand All @@ -133,8 +138,8 @@ def font_sizes(self, with_unit=True):
setattr(
fs,
name.replace('_font_size', ''),
('%dpx' % getattr(self, name)
) if with_unit else getattr(self, name))
('%dpx' % getattr(self, name))
if with_unit else getattr(self, name))
return fs

def to_dict(self):
Expand Down
94 changes: 94 additions & 0 deletions pygal/ghost.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# -*- coding: utf-8 -*-
# This file is part of pygal
#
# A python svg graph plotting library
# Copyright © 2012 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/>.
"""
Ghost container
It is used to delegate rendering to real objects but keeping config in place
"""

import io
from importlib import import_module
from pygal.config import Config
from pygal.serie import Serie, Value
from pygal.graph import CHARTS_NAMES


REAL_CHARTS = {}
for NAME in CHARTS_NAMES:
mod = import_module('pygal.graph.%s' % NAME.lower())
REAL_CHARTS[NAME] = getattr(mod, NAME)


class Ghost(object):

def __init__(self, config=None, **kwargs):
"""Init config"""
self.config = config or Config()
self.config(**kwargs)
self.series = []

def add(self, title, values):
"""Add a serie to this graph"""
self.series.append(
Serie(title, values, len(self.series), Value))

def make_instance(self):
self.config(**self.__dict__)
name = self.__class__.__name__
cls = REAL_CHARTS[name]
self._last__inst = cls(self.config, self.series)
return self._last__inst

# Rendering
def render(self, is_unicode=False):
return self.make_instance().render(is_unicode=is_unicode)

def render_tree(self):
return self.make_instance().render_tree()

def render_pyquery(self):
"""Render the graph, and return a pyquery wrapped tree"""
from pyquery import PyQuery as pq
return pq(self.render_tree())

def render_in_browser(self):
"""Render the graph, open it in your browser with black magic"""
from lxml.html import open_in_browser
open_in_browser(self.render_tree(), encoding='utf-8')

def render_response(self):
"""Render the graph, and return a Flask response"""
from flask import Response
return Response(self.render(), mimetype='image/svg+xml')

def render_to_file(self, filename):
"""Render the graph, and write it to filename"""
with io.open(filename, 'w', encoding='utf-8') as f:
f.write(self.render(is_unicode=True))

def render_to_png(self, filename):
"""Render the graph, convert it to png and write it to filename"""
import cairosvg
from io import BytesIO
fakefile = BytesIO()
fakefile.write(self.render())
fakefile.seek(0)
cairosvg.surface.PNGSurface.convert(
file_obj=fakefile, write_to=filename)
16 changes: 16 additions & 0 deletions pygal/graph/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,19 @@
Graph modules
"""

CHARTS_NAMES = [
'Bar',
'Dot',
'Funnel',
'Gauge',
'HorizontalBar',
'HorizontalStackedBar',
'Line',
'Pie',
'Pyramid',
'Radar',
'StackedBar',
'StackedLine',
'XY'
]
48 changes: 5 additions & 43 deletions pygal/graph/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,11 @@
"""

from __future__ import division
import io
from pygal.serie import Serie, Value
from pygal.view import Margin, Box
from pygal.serie import Value
from pygal.util import (
get_text_box, get_texts_box, cut, rad, humanize, truncate)
from pygal.svg import Svg
from pygal.config import Config
from pygal.util import cached_property
from math import sin, cos, sqrt

Expand All @@ -38,25 +36,19 @@ class BaseGraph(object):

__value__ = Value

def __init__(self, config=None, **kwargs):
def __init__(self, config, series):
"""Init the graph"""
self.config = config or Config()
self.config(**kwargs)
self.config = config
self.series = series
self.horizontal = getattr(self, 'horizontal', False)
self.svg = Svg(self)
self.series = []
self._x_labels = None
self._y_labels = None
self._box = None
self.nodes = {}
self.margin = None
self.view = None

def add(self, title, values):
"""Add a serie to this graph"""
self.series.append(
Serie(title, values, len(self.series), self.__value__))

def reinit(self):
"""(Re-)Init the graph"""
self.margin = Margin(*([20] * 4))
Expand Down Expand Up @@ -191,7 +183,7 @@ def _render(self):
else:
self.svg.pre_render(True)

def render(self, is_unicode=False):
def render(self, is_unicode):
"""Render the graph, and return the svg string"""
self._render()
return self.svg.render(
Expand All @@ -201,33 +193,3 @@ def render_tree(self):
"""Render the graph, and return lxml tree"""
self._render()
return self.svg.root

def render_pyquery(self):
"""Render the graph, and return a pyquery wrapped tree"""
from pyquery import PyQuery as pq
return pq(self.render_tree())

def render_in_browser(self):
"""Render the graph, open it in your browser with black magic"""
from lxml.html import open_in_browser
open_in_browser(self.render_tree(), encoding='utf-8')

def render_response(self):
"""Render the graph, and return a Flask response"""
from flask import Response
return Response(self.render(), mimetype='image/svg+xml')

def render_to_file(self, filename):
"""Render the graph, and write it to filename"""
with io.open(filename, 'w', encoding='utf-8') as f:
f.write(self.render(is_unicode=True))

def render_to_png(self, filename):
"""Render the graph, convert it to png and write it to filename"""
import cairosvg
from io import BytesIO
fakefile = BytesIO()
fakefile.write(self.render())
fakefile.seek(0)
cairosvg.surface.PNGSurface.convert(
file_obj=fakefile, write_to=filename)
12 changes: 1 addition & 11 deletions pygal/graph/horizontal.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""
Horizontal graph
Horizontal graph base
"""
from pygal.graph.graph import Graph
from pygal.graph.bar import Bar
from pygal.graph.stackedbar import StackedBar


class HorizontalGraph(Graph):
Expand All @@ -46,11 +44,3 @@ def _compute(self):
if self.first_pass:
for serie in self.series:
serie.values = list(reversed(serie.values))


class HorizontalBar(HorizontalGraph, Bar):
"""Horizontal Bar graph"""


class HorizontalStackedBar(HorizontalGraph, StackedBar):
"""Horizontal Stacked Bar graph"""
28 changes: 28 additions & 0 deletions pygal/graph/horizontalbar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# This file is part of pygal
#
# A python svg graph plotting library
# Copyright © 2012 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/>.
"""
Horizontal bar graph
"""
from pygal.graph.horizontal import HorizontalGraph
from pygal.graph.bar import Bar


class HorizontalBar(HorizontalGraph, Bar):
"""Horizontal Bar graph"""
28 changes: 28 additions & 0 deletions pygal/graph/horizontalstackedbar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# This file is part of pygal
#
# A python svg graph plotting library
# Copyright © 2012 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/>.
"""
Horizontal stacked graph
"""
from pygal.graph.horizontal import HorizontalGraph
from pygal.graph.stackedbar import StackedBar


class HorizontalStackedBar(HorizontalGraph, StackedBar):
"""Horizontal Stacked Bar graph"""
Loading

0 comments on commit 56a876e

Please sign in to comment.