diff --git a/mopidy/local/json.py b/mopidy/local/json.py index aa16a6df..e27015f2 100644 --- a/mopidy/local/json.py +++ b/mopidy/local/json.py @@ -189,11 +189,12 @@ class JsonLibrary(local.Library): def search(self, query=None, limit=100, offset=0, uris=None, exact=False): tracks = self._tracks.values() - # TODO: pass limit and offset into search helpers if exact: - return search.find_exact(tracks, query=query, uris=uris) + return search.find_exact( + tracks, query=query, limit=limit, offset=offset, uris=uris) else: - return search.search(tracks, query=query, uris=uris) + return search.search( + tracks, query=query, limit=limit, offset=offset, uris=uris) def begin(self): return compat.itervalues(self._tracks) diff --git a/mopidy/local/search.py b/mopidy/local/search.py index e63d0f8d..1f82366f 100644 --- a/mopidy/local/search.py +++ b/mopidy/local/search.py @@ -3,7 +3,18 @@ from __future__ import absolute_import, unicode_literals from mopidy.models import SearchResult -def find_exact(tracks, query=None, uris=None): +def find_exact(tracks, query=None, limit=100, offset=0, uris=None): + """ + Filter a list of tracks where ``field`` is ``values``. + + :param list tracks: a list of :class:`~mopidy.models.Track` + :param dict query: one or more field/value pairs to search for + :param int limit: maximum number of results to return + :param int offset: offset into result set to use. + :param uris: zero or more URI roots to limit the search to + :type uris: list of strings or :class:`None` + :rtype: :class:`~mopidy.models.SearchResult` + """ # TODO Only return results within URI roots given by ``uris`` if query is None: @@ -96,10 +107,22 @@ def find_exact(tracks, query=None, uris=None): raise LookupError('Invalid lookup field: %s' % field) # TODO: add local:search: - return SearchResult(uri='local:search', tracks=tracks) + return SearchResult( + uri='local:search', tracks=tracks[offset:offset + limit]) -def search(tracks, query=None, uris=None): +def search(tracks, query=None, limit=100, offset=0, uris=None): + """ + Filter a list of tracks where ``field`` is like ``values``. + + :param list tracks: a list of :class:`~mopidy.models.Track` + :param dict query: one or more field/value pairs to search for + :param int limit: maximum number of results to return + :param int offset: offset into result set to use. + :param uris: zero or more URI roots to limit the search to + :type uris: list of strings or :class:`None` + :rtype: :class:`~mopidy.models.SearchResult` + """ # TODO Only return results within URI roots given by ``uris`` if query is None: @@ -195,7 +218,8 @@ def search(tracks, query=None, uris=None): else: raise LookupError('Invalid lookup field: %s' % field) # TODO: add local:search: - return SearchResult(uri='local:search', tracks=tracks) + return SearchResult(uri='local:search', + tracks=tracks[offset:offset + limit]) def _validate_query(query): diff --git a/tests/local/test_json.py b/tests/local/test_json.py index 0d62c2e3..6d57c4d0 100644 --- a/tests/local/test_json.py +++ b/tests/local/test_json.py @@ -1,9 +1,13 @@ from __future__ import absolute_import, unicode_literals + import unittest from mopidy.local import json -from mopidy.models import Ref +from mopidy.models import Ref, Track + + +from tests import path_to_data_dir class BrowseCacheTest(unittest.TestCase): @@ -38,3 +42,52 @@ class BrowseCacheTest(unittest.TestCase): def test_lookup_foo_baz(self): result = self.cache.lookup('local:directory:foo/unknown') self.assertEqual([], result) + + +class JsonLibraryTest(unittest.TestCase): + + config = { + 'local': { + 'media_dir': path_to_data_dir(''), + 'data_dir': path_to_data_dir(''), + 'playlists_dir': b'', + 'library': 'json', + }, + } + + def setUp(self): # noqa: N802 + self.library = json.JsonLibrary(self.config) + + def _create_tracks(self, count): + for i in range(count): + self.library.add(Track(uri='local:track:%d' % i)) + + def test_search_should_default_limit_results(self): + self._create_tracks(101) + + result = self.library.search() + result_exact = self.library.search(exact=True) + + self.assertEqual(len(result.tracks), 100) + self.assertEqual(len(result_exact.tracks), 100) + + def test_search_should_limit_results(self): + self._create_tracks(100) + + result = self.library.search(limit=35) + result_exact = self.library.search(exact=True, limit=35) + + self.assertEqual(len(result.tracks), 35) + self.assertEqual(len(result_exact.tracks), 35) + + def test_search_should_offset_results(self): + self._create_tracks(200) + + expected = self.library.search(limit=110).tracks[10:] + expected_exact = self.library.search(exact=True, limit=110).tracks[10:] + + result = self.library.search(offset=10).tracks + result_exact = self.library.search(offset=10, exact=True).tracks + + self.assertEqual(expected, result) + self.assertEqual(expected_exact, result_exact)