jenkins-bot has submitted this change and it was merged.
Change subject: Reimplement Site.undelete and Page.undelete
......................................................................
Reimplement Site.undelete and Page.undelete
* Reimplement Site.undelete and Page.undelete
* Make Page.markDeletedRevision raise ValueError if an invalid timestamp
is passed, fix marking
* Add tests in page_tests.py (requires sysop)
* Rename summary param for delete/undelete to reason
Site.deletedrevs needs to be updated to listdeletedrevisions for 1.25wmf.
Change-Id: I1eb2c158f6450bf7b4e9c3f26c83bb7674b9f766
Bug: T74733
---
M pywikibot/page.py
M pywikibot/site.py
M tests/page_tests.py
3 files changed, 96 insertions(+), 20 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/page.py b/pywikibot/page.py
index d96b8cb..386f6cc 100644
--- a/pywikibot/page.py
+++ b/pywikibot/page.py
@@ -1532,10 +1532,8 @@
self.text = template + self.text
return self.save(comment=reason)
- # all these DeletedRevisions methods need to be reviewed and harmonized
- # with the new framework; they do not appear functional
def loadDeletedRevisions(self, step=None, total=None):
- """Retrieve all deleted revisions for this Page from
Special/Undelete.
+ """Retrieve deleted revisions for this Page.
Stores all revisions' timestamps, dates, editors and comments in
self._deletedRevs attribute.
@@ -1576,21 +1574,18 @@
"""Mark the revision identified by timestamp for undeletion.
@param undelete: if False, mark the revision to remain deleted.
-
+ @type undelete: bool
"""
if not hasattr(self, "_deletedRevs"):
self.loadDeletedRevisions()
if timestamp not in self._deletedRevs:
- # TODO: Throw an exception?
- return
- self._deletedRevs[timestamp][4] = undelete
- self._deletedRevsModified = True
+ raise ValueError(u'Timestamp %d is not a deleted revision' %
timestamp)
+ self._deletedRevs[timestamp]['marked'] = undelete
- @deprecate_arg("throttle", None)
- def undelete(self, comment=None):
+ @deprecate_arg('throttle', None)
+ @deprecate_arg('comment', 'reason')
+ def undelete(self, reason=None):
"""Undelete revisions based on the markers set by previous calls.
-
- NOT IMPLEMENTED.
If no calls have been made since loadDeletedRevisions(), everything
will be restored.
@@ -1608,11 +1603,17 @@
pg.markDeletedRevision(rev) #mark for undeletion
pg.undelete('This will restore only selected revisions.')
- @param comment: The undeletion edit summary.
- @type comment: basestring
+ @param reason: Reason for the action.
+ @type reason: basestring
+
"""
- # FIXME: Site.undelete needs to be implemented.
- raise NotImplementedError('Page.undelete is not implemented.')
+ undelete_revs = [ts for ts, rev in self._deletedRevs.items()
+ if 'marked' in rev and rev['marked']]
+ if reason is None:
+ pywikibot.warning('Not passing a reason for undelete() is
deprecated.')
+ pywikibot.output(u'Undeleting %s.' % (self.title(asLink=True)))
+ reason = pywikibot.input(u'Please enter a reason for the
undeletion:')
+ self.site.undelete_page(self, reason, undelete_revs)
@deprecate_arg("throttle", None)
def protect(self, edit=False, move=False, create=None, upload=None,
diff --git a/pywikibot/site.py b/pywikibot/site.py
index b1e9c7d..1483080 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -1411,6 +1411,7 @@
'centralauth',
'delete',
'deleteglobalaccount',
+ 'undelete',
'edit',
'email',
'import',
@@ -3657,6 +3658,7 @@
wlgen.request["wlshow"] = "|".join(wlshow)
return wlgen
+ # TODO: T75370
def deletedrevs(self, page, start=None, end=None, reverse=None,
get_text=False, step=None, total=None):
"""Iterate deleted revisions.
@@ -4114,23 +4116,64 @@
_dl_errors = {
"noapiwrite": "API editing not enabled on %(site)s wiki",
"writeapidenied": "User %(user)s not allowed to edit through the
API",
- "permissiondenied": "User %(user)s not authorized to delete pages
on %(site)s wiki.",
+ "permissiondenied": "User %(user)s not authorized to (un)delete
"
+ "pages on %(site)s wiki.",
"cantdelete": "Could not delete [[%(title)s]]. Maybe it was
deleted already.",
+ "cantundelete": "Could not undelete [[%(title)s]]. "
+ "Revision may not exist or was already undeleted."
} # other errors shouldn't occur because of pre-submission checks
@must_be(group='sysop')
- def deletepage(self, page, summary):
+ @deprecate_arg("summary", "reason")
+ def deletepage(self, page, reason):
"""Delete page from the wiki. Requires appropriate privilege
level.
@param page: Page to be deleted.
- @param summary: Edit summary (required!).
+ @type page: Page
+ @param reason: Deletion reason.
+ @type reason: basestring
"""
token = self.tokens['delete']
self.lock_page(page)
req = api.Request(site=self, action="delete", token=token,
title=page.title(withSection=False),
- reason=summary)
+ reason=reason)
+ try:
+ req.submit()
+ except api.APIError as err:
+ errdata = {
+ 'site': self,
+ 'title': page.title(withSection=False),
+ 'user': self.user(),
+ }
+ if err.code in self._dl_errors:
+ raise Error(self._dl_errors[err.code] % errdata)
+ pywikibot.debug(u"delete: Unexpected error code '%s'
received."
+ % err.code,
+ _logger)
+ raise
+ finally:
+ self.unlock_page(page)
+
+ @must_be(group='sysop')
+ @deprecate_arg("summary", "reason")
+ def undelete_page(self, page, reason, revisions=None):
+ """Undelete page from the wiki. Requires appropriate privilege
level.
+
+ @param page: Page to be deleted.
+ @type page: Page
+ @param revisions: List of timestamps to restore. If None, restores all
revisions.
+ @type revisions: list
+ @param reason: Undeletion reason.
+ @type reason: basestring
+
+ """
+ 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)
try:
req.submit()
except api.APIError as err:
diff --git a/tests/page_tests.py b/tests/page_tests.py
index a756d5d..63e5e32 100644
--- a/tests/page_tests.py
+++ b/tests/page_tests.py
@@ -575,6 +575,38 @@
self.assertTrue(rv)
+class TestPageDelete(TestCase):
+
+ """Test page delete / undelete actions."""
+
+ family = 'test'
+ code = 'test'
+
+ write = True
+ sysop = True
+
+ def test_delete(self):
+ """Test the site.delete and site.undelete
method."""
+ site = self.get_site()
+ p = pywikibot.Page(site, u'User:Unicodesnowman/DeleteTest')
+ # Ensure the page exists
+ p.text = 'pywikibot unit test page'
+ p.save('unit test', botflag=True)
+ # Test deletion
+ p.delete(reason='pywikibot unit test', prompt=False, mark=False)
+ self.assertRaises(pywikibot.NoPage, p.get, force=True)
+ # Test undeleting last two revisions
+ del_revs = list(p.loadDeletedRevisions())
+ revid = p.getDeletedRevision(del_revs[-1])[u'revid']
+ p.markDeletedRevision(del_revs[-1])
+ p.markDeletedRevision(del_revs[-2])
+ self.assertRaises(ValueError, p.markDeletedRevision, 123)
+ p.undelete(reason='pywikibot unit test')
+ revs = list(p.getVersionHistory())
+ self.assertEqual(len(revs), 2)
+ self.assertEqual(revs[1].revid, revid)
+
+
class TestPageProtect(TestCase):
"""Test page protect / unprotect actions."""
--
To view, visit
https://gerrit.wikimedia.org/r/181235
To unsubscribe, visit
https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I1eb2c158f6450bf7b4e9c3f26c83bb7674b9f766
Gerrit-PatchSet: 9
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 <>