From fc21d466f0455d441a3540a89508a26a47a9b6ad Mon Sep 17 00:00:00 2001 From: Ali Ukani Date: Mon, 26 Jan 2015 16:16:46 -0500 Subject: [PATCH 1/2] local: use limit and offset when searching json library Fixes the json local library's search behavior. Uses limit and offset arguments when returning search results. --- mopidy/local/json.py | 7 ++--- mopidy/local/search.py | 31 +++++++++++++++++++--- tests/local/test_json.py | 55 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 8 deletions(-) diff --git a/mopidy/local/json.py b/mopidy/local/json.py index 38e1bf6c..f6ff879b 100644 --- a/mopidy/local/json.py +++ b/mopidy/local/json.py @@ -157,11 +157,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..9e56d73b 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 queries 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 queries 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,7 @@ 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..545833d5 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 xrange(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) From ead147f482995baeac8349871c916c9df6d34840 Mon Sep 17 00:00:00 2001 From: Ali Ukani Date: Mon, 16 Feb 2015 00:47:48 -0500 Subject: [PATCH 2/2] Fix flake8 errors, prepare for Python 3 port Fixes flake8 warnings Reword docstring for find_exact Use range instead of xrange in preparation for porting to Python 3 --- mopidy/local/search.py | 9 +++++---- tests/local/test_json.py | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mopidy/local/search.py b/mopidy/local/search.py index 9e56d73b..1f82366f 100644 --- a/mopidy/local/search.py +++ b/mopidy/local/search.py @@ -8,7 +8,7 @@ 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 queries to search for + :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 @@ -108,7 +108,7 @@ def find_exact(tracks, query=None, limit=100, offset=0, uris=None): # TODO: add local:search: return SearchResult( - uri='local:search', tracks=tracks[offset:offset+limit]) + uri='local:search', tracks=tracks[offset:offset + limit]) def search(tracks, query=None, limit=100, offset=0, uris=None): @@ -116,7 +116,7 @@ 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 queries to search for + :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 @@ -218,7 +218,8 @@ def search(tracks, query=None, limit=100, offset=0, uris=None): else: raise LookupError('Invalid lookup field: %s' % field) # TODO: add local:search: - return SearchResult(uri='local:search', tracks=tracks[offset:offset+limit]) + 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 545833d5..6d57c4d0 100644 --- a/tests/local/test_json.py +++ b/tests/local/test_json.py @@ -59,7 +59,7 @@ class JsonLibraryTest(unittest.TestCase): self.library = json.JsonLibrary(self.config) def _create_tracks(self, count): - for i in xrange(count): + for i in range(count): self.library.add(Track(uri='local:track:%d' % i)) def test_search_should_default_limit_results(self):