diff --git a/src/calibre/db/backend.py b/src/calibre/db/backend.py
index 29b789b5f9..9001d2a050 100644
--- a/src/calibre/db/backend.py
+++ b/src/calibre/db/backend.py
@@ -1432,7 +1432,7 @@ class DB:
@user_version.setter
def user_version(self, val):
- self.execute('PRAGMA user_version=%d'%int(val))
+ self.execute(f'PRAGMA user_version={int(val)}')
def initialize_database(self):
metadata_sqlite = P('metadata_sqlite.sql', data=True,
diff --git a/src/calibre/db/cli/cmd_restore_database.py b/src/calibre/db/cli/cmd_restore_database.py
index 88169e711e..ab4e75d11d 100644
--- a/src/calibre/db/cli/cmd_restore_database.py
+++ b/src/calibre/db/cli/cmd_restore_database.py
@@ -54,7 +54,7 @@ class Progress:
if msg is None:
self.total = float(step)
else:
- prints(msg, '...', '%d%%' % int(100 * (step / self.total)))
+ prints(msg, '...', f'{int(100*(step/self.total))}%')
def main(opts, args, dbctx):
diff --git a/src/calibre/ebooks/metadata/__init__.py b/src/calibre/ebooks/metadata/__init__.py
index 19606d0fea..55d46a44c2 100644
--- a/src/calibre/ebooks/metadata/__init__.py
+++ b/src/calibre/ebooks/metadata/__init__.py
@@ -251,7 +251,7 @@ def fmt_sidx(i, fmt='%.2f', use_roman=False):
except Exception:
return str(i)
if int(i) == i:
- return roman(int(i)) if use_roman else '%d'%int(i)
+ return roman(int(i)) if use_roman else str(int(i))
ans = fmt%i
if '.' in ans:
ans = ans.rstrip('0')
diff --git a/src/calibre/ebooks/mobi/mobiml.py b/src/calibre/ebooks/mobi/mobiml.py
index e60d7dc59e..75a0962969 100644
--- a/src/calibre/ebooks/mobi/mobiml.py
+++ b/src/calibre/ebooks/mobi/mobiml.py
@@ -160,8 +160,8 @@ class MobiMLizer:
return ptsize
embase = self.profile.fbase
if round(ptsize) < embase:
- return '%dpt' % int(round(ptsize))
- return '%dem' % int(round(ptsize / embase))
+ return f'{int(round(ptsize))}pt'
+ return f'{int(round(ptsize/embase))}em'
def preize_text(self, text, pre_wrap=False):
text = str(text)
@@ -503,7 +503,7 @@ class MobiMLizer:
istate.attrib['width'] = raww
else:
prop = style['width'] / self.profile.width
- istate.attrib['width'] = '%d%%' % int(round(prop * 100))
+ istate.attrib['width'] = f'{int(round(prop*100))}%'
elif display == 'table':
tag = 'table'
elif display == 'table-row':
diff --git a/src/calibre/ebooks/mobi/reader/mobi6.py b/src/calibre/ebooks/mobi/reader/mobi6.py
index 5554c6d58a..085fc2f42f 100644
--- a/src/calibre/ebooks/mobi/reader/mobi6.py
+++ b/src/calibre/ebooks/mobi/reader/mobi6.py
@@ -533,7 +533,7 @@ class MobiReader:
try:
nval = float(val[:-2])
nval *= 16 * (168.451/72) # Assume this was set using the Kindle profile
- attrib[attr] = '%dpx'%int(nval)
+ attrib[attr] = f'{int(nval)}px'
except:
del attrib[attr]
elif val.lower().endswith('%'):
@@ -558,7 +558,7 @@ class MobiReader:
if 'filepos' in attrib:
filepos = attrib.pop('filepos')
try:
- attrib['href'] = '#filepos%d' % int(filepos)
+ attrib['href'] = f'#filepos{int(filepos)}'
except ValueError:
pass
if (tag.tag == 'a' and attrib.get('id', '').startswith('filepos') and
diff --git a/src/calibre/ebooks/pdf/reflow.py b/src/calibre/ebooks/pdf/reflow.py
index ff82cffa22..de2b1a2d40 100644
--- a/src/calibre/ebooks/pdf/reflow.py
+++ b/src/calibre/ebooks/pdf/reflow.py
@@ -151,8 +151,7 @@ class Image(Element):
self.align = 'L'
def to_html(self):
- return '
' % \
- (self.src, int(self.width), int(self.height))
+ return f'
'
def dump(self, f):
f.write(self.to_html())
diff --git a/src/calibre/gui2/dialogs/custom_recipes.py b/src/calibre/gui2/dialogs/custom_recipes.py
index 49c8356d5b..43a004c301 100644
--- a/src/calibre/gui2/dialogs/custom_recipes.py
+++ b/src/calibre/gui2/dialogs/custom_recipes.py
@@ -154,7 +154,7 @@ def py3_repr(x):
def options_to_recipe_source(title, oldest_article, max_articles_per_feed, feeds):
- classname = 'BasicUserRecipe%d' % int(time.time())
+ classname = f'BasicUserRecipe{int(time.time())}'
title = str(title).strip() or classname
indent = ' ' * 8
if feeds:
diff --git a/src/calibre/gui2/linux_file_dialogs.py b/src/calibre/gui2/linux_file_dialogs.py
index 126b550db2..42b8d36092 100644
--- a/src/calibre/gui2/linux_file_dialogs.py
+++ b/src/calibre/gui2/linux_file_dialogs.py
@@ -233,7 +233,7 @@ def zenity_cmd(window, title, *rest):
ans = ['zenity', '--modal', '--file-selection', '--title=' + title, '--separator=\n']
winid = get_winid(window)
if winid is not None:
- ans += ['--attach=%d' % int(winid)]
+ ans += [f'--attach={int(winid)}']
return ans + list(rest)
diff --git a/src/calibre/library/catalogs/epub_mobi_builder.py b/src/calibre/library/catalogs/epub_mobi_builder.py
index 7a00b1b0e5..948ea35bb2 100644
--- a/src/calibre/library/catalogs/epub_mobi_builder.py
+++ b/src/calibre/library/catalogs/epub_mobi_builder.py
@@ -1555,7 +1555,7 @@ class CatalogBuilder:
aTag = soup.new_tag('a')
if self.opts.generate_descriptions:
- aTag['href'] = 'book_%d.html' % (int(float(book['id'])))
+ aTag['href'] = 'book_{}.html'.format(int(float(book['id'])))
# Generate the title from the template
args = self.generate_format_args(book)
@@ -1706,7 +1706,7 @@ class CatalogBuilder:
aTag = soup.new_tag('a')
if self.opts.generate_descriptions:
- aTag['href'] = 'book_%d.html' % (int(float(new_entry['id'])))
+ aTag['href'] = 'book_{}.html'.format(int(float(new_entry['id'])))
# Generate the title from the template
args = self.generate_format_args(new_entry)
@@ -1758,7 +1758,7 @@ class CatalogBuilder:
aTag = soup.new_tag('a')
if self.opts.generate_descriptions:
- aTag['href'] = 'book_%d.html' % (int(float(new_entry['id'])))
+ aTag['href'] = 'book_{}.html'.format(int(float(new_entry['id'])))
# Generate the title from the template
args = self.generate_format_args(new_entry)
@@ -1923,7 +1923,7 @@ class CatalogBuilder:
aTag = soup.new_tag('a')
if self.opts.generate_descriptions:
- aTag['href'] = 'book_%d.html' % (int(float(new_entry['id'])))
+ aTag['href'] = 'book_{}.html'.format(int(float(new_entry['id'])))
aTag.insert(0, NavigableString(new_entry['title']))
pBookTag.insert(ptc, aTag)
ptc += 1
@@ -1972,7 +1972,7 @@ class CatalogBuilder:
aTag = soup.new_tag('a')
if self.opts.generate_descriptions:
- aTag['href'] = 'book_%d.html' % (int(float(new_entry['id'])))
+ aTag['href'] = 'book_{}.html'.format(int(float(new_entry['id'])))
aTag.insert(0, NavigableString(new_entry['title']))
pBookTag.insert(ptc, aTag)
ptc += 1
@@ -2274,7 +2274,7 @@ class CatalogBuilder:
# Add the book title
aTag = soup.new_tag('a')
if self.opts.generate_descriptions:
- aTag['href'] = 'book_%d.html' % (int(float(book['id'])))
+ aTag['href'] = 'book_{}.html'.format(int(float(book['id'])))
# Generate the title from the template
args = self.generate_format_args(book)
@@ -2406,7 +2406,7 @@ class CatalogBuilder:
aTag = soup.new_tag('a')
if self.opts.generate_descriptions:
- aTag['href'] = 'book_%d.html' % (int(float(book['id'])))
+ aTag['href'] = 'book_{}.html'.format(int(float(book['id'])))
# Use series, series index if avail else just title
# aTag.insert(0,'%d. %s · %s' % (book['series_index'],escape(book['title']), ' & '.join(book['authors'])))
@@ -2566,7 +2566,7 @@ class CatalogBuilder:
# Link to book
aTag = soup.new_tag('a')
if self.opts.generate_descriptions:
- aTag['href'] = 'book_%d.html' % (int(float(book['id'])))
+ aTag['href'] = 'book_{}.html'.format(int(float(book['id'])))
# Generate the title from the template
args = self.generate_format_args(book)
@@ -2728,7 +2728,7 @@ class CatalogBuilder:
_soup = BeautifulSoup('', selfClosingTags=['img'])
thumb = _soup.new_tag('img')
if book.get('cover'):
- thumb['src'] = '../images/thumbnail_%d.jpg' % int(book['id'])
+ thumb['src'] = '../images/thumbnail_{}.jpg'.format(int(book['id']))
else:
thumb['src'] = '../images/thumbnail_default.jpg'
thumb['alt'] = 'cover thumbnail'
@@ -2766,7 +2766,7 @@ class CatalogBuilder:
btc = 0
# Insert the title anchor for inbound links
aTag = soup.new_tag('a')
- aTag['id'] = 'book%d' % int(book['id'])
+ aTag['id'] = 'book{}'.format(int(book['id']))
divTag = soup.new_tag('div')
divTag.insert(0, aTag)
body.insert(btc, divTag)
@@ -2839,7 +2839,7 @@ class CatalogBuilder:
soup = self.generate_html_description_header(title)
# Write the book entry to content_dir
- with open('%s/book_%d.html' % (self.content_dir, int(title['id'])), 'wb') as outfile:
+ with open('{}/book_{}.html'.format(self.content_dir, int(title['id'])), 'wb') as outfile:
outfile.write(prettify(soup).encode('utf-8'))
def generate_html_empty_header(self, title):
@@ -2990,7 +2990,7 @@ class CatalogBuilder:
makeelement('content', navPointTag, src='content/ByDateAdded.html')
elif self.opts.generate_descriptions:
# Descriptions only
- makeelement('content', navPointTag, src='content/book_%d.html' % int(self.books_by_description[0]['id']))
+ makeelement('content', navPointTag, src='content/book_{}.html'.format(int(self.books_by_description[0]['id'])))
def generate_ncx_section_header(self, section_id, section_header, content_src):
root = self.ncx_root
@@ -3038,7 +3038,8 @@ class CatalogBuilder:
section_header = f'{tocTitle} [{len(self.books_by_description)}]'
if self.generate_for_kindle_mobi:
section_header = tocTitle
- navPointTag = self.generate_ncx_section_header('bydescription-ID', section_header, 'content/book_%d.html' % int(self.books_by_description[0]['id']))
+ navPointTag = self.generate_ncx_section_header(
+ 'bydescription-ID', section_header, 'content/book_{}.html'.format(int(self.books_by_description[0]['id'])))
self.update_progress_full_step(_('NCX for descriptions'))
@@ -3047,7 +3048,7 @@ class CatalogBuilder:
# Loop over the titles
for book in self.books_by_description:
- sec_id = 'book%dID' % int(book['id'])
+ sec_id = 'book{}ID'.format(int(book['id']))
if book['series']:
series_index = str(book['series_index'])
if series_index.endswith('.0'):
@@ -3073,7 +3074,7 @@ class CatalogBuilder:
# Include Author for non-Kindle
sec_text = self.format_ncx_text('{} · {}'.format(book['title'], book['author']), dest='title')
- content_src='content/book_%d.html#book%d' % (int(book['id']), int(book['id']))
+ content_src='content/book_{}.html#book{}'.format(int(book['id']), int(book['id']))
cm_tags = {}
if book['date']:
@@ -3677,7 +3678,7 @@ class CatalogBuilder:
for book in self.books_by_description:
# manifest
- manifest_item('book%d' % int(book['id']), 'content/book_%d.html' % int(book['id']), 'application/xhtml+xml', add_to_spine=True)
+ manifest_item('book{}'.format(int(book['id'])), 'content/book_{}.html'.format(int(book['id'])), 'application/xhtml+xml', add_to_spine=True)
# Guide
if self.generate_for_kindle_mobi:
@@ -3922,12 +3923,12 @@ class CatalogBuilder:
(_('Thumbnail'), i, len(self.books_by_title)),
i / float(len(self.books_by_title)))
- thumb_file = 'thumbnail_%d.jpg' % int(title['id'])
+ thumb_file = 'thumbnail_{}.jpg'.format(int(title['id']))
thumb_generated = True
valid_cover = True
try:
self.generate_thumbnail(title, image_dir, thumb_file)
- thumbs.append('thumbnail_%d.jpg' % int(title['id']))
+ thumbs.append('thumbnail_{}.jpg'.format(int(title['id'])))
except:
if 'cover' in title and os.path.exists(title['cover']):
valid_cover = False
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index 37b4c3521d..497de92981 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -90,7 +90,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
@user_version.setter
def user_version(self, val):
- self.conn.execute('pragma user_version=%d'%int(val))
+ self.conn.execute(f'pragma user_version={int(val)}')
self.conn.commit()
@property
diff --git a/src/calibre/srv/http_response.py b/src/calibre/srv/http_response.py
index 0e2a97e1b5..8d5d672d08 100644
--- a/src/calibre/srv/http_response.py
+++ b/src/calibre/srv/http_response.py
@@ -506,7 +506,7 @@ class HTTPConnection(HTTPRequest):
outheaders.set('Server', f'calibre {__version__}', replace_all=True)
keep_alive = not self.close_after_response and self.opts.timeout > 0
if keep_alive:
- outheaders.set('Keep-Alive', 'timeout=%d' % int(self.opts.timeout))
+ outheaders.set('Keep-Alive', f'timeout={int(self.opts.timeout)}')
if 'Connection' not in outheaders:
if self.response_protocol is HTTP11:
if self.close_after_response:
diff --git a/src/calibre/web/feeds/recipes/collection.py b/src/calibre/web/feeds/recipes/collection.py
index 1a4921d5ac..b47eea443a 100644
--- a/src/calibre/web/feeds/recipes/collection.py
+++ b/src/calibre/web/feeds/recipes/collection.py
@@ -574,7 +574,7 @@ class SchedulerConfig:
if urn.startswith('recipe_'):
urn = 'builtin:'+urn[7:]
else:
- urn = 'custom:%d'%int(urn)
+ urn = f'custom:{int(urn)}'
try:
username, password = c[k]
except:
@@ -596,14 +596,14 @@ class SchedulerConfig:
urn = 'builtin:'+r['id'][7:]
elif not r['builtin']:
try:
- urn = 'custom:%d'%int(r['id'])
+ urn = 'custom:{}'.format(int(r['id']))
except:
return
schedule = r['schedule']
typ = 'interval'
if schedule > 1e5:
typ = 'day/time'
- raw = '%d'%int(schedule)
+ raw = str(int(schedule))
day = int(raw[0]) - 1
hour = int(raw[2:4]) - 1
minute = int(raw[-2:]) - 1
diff --git a/src/calibre/web/feeds/templates.py b/src/calibre/web/feeds/templates.py
index 15a9730435..7e484b5f88 100644
--- a/src/calibre/web/feeds/templates.py
+++ b/src/calibre/web/feeds/templates.py
@@ -313,7 +313,7 @@ class TouchscreenFeedTemplate(Template):
if f > 0:
link = A(attrs('feed_link'),
trim_title(feeds[f-1].title),
- href='../feed_%d/index.html' % int(f-1))
+ href=f'../feed_{int(f-1)}/index.html')
navbar_tr.append(TD(attrs('feed_prev'),link))
# Up to Sections
@@ -325,7 +325,7 @@ class TouchscreenFeedTemplate(Template):
if f < len(feeds)-1:
link = A(attrs('feed_link'),
trim_title(feeds[f+1].title),
- href='../feed_%d/index.html' % int(f+1))
+ href=f'../feed_{int(f+1)}/index.html')
navbar_tr.append(TD(attrs('feed_next'),link))
navbar_t.append(navbar_tr)
top_navbar = navbar_t