core/backend: Remove find_exact from backends
Functionality has been replaced with an `exact` param in the search method. Backends that still implement find_exact will continue being called via the old method for now.
This commit is contained in:
parent
636d8f1115
commit
24fe242d56
@ -138,6 +138,11 @@ v1.0.0 (UNRELEASED)
|
||||
|
||||
- Remove :attr:`mopidy.backend.PlaylistsProvider.playlists` property.
|
||||
|
||||
- Removed ``find_exact`` from :class:`mopidy.backend.LibraryProvider` and
|
||||
added an ``exact`` param to :meth:`mopidy.backend.LibraryProvider.search`
|
||||
to replace the old code path. Core will continue supporting backends that
|
||||
have not upgraded for now.
|
||||
|
||||
**Commands**
|
||||
|
||||
- Make the ``mopidy`` command print a friendly error message if the
|
||||
|
||||
@ -119,15 +119,6 @@ class LibraryProvider(object):
|
||||
result[uri] = [models.Image(uri=u) for u in image_uris]
|
||||
return result
|
||||
|
||||
# TODO: replace with search(query, exact=True, ...)
|
||||
def find_exact(self, query=None, uris=None):
|
||||
"""
|
||||
See :meth:`mopidy.core.LibraryController.find_exact`.
|
||||
|
||||
*MAY be implemented by subclass.*
|
||||
"""
|
||||
pass
|
||||
|
||||
def lookup(self, uri):
|
||||
"""
|
||||
See :meth:`mopidy.core.LibraryController.lookup`.
|
||||
@ -144,11 +135,14 @@ class LibraryProvider(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
def search(self, query=None, uris=None):
|
||||
def search(self, query=None, uris=None, exact=False):
|
||||
"""
|
||||
See :meth:`mopidy.core.LibraryController.search`.
|
||||
|
||||
*MAY be implemented by subclass.*
|
||||
|
||||
.. versionadded:: 1.0
|
||||
The ``exact`` param which replaces the old ``find_exact``.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@ -160,6 +160,12 @@ class LibraryController(object):
|
||||
{'any': ['a']}, uris=['file:///media/music', 'spotify:'])
|
||||
find_exact(any=['a'], uris=['file:///media/music', 'spotify:'])
|
||||
|
||||
.. versionchanged:: 1.0
|
||||
This method now calls
|
||||
:meth:`~mopidy.backend.LibraryProvider.search` on the backends
|
||||
instead of the deprecated ``find_exact``. If the backend still
|
||||
implements ``find_exact`` we will continue to use it for now.
|
||||
|
||||
:param query: one or more queries to search for
|
||||
:type query: dict
|
||||
:param uris: zero or more URI roots to limit the search to
|
||||
@ -167,10 +173,15 @@ class LibraryController(object):
|
||||
:rtype: list of :class:`mopidy.models.SearchResult`
|
||||
"""
|
||||
query = _normalize_query(query or kwargs)
|
||||
futures = [
|
||||
backend.library.find_exact(query=query, uris=backend_uris)
|
||||
for (backend, backend_uris)
|
||||
in self._get_backends_to_uris(uris).items()]
|
||||
futures = []
|
||||
for backend, backend_uris in self._get_backends_to_uris(uris).items():
|
||||
if hasattr(backend.library, 'find_exact'):
|
||||
futures.append(backend.library.find_exact(
|
||||
query=query, uris=backend_uris))
|
||||
else:
|
||||
futures.append(backend.library.search(
|
||||
query=query, uris=backend_uris, exact=True))
|
||||
|
||||
return [result for result in pykka.get_all(futures) if result]
|
||||
|
||||
def lookup(self, uri=None, uris=None):
|
||||
|
||||
@ -212,54 +212,50 @@ class CoreLibraryTest(unittest.TestCase):
|
||||
result1 = SearchResult(tracks=[track1])
|
||||
result2 = SearchResult(tracks=[track2])
|
||||
|
||||
self.library1.find_exact().get.return_value = result1
|
||||
self.library1.find_exact.reset_mock()
|
||||
self.library2.find_exact().get.return_value = result2
|
||||
self.library2.find_exact.reset_mock()
|
||||
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.find_exact.assert_called_once_with(
|
||||
query=dict(any=['a']), uris=None)
|
||||
self.library2.find_exact.assert_called_once_with(
|
||||
query=dict(any=['a']), uris=None)
|
||||
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.find_exact.assert_called_once_with(
|
||||
query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'])
|
||||
self.assertFalse(self.library2.find_exact.called)
|
||||
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.find_exact.assert_called_once_with(
|
||||
query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'])
|
||||
self.library2.find_exact.assert_called_once_with(
|
||||
query=dict(any=['a']), uris=['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.find_exact().get.return_value = result1
|
||||
self.library1.find_exact.reset_mock()
|
||||
self.library2.find_exact().get.return_value = None
|
||||
self.library2.find_exact.reset_mock()
|
||||
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.find_exact.assert_called_once_with(
|
||||
query=dict(any=['a']), uris=None)
|
||||
self.library2.find_exact.assert_called_once_with(
|
||||
query=dict(any=['a']), uris=None)
|
||||
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')
|
||||
@ -267,19 +263,17 @@ class CoreLibraryTest(unittest.TestCase):
|
||||
result1 = SearchResult(tracks=[track1])
|
||||
result2 = SearchResult(tracks=[track2])
|
||||
|
||||
self.library1.find_exact().get.return_value = result1
|
||||
self.library1.find_exact.reset_mock()
|
||||
self.library2.find_exact().get.return_value = result2
|
||||
self.library2.find_exact.reset_mock()
|
||||
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.find_exact.assert_called_once_with(
|
||||
query=dict(any=['a']), uris=None)
|
||||
self.library2.find_exact.assert_called_once_with(
|
||||
query=dict(any=['a']), uris=None)
|
||||
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')
|
||||
@ -363,5 +357,29 @@ class CoreLibraryTest(unittest.TestCase):
|
||||
|
||||
def test_find_exact_normalises_bad_queries(self):
|
||||
self.core.library.find_exact({'any': 'foobar'})
|
||||
self.library1.find_exact.assert_called_once_with(
|
||||
query={'any': ['foobar']}, uris=None)
|
||||
self.library1.search.assert_called_once_with(
|
||||
query={'any': ['foobar']}, uris=None, exact=True)
|
||||
|
||||
|
||||
class LegacyLibraryProvider(backend.LibraryProvider):
|
||||
def find_exact(self, query=None, uris=None):
|
||||
pass
|
||||
|
||||
|
||||
class LegacyCoreLibraryTest(unittest.TestCase):
|
||||
def test_backend_with_find_exact_still_works(self):
|
||||
b1 = mock.Mock()
|
||||
b1.uri_schemes.get.return_value = ['dummy1']
|
||||
b1.library = mock.Mock(spec=LegacyLibraryProvider)
|
||||
|
||||
b2 = mock.Mock()
|
||||
b2.uri_schemes.get.return_value = ['dummy2']
|
||||
b2.library = mock.Mock(spec=backend.LibraryProvider)
|
||||
|
||||
c = core.Core(mixer=None, backends=[b1, b2])
|
||||
c.library.find_exact(query={'any': ['a']})
|
||||
|
||||
b1.library.find_exact.assert_called_once_with(
|
||||
query=dict(any=['a']), uris=None)
|
||||
b2.library.search.assert_called_once_with(
|
||||
query=dict(any=['a']), uris=None, exact=True)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user