diff --git a/mopidy/core/library.py b/mopidy/core/library.py index 89a2037a..9aaa386e 100644 --- a/mopidy/core/library.py +++ b/mopidy/core/library.py @@ -4,6 +4,7 @@ import collections import logging import operator import urlparse +import warnings import pykka @@ -132,6 +133,7 @@ class LibraryController(object): .. deprecated:: 1.0 Use :meth:`search` with ``exact`` set. """ + warnings.warn('library.find_exact() is deprecated', DeprecationWarning) return self.search(query=query, uris=uris, exact=True, **kwargs) def lookup(self, uri=None, uris=None): diff --git a/mopidy/mpd/protocol/music_db.py b/mopidy/mpd/protocol/music_db.py index a942abf5..59a1f9b6 100644 --- a/mopidy/mpd/protocol/music_db.py +++ b/mopidy/mpd/protocol/music_db.py @@ -100,7 +100,7 @@ def count(context, *args): query = _query_from_mpd_search_parameters(args, _SEARCH_MAPPING) except ValueError: raise exceptions.MpdArgError('incorrect arguments') - results = context.core.library.find_exact(**query).get() + results = context.core.library.search(query=query, exact=True).get() result_tracks = _get_tracks(results) return [ ('songs', len(result_tracks)), @@ -141,7 +141,7 @@ def find(context, *args): except ValueError: return - results = context.core.library.find_exact(**query).get() + results = context.core.library.search(query=query, exact=True).get() result_tracks = [] if ('artist' not in query and 'albumartist' not in query and @@ -168,7 +168,7 @@ def findadd(context, *args): query = _query_from_mpd_search_parameters(args, _SEARCH_MAPPING) except ValueError: return - results = context.core.library.find_exact(**query).get() + results = context.core.library.search(query=query, exact=True).get() context.core.tracklist.add(_get_tracks(results)) diff --git a/tests/core/test_library.py b/tests/core/test_library.py index 51313daa..4a96042d 100644 --- a/tests/core/test_library.py +++ b/tests/core/test_library.py @@ -1,6 +1,7 @@ from __future__ import absolute_import, unicode_literals import unittest +import warnings import mock @@ -206,75 +207,6 @@ class CoreLibraryTest(unittest.TestCase): self.library1.refresh.assert_called_once_with(None) self.library2.refresh.assert_called_twice_with(None) - def test_find_exact_combines_results_from_all_backends(self): - track1 = Track(uri='dummy1:a') - track2 = Track(uri='dummy2:a') - result1 = SearchResult(tracks=[track1]) - result2 = SearchResult(tracks=[track2]) - - self.library1.search.return_value.get.return_value = result1 - self.library2.search.return_value.get.return_value = result2 - - result = self.core.library.find_exact(any=['a']) - - self.assertIn(result1, result) - self.assertIn(result2, result) - self.library1.search.assert_called_once_with( - query=dict(any=['a']), uris=None, exact=True) - self.library2.search.assert_called_once_with( - query=dict(any=['a']), uris=None, exact=True) - - def test_find_exact_with_uris_selects_dummy1_backend(self): - self.core.library.find_exact( - any=['a'], uris=['dummy1:', 'dummy1:foo', 'dummy3:']) - - self.library1.search.assert_called_once_with( - query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'], exact=True) - self.assertFalse(self.library2.search.called) - - def test_find_exact_with_uris_selects_both_backends(self): - self.core.library.find_exact( - any=['a'], uris=['dummy1:', 'dummy1:foo', 'dummy2:']) - - self.library1.search.assert_called_once_with( - query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'], exact=True) - self.library2.search.assert_called_once_with( - query=dict(any=['a']), uris=['dummy2:'], exact=True) - - def test_find_exact_filters_out_none(self): - track1 = Track(uri='dummy1:a') - result1 = SearchResult(tracks=[track1]) - - self.library1.search.return_value.get.return_value = result1 - self.library2.search.return_value.get.return_value = None - - result = self.core.library.find_exact(any=['a']) - - self.assertIn(result1, result) - self.assertNotIn(None, result) - self.library1.search.assert_called_once_with( - query=dict(any=['a']), uris=None, exact=True) - self.library2.search.assert_called_once_with( - query=dict(any=['a']), uris=None, exact=True) - - def test_find_accepts_query_dict_instead_of_kwargs(self): - track1 = Track(uri='dummy1:a') - track2 = Track(uri='dummy2:a') - result1 = SearchResult(tracks=[track1]) - result2 = SearchResult(tracks=[track2]) - - self.library1.search.return_value.get.return_value = result1 - self.library2.search.return_value.get.return_value = result2 - - result = self.core.library.find_exact(dict(any=['a'])) - - self.assertIn(result1, result) - self.assertIn(result2, result) - self.library1.search.assert_called_once_with( - query=dict(any=['a']), uris=None, exact=True) - self.library2.search.assert_called_once_with( - query=dict(any=['a']), uris=None, exact=True) - def test_search_combines_results_from_all_backends(self): track1 = Track(uri='dummy1:a') track2 = Track(uri='dummy2:a') @@ -355,8 +287,90 @@ class CoreLibraryTest(unittest.TestCase): self.library1.search.assert_called_once_with( query={'any': ['foobar']}, uris=None, exact=False) + +class DeprecatedCoreLibraryTest(CoreLibraryTest): + def setUp(self): # noqa: N802 + super(DeprecatedCoreLibraryTest, self).setUp() + self._warnings_filters = warnings.filters + warnings.filters = warnings.filters[:] + warnings.filterwarnings('ignore', '.*library.find_exact.*') + + def tearDown(self): # noqa: N802 + super(DeprecatedCoreLibraryTest, self).tearDown() + warnings.filters = self._warnings_filters + + def test_find_exact_combines_results_from_all_backends(self): + track1 = Track(uri='dummy1:a') + track2 = Track(uri='dummy2:a') + result1 = SearchResult(tracks=[track1]) + result2 = SearchResult(tracks=[track2]) + + self.library1.search.return_value.get.return_value = result1 + self.library2.search.return_value.get.return_value = result2 + + result = self.core.library.find_exact(any=['a']) + + self.assertIn(result1, result) + self.assertIn(result2, result) + self.library1.search.assert_called_once_with( + query=dict(any=['a']), uris=None, exact=True) + self.library2.search.assert_called_once_with( + query=dict(any=['a']), uris=None, exact=True) + + def test_find_exact_with_uris_selects_dummy1_backend(self): + self.core.library.find_exact( + any=['a'], uris=['dummy1:', 'dummy1:foo', 'dummy3:']) + + self.library1.search.assert_called_once_with( + query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'], exact=True) + self.assertFalse(self.library2.search.called) + + def test_find_exact_with_uris_selects_both_backends(self): + self.core.library.find_exact( + any=['a'], uris=['dummy1:', 'dummy1:foo', 'dummy2:']) + + self.library1.search.assert_called_once_with( + query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'], exact=True) + self.library2.search.assert_called_once_with( + query=dict(any=['a']), uris=['dummy2:'], exact=True) + + def test_find_exact_filters_out_none(self): + track1 = Track(uri='dummy1:a') + result1 = SearchResult(tracks=[track1]) + + self.library1.search.return_value.get.return_value = result1 + self.library2.search.return_value.get.return_value = None + + result = self.core.library.find_exact(any=['a']) + + self.assertIn(result1, result) + self.assertNotIn(None, result) + self.library1.search.assert_called_once_with( + query=dict(any=['a']), uris=None, exact=True) + self.library2.search.assert_called_once_with( + query=dict(any=['a']), uris=None, exact=True) + + def test_find_accepts_query_dict_instead_of_kwargs(self): + track1 = Track(uri='dummy1:a') + track2 = Track(uri='dummy2:a') + result1 = SearchResult(tracks=[track1]) + result2 = SearchResult(tracks=[track2]) + + self.library1.search.return_value.get.return_value = result1 + self.library2.search.return_value.get.return_value = result2 + + result = self.core.library.find_exact(dict(any=['a'])) + + self.assertIn(result1, result) + self.assertIn(result2, result) + self.library1.search.assert_called_once_with( + query=dict(any=['a']), uris=None, exact=True) + self.library2.search.assert_called_once_with( + query=dict(any=['a']), uris=None, exact=True) + def test_find_exact_normalises_bad_queries(self): self.core.library.find_exact({'any': 'foobar'}) + self.library1.search.assert_called_once_with( query={'any': ['foobar']}, uris=None, exact=True) @@ -369,8 +383,18 @@ class LegacyFindExactToSearchLibraryTest(unittest.TestCase): self.backend.library = mock.Mock(spec=backend.LibraryProvider) self.core = core.Core(mixer=None, backends=[self.backend]) + self._warnings_filters = warnings.filters + warnings.filters = warnings.filters[:] + warnings.filterwarnings('ignore', '.*library.find_exact.*') + + def tearDown(self): # noqa: N802 + warnings.filters = self._warnings_filters + def test_core_find_exact_calls_backend_search_with_exact(self): - self.core.library.find_exact(query={'any': ['a']}) + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + self.core.library.find_exact(query={'any': ['a']}) + self.backend.library.search.assert_called_once_with( query=dict(any=['a']), uris=None, exact=True) diff --git a/tests/local/test_library.py b/tests/local/test_library.py index 39f0e53e..7ab67fa6 100644 --- a/tests/local/test_library.py +++ b/tests/local/test_library.py @@ -84,6 +84,10 @@ class LocalLibraryProviderTest(unittest.TestCase): pykka.ActorRegistry.stop_all() actor.LocalBackend.libraries = [] + def find_exact(self, **query): + # TODO: remove this helper? + return self.library.search(query=query, exact=True) + def test_refresh(self): self.library.refresh() @@ -149,228 +153,228 @@ class LocalLibraryProviderTest(unittest.TestCase): # TODO: move to search_test module def test_find_exact_no_hits(self): - result = self.library.find_exact(track_name=['unknown track']) + result = self.find_exact(track_name=['unknown track']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(artist=['unknown artist']) + result = self.find_exact(artist=['unknown artist']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(albumartist=['unknown albumartist']) + result = self.find_exact(albumartist=['unknown albumartist']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(composer=['unknown composer']) + result = self.find_exact(composer=['unknown composer']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(performer=['unknown performer']) + result = self.find_exact(performer=['unknown performer']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(album=['unknown album']) + result = self.find_exact(album=['unknown album']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(date=['1990']) + result = self.find_exact(date=['1990']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(genre=['unknown genre']) + result = self.find_exact(genre=['unknown genre']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(track_no=['9']) + result = self.find_exact(track_no=['9']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(track_no=['no_match']) + result = self.find_exact(track_no=['no_match']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(comment=['fake comment']) + result = self.find_exact(comment=['fake comment']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(uri=['fake uri']) + result = self.find_exact(uri=['fake uri']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(any=['unknown any']) + result = self.find_exact(any=['unknown any']) self.assertEqual(list(result[0].tracks), []) def test_find_exact_uri(self): track_1_uri = 'local:track:path1' - result = self.library.find_exact(uri=track_1_uri) + result = self.find_exact(uri=track_1_uri) self.assertEqual(list(result[0].tracks), self.tracks[:1]) track_2_uri = 'local:track:path2' - result = self.library.find_exact(uri=track_2_uri) + result = self.find_exact(uri=track_2_uri) self.assertEqual(list(result[0].tracks), self.tracks[1:2]) def test_find_exact_track_name(self): - result = self.library.find_exact(track_name=['track1']) + result = self.find_exact(track_name=['track1']) self.assertEqual(list(result[0].tracks), self.tracks[:1]) - result = self.library.find_exact(track_name=['track2']) + result = self.find_exact(track_name=['track2']) self.assertEqual(list(result[0].tracks), self.tracks[1:2]) def test_find_exact_artist(self): - result = self.library.find_exact(artist=['artist1']) + result = self.find_exact(artist=['artist1']) self.assertEqual(list(result[0].tracks), self.tracks[:1]) - result = self.library.find_exact(artist=['artist2']) + result = self.find_exact(artist=['artist2']) self.assertEqual(list(result[0].tracks), self.tracks[1:2]) - result = self.library.find_exact(artist=['artist3']) + result = self.find_exact(artist=['artist3']) self.assertEqual(list(result[0].tracks), self.tracks[3:4]) def test_find_exact_composer(self): - result = self.library.find_exact(composer=['artist5']) + result = self.find_exact(composer=['artist5']) self.assertEqual(list(result[0].tracks), self.tracks[4:5]) - result = self.library.find_exact(composer=['artist6']) + result = self.find_exact(composer=['artist6']) self.assertEqual(list(result[0].tracks), []) def test_find_exact_performer(self): - result = self.library.find_exact(performer=['artist6']) + result = self.find_exact(performer=['artist6']) self.assertEqual(list(result[0].tracks), self.tracks[5:6]) - result = self.library.find_exact(performer=['artist5']) + result = self.find_exact(performer=['artist5']) self.assertEqual(list(result[0].tracks), []) def test_find_exact_album(self): - result = self.library.find_exact(album=['album1']) + result = self.find_exact(album=['album1']) self.assertEqual(list(result[0].tracks), self.tracks[:1]) - result = self.library.find_exact(album=['album2']) + result = self.find_exact(album=['album2']) self.assertEqual(list(result[0].tracks), self.tracks[1:2]) def test_find_exact_albumartist(self): # Artist is both track artist and album artist - result = self.library.find_exact(albumartist=['artist1']) + result = self.find_exact(albumartist=['artist1']) self.assertEqual(list(result[0].tracks), [self.tracks[0]]) # Artist is both track and album artist - result = self.library.find_exact(albumartist=['artist2']) + result = self.find_exact(albumartist=['artist2']) self.assertEqual(list(result[0].tracks), [self.tracks[1]]) # Artist is just album artist - result = self.library.find_exact(albumartist=['artist3']) + result = self.find_exact(albumartist=['artist3']) self.assertEqual(list(result[0].tracks), [self.tracks[2]]) def test_find_exact_track_no(self): - result = self.library.find_exact(track_no=['1']) + result = self.find_exact(track_no=['1']) self.assertEqual(list(result[0].tracks), self.tracks[:1]) - result = self.library.find_exact(track_no=['2']) + result = self.find_exact(track_no=['2']) self.assertEqual(list(result[0].tracks), self.tracks[1:2]) def test_find_exact_genre(self): - result = self.library.find_exact(genre=['genre1']) + result = self.find_exact(genre=['genre1']) self.assertEqual(list(result[0].tracks), self.tracks[4:5]) - result = self.library.find_exact(genre=['genre2']) + result = self.find_exact(genre=['genre2']) self.assertEqual(list(result[0].tracks), self.tracks[5:6]) def test_find_exact_date(self): - result = self.library.find_exact(date=['2001']) + result = self.find_exact(date=['2001']) self.assertEqual(list(result[0].tracks), []) - result = self.library.find_exact(date=['2001-02-03']) + result = self.find_exact(date=['2001-02-03']) self.assertEqual(list(result[0].tracks), self.tracks[:1]) - result = self.library.find_exact(date=['2002']) + result = self.find_exact(date=['2002']) self.assertEqual(list(result[0].tracks), self.tracks[1:2]) def test_find_exact_comment(self): - result = self.library.find_exact( + result = self.find_exact( comment=['This is a fantastic track']) self.assertEqual(list(result[0].tracks), self.tracks[3:4]) - result = self.library.find_exact( + result = self.find_exact( comment=['This is a fantastic']) self.assertEqual(list(result[0].tracks), []) def test_find_exact_any(self): # Matches on track artist - result = self.library.find_exact(any=['artist1']) + result = self.find_exact(any=['artist1']) self.assertEqual(list(result[0].tracks), self.tracks[:1]) - result = self.library.find_exact(any=['artist2']) + result = self.find_exact(any=['artist2']) self.assertEqual(list(result[0].tracks), self.tracks[1:2]) # Matches on track name - result = self.library.find_exact(any=['track1']) + result = self.find_exact(any=['track1']) self.assertEqual(list(result[0].tracks), self.tracks[:1]) - result = self.library.find_exact(any=['track2']) + result = self.find_exact(any=['track2']) self.assertEqual(list(result[0].tracks), self.tracks[1:2]) # Matches on track album - result = self.library.find_exact(any=['album1']) + result = self.find_exact(any=['album1']) self.assertEqual(list(result[0].tracks), self.tracks[:1]) # Matches on track album artists - result = self.library.find_exact(any=['artist3']) + result = self.find_exact(any=['artist3']) self.assertEqual(len(result[0].tracks), 2) self.assertIn(self.tracks[2], result[0].tracks) self.assertIn(self.tracks[3], result[0].tracks) # Matches on track composer - result = self.library.find_exact(any=['artist5']) + result = self.find_exact(any=['artist5']) self.assertEqual(list(result[0].tracks), self.tracks[4:5]) # Matches on track performer - result = self.library.find_exact(any=['artist6']) + result = self.find_exact(any=['artist6']) self.assertEqual(list(result[0].tracks), self.tracks[5:6]) # Matches on track genre - result = self.library.find_exact(any=['genre1']) + result = self.find_exact(any=['genre1']) self.assertEqual(list(result[0].tracks), self.tracks[4:5]) - result = self.library.find_exact(any=['genre2']) + result = self.find_exact(any=['genre2']) self.assertEqual(list(result[0].tracks), self.tracks[5:6]) # Matches on track date - result = self.library.find_exact(any=['2002']) + result = self.find_exact(any=['2002']) self.assertEqual(list(result[0].tracks), self.tracks[1:2]) # Matches on track comment - result = self.library.find_exact( + result = self.find_exact( any=['This is a fantastic track']) self.assertEqual(list(result[0].tracks), self.tracks[3:4]) # Matches on URI - result = self.library.find_exact(any=['local:track:path1']) + result = self.find_exact(any=['local:track:path1']) self.assertEqual(list(result[0].tracks), self.tracks[:1]) def test_find_exact_wrong_type(self): with self.assertRaises(LookupError): - self.library.find_exact(wrong=['test']) + self.find_exact(wrong=['test']) def test_find_exact_with_empty_query(self): with self.assertRaises(LookupError): - self.library.find_exact(artist=['']) + self.find_exact(artist=['']) with self.assertRaises(LookupError): - self.library.find_exact(albumartist=['']) + self.find_exact(albumartist=['']) with self.assertRaises(LookupError): - self.library.find_exact(track_name=['']) + self.find_exact(track_name=['']) with self.assertRaises(LookupError): - self.library.find_exact(composer=['']) + self.find_exact(composer=['']) with self.assertRaises(LookupError): - self.library.find_exact(performer=['']) + self.find_exact(performer=['']) with self.assertRaises(LookupError): - self.library.find_exact(album=['']) + self.find_exact(album=['']) with self.assertRaises(LookupError): - self.library.find_exact(track_no=['']) + self.find_exact(track_no=['']) with self.assertRaises(LookupError): - self.library.find_exact(genre=['']) + self.find_exact(genre=['']) with self.assertRaises(LookupError): - self.library.find_exact(date=['']) + self.find_exact(date=['']) with self.assertRaises(LookupError): - self.library.find_exact(comment=['']) + self.find_exact(comment=['']) with self.assertRaises(LookupError): - self.library.find_exact(any=['']) + self.find_exact(any=['']) def test_search_no_hits(self): result = self.library.search(track_name=['unknown track'])