diff options
author | Apprentice Harper <[email protected]> | 2020-09-27 11:54:49 +0100 |
---|---|---|
committer | Apprentice Harper <[email protected]> | 2020-09-27 11:54:49 +0100 |
commit | de50a02af92ef2bdd142dfb0bfb8e288ebf3bb67 (patch) | |
tree | d6544ffc055553a997020166694142f53a913e08 /Obok_plugin | |
parent | 6920f79a263516a566646f3075a3c94e99cf3c37 (diff) |
More generic 3.0 changes, to be tested.
Diffstat (limited to 'Obok_plugin')
-rw-r--r-- | Obok_plugin/action.py | 6 | ||||
-rw-r--r-- | Obok_plugin/common_utils.py | 13 | ||||
-rw-r--r-- | Obok_plugin/config.py | 52 | ||||
-rw-r--r-- | Obok_plugin/obok/obok.py | 94 | ||||
-rw-r--r-- | Obok_plugin/utilities.py | 9 |
5 files changed, 79 insertions, 95 deletions
diff --git a/Obok_plugin/action.py b/Obok_plugin/action.py index 802a833..e94204f 100644 --- a/Obok_plugin/action.py +++ b/Obok_plugin/action.py @@ -1,8 +1,8 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -from __future__ import (unicode_literals, division, absolute_import, - print_function) -__license__ = 'GPL v3' +_license__ = 'GPL v3' __docformat__ = 'restructuredtext en' diff --git a/Obok_plugin/common_utils.py b/Obok_plugin/common_utils.py index babad1c..21b7f19 100644 --- a/Obok_plugin/common_utils.py +++ b/Obok_plugin/common_utils.py @@ -1,7 +1,6 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -from __future__ import (unicode_literals, division, absolute_import, - print_function) __license__ = 'GPL v3' __copyright__ = '2012, David Forrester <[email protected]>' @@ -9,13 +8,7 @@ __docformat__ = 'restructuredtext en' import os, time, re, sys from datetime import datetime -try: - from PyQt5.Qt import (Qt, QIcon, QPixmap, QLabel, QDialog, QHBoxLayout, QProgressBar, - QTableWidgetItem, QFont, QLineEdit, QComboBox, - QVBoxLayout, QDialogButtonBox, QStyledItemDelegate, QDateTime, - QRegExpValidator, QRegExp, QDate, QDateEdit) -except ImportError: - from PyQt4.Qt import (Qt, QIcon, QPixmap, QLabel, QDialog, QHBoxLayout, QProgressBar, +from PyQt5.Qt import (Qt, QIcon, QPixmap, QLabel, QDialog, QHBoxLayout, QProgressBar, QTableWidgetItem, QFont, QLineEdit, QComboBox, QVBoxLayout, QDialogButtonBox, QStyledItemDelegate, QDateTime, QRegExpValidator, QRegExp, QDate, QDateEdit) diff --git a/Obok_plugin/config.py b/Obok_plugin/config.py index 522b86a..2830dad 100644 --- a/Obok_plugin/config.py +++ b/Obok_plugin/config.py @@ -1,16 +1,10 @@ -# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -from __future__ import (unicode_literals, division, absolute_import, - print_function) +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- -try: - from PyQt5.Qt import (Qt, QGroupBox, QListWidget, QLineEdit, QDialogButtonBox, QWidget, QLabel, QDialog, QVBoxLayout, QAbstractItemView, QIcon, QHBoxLayout, QComboBox, QListWidgetItem, QFileDialog) -except ImportError: - from PyQt4.Qt import (Qt, QGroupBox, QListWidget, QLineEdit, QDialogButtonBox, QWidget, QLabel, QDialog, QVBoxLayout, QAbstractItemView, QIcon, QHBoxLayout, QComboBox, QListWidgetItem, QFileDialog) +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -try: - from PyQt5 import Qt as QtGui -except ImportError: - from PyQt4 import QtGui +from PyQt5.Qt import (Qt, QGroupBox, QListWidget, QLineEdit, QDialogButtonBox, QWidget, QLabel, QDialog, QVBoxLayout, QAbstractItemView, QIcon, QHBoxLayout, QComboBox, QListWidgetItem, QFileDialog) +from PyQt5 import Qt as QtGui from calibre.gui2 import (error_dialog, question_dialog, info_dialog, open_url) from calibre.utils.config import JSONConfig, config_dir @@ -50,25 +44,25 @@ class ConfigWidget(QWidget): self.find_homes.setCurrentIndex(index) self.serials_button = QtGui.QPushButton(self) - self.serials_button.setToolTip(_(u"Click to manage Kobo serial numbers for Kobo ebooks")) - self.serials_button.setText(u"Kobo devices serials") + self.serials_button.setToolTip(_("Click to manage Kobo serial numbers for Kobo ebooks")) + self.serials_button.setText("Kobo devices serials") self.serials_button.clicked.connect(self.edit_serials) layout.addWidget(self.serials_button) self.kobo_directory_button = QtGui.QPushButton(self) - self.kobo_directory_button.setToolTip(_(u"Click to specify the Kobo directory")) - self.kobo_directory_button.setText(u"Kobo directory") + self.kobo_directory_button.setToolTip(_("Click to specify the Kobo directory")) + self.kobo_directory_button.setText("Kobo directory") self.kobo_directory_button.clicked.connect(self.edit_kobo_directory) layout.addWidget(self.kobo_directory_button) def edit_serials(self): - d = ManageKeysDialog(self,u"Kobo device serial number",self.tmpserials, AddSerialDialog) + d = ManageKeysDialog(self,"Kobo device serial number",self.tmpserials, AddSerialDialog) d.exec_() def edit_kobo_directory(self): - tmpkobodirectory = QFileDialog.getExistingDirectory(self, u"Select Kobo directory", self.kobodirectory or "/home", QFileDialog.ShowDirsOnly) + tmpkobodirectory = QFileDialog.getExistingDirectory(self, "Select Kobo directory", self.kobodirectory or "/home", QFileDialog.ShowDirsOnly) if tmpkobodirectory != u"" and tmpkobodirectory is not None: self.kobodirectory = tmpkobodirectory @@ -91,7 +85,7 @@ class ManageKeysDialog(QDialog): self.plugin_keys = plugin_keys self.create_key = create_key self.keyfile_ext = keyfile_ext - self.json_file = (keyfile_ext == u"k4i") + self.json_file = (keyfile_ext == "k4i") self.setWindowTitle("{0} {1}: Manage {2}s".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name)) @@ -99,13 +93,13 @@ class ManageKeysDialog(QDialog): layout = QVBoxLayout(self) self.setLayout(layout) - keys_group_box = QGroupBox(_(u"{0}s".format(self.key_type_name)), self) + keys_group_box = QGroupBox(_("{0}s".format(self.key_type_name)), self) layout.addWidget(keys_group_box) keys_group_box_layout = QHBoxLayout() keys_group_box.setLayout(keys_group_box_layout) self.listy = QListWidget(self) - self.listy.setToolTip(u"{0}s that will be used to decrypt ebooks".format(self.key_type_name)) + self.listy.setToolTip("{0}s that will be used to decrypt ebooks".format(self.key_type_name)) self.listy.setSelectionMode(QAbstractItemView.SingleSelection) self.populate_list() keys_group_box_layout.addWidget(self.listy) @@ -114,12 +108,12 @@ class ManageKeysDialog(QDialog): keys_group_box_layout.addLayout(button_layout) self._add_key_button = QtGui.QToolButton(self) self._add_key_button.setIcon(QIcon(I('plus.png'))) - self._add_key_button.setToolTip(u"Create new {0}".format(self.key_type_name)) + self._add_key_button.setToolTip("Create new {0}".format(self.key_type_name)) self._add_key_button.clicked.connect(self.add_key) button_layout.addWidget(self._add_key_button) self._delete_key_button = QtGui.QToolButton(self) - self._delete_key_button.setToolTip(_(u"Delete highlighted key")) + self._delete_key_button.setToolTip(_("Delete highlighted key")) self._delete_key_button.setIcon(QIcon(I('list_remove.png'))) self._delete_key_button.clicked.connect(self.delete_key) button_layout.addWidget(self._delete_key_button) @@ -155,7 +149,7 @@ class ManageKeysDialog(QDialog): new_key_value = d.key_value if new_key_value in self.plugin_keys: info_dialog(None, "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION,self.key_type_name), - u"This {0} is already in the list of {0}s has not been added.".format(self.key_type_name), show=True) + "This {0} is already in the list of {0}s has not been added.".format(self.key_type_name), show=True) return self.plugin_keys.append(d.key_value) @@ -166,7 +160,7 @@ class ManageKeysDialog(QDialog): if not self.listy.currentItem(): return keyname = self.listy.currentItem().text() - if not question_dialog(self, "{0} {1}: Confirm Delete".format(PLUGIN_NAME, PLUGIN_VERSION), u"Do you really want to delete the {1} <strong>{0}</strong>?".format(keyname, self.key_type_name), show_copy_button=False, default_yes=False): + if not question_dialog(self, "{0} {1}: Confirm Delete".format(PLUGIN_NAME, PLUGIN_VERSION), "Do you really want to delete the {1} <strong>{0}</strong>?".format(keyname, self.key_type_name), show_copy_button=False, default_yes=False): return self.plugin_keys.remove(keyname) @@ -177,7 +171,7 @@ class AddSerialDialog(QDialog): def __init__(self, parent=None,): QDialog.__init__(self, parent) self.parent = parent - self.setWindowTitle(u"{0} {1}: Add New eInk Kobo Serial Number".format(PLUGIN_NAME, PLUGIN_VERSION)) + self.setWindowTitle("{0} {1}: Add New eInk Kobo Serial Number".format(PLUGIN_NAME, PLUGIN_VERSION)) layout = QVBoxLayout(self) self.setLayout(layout) @@ -188,9 +182,9 @@ class AddSerialDialog(QDialog): key_group = QHBoxLayout() data_group_box_layout.addLayout(key_group) - key_group.addWidget(QLabel(u"EInk Kobo Serial Number:", self)) + key_group.addWidget(QLabel("EInk Kobo Serial Number:", self)) self.key_ledit = QLineEdit("", self) - self.key_ledit.setToolTip(u"Enter an eInk Kobo serial number. EInk Kobo serial numbers are 13 characters long and usually start with a 'N'. Kobo Serial Numbers are case-sensitive, so be sure to enter the upper and lower case letters unchanged.") + self.key_ledit.setToolTip("Enter an eInk Kobo serial number. EInk Kobo serial numbers are 13 characters long and usually start with a 'N'. Kobo Serial Numbers are case-sensitive, so be sure to enter the upper and lower case letters unchanged.") key_group.addWidget(self.key_ledit) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) @@ -210,9 +204,9 @@ class AddSerialDialog(QDialog): def accept(self): if len(self.key_name) == 0 or self.key_name.isspace(): - errmsg = u"Please enter an eInk Kindle Serial Number or click Cancel in the dialog." + errmsg = "Please enter an eInk Kindle Serial Number or click Cancel in the dialog." return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) if len(self.key_name) != 13: - errmsg = u"EInk Kobo Serial Numbers must be 13 characters long. This is {0:d} characters long.".format(len(self.key_name)) + errmsg = "EInk Kobo Serial Numbers must be 13 characters long. This is {0:d} characters long.".format(len(self.key_name)) return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) QDialog.accept(self) diff --git a/Obok_plugin/obok/obok.py b/Obok_plugin/obok/obok.py index 80bc058..d20f6dc 100644 --- a/Obok_plugin/obok/obok.py +++ b/Obok_plugin/obok/obok.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Version 4.0.0 September 2020 @@ -156,7 +156,7 @@ from __future__ import print_function __version__ = '4.0.0' -__about__ = u"Obok v{0}\nCopyright © 2012-2020 Physisticated et al.".format(__version__) +__about__ = "Obok v{0}\nCopyright © 2012-2020 Physisticated et al.".format(__version__) import sys import os @@ -176,10 +176,10 @@ import tempfile can_parse_xml = True try: from xml.etree import ElementTree as ET - # print u"using xml.etree for xml parsing" + # print "using xml.etree for xml parsing" except ImportError: can_parse_xml = False - # print u"Cannot find xml.etree, disabling extraction of serial numbers" + # print "Cannot find xml.etree, disabling extraction of serial numbers" # List of all known hash keys KOBO_HASH_KEYS = ['88b3a2e13', 'XzUhGYdFp', 'NoCanLook','QJhwzAtXL'] @@ -279,10 +279,10 @@ class SafeUnbuffered: if self.encoding == None: self.encoding = "utf-8" def write(self, data): - if isinstance(data,bytes): + if isinstance(data,str): data = data.encode(self.encoding,"replace") - self.stream.write(data) - self.stream.flush() + self.stream.buffer.write(data) + self.stream.buffer.flush() def __getattr__(self, attr): return getattr(self.stream, attr) @@ -312,9 +312,9 @@ class KoboLibrary(object): # step 1. check whether this looks like a real device if (device_path): # we got a device path - self.kobodir = os.path.join(device_path, u".kobo") + self.kobodir = os.path.join(device_path, ".kobo") # devices use KoboReader.sqlite - kobodb = os.path.join(self.kobodir, u"KoboReader.sqlite") + kobodb = os.path.join(self.kobodir, "KoboReader.sqlite") if (not(os.path.isfile(kobodb))): # device path seems to be wrong, unset it device_path = u"" @@ -326,22 +326,22 @@ class KoboLibrary(object): if (len(serials) == 0): # we got a device path but no saved serial # try to get the serial from the device - # print u"get_device_settings - device_path = {0}".format(device_path) + # print "get_device_settings - device_path = {0}".format(device_path) # get serial from device_path/.adobe-digital-editions/device.xml if can_parse_xml: devicexml = os.path.join(device_path, '.adobe-digital-editions', 'device.xml') - # print u"trying to load {0}".format(devicexml) + # print "trying to load {0}".format(devicexml) if (os.path.exists(devicexml)): - # print u"trying to parse {0}".format(devicexml) + # print "trying to parse {0}".format(devicexml) xmltree = ET.parse(devicexml) for node in xmltree.iter(): if "deviceSerial" in node.tag: serial = node.text - # print u"found serial {0}".format(serial) + # print "found serial {0}".format(serial) serials.append(serial) break else: - # print u"cannot get serials from device." + # print "cannot get serials from device." device_path = u"" self.kobodir = u"" kobodb = u"" @@ -357,19 +357,19 @@ class KoboLibrary(object): if sys.getwindowsversion().major > 5: if 'LOCALAPPDATA' in os.environ.keys(): # Python 2.x does not return unicode env. Use Python 3.x - self.kobodir = winreg.ExpandEnvironmentStrings(u"%LOCALAPPDATA%") + self.kobodir = winreg.ExpandEnvironmentStrings("%LOCALAPPDATA%") if (self.kobodir == u""): if 'USERPROFILE' in os.environ.keys(): # Python 2.x does not return unicode env. Use Python 3.x - self.kobodir = os.path.join(winreg.ExpandEnvironmentStrings(u"%USERPROFILE%"), u"Local Settings", u"Application Data") - self.kobodir = os.path.join(self.kobodir, u"Kobo", u"Kobo Desktop Edition") + self.kobodir = os.path.join(winreg.ExpandEnvironmentStrings("%USERPROFILE%"), "Local Settings", "Application Data") + self.kobodir = os.path.join(self.kobodir, "Kobo", "Kobo Desktop Edition") elif sys.platform.startswith('darwin'): - self.kobodir = os.path.join(os.environ['HOME'], u"Library", u"Application Support", u"Kobo", u"Kobo Desktop Edition") + self.kobodir = os.path.join(os.environ['HOME'], "Library", "Application Support", "Kobo", "Kobo Desktop Edition") #elif linux_path != None: # Probably Linux, let's get the wine prefix and path to Kobo. - # self.kobodir = os.path.join(linux_path, u"Local Settings", u"Application Data", u"Kobo", u"Kobo Desktop Edition") + # self.kobodir = os.path.join(linux_path, "Local Settings", "Application Data", "Kobo", "Kobo Desktop Edition") # desktop versions use Kobo.sqlite - kobodb = os.path.join(self.kobodir, u"Kobo.sqlite") + kobodb = os.path.join(self.kobodir, "Kobo.sqlite") # check for existence of file if (not(os.path.isfile(kobodb))): # give up here, we haven't found anything useful @@ -377,7 +377,7 @@ class KoboLibrary(object): kobodb = u"" if (self.kobodir != u""): - self.bookdir = os.path.join(self.kobodir, u"kepub") + self.bookdir = os.path.join(self.kobodir, "kepub") # make a copy of the database in a temporary file # so we can ensure it's not using WAL logging which sqlite3 can't do. self.newdb = tempfile.NamedTemporaryFile(mode='wb', delete=False) @@ -437,7 +437,7 @@ class KoboLibrary(object): def __bookfile (self, volumeid): """The filename needed to open a given book.""" - return os.path.join(self.kobodir, u"kepub", volumeid) + return os.path.join(self.kobodir, "kepub", volumeid) def __getmacaddrs (self): """The list of all MAC addresses on this machine.""" @@ -454,7 +454,7 @@ class KoboLibrary(object): output = subprocess.check_output('/sbin/ifconfig -a', shell=True) matches = c.findall(output) for m in matches: - # print u"m:{0}".format(m[0]) + # print "m:{0}".format(m[0]) macaddrs.append(m[0].upper()) else: # probably linux @@ -607,32 +607,32 @@ class KoboFile(object): # assume utf-8 with no BOM textoffset = 0 stride = 1 - print(u"Checking text:{0}:".format(contents[:10])) + print("Checking text:{0}:".format(contents[:10])) # check for byte order mark if contents[:3]==b"\xef\xbb\xbf": # seems to be utf-8 with BOM - print(u"Could be utf-8 with BOM") + print("Could be utf-8 with BOM") textoffset = 3 elif contents[:2]==b"\xfe\xff": # seems to be utf-16BE - print(u"Could be utf-16BE") + print("Could be utf-16BE") textoffset = 3 stride = 2 elif contents[:2]==b"\xff\xfe": # seems to be utf-16LE - print(u"Could be utf-16LE") + print("Could be utf-16LE") textoffset = 2 stride = 2 else: - print(u"Perhaps utf-8 without BOM") + print("Perhaps utf-8 without BOM") # now check that the first few characters are in the ASCII range for i in range(textoffset,textoffset+5*stride,stride): if contents[i]<32 or contents[i]>127: # Non-ascii, so decryption probably failed - print(u"Bad character at {0}, value {1}".format(i,contents[i])) + print("Bad character at {0}, value {1}".format(i,contents[i])) raise ValueError - print(u"Seems to be good text") + print("Seems to be good text") return True if contents[:5]==b"<?xml" or contents[:8]==b"\xef\xbb\xbf<?xml": # utf-8 @@ -653,13 +653,13 @@ class KoboFile(object): # utf-16LE of weird <!DOCTYPE start return True else: - print(u"Bad XML: {0}".format(contents[:8])) + print("Bad XML: {0}".format(contents[:8])) raise ValueError elif self.mimetype == 'image/jpeg': if contents[:3] == b'\xff\xd8\xff': return True else: - print(u"Bad JPEG: {0}".format(contents[:3].hex())) + print("Bad JPEG: {0}".format(contents[:3].hex())) raise ValueError() return False @@ -682,18 +682,18 @@ class KoboFile(object): return contents def decrypt_book(book, lib): - print(u"Converting {0}".format(book.title)) + print("Converting {0}".format(book.title)) zin = zipfile.ZipFile(book.filename, "r") # make filename out of Unicode alphanumeric and whitespace equivalents from title - outname = u"{0}.epub".format(re.sub('[^\s\w]', '_', book.title, 0, re.UNICODE)) + outname = "{0}.epub".format(re.sub('[^\s\w]', '_', book.title, 0, re.UNICODE)) if (book.type == 'drm-free'): - print(u"DRM-free book, conversion is not needed") + print("DRM-free book, conversion is not needed") shutil.copyfile(book.filename, outname) - print(u"Book saved as {0}".format(os.path.join(os.getcwd(), outname))) + print("Book saved as {0}".format(os.path.join(os.getcwd(), outname))) return 0 result = 1 for userkey in lib.userkeys: - print(u"Trying key: {0}".format(userkey.hex())) + print("Trying key: {0}".format(userkey.hex())) try: zout = zipfile.ZipFile(outname, "w", zipfile.ZIP_DEFLATED) for filename in zin.namelist(): @@ -705,12 +705,12 @@ def decrypt_book(book, lib): file.check(contents) zout.writestr(filename, contents) zout.close() - print(u"Decryption succeeded.") - print(u"Book saved as {0}".format(os.path.join(os.getcwd(), outname))) + print("Decryption succeeded.") + print("Book saved as {0}".format(os.path.join(os.getcwd(), outname))) result = 0 break except ValueError: - print(u"Decryption failed.") + print("Decryption failed.") zout.close() os.remove(outname) zin.close() @@ -719,7 +719,7 @@ def decrypt_book(book, lib): def cli_main(): description = __about__ - epilog = u"Parsing of arguments failed." + epilog = "Parsing of arguments failed." parser = argparse.ArgumentParser(prog=sys.argv[0], description=description, epilog=epilog) parser.add_argument('--devicedir', default='/media/KOBOeReader', help="directory of connected Kobo device") parser.add_argument('--all', action='store_true', help="flag for converting all books on device") @@ -735,25 +735,25 @@ def cli_main(): books = lib.books else: for i, book in enumerate(lib.books): - print(u"{0}: {1}".format(i + 1, book.title)) - print(u"Or 'all'") + print("{0}: {1}".format(i + 1, book.title)) + print("Or 'all'") - choice = input(u"Convert book number... ") - if choice == u'all': + choice = input("Convert book number... ") + if choice == "all": books = list(lib.books) else: try: num = int(choice) books = [lib.books[num - 1]] except (ValueError, IndexError): - print(u"Invalid choice. Exiting...") + print("Invalid choice. Exiting...") exit() results = [decrypt_book(book, lib) for book in books] lib.close() overall_result = all(result != 0 for result in results) if overall_result != 0: - print(u"Could not decrypt book with any of the keys found.") + print("Could not decrypt book with any of the keys found.") return overall_result diff --git a/Obok_plugin/utilities.py b/Obok_plugin/utilities.py index f81bd1c..b2f02ad 100644 --- a/Obok_plugin/utilities.py +++ b/Obok_plugin/utilities.py @@ -1,6 +1,6 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -from __future__ import (unicode_literals, division, absolute_import, - print_function) __license__ = 'GPL v3' __docformat__ = 'restructuredtext en' @@ -13,10 +13,7 @@ except ImportError: from io import StringIO from traceback import print_exc -try: - from PyQt5.Qt import (Qt, QDialog, QPixmap, QIcon, QLabel, QHBoxLayout, QFont, QTableWidgetItem) -except ImportError: - from PyQt4.Qt import (Qt, QDialog, QPixmap, QIcon, QLabel, QHBoxLayout, QFont, QTableWidgetItem) +from PyQt5.Qt import (Qt, QDialog, QPixmap, QIcon, QLabel, QHBoxLayout, QFont, QTableWidgetItem) from calibre.utils.config import config_dir from calibre.constants import iswindows, DEBUG |