Hi, I have ported qreator to Python 3, you can find a debdiff in attachment.
I did not test everything, so there might still be some issues around. I did not forward it to upstream, feel free to do it if you want. regards, Hugo -- Hugo Lefeuvre (hle) | www.owl.eu.com RSA4096_ 360B 03B3 BF27 4F4D 7A3F D5E8 14AA 1EB8 A247 3DFD ed25519_ 37B2 6D38 0B25 B8A2 6B9F 3A65 A36F 5357 5F2D DC4C
diff -Nru qreator-16.06.1/debian/changelog qreator-16.06.1/debian/changelog --- qreator-16.06.1/debian/changelog 2019-03-30 15:35:12.000000000 -0400 +++ qreator-16.06.1/debian/changelog 2019-08-30 10:37:56.000000000 -0400 @@ -1,3 +1,10 @@ +qreator (16.06.1-3.2) unstable; urgency=medium + + * Non-maintainer upload. + * Port to Python 3 (Closes: #938316). + + -- Hugo Lefeuvre <h...@debian.org> Fri, 30 Aug 2019 10:37:56 -0400 + qreator (16.06.1-3.1) unstable; urgency=medium * Non-maintainer upload. diff -Nru qreator-16.06.1/debian/control qreator-16.06.1/debian/control --- qreator-16.06.1/debian/control 2018-04-14 08:48:31.000000000 -0400 +++ qreator-16.06.1/debian/control 2019-08-30 10:37:56.000000000 -0400 @@ -3,8 +3,27 @@ Priority: optional Maintainer: Chow Loong Jin <hyper...@debian.org> Build-Depends: debhelper (>= 8.0.0), - python-all (>= 2.6.6-3~), - python-distutils-extra + geoclue-2.0, + gir1.2-champlain-0.12, + gir1.2-clutter-1.0, + gir1.2-gdkpixbuf-2.0, + gir1.2-geoclue-2.0, + gir1.2-glib-2.0, + gir1.2-gtk-3.0, + gir1.2-gtkchamplain-0.12, + gir1.2-gtkclutter-1.0, + gir1.2-nm-1.0, + python3-all (>= 2.6.6-3~), + python3-cairo, + python3-dbus, + python3-distutils-extra, + python3-gi, + python3-gi-cairo, + python3-pil (>= 2.0.0), + python3-qrencode, + python3-requests, + python3-vobject, + python3-xdg Standards-Version: 4.1.3 Homepage: https://launchpad.net/qreator Vcs-Git: https://anonscm.debian.org/git/collab-maint/qreator.git @@ -12,26 +31,27 @@ Package: qreator Architecture: all -Depends: ${python:Depends}, ${misc:Depends}, - python-pil (>= 2.0.0), - python-cairo, - python-dbus, - python-gi, - python-gi-cairo, +Depends: geoclue-2.0, gir1.2-champlain-0.12, gir1.2-clutter-1.0, + gir1.2-gdkpixbuf-2.0, gir1.2-geoclue-2.0, gir1.2-glib-2.0, - gir1.2-gdkpixbuf-2.0, gir1.2-gtk-3.0, gir1.2-gtkchamplain-0.12, gir1.2-gtkclutter-1.0, gir1.2-nm-1.0, - python-qrencode, - python-requests, - python-vobject, - python-xdg, - geoclue-2.0 + python3-cairo, + python3-dbus, + python3-gi, + python3-gi-cairo, + python3-pil (>= 2.0.0), + python3-qrencode, + python3-requests, + python3-vobject, + python3-xdg, + ${misc:Depends}, + ${python3:Depends} Description: graphical utility for creating QR codes Qreator enables you to easily create your own QR codes to encode different types of information in an efficient, compact and cool way. diff -Nru qreator-16.06.1/debian/patches/python3-port.patch qreator-16.06.1/debian/patches/python3-port.patch --- qreator-16.06.1/debian/patches/python3-port.patch 1969-12-31 19:00:00.000000000 -0500 +++ qreator-16.06.1/debian/patches/python3-port.patch 2019-08-30 10:37:56.000000000 -0400 @@ -0,0 +1,426 @@ +Subject: Port to python 3 +Author: Hugo Lefeuvre <h...@debian.org> +Last-Update: 2019-08-30 +--- a/qreator/QRCode.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/qreator/QRCode.py 2019-08-30 16:12:48.309437828 -0400 +@@ -18,7 +18,7 @@ + try: + import qrencode + except ImportError: +- print "You need to install the python-qrencode package" ++ print("You need to install the python-qrencode package") + sys.exit(1) + from PIL import Image + from PIL import ImageOps +@@ -143,11 +143,11 @@ + def _add_border(self, current_color_bg=None): + '''Adds a border to the QR code''' + if current_color_bg: +- fill = (current_color_bg[0], current_color_bg[1], +- current_color_bg[2], 255) ++ fill = (int(current_color_bg[0]), int(current_color_bg[1]), ++ int(current_color_bg[2]), 255) + else: + fill = 'white' + # Add a border +- border_size = (self.output_size - self.image.size[0]) / 2 ++ border_size = int((self.output_size - self.image.size[0]) / 2) + self.image = ImageOps.expand(self.image, border=border_size, + fill=fill) +--- a/qreator/qrcodes/QRCodeLocation.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/qreator/qrcodes/QRCodeLocation.py 2019-08-30 10:53:58.819320724 -0400 +@@ -15,8 +15,8 @@ + ### END LICENSE + + from qreator_lib.i18n import _ +-from QRCodeType import QRCodeType +-from QRCodeLocationGtk import QRCodeLocationGtk ++from .QRCodeType import QRCodeType ++from .QRCodeLocationGtk import QRCodeLocationGtk + + class QRCodeLocation(QRCodeType): + description = _('Geolocation') +--- a/qreator/qrcodes/QRCodeText.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/qreator/qrcodes/QRCodeText.py 2019-08-30 10:53:58.819320724 -0400 +@@ -16,7 +16,7 @@ + + from qreator_lib.i18n import _ + from . QRCodeType import QRCodeType +-from QRCodeTextGtk import QRCodeTextGtk ++from .QRCodeTextGtk import QRCodeTextGtk + + class QRCodeText(QRCodeType): + description = _('Text') +--- a/qreator/qrcodes/QRCodeType.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/qreator/qrcodes/QRCodeType.py 2019-08-30 10:53:58.819320724 -0400 +@@ -34,7 +34,7 @@ + cls.dataformats.append(cls) + + +-class QRCodeType(object): ++class QRCodeType(object, metaclass=DataformatsMount): + """This class is the base for QRCode dataformats. It is not used itself. + + Classes implementing a dataformat type should provide the following class +@@ -58,7 +58,6 @@ + to the general code update function. + ==================== ===================================================== + """ +- __metaclass__ = DataformatsMount + + # replace the description, and make it translatable with _("") + description = "DataFormat" +--- a/qreator/qrcodes/QRCodeURLGtk.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/qreator/qrcodes/QRCodeURLGtk.py 2019-08-30 16:59:30.609128046 -0400 +@@ -15,7 +15,7 @@ + ### END LICENSE + + from gi.repository import Gtk, GObject +-from GtkHelpers import clear_text_entry, show_clear_icon ++from .GtkHelpers import clear_text_entry, show_clear_icon + from qreator_lib.helpers import get_data_file + from qreator_lib.i18n import _ + import requests +@@ -33,9 +33,9 @@ + def short_url(self): + self.r = requests.get("{0}?format=simple&url={1}".format(self.api_url, + self.url)) +- if self.r.content.startswith("Error"): ++ if self.r.content.startswith(b'Error'): + raise Exception(self.r.content) +- return self.r.content ++ return self.r.content.decode("UTF-8") + + + class TinyUrlShortener(object): +@@ -48,7 +48,7 @@ + + def short_url(self): + self.r = requests.get("{0}?url={1}".format(self.api_url, self.url)) +- return self.r.content ++ return self.r.content.decode("UTF-8") + + + class BitlyShortener(object): +--- a/qreator/qrcodes/QRCodeURL.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/qreator/qrcodes/QRCodeURL.py 2019-08-30 10:53:58.819320724 -0400 +@@ -15,8 +15,8 @@ + ### END LICENSE + + from qreator_lib.i18n import _ +-from QRCodeType import QRCodeType +-from QRCodeURLGtk import QRCodeURLGtk ++from .QRCodeType import QRCodeType ++from .QRCodeURLGtk import QRCodeURLGtk + + class QRCodeURL(QRCodeType): + description = _('URL') +--- a/qreator/qrcodes/QRCodeVCardGtk.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/qreator/qrcodes/QRCodeVCardGtk.py 2019-08-30 16:17:51.540296752 -0400 +@@ -33,7 +33,7 @@ + # X-KADDRESSBOOK-X-ManagersName, X-KADDRESSBOOK-X-Office + # X-KADDRESSBOOK-X-Profession, X-KADDRESSBOOK-X-SpouseName + +-from GtkHelpers import clear_text_entry, show_clear_icon ++from .GtkHelpers import clear_text_entry, show_clear_icon + from gi.repository import Gtk, GObject + from qreator_lib.helpers import get_data_file + from qreator_lib.i18n import _ +@@ -69,8 +69,8 @@ + (_("Textphone"), "textphone"), + ] + +-USAGE_TYPES = [(_("Home"), u"home"), +- (_("Work"), u"work")] ++USAGE_TYPES = [(_("Home"), "home"), ++ (_("Work"), "work")] + + + def on_icon(widget=None, icon=None, button=None): +@@ -157,7 +157,7 @@ + def add_entries(self, card): + text = self.entry.get_text() + if text: +- card.add(self.entry_field).value = text.decode("utf-8") ++ card.add(self.entry_field).value = text + return card + + +@@ -194,7 +194,7 @@ + def add_entries(self, card): + text = self.entry.get_text() + if text: +- card.add(self.entry_field).value = text.decode("utf-8") ++ card.add(self.entry_field).value = text + getattr(card, + self.entry_field).type_param = USAGE_TYPES[ + self.usagecombo.get_active()][1] +@@ -241,7 +241,7 @@ + def add_entries(self, card): + text = self.entry.get_text() + if text: +- card.add(self.entry_field).value = text.decode("utf-8") ++ card.add(self.entry_field).value = text + tp = [USAGE_TYPES[self.usagecombo.get_active()][1], + PHONE_TYPES[self.phonecombo.get_active()][1]] + getattr(card, +@@ -328,9 +328,9 @@ + if street or city or region or code or country or postbox: + card.add("adr") + card.adr.value = vobject.vcard.Address( +- street.decode("utf-8"), city.decode("utf-8"), +- region.decode("utf-8"), code.decode("utf-8"), +- country.decode("utf-8"), postbox.decode("utf-8")) ++ street, city, ++ region, code, ++ country, postbox) + getattr(card, + self.entry_field).type_param = USAGE_TYPES[ + self.usagecombo.get_active()][1] +@@ -370,9 +370,9 @@ + f = self['entry2'].get_text() + g = self['entry1'].get_text() + self.j.n.value = vobject.vcard.Name( +- family=f.decode("utf-8"), given=g.decode("utf-8")) ++ family=f, given=g) + self.j.add("fn") +- self.j.fn.value = self.fullname_template.format(f, g).decode("utf-8") ++ self.j.fn.value = self.fullname_template.format(f, g) + + for e in VCardEntry.instances: + self.j = e.add_entries(self.j) +--- a/qreator/qrcodes/QRCodeVCard.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/qreator/qrcodes/QRCodeVCard.py 2019-08-30 10:53:58.819320724 -0400 +@@ -15,8 +15,8 @@ + ### END LICENSE + + from qreator_lib.i18n import _ +-from QRCodeType import QRCodeType +-from QRCodeVCardGtk import QRCodeVCardGtk ++from .QRCodeType import QRCodeType ++from .QRCodeVCardGtk import QRCodeVCardGtk + + + class QRCodeVCard(QRCodeType): +--- a/qreator/qrcodes/QRCodeWifiGtk.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/qreator/qrcodes/QRCodeWifiGtk.py 2019-08-30 17:00:44.268871912 -0400 +@@ -14,7 +14,7 @@ + # with this program. If not, see <http://www.gnu.org/licenses/>. + ### END LICENSE + +-from GtkHelpers import clear_text_entry, show_clear_icon ++from .GtkHelpers import clear_text_entry, show_clear_icon + from qreator_lib.i18n import _ + from qreator_lib.helpers import get_data_file + from gi.repository import Gtk, GLib, GdkPixbuf, NM +@@ -88,7 +88,7 @@ + for ssid in ssids: + if not ssid[1] in ssidelements: + p = self.strength_pixbufs[min(99, ssid[0]) // 25] +- self.SSIDmodel.append([ssid[1], p]) ++ self.SSIDmodel.append([ssid[1].decode("UTF-8"), p]) + self.comboboxSSID.set_model(self.SSIDmodel) + + return True # -> repeat the timeout calls +--- a/qreator/qrcodes/QRCodeWifi.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/qreator/qrcodes/QRCodeWifi.py 2019-08-30 10:53:58.819320724 -0400 +@@ -15,8 +15,8 @@ + ### END LICENSE + + from qreator_lib.i18n import _ +-from QRCodeType import QRCodeType +-from QRCodeWifiGtk import QRCodeWifiGtk ++from .QRCodeType import QRCodeType ++from .QRCodeWifiGtk import QRCodeWifiGtk + + class QRCodeWifi(QRCodeType): + description = _('Wifi network') +--- a/qreator/QreatorWindow.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/qreator/QreatorWindow.py 2019-08-30 18:22:08.963700068 -0400 +@@ -27,8 +27,8 @@ + from qreator_lib import Window + from qreator_lib.helpers import get_media_file + +-from QRCode import QRCode +-from QRCode import QRCodeOutput ++from .QRCode import QRCode ++from .QRCode import QRCodeOutput + + from qreator.qrcodes.QRCodeType import QRCodeType + +--- a/qreator_lib/Builder.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/qreator_lib/Builder.py 2019-08-30 10:53:58.819320724 -0400 +@@ -120,7 +120,7 @@ + connection_dict = {} + connection_dict.update(self.glade_handler_dict) + connection_dict.update(callback_handler_dict) +- for item in connection_dict.items(): ++ for item in list(connection_dict.items()): + if item[1] is None: + # the handler is missing so reroute to default_handler + handler = functools.partial( +@@ -167,7 +167,7 @@ + ''' provides an object with attributes as glade widgets''' + def __init__(self, widget_dict): + self._widget_dict = widget_dict +- for (widget_name, widget) in widget_dict.items(): ++ for (widget_name, widget) in list(widget_dict.items()): + setattr(self, widget_name, widget) + + # Mangle any non-usable names (like with spaces or dashes) +@@ -176,7 +176,7 @@ + consider using a pythonic name instead of design name '%s'""" + consider_message = """consider using a pythonic name instead of design name '%s'""" + +- for (widget_name, widget) in widget_dict.items(): ++ for (widget_name, widget) in list(widget_dict.items()): + pyname = make_pyname(widget_name) + if pyname != widget_name: + if hasattr(self, pyname): +@@ -187,7 +187,7 @@ + + def iterator(): + '''Support 'for o in self' ''' +- return iter(widget_dict.values()) ++ return iter(list(widget_dict.values())) + setattr(self, '__iter__', iterator) + + def __getitem__(self, name): +@@ -260,7 +260,7 @@ + + callback_handler_dict = dict_from_callback_obj(callback_obj) + +- for item in builder.widgets.items(): ++ for item in list(builder.widgets.items()): + (widget_name, widget) = item + signal_ids = [] + try: +@@ -296,7 +296,7 @@ + widget_name, widget = item + + for handler_name in handler_names: +- target = handler_name in callback_handler_dict.keys() ++ target = handler_name in list(callback_handler_dict.keys()) + connection = (widget_name, signal_name, handler_name) + duplicate = connection in connections + if target and not duplicate: +@@ -312,7 +312,7 @@ + + connected_functions = [x[2] for x in connections] + +- handler_names = callback_handler_dict.keys() ++ handler_names = list(callback_handler_dict.keys()) + unconnected = [x for x in handler_names if x.startswith('on_')] + + for handler_name in connected_functions: +--- a/setup.py 2019-08-30 10:53:58.823320698 -0400 ++++ b/setup.py 2019-08-30 11:10:50.726701711 -0400 +@@ -23,7 +23,7 @@ + try: + import DistUtilsExtra.auto + except ImportError: +- print >> sys.stderr, 'To build qreator you need https://launchpad.net/python-distutils-extra' ++ print('To build qreator you need https://launchpad.net/python-distutils-extra', file=sys.stderr) + sys.exit(1) + assert DistUtilsExtra.auto.__version__ >= '2.18', 'needs DistUtilsExtra.auto >= 2.18' + +@@ -32,8 +32,8 @@ + filename = os.path.join(libdir, 'qreator_lib/qreatorconfig.py') + oldvalues = {} + try: +- fin = file(filename, 'r') +- fout = file(filename + '.new', 'w') ++ fin = open(filename, 'r') ++ fout = open(filename + '.new', 'w') + + for line in fin: + fields = line.split(' = ') # Separate variable from value +@@ -46,8 +46,8 @@ + fout.close() + fin.close() + os.rename(fout.name, fin.name) +- except (OSError, IOError), e: +- print ("ERROR: Can't find %s" % filename) ++ except (OSError, IOError) as e: ++ print(("ERROR: Can't find %s" % filename)) + sys.exit(1) + return oldvalues + +@@ -65,7 +65,7 @@ + desktop_file = desktop_path + '/qreator.desktop' + + if not os.path.exists(old_desktop_file): +- print ("ERROR: Can't find", old_desktop_file) ++ print(("ERROR: Can't find", old_desktop_file)) + sys.exit(1) + elif target_data != prefix + '/': + # This is an /opt install, so rename desktop file to use extras- +@@ -75,7 +75,7 @@ + os.rename(old_desktop_file, desktop_file) + os.rmdir(old_desktop_path) + except OSError as e: +- print ("ERROR: Can't rename", old_desktop_file, ":", e) ++ print(("ERROR: Can't rename", old_desktop_file, ":", e)) + sys.exit(1) + + return desktop_file +@@ -83,8 +83,8 @@ + def update_desktop_file(filename, target_pkgdata, target_scripts): + + try: +- fin = file(filename, 'r') +- fout = file(filename + '.new', 'w') ++ fin = open(filename, 'r') ++ fout = open(filename + '.new', 'w') + + for line in fin: + if 'Icon=' in line: +@@ -100,8 +100,8 @@ + fout.close() + fin.close() + os.rename(fout.name, fin.name) +- except (OSError, IOError), e: +- print ("ERROR: Can't find %s" % filename) ++ except (OSError, IOError) as e: ++ print(("ERROR: Can't find %s" % filename)) + sys.exit(1) + + def compile_schemas(root, target_data): +--- a/qreator/__init__.py 2019-08-30 15:40:08.983367677 -0400 ++++ b/qreator/__init__.py 2019-08-30 15:40:32.191217413 -0400 +@@ -40,22 +40,18 @@ + plugin_warnings.append("%s: %s." % (name, e)) + + +-def UTF8_(message): +- return _(message).decode('UTF-8') +- +- + def parse_options(qr_types): + """Support for command line options""" + parser = optparse.OptionParser(version="%%prog %s" % get_version()) + parser.add_option( + "-v", "--verbose", action="count", dest="verbose", +- help=UTF8_("Show debug messages (-vv debugs qreator_lib also)")) ++ help="Show debug messages (-vv debugs qreator_lib also)") + + for n, qr in enumerate(qr_types): + parser.add_option( + qr.cmdline_option_short, qr.cmdline_option_long, + dest="view", action="store_const", const=n, +- help=qr.message.decode('UTF-8')) ++ help=qr.message) + + (options, args) = parser.parse_args() + +--- a/qreator_lib/helpers.py 2019-08-30 15:48:23.041626692 -0400 ++++ b/qreator_lib/helpers.py 2019-08-30 15:51:41.125317528 -0400 +@@ -104,7 +104,7 @@ + logger.setLevel(logging.DEBUG) + plugin_logger.setLevel(logging.DEBUG) + logger.debug('logging enabled') +- if opts.verbose > 1: ++ if opts.verbose and opts.verbose > 1: + lib_logger.setLevel(logging.DEBUG) + + def get_help_uri(page=None): diff -Nru qreator-16.06.1/debian/patches/series qreator-16.06.1/debian/patches/series --- qreator-16.06.1/debian/patches/series 2019-03-27 16:45:54.000000000 -0400 +++ qreator-16.06.1/debian/patches/series 2019-08-30 10:37:56.000000000 -0400 @@ -4,3 +4,4 @@ Port-to-libnm.patch Fix-IndexError-when-a-wifi-network-has-100-strength.patch Fix-python-pil-imports.patch +python3-port.patch diff -Nru qreator-16.06.1/debian/rules qreator-16.06.1/debian/rules --- qreator-16.06.1/debian/rules 2018-04-14 08:48:31.000000000 -0400 +++ qreator-16.06.1/debian/rules 2019-08-30 10:37:56.000000000 -0400 @@ -1,9 +1,11 @@ #!/usr/bin/make -f # -*- makefile -*- +export PYBUILD_INSTALL_ARGS_python3=--install-lib=/usr/share/qreator + %: - dh $@ --with=python2 + dh $@ --buildsystem=pybuild --with=python3 override_dh_auto_install: - dh_auto_install -- --install-lib=/usr/share/qreator + dh_auto_install rm -f debian/qreator/usr/share/qreator/qreator/qrcodes/QRCodeSoftwareCenter*
signature.asc
Description: PGP signature