jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/456998 )
Change subject: [IMPR] Derive RedirectRobot from MultipleSitesBot ......................................................................
[IMPR] Derive RedirectRobot from MultipleSitesBot
Derive RedirectRobot from MultipleSitesBot. This will allow having multiple sites generators with redirect.py in future.
- setup "repo" and "is_repo" attributes in init_page method - sdtemplate becomes a property which calls get_sd_template with current_page.site - introduce a site parameter in get_sd_template - do no longer check for logged in and 'delete' option inside get_sd_template because this is done before the method is called - always print a warning if get_sd_template fails - update tests
Bug: T211586 Change-Id: Ica37a9ffb813dee7fd1720685e8c0d69b5bbd983 --- M scripts/redirect.py M tests/redirect_bot_tests.py 2 files changed, 57 insertions(+), 35 deletions(-)
Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
diff --git a/scripts/redirect.py b/scripts/redirect.py index 4a863db..b72fac5 100755 --- a/scripts/redirect.py +++ b/scripts/redirect.py @@ -82,8 +82,8 @@ import pywikibot
from pywikibot import i18n, xmlreader -from pywikibot.bot import (ExistingPageBot, OptionHandler, RedirectPageBot, - SingleSiteBot) +from pywikibot.bot import (ExistingPageBot, MultipleSitesBot, OptionHandler, + RedirectPageBot) from pywikibot.textlib import extract_templates_and_params_regex_simple from pywikibot.tools import PYTHON_VERSION
@@ -383,7 +383,7 @@ continue
-class RedirectRobot(SingleSiteBot, ExistingPageBot, RedirectPageBot): +class RedirectRobot(MultipleSitesBot, ExistingPageBot, RedirectPageBot):
"""Redirect bot."""
@@ -395,9 +395,6 @@ 'sdtemplate': None, }) super().__init__(**kwargs) - self.repo = self.site.data_repository() - self.is_repo = self.repo if self.repo == self.site else None - self.sdtemplate = self.get_sd_template()
# connect the action treat to treat_page method called by treat if action == 'double': @@ -410,48 +407,59 @@ raise NotImplementedError('No valid action "{}" found.' .format(action))
- def get_sd_template(self) -> Optional[str]: + def get_sd_template(self, site=None) -> Optional[str]: """Look for speedy deletion template and return it.
+ @param site: site for which the template has to be given + @type site: pywikibot.BaseSite @return: A valid speedy deletion template. """ - if self.opt.delete and not self.site.has_right('delete'): + title = None + if site: sd = self.opt.sdtemplate - if not sd and i18n.twhas_key(self.site, + if not sd and i18n.twhas_key(site, 'redirect-broken-redirect-template'): - sd = i18n.twtranslate(self.site, + sd = i18n.twtranslate(site, 'redirect-broken-redirect-template') - # TODO: Add bot's signature if needed (Bug: T131517)
# check whether template exists for this site - title = None if sd: template = extract_templates_and_params_regex_simple(sd) if template: title = template[0][0] - page = pywikibot.Page(self.site, title, ns=10) + page = pywikibot.Page(site, title, ns=10) if page.exists(): return sd - pywikibot.warning( - 'No speedy deletion template {}available.' - .format('"{}" '.format(title) if title else '')) + + pywikibot.warning( + 'No speedy deletion template {}available.' + .format('"{}" '.format(title) if title else '')) return None
+ @property + def sdtemplate(self): + """Gives the speedy deletion template for the current_page.""" + return self.get_sd_template(self.current_page.site) + def init_page(self, item) -> pywikibot.Page: """Ensure that we process page objects.""" + default_site = pywikibot.Site() if isinstance(item, str): - item = pywikibot.Page(self.site, item) + item = pywikibot.Page(default_site, item) elif isinstance(item, tuple): redir_name, code, target, final = item - item = pywikibot.Page(self.site, redir_name) + item = pywikibot.Page(default_site, redir_name) item._redirect_type = code - return super().init_page(item) + page = super().init_page(item) + self.repo = page.site.data_repository() + self.is_repo = self.repo if self.repo == page.site else None + return page
def delete_redirect(self, page, summary_key) -> None: """Delete the redirect page.""" - assert page.site == self.site, ( + assert page.site == self.current_page.site, ( 'target page is on different site {0}'.format(page.site)) - reason = i18n.twtranslate(self.site, summary_key) + reason = i18n.twtranslate(page.site, summary_key) if page.site.has_right('delete'): page.delete(reason, prompt=False) elif self.sdtemplate: @@ -505,10 +513,10 @@ else: pywikibot.output('{0} has been moved to {1}' .format(redir_page, movedTarget)) - reason = i18n.twtranslate(self.site, - 'redirect-fix-broken-moved', - {'to': movedTarget.title( - as_link=True)}) + reason = i18n.twtranslate( + redir_page.site, 'redirect-fix-broken-moved', + {'to': movedTarget.title(as_link=True, + allow_interwiki=False)}) content = redir_page.get(get_redirect=True) redir_page.set_redirect_target( movedTarget, keep_section=True, save=False) @@ -639,9 +647,9 @@ break redir.set_redirect_target(targetPage, keep_section=True, save=False) - summary = i18n.twtranslate(self.site, 'redirect-fix-double', - {'to': targetPage.title(as_link=True)} - ) + summary = i18n.twtranslate( + redir.site, 'redirect-fix-double', + {'to': targetPage.title(as_link=True, allow_interwiki=False)}) self.userPut(redir, oldText, redir.text, summary=summary, ignore_save_related_errors=True, ignore_server_errors=True) @@ -739,7 +747,6 @@ if not action: pywikibot.bot.suggest_help(missing_action=True) else: - pywikibot.Site().login() options['generator'] = RedirectGenerator(action, **gen_options) bot = RedirectRobot(action, **options) bot.run() diff --git a/tests/redirect_bot_tests.py b/tests/redirect_bot_tests.py index 5986f34..dea9aa5 100644 --- a/tests/redirect_bot_tests.py +++ b/tests/redirect_bot_tests.py @@ -16,6 +16,21 @@ from tests.aspects import DefaultSiteTestCase
+class RedirectTestRobot(RedirectRobot): + + """RedirectRobot test class.""" + + @property + def current_page(self): + """Patch current_page to return any page.""" + return Page(self.site, 'Main', ns=4) + + @property + def site(self): + """Patch site to return a site object.""" + return pywikibot.Site() + + @patch.object(Page, 'exists', new=Mock(return_value=True)) class TestGetSDTemplateNoSysop(DefaultSiteTestCase):
@@ -24,32 +39,32 @@ def test_with_delete_and_existing_sdtemplate(self): """Test with delete and existing sdtemplate.""" options = {'delete': True, 'sdtemplate': '{{t}}'} - bot = RedirectRobot('broken', **options) + bot = RedirectTestRobot('broken', **options) self.assertEqual(bot.sdtemplate, '{{t}}')
@patch.object(i18n, 'twhas_key', new=Mock(return_value=True)) @patch.object(i18n, 'twtranslate', new=Mock(return_value='{{sd_title}}')) def test_with_delete_and_i18n_sd(self): """Test with delete and i18n template.""" - bot = RedirectRobot('broken', delete=True) + bot = RedirectTestRobot('broken', delete=True) self.assertEqual(bot.sdtemplate, '{{sd_title}}')
@patch.object(i18n, 'twhas_key', new=Mock(return_value=False)) def test_with_delete_no_sd_no_i18n(self): """Test with delete and no i18n template.""" + bot = RedirectTestRobot('broken', delete=True) with patch.object(pywikibot, 'warning') as w: - bot = RedirectRobot('broken', delete=True) + self.assertIsNone(bot.sdtemplate) w.assert_called_with('No speedy deletion template available.') - self.assertIsNone(bot.sdtemplate)
def test_with_delete_and_non_existing_sdtemplate(self): """Test with delete and non-exisitng sdtemplate.""" options = {'delete': True, 'sdtemplate': 'txt {{n|a}} txt'} + bot = RedirectTestRobot('broken', **options) with patch.object(Page, 'exists', new=Mock(return_value=False)): with patch.object(pywikibot, 'warning') as w: - bot = RedirectRobot('broken', **options) + self.assertIsNone(bot.sdtemplate, None) w.assert_called_with('No speedy deletion template "n" available.') - self.assertIsNone(bot.sdtemplate)
if __name__ == '__main__': # pragma: no cover