Blob Blame History Raw
From 7522c02b6e893fc49309a5d550d68733477af83c Mon Sep 17 00:00:00 2001
From: Adam Williamson <awilliam@redhat.com>
Date: Wed, 3 Feb 2016 05:48:53 +0100
Subject: [PATCH] [#106] fix GeneratorList with Python 3 (add __next__)

Credit for this fix goes to @tosher:
https://github.com/mwclient/mwclient/issues#issuecomment-154751657
I just figured out exactly what changes his comment suggested,
and poked around a bit to figure out what was going on and why
they're needed.

`GeneratorList` (and things deriving from it, e.g. `Category`)
was broken for iteration purposes in Python 3. In Python 3
the iterator protocol requires a `__next__` method, not a `next`
method as in Python 2. 8d0650c renamed `List`'s `next` method
to `__next__` and added a small wrapper `next` method to account
for this, but did not make the same change for `GeneratorList`.
So when you iterate over a `GeneratorList` with Python 3, it
winds up calling `List.__next__` (since `GeneratorList` inherits
from `List`), not `GeneratorList.next`. So we don't hit the bit
that turns the results into mwclient page objects, and just get
the raw dicts from the `List` method.

We also have to change a couple of direct calls to `List.next`
to call `List.__next__` instead. If we don't do this, then when
the call originates from a child class, things get messed up,
because `List.next` calls `self.__next__` - and that will wind
up calling the child class' `__next__`, not `List`'s `__next__`.

Confused yet? :)
---
 mwclient/listing.py | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/mwclient/listing.py b/mwclient/listing.py
index 656df70..07ffd17 100644
--- a/mwclient/listing.py
+++ b/mwclient/listing.py
@@ -57,7 +57,7 @@ class List(object):
             if self.last:
                 raise StopIteration
             self.load_chunk()
-            return List.next(self, full=full)
+            return List.__next__(self, full=full)
 
     def next(self, full=False):
         """ For Python 2.x support """
@@ -139,14 +139,18 @@ class GeneratorList(List):
 
         self.page_class = mwclient.page.Page
 
-    def next(self):
-        info = List.next(self, full=True)
+    def __next__(self):
+        info = List.__next__(self, full=True)
         if info['ns'] == 14:
             return Category(self.site, u'', info)
         if info['ns'] == 6:
             return mwclient.image.Image(self.site, u'', info)
         return mwclient.page.Page(self.site, u'', info)
 
+    def next(self):
+        """ For Python 2.x support """
+        return self.__next__()
+
     def load_chunk(self):
         # Put this here so that the constructor does not fail
         # on uninitialized sites
-- 
2.5.0