Skip to content

Commit ebd5cd4

Browse files
General cursor (generator) like object for Twython functions
* If the endpoint has an iter_mode, the function is able to be used in Twython.cursor * Deprecate Twython.search_gen Fixes ryanmcgrath#238
1 parent 123e023 commit ebd5cd4

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed

HISTORY.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ History
1010
- Pass ``client_args`` to the streaming ``__init__``, much like in core Twython (you can pass headers, timeout, hooks, proxies, etc.).
1111
- Streamer has new parameter ``handlers`` which accepts a list of strings related to functions that are apart of the Streaming class and start with "on\_". i.e. ['delete'] is passed, when 'delete' is received from a stream response; ``on_delete`` will be called.
1212
- When an actual request error happens and a ``RequestException`` is raised, it is caught and a ``TwythonError`` is raised instead for convenience.
13+
- Added "cursor"-like functionality. Endpoints with the attribute ``iter_mode`` will be able to be passed to ``Twython.cursor`` and returned as a generator.
14+
- ``Twython.search_gen`` has been deprecated. Please use ``twitter.cursor(twitter.search, q='your_query')`` instead, where ``twitter`` is your ``Twython`` instance.
1315

1416
3.0.0 (2013-06-18)
1517
++++++++++++++++++

twython/api.py

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,16 @@
1414
from requests_oauthlib import OAuth1, OAuth2
1515

1616
from . import __version__
17+
from .advisory import TwythonDeprecationWarning
1718
from .compat import json, urlencode, parse_qsl, quote_plus, str, is_py2
1819
from .endpoints import EndpointsMixin
1920
from .exceptions import TwythonError, TwythonAuthError, TwythonRateLimitError
2021
from .helpers import _transparent_params
2122

23+
import warnings
24+
25+
warnings.simplefilter('always', TwythonDeprecationWarning) # For Python 2.7 >
26+
2227

2328
class Twython(EndpointsMixin, object):
2429
def __init__(self, app_key=None, app_secret=None, oauth_token=None,
@@ -376,22 +381,65 @@ def search_gen(self, search_query, **params):
376381
>>> print result
377382
378383
"""
379-
content = self.search(q=search_query, **params)
384+
warnings.warn(
385+
'This method is deprecated. You should use Twython.cursor instead. [eg. Twython.cursor(Twython.search, q=\'your_query\')]',
386+
TwythonDeprecationWarning,
387+
stacklevel=2
388+
)
389+
return self.cursor(self.search, q=search_query, **params)
390+
391+
def cursor(self, function, **params):
392+
"""Returns a generator for results that match a specified query.
393+
394+
:param function: Instance of a Twython function (Twython.get_home_timeline, Twython.search)
395+
:param \*\*params: Extra parameters to send with your request (usually parameters excepted by the Twitter API endpoint)
396+
:rtype: generator
397+
398+
Usage::
380399
381-
if not content.get('statuses'):
400+
>>> from twython import Twython
401+
>>> twitter = Twython(APP_KEY, APP_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
402+
403+
>>> results = twitter.cursor(twitter.search, q='python')
404+
>>> for result in results:
405+
>>> print result
406+
407+
"""
408+
if not hasattr(function, 'iter_mode'):
409+
raise TwythonError('Unable to create generator for Twython method "%s"' % function.__name__)
410+
411+
content = function(**params)
412+
413+
if not content:
382414
raise StopIteration
383415

384-
for tweet in content['statuses']:
385-
yield tweet
416+
if function.iter_mode == 'cursor' and content['next_cursor_str'] == '0':
417+
raise StopIteration
418+
419+
if hasattr(function, 'iter_key'):
420+
results = content.get(function.iter_key)
421+
else:
422+
results = content
423+
424+
for result in results:
425+
yield result
386426

387427
try:
388-
if not 'since_id' in params:
389-
params['since_id'] = (int(content['statuses'][0]['id_str']) + 1)
428+
if function.iter_mode == 'id':
429+
if not 'max_id' in params:
430+
# Add 1 to the id because since_id and max_id are inclusive
431+
if hasattr(function, 'iter_metadata'):
432+
since_id = content[function.iter_metadata].get('since_id_str')
433+
else:
434+
since_id = content[0]['id_str']
435+
params['since_id'] = (int(since_id) - 1)
436+
elif function.iter_mode == 'cursor':
437+
params['cursor'] = content['next_cursor_str']
390438
except (TypeError, ValueError): # pragma: no cover
391439
raise TwythonError('Unable to generate next page of search results, `page` is not a number.')
392440

393-
for tweet in self.search_gen(search_query, **params):
394-
yield tweet
441+
for result in self.cursor(function, **params):
442+
yield result
395443

396444
@staticmethod
397445
def unicode2utf8(text):

twython/endpoints.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def get_mentions_timeline(self, **params):
2424
2525
"""
2626
return self.get('statuses/mentions_timeline', params=params)
27+
get_mentions_timeline.iter_mode = 'id'
2728

2829
def get_user_timeline(self, **params):
2930
"""Returns a collection of the most recent Tweets posted by the user
@@ -33,6 +34,7 @@ def get_user_timeline(self, **params):
3334
3435
"""
3536
return self.get('statuses/user_timeline', params=params)
37+
get_user_timeline.iter_mode = 'id'
3638

3739
def get_home_timeline(self, **params):
3840
"""Returns a collection of the most recent Tweets and retweets
@@ -42,6 +44,7 @@ def get_home_timeline(self, **params):
4244
4345
"""
4446
return self.get('statuses/home_timeline', params=params)
47+
get_home_timeline.iter_mode = 'id'
4548

4649
def retweeted_of_me(self, **params):
4750
"""Returns the most recent tweets authored by the authenticating user
@@ -51,6 +54,7 @@ def retweeted_of_me(self, **params):
5154
5255
"""
5356
return self.get('statuses/retweets_of_me', params=params)
57+
retweeted_of_me.iter_mode = 'id'
5458

5559
# Tweets
5660
def get_retweets(self, **params):
@@ -128,6 +132,9 @@ def search(self, **params):
128132
129133
"""
130134
return self.get('search/tweets', params=params)
135+
search.iter_mode = 'id'
136+
search.iter_key = 'statuses'
137+
search.iter_metadata = 'search_metadata'
131138

132139
# Direct Messages
133140
def get_direct_messages(self, **params):
@@ -268,7 +275,9 @@ def get_friends_list(self, **params):
268275
Docs: https://dev.twitter.com/docs/api/1.1/get/friends/list
269276
270277
"""
278+
print 'here 1'
271279
return self.get('friends/list', params=params)
280+
get_friends_list.iterator_mode = 'cursor'
272281

273282
def get_followers_list(self, **params):
274283
"""Returns a cursored collection of user objects for users

0 commit comments

Comments
 (0)