From 8044f3e7e20f9628ee86f795e9126a350ddcffb1 Mon Sep 17 00:00:00 2001 From: Monsyne Dragon Date: Tue, 10 Feb 2015 19:29:07 +0000 Subject: [PATCH] Add mark/limit paging to find call. Adds Mark/limit to find_streams for api usage. The 'mark' is an opaque parameter (called '_mark') added into each item in the list of returned items (currently a mildly obscured ID for streams, that could be changed.) Returned items are sorted in descending order (by ID for streams), allowing paging from the 'top' to the bottom. By prefacing the 'mark' param with a '+', you can page in ascending order as well. This same paging scheme can be used for a future events api, as well. Change-Id: Ie358c0d1d8644dac24cad3992188ec22d66c5328 --- tests/test_db.py | 26 ++++++++++++++++++++++++++ winchester/db/interface.py | 29 ++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/tests/test_db.py b/tests/test_db.py index 78f5d70..161cfe7 100644 --- a/tests/test_db.py +++ b/tests/test_db.py @@ -449,3 +449,29 @@ class TestDB(unittest.TestCase): def test_find_stream_count(self): count = self.db.find_streams(count=True) self.assertEqual([{'count': 8}], count) + + def test_find_stream_limit(self): + streams = self.db.find_streams(limit=2) + self.assertEqual(len(streams), 2) + self.assertEqual(streams[0]['id'], 8) + self.assertEqual(streams[1]['id'], 7) + + def test_find_stream_limit_asc(self): + streams = self.db.find_streams(limit=2, mark='+') + self.assertEqual(len(streams), 2) + self.assertEqual(streams[0]['id'], 1) + self.assertEqual(streams[1]['id'], 2) + + def test_find_stream_mark(self): + streams = self.db.find_streams(mark='7') + for stream in streams: + self.assertIn('_mark', stream) + self.assertEqual(streams[0]['id'], 6) + self.assertEqual(streams[1]['id'], 5) + + def test_find_stream_mark_asc(self): + streams = self.db.find_streams(mark='+2') + for stream in streams: + self.assertIn('_mark', stream) + self.assertEqual(streams[0]['id'], 3) + self.assertEqual(streams[1]['id'], 4) diff --git a/winchester/db/interface.py b/winchester/db/interface.py index b94e21b..ab4c165 100644 --- a/winchester/db/interface.py +++ b/winchester/db/interface.py @@ -238,8 +238,24 @@ class DBInterface(object): def find_streams(self, count=False, stream_id=None, state=None, older_than=None, younger_than=None, name=None, distinguishing_traits=None, - session=None, include_events=False): + session=None, include_events=False, + limit=None, mark=None): + + order_desc = True + q = session.query(models.Stream) + if mark is not None: + if mark.startswith('+'): + order_desc=False + mark = mark[1:] + if mark.startswith('-'): + order_desc=True + mark = mark[1:] + if mark: + if order_desc: + q = q.filter(models.Stream.id < int(mark, 16)) + else: + q = q.filter(models.Stream.id > int(mark, 16)) if stream_id is not None: q = q.filter(models.Stream.id == stream_id) if state is not None: @@ -260,9 +276,20 @@ class DBInterface(object): q = q.count() return [{"count": q}] + if order_desc: + q = q.order_by(models.Stream.id.desc()) + mark_fmt = '%x' + else: + q = q.order_by(models.Stream.id.asc()) + mark_fmt = '+%x' + + if limit is not None: + q = q.limit(limit) + stream_info = [] for stream in q.all(): info = stream.as_dict + info['_mark'] = mark_fmt % stream.id if include_events: info['events'] = self.get_stream_events(stream, session=session) stream_info.append(info)