mirror of
https://github.com/fergalmoran/picard.git
synced 2026-02-22 07:34:21 +00:00
Add a tagger.iter_files_from_objects method
Similar to get_files_from_objects, but uses an iterator instead of creating a list.
This commit is contained in:
@@ -111,11 +111,11 @@ from picard.util import (
|
||||
decode_filename,
|
||||
encode_filename,
|
||||
is_hidden,
|
||||
iter_unique,
|
||||
mbid_validate,
|
||||
normpath,
|
||||
process_events_iter,
|
||||
thread,
|
||||
uniqify,
|
||||
versions,
|
||||
webbrowser2,
|
||||
)
|
||||
@@ -582,7 +582,7 @@ class Tagger(QtWidgets.QApplication):
|
||||
|
||||
def copy_files(self, objects):
|
||||
mimeData = QtCore.QMimeData()
|
||||
mimeData.setUrls([QtCore.QUrl.fromLocalFile(f.filename) for f in (self.get_files_from_objects(objects))])
|
||||
mimeData.setUrls([QtCore.QUrl.fromLocalFile(f.filename) for f in self.iter_files_from_objects(objects)])
|
||||
self.clipboard().setMimeData(mimeData)
|
||||
|
||||
def paste_files(self, target):
|
||||
@@ -646,12 +646,16 @@ class Tagger(QtWidgets.QApplication):
|
||||
|
||||
def get_files_from_objects(self, objects, save=False):
|
||||
"""Return list of files from list of albums, clusters, tracks or files."""
|
||||
return uniqify(chain(*[obj.iterfiles(save) for obj in objects]))
|
||||
return list(self.iter_files_from_objects(objects, save=save))
|
||||
|
||||
@staticmethod
|
||||
def iter_files_from_objects(objects, save=False):
|
||||
"""Creates an iterator over all unique files from list of albums, clusters, tracks or files."""
|
||||
return iter_unique(chain(*(obj.iterfiles(save) for obj in objects)))
|
||||
|
||||
def save(self, objects):
|
||||
"""Save the specified objects."""
|
||||
files = self.get_files_from_objects(objects, save=True)
|
||||
for file in files:
|
||||
for file in self.iter_files_from_objects(objects, save=True):
|
||||
file.save()
|
||||
|
||||
def load_album(self, album_id, discid=None):
|
||||
@@ -707,7 +711,7 @@ class Tagger(QtWidgets.QApplication):
|
||||
if album.id not in self.albums:
|
||||
return
|
||||
album.stop_loading()
|
||||
self.remove_files(self.get_files_from_objects([album]))
|
||||
self.remove_files(album.iterfiles())
|
||||
del self.albums[album.id]
|
||||
if album.release_group:
|
||||
album.release_group.remove_album(album.id)
|
||||
@@ -720,7 +724,7 @@ class Tagger(QtWidgets.QApplication):
|
||||
def remove_nat(self, track):
|
||||
"""Remove the specified non-album track."""
|
||||
log.debug("Removing %r", track)
|
||||
self.remove_files(self.get_files_from_objects([track]))
|
||||
self.remove_files(track.iterfiles())
|
||||
if not self.nats:
|
||||
return
|
||||
self.nats.tracks.remove(track)
|
||||
@@ -801,8 +805,7 @@ class Tagger(QtWidgets.QApplication):
|
||||
"""Analyze the file(s)."""
|
||||
if not self.use_acoustid:
|
||||
return
|
||||
files = self.get_files_from_objects(objs)
|
||||
for file in files:
|
||||
for file in self.iter_files_from_objects(objs):
|
||||
if file.can_analyze():
|
||||
file.set_pending()
|
||||
self._acoustid.analyze(file, partial(file._lookup_finished, File.LOOKUP_ACOUSTID))
|
||||
@@ -811,12 +814,11 @@ class Tagger(QtWidgets.QApplication):
|
||||
"""Generate the fingerprints without matching the files."""
|
||||
if not self.use_acoustid:
|
||||
return
|
||||
files = self.get_files_from_objects(objs)
|
||||
|
||||
def finished(file, result):
|
||||
file.clear_pending()
|
||||
|
||||
for file in files:
|
||||
for file in self.iter_files_from_objects(objs):
|
||||
file.set_pending()
|
||||
self._acoustid.fingerprint(file, partial(finished, file))
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ from picard.plugin import ExtensionPoint
|
||||
from picard.track import Track
|
||||
from picard.util import (
|
||||
icontheme,
|
||||
iter_unique,
|
||||
restore_method,
|
||||
thread,
|
||||
throttle,
|
||||
@@ -1043,16 +1044,16 @@ class MainWindow(QtWidgets.QMainWindow, PreserveGeometry):
|
||||
return QtCore.QUrl.fromLocalFile(url)
|
||||
|
||||
def play_file(self):
|
||||
files = self.tagger.get_files_from_objects(self.selected_objects)
|
||||
for file in files:
|
||||
for file in self.tagger.iter_files_from_objects(self.selected_objects):
|
||||
QtGui.QDesktopServices.openUrl(self._openUrl(file.filename))
|
||||
|
||||
def _on_player_error(self, error, msg):
|
||||
self.set_statusbar_message(msg, echo=log.warning, translate=None)
|
||||
|
||||
def open_folder(self):
|
||||
files = self.tagger.get_files_from_objects(self.selected_objects)
|
||||
folders = set([os.path.dirname(f.filename) for f in files])
|
||||
folders = iter_unique(
|
||||
os.path.dirname(f.filename) for f
|
||||
in self.tagger.iter_files_from_objects(self.selected_objects))
|
||||
for folder in folders:
|
||||
QtGui.QDesktopServices.openUrl(self._openUrl(folder))
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ class Player(QtCore.QObject):
|
||||
playlist = QtMultimedia.QMediaPlaylist(self)
|
||||
playlist.setPlaybackMode(QtMultimedia.QMediaPlaylist.Sequential)
|
||||
playlist.addMedia([QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(file.filename))
|
||||
for file in self.tagger.get_files_from_objects(self._selected_objects)])
|
||||
for file in self.tagger.iter_files_from_objects(self._selected_objects)])
|
||||
self._player.setPlaylist(playlist)
|
||||
self._player.play()
|
||||
|
||||
|
||||
@@ -367,6 +367,6 @@ class AlbumSearchDialog(SearchDialog):
|
||||
release["musicbrainz_albumid"])
|
||||
album = self.tagger.load_album(release["musicbrainz_albumid"])
|
||||
if self.cluster:
|
||||
files = self.tagger.get_files_from_objects([self.cluster])
|
||||
files = self.cluster.iterfiles()
|
||||
self.tagger.move_files_to_album(files, release["musicbrainz_albumid"],
|
||||
album)
|
||||
|
||||
@@ -369,6 +369,13 @@ def uniqify(seq):
|
||||
return [x for x in seq if x not in seen and not add_seen(x)]
|
||||
|
||||
|
||||
def iter_unique(seq):
|
||||
"""Creates an iterator only returning unique values from seq"""
|
||||
seen = set()
|
||||
add_seen = seen.add
|
||||
return (x for x in seq if x not in seen and not add_seen(x))
|
||||
|
||||
|
||||
# order is important
|
||||
_tracknum_regexps = (
|
||||
# search for explicit track number (prefix "track")
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
# Copyright (C) 2006-2007 Lukáš Lalinský
|
||||
# Copyright (C) 2010 fatih
|
||||
# Copyright (C) 2010-2011, 2014, 2018-2019 Philipp Wolfer
|
||||
# Copyright (C) 2010-2011, 2014, 2018-2020 Philipp Wolfer
|
||||
# Copyright (C) 2012, 2014, 2018 Wieland Hoffmann
|
||||
# Copyright (C) 2013 Ionuț Ciocîrlan
|
||||
# Copyright (C) 2013-2014, 2018-2020 Laurent Monin
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
import builtins
|
||||
from collections import namedtuple
|
||||
from collections.abc import Iterator
|
||||
import os.path
|
||||
import unittest
|
||||
|
||||
@@ -42,8 +43,10 @@ from picard.util import (
|
||||
find_best_match,
|
||||
imageinfo,
|
||||
is_absolute_path,
|
||||
iter_unique,
|
||||
limited_join,
|
||||
sort_by_similarity,
|
||||
uniqify,
|
||||
)
|
||||
|
||||
|
||||
@@ -450,3 +453,20 @@ class LimitedJoin(PicardTestCase):
|
||||
expected = '0,1,2,3,…,6,7,8,9'
|
||||
result = limited_join(self.list, len(self.list) - 1, ',')
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
|
||||
class IterUniqifyTest(PicardTestCase):
|
||||
|
||||
def test_unique(self):
|
||||
items = [1, 2, 3, 2, 3, 4]
|
||||
result = uniqify(items)
|
||||
self.assertEqual([1, 2, 3, 4], result)
|
||||
|
||||
|
||||
class IterUniqueTest(PicardTestCase):
|
||||
|
||||
def test_unique(self):
|
||||
items = [1, 2, 3, 2, 3, 4]
|
||||
result = iter_unique(items)
|
||||
self.assertTrue(isinstance(result, Iterator))
|
||||
self.assertEqual([1, 2, 3, 4], list(result))
|
||||
|
||||
Reference in New Issue
Block a user