Merge lp:~who+dev/inkscape/inkscape-p23 into lp:~inkscape.dev/inkscape/trunk

Proposed by Windell Oskay
Status: Needs review
Proposed branch: lp:~who+dev/inkscape/inkscape-p23
Merge into: lp:~inkscape.dev/inkscape/trunk
Diff against target: 231 lines (+43/-25)
6 files modified
share/extensions/bezmisc.py (+25/-11)
share/extensions/cspsubdiv.py (+2/-1)
share/extensions/inkex.py (+6/-4)
share/extensions/simplepath.py (+7/-7)
share/extensions/simplestyle.py (+2/-1)
share/extensions/simpletransform.py (+1/-1)
To merge this branch: bzr merge lp:~who+dev/inkscape/inkscape-p23
Reviewer Review Type Date Requested Status
Inkscape Developers Pending
Review via email: mp+319886@code.launchpad.net

Commit message

Update certain extensions for compatibility with Python 3.

Description of the change

Summary: Change to several of the core python extension files for compatibility with Python 3. These modifications allow them to continue working in python 2.x, without adding dependencies.

Submitted for code review and possible merging.

The changed files are:
inkex.py
bezmisc.py
cspsubdiv.py
simplepath.py
simplestyle.py
simpletransform.py

In addition to these, I would note that ffgeom.py and cubicsuperpath.py work in both Python 2 and 3 without changes. I have not tested other extension files for compatibility.

These changes appear to be non-breaking within Inkscape, as tested via invoking extensions that depend upon these, including flatten, Voronoi pattern (generate from path), and alphabetsoup. I have tested back to Python 2.6 under Inkscape 0.91, and up to Python 3.6 on the command line. While this is neither a formal test procedure nor exhaustive, I have not observed issues or errors due to these changes. If there are formal tests that could identify other issues, I would certainly welcome learning about them.

One coding note that I have is that the function definitions in bezmisc.py required "manually" unpacking the named tuples on their inputs, which adds one line of code to each function. (It could be approached in other ways, but many of those would break extensions that rely upon this.) Someone more expert at python may know of a more elegant approach. I would welcome such suggestions.

I would assert that making the extension environment compatible with Python 3 is a worthwhile goal, even if we are quite some ways away from making Python 3 compatibility an option or requirement. A good near-term goal is that we encourage extension developers to write code that is compatible with both Python 2 and Python 3. The changes in this branch correct several issues that prevent existing extensions (those that call these "core" files) from running under Python 3.

This set of changes in this branch also potentially allows certain Inkscape extensions to be run from the command line without opening the Inkscape GUI (not otherwise possible for verbs) on systems running either Python 2 or 3 as default.

To post a comment you must log in.

Unmerged revisions

15598. By Windell Oskay

changes for compatibility with python 3

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'share/extensions/bezmisc.py'
--- share/extensions/bezmisc.py 2016-03-16 09:58:21 +0000
+++ share/extensions/bezmisc.py 2017-03-15 02:08:29 +0000
@@ -18,6 +18,7 @@
18Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.18Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19'''19'''
2020
21from __future__ import print_function
21import math, cmath22import math, cmath
2223
23def rootWrapper(a,b,c,d):24def rootWrapper(a,b,c,d):
@@ -55,8 +56,9 @@
55 return 1.0*(-d/c),56 return 1.0*(-d/c),
56 return ()57 return ()
5758
58def bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))):59def bezierparameterize(input):
59 #parametric bezier60 #parametric bezier
61 ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))=input
60 x0=bx062 x0=bx0
61 y0=by063 y0=by0
62 cx=3*(bx1-x0)64 cx=3*(bx1-x0)
@@ -69,8 +71,9 @@
69 return ax,ay,bx,by,cx,cy,x0,y071 return ax,ay,bx,by,cx,cy,x0,y0
70 #ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))72 #ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
7173
72def linebezierintersect(((lx1,ly1),(lx2,ly2)),((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))):74def linebezierintersect(input):
73 #parametric line75 #parametric line
76 ((lx1,ly1),(lx2,ly2)),((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))=input
74 dd=lx177 dd=lx1
75 cc=lx2-lx178 cc=lx2-lx1
76 bb=ly179 bb=ly1
@@ -99,19 +102,23 @@
99 retval.append(bezierpointatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),i))102 retval.append(bezierpointatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),i))
100 return retval103 return retval
101104
102def bezierpointatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t):105def bezierpointatt(param1,t):
106 ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))=param1
103 ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))107 ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
104 x=ax*(t**3)+bx*(t**2)+cx*t+x0108 x=ax*(t**3)+bx*(t**2)+cx*t+x0
105 y=ay*(t**3)+by*(t**2)+cy*t+y0109 y=ay*(t**3)+by*(t**2)+cy*t+y0
106 return x,y110 return x,y
107111
108def bezierslopeatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t):112def bezierslopeatt(param1,t):
113 ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))=param1
109 ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))114 ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
110 dx=3*ax*(t**2)+2*bx*t+cx115 dx=3*ax*(t**2)+2*bx*t+cx
111 dy=3*ay*(t**2)+2*by*t+cy116 dy=3*ay*(t**2)+2*by*t+cy
112 return dx,dy117 return dx,dy
113118
114def beziertatslope(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),(dy,dx)):119def beziertatslope(param1,param2):
120 ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))=param1
121 (dy,dx)=param2
115 ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))122 ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
116 #quadratic coefficents of slope formula123 #quadratic coefficents of slope formula
117 if dx:124 if dx:
@@ -136,9 +143,12 @@
136 retval.append(i)143 retval.append(i)
137 return retval144 return retval
138145
139def tpoint((x1,y1),(x2,y2),t):146def tpoint(param1,param2,t):
147 (x1,y1)=param1
148 (x2,y2)=param2
140 return x1+t*(x2-x1),y1+t*(y2-y1)149 return x1+t*(x2-x1),y1+t*(y2-y1)
141def beziersplitatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t):150def beziersplitatt(param1,t):
151 ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))=param1
142 m1=tpoint((bx0,by0),(bx1,by1),t)152 m1=tpoint((bx0,by0),(bx1,by1),t)
143 m2=tpoint((bx1,by1),(bx2,by2),t)153 m2=tpoint((bx1,by1),(bx2,by2),t)
144 m3=tpoint((bx2,by2),(bx3,by3),t)154 m3=tpoint((bx2,by2),(bx3,by3),t)
@@ -167,7 +177,9 @@
167mat-report no. 1992-10, Mathematical Institute, The Technical177mat-report no. 1992-10, Mathematical Institute, The Technical
168University of Denmark. 178University of Denmark.
169'''179'''
170def pointdistance((x1,y1),(x2,y2)):180def pointdistance(point1,point2):
181 (x1,y1)=point1
182 (x2,y2)=point2
171 return math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2))183 return math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2))
172def Gravesen_addifclose(b, len, error = 0.001):184def Gravesen_addifclose(b, len, error = 0.001):
173 box = 0185 box = 0
@@ -214,13 +226,15 @@
214 #print multiplier, endsum, interval, asum, bsum, est1, est0226 #print multiplier, endsum, interval, asum, bsum, est1, est0
215 return est1227 return est1
216228
217def bezierlengthSimpson(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)), tolerance = 0.001):229def bezierlengthSimpson(param1, tolerance = 0.001):
230 ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))=param1
218 global balfax,balfbx,balfcx,balfay,balfby,balfcy231 global balfax,balfbx,balfcx,balfay,balfby,balfcy
219 ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))232 ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
220 balfax,balfbx,balfcx,balfay,balfby,balfcy = 3*ax,2*bx,cx,3*ay,2*by,cy233 balfax,balfbx,balfcx,balfay,balfby,balfcy = 3*ax,2*bx,cx,3*ay,2*by,cy
221 return Simpson(balf, 0.0, 1.0, 4096, tolerance)234 return Simpson(balf, 0.0, 1.0, 4096, tolerance)
222235
223def beziertatlength(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)), l = 0.5, tolerance = 0.001):236def beziertatlength(param1, l = 0.5, tolerance = 0.001):
237 ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))=param1
224 global balfax,balfbx,balfcx,balfay,balfby,balfcy238 global balfax,balfbx,balfcx,balfay,balfby,balfcy
225 ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))239 ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
226 balfax,balfbx,balfcx,balfay,balfby,balfcy = 3*ax,2*bx,cx,3*ay,2*by,cy240 balfax,balfbx,balfcx,balfay,balfby,balfcy = 3*ax,2*bx,cx,3*ay,2*by,cy
@@ -268,7 +282,7 @@
268 print s, st282 print s, st
269 '''283 '''
270 for curve in curves:284 for curve in curves:
271 print beziertatlength(curve,0.5)285 print(beziertatlength(curve,0.5))
272286
273287
274# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99288# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
275289
=== modified file 'share/extensions/cspsubdiv.py'
--- share/extensions/cspsubdiv.py 2011-11-21 20:58:06 +0000
+++ share/extensions/cspsubdiv.py 2017-03-15 02:08:29 +0000
@@ -2,7 +2,8 @@
2from bezmisc import *2from bezmisc import *
3from ffgeom import *3from ffgeom import *
44
5def maxdist(((p0x,p0y),(p1x,p1y),(p2x,p2y),(p3x,p3y))):5def maxdist(input):
6 ((p0x,p0y),(p1x,p1y),(p2x,p2y),(p3x,p3y))=input
6 p0 = Point(p0x,p0y)7 p0 = Point(p0x,p0y)
7 p1 = Point(p1x,p1y)8 p1 = Point(p1x,p1y)
8 p2 = Point(p2x,p2y)9 p2 = Point(p2x,p2y)
910
=== modified file 'share/extensions/inkex.py'
--- share/extensions/inkex.py 2016-05-26 09:28:23 +0000
+++ share/extensions/inkex.py 2017-03-15 02:08:29 +0000
@@ -98,11 +98,13 @@
98 ...98 ...
99 inkex.errormsg(_("This extension requires two selected paths."))99 inkex.errormsg(_("This extension requires two selected paths."))
100 """100 """
101 if isinstance(msg, unicode):101 if sys.version_info.major == 2:
102 sys.stderr.write(msg.encode("utf-8") + "\n")102 if isinstance(msg, unicode):
103 sys.stderr.write(msg.encode("utf-8") + "\n")
104 else:
105 sys.stderr.write((unicode(msg, "utf-8", errors='replace') + "\n").encode("utf-8"))
103 else:106 else:
104 sys.stderr.write((unicode(msg, "utf-8", errors='replace') + "\n").encode("utf-8"))107 sys.stderr.write(msg + "\n")
105
106108
107def are_near_relative(a, b, eps):109def are_near_relative(a, b, eps):
108 return (a-b <= a*eps) and (a-b >= -a*eps)110 return (a-b <= a*eps) and (a-b >= -a*eps)
109111
=== modified file 'share/extensions/simplepath.py' (properties changed: -x to +x)
--- share/extensions/simplepath.py 2016-03-16 09:58:21 +0000
+++ share/extensions/simplepath.py 2017-03-15 02:08:29 +0000
@@ -48,7 +48,7 @@
48 offset = m.end()48 offset = m.end()
49 continue49 continue
50 #TODO: create new exception50 #TODO: create new exception
51 raise Exception, 'Invalid path data!'51 raise Exception('Invalid path data!')
52'''52'''
53pathdefs = {commandfamily:53pathdefs = {commandfamily:
54 [54 [
@@ -86,14 +86,14 @@
86 86
87 while 1:87 while 1:
88 try:88 try:
89 token, isCommand = lexer.next()89 token, isCommand = next(lexer)
90 except StopIteration:90 except StopIteration:
91 break91 break
92 params = []92 params = []
93 needParam = True93 needParam = True
94 if isCommand:94 if isCommand:
95 if not lastCommand and token.upper() != 'M':95 if not lastCommand and token.upper() != 'M':
96 raise Exception, 'Invalid path, must begin with moveto.' 96 raise Exception('Invalid path, must begin with moveto.')
97 else: 97 else:
98 command = token98 command = token
99 else:99 else:
@@ -106,16 +106,16 @@
106 else:106 else:
107 command = pathdefs[lastCommand.upper()][0].lower()107 command = pathdefs[lastCommand.upper()][0].lower()
108 else:108 else:
109 raise Exception, 'Invalid path, no initial command.' 109 raise Exception('Invalid path, no initial command.')
110 numParams = pathdefs[command.upper()][1]110 numParams = pathdefs[command.upper()][1]
111 while numParams > 0:111 while numParams > 0:
112 if needParam:112 if needParam:
113 try: 113 try:
114 token, isCommand = lexer.next()114 token, isCommand = next(lexer)
115 if isCommand:115 if isCommand:
116 raise Exception, 'Invalid number of parameters'116 raise Exception('Invalid number of parameters')
117 except StopIteration:117 except StopIteration:
118 raise Exception, 'Unexpected end of path'118 raise Exception('Unexpected end of path')
119 cast = pathdefs[command.upper()][2][-numParams]119 cast = pathdefs[command.upper()][2][-numParams]
120 param = cast(token)120 param = cast(token)
121 if command.islower():121 if command.islower():
122122
=== modified file 'share/extensions/simplestyle.py' (properties changed: -x to +x)
--- share/extensions/simplestyle.py 2016-03-16 09:58:21 +0000
+++ share/extensions/simplestyle.py 2017-03-15 02:08:29 +0000
@@ -1,3 +1,4 @@
1#!/usr/bin/env python
1"""2"""
2simplestyle.py3simplestyle.py
3Two simple functions for working with inline css4Two simple functions for working with inline css
@@ -17,7 +18,7 @@
1718
18You should have received a copy of the GNU General Public License19You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software20along with this program; if not, write to the Free Software
20Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.21Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21"""22"""
2223
23svgcolors={24svgcolors={
2425
=== modified file 'share/extensions/simpletransform.py' (properties changed: -x to +x)
--- share/extensions/simpletransform.py 2016-03-16 09:58:21 +0000
+++ share/extensions/simpletransform.py 2017-03-15 02:08:29 +0000
@@ -131,7 +131,7 @@
131def fuseTransform(node):131def fuseTransform(node):
132 if node.get('d')==None:132 if node.get('d')==None:
133 #FIXME: how do you raise errors?133 #FIXME: how do you raise errors?
134 raise AssertionError, 'can not fuse "transform" of elements that have no "d" attribute'134 raise AssertionError('can not fuse "transform" of elements that have no "d" attribute')
135 t = node.get("transform")135 t = node.get("transform")
136 if t == None:136 if t == None:
137 return137 return