diff --git a/beets/dbcore/queryparse.py b/beets/dbcore/queryparse.py index f84ed7436..f14420448 100644 --- a/beets/dbcore/queryparse.py +++ b/beets/dbcore/queryparse.py @@ -250,7 +250,7 @@ def parse_sorted_query( # Split up query in to comma-separated subqueries, each representing # an AndQuery, which need to be joined together in one OrQuery subquery_parts = [] - for part in parts + [","]: + for part in [*parts, ","]: if part.endswith(","): # Ensure we can catch "foo, bar" as well as "foo , bar" last_subquery_part = part[:-1] diff --git a/beets/importer/__init__.py b/beets/importer/__init__.py index 586b238e6..6e49ba9e2 100644 --- a/beets/importer/__init__.py +++ b/beets/importer/__init__.py @@ -28,11 +28,11 @@ from .tasks import ( # Note: Stages are not exposed to the public API __all__ = [ - "ImportSession", - "ImportAbortError", "Action", - "ImportTask", "ArchiveImportTask", + "ImportAbortError", + "ImportSession", + "ImportTask", "SentinelImportTask", "SingletonImportTask", ] diff --git a/beets/importer/stages.py b/beets/importer/stages.py index 5474053d0..0f8cf922b 100644 --- a/beets/importer/stages.py +++ b/beets/importer/stages.py @@ -388,5 +388,5 @@ def _extend_pipeline(tasks, *stages): else: task_iter = tasks - ipl = pipeline.Pipeline([task_iter] + list(stages)) + ipl = pipeline.Pipeline([task_iter, *list(stages)]) return pipeline.multiple(ipl.pull()) diff --git a/beets/importer/tasks.py b/beets/importer/tasks.py index f6417401b..646b64e7f 100644 --- a/beets/importer/tasks.py +++ b/beets/importer/tasks.py @@ -234,7 +234,7 @@ class ImportTask(BaseImportTask): or APPLY (in which case the data comes from the choice). """ if self.choice_flag in (Action.ASIS, Action.RETAG): - likelies, consensus = util.get_most_common_tags(self.items) + likelies, _ = util.get_most_common_tags(self.items) return likelies elif self.choice_flag is Action.APPLY and self.match: return self.match.info.copy() @@ -892,7 +892,7 @@ class ArchiveImportTask(SentinelImportTask): # The (0, 0, -1) is added to date_time because the # function time.mktime expects a 9-element tuple. # The -1 indicates that the DST flag is unknown. - date_time = time.mktime(f.date_time + (0, 0, -1)) + date_time = time.mktime((*f.date_time, 0, 0, -1)) fullpath = os.path.join(extract_to, f.filename) os.utime(fullpath, (date_time, date_time)) diff --git a/beets/library/__init__.py b/beets/library/__init__.py index 22416ecb5..0f3d7d155 100644 --- a/beets/library/__init__.py +++ b/beets/library/__init__.py @@ -17,13 +17,13 @@ def __getattr__(name: str): __all__ = [ - "Library", - "LibModel", "Album", - "Item", - "parse_query_parts", - "parse_query_string", "FileOperationError", + "Item", + "LibModel", + "Library", "ReadError", "WriteError", + "parse_query_parts", + "parse_query_string", ] diff --git a/beets/plugins.py b/beets/plugins.py index 0dc2754b9..c41541132 100644 --- a/beets/plugins.py +++ b/beets/plugins.py @@ -161,7 +161,7 @@ class BeetsPlugin(metaclass=abc.ABCMeta): import_stages: list[ImportStageFunc] def __init_subclass__(cls) -> None: - """Enable legacy metadata‐source plugins to work with the new interface. + """Enable legacy metadata source plugins to work with the new interface. When a plugin subclass of BeetsPlugin defines a `data_source` attribute but does not inherit from MetadataSourcePlugin, this hook: diff --git a/beets/test/helper.py b/beets/test/helper.py index 3cb1e4c3c..adc64088d 100644 --- a/beets/test/helper.py +++ b/beets/test/helper.py @@ -120,7 +120,7 @@ def capture_stdout(): def has_program(cmd, args=["--version"]): """Returns `True` if `cmd` can be executed.""" - full_cmd = [cmd] + args + full_cmd = [cmd, *args] try: with open(os.devnull, "wb") as devnull: subprocess.check_call( diff --git a/beets/ui/commands/import_/display.py b/beets/ui/commands/import_/display.py index 7858c7152..bdc44d51f 100644 --- a/beets/ui/commands/import_/display.py +++ b/beets/ui/commands/import_/display.py @@ -339,13 +339,9 @@ class ChangeRepresentation: max_width_l = max(get_width(line_tuple[0]) for line_tuple in lines) max_width_r = max(get_width(line_tuple[1]) for line_tuple in lines) - if ( - (max_width_l <= col_width) - and (max_width_r <= col_width) - or ( - ((max_width_l > col_width) or (max_width_r > col_width)) - and ((max_width_l + max_width_r) <= col_width * 2) - ) + if ((max_width_l <= col_width) and (max_width_r <= col_width)) or ( + ((max_width_l > col_width) or (max_width_r > col_width)) + and ((max_width_l + max_width_r) <= col_width * 2) ): # All content fits. Either both maximum widths are below column # widths, or one of the columns is larger than allowed but the @@ -559,7 +555,7 @@ def penalty_string(distance: Distance, limit: int | None = None) -> str: penalties.append(key) if penalties: if limit and len(penalties) > limit: - penalties = penalties[:limit] + ["..."] + penalties = [*penalties[:limit], "..."] # Prefix penalty string with U+2260: Not Equal To penalty_string = f"\u2260 {', '.join(penalties)}" return ui.colorize("changed", penalty_string) diff --git a/beets/ui/commands/import_/session.py b/beets/ui/commands/import_/session.py index 9c8c8dd62..42a809634 100644 --- a/beets/ui/commands/import_/session.py +++ b/beets/ui/commands/import_/session.py @@ -256,13 +256,11 @@ class TerminalImportSession(importer.ImportSession): # Add a "dummy" choice for the other baked-in option, for # duplicate checking. - all_choices = ( - [ - PromptChoice("a", "Apply", None), - ] - + choices - + extra_choices - ) + all_choices = [ + PromptChoice("a", "Apply", None), + *choices, + *extra_choices, + ] # Check for conflicts. short_letters = [c.short for c in all_choices] @@ -501,7 +499,7 @@ def choose_candidate( if config["import"]["bell"]: ui.print_("\a", end="") sel = ui.input_options( - ("Apply", "More candidates") + choice_opts, + ("Apply", "More candidates", *choice_opts), require=require, default=default, ) diff --git a/beets/ui/commands/write.py b/beets/ui/commands/write.py index 05c3c7565..87fba8236 100644 --- a/beets/ui/commands/write.py +++ b/beets/ui/commands/write.py @@ -15,7 +15,7 @@ def write_items(lib, query, pretend, force): """Write tag information from the database to the respective files in the filesystem. """ - items, albums = do_query(lib, query, False, False) + items, _ = do_query(lib, query, False, False) for item in items: # Item deleted? diff --git a/beets/util/artresizer.py b/beets/util/artresizer.py index 72007d0b5..6fec62774 100644 --- a/beets/util/artresizer.py +++ b/beets/util/artresizer.py @@ -268,7 +268,8 @@ class IMBackend(LocalBackend): # with regards to the height. # ImageMagick already seems to default to no interlace, but we include # it here for the sake of explicitness. - cmd: list[str] = self.convert_cmd + [ + cmd: list[str] = [ + *self.convert_cmd, syspath(path_in, prefix=False), "-resize", f"{maxwidth}x>", @@ -298,7 +299,8 @@ class IMBackend(LocalBackend): return path_out def get_size(self, path_in: bytes) -> tuple[int, int] | None: - cmd: list[str] = self.identify_cmd + [ + cmd: list[str] = [ + *self.identify_cmd, "-format", "%w %h", syspath(path_in, prefix=False), @@ -336,7 +338,8 @@ class IMBackend(LocalBackend): if not path_out: path_out = get_temp_filename(__name__, "deinterlace_IM_", path_in) - cmd = self.convert_cmd + [ + cmd = [ + *self.convert_cmd, syspath(path_in, prefix=False), "-interlace", "none", @@ -351,7 +354,7 @@ class IMBackend(LocalBackend): return path_in def get_format(self, path_in: bytes) -> str | None: - cmd = self.identify_cmd + ["-format", "%[magick]", syspath(path_in)] + cmd = [*self.identify_cmd, "-format", "%[magick]", syspath(path_in)] try: # Image formats should really only be ASCII strings such as "PNG", @@ -368,7 +371,8 @@ class IMBackend(LocalBackend): target: bytes, deinterlaced: bool, ) -> bytes: - cmd = self.convert_cmd + [ + cmd = [ + *self.convert_cmd, syspath(source), *(["-interlace", "none"] if deinterlaced else []), syspath(target), @@ -400,14 +404,16 @@ class IMBackend(LocalBackend): # to grayscale and then pipe them into the `compare` command. # On Windows, ImageMagick doesn't support the magic \\?\ prefix # on paths, so we pass `prefix=False` to `syspath`. - convert_cmd = self.convert_cmd + [ + convert_cmd = [ + *self.convert_cmd, syspath(im2, prefix=False), syspath(im1, prefix=False), "-colorspace", "gray", "MIFF:-", ] - compare_cmd = self.compare_cmd + [ + compare_cmd = [ + *self.compare_cmd, "-define", "phash:colorspaces=sRGB,HCLp", "-metric", @@ -487,7 +493,7 @@ class IMBackend(LocalBackend): ("-set", k, v) for k, v in metadata.items() ) str_file = os.fsdecode(file) - command = self.convert_cmd + [str_file, *assignments, str_file] + command = [*self.convert_cmd, str_file, *assignments, str_file] util.command_output(command) @@ -828,7 +834,7 @@ class ArtResizer: "jpeg": "jpg", }.get(new_format, new_format) - fname, ext = os.path.splitext(path_in) + fname, _ = os.path.splitext(path_in) path_new = fname + b"." + new_format.encode("utf8") # allows the exception to propagate, while still making sure a changed diff --git a/beets/util/pipeline.py b/beets/util/pipeline.py index 2ed593904..2c1e72e53 100644 --- a/beets/util/pipeline.py +++ b/beets/util/pipeline.py @@ -192,7 +192,7 @@ def stage( task: R | T | None = None while True: task = yield task - task = func(*(args + (task,))) + task = func(*args, task) return coro @@ -216,7 +216,7 @@ def mutator_stage(func: Callable[[Unpack[A], T], R]): task = None while True: task = yield task - func(*(args + (task,))) + func(*args, task) return coro diff --git a/beetsplug/bpd/__init__.py b/beetsplug/bpd/__init__.py index 0359259b7..ea2e561b3 100644 --- a/beetsplug/bpd/__init__.py +++ b/beetsplug/bpd/__init__.py @@ -1037,7 +1037,7 @@ class Command: raise BPDError(ERROR_PERMISSION, "insufficient privileges") try: - args = [conn] + self.args + args = [conn, *self.args] results = func(*args) if results: for data in results: diff --git a/beetsplug/bpd/gstplayer.py b/beetsplug/bpd/gstplayer.py index f356b3066..e4f38af88 100644 --- a/beetsplug/bpd/gstplayer.py +++ b/beetsplug/bpd/gstplayer.py @@ -37,7 +37,7 @@ except ValueError as e: # makes it so the test collector functions as inteded. raise ImportError from e -from gi.repository import GLib, Gst # noqa: E402 +from gi.repository import GLib, Gst Gst.init(None) @@ -115,7 +115,7 @@ class GstPlayer: elif message.type == Gst.MessageType.ERROR: # error self.player.set_state(Gst.State.NULL) - err, debug = message.parse_error() + err, _ = message.parse_error() print(f"Error: {err}") self.playing = False @@ -205,7 +205,7 @@ class GstPlayer: def seek(self, position): """Seeks to position (in seconds).""" - cur_pos, cur_len = self.time() + _, cur_len = self.time() if position > cur_len: self.stop() return diff --git a/beetsplug/bpsync.py b/beetsplug/bpsync.py index fbdf8cc70..34cb08cce 100644 --- a/beetsplug/bpsync.py +++ b/beetsplug/bpsync.py @@ -73,7 +73,7 @@ class BPSyncPlugin(BeetsPlugin): """Retrieve and apply info from the autotagger for items matched by query. """ - for item in lib.items(query + ["singleton:true"]): + for item in lib.items([*query, "singleton:true"]): if not item.mb_trackid: self._log.info( "Skipping singleton with no mb_trackid: {}", item diff --git a/beetsplug/convert.py b/beetsplug/convert.py index 74ced8ae3..2e837c77f 100644 --- a/beetsplug/convert.py +++ b/beetsplug/convert.py @@ -274,7 +274,7 @@ class ConvertPlugin(BeetsPlugin): pretend, hardlink, link, - playlist, + _, force, ) = self._get_opts_and_config(empty_opts) diff --git a/beetsplug/discogs.py b/beetsplug/discogs.py index 29600a676..08d437d2d 100644 --- a/beetsplug/discogs.py +++ b/beetsplug/discogs.py @@ -572,7 +572,7 @@ class DiscogsPlugin(MetadataSourcePlugin): processed = self._process_clean_tracklist( clean_tracklist, album_artist_data ) - tracks, index_tracks, index, divisions, next_divisions = processed + tracks, index_tracks, *_ = processed # Fix up medium and medium_index for each track. Discogs position is # unreliable, but tracks are in order. medium = None diff --git a/beetsplug/export.py b/beetsplug/export.py index e6c2b88c7..21db190b1 100644 --- a/beetsplug/export.py +++ b/beetsplug/export.py @@ -148,7 +148,7 @@ class ExportPlugin(BeetsPlugin): album=opts.album, ): try: - data, item = data_emitter(included_keys or "*") + data, _ = data_emitter(included_keys or "*") except (mediafile.UnreadableFileError, OSError) as ex: self._log.error("cannot read file: {}", ex) continue diff --git a/beetsplug/fetchart.py b/beetsplug/fetchart.py index f1cc85f44..ab5a17228 100644 --- a/beetsplug/fetchart.py +++ b/beetsplug/fetchart.py @@ -867,7 +867,7 @@ class ITunesStore(RemoteArtSource): ) except KeyError as e: self._log.debug( - "Malformed itunes candidate: {} not found in {}", # NOQA E501 + "Malformed itunes candidate: {} not found in {}", e, list(c.keys()), ) diff --git a/beetsplug/fromfilename.py b/beetsplug/fromfilename.py index c3fb4bc6b..be7fee23a 100644 --- a/beetsplug/fromfilename.py +++ b/beetsplug/fromfilename.py @@ -88,7 +88,7 @@ def apply_matches(d, log): """Given a mapping from items to field dicts, apply the fields to the objects. """ - some_map = list(d.values())[0] + some_map = next(iter(d.values())) keys = some_map.keys() # Only proceed if the "tag" field is equal across all filenames. diff --git a/beetsplug/keyfinder.py b/beetsplug/keyfinder.py index e2aff24e5..e0e9b8740 100644 --- a/beetsplug/keyfinder.py +++ b/beetsplug/keyfinder.py @@ -62,7 +62,7 @@ class KeyFinderPlugin(BeetsPlugin): try: output = util.command_output( - command + [util.syspath(item.path)] + [*command, util.syspath(item.path)] ).stdout except (subprocess.CalledProcessError, OSError) as exc: self._log.error("execution failed: {}", exc) diff --git a/beetsplug/lastgenre/__init__.py b/beetsplug/lastgenre/__init__.py index 1bb874c04..121d76596 100644 --- a/beetsplug/lastgenre/__init__.py +++ b/beetsplug/lastgenre/__init__.py @@ -68,12 +68,12 @@ def flatten_tree( if isinstance(elem, dict): for k, v in elem.items(): - flatten_tree(v, path + [k], branches) + flatten_tree(v, [*path, k], branches) elif isinstance(elem, list): for sub in elem: flatten_tree(sub, path, branches) else: - branches.append(path + [str(elem)]) + branches.append([*path, str(elem)]) def find_parents(candidate: str, branches: list[list[str]]) -> list[str]: diff --git a/beetsplug/mbsubmit.py b/beetsplug/mbsubmit.py index f6d197256..7136f4c29 100644 --- a/beetsplug/mbsubmit.py +++ b/beetsplug/mbsubmit.py @@ -69,7 +69,7 @@ class MBSubmitPlugin(BeetsPlugin): paths.append(displayable_path(p)) try: picard_path = self.config["picard_path"].as_str() - subprocess.Popen([picard_path] + paths) + subprocess.Popen([picard_path, *paths]) self._log.info("launched picard from\n{}", picard_path) except OSError as exc: self._log.error("Could not open picard, got error:\n{}", exc) diff --git a/beetsplug/mbsync.py b/beetsplug/mbsync.py index 5b74b67c9..45f34e865 100644 --- a/beetsplug/mbsync.py +++ b/beetsplug/mbsync.py @@ -71,7 +71,7 @@ class MBSyncPlugin(BeetsPlugin): """Retrieve and apply info from the autotagger for items matched by query. """ - for item in lib.items(query + ["singleton:true"]): + for item in lib.items([*query, "singleton:true"]): if not item.mb_trackid: self._log.info( "Skipping singleton with no mb_trackid: {}", item diff --git a/beetsplug/replaygain.py b/beetsplug/replaygain.py index a8c887caa..4e8b429ea 100644 --- a/beetsplug/replaygain.py +++ b/beetsplug/replaygain.py @@ -642,11 +642,11 @@ class CommandBackend(Backend): cmd: list[str] = [self.command, "-o", "-s", "s"] if self.noclip: # Adjust to avoid clipping. - cmd = cmd + ["-k"] + cmd = [*cmd, "-k"] else: # Disable clipping warning. - cmd = cmd + ["-c"] - cmd = cmd + ["-d", str(int(target_level - 89))] + cmd = [*cmd, "-c"] + cmd = [*cmd, "-d", str(int(target_level - 89))] cmd = cmd + [syspath(i.path) for i in items] self._log.debug("analyzing {} files", len(items)) @@ -1105,7 +1105,7 @@ class AudioToolsBackend(Backend): # The first item is taken and opened to get the sample rate to # initialize the replaygain object. The object is used for all the # tracks in the album to get the album values. - item = list(task.items)[0] + item = next(iter(task.items)) audiofile = self.open_audio_file(item) rg = self.init_replaygain(audiofile, item) diff --git a/beetsplug/the.py b/beetsplug/the.py index 664d4c01e..b29fc728d 100644 --- a/beetsplug/the.py +++ b/beetsplug/the.py @@ -58,9 +58,9 @@ class ThePlugin(BeetsPlugin): p, ) if self.config["a"]: - self.patterns = [PATTERN_A] + self.patterns + self.patterns = [PATTERN_A, *self.patterns] if self.config["the"]: - self.patterns = [PATTERN_THE] + self.patterns + self.patterns = [PATTERN_THE, *self.patterns] if not self.patterns: self._log.warning("no patterns defined!") diff --git a/pyproject.toml b/pyproject.toml index 6cdc19285..b14f442ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -306,7 +306,7 @@ select = [ "ISC", # flake8-implicit-str-concat "N", # pep8-naming "PT", # flake8-pytest-style - # "RUF", # ruff + "RUF", # ruff "UP", # pyupgrade "TC", # flake8-type-checking "W", # pycodestyle @@ -320,6 +320,8 @@ ignore = [ "test/plugins/test_ftintitle.py" = ["E501"] "test/test_util.py" = ["E501"] "test/ui/test_field_diff.py" = ["E501"] +"test/util/test_id_extractors.py" = ["E501"] +"test/**" = ["RUF001"] # we use Unicode characters in tests [tool.ruff.lint.isort] split-on-trailing-comma = false diff --git a/test/autotag/test_distance.py b/test/autotag/test_distance.py index 3686f82c9..ac0864564 100644 --- a/test/autotag/test_distance.py +++ b/test/autotag/test_distance.py @@ -337,15 +337,15 @@ class TestDataSourceDistance: _p("Original", "Original", 0.5, 1.0, True, MATCH, id="match"), _p("Original", "Other", 0.5, 1.0, True, MISMATCH, id="mismatch"), _p("Other", "Original", 0.5, 1.0, True, MISMATCH, id="mismatch"), - _p("Original", "unknown", 0.5, 1.0, True, MISMATCH, id="mismatch-unknown"), # noqa: E501 - _p("Original", None, 0.5, 1.0, True, MISMATCH, id="mismatch-no-info"), # noqa: E501 + _p("Original", "unknown", 0.5, 1.0, True, MISMATCH, id="mismatch-unknown"), + _p("Original", None, 0.5, 1.0, True, MISMATCH, id="mismatch-no-info"), _p(None, "Other", 0.5, 1.0, True, MISMATCH, id="mismatch-no-original-multiple-sources"), # noqa: E501 _p(None, "Other", 0.5, 1.0, False, MATCH, id="match-no-original-but-single-source"), # noqa: E501 _p("unknown", "unknown", 0.5, 1.0, True, MATCH, id="match-unknown"), - _p("Original", "Other", 1.0, 1.0, True, 0.25, id="mismatch-max-penalty"), # noqa: E501 - _p("Original", "Other", 0.5, 5.0, True, 0.3125, id="mismatch-high-weight"), # noqa: E501 - _p("Original", "Other", 0.0, 1.0, True, MATCH, id="match-no-penalty"), # noqa: E501 - _p("Original", "Other", 0.5, 0.0, True, MATCH, id="match-no-weight"), # noqa: E501 + _p("Original", "Other", 1.0, 1.0, True, 0.25, id="mismatch-max-penalty"), + _p("Original", "Other", 0.5, 5.0, True, 0.3125, id="mismatch-high-weight"), + _p("Original", "Other", 0.0, 1.0, True, MATCH, id="match-no-penalty"), + _p("Original", "Other", 0.5, 0.0, True, MATCH, id="match-no-weight"), ], ) # fmt: skip def test_distance(self, item, info, expected_distance): diff --git a/test/plugins/test_edit.py b/test/plugins/test_edit.py index d0e03d0e5..f715fd9e8 100644 --- a/test/plugins/test_edit.py +++ b/test/plugins/test_edit.py @@ -350,8 +350,8 @@ class EditDuringImporterNonSingletonTest(EditDuringImporterTestCase): self.lib.items(), self.items_orig, ["title"], - self.IGNORED - + [ + [ + *self.IGNORED, "albumartist", "mb_albumartistid", "mb_albumartistids", @@ -378,7 +378,7 @@ class EditDuringImporterNonSingletonTest(EditDuringImporterTestCase): self.lib.items(), self.items_orig, [], - self.IGNORED + ["albumartist", "mb_albumartistid"], + [*self.IGNORED, "albumartist", "mb_albumartistid"], ) assert all("Tag Track" in i.title for i in self.lib.items()) @@ -490,6 +490,6 @@ class EditDuringImporterSingletonTest(EditDuringImporterTestCase): self.lib.items(), self.items_orig, ["title"], - self.IGNORED + ["albumartist", "mb_albumartistid"], + [*self.IGNORED, "albumartist", "mb_albumartistid"], ) assert all("Edited Track" in i.title for i in self.lib.items()) diff --git a/test/plugins/test_lyrics.py b/test/plugins/test_lyrics.py index 23db03fef..376f0b9f2 100644 --- a/test/plugins/test_lyrics.py +++ b/test/plugins/test_lyrics.py @@ -431,7 +431,7 @@ class TestTekstowoLyrics(LyricsBackendTest): [ ("tekstowopl/piosenka24kgoldncityofangels1", True), ( - "tekstowopl/piosenkabeethovenbeethovenpianosonata17tempestthe3rdmovement", # noqa: E501 + "tekstowopl/piosenkabeethovenbeethovenpianosonata17tempestthe3rdmovement", False, ), ], @@ -614,7 +614,7 @@ class TestTranslation: [00:00:50] [00:01.00] Some more synced lyrics / Quelques paroles plus synchronisées - Source: https://lrclib.net/api/123""", # noqa: E501 + Source: https://lrclib.net/api/123""", id="synced", ), pytest.param( diff --git a/test/plugins/test_random.py b/test/plugins/test_random.py index 9bcf8e59b..cb21edf47 100644 --- a/test/plugins/test_random.py +++ b/test/plugins/test_random.py @@ -72,8 +72,8 @@ class RandomTest(TestHelper, unittest.TestCase): print(f"{i:2d} {'*' * positions.count(i)}") return self._stats(positions) - mean1, stdev1, median1 = experiment("artist") - mean2, stdev2, median2 = experiment("track") + _, stdev1, median1 = experiment("artist") + _, stdev2, median2 = experiment("track") assert 0 == pytest.approx(median1, abs=1) assert len(self.items) // 2 == pytest.approx(median2, abs=1) assert stdev2 > stdev1 diff --git a/test/test_art_resize.py b/test/test_art_resize.py index 0ccbb0eae..55deb8cb6 100644 --- a/test/test_art_resize.py +++ b/test/test_art_resize.py @@ -136,7 +136,8 @@ class ArtResizerFileSizeTest(CleanupModulesMixin, BeetsTestCase): """ im = IMBackend() path = im.deinterlace(self.IMG_225x225) - cmd = im.identify_cmd + [ + cmd = [ + *im.identify_cmd, "-format", "%[interlace]", syspath(path, prefix=False), diff --git a/test/test_dbcore.py b/test/test_dbcore.py index 653adf298..74e378275 100644 --- a/test/test_dbcore.py +++ b/test/test_dbcore.py @@ -411,7 +411,7 @@ class ModelTest(unittest.TestCase): def test_computed_field(self): model = ModelFixtureWithGetters() assert model.aComputedField == "thing" - with pytest.raises(KeyError, match="computed field .+ deleted"): + with pytest.raises(KeyError, match=r"computed field .+ deleted"): del model.aComputedField def test_items(self): diff --git a/test/test_library.py b/test/test_library.py index 7c0529001..4acf34746 100644 --- a/test/test_library.py +++ b/test/test_library.py @@ -1056,7 +1056,7 @@ class PathStringTest(BeetsTestCase): assert isinstance(self.i.path, bytes) def test_fetched_item_path_is_bytestring(self): - i = list(self.lib.items())[0] + i = next(iter(self.lib.items())) assert isinstance(i.path, bytes) def test_unicode_path_becomes_bytestring(self): @@ -1070,14 +1070,14 @@ class PathStringTest(BeetsTestCase): """, (self.i.id, "somepath"), ) - i = list(self.lib.items())[0] + i = next(iter(self.lib.items())) assert isinstance(i.path, bytes) def test_special_chars_preserved_in_database(self): path = "b\xe1r".encode() self.i.path = path self.i.store() - i = list(self.lib.items())[0] + i = next(iter(self.lib.items())) assert i.path == path def test_special_char_path_added_to_database(self): @@ -1086,7 +1086,7 @@ class PathStringTest(BeetsTestCase): i = item() i.path = path self.lib.add(i) - i = list(self.lib.items())[0] + i = next(iter(self.lib.items())) assert i.path == path def test_destination_returns_bytestring(self): diff --git a/test/test_plugins.py b/test/test_plugins.py index 6f7026718..e161a4de6 100644 --- a/test/test_plugins.py +++ b/test/test_plugins.py @@ -308,7 +308,9 @@ class PromptChoicesTest(TerminalImportMixin, PluginImportTestCase): "Enter search", "enter Id", "aBort", - ) + ("Foo", "baR") + "Foo", + "baR", + ) self.importer.add_choice(Action.SKIP) self.importer.run() @@ -342,7 +344,9 @@ class PromptChoicesTest(TerminalImportMixin, PluginImportTestCase): "Enter search", "enter Id", "aBort", - ) + ("Foo", "baR") + "Foo", + "baR", + ) config["import"]["singletons"] = True self.importer.add_choice(Action.SKIP) @@ -381,7 +385,8 @@ class PromptChoicesTest(TerminalImportMixin, PluginImportTestCase): "Enter search", "enter Id", "aBort", - ) + ("baZ",) + "baZ", + ) self.importer.add_choice(Action.SKIP) self.importer.run() self.mock_input_options.assert_called_once_with( @@ -416,7 +421,8 @@ class PromptChoicesTest(TerminalImportMixin, PluginImportTestCase): "Enter search", "enter Id", "aBort", - ) + ("Foo",) + "Foo", + ) # DummyPlugin.foo() should be called once with patch.object(DummyPlugin, "foo", autospec=True) as mock_foo: @@ -458,7 +464,8 @@ class PromptChoicesTest(TerminalImportMixin, PluginImportTestCase): "Enter search", "enter Id", "aBort", - ) + ("Foo",) + "Foo", + ) # DummyPlugin.foo() should be called once with helper.control_stdin("f\n"): diff --git a/test/ui/commands/test_completion.py b/test/ui/commands/test_completion.py index f1e53f238..ee2881a0e 100644 --- a/test/ui/commands/test_completion.py +++ b/test/ui/commands/test_completion.py @@ -56,7 +56,7 @@ class CompletionTest(IOMixin, TestPluginTestCase): test_script_name = os.path.join(_common.RSRC, b"test_completion.sh") with open(test_script_name, "rb") as test_script_file: tester.stdin.writelines(test_script_file) - out, err = tester.communicate() + out, _ = tester.communicate() assert tester.returncode == 0 assert out == b"completion tests passed\n", ( "test/test_completion.sh did not execute properly. " diff --git a/test/ui/commands/test_modify.py b/test/ui/commands/test_modify.py index b9cc1524d..77d378032 100644 --- a/test/ui/commands/test_modify.py +++ b/test/ui/commands/test_modify.py @@ -190,27 +190,23 @@ class ModifyTest(BeetsTestCase): assert mediafile.initial_key is None def test_arg_parsing_colon_query(self): - (query, mods, dels) = modify_parse_args( - ["title:oldTitle", "title=newTitle"] - ) + query, mods, _ = modify_parse_args(["title:oldTitle", "title=newTitle"]) assert query == ["title:oldTitle"] assert mods == {"title": "newTitle"} def test_arg_parsing_delete(self): - (query, mods, dels) = modify_parse_args(["title:oldTitle", "title!"]) + query, _, dels = modify_parse_args(["title:oldTitle", "title!"]) assert query == ["title:oldTitle"] assert dels == ["title"] def test_arg_parsing_query_with_exclaimation(self): - (query, mods, dels) = modify_parse_args( + query, mods, _ = modify_parse_args( ["title:oldTitle!", "title=newTitle!"] ) assert query == ["title:oldTitle!"] assert mods == {"title": "newTitle!"} def test_arg_parsing_equals_in_value(self): - (query, mods, dels) = modify_parse_args( - ["title:foo=bar", "title=newTitle"] - ) + query, mods, _ = modify_parse_args(["title:foo=bar", "title=newTitle"]) assert query == ["title:foo=bar"] assert mods == {"title": "newTitle"} diff --git a/test/ui/commands/test_utils.py b/test/ui/commands/test_utils.py index bd07a27c7..075f522a7 100644 --- a/test/ui/commands/test_utils.py +++ b/test/ui/commands/test_utils.py @@ -19,7 +19,7 @@ class QueryTest(BeetsTestCase): ) item = library.Item.from_path(itempath) self.lib.add(item) - return item, itempath + return item def add_album(self, items): album = self.lib.add_album(items) @@ -47,13 +47,13 @@ class QueryTest(BeetsTestCase): self.check_do_query(2, 0, album=False) def test_query_album(self): - item, itempath = self.add_item() + item = self.add_item() self.add_album([item]) self.check_do_query(1, 1, album=True) self.check_do_query(0, 1, album=True, also_items=False) - item, itempath = self.add_item() - item2, itempath = self.add_item() + item = self.add_item() + item2 = self.add_item() self.add_album([item, item2]) self.check_do_query(3, 2, album=True) self.check_do_query(0, 2, album=True, also_items=False) diff --git a/test/ui/test_ui.py b/test/ui/test_ui.py index a37d4bb29..a0bf2e598 100644 --- a/test/ui/test_ui.py +++ b/test/ui/test_ui.py @@ -374,7 +374,7 @@ class ShowModelChangeTest(IOMixin, unittest.TestCase): def test_both_values_shown(self): self.a.title = "foo" self.b.title = "bar" - change, out = self._show() + _, out = self._show() assert "foo" in out assert "bar" in out diff --git a/test/util/test_id_extractors.py b/test/util/test_id_extractors.py index 4918b4361..e510dd5d8 100644 --- a/test/util/test_id_extractors.py +++ b/test/util/test_id_extractors.py @@ -10,26 +10,26 @@ from beets.util.id_extractors import extract_release_id [ ("spotify", "39WqpoPgZxygo6YQjehLJJ", "39WqpoPgZxygo6YQjehLJJ"), ("spotify", "blah blah", None), - ("spotify", "https://open.spotify.com/album/39WqpoPgZxygo6YQjehLJJ", "39WqpoPgZxygo6YQjehLJJ"), # noqa: E501 + ("spotify", "https://open.spotify.com/album/39WqpoPgZxygo6YQjehLJJ", "39WqpoPgZxygo6YQjehLJJ"), ("deezer", "176356382", "176356382"), ("deezer", "blah blah", None), ("deezer", "https://www.deezer.com/album/176356382", "176356382"), ("beatport", "3089651", "3089651"), ("beatport", "blah blah", None), - ("beatport", "https://www.beatport.com/release/album-name/3089651", "3089651"), # noqa: E501 - ("discogs", "http://www.discogs.com/G%C3%BCnther-Lause-Meru-Ep/release/4354798", "4354798"), # noqa: E501 - ("discogs", "http://www.discogs.com/release/4354798-G%C3%BCnther-Lause-Meru-Ep", "4354798"), # noqa: E501 - ("discogs", "http://www.discogs.com/G%C3%BCnther-4354798Lause-Meru-Ep/release/4354798", "4354798"), # noqa: E501 - ("discogs", "http://www.discogs.com/release/4354798-G%C3%BCnther-4354798Lause-Meru-Ep/", "4354798"), # noqa: E501 + ("beatport", "https://www.beatport.com/release/album-name/3089651", "3089651"), + ("discogs", "http://www.discogs.com/G%C3%BCnther-Lause-Meru-Ep/release/4354798", "4354798"), + ("discogs", "http://www.discogs.com/release/4354798-G%C3%BCnther-Lause-Meru-Ep", "4354798"), + ("discogs", "http://www.discogs.com/G%C3%BCnther-4354798Lause-Meru-Ep/release/4354798", "4354798"), + ("discogs", "http://www.discogs.com/release/4354798-G%C3%BCnther-4354798Lause-Meru-Ep/", "4354798"), ("discogs", "[r4354798]", "4354798"), ("discogs", "r4354798", "4354798"), ("discogs", "4354798", "4354798"), ("discogs", "yet-another-metadata-provider.org/foo/12345", None), ("discogs", "005b84a0-ecd6-39f1-b2f6-6eb48756b268", None), - ("musicbrainz", "28e32c71-1450-463e-92bf-e0a46446fc11", "28e32c71-1450-463e-92bf-e0a46446fc11"), # noqa: E501 + ("musicbrainz", "28e32c71-1450-463e-92bf-e0a46446fc11", "28e32c71-1450-463e-92bf-e0a46446fc11"), ("musicbrainz", "blah blah", None), - ("musicbrainz", "https://musicbrainz.org/entity/28e32c71-1450-463e-92bf-e0a46446fc11", "28e32c71-1450-463e-92bf-e0a46446fc11"), # noqa: E501 - ("bandcamp", "https://nameofartist.bandcamp.com/album/nameofalbum", "https://nameofartist.bandcamp.com/album/nameofalbum"), # noqa: E501 + ("musicbrainz", "https://musicbrainz.org/entity/28e32c71-1450-463e-92bf-e0a46446fc11", "28e32c71-1450-463e-92bf-e0a46446fc11"), + ("bandcamp", "https://nameofartist.bandcamp.com/album/nameofalbum", "https://nameofartist.bandcamp.com/album/nameofalbum"), ], ) # fmt: skip def test_extract_release_id(source, id_string, expected):