diff --git a/pyproject.toml b/pyproject.toml index 27cec512a3..0606737fc6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ quote-style = 'single' explicit-preview-rules = true ignore = [ 'E402', 'E722', 'E741', - 'UP012', 'UP030', 'UP032', 'UP038', 'C413', 'C420', 'PIE790', 'ISC003', + 'UP012', 'UP030', 'UP038', 'C413', 'C420', 'PIE790', 'ISC003', 'RUF001', 'RUF002', 'RUF003', 'RUF005', 'RUF012', 'RUF013', 'RUF015', 'RUF031', 'RUF100', 'F841', # because in preview, unused tuple unpacking variable that not use dummy syntax (prefix '_' underscore) # raise error 'unused-variable', sigh (https://github.com/astral-sh/ruff/issues/8884) @@ -32,7 +32,7 @@ ignore = [ select = [ 'E', 'F', 'I', 'W', 'INT', 'Q', 'UP', 'YTT', 'TID', 'C4', 'COM818', 'PIE', 'RET501', 'ISC', - 'RUF', # nota: RUF can flag many unsolicited errors + 'RUF', # note: RUF can flag many unsolicited errors # preview rules 'RUF051', 'RUF056', # useless dict operation 'RUF055', # unnecessary regex diff --git a/src/calibre/db/tests/legacy.py b/src/calibre/db/tests/legacy.py index 793faf93f1..f22f1dcc61 100644 --- a/src/calibre/db/tests/legacy.py +++ b/src/calibre/db/tests/legacy.py @@ -32,7 +32,8 @@ class ET: legacy = self.legacy or test.init_legacy(test.cloned_library) oldres = getattr(old, self.func_name)(*self.args, **self.kwargs) newres = getattr(legacy, self.func_name)(*self.args, **self.kwargs) - test.assertEqual(oldres, newres, f'Equivalence test for {self.func_name} with args: {reprlib.repr(self.args)} and kwargs: {reprlib.repr(self.kwargs)} failed') + test.assertEqual(oldres, newres, + f'Equivalence test for {self.func_name} with args: {reprlib.repr(self.args)} and kwargs: {reprlib.repr(self.kwargs)} failed') self.retval = newres return newres diff --git a/src/calibre/db/tests/writing.py b/src/calibre/db/tests/writing.py index fe5b6b58aa..b66339558f 100644 --- a/src/calibre/db/tests/writing.py +++ b/src/calibre/db/tests/writing.py @@ -70,7 +70,7 @@ class WritingTest(BaseTest): test.setter(db)(1, val) old_cached_res = getter(1) self.assertEqual(old_cached_res, cached_res, - f'Failed setting for {test.name} with value {val!r}, cached value not the same. Old: {old_cached_res!r} != New: {cached_res!r}') + f'Failed setting for {test.name} with value {val!r}, cached value not the same. Old: {old_cached_res!r} != New: {cached_res!r}') db.refresh() old_sqlite_res = getter(1) self.assertEqual(old_sqlite_res, sqlite_res, diff --git a/src/calibre/devices/kobo/driver.py b/src/calibre/devices/kobo/driver.py index 50632bb032..6cfda4774b 100644 --- a/src/calibre/devices/kobo/driver.py +++ b/src/calibre/devices/kobo/driver.py @@ -2701,7 +2701,8 @@ class KOBOTOUCH(KOBO): debug_print(f'KoboTouch:update_device_database_collections - book.title={book.title}') debug_print( f'KoboTouch:update_device_database_collections - contentId={book.contentID},' - f'update_core_metadata={update_core_metadata},update_purchased_kepubs={update_purchased_kepubs}, book.is_sideloaded={book.is_sideloaded}') + f'update_core_metadata={update_core_metadata},update_purchased_kepubs={update_purchased_kepubs}, ' + f'book.is_sideloaded={book.is_sideloaded}') if update_core_metadata and (update_purchased_kepubs or book.is_sideloaded): if show_debug: debug_print('KoboTouch:update_device_database_collections - calling set_core_metadata') @@ -2939,7 +2940,8 @@ class KOBOTOUCH(KOBO): if show_debug: debug_print( f'KoboTouch:_calculate_kobo_cover_size - expand_to={expand_to}' - f' (vs. kobo_size={kobo_size}) & resize_to={resize_to}, keep_cover_aspect={keep_cover_aspect} & letterbox_fs_covers={letterbox_fs_covers}, png_covers={png_covers}') + f' (vs. kobo_size={kobo_size}) & resize_to={resize_to}, keep_cover_aspect={keep_cover_aspect} ' + f'& letterbox_fs_covers={letterbox_fs_covers}, png_covers={png_covers}') # NOTE: To speed things up, we enforce a lower # compression level for png_covers, as the final diff --git a/src/calibre/ebooks/conversion/plugins/pdb_input.py b/src/calibre/ebooks/conversion/plugins/pdb_input.py index a20b43db55..99cb13794c 100644 --- a/src/calibre/ebooks/conversion/plugins/pdb_input.py +++ b/src/calibre/ebooks/conversion/plugins/pdb_input.py @@ -24,7 +24,8 @@ class PDBInput(InputFormatPlugin): Reader = get_reader(header.ident) if Reader is None: - raise PDBError('No reader available for format within container.\n Identity is {}. Book type is {}'.format(header.ident, IDENTITY_TO_NAME.get(header.ident, _('Unknown')))) + raise PDBError('No reader available for format within container.\n Identity is {}. Book type is {}'.format( + header.ident, IDENTITY_TO_NAME.get(header.ident, _('Unknown')))) log.debug(f'Detected ebook format as: {IDENTITY_TO_NAME[header.ident]} with identity: {header.ident}') diff --git a/src/calibre/ebooks/htmlz/oeb2html.py b/src/calibre/ebooks/htmlz/oeb2html.py index dd9e9891b8..abb8cf256c 100644 --- a/src/calibre/ebooks/htmlz/oeb2html.py +++ b/src/calibre/ebooks/htmlz/oeb2html.py @@ -55,7 +55,8 @@ class OEB2HTML: def mlize_spine(self, oeb_book): output = [ - f'{prepare_string_for_xml(self.book_title)}' + '' + f'{prepare_string_for_xml(self.book_title)}' ] for item in oeb_book.spine: self.log.debug(f'Converting {item.href} to HTML...') diff --git a/src/calibre/ebooks/lrf/objects.py b/src/calibre/ebooks/lrf/objects.py index 32cde2a77f..f731c0becc 100644 --- a/src/calibre/ebooks/lrf/objects.py +++ b/src/calibre/ebooks/lrf/objects.py @@ -1182,7 +1182,8 @@ class BookAttr(StyleObject, LRFObject): s = f'\n' s += f'\n' doc = self._document - s += f'\n' + s += f'\n' for font in self._document.font_map.values(): s += str(font) s += '\n' diff --git a/src/calibre/ebooks/pml/pmlconverter.py b/src/calibre/ebooks/pml/pmlconverter.py index d72a6ef72d..6fea58bb78 100644 --- a/src/calibre/ebooks/pml/pmlconverter.py +++ b/src/calibre/ebooks/pml/pmlconverter.py @@ -157,8 +157,10 @@ class PML_HTMLizer: def prepare_pml(self, pml): # Give Chapters the form \\*='text'text\\*. This is used for generating # the TOC later. - pml = re.sub(r'(?msu)(?P\\x)(?P.*?)(?P=c)', lambda match: '{}="{}"{}{}'.format(match.group('c'), self.strip_pml(match.group('text')), match.group('text'), match.group('c')), pml) - pml = re.sub(r'(?msu)(?P\\X[0-4])(?P.*?)(?P=c)', lambda match: '{}="{}"{}{}'.format(match.group('c'), self.strip_pml(match.group('text')), match.group('text'), match.group('c')), pml) + pml = re.sub(r'(?msu)(?P\\x)(?P.*?)(?P=c)', lambda match: '{}="{}"{}{}'.format( + match.group('c'), self.strip_pml(match.group('text')), match.group('text'), match.group('c')), pml) + pml = re.sub(r'(?msu)(?P\\X[0-4])(?P.*?)(?P=c)', lambda match: '{}="{}"{}{}'.format( + match.group('c'), self.strip_pml(match.group('text')), match.group('text'), match.group('c')), pml) # Remove comments pml = re.sub(r'(?mus)\\v(?P.*?)\\v', '', pml) @@ -170,8 +172,10 @@ class PML_HTMLizer: pml = re.sub(r'(?mus)^[ ]*$', '', pml) # Footnotes and Sidebars. - pml = re.sub(r'(?mus).+?)">\s*(?P.*?)\s*', lambda match: '\\FN="{}"{}\\FN'.format(match.group('target'), match.group('text')) if match.group('text') else '', pml) - pml = re.sub(r'(?mus).+?)">\s*(?P.*?)\s*', lambda match: '\\SB="{}"{}\\SB'.format(match.group('target'), match.group('text')) if match.group('text') else '', pml) + pml = re.sub(r'(?mus).+?)">\s*(?P.*?)\s*', lambda match: '\\FN="{}"{}\\FN'.format( + match.group('target'), match.group('text')) if match.group('text') else '', pml) + pml = re.sub(r'(?mus).+?)">\s*(?P.*?)\s*', lambda match: '\\SB="{}"{}\\SB'.format( + match.group('target'), match.group('text')) if match.group('text') else '', pml) # Convert &'s into entities so & in the text doesn't get turned into # &. It will display as & @@ -751,7 +755,9 @@ def pml_to_html(pml): def footnote_sidebar_to_html(pre_id, id, pml): id = id.strip('\x01') if id.strip(): - html = f'

{pml_to_html(pml)}return
' + html = ( + f'

{pml_to_html(pml)}' + f'return
') else: html = f'

{pml_to_html(pml)}
' return html diff --git a/src/calibre/ebooks/rtf/rtfml.py b/src/calibre/ebooks/rtf/rtfml.py index 3bc069758e..0aed5b31bc 100644 --- a/src/calibre/ebooks/rtf/rtfml.py +++ b/src/calibre/ebooks/rtf/rtfml.py @@ -150,7 +150,7 @@ class RTFMLizer: return text def header(self): - header = f'{{\\rtf1{{\\info{{\\title {self.oeb_book.metadata.title[0].value}}}{{\\author {authors_to_string([x.value for x in self.oeb_book.metadata.creator])}}}}}\\ansi\\ansicpg1252\\deff0\\deflang1033\n' + header = f'{{\\rtf1{{\\info{{\\title {self.oeb_book.metadata.title[0].value}}}{{\\author {authors_to_string([x.value for x in self.oeb_book.metadata.creator])}}}}}\\ansi\\ansicpg1252\\deff0\\deflang1033\n' # noqa: E501 return header + ( '{\\fonttbl{\\f0\\froman\\fprq2\\fcharset128 Times New Roman;}{\\f1\\froman\\fprq2\\fcharset128 Times New Roman;}{\\f2\\fswiss\\fprq2\\fcharset128 Arial;}{\\f3\\fnil\\fprq2\\fcharset128 Arial;}{\\f4\\fnil\\fprq2\\fcharset128 MS Mincho;}{\\f5\\fnil\\fprq2\\fcharset128 Tahoma;}{\\f6\\fnil\\fprq0\\fcharset128 Tahoma;}}\n' # noqa: E501 '{\\stylesheet{\\ql \\li0\\ri0\\nowidctlpar\\wrapdefault\\faauto\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\af25\\afs24\\alang1033 \\ltrch\\fcs0 \\fs24\\lang1033\\langfe255\\cgrid\\langnp1033\\langfenp255 \\snext0 Normal;}\n' # noqa: E501 diff --git a/src/calibre/gui2/dialogs/message_box.py b/src/calibre/gui2/dialogs/message_box.py index 0073dcb5fe..7dd810e59b 100644 --- a/src/calibre/gui2/dialogs/message_box.py +++ b/src/calibre/gui2/dialogs/message_box.py @@ -446,7 +446,8 @@ class JobError(QDialog): # {{{ d = QTextDocument() d.setHtml(self.msg_label.text()) QApplication.clipboard().setText( - f'calibre, version {__version__} ({sys.platform}, embedded-python: {isfrozen})\n{self.windowTitle()!s}: {d.toPlainText()!s}\n\n{self.det_msg.toPlainText()!s}') + f'calibre, version {__version__} ({sys.platform}, embedded-python: {isfrozen})\n' + f'{self.windowTitle()!s}: {d.toPlainText()!s}\n\n{self.det_msg.toPlainText()!s}') if hasattr(self, 'ctc_button'): self.ctc_button.setText(_('Copied')) diff --git a/src/calibre/gui2/tweak_book/editor/smarts/html.py b/src/calibre/gui2/tweak_book/editor/smarts/html.py index ad60d65c1c..da6a8bd741 100644 --- a/src/calibre/gui2/tweak_book/editor/smarts/html.py +++ b/src/calibre/gui2/tweak_book/editor/smarts/html.py @@ -50,7 +50,9 @@ class Tag: self.self_closing = self_closing def __repr__(self): - return f'<{self.name} start_block={self.start_block.blockNumber()} start_offset={self.start_offset} end_block={self.end_block.blockNumber()} end_offset={self.end_offset} self_closing={self.self_closing}>' + return ( + f'<{self.name} start_block={self.start_block.blockNumber()} start_offset={self.start_offset} ' + f'end_block={self.end_block.blockNumber()} end_offset={self.end_offset} self_closing={self.self_closing}>') __str__ = __repr__ diff --git a/src/calibre/gui2/tweak_book/editor/snippets.py b/src/calibre/gui2/tweak_book/editor/snippets.py index 69ff49d758..0ccc39dca8 100644 --- a/src/calibre/gui2/tweak_book/editor/snippets.py +++ b/src/calibre/gui2/tweak_book/editor/snippets.py @@ -234,7 +234,9 @@ class EditorTabStop: self.join_previous_edit = False def __repr__(self): - return f'EditorTabStop(num={self.num!r} text={self.text!r} left={self.left!r} right={self.right!r} is_deleted={self.is_deleted!r} mirrors={self.mirrors!r})' + return ( + f'EditorTabStop(num={self.num!r} text={self.text!r} left={self.left!r} right={self.right!r} ' + f'is_deleted={self.is_deleted!r} mirrors={self.mirrors!r})') __str__ = __unicode__ = __repr__ def apply_selected_text(self, text): diff --git a/src/calibre/gui2/tweak_book/live_css.py b/src/calibre/gui2/tweak_book/live_css.py index 273e08b55c..dc255e77ec 100644 --- a/src/calibre/gui2/tweak_book/live_css.py +++ b/src/calibre/gui2/tweak_book/live_css.py @@ -394,7 +394,9 @@ class Property: self.is_overriden = False def __repr__(self): - return f'' + return ( + f'') class LiveCSS(QWidget): diff --git a/src/calibre/gui2/tweak_book/preview.py b/src/calibre/gui2/tweak_book/preview.py index 1f76bacbbf..b8687b4a9d 100644 --- a/src/calibre/gui2/tweak_book/preview.py +++ b/src/calibre/gui2/tweak_book/preview.py @@ -87,7 +87,9 @@ class ParseItem: self.parsing_done = False def __repr__(self): - return f'ParsedItem(name={self.name!r}, length={self.length!r}, fingerprint={self.fingerprint!r}, parsing_done={self.parsing_done!r}, parsed_data_is_None={self.parsed_data is None!r})' + return ( + f'ParsedItem(name={self.name!r}, length={self.length!r}, fingerprint={self.fingerprint!r}, ' + f'parsing_done={self.parsing_done!r}, parsed_data_is_None={self.parsed_data is None!r})') class ParseWorker(Thread): diff --git a/src/calibre/gui2/tweak_book/save.py b/src/calibre/gui2/tweak_book/save.py index d69bd0ea5e..469459983f 100644 --- a/src/calibre/gui2/tweak_book/save.py +++ b/src/calibre/gui2/tweak_book/save.py @@ -56,7 +56,8 @@ def save_container(container, path): except OSError as err: if err.errno != errno.EPERM: raise - raise OSError(f'Failed to change permissions of {temp.name} to {oct(st.st_mode)} ({format_permissions(st.st_mode)}), with error: {errno.errorcode[err.errno]}. Most likely the {os.path.dirname(temp.name)} directory has a restrictive umask') + raise OSError(f'Failed to change permissions of {temp.name} to {oct(st.st_mode)} ({format_permissions(st.st_mode)}), ' + f'with error: {errno.errorcode[err.errno]}. Most likely the {os.path.dirname(temp.name)} directory has a restrictive umask') try: os.fchown(fno, st.st_uid, st.st_gid) except OSError as err: diff --git a/src/calibre/srv/content.py b/src/calibre/srv/content.py index 9ec25c1782..20f5cb3b0d 100644 --- a/src/calibre/srv/content.py +++ b/src/calibre/srv/content.py @@ -222,7 +222,8 @@ def book_fmt(ctx, rd, library_id, db, book_id, fmt): dest.seek(0) cd = rd.query.get('content_disposition', 'attachment') - rd.outheaders['Content-Disposition'] = f'''{cd}; filename="{book_filename(rd, book_id, mi, fmt)}"; filename*=utf-8''{book_filename(rd, book_id, mi, fmt, as_encoded_unicode=True)}''' + rd.outheaders['Content-Disposition'] = ( + f'''{cd}; filename="{book_filename(rd, book_id, mi, fmt)}"; filename*=utf-8''{book_filename(rd, book_id, mi, fmt, as_encoded_unicode=True)}''') return create_file_copy(ctx, rd, 'fmt', library_id, book_id, fmt, mtime, copy_func, extra_etag_data=extra_etag_data) # }}} @@ -465,7 +466,8 @@ def get_note_resource(ctx, rd, scheme, digest, library_id): raise HTTPNotFound(f'Notes resource {scheme}:{digest} not found') name = d['name'] rd.outheaders['Content-Type'] = guess_type(name)[0] or 'application/octet-stream' - rd.outheaders['Content-Disposition'] = f'''inline; filename="{fname_for_content_disposition(name)}"; filename*=utf-8''{fname_for_content_disposition(name, as_encoded_unicode=True)}''' + rd.outheaders['Content-Disposition'] = ( + f'''inline; filename="{fname_for_content_disposition(name)}"; filename*=utf-8''{fname_for_content_disposition(name, as_encoded_unicode=True)}''') rd.outheaders['Last-Modified'] = http_date(d['mtime']) return d['data'] @@ -522,7 +524,8 @@ def set_note(ctx, rd, field, item_id, library_id): def data_file(rd, fname, path, stat_result): cd = rd.query.get('content_disposition', 'attachment') - rd.outheaders['Content-Disposition'] = f'''{cd}; filename="{fname_for_content_disposition(fname)}"; filename*=utf-8''{fname_for_content_disposition(fname, as_encoded_unicode=True)}''' + rd.outheaders['Content-Disposition'] = ( + f'''{cd}; filename="{fname_for_content_disposition(fname)}"; filename*=utf-8''{fname_for_content_disposition(fname, as_encoded_unicode=True)}''') return rd.filesystem_file_with_custom_etag(share_open(path, 'rb'), stat_result.st_dev, stat_result.st_ino, stat_result.st_size, stat_result.st_mtime) diff --git a/src/calibre/utils/webengine.py b/src/calibre/utils/webengine.py index a20d5c2cd8..e790012060 100644 --- a/src/calibre/utils/webengine.py +++ b/src/calibre/utils/webengine.py @@ -111,7 +111,9 @@ class to_js_bound(QObject): self.name = name def __call__(self, *args): - self.parent().page.runJavaScript(f'if (window.python_comm) python_comm._from_python({json.dumps(self.name)}, {json.dumps(args)})', QWebEngineScript.ScriptWorldId.ApplicationWorld) + self.parent().page.runJavaScript( + f'if (window.python_comm) python_comm._from_python({json.dumps(self.name)}, {json.dumps(args)})', + QWebEngineScript.ScriptWorldId.ApplicationWorld) emit = __call__ diff --git a/src/calibre/web/feeds/__init__.py b/src/calibre/web/feeds/__init__.py index 34d970ea4e..89f9863357 100644 --- a/src/calibre/web/feeds/__init__.py +++ b/src/calibre/web/feeds/__init__.py @@ -232,7 +232,9 @@ class Feed: self.articles.append(article) else: try: - self.logger.debug('Skipping article {} ({}) from feed {} as it is too old.'.format(title, article.localtime.strftime('%a, %d %b, %Y %H:%M'), self.title)) + self.logger.debug( + 'Skipping article {} ({}) from feed {} as it is too old.'.format( + title, article.localtime.strftime('%a, %d %b, %Y %H:%M'), self.title)) except UnicodeDecodeError: if not isinstance(title, str): title = title.decode('utf-8', 'replace')