jenkins-bot has submitted this change and it was merged.
Change subject: Make obsolete site object can be created ......................................................................
Make obsolete site object can be created
Per discussion, this patch makes it possible to create an obsolete site object while the site object will be prevented from writing. In other words, it will be a read-only site. Consequently, this patch solves bug 55146. Note that although obsolete sites now become readable, they will not be in site.languages().
In addition, this patch makes pagelanglinks() return only non-obsolete sites by default to make old scripts still functional, but it adds a parameter to suppress this functionality.
Tests adapted by Merlijn van Deen valhallasw@gmail.com
Bug: 61120 Bug: 55146
Change-Id: Ia12660ae2c16148ee7e13977155f1940fe560df1 Original-Change-Id: I3d6ef66c369da7f0b64b821d7d78454192601839 --- M pywikibot/page.py M pywikibot/site.py M tests/site_tests.py 3 files changed, 49 insertions(+), 15 deletions(-)
Approvals: Nullzero: Looks good to me, but someone else must approve Xqt: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/page.py b/pywikibot/page.py index f95b39b..6c0178d 100644 --- a/pywikibot/page.py +++ b/pywikibot/page.py @@ -997,31 +997,40 @@ # ignore any links with invalid contents continue
- def langlinks(self): + def langlinks(self, include_obsolete=False): """Return a list of all interlanguage Links on this page. + + @param include_obsolete: if true, return even Link objects whose site + is obsolete
""" # Data might have been preloaded if not hasattr(self, '_langlinks'): - self._langlinks = list(self.iterlanglinks()) + self._langlinks = list(self.iterlanglinks(include_obsolete=True))
- return self._langlinks + if include_obsolete: + return self._langlinks + else: + return filter(lambda i: not i.site.obsolete, self._langlinks)
- def iterlanglinks(self, step=None, total=None): + def iterlanglinks(self, step=None, total=None, include_obsolete=False): """Iterate all interlanguage links on this page.
@param step: limit each API call to this number of pages @param total: iterate no more than this number of pages in total + @param include_obsolete: if true, yield even Link object whose site + is obsolete @return: a generator that yields Link objects.
""" if hasattr(self, '_langlinks'): - return iter(self._langlinks) + return iter(self.langlinks(include_obsolete=include_obsolete)) # XXX We might want to fill _langlinks when the Site # method is called. If we do this, we'll have to think # about what will happen if the generator is not completely # iterated upon. - return self.site.pagelanglinks(self, step=step, total=total) + return self.site.pagelanglinks(self, step=step, total=total, + include_obsolete=include_obsolete)
def data_item(self): """ diff --git a/pywikibot/site.py b/pywikibot/site.py index 0d1e92d..14b916a 100644 --- a/pywikibot/site.py +++ b/pywikibot/site.py @@ -129,15 +129,15 @@ else: self.__family = fam
+ self.obsolete = False # if we got an outdated language code, use the new one instead. if self.__code in self.__family.obsolete: if self.__family.obsolete[self.__code] is not None: self.__code = self.__family.obsolete[self.__code] else: # no such language anymore - raise NoSuchSite("Language %s in family %s is obsolete" - % (self.__code, self.__family.name)) - if self.__code not in self.languages(): + self.obsolete = True + elif self.__code not in self.languages(): if self.__family.name in list(self.__family.langs.keys()) and \ len(self.__family.langs) == 1: oldcode = self.__code @@ -707,10 +707,15 @@ @param right: the rights the logged in user should have not supported yet and thus ignored. @returns: a decorator to make sure the requirement is statisfied when - the decorated function is called. + the decorated function is called. The function can be called + with as_group='sysop' to override the group set in the + decorator. """ def decorator(fn): def callee(self, *args, **kwargs): + if self.obsolete: + raise NoSuchSite("Language %s in family %s is obsolete" + % (self.code, self.family.name)) grp = kwargs.pop('as_group', group) if grp == 'user': self.login(False) @@ -1959,8 +1964,14 @@ # No such function in the API (this method isn't called anywhere) raise NotImplementedError
- def pagelanglinks(self, page, step=None, total=None): - """Iterate all interlanguage links on page, yielding Link objects.""" + def pagelanglinks(self, page, step=None, total=None, + include_obsolete=False): + """Iterate all interlanguage links on page, yielding Link objects. + + @param include_obsolete: if true, yield even Link objects whose + site is obsolete + + """ lltitle = page.title(withSection=False) llquery = self._generator(api.PropertyGenerator, type_arg="langlinks", @@ -1974,9 +1985,13 @@ if 'langlinks' not in pageitem: continue for linkdata in pageitem['langlinks']: - yield pywikibot.Link.langlinkUnsafe(linkdata['lang'], - linkdata['*'], - source=self) + link = pywikibot.Link.langlinkUnsafe(linkdata['lang'], + linkdata['*'], + source=self) + if link.site.obsolete and not include_obsolete: + continue + else: + yield link
def page_extlinks(self, page, step=None, total=None): """Iterate all external links on page, yielding URL strings.""" diff --git a/tests/site_tests.py b/tests/site_tests.py index 79db3e2..10e5bdf 100644 --- a/tests/site_tests.py +++ b/tests/site_tests.py @@ -1113,7 +1113,11 @@ # Implemented without setUpClass(cls) and global variables as objects # were not completely disposed and recreated but retained 'memory' def setUp(self): + self.code = 'test' + self.family = lambda: None + self.family.name = 'test' self._logged_in_as = None + self.obsolete = False
def login(self, sysop): # mock call @@ -1158,6 +1162,12 @@ self.assertEqual(retval[1], kwargs) self.assertEqual(self._logged_in_as, 'sysop')
+ def testObsoleteSite(self): + self.obsolete = True + args = (1, 2, 'a', 'b') + kwargs = {'i': 'j', 'k': 'l'} + self.assertRaises(pywikibot.NoSuchSite, self.call_this_user_req_function, args, kwargs) + if __name__ == '__main__': try: try: