Skip to content

Commit

Permalink
Document pygal.*
Browse files Browse the repository at this point in the history
  • Loading branch information
paradoxxxzero committed Jul 15, 2015
1 parent 09480b5 commit 6f59ff1
Show file tree
Hide file tree
Showing 14 changed files with 183 additions and 64 deletions.
21 changes: 12 additions & 9 deletions pygal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""
Main pygal package
Main pygal package.
This package holds all available charts in pygal, the Config class
and the maps extensions namespace module.
Expand Down Expand Up @@ -76,16 +76,17 @@


class PluginImportFixer(object):
"""Allow external map plugins to be imported from pygal.maps package.
It is a ``sys.meta_path`` loader.

"""
Allow external map plugins to be imported from pygal.maps package.
def __init__(self):
pass
It is a ``sys.meta_path`` loader.
"""

def find_module(self, fullname, path=None):
"""This method says if the module to load can be loaded by
the load_module function, that is here if it is a ``pygal.maps.*``
"""
Tell if the module to load can be loaded by
the load_module function, ie: if it is a ``pygal.maps.*``
module.
"""
if fullname.startswith('pygal.maps.') and hasattr(
Expand All @@ -94,8 +95,10 @@ def find_module(self, fullname, path=None):
return None

def load_module(self, name):
"""Loads the ``pygal.maps.name`` module from
the previously loaded plugin"""
"""
Load the ``pygal.maps.name`` module from the previously
loaded plugin
"""
if name not in sys.modules:
sys.modules[name] = getattr(maps, name.split('.')[2])
return sys.modules[name]
Expand Down
19 changes: 12 additions & 7 deletions pygal/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""
Various hacks for transparent python 2 / python 3 support
"""
"""Various hacks for transparent python 2 / python 3 support"""

import sys
from collections import Iterable
Expand All @@ -34,32 +32,38 @@


def is_list_like(value):
"""Return whether value is an iterable but not a mapping / string"""
return isinstance(value, Iterable) and not isinstance(value, (base, dict))


def is_str(string):
"""Return whether value is a string or a byte list"""
return isinstance(string, base)


def to_str(string):
if not is_str(string):
return coerce(string)
return string
def to_str(obj):
"""Cast obj to unicode string"""
if not is_str(obj):
return coerce(obj)
return obj


def to_unicode(string):
"""Force stirng to be a string in python 3 or a unicode in python 2"""
if not isinstance(string, coerce):
return string.decode('utf-8')
return string


def u(s):
"""Emulate u'str' in python 2, do nothing in python 3"""
if sys.version_info[0] == 2:
return s.decode('utf-8')
return s


def total_seconds(td):
"""Backport of `timedelta.total_second` function for python 2.6"""
if sys.version_info[:2] == (2, 6):
return (
(td.days * 86400 + td.seconds) * 10 ** 6 + td.microseconds
Expand All @@ -68,6 +72,7 @@ def total_seconds(td):


def timestamp(x):
"""Get a timestamp from a date in python 3 and python 2"""
if hasattr(x, 'timestamp'):
from datetime import timezone
if x.tzinfo is None:
Expand Down
5 changes: 1 addition & 4 deletions pygal/adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""
Value adapters to use when a chart doesn't accept all value types
"""
"""Value adapters to use when a chart doesn't accept all value types"""
from decimal import Decimal


Expand Down
9 changes: 5 additions & 4 deletions pygal/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,10 @@ def parse_color(color):


def unparse_color(r, g, b, a, type):
"""Take the r, g, b, a color values and give back
a type css color string. This is the inverse function of parse_color"""

"""
Take the r, g, b, a color values and give back
a type css color string. This is the inverse function of parse_color
"""
if type == '#rgb':
# Don't lose precision on rgb shortcut
if r % 17 == 0 and g % 17 == 0 and b % 17 == 0:
Expand Down Expand Up @@ -168,7 +169,7 @@ def adjust(color, attribute, percent):


def rotate(color, percent):
"""Rotates a color by changing its hue value by percent"""
"""Rotate a color by changing its hue value by percent"""
return adjust(color, 0, percent)


Expand Down
24 changes: 16 additions & 8 deletions pygal/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""Config module holding all options and their default values."""

"""
Config module holding all options and their default values.
"""
from copy import deepcopy
from pygal.style import Style, DefaultStyle
from pygal.interpolate import INTERPOLATIONS
Expand All @@ -29,6 +27,7 @@


class Key(object):

"""
Represents a config parameter.
Expand All @@ -45,7 +44,7 @@ class Key(object):
def __init__(
self, default_value, type_, category, doc,
subdoc="", subtype=None):

"""Create a configuration key"""
self.value = default_value
self.type = type_
self.doc = doc
Expand All @@ -59,6 +58,10 @@ def __init__(
CONFIG_ITEMS.append(self)

def __repr__(self):
"""
Make a documentation repr.
This is a hack to generate doc from inner doc
"""
return """
Type: %s%s     
Default: %r     
Expand Down Expand Up @@ -120,10 +123,11 @@ def coerce(self, value):


class MetaConfig(type):
"""
Metaclass for configs. Used to get the key name and set it on the value.
"""

"""Config metaclass. Used to get the key name and set it on the value."""

def __new__(mcs, classname, bases, classdict):
"""Get the name of the key and set it on the key"""
for k, v in classdict.items():
if isinstance(v, Key):
v.name = k
Expand All @@ -132,6 +136,7 @@ def __new__(mcs, classname, bases, classdict):


class BaseConfig(MetaConfig('ConfigBase', (object,), {})):

"""
This class holds the common method for configs.
Expand Down Expand Up @@ -159,7 +164,7 @@ def __call__(self, **kwargs):
self._update(kwargs)

def _update(self, kwargs):
"""Updates the config with the given dictionary"""
"""Update the config with the given dictionary"""
self.__dict__.update(
dict([(k, v) for (k, v) in kwargs.items()
if not k.startswith('_') and k in dir(self)]))
Expand All @@ -182,6 +187,7 @@ def copy(self):


class CommonConfig(BaseConfig):

"""Class holding options used in both chart and serie configuration"""

stroke = Key(
Expand Down Expand Up @@ -213,6 +219,7 @@ class CommonConfig(BaseConfig):


class Config(CommonConfig):

"""Class holding config values"""

style = Key(
Expand Down Expand Up @@ -496,6 +503,7 @@ class Config(CommonConfig):


class SerieConfig(CommonConfig):

"""Class holding serie config values"""

secondary = Key(
Expand Down
3 changes: 3 additions & 0 deletions pygal/etree.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@


class Etree(object):

"""Etree wrapper using lxml.etree or standard xml.etree"""

def __init__(self):
"""Create the wrapper"""
from xml.etree import ElementTree as _py_etree
self._py_etree = _py_etree
try:
Expand All @@ -43,6 +45,7 @@ def __init__(self):
self.lxml = self._etree is self._lxml_etree

def __getattribute__(self, attr):
"""Retrieve attr from current active etree implementation"""
if (attr not in object.__getattribute__(self, '__dict__') and
attr not in Etree.__dict__):
return object.__getattribute__(self._etree, attr)
Expand Down
1 change: 0 additions & 1 deletion pygal/interpolate.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ def quadratic_interpolate(x, y, precision=250, **kwargs):
Interpolate x, y using a quadratic algorithm
https://en.wikipedia.org/wiki/Spline_(mathematics)
"""

n = len(x) - 1
delta_x = [x2 - x1 for x1, x2 in zip(x, x[1:])]
delta_y = [y2 - y1 for y1, y2 in zip(y, y[1:])]
Expand Down
11 changes: 6 additions & 5 deletions pygal/serie.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""
Little helpers for series
"""
"""Serie property holder"""
from pygal.util import cached_property


class Serie(object):
"""Serie containing title, values and the graph serie index"""

"""Serie class containing title, values and the graph serie index"""

def __init__(self, index, title, values, config, metadata=None):
"""Create the serie with its options"""
self.index = index
self.title = title
self.values = values
Expand All @@ -35,4 +35,5 @@ def __init__(self, index, title, values, config, metadata=None):

@cached_property
def safe_values(self):
"""Property containing all values that are not None"""
return list(filter(lambda x: x is not None, self.values))
12 changes: 9 additions & 3 deletions pygal/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,20 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""
Class holding state during render

"""
"""Class holding state during render"""


class State(object):

"""
Class containing config values
overriden by chart values
overriden by keyword args
"""

def __init__(self, graph, **kwargs):
"""Create the transient state"""
self.__dict__.update(**graph.config.__dict__)
self.__dict__.update(**graph.__dict__)
self.__dict__.update(**kwargs)
23 changes: 19 additions & 4 deletions pygal/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""
Charts styling
"""
"""Charts styling classes"""

from __future__ import division
from pygal.util import cycle_fill
from pygal import colors
Expand All @@ -27,7 +26,9 @@


class Style(object):

"""Styling class containing colors for the css generation"""

def __init__(
self,
background='black',
Expand All @@ -45,6 +46,7 @@ def __init__(
'#899ca1', '#f8f8f2', '#bf4646', '#516083', '#f92672',
'#82b414', '#fd971f', '#56c2d6', '#808384', '#8c54fe',
'#465457')):
"""Create the style"""
self.background = background
self.plot_background = plot_background
self.foreground = foreground
Expand All @@ -58,7 +60,6 @@ def __init__(

def get_colors(self, prefix, len_):
"""Get the css color list"""

def color(tupl):
"""Make a color css"""
return ((
Expand All @@ -75,6 +76,7 @@ def color(tupl):
return '\n'.join(map(color, enumerate(colors)))

def to_dict(self):
"""Convert instance to a serializable mapping."""
config = {}
for attr in dir(self):
if not attr.startswith('__'):
Expand Down Expand Up @@ -296,10 +298,23 @@ def to_dict(self):
name = op.capitalize() + 'Style'

def get_style_for(op_name):
"""
Return a callable that returns a Style instance
for the given operation
"""
operation = getattr(colors, op_name)

def parametric_style(color, step=10, max_=None, base_style=None,
**kwargs):
"""
Generate a parametric Style instance of the parametric operation
This takes several parameters:
* a `step` which correspond on how many colors will be needed
* a `max_` which defines the maximum amplitude of the color effect
* a `base_style` which will be taken as default for everything
except colors
* any keyword arguments setting other style parameters
"""
if max_ is None:
violency = {
'darken': 50,
Expand Down

0 comments on commit 6f59ff1

Please sign in to comment.