Make IdIerator work correctly (Finally!)
authorAaron Hill <aa1ronham@gmail.com>
Sat, 12 Apr 2014 21:32:05 +0000 (17:32 -0400)
committerAaron Hill <aa1ronham@gmail.com>
Sat, 12 Apr 2014 21:32:05 +0000 (17:32 -0400)
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
tweepy/models.py

index 4c06f17a9f2fab3af9885f831c17c2c7fde1152a..ef81c524403c0f8c3028b2398312c3eda2dc2311 100644 (file)
@@ -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):
index f435a70af4dd4aac518a3122b8611cbeecf3724e..cc169bab4895bad208f62cac8c7b6d56a4f4e4c9 100644 (file)
@@ -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')]