From 191687f12c765bec8b95ad42e894165b1071d537 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 12 Apr 2014 17:32:05 -0400 Subject: [PATCH] Make IdIerator work correctly (Finally!) The IdIterator class now correctly requests new pages of results. It doesn't allow going back past the first page requested by next(), as there's no way to do this properly with Twitter's API. --- tweepy/cursor.py | 37 +++++++++++++++++++++++-------------- tweepy/models.py | 6 ++++-- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/tweepy/cursor.py b/tweepy/cursor.py index 4c06f17..ef81c52 100644 --- a/tweepy/cursor.py +++ b/tweepy/cursor.py @@ -84,23 +84,30 @@ 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') - self.count = 0 + self.num_tweets = 0 + self.results = [] + self.index = 0 def next(self): """Fetch a set of items with IDs less than current set.""" if self.limit and self.limit == self.count: raise StopIteration - # 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 self.index >= len(self.results) - 1: + data = self.method(max_id=self.max_id, *self.args, **self.kargs) + if len(self.results) != 0: + self.index += 1 + self.results.append(data) + else: + self.index += 1 + data = self.results[self.index] + if len(data) == 0: raise StopIteration - self.max_id = data.max_id - self.since_id = data.since_id - self.count += 1 + # TODO: Make this not dependant on the parser making max_id and + # since_id available + self.max_id = data.max_id + self.num_tweets += 1 return data def prev(self): @@ -108,13 +115,15 @@ class IdIterator(BaseIterator): if self.limit and self.limit == self.count: raise StopIteration - since_id = self.max_id - data = self.method(since_id = since_id, *self.args, **self.kargs) - if len(data) == 0: + self.index -= 1 + if self.index < 0: + # There's no way to fetch a set of tweets directly 'above' the + # current set raise StopIteration + + data = self.results[self.index] self.max_id = data.max_id - self.since_id = data.since_id - self.count += 1 + self.num_tweets += 1 return data class PageIterator(BaseIterator): diff --git a/tweepy/models.py b/tweepy/models.py index f435a70..cc169ba 100644 --- a/tweepy/models.py +++ b/tweepy/models.py @@ -18,14 +18,16 @@ class ResultSet(list): if self._max_id: return self._max_id ids = self.ids() - return max(ids) if ids else None + # Max_id is always set to the *smallest* id, minus one, in the set + return (min(ids) - 1) 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 + # Since_id is always set to the *greatest* id in the set + return max(ids) if ids else None def ids(self): return [item.id for item in self if hasattr(item, 'id')] -- 2.25.1