Commit edfde16c authored by Joshua Roesslein's avatar Joshua Roesslein
Browse files

Merge ID based cursors branch.

parents 02a43b7f 0106b117
import unittest
from tweepy.models import ResultSet
class NoIdItem(object): pass
class IdItem(object):
def __init__(self, id):
self.id = id
ids_fixture = [1, 10, 8, 50, 2, 100, 5]
class TweepyResultSetTests(unittest.TestCase):
def setUp(self):
self.results = ResultSet()
for i in ids_fixture:
self.results.append(IdItem(i))
self.results.append(NoIdItem())
def testids(self):
ids = self.results.ids()
self.assertListEqual(ids, ids_fixture)
def testmaxid(self):
self.assertEqual(self.results.max_id, 100)
def testsinceid(self):
self.assertEqual(self.results.since_id, 1)
......@@ -37,7 +37,7 @@ class API(object):
home_timeline = bind_api(
path = '/statuses/home_timeline.json',
payload_type = 'status', payload_list = True,
allowed_param = ['since_id', 'max_id', 'count', 'page'],
allowed_param = ['since_id', 'max_id', 'count'],
require_auth = True
)
......@@ -46,7 +46,7 @@ class API(object):
path = '/statuses/user_timeline.json',
payload_type = 'status', payload_list = True,
allowed_param = ['id', 'user_id', 'screen_name', 'since_id',
'max_id', 'count', 'page', 'include_rts']
'max_id', 'count', 'include_rts']
)
""" statuses/mentions """
......@@ -85,7 +85,7 @@ class API(object):
retweets_of_me = bind_api(
path = '/statuses/retweets_of_me.json',
payload_type = 'status', payload_list = True,
allowed_param = ['since_id', 'max_id', 'count', 'page'],
allowed_param = ['since_id', 'max_id', 'count'],
require_auth = True
)
......@@ -195,7 +195,7 @@ class API(object):
direct_messages = bind_api(
path = '/direct_messages.json',
payload_type = 'direct_message', payload_list = True,
allowed_param = ['since_id', 'max_id', 'count', 'page'],
allowed_param = ['since_id', 'max_id', 'count'],
require_auth = True
)
......@@ -282,7 +282,7 @@ class API(object):
friends = bind_api(
path = '/friends/list.json',
payload_type = 'user', payload_list = True,
allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
)
""" friendships/incoming """
......@@ -310,7 +310,7 @@ class API(object):
followers = bind_api(
path = '/followers/list.json',
payload_type = 'user', payload_list = True,
allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
)
""" account/verify_credentials """
......@@ -432,7 +432,7 @@ class API(object):
blocks = bind_api(
path = '/blocks/list.json',
payload_type = 'user', payload_list = True,
allowed_param = ['page'],
allowed_param = ['cursor'],
require_auth = True
)
......
......@@ -200,6 +200,9 @@ def bind_api(**config):
# Set pagination mode
if 'cursor' in APIMethod.allowed_param:
_call.pagination_mode = 'cursor'
elif 'max_id' in APIMethod.allowed_param and \
'since_id' in APIMethod.allowed_param:
_call.pagination_mode = 'id'
elif 'page' in APIMethod.allowed_param:
_call.pagination_mode = 'page'
......
......@@ -11,8 +11,12 @@ class Cursor(object):
if hasattr(method, 'pagination_mode'):
if method.pagination_mode == 'cursor':
self.iterator = CursorIterator(method, args, kargs)
else:
elif method.pagination_mode == 'id':
self.iterator = IdIterator(method, args, kargs)
elif method.pagination_mode == 'page':
self.iterator = PageIterator(method, args, kargs)
else:
raise TweepError('Invalid pagination mode.')
else:
raise TweepError('This method does not perform pagination')
......@@ -74,6 +78,31 @@ class CursorIterator(BaseIterator):
self.count -= 1
return data
class IdIterator(BaseIterator):
def __init__(self, method, args, kargs):
BaseIterator.__init__(self, method, args, kargs)
self.max_id = kargs.get('max_id')
self.since_id = kargs.get('since_id')
def next(self):
"""Fetch a set of items with IDs less than current set."""
# max_id is inclusive so decrement by one
# to avoid requesting duplicate items.
max_id = self.since_id - 1 if self.max_id else None
data = self.method(max_id = max_id, *self.args, **self.kargs)
self.max_id = data.max_id
self.since_id = data.since_id
return data
def prev(self):
"""Fetch a set of items with IDs greater than current set."""
since_id = self.max_id
data = self.method(since_id = since_id, *self.args, **self.kargs)
self.max_id = data.max_id
self.since_id = data.since_id
return data
class PageIterator(BaseIterator):
def __init__(self, method, args, kargs):
......
......@@ -9,7 +9,21 @@ from tweepy.utils import parse_datetime, parse_html_value, parse_a_href, \
class ResultSet(list):
"""A list like object that holds results from a Twitter API query."""
def __init__(self, max_id=None, since_id=None):
super(ResultSet, self).__init__()
self._max_id = max_id
self._since_id = since_id
@property
def max_id(self):
return self._max_id or max(self.ids())
@property
def since_id(self):
return self._since_id or min(self.ids())
def ids(self):
return [item.id for item in self if hasattr(item, 'id')]
class Model(object):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment