diff --git a/.pylintrc b/.pylintrc index 701e3e4..ba5a914 100644 --- a/.pylintrc +++ b/.pylintrc @@ -65,11 +65,7 @@ disable=print-statement, unpacking-in-except, old-raise-syntax, backtick, - long-suffix, - old-ne-operator, - old-octal-literal, import-star-module-level, - non-ascii-bytes-literal, raw-checker-failed, bad-inline-option, locally-disabled, @@ -117,7 +113,6 @@ disable=print-statement, range-builtin-not-iterating, filter-builtin-not-iterating, using-cmp-argument, - eq-without-hash, div-method, idiv-method, rdiv-method, @@ -138,7 +133,15 @@ disable=print-statement, xreadlines-attribute, deprecated-sys-function, exception-escape, - comprehension-escape + comprehension-escape, + import-error, + no-name-in-module, + attribute-defined-outside-init, + missing-class-docstring, + missing-function-docstring, + unnecessary-lambda, + broad-except, + bare-except, # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option @@ -422,7 +425,9 @@ good-names=i, k, ex, Run, - _ + _, + db, + f # Good variable names regexes, separated by a comma. If names match any regex, # they will always be accepted diff --git a/action.py b/action.py index 211e921..9540330 100644 --- a/action.py +++ b/action.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +"""KOReader Sync Plugin for Calibre.""" + from datetime import datetime from functools import partial import io @@ -7,32 +9,33 @@ import os import re import sys -from calibre.utils.iso8601 import utc_tz, local_tz -from PyQt5.Qt import QUrl # pylint: disable=no-name-in-module -from calibre_plugins.koreader.slpp import slpp as lua # pylint: disable=import-error +from PyQt5.Qt import QUrl +from calibre_plugins.koreader.slpp import slpp as lua from calibre_plugins.koreader.config import ( SUPPORTED_DEVICES, UNSUPPORTED_DEVICES, COLUMNS, - CONFIG, # pylint: disable=import-error + CONFIG, ) from calibre_plugins.koreader import ( DEBUG, DRY_RUN, PYDEVD, - KoreaderSync, # pylint: disable=import-error + KoreaderSync, ) -from calibre.gui2.dialogs.message_box import MessageBox # pylint: disable=no-name-in-module, disable=import-error -from calibre.gui2.actions import InterfaceAction # pylint: disable=no-name-in-module, disable=import-error + +from calibre.utils.iso8601 import utc_tz, local_tz +from calibre.gui2.dialogs.message_box import MessageBox +from calibre.gui2.actions import InterfaceAction from calibre.gui2 import ( error_dialog, warning_dialog, info_dialog, - open_url, # pylint: disable=no-name-in-module, disable=import-error + open_url, ) -from calibre.devices.usbms.driver import debug_print as root_debug_print # pylint: disable=no-name-in-module, disable=import-error -from calibre.constants import numeric_version # pylint: disable=no-name-in-module, disable=import-error +from calibre.devices.usbms.driver import debug_print as root_debug_print +from calibre.constants import numeric_version __license__ = 'GNU GPLv3' __copyright__ = '2021, harmtemolder ' @@ -49,7 +52,7 @@ # '/Applications/PyCharm.app/Contents/debug-eggs/pydevd-pycharm.egg' # macOS '/opt/pycharm-professional/debug-eggs/pydevd-pycharm.egg' # Manjaro Linux ) - import pydevd_pycharm # pylint: disable=import-error + import pydevd_pycharm pydevd_pycharm.settrace( 'localhost', stdoutToServer=True, stderrToServer=True, @@ -79,12 +82,12 @@ def genesis(self): debug_print('start') base = self.interface_action_base_plugin - self.version = '{} (v{}.{}.{})'.format(base.name, *base.version) + self.version = f'{base.name} (v{".".join(map(str, base.version))})' # Overwrite icon with actual KOReader logo - icon = get_icons( + icon = get_icons( # pylint: disable=undefined-variable 'images/icon.png' - ) # pylint: disable=undefined-variable + ) self.qaction.setIcon(icon) # Left-click action @@ -148,16 +151,16 @@ def show_readme(self): def show_about(self): debug_print = partial(module_debug_print, 'KoreaderAction:show_about:') debug_print('start') - text = get_resources('about.txt').decode( + text = get_resources('about.txt').decode( # pylint: disable=undefined-variable 'utf-8' - ) # pylint: disable=undefined-variable - icon = get_icons( + ) + icon = get_icons( # pylint: disable=undefined-variable 'images/icon.png' - ) # pylint: disable=undefined-variable + ) about_dialog = MessageBox( MessageBox.INFO, - 'About {}'.format(self.version), + f'About {self.version}', text, det_msg='', q_icon=icon, @@ -173,7 +176,6 @@ def apply_settings(self): 'KoreaderAction:apply_settings:' ) debug_print('start') - pass def get_connected_device(self): """Tries to get the connected device, if any @@ -244,15 +246,13 @@ def get_paths(self, device): paths = { book.uuid: re.sub( - '\.(\w+)$', '.sdr/metadata.\\1.lua', book.path + r'\.(\w+)$', r'.sdr/metadata.\1.lua', book.path ) for book in device.books() } debug_print( - 'generated {} path(s) to sidecar Lua files:\n\t'.format( - len(paths) - ), + f'generated {len(paths)} path(s) to sidecar Lua files:\n\t', '\n\t'.join(paths.values()) ) @@ -286,7 +286,7 @@ def get_sidecar(self, device, path): debug_print('could not decode ', contents) return None - debug_print('parsing {}'.format(path)) + debug_print(f'parsing {path}') parsed_contents = self.parse_sidecar_lua(decoded_contents) parsed_contents['calculated']['date_sidecar_modified'] = datetime.fromtimestamp( os.path.getmtime(path)).replace(tzinfo=local_tz @@ -350,7 +350,7 @@ def update_metadata(self, uuid, keys_values_to_update): book_id = None if not book_id: - debug_print('could not find {} in calibre’s library'.format(uuid)) + debug_print(f'could not find {uuid} in calibre’s library') return False, {'result': 'could not find uuid in calibre’s library'} # Get the current metadata for the book from the library @@ -414,10 +414,8 @@ def check_device(self, device): error_dialog( self.gui, 'Device not supported', - 'Devices of the type {} are not supported by this plugin. I ' - 'have tried to get it working, but couldn’t. Sorry.'.format( - device_class - ), + f'Devices of the type {device_class} are not supported by this plugin. I ' + f'have tried to get it working, but couldn’t. Sorry.', det_msg='', show=True, show_copy_button=False @@ -433,11 +431,10 @@ def check_device(self, device): warning_dialog( self.gui, 'Device not yet supported', - 'Devices of the type {} are not yet supported by this plugin. ' - 'Please check if there already is a feature request for this ' - 'here. If not, feel free to create ' - 'one. I\'ll try to sync anyway.'.format(device_class), + f'Devices of the type {device_class} are not yet supported by this plugin. ' + f'Please check if there already is a feature request for this ' + f'' + f'here. If not, feel free to create one. I\'ll try to sync anyway.', det_msg='', show=True, show_copy_button=False @@ -465,7 +462,7 @@ def push_metadata_to_koreader_sidecar(self, book_uuid, path): book_id = None if not book_id: - debug_print('could not find {} in calibre’s library'.format(book_uuid)) + debug_print(f'could not find {book_uuid} in calibre’s library') return "failure", { 'result': f"Could not find uuid {book_uuid} in Calibre's library." } @@ -491,10 +488,10 @@ def push_metadata_to_koreader_sidecar(self, book_uuid, path): # dir exists, so we're fine pass - with open(path, "w") as f: + with open(path, "w", encoding="utf-8") as f: debug_print(f"Writing to {path}") f.write(sidecar_lua_formatted) - + return "success", { 'result': 'success', 'book_id': book_id, @@ -550,7 +547,7 @@ def sync_missing_sidecars_to_koreader(self): num_fail = 0 for book_uuid, path in sidecar_paths_not_exist.items(): result, details = self.push_metadata_to_koreader_sidecar(book_uuid, path) - if result is "success": + if result is "success": num_success += 1 results.append( { @@ -559,7 +556,7 @@ def sync_missing_sidecars_to_koreader(self): 'sidecar_path': path, } ) - elif result is "failure": + elif result is "failure": num_fail += 1 results.append( { @@ -662,18 +659,14 @@ def sync_to_calibre(self): # No column mapped, so do not sync continue - property = column['sidecar_property'] + sidecar_property = column['sidecar_property'] value = sidecar_contents - for subproperty in property: + for subproperty in sidecar_property: if subproperty in value: value = value[subproperty] else: - debug_print( - 'subproperty "{}" not found in value'.format( - subproperty - ) - ) + debug_print(f'subproperty "{subproperty}" not found in value') value = None break diff --git a/config.py b/config.py index 95c163d..e9071cb 100644 --- a/config.py +++ b/config.py @@ -1,11 +1,13 @@ #!/usr/bin/env python3 +"""Config for KOReader Sync plugin for Calibre.""" + import math import os import json from functools import partial -from PyQt5.Qt import ( # pylint: disable=no-name-in-module +from PyQt5.Qt import ( QComboBox, QGridLayout, QHBoxLayout, @@ -15,11 +17,11 @@ Qt, ) -from PyQt5.QtGui import QPixmap # pylint: disable=no-name-in-module -from calibre.constants import numeric_version # pylint: disable=no-name-in-module, disable=import-error -from calibre.devices.usbms.driver import debug_print as root_debug_print # pylint: disable=no-name-in-module, disable=import-error -from calibre.utils.config import JSONConfig # pylint: disable=no-name-in-module, disable=import-error -from calibre_plugins.koreader import clean_bookmarks # pylint: disable=import-error +from PyQt5.QtGui import QPixmap +from calibre.constants import numeric_version +from calibre.devices.usbms.driver import debug_print as root_debug_print +from calibre.utils.config import JSONConfig +from calibre_plugins.koreader import clean_bookmarks __license__ = 'GNU GPLv3' __copyright__ = '2021, harmtemolder ' @@ -152,8 +154,8 @@ }] CONFIG = JSONConfig(os.path.join('plugins', 'KOReader Sync.json')) -for column in COLUMNS: - CONFIG.defaults[column['name']] = '' +for this_column in COLUMNS: + CONFIG.defaults[this_column['name']] = '' if numeric_version >= (5, 5, 0): module_debug_print = partial(root_debug_print, ' koreader:config:', sep='') @@ -174,7 +176,10 @@ def __init__(self, plugin_action): # Add icon and title title_layout = TitleLayout( - self, 'images/icon.png', 'Configure {}'.format(self.action.version)) + self, + 'images/icon.png', + f'Configure {self.action.version}', + ) layout.addLayout(title_layout) # Add custom column dropdowns @@ -210,7 +215,7 @@ def __init__(self, parent, icon, title): self.addWidget(icon_label) # Add title - title_label = QLabel('

{}

'.format(title), parent) + title_label = QLabel(f'

{title}

', parent) self.addWidget(title_label) # Add empty space @@ -288,8 +293,10 @@ def get_rating_columns(self): class CustomColumnComboBox(QComboBox): - def __init__(self, parent, custom_columns={}, selected_column=''): + def __init__(self, parent, custom_columns=None, selected_column=''): QComboBox.__init__(self, parent) + if custom_columns is None: + custom_columns = {} self.populate_combo(custom_columns, selected_column) def populate_combo(self, custom_columns, selected_column): @@ -300,7 +307,7 @@ def populate_combo(self, custom_columns, selected_column): for key in sorted(custom_columns.keys()): self.column_names.append(key) - display_name = '{} ({})'.format(custom_columns[key]['name'], key) + display_name = f'{custom_columns[key]["name"]} ({key})' self.addItem(display_name) if key == selected_column: selected_idx = len(self.column_names) - 1