From 1cada459cf01ffc06bb56949c83c7295417a93c782647dc8b13b02637cb56718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Br=C3=BCns?= Date: Fri, 9 Aug 2019 14:06:24 +0000 Subject: [PATCH] Accepting request 719866 from home:StefanBruens:branches:graphics Port away from Python2 OBS-URL: https://build.opensuse.org/request/show/719866 OBS-URL: https://build.opensuse.org/package/show/graphics/inkscape?expand=0&rev=52 --- ...cript-for-translations-with-Python-3.patch | 79 + ...f34_extensions_python3_compatibility.patch | 34 + inkscape.changes | 14 + inkscape.spec | 39 +- mr_568_extensions_python3_compatibility.patch | 4914 +++++++++++++++++ mr_582_extensions_python3_compatibility.patch | 130 + 6 files changed, 5191 insertions(+), 19 deletions(-) create mode 100644 0001-Run-python-script-for-translations-with-Python-3.patch create mode 100644 f5e0ea893f34_extensions_python3_compatibility.patch create mode 100644 mr_568_extensions_python3_compatibility.patch create mode 100644 mr_582_extensions_python3_compatibility.patch diff --git a/0001-Run-python-script-for-translations-with-Python-3.patch b/0001-Run-python-script-for-translations-with-Python-3.patch new file mode 100644 index 0000000..e984322 --- /dev/null +++ b/0001-Run-python-script-for-translations-with-Python-3.patch @@ -0,0 +1,79 @@ +From 5d0de061d393cc0aa134708a7482e9913a0d0736 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20Br=C3=BCns?= +Date: Tue, 30 Jul 2019 16:02:49 +0200 +Subject: [PATCH] Run python script for translations with Python 3 + +--- + share/filters/CMakeLists.txt | 2 +- + share/palettes/CMakeLists.txt | 2 +- + share/patterns/CMakeLists.txt | 2 +- + share/symbols/CMakeLists.txt | 2 +- + share/templates/CMakeLists.txt | 2 +- + 5 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/share/filters/CMakeLists.txt b/share/filters/CMakeLists.txt +index bfcdd78..17cb98f 100644 +--- a/share/filters/CMakeLists.txt ++++ b/share/filters/CMakeLists.txt +@@ -1,6 +1,6 @@ + add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/filters.svg.h +- COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${CMAKE_CURRENT_SOURCE_DIR}/filters.svg > ${CMAKE_CURRENT_SOURCE_DIR}/filters.svg.h ++ COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${CMAKE_CURRENT_SOURCE_DIR}/filters.svg > ${CMAKE_CURRENT_SOURCE_DIR}/filters.svg.h + MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/filters.svg + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py + ) +diff --git a/share/palettes/CMakeLists.txt b/share/palettes/CMakeLists.txt +index 49b1b5e..ef6f501 100644 +--- a/share/palettes/CMakeLists.txt ++++ b/share/palettes/CMakeLists.txt +@@ -2,7 +2,7 @@ set(I18N_FILES "inkscape.gpl" "svg.gpl" "Tango-Palette.gpl") + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/palettes.h +- COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${I18N_FILES} > ${CMAKE_CURRENT_SOURCE_DIR}/palettes.h ++ COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${I18N_FILES} > ${CMAKE_CURRENT_SOURCE_DIR}/palettes.h + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${I18N_FILES} + ) +diff --git a/share/patterns/CMakeLists.txt b/share/patterns/CMakeLists.txt +index 4dd4153..4d63fc0 100644 +--- a/share/patterns/CMakeLists.txt ++++ b/share/patterns/CMakeLists.txt +@@ -1,6 +1,6 @@ + add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/patterns.svg.h +- COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${CMAKE_CURRENT_SOURCE_DIR}/patterns.svg > ${CMAKE_CURRENT_SOURCE_DIR}/patterns.svg.h ++ COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${CMAKE_CURRENT_SOURCE_DIR}/patterns.svg > ${CMAKE_CURRENT_SOURCE_DIR}/patterns.svg.h + MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/patterns.svg + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py + ) +diff --git a/share/symbols/CMakeLists.txt b/share/symbols/CMakeLists.txt +index 36f7564..ed0bc43 100644 +--- a/share/symbols/CMakeLists.txt ++++ b/share/symbols/CMakeLists.txt +@@ -2,7 +2,7 @@ file(GLOB _FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.svg") + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/symbols.h +- COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${_FILES} > ${CMAKE_CURRENT_SOURCE_DIR}/symbols.h ++ COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${_FILES} > ${CMAKE_CURRENT_SOURCE_DIR}/symbols.h + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${_FILES} + ) +diff --git a/share/templates/CMakeLists.txt b/share/templates/CMakeLists.txt +index a267e43..8a95704 100644 +--- a/share/templates/CMakeLists.txt ++++ b/share/templates/CMakeLists.txt +@@ -2,7 +2,7 @@ file(GLOB _FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.svg") + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/templates.h +- COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${_FILES} > ${CMAKE_CURRENT_SOURCE_DIR}/templates.h ++ COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${_FILES} > ${CMAKE_CURRENT_SOURCE_DIR}/templates.h + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/i18n.py ${_FILES} + ) +-- +2.22.0 + diff --git a/f5e0ea893f34_extensions_python3_compatibility.patch b/f5e0ea893f34_extensions_python3_compatibility.patch new file mode 100644 index 0000000..eb13e03 --- /dev/null +++ b/f5e0ea893f34_extensions_python3_compatibility.patch @@ -0,0 +1,34 @@ +From f5e0ea893f34c91f25d4781b37ee6eff15a7e213 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Thu, 7 Mar 2019 21:48:37 +0100 +Subject: [PATCH] extensions 2to3: fix dxf_outlines + +--- + share/extensions/dxf_outlines.py | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/share/extensions/dxf_outlines.py b/share/extensions/dxf_outlines.py +index 63d813f94c..e07681bbba 100755 +--- a/share/extensions/dxf_outlines.py ++++ b/share/extensions/dxf_outlines.py +@@ -31,6 +31,7 @@ along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + ''' + # standard library ++import sys + import math + # local library + import inkex +@@ -101,7 +102,8 @@ class MyEffect(inkex.Effect): + self.d = array([0], float) # knot vector + self.poly = [[0.0,0.0]] # LWPOLYLINE data + def output(self): +- print(b''.join(self.dxf)) ++ stdout = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer ++ stdout.write(b''.join(self.dxf)) + def dxf_add(self, str): + self.dxf.append(str.encode(self.options.char_encode)) + def dxf_line(self,csp): +-- +2.21.0 + diff --git a/inkscape.changes b/inkscape.changes index 766064c..8f77c50 100644 --- a/inkscape.changes +++ b/inkscape.changes @@ -1,3 +1,17 @@ +------------------------------------------------------------------- +Tue Jul 30 16:18:54 UTC 2019 - Stefan Brüns + +- Change Python dependencies to Python 3 as Python 2 will be EOL in 2020. +- Use Python 3 to extract translations, add + 0001-Run-python-script-for-translations-with-Python-3.patch +- Make extensions compatible with Python 3 + (https://bugs.launchpad.net/inkscape/+bug/1735363) + * Add mr_568_extensions_python3_compatibility.patch + * Add f5e0ea893f34_extensions_python3_compatibility.patch + * Add mr_582_extensions_python3_compatibility.patch +- Some spec cleanups (buildroot, defattr) +- Require extensions-extra for gimp extension + ------------------------------------------------------------------- Fri May 31 08:43:53 UTC 2019 - Bjørn Lie diff --git a/inkscape.spec b/inkscape.spec index 0b4c10a..2d9701e 100644 --- a/inkscape.spec +++ b/inkscape.spec @@ -37,6 +37,14 @@ Patch1: build_internal_libraries_as_static.patch Patch2: fix_install_targets.patch # PATCH-FIX-UPSTREAM inkscape-fix-for-poppler-0.76.patch -- Fix build with poppler 0.76 Patch3: inkscape-fix-for-poppler-0.76.patch +# PATCH-FIX-OPENSUSE -- run i18n string extraction with python3 +Patch4: 0001-Run-python-script-for-translations-with-Python-3.patch +# PATCH-FIX-UPSTREAM https://gitlab.com/inkscape/inkscape/merge_requests/568.patch -- fixed in 0.92.5 +Patch5: mr_568_extensions_python3_compatibility.patch +# PATCH-FIX-UPSTREAM https://gitlab.com/inkscape/inkscape/commit/f5e0ea893f34c91f25d4781b37ee6eff15a7e213 +Patch6: f5e0ea893f34_extensions_python3_compatibility.patch +# PATCH-FIX-UPSTREAM https://gitlab.com/inkscape/inkscape/merge_requests/582.patch -- fixed in 0.92.5 +Patch7: mr_582_extensions_python3_compatibility.patch BuildRequires: gtkspell-devel %if 0%{?suse_version} > 1325 @@ -60,9 +68,9 @@ BuildRequires: libxslt-devel BuildRequires: perl BuildRequires: popt-devel BuildRequires: potrace-devel -BuildRequires: python-devel -BuildRequires: python-gtk-devel -BuildRequires: python2-xml +BuildRequires: python3-devel +BuildRequires: python3-gobject-devel +BuildRequires: python3-xml BuildRequires: update-desktop-files BuildRequires: pkgconfig(dbus-glib-1) BuildRequires: pkgconfig(libcdr-0.1) @@ -72,11 +80,10 @@ BuildRequires: pkgconfig(libpng) BuildRequires: pkgconfig(librevenge-0.0) BuildRequires: pkgconfig(libvisio-0.1) BuildRequires: pkgconfig(libwpg-0.3) -Requires: python-gtk +Requires: python3-gobject Recommends: %{name}-lang -Recommends: python-lxml -Recommends: python-scour -BuildRoot: %{_tmppath}/%{name}-%{version}-build +Recommends: python3-lxml +Recommends: python3-scour %description Inkscape is a vector graphics editor. @@ -87,15 +94,15 @@ Group: Productivity/Graphics/Vector Editors Requires: %{name} = %{version} # ps2pdf-ext.py is a wrapper around ps2pdf, which lives in ghostscript package. Requires: ghostscript -Requires: python-lxml -Requires: python-xml +Requires: python3-lxml +Requires: python3-xml # for cdr and wmf modules Recommends: yudit # dxf_output.inx, eqtexsvg.inx: Requires: pstoedit Enhances: %{name} -# python-xml is already likely installed, so the big dependency is python-lxml. Hence this supplements. -Supplements: packageand(%{name}:python-lxml) +# python3-xml is already likely installed, so the big dependency is python3-lxml. Hence this supplements. +Supplements: packageand(%{name}:python3-lxml) %description extensions-extra Extra extensions for Inkscape. Recommended for everybody who wants to @@ -134,6 +141,7 @@ Inkscape is a vector graphics editor. Summary: GIMP extensions for Inkscape Group: Productivity/Graphics/Vector Editors Requires: %{name} = %{version} +Requires: %{name}-extensions-extra = %{version} Requires: gimp Enhances: %{name} Supplements: packageand(%{name}:gimp) @@ -209,7 +217,7 @@ install -D -m 0644 %{SOURCE1} %{buildroot}%{_datadir}/inkscape/palettes # split extensions bash %{SOURCE2} %{buildroot}%{_datadir}/inkscape/extensions "%%{_datadir}/inkscape/extensions/" -sed -i -e "1 s,#! */usr/bin/env python,#!/usr/bin/python2," %{buildroot}%{_datadir}/inkscape/extensions/*.py +sed -i -e "1 s,#! */usr/bin/env python,#!/usr/bin/python3," %{buildroot}%{_datadir}/inkscape/extensions/*.py # Localized man pages, correct install path for man in %{buildroot}%{_mandir}/man1/inkscape.*.1; do @@ -240,7 +248,6 @@ install -D -m 0644 inkscape.appdata.xml %{buildroot}%{_datadir}/metainfo/inkscap # create a conflict between the lang subpackage and bundles %files -f inkscape.lst -f %{name}.man-lang -%defattr(-,root,root) %{_bindir}/* %{_libdir}/libinkscape_base.so %{_datadir}/applications/inkscape.desktop @@ -285,7 +292,6 @@ install -D -m 0644 inkscape.appdata.xml %{buildroot}%{_datadir}/metainfo/inkscap %exclude %{_datadir}/inkscape/extensions/ps2pdf-ext.py %files extensions-extra -f inkscape-extensions-extra.lst -%defattr(-,root,root) %{_datadir}/inkscape/extensions/Barcode # ps2pdf-ext is a wrapper around ps2pdf binary (part of ghostscript) %{_datadir}/inkscape/extensions/ps_input.inx @@ -299,23 +305,18 @@ install -D -m 0644 inkscape.appdata.xml %{buildroot}%{_datadir}/metainfo/inkscap %exclude %{_datadir}/inkscape/extensions/sk* %files extensions-dia -%defattr(-,root,root) %{_datadir}/inkscape/extensions/dia* %files extensions-fig -%defattr(-,root,root) %{_datadir}/inkscape/extensions/fig* %files extensions-gimp -%defattr(-,root,root) # NOTE: export_gimp_palette* does not depend on gimp, but belongs here logically: %{_datadir}/inkscape/extensions/*gimp* %files extensions-skencil -%defattr(-,root,root) %{_datadir}/inkscape/extensions/sk* %files lang -f %{name}.lang -%defattr(-,root,root) %changelog diff --git a/mr_568_extensions_python3_compatibility.patch b/mr_568_extensions_python3_compatibility.patch new file mode 100644 index 0000000..a7b2d0d --- /dev/null +++ b/mr_568_extensions_python3_compatibility.patch @@ -0,0 +1,4914 @@ +From 006353b6342416ef7518c70e21081496708b8ad0 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 09:24:55 +0100 +Subject: [PATCH 01/17] extensions 2to3: ne raise except has_key + +--- + share/extensions/coloreffect.py | 4 ++-- + share/extensions/convert2dashes.py | 4 ++-- + share/extensions/dpiswitcher.py | 2 +- + share/extensions/dxf_input.py | 20 ++++++++-------- + share/extensions/dxf_outlines.py | 4 ++-- + share/extensions/gcodetools.py | 18 +++++++-------- + share/extensions/generate_voronoi.py | 4 ++-- + share/extensions/grid_polar.py | 2 +- + share/extensions/hpgl_input.py | 2 +- + share/extensions/hpgl_output.py | 2 +- + share/extensions/interp.py | 2 +- + share/extensions/jessyInk_autoTexts.py | 2 +- + share/extensions/jessyInk_effects.py | 8 +++---- + share/extensions/jessyInk_export.py | 2 +- + share/extensions/jessyInk_summary.py | 12 +++++----- + share/extensions/jessyInk_video.py | 8 +++---- + share/extensions/jessyInk_view.py | 6 ++--- + share/extensions/markers_strokepaint.py | 2 +- + share/extensions/merge_styles.py | 6 ++--- + share/extensions/pathmodifier.py | 4 ++-- + share/extensions/pixelsnap.py | 6 ++--- + share/extensions/plotter.py | 6 ++--- + share/extensions/print_win32_vector.py | 8 +++---- + share/extensions/render_alphabetsoup.py | 2 +- + share/extensions/run_command.py | 4 ++-- + share/extensions/simplepath.py | 10 ++++---- + share/extensions/simpletransform.py | 2 +- + share/extensions/svg_and_media_zip_output.py | 6 ++--- + share/extensions/synfig_fileformat.py | 6 ++--- + share/extensions/synfig_output.py | 24 ++++++++++---------- + share/extensions/synfig_prepare.py | 6 ++--- + share/extensions/text_braille.py | 2 +- + share/extensions/uniconv_output.py | 4 ++-- + share/extensions/voronoi2svg.py | 2 +- + share/extensions/webslicer_export.py | 2 +- + 35 files changed, 102 insertions(+), 102 deletions(-) + +diff --git a/share/extensions/coloreffect.py b/share/extensions/coloreffect.py +index d33ac41fe3..94e909a728 100755 +--- a/share/extensions/coloreffect.py ++++ b/share/extensions/coloreffect.py +@@ -52,7 +52,7 @@ class ColorEffect(inkex.Effect): + if new_val != val: + node.set(attr, new_val) + +- if node.attrib.has_key('style'): ++ if 'style' in node.attrib: + # References for style attribute: + # http://www.w3.org/TR/SVG11/styling.html#StyleAttribute, + # http://www.w3.org/TR/CSS21/syndata.html +@@ -131,7 +131,7 @@ class ColorEffect(inkex.Effect): + for child in newnode: + self.changeStyle(child) + xlink = inkex.addNS('href','xlink') +- if newnode.attrib.has_key(xlink): ++ if xlink in newnode.attrib: + href=newnode.get(xlink) + if href.startswith('#'): + id = href[len('#'):len(href)] +diff --git a/share/extensions/convert2dashes.py b/share/extensions/convert2dashes.py +index 1d1ba97360..44241c2548 100755 +--- a/share/extensions/convert2dashes.py ++++ b/share/extensions/convert2dashes.py +@@ -66,10 +66,10 @@ class SplitIt(inkex.Effect): + dashes = [] + offset = 0 + style = simplestyle.parseStyle(node.get('style')) +- if style.has_key('stroke-dasharray'): ++ if 'stroke-dasharray' in style: + if style['stroke-dasharray'].find(',') > 0: + dashes = [float (dash) for dash in style['stroke-dasharray'].split(',')] +- if style.has_key('stroke-dashoffset'): ++ if 'stroke-dashoffset' in style: + offset = style['stroke-dashoffset'] + if dashes: + p = cubicsuperpath.parsePath(node.get('d')) +diff --git a/share/extensions/dpiswitcher.py b/share/extensions/dpiswitcher.py +index 317616db51..dcffa202db 100644 +--- a/share/extensions/dpiswitcher.py ++++ b/share/extensions/dpiswitcher.py +@@ -409,7 +409,7 @@ class DPISwitcher(inkex.Effect): + namedview = svg.find(inkex.addNS('namedview', 'sodipodi')) + namedview.set(inkex.addNS('document-units', 'inkscape'), "px") + self.units = self.parse_length(svg.get('width'))[1] +- if self.units and self.units <> "px" and self.units <> "" and self.units <> "%": ++ if self.units and self.units != "px" and self.units != "" and self.units != "%": + if self.options.switcher == "0": + self.unitExponent = 1.0/(self.factor_a/self.__uuconv[self.units]) + else: +diff --git a/share/extensions/dxf_input.py b/share/extensions/dxf_input.py +index 1dcbac7b8d..cd0e508b59 100755 +--- a/share/extensions/dxf_input.py ++++ b/share/extensions/dxf_input.py +@@ -262,7 +262,7 @@ def export_DIMENSION(): + y = height - scale*(vals[groups['21']][0] - ymin) + size = 12 # default fontsize in px + if vals[groups['3']]: +- if DIMTXT.has_key(vals[groups['3']][0]): ++ if vals[groups['3']][0] in DIMTXT: + size = scale*DIMTXT[vals[groups['3']][0]] + if size < 2: + size = 2 +@@ -428,7 +428,7 @@ else: + desc.text = '%s - scale = %f, origin = (%f, %f), method = %s' % (unicode(args[0], options.input_encode), scale, xmin, ymin, options.scalemethod) + scale *= 96.0/25.4 # convert from mm to pixels + +-if not layer_nodes.has_key('0'): ++if '0' not in layer_nodes: + attribs = {inkex.addNS('groupmode','inkscape'): 'layer', inkex.addNS('label','inkscape'): '0'} + layer_nodes['0'] = inkex.etree.SubElement(doc.getroot(), 'g', attribs) + layer_colors['0'] = 7 +@@ -454,7 +454,7 @@ while line[0] and (line[1] != 'ENDSEC' or not inENTITIES): + inENTITIES = True + elif line[1] == 'POLYLINE': + polylines += 1 +- if entity and groups.has_key(line[0]): ++ if entity and line[0] in groups: + seqs.append(line[0]) # list of group codes + if line[0] == '1' or line[0] == '2' or line[0] == '3' or line[0] == '6' or line[0] == '8': # text value + val = line[1].replace('\~', ' ') +@@ -474,24 +474,24 @@ while line[0] and (line[1] != 'ENDSEC' or not inENTITIES): + else: # unscaled float value + val = float(line[1]) + vals[groups[line[0]]].append(val) +- elif entities.has_key(line[1]): +- if entities.has_key(entity): ++ elif line[1] in entities: ++ if entity in entities: + if block != defs: # in a BLOCK + layer = block + elif vals[groups['8']]: # use Common Layer Name + if not vals[groups['8']][0]: + vals[groups['8']][0] = '0' # use default name +- if not layer_nodes.has_key(vals[groups['8']][0]): ++ if vals[groups['8']][0] not in layer_nodes: + attribs = {inkex.addNS('groupmode','inkscape'): 'layer', inkex.addNS('label','inkscape'): '%s' % vals[groups['8']][0]} + layer_nodes[vals[groups['8']][0]] = inkex.etree.SubElement(doc.getroot(), 'g', attribs) + layer = layer_nodes[vals[groups['8']][0]] + color = '#000000' # default color + if vals[groups['8']]: +- if layer_colors.has_key(vals[groups['8']][0]): +- if colors.has_key(layer_colors[vals[groups['8']][0]]): ++ if vals[groups['8']][0] in layer_colors: ++ if layer_colors[vals[groups['8']][0]] in colors: + color = colors[layer_colors[vals[groups['8']][0]]] + if vals[groups['62']]: # Common Color Number +- if colors.has_key(vals[groups['62']][0]): ++ if vals[groups['62']][0] in colors: + color = colors[vals[groups['62']][0]] + style = simplestyle.formatStyle({'stroke': '%s' % color, 'fill': 'none'}) + w = 0.5 # default lineweight for POINT +@@ -502,7 +502,7 @@ while line[0] and (line[1] != 'ENDSEC' or not inENTITIES): + w = 0.5 + style = simplestyle.formatStyle({'stroke': '%s' % color, 'fill': 'none', 'stroke-width': '%.1f' % w}) + if vals[groups['6']]: # Common Linetype +- if linetypes.has_key(vals[groups['6']][0]): ++ if vals[groups['6']][0] in linetypes: + style += ';' + linetypes[vals[groups['6']][0]] + extrude = 1.0 + if vals[groups['230']]: +diff --git a/share/extensions/dxf_outlines.py b/share/extensions/dxf_outlines.py +index 53de1066d5..876f41f5f9 100755 +--- a/share/extensions/dxf_outlines.py ++++ b/share/extensions/dxf_outlines.py +@@ -194,7 +194,7 @@ class MyEffect(inkex.Effect): + style = node.get('style') + if style: + style = simplestyle.parseStyle(style) +- if style.has_key('stroke'): ++ if 'stroke' in style: + if style['stroke'] and style['stroke'] != 'none' and style['stroke'][0:3] != 'url': + rgb = simplestyle.parseColor(style['stroke']) + hsl = coloreffect.ColorEffect.rgb_to_hsl(coloreffect.ColorEffect(),rgb[0]/255.0,rgb[1]/255.0,rgb[2]/255.0) +@@ -286,7 +286,7 @@ class MyEffect(inkex.Effect): + style = group.get('style') + if style: + style = simplestyle.parseStyle(style) +- if style.has_key('display'): ++ if 'display' in style: + if style['display'] == 'none' and self.options.layer_option and self.options.layer_option=='visible': + return + layer = group.get(inkex.addNS('label', 'inkscape')) +diff --git a/share/extensions/gcodetools.py b/share/extensions/gcodetools.py +index be471136ed..27fedd9a5f 100755 +--- a/share/extensions/gcodetools.py ++++ b/share/extensions/gcodetools.py +@@ -1325,7 +1325,7 @@ def csp_segment_convex_hull(sp1,sp2): + if not (m1 and m2) and m3 : return [c,a,d] + if not (m1 and m3) and m2 : return [b,c,d] + +- raise ValueError, "csp_segment_convex_hull happened which is something that shouldn't happen!" ++ raise ValueError("csp_segment_convex_hull happened which is something that shouldn't happen!") + + + ################################################################################ +@@ -1474,7 +1474,7 @@ def atan2(*arg): + + return (math.pi/2 - math.atan2(arg[0],arg[1]) ) % math.pi2 + else : +- raise ValueError, "Bad argumets for atan! (%s)" % arg ++ raise ValueError("Bad argumets for atan! (%s)" % arg) + + def get_text(node) : + value = None +@@ -2331,11 +2331,11 @@ def biarc(sp1, sp2, z1, z2, depth=0): + elif csmall and a!=0: beta = -b/a + elif not asmall: + discr = b*b-4*a*c +- if discr < 0: raise ValueError, (a,b,c,discr) ++ if discr < 0: raise ValueError(a,b,c,discr) + disq = discr**.5 + beta1 = (-b - disq) / 2 / a + beta2 = (-b + disq) / 2 / a +- if beta1*beta2 > 0 : raise ValueError, (a,b,c,disq,beta1,beta2) ++ if beta1*beta2 > 0 : raise ValueError(a,b,c,disq,beta1,beta2) + beta = max(beta1, beta2) + elif asmall and bsmall: + return biarc_split(sp1, sp2, z1, z2, depth) +@@ -2984,7 +2984,7 @@ class Polygon: + + while len(edges)>0 : + poly = [] +- if loops > len_edges : raise ValueError, "Hull error" ++ if loops > len_edges : raise ValueError("Hull error") + loops+=1 + # Find left most vertex. + start = (1e100,1) +@@ -2995,7 +2995,7 @@ class Polygon: + loops1 = 0 + while (last[1]!=start[0] or first_run) : + first_run = False +- if loops1 > len_edges : raise ValueError, "Hull error" ++ if loops1 > len_edges : raise ValueError("Hull error") + loops1 += 1 + next = get_closes_edge_by_angle(edges[last[1]],last) + #draw_pointer(next[0]+next[1],"Green","line", comment=i, width= 1) +@@ -4894,11 +4894,11 @@ class Gcodetools(inkex.Effect): + elif csmall and a!=0: beta = -b/a + elif not asmall: + discr = b*b-4*a*c +- if discr < 0: raise ValueError, (a,b,c,discr) ++ if discr < 0: raise ValueError(a,b,c,discr) + disq = discr**.5 + beta1 = (-b - disq) / 2 / a + beta2 = (-b + disq) / 2 / a +- if beta1*beta2 > 0 : raise ValueError, (a,b,c,disq,beta1,beta2) ++ if beta1*beta2 > 0 : raise ValueError(a,b,c,disq,beta1,beta2) + beta = max(beta1, beta2) + elif asmall and bsmall: + return biarc_split(sp1, sp2, z1, z2, depth) +@@ -6359,7 +6359,7 @@ G01 Z1 (going to cutting z)\n""", + time_ = l/feed + c1,c2 = self.graffiti_reference_points[layer][0][0],self.graffiti_reference_points[layer][1][0] + d = math.sqrt( (c1[0]-c2[0])**2 + (c1[1]-c2[1])**2 ) +- if d == 0 : raise ValueError, "Error! Reference points should not be the same!" ++ if d == 0 : raise ValueError("Error! Reference points should not be the same!") + for i in range(int(time_*emmit+1)) : + t = i/(time_*emmit) + r1,r2 = start[0]*(1-t) + end[0]*t, start[1]*(1-t) + end[1]*t +diff --git a/share/extensions/generate_voronoi.py b/share/extensions/generate_voronoi.py +index 4cf541aa20..5184dcbbc6 100755 +--- a/share/extensions/generate_voronoi.py ++++ b/share/extensions/generate_voronoi.py +@@ -183,14 +183,14 @@ class Pattern(inkex.Effect): + # link selected object to pattern + obj = self.selected[self.options.ids[0]] + style = {} +- if obj.attrib.has_key('style'): ++ if 'style' in obj.attrib: + style = simplestyle.parseStyle(obj.attrib['style']) + style['fill'] = 'url(#%s)' % pattern.get('id') + obj.attrib['style'] = simplestyle.formatStyle(style) + if obj.tag == inkex.addNS('g', 'svg'): + for node in obj: + style = {} +- if node.attrib.has_key('style'): ++ if 'style' in node.attrib: + style = simplestyle.parseStyle(node.attrib['style']) + style['fill'] = 'url(#%s)' % pattern.get('id') + node.attrib['style'] = simplestyle.formatStyle(style) +diff --git a/share/extensions/grid_polar.py b/share/extensions/grid_polar.py +index c5a7e7062c..41d099b24f 100755 +--- a/share/extensions/grid_polar.py ++++ b/share/extensions/grid_polar.py +@@ -189,7 +189,7 @@ class Grid_Polar(inkex.Effect): + rmax*sin(angle), rmax*cos(angle), + self.options.a_subdivs_th, 'RadialMinorGridline'+str(i), grid) + +- if self.options.c_dot_dia <> 0: #if a non-zero diameter, draw the centre dot ++ if self.options.c_dot_dia != 0: #if a non-zero diameter, draw the centre dot + draw_SVG_circle(self.options.c_dot_dia /2.0, + 0, 0, 0, '#000000', 'CentreDot', grid) + +diff --git a/share/extensions/hpgl_input.py b/share/extensions/hpgl_input.py +index 13d6d00ecc..37607358bc 100755 +--- a/share/extensions/hpgl_input.py ++++ b/share/extensions/hpgl_input.py +@@ -59,7 +59,7 @@ except Exception as inst: + exit(1) + else: + type, value, traceback = sys.exc_info() +- raise ValueError, ("", type, value), traceback ++ raise ValueError("", type, value).with_traceback(traceback) + + # issue warning if unknown commands where found + if 'UNKNOWN_COMMANDS' in warnings: +diff --git a/share/extensions/hpgl_output.py b/share/extensions/hpgl_output.py +index f593e9cf50..20ec363fde 100755 +--- a/share/extensions/hpgl_output.py ++++ b/share/extensions/hpgl_output.py +@@ -58,7 +58,7 @@ class HpglOutput(inkex.Effect): + return + else: + type, value, traceback = sys.exc_info() +- raise ValueError, ("", type, value), traceback ++ raise ValueError("", type, value).with_traceback(traceback) + # convert raw HPGL to HPGL + hpglInit = 'IN' + if self.options.force > 0: +diff --git a/share/extensions/interp.py b/share/extensions/interp.py +index fd80ab4128..1754e82c55 100755 +--- a/share/extensions/interp.py ++++ b/share/extensions/interp.py +@@ -152,7 +152,7 @@ class Interp(inkex.Effect): + sst = copy.deepcopy(styles[sorted_ids[i-1]]) + est = copy.deepcopy(styles[sorted_ids[i]]) + basestyle = copy.deepcopy(sst) +- if basestyle.has_key('stroke-width'): ++ if 'stroke-width' in basestyle: + basestyle['stroke-width'] = self.tweenstyleunit('stroke-width',sst,est,0) + + #prepare for experimental style tweening +diff --git a/share/extensions/jessyInk_autoTexts.py b/share/extensions/jessyInk_autoTexts.py +index 2c52964da9..a865a2aec2 100755 +--- a/share/extensions/jessyInk_autoTexts.py ++++ b/share/extensions/jessyInk_autoTexts.py +@@ -59,7 +59,7 @@ class JessyInk_AutoTexts(inkex.Effect): + elif self.options.autoText == "numberOfSlides": + nodes[0].set("{" + inkex.NSS["jessyink"] + "}autoText","numberOfSlides") + else: +- if nodes[0].attrib.has_key("{" + inkex.NSS["jessyink"] + "}autoText"): ++ if "{" + inkex.NSS["jessyink"] + "}autoText" in nodes[0].attrib: + del nodes[0].attrib["{" + inkex.NSS["jessyink"] + "}autoText"] + + # Create effect instance +diff --git a/share/extensions/jessyInk_effects.py b/share/extensions/jessyInk_effects.py +index dc56d3a75e..89a8286c7f 100755 +--- a/share/extensions/jessyInk_effects.py ++++ b/share/extensions/jessyInk_effects.py +@@ -55,19 +55,19 @@ class JessyInk_Effects(inkex.Effect): + if (self.options.effectIn == "appear") or (self.options.effectIn == "fade") or (self.options.effectIn == "pop"): + node.set("{" + inkex.NSS["jessyink"] + "}effectIn","name:" + self.options.effectIn + ";order:" + self.options.effectInOrder + ";length:" + str(int(self.options.effectInDuration * 1000))) + # Remove possible view argument. +- if node.attrib.has_key("{" + inkex.NSS["jessyink"] + "}view"): ++ if "{" + inkex.NSS["jessyink"] + "}view" in node.attrib: + del node.attrib["{" + inkex.NSS["jessyink"] + "}view"] + else: +- if node.attrib.has_key("{" + inkex.NSS["jessyink"] + "}effectIn"): ++ if "{" + inkex.NSS["jessyink"] + "}effectIn" in node.attrib: + del node.attrib["{" + inkex.NSS["jessyink"] + "}effectIn"] + + if (self.options.effectOut == "appear") or (self.options.effectOut == "fade") or (self.options.effectOut == "pop"): + node.set("{" + inkex.NSS["jessyink"] + "}effectOut","name:" + self.options.effectOut + ";order:" + self.options.effectOutOrder + ";length:" + str(int(self.options.effectOutDuration * 1000))) + # Remove possible view argument. +- if node.attrib.has_key("{" + inkex.NSS["jessyink"] + "}view"): ++ if "{" + inkex.NSS["jessyink"] + "}view" in node.attrib: + del node.attrib["{" + inkex.NSS["jessyink"] + "}view"] + else: +- if node.attrib.has_key("{" + inkex.NSS["jessyink"] + "}effectOut"): ++ if "{" + inkex.NSS["jessyink"] + "}effectOut" in node.attrib: + del node.attrib["{" + inkex.NSS["jessyink"] + "}effectOut"] + + # Create effect instance +diff --git a/share/extensions/jessyInk_export.py b/share/extensions/jessyInk_export.py +index 1c7cc8c371..a08cfb6ddb 100755 +--- a/share/extensions/jessyInk_export.py ++++ b/share/extensions/jessyInk_export.py +@@ -53,7 +53,7 @@ def dictToPropStr(dictio): + def setStyle(node, propKey, propValue): + props = {} + +- if node.attrib.has_key("style"): ++ if "style" in node.attrib: + props = propStrToDict(node.get("style")) + + props[propKey] = propValue +diff --git a/share/extensions/jessyInk_summary.py b/share/extensions/jessyInk_summary.py +index c5be47a49f..9010483f3d 100755 +--- a/share/extensions/jessyInk_summary.py ++++ b/share/extensions/jessyInk_summary.py +@@ -97,7 +97,7 @@ class JessyInk_Summary(inkex.Effect): + if transitionInAttribute: + transInDict = propListToDict(propStrToList(transitionInAttribute)) + +- if (transInDict["name"] != "appear") and transInDict.has_key("length"): ++ if (transInDict["name"] != "appear") and "length" in transInDict: + inkex.errormsg(_("{0}Transition in: {1} ({2!s} s)").format(prefix, transInDict["name"], int(transInDict["length"]) / 1000.0)) + else: + inkex.errormsg(_("{0}Transition in: {1}").format(prefix, transInDict["name"])) +@@ -106,7 +106,7 @@ class JessyInk_Summary(inkex.Effect): + if transitionOutAttribute: + transOutDict = propListToDict(propStrToList(transitionOutAttribute)) + +- if (transOutDict["name"] != "appear") and transOutDict.has_key("length"): ++ if (transOutDict["name"] != "appear") and "length" in transOutDict: + inkex.errormsg(_("{0}Transition out: {1} ({2!s} s)").format(prefix, transOutDict["name"], int(transOutDict["length"]) / 1000.0)) + else: + inkex.errormsg(_("{0}Transition out: {1}").format(prefix, transOutDict["name"])) +@@ -130,7 +130,7 @@ class JessyInk_Summary(inkex.Effect): + dictio["id"] = effectNode.get("id") + dictio["type"] = "effect" + +- if not effects.has_key(dictio["order"]): ++ if dictio["order"] not in effects: + effects[dictio["order"]] = [] + + effects[dictio["order"]].append(dictio) +@@ -141,7 +141,7 @@ class JessyInk_Summary(inkex.Effect): + dictio["id"] = effectNode.get("id") + dictio["type"] = "effect" + +- if not effects.has_key(dictio["order"]): ++ if dictio["order"] not in effects: + effects[dictio["order"]] = [] + + effects[dictio["order"]].append(dictio) +@@ -151,7 +151,7 @@ class JessyInk_Summary(inkex.Effect): + dictio["id"] = viewNode.get("id") + dictio["type"] = "view" + +- if not effects.has_key(dictio["order"]): ++ if dictio["order"] not in effects: + effects[dictio["order"]] = [] + + effects[dictio["order"]].append(dictio) +@@ -182,7 +182,7 @@ class JessyInk_Summary(inkex.Effect): + if item["name"] != "appear": + tmpStr += _(" using effect \"{0}\"").format(item["name"]) + +- if item.has_key("length"): ++ if "length" in item: + tmpStr += _(" in {0!s} s").format(int(item["length"]) / 1000.0) + + inkex.errormsg(tmpStr + ".\n") +diff --git a/share/extensions/jessyInk_video.py b/share/extensions/jessyInk_video.py +index bd20d837f1..cf5052c446 100755 +--- a/share/extensions/jessyInk_video.py ++++ b/share/extensions/jessyInk_video.py +@@ -86,15 +86,15 @@ def findInternalLinks(node, docRoot, nodeDict = {}): + for entry in re.findall("url\(#.*\)", etree.tostring(node)): + linkId = entry[5:len(entry) - 1] + +- if not nodeDict.has_key(linkId): ++ if linkId not in nodeDict: + nodeDict[linkId] = deepcopy(docRoot.xpath("//*[@id='" + linkId + "']", namespaces=inkex.NSS)[0]) + nodeDict = findInternalLinks(nodeDict[linkId], docRoot, nodeDict) + + for entry in node.iter(): +- if entry.attrib.has_key('{' + inkex.NSS['xlink'] + '}href'): ++ if '{' + inkex.NSS['xlink'] + '}href' in entry.attrib: + linkId = entry.attrib['{' + inkex.NSS['xlink'] + '}href'][1:len(entry.attrib['{' + inkex.NSS['xlink'] + '}href'])] + +- if not nodeDict.has_key(linkId): ++ if linkId not in nodeDict: + nodeDict[linkId] = deepcopy(docRoot.xpath("//*[@id='" + linkId + "']", namespaces=inkex.NSS)[0]) + nodeDict = findInternalLinks(nodeDict[linkId], docRoot, nodeDict) + +@@ -112,7 +112,7 @@ def getNewId(prefix, docRoot): + + def deleteIds(node): + for entry in node.iter(): +- if entry.attrib.has_key('id'): ++ if 'id' in entry.attrib: + del entry.attrib['id'] + + # Create effect instance +diff --git a/share/extensions/jessyInk_view.py b/share/extensions/jessyInk_view.py +index 37a30758f0..d020263db5 100755 +--- a/share/extensions/jessyInk_view.py ++++ b/share/extensions/jessyInk_view.py +@@ -90,13 +90,13 @@ class JessyInk_Effects(inkex.Effect): + rect.set("{" + inkex.NSS["jessyink"] + "}view","name:view;order:" + self.options.viewOrder + ";length:" + str(int(self.options.viewDuration * 1000))) + + # Remove possible effect arguments. +- if rect.attrib.has_key("{" + inkex.NSS["jessyink"] + "}effectIn"): ++ if "{" + inkex.NSS["jessyink"] + "}effectIn" in rect.attrib: + del rect.attrib["{" + inkex.NSS["jessyink"] + "}effectIn"] + +- if rect.attrib.has_key("{" + inkex.NSS["jessyink"] + "}effectOut"): ++ if "{" + inkex.NSS["jessyink"] + "}effectOut" in rect.attrib: + del rect.attrib["{" + inkex.NSS["jessyink"] + "}effectOut"] + else: +- if node.attrib.has_key("{" + inkex.NSS["jessyink"] + "}view"): ++ if "{" + inkex.NSS["jessyink"] + "}view" in node.attrib: + del node.attrib["{" + inkex.NSS["jessyink"] + "}view"] + + # Create effect instance +diff --git a/share/extensions/markers_strokepaint.py b/share/extensions/markers_strokepaint.py +index d922ef474e..34e2216de1 100755 +--- a/share/extensions/markers_strokepaint.py ++++ b/share/extensions/markers_strokepaint.py +@@ -123,7 +123,7 @@ class MyEffect(inkex.Effect): + stroke = "none"; + + for mprop in mprops: +- if style.has_key(mprop) and style[mprop] != 'none'and style[mprop][:5] == 'url(#': ++ if mprop in style and style[mprop] != 'none'and style[mprop][:5] == 'url(#': + marker_id = style[mprop][5:-1] + + try: +diff --git a/share/extensions/merge_styles.py b/share/extensions/merge_styles.py +index cdd7b5ed58..d76333ae04 100755 +--- a/share/extensions/merge_styles.py ++++ b/share/extensions/merge_styles.py +@@ -56,7 +56,7 @@ class Style(dict): + def add(self, c, el): + self.total.append( (c, el) ) + for name,value in c.iteritems(): +- if not self.has_key(name): ++ if name not in self: + self[name] = value + if self[name] == value: + self.weights[name] += 1 +@@ -76,7 +76,7 @@ class Style(dict): + def __eq__(self, o): + """Not equals, prefer to overload 'in' but that doesn't seem possible""" + for arg in self.keys(): +- if o.has_key(arg) and self[arg] != o[arg]: ++ if arg in o and self[arg] != o[arg]: + return False + return True + +@@ -122,7 +122,7 @@ class MergeStyles(inkex.Effect): + st.remove(common.keys()) + el.attrib['style'] = st.to_str("") + +- olds = el.attrib.has_key('class') and el.attrib['class'].split() or [] ++ olds = 'class' in el.attrib and el.attrib['class'].split() or [] + if newclass not in olds: + olds.append(newclass) + el.attrib['class'] = ' '.join(olds) +diff --git a/share/extensions/pathmodifier.py b/share/extensions/pathmodifier.py +index bf45dd77a2..01c9a63845 100755 +--- a/share/extensions/pathmodifier.py ++++ b/share/extensions/pathmodifier.py +@@ -129,7 +129,7 @@ class PathModifier(inkex.Effect): + newNode = self.document.getroot().xpath(path, namespaces=inkex.NSS)[0] + return newNode + else: +- raise AssertionError, "Trying to follow empty xlink.href attribute." ++ raise AssertionError("Trying to follow empty xlink.href attribute.") + + def unlinkClone(self,node,doReplace): + if node.tag == inkex.addNS('use','svg') or node.tag=='use': +@@ -144,7 +144,7 @@ class PathModifier(inkex.Effect): + + return newNode + else: +- raise AssertionError, "Only clones can be unlinked..." ++ raise AssertionError("Only clones can be unlinked...") + + + +diff --git a/share/extensions/pixelsnap.py b/share/extensions/pixelsnap.py +index 1628229200..2d2ccf834a 100755 +--- a/share/extensions/pixelsnap.py ++++ b/share/extensions/pixelsnap.py +@@ -470,7 +470,7 @@ class PixelSnapEffect(inkex.Effect): + for e in elem: + try: + self.pixel_snap(e, transform) +- except TransformError, e: ++ except TransformError as e: + print >>sys.stderr, e + return + +@@ -480,7 +480,7 @@ class PixelSnapEffect(inkex.Effect): + self.snap_transform(elem) + try: + self.snap_stroke(elem, parent_transform) +- except TransformError, e: ++ except TransformError as e: + print >>sys.stderr, e + + if elemtype(elem, 'path'): +@@ -498,7 +498,7 @@ class PixelSnapEffect(inkex.Effect): + for id, elem in self.selected.iteritems(): + try: + self.pixel_snap(elem) +- except TransformError, e: ++ except TransformError as e: + print >>sys.stderr, e + + +diff --git a/share/extensions/plotter.py b/share/extensions/plotter.py +index 800142bb2b..4af4d97963 100755 +--- a/share/extensions/plotter.py ++++ b/share/extensions/plotter.py +@@ -69,7 +69,7 @@ class Plot(inkex.Effect): + return 1 + else: + type, value, traceback = sys.exc_info() +- raise ValueError, ('', type, value), traceback ++ raise ValueError('', type, value).with_traceback(traceback) + # TODO: Get preview to work. This requires some work on the C++ side to be able to determine if it is + # a preview or a final run. (Remember to set to true) + ''' +@@ -142,7 +142,7 @@ class Plot(inkex.Effect): + # gracefully exit script when pySerial is missing + try: + import serial +- except ImportError, e: ++ except ImportError as e: + inkex.errormsg(_("pySerial is not installed. Please follow these steps:") + + "\n\n" + _("1. Download and extract (unzip) this file to your local harddisk:") + + "\n" + " https://pypi.python.org/packages/source/p/pyserial/pyserial-2.7.tar.gz" +@@ -201,7 +201,7 @@ class Plot(inkex.Effect): + return + else: + type, value, traceback = sys.exc_info() +- raise ValueError, ('', type, value), traceback ++ raise ValueError('', type, value).with_traceback(traceback) + # send data to plotter + mySerial.write(self.hpgl) + mySerial.read(2) +diff --git a/share/extensions/print_win32_vector.py b/share/extensions/print_win32_vector.py +index 19c4ccb7eb..a65886fc1f 100755 +--- a/share/extensions/print_win32_vector.py ++++ b/share/extensions/print_win32_vector.py +@@ -58,13 +58,13 @@ class MyEffect(inkex.Effect): + style = node.get('style') + if style: + style = simplestyle.parseStyle(style) +- if style.has_key('stroke'): ++ if 'stroke' in style: + if style['stroke'] and style['stroke'] != 'none' and style['stroke'][0:3] != 'url': + rgb = simplestyle.parseColor(style['stroke']) +- if style.has_key('stroke-width'): ++ if 'stroke-width' in style: + stroke = self.unittouu(style['stroke-width'])/self.unittouu('1px') + stroke = int(stroke*self.scale) +- if style.has_key('fill'): ++ if 'fill' in style: + if style['fill'] and style['fill'] != 'none' and style['fill'][0:3] != 'url': + fill = simplestyle.parseColor(style['fill']) + fillcolor = fill[0] + 256*fill[1] + 256*256*fill[2] +@@ -152,7 +152,7 @@ class MyEffect(inkex.Effect): + style = group.get('style') + if style: + style = simplestyle.parseStyle(style) +- if style.has_key('display'): ++ if 'display' in style: + if style['display'] == 'none' and self.visibleLayers: + return + trans = group.get('transform') +diff --git a/share/extensions/render_alphabetsoup.py b/share/extensions/render_alphabetsoup.py +index 4aa6af4c7d..c529e6202c 100755 +--- a/share/extensions/render_alphabetsoup.py ++++ b/share/extensions/render_alphabetsoup.py +@@ -328,7 +328,7 @@ def randomize_input_string(tokens, zoom ): # generate a glyph starting fr + for i in range(0,len(tokens)): + char = tokens[i] + #if ( re.match("[a-zA-Z0-9?]", char)): +- if ( alphabet.has_key(char)): ++ if ( char in alphabet): + if ((i > 0) and (char == tokens[i-1])): # if this letter matches previous letter + imagelist.append(imagelist[len(stack)-1])# make them the same image + else: # generate image for letter +diff --git a/share/extensions/run_command.py b/share/extensions/run_command.py +index 950e9ed7cd..d760567a19 100755 +--- a/share/extensions/run_command.py ++++ b/share/extensions/run_command.py +@@ -66,7 +66,7 @@ def run(command_format, prog_name): + msg = "%s failed:\n%s\n%s\n" % (prog_name, out, err) + elif err: + sys.stderr.write("%s executed but logged the following error:\n%s\n%s\n" % (prog_name, out, err)) +- except Exception, inst: ++ except Exception as inst: + msg = "Error attempting to run %s: %s" % (prog_name, str(inst)) + + # If successful, copy the output file to stdout. +@@ -79,7 +79,7 @@ def run(command_format, prog_name): + data = f.read() + sys.stdout.write(data) + f.close() +- except IOError, inst: ++ except IOError as inst: + msg = "Error reading temporary file: %s" % str(inst) + + # Clean up. +diff --git a/share/extensions/simplepath.py b/share/extensions/simplepath.py +index 5d99e46e76..a83cbb4529 100644 +--- a/share/extensions/simplepath.py ++++ b/share/extensions/simplepath.py +@@ -48,7 +48,7 @@ def lexPath(d): + offset = m.end() + continue + #TODO: create new exception +- raise Exception, 'Invalid path data!' ++ raise Exception('Invalid path data!') + ''' + pathdefs = {commandfamily: + [ +@@ -93,7 +93,7 @@ def parsePath(d): + needParam = True + if isCommand: + if not lastCommand and token.upper() != 'M': +- raise Exception, 'Invalid path, must begin with moveto.' ++ raise Exception('Invalid path, must begin with moveto.') + else: + command = token + else: +@@ -106,16 +106,16 @@ def parsePath(d): + else: + command = pathdefs[lastCommand.upper()][0].lower() + else: +- raise Exception, 'Invalid path, no initial command.' ++ raise Exception('Invalid path, no initial command.') + numParams = pathdefs[command.upper()][1] + while numParams > 0: + if needParam: + try: + token, isCommand = lexer.next() + if isCommand: +- raise Exception, 'Invalid number of parameters' ++ raise Exception('Invalid number of parameters') + except StopIteration: +- raise Exception, 'Unexpected end of path' ++ raise Exception('Unexpected end of path') + cast = pathdefs[command.upper()][2][-numParams] + param = cast(token) + if command.islower(): +diff --git a/share/extensions/simpletransform.py b/share/extensions/simpletransform.py +index f6f68d2be6..9cb7651857 100644 +--- a/share/extensions/simpletransform.py ++++ b/share/extensions/simpletransform.py +@@ -131,7 +131,7 @@ def applyTransformToPath(mat,path): + def fuseTransform(node): + if node.get('d')==None: + #FIXME: how do you raise errors? +- raise AssertionError, 'can not fuse "transform" of elements that have no "d" attribute' ++ raise AssertionError('can not fuse "transform" of elements that have no "d" attribute') + t = node.get("transform") + if t == None: + return +diff --git a/share/extensions/svg_and_media_zip_output.py b/share/extensions/svg_and_media_zip_output.py +index e021bfd4e3..1a148f8a8a 100755 +--- a/share/extensions/svg_and_media_zip_output.py ++++ b/share/extensions/svg_and_media_zip_output.py +@@ -160,12 +160,12 @@ class CompressedMediaOutput(inkex.Effect): + if not s: + return fonts + +- if s.has_key('font-family'): +- if s.has_key('font-weight'): ++ if 'font-family' in s: ++ if 'font-weight' in s: + fonts.append(s['font-family'] + ' ' + s['font-weight']) + else: + fonts.append(s['font-family']) +- elif s.has_key('-inkscape-font-specification'): ++ elif '-inkscape-font-specification' in s: + fonts.append(s['-inkscape-font-specification']) + return fonts + +diff --git a/share/extensions/synfig_fileformat.py b/share/extensions/synfig_fileformat.py +index 6c93e6b87f..41e6bee38c 100755 +--- a/share/extensions/synfig_fileformat.py ++++ b/share/extensions/synfig_fileformat.py +@@ -204,11 +204,11 @@ def paramType(layer, param, value=None): + if param in layer_params.keys(): + return layer_params[param][0] + else: +- raise Exception, "Invalid parameter type for layer" ++ raise Exception("Invalid parameter type for layer") + else: + # Unknown layer, try to determine parameter type based on value + if value is None: +- raise Exception, "No information for given layer" ++ raise Exception("No information for given layer") + if type(value) == int: + return "integer" + elif type(value) == float: +@@ -221,7 +221,7 @@ def paramType(layer, param, value=None): + elif 0.0 in value.keys(): + return "gradient" + else: +- raise Exception, "Could not automatically determine parameter type" ++ raise Exception("Could not automatically determine parameter type") + elif type(value) == list: + if len(value) == 2: + return "vector" +diff --git a/share/extensions/synfig_output.py b/share/extensions/synfig_output.py +index bcd1eeaf32..5a36934aae 100755 +--- a/share/extensions/synfig_output.py ++++ b/share/extensions/synfig_output.py +@@ -393,7 +393,7 @@ class SynfigDocument(object): + for layer in value: + el.append(layer) + else: +- raise AssertionError, "Unsupported param type %s" % (param_type) ++ raise AssertionError("Unsupported param type %s" % (param_type)) + + if guid: + el.set("guid", guid) +@@ -446,7 +446,7 @@ class SynfigDocument(object): + guid -- guid of the parameter value + """ + if modify_linked: +- raise AssertionError, "Modifying linked parameters is not supported" ++ raise AssertionError("Modifying linked parameters is not supported") + + layer_type = layer.get("type") + assert layer_type, "Layer does not have a type" +@@ -463,7 +463,7 @@ class SynfigDocument(object): + if len(existing) == 0: + self.build_param(layer, name, value, param_type, guid) + elif len(existing) > 1: +- raise AssertionError, "Found multiple parameters with the same name" ++ raise AssertionError("Found multiple parameters with the same name") + else: + new_param = self.build_param(None, name, value, param_type, guid) + layer.replace(existing[0], new_param) +@@ -505,7 +505,7 @@ class SynfigDocument(object): + elif param_type == "integer": + return int(param[0].get("integer", "0")) + else: +- raise Exception, "Getting this type of parameter not yet implemented" ++ raise Exception("Getting this type of parameter not yet implemented") + + ### Global defs, and related + +@@ -530,7 +530,7 @@ class SynfigDocument(object): + elif link != "": + gradient["link"] = link + else: +- raise MalformedSVGError, "Gradient has neither stops nor link" ++ raise MalformedSVGError("Gradient has neither stops nor link") + self.gradients[gradient_id] = gradient + + def add_radial_gradient(self, gradient_id, center, radius, focus, mtx=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], stops=[], link="", spread_method="pad"): +@@ -549,7 +549,7 @@ class SynfigDocument(object): + elif link != "": + gradient["link"] = link + else: +- raise MalformedSVGError, "Gradient has neither stops nor link" ++ raise MalformedSVGError("Gradient has neither stops nor link") + self.gradients[gradient_id] = gradient + + def get_gradient(self, gradient_id): +@@ -598,7 +598,7 @@ class SynfigDocument(object): + + # If the gradient does have a link, find the color stops recursively + if gradient["link"] not in self.gradients.keys(): +- raise MalformedSVGError, "Linked gradient ID not found" ++ raise MalformedSVGError("Linked gradient ID not found") + + linked_gradient = self.get_gradient(gradient["link"]) + gradient["stops"] = linked_gradient["stops"] +@@ -772,7 +772,7 @@ class SynfigDocument(object): + Returns: list of layers + """ + if filter_id not in self.filters.keys(): +- raise MalformedSVGError, "Filter %s not found" % filter_id ++ raise MalformedSVGError("Filter %s not found" % filter_id) + + try: + ret = self.filters[filter_id](self, layers, is_end) +@@ -907,7 +907,7 @@ def path_to_bline_list(path_d, nodetypes=None, mtx=[[1.0, 0.0, 0.0], [0.0, 1.0, + for s in path: + cmd, params = s + if cmd != "M" and bline_list == []: +- raise MalformedSVGError, "Bad path data: path doesn't start with moveto, %s, %s" % (s, path) ++ raise MalformedSVGError("Bad path data: path doesn't start with moveto, %s, %s" % (s, path)) + elif cmd == "M": + # Add previous point to subpath + if last: +@@ -1171,7 +1171,7 @@ class SynfigExport(SynfigPrep): + style = extract_style(stop) + stops[offset] = extract_color(style, "stop-color", "stop-opacity") + else: +- raise MalformedSVGError, "Child of gradient is not a stop" ++ raise MalformedSVGError("Child of gradient is not a stop") + + return stops + +@@ -1224,7 +1224,7 @@ class SynfigExport(SynfigPrep): + elif mode == "lighten": + blend_method = "brighten" + else: +- raise MalformedSVGError, "Invalid blend method" ++ raise MalformedSVGError("Invalid blend method") + + if child.get("in2") == "BackgroundImage": + encapsulate_result = False +@@ -1342,7 +1342,7 @@ if __name__ == '__main__': + try: + e = SynfigExport() + e.affect(output=False) +- except MalformedSVGError, e: ++ except MalformedSVGError as e: + errormsg(e) + + # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99 +diff --git a/share/extensions/synfig_prepare.py b/share/extensions/synfig_prepare.py +index ebc50fd8e1..3785920ae5 100755 +--- a/share/extensions/synfig_prepare.py ++++ b/share/extensions/synfig_prepare.py +@@ -97,7 +97,7 @@ class InkscapeActionGroup(object): + """ + node_id = node.get("id", None) + if node_id is None: +- raise MalformedSVGError, "Node has no id" ++ raise MalformedSVGError("Node has no id") + self.select_id(node_id) + + def select_nodes(self, nodes): +@@ -293,7 +293,7 @@ def split_fill_and_stroke(path_node): + d = attribs["d"] + del attribs["d"] + else: +- raise AssertionError, "Cannot split stroke and fill of non-path element" ++ raise AssertionError("Cannot split stroke and fill of non-path element") + + if addNS("nodetypes", "sodipodi") in attribs.keys(): + nodetypes = attribs[addNS("nodetypes", "sodipodi")] +@@ -494,7 +494,7 @@ if __name__ == '__main__': + try: + e = SynfigPrep() + e.affect() +- except MalformedSVGError, e: ++ except MalformedSVGError as e: + errormsg(e) + + +diff --git a/share/extensions/text_braille.py b/share/extensions/text_braille.py +index ba2e3d81b1..d778f19eac 100755 +--- a/share/extensions/text_braille.py ++++ b/share/extensions/text_braille.py +@@ -37,7 +37,7 @@ class C(chardataeffect.CharDataEffect): + def process_chardata(self,text, line, par): + r = "" + for c in text: +- if convert_table.has_key(c.lower()): ++ if c.lower() in convert_table: + r = r + convert_table[c.lower()] + else: + r = r + c +diff --git a/share/extensions/uniconv_output.py b/share/extensions/uniconv_output.py +index de6b6409ff..170477540a 100755 +--- a/share/extensions/uniconv_output.py ++++ b/share/extensions/uniconv_output.py +@@ -63,7 +63,7 @@ def run(command_format, prog_name, uniconv_format): + msg = "Neither subprocess.Popen nor popen2.Popen3 is available" + if rc and msg is None: + msg = "%s failed:\n%s\n%s\n" % (prog_name, out, err) +- except Exception, inst: ++ except Exception as inst: + msg = "Error attempting to run %s: %s" % (prog_name, str(inst)) + + # If successful, copy the output file to stdout. +@@ -76,7 +76,7 @@ def run(command_format, prog_name, uniconv_format): + data = f.read() + sys.stdout.write(data) + f.close() +- except IOError, inst: ++ except IOError as inst: + msg = "Error reading temporary file: %s" % str(inst) + + # Clean up. +diff --git a/share/extensions/voronoi2svg.py b/share/extensions/voronoi2svg.py +index 5232fb81ea..a180eaa583 100644 +--- a/share/extensions/voronoi2svg.py ++++ b/share/extensions/voronoi2svg.py +@@ -258,7 +258,7 @@ class Voronoi2svg(inkex.Effect): + pts.append(Point(pt[0],pt[1])) + fill = 'none' + if self.options.delaunayFillOptions != "delaunay-no-fill": +- if node.attrib.has_key('style'): ++ if 'style' in node.attrib: + style = node.get('style') # fixme: this will break for presentation attributes! + if style: + declarations = style.split(';') +diff --git a/share/extensions/webslicer_export.py b/share/extensions/webslicer_export.py +index 9acb9d6c37..28c4f9ba82 100755 +--- a/share/extensions/webslicer_export.py ++++ b/share/extensions/webslicer_export.py +@@ -63,7 +63,7 @@ class WebSlicer_Export(WebSlicer_Effect): + # Try to create it: + try: + os.makedirs( self.options.dir ) +- except Exception, e: ++ except Exception as e: + inkex.errormsg( _('Can\'t create "%s".') % self.options.dir ) + inkex.errormsg( _('Error: %s') % e ) + return {'error':'Can\'t create the directory to export.'} +-- +2.21.0 + + +From cac83ec8b8d399340e9952b3438bc62318293cb3 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 09:33:54 +0100 +Subject: [PATCH 02/17] extensions 2to3: next basestring + +--- + share/extensions/simplepath.py | 4 ++-- + share/extensions/tar_layers.py | 3 +++ + share/extensions/voronoi.py | 2 +- + 3 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/share/extensions/simplepath.py b/share/extensions/simplepath.py +index a83cbb4529..0ee958b9f3 100644 +--- a/share/extensions/simplepath.py ++++ b/share/extensions/simplepath.py +@@ -86,7 +86,7 @@ def parsePath(d): + + while 1: + try: +- token, isCommand = lexer.next() ++ token, isCommand = next(lexer) + except StopIteration: + break + params = [] +@@ -111,7 +111,7 @@ def parsePath(d): + while numParams > 0: + if needParam: + try: +- token, isCommand = lexer.next() ++ token, isCommand = next(lexer) + if isCommand: + raise Exception('Invalid number of parameters') + except StopIteration: +diff --git a/share/extensions/tar_layers.py b/share/extensions/tar_layers.py +index 3ba5aa55e1..186e3c4689 100755 +--- a/share/extensions/tar_layers.py ++++ b/share/extensions/tar_layers.py +@@ -29,6 +29,9 @@ import StringIO + import calendar + import time + ++if sys.version_info[0] > 2: ++ basestring = str ++ + # Inkscape Libraries + import inkex + import simplestyle +diff --git a/share/extensions/voronoi.py b/share/extensions/voronoi.py +index ac2c13f8fa..272f074dd9 100644 +--- a/share/extensions/voronoi.py ++++ b/share/extensions/voronoi.py +@@ -700,7 +700,7 @@ class SiteList(object): + def __iter__(this): return this + def next(this): + try: +- return this.generator.next() ++ return next(this.generator) + except StopIteration: + return None + +-- +2.21.0 + + +From 13d4f99f073be2228f1fb15b4434579896480818 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 09:44:31 +0100 +Subject: [PATCH 03/17] extensions 2to3: print + +--- + share/extensions/bezmisc.py | 2 +- + share/extensions/dm2svg.py | 16 ++++--- + share/extensions/dpiswitcher.py | 18 ++++---- + share/extensions/dxf_outlines.py | 2 +- + share/extensions/eqtexsvg.py | 10 +++-- + share/extensions/export_gimp_palette.py | 4 +- + share/extensions/hpgl_output.py | 2 +- + share/extensions/pixelsnap.py | 7 +-- + share/extensions/render_barcode.py | 4 +- + share/extensions/render_barcode_qrcode.py | 4 +- + share/extensions/voronoi.py | 52 ++++++++++++----------- + 11 files changed, 65 insertions(+), 56 deletions(-) + +diff --git a/share/extensions/bezmisc.py b/share/extensions/bezmisc.py +index c36e8e1b4e..274f87a854 100755 +--- a/share/extensions/bezmisc.py ++++ b/share/extensions/bezmisc.py +@@ -268,7 +268,7 @@ if __name__ == '__main__': + print s, st + ''' + for curve in curves: +- print beziertatlength(curve,0.5) ++ print(beziertatlength(curve,0.5)) + + + # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99 +diff --git a/share/extensions/dm2svg.py b/share/extensions/dm2svg.py +index 74afe6adf8..a8784a3002 100755 +--- a/share/extensions/dm2svg.py ++++ b/share/extensions/dm2svg.py +@@ -21,13 +21,15 @@ along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + ''' + ++from __future__ import print_function ++ + import struct + + def process_file(filename): + try: + f = open(filename, 'rb') + except IOError as e: +- print >> sys.stderr, 'Unable to open %s: %s' % (filename, e) ++ print('Unable to open %s: %s' % (filename, e), file=sys.stderr) + return + + with f: +@@ -73,10 +75,10 @@ def process_file(filename): + points = ' '.join(','.join(map(str, e)) for e in coords) + svg_element = '' % (points, timestamp) + else: +- print >> sys.stderr, 'Unsupported tag: %s\n' % tag ++ print('Unsupported tag: %s\n' % tag, file=sys.stderr) + + # Emit the footer to finish it off +- print '\n\n' ++ print('\n\n') + + + def read_point(f, ymax): +@@ -90,7 +92,7 @@ def read_point(f, ymax): + def emit_header(f): + id, version, width, height, page_type = struct.unpack('<32sBHHBxx', f.read(40)) + +- print ''' ++ print(''' + + + +-''' % locals() ++''' % locals()) + + return height + + + def emit_element(message): + if message: +- print '%s\n' % message ++ print('%s\n' % message) + + + if __name__ == '__main__': +@@ -123,6 +125,6 @@ if __name__ == '__main__': + if len(sys.argv) == 2: + process_file(sys.argv[1]) + else: +- print >> sys.stderr, 'Usage: %s ' % sys.argv[0] ++ print('Usage: %s ' % sys.argv[0], file=sys.stderr) + + # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99 +diff --git a/share/extensions/dpiswitcher.py b/share/extensions/dpiswitcher.py +index dcffa202db..47bb4458b6 100644 +--- a/share/extensions/dpiswitcher.py ++++ b/share/extensions/dpiswitcher.py +@@ -373,34 +373,34 @@ class DPISwitcher(inkex.Effect): + sys.stdout = sys.stderr + svg = self.document.getroot() + if self.options.action == '"page_info"': +- print ":::SVG document related info:::" +- print "version: " + str(svg.get(inkex.addNS('version',u'inkscape'))) ++ print(":::SVG document related info:::") ++ print("version: " + str(svg.get(inkex.addNS('version',u'inkscape')))) + width = svg.get('width') + if width: +- print "width: " + width ++ print("width: " + width) + height = svg.get('height') + if height: +- print "height: " + height ++ print("height: " + height) + viewBox = svg.get('viewBox') + if viewBox: +- print "viewBox: " + viewBox ++ print("viewBox: " + viewBox) + namedview = svg.find(inkex.addNS('namedview', 'sodipodi')) + docunits= namedview.get(inkex.addNS('document-units', 'inkscape')) + if docunits: +- print "document-units: " + docunits ++ print("document-units: " + docunits) + units = namedview.get('units') + if units: +- print "units: " + units ++ print("units: " + units) + xpathStr = '//sodipodi:guide' + guides = svg.xpath(xpathStr, namespaces=inkex.NSS) + xpathStr = '//inkscape:grid' + if guides: + numberGuides = len(guides) +- print "Document has " + str(numberGuides) + " guides" ++ print("Document has " + str(numberGuides) + " guides") + grids = svg.xpath(xpathStr, namespaces=inkex.NSS) + i = 1 + for grid in grids: +- print "Grid number " + str(i) + ": Units: " + grid.get("units") ++ print("Grid number " + str(i) + ": Units: " + grid.get("units")) + i = i+1 + else: + if self.options.switcher == "0": +diff --git a/share/extensions/dxf_outlines.py b/share/extensions/dxf_outlines.py +index 876f41f5f9..59b136d09c 100755 +--- a/share/extensions/dxf_outlines.py ++++ b/share/extensions/dxf_outlines.py +@@ -99,7 +99,7 @@ class MyEffect(inkex.Effect): + self.d = array([0], float) # knot vector + self.poly = [[0.0,0.0]] # LWPOLYLINE data + def output(self): +- print ''.join(self.dxf) ++ print(''.join(self.dxf)) + def dxf_add(self, str): + self.dxf.append(str.encode(self.options.char_encode)) + def dxf_line(self,csp): +diff --git a/share/extensions/eqtexsvg.py b/share/extensions/eqtexsvg.py +index 99d3c06601..d67004d468 100755 +--- a/share/extensions/eqtexsvg.py ++++ b/share/extensions/eqtexsvg.py +@@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + """ + ++from __future__ import print_function ++ + import inkex, os, tempfile, sys, xml.dom.minidom + + def parse_pkgs(pkgstring): +@@ -119,7 +121,7 @@ class EQTEXSVG(inkex.Effect): + os.rmdir(base_dir) + + if self.options.formula == "": +- print >>sys.stderr, "empty LaTeX input. Nothing to be done" ++ print("empty LaTeX input. Nothing to be done", file=sys.stderr) + return + + add_header = parse_pkgs(self.options.packages) +@@ -129,9 +131,9 @@ class EQTEXSVG(inkex.Effect): + try: + os.stat(dvi_file) + except OSError: +- print >>sys.stderr, "invalid LaTeX input:" +- print >>sys.stderr, self.options.formula +- print >>sys.stderr, "temporary files were left in:", base_dir ++ print("invalid LaTeX input:", file=sys.stderr) ++ print(self.options.formula, file=sys.stderr) ++ print("temporary files were left in:", base_dir, file=sys.stderr) + sys.exit(1) + + os.system('dvips -q -f -E -D 600 -y 5000 -o "%s" "%s"' % (ps_file, dvi_file)) +diff --git a/share/extensions/export_gimp_palette.py b/share/extensions/export_gimp_palette.py +index 9c04d6e34c..eaf08781ce 100755 +--- a/share/extensions/export_gimp_palette.py ++++ b/share/extensions/export_gimp_palette.py +@@ -47,10 +47,10 @@ stream = open(sys.argv[-1:][0],'r') + dom = parse(stream) + stream.close() + walk(dom) +-print 'GIMP Palette\nName: %s\n#' % (dom.getElementsByTagName('svg')[0].getAttribute(DOCNAME).split('.')[0]) ++print('GIMP Palette\nName: %s\n#' % (dom.getElementsByTagName('svg')[0].getAttribute(DOCNAME).split('.')[0])) + + for k,v in sorted(colors.items()): +- print k+v ++ print(k+v) + + + # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99 +diff --git a/share/extensions/hpgl_output.py b/share/extensions/hpgl_output.py +index 20ec363fde..812bc693fe 100755 +--- a/share/extensions/hpgl_output.py ++++ b/share/extensions/hpgl_output.py +@@ -70,7 +70,7 @@ class HpglOutput(inkex.Effect): + def output(self): + # print to file + if self.hpgl != '': +- print self.hpgl ++ print(self.hpgl) + + if __name__ == '__main__': + # start extension +diff --git a/share/extensions/pixelsnap.py b/share/extensions/pixelsnap.py +index 2d2ccf834a..96a8617e2f 100755 +--- a/share/extensions/pixelsnap.py ++++ b/share/extensions/pixelsnap.py +@@ -59,6 +59,7 @@ Note: Paths that have curves & arcs on some sides of the bounding box won't + """ + + from __future__ import division ++from __future__ import print_function + + import sys + # *** numpy causes issue #4 on Mac OS 10.6.2. I use it for +@@ -471,7 +472,7 @@ class PixelSnapEffect(inkex.Effect): + try: + self.pixel_snap(e, transform) + except TransformError as e: +- print >>sys.stderr, e ++ print(e, file=sys.stderr) + return + + if not elemtype(elem, ('path', 'rect', 'image')): +@@ -481,7 +482,7 @@ class PixelSnapEffect(inkex.Effect): + try: + self.snap_stroke(elem, parent_transform) + except TransformError as e: +- print >>sys.stderr, e ++ print(e, file=sys.stderr) + + if elemtype(elem, 'path'): + self.snap_path_scale(elem, parent_transform) +@@ -499,7 +500,7 @@ class PixelSnapEffect(inkex.Effect): + try: + self.pixel_snap(elem) + except TransformError as e: +- print >>sys.stderr, e ++ print(e, file=sys.stderr) + + + if __name__ == '__main__': +diff --git a/share/extensions/render_barcode.py b/share/extensions/render_barcode.py +index 63436f03c0..e08ec663b4 100755 +--- a/share/extensions/render_barcode.py ++++ b/share/extensions/render_barcode.py +@@ -78,12 +78,12 @@ def test_barcode(): + ('Upca', '12345678911'), + ('Upce', '123456'), + ): +- print "RENDER TEST: %s" % kind ++ print("RENDER TEST: %s" % kind) + bargen = getBarcode(kind, text=text) + if bargen is not None: + barcode = bargen.generate() + if barcode is not None: +- print inkex.etree.tostring(barcode, pretty_print=True) ++ print(inkex.etree.tostring(barcode, pretty_print=True)) + + + if __name__ == '__main__': +diff --git a/share/extensions/render_barcode_qrcode.py b/share/extensions/render_barcode_qrcode.py +index 062488ca1d..d829eb0604 100755 +--- a/share/extensions/render_barcode_qrcode.py ++++ b/share/extensions/render_barcode_qrcode.py +@@ -1,5 +1,7 @@ + #!/usr/bin/env python + ++from __future__ import print_function ++ + import math, sys + import inkex + from simpletransform import computePointInNode +@@ -1008,7 +1010,7 @@ class QRBitBuffer: + def get(self, index): + bufIndex = math.floor(index / 8) + val = ( (self.buffer[bufIndex] >> (7 - index % 8) ) & 1) == 1 +- print "get ", val ++ print("get ", val) + return ( (self.buffer[bufIndex] >> (7 - index % 8) ) & 1) == 1 + def put(self, num, length): + for i in range(length): +diff --git a/share/extensions/voronoi.py b/share/extensions/voronoi.py +index 272f074dd9..af83007f1a 100644 +--- a/share/extensions/voronoi.py ++++ b/share/extensions/voronoi.py +@@ -29,8 +29,10 @@ + # + ############################################################################# + ++from __future__ import print_function ++ + def usage(): +- print """ ++ print(""" + voronoi - compute Voronoi diagram or Delaunay triangulation + + voronoi [-t -p -d] [filename] +@@ -67,7 +69,7 @@ On unsorted data uniformly distributed in the unit square, voronoi uses about + AUTHOR + Steve J. Fortune (1987) A Sweepline Algorithm for Voronoi Diagrams, + Algorithmica 2, 153-174. +-""" ++""") + + ############################################################################# + # +@@ -123,39 +125,39 @@ class Context(object): + + def outSite(self,s): + if(self.debug): +- print "site (%d) at %f %f" % (s.sitenum, s.x, s.y) ++ print("site (%d) at %f %f" % (s.sitenum, s.x, s.y)) + elif(self.triangulate): + pass + elif(self.plot): + self.circle (s.x, s.y, cradius) + elif(self.doPrint): +- print "s %f %f" % (s.x, s.y) ++ print("s %f %f" % (s.x, s.y)) + + def outVertex(self,s): + self.vertices.append((s.x,s.y)) + if(self.debug): +- print "vertex(%d) at %f %f" % (s.sitenum, s.x, s.y) ++ print("vertex(%d) at %f %f" % (s.sitenum, s.x, s.y)) + elif(self.triangulate): + pass + elif(self.doPrint and not self.plot): +- print "v %f %f" % (s.x,s.y) ++ print("v %f %f" % (s.x,s.y)) + + def outTriple(self,s1,s2,s3): + self.triangles.append((s1.sitenum, s2.sitenum, s3.sitenum)) + if(self.debug): +- print "circle through left=%d right=%d bottom=%d" % (s1.sitenum, s2.sitenum, s3.sitenum) ++ print("circle through left=%d right=%d bottom=%d" % (s1.sitenum, s2.sitenum, s3.sitenum)) + elif(self.triangulate and self.doPrint and not self.plot): +- print "%d %d %d" % (s1.sitenum, s2.sitenum, s3.sitenum) ++ print("%d %d %d" % (s1.sitenum, s2.sitenum, s3.sitenum)) + + def outBisector(self,edge): + self.lines.append((edge.a, edge.b, edge.c)) + if(self.debug): +- print "line(%d) %gx+%gy=%g, bisecting %d %d" % (edge.edgenum, edge.a, edge.b, edge.c, edge.reg[0].sitenum, edge.reg[1].sitenum) ++ print("line(%d) %gx+%gy=%g, bisecting %d %d" % (edge.edgenum, edge.a, edge.b, edge.c, edge.reg[0].sitenum, edge.reg[1].sitenum)) + elif(self.triangulate): + if(self.plot): + self.line(edge.reg[0].x, edge.reg[0].y, edge.reg[1].x, edge.reg[1].y) + elif(self.doPrint and not self.plot): +- print "l %f %f %f" % (edge.a, edge.b, edge.c) ++ print("l %f %f %f" % (edge.a, edge.b, edge.c)) + + def outEdge(self,edge): + sitenumL = -1 +@@ -169,9 +171,9 @@ class Context(object): + if self.plot: + self.clip_line(edge) + elif(self.doPrint): +- print "e %d" % edge.edgenum, +- print " %d " % sitenumL, +- print "%d" % sitenumR ++ print("e %d" % edge.edgenum, end=' ') ++ print(" %d " % sitenumL, end=' ') ++ print("%d" % sitenumR) + + #------------------------------------------------------------------ + def voronoi(siteList,context): +@@ -325,7 +327,7 @@ class Site(object): + self.sitenum = sitenum + + def dump(self): +- print "Site #%d (%g, %g)" % (self.sitenum,self.x,self.y) ++ print("Site #%d (%g, %g)" % (self.sitenum,self.x,self.y)) + + def __cmp__(self,other): + if self.y < other.y: +@@ -360,9 +362,9 @@ class Edge(object): + self.edgenum = 0 + + def dump(self): +- print "(#%d a=%g, b=%g, c=%g)" % (self.edgenum,self.a,self.b,self.c) +- print "ep",self.ep +- print "reg",self.reg ++ print("(#%d a=%g, b=%g, c=%g)" % (self.edgenum,self.a,self.b,self.c)) ++ print("ep",self.ep) ++ print("reg",self.reg) + + def setEndpoint(self, lrFlag, site): + self.ep[lrFlag] = site +@@ -417,15 +419,15 @@ class Halfedge(object): + self.ystar = BIG_FLOAT + + def dump(self): +- print "Halfedge--------------------------" +- print "left: ", self.left +- print "right: ", self.right +- print "edge: ", self.edge +- print "pm: ", self.pm +- print "vertex: ", ++ print("Halfedge--------------------------") ++ print("left: ", self.left) ++ print("right: ", self.right) ++ print("edge: ", self.edge) ++ print("pm: ", self.pm) ++ print("vertex: ", end=' ') + if self.vertex: self.vertex.dump() +- else: print "None" +- print "ystar: ", self.ystar ++ else: print("None") ++ print("ystar: ", self.ystar) + + + def __cmp__(self,other): +-- +2.21.0 + + +From d95b05882ab7e7cb3cd8d1d65a8471018424e892 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 10:15:40 +0100 +Subject: [PATCH 04/17] extensions 2to3: tuple_params + +--- + share/extensions/addnodes.py | 4 +- + share/extensions/bezmisc.py | 34 ++++++++++---- + share/extensions/convert2dashes.py | 4 +- + share/extensions/cspsubdiv.py | 3 +- + share/extensions/draw_from_triangle.py | 15 ++++-- + share/extensions/dxf_outlines.py | 4 +- + share/extensions/gcodetools.py | 46 ++++++++++++++----- + share/extensions/interp.py | 8 +++- + share/extensions/jitternodes.py | 3 +- + share/extensions/measure.py | 8 +++- + share/extensions/motion.py | 3 +- + share/extensions/polyhedron_3d.py | 10 ++-- + share/extensions/pturtle.py | 6 ++- + share/extensions/render_barcode_datamatrix.py | 10 ++-- + share/extensions/straightseg.py | 4 +- + share/extensions/summersnight.py | 3 +- + share/extensions/triangle.py | 10 +++- + share/extensions/wireframe_sphere.py | 4 +- + 18 files changed, 130 insertions(+), 49 deletions(-) + +diff --git a/share/extensions/addnodes.py b/share/extensions/addnodes.py +index 4e57f0185a..a2f70c885f 100755 +--- a/share/extensions/addnodes.py ++++ b/share/extensions/addnodes.py +@@ -27,7 +27,9 @@ import cubicsuperpath, simplestyle, copy, math, re, bezmisc + + def numsegs(csp): + return sum([len(p)-1 for p in csp]) +-def tpoint((x1,y1), (x2,y2), t = 0.5): ++def tpoint(_x1_y1, _x2_y2, t = 0.5): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + return [x1+t*(x2-x1),y1+t*(y2-y1)] + def cspbezsplit(sp1, sp2, t = 0.5): + m1=tpoint(sp1[1],sp1[2],t) +diff --git a/share/extensions/bezmisc.py b/share/extensions/bezmisc.py +index 274f87a854..a563178868 100755 +--- a/share/extensions/bezmisc.py ++++ b/share/extensions/bezmisc.py +@@ -55,8 +55,9 @@ def rootWrapper(a,b,c,d): + return 1.0*(-d/c), + return () + +-def bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))): ++def bezierparameterize(xxx_todo_changeme): + #parametric bezier ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme + x0=bx0 + y0=by0 + cx=3*(bx1-x0) +@@ -69,8 +70,10 @@ def bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))): + return ax,ay,bx,by,cx,cy,x0,y0 + #ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + +-def linebezierintersect(((lx1,ly1),(lx2,ly2)),((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))): ++def linebezierintersect(xxx_todo_changeme1, xxx_todo_changeme2): + #parametric line ++ ((lx1,ly1),(lx2,ly2)) = xxx_todo_changeme1 ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme2 + dd=lx1 + cc=lx2-lx1 + bb=ly1 +@@ -99,19 +102,23 @@ def linebezierintersect(((lx1,ly1),(lx2,ly2)),((bx0,by0),(bx1,by1),(bx2,by2),(bx + retval.append(bezierpointatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),i)) + return retval + +-def bezierpointatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t): ++def bezierpointatt(xxx_todo_changeme3,t): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme3 + ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + x=ax*(t**3)+bx*(t**2)+cx*t+x0 + y=ay*(t**3)+by*(t**2)+cy*t+y0 + return x,y + +-def bezierslopeatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t): ++def bezierslopeatt(xxx_todo_changeme4,t): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme4 + ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + dx=3*ax*(t**2)+2*bx*t+cx + dy=3*ay*(t**2)+2*by*t+cy + return dx,dy + +-def beziertatslope(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),(dy,dx)): ++def beziertatslope(xxx_todo_changeme5, xxx_todo_changeme6): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme5 ++ (dy,dx) = xxx_todo_changeme6 + ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + #quadratic coefficents of slope formula + if dx: +@@ -136,9 +143,12 @@ def beziertatslope(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),(dy,dx)): + retval.append(i) + return retval + +-def tpoint((x1,y1),(x2,y2),t): ++def tpoint(_x1_y1, _x2_y2, t): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + return x1+t*(x2-x1),y1+t*(y2-y1) +-def beziersplitatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t): ++def beziersplitatt(xxx_todo_changeme9,t): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme9 + m1=tpoint((bx0,by0),(bx1,by1),t) + m2=tpoint((bx1,by1),(bx2,by2),t) + m3=tpoint((bx2,by2),(bx3,by3),t) +@@ -167,7 +177,9 @@ Jens Gravesen + mat-report no. 1992-10, Mathematical Institute, The Technical + University of Denmark. + ''' +-def pointdistance((x1,y1),(x2,y2)): ++def pointdistance(_x1_y1, _x2_y2): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + return math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2)) + def Gravesen_addifclose(b, len, error = 0.001): + box = 0 +@@ -214,13 +226,15 @@ def Simpson(f, a, b, n_limit, tolerance): + #print multiplier, endsum, interval, asum, bsum, est1, est0 + return est1 + +-def bezierlengthSimpson(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)), tolerance = 0.001): ++def bezierlengthSimpson(xxx_todo_changeme12, tolerance = 0.001): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme12 + global balfax,balfbx,balfcx,balfay,balfby,balfcy + ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + balfax,balfbx,balfcx,balfay,balfby,balfcy = 3*ax,2*bx,cx,3*ay,2*by,cy + return Simpson(balf, 0.0, 1.0, 4096, tolerance) + +-def beziertatlength(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)), l = 0.5, tolerance = 0.001): ++def beziertatlength(xxx_todo_changeme13, l = 0.5, tolerance = 0.001): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme13 + global balfax,balfbx,balfcx,balfay,balfby,balfcy + ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + balfax,balfbx,balfcx,balfay,balfby,balfcy = 3*ax,2*bx,cx,3*ay,2*by,cy +diff --git a/share/extensions/convert2dashes.py b/share/extensions/convert2dashes.py +index 44241c2548..f0feee790b 100755 +--- a/share/extensions/convert2dashes.py ++++ b/share/extensions/convert2dashes.py +@@ -26,7 +26,9 @@ import cubicsuperpath + import bezmisc + import simplestyle + +-def tpoint((x1,y1), (x2,y2), t = 0.5): ++def tpoint(_x1_y1, _x2_y2, t = 0.5): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + return [x1+t*(x2-x1),y1+t*(y2-y1)] + def cspbezsplit(sp1, sp2, t = 0.5): + m1=tpoint(sp1[1],sp1[2],t) +diff --git a/share/extensions/cspsubdiv.py b/share/extensions/cspsubdiv.py +index c34236afec..c44e50ce49 100755 +--- a/share/extensions/cspsubdiv.py ++++ b/share/extensions/cspsubdiv.py +@@ -2,7 +2,8 @@ + from bezmisc import * + from ffgeom import * + +-def maxdist(((p0x,p0y),(p1x,p1y),(p2x,p2y),(p3x,p3y))): ++def maxdist(xxx_todo_changeme): ++ ((p0x,p0y),(p1x,p1y),(p2x,p2y),(p3x,p3y)) = xxx_todo_changeme + p0 = Point(p0x,p0y) + p1 = Point(p1x,p1y) + p2 = Point(p2x,p2y) +diff --git a/share/extensions/draw_from_triangle.py b/share/extensions/draw_from_triangle.py +index fd966b1d19..3b519fe759 100755 +--- a/share/extensions/draw_from_triangle.py ++++ b/share/extensions/draw_from_triangle.py +@@ -70,7 +70,9 @@ def draw_SVG_tri(vert_mat, params, style, name, parent): + inkex.etree.SubElement(parent, inkex.addNS('path','svg'), tri_attribs ) + + #draw an SVG line segment between the given (raw) points +-def draw_SVG_line( (x1, y1), (x2, y2), style, name, parent): ++def draw_SVG_line(_x1_y1, _x2_y2, style, name, parent): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + line_style = { 'stroke': style.l_col, 'stroke-width':str(style.l_th), 'fill': style.l_fill } + line_attribs = {'style':simplestyle.formatStyle(line_style), + inkex.addNS('label','inkscape'):name, +@@ -85,10 +87,14 @@ def draw_vertex_lines( vert_mat, params, width, name, parent): + + #MATHEMATICAL ROUTINES + +-def distance( (x0,y0),(x1,y1)):#find the pythagorean distance ++def distance(_x0_y0, _x1_y1):#find the pythagorean distance ++ (x0, y0) = _x0_y0 ++ (x1, y1) = _x1_y1 + return sqrt( (x0-x1)*(x0-x1) + (y0-y1)*(y0-y1) ) + +-def vector_from_to( (x0,y0),(x1,y1) ):#get the vector from (x0,y0) to (x1,y1) ++def vector_from_to(_x0_y0, _x1_y1 ):#get the vector from (x0,y0) to (x1,y1) ++ (x0, y0) = _x0_y0 ++ (x1, y1) = _x1_y1 + return (x1-x0, y1-y0) + + def get_cartesian_pt( t, p):#get the cartesian coordinates from a trilinear set +@@ -97,7 +103,8 @@ def get_cartesian_pt( t, p):#get the cartesian coordinates from a trilinear set + c2 = p[0][2]*t[2]/denom + return ( c1*p[2][1][0]+c2*p[2][0][0], c1*p[2][1][1]+c2*p[2][0][1] ) + +-def get_cartesian_tri( ((t11,t12,t13),(t21,t22,t23),(t31,t32,t33)), params):#get the cartesian points from a trilinear vertex matrix ++def get_cartesian_tri(xxx_todo_changeme6, params):#get the cartesian points from a trilinear vertex matrix ++ ((t11,t12,t13),(t21,t22,t23),(t31,t32,t33)) = xxx_todo_changeme6 + p1=get_cartesian_pt( (t11,t12,t13), params ) + p2=get_cartesian_pt( (t21,t22,t23), params ) + p3=get_cartesian_pt( (t31,t32,t33), params ) +diff --git a/share/extensions/dxf_outlines.py b/share/extensions/dxf_outlines.py +index 59b136d09c..8d87576b06 100755 +--- a/share/extensions/dxf_outlines.py ++++ b/share/extensions/dxf_outlines.py +@@ -49,7 +49,9 @@ except: + inkex.errormsg(_("Failed to import the numpy or numpy.linalg modules. These modules are required by this extension. Please install them and try again.")) + inkex.sys.exit() + +-def pointdistance((x1,y1),(x2,y2)): ++def pointdistance(_x1_y1, _x2_y2): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + return math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2)) + + def get_fit(u, csp, col): +diff --git a/share/extensions/gcodetools.py b/share/extensions/gcodetools.py +index 27fedd9a5f..8c312784fa 100755 +--- a/share/extensions/gcodetools.py ++++ b/share/extensions/gcodetools.py +@@ -99,7 +99,8 @@ except: + exit() + + +-def bezierslopeatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t): ++def bezierslopeatt(xxx_todo_changeme20,t): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme20 + ax,ay,bx,by,cx,cy,x0,y0=bezmisc.bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + dx=3*ax*(t**2)+2*bx*t+cx + dy=3*ay*(t**2)+2*by*t+cy +@@ -1349,7 +1350,9 @@ def bounds_intersect(a, b) : + return not ( (a[0]>b[2]) or (b[0]>a[2]) or (a[1]>b[3]) or (b[1]>a[3]) ) + + +-def tpoint((x1,y1),(x2,y2),t): ++def tpoint(_x1_y1, _x2_y2, t): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + return [x1+t*(x2-x1),y1+t*(y2-y1)] + + +@@ -1383,7 +1386,8 @@ def bez_normalized_slope(bez,t): + ### Some vector functions + ################################################################################ + +-def normalize((x,y)) : ++def normalize(_x_y) : ++ (x, y) = _x_y + l = math.sqrt(x**2+y**2) + if l == 0 : return [0.,0.] + else : return [x/l, y/l] +@@ -5189,7 +5193,7 @@ class Gcodetools(inkex.Effect): + eye_dist = 100 #3D constant. Try varying it for your eyes + + +- def bisect((nx1,ny1),(nx2,ny2)) : ++ def bisect(_nx1_ny1, _nx2_ny2) : + """LT Find angle bisecting the normals n1 and n2 + + Parameters: Normalised normals +@@ -5199,6 +5203,8 @@ class Gcodetools(inkex.Effect): + Note that bisect(n1,n2) and bisect(n2,n1) give opposite sinBis2 results + If sinturn is less than the user's requested angle tolerance, I return 0 + """ ++ (nx1, ny1) = _nx1_ny1 ++ (nx2, ny2) = _nx2_ny2 + #We can get absolute value of cos(bisector vector) + #Note: Need to use max in case of rounding errors + cosBis = math.sqrt(max(0,(1.0+nx1*nx2-ny1*ny2)/2.0)) +@@ -5219,7 +5225,7 @@ class Gcodetools(inkex.Effect): + return (cosBis/costurn,sinBis/costurn, sinturn) + #end bisect + +- def get_radius_to_line((x1,y1),(nx1,ny1), (nx2,ny2),(x2,y2),(nx23,ny23),(x3,y3),(nx3,ny3)): ++ def get_radius_to_line(_x1_y1, _nx1_ny1, _nx2_ny2, _x2_y2, _nx23_ny23, _x3_y3, _nx3_ny3): + """LT find biggest circle we can engrave here, if constrained by line 2-3 + + Parameters: +@@ -5245,7 +5251,13 @@ class Gcodetools(inkex.Effect): + # Algorithm uses dot products of normals to find radius + # and hence coordinates of centre + """ +- ++ (x1, y1) = _x1_y1 ++ (nx1, ny1) = _nx1_ny1 ++ (nx2, ny2) = _nx2_ny2 ++ (x2, y2) = _x2_y2 ++ (nx23, ny23) = _nx23_ny23 ++ (x3, y3) = _x3_y3 ++ (nx3, ny3) = _nx3_ny3 + global max_dist + + #Start by converting coordinates to be relative to x1,y1 +@@ -5279,7 +5291,7 @@ class Gcodetools(inkex.Effect): + return min(r, max_dist) + #end of get_radius_to_line + +- def get_radius_to_point((x1,y1),(nx,ny), (x2,y2)): ++ def get_radius_to_point(_x1_y1, _nx_ny, _x2_y2): + """LT find biggest circle we can engrave here, constrained by point x2,y2 + + This function can be used in three ways: +@@ -5293,7 +5305,9 @@ class Gcodetools(inkex.Effect): + It turns out that finding a circle touching a point is harder than a circle + touching a line. + """ +- ++ (x1, y1) = _x1_y1 ++ (nx, ny) = _nx_ny ++ (x2, y2) = _x2_y2 + global max_dist + + #Start by converting coordinates to be relative to x1,y1 +@@ -5356,7 +5370,7 @@ class Gcodetools(inkex.Effect): + return bez_divide(a,[abx,aby],[abcx,abcy],m) + bez_divide(m,[bcdx,bcdy],[cdx,cdy],d) + #end of bez_divide + +- def get_biggest((x1,y1),(nx,ny)): ++ def get_biggest(_x1_y1, _nx_ny): + """LT Find biggest circle we can draw inside path at point x1,y1 normal nx,ny + + Parameters: +@@ -5366,6 +5380,8 @@ class Gcodetools(inkex.Effect): + tuple (j,i,r) + ..where j and i are indices of limiting segment, r is radius + """ ++ (x1, y1) = _x1_y1 ++ (nx, ny) = _nx_ny + global max_dist, nlLT, i, j + n1 = nlLT[j][i-1] #current node + jjmin = -1 +@@ -5414,7 +5430,7 @@ class Gcodetools(inkex.Effect): + return (jjmin,iimin,r) + #end of get_biggest + +- def line_divide((x0,y0),j0,i0,(x1,y1),j1,i1,(nx,ny),length): ++ def line_divide(_x0_y0, j0, i0, _x1_y1, j1, i1, _nx_ny, length): + """LT recursively divide a line as much as necessary + + NOTE: This function is not currently used +@@ -5429,6 +5445,9 @@ class Gcodetools(inkex.Effect): + each a list of 3 reals: x, y coordinates, radius + + """ ++ (x0, y0) = _x0_y0 ++ (x1, y1) = _x1_y1 ++ (nx, ny) = _nx_ny + global nlLT, i, j, lmin + x2=(x0+x1)/2 + y2=(y0+y1)/2 +@@ -5441,12 +5460,13 @@ class Gcodetools(inkex.Effect): + return [ line_divide((x0,y0),j0,i0,(x2,y2),j2,i2,(nx,ny),length/2), line_divide((x2,y2),j2,i2,(x1,y1),j1,i1,(nx,ny),length/2)] + #end of line_divide() + +- def save_point((x,y),w,i,j,ii,jj): ++ def save_point(_x_y,w,i,j,ii,jj): + """LT Save this point and delete previous one if linear + + The point is, we generate tons of points but many may be in a straight 3D line. + There is no benefit in saving the imtermediate points. + """ ++ (x, y) = _x_y + global wl, cspm + x=round(x,4) #round to 4 decimals + y=round(y,4) #round to 4 decimals +@@ -5474,13 +5494,15 @@ class Gcodetools(inkex.Effect): + wl+=[w] + #end of save_point + +- def draw_point((x0,y0),(x,y),w,t): ++ def draw_point(_x0_y0, _x_y,w,t): + """LT Draw this point as a circle with a 1px dot in the middle (x,y) + and a 3D line from (x0,y0) down to x,y. 3D line thickness should be t/2 + + Note that points that are subsequently erased as being unneeded do get + displayed, but this helps the user see the total area covered. + """ ++ (x0, y0) = _x0_y0 ++ (x, y) = _x_y + global gcode_3Dleft ,gcode_3Dright + if self.options.engraving_draw_calculation_paths : + inkex.etree.SubElement( engraving_group, inkex.addNS('path','svg'), +diff --git a/share/extensions/interp.py b/share/extensions/interp.py +index 1754e82c55..ea0889743a 100755 +--- a/share/extensions/interp.py ++++ b/share/extensions/interp.py +@@ -24,11 +24,15 @@ def interpcoord(v1,v2,p): + return v1+((v2-v1)*p) + def interppoints(p1,p2,p): + return [interpcoord(p1[0],p2[0],p),interpcoord(p1[1],p2[1],p)] +-def pointdistance((x1,y1),(x2,y2)): ++def pointdistance(_x1_y1, _x2_y2): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + return math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2)) + def bezlenapprx(sp1, sp2): + return pointdistance(sp1[1], sp1[2]) + pointdistance(sp1[2], sp2[0]) + pointdistance(sp2[0], sp2[1]) +-def tpoint((x1,y1), (x2,y2), t = 0.5): ++def tpoint(_x1_y1, _x2_y2, t = 0.5): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + return [x1+t*(x2-x1),y1+t*(y2-y1)] + def cspbezsplit(sp1, sp2, t = 0.5): + m1=tpoint(sp1[1],sp1[2],t) +diff --git a/share/extensions/jitternodes.py b/share/extensions/jitternodes.py +index d6f5ce36d1..b8c20d1046 100755 +--- a/share/extensions/jitternodes.py ++++ b/share/extensions/jitternodes.py +@@ -19,7 +19,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + ''' + import random, math, inkex, cubicsuperpath + +-def randomize((x, y), rx, ry, dist): ++def randomize(_x_y, rx, ry, dist): ++ (x, y) = _x_y + + if dist == "Gaussian": + r1 = random.gauss(0.0,rx) +diff --git a/share/extensions/measure.py b/share/extensions/measure.py +index d025f142c6..f6ce082752 100755 +--- a/share/extensions/measure.py ++++ b/share/extensions/measure.py +@@ -73,11 +73,15 @@ def interpcoord(v1,v2,p): + return v1+((v2-v1)*p) + def interppoints(p1,p2,p): + return [interpcoord(p1[0],p2[0],p),interpcoord(p1[1],p2[1],p)] +-def pointdistance((x1,y1),(x2,y2)): ++def pointdistance(_x1_y1, _x2_y2): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + return math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2)) + def bezlenapprx(sp1, sp2): + return pointdistance(sp1[1], sp1[2]) + pointdistance(sp1[2], sp2[0]) + pointdistance(sp2[0], sp2[1]) +-def tpoint((x1,y1), (x2,y2), t = 0.5): ++def tpoint(_x1_y1, _x2_y2, t = 0.5): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + return [x1+t*(x2-x1),y1+t*(y2-y1)] + def cspbezsplit(sp1, sp2, t = 0.5): + m1=tpoint(sp1[1],sp1[2],t) +diff --git a/share/extensions/motion.py b/share/extensions/motion.py +index 3af80d5c13..6046665dcb 100755 +--- a/share/extensions/motion.py ++++ b/share/extensions/motion.py +@@ -30,7 +30,8 @@ class Motion(inkex.Effect): + dest="magnitude", default=100.0, + help="magnitude of the motion vector") + +- def makeface(self,last,(cmd, params)): ++ def makeface(self,last, xxx_todo_changeme): ++ (cmd, params) = xxx_todo_changeme + a = [] + a.append(['M',last[:]]) + a.append([cmd, params[:]]) +diff --git a/share/extensions/polyhedron_3d.py b/share/extensions/polyhedron_3d.py +index a74a64e694..c39d351749 100755 +--- a/share/extensions/polyhedron_3d.py ++++ b/share/extensions/polyhedron_3d.py +@@ -139,7 +139,8 @@ def get_obj_data(obj, name): + + #RENDERING AND SVG OUTPUT FUNCTIONS + +-def draw_SVG_dot((cx, cy), st, name, parent): ++def draw_SVG_dot(_cx_cy, st, name, parent): ++ (cx, cy) = _cx_cy + style = { 'stroke': '#000000', 'stroke-width':str(st.th), 'fill': st.fill, 'stroke-opacity':st.s_opac, 'fill-opacity':st.f_opac} + circ_attribs = {'style':simplestyle.formatStyle(style), + inkex.addNS('label','inkscape'):name, +@@ -147,7 +148,9 @@ def draw_SVG_dot((cx, cy), st, name, parent): + 'cx':str(cx), 'cy':str(-cy)} + inkex.etree.SubElement(parent, inkex.addNS('circle','svg'), circ_attribs ) + +-def draw_SVG_line((x1, y1),(x2, y2), st, name, parent): ++def draw_SVG_line(_x1_y1, _x2_y2, st, name, parent): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + style = { 'stroke': '#000000', 'stroke-width':str(st.th), 'stroke-linecap':st.linecap} + line_attribs = {'style':simplestyle.formatStyle(style), + inkex.addNS('label','inkscape'):name, +@@ -186,8 +189,9 @@ def draw_faces( faces_data, pts, obj, shading, fill_col,st, parent): + face_no = face[3]#the number of the face to draw + draw_SVG_poly(pts, obj.fce[ face_no ], st, 'Face:'+str(face_no), parent) + +-def get_darkened_colour( (r,g,b), factor): ++def get_darkened_colour(_r_g_b, factor): + #return a hex triplet of colour, reduced in lightness proportionally to a value between 0 and 1 ++ (r, g, b) = _r_g_b + return '#' + "%02X" % floor( factor*r ) \ + + "%02X" % floor( factor*g ) \ + + "%02X" % floor( factor*b ) #make the colour string +diff --git a/share/extensions/pturtle.py b/share/extensions/pturtle.py +index a4925bf4ca..d3cc3e90ff 100755 +--- a/share/extensions/pturtle.py ++++ b/share/extensions/pturtle.py +@@ -55,7 +55,8 @@ class pTurtle: + def clear(self): + self.clean() + self.home() +- def setpos(self,(x,y)): ++ def setpos(self, _x_y): ++ (x, y) = _x_y + if self.__new: + self.__path += "M"+",".join([str(i) for i in self.__pos]) + self.__new = False +@@ -68,7 +69,8 @@ class pTurtle: + self.__heading = deg + def getheading(self): + return self.__heading +- def sethome(self,(x,y)): ++ def sethome(self, _x_y): ++ (x, y) = _x_y + self.__home = [x, y] + def getPath(self): + return self.__path +diff --git a/share/extensions/render_barcode_datamatrix.py b/share/extensions/render_barcode_datamatrix.py +index 659e74de6a..a012db9412 100755 +--- a/share/extensions/render_barcode_datamatrix.py ++++ b/share/extensions/render_barcode_datamatrix.py +@@ -95,8 +95,9 @@ symbols = { + #===================================================================== + + #create a 2d list corresponding to the 1's and 0s of the DataMatrix +-def encode(text, (nrow, ncol) ): ++def encode(text, xxx_todo_changeme ): + #retreive the parameters of this size of DataMatrix ++ (nrow, ncol) = xxx_todo_changeme + data_nrow, data_ncol, reg_row, reg_col, nd, nc, inter = get_parameters( nrow, ncol ) + + if not ((nrow == 144) and (ncol == 144)): #we have a regular datamatrix +@@ -510,8 +511,9 @@ def utah(array, nrow, ncol, row, col, char): + + #"place_bits" fills an nrow x ncol array with the bits from the + # codewords in data. +-def place_bits(data, (nrow, ncol)): ++def place_bits(data, xxx_todo_changeme1): + # First, fill the array[] with invalid entries */ ++ (nrow, ncol) = xxx_todo_changeme1 + INVALID = 2 + array = [[INVALID] * ncol for i in xrange(nrow)] #initialise and fill with -1's (invalid value) + # Starting in the correct location for character #1, bit 8,... +@@ -609,7 +611,9 @@ def add_finder_pattern( array, data_nrow, data_ncol, reg_row, reg_col ): + #===================================================================== + + #SVG element generation routine +-def draw_SVG_square((w,h), (x,y), parent): ++def draw_SVG_square(_w_h, _x_y, parent): ++ (w, h) = _w_h ++ (x, y) = _x_y + + style = { 'stroke' : 'none', + 'stroke-width' : '1', +diff --git a/share/extensions/straightseg.py b/share/extensions/straightseg.py +index 9222ed5b5c..d477dbdf07 100755 +--- a/share/extensions/straightseg.py ++++ b/share/extensions/straightseg.py +@@ -18,7 +18,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + ''' + import math, inkex, simplepath, sys + +-def pointAtPercent((x1, y1), (x2, y2), percent): ++def pointAtPercent(_x1_y1, _x2_y2, percent): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + percent /= 100.0 + x = x1 + (percent * (x2 - x1)) + y = y1 + (percent * (y2 - y1)) +diff --git a/share/extensions/summersnight.py b/share/extensions/summersnight.py +index abc9327e54..3714e47e5f 100755 +--- a/share/extensions/summersnight.py ++++ b/share/extensions/summersnight.py +@@ -116,7 +116,8 @@ class Project(inkex.Effect): + simpletransform.applyTransformToPath(mat, p) + path.set('d',cubicsuperpath.formatPath(p)) + +- def trafopoint(self,(x,y)): ++ def trafopoint(self, _x_y): ++ (x, y) = _x_y + #Transform algorithm thanks to Jose Hevia (freon) + vector = Segment(Point(self.q['x'],self.q['y']),Point(x,y)) + xratio = abs(vector.delta_x())/self.q['width'] +diff --git a/share/extensions/triangle.py b/share/extensions/triangle.py +index 32bd2a1db8..19e0177d7c 100755 +--- a/share/extensions/triangle.py ++++ b/share/extensions/triangle.py +@@ -37,7 +37,11 @@ import simplestyle, sys + from simpletransform import computePointInNode + from math import * + +-def draw_SVG_tri( (x1, y1), (x2, y2), (x3, y3), (ox,oy), width, name, parent): ++def draw_SVG_tri(_x1_y1, _x2_y2, _x3_y3, _ox_oy, width, name, parent): ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 ++ (x3, y3) = _x3_y3 ++ (ox, oy) = _ox_oy + style = { 'stroke': '#000000', 'stroke-width':str(width), 'fill': 'none' } + tri_attribs = {'style':simplestyle.formatStyle(style), + inkex.addNS('label','inkscape'):name, +@@ -63,7 +67,9 @@ def pt_on_circ(radius, angle): #return the x,y coordinate of the polar coordinat + y = radius * sin(angle) + return [x, y] + +-def v_add( (x1,y1),(x2,y2) ):#add an offset to coordinates ++def v_add(_x1_y1, _x2_y2):#add an offset to coordinates ++ (x1, y1) = _x1_y1 ++ (x2, y2) = _x2_y2 + return [x1+x2, y1+y2] + + def is_valid_tri_from_sides(a,b,c):#check whether triangle with sides a,b,c is valid +diff --git a/share/extensions/wireframe_sphere.py b/share/extensions/wireframe_sphere.py +index 9a8d646e31..870b75413b 100755 +--- a/share/extensions/wireframe_sphere.py ++++ b/share/extensions/wireframe_sphere.py +@@ -63,7 +63,9 @@ from simpletransform import computePointInNode + + + #SVG OUTPUT FUNCTIONS ================================================ +-def draw_SVG_ellipse((rx, ry), (cx, cy), width, parent, start_end=(0,2*pi),transform='' ): ++def draw_SVG_ellipse(_rx_ry, _cx_cy, width, parent, start_end=(0,2*pi),transform='' ): ++ (rx, ry) = _rx_ry ++ (cx, cy) = _cx_cy + + style = { 'stroke' : '#000000', + 'stroke-width' : str(width), +-- +2.21.0 + + +From 0cf86ada6273eaa5820db5563fe97061e9140f2f Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 10:42:04 +0100 +Subject: [PATCH 05/17] extensions 2to3: imports urllib + +--- + share/extensions/dxf_input.py | 9 +++++++-- + share/extensions/embedimage.py | 9 +++++++-- + share/extensions/gcodetools.py | 9 ++++++--- + share/extensions/hpgl_decoder.py | 7 ++++++- + share/extensions/hpgl_input.py | 1 - + share/extensions/svg_and_media_zip_output.py | 9 +++++++-- + share/extensions/tar_layers.py | 5 ++++- + 7 files changed, 37 insertions(+), 12 deletions(-) + +diff --git a/share/extensions/dxf_input.py b/share/extensions/dxf_input.py +index cd0e508b59..65a6963528 100755 +--- a/share/extensions/dxf_input.py ++++ b/share/extensions/dxf_input.py +@@ -23,8 +23,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + ''' + + import inkex, simplestyle, math +-from StringIO import StringIO +-from urllib import quote ++import sys ++if sys.version_info[0] < 3: ++ from StringIO import StringIO ++ from urllib import quote ++else: ++ from io import StringIO ++ from urllib.parse import quote + + + def export_MTEXT(): +diff --git a/share/extensions/embedimage.py b/share/extensions/embedimage.py +index 9ebe084a32..4f8db2fd03 100755 +--- a/share/extensions/embedimage.py ++++ b/share/extensions/embedimage.py +@@ -20,8 +20,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + import base64 + import os + import sys +-import urllib +-import urlparse ++if sys.version_info[0] < 3: ++ import urllib ++ import urlparse ++else: ++ import urllib.request as urllib ++ import urllib.parse as urlparse ++ + # local library + import inkex + +diff --git a/share/extensions/gcodetools.py b/share/extensions/gcodetools.py +index 8c312784fa..d1656bae1c 100755 +--- a/share/extensions/gcodetools.py ++++ b/share/extensions/gcodetools.py +@@ -6322,9 +6322,12 @@ G01 Z1 (going to cutting z)\n""", + + def update(self) : + try : +- import urllib +- f = urllib.urlopen("http://www.cnc-club.ru/gcodetools_latest_version", proxies = urllib.getproxies()) +- a = f.read() ++ if sys.version_info[0] < 3: ++ import urllib2 ++ else: ++ import urllib.request as urllib2 ++ f = urllib2.urlopen("http://www.cnc-club.ru/gcodetools_latest_version") ++ a = f.read().decode() + for s in a.split("\n") : + r = re.search(r"Gcodetools\s+latest\s+version\s*=\s*(.*)",s) + if r : +diff --git a/share/extensions/hpgl_decoder.py b/share/extensions/hpgl_decoder.py +index 8f3c18e420..bbedf9f225 100644 +--- a/share/extensions/hpgl_decoder.py ++++ b/share/extensions/hpgl_decoder.py +@@ -19,7 +19,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + # standard libraries + import math +-from StringIO import StringIO ++import sys ++if sys.version_info[0] < 3: ++ from StringIO import StringIO ++else: ++ from io import StringIO ++ + # local library + import inkex + +diff --git a/share/extensions/hpgl_input.py b/share/extensions/hpgl_input.py +index 37607358bc..f9b8465dd3 100755 +--- a/share/extensions/hpgl_input.py ++++ b/share/extensions/hpgl_input.py +@@ -20,7 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + # standard libraries + import sys +-from StringIO import StringIO + # local libraries + import hpgl_decoder + import inkex +diff --git a/share/extensions/svg_and_media_zip_output.py b/share/extensions/svg_and_media_zip_output.py +index 1a148f8a8a..51887e5b53 100755 +--- a/share/extensions/svg_and_media_zip_output.py ++++ b/share/extensions/svg_and_media_zip_output.py +@@ -37,8 +37,6 @@ TODOs + - consider switching to lzma in order to allow cross platform compression with no encoding problem... + ''' + # standard library +-import urlparse +-import urllib + import os, os.path + import string + import zipfile +@@ -50,6 +48,13 @@ import locale + import inkex + import simplestyle + ++if sys.version_info[0] < 3: ++ import urllib ++ import urlparse ++else: ++ import urllib.request as urllib ++ import urllib.parse as urlparse ++ + locale.setlocale(locale.LC_ALL, '') + inkex.localize() # TODO: test if it's still needed now that localize is called from inkex. + +diff --git a/share/extensions/tar_layers.py b/share/extensions/tar_layers.py +index 186e3c4689..8b60d889d1 100755 +--- a/share/extensions/tar_layers.py ++++ b/share/extensions/tar_layers.py +@@ -25,7 +25,10 @@ import os + import sys + import copy + import tarfile +-import StringIO ++if sys.version_info[0] < 3: ++ import StringIO ++else: ++ import io as StringIO + import calendar + import time + +-- +2.21.0 + + +From b0aea05e7a287fb6be8b18a3fec812b367310dd5 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 11:10:14 +0100 +Subject: [PATCH 06/17] extensions 2to3: unicode + +--- + share/extensions/dxf_input.py | 1 + + share/extensions/embedimage.py | 6 +-- + share/extensions/gcodetools.py | 4 ++ + share/extensions/inkex.py | 3 ++ + share/extensions/jessyInk_transitions.py | 4 ++ + share/extensions/render_barcode_qrcode.py | 4 ++ + share/extensions/svg_and_media_zip_output.py | 4 ++ + share/extensions/svgcalendar.py | 4 ++ + share/extensions/text_braille.py | 52 ++++++++++---------- + 9 files changed, 52 insertions(+), 30 deletions(-) + +diff --git a/share/extensions/dxf_input.py b/share/extensions/dxf_input.py +index 65a6963528..91e7a02e21 100755 +--- a/share/extensions/dxf_input.py ++++ b/share/extensions/dxf_input.py +@@ -30,6 +30,7 @@ if sys.version_info[0] < 3: + else: + from io import StringIO + from urllib.parse import quote ++ unicode = lambda s, enc: s.decode(enc) if isinstance(s, bytes) else s + + + def export_MTEXT(): +diff --git a/share/extensions/embedimage.py b/share/extensions/embedimage.py +index 4f8db2fd03..4e5ce585de 100755 +--- a/share/extensions/embedimage.py ++++ b/share/extensions/embedimage.py +@@ -79,10 +79,8 @@ class Embedder(inkex.Effect): + if (absref != None): + path=absref + +- try: +- path=unicode(path, "utf-8") +- except TypeError: +- path=path ++ if isinstance(path, bytes): ++ path = path.decode("utf-8") + + if (not os.path.isfile(path)): + inkex.errormsg(_('No xlink:href or sodipodi:absref attributes found, or they do not point to an existing file! Unable to embed image.')) +diff --git a/share/extensions/gcodetools.py b/share/extensions/gcodetools.py +index d1656bae1c..dc38eaa796 100755 +--- a/share/extensions/gcodetools.py ++++ b/share/extensions/gcodetools.py +@@ -80,6 +80,10 @@ import time + import cmath + import codecs + import random ++ ++if sys.version_info[0] >= 3: ++ unicode = lambda s: s.decode() if isinstance(s, bytes) else str(s) ++ + # local library + import inkex + import simplestyle +diff --git a/share/extensions/inkex.py b/share/extensions/inkex.py +index 9d3bb0c6dc..8a94c55cc1 100755 +--- a/share/extensions/inkex.py ++++ b/share/extensions/inkex.py +@@ -35,6 +35,9 @@ import re + import sys + from math import * + ++if sys.version_info[0] >= 3: ++ unicode = str ++ + # a dictionary of all of the xmlns prefixes in a standard inkscape doc + NSS = { + u'sodipodi' :u'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd', +diff --git a/share/extensions/jessyInk_transitions.py b/share/extensions/jessyInk_transitions.py +index f463b2fb5d..9997799a19 100755 +--- a/share/extensions/jessyInk_transitions.py ++++ b/share/extensions/jessyInk_transitions.py +@@ -16,6 +16,10 @@ + # These lines are only needed if you don't put the script directly into + # the installation directory + import sys ++ ++if sys.version_info[0] >= 3: ++ unicode = lambda s, enc: s ++ + # Unix + sys.path.append('/usr/share/inkscape/extensions') + # OS X +diff --git a/share/extensions/render_barcode_qrcode.py b/share/extensions/render_barcode_qrcode.py +index d829eb0604..9e86296077 100755 +--- a/share/extensions/render_barcode_qrcode.py ++++ b/share/extensions/render_barcode_qrcode.py +@@ -3,6 +3,10 @@ + from __future__ import print_function + + import math, sys ++ ++if sys.version_info[0] >= 3: ++ unicode = lambda s, enc: s.decode(enc) if isinstance(s, bytes) else s ++ + import inkex + from simpletransform import computePointInNode + +diff --git a/share/extensions/svg_and_media_zip_output.py b/share/extensions/svg_and_media_zip_output.py +index 51887e5b53..f3df1d9908 100755 +--- a/share/extensions/svg_and_media_zip_output.py ++++ b/share/extensions/svg_and_media_zip_output.py +@@ -44,6 +44,10 @@ import shutil + import sys + import tempfile + import locale ++ ++if sys.version_info[0] >= 3: ++ unicode = lambda s, enc: s.decode(enc) if isinstance(s, bytes) else s ++ + # local library + import inkex + import simplestyle +diff --git a/share/extensions/svgcalendar.py b/share/extensions/svgcalendar.py +index 29dee262bb..b0f9d1a2b4 100755 +--- a/share/extensions/svgcalendar.py ++++ b/share/extensions/svgcalendar.py +@@ -34,6 +34,10 @@ import calendar + import re + from datetime import * + ++import sys ++if sys.version_info[0] >= 3: ++ unicode = lambda s, enc: s.decode(enc) if isinstance(s, bytes) else s ++ + import inkex + import simplestyle + +diff --git a/share/extensions/text_braille.py b/share/extensions/text_braille.py +index d778f19eac..2a220bbeee 100755 +--- a/share/extensions/text_braille.py ++++ b/share/extensions/text_braille.py +@@ -4,32 +4,32 @@ + import chardataeffect, inkex, string + + convert_table = {\ +-'a': unicode("⠁", "utf-8"),\ +-'b': unicode("⠃", "utf-8"),\ +-'c': unicode("⠉", "utf-8"),\ +-'d': unicode("⠙", "utf-8"),\ +-'e': unicode("⠑", "utf-8"),\ +-'f': unicode("⠋", "utf-8"),\ +-'g': unicode("⠛", "utf-8"),\ +-'h': unicode("⠓", "utf-8"),\ +-'i': unicode("⠊", "utf-8"),\ +-'j': unicode("⠚", "utf-8"),\ +-'k': unicode("⠅", "utf-8"),\ +-'l': unicode("⠇", "utf-8"),\ +-'m': unicode("⠍", "utf-8"),\ +-'n': unicode("⠝", "utf-8"),\ +-'o': unicode("⠕", "utf-8"),\ +-'p': unicode("⠏", "utf-8"),\ +-'q': unicode("⠟", "utf-8"),\ +-'r': unicode("⠗", "utf-8"),\ +-'s': unicode("⠎", "utf-8"),\ +-'t': unicode("⠞", "utf-8"),\ +-'u': unicode("⠥", "utf-8"),\ +-'v': unicode("⠧", "utf-8"),\ +-'w': unicode("⠺", "utf-8"),\ +-'x': unicode("⠭", "utf-8"),\ +-'y': unicode("⠽", "utf-8"),\ +-'z': unicode("⠵", "utf-8"),\ ++'a': u'\u2801', ++'c': u'\u2809', ++'b': u'\u2803', ++'e': u'\u2811', ++'d': u'\u2819', ++'g': u'\u281b', ++'f': u'\u280b', ++'i': u'\u280a', ++'h': u'\u2813', ++'k': u'\u2805', ++'j': u'\u281a', ++'m': u'\u280d', ++'l': u'\u2807', ++'o': u'\u2815', ++'n': u'\u281d', ++'q': u'\u281f', ++'p': u'\u280f', ++'s': u'\u280e', ++'r': u'\u2817', ++'u': u'\u2825', ++'t': u'\u281e', ++'w': u'\u283a', ++'v': u'\u2827', ++'y': u'\u283d', ++'x': u'\u282d', ++'z': u'\u2835', + } + + class C(chardataeffect.CharDataEffect): +-- +2.21.0 + + +From 7edcb7389e9abc1c09bf2b03002f167451b609b3 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 11:26:00 +0100 +Subject: [PATCH 07/17] extensions 2to3: xrange + +--- + share/extensions/addnodes.py | 4 ++-- + share/extensions/bezmisc.py | 2 +- + share/extensions/gcodetools.py | 10 +++++++--- + share/extensions/interp.py | 2 +- + share/extensions/measure.py | 2 +- + share/extensions/render_barcode_datamatrix.py | 5 +++++ + 6 files changed, 17 insertions(+), 8 deletions(-) + +diff --git a/share/extensions/addnodes.py b/share/extensions/addnodes.py +index a2f70c885f..bd1440102a 100755 +--- a/share/extensions/addnodes.py ++++ b/share/extensions/addnodes.py +@@ -51,7 +51,7 @@ def csplength(csp): + lengths = [] + for sp in csp: + lengths.append([]) +- for i in xrange(1,len(sp)): ++ for i in range(1,len(sp)): + l = cspseglength(sp[i-1],sp[i]) + lengths[-1].append(l) + total += l +@@ -102,7 +102,7 @@ class SplitIt(inkex.Effect): + else: + splits = math.ceil(length/self.options.max) + +- for s in xrange(int(splits),1,-1): ++ for s in range(int(splits),1,-1): + new[-1][-1], next, sub[i] = cspbezsplitatlength(new[-1][-1], sub[i], 1.0/s) + new[-1].append(next[:]) + new[-1].append(sub[i]) +diff --git a/share/extensions/bezmisc.py b/share/extensions/bezmisc.py +index a563178868..359db54213 100755 +--- a/share/extensions/bezmisc.py ++++ b/share/extensions/bezmisc.py +@@ -220,7 +220,7 @@ def Simpson(f, a, b, n_limit, tolerance): + asum += bsum + bsum = 0.0 + est0 = est1 +- for i in xrange(1, n, 2): ++ for i in range(1, n, 2): + bsum += f(a + (i * interval)) + est1 = multiplier * (endsum + (2.0 * asum) + (4.0 * bsum)) + #print multiplier, endsum, interval, asum, bsum, est1, est0 +diff --git a/share/extensions/gcodetools.py b/share/extensions/gcodetools.py +index dc38eaa796..590aa2209e 100755 +--- a/share/extensions/gcodetools.py ++++ b/share/extensions/gcodetools.py +@@ -83,6 +83,10 @@ import random + + if sys.version_info[0] >= 3: + unicode = lambda s: s.decode() if isinstance(s, bytes) else str(s) ++ xrange = range ++ range_list = lambda *a: list(range(*a)) ++else: ++ range_list = range + + # local library + import inkex +@@ -3036,7 +3040,7 @@ class Arangement_Genetic: + def add_random_species(self,count): + for i in range(count): + specimen = [] +- order = range(self.genes_count) ++ order = range_list(self.genes_count) + random.shuffle(order) + for j in order: + specimen += [ [j, random.random(), random.random()] ] +@@ -3125,7 +3129,7 @@ class Arangement_Genetic: + specimen[i] = [parent1[i][0], parent1[i][1]*tr+parent2[i][1]*(1-tr),parent1[i][2]*tp+parent2[i][2]*(1-tp)] + genes_order += [ parent1[i][0] ] + +- for i in range(0,start_gene)+range(end_gene,self.genes_count) : ++ for i in range_list(0,start_gene)+range_list(end_gene,self.genes_count) : + tr = 0. #rotation_mutate_param + tp = 0. #xposition_mutate_param + j = i +@@ -3727,7 +3731,7 @@ class Gcodetools(inkex.Effect): + + + ### Sort to reduce Rapid distance +- k = range(1,len(p)) ++ k = range_list(1,len(p)) + keys = [0] + while len(k)>0: + end = p[keys[-1]][-1][1] +diff --git a/share/extensions/interp.py b/share/extensions/interp.py +index ea0889743a..7d6b6fa454 100755 +--- a/share/extensions/interp.py ++++ b/share/extensions/interp.py +@@ -54,7 +54,7 @@ def csplength(csp): + lengths = [] + for sp in csp: + lengths.append([]) +- for i in xrange(1,len(sp)): ++ for i in range(1,len(sp)): + l = cspseglength(sp[i-1],sp[i]) + lengths[-1].append(l) + total += l +diff --git a/share/extensions/measure.py b/share/extensions/measure.py +index f6ce082752..7a8bf96e15 100755 +--- a/share/extensions/measure.py ++++ b/share/extensions/measure.py +@@ -103,7 +103,7 @@ def csplength(csp): + lengths = [] + for sp in csp: + lengths.append([]) +- for i in xrange(1,len(sp)): ++ for i in range(1,len(sp)): + l = cspseglength(sp[i-1],sp[i]) + lengths[-1].append(l) + total += l +diff --git a/share/extensions/render_barcode_datamatrix.py b/share/extensions/render_barcode_datamatrix.py +index a012db9412..7c6c333459 100755 +--- a/share/extensions/render_barcode_datamatrix.py ++++ b/share/extensions/render_barcode_datamatrix.py +@@ -51,6 +51,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + 0.50 2009-10-25 Full functionality, up to 144x144. + ASCII and compressed digit encoding only. + ''' ++ ++import sys ++if sys.version_info[0] >= 3: ++ xrange = range ++ + # local library + import inkex + import simplestyle +-- +2.21.0 + + +From 9fcc4c63563521e68abb69e77efcdfc7e4fd4507 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 11:38:21 +0100 +Subject: [PATCH 08/17] extensions 2to3: map + +--- + share/extensions/layout_nup.py | 2 +- + share/extensions/restack.py | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/share/extensions/layout_nup.py b/share/extensions/layout_nup.py +index 022aa0d3f4..19e126d080 100755 +--- a/share/extensions/layout_nup.py ++++ b/share/extensions/layout_nup.py +@@ -155,7 +155,7 @@ class Nup(inkex.Effect): + pgSize = self.expandTuple(unit, pgSize, length = 2) + # num = tuple(map(lambda ev: eval(str(ev)), num)) + +- pgEdge = map(sum,zip(pgMargin, pgPadding)) ++ pgEdge = list(map(sum,zip(pgMargin, pgPadding))) + + top, right, bottom, left = 0,1,2,3 + width, height = 0,1 +diff --git a/share/extensions/restack.py b/share/extensions/restack.py +index d38e18b525..79a7565e7f 100755 +--- a/share/extensions/restack.py ++++ b/share/extensions/restack.py +@@ -112,7 +112,7 @@ class Restack(inkex.Effect): + dimen = dict() + for line in reader: + if len(line) > 0: +- dimen[line[0]] = map( float, line[1:]) ++ dimen[line[0]] = list(map( float, line[1:])) + + if not bsubprocess: #close file if opened using os.popen3 + f.close +-- +2.21.0 + + +From a46a6cafe06ae9fd991560191e83cb83d1dab770 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 12:05:56 +0100 +Subject: [PATCH 09/17] extensions 2to3: dict + +--- + share/extensions/addnodes.py | 2 +- + share/extensions/chardataeffect.py | 2 +- + share/extensions/coloreffect.py | 2 +- + share/extensions/convert2dashes.py | 2 +- + share/extensions/dimension.py | 2 +- + share/extensions/dots.py | 2 +- + share/extensions/dpiswitcher.py | 4 ++-- + share/extensions/draw_from_triangle.py | 2 +- + share/extensions/edge3d.py | 2 +- + share/extensions/embedimage.py | 2 +- + share/extensions/extractimage.py | 2 +- + share/extensions/extrude.py | 2 +- + share/extensions/flatten.py | 2 +- + share/extensions/fractalize.py | 2 +- + share/extensions/funcplot.py | 2 +- + share/extensions/gcodetools.py | 6 +++--- + share/extensions/handles.py | 2 +- + share/extensions/image_attributes.py | 6 +++--- + share/extensions/inkscape_follow_link.py | 2 +- + share/extensions/interp.py | 6 +++--- + share/extensions/interp_att_g.py | 2 +- + share/extensions/jitternodes.py | 2 +- + share/extensions/lorem_ipsum.py | 2 +- + share/extensions/markers_strokepaint.py | 2 +- + share/extensions/measure.py | 2 +- + share/extensions/merge_styles.py | 8 ++++---- + share/extensions/motion.py | 2 +- + share/extensions/new_glyph_layer.py | 2 +- + share/extensions/param_curves.py | 2 +- + share/extensions/pathalongpath.py | 4 ++-- + share/extensions/pathmodifier.py | 14 +++++++------- + share/extensions/pathscatter.py | 4 ++-- + share/extensions/pixelsnap.py | 2 +- + share/extensions/replace_font.py | 2 +- + share/extensions/restack.py | 8 ++++---- + share/extensions/simplestyle.py | 2 +- + share/extensions/split.py | 2 +- + share/extensions/straightseg.py | 2 +- + share/extensions/synfig_fileformat.py | 2 +- + share/extensions/text_extract.py | 6 +++--- + share/extensions/text_merge.py | 6 +++--- + share/extensions/ungroup_deep.py | 2 +- + share/extensions/webslicer_create_group.py | 4 ++-- + share/extensions/whirl.py | 2 +- + 44 files changed, 70 insertions(+), 70 deletions(-) + +diff --git a/share/extensions/addnodes.py b/share/extensions/addnodes.py +index bd1440102a..1970f330f7 100755 +--- a/share/extensions/addnodes.py ++++ b/share/extensions/addnodes.py +@@ -82,7 +82,7 @@ class SplitIt(inkex.Effect): + + def effect(self): + +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('path','svg'): + p = cubicsuperpath.parsePath(node.get('d')) + +diff --git a/share/extensions/chardataeffect.py b/share/extensions/chardataeffect.py +index f81de6b801..25b0a14e9d 100755 +--- a/share/extensions/chardataeffect.py ++++ b/share/extensions/chardataeffect.py +@@ -32,7 +32,7 @@ class CharDataEffect(inkex.Effect): + if len(self.selected)==0: + self.recurse(self.document.getroot()) + else: +- for id,node in self.selected.iteritems(): ++ for id,node in self.selected.items(): + self.recurse(node) + + def recurse(self,node): +diff --git a/share/extensions/coloreffect.py b/share/extensions/coloreffect.py +index 94e909a728..fbed3c931f 100755 +--- a/share/extensions/coloreffect.py ++++ b/share/extensions/coloreffect.py +@@ -36,7 +36,7 @@ class ColorEffect(inkex.Effect): + if len(self.selected)==0: + self.getAttribs(self.document.getroot()) + else: +- for id,node in self.selected.iteritems(): ++ for id,node in self.selected.items(): + self.getAttribs(node) + + def getAttribs(self,node): +diff --git a/share/extensions/convert2dashes.py b/share/extensions/convert2dashes.py +index f0feee790b..1590c9183f 100755 +--- a/share/extensions/convert2dashes.py ++++ b/share/extensions/convert2dashes.py +@@ -52,7 +52,7 @@ class SplitIt(inkex.Effect): + self.not_converted = [] + + def effect(self): +- for i, node in self.selected.iteritems(): ++ for i, node in self.selected.items(): + self.convert2dash(node) + if len(self.not_converted): + inkex.errormsg(_('Total number of objects not converted: {}\n').format(len(self.not_converted))) +diff --git a/share/extensions/dimension.py b/share/extensions/dimension.py +index e6b2d8f85a..1b3678b66c 100755 +--- a/share/extensions/dimension.py ++++ b/share/extensions/dimension.py +@@ -171,7 +171,7 @@ class Dimension(pathmodifier.PathModifier): + line.set('stroke-width', str(0.5*scale)) + group.append(line) + +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + group.append(node) + + layer.append(group) +diff --git a/share/extensions/dots.py b/share/extensions/dots.py +index 296a56dfc4..d803153d96 100755 +--- a/share/extensions/dots.py ++++ b/share/extensions/dots.py +@@ -46,7 +46,7 @@ class Dots(inkex.Effect): + def effect(self): + selection = self.selected + if (selection): +- for id, node in selection.iteritems(): ++ for id, node in selection.items(): + if node.tag == inkex.addNS('path','svg'): + self.addDot(node) + else: +diff --git a/share/extensions/dpiswitcher.py b/share/extensions/dpiswitcher.py +index 47bb4458b6..0f8fd4c048 100644 +--- a/share/extensions/dpiswitcher.py ++++ b/share/extensions/dpiswitcher.py +@@ -237,9 +237,9 @@ class DPISwitcher(inkex.Effect): + def parse_length(self, length, percent=False): + """Parse SVG length.""" + if self.options.switcher == "0": # dpi90to96 +- known_units = self.__uuconvLegacy.keys() ++ known_units = list(self.__uuconvLegacy.keys()) + else: # dpi96to90 +- known_units = self.__uuconv.keys() ++ known_units = list(self.__uuconv.keys()) + if percent: + unitmatch = re.compile('(%s)$' % '|'.join(known_units + ['%'])) + else: +diff --git a/share/extensions/draw_from_triangle.py b/share/extensions/draw_from_triangle.py +index 3b519fe759..3fd0ebb3ff 100755 +--- a/share/extensions/draw_from_triangle.py ++++ b/share/extensions/draw_from_triangle.py +@@ -316,7 +316,7 @@ class Draw_From_Triangle(inkex.Effect): + so = self.options #shorthand + + pts = [] #initialise in case nothing is selected and following loop is not executed +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('path','svg'): + pts = get_n_points_from_path( node, 3 ) #find the (x,y) coordinates of the first 3 points of the path + +diff --git a/share/extensions/edge3d.py b/share/extensions/edge3d.py +index 86df529088..513d50a958 100755 +--- a/share/extensions/edge3d.py ++++ b/share/extensions/edge3d.py +@@ -72,7 +72,7 @@ class Edge3d(inkex.Effect): + for the current shade. shade is a floating point 0-1 white-black""" + # size of a wedge for shade i, wedges come in pairs + delta = 360. / self.options.shades / 2. +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('path','svg'): + d = node.get('d') + p = simplepath.parsePath(d) +diff --git a/share/extensions/embedimage.py b/share/extensions/embedimage.py +index 4e5ce585de..cafe3f1db7 100755 +--- a/share/extensions/embedimage.py ++++ b/share/extensions/embedimage.py +@@ -51,7 +51,7 @@ class Embedder(inkex.Effect): + self.document=document + self.selected=selected + if (self.options.ids): +- for id, node in selected.iteritems(): ++ for id, node in selected.items(): + if node.tag == inkex.addNS('image','svg'): + self.embedImage(node) + +diff --git a/share/extensions/extractimage.py b/share/extensions/extractimage.py +index 031a01560f..87ba6d6422 100755 +--- a/share/extensions/extractimage.py ++++ b/share/extensions/extractimage.py +@@ -44,7 +44,7 @@ class MyEffect(inkex.Effect): + path = self.options.filepath + if (path != ''): + if (self.options.ids): +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('image','svg'): + xlink = node.get(inkex.addNS('href','xlink')) + if (xlink[:4]=='data'): +diff --git a/share/extensions/extrude.py b/share/extensions/extrude.py +index b11d0d36c7..2a4d14ff79 100755 +--- a/share/extensions/extrude.py ++++ b/share/extensions/extrude.py +@@ -35,7 +35,7 @@ class Extrude(inkex.Effect): + + def effect(self): + paths = [] +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == '{http://www.w3.org/2000/svg}path': + paths.append(node) + if len(paths) < 2: +diff --git a/share/extensions/flatten.py b/share/extensions/flatten.py +index 7b4d2a7d62..ccd0373db2 100755 +--- a/share/extensions/flatten.py ++++ b/share/extensions/flatten.py +@@ -26,7 +26,7 @@ class MyEffect(inkex.Effect): + dest="flat", default=10.0, + help="Minimum flatness of the subdivided curves") + def effect(self): +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('path','svg'): + d = node.get('d') + p = cubicsuperpath.parsePath(d) +diff --git a/share/extensions/fractalize.py b/share/extensions/fractalize.py +index c6bbe397ac..68ad698026 100755 +--- a/share/extensions/fractalize.py ++++ b/share/extensions/fractalize.py +@@ -55,7 +55,7 @@ class PathFractalize(inkex.Effect): + dest="smooth", default="4.0", + help="Smoothness of the subdivision") + def effect(self): +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('path','svg'): + d = node.get('d') + p = simplepath.parsePath(d) +diff --git a/share/extensions/funcplot.py b/share/extensions/funcplot.py +index 557aac302b..3f0e9989d9 100755 +--- a/share/extensions/funcplot.py ++++ b/share/extensions/funcplot.py +@@ -251,7 +251,7 @@ class FuncPlot(inkex.Effect): + + def effect(self): + newpath = None +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('rect','svg'): + # create new path with basic dimensions of selected rectangle + newpath = inkex.etree.Element(inkex.addNS('path','svg')) +diff --git a/share/extensions/gcodetools.py b/share/extensions/gcodetools.py +index 590aa2209e..e639310f6d 100755 +--- a/share/extensions/gcodetools.py ++++ b/share/extensions/gcodetools.py +@@ -3018,7 +3018,7 @@ class Polygon: + self.polygon += [ poly ] + # Remove all edges that are intersects new poly (any vertex inside new poly) + poly_ = Polygon([poly]) +- for p in edges.keys()[:] : ++ for p in list(edges.keys()) : + if poly_.point_inside(list(p)) : del edges[p] + self.draw(color="Green", width=1) + +@@ -4545,7 +4545,7 @@ class Gcodetools(inkex.Effect): + self.check_dir() + gcode = "" + +- biarc_group = inkex.etree.SubElement( self.selected_paths.keys()[0] if len(self.selected_paths.keys())>0 else self.layers[0], inkex.addNS('g','svg') ) ++ biarc_group = inkex.etree.SubElement( list(self.selected_paths.keys())[0] if len(self.selected_paths)>0 else self.layers[0], inkex.addNS('g','svg') ) + print_(("self.layers=",self.layers)) + print_(("paths=",paths)) + colors = {} +@@ -6038,7 +6038,7 @@ G01 Z1 (going to cutting z)\n""", + else : + paths = self.selected_paths + # Set group +- group = inkex.etree.SubElement( self.selected_paths.keys()[0] if len(self.selected_paths.keys())>0 else self.layers[0], inkex.addNS('g','svg') ) ++ group = inkex.etree.SubElement( list(self.selected_paths.keys())[0] if len(self.selected_paths)>0 else self.layers[0], inkex.addNS('g','svg') ) + trans_ = [[1,0.3,0],[0,0.5,0]] + + self.set_markers() +diff --git a/share/extensions/handles.py b/share/extensions/handles.py +index 6987a3bb22..ffede1cf57 100755 +--- a/share/extensions/handles.py ++++ b/share/extensions/handles.py +@@ -20,7 +20,7 @@ import inkex, simplepath, simplestyle + + class Handles(inkex.Effect): + def effect(self): +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('path','svg'): + p = simplepath.parsePath(node.get('d')) + a =[] +diff --git a/share/extensions/image_attributes.py b/share/extensions/image_attributes.py +index 98cc5204ff..a0bf13daa0 100755 +--- a/share/extensions/image_attributes.py ++++ b/share/extensions/image_attributes.py +@@ -105,13 +105,13 @@ class SetAttrImage(inkex.Effect): + + def change_selected_only(self, selected, attribute): + if selected: +- for node_id, node in selected.iteritems(): ++ for node_id, node in selected.items(): + if node.tag == inkex.addNS('image', 'svg'): + self.change_attribute(node, attribute) + + def change_in_selection(self, selected, attribute): + if selected: +- for node_id, node in selected.iteritems(): ++ for node_id, node in selected.items(): + self.change_all_images(node, attribute) + + def change_in_document(self, selected, attribute): +@@ -119,7 +119,7 @@ class SetAttrImage(inkex.Effect): + + def change_on_parent_group(self, selected, attribute): + if selected: +- for node_id, node in selected.iteritems(): ++ for node_id, node in selected.items(): + self.change_attribute(node.getparent(), attribute) + + def change_on_root_only(self, selected, attribute): +diff --git a/share/extensions/inkscape_follow_link.py b/share/extensions/inkscape_follow_link.py +index bf19cb84f4..48e8b8bb57 100755 +--- a/share/extensions/inkscape_follow_link.py ++++ b/share/extensions/inkscape_follow_link.py +@@ -19,7 +19,7 @@ class FollowLink(inkex.Effect): + + def effect(self): + if (self.options.ids): +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('a','svg'): + self.url = node.get(inkex.addNS('href','xlink')) + vwswli = VisitWebSiteWithoutLockingInkscape(self.url) +diff --git a/share/extensions/interp.py b/share/extensions/interp.py +index 7d6b6fa454..e7e2fa2dc4 100755 +--- a/share/extensions/interp.py ++++ b/share/extensions/interp.py +@@ -134,7 +134,7 @@ class Interp(inkex.Effect): + + if self.options.zsort: + # work around selection order swapping with Live Preview +- sorted_ids = pathmodifier.zSort(self.document.getroot(),self.selected.keys()) ++ sorted_ids = pathmodifier.zSort(self.document.getroot(),list(self.selected.keys())) + else: + # use selection order (default) + sorted_ids = self.options.ids +@@ -209,9 +209,9 @@ class Interp(inkex.Effect): + t += l / etotal + lengths.setdefault(t,0) + lengths[t] += -1 +- sadd = [k for (k,v) in lengths.iteritems() if v < 0] ++ sadd = [k for (k,v) in lengths.items() if v < 0] + sadd.sort() +- eadd = [k for (k,v) in lengths.iteritems() if v > 0] ++ eadd = [k for (k,v) in lengths.items() if v > 0] + eadd.sort() + + t = 0 +diff --git a/share/extensions/interp_att_g.py b/share/extensions/interp_att_g.py +index 8718caf41f..74abb64344 100755 +--- a/share/extensions/interp_att_g.py ++++ b/share/extensions/interp_att_g.py +@@ -121,7 +121,7 @@ class InterpAttG(inkex.Effect): + if len( self.selected ) > 1: + # multiple selection + if self.options.zsort: +- sorted_ids = zSort(self.document.getroot(),self.selected.keys()) ++ sorted_ids = zSort(self.document.getroot(),list(self.selected.keys())) + else: + sorted_ids = self.options.ids + self.collection = list(sorted_ids) +diff --git a/share/extensions/jitternodes.py b/share/extensions/jitternodes.py +index b8c20d1046..a1b1bd83d6 100755 +--- a/share/extensions/jitternodes.py ++++ b/share/extensions/jitternodes.py +@@ -83,7 +83,7 @@ class JitterNodes(inkex.Effect): + help="The selected UI-tab when OK was pressed") + + def effect(self): +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('path','svg'): + d = node.get('d') + p = cubicsuperpath.parsePath(d) +diff --git a/share/extensions/lorem_ipsum.py b/share/extensions/lorem_ipsum.py +index efb2361ea2..18ee104dd5 100755 +--- a/share/extensions/lorem_ipsum.py ++++ b/share/extensions/lorem_ipsum.py +@@ -217,7 +217,7 @@ class MyEffect(inkex.Effect): + + def effect(self): + found=0 +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('flowRoot','svg'): + found+=1 + if found==1: +diff --git a/share/extensions/markers_strokepaint.py b/share/extensions/markers_strokepaint.py +index 34e2216de1..e685232a0b 100755 +--- a/share/extensions/markers_strokepaint.py ++++ b/share/extensions/markers_strokepaint.py +@@ -74,7 +74,7 @@ class MyEffect(inkex.Effect): + if defs == None: + defs = inkex.etree.SubElement(self.document.getroot(),inkex.addNS('defs','svg')) + +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + mprops = ['marker','marker-start','marker-mid','marker-end'] + try: + style = simplestyle.parseStyle(node.get('style')) +diff --git a/share/extensions/measure.py b/share/extensions/measure.py +index 7a8bf96e15..faf2d5463e 100755 +--- a/share/extensions/measure.py ++++ b/share/extensions/measure.py +@@ -227,7 +227,7 @@ class Length(inkex.Effect): + self.options.fontsize /= factor + factor *= scale/self.unittouu('1'+self.options.unit) + # loop over all selected paths +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('path','svg'): + mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) + p = cubicsuperpath.parsePath(node.get('d')) +diff --git a/share/extensions/merge_styles.py b/share/extensions/merge_styles.py +index d76333ae04..9bdacbb549 100755 +--- a/share/extensions/merge_styles.py ++++ b/share/extensions/merge_styles.py +@@ -38,7 +38,7 @@ class Style(dict): + self[name.strip()] = value.strip() + + def entries(self): +- return [ "%s:%s;" % (n,v) for (n,v) in self.iteritems() ] ++ return [ "%s:%s;" % (n,v) for (n,v) in self.items() ] + + def to_str(self, sep="\n "): + return " " + "\n ".join(self.entries()) +@@ -55,7 +55,7 @@ class Style(dict): + + def add(self, c, el): + self.total.append( (c, el) ) +- for name,value in c.iteritems(): ++ for name,value in c.items(): + if name not in self: + self[name] = value + if self[name] == value: +@@ -63,7 +63,7 @@ class Style(dict): + + def clean(self, threshold): + """Removes any elements that aren't the same using a weighted threshold""" +- for attr in self.keys(): ++ for attr in list(self.keys()): + if self.weights[attr] < len(self.total) - threshold: + self.pop(attr) + +@@ -119,7 +119,7 @@ class MergeStyles(inkex.Effect): + styles.text = (styles.text or "") + "\n" + common.css( newclass ) + + for (st, el) in common.all_matches(): +- st.remove(common.keys()) ++ st.remove(list(common.keys())) + el.attrib['style'] = st.to_str("") + + olds = 'class' in el.attrib and el.attrib['class'].split() or [] +diff --git a/share/extensions/motion.py b/share/extensions/motion.py +index 6046665dcb..47e3c36f02 100755 +--- a/share/extensions/motion.py ++++ b/share/extensions/motion.py +@@ -59,7 +59,7 @@ class Motion(inkex.Effect): + def effect(self): + self.vx = math.cos(math.radians(self.options.angle))*self.options.magnitude + self.vy = math.sin(math.radians(self.options.angle))*self.options.magnitude +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('path','svg'): + group = inkex.etree.SubElement(node.getparent(),inkex.addNS('g','svg')) + self.facegroup = inkex.etree.SubElement(group, inkex.addNS('g','svg')) +diff --git a/share/extensions/new_glyph_layer.py b/share/extensions/new_glyph_layer.py +index d6622cc620..4bd35b6a65 100755 +--- a/share/extensions/new_glyph_layer.py ++++ b/share/extensions/new_glyph_layer.py +@@ -51,7 +51,7 @@ class NewGlyphLayer(inkex.Effect): + + #TODO: make it optional ("Use current selection as template glyph") + # Move selection to the newly created layer +- for id,node in self.selected.iteritems(): ++ for id,node in self.selected.items(): + layer.append(node) + + if __name__ == '__main__': +diff --git a/share/extensions/param_curves.py b/share/extensions/param_curves.py +index e38d5208ae..b436ea45e0 100755 +--- a/share/extensions/param_curves.py ++++ b/share/extensions/param_curves.py +@@ -198,7 +198,7 @@ class ParamCurves(inkex.Effect): + help="dummy") + + def effect(self): +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('rect','svg'): + # create new path with basic dimensions of selected rectangle + newpath = inkex.etree.Element(inkex.addNS('path','svg')) +diff --git a/share/extensions/pathalongpath.py b/share/extensions/pathalongpath.py +index 8c3d420162..83eb3eef1c 100755 +--- a/share/extensions/pathalongpath.py ++++ b/share/extensions/pathalongpath.py +@@ -232,7 +232,7 @@ class PathAlongPath(pathmodifier.Diffeo): + if dx < 0.01: + exit(_("The total length of the pattern is too small :\nPlease choose a larger object or set 'Space between copies' > 0")) + +- for id, node in self.patterns.iteritems(): ++ for id, node in self.patterns.items(): + if node.tag == inkex.addNS('path','svg') or node.tag=='path': + d = node.get('d') + p0 = cubicsuperpath.parsePath(d) +@@ -240,7 +240,7 @@ class PathAlongPath(pathmodifier.Diffeo): + flipxy(p0) + + newp=[] +- for skelnode in self.skeletons.itervalues(): ++ for skelnode in self.skeletons.values(): + self.curSekeleton=cubicsuperpath.parsePath(skelnode.get('d')) + if self.options.vertical: + flipxy(self.curSekeleton) +diff --git a/share/extensions/pathmodifier.py b/share/extensions/pathmodifier.py +index 01c9a63845..8d4b2b8f18 100755 +--- a/share/extensions/pathmodifier.py ++++ b/share/extensions/pathmodifier.py +@@ -65,7 +65,7 @@ class PathModifier(inkex.Effect): + + def duplicateNodes(self, aList): + clones={} +- for id,node in aList.iteritems(): ++ for id,node in aList.items(): + clone=copy.deepcopy(node) + #!!!--> should it be given an id? + #seems to work without this!?! +@@ -82,7 +82,7 @@ class PathModifier(inkex.Effect): + return(id) + + def expandGroups(self,aList,transferTransform=True): +- for id, node in aList.items(): ++ for id, node in list(aList.items()): + if node.tag == inkex.addNS('g','svg') or node.tag=='g': + mat=parseTransform(node.get("transform")) + for child in node: +@@ -95,7 +95,7 @@ class PathModifier(inkex.Effect): + return(aList) + + def expandGroupsUnlinkClones(self,aList,transferTransform=True,doReplace=True): +- for id in aList.keys()[:]: ++ for id in list(aList.keys()): + node=aList[id] + if node.tag == inkex.addNS('g','svg') or node.tag=='g': + self.expandGroups(aList,transferTransform) +@@ -223,7 +223,7 @@ class PathModifier(inkex.Effect): + return(self.groupToPath(node,doReplace)) + elif node.tag == inkex.addNS('path','svg') or node.tag == 'path': + #remove inkscape attributes, otherwise any modif of 'd' will be discarded! +- for attName in node.attrib.keys(): ++ for attName in list(node.attrib.keys()): + if ("sodipodi" in attName) or ("inkscape" in attName): + del node.attrib[attName] + fuseTransform(node) +@@ -237,7 +237,7 @@ class PathModifier(inkex.Effect): + + def objectsToPaths(self,aList,doReplace=True): + newSelection={} +- for id,node in aList.items(): ++ for id,node in list(aList.items()): + newnode=self.objectToPath(node,doReplace) + del aList[id] + aList[newnode.get('id')]=newnode +@@ -253,7 +253,7 @@ class PathModifier(inkex.Effect): + #self.expandGroupsUnlinkClones(self.selected, True) + self.objectsToPaths(self.selected, True) + self.bbox=computeBBox(self.selected.values()) +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('path','svg'): + d = node.get('d') + p = cubicsuperpath.parsePath(d) +@@ -298,7 +298,7 @@ class Diffeo(PathModifier): + self.expandGroups(self.selected, True) + self.objectsToPaths(self.selected, True) + self.bbox=computeBBox(self.selected.values()) +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('path','svg') or node.tag=='path': + d = node.get('d') + p = cubicsuperpath.parsePath(d) +diff --git a/share/extensions/pathscatter.py b/share/extensions/pathscatter.py +index 361e8f8e17..363c69280b 100755 +--- a/share/extensions/pathscatter.py ++++ b/share/extensions/pathscatter.py +@@ -168,7 +168,7 @@ class PathScatter(pathmodifier.Diffeo): + + if self.options.copymode=="copy": + duplist=self.duplicateNodes({id:self.patternNode}) +- self.patternNode = duplist.values()[0] ++ self.patternNode = list(duplist.values())[0] + + #TODO: allow 4th option: duplicate the first copy and clone the next ones. + if "%s"%self.options.copymode=="clone": +@@ -251,7 +251,7 @@ class PathScatter(pathmodifier.Diffeo): + #inkex.debug(patternList) + + counter=0 +- for skelnode in self.skeletons.itervalues(): ++ for skelnode in self.skeletons.values(): + self.curSekeleton=cubicsuperpath.parsePath(skelnode.get('d')) + for comp in self.curSekeleton: + self.skelcomp,self.lengths=linearize(comp) +diff --git a/share/extensions/pixelsnap.py b/share/extensions/pixelsnap.py +index 96a8617e2f..49de6ec827 100755 +--- a/share/extensions/pixelsnap.py ++++ b/share/extensions/pixelsnap.py +@@ -496,7 +496,7 @@ class PixelSnapEffect(inkex.Effect): + + self.document_offset = self.unittouu(svg.attrib['height']) % 1 # although SVG units are absolute, the elements are positioned relative to the top of the page, rather than zero + +- for id, elem in self.selected.iteritems(): ++ for id, elem in self.selected.items(): + try: + self.pixel_snap(elem) + except TransformError as e: +diff --git a/share/extensions/replace_font.py b/share/extensions/replace_font.py +index 06d8a8661f..41ac863cda 100755 +--- a/share/extensions/replace_font.py ++++ b/share/extensions/replace_font.py +@@ -187,7 +187,7 @@ class ReplaceFont(inkex.Effect): + to_return = [] + if scope == "selection_only": + self.selected_items = [] +- for item in self.selected.iteritems(): ++ for item in self.selected.items(): + self.find_child_text_items(item[1]) + items = self.selected_items + if len(items) == 0: +diff --git a/share/extensions/restack.py b/share/extensions/restack.py +index 79a7565e7f..a1dabc9bad 100755 +--- a/share/extensions/restack.py ++++ b/share/extensions/restack.py +@@ -118,13 +118,13 @@ class Restack(inkex.Effect): + f.close + + #find the center of all selected objects **Not the average! +- x,y,w,h = dimen[objects.keys()[0]] ++ x,y,w,h = dimen[list(objects.keys())[0]] + minx = x + miny = y + maxx = x + w + maxy = y + h + +- for id, node in objects.iteritems(): ++ for id, node in objects.items(): + # get the bounding box + x,y,w,h = dimen[id] + if x < minx: +@@ -140,7 +140,7 @@ class Restack(inkex.Effect): + midy = (miny + maxy) / 2 + + #calculate distances for each selected object +- for id, node in objects.iteritems(): ++ for id, node in objects.items(): + # get the bounding box + x,y,w,h = dimen[id] + +@@ -194,7 +194,7 @@ class Restack(inkex.Effect): + objects.append(child) + else: + parentnode = self.current_layer +- for id_ in zSort(self.document.getroot(), self.selected.keys()): ++ for id_ in zSort(self.document.getroot(), list(self.selected.keys())): + objects.append(self.selected[id_]) + if self.options.zsort == "rev": + objects.reverse() +diff --git a/share/extensions/simplestyle.py b/share/extensions/simplestyle.py +index 32328a40d8..75a809713c 100644 +--- a/share/extensions/simplestyle.py ++++ b/share/extensions/simplestyle.py +@@ -180,7 +180,7 @@ def parseStyle(s): + + def formatStyle(a): + """Format an inline style attribute from a dictionary""" +- return ";".join([att+":"+str(val) for att,val in a.iteritems()]) ++ return ";".join([att+":"+str(val) for att,val in a.items()]) + + def isColor(c): + """Determine if its a color we can use. If not, leave it unchanged.""" +diff --git a/share/extensions/split.py b/share/extensions/split.py +index 4e83b3d334..538fc41ab9 100755 +--- a/share/extensions/split.py ++++ b/share/extensions/split.py +@@ -194,7 +194,7 @@ class Split(inkex.Effect): + preserve = self.options.preserve + + #checks if the selected elements are text nodes +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if not (node.tag == inkex.addNS("text", "svg") or node.tag == inkex.addNS("flowRoot", "svg")): + inkex.debug("Please select only text elements.") + break +diff --git a/share/extensions/straightseg.py b/share/extensions/straightseg.py +index d477dbdf07..67b37a52fb 100755 +--- a/share/extensions/straightseg.py ++++ b/share/extensions/straightseg.py +@@ -38,7 +38,7 @@ class SegmentStraightener(inkex.Effect): + dest="behave", default=1, + help="straightening behavior for cubic segments") + def effect(self): +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + if node.tag == inkex.addNS('path', 'svg'): + d = node.get('d') + p = simplepath.parsePath(d) +diff --git a/share/extensions/synfig_fileformat.py b/share/extensions/synfig_fileformat.py +index 41e6bee38c..59ec990edc 100755 +--- a/share/extensions/synfig_fileformat.py ++++ b/share/extensions/synfig_fileformat.py +@@ -195,7 +195,7 @@ blend_method_names = { + 19 : "alpha over" #deprecated + } + +-blend_methods = dict((v, k) for (k, v) in blend_method_names.iteritems()) ++blend_methods = dict((v, k) for (k, v) in blend_method_names.items()) + + ###### Functions ########################################## + def paramType(layer, param, value=None): +diff --git a/share/extensions/text_extract.py b/share/extensions/text_extract.py +index b6b575dfc3..71e02108ab 100755 +--- a/share/extensions/text_extract.py ++++ b/share/extensions/text_extract.py +@@ -91,13 +91,13 @@ class Extract(inkex.Effect): + f.close + + #find the center of all selected objects **Not the average! +- x,y,w,h = dimen[self.selected.keys()[0]] ++ x,y,w,h = dimen[list(self.selected.keys())[0]] + minx = x + miny = y + maxx = x + w + maxy = y + h + +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + # get the bounding box + x,y,w,h = dimen[id] + if x < minx: +@@ -113,7 +113,7 @@ class Extract(inkex.Effect): + midy = (miny + maxy) / 2 + + #calculate distances for each selected object +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + # get the bounding box + x,y,w,h = dimen[id] + +diff --git a/share/extensions/text_merge.py b/share/extensions/text_merge.py +index a3ba29022d..ac67a01bbb 100755 +--- a/share/extensions/text_merge.py ++++ b/share/extensions/text_merge.py +@@ -99,13 +99,13 @@ class Merge(inkex.Effect): + f.close + + #find the center of all selected objects **Not the average! +- x,y,w,h = dimen[self.selected.keys()[0]] ++ x,y,w,h = dimen[list(self.selected.keys())[0]] + minx = x + miny = y + maxx = x + w + maxy = y + h + +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + # get the bounding box + x,y,w,h = dimen[id] + if x < minx: +@@ -121,7 +121,7 @@ class Merge(inkex.Effect): + midy = (miny + maxy) / 2 + + #calculate distances for each selected object +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + # get the bounding box + x,y,w,h = dimen[id] + +diff --git a/share/extensions/ungroup_deep.py b/share/extensions/ungroup_deep.py +index 359232007d..2eb212752d 100644 +--- a/share/extensions/ungroup_deep.py ++++ b/share/extensions/ungroup_deep.py +@@ -270,7 +270,7 @@ class Ungroup(inkex.Effect): + + def effect(self): + if len(self.selected): +- for elem in self.selected.itervalues(): ++ for elem in self.selected.values(): + self._deep_ungroup(elem) + else: + for elem in self.document.getroot(): +diff --git a/share/extensions/webslicer_create_group.py b/share/extensions/webslicer_create_group.py +index 567c911aa9..7a447d8807 100755 +--- a/share/extensions/webslicer_create_group.py ++++ b/share/extensions/webslicer_create_group.py +@@ -69,7 +69,7 @@ class WebSlicer_CreateGroup(WebSlicer_Effect): + if len(self.selected) == 0: + inkex.errormsg(_('You must to select some "Slicer rectangles" or other "Layout groups".')) + exit(1) +- for id,node in self.selected.iteritems(): ++ for id,node in self.selected.items(): + if node not in self.layer_descendants: + inkex.errormsg(_('Oops... The element "%s" is not in the Web Slicer layer') % id) + exit(2) +@@ -81,7 +81,7 @@ class WebSlicer_CreateGroup(WebSlicer_Effect): + 'width_unity', 'height_unity', + 'bg_color' ] ) + +- for id,node in self.selected.iteritems(): ++ for id,node in self.selected.items(): + group.insert( 1, node ) + + +diff --git a/share/extensions/whirl.py b/share/extensions/whirl.py +index 93e04c60da..d132ba1499 100755 +--- a/share/extensions/whirl.py ++++ b/share/extensions/whirl.py +@@ -32,7 +32,7 @@ class Whirl(inkex.Effect): + help="direction of rotation") + def effect(self): + view_center = computePointInNode(list(self.view_center), self.current_layer) +- for id, node in self.selected.iteritems(): ++ for id, node in self.selected.items(): + rotation = -1 + if self.options.rotation == True: + rotation = 1 +-- +2.21.0 + + +From 22a042c74443cc15ce1b3cd6300b0f76ddac7a53 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 12:14:00 +0100 +Subject: [PATCH 10/17] extensions 2to3: string (module) + +--- + share/extensions/dpiswitcher.py | 3 +-- + share/extensions/hpgl_encoder.py | 5 ++--- + share/extensions/interp_att_g.py | 5 ++--- + share/extensions/render_alphabetsoup.py | 3 +-- + 4 files changed, 6 insertions(+), 10 deletions(-) + +diff --git a/share/extensions/dpiswitcher.py b/share/extensions/dpiswitcher.py +index 0f8fd4c048..5a3f6e429f 100644 +--- a/share/extensions/dpiswitcher.py ++++ b/share/extensions/dpiswitcher.py +@@ -43,7 +43,6 @@ TODO: + # standard libraries + import sys + import re +-import string + import math + from lxml import etree + # local libraries +@@ -347,7 +346,7 @@ class DPISwitcher(inkex.Effect): + xpathStr = '//sodipodi:guide' + guides = svg.xpath(xpathStr, namespaces=inkex.NSS) + for guide in guides: +- point = string.split(guide.get("position"), ",") ++ point = guide.get("position").split(",") + guide.set("position", str(float(point[0].strip()) * self.factor_a ) + "," + str(float(point[1].strip()) * self.factor_a )) + + def scaleGrid(self, svg): +diff --git a/share/extensions/hpgl_encoder.py b/share/extensions/hpgl_encoder.py +index b9975215f9..075683d4aa 100644 +--- a/share/extensions/hpgl_encoder.py ++++ b/share/extensions/hpgl_encoder.py +@@ -21,7 +21,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + # standard libraries + import math + import re +-import string + # local libraries + import bezmisc + import cspsubdiv +@@ -95,9 +94,9 @@ class hpglEncoder: + self.debugValues['viewBoxHeight'] = "-" + viewBox = self.doc.get('viewBox') + if viewBox: +- viewBox2 = string.split(viewBox, ',') ++ viewBox2 = viewBox.split(',') + if len(viewBox2) < 4: +- viewBox2 = string.split(viewBox, ' ') ++ viewBox2 = viewBox.split(' ') + if self.options.debug: + self.debugValues['viewBoxWidth'] = viewBox2[2] + self.debugValues['viewBoxHeight'] = viewBox2[3] +diff --git a/share/extensions/interp_att_g.py b/share/extensions/interp_att_g.py +index 74abb64344..547bb33e63 100755 +--- a/share/extensions/interp_att_g.py ++++ b/share/extensions/interp_att_g.py +@@ -19,7 +19,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + # standard library + import math + import re +-import string + # local library + import inkex + import simplestyle +@@ -68,8 +67,8 @@ class InterpAttG(inkex.Effect): + help="The selected UI-tab when OK was pressed") + + def getColorValues(self): +- sv = string.replace( self.options.start_val, '#', '' ) +- ev = string.replace( self.options.end_val, '#', '' ) ++ sv = self.options.start_val.replace('#', '' ) ++ ev = self.options.end_val.replace('#', '' ) + if re.search('\s|,', sv): + # There are separators. That must be a integer RGB color definition. + sv = re.split( '[\s,]+', sv ) +diff --git a/share/extensions/render_alphabetsoup.py b/share/extensions/render_alphabetsoup.py +index c529e6202c..4666ef55f5 100755 +--- a/share/extensions/render_alphabetsoup.py ++++ b/share/extensions/render_alphabetsoup.py +@@ -22,7 +22,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + import copy + import math + import cmath +-import string + import random + import os + import sys +@@ -332,7 +331,7 @@ def randomize_input_string(tokens, zoom ): # generate a glyph starting fr + if ((i > 0) and (char == tokens[i-1])): # if this letter matches previous letter + imagelist.append(imagelist[len(stack)-1])# make them the same image + else: # generate image for letter +- stack = string.split( alphabet[char][random.randint(0,(len(alphabet[char])-1))] , "." ) ++ stack = alphabet[char][random.randint(0,(len(alphabet[char])-1))].split(".") + #stack = string.split( alphabet[char][random.randint(0,(len(alphabet[char])-2))] , "." ) + imagelist.append( draw_crop_scale( stack, zoom )) + elif( char == " "): # add a " " space to the image list +-- +2.21.0 + + +From 76fb3d5a19403af08823a725bdd95d5fe4005d33 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 12:55:49 +0100 +Subject: [PATCH 11/17] extensions 2to3: Barcode + +--- + share/extensions/Barcode/Code39.py | 4 ++-- + share/extensions/Barcode/Code39Ext.py | 10 +++++----- + share/extensions/Barcode/Code93.py | 10 +++++----- + share/extensions/Barcode/Rm4scc.py | 6 +++--- + 4 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/share/extensions/Barcode/Code39.py b/share/extensions/Barcode/Code39.py +index 0d4d445b1e..63ed0a8e70 100644 +--- a/share/extensions/Barcode/Code39.py ++++ b/share/extensions/Barcode/Code39.py +@@ -19,7 +19,7 @@ + Python barcode renderer for Code39 barcodes. Designed for use with Inkscape. + """ + +-from Base import Barcode ++from .Base import Barcode + + ENCODE = { + '0': '000110100', +@@ -77,7 +77,7 @@ class Code39(Barcode): + # into full ascii, but this feature is + # not enabled here + for char in '*' + self.text + '*': +- if not ENCODE.has_key(char): ++ if char not in ENCODE: + char = '-' + result = result + ENCODE[char] + '0' + +diff --git a/share/extensions/Barcode/Code39Ext.py b/share/extensions/Barcode/Code39Ext.py +index 3edf82d2e4..99d7ce5f7d 100644 +--- a/share/extensions/Barcode/Code39Ext.py ++++ b/share/extensions/Barcode/Code39Ext.py +@@ -19,7 +19,7 @@ + Python barcode renderer for Code39 Extended barcodes. Designed for Inkscape. + """ + +-from Code39 import Code39 ++from .Code39 import Code39 + + encode = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') + +@@ -51,13 +51,13 @@ class Code39Ext(Code39): + # We are only going to extend the Code39 barcodes + result = '' + for char in text: +- if mapA.has_key(char): ++ if char in mapA: + char = '%' + mapA[char] +- elif mapB.has_key(char): ++ elif char in mapB: + char = '$' + mapB[char] +- elif mapC.has_key(char): ++ elif char in mapC: + char = '/' + mapC[char] +- elif mapD.has_key(char): ++ elif char in mapD: + char = '+' + mapD[char] + result = result + char + +diff --git a/share/extensions/Barcode/Code93.py b/share/extensions/Barcode/Code93.py +index 939a739dd8..76a74bccd3 100644 +--- a/share/extensions/Barcode/Code93.py ++++ b/share/extensions/Barcode/Code93.py +@@ -95,18 +95,18 @@ class Code93(Barcode): + def encode_ascii(self, text): + result = [] + for char in text: +- if MAP.has_key(char): ++ if char in MAP: + result.append(char) +- elif MAP_A.has_key(char): ++ elif char in MAP_A: + result.append('(%)') + result.append(MAP_A[char]) +- elif MAP_B.has_key(char): ++ elif char in MAP_B: + result.append('($)') + result.append(MAP_B[char]) +- elif MAP_C.has_key(char): ++ elif char in MAP_C: + result.append('(/)') + result.append(MAP_C[char]) +- elif MAP_D.has_key(char): ++ elif char in MAP_D: + result.append('(+)') + result.append(MAP_D[char]) + return result +diff --git a/share/extensions/Barcode/Rm4scc.py b/share/extensions/Barcode/Rm4scc.py +index 7c36f26ee3..6f9e8aaa57 100644 +--- a/share/extensions/Barcode/Rm4scc.py ++++ b/share/extensions/Barcode/Rm4scc.py +@@ -19,7 +19,7 @@ + Python barcode renderer for RM4CC barcodes. Designed for use with Inkscape. + """ + +-from Base import Barcode ++from .Base import Barcode + + map = { + '(' : '25', +@@ -79,7 +79,7 @@ class Rm4scc(Barcode): + + i = 0 + for char in text: +- if map.has_key(char): ++ if char in map: + result = result + map[char] + i = i + 1 + +@@ -90,7 +90,7 @@ class Rm4scc(Barcode): + total_lower = 0 + total_upper = 0 + for char in text: +- if map.has_key(char): ++ if char in map: + bars = map[char][0:8:2] + lower = 0 + upper = 0 +-- +2.21.0 + + +From 6600a8f300676d88024d19964024cfa1e20d4b22 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 12:57:07 +0100 +Subject: [PATCH 12/17] extensions 2to3: run tests with Python 3.7 + +--- + share/extensions/color_randomize.py | 4 ++-- + share/extensions/guides_creator.py | 8 ++++---- + share/extensions/inkex.py | 8 +++++--- + share/extensions/polyhedron_3d.py | 2 ++ + share/extensions/svg_and_media_zip_output.py | 6 ++++-- + share/extensions/test/render_barcode.test.py | 2 +- + 6 files changed, 18 insertions(+), 12 deletions(-) + +diff --git a/share/extensions/color_randomize.py b/share/extensions/color_randomize.py +index 93abcf1742..eb46ba6dc0 100755 +--- a/share/extensions/color_randomize.py ++++ b/share/extensions/color_randomize.py +@@ -20,7 +20,7 @@ class C(coloreffect.ColorEffect): + action="store", type="int", + dest="lightness_range", default=0, + help="Lightness range") +- self.OptionParser.add_option("-o", "--opacity_range", ++ self.OptionParser.add_option("-o", "--opacity_range", + action="store", type="int", + dest="opacity_range", default=0, + help="Opacity range") +@@ -51,7 +51,7 @@ class C(coloreffect.ColorEffect): + if self.options.lightness_range > 0: + hsl[2] = self.randomize_hsl(self.options.lightness_range, hsl[2]) + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) +- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) ++ return '%02x%02x%02x' % tuple(int(i * 0xFF) for i in rgb) + + def opacmod(self, opacity): + if self.options.opacity_range > 0: +diff --git a/share/extensions/guides_creator.py b/share/extensions/guides_creator.py +index 70144d9dd8..ecc0008872 100755 +--- a/share/extensions/guides_creator.py ++++ b/share/extensions/guides_creator.py +@@ -140,7 +140,7 @@ class Guides_Creator(inkex.Effect): + inkex.Effect.__init__(self) + + # Define option for the tab. +- self.OptionParser.add_option("--tab", ++ self.OptionParser.add_option("--tab", + action="store",type="string", + dest="tab", default="regular_guides", + help="") +@@ -486,8 +486,8 @@ class Guides_Creator(inkex.Effect): + drawVerticalGuides(v_subdiv,rectangle_width,rectangle_height,0,nv,begin_from) + + if __name__ == '__main__': +- # Create effect instance and apply it. +- effect = Guides_Creator() +- effect.affect() ++ # Create effect instance and apply it. ++ effect = Guides_Creator() ++ effect.affect() + + ## end of file guide_creator.py ## +diff --git a/share/extensions/inkex.py b/share/extensions/inkex.py +index 8a94c55cc1..d31e467f9c 100755 +--- a/share/extensions/inkex.py ++++ b/share/extensions/inkex.py +@@ -35,9 +35,6 @@ import re + import sys + from math import * + +-if sys.version_info[0] >= 3: +- unicode = str +- + # a dictionary of all of the xmlns prefixes in a standard inkscape doc + NSS = { + u'sodipodi' :u'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd', +@@ -106,6 +103,11 @@ def errormsg(msg): + else: + sys.stderr.write((unicode(msg, "utf-8", errors='replace') + "\n").encode("utf-8")) + ++if sys.version_info[0] >= 3: ++ def errormsg(msg): ++ if isinstance(msg, bytes): ++ msg = msg.decode(errors='replace') ++ sys.stderr.write(msg + "\n") + + def are_near_relative(a, b, eps): + return (a-b <= a*eps) and (a-b >= -a*eps) +diff --git a/share/extensions/polyhedron_3d.py b/share/extensions/polyhedron_3d.py +index c39d351749..265900e76b 100755 +--- a/share/extensions/polyhedron_3d.py ++++ b/share/extensions/polyhedron_3d.py +@@ -137,6 +137,8 @@ def get_obj_data(obj, name): + if obj.name == '':#no name was found, use filename, without extension (.obj) + obj.name = name[0:-4] + ++ infile.close() ++ + #RENDERING AND SVG OUTPUT FUNCTIONS + + def draw_SVG_dot(_cx_cy, st, name, parent): +diff --git a/share/extensions/svg_and_media_zip_output.py b/share/extensions/svg_and_media_zip_output.py +index f3df1d9908..927bbdcc42 100755 +--- a/share/extensions/svg_and_media_zip_output.py ++++ b/share/extensions/svg_and_media_zip_output.py +@@ -145,10 +145,12 @@ class CompressedMediaOutput(inkex.Effect): + and add it to the temporary compressed file + ''' + dst_file = os.path.join(self.tmp_dir, docstripped) +- stream = open(dst_file,'w') ++ stream = open(dst_file,'wb') + self.document.write(stream) + stream.close() +- z.write(dst_file,docstripped.encode(self.encoding)+'.svg') ++ if sys.version_info[0] < 3: ++ docstripped = docstripped.encode(self.encoding) ++ z.write(dst_file, docstripped + '.svg') + + def is_text(self, node): + ''' +diff --git a/share/extensions/test/render_barcode.test.py b/share/extensions/test/render_barcode.test.py +index f2ce23873b..a346b601c5 100755 +--- a/share/extensions/test/render_barcode.test.py ++++ b/share/extensions/test/render_barcode.test.py +@@ -25,7 +25,7 @@ class InsertBarcodeBasicTest(unittest.TestCase): + for line in fhl: + line = line.replace('\n', '').replace('\r', '') + (btype, text, code) = line.split(':') +- if not self.data.has_key(btype): ++ if btype not in self.data: + self.data[btype] = [] + self.data[btype].append( [ text, code ] ) + fhl.close() +-- +2.21.0 + + +From 68f934181d5e630293b6dc20cfd7a7339ea4e238 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 13:30:11 +0100 +Subject: [PATCH 13/17] extensions 2to3: '%x' int + +--- + share/extensions/color_HSL_adjust.py | 2 +- + share/extensions/color_lesshue.py | 2 +- + share/extensions/color_lesslight.py | 2 +- + share/extensions/color_lesssaturation.py | 2 +- + share/extensions/color_morehue.py | 2 +- + share/extensions/color_morelight.py | 2 +- + share/extensions/color_moresaturation.py | 2 +- + 7 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/share/extensions/color_HSL_adjust.py b/share/extensions/color_HSL_adjust.py +index 473c4bd1e2..3dbb660315 100755 +--- a/share/extensions/color_HSL_adjust.py ++++ b/share/extensions/color_HSL_adjust.py +@@ -61,7 +61,7 @@ class C(coloreffect.ColorEffect): + hsl[2] = self.clamp(0.0, lightval, 1.0) + #inkex.debug("hsl new: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2])) + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) +- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) ++ return '%02x%02x%02x' % tuple(int(i * 0xFF) for i in rgb) + + c = C() + c.affect() +diff --git a/share/extensions/color_lesshue.py b/share/extensions/color_lesshue.py +index d34a75019d..b67a7cfafe 100755 +--- a/share/extensions/color_lesshue.py ++++ b/share/extensions/color_lesshue.py +@@ -9,7 +9,7 @@ class C(coloreffect.ColorEffect): + if hsl[0] < 0.0: + hsl[0] = 1.0 + hsl[0] + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) +- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) ++ return '%02x%02x%02x' % tuple(int(i * 0xFF) for i in rgb) + + c = C() + c.affect() +diff --git a/share/extensions/color_lesslight.py b/share/extensions/color_lesslight.py +index 94dfb412d0..4466a37268 100755 +--- a/share/extensions/color_lesslight.py ++++ b/share/extensions/color_lesslight.py +@@ -9,7 +9,7 @@ class C(coloreffect.ColorEffect): + if hsl[2] < 0.0: + hsl[2] = 0.0 + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) +- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) ++ return '%02x%02x%02x' % tuple(int(i * 0xFF) for i in rgb) + + c = C() + c.affect() +diff --git a/share/extensions/color_lesssaturation.py b/share/extensions/color_lesssaturation.py +index 1d3702c767..b01b38d420 100755 +--- a/share/extensions/color_lesssaturation.py ++++ b/share/extensions/color_lesssaturation.py +@@ -9,7 +9,7 @@ class C(coloreffect.ColorEffect): + if hsl[1] < 0.0: + hsl[1] = 0.0 + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) +- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) ++ return '%02x%02x%02x' % tuple(int(i * 0xFF) for i in rgb) + + c = C() + c.affect() +diff --git a/share/extensions/color_morehue.py b/share/extensions/color_morehue.py +index 7d3406ec0e..40dd8bef5b 100755 +--- a/share/extensions/color_morehue.py ++++ b/share/extensions/color_morehue.py +@@ -9,7 +9,7 @@ class C(coloreffect.ColorEffect): + if hsl[0] > 1.0: + hsl[0] = hsl[0] - 1.0 + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) +- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) ++ return '%02x%02x%02x' % tuple(int(i * 0xFF) for i in rgb) + + c = C() + c.affect() +diff --git a/share/extensions/color_morelight.py b/share/extensions/color_morelight.py +index bbc418c3f7..44ab29efce 100755 +--- a/share/extensions/color_morelight.py ++++ b/share/extensions/color_morelight.py +@@ -9,7 +9,7 @@ class C(coloreffect.ColorEffect): + if hsl[2] > 1.0: + hsl[2] = 1.0 + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) +- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) ++ return '%02x%02x%02x' % tuple(int(i * 0xFF) for i in rgb) + + c = C() + c.affect() +diff --git a/share/extensions/color_moresaturation.py b/share/extensions/color_moresaturation.py +index 4ecb4987c0..a8248437f9 100755 +--- a/share/extensions/color_moresaturation.py ++++ b/share/extensions/color_moresaturation.py +@@ -9,7 +9,7 @@ class C(coloreffect.ColorEffect): + if hsl[1] > 1.0: + hsl[1] = 1.0 + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) +- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) ++ return '%02x%02x%02x' % tuple(int(i * 0xFF) for i in rgb) + + c = C() + c.affect() +-- +2.21.0 + + +From 305d561f00382731079049371e5f8b443b9b4b49 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 16:53:13 +0100 +Subject: [PATCH 14/17] extensions 2to3: Popen(universal_newlines=True) + +--- + share/extensions/inkex.py | 3 ++- + share/extensions/restack.py | 3 ++- + share/extensions/text_extract.py | 5 +++-- + share/extensions/text_merge.py | 5 +++-- + 4 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/share/extensions/inkex.py b/share/extensions/inkex.py +index d31e467f9c..44d3b1252f 100755 +--- a/share/extensions/inkex.py ++++ b/share/extensions/inkex.py +@@ -274,7 +274,8 @@ class Effect: + original = etree.tostring(self.original_document) + result = etree.tostring(self.document) + if original != result: +- self.document.write(sys.stdout) ++ out = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer ++ self.document.write(out) + + def affect(self, args=sys.argv[1:], output=True): + """Affect an SVG document with a callback effect""" +diff --git a/share/extensions/restack.py b/share/extensions/restack.py +index a1dabc9bad..855a53c47e 100755 +--- a/share/extensions/restack.py ++++ b/share/extensions/restack.py +@@ -95,7 +95,8 @@ class Restack(inkex.Effect): + #get all bounding boxes in file by calling inkscape again with the --query-all command line option + #it returns a comma separated list structured id,x,y,w,h + if bsubprocess: +- p = Popen('inkscape --query-all "%s"' % (file), shell=True, stdout=PIPE, stderr=PIPE) ++ p = Popen('inkscape --query-all "%s"' % (file), shell=True, stdout=PIPE, stderr=PIPE, ++ universal_newlines=True) + err = p.stderr + f = p.communicate()[0] + try: +diff --git a/share/extensions/text_extract.py b/share/extensions/text_extract.py +index 71e02108ab..6d6b156544 100755 +--- a/share/extensions/text_extract.py ++++ b/share/extensions/text_extract.py +@@ -68,7 +68,8 @@ class Extract(inkex.Effect): + # get all bounding boxes in file by calling inkscape again with the --query-all command line option + # it returns a comma separated list structured id,x,y,w,h + if bsubprocess: +- p = Popen('inkscape --query-all "%s"' % (file), shell=True, stdout=PIPE, stderr=PIPE) ++ p = Popen('inkscape --query-all "%s"' % (file), shell=True, stdout=PIPE, stderr=PIPE, ++ universal_newlines=True) + err = p.stderr + f = p.communicate()[0] + try: +@@ -85,7 +86,7 @@ class Extract(inkex.Effect): + dimen = dict() + for line in reader: + if len(line) > 0: +- dimen[line[0]] = map( float, line[1:]) ++ dimen[line[0]] = list(map( float, line[1:])) + + if not bsubprocess: #close file if opened using os.popen3 + f.close +diff --git a/share/extensions/text_merge.py b/share/extensions/text_merge.py +index ac67a01bbb..f79367b27f 100755 +--- a/share/extensions/text_merge.py ++++ b/share/extensions/text_merge.py +@@ -76,7 +76,8 @@ class Merge(inkex.Effect): + # get all bounding boxes in file by calling inkscape again with the --query-all command line option + # it returns a comma separated list structured id,x,y,w,h + if bsubprocess: +- p = Popen('inkscape --query-all "%s"' % (file), shell=True, stdout=PIPE, stderr=PIPE) ++ p = Popen('inkscape --query-all "%s"' % (file), shell=True, stdout=PIPE, stderr=PIPE, ++ universal_newlines=True) + err = p.stderr + f = p.communicate()[0] + try: +@@ -93,7 +94,7 @@ class Merge(inkex.Effect): + dimen = dict() + for line in reader: + if len(line) > 0: +- dimen[line[0]] = map( float, line[1:]) ++ dimen[line[0]] = list(map( float, line[1:])) + + if not bsubprocess: #close file if opened using os.popen3 + f.close +-- +2.21.0 + + +From ebb4c8eb90eede6f2015b228b776710d0c1a56d7 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 18:09:28 +0100 +Subject: [PATCH 15/17] extensions 2to3: TabError + +--- + share/extensions/gcodetools.py | 98 ++++++++++----------- + share/extensions/setup_typography_canvas.py | 10 +-- + 2 files changed, 54 insertions(+), 54 deletions(-) + +diff --git a/share/extensions/gcodetools.py b/share/extensions/gcodetools.py +index e639310f6d..c2b7898c91 100755 +--- a/share/extensions/gcodetools.py ++++ b/share/extensions/gcodetools.py +@@ -288,25 +288,25 @@ def point_inside_csp(p,csp, on_the_path = True) : + for i in range(1, len(subpath)) : + sp1, sp2 = subpath[i-1], subpath[i] + ax,ay,bx,by,cx,cy,dx,dy = csp_parameterize(sp1,sp2) +- if ax==0 and bx==0 and cx==0 and dx==x : ++ if ax==0 and bx==0 and cx==0 and dx==x : + #we've got a special case here +- b = csp_true_bounds( [[sp1,sp2]]) +- if b[1][1]<=y<=b[3][1] : ++ b = csp_true_bounds( [[sp1,sp2]]) ++ if b[1][1]<=y<=b[3][1] : + # points is on the path +- return on_the_path +- else : ++ return on_the_path ++ else : + # we can skip this segment because it wont influence the answer. +- pass +- else: +- for t in csp_line_intersection([x,y],[x,y+5],sp1,sp2) : +- if t == 0 or t == 1 : ++ pass ++ else: ++ for t in csp_line_intersection([x,y],[x,y+5],sp1,sp2) : ++ if t == 0 or t == 1 : + #we've got another special case here +- x1,y1 = csp_at_t(sp1,sp2,t) +- if y1==y : ++ x1,y1 = csp_at_t(sp1,sp2,t) ++ if y1==y : + # the point is on the path +- return on_the_path ++ return on_the_path + # if t == 0 we should have considered this case previously. +- if t == 1 : ++ if t == 1 : + # we have to check the next segmant if it is on the same side of the ray + st_d = csp_normalized_slope(sp1,sp2,1)[0] + if st_d == 0 : st_d = csp_normalized_slope(sp1,sp2,0.99)[0] +@@ -315,20 +315,20 @@ def point_inside_csp(p,csp, on_the_path = True) : + if (i+j) % len(subpath) == 0 : continue # skip the closing segment + sp11,sp22 = subpath[(i-1+j) % len(subpath)], subpath[(i+j) % len(subpath)] + ax1,ay1,bx1,by1,cx1,cy1,dx1,dy1 = csp_parameterize(sp1,sp2) +- if ax1==0 and bx1==0 and cx1==0 and dx1==x : continue # this segment parallel to the ray, so skip it ++ if ax1==0 and bx1==0 and cx1==0 and dx1==x : continue # this segment parallel to the ray, so skip it + en_d = csp_normalized_slope(sp11,sp22,0)[0] + if en_d == 0 : en_d = csp_normalized_slope(sp11,sp22,0.01)[0] + if st_d*en_d <=0 : +- ray_intersections_count += 1 +- break +- else : +- x1,y1 = csp_at_t(sp1,sp2,t) +- if y1==y : ++ ray_intersections_count += 1 ++ break ++ else : ++ x1,y1 = csp_at_t(sp1,sp2,t) ++ if y1==y : + # the point is on the path +- return on_the_path +- else : +- if y1>y and 3*ax*t**2 + 2*bx*t + cx !=0 : # if it's 0 the path only touches the ray +- ray_intersections_count += 1 ++ return on_the_path ++ else : ++ if y1>y and 3*ax*t**2 + 2*bx*t + cx !=0 : # if it's 0 the path only touches the ray ++ ray_intersections_count += 1 + return ray_intersections_count%2 == 1 + + def csp_close_all_subpaths(csp, tolerance = 0.000001): +@@ -1162,10 +1162,10 @@ def csp_seg_bound_to_csp_seg_bound_max_min_distance(sp1,sp2,sp3,sp4) : + + def csp_reverse(csp) : + for i in range(len(csp)) : +- n = [] +- for j in csp[i] : ++ n = [] ++ for j in csp[i] : + n = [ [j[2][:],j[1][:],j[0][:]] ] + n +- csp[i] = n[:] ++ csp[i] = n[:] + return csp + + +@@ -1221,9 +1221,9 @@ def csp_concat_subpaths(*s): + if s1 == [] : return s2 + if s2 == [] : return s1 + if (s1[-1][1][0]-s2[0][1][0])**2 + (s1[-1][1][1]-s2[0][1][1])**2 > 0.00001 : +- return s1[:-1]+[ [s1[-1][0],s1[-1][1],s1[-1][1]], [s2[0][1],s2[0][1],s2[0][2]] ] + s2[1:] +- else : +- return s1[:-1]+[ [s1[-1][0],s2[0][1],s2[0][2]] ] + s2[1:] ++ return s1[:-1]+[ [s1[-1][0],s1[-1][1],s1[-1][1]], [s2[0][1],s2[0][1],s2[0][2]] ] + s2[1:] ++ else : ++ return s1[:-1]+[ [s1[-1][0],s2[0][1],s2[0][2]] ] + s2[1:] + + if len(s) == 0 : return [] + if len(s) ==1 : return s[0] +@@ -1568,7 +1568,7 @@ def draw_pointer(x,color = "#f00", figure = "cross", group = None, comment = "", + + + def straight_segments_intersection(a,b, true_intersection = True) : # (True intersection means check ta and tb are in [0,1]) +- ax,bx,cx,dx, ay,by,cy,dy = a[0][0],a[1][0],b[0][0],b[1][0], a[0][1],a[1][1],b[0][1],b[1][1] ++ ax,bx,cx,dx, ay,by,cy,dy = a[0][0],a[1][0],b[0][0],b[1][0], a[0][1],a[1][1],b[0][1],b[1][1] + if (ax==bx and ay==by) or (cx==dx and cy==dy) : return False, 0, 0 + if (bx-ax)*(dy-cy)-(by-ay)*(dx-cx)==0 : # Lines are parallel + ta = (ax-cx)/(dx-cx) if cx!=dx else (ay-cy)/(dy-cy) +@@ -4030,7 +4030,7 @@ class Gcodetools(inkex.Effect): + trans = numpy.linalg.inv(trans).tolist()[:2] + return trans + else : +- return transform ++ return transform + + + def apply_transforms(self,g,csp, reverse=False): +@@ -4380,9 +4380,9 @@ class Gcodetools(inkex.Effect): + if value == None or key == None: continue + #print_("Found tool parameter '%s':'%s'" % (key,value)) + if key in self.default_tool.keys() : +- try : ++ try : + tool[key] = type(self.default_tool[key])(value) +- except : ++ except : + tool[key] = self.default_tool[key] + self.error(_("Warning! Tool's and default tool's parameter's (%s) types are not the same ( type('%s') != type('%s') ).") % (key, value, self.default_tool[key]), "tools_warning") + else : +@@ -4732,7 +4732,7 @@ class Gcodetools(inkex.Effect): + if (bounds[2]-bounds[0])**2+(bounds[3]-bounds[1])**2 < self.options.area_find_artefacts_diameter**2: + if self.options.area_find_artefacts_action == "mark with an arrow" : + arrow = cubicsuperpath.parsePath( 'm %s,%s 2.9375,-6.343750000001 0.8125,1.90625 6.843748640396,-6.84374864039 0,0 0.6875,0.6875 -6.84375,6.84375 1.90625,0.812500000001 z' % (subpath[0][1][0],subpath[0][1][1]) ) +- arrow = self.apply_transforms(path,arrow,True) ++ arrow = self.apply_transforms(path,arrow,True) + inkex.etree.SubElement(parent, inkex.addNS('path','svg'), + { + 'd': cubicsuperpath.formatPath(arrow), +@@ -4794,26 +4794,26 @@ class Gcodetools(inkex.Effect): + # Reverse path if needed. + if min_y!=float("-inf") : + # Move outline subpath to the beginning of csp +- subp = csp[min_i] +- del csp[min_i] +- j = min_j ++ subp = csp[min_i] ++ del csp[min_i] ++ j = min_j + # Split by the topmost point and join again +- if min_t in [0,1]: +- if min_t == 0: j=j-1 +- subp[-1][2], subp[0][0] = subp[-1][1], subp[0][1] +- subp = [ [subp[j][1], subp[j][1], subp[j][2]] ] + subp[j+1:] + subp[:j] + [ [subp[j][0], subp[j][1], subp[j][1]] ] ++ if min_t in [0,1]: ++ if min_t == 0: j=j-1 ++ subp[-1][2], subp[0][0] = subp[-1][1], subp[0][1] ++ subp = [ [subp[j][1], subp[j][1], subp[j][2]] ] + subp[j+1:] + subp[:j] + [ [subp[j][0], subp[j][1], subp[j][1]] ] + else: +- sp1,sp2,sp3 = csp_split(subp[j-1],subp[j],min_t) +- subp[-1][2], subp[0][0] = subp[-1][1], subp[0][1] ++ sp1,sp2,sp3 = csp_split(subp[j-1],subp[j],min_t) ++ subp[-1][2], subp[0][0] = subp[-1][1], subp[0][1] + subp = [ [ sp2[1], sp2[1],sp2[2] ] ] + [sp3] + subp[j+1:] + subp[:j-1] + [sp1] + [[ sp2[0], sp2[1],sp2[1] ]] +- csp = [subp] + csp ++ csp = [subp] + csp + # reverse path if needed + if csp_subpath_ccw(csp[0]) : + for i in range(len(csp)): +- n = [] +- for j in csp[i]: +- n = [ [j[2][:],j[1][:],j[0][:]] ] + n +- csp[i] = n[:] ++ n = [] ++ for j in csp[i]: ++ n = [ [j[2][:],j[1][:],j[0][:]] ] + n ++ csp[i] = n[:] + + + d = cubicsuperpath.formatPath(csp) +@@ -6479,7 +6479,7 @@ G01 Z1 (going to cutting z)\n""", + self.graffiti_reference_points[layer] = self.graffiti_reference_points[self.layers[i]] + break + if reference_points == None : +- self.error('There are no graffiti reference points for layer %s'%layer,"error") ++ self.error('There are no graffiti reference points for layer %s'%layer,"error") + + # Transform reference points + for i in range(len(self.graffiti_reference_points[layer])): +diff --git a/share/extensions/setup_typography_canvas.py b/share/extensions/setup_typography_canvas.py +index 209c9757f1..55758ee331 100755 +--- a/share/extensions/setup_typography_canvas.py ++++ b/share/extensions/setup_typography_canvas.py +@@ -69,7 +69,7 @@ class SetupTypographyCanvas(inkex.Effect): + self.svg = self.document.getroot() + self.svg.set("width", str(emsize)) + self.svg.set("height", str(emsize)) +- self.svg.set("viewBox", "0 0 " + str(emsize) + " " + str(emsize) ) ++ self.svg.set("viewBox", "0 0 " + str(emsize) + " " + str(emsize) ) + + baseline = descender + # Create guidelines +@@ -79,10 +79,10 @@ class SetupTypographyCanvas(inkex.Effect): + self.create_horizontal_guideline("xheight", baseline+xheight) + self.create_horizontal_guideline("descender", baseline-descender) + +- namedview = self.svg.find(inkex.addNS('namedview', 'sodipodi')) +- namedview.set(inkex.addNS('document-units', 'inkscape'), 'px') +- namedview.set(inkex.addNS('cx', 'inkscape'), str(emsize/2.0 )) +- namedview.set(inkex.addNS('cy', 'inkscape'), str(emsize/2.0 )) ++ namedview = self.svg.find(inkex.addNS('namedview', 'sodipodi')) ++ namedview.set(inkex.addNS('document-units', 'inkscape'), 'px') ++ namedview.set(inkex.addNS('cx', 'inkscape'), str(emsize/2.0 )) ++ namedview.set(inkex.addNS('cy', 'inkscape'), str(emsize/2.0 )) + + + if __name__ == '__main__': +-- +2.21.0 + + +From a0f105a3b501c4f68ca4a3e3bc4a7b21923833b2 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Mon, 4 Mar 2019 23:16:38 +0100 +Subject: [PATCH 16/17] extensions 2to3: // stdout.buffer sort(key) + +--- + share/extensions/Barcode/Code25i.py | 2 +- + share/extensions/dm2svg.py | 2 +- + share/extensions/dxf_input.py | 3 ++- + share/extensions/dxf_outlines.py | 2 +- + share/extensions/gcodetools.py | 2 +- + share/extensions/gimp_xcf.py | 3 ++- + share/extensions/guillotine.py | 11 ++--------- + share/extensions/hpgl_input.py | 3 ++- + share/extensions/jessyInk_export.py | 3 ++- + share/extensions/jessyInk_video.py | 5 +++-- + share/extensions/new_glyph_layer.py | 4 +++- + share/extensions/render_barcode_datamatrix.py | 12 ++++++------ + share/extensions/render_barcode_qrcode.py | 2 +- + share/extensions/run_command.py | 3 ++- + share/extensions/scour.inkscape.py | 5 +++-- + share/extensions/svg_and_media_zip_output.py | 3 ++- + share/extensions/synfig_output.py | 3 ++- + share/extensions/tar_layers.py | 14 ++++++-------- + share/extensions/uniconv_output.py | 3 ++- + share/extensions/wireframe_sphere.py | 2 +- + 20 files changed, 45 insertions(+), 42 deletions(-) + +diff --git a/share/extensions/Barcode/Code25i.py b/share/extensions/Barcode/Code25i.py +index 2c751559cf..b2265d2135 100644 +--- a/share/extensions/Barcode/Code25i.py ++++ b/share/extensions/Barcode/Code25i.py +@@ -49,7 +49,7 @@ class Code25i(Barcode): + number = '0' + number + + # Number is encoded by pairs of 2 figures +- size = len(number) / 2 ++ size = len(number) // 2 + encoded = '1010' + for i in range(size): + # First in the pair is encoded in black (1), second in white (0) +diff --git a/share/extensions/dm2svg.py b/share/extensions/dm2svg.py +index a8784a3002..d9b7d81ff5 100755 +--- a/share/extensions/dm2svg.py ++++ b/share/extensions/dm2svg.py +@@ -41,7 +41,7 @@ def process_file(filename): + + while True: + tag = f.read(1) +- if tag == '': ++ if tag == b'': + break + + if ord(tag) > 128: +diff --git a/share/extensions/dxf_input.py b/share/extensions/dxf_input.py +index 91e7a02e21..3e15c0b8fd 100755 +--- a/share/extensions/dxf_input.py ++++ b/share/extensions/dxf_input.py +@@ -534,6 +534,7 @@ while line[0] and (line[1] != 'ENDSEC' or not inENTITIES): + + if polylines: + inkex.errormsg(_('%d ENTITIES of type POLYLINE encountered and ignored. Please try to convert to Release 13 format using QCad.') % polylines) +-doc.write(inkex.sys.stdout) ++out = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer ++doc.write(out) + + # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99 +diff --git a/share/extensions/dxf_outlines.py b/share/extensions/dxf_outlines.py +index 8d87576b06..63d813f94c 100755 +--- a/share/extensions/dxf_outlines.py ++++ b/share/extensions/dxf_outlines.py +@@ -101,7 +101,7 @@ class MyEffect(inkex.Effect): + self.d = array([0], float) # knot vector + self.poly = [[0.0,0.0]] # LWPOLYLINE data + def output(self): +- print(''.join(self.dxf)) ++ print(b''.join(self.dxf)) + def dxf_add(self, str): + self.dxf.append(str.encode(self.options.char_encode)) + def dxf_line(self,csp): +diff --git a/share/extensions/gcodetools.py b/share/extensions/gcodetools.py +index c2b7898c91..a46cbd4ae2 100755 +--- a/share/extensions/gcodetools.py ++++ b/share/extensions/gcodetools.py +@@ -1552,7 +1552,7 @@ def draw_pointer(x,color = "#f00", figure = "cross", group = None, comment = "", + draw_text(text,x[0]+size*2.2,x[1]-size, group = group, font_size = font_size) + if figure == "line" : + s = "" +- for i in range(1,len(x)/2) : ++ for i in range(1,len(x) // 2) : + s+= " %s, %s " %(x[i*2],x[i*2+1]) + attrib.update({"d": "M %s,%s L %s"%(x[0],x[1],s), "style":"fill:none;stroke:%s;stroke-width:%f;"%(color,width),"comment":str(comment)}) + inkex.etree.SubElement( group, inkex.addNS('path','svg'), attrib) +diff --git a/share/extensions/gimp_xcf.py b/share/extensions/gimp_xcf.py +index d79717828e..e771ff813a 100755 +--- a/share/extensions/gimp_xcf.py ++++ b/share/extensions/gimp_xcf.py +@@ -273,7 +273,8 @@ class MyEffect(inkex.Effect): + except: + pass + try: +- sys.stdout.write(x.read()) ++ stdout = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer ++ stdout.write(x.read()) + finally: + x.close() + self.clear_tmp() +diff --git a/share/extensions/guillotine.py b/share/extensions/guillotine.py +index ee7ae39fa2..7ce53143f8 100755 +--- a/share/extensions/guillotine.py ++++ b/share/extensions/guillotine.py +@@ -52,13 +52,6 @@ import simplestyle + + locale.setlocale(locale.LC_ALL, '') + +-def float_sort(a, b): +- ''' +- This is used to sort the horizontal and vertical guide positions, +- which are floating point numbers, but which are held as text. +- ''' +- return cmp(float(a), float(b)) +- + class Guillotine(inkex.Effect): + """Exports slices made using guides""" + def __init__(self): +@@ -131,7 +124,7 @@ class Guillotine(inkex.Effect): + if h >= 0 and float(h) <= float(height): + horizontals.append(h) + horizontals.append(height) +- horizontals.sort(cmp=float_sort) ++ horizontals.sort(key=float) + return horizontals + + def get_vertical_slice_positions(self): +@@ -147,7 +140,7 @@ class Guillotine(inkex.Effect): + if v >= 0 and float(v) <= float(width): + verticals.append(v) + verticals.append(width) +- verticals.sort(cmp=float_sort) ++ verticals.sort(key=float) + return verticals + + def get_slices(self): +diff --git a/share/extensions/hpgl_input.py b/share/extensions/hpgl_input.py +index f9b8465dd3..f7edb9dcb2 100755 +--- a/share/extensions/hpgl_input.py ++++ b/share/extensions/hpgl_input.py +@@ -65,6 +65,7 @@ if 'UNKNOWN_COMMANDS' in warnings: + inkex.errormsg(_("The HPGL data contained unknown (unsupported) commands, there is a possibility that the drawing is missing some content.")) + + # deliver document to inkscape +-doc.write(inkex.sys.stdout) ++out = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer ++doc.write(out) + + # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99 +diff --git a/share/extensions/jessyInk_export.py b/share/extensions/jessyInk_export.py +index a08cfb6ddb..98cd897551 100755 +--- a/share/extensions/jessyInk_export.py ++++ b/share/extensions/jessyInk_export.py +@@ -122,7 +122,8 @@ class MyEffect(inkex.Effect): + msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) + + # Output the file. +- sys.stdout.write(out.read()) ++ stdout = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer ++ stdout.write(out.read()) + sys.stdout.close() + out.close() + +diff --git a/share/extensions/jessyInk_video.py b/share/extensions/jessyInk_video.py +index cf5052c446..ea86b30d80 100755 +--- a/share/extensions/jessyInk_video.py ++++ b/share/extensions/jessyInk_video.py +@@ -57,7 +57,7 @@ class JessyInk_Effects(inkex.Effect): + inkex.errormsg(_("Could not obtain the selected layer for inclusion of the video element.\n\n")) + + # Parse template file. +- tmplFile = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'jessyInk_video.svg'), 'r') ++ tmplFile = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'jessyInk_video.svg'), 'rb') + tmplRoot = etree.fromstring(tmplFile.read()) + tmplFile.close() + +@@ -83,7 +83,8 @@ class JessyInk_Effects(inkex.Effect): + layer[0].append(elem) + + def findInternalLinks(node, docRoot, nodeDict = {}): +- for entry in re.findall("url\(#.*\)", etree.tostring(node)): ++ for entry in re.findall(b"url\(#.*\)", etree.tostring(node)): ++ entry = entry.decode() + linkId = entry[5:len(entry) - 1] + + if linkId not in nodeDict: +diff --git a/share/extensions/new_glyph_layer.py b/share/extensions/new_glyph_layer.py +index 4bd35b6a65..b5cb164560 100755 +--- a/share/extensions/new_glyph_layer.py ++++ b/share/extensions/new_glyph_layer.py +@@ -35,7 +35,9 @@ class NewGlyphLayer(inkex.Effect): + + def effect(self): + # Get all the options +- unicode_chars = self.options.unicodechars.decode(self.encoding) ++ unicode_chars = self.options.unicodechars ++ if sys.version_info[0] < 3: ++ unicode_chars = unicode_chars.decode(self.encoding) + + #TODO: remove duplicate chars + +diff --git a/share/extensions/render_barcode_datamatrix.py b/share/extensions/render_barcode_datamatrix.py +index 7c6c333459..891a65975e 100755 +--- a/share/extensions/render_barcode_datamatrix.py ++++ b/share/extensions/render_barcode_datamatrix.py +@@ -267,7 +267,7 @@ def interleave( blocks, inter): + else: + result = [] + for block in blocks: #for each codeword block in the stream +- block_length = len(block)/inter #length of each interleaved block ++ block_length = len(block) // inter #length of each interleaved block + inter_blocks = [[0] * block_length for i in xrange(inter)] #the interleaved blocks + + for i in range(block_length): #for each element in the interleaved blocks +@@ -287,7 +287,7 @@ def combine_interleaved( blocks, inter, nd, nc, size144): + return blocks + else: + result = [] +- for i in range( len(blocks) / inter ): #for each group of "inter" blocks -> one full datamatrix ++ for i in range( len(blocks) // inter ): #for each group of "inter" blocks -> one full datamatrix + data_codewords = [] #interleaved data blocks + + if size144: +@@ -298,10 +298,10 @@ def combine_interleaved( blocks, inter, nd, nc, size144): + nc_range = nc*inter + + for j in range(nd_range): #for each codeword in the final list +- data_codewords.append( blocks[i*inter + j%inter][j/inter] ) ++ data_codewords.append( blocks[i*inter + j%inter][j // inter] ) + + for j in range(nc_range): #for each block, add the ecc codewords +- data_codewords.append( blocks[i*inter + j%inter][nd + j/inter] ) ++ data_codewords.append( blocks[i*inter + j%inter][nd + j // inter] ) + + result.append(data_codewords) + return result +@@ -603,8 +603,8 @@ def add_finder_pattern( array, data_nrow, data_ncol, reg_row, reg_col ): + + for i in range( data_nrow*reg_row ): + for j in range( data_ncol* reg_col ): +- dest_col = j + 1 + 2*(j/(data_ncol)) #offset by 1, plus two for every addition block +- dest_row = i + 1 + 2*(i/(data_nrow)) ++ dest_col = j + 1 + 2*(j // data_ncol) #offset by 1, plus two for every addition block ++ dest_row = i + 1 + 2*(i // data_nrow) + + datamatrix[dest_row][dest_col] = array[i][j] #transfer from the plain bit array + +diff --git a/share/extensions/render_barcode_qrcode.py b/share/extensions/render_barcode_qrcode.py +index 9e86296077..e81a216f55 100755 +--- a/share/extensions/render_barcode_qrcode.py ++++ b/share/extensions/render_barcode_qrcode.py +@@ -977,7 +977,7 @@ class QRRSBlock: + if rsBlock == None: + raise Exception("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel) + +- length = len(rsBlock) / 3 ++ length = len(rsBlock) // 3 + + list = [] + +diff --git a/share/extensions/run_command.py b/share/extensions/run_command.py +index d760567a19..0c19d44fe7 100755 +--- a/share/extensions/run_command.py ++++ b/share/extensions/run_command.py +@@ -77,7 +77,8 @@ def run(command_format, prog_name): + try: + f = open(svgfile, "rb") + data = f.read() +- sys.stdout.write(data) ++ stdout = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer ++ stdout.write(data) + f.close() + except IOError as inst: + msg = "Error reading temporary file: %s" % str(inst) +diff --git a/share/extensions/scour.inkscape.py b/share/extensions/scour.inkscape.py +index bf60b9617b..6ec280f6ae 100755 +--- a/share/extensions/scour.inkscape.py ++++ b/share/extensions/scour.inkscape.py +@@ -55,9 +55,10 @@ class ScourInkscape (inkex.Effect): + + def effect(self): + try: +- input = file(self.args[0], "r") ++ input = open(self.args[0], "r") + self.options.infilename = self.args[0] +- sys.stdout.write(scourString(input.read(), self.options).encode("UTF-8")) ++ stdout = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer ++ stdout.write(scourString(input.read(), self.options).encode("UTF-8")) + input.close() + sys.stdout.close() + except Exception as e: +diff --git a/share/extensions/svg_and_media_zip_output.py b/share/extensions/svg_and_media_zip_output.py +index 927bbdcc42..8fd7b7ebad 100755 +--- a/share/extensions/svg_and_media_zip_output.py ++++ b/share/extensions/svg_and_media_zip_output.py +@@ -99,7 +99,8 @@ class CompressedMediaOutput(inkex.Effect): + msvcrt.setmode(1, os.O_BINARY) + except: + pass +- sys.stdout.write(out.read()) ++ stdout = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer ++ stdout.write(out.read()) + out.close() + shutil.rmtree(self.tmp_dir) + +diff --git a/share/extensions/synfig_output.py b/share/extensions/synfig_output.py +index 5a36934aae..60d2653ea8 100755 +--- a/share/extensions/synfig_output.py ++++ b/share/extensions/synfig_output.py +@@ -1072,7 +1072,8 @@ class SynfigExport(SynfigPrep): + for layer in layers: + root_canvas.append(layer) + +- d.get_root_tree().write(sys.stdout) ++ out = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer ++ d.get_root_tree().write(out) + + def convert_node(self, node, d): + """Convert an SVG node to a list of Synfig layers""" +diff --git a/share/extensions/tar_layers.py b/share/extensions/tar_layers.py +index 8b60d889d1..f6586326c9 100755 +--- a/share/extensions/tar_layers.py ++++ b/share/extensions/tar_layers.py +@@ -25,10 +25,7 @@ import os + import sys + import copy + import tarfile +-if sys.version_info[0] < 3: +- import StringIO +-else: +- import io as StringIO ++import io + import calendar + import time + +@@ -89,17 +86,18 @@ class LayersOutput(inkex.Effect): + return node.tag == GROUP and node.attrib.get(GROUPMODE,'').lower() == 'layer' + + def io_document(self, name, doc): +- string = StringIO.StringIO() ++ string = io.BytesIO() + doc.write(string) +- string.seek(0) + info = tarfile.TarInfo(name=name+'.svg') + info.mtime = calendar.timegm(time.gmtime()) +- info.size = len(string.buf) ++ info.size = string.tell() ++ string.seek(0) + return dict(tarinfo=info, fileobj=string) + + def effect(self): + # open output tar file as a stream (to stdout) +- tar = tarfile.open(fileobj=sys.stdout, mode='w|') ++ out = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer ++ tar = tarfile.open(fileobj=out, mode='w|') + + # Switch stdout to binary on Windows. + if sys.platform == "win32": +diff --git a/share/extensions/uniconv_output.py b/share/extensions/uniconv_output.py +index 170477540a..d5a8b9405c 100755 +--- a/share/extensions/uniconv_output.py ++++ b/share/extensions/uniconv_output.py +@@ -74,7 +74,8 @@ def run(command_format, prog_name, uniconv_format): + try: + f = open(outfile, "rb") + data = f.read() +- sys.stdout.write(data) ++ stdout = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer ++ stdout.write(data) + f.close() + except IOError as inst: + msg = "Error reading temporary file: %s" % str(inst) +diff --git a/share/extensions/wireframe_sphere.py b/share/extensions/wireframe_sphere.py +index 870b75413b..e8428f48ba 100755 +--- a/share/extensions/wireframe_sphere.py ++++ b/share/extensions/wireframe_sphere.py +@@ -149,7 +149,7 @@ class Wireframe_Sphere(inkex.Effect): + + delta_long = 360.0/so.NUM_LONG #angle between neighbouring lines of longitude in degrees + +- for i in range(0,so.NUM_LONG/2): ++ for i in range(0,so.NUM_LONG // 2): + long_angle = so.ROT_OFFSET + (i*delta_long)*(pi/180.0); #The longitude of this particular line in radians + if long_angle > pi: + long_angle -= 2*pi +-- +2.21.0 + + +From 6e5fe7edb9ac3db28874e9fb4f859482bf3d05fe Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Wed, 6 Mar 2019 09:43:26 +0100 +Subject: [PATCH 17/17] extensions 2to3: rename xxx_todo_changeme + +--- + share/extensions/bezmisc.py | 36 +++++++++---------- + share/extensions/cspsubdiv.py | 4 +-- + share/extensions/draw_from_triangle.py | 4 +-- + share/extensions/gcodetools.py | 4 +-- + share/extensions/motion.py | 4 +-- + share/extensions/render_barcode_datamatrix.py | 8 ++--- + 6 files changed, 30 insertions(+), 30 deletions(-) + +diff --git a/share/extensions/bezmisc.py b/share/extensions/bezmisc.py +index 359db54213..36c28fd81e 100755 +--- a/share/extensions/bezmisc.py ++++ b/share/extensions/bezmisc.py +@@ -55,9 +55,9 @@ def rootWrapper(a,b,c,d): + return 1.0*(-d/c), + return () + +-def bezierparameterize(xxx_todo_changeme): ++def bezierparameterize(arg): + #parametric bezier +- ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = arg + x0=bx0 + y0=by0 + cx=3*(bx1-x0) +@@ -70,10 +70,10 @@ def bezierparameterize(xxx_todo_changeme): + return ax,ay,bx,by,cx,cy,x0,y0 + #ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + +-def linebezierintersect(xxx_todo_changeme1, xxx_todo_changeme2): ++def linebezierintersect(arg_a, arg_b): + #parametric line +- ((lx1,ly1),(lx2,ly2)) = xxx_todo_changeme1 +- ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme2 ++ ((lx1,ly1),(lx2,ly2)) = arg_a ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = arg_b + dd=lx1 + cc=lx2-lx1 + bb=ly1 +@@ -102,23 +102,23 @@ def linebezierintersect(xxx_todo_changeme1, xxx_todo_changeme2): + retval.append(bezierpointatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),i)) + return retval + +-def bezierpointatt(xxx_todo_changeme3,t): +- ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme3 ++def bezierpointatt(arg, t): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = arg + ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + x=ax*(t**3)+bx*(t**2)+cx*t+x0 + y=ay*(t**3)+by*(t**2)+cy*t+y0 + return x,y + +-def bezierslopeatt(xxx_todo_changeme4,t): +- ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme4 ++def bezierslopeatt(arg, t): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = arg + ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + dx=3*ax*(t**2)+2*bx*t+cx + dy=3*ay*(t**2)+2*by*t+cy + return dx,dy + +-def beziertatslope(xxx_todo_changeme5, xxx_todo_changeme6): +- ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme5 +- (dy,dx) = xxx_todo_changeme6 ++def beziertatslope(arg, d): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = arg ++ (dy,dx) = d + ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + #quadratic coefficents of slope formula + if dx: +@@ -147,8 +147,8 @@ def tpoint(_x1_y1, _x2_y2, t): + (x1, y1) = _x1_y1 + (x2, y2) = _x2_y2 + return x1+t*(x2-x1),y1+t*(y2-y1) +-def beziersplitatt(xxx_todo_changeme9,t): +- ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme9 ++def beziersplitatt(arg, t): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = arg + m1=tpoint((bx0,by0),(bx1,by1),t) + m2=tpoint((bx1,by1),(bx2,by2),t) + m3=tpoint((bx2,by2),(bx3,by3),t) +@@ -226,15 +226,15 @@ def Simpson(f, a, b, n_limit, tolerance): + #print multiplier, endsum, interval, asum, bsum, est1, est0 + return est1 + +-def bezierlengthSimpson(xxx_todo_changeme12, tolerance = 0.001): +- ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme12 ++def bezierlengthSimpson(arg, tolerance = 0.001): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = arg + global balfax,balfbx,balfcx,balfay,balfby,balfcy + ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + balfax,balfbx,balfcx,balfay,balfby,balfcy = 3*ax,2*bx,cx,3*ay,2*by,cy + return Simpson(balf, 0.0, 1.0, 4096, tolerance) + +-def beziertatlength(xxx_todo_changeme13, l = 0.5, tolerance = 0.001): +- ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme13 ++def beziertatlength(arg, l = 0.5, tolerance = 0.001): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = arg + global balfax,balfbx,balfcx,balfay,balfby,balfcy + ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + balfax,balfbx,balfcx,balfay,balfby,balfcy = 3*ax,2*bx,cx,3*ay,2*by,cy +diff --git a/share/extensions/cspsubdiv.py b/share/extensions/cspsubdiv.py +index c44e50ce49..8187beac71 100755 +--- a/share/extensions/cspsubdiv.py ++++ b/share/extensions/cspsubdiv.py +@@ -2,8 +2,8 @@ + from bezmisc import * + from ffgeom import * + +-def maxdist(xxx_todo_changeme): +- ((p0x,p0y),(p1x,p1y),(p2x,p2y),(p3x,p3y)) = xxx_todo_changeme ++def maxdist(arg): ++ ((p0x,p0y),(p1x,p1y),(p2x,p2y),(p3x,p3y)) = arg + p0 = Point(p0x,p0y) + p1 = Point(p1x,p1y) + p2 = Point(p2x,p2y) +diff --git a/share/extensions/draw_from_triangle.py b/share/extensions/draw_from_triangle.py +index 3fd0ebb3ff..2a44659a57 100755 +--- a/share/extensions/draw_from_triangle.py ++++ b/share/extensions/draw_from_triangle.py +@@ -103,8 +103,8 @@ def get_cartesian_pt( t, p):#get the cartesian coordinates from a trilinear set + c2 = p[0][2]*t[2]/denom + return ( c1*p[2][1][0]+c2*p[2][0][0], c1*p[2][1][1]+c2*p[2][0][1] ) + +-def get_cartesian_tri(xxx_todo_changeme6, params):#get the cartesian points from a trilinear vertex matrix +- ((t11,t12,t13),(t21,t22,t23),(t31,t32,t33)) = xxx_todo_changeme6 ++def get_cartesian_tri(arg, params):#get the cartesian points from a trilinear vertex matrix ++ ((t11,t12,t13),(t21,t22,t23),(t31,t32,t33)) = arg + p1=get_cartesian_pt( (t11,t12,t13), params ) + p2=get_cartesian_pt( (t21,t22,t23), params ) + p3=get_cartesian_pt( (t31,t32,t33), params ) +diff --git a/share/extensions/gcodetools.py b/share/extensions/gcodetools.py +index a46cbd4ae2..54b53cf867 100755 +--- a/share/extensions/gcodetools.py ++++ b/share/extensions/gcodetools.py +@@ -107,8 +107,8 @@ except: + exit() + + +-def bezierslopeatt(xxx_todo_changeme20,t): +- ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = xxx_todo_changeme20 ++def bezierslopeatt(arg, t): ++ ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) = arg + ax,ay,bx,by,cx,cy,x0,y0=bezmisc.bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))) + dx=3*ax*(t**2)+2*bx*t+cx + dy=3*ay*(t**2)+2*by*t+cy +diff --git a/share/extensions/motion.py b/share/extensions/motion.py +index 47e3c36f02..6ff24047ba 100755 +--- a/share/extensions/motion.py ++++ b/share/extensions/motion.py +@@ -30,8 +30,8 @@ class Motion(inkex.Effect): + dest="magnitude", default=100.0, + help="magnitude of the motion vector") + +- def makeface(self,last, xxx_todo_changeme): +- (cmd, params) = xxx_todo_changeme ++ def makeface(self, last, arg): ++ (cmd, params) = arg + a = [] + a.append(['M',last[:]]) + a.append([cmd, params[:]]) +diff --git a/share/extensions/render_barcode_datamatrix.py b/share/extensions/render_barcode_datamatrix.py +index 891a65975e..881640f462 100755 +--- a/share/extensions/render_barcode_datamatrix.py ++++ b/share/extensions/render_barcode_datamatrix.py +@@ -100,9 +100,9 @@ symbols = { + #===================================================================== + + #create a 2d list corresponding to the 1's and 0s of the DataMatrix +-def encode(text, xxx_todo_changeme ): ++def encode(text, n_row_col): + #retreive the parameters of this size of DataMatrix +- (nrow, ncol) = xxx_todo_changeme ++ (nrow, ncol) = n_row_col + data_nrow, data_ncol, reg_row, reg_col, nd, nc, inter = get_parameters( nrow, ncol ) + + if not ((nrow == 144) and (ncol == 144)): #we have a regular datamatrix +@@ -516,9 +516,9 @@ def utah(array, nrow, ncol, row, col, char): + + #"place_bits" fills an nrow x ncol array with the bits from the + # codewords in data. +-def place_bits(data, xxx_todo_changeme1): ++def place_bits(data, n_row_col): + # First, fill the array[] with invalid entries */ +- (nrow, ncol) = xxx_todo_changeme1 ++ (nrow, ncol) = n_row_col + INVALID = 2 + array = [[INVALID] * ncol for i in xrange(nrow)] #initialise and fill with -1's (invalid value) + # Starting in the correct location for character #1, bit 8,... +-- +2.21.0 + diff --git a/mr_582_extensions_python3_compatibility.patch b/mr_582_extensions_python3_compatibility.patch new file mode 100644 index 0000000..05a9018 --- /dev/null +++ b/mr_582_extensions_python3_compatibility.patch @@ -0,0 +1,130 @@ +From d3ed2703736d9157b2cdadd4b5a95324aacc6191 Mon Sep 17 00:00:00 2001 +From: Thomas Holder +Date: Tue, 12 Mar 2019 16:29:56 +0100 +Subject: [PATCH] extensions 2to3: follow-up + +--- + share/extensions/color_desaturate.py | 2 +- + share/extensions/dxf_input.py | 2 +- + share/extensions/dxf_outlines.py | 2 +- + share/extensions/ink2canvas/svg.py | 6 +++++- + share/extensions/voronoi.py | 12 +++++++++--- + 5 files changed, 17 insertions(+), 7 deletions(-) + +diff --git a/share/extensions/color_desaturate.py b/share/extensions/color_desaturate.py +index a2350a4d32..978e199a29 100755 +--- a/share/extensions/color_desaturate.py ++++ b/share/extensions/color_desaturate.py +@@ -3,7 +3,7 @@ import coloreffect + + class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): +- l = (max(r,g,b)+min(r,g,b))/2 ++ l = (max(r,g,b)+min(r,g,b)) // 2 + ig=int(round(l)) + return '%02x%02x%02x' % (ig,ig,ig) + +diff --git a/share/extensions/dxf_input.py b/share/extensions/dxf_input.py +index 3e15c0b8fd..8754e7cb63 100755 +--- a/share/extensions/dxf_input.py ++++ b/share/extensions/dxf_input.py +@@ -109,7 +109,7 @@ def export_SPLINE(): + vals[groups['20']].insert(i-1, (1.0 - a1)*vals[groups['20']][i-2] + a1*vals[groups['20']][i-1]) + ctrls = len(vals[groups['10']]) + path = 'M %f,%f' % (vals[groups['10']][0], vals[groups['20']][0]) +- for i in range (0, (ctrls - 1)/3): ++ for i in range (0, (ctrls - 1) // 3): + path += ' C %f,%f %f,%f %f,%f' % (vals[groups['10']][3*i + 1], vals[groups['20']][3*i + 1], vals[groups['10']][3*i + 2], vals[groups['20']][3*i + 2], vals[groups['10']][3*i + 3], vals[groups['20']][3*i + 3]) + if vals[groups['70']][0] & 1: # closed path + path += ' z' +diff --git a/share/extensions/dxf_outlines.py b/share/extensions/dxf_outlines.py +index e07681bbba..53c1a523e6 100755 +--- a/share/extensions/dxf_outlines.py ++++ b/share/extensions/dxf_outlines.py +@@ -103,7 +103,7 @@ class MyEffect(inkex.Effect): + self.poly = [[0.0,0.0]] # LWPOLYLINE data + def output(self): + stdout = sys.stdout if sys.version_info[0] < 3 else sys.stdout.buffer +- stdout.write(b''.join(self.dxf)) ++ stdout.write(b''.join(self.dxf) + b'\n') + def dxf_add(self, str): + self.dxf.append(str.encode(self.options.char_encode)) + def dxf_line(self,csp): +diff --git a/share/extensions/ink2canvas/svg.py b/share/extensions/ink2canvas/svg.py +index f4dca8279d..8d1402b7b0 100644 +--- a/share/extensions/ink2canvas/svg.py ++++ b/share/extensions/ink2canvas/svg.py +@@ -16,6 +16,10 @@ along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + ''' + ++import sys ++if sys.version_info[0] > 2: ++ unicode = lambda s: s.decode() if isinstance(s, bytes) else str(s) ++ + import inkex + import simplestyle + from simplepath import parsePath +@@ -326,7 +330,7 @@ class Polygon(Path): + points = map(lambda x: x.split(","), points) + comm = [] + for pt in points: # creating path command similar +- pt = map(float, pt) ++ pt = list(map(float, pt)) + comm.append(["L", pt]) + comm[0][0] = "M" # first command must be a 'M' => moveTo + return comm +diff --git a/share/extensions/voronoi.py b/share/extensions/voronoi.py +index af83007f1a..d3e9b124df 100644 +--- a/share/extensions/voronoi.py ++++ b/share/extensions/voronoi.py +@@ -189,7 +189,7 @@ def voronoi(siteList,context): + if not priorityQ.isEmpty(): + minpt = priorityQ.getMinPt() + +- if (newsite and (priorityQ.isEmpty() or cmp(newsite,minpt) < 0)): ++ if (newsite and (priorityQ.isEmpty() or newsite < minpt)): + # newsite is smallest - this is a site event + context.outSite(newsite) + +@@ -341,6 +341,9 @@ class Site(object): + else: + return 0 + ++ def __lt__(self, other): ++ return self.__cmp__(other) < 0 ++ + def distance(self,other): + dx = self.x - other.x + dy = self.y - other.y +@@ -442,6 +445,9 @@ class Halfedge(object): + else: + return 0 + ++ def __lt__(self, other): ++ return self.__cmp__(other) < 0 ++ + def leftreg(self,default): + if not self.edge: + return default +@@ -519,7 +525,7 @@ class Halfedge(object): + + xint = (e1.c*e2.b - e2.c*e1.b) / d + yint = (e2.c*e1.a - e1.c*e2.a) / d +- if(cmp(e1.reg[1],e2.reg[1]) < 0): ++ if e1.reg[1] < e2.reg[1]: + he = self + e = e1 + else: +@@ -637,7 +643,7 @@ class PriorityQueue(object): + he.ystar = site.y + offset + last = self.hash[self.getBucket(he)] + next = last.qnext +- while((next is not None) and cmp(he,next) > 0): ++ while((next is not None) and he > next): + last = next + next = last.qnext + he.qnext = last.qnext +-- +2.21.0 +