Merge pull request #1077 from adamcik/feature/deprecate-find_exact-in-backends
core/backend: Remove find_exact from backends
This commit is contained in:
commit
b5c07ca803
@ -138,6 +138,11 @@ v1.0.0 (UNRELEASED)
|
|||||||
|
|
||||||
- Remove :attr:`mopidy.backend.PlaylistsProvider.playlists` property.
|
- 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**
|
**Commands**
|
||||||
|
|
||||||
- Make the ``mopidy`` command print a friendly error message if the
|
- 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]
|
result[uri] = [models.Image(uri=u) for u in image_uris]
|
||||||
return result
|
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):
|
def lookup(self, uri):
|
||||||
"""
|
"""
|
||||||
See :meth:`mopidy.core.LibraryController.lookup`.
|
See :meth:`mopidy.core.LibraryController.lookup`.
|
||||||
@ -144,11 +135,14 @@ class LibraryProvider(object):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def search(self, query=None, uris=None):
|
def search(self, query=None, uris=None, exact=False):
|
||||||
"""
|
"""
|
||||||
See :meth:`mopidy.core.LibraryController.search`.
|
See :meth:`mopidy.core.LibraryController.search`.
|
||||||
|
|
||||||
*MAY be implemented by subclass.*
|
*MAY be implemented by subclass.*
|
||||||
|
|
||||||
|
.. versionadded:: 1.0
|
||||||
|
The ``exact`` param which replaces the old ``find_exact``.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@ -160,6 +160,12 @@ class LibraryController(object):
|
|||||||
{'any': ['a']}, uris=['file:///media/music', 'spotify:'])
|
{'any': ['a']}, uris=['file:///media/music', 'spotify:'])
|
||||||
find_exact(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
|
:param query: one or more queries to search for
|
||||||
:type query: dict
|
:type query: dict
|
||||||
:param uris: zero or more URI roots to limit the search to
|
: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`
|
:rtype: list of :class:`mopidy.models.SearchResult`
|
||||||
"""
|
"""
|
||||||
query = _normalize_query(query or kwargs)
|
query = _normalize_query(query or kwargs)
|
||||||
futures = [
|
futures = []
|
||||||
backend.library.find_exact(query=query, uris=backend_uris)
|
for backend, backend_uris in self._get_backends_to_uris(uris).items():
|
||||||
for (backend, backend_uris)
|
if hasattr(backend.library, 'find_exact'):
|
||||||
in self._get_backends_to_uris(uris).items()]
|
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]
|
return [result for result in pykka.get_all(futures) if result]
|
||||||
|
|
||||||
def lookup(self, uri=None, uris=None):
|
def lookup(self, uri=None, uris=None):
|
||||||
|
|||||||
@ -212,54 +212,50 @@ class CoreLibraryTest(unittest.TestCase):
|
|||||||
result1 = SearchResult(tracks=[track1])
|
result1 = SearchResult(tracks=[track1])
|
||||||
result2 = SearchResult(tracks=[track2])
|
result2 = SearchResult(tracks=[track2])
|
||||||
|
|
||||||
self.library1.find_exact().get.return_value = result1
|
self.library1.search.return_value.get.return_value = result1
|
||||||
self.library1.find_exact.reset_mock()
|
self.library2.search.return_value.get.return_value = result2
|
||||||
self.library2.find_exact().get.return_value = result2
|
|
||||||
self.library2.find_exact.reset_mock()
|
|
||||||
|
|
||||||
result = self.core.library.find_exact(any=['a'])
|
result = self.core.library.find_exact(any=['a'])
|
||||||
|
|
||||||
self.assertIn(result1, result)
|
self.assertIn(result1, result)
|
||||||
self.assertIn(result2, result)
|
self.assertIn(result2, result)
|
||||||
self.library1.find_exact.assert_called_once_with(
|
self.library1.search.assert_called_once_with(
|
||||||
query=dict(any=['a']), uris=None)
|
query=dict(any=['a']), uris=None, exact=True)
|
||||||
self.library2.find_exact.assert_called_once_with(
|
self.library2.search.assert_called_once_with(
|
||||||
query=dict(any=['a']), uris=None)
|
query=dict(any=['a']), uris=None, exact=True)
|
||||||
|
|
||||||
def test_find_exact_with_uris_selects_dummy1_backend(self):
|
def test_find_exact_with_uris_selects_dummy1_backend(self):
|
||||||
self.core.library.find_exact(
|
self.core.library.find_exact(
|
||||||
any=['a'], uris=['dummy1:', 'dummy1:foo', 'dummy3:'])
|
any=['a'], uris=['dummy1:', 'dummy1:foo', 'dummy3:'])
|
||||||
|
|
||||||
self.library1.find_exact.assert_called_once_with(
|
self.library1.search.assert_called_once_with(
|
||||||
query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'])
|
query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'], exact=True)
|
||||||
self.assertFalse(self.library2.find_exact.called)
|
self.assertFalse(self.library2.search.called)
|
||||||
|
|
||||||
def test_find_exact_with_uris_selects_both_backends(self):
|
def test_find_exact_with_uris_selects_both_backends(self):
|
||||||
self.core.library.find_exact(
|
self.core.library.find_exact(
|
||||||
any=['a'], uris=['dummy1:', 'dummy1:foo', 'dummy2:'])
|
any=['a'], uris=['dummy1:', 'dummy1:foo', 'dummy2:'])
|
||||||
|
|
||||||
self.library1.find_exact.assert_called_once_with(
|
self.library1.search.assert_called_once_with(
|
||||||
query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'])
|
query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'], exact=True)
|
||||||
self.library2.find_exact.assert_called_once_with(
|
self.library2.search.assert_called_once_with(
|
||||||
query=dict(any=['a']), uris=['dummy2:'])
|
query=dict(any=['a']), uris=['dummy2:'], exact=True)
|
||||||
|
|
||||||
def test_find_exact_filters_out_none(self):
|
def test_find_exact_filters_out_none(self):
|
||||||
track1 = Track(uri='dummy1:a')
|
track1 = Track(uri='dummy1:a')
|
||||||
result1 = SearchResult(tracks=[track1])
|
result1 = SearchResult(tracks=[track1])
|
||||||
|
|
||||||
self.library1.find_exact().get.return_value = result1
|
self.library1.search.return_value.get.return_value = result1
|
||||||
self.library1.find_exact.reset_mock()
|
self.library2.search.return_value.get.return_value = None
|
||||||
self.library2.find_exact().get.return_value = None
|
|
||||||
self.library2.find_exact.reset_mock()
|
|
||||||
|
|
||||||
result = self.core.library.find_exact(any=['a'])
|
result = self.core.library.find_exact(any=['a'])
|
||||||
|
|
||||||
self.assertIn(result1, result)
|
self.assertIn(result1, result)
|
||||||
self.assertNotIn(None, result)
|
self.assertNotIn(None, result)
|
||||||
self.library1.find_exact.assert_called_once_with(
|
self.library1.search.assert_called_once_with(
|
||||||
query=dict(any=['a']), uris=None)
|
query=dict(any=['a']), uris=None, exact=True)
|
||||||
self.library2.find_exact.assert_called_once_with(
|
self.library2.search.assert_called_once_with(
|
||||||
query=dict(any=['a']), uris=None)
|
query=dict(any=['a']), uris=None, exact=True)
|
||||||
|
|
||||||
def test_find_accepts_query_dict_instead_of_kwargs(self):
|
def test_find_accepts_query_dict_instead_of_kwargs(self):
|
||||||
track1 = Track(uri='dummy1:a')
|
track1 = Track(uri='dummy1:a')
|
||||||
@ -267,19 +263,17 @@ class CoreLibraryTest(unittest.TestCase):
|
|||||||
result1 = SearchResult(tracks=[track1])
|
result1 = SearchResult(tracks=[track1])
|
||||||
result2 = SearchResult(tracks=[track2])
|
result2 = SearchResult(tracks=[track2])
|
||||||
|
|
||||||
self.library1.find_exact().get.return_value = result1
|
self.library1.search.return_value.get.return_value = result1
|
||||||
self.library1.find_exact.reset_mock()
|
self.library2.search.return_value.get.return_value = result2
|
||||||
self.library2.find_exact().get.return_value = result2
|
|
||||||
self.library2.find_exact.reset_mock()
|
|
||||||
|
|
||||||
result = self.core.library.find_exact(dict(any=['a']))
|
result = self.core.library.find_exact(dict(any=['a']))
|
||||||
|
|
||||||
self.assertIn(result1, result)
|
self.assertIn(result1, result)
|
||||||
self.assertIn(result2, result)
|
self.assertIn(result2, result)
|
||||||
self.library1.find_exact.assert_called_once_with(
|
self.library1.search.assert_called_once_with(
|
||||||
query=dict(any=['a']), uris=None)
|
query=dict(any=['a']), uris=None, exact=True)
|
||||||
self.library2.find_exact.assert_called_once_with(
|
self.library2.search.assert_called_once_with(
|
||||||
query=dict(any=['a']), uris=None)
|
query=dict(any=['a']), uris=None, exact=True)
|
||||||
|
|
||||||
def test_search_combines_results_from_all_backends(self):
|
def test_search_combines_results_from_all_backends(self):
|
||||||
track1 = Track(uri='dummy1:a')
|
track1 = Track(uri='dummy1:a')
|
||||||
@ -363,5 +357,29 @@ class CoreLibraryTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_find_exact_normalises_bad_queries(self):
|
def test_find_exact_normalises_bad_queries(self):
|
||||||
self.core.library.find_exact({'any': 'foobar'})
|
self.core.library.find_exact({'any': 'foobar'})
|
||||||
self.library1.find_exact.assert_called_once_with(
|
self.library1.search.assert_called_once_with(
|
||||||
query={'any': ['foobar']}, uris=None)
|
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