http://www.mediawiki.org/wiki/Special:Code/pywikipedia/9585
Revision: 9585
Author: xqt
Date: 2011-10-04 17:12:58 +0000 (Tue, 04 Oct 2011)
Log Message:
-----------
new method Page.__unicode__() from rewrite;
bugfix: save _autoFormat as attribute of Page object
ask for a reason for undeleting a page if comment parameter is None;
update doc strings from rewrite branch
Modified Paths:
--------------
trunk/pywikipedia/wikipedia.py
Modified: trunk/pywikipedia/wikipedia.py
===================================================================
--- trunk/pywikipedia/wikipedia.py 2011-10-04 17:01:33 UTC (rev 9584)
+++ trunk/pywikipedia/wikipedia.py 2011-10-04 17:12:58 UTC (rev 9585)
@@ -172,6 +172,7 @@
r"name='wpWatchthis' checked='checked'")
Rlink = re.compile(r'\[\[(?P<title>[^\]\|\[]*)(\|[^\]]*)?\]\]')
+# Page objects (defined here) represent the page itself, including its contents.
class Page(object):
"""Page: A MediaWiki page
@@ -259,6 +260,9 @@
"""
def __init__(self, site, title, insite=None, defaultNamespace=0):
+ """Instantiate a Page object.
+
+ """
try:
# if _editrestriction is True, it means that the page has been found
# to have an edit restriction, but we do not know yet whether the
@@ -427,6 +431,15 @@
"""Return the Site object for the wiki on which this Page resides."""
return self._site
+ def namespace(self):
+ """Return the number of the namespace of the page.
+
+ Only recognizes those namespaces defined in family.py.
+ If not defined, it will return 0 (the main namespace).
+
+ """
+ return self._namespace
+
def encoding(self):
"""Return the character encoding used on this Page's wiki Site."""
return self._site.encoding()
@@ -536,11 +549,37 @@
"""Return a console representation of the pagelink."""
return self.aslink().encode(config.console_encoding, 'replace')
+ def __unicode__(self):
+ return self.title(asLink=True, forceInterwiki=True)
+
def __repr__(self):
"""Return a more complete string representation."""
return "%s{%s}" % (self.__class__.__name__, str(self))
- #@deprecated("Page.title(asLink=True)")
+ def __cmp__(self, other):
+ """Test for equality and inequality of Page objects.
+
+ Page objects are "equal" if and only if they are on the same site
+ and have the same normalized title, including section if any.
+
+ Page objects are sortable by namespace first, then by title.
+
+ """
+ if not isinstance(other, Page):
+ # especially, return -1 if other is None
+ return -1
+ if self._site == other._site:
+ return cmp(self._title, other._title)
+ else:
+ return cmp(self._site, other._site)
+
+ def __hash__(self):
+ # Pseudo method that makes it possible to store Page objects as keys
+ # in hash-tables. This relies on the fact that the string
+ # representation of an instance can not change after the construction.
+ return hash(unicode(self))
+
+ @deprecated("Page.title(asLink=True)")
def aslink(self, forceInterwiki=False, textlink=False, noInterwiki=False):
"""Return a string representation in the form of a wikilink.
@@ -570,9 +609,9 @@
"""
if not hasattr(self, '_autoFormat'):
import date
- _autoFormat = date.getAutoFormat(self.site().language(),
- self.titleWithoutNamespace())
- return _autoFormat
+ self._autoFormat = date.getAutoFormat(self.site().language(),
+ self.titleWithoutNamespace())
+ return self._autoFormat
def isAutoTitle(self):
"""Return True if title of this Page is in the autoFormat dictionary."""
@@ -1321,15 +1360,6 @@
# no restricting template found
return True
- def namespace(self):
- """Return the number of the namespace of the page.
-
- Only recognizes those namespaces defined in family.py.
- If not defined, it will return 0 (the main namespace).
-
- """
- return self._namespace
-
def getReferences(self, follow_redirects=True, withTemplateInclusion=True,
onlyTemplateInclusion=False, redirectsOnly=False, internal = False):
"""Yield all pages that link to the page by API
@@ -2335,22 +2365,6 @@
allDone = True
return cats
- def __cmp__(self, other):
- """Test for equality and inequality of Page objects"""
- if not isinstance(other, Page):
- # especially, return -1 if other is None
- return -1
- if self._site == other._site:
- return cmp(self._title, other._title)
- else:
- return cmp(self._site, other._site)
-
- def __hash__(self):
- # Pseudo method that makes it possible to store Page objects as keys
- # in hash-tables. This relies on the fact that the string
- # representation of an instance can not change after the construction.
- return hash(str(self))
-
def linkedPages(self, withImageLinks = False):
"""Return a list of Pages that this Page links to.
@@ -2925,8 +2939,7 @@
def move(self, newtitle, reason=None, movetalkpage=True, movesubpages=False, sysop=False,
throttle=True, deleteAndMove=False, safe=True, fixredirects=True, leaveRedirect=True):
- """Move this page to new title given by newtitle. If safe, don't try
- to move and delete if not directly requested.
+ """Move this page to new title.
* fixredirects has no effect in MW < 1.13
@@ -2938,6 +2951,7 @@
(usually requires sysop privileges, depending on wiki settings)
@param safe: If false, attempt to delete existing page at newtitle
(if there is one) and then move this page to that title
+
"""
if not self.site().has_api() or self.site().versionnumber() < 12:
return self._moveOld(newtitle, reason, movetalkpage, sysop,
@@ -3124,14 +3138,13 @@
return False
def delete(self, reason=None, prompt=True, throttle=True, mark=False):
- """Deletes the page from the wiki.
+ """Deletes the page from the wiki. Requires administrator status.
- Requires administrator status. If reason is None, asks for a
- reason. If prompt is True, asks the user if he wants to delete the
- page.
+ @param reason: The edit summary for the deletion. If None, ask for it.
+ @param prompt: If true, prompt user for confirmation before deleting.
+ @param mark: if true, and user does not have sysop rights, place a
+ speedy-deletion request on the page instead.
- If the user does not have admin rights and mark is True,
- the page is marked for deletion instead.
"""
# Login
try:
@@ -3153,8 +3166,9 @@
if throttle:
put_throttle()
if reason is None:
+ output(u'Deleting %s.' % (self.title(asLink=True)))
reason = input(u'Please enter a reason for the deletion:')
- answer = 'y'
+ answer = u'y'
if prompt and not hasattr(self.site(), '_noDeletePrompt'):
answer = inputChoice(u'Do you want to delete %s?' % self.aslink(forceInterwiki = True), ['yes', 'no', 'all'], ['y', 'N', 'a'], 'N')
if answer == 'a':
@@ -3221,13 +3235,15 @@
output(data)
return False
- def loadDeletedRevisions(self):
+ def loadDeletedRevisions(self, step=None, total=None):
"""Retrieve all deleted revisions for this Page from Special/Undelete.
- Stores all revisions' timestamps, dates, editors and comments.
- Returns list of timestamps (which can be used to retrieve revisions
- later on).
+ Stores all revisions' timestamps, dates, editors and comments in
+ self._deletedRevs attribute.
+ @return: list of timestamps (which can be used to retrieve
+ revisions later on).
+
"""
# Login
self._getActionUser(action = 'deletedhistory', sysop = True)
@@ -3287,9 +3303,10 @@
def getDeletedRevision(self, timestamp, retrieveText=False):
"""Return a particular deleted revision by timestamp.
- Return value is a list of [date, editor, comment, text, restoration
- marker]. text will be None, unless retrieveText is True (or has been
- retrieved earlier).
+ @return: a list of [date, editor, comment, text, restoration
+ marker]. text will be None, unless retrieveText is True (or has
+ been retrieved earlier). If timestamp is not found, returns
+ None.
"""
if self._deletedRevs is None:
@@ -3314,7 +3331,7 @@
def markDeletedRevision(self, timestamp, undelete=True):
"""Mark the revision identified by timestamp for undeletion.
- If undelete is False, mark the revision to remain deleted.
+ @param undelete: if False, mark the revision to remain deleted.
"""
if self._deletedRevs is None:
@@ -3325,23 +3342,25 @@
self._deletedRevs[timestamp][4] = undelete
self._deletedRevsModified = True
- def undelete(self, comment='', throttle=True):
- """Undeletes page based on the undeletion markers set by previous calls.
+ def undelete(self, comment=None, throttle=True):
+ """Undelete page based on the undeletion markers set by previous calls.
If no calls have been made since loadDeletedRevisions(), everything
will be restored.
Simplest case:
- wikipedia.Page(...).undelete('This will restore all revisions')
+ Page(...).undelete('This will restore all revisions')
More complex:
- pg = wikipedia.Page(...)
+ pg = Page(...)
revs = pg.loadDeletedRevsions()
for rev in revs:
if ... #decide whether to undelete a revision
pg.markDeletedRevision(rev) #mark for undeletion
pg.undelete('This will restore only selected revisions.')
+ @param comment: The undeletion edit summary.
+
"""
# Login
self._getActionUser(action = 'undelete', sysop = True)
@@ -3350,6 +3369,10 @@
self.site().checkBlocks(sysop = True)
token = self.site().getToken(self, sysop=True)
+ if comment is None:
+ output(u'Preparing to undelete %s.'
+ % (self.title(asLink=True)))
+ comment = input(u'Please enter a reason for the undeletion:')
if throttle:
put_throttle()
@@ -3399,9 +3422,10 @@
return result
- def protect(self, editcreate = 'sysop', move = 'sysop', unprotect = False, reason = None, editcreate_duration = 'infinite',
+ def protect(self, editcreate='sysop', move='sysop', unprotect=False,
+ reason=None, editcreate_duration='infinite',
move_duration = 'infinite', cascading = False, prompt = True, throttle = True):
- """(Un)protect a wiki title. Requires administrator status.
+ """(Un)protect a wiki page. Requires administrator status.
If the title is not exist, the protection only ec (aka edit/create) available
If reason is None, asks for a reason. If prompt is True, asks the
@@ -4582,12 +4606,13 @@
return x
def html2unicode(text, ignore = []):
- """Replace all HTML entities in text by equivalent unicode characters."""
+ """Return text, replacing HTML entities by equivalent unicode characters."""
# This regular expression will match any decimal and hexadecimal entity and
# also entities that might be named entities.
- entityR = re.compile(r'&(#(?P<decimal>\d+)|#x(?P<hex>[0-9a-fA-F]+)|(?P<name>[A-Za-z]+));')
- #These characters are Html-illegal, but sadly you *can* find some of these and
- #converting them to unichr(decimal) is unsuitable
+ entityR = re.compile(
+ r'&(#(?P<decimal>\d+)|#x(?P<hex>[0-9a-fA-F]+)|(?P<name>[A-Za-z]+));')
+ # These characters are Html-illegal, but sadly you *can* find some of
+ # these and converting them to unichr(decimal) is unsuitable
convertIllegalHtmlEntities = {
128 : 8364, # €
130 : 8218, # ‚
@@ -4639,7 +4664,7 @@
unicodeCodepoint = htmlentitydefs.name2codepoint[name]
result += text[:match.start()]
try:
- unicodeCodepoint=convertIllegalHtmlEntities[unicodeCodepoint]
+ unicodeCodepoint = convertIllegalHtmlEntities[unicodeCodepoint]
except KeyError:
pass
if unicodeCodepoint and unicodeCodepoint not in ignore and (WIDEBUILD or unicodeCodepoint < 65534):
http://www.mediawiki.org/wiki/Special:Code/pywikipedia/9584
Revision: 9584
Author: xqt
Date: 2011-10-04 17:01:33 +0000 (Tue, 04 Oct 2011)
Log Message:
-----------
fix for default disambig set;
remove unused argument "nofollow_redirects";
minor doc changes
Modified Paths:
--------------
branches/rewrite/pywikibot/page.py
Modified: branches/rewrite/pywikibot/page.py
===================================================================
--- branches/rewrite/pywikibot/page.py 2011-10-04 14:43:39 UTC (rev 9583)
+++ branches/rewrite/pywikibot/page.py 2011-10-04 17:01:33 UTC (rev 9584)
@@ -230,7 +230,6 @@
return self.autoFormat()[0] is not None
@deprecate_arg("throttle", None)
- @deprecate_arg("nofollow_redirects", None)
@deprecate_arg("change_edit_time", None)
def get(self, force=False, get_redirect=False, sysop=False):
"""Return the wiki-text of the page.
@@ -297,7 +296,6 @@
raise self._getexception
@deprecate_arg("throttle", None)
- @deprecate_arg("nofollow_redirects", None)
@deprecate_arg("change_edit_time", None)
def getOldVersion(self, oldid, force=False, get_redirect=False,
sysop=False):
@@ -528,7 +526,7 @@
try:
default = set(self.site.family.disambig('_default'))
except KeyError:
- default = set(u'Disambig')
+ default = set([u'Disambig'])
try:
distl = self.site.family.disambig(self.site.code,
fallback=False)
@@ -1131,7 +1129,7 @@
def delete(self, reason=None, prompt=True, throttle=None, mark=False):
"""Deletes the page from the wiki. Requires administrator status.
- @param reason: The edit summary for the deletion.
+ @param reason: The edit summary for the deletion. If None, ask for it.
@param prompt: If true, prompt user for confirmation before deleting.
@param mark: if true, and user does not have sysop rights, place a
speedy-deletion request on the page instead.
@@ -1221,10 +1219,10 @@
If no calls have been made since loadDeletedRevisions(), everything
will be restored.
- Simplest case::
+ Simplest case:
Page(...).undelete('This will restore all revisions')
- More complex::
+ More complex:
pg = Page(...)
revs = pg.loadDeletedRevsions()
for rev in revs:
http://www.mediawiki.org/wiki/Special:Code/pywikipedia/9580
Revision: 9580
Author: xqt
Date: 2011-10-03 19:05:34 +0000 (Mon, 03 Oct 2011)
Log Message:
-----------
Do not edit empty pages (should also prevent wrong edits due to bug #3414669 - interwiki.py removes page text)
Modified Paths:
--------------
trunk/pywikipedia/interwiki.py
Modified: trunk/pywikipedia/interwiki.py
===================================================================
--- trunk/pywikipedia/interwiki.py 2011-10-03 16:27:16 UTC (rev 9579)
+++ trunk/pywikipedia/interwiki.py 2011-10-03 19:05:34 UTC (rev 9580)
@@ -1740,6 +1740,11 @@
pywikibot.output(u"Not editing %s: page does not exist"
% page.aslink(True))
raise SaveError
+ if page.isEmpty():
+ pywikibot.output(u"Not editing %s: page is empty"
+ % page.aslink(True))
+ raise SaveError
+
# clone original newPages dictionary, so that we can modify it to the
# local page's needs
http://www.mediawiki.org/wiki/Special:Code/pywikipedia/9578
Revision: 9578
Author: xqt
Date: 2011-10-03 15:59:59 +0000 (Mon, 03 Oct 2011)
Log Message:
-----------
fix comments for getall methods
Modified Paths:
--------------
trunk/pywikipedia/wikipedia.py
Modified: trunk/pywikipedia/wikipedia.py
===================================================================
--- trunk/pywikipedia/wikipedia.py 2011-10-03 14:53:28 UTC (rev 9577)
+++ trunk/pywikipedia/wikipedia.py 2011-10-03 15:59:59 UTC (rev 9578)
@@ -36,7 +36,7 @@
put_throttle: Call to limit rate of write-access to wiki
Other functions:
- getall(): Load a group of pages via Special:Export
+ getall(): Load a group of pages
handleArgs(): Process all standard command line arguments (such as
-family, -lang, -log and others)
translate(xx, dict): dict is a dictionary, giving text depending on
@@ -4041,7 +4041,7 @@
self._norm = dict([(x['from'],x['to']) for x in data['query']['normalized']])
for vals in data['query']['pages'].values():
self.oneDoneApi(vals)
- else:
+ else: #read pages via Special:Export
while True:
try:
data = self.getData()
@@ -4383,7 +4383,7 @@
return query.GetData(params, self.site)
def getall(site, pages, throttle=True, force=False):
- """Use Special:Export to bulk-retrieve a group of pages from site
+ """Bulk-retrieve a group of pages from site
Arguments: site = Site object
pages = iterable that yields Page objects