diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000..940c3e7
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,249 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=test
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once).
+disable=W0142
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html
+output-format=colorized
+
+# Include message's id in output
+include-ids=yes
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=no
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=yes
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=no
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+# ignored-classes=
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=79
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Za-z_][A-Za-z0-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-z0-9_]{0,30}$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-z0-9_]{0,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-z0-9_]{0,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-z0-9_]{0,30}$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,db,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=20
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branchs=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=10
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=0
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=80
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
diff --git a/pygal/__init__.py b/pygal/__init__.py
index 5572bcd..7f5037b 100644
--- a/pygal/__init__.py
+++ b/pygal/__init__.py
@@ -16,6 +16,10 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see .
+"""
+Pygal - A python svg graph plotting library
+
+"""
__version__ = '0.9.21'
@@ -30,7 +34,8 @@ from pygal.graph.pie import Pie
from pygal.graph.radar import Radar
from pygal.config import Config
-"""List of all chart types"""
+
+#: List of all chart types
CHARTS = [
Bar, HorizontalBar, StackedBar, HorizontalStackedBar,
Line, StackedLine, XY, Pie, Radar]
diff --git a/pygal/config.py b/pygal/config.py
index 6679193..7438ffd 100644
--- a/pygal/config.py
+++ b/pygal/config.py
@@ -16,6 +16,12 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see .
+
+"""
+Config module with all options
+"""
+
+
from pygal.style import DefaultStyle
@@ -27,72 +33,73 @@ class Config(object):
"""Class holding config values"""
_horizontal = False
- # Graph width
+ #: Graph width
width = 800
- # Graph height
+ #: Graph height
height = 600
- # Display values in human readable format (ie: 12.4M)
+ #: Display values in human readable format (ie: 12.4M)
human_readable = False
- # Display values in logarithmic scale
+ #: Display values in logarithmic scale
logarithmic = False
- # If set to a filename, this will replace the default css
+ #: If set to a filename, this will replace the default css
base_css = None
- # or default js
+ #: or default js
base_js = None
- # Style holding values injected in css
+ #: Style holding values injected in css
style = DefaultStyle
- # Various font sizes
+ #: Various font sizes
label_font_size = 10
value_font_size = 8
tooltip_font_size = 20
title_font_size = 16
legend_font_size = 14
- # Specify labels rotation angles in degrees
+ #: Specify labels rotation angles in degrees
x_label_rotation = 0
y_label_rotation = 0
- # Set to false to remove legend
+ #: Set to false to remove legend
show_legend = True
- # Set to false to remove dots
+ #: Set to false to remove dots
show_dots = True
- # Size of legend boxes
+ #: Size of legend boxes
legend_box_size = 12
- # X labels, must have same len than data.
- # Leave it to None to disable x labels display.
+ #: X labels, must have same len than data.
+ #: Leave it to None to disable x labels display.
x_labels = None
- # You can specify explicit y labels (must be list(int))
+ #: You can specify explicit y labels (must be list(int))
y_labels = None
- # Graph title
- # Leave it to None to disable title.
+ #: Graph title
+ #: Leave it to None to disable title.
title = None
- # Set this to the desired radius in px
+ #: Set this to the desired radius in px
rounded_bars = False
- # Always include x axis
+ #: Always include x axis
include_x_axis = False
- # Fill areas under lines
+ #: Fill areas under lines
fill = False
- # Line dots (set it to false to get a scatter plot)
+ #: Line dots (set it to false to get a scatter plot)
stroke = True
- # Interpolation, this requires scipy module
- # May be any of ‘linear’, ’nearest’, ‘zero’, ‘slinear’, ‘quadratic, ‘cubic’
- # 'krogh', 'barycentric', 'univariate', or an integer specifying the order
- # of the spline interpolator
+ #: Interpolation, this requires scipy module
+ #: May be any of 'linear', 'nearest', 'zero', 'slinear', 'quadratic,
+ #: 'cubic', 'krogh', 'barycentric', 'univariate',
+ #: or an integer specifying the order
+ #: of the spline interpolator
interpolate = None
- # Number of interpolated points between two values
+ #: Number of interpolated points between two values
interpolation_precision = 250
- # Set the ordinate zero value (for filling)
+ #: Set the ordinate zero value (for filling)
zero = 0
- # Text to display when no data is given
+ #: Text to display when no data is given
no_data_text = "No data"
- # Print values when graph is in non interactive mode
+ #: Print values when graph is in non interactive mode
print_values = True
- # Print zeroes when graph is in non interactive mode
+ #: Print zeroes when graph is in non interactive mode
print_zeroes = False
- # Animate tooltip steps (0 disable animation)
+ #: Animate tooltip steps (0 disable animation)
animation_steps = 0
- # Don't write xml declaration and return unicode instead of string
- # (usefull for writing output in html)
+ #: Don't write xml declaration and return unicode instead of string
+ #: (usefull for writing output in html)
disable_xml_declaration = False
- # Write width and height attributes
+ #: Write width and height attributes
explicit_size = False
def __init__(self, **kwargs):
diff --git a/pygal/graph/bar.py b/pygal/graph/bar.py
index ad032e9..76efa61 100644
--- a/pygal/graph/bar.py
+++ b/pygal/graph/bar.py
@@ -39,6 +39,17 @@ class Bar(Graph):
for i, ((x, y), (X, Y)) in enumerate(view_values):
if None in (x, y):
continue
+
+ # +-------+
+ # | |
+ # | |
+ # | +-------+
+ # | | |
+ # | | |
+ # | | |
+ # +-------+-------+
+ # (x,y) (X,Y)
+ #
# x and y are left range coords and X, Y right ones
val = self._format(values[i][1][1])
if self._horizontal:
diff --git a/pygal/interpolate.py b/pygal/interpolate.py
index 86c1a61..bf47727 100644
--- a/pygal/interpolate.py
+++ b/pygal/interpolate.py
@@ -16,15 +16,21 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see .
+"""
+Interpolation using scipy
+"""
from pygal.util import ident
+
+scipy = None
try:
import scipy
from scipy import interpolate
-except:
- scipy = None
+except ImportError:
+ pass
def interpolation(x, y, kind):
+ """Make the interpolation function"""
assert scipy != None, 'You must have scipy installed to use interpolation'
order = None
if len(y) < len(x):
diff --git a/pygal/serie.py b/pygal/serie.py
index 6c65c15..05373ac 100644
--- a/pygal/serie.py
+++ b/pygal/serie.py
@@ -16,9 +16,13 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see .
+"""
+Little helpers for series
+"""
class Serie(object):
+ """Serie containing title, values and the graph serie index"""
def __init__(self, title, values, index):
self.title = title
self.values = values
@@ -26,6 +30,7 @@ class Serie(object):
class Label(object):
+ """A label with his position"""
def __init__(self, label, pos):
self.label = label
self.pos = pos
diff --git a/pygal/style.py b/pygal/style.py
index bb7f3dd..1f1e1fb 100644
--- a/pygal/style.py
+++ b/pygal/style.py
@@ -16,9 +16,13 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see .
+"""
+Charts styling
+"""
class Style(object):
+ """Styling class containing colors for the css generation"""
def __init__(self,
background='black',
plot_background='#111',
@@ -33,19 +37,21 @@ class Style(object):
'#899ca1', '#f8f8f2', '#808384', '#bf4646', '#516083',
'#f92672', '#82b414', '#fd971f', '#56c2d6', '#8c54fe',
'#465457')):
- self.background = background
- self.plot_background = plot_background
- self.foreground = foreground
- self.foreground_light = foreground_light
- self.foreground_dark = foreground_dark
- self.opacity = opacity
- self.opacity_hover = opacity_hover
- self.transition = transition
- self._colors = colors
+ self.background = background
+ self.plot_background = plot_background
+ self.foreground = foreground
+ self.foreground_light = foreground_light
+ self.foreground_dark = foreground_dark
+ self.opacity = opacity
+ self.opacity_hover = opacity_hover
+ self.transition = transition
+ self._colors = colors
@property
def colors(self):
+ """Get the css color list"""
def color(tupl):
+ """Make a color css"""
return (
'.color-{0} {{\n'
' stroke: {1};\n'
diff --git a/pygal/view.py b/pygal/view.py
index dd1c159..66bdc9b 100644
--- a/pygal/view.py
+++ b/pygal/view.py
@@ -16,11 +16,16 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see .
+"""
+Projection and bounding helpers
+"""
+
from __future__ import division
from math import sin, cos, log10
class Margin(object):
+ """Graph margin"""
def __init__(self, top, right, bottom, left):
self.top = top
self.right = right
@@ -29,14 +34,17 @@ class Margin(object):
@property
def x(self):
+ """Helper for total x margin"""
return self.left + self.right
@property
def y(self):
+ """Helper for total y margin"""
return self.top + self.bottom
class Box(object):
+ """Chart boundings"""
_margin = .02
def __init__(self):
@@ -45,17 +53,21 @@ class Box(object):
@property
def width(self):
+ """Helper for box width"""
return self.xmax - self.xmin
@property
def height(self):
+ """Helper for box height"""
return self.ymax - self.ymin
def swap(self):
+ """Return the box (for horizontal qraphs)"""
self.xmin, self.ymin = self.ymin, self.xmin
self.xmax, self.ymax = self.ymax, self.xmax
def fix(self, with_margin=True):
+ """Correct box when no values and take margin in account"""
if not self.width:
self.xmax = self.xmin + 1
if not self.height:
@@ -71,6 +83,7 @@ class Box(object):
class View(object):
+ """Projection base class"""
def __init__(self, width, height, box):
self.width = width
self.height = height
@@ -78,23 +91,29 @@ class View(object):
self.box.fix()
def x(self, x):
+ """Project x"""
if x == None:
return None
return self.width * (x - self.box.xmin) / self.box.width
def y(self, y):
+ """Project y"""
if y == None:
return None
return (self.height - self.height *
(y - self.box.ymin) / self.box.height)
def __call__(self, xy):
+ """Project x and y"""
x, y = xy
return (self.x(x), self.y(y))
class PolarView(View):
+ """Polar projection for pie like graphs"""
+
def __call__(self, rhotheta):
+ """Project rho and theta"""
if None in rhotheta:
return None, None
rho, theta = rhotheta
@@ -104,6 +123,9 @@ class PolarView(View):
class LogView(View):
+ """Logarithmic projection """
+ # Do not want to call the parent here
+ # pylint: disable-msg=W0231
def __init__(self, width, height, box):
self.width = width
self.height = height
@@ -115,6 +137,7 @@ class LogView(View):
self.box.fix(False)
def y(self, y):
+ """Project y"""
if y == None or y <= 0:
return None
return (self.height - self.height *