Commit 21055ad5 authored by Joshua Roesslein's avatar Joshua Roesslein
Browse files

Merge remote-tracking branch 'master' into search-v1.1

Conflicts:
	tweepy/models.py
parents 2098078d 4d75a024
--- ---
script: nosetests -v tests.test_api tests.test_streaming script: nosetests -v tests.test_api tests.test_streaming tests.test_cursors
language: python language: python
env: env:
global: global:
......
...@@ -312,43 +312,6 @@ class TweepyAPITests(unittest.TestCase): ...@@ -312,43 +312,6 @@ class TweepyAPITests(unittest.TestCase):
self.assertTrue(place_name_in_list('Austin, TX', self.assertTrue(place_name_in_list('Austin, TX',
self.api.reverse_geocode(lat=30.267370168467806, long= -97.74261474609375))) # Austin, TX, USA self.api.reverse_geocode(lat=30.267370168467806, long= -97.74261474609375))) # Austin, TX, USA
class TweepyCursorTests(unittest.TestCase):
def setUp(self):
auth = OAuthHandler(oauth_consumer_key, oauth_consumer_secret)
auth.set_access_token(oauth_token, oauth_token_secret)
self.api = API(auth)
self.api.retry_count = 2
self.api.retry_delay = 5
def testpagecursoritems(self):
items = list(Cursor(self.api.user_timeline).items())
self.assert_(len(items) > 0)
items = list(Cursor(self.api.user_timeline, 'twitter').items(30))
self.assert_(len(items) == 30)
def testpagecursorpages(self):
pages = list(Cursor(self.api.user_timeline).pages())
self.assert_(len(pages) > 0)
pages = list(Cursor(self.api.user_timeline, 'twitter').pages(5))
self.assert_(len(pages) == 5)
def testcursorcursoritems(self):
items = list(Cursor(self.api.friends_ids).items())
self.assert_(len(items) > 0)
items = list(Cursor(self.api.followers_ids, 'twitter').items(30))
self.assert_(len(items) == 30)
def testcursorcursorpages(self):
pages = list(Cursor(self.api.friends_ids).pages())
self.assert_(len(pages) > 0)
pages = list(Cursor(self.api.followers_ids, 'twitter').pages(5))
self.assert_(len(pages) == 5)
class TweepyCacheTests(unittest.TestCase): class TweepyCacheTests(unittest.TestCase):
timeout = 2.0 timeout = 2.0
......
import unittest
from tweepy import API, Cursor
from config import create_auth
class TweepyCursorTests(unittest.TestCase):
def setUp(self):
self.api = API(create_auth())
self.api.retry_count = 2
self.api.retry_delay = 5
def testidcursoritems(self):
items = list(Cursor(self.api.user_timeline).items(25))
self.assertEqual(len(items), 25)
def testidcursorpages(self):
pages = list(Cursor(self.api.user_timeline).pages(5))
self.assertEqual(len(pages), 5)
def testcursorcursoritems(self):
items = list(Cursor(self.api.friends_ids).items())
self.assert_(len(items) > 0)
items = list(Cursor(self.api.followers_ids, 'twitter').items(30))
self.assert_(len(items) == 30)
def testcursorcursorpages(self):
pages = list(Cursor(self.api.friends_ids).pages())
self.assert_(len(pages) > 0)
pages = list(Cursor(self.api.followers_ids, 'twitter').pages(5))
self.assert_(len(pages) == 5)
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): ...@@ -37,7 +37,7 @@ class API(object):
home_timeline = bind_api( home_timeline = bind_api(
path = '/statuses/home_timeline.json', path = '/statuses/home_timeline.json',
payload_type = 'status', payload_list = True, payload_type = 'status', payload_list = True,
allowed_param = ['since_id', 'max_id', 'count', 'page'], allowed_param = ['since_id', 'max_id', 'count'],
require_auth = True require_auth = True
) )
...@@ -46,7 +46,7 @@ class API(object): ...@@ -46,7 +46,7 @@ class API(object):
path = '/statuses/user_timeline.json', path = '/statuses/user_timeline.json',
payload_type = 'status', payload_list = True, payload_type = 'status', payload_list = True,
allowed_param = ['id', 'user_id', 'screen_name', 'since_id', allowed_param = ['id', 'user_id', 'screen_name', 'since_id',
'max_id', 'count', 'page', 'include_rts'] 'max_id', 'count', 'include_rts']
) )
""" statuses/mentions """ """ statuses/mentions """
...@@ -85,7 +85,7 @@ class API(object): ...@@ -85,7 +85,7 @@ class API(object):
retweets_of_me = bind_api( retweets_of_me = bind_api(
path = '/statuses/retweets_of_me.json', path = '/statuses/retweets_of_me.json',
payload_type = 'status', payload_list = True, payload_type = 'status', payload_list = True,
allowed_param = ['since_id', 'max_id', 'count', 'page'], allowed_param = ['since_id', 'max_id', 'count'],
require_auth = True require_auth = True
) )
...@@ -195,7 +195,7 @@ class API(object): ...@@ -195,7 +195,7 @@ class API(object):
direct_messages = bind_api( direct_messages = bind_api(
path = '/direct_messages.json', path = '/direct_messages.json',
payload_type = 'direct_message', payload_list = True, 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 require_auth = True
) )
...@@ -282,7 +282,7 @@ class API(object): ...@@ -282,7 +282,7 @@ class API(object):
friends = bind_api( friends = bind_api(
path = '/friends/list.json', path = '/friends/list.json',
payload_type = 'user', payload_list = True, 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 """ """ friendships/incoming """
...@@ -310,7 +310,7 @@ class API(object): ...@@ -310,7 +310,7 @@ class API(object):
followers = bind_api( followers = bind_api(
path = '/followers/list.json', path = '/followers/list.json',
payload_type = 'user', payload_list = True, 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 """ """ account/verify_credentials """
...@@ -432,7 +432,7 @@ class API(object): ...@@ -432,7 +432,7 @@ class API(object):
blocks = bind_api( blocks = bind_api(
path = '/blocks/list.json', path = '/blocks/list.json',
payload_type = 'user', payload_list = True, payload_type = 'user', payload_list = True,
allowed_param = ['page'], allowed_param = ['cursor'],
require_auth = True require_auth = True
) )
......
...@@ -200,6 +200,9 @@ def bind_api(**config): ...@@ -200,6 +200,9 @@ def bind_api(**config):
# Set pagination mode # Set pagination mode
if 'cursor' in APIMethod.allowed_param: if 'cursor' in APIMethod.allowed_param:
_call.pagination_mode = 'cursor' _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: elif 'page' in APIMethod.allowed_param:
_call.pagination_mode = 'page' _call.pagination_mode = 'page'
......
...@@ -11,8 +11,12 @@ class Cursor(object): ...@@ -11,8 +11,12 @@ class Cursor(object):
if hasattr(method, 'pagination_mode'): if hasattr(method, 'pagination_mode'):
if method.pagination_mode == 'cursor': if method.pagination_mode == 'cursor':
self.iterator = CursorIterator(method, args, kargs) 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) self.iterator = PageIterator(method, args, kargs)
else:
raise TweepError('Invalid pagination mode.')
else: else:
raise TweepError('This method does not perform pagination') raise TweepError('This method does not perform pagination')
...@@ -74,6 +78,35 @@ class CursorIterator(BaseIterator): ...@@ -74,6 +78,35 @@ class CursorIterator(BaseIterator):
self.count -= 1 self.count -= 1
return data 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)
if len(data) == 0:
raise StopIteration
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)
if len(data) == 0:
raise StopIteration
self.max_id = data.max_id
self.since_id = data.since_id
return data
class PageIterator(BaseIterator): class PageIterator(BaseIterator):
def __init__(self, method, args, kargs): def __init__(self, method, args, kargs):
......
...@@ -9,7 +9,27 @@ from tweepy.utils import parse_datetime, parse_html_value, parse_a_href, \ ...@@ -9,7 +9,27 @@ from tweepy.utils import parse_datetime, parse_html_value, parse_a_href, \
class ResultSet(list): class ResultSet(list):
"""A list like object that holds results from a Twitter API query.""" """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):
if self._max_id:
return self._max_id
ids = self.ids()
return max(ids) if ids else None
@property
def since_id(self):
if self._since_id:
return self._since_id
ids = self.ids()
return min(ids) if ids else None
def ids(self):
return [item.id for item in self if hasattr(item, 'id')]
class Model(object): 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