Replace percent formatting

This commit is contained in:
Šarūnas Nejus 2025-07-08 08:17:09 +01:00
parent 4a361bd501
commit 9352a79e41
No known key found for this signature in database
GPG key ID: DD28F6704DBE3435
25 changed files with 70 additions and 93 deletions

View file

@ -78,9 +78,9 @@ def string_dist(str1: str | None, str2: str | None) -> float:
# example, "the something" should be considered equal to # example, "the something" should be considered equal to
# "something, the". # "something, the".
for word in SD_END_WORDS: for word in SD_END_WORDS:
if str1.endswith(", %s" % word): if str1.endswith(f", {word}"):
str1 = f"{word} {str1[: -len(word) - 2]}" str1 = f"{word} {str1[: -len(word) - 2]}"
if str2.endswith(", %s" % word): if str2.endswith(f", {word}"):
str2 = f"{word} {str2[: -len(word) - 2]}" str2 = f"{word} {str2[: -len(word) - 2]}"
# Perform a couple of basic normalizing substitutions. # Perform a couple of basic normalizing substitutions.
@ -444,7 +444,7 @@ def distance(
# Preferred media options. # Preferred media options.
media_patterns: Sequence[str] = preferred_config["media"].as_str_seq() media_patterns: Sequence[str] = preferred_config["media"].as_str_seq()
options = [ options = [
re.compile(r"(\d+x)?(%s)" % pat, re.I) for pat in media_patterns re.compile(rf"(\d+x)?({pat})", re.I) for pat in media_patterns
] ]
if options: if options:
dist.add_priority("media", album_info.media, options) dist.add_priority("media", album_info.media, options)

View file

@ -1158,7 +1158,7 @@ class Database:
""" """
# Get current schema. # Get current schema.
with self.transaction() as tx: with self.transaction() as tx:
rows = tx.query("PRAGMA table_info(%s)" % table) rows = tx.query(f"PRAGMA table_info({table})")
current_fields = {row[1] for row in rows} current_fields = {row[1] for row in rows}
field_names = set(fields.keys()) field_names = set(fields.keys())

View file

@ -482,7 +482,7 @@ class Album(LibModel):
""" """
item = self.items().get() item = self.items().get()
if not item: if not item:
raise ValueError("empty album for album id %d" % self.id) raise ValueError(f"empty album for album id {self.id}")
return os.path.dirname(item.path) return os.path.dirname(item.path)
def _albumtotal(self): def _albumtotal(self):

View file

@ -831,8 +831,8 @@ class AutotagStub:
def _make_track_match(self, artist, album, number): def _make_track_match(self, artist, album, number):
return TrackInfo( return TrackInfo(
title="Applied Track %d" % number, title=f"Applied Track {number}",
track_id="match %d" % number, track_id=f"match {number}",
artist=artist, artist=artist,
length=1, length=1,
index=0, index=0,

View file

@ -269,7 +269,7 @@ def input_options(
) )
): ):
# The first option is the default; mark it. # The first option is the default; mark it.
show_letter = "[%s]" % found_letter.upper() show_letter = f"[{found_letter.upper()}]"
is_default = True is_default = True
else: else:
show_letter = found_letter.upper() show_letter = found_letter.upper()
@ -308,9 +308,9 @@ def input_options(
if isinstance(default, int): if isinstance(default, int):
default_name = str(default) default_name = str(default)
default_name = colorize("action_default", default_name) default_name = colorize("action_default", default_name)
tmpl = "# selection (default %s)" tmpl = "# selection (default {})"
prompt_parts.append(tmpl % default_name) prompt_parts.append(tmpl.format(default_name))
prompt_part_lengths.append(len(tmpl % str(default))) prompt_part_lengths.append(len(tmpl) - 2 + len(str(default)))
else: else:
prompt_parts.append("# selection") prompt_parts.append("# selection")
prompt_part_lengths.append(len(prompt_parts[-1])) prompt_part_lengths.append(len(prompt_parts[-1]))
@ -349,7 +349,7 @@ def input_options(
if not fallback_prompt: if not fallback_prompt:
fallback_prompt = "Enter one of " fallback_prompt = "Enter one of "
if numrange: if numrange:
fallback_prompt += "%i-%i, " % numrange fallback_prompt += "{}-{}, ".format(*numrange)
fallback_prompt += ", ".join(display_letters) + ":" fallback_prompt += ", ".join(display_letters) + ":"
resp = input_(prompt) resp = input_(prompt)
@ -406,7 +406,7 @@ def input_select_objects(prompt, objs, rep, prompt_all=None):
objects individually. objects individually.
""" """
choice = input_options( choice = input_options(
("y", "n", "s"), False, "%s? (Yes/no/select)" % (prompt_all or prompt) ("y", "n", "s"), False, f"{prompt_all or prompt}? (Yes/no/select)"
) )
print() # Blank line. print() # Blank line.
@ -420,7 +420,7 @@ def input_select_objects(prompt, objs, rep, prompt_all=None):
answer = input_options( answer = input_options(
("y", "n", "q"), ("y", "n", "q"),
True, True,
"%s? (yes/no/quit)" % prompt, f"{prompt}? (yes/no/quit)",
"Enter Y or N:", "Enter Y or N:",
) )
if answer == "y": if answer == "y":
@ -534,7 +534,7 @@ def _colorize(color, text):
# over all "ANSI codes" in `color`. # over all "ANSI codes" in `color`.
escape = "" escape = ""
for code in color: for code in color:
escape = escape + COLOR_ESCAPE + "%im" % ANSI_CODES[code] escape = escape + COLOR_ESCAPE + f"{ANSI_CODES[code]}m"
return escape + text + RESET_COLOR return escape + text + RESET_COLOR
@ -1475,7 +1475,7 @@ class SubcommandsOptionParser(CommonOptionsParser):
for subcommand in subcommands: for subcommand in subcommands:
name = subcommand.name name = subcommand.name
if subcommand.aliases: if subcommand.aliases:
name += " (%s)" % ", ".join(subcommand.aliases) name += f" ({', '.join(subcommand.aliases)})"
disp_names.append(name) disp_names.append(name)
# Set the help position based on the max width. # Set the help position based on the max width.
@ -1488,26 +1488,18 @@ class SubcommandsOptionParser(CommonOptionsParser):
# Lifted directly from optparse.py. # Lifted directly from optparse.py.
name_width = help_position - formatter.current_indent - 2 name_width = help_position - formatter.current_indent - 2
if len(name) > name_width: if len(name) > name_width:
name = "%*s%s\n" % (formatter.current_indent, "", name) name = f"{' ' * formatter.current_indent}{name}\n"
indent_first = help_position indent_first = help_position
else: else:
name = "%*s%-*s " % ( name = f"{' ' * formatter.current_indent}{name:<{name_width}}\n"
formatter.current_indent,
"",
name_width,
name,
)
indent_first = 0 indent_first = 0
result.append(name) result.append(name)
help_width = formatter.width - help_position help_width = formatter.width - help_position
help_lines = textwrap.wrap(subcommand.help, help_width) help_lines = textwrap.wrap(subcommand.help, help_width)
help_line = help_lines[0] if help_lines else "" help_line = help_lines[0] if help_lines else ""
result.append("%*s%s\n" % (indent_first, "", help_line)) result.append(f"{' ' * indent_first}{help_line}\n")
result.extend( result.extend(
[ [f"{' ' * help_position}{line}\n" for line in help_lines[1:]]
"%*s%s\n" % (help_position, "", line)
for line in help_lines[1:]
]
) )
formatter.dedent() formatter.dedent()

View file

@ -144,13 +144,13 @@ def fields_func(lib, opts, args):
with lib.transaction() as tx: with lib.transaction() as tx:
# The SQL uses the DISTINCT to get unique values from the query # The SQL uses the DISTINCT to get unique values from the query
unique_fields = "SELECT DISTINCT key FROM (%s)" unique_fields = "SELECT DISTINCT key FROM ({})"
print_("Item flexible attributes:") print_("Item flexible attributes:")
_print_keys(tx.query(unique_fields % library.Item._flex_table)) _print_keys(tx.query(unique_fields.format(library.Item._flex_table)))
print_("Album flexible attributes:") print_("Album flexible attributes:")
_print_keys(tx.query(unique_fields % library.Album._flex_table)) _print_keys(tx.query(unique_fields.format(library.Album._flex_table)))
fields_cmd = ui.Subcommand( fields_cmd = ui.Subcommand(
@ -1926,7 +1926,7 @@ default_commands.append(stats_cmd)
def show_version(lib, opts, args): def show_version(lib, opts, args):
print_("beets version %s" % beets.__version__) print_(f"beets version {beets.__version__}")
print_(f"Python version {python_version()}") print_(f"Python version {python_version()}")
# Show plugins. # Show plugins.
names = sorted(p.name for p in plugins.find_plugins()) names = sorted(p.name for p in plugins.find_plugins())
@ -1990,7 +1990,7 @@ def modify_items(lib, mods, dels, query, write, move, album, confirm, inherit):
extra = "" extra = ""
changed = ui.input_select_objects( changed = ui.input_select_objects(
"Really modify%s" % extra, f"Really modify{extra}",
changed, changed,
lambda o: print_and_modify(o, mods, dels), lambda o: print_and_modify(o, mods, dels),
) )
@ -2168,7 +2168,7 @@ def move_items(
else: else:
if confirm: if confirm:
objs = ui.input_select_objects( objs = ui.input_select_objects(
"Really %s" % act, f"Really {act}",
objs, objs,
lambda o: show_path_changes( lambda o: show_path_changes(
[(o.path, o.destination(basedir=dest))] [(o.path, o.destination(basedir=dest))]
@ -2461,22 +2461,18 @@ def completion_script(commands):
yield "_beet() {\n" yield "_beet() {\n"
# Command names # Command names
yield " local commands='%s'\n" % " ".join(command_names) yield f" local commands={' '.join(command_names)!r}\n"
yield "\n" yield "\n"
# Command aliases # Command aliases
yield " local aliases='%s'\n" % " ".join(aliases.keys()) yield f" local aliases={' '.join(aliases.keys())!r}\n"
for alias, cmd in aliases.items(): for alias, cmd in aliases.items():
yield f" local alias__{alias.replace('-', '_')}={cmd}\n" yield f" local alias__{alias.replace('-', '_')}={cmd}\n"
yield "\n" yield "\n"
# Fields # Fields
yield " fields='%s'\n" % " ".join( fields = library.Item._fields.keys() | library.Album._fields.keys()
set( yield f" fields={' '.join(fields)!r}\n"
list(library.Item._fields.keys())
+ list(library.Album._fields.keys())
)
)
# Command options # Command options
for cmd, opts in options.items(): for cmd, opts in options.items():

View file

@ -559,7 +559,7 @@ def spawn(coro):
and child coroutines run concurrently. and child coroutines run concurrently.
""" """
if not isinstance(coro, types.GeneratorType): if not isinstance(coro, types.GeneratorType):
raise ValueError("%s is not a coroutine" % coro) raise ValueError(f"{coro} is not a coroutine")
return SpawnEvent(coro) return SpawnEvent(coro)
@ -569,7 +569,7 @@ def call(coro):
returns a value using end(), then this event returns that value. returns a value using end(), then this event returns that value.
""" """
if not isinstance(coro, types.GeneratorType): if not isinstance(coro, types.GeneratorType):
raise ValueError("%s is not a coroutine" % coro) raise ValueError(f"{coro} is not a coroutine")
return DelegationEvent(coro) return DelegationEvent(coro)

View file

@ -136,7 +136,7 @@ class Symbol:
self.original = original self.original = original
def __repr__(self): def __repr__(self):
return "Symbol(%s)" % repr(self.ident) return f"Symbol({self.ident!r})"
def evaluate(self, env): def evaluate(self, env):
"""Evaluate the symbol in the environment, returning a Unicode """Evaluate the symbol in the environment, returning a Unicode
@ -178,7 +178,7 @@ class Call:
except Exception as exc: except Exception as exc:
# Function raised exception! Maybe inlining the name of # Function raised exception! Maybe inlining the name of
# the exception will help debug. # the exception will help debug.
return "<%s>" % str(exc) return f"<{exc}>"
return str(out) return str(out)
else: else:
return self.original return self.original
@ -224,7 +224,7 @@ class Expression:
self.parts = parts self.parts = parts
def __repr__(self): def __repr__(self):
return "Expression(%s)" % (repr(self.parts)) return f"Expression({self.parts!r})"
def evaluate(self, env): def evaluate(self, env):
"""Evaluate the entire expression in the environment, returning """Evaluate the entire expression in the environment, returning
@ -296,9 +296,6 @@ class Parser:
GROUP_CLOSE, GROUP_CLOSE,
ESCAPE_CHAR, ESCAPE_CHAR,
) )
special_char_re = re.compile(
r"[%s]|\Z" % "".join(re.escape(c) for c in special_chars)
)
escapable_chars = (SYMBOL_DELIM, FUNC_DELIM, GROUP_CLOSE, ARG_SEP) escapable_chars = (SYMBOL_DELIM, FUNC_DELIM, GROUP_CLOSE, ARG_SEP)
terminator_chars = (GROUP_CLOSE,) terminator_chars = (GROUP_CLOSE,)
@ -310,16 +307,10 @@ class Parser:
""" """
# Append comma (ARG_SEP) to the list of special characters only when # Append comma (ARG_SEP) to the list of special characters only when
# parsing function arguments. # parsing function arguments.
extra_special_chars = () extra_special_chars = (ARG_SEP,) if self.in_argument else ()
special_char_re = self.special_char_re special_chars = (*self.special_chars, *extra_special_chars)
if self.in_argument:
extra_special_chars = (ARG_SEP,)
special_char_re = re.compile( special_char_re = re.compile(
r"[%s]|\Z" rf"[{''.join(map(re.escape, special_chars))}]|\Z"
% "".join(
re.escape(c)
for c in self.special_chars + extra_special_chars
)
) )
text_parts = [] text_parts = []
@ -327,7 +318,7 @@ class Parser:
while self.pos < len(self.string): while self.pos < len(self.string):
char = self.string[self.pos] char = self.string[self.pos]
if char not in self.special_chars + extra_special_chars: if char not in special_chars:
# A non-special character. Skip to the next special # A non-special character. Skip to the next special
# character, treating the interstice as literal text. # character, treating the interstice as literal text.
next_pos = ( next_pos = (

View file

@ -19,7 +19,7 @@ def human_seconds_short(interval):
string. string.
""" """
interval = int(interval) interval = int(interval)
return "%i:%02i" % (interval // 60, interval % 60) return f"{interval // 60}:{interval % 60:02d}"
def human_bytes(size): def human_bytes(size):

View file

@ -52,7 +52,7 @@ except ImportError as e:
PROTOCOL_VERSION = "0.16.0" PROTOCOL_VERSION = "0.16.0"
BUFSIZE = 1024 BUFSIZE = 1024
HELLO = "OK MPD %s" % PROTOCOL_VERSION HELLO = f"OK MPD {PROTOCOL_VERSION}"
CLIST_BEGIN = "command_list_begin" CLIST_BEGIN = "command_list_begin"
CLIST_VERBOSE_BEGIN = "command_list_ok_begin" CLIST_VERBOSE_BEGIN = "command_list_ok_begin"
CLIST_END = "command_list_end" CLIST_END = "command_list_end"
@ -1219,7 +1219,7 @@ class Server(BaseServer):
if dirpath.startswith("/"): if dirpath.startswith("/"):
# Strip leading slash (libmpc rejects this). # Strip leading slash (libmpc rejects this).
dirpath = dirpath[1:] dirpath = dirpath[1:]
yield "directory: %s" % dirpath yield f"directory: {dirpath}"
def _listall(self, basepath, node, info=False): def _listall(self, basepath, node, info=False):
"""Helper function for recursive listing. If info, show """Helper function for recursive listing. If info, show

View file

@ -41,7 +41,7 @@ def span_from_str(span_str):
def normalize_year(d, yearfrom): def normalize_year(d, yearfrom):
"""Convert string to a 4 digits year""" """Convert string to a 4 digits year"""
if yearfrom < 100: if yearfrom < 100:
raise BucketError("%d must be expressed on 4 digits" % yearfrom) raise BucketError(f"{yearfrom} must be expressed on 4 digits")
# if two digits only, pick closest year that ends by these two # if two digits only, pick closest year that ends by these two
# digits starting from yearfrom # digits starting from yearfrom
@ -55,14 +55,13 @@ def span_from_str(span_str):
years = [int(x) for x in re.findall(r"\d+", span_str)] years = [int(x) for x in re.findall(r"\d+", span_str)]
if not years: if not years:
raise ui.UserError( raise ui.UserError(
"invalid range defined for year bucket '%s': no year found" f"invalid range defined for year bucket {span_str!r}: no year found"
% span_str
) )
try: try:
years = [normalize_year(x, years[0]) for x in years] years = [normalize_year(x, years[0]) for x in years]
except BucketError as exc: except BucketError as exc:
raise ui.UserError( raise ui.UserError(
"invalid range defined for year bucket '%s': %s" % (span_str, exc) f"invalid range defined for year bucket {span_str!r}: {exc}"
) )
res = {"from": years[0], "str": span_str} res = {"from": years[0], "str": span_str}
@ -126,18 +125,18 @@ def str2fmt(s):
"tonchars": len(m.group("toyear")), "tonchars": len(m.group("toyear")),
} }
res["fmt"] = ( res["fmt"] = (
f"{m['bef']}%s{m['sep']}{'%s' if res['tonchars'] else ''}{m['after']}" f"{m['bef']}{{}}{m['sep']}{'{}' if res['tonchars'] else ''}{m['after']}"
) )
return res return res
def format_span(fmt, yearfrom, yearto, fromnchars, tonchars): def format_span(fmt, yearfrom, yearto, fromnchars, tonchars):
"""Return a span string representation.""" """Return a span string representation."""
args = str(yearfrom)[-fromnchars:] args = [str(yearfrom)[-fromnchars:]]
if tonchars: if tonchars:
args = (str(yearfrom)[-fromnchars:], str(yearto)[-tonchars:]) args.append(str(yearto)[-tonchars:])
return fmt % args return fmt.format(*args)
def extract_modes(spans): def extract_modes(spans):
@ -166,7 +165,7 @@ def build_alpha_spans(alpha_spans_str, alpha_regexs):
else: else:
raise ui.UserError( raise ui.UserError(
"invalid range defined for alpha bucket " "invalid range defined for alpha bucket "
"'%s': no alphanumeric character found" % elem f"'{elem}': no alphanumeric character found"
) )
spans.append( spans.append(
re.compile( re.compile(

View file

@ -593,7 +593,7 @@ class CoverArtArchive(RemoteArtSource):
class Amazon(RemoteArtSource): class Amazon(RemoteArtSource):
NAME = "Amazon" NAME = "Amazon"
ID = "amazon" ID = "amazon"
URL = "https://images.amazon.com/images/P/%s.%02i.LZZZZZZZ.jpg" URL = "https://images.amazon.com/images/P/{}.{:02d}.LZZZZZZZ.jpg"
INDICES = (1, 2) INDICES = (1, 2)
def get( def get(
@ -606,7 +606,7 @@ class Amazon(RemoteArtSource):
if album.asin: if album.asin:
for index in self.INDICES: for index in self.INDICES:
yield self._candidate( yield self._candidate(
url=self.URL % (album.asin, index), url=self.URL.format(album.asin, index),
match=MetadataMatch.EXACT, match=MetadataMatch.EXACT,
) )

View file

@ -28,8 +28,7 @@ class InlineError(Exception):
def __init__(self, code, exc): def __init__(self, code, exc):
super().__init__( super().__init__(
("error in inline path field code:\n%s\n%s: %s") f"error in inline path field code:\n{code}\n{type(exc).__name__}: {exc}"
% (code, type(exc).__name__, str(exc))
) )

View file

@ -46,7 +46,7 @@ class Amarok(MetaSource):
query_xml = '<query version="1.0"> \ query_xml = '<query version="1.0"> \
<filters> \ <filters> \
<and><include field="filename" value=%s /></and> \ <and><include field="filename" value={} /></and> \
</filters> \ </filters> \
</query>' </query>'
@ -68,7 +68,7 @@ class Amarok(MetaSource):
# of the result set. So query for the filename and then try to match # of the result set. So query for the filename and then try to match
# the correct item from the results we get back # the correct item from the results we get back
results = self.collection.Query( results = self.collection.Query(
self.query_xml % quoteattr(basename(path)) self.query_xml.format(quoteattr(basename(path)))
) )
for result in results: for result in results:
if result["xesam:url"] != path: if result["xesam:url"] != path:

View file

@ -111,7 +111,7 @@ class MPDUpdatePlugin(BeetsPlugin):
return return
if password: if password:
s.send(b'password "%s"\n' % password.encode("utf8")) s.send(f'password "{password}"\n'.encode())
resp = s.readline() resp = s.readline()
if b"OK" not in resp: if b"OK" not in resp:
self._log.warning("Authentication failed: {0!r}", resp) self._log.warning("Authentication failed: {0!r}", resp)

View file

@ -57,7 +57,7 @@ class RewritePlugin(BeetsPlugin):
raise ui.UserError("invalid rewrite specification") raise ui.UserError("invalid rewrite specification")
if fieldname not in library.Item._fields: if fieldname not in library.Item._fields:
raise ui.UserError( raise ui.UserError(
"invalid field name (%s) in rewriter" % fieldname f"invalid field name ({fieldname}) in rewriter"
) )
self._log.debug("adding template field {0}", key) self._log.debug("adding template field {0}", key)
pattern = re.compile(pattern.lower()) pattern = re.compile(pattern.lower())

View file

@ -77,7 +77,7 @@ def json_generator(items, root, expand=False):
representation representation
:returns: generator that yields strings :returns: generator that yields strings
""" """
yield '{"%s":[' % root yield f'{{"{root}":['
first = True first = True
for item in items: for item in items:
if first: if first:

View file

@ -384,9 +384,9 @@ Here's an example that adds a ``$disc_and_track`` field:
number. number.
""" """
if item.disctotal > 1: if item.disctotal > 1:
return u'%02i.%02i' % (item.disc, item.track) return f"{item.disc:02d}.{item.track:02d}"
else: else:
return u'%02i' % (item.track) return f"{item.track:02d}"
With this plugin enabled, templates can reference ``$disc_and_track`` as they With this plugin enabled, templates can reference ``$disc_and_track`` as they
can any standard metadata field. can any standard metadata field.

View file

@ -20,8 +20,7 @@ Here are a couple of examples of expressions:
item_fields: item_fields:
initial: albumartist[0].upper() + u'.' initial: albumartist[0].upper() + u'.'
disc_and_track: u'%02i.%02i' % (disc, track) if disc_and_track: f"{disc:02d}.{track:02d}" if disctotal > 1 else f"{track:02d}"
disctotal > 1 else u'%02i' % (track)
Note that YAML syntax allows newlines in values if the subsequent lines are Note that YAML syntax allows newlines in values if the subsequent lines are
indented. indented.

View file

@ -280,6 +280,7 @@ select = [
"PT", # flake8-pytest-style "PT", # flake8-pytest-style
# "RUF", # ruff # "RUF", # ruff
# "UP", # pyupgrade # "UP", # pyupgrade
"UP031", # do not use percent formatting
"UP032", # use f-string instead of format call "UP032", # use f-string instead of format call
"TCH", # flake8-type-checking "TCH", # flake8-type-checking
"W", # pycodestyle "W", # pycodestyle

View file

@ -82,7 +82,7 @@ class DGAlbumInfoTest(BeetsTestCase):
"""Return a Bag that mimics a discogs_client.Release with a """Return a Bag that mimics a discogs_client.Release with a
tracklist where tracks have the specified `positions`.""" tracklist where tracks have the specified `positions`."""
tracks = [ tracks = [
self._make_track("TITLE%s" % i, position) self._make_track(f"TITLE{i}", position)
for (i, position) in enumerate(positions, start=1) for (i, position) in enumerate(positions, start=1)
] ]
return self._make_release(tracks) return self._make_release(tracks)

View file

@ -99,7 +99,7 @@ class MBAlbumInfoTest(MusicBrainzTestCase):
for recording in tracks: for recording in tracks:
i += 1 i += 1
track = { track = {
"id": "RELEASE TRACK ID %d" % i, "id": f"RELEASE TRACK ID {i}",
"recording": recording, "recording": recording,
"position": i, "position": i,
"number": "A1", "number": "A1",
@ -140,7 +140,7 @@ class MBAlbumInfoTest(MusicBrainzTestCase):
for recording in data_tracks: for recording in data_tracks:
i += 1 i += 1
data_track = { data_track = {
"id": "RELEASE TRACK ID %d" % i, "id": f"RELEASE TRACK ID {i}",
"recording": recording, "recording": recording,
"position": i, "position": i,
"number": "A1", "number": "A1",

View file

@ -256,7 +256,7 @@ class TransactionTest(unittest.TestCase):
def test_query_no_increase_revision(self): def test_query_no_increase_revision(self):
old_rev = self.db.revision old_rev = self.db.revision
with self.db.transaction() as tx: with self.db.transaction() as tx:
tx.query("PRAGMA table_info(%s)" % ModelFixture1._table) tx.query(f"PRAGMA table_info({ModelFixture1._table})")
assert self.db.revision == old_rev assert self.db.revision == old_rev

View file

@ -1033,7 +1033,7 @@ class ArtDestinationTest(BeetsTestCase):
def test_art_filename_respects_setting(self): def test_art_filename_respects_setting(self):
art = self.ai.art_destination("something.jpg") art = self.ai.art_destination("something.jpg")
new_art = bytestring_path("%sartimage.jpg" % os.path.sep) new_art = bytestring_path(f"{os.path.sep}artimage.jpg")
assert new_art in art assert new_art in art
def test_art_path_in_item_dir(self): def test_art_path_in_item_dir(self):

View file

@ -1020,7 +1020,7 @@ class ConfigTest(TestPluginTestCase):
def test_cli_config_file_loads_plugin_commands(self): def test_cli_config_file_loads_plugin_commands(self):
with open(self.cli_config_path, "w") as file: with open(self.cli_config_path, "w") as file:
file.write("pluginpath: %s\n" % _common.PLUGINPATH) file.write(f"pluginpath: {_common.PLUGINPATH}\n")
file.write("plugins: test") file.write("plugins: test")
self.run_command("--config", self.cli_config_path, "plugin", lib=None) self.run_command("--config", self.cli_config_path, "plugin", lib=None)