Hello community,

here is the log from the commit of package python-pycha for openSUSE:Leap:15.2 
checked in at 2020-03-02 13:20:37
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Leap:15.2/python-pycha (Old)
 and      /work/SRC/openSUSE:Leap:15.2/.python-pycha.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pycha"

Mon Mar  2 13:20:37 2020 rev:11 rq:776958 version:0.8.1

Changes:
--------
--- /work/SRC/openSUSE:Leap:15.2/python-pycha/python-pycha.changes      
2020-01-15 15:51:49.455542221 +0100
+++ /work/SRC/openSUSE:Leap:15.2/.python-pycha.new.26092/python-pycha.changes   
2020-03-02 13:20:38.166073868 +0100
@@ -1,0 +2,17 @@
+Thu Jan 30 15:16:25 UTC 2020 - Todd R <toddrme2...@gmail.com>
+
+- Update to 0.8.1
+  * Forgot to update Changelog for 0.8.0
+- Update to 0.8.0
+  * Add support for Python 3 by encukou
+  * Add support for Tox, Pyflakes, Coverage and Buildbucket pipelines
+  * Remove support for Buildout
+
+-------------------------------------------------------------------
+Wed Apr  3 03:55:04 UTC 2019 - John Vandenberg <jay...@gmail.com>
+
+- Fix fdupes to avoid python3 package egg-info being symlinks into
+  the python2 package which may not be installed.
+- Use %license
+
+-------------------------------------------------------------------

Old:
----
  pycha-0.7.0.tar.gz

New:
----
  pycha-0.8.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pycha.spec ++++++
--- /var/tmp/diff_new_pack.D9Pi1x/_old  2020-03-02 13:20:38.510074550 +0100
+++ /var/tmp/diff_new_pack.D9Pi1x/_new  2020-03-02 13:20:38.510074550 +0100
@@ -1,9 +1,7 @@
 #
 # spec file for package python-pycha
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
-# Copyright (c) 2016 Dr. Axel Braun
-# Copyright (c) 2017 Oliver Kurz
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -14,25 +12,28 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
-
-%define         mod_name pycha
 Name:           python-pycha
-Version:        0.7.0
+Version:        0.8.1
 Release:        0
 Summary:        A library for making charts with Python
-License:        LGPL-3.0+
+License:        LGPL-3.0-or-later
 Group:          Development/Languages/Python
-Url:            http://bitbucket.org/lgs/%{mod_name}/
-Source:         
https://pypi.io/packages/source/p/%{mod_name}/%{mod_name}-%{version}.tar.gz
+URL:            http://bitbucket.org/lgs/pycha/
+Source:         
https://files.pythonhosted.org/packages/source/p/pycha/pycha-%{version}.tar.gz
 BuildRequires:  %{python_module setuptools}
-BuildRequires:  python-rpm-macros
 BuildRequires:  fdupes
-BuildRoot:      %{_tmppath}/%{name}-%{version}-build
+BuildRequires:  python-rpm-macros
+Requires:       python-cairocffi
+Requires:       python-six
+# SECTION test requirements
+BuildRequires:  %{python_module cairocffi}
+BuildRequires:  %{python_module six}
+# /SECTION
 BuildArch:      noarch
 %python_subpackages
 
@@ -44,18 +45,18 @@
 web programming. Pycha was developed for the server side.
 
 %prep
-%setup -q -n %{mod_name}-%{version}
+%setup -q -n pycha-%{version}
 
 %build
 %python_build
 
 %install
 %python_install
-%fdupes -s %{buildroot}
+%python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %files %{python_files}
-%defattr(-,root,root,-)
-%doc COPYING README.txt CHANGES.txt AUTHORS
+%doc README.txt CHANGES.txt AUTHORS
+%license COPYING
 %{python_sitelib}/*
 %python3_only %{_bindir}/chavier
 

++++++ pycha-0.7.0.tar.gz -> pycha-0.8.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/CHANGES.txt new/pycha-0.8.1/CHANGES.txt
--- old/pycha-0.7.0/CHANGES.txt 2013-04-07 20:47:07.000000000 +0200
+++ new/pycha-0.8.1/CHANGES.txt 2019-11-18 07:45:36.000000000 +0100
@@ -1,6 +1,16 @@
 Changes
 =======
 
+0.8.1 (2019-11-17)
+---------------------
+- Forgot to update Changelog for 0.8.0
+
+0.8.0 (2019-11-17)
+---------------------
+- Add support for Python 3 by encukou
+- Add support for Tox, Pyflakes, Coverage and Buildbucket pipelines
+- Remove support for Buildout
+
 0.7.0 (2012-04-07)
 ------------------
 - Radial Chart by Roberto Garcia Carvajal
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/PKG-INFO new/pycha-0.8.1/PKG-INFO
--- old/pycha-0.7.0/PKG-INFO    2013-04-07 20:55:50.000000000 +0200
+++ new/pycha-0.8.1/PKG-INFO    2019-11-18 07:47:15.000000000 +0100
@@ -1,6 +1,6 @@
-Metadata-Version: 1.0
+Metadata-Version: 2.1
 Name: pycha
-Version: 0.7.0
+Version: 0.8.1
 Summary: A library for making charts with Python
 Home-page: http://bitbucket.org/lgs/pycha/
 Author: Lorenzo Gil Sanchez
@@ -62,6 +62,16 @@
         Changes
         =======
         
+        0.8.1 (2019-11-17)
+        ---------------------
+        - Forgot to update Changelog for 0.8.0
+        
+        0.8.0 (2019-11-17)
+        ---------------------
+        - Add support for Python 3 by encukou
+        - Add support for Tox, Pyflakes, Coverage and Buildbucket pipelines
+        - Remove support for Buildout
+        
         0.7.0 (2012-04-07)
         ------------------
         - Radial Chart by Roberto Garcia Carvajal
@@ -157,3 +167,4 @@
         
 Keywords: chart cairo
 Platform: UNKNOWN
+Provides-Extra: testing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/examples/draw.py 
new/pycha-0.8.1/examples/draw.py
--- old/pycha-0.7.0/examples/draw.py    1970-01-01 01:00:00.000000000 +0100
+++ new/pycha-0.8.1/examples/draw.py    2010-05-29 11:01:44.000000000 +0200
@@ -0,0 +1,201 @@
+#! /usr/bin/env python
+import cairo
+from math import pi, sqrt
+
+class Diagram(object):
+    def __init__(self, filename, width, height):
+        self.surface = cairo.SVGSurface(filename + '.svg', width, height)
+        cr = self.cr = cairo.Context(self.surface)
+
+        cr.scale(width, height)
+        cr.set_line_width(0.01)
+
+        cr.rectangle(0, 0, 1, 1)
+        cr.set_source_rgb(1, 1, 1)
+        cr.fill()
+
+        self.draw_dest(cr)
+
+        cr.set_line_width( max(cr.device_to_user_distance(2, 2)) )
+        cr.set_source_rgb(0, 0, 0)
+        cr.rectangle(0, 0, 1, 1)
+        cr.stroke()
+
+        self.surface.write_to_png(filename + '.png')
+        cr.show_page()
+        self.surface.finish()
+
+class SetSourceRGBA(Diagram):
+    def draw_dest(self, cr):
+        cr.set_source_rgb(0, 0, 0)         #rgba
+        cr.move_to(0, 0)                   #rgba
+        cr.line_to(1, 1)                   #rgba
+        cr.move_to(1, 0)                   #rgba
+        cr.line_to(0, 1)                   #rgba
+        cr.set_line_width(0.2)             #rgba
+        cr.stroke()                        #rgba
+                                           #rgba
+        cr.rectangle(0, 0, 0.5, 0.5)       #rgba
+        cr.set_source_rgba(1, 0, 0, 0.80)  #rgba
+        cr.fill()                          #rgba
+                                           #rgba
+        cr.rectangle(0, 0.5, 0.5, 0.5)     #rgba
+        cr.set_source_rgba(0, 1, 0, 0.60)  #rgba
+        cr.fill()                          #rgba
+                                           #rgba
+        cr.rectangle(0.5, 0, 0.5, 0.5)     #rgba
+        cr.set_source_rgba(0, 0, 1, 0.40)  #rgba
+        cr.fill()                          #rgba
+
+class SetSourceGradient(Diagram):
+    def draw_dest(self, cr):
+        radial = cairo.RadialGradient(0.25, 0.25, 0.1,  0.5, 0.5, 0.5) 
#gradient
+        radial.add_color_stop_rgb(0,  1.0, 0.8, 0.8)                   
#gradient
+        radial.add_color_stop_rgb(1,  0.9, 0.0, 0.0)                   
#gradient
+                                                                       
#gradient
+        for i in range(1, 10):                                         
#gradient
+            for j in range(1, 10):                                     
#gradient
+                cr.rectangle(i/10.0 - 0.04, j/10.0 - 0.04, 0.08, 0.08) 
#gradient
+        cr.set_source(radial)                                          
#gradient
+        cr.fill()                                                      
#gradient
+                                                                       
#gradient
+        linear = cairo.LinearGradient(0.25, 0.35, 0.75, 0.65)          
#gradient
+        linear.add_color_stop_rgba(0.00,  1, 1, 1, 0)                  
#gradient
+        linear.add_color_stop_rgba(0.25,  0, 1, 0, 0.5)                
#gradient
+        linear.add_color_stop_rgba(0.50,  1, 1, 1, 0)                  
#gradient
+        linear.add_color_stop_rgba(0.75,  0, 0, 1, 0.5)                
#gradient
+        linear.add_color_stop_rgba(1.00,  1, 1, 1, 0)                  
#gradient
+                                                                       
#gradient
+        cr.rectangle(0.0, 0.0, 1, 1)                                   
#gradient
+        cr.set_source(linear)                                          
#gradient
+        cr.fill()                                                      
#gradient
+
+class PathDiagram(Diagram):
+    def draw_dest(self, cr):
+        self.draw_dest_path(cr)
+
+        path = list(cr.copy_path_flat())
+
+        cr.set_line_width(max(cr.device_to_user_distance(3, 3)))
+        cr.set_source_rgb(0, 0.6, 0)
+        cr.stroke()
+
+        if len(path) and path[-1][0] != cairo.PATH_CLOSE_PATH:
+            x, y = path[0][1]
+            cr.arc(x, y, max(cr.device_to_user_distance(5, 5)), 0, 2*pi)
+            cr.set_source_rgba(0.0, 0.6, 0.0, 0.5)
+            cr.fill()
+
+            x, y = path[-1][1]
+            cr.arc(x, y, max(cr.device_to_user_distance(5, 5)), 0, 2*pi)
+            cr.set_source_rgba(0.0, 0.0, 0.75, 0.5)
+            cr.fill()
+
+class PathDiagramMoveTo(PathDiagram):
+    def draw_dest_path(self, cr):
+        cr.move_to(0.25, 0.25)                     #moveto
+
+class PathDiagramLineTo(PathDiagramMoveTo):
+    def draw_dest_path(self, cr):
+        PathDiagramMoveTo.draw_dest_path(self, cr)
+        cr.line_to(0.5, 0.375)                     #lineto
+        cr.rel_line_to(0.25, -0.125)               #lineto
+
+class PathDiagramArcTo(PathDiagramLineTo):
+    def draw_dest_path(self, cr):
+        PathDiagramLineTo.draw_dest_path(self, cr)
+        cr.arc(0.5, 0.5, 0.25 * sqrt(2), -0.25 * pi, 0.25 * pi) #arc
+
+class PathDiagramCurveTo(PathDiagramArcTo):
+    def draw_dest_path(self, cr):
+        if type(self) == PathDiagramCurveTo:
+            cr.save()
+            for x, y in ((0.5, 0.625), (0.5, 0.875)):
+                cr.new_sub_path()
+                cr.arc(x, y, max(cr.device_to_user_distance(3, 3)), 0, 2*pi)
+                cr.set_source_rgba(0.5, 0, 0, 0.5)
+                cr.fill()
+            for (x, y, w, h) in ((0.25, 0.75, 0.25, 0.125),
+                    (0.75, 0.75, -0.25, -0.125)):
+                cr.move_to(x, y)
+                cr.rel_line_to(w, h)
+                cr.set_line_width(max(cr.device_to_user_distance(2, 2)))
+                cr.set_source_rgba(0.5, 0, 0, 0.25)
+                cr.stroke()
+            cr.restore()
+        PathDiagramArcTo.draw_dest_path(self, cr)
+        cr.rel_curve_to(-0.25, -0.125, -0.25, 0.125, -0.5, 0)  #curveto
+
+class PathDiagramClose(PathDiagramCurveTo):
+    def draw_dest_path(self, cr):
+        PathDiagramCurveTo.draw_dest_path(self, cr)
+        cr.close_path()                                        #closepath
+
+class TextExtents(Diagram):
+    def draw_dest(self, cr):
+        text = 'joy'
+        cr.select_font_face('Georgia', cairo.FONT_SLANT_NORMAL, 
cairo.FONT_WEIGHT_BOLD)
+        cr.set_font_size(0.5)
+        px = max(cr.device_to_user_distance(1, 1))
+        fascent, fdescent, fheight, fxadvance, fyadvance = cr.font_extents()
+        xbearing, ybearing, width, height, xadvance, yadvance = \
+                cr.text_extents(text)
+        x = 0.5 - xbearing - width / 2
+        y = 0.5 - fdescent + fheight / 2
+
+        # baseline, descent, ascent, height
+        cr.set_line_width(4 * px)
+        cr.set_dash([9 * px], 0)
+        cr.set_source_rgba(0, 0.6, 0, 0.5)
+        cr.move_to(x + xbearing, y)
+        cr.rel_line_to(width, 0)
+        cr.move_to(x + xbearing, y + fdescent)
+        cr.rel_line_to(width, 0)
+        cr.move_to(x + xbearing, y - fascent)
+        cr.rel_line_to(width, 0)
+        cr.move_to(x + xbearing, y - fheight)
+        cr.rel_line_to(width, 0)
+        cr.stroke()
+
+        # extents: width & height
+        cr.set_source_rgba(0, 0, 0.75, 0.5)
+        cr.set_line_width(1 * px)
+        cr.set_dash([3 * px], 0)
+        cr.rectangle(x + xbearing, y + ybearing, width, height)
+        cr.stroke()
+
+        # text
+        cr.move_to(x, y)
+        cr.set_source_rgb(0, 0, 0)
+        cr.show_text(text)
+
+        # bearing
+        cr.set_dash([], 0)
+        cr.set_line_width(2 * px)
+        cr.set_source_rgba(0, 0, 0.75, 0.5)
+        cr.move_to(x, y)
+        cr.rel_line_to(xbearing, ybearing)
+        cr.stroke()
+        print xbearing, ybearing
+
+        # text's advance
+        cr.set_source_rgba(0, 0, 0.75, 0.5)
+        cr.arc(x + xadvance, y + yadvance, 5 * px, 0, 2 * pi)
+        cr.fill()
+
+        # reference point
+        cr.arc(x, y, 5 * px, 0, 2 * pi)
+        cr.set_source_rgba(0.75, 0, 0, 0.5)
+        cr.fill()
+
+
+if __name__ == '__main__':
+    size = 600
+    # SetSourceRGBA('setsourcergba', size, size)
+    # SetSourceGradient('setsourcegradient', size, size)
+    # PathDiagramMoveTo('path-moveto', size, size)
+    # PathDiagramLineTo('path-lineto', size, size)
+    # PathDiagramArcTo('path-arcto', size, size)
+    # PathDiagramCurveTo('path-curveto', size, size)
+    # PathDiagramClose('path-close', size, size)
+    TextExtents('textextents', size, size)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/examples/rotate.py 
new/pycha-0.8.1/examples/rotate.py
--- old/pycha-0.7.0/examples/rotate.py  1970-01-01 01:00:00.000000000 +0100
+++ new/pycha-0.8.1/examples/rotate.py  2010-05-30 10:31:29.000000000 +0200
@@ -0,0 +1,28 @@
+import math
+
+import cairo
+
+
+surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 500, 500)
+
+cx = cairo.Context(surface)
+cx.set_source_rgb(1, 1, 1)
+cx.paint()
+
+cx.set_source_rgb(0, 0, 0)
+
+label = 'rotate'
+x, y = 200, 300
+px = max(cx.device_to_user_distance(1, 1))
+cx.arc(x, y, 2 * px, 0, 2 * math.pi)
+
+xb, yb, width, height, xa, ya = cx.text_extents(label)
+
+cx.translate(x, y)
+cx.rotate(math.radians(60))
+cx.move_to(-xb, -yb)
+cx.show_text(label)
+cx.rectangle(0, 0, width, height)
+cx.stroke()
+
+surface.write_to_png('rotate.png')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha/__init__.py 
new/pycha-0.8.1/pycha/__init__.py
--- old/pycha-0.7.0/pycha/__init__.py   2013-04-07 20:49:51.000000000 +0200
+++ new/pycha-0.8.1/pycha/__init__.py   2019-11-18 07:45:48.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright(c) 2007-2010 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
+# Copyright(c) 2007-2012 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -15,4 +15,4 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with PyCha.  If not, see <http://www.gnu.org/licenses/>.
 
-version = "0.7.0"
+version = "0.8.1"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha/bar.py new/pycha-0.8.1/pycha/bar.py
--- old/pycha-0.7.0/pycha/bar.py        2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/pycha/bar.py        2019-11-18 07:21:48.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright(c) 2007-2010 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
+# Copyright(c) 2007-2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -43,7 +43,7 @@
         if len(uniqx) == 1:
             self.minxdelta = 1.0
         else:
-            self.minxdelta = min([abs(uniqx[j] - uniqx[j-1])
+            self.minxdelta = min([abs(uniqx[j] - uniqx[j - 1])
                                   for j in range(1, len(uniqx))])
 
         k = self.minxdelta * self.xscale
@@ -70,7 +70,7 @@
             h = self.layout.chart.h * bar.h
 
             if (w < 1 or h < 1) and self.options.yvals.skipSmallValues:
-                return # don't draw when the bar is too small
+                return  # don't draw when the bar is too small
 
             if self.options.stroke.shadow:
                 cx.set_source_rgba(0, 0, 0, 0.15)
@@ -129,13 +129,11 @@
         for i, (name, store) in enumerate(self.datasets):
             for item in store:
                 if len(item) == 3:
-                    xval, yval, yerr = item
+                    xval, yval, _ = item
                 else:
                     xval, yval = item
-                    yerr = 0.0
 
-                x = (((xval - self.minxval) * self.xscale)
-                    + self.barMargin + (i * self.barWidthForSet))
+                x = (((xval - self.minxval) * self.xscale) + self.barMargin + 
(i * self.barWidthForSet))
                 w = self.barWidthForSet
                 h = abs(yval) * self.yscale
                 if yval > 0:
@@ -154,7 +152,7 @@
         self.xticks = [(tick[0] + offset, tick[1]) for tick in self.xticks]
 
     def _getShadowRectangle(self, x, y, w, h):
-        return (x-2, y-2, w+4, h+2)
+        return (x - 2, y - 2, w + 4, h + 2)
 
     def _renderYVal(self, cx, label, labelW, labelH, barX, barY, barW, barH):
         x = barX + (barW / 2.0) - (labelW / 2.0)
@@ -207,8 +205,7 @@
                     xval, yval = item
                     yerr = 0.0
 
-                y = (((xval - self.minxval) * self.xscale)
-                     + self.barMargin + (i * self.barWidthForSet))
+                y = (((xval - self.minxval) * self.xscale) + self.barMargin + 
(i * self.barWidthForSet))
                 h = self.barWidthForSet
                 w = abs(yval) * self.yscale
                 if yval > 0:
@@ -238,7 +235,7 @@
                 self._renderLine(cx, tick, False)
 
     def _getShadowRectangle(self, x, y, w, h):
-        return (x, y-2, w+2, h+4)
+        return (x, y - 2, w + 2, h + 4)
 
     def _renderXAxisLabel(self, cx, labelText):
         labelText = self.options.axis.x.label
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha/chart.py 
new/pycha-0.8.1/pycha/chart.py
--- old/pycha-0.7.0/pycha/chart.py      2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/pycha/chart.py      2019-11-18 07:16:36.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright(c) 2007-2010 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
+# Copyright(c) 2007-2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -16,12 +16,13 @@
 # along with PyCha.  If not, see <http://www.gnu.org/licenses/>.
 
 import copy
-import inspect
 import math
 
-import cairo
+import cairocffi as cairo
+from six.moves import reduce
 
 from pycha.color import ColorScheme, hex2rgb, DEFAULT_COLOR
+from pycha.compat import getfullargspec
 from pycha.utils import safe_unicode
 
 
@@ -138,7 +139,7 @@
 
         # Remove invalid args before calling the constructor
         kwargs = dict(self.options.colorScheme.args)
-        validArgs = inspect.getargspec(colorSchemeClass.__init__)[0]
+        validArgs = getfullargspec(colorSchemeClass.__init__).args
         kwargs = dict([(k, v) for k, v in kwargs.items() if k in validArgs])
         self.colorScheme = colorSchemeClass(keys, **kwargs)
 
@@ -169,7 +170,7 @@
         if x_range_is_defined:
             self.minxval, self.maxxval = self.options.axis.x.range
         else:
-            xdata = [pair[0] for pair in reduce(lambda a, b: a+b, stores)]
+            xdata = [pair[0] for pair in reduce(lambda a, b: a + b, stores)]
             self.minxval = float(min(xdata))
             self.maxxval = float(max(xdata))
             if self.minxval * self.maxxval > 0 and self.minxval > 0:
@@ -185,7 +186,7 @@
         if y_range_is_defined:
             self.minyval, self.maxyval = self.options.axis.y.range
         else:
-            ydata = [pair[1] for pair in reduce(lambda a, b: a+b, stores)]
+            ydata = [pair[1] for pair in reduce(lambda a, b: a + b, stores)]
             self.minyval = float(min(ydata))
             self.maxyval = float(max(ydata))
             if self.minyval * self.maxyval > 0 and self.minyval > 0:
@@ -197,7 +198,7 @@
         else:
             self.yscale = 1.0 / self.yrange
 
-        if self.minyval * self.maxyval < 0: # different signs
+        if self.minyval * self.maxyval < 0:  # different signs
             self.origin = abs(self.minyval) * self.yscale
         else:
             self.origin = 0.0
@@ -311,11 +312,11 @@
         if self.options.background.chartColor:
             cx.set_source_rgb(*hex2rgb(self.options.background.chartColor))
             surface_width, surface_height = self.getSurfaceSize()
-            cx.rectangle(self.options.padding.left, self.options.padding.top,
-                         surface_width - (self.options.padding.left
-                                          + self.options.padding.right),
-                         surface_height - (self.options.padding.top
-                                           + self.options.padding.bottom))
+            cx.rectangle(
+                self.options.padding.left, self.options.padding.top,
+                surface_width - (self.options.padding.left + 
self.options.padding.right),
+                surface_height - (self.options.padding.top + 
self.options.padding.bottom)
+            )
             cx.fill()
 
         if self.options.background.lineColor:
@@ -404,8 +405,10 @@
         x = self.layout.y_ticks.x + self.layout.y_ticks.w
         y = self.layout.y_ticks.y + tick[0] * self.layout.y_ticks.h
 
-        text_position = ((self.layout.y_tick_labels.x
-                          + self.layout.y_tick_labels.w / 2.0), y)
+        text_position = (
+            (self.layout.y_tick_labels.x + self.layout.y_tick_labels.w / 2.0),
+            y
+        )
 
         return self._renderTick(cx, tick,
                                 x, y,
@@ -419,8 +422,10 @@
         x = self.layout.x_ticks.x + tick[0] * self.layout.x_ticks.w
         y = self.layout.x_ticks.y
 
-        text_position = (x, (self.layout.x_tick_labels.y
-                             + self.layout.x_tick_labels.h / 2.0))
+        text_position = (
+            x,
+            (self.layout.x_tick_labels.y + self.layout.x_tick_labels.h / 2.0)
+        )
 
         return self._renderTick(cx, tick,
                                 x, y,
@@ -531,9 +536,7 @@
             extents = cx.text_extents(title)
             title_width = extents[2]
 
-            x = (self.layout.title.x
-                 + self.layout.title.w / 2.0
-                 - title_width / 2.0)
+            x = (self.layout.title.x + self.layout.title.w / 2.0 - title_width 
/ 2.0)
             y = self.layout.title.y - extents[1]
 
             cx.move_to(x, y)
@@ -568,13 +571,13 @@
         # Compute legend position
         legend = self.options.legend
         if legend.position.right is not None:
-            legend.position.left = (surface_width
-                                    - legend.position.right
-                                    - width)
+            legend.position.left = (
+                surface_width - legend.position.right - width
+            )
         if legend.position.bottom is not None:
-            legend.position.top = (surface_height
-                                   - legend.position.bottom
-                                   - height)
+            legend.position.top = (
+                surface_height - legend.position.bottom - height
+            )
 
         # Draw the legend
         cx.save()
@@ -621,7 +624,7 @@
 
     def __str__(self):
         msg = "<pycha.chart.Area@(%.2f, %.2f) %.2f x %.2f>"
-        return  msg % (self.x, self.y, self.w, self.h)
+        return msg % (self.x, self.y, self.w, self.h)
 
 
 def get_text_extents(cx, text, font, font_size, encoding):
@@ -651,15 +654,15 @@
         self.chart = Area()
 
         self._areas = (
-            (self.title, (1, 126/255.0, 0)), # orange
-            (self.y_label, (41/255.0, 91/255.0, 41/255.0)), # grey
-            (self.x_label, (41/255.0, 91/255.0, 41/255.0)), # grey
-            (self.y_tick_labels, (0, 115/255.0, 0)), # green
-            (self.x_tick_labels, (0, 115/255.0, 0)), # green
-            (self.y_ticks, (229/255.0, 241/255.0, 18/255.0)), # yellow
-            (self.x_ticks, (229/255.0, 241/255.0, 18/255.0)), # yellow
-            (self.chart, (75/255.0, 75/255.0, 1.0)), # blue
-            )
+            (self.title, (1, 126 / 255.0, 0)),  # orange
+            (self.y_label, (41 / 255.0, 91 / 255.0, 41 / 255.0)),  # grey
+            (self.x_label, (41 / 255.0, 91 / 255.0, 41 / 255.0)),  # grey
+            (self.y_tick_labels, (0, 115 / 255.0, 0)),  # green
+            (self.x_tick_labels, (0, 115 / 255.0, 0)),  # green
+            (self.y_ticks, (229 / 255.0, 241 / 255.0, 18 / 255.0)),  # yellow
+            (self.x_ticks, (229 / 255.0, 241 / 255.0, 18 / 255.0)),  # yellow
+            (self.chart, (75 / 255.0, 75 / 255.0, 1.0)),  # blue
+        )
 
     def update(self, cx, options, width, height, xticks, yticks):
         self.title.x = options.padding.left
@@ -691,23 +694,16 @@
         self.y_label.x = options.padding.left
         self.y_label.y = options.padding.top + self.title.h
         self.y_label.w = y_axis_label_width
-        self.y_label.h = height - (options.padding.bottom
-                                   + options.padding.top
-                                   + x_axis_label_height
-                                   + x_axis_tick_labels_height
-                                   + options.axis.tickSize
-                                   + self.title.h)
-        self.x_label.x = (options.padding.left
-                          + y_axis_label_width
-                          + y_axis_tick_labels_width
-                          + options.axis.tickSize)
-        self.x_label.y = height - (options.padding.bottom
-                                   + x_axis_label_height)
-        self.x_label.w = width - (options.padding.left
-                                  + options.padding.right
-                                  + options.axis.tickSize
-                                  + y_axis_label_width
-                                  + y_axis_tick_labels_width)
+        self.y_label.h = height - (
+            options.padding.bottom + options.padding.top + x_axis_label_height 
+ x_axis_tick_labels_height + options.axis.tickSize + self.title.h
+        )
+        self.x_label.x = (
+            options.padding.left + y_axis_label_width + 
y_axis_tick_labels_width + options.axis.tickSize
+        )
+        self.x_label.y = height - (options.padding.bottom + 
x_axis_label_height)
+        self.x_label.w = width - (
+            options.padding.left + options.padding.right + 
options.axis.tickSize + y_axis_label_width + y_axis_tick_labels_width
+        )
         self.x_label.h = x_axis_label_height
 
         self.y_tick_labels.x = self.y_label.x + self.y_label.w
@@ -756,21 +752,21 @@
 
         max_width = max_height = 0.0
         if not axis.hide:
-            extents = [cx.text_extents(safe_unicode(
-                        tick[1], options.encoding,
-                        ))[2:4] # get width and height as a tuple
-                       for tick in ticks]
+            extents = [
+                cx.text_extents(safe_unicode(tick[1], options.encoding))[2:4]  
# get width and height as a tuple
+                for tick in ticks
+            ]
             if extents:
                 widths, heights = zip(*extents)
                 max_width, max_height = max(widths), max(heights)
                 if axis.rotate:
                     radians = math.radians(axis.rotate)
-                    sin = math.sin(radians)
-                    cos = math.cos(radians)
+                    sin = abs(math.sin(radians))
+                    cos = abs(math.cos(radians))
                     max_width, max_height = (
                         max_width * cos + max_height * sin,
                         max_width * sin + max_height * cos,
-                        )
+                    )
         cx.restore()
         return max_width, max_height
 
@@ -873,7 +869,7 @@
         args=Option(
             initialColor=DEFAULT_COLOR,
             colors=None,
-            ),
+        ),
     ),
     title=None,
     titleColor='#000000',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha/color.py 
new/pycha-0.8.1/pycha/color.py
--- old/pycha-0.7.0/pycha/color.py      2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/pycha/color.py      2019-11-18 07:17:27.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright(c) 2007-2010 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
+# Copyright(c) 2007-2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #              2009 by Yaco S.L. <l...@yaco.es>
 #
 # This file is part of PyCha.
@@ -18,6 +18,8 @@
 
 import math
 
+import six
+
 from pycha.utils import clamp
 
 
@@ -36,9 +38,9 @@
         return hexstring
 
     top = float(int(digits * 'f', 16))
-    r = int(hexstring[1:digits+1], 16)
-    g = int(hexstring[digits+1:digits*2+1], 16)
-    b = int(hexstring[digits*2+1:digits*3+1], 16)
+    r = int(hexstring[1:digits + 1], 16)
+    g = int(hexstring[digits + 1:digits * 2 + 1], 16)
+    b = int(hexstring[digits * 2 + 1:digits * 3 + 1], 16)
     return r / top, g / top, b / top
 
 
@@ -111,7 +113,7 @@
     grey='#444444',
     black='#000000',
     darkcyan='#305755',
-    )
+)
 
 
 class ColorSchemeMetaclass(type):
@@ -123,11 +125,10 @@
         return klass
 
 
-class ColorScheme(dict):
+class ColorScheme(six.with_metaclass(ColorSchemeMetaclass, dict)):
     """A color scheme is a dictionary where the keys match the keys
     constructor argument and the values are colors"""
 
-    __metaclass__ = ColorSchemeMetaclass
     __registry__ = {}
 
     def __init__(self, keys):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha/compat.py 
new/pycha-0.8.1/pycha/compat.py
--- old/pycha-0.7.0/pycha/compat.py     1970-01-01 01:00:00.000000000 +0100
+++ new/pycha-0.8.1/pycha/compat.py     2019-11-18 06:56:01.000000000 +0100
@@ -0,0 +1,27 @@
+# Copyright(c) 2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
+#
+# This file is part of PyCha.
+#
+# PyCha 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.
+#
+# PyCha 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 PyCha.  If not, see <http://www.gnu.org/licenses/>.
+
+import sys
+
+# True if we are running on Python 3.
+PY3 = sys.version_info[0] == 3
+
+
+if PY3:  # pragma: no cover
+    from inspect import getfullargspec  # noqa
+else:  # pragma: no cover
+    from inspect import getargspec as getfullargspec  # noqa
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha/line.py 
new/pycha-0.8.1/pycha/line.py
--- old/pycha-0.7.0/pycha/line.py       2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/pycha/line.py       2019-11-18 07:11:13.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright(c) 2007-2010 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
+# Copyright(c) 2007-2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -48,7 +48,7 @@
             lastX = None
             if self.options.shouldFill:
                 # Go to the (0,0) coordinate to start drawing the area
-                #cx.move_to(self.layout.chart.x,
+                # cx.move_to(self.layout.chart.x,
                 #           self.layout.chart.y + self.layout.chart.h)
                 offset = (1.0 - self.origin) * self.layout.chart.h
                 cx.move_to(self.layout.chart.x, self.layout.chart.y + offset)
@@ -57,33 +57,30 @@
                 if point.name == storeName:
                     if not self.options.shouldFill and firstPoint:
                         # starts the first point of the line
-                        cx.move_to(point.x * self.layout.chart.w
-                                   + self.layout.chart.x,
-                                   point.y * self.layout.chart.h
-                                   + self.layout.chart.y)
+                        cx.move_to(
+                            point.x * self.layout.chart.w + 
self.layout.chart.x,
+                            point.y * self.layout.chart.h + self.layout.chart.y
+                        )
                         firstPoint = False
                         continue
-                    cx.line_to(point.x * self.layout.chart.w
-                               + self.layout.chart.x,
-                               point.y * self.layout.chart.h
-                               + self.layout.chart.y)
+                    cx.line_to(
+                        point.x * self.layout.chart.w + self.layout.chart.x,
+                        point.y * self.layout.chart.h + self.layout.chart.y
+                    )
                     # we remember the last X coordinate to close the area
                     # properly. See bug #4
                     lastX = point.x
 
             if self.options.shouldFill:
                 # Close the path to the start point
-                y = ((1.0 - self.origin) * self.layout.chart.h
-                     + self.layout.chart.y)
-                cx.line_to(lastX * self.layout.chart.w
-                           + self.layout.chart.x, y)
+                y = ((1.0 - self.origin) * self.layout.chart.h + 
self.layout.chart.y)
+                cx.line_to(lastX * self.layout.chart.w + self.layout.chart.x, 
y)
                 cx.line_to(self.layout.chart.x, y)
                 cx.close_path()
             else:
                 cx.set_source_rgb(*self.colorScheme[storeName])
                 cx.stroke()
 
-
         cx.save()
         cx.set_line_width(self.options.stroke.width)
         if self.options.shouldFill:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha/pie.py new/pycha-0.8.1/pycha/pie.py
--- old/pycha-0.7.0/pycha/pie.py        2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/pycha/pie.py        2019-11-18 07:19:36.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright(c) 2007-2010 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
+# Copyright(c) 2007-2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -17,7 +17,7 @@
 
 import math
 
-import cairo
+import cairocffi as cairo
 
 from pycha.chart import Chart, Option, Layout, Area, get_text_extents
 from pycha.color import hex2rgb
@@ -208,7 +208,7 @@
         self._areas = (
             (self.title, (1, 126 / 255.0, 0)),  # orange
             (self.chart, (75 / 255.0, 75 / 255.0, 1.0)),  # blue
-            )
+        )
 
         self._lines = []
 
@@ -227,8 +227,9 @@
         self.chart.x = self.title.x
         self.chart.y = self.title.y + self.title.h
         self.chart.w = self.title.w
-        self.chart.h = height - self.title.h - (options.padding.top
-                                                + options.padding.bottom)
+        self.chart.h = height - self.title.h - (
+            options.padding.top + options.padding.bottom
+        )
 
         centerx = self.chart.x + self.chart.w * 0.5
         centery = self.chart.y + self.chart.h * 0.5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha/polygonal.py 
new/pycha-0.8.1/pycha/polygonal.py
--- old/pycha-0.7.0/pycha/polygonal.py  2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/pycha/polygonal.py  2019-11-18 07:23:56.000000000 +0100
@@ -1,4 +1,5 @@
 # Copyright(c) 2011 by Roberto Garcia Carvajal <rober...@gmail.com>
+#              2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -64,12 +65,8 @@
             count = len(self.xticks)
             for index, tick in enumerate(self.xticks):
                 ang = math.pi / 2 - index * 2 * math.pi / count
-                x = (self.layout.chart.x + self.layout.chart.w / 2
-                     - math.cos(ang)
-                     * min(self.layout.chart.w / 2, self.layout.chart.h / 2))
-                y = (self.layout.chart.y + self.layout.chart.h / 2
-                     - math.sin(ang)
-                     * min(self.layout.chart.w / 2, self.layout.chart.h / 2))
+                x = (self.layout.chart.x + self.layout.chart.w / 2 - 
math.cos(ang) * min(self.layout.chart.w / 2, self.layout.chart.h / 2))
+                y = (self.layout.chart.y + self.layout.chart.h / 2 - 
math.sin(ang) * min(self.layout.chart.w / 2, self.layout.chart.h / 2))
                 if init is None:
                     cx.move_to(x, y)
                     init = (x, y)
@@ -95,10 +92,8 @@
         count = len(self.xticks)
         for index, tick in enumerate(self.xticks):
             ang = math.pi / 2 - index * 2 * math.pi / count
-            x = (self.layout.chart.x + self.layout.chart.w / 2
-                 - math.cos(ang) * rad)
-            y = (self.layout.chart.y + self.layout.chart.h / 2
-                 - math.sin(ang) * rad)
+            x = (self.layout.chart.x + self.layout.chart.w / 2 - math.cos(ang) 
* rad)
+            y = (self.layout.chart.y + self.layout.chart.h / 2 - math.sin(ang) 
* rad)
             if init is None:
                 cx.move_to(x, y)
                 init = (x, y)
@@ -166,11 +161,10 @@
 
         if self.options.axis.y.rotate:
             radians = math.radians(self.options.axis.y.rotate)
-            cx.move_to(x - self.options.axis.tickSize
-                       - (labelWidth * math.cos(radians))
-                       - 4,
-                       y + (labelWidth * math.sin(radians))
-                       + labelHeight / (2.0 / math.cos(radians)))
+            cx.move_to(
+                x - self.options.axis.tickSize - (labelWidth * 
math.cos(radians)) - 4,
+                y + (labelWidth * math.sin(radians)) + labelHeight / (2.0 / 
math.cos(radians))
+            )
             cx.rotate(-radians)
             cx.show_text(label)
             cx.rotate(radians)  # this is probably faster than a save/restore
@@ -263,10 +257,10 @@
 
         if self.options.axis.x.rotate:
             radians = math.radians(self.options.axis.x.rotate)
-            cx.move_to(x - (labelHeight * math.cos(radians)),
-                       y + self.options.axis.tickSize
-                       + (labelHeight * math.cos(radians))
-                       + 4.0)
+            cx.move_to(
+                x - (labelHeight * math.cos(radians)),
+                y + self.options.axis.tickSize + (labelHeight * 
math.cos(radians)) + 4.0
+            )
             cx.rotate(radians)
             cx.show_text(label)
             cx.rotate(-radians)
@@ -327,13 +321,12 @@
                         continue
                     cx.line_to(x, y)
 
-            if not firstPointCoord is None:
+            if firstPointCoord is not None:
                 cx.line_to(firstPointCoord[0], firstPointCoord[1])
 
             if self.options.shouldFill:
                 # Close the path to the start point
-                y = ((1.0 - self.origin)
-                     * self.layout.chart.h + self.layout.chart.y)
+                y = ((1.0 - self.origin) * self.layout.chart.h + 
self.layout.chart.y)
             else:
                 cx.set_source_rgb(*self.colorScheme[storeName])
                 cx.stroke()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha/radial.py 
new/pycha-0.8.1/pycha/radial.py
--- old/pycha-0.7.0/pycha/radial.py     2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/pycha/radial.py     2019-11-18 07:09:58.000000000 +0100
@@ -1,4 +1,5 @@
 # Copyright(c) 2011 by Roberto Garcia Carvajal <rober...@gmail.com>
+#              2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -139,11 +140,10 @@
 
         if self.options.axis.y.rotate:
             radians = math.radians(self.options.axis.y.rotate)
-            cx.move_to(x - self.options.axis.tickSize
-                       - (labelWidth * math.cos(radians))
-                       - 4,
-                       y + (labelWidth * math.sin(radians))
-                       + labelHeight / (2.0 / math.cos(radians)))
+            cx.move_to(
+                x - self.options.axis.tickSize - (labelWidth * 
math.cos(radians)) - 4,
+                y + (labelWidth * math.sin(radians)) + labelHeight / (2.0 / 
math.cos(radians))
+            )
             cx.rotate(-radians)
             cx.show_text(label)
             cx.rotate(radians)  # this is probably faster than a save/restore
@@ -236,10 +236,10 @@
 
         if self.options.axis.x.rotate:
             radians = math.radians(self.options.axis.x.rotate)
-            cx.move_to(x - (labelHeight * math.cos(radians)),
-                       y + self.options.axis.tickSize
-                       + (labelHeight * math.cos(radians))
-                       + 4.0)
+            cx.move_to(
+                x - (labelHeight * math.cos(radians)),
+                y + self.options.axis.tickSize + (labelHeight * 
math.cos(radians)) + 4.0
+            )
             cx.rotate(radians)
             cx.show_text(label)
             cx.rotate(-radians)
@@ -301,13 +301,12 @@
                         continue
                     cx.line_to(x, y)
 
-            if not firstPointCoord is None:
+            if firstPointCoord is not None:
                 cx.line_to(firstPointCoord[0], firstPointCoord[1])
 
             if self.options.shouldFill:
                 # Close the path to the start point
-                y = ((1.0 - self.origin)
-                     * self.layout.chart.h + self.layout.chart.y)
+                y = ((1.0 - self.origin) * self.layout.chart.h + 
self.layout.chart.y)
             else:
                 cx.set_source_rgb(*self.colorScheme[storeName])
                 cx.stroke()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha/ring.py 
new/pycha-0.8.1/pycha/ring.py
--- old/pycha-0.7.0/pycha/ring.py       2013-04-07 20:23:53.000000000 +0200
+++ new/pycha-0.8.1/pycha/ring.py       2019-11-18 07:19:07.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright(c) 2007-2010 by Roberto Garcia Carvajal <rober...@gmail.com>
+# Copyright(c) 2007-2019 by Roberto Garcia Carvajal <rober...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -38,18 +38,18 @@
 
     def _updateChart(self):
         """Evaluates measures for pie charts"""
-        self.rings = [i
-                      for i in set(
-                      [data[0]
-                        for dataset in self.datasets
-                        for data in dataset[1]])]
+        self.rings = [
+            i
+            for i in set([data[0] for dataset in self.datasets for data in 
dataset[1]])
+        ]
 
         self.nrings = len(self.rings)
 
         self.dataset_names = [i for i in
                               set([data[0] for data in self.datasets])]
-        self.dataset_order = {val: i
-            for i, val in enumerate(self.dataset_names)}
+        self.dataset_order = {
+            val: i for i, val in enumerate(self.dataset_names)
+        }
 
         slices = {i: list() for i in self.rings}
 
@@ -74,8 +74,8 @@
                     angle += fraction
                     fraction = slice['value'] / s[i]
                     self.slices[i].append(
-                        Slice(slice['name'], fraction, i, slice['value'],
-                        angle))
+                        Slice(slice['name'], fraction, i, slice['value'], 
angle)
+                    )
 
     def _updateTicks(self):
         """Evaluates pie ticks"""
@@ -84,7 +84,7 @@
         if self.options.axis.x.ticks:
             ticks = [tick['v'] for tick in self.options.axis.x.ticks]
             if frozenset(lookups) != frozenset(ticks):
-                #TODO: Is there better option than ValueError?
+                # TODO: Is there better option than ValueError?
                 raise ValueError(u"Incompatible ticks")
             for tick in self.options.axis.x.ticks:
                 if not isinstance(tick, Option):
@@ -248,7 +248,7 @@
         self._areas = (
             (self.title, (1, 126 / 255.0, 0)),  # orange
             (self.chart, (75 / 255.0, 75 / 255.0, 1.0)),  # blue
-            )
+        )
 
         self._lines = []
 
@@ -265,8 +265,9 @@
         self.chart.x = self.title.x
         self.chart.y = self.title.y + self.title.h
         self.chart.w = self.title.w
-        self.chart.h = height - self.title.h - (options.padding.top
-                                                + options.padding.bottom)
+        self.chart.h = height - self.title.h - (
+            options.padding.top + options.padding.bottom
+        )
 
         self.radius = min(self.chart.w / 2.0, self.chart.h / 2.0)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha/stackedbar.py 
new/pycha-0.8.1/pycha/stackedbar.py
--- old/pycha-0.7.0/pycha/stackedbar.py 2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/pycha/stackedbar.py 2019-11-18 07:20:21.000000000 +0100
@@ -1,4 +1,5 @@
 # Copyright(c) 2009 by Yaco S.L. <l...@yaco.es>
+#              2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -15,6 +16,8 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with PyCha.  If not, see <http://www.gnu.org/licenses/>.
 
+from six.moves import reduce, xrange
+
 from pycha.bar import BarChart, VerticalBarChart, HorizontalBarChart, Rect
 from pycha.chart import uniqueIndices
 
@@ -35,12 +38,12 @@
             # Fix the yscale as we accumulate the y values
             stores = self._getDatasetsValues()
             n_stores = len(stores)
-            flat_y = [pair[1] for pair in reduce(lambda a, b: a+b, stores)]
-            store_size = len(flat_y) / n_stores
+            flat_y = [pair[1] for pair in reduce(lambda a, b: a + b, stores)]
+            store_size = len(flat_y) // n_stores
             accum = [sum(flat_y[j]for j in xrange(i,
                                                   i + store_size * n_stores,
                                                   store_size))
-                     for i in range(len(flat_y) / n_stores)]
+                     for i in range(len(flat_y) // n_stores)]
             self.yrange = float(max(accum))
             if self.yrange == 0:
                 self.yscale = 1.0
@@ -55,7 +58,7 @@
         if len(uniqx) == 1:
             self.minxdelta = 1.0
         else:
-            self.minxdelta = min([abs(uniqx[j] - uniqx[j-1])
+            self.minxdelta = min([abs(uniqx[j] - uniqx[j - 1])
                                   for j in range(1, len(uniqx))])
 
         k = self.minxdelta * self.xscale
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha/utils.py 
new/pycha-0.8.1/pycha/utils.py
--- old/pycha-0.7.0/pycha/utils.py      2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/pycha/utils.py      2019-11-14 07:58:27.000000000 +0100
@@ -16,6 +16,11 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with PyCha.  If not, see <http://www.gnu.org/licenses/>.
 
+import six
+
+unicode = six.text_type
+
+
 def clamp(minValue, maxValue, value):
     """Make sure value is between minValue and maxValue"""
     if value < minValue:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha.egg-info/PKG-INFO 
new/pycha-0.8.1/pycha.egg-info/PKG-INFO
--- old/pycha-0.7.0/pycha.egg-info/PKG-INFO     2013-04-07 20:54:46.000000000 
+0200
+++ new/pycha-0.8.1/pycha.egg-info/PKG-INFO     2019-11-18 07:47:15.000000000 
+0100
@@ -1,6 +1,6 @@
-Metadata-Version: 1.0
+Metadata-Version: 2.1
 Name: pycha
-Version: 0.7.0
+Version: 0.8.1
 Summary: A library for making charts with Python
 Home-page: http://bitbucket.org/lgs/pycha/
 Author: Lorenzo Gil Sanchez
@@ -62,6 +62,16 @@
         Changes
         =======
         
+        0.8.1 (2019-11-17)
+        ---------------------
+        - Forgot to update Changelog for 0.8.0
+        
+        0.8.0 (2019-11-17)
+        ---------------------
+        - Add support for Python 3 by encukou
+        - Add support for Tox, Pyflakes, Coverage and Buildbucket pipelines
+        - Remove support for Buildout
+        
         0.7.0 (2012-04-07)
         ------------------
         - Radial Chart by Roberto Garcia Carvajal
@@ -157,3 +167,4 @@
         
 Keywords: chart cairo
 Platform: UNKNOWN
+Provides-Extra: testing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha.egg-info/SOURCES.txt 
new/pycha-0.8.1/pycha.egg-info/SOURCES.txt
--- old/pycha-0.7.0/pycha.egg-info/SOURCES.txt  2013-04-07 20:54:46.000000000 
+0200
+++ new/pycha-0.8.1/pycha.egg-info/SOURCES.txt  2019-11-18 07:47:15.000000000 
+0100
@@ -3,12 +3,14 @@
 COPYING
 MANIFEST.in
 README.txt
+setup.cfg
 setup.py
 chavier/__init__.py
 chavier/app.py
 chavier/dialogs.py
 chavier/gui.py
 examples/barchart.py
+examples/draw.py
 examples/errorbarchart.py
 examples/interval.py
 examples/linechart.py
@@ -16,6 +18,7 @@
 examples/piechart.py
 examples/pychadownloads.py
 examples/ringchart.py
+examples/rotate.py
 examples/scatterchart.py
 examples/stackedbarchart.py
 examples/svg.py
@@ -25,6 +28,7 @@
 pycha/bar.py
 pycha/chart.py
 pycha/color.py
+pycha/compat.py
 pycha/line.py
 pycha/pie.py
 pycha/polygonal.py
@@ -37,6 +41,7 @@
 pycha.egg-info/SOURCES.txt
 pycha.egg-info/dependency_links.txt
 pycha.egg-info/entry_points.txt
+pycha.egg-info/requires.txt
 pycha.egg-info/top_level.txt
 pycha.egg-info/zip-safe
 tests/__init__.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha.egg-info/requires.txt 
new/pycha-0.8.1/pycha.egg-info/requires.txt
--- old/pycha-0.7.0/pycha.egg-info/requires.txt 1970-01-01 01:00:00.000000000 
+0100
+++ new/pycha-0.8.1/pycha.egg-info/requires.txt 2019-11-18 07:47:15.000000000 
+0100
@@ -0,0 +1,9 @@
+six
+cairocffi
+
+[testing]
+coverage
+mccabe
+pep8
+pyflakes
+flake8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/pycha.egg-info/top_level.txt 
new/pycha-0.8.1/pycha.egg-info/top_level.txt
--- old/pycha-0.7.0/pycha.egg-info/top_level.txt        2013-04-07 
20:54:46.000000000 +0200
+++ new/pycha-0.8.1/pycha.egg-info/top_level.txt        2019-11-18 
07:47:15.000000000 +0100
@@ -1,2 +1,2 @@
-pycha
 chavier
+pycha
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/setup.cfg new/pycha-0.8.1/setup.cfg
--- old/pycha-0.7.0/setup.cfg   2013-04-07 20:55:50.000000000 +0200
+++ new/pycha-0.8.1/setup.cfg   2019-11-18 07:47:15.000000000 +0100
@@ -1,5 +1,11 @@
+[aliases]
+testing = develop easy_install pycha[testing]
+
+[flake8]
+ignore = E501
+max-complexity = -1
+
 [egg_info]
 tag_build = 
 tag_date = 0
-tag_svn_revision = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/setup.py new/pycha-0.8.1/setup.py
--- old/pycha-0.7.0/setup.py    2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/setup.py    2019-11-18 07:24:44.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright(c) 2007-2010 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
+# Copyright(c) 2007-2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -20,33 +20,46 @@
 
 from pycha import version
 
+
 def read(*rnames):
     return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
 
+
+base_requirements = [
+    'six',
+    'cairocffi',
+]
+
+testing_requirements = [
+    'coverage',
+    'mccabe',    # required by flake8
+    'pep8',      # required by flake8
+    'pyflakes',  # required by flake8
+    'flake8',
+]
+
+
 setup(
     name="pycha",
     version=version,
     author="Lorenzo Gil Sanchez",
     author_email="lorenzo.gil.sanc...@gmail.com",
     description="A library for making charts with Python",
-    long_description=(
-        read('README.txt')
-        + '\n\n' +
-        read('CHANGES.txt')
-    ),
+    long_description=(read('README.txt') + '\n\n' + read('CHANGES.txt')),
     license="LGPL 3",
     keywords="chart cairo",
     packages=['pycha', 'chavier'],
     url='http://bitbucket.org/lgs/pycha/',
-    # if would be nice if pycairo would have an egg (sigh)
-#    install_requires = [
-#        'pycairo',
-#    ],
+    install_requires=base_requirements,
     zip_safe=True,
     entry_points={
         'gui_scripts': [
             'chavier = chavier.app:main',
         ]
     },
+    tests_require=base_requirements,
+    extras_require={
+        'testing': testing_requirements,
+    },
     test_suite="tests",
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/tests/bar.py new/pycha-0.8.1/tests/bar.py
--- old/pycha-0.7.0/tests/bar.py        2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/tests/bar.py        2019-11-15 07:08:26.000000000 +0100
@@ -17,7 +17,7 @@
 
 import unittest
 
-import cairo
+import cairocffi as cairo
 
 import pycha.bar
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/tests/chart.py 
new/pycha-0.8.1/tests/chart.py
--- old/pycha-0.7.0/tests/chart.py      2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/tests/chart.py      2019-11-15 07:32:31.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright(c) 2007-2010 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
+# Copyright(c) 2007-2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -17,7 +17,7 @@
 
 import unittest
 
-import cairo
+import cairocffi as cairo
 
 import pycha.chart
 
@@ -35,7 +35,7 @@
         self.assertEqual(pycha.chart.uniqueIndices(arr), range(4))
 
         arr = (range(0), )
-        self.assertEqual(pycha.chart.uniqueIndices(arr), [])
+        self.assertEqual(pycha.chart.uniqueIndices(arr), range(0))
 
 
 class AreaTests(unittest.TestCase):
@@ -138,7 +138,7 @@
         dataset = (('dataset1', ([0, 1], [1, 1])), )
         ch.addDataset(dataset)
         ch._setColorscheme()
-        self.assert_(isinstance(ch.colorScheme, dict))
+        self.assertTrue(isinstance(ch.colorScheme, dict))
         self.assertEqual(ch.colorScheme, {'dataset1': (0.0, 0.0, 0.0)})
 
         options = {'colorScheme': {'name': 'foo'}}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/tests/color.py 
new/pycha-0.8.1/tests/color.py
--- old/pycha-0.7.0/tests/color.py      2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/tests/color.py      2019-11-15 07:32:40.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright(c) 2007-2010 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
+# Copyright(c) 2007-2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #              2009 by Yaco S.L. <l...@yaco.es>
 #
 # This file is part of PyCha.
@@ -29,7 +29,7 @@
 
     def test_hex2rgb(self):
         color = pycha.color.hex2rgb('#ff0000')
-        self.assert_(isinstance(color, tuple))
+        self.assertTrue(isinstance(color, tuple))
         self.assertAlmostEqual(1, color[0])
         self.assertAlmostEqual(0, color[1])
         self.assertAlmostEqual(0, color[2])
@@ -38,13 +38,13 @@
         self.assertEqual(color, color2)
 
         color = pycha.color.hex2rgb('#000fff000', digits=3)
-        self.assert_(isinstance(color, tuple))
+        self.assertTrue(isinstance(color, tuple))
         self.assertEqual(0, color[0])
         self.assertEqual(1, color[1])
         self.assertEqual(0, color[2])
 
         color = pycha.color.hex2rgb('#00000000ffff', digits=4)
-        self.assert_(isinstance(color, tuple))
+        self.assertTrue(isinstance(color, tuple))
         self.assertEqual(0, color[0])
         self.assertEqual(0, color[1])
         self.assertEqual(1, color[2])
@@ -82,13 +82,13 @@
     def test_basicColors(self):
         colors = ('red', 'green', 'blue', 'grey', 'black', 'darkcyan')
         for color in colors:
-            self.assert_(color in pycha.color.basicColors)
+            self.assertTrue(color in pycha.color.basicColors)
 
     def test_ColorSchemeRegistry(self):
-        self.assertEquals(SimpleColorScheme,
-                          pycha.color.ColorScheme.getColorScheme('simple'))
-        self.assertEquals(None,
-                          pycha.color.ColorScheme.getColorScheme('foo'))
+        self.assertEqual(SimpleColorScheme,
+                         pycha.color.ColorScheme.getColorScheme('simple'))
+        self.assertEqual(None,
+                         pycha.color.ColorScheme.getColorScheme('foo'))
 
     def test_FixedColorScheme(self):
         keys = range(3)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/tests/line.py 
new/pycha-0.8.1/tests/line.py
--- old/pycha-0.7.0/tests/line.py       2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/tests/line.py       2019-11-15 07:32:49.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright (c) 2007-2010 by Lorenzo Gil Sanchez 
<lorenzo.gil.sanc...@gmail.com>
+# Copyright (c) 2007-2019 by Lorenzo Gil Sanchez 
<lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -17,7 +17,7 @@
 
 import unittest
 
-import cairo
+import cairocffi as cairo
 
 import pycha.line
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/tests/pie.py new/pycha-0.8.1/tests/pie.py
--- old/pycha-0.7.0/tests/pie.py        2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/tests/pie.py        2019-11-15 07:32:53.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright (c) 2007-2010 by Lorenzo Gil Sanchez 
<lorenzo.gil.sanc...@gmail.com>
+# Copyright (c) 2007-2019 by Lorenzo Gil Sanchez 
<lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -17,7 +17,7 @@
 import math
 import unittest
 
-import cairo
+import cairocffi as cairo
 
 import pycha.pie
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/tests/runner.py 
new/pycha-0.8.1/tests/runner.py
--- old/pycha-0.7.0/tests/runner.py     2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/tests/runner.py     2019-11-15 07:32:57.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright (c) 2007-2010 by Lorenzo Gil Sanchez 
<lorenzo.gil.sanc...@gmail.com>
+# Copyright (c) 2007-2019 by Lorenzo Gil Sanchez 
<lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -17,12 +17,13 @@
 
 import unittest
 
-import bar
-import chart
-import color
-import line
-import pie
-import utils
+from . import bar
+from . import chart
+from . import color
+from . import line
+from . import pie
+from . import utils
+
 
 def test_suite():
     return unittest.TestSuite((
@@ -34,5 +35,6 @@
         utils.test_suite(),
     ))
 
+
 if __name__ == '__main__':
     unittest.main(defaultTest='test_suite')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pycha-0.7.0/tests/stackedbar.py 
new/pycha-0.8.1/tests/stackedbar.py
--- old/pycha-0.7.0/tests/stackedbar.py 2013-04-07 20:20:31.000000000 +0200
+++ new/pycha-0.8.1/tests/stackedbar.py 2019-11-15 07:34:09.000000000 +0100
@@ -1,4 +1,5 @@
 # Copyright (c) 2009-2010 by Yaco S.L. <l...@yaco.es>
+#               2019 by Lorenzo Gil Sanchez <lorenzo.gil.sanc...@gmail.com>
 #
 # This file is part of PyCha.
 #
@@ -17,7 +18,7 @@
 
 import unittest
 
-import cairo
+import cairocffi as cairo
 
 import pycha.stackedbar
 


Reply via email to