Revision: 5780 Author: russblau Date: 2008-08-01 20:52:39 +0000 (Fri, 01 Aug 2008)
Log Message: ----------- more methods implemented
Modified Paths: -------------- branches/rewrite/pywikibot/data/api.py branches/rewrite/pywikibot/site.py
Modified: branches/rewrite/pywikibot/data/api.py =================================================================== --- branches/rewrite/pywikibot/data/api.py 2008-08-01 20:36:19 UTC (rev 5779) +++ branches/rewrite/pywikibot/data/api.py 2008-08-01 20:52:39 UTC (rev 5780) @@ -169,7 +169,8 @@ # TODO catch http errors action = self.params.get("action", "") write = action in ( - "edit", "move" + "edit", "move", "rollback", "delete", "undelete", + "protect", "block", "unblock" ) self.site.throttle(write=write) uri = self.site.scriptpath() + "/api.php"
Modified: branches/rewrite/pywikibot/site.py =================================================================== --- branches/rewrite/pywikibot/site.py 2008-08-01 20:36:19 UTC (rev 5779) +++ branches/rewrite/pywikibot/site.py 2008-08-01 20:52:39 UTC (rev 5780) @@ -743,14 +743,23 @@ self.page_embeddedin(page, filterRedirects) )
- def pagelinks(self, page, namespaces=None): - """Iterate internal wikilinks contained (or transcluded) on page.""" + def pagelinks(self, page, namespaces=None, follow_redirects=False): + """Iterate internal wikilinks contained (or transcluded) on page. + + @param namespaces: Only iterate pages in these namespaces (default: all) + @type namespaces: list of ints + @param follow_redirects: if True, yields the target of any redirects, + rather than the redirect page + + """ plgen = api.PageGenerator("links", site=self) if hasattr(page, "_pageid"): plgen.request['pageids'] = str(page._pageid) else: pltitle = page.title(withSection=False).encode(self.encoding()) plgen.request['titles'] = pltitle + if follow_redirects: + plgen.request['redirects'] = '' if namespaces is not None: plgen.request["gplnamespace"] = u"|".join(unicode(ns) for ns in namespaces) @@ -758,6 +767,7 @@
def pagecategories(self, page, withSortKey=False): """Iterate categories to which page belongs.""" + # Sortkey doesn't work with generator; FIXME or deprecate clgen = api.CategoryPageGenerator("categories", site=self) if hasattr(page, "_pageid"): @@ -1704,8 +1714,8 @@ if not recreate: raise Error("Page %s does not exist on %s wiki." % (page.title(withSection=False), self)) + token = self.token(page, "edit") self.lock_page(page) - token = self.token(page, "edit") if lastrev is not None and page.latestRevision() != lastrev: raise Error("editpage: Edit conflict detected; saving aborted.") req = api.Request(site=self, action="edit", @@ -1852,8 +1862,8 @@ if not page.exists(): raise Error("Cannot move page %s because it does not exist on %s." % (oldtitle, self)) + token = self.token(page, "move") self.lock_page(page) - token = self.token(page, "move") req = api.Request(site=self, action="move", to=newtitle, token=token, reason=summary) req['from'] = oldtitle # "from" is a python keyword @@ -1865,7 +1875,6 @@ result = req.submit() logger.debug("movepage response: %s" % result) except api.APIError, err: - self.unlock_page(page) if err.code.endswith("anon") and self.logged_in(): logger.debug( "movepage: received '%s' even though bot is logged in" % err.code) @@ -1882,7 +1891,8 @@ logger.debug("movepage: Unexpected error code '%s' received." % err.code) raise - self.unlock_page(page) + finally: + self.unlock_page(page) if "move" not in result: logger.error("movepage: %s" % result) raise Error("movepage: unexpected response") @@ -1892,11 +1902,122 @@ % (page.toggleTalkPage().title(asLink=True))) return pywikibot.Page(page, newtitle)
- + # catalog of rollback errors for use in error messages + _rb_errors = { + "noapiwrite": + "API editing not enabled on %(site)s wiki", + "writeapidenied": + "User %(user)s not allowed to edit through the API", + "alreadyrolled": + "Page [[%(title)s]] already rolled back; action aborted.", + } # other errors shouldn't arise because we check for those errors + + def rollbackpage(self, page, summary=u''): + """Roll back page to version before last user's edits. + + As a precaution against errors, this method will fail unless + the page history contains at least two revisions, and at least + one that is not by the same user who made the last edit. + + @param page: the Page to be rolled back (must exist) + @param summary: edit summary (defaults to a standardized message) + + """ + if len(page._revisions) < 2: + raise pywikibot.Error( + u"Rollback of %s aborted; load revision history first." + % page.title(asLink=True)) + last_rev = page._revisions[page.latestRevision()] + last_user = last_rev.user + for rev in sorted(page._revisions.keys(), reverse=True): + # start with most recent revision first + if rev.user != last_user: + prev_user = rev.user + break + else: + raise pywikibot.Error( + u"Rollback of %s aborted; only one user in revision history." + % page.title(asLink=True)) + summary = summary or ( +u"Reverted edits by [[Special:Contributions/%(last_user)s|%(last_user)s]] " +u"([[User talk:%(last_user)s|Talk]]) to last version by %(prev_user)s" + % locals()) + token = self.token(page, "rollback") + self.lock_page(page) + req = api.Request(site=self, action="rollback", + title=page.title(withSection=False), + user=last_user, + token=token) + try: + result = req.submit() + except api.APIError, err: + errdata = { + 'site': self, + 'title': page.title(withSection=False), + 'user': self.user(), + } + if err.code in self._rb_errors: + raise Error(self._rb_errors[err.code] % errdata) + logger.debug("rollback: Unexpected error code '%s' received." + % err.code) + raise + finally: + self.unlock_page(page) + + # catalog of delete errors for use in error messages + _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.", + "cantdelete": + "Could not delete [[%(title)s]]. Maybe it was deleted already.", + } # other errors shouldn't occur because of pre-submission checks + + def deletepage(self, page, summary): + """Delete page from the wiki. Requires appropriate privilege level. + + @param page: Page to be deleted. + @param summary: Edit summary (required!). + + """ + try: + self.login(sysop=True) + except pywikibot.Error, e: + raise Error("delete: Unable to login as sysop (%s)" + % e.__class__.__name__) + if not self.logged_in(sysop=True): + raise Error("delete: Unable to login as sysop") + token = self.token("delete") + req = api.Request(site=self, action="delete", token=token, + title=page.title(withSection=False), + reason=summary) + try: + result = req.submit() + except api.APIError, 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) + logger.debug("delete: Unexpected error code '%s' received." + % err.code) + raise + finally: + self.unlock_page(page) + + # TODO: implement undelete + + + #### METHODS NOT IMPLEMENTED YET (but may be delegated to Family object) #### class NotImplementedYet:
- def isBlocked(self, sysop = False): + def isBlocked(self, sysop=False): """Check if the user is blocked.""" try: text = self.getUrl(u'%saction=query&meta=userinfo&uiprop=blockinfo'