jenkins-bot has submitted this change and it was merged.
Change subject: Update DeletionBot for undelete, implement tests
......................................................................
Update DeletionBot for undelete, implement tests
Update DeletionBot to support i18n messages for undelete, pass
mark=True to Page.delete() if -always is set (gets rid of prompt)
Add tests for Site.undelete and the deletionbot script.
Fix issues with Page.undelete and Site.undelete_page when an error
is raised if None is passed for revisions/timestamps.
Fix unhandled exception with delete.py if undeleting a page that
exists,
Bug: T74733
Bug: T57255
Bug: T62572
Change-Id: Ie474bc289951492f7fabc5ea53f63732df7acfdf
---
M pywikibot/page.py
M pywikibot/site.py
M scripts/delete.py
M tests/__init__.py
A tests/deletionbot_tests.py
M tests/site_tests.py
6 files changed, 175 insertions(+), 13 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/page.py b/pywikibot/page.py
index cc3012d..2fcb3a5 100644
--- a/pywikibot/page.py
+++ b/pywikibot/page.py
@@ -1607,8 +1607,11 @@
@type reason: basestring
"""
- undelete_revs = [ts for ts, rev in self._deletedRevs.items()
- if 'marked' in rev and rev['marked']]
+ if hasattr(self, "_deletedRevs"):
+ undelete_revs = [ts for ts, rev in self._deletedRevs.items()
+ if 'marked' in rev and rev['marked']]
+ else:
+ undelete_revs = []
if reason is None:
pywikibot.warning('Not passing a reason for undelete() is
deprecated.')
pywikibot.output(u'Undeleting %s.' % (self.title(asLink=True)))
diff --git a/pywikibot/site.py b/pywikibot/site.py
index 6fa32a7..362f7a3 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -4198,9 +4198,14 @@
"""
token = self.tokens['undelete']
self.lock_page(page)
- req = api.Request(site=self, action="undelete", token=token,
- title=page.title(withSection=False),
- timestamps=revisions, reason=reason)
+
+ if revisions is None:
+ req = api.Request(site=self, action='undelete', token=token,
+ title=page.title(withSection=False), reason=reason)
+ else:
+ req = api.Request(site=self, action='undelete', token=token,
+ title=page.title(withSection=False),
+ timestamps=revisions, reason=reason)
try:
req.submit()
except api.APIError as err:
diff --git a/scripts/delete.py b/scripts/delete.py
index fe4f1b6..93f6f8a 100644
--- a/scripts/delete.py
+++ b/scripts/delete.py
@@ -64,13 +64,17 @@
self.summary = summary
def treat(self, page):
- """Delete one page from the generator."""
+ """Process one page from the generator."""
self.current_page = page
if self.getOption('undelete'):
- page.undelete(self.summary)
+ if page.exists():
+ pywikibot.output(u'Skipping: %s already exists.' % page)
+ else:
+ page.undelete(self.summary)
else:
if page.exists():
- page.delete(self.summary, not self.getOption('always'))
+ page.delete(self.summary, not self.getOption('always'),
+ self.getOption('always'))
else:
pywikibot.output(u'Skipping: %s does not exist.' % page)
@@ -95,6 +99,7 @@
mysite = pywikibot.Site()
for arg in local_args:
+
if arg == '-always':
options['always'] = True
elif arg.startswith('-summary'):
@@ -115,21 +120,23 @@
pageName = arg[found:]
if not summary:
+ un = 'un' if 'undelete' in options else ''
if pageName:
if arg.startswith('-cat') or arg.startswith('-subcats'):
summary = i18n.twtranslate(mysite, 'delete-from-category',
{'page': pageName})
elif arg.startswith('-links'):
- summary = i18n.twtranslate(mysite, 'delete-linked-pages',
+ summary = i18n.twtranslate(mysite, un +
'delete-linked-pages',
{'page': pageName})
elif arg.startswith('-ref'):
summary = i18n.twtranslate(mysite, 'delete-referring-pages',
{'page': pageName})
elif arg.startswith('-imageused'):
- summary = i18n.twtranslate(mysite, 'delete-images',
+ summary = i18n.twtranslate(mysite, un + 'delete-images',
{'page': pageName})
elif arg.startswith('-file'):
- summary = i18n.twtranslate(mysite, 'delete-from-file')
+ summary = i18n.twtranslate(mysite, un + 'delete-from-file')
+
generator = genFactory.getCombinedGenerator()
# We are just deleting pages, so we have no need of using a preloading
# page generator to actually get the text of those pages.
diff --git a/tests/__init__.py b/tests/__init__.py
index bd6e9c5..2634a8b 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -92,6 +92,7 @@
'script',
'archivebot',
'data_ingestion',
+ 'deletionbot',
'cache',
]
diff --git a/tests/deletionbot_tests.py b/tests/deletionbot_tests.py
new file mode 100644
index 0000000..7c0d893
--- /dev/null
+++ b/tests/deletionbot_tests.py
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+"""Tests for scripts/delete.py."""
+#
+# (C) Pywikibot team, 2014
+#
+# Distributed under the terms of the MIT license.
+#
+__version__ = '$Id$'
+
+import pywikibot
+import pywikibot.page
+
+from scripts import delete
+
+from tests.aspects import unittest, TestCase
+
+
+class TestDeletionBotWrite(TestCase):
+
+ """Test deletionbot script."""
+
+ family = 'test'
+ code = 'test'
+
+ sysop = True
+ write = True
+
+ def test_delete(self):
+ """Test deletionbot on the test wiki."""
+ site = self.get_site()
+ cat = pywikibot.Category(site, 'Pywikibot Delete Test')
+ delete.main('-cat:Pywikibot_Delete_Test', '-always')
+ self.assertEqual(len(list(cat.members())), 0)
+ delete.main('-page:User:Unicodesnowman/DeleteTest1', '-always',
+ '-undelete', '-summary=pywikibot unit tests')
+ delete.main('-page:User:Unicodesnowman/DeleteTest2', '-always',
+ '-undelete', '-summary=pywikibot unit tests')
+ self.assertEqual(len(list(cat.members())), 2)
+
+ def test_undelete_existing(self):
+ """Test undeleting an existing page."""
+ site = self.get_site()
+ p1 = pywikibot.Page(site, 'User:Unicodesnowman/ExistingPage')
+ if not p1.exists():
+ p1.text = 'pywikibot unit test page'
+ p1.save('unit test', botflag=True)
+ delete.main('-page:User:Unicodesnowman/ExistingPage', '-always',
+ '-undelete', '-summary=pywikibot unit tests')
+
+
+class TestDeletionBotUser(TestCase):
+
+ """Test deletionbot as a user (not sysop)."""
+
+ family = 'test'
+ code = 'test'
+
+ user = True
+ write = True
+
+ def test_delete_mark(self):
+ site = self.get_site()
+ if site.username(sysop=True):
+ raise unittest.SkipTest('can\'t test mark with sysop account')
+
+ p1 = pywikibot.Page(site, 'User:Unicodesnowman/DeleteMark')
+ if not p1.exists():
+ p1.text = 'foo'
+ p1.save('unit test', botflag=True)
+ delete.main('-page:User:Unicodesnowman/DeleteMark', '-always',
+ '-summary=pywikibot unit test. Do NOT actually delete.')
+ self.assertEqual(p1.get(force=True), '{{delete|1=pywikibot unit test. '
+ 'Do NOT actually delete.}}\nfoo')
+ p1.text = 'foo'
+ p1.save('unit test', botflag=True)
+
+
+class TestDeletionBot(TestCase):
+
+ """Test deletionbot with patching to make it
non-write."""
+
+ family = 'test'
+ code = 'test'
+
+ cached = True
+
+ delete_args = []
+ undelete_args = []
+
+ def setUp(self):
+ self._original_delete = pywikibot.Page.delete
+ self._original_undelete = pywikibot.Page.undelete
+ pywikibot.Page.delete = delete_dummy
+ pywikibot.Page.undelete = undelete_dummy
+ super(TestDeletionBot, self).setUp()
+
+ def tearDown(self):
+ pywikibot.Page.delete = self._original_delete
+ pywikibot.Page.undelete = self._original_undelete
+ super(TestDeletionBot, self).tearDown()
+
+ def test_dry(self):
+ delete.main('-page:Main Page', '-always',
'-summary:foo')
+ self.assertEqual(self.delete_args, ['[[Main Page]]', 'foo',
False, True])
+ delete.main('-page:FoooOoOooO', '-always',
'-summary:foo', '-undelete')
+ self.assertEqual(self.undelete_args, ['[[FoooOoOooO]]', 'foo'])
+
+
+def delete_dummy(self, reason, prompt, mark):
+ TestDeletionBot.delete_args = [self.title(asLink=True), reason, prompt, mark]
+
+
+def undelete_dummy(self, reason):
+ TestDeletionBot.undelete_args = [self.title(asLink=True), reason]
+
+
+if __name__ == '__main__':
+ try:
+ unittest.main()
+ except SystemExit:
+ pass
diff --git a/tests/site_tests.py b/tests/site_tests.py
index 406e969..df5b2b1 100644
--- a/tests/site_tests.py
+++ b/tests/site_tests.py
@@ -1150,9 +1150,9 @@
total=5)
-class SiteProtectTestCase(DefaultSiteTestCase):
+class TestSiteSysopWrite(TestCase):
- """Test site protect / unprotect using a sysop
account."""
+ """Test site sysop methods that require writing."""
family = 'test'
code = 'test'
@@ -1230,6 +1230,31 @@
protections={'edit': 'anInvalidValue'},
page=p1, reason='Pywikibot unit test')
+ def test_delete(self):
+ """Test the site.deletepage() and site.undelete_page()
methods."""
+ site = self.get_site()
+ p = pywikibot.Page(site, u'User:Unicodesnowman/DeleteTestSite')
+ # Verify state
+ if not p.exists():
+ site.undelete_page(p, 'pywikibot unit tests')
+
+ site.deletepage(p, reason='pywikibot unit tests')
+ self.assertRaises(pywikibot.NoPage, p.get, force=True)
+
+ site.undelete_page(p, 'pywikibot unit tests',
+ revisions=[u'2014-12-21T06:07:47Z',
+ u'2014-12-21T06:07:31Z'])
+
+ revs = list(p.getVersionHistory())
+ self.assertEqual(len(revs), 2)
+ self.assertEqual(revs[0].revid, 219995)
+ self.assertEqual(revs[1].revid, 219994)
+
+ site.deletepage(p, reason='pywikibot unit tests')
+ site.undelete_page(p, 'pywikibot unit tests')
+ revs = list(p.getVersionHistory())
+ self.assertTrue(len(revs) > 2)
+
class SiteUserTestCase2(DefaultSiteTestCase):
--
To view, visit
https://gerrit.wikimedia.org/r/181359
To unsubscribe, visit
https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ie474bc289951492f7fabc5ea53f63732df7acfdf
Gerrit-PatchSet: 10
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Unicodesnowman <admin(a)glados.cc>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(a)gmail.com>
Gerrit-Reviewer: Merlijn van Deen <valhallasw(a)arctus.nl>
Gerrit-Reviewer: Unicodesnowman <admin(a)glados.cc>
Gerrit-Reviewer: XZise <CommodoreFabianus(a)gmx.de>
Gerrit-Reviewer: jenkins-bot <>