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 -- GitLab