Revision: 5921
Author: russblau
Date: 2008-09-26 19:35:08 +0000 (Fri, 26 Sep 2008)
Log Message:
-----------
Made site.userinfo a property; fixed api.update_page to store page text; added tests, tests, and more tests.
Modified Paths:
--------------
branches/rewrite/pywikibot/data/api.py
branches/rewrite/pywikibot/site.py
branches/rewrite/pywikibot/tests/site_tests.py
Modified: branches/rewrite/pywikibot/data/api.py
===================================================================
--- branches/rewrite/pywikibot/data/api.py 2008-09-26 12:34:30 UTC (rev 5920)
+++ branches/rewrite/pywikibot/data/api.py 2008-09-26 19:35:08 UTC (rev 5921)
@@ -576,14 +576,28 @@
"Page %s has neither 'pageid' nor 'missing' attribute"
% pagedict['title'])
page._redir = 'redirect' in pagedict
- if 'lastrevid' in pagedict:
- page._revid = pagedict['lastrevid']
if 'touched' in pagedict:
page._timestamp = pagedict['touched']
if 'protection' in pagedict:
page._protection = {}
for item in pagedict['protection']:
page._protection[item['type']] = item['level'], item['expiry']
+ if 'revisions' in pagedict:
+ for rev in pagedict['revisions']:
+ revision = pywikibot.page.Revision(
+ revid=rev['revid'],
+ timestamp=rev['timestamp'],
+ user=rev['user'],
+ anon=rev.has_key('anon'),
+ comment=rev.get('comment', u''),
+ minor=rev.has_key('minor'),
+ text=rev.get('*', None)
+ )
+ page._revisions[revision.revid] = revision
+ if 'lastrevid' in pagedict:
+ page._revid = pagedict['lastrevid']
+ if page._revid in page._revisions:
+ page._text = page._revisions[page._revid].text
if __name__ == "__main__":
Modified: branches/rewrite/pywikibot/site.py
===================================================================
--- branches/rewrite/pywikibot/site.py 2008-09-26 12:34:30 UTC (rev 5920)
+++ branches/rewrite/pywikibot/site.py 2008-09-26 19:35:08 UTC (rev 5921)
@@ -207,7 +207,6 @@
return self.family.langs.keys()
-
def validLanguageLinks(self):
"""Return list of language codes that can be used in interwiki links."""
@@ -368,9 +367,6 @@
## Site methods from version 1.0 (as these are implemented in this file,
## or declared deprecated/obsolete, they will be removed from this list)
##########
-## validLanguageLinks: A list of language codes that can be used in interwiki
-## links.
-##
## messages: return True if there are new messages on the site
## cookies: return user's cookies as a string
##
@@ -379,24 +375,8 @@
## postForm: Post form data to an address at this site.
## postData: Post encoded form data to an http address at this site.
##
-## redirect: Return the localized redirect tag for the site.
-## redirectRegex: Return compiled regular expression matching on redirect
-## pages.
-## mediawiki_message: Retrieve the text of a specified MediaWiki message
-## has_mediawiki_message: True if this site defines specified MediaWiki
-## message
-##
## shared_image_repository: Return tuple of image repositories used by this
## site.
-## category_on_one_line: Return True if this site wants all category links
-## on one line.
-## interwiki_putfirst: Return list of language codes for ordering of
-## interwiki links.
-## linkto(title): Return string in the form of a wikilink to 'title'
-## isInterwikiLink(s): Return True if 's' is in the form of an interwiki
-## link.
-## getSite(lang): Return Site object for wiki in same family, language
-## 'lang'.
## version: Return MediaWiki version string from Family file.
## versionnumber: Return int identifying the MediaWiki version.
## live_version: Return version number read from Special:Version.
@@ -413,7 +393,6 @@
## newimages(): Special:Log&type=upload
## longpages(): Special:Longpages
## shortpages(): Special:Shortpages
-## categories(): Special:Categories (yields Category objects)
## deadendpages(): Special:Deadendpages
## ancientpages(): Special:Ancientpages
## lonelypages(): Special:Lonelypages
@@ -459,16 +438,7 @@
return
# ANYTHING BELOW THIS POINT IS NOT YET IMPLEMENTED IN __init__()
- self._mediawiki_messages = {}
self.nocapitalize = self.__code in self.family.nocapitalize
- self._userData = [False, False]
- self._userName = [None, None]
- self._isLoggedIn = [None, None]
- self._isBlocked = [None, None]
- self._messages = [None, None]
- self._rights = [None, None]
- self._token = [None, None]
- self._cookies = [None, None]
# Calculating valid languages took quite long, so we calculate it once
# in initialization instead of each time it is used.
self._validlanguages = []
@@ -482,9 +452,9 @@
@param sysop: if True, require sysop privileges.
"""
- if self.getuserinfo()['name'] != self._username:
+ if self.userinfo['name'] != self._username:
return False
- return (not sysop) or 'sysop' in self.getuserinfo()['groups']
+ return (not sysop) or 'sysop' in self.userinfo['groups']
def loggedInAs(self, sysop = False):
"""Return the current username if logged in, otherwise return None.
@@ -501,7 +471,7 @@
self._getsiteinfo()
# check whether a login cookie already exists for this user
if hasattr(self, "_userinfo"):
- if self._userinfo['name'] == self._username:
+ if self.userinfo['name'] == self._username:
return
if not self.logged_in(sysop):
loginMan = api.LoginManager(site=self, sysop=sysop,
@@ -544,6 +514,8 @@
self._userinfo = uidata['query']['userinfo']
return self._userinfo
+ userinfo = property(fget=getuserinfo, doc=getuserinfo.__doc__)
+
def is_blocked(self, sysop=False):
"""Return true if and only if user is blocked.
@@ -685,6 +657,7 @@
return self._siteinfo
def case(self):
+ """Return this site's capitalization rule."""
return self.siteinfo['case']
@@ -840,7 +813,7 @@
% (len(cache), self)
)
for pagedata in rvgen:
-# logger.debug("Preloading %s" % pagedata)
+ logger.debug("Preloading %s" % pagedata)
try:
if pagedata['title'] not in cache:
raise Error(
@@ -914,7 +887,7 @@
if filterRedirects is not None:
blgen.request["gblfilterredir"] = filterRedirects and "redirects"\
or "nonredirects"
- if followRedirects:
+ if followRedirects: #FIXME This doesn't work correctly
blgen.request["gblredirect"] = ""
return blgen
@@ -1819,22 +1792,22 @@
"deletedrevs: start must be later than end with reverse=False")
if not self.logged_in():
self.login()
- if "deletedhistory" not in self.getuserinfo()['rights']:
+ if "deletedhistory" not in self.userinfo['rights']:
try:
self.login(True)
except NoUsername:
pass
- if "deletedhistory" not in self.getuserinfo()['rights']:
+ if "deletedhistory" not in self.userinfo['rights']:
raise Error(
"deletedrevs: User:%s not authorized to access deleted revisions."
% self.user())
if get_text:
- if "undelete" not in self.getuserinfo()['rights']:
+ if "undelete" not in self.userinfo['rights']:
try:
self.login(True)
except NoUsername:
pass
- if "undelete" not in self.getuserinfo()['rights']:
+ if "undelete" not in self.userinfo['rights']:
raise Error(
"deletedrevs: User:%s not authorized to view deleted content."
% self.user())
@@ -1958,7 +1931,7 @@
req['minor'] = ""
elif notminor:
req['notminor'] = ""
- if 'bot' in self.getuserinfo()['groups']:
+ if 'bot' in self.userinfo['groups']:
req['bot'] = ""
if recreate:
req['recreate'] = ""
Modified: branches/rewrite/pywikibot/tests/site_tests.py
===================================================================
--- branches/rewrite/pywikibot/tests/site_tests.py 2008-09-26 12:34:30 UTC (rev 5920)
+++ branches/rewrite/pywikibot/tests/site_tests.py 2008-09-26 19:35:08 UTC (rev 5921)
@@ -20,93 +20,132 @@
class TestSiteObject(unittest.TestCase):
"""Test cases for Site methods."""
+ def assertType(self, obj, cls):
+ """Assert that obj is an instance of type cls"""
+ return self.assertTrue(isinstance(obj, cls))
+
def testBaseMethods(self):
"""Test cases for BaseSite methods"""
self.assertEqual(mysite.family.name, pywikibot.config.family)
self.assertEqual(mysite.code, pywikibot.config.mylang)
- self.assertTrue(isinstance(mysite.language(), basestring))
- self.assertTrue(isinstance(mysite == pywikibot.Site("en", "wikipedia"),
- bool))
- self.assertTrue(isinstance(mysite.user(), (basestring, type(None))))
+ self.assertType(mysite.lang, basestring)
+ self.assertType(mysite == pywikibot.Site("en", "wikipedia"), bool)
+ self.assertType(mysite.user(), (basestring, type(None)))
self.assertEqual(mysite.sitename(),
- "%s:%s" % (pywikibot.config.family, pywikibot.config.mylang))
+ "%s:%s" % (pywikibot.config.family,
+ pywikibot.config.mylang))
self.assertEqual(repr(mysite),
'Site("%s", "%s")'
% (pywikibot.config.mylang, pywikibot.config.family))
- self.assertTrue(isinstance(mysite.linktrail(), basestring))
+ self.assertType(mysite.linktrail(), basestring)
+ self.assertType(mysite.redirect(default=True), basestring)
+ self.assertType(mysite.disambcategory(), pywikibot.Category)
+ self.assertEqual(mysite.linkto("foo"), u"[[Foo]]")
+ self.assertFalse(mysite.isInterwikiLink("foo"))
+ self.assertType(mysite.redirectRegex().pattern, basestring)
+ self.assertType(mysite.category_on_one_line(), bool)
+ for grp in ("user", "autoconfirmed", "bot", "sysop", "nosuchgroup"):
+ self.assertType(mysite.has_group(grp), bool)
+ for rgt in ("read", "edit", "move", "delete", "rollback", "block",
+ "nosuchright"):
+ self.assertType(mysite.has_right(rgt), bool)
+
+ def testLanguageMethods(self):
+ """Test cases for languages() and related methods"""
+
langs = mysite.languages()
- self.assertTrue(isinstance(langs, list))
+ self.assertType(langs, list)
self.assertTrue(mysite.code in langs)
obs = mysite.family.obsolete
ipf = mysite.interwiki_putfirst()
- self.assertTrue(isinstance(ipf, list))
- for item in ipf:
- self.assertTrue(item in langs or item in obs)
- self.assertEqual(mysite.ns_index("Talk"), 1)
+ self.assertType(ipf, list)
+ self.assertTrue(all(item in langs or item in obs
+ for item in ipf))
+ self.assertTrue(all(item in langs
+ for item in mysite.validLanguageLinks()))
+
+ def testNamespaceMethods(self):
+ """Test cases for methods manipulating namespace names"""
+
+ builtins = {'Talk': 1, # these should work in any MW wiki
+ 'User': 2,
+ 'User talk': 3,
+ 'Project': 4,
+ 'Project talk': 5,
+ 'Image': 6,
+ 'Image talk': 7,
+ 'MediaWiki': 8,
+ 'MediaWiki talk': 9,
+ 'Template': 10,
+ 'Template talk': 11,
+ 'Help': 12,
+ 'Help talk': 13,
+ 'Category': 14,
+ 'Category talk': 15,
+ }
+ self.assertTrue(all(mysite.ns_index(b) == builtins[b]
+ for b in builtins))
ns = mysite.namespaces()
- self.assertTrue(isinstance(ns, dict))
- for x in xrange(0, 16): # built-in namespaces always present
- self.assertTrue(x in ns)
- self.assertTrue(isinstance(ns[x], list))
- self.assertTrue(isinstance(mysite.ns_normalize("project"), basestring))
- self.assertTrue(isinstance(mysite.redirect(), basestring))
- self.assertTrue(isinstance(mysite.disambcategory(), pywikibot.Category))
- self.assertTrue(isinstance(mysite.redirectRegex().pattern, basestring))
- self.assertTrue(isinstance(mysite.category_on_one_line(), bool))
- for grp in ("user", "autoconfirmed", "bot", "sysop", "nosuchgroup"):
- self.assertTrue(isinstance(mysite.has_group(grp), bool))
- for rgt in ("read", "edit", "move", "delete", "rollback", "block",
- "nosuchright"):
- self.assertTrue(isinstance(mysite.has_right(rgt), bool))
-
- def testApiMethods(self):
- """Test generic ApiSite methods"""
-
- self.assertTrue(isinstance(mysite.logged_in(), bool))
- self.assertTrue(isinstance(mysite.getuserinfo(), dict))
- self.assertTrue(isinstance(mysite.is_blocked(), bool))
- self.assertTrue(isinstance(mysite.messages(), bool))
- self.assertTrue(isinstance(mysite.getcurrenttimestamp(), basestring))
- self.assertTrue(isinstance(mysite.siteinfo, dict))
- self.assertTrue(isinstance(mysite.case(), basestring))
- self.assertTrue(isinstance(mysite.namespaces(), dict))
+ self.assertType(ns, dict)
+ self.assertTrue(all(x in ns for x in xrange(0, 16)))
+ # built-in namespaces always present
+ self.assertType(mysite.ns_normalize("project"), basestring)
self.assertTrue(all(isinstance(key, int)
- for key in mysite.namespaces()))
+ for key in ns))
self.assertTrue(all(isinstance(val, list)
- for val in mysite.namespaces().values()))
+ for val in ns.values()))
self.assertTrue(all(isinstance(name, basestring)
- for val in mysite.namespaces().values()
+ for val in ns.values()
for name in val))
self.assertTrue(all(isinstance(mysite.namespace(key), basestring)
- for key in mysite.namespaces()))
+ for key in ns))
self.assertTrue(all(isinstance(mysite.namespace(key, True), list)
- for key in mysite.namespaces()))
+ for key in ns))
self.assertTrue(all(isinstance(item, basestring)
- for key in mysite.namespaces()
+ for key in ns
for item in mysite.namespace(key, True)))
- ver = mysite.live_version()
- self.assertTrue(isinstance(ver, tuple))
- self.assertTrue(all(isinstance(ver[i], int) for i in (0, 1)))
- self.assertTrue(isinstance(ver[2], basestring))
+
+ def testApiMethods(self):
+ """Test generic ApiSite methods"""
+
+ self.assertType(mysite.logged_in(), bool)
+ self.assertType(mysite.logged_in(True), bool)
+ self.assertType(mysite.userinfo, dict)
+ self.assertType(mysite.is_blocked(), bool)
+ self.assertType(mysite.is_blocked(True), bool)
+ self.assertType(mysite.messages(), bool)
+ self.assertType(mysite.has_right("edit"), bool)
+ self.assertFalse(mysite.has_right("nonexistent_right"))
+ self.assertType(mysite.has_right("edit", True), bool)
+ self.assertFalse(mysite.has_right("nonexistent_right", True))
+ self.assertType(mysite.has_group("bots"), bool)
+ self.assertFalse(mysite.has_group("nonexistent_group"))
+ self.assertType(mysite.has_group("bots", True), bool)
+ self.assertFalse(mysite.has_group("nonexistent_group", True))
for msg in ("1movedto2", "about", "aboutpage", "aboutsite",
"accesskey-n-portal"):
self.assertTrue(mysite.has_mediawiki_message(msg))
- self.assertTrue(isinstance(mysite.mediawiki_message(msg),
- basestring))
+ self.assertType(mysite.mediawiki_message(msg), basestring)
self.assertFalse(mysite.has_mediawiki_message("nosuchmessage"))
self.assertRaises(KeyError, mysite.mediawiki_message, "nosuchmessage")
+ self.assertType(mysite.getcurrenttimestamp(), basestring)
+ self.assertType(mysite.siteinfo, dict)
+ self.assertType(mysite.case(), basestring)
+ ver = mysite.live_version()
+ self.assertType(ver, tuple)
+ self.assertTrue(all(isinstance(ver[i], int) for i in (0, 1)))
+ self.assertType(ver[2], basestring)
def testPageMethods(self):
"""Test ApiSite methods for getting page-specific info"""
- self.assertTrue(isinstance(mysite.page_exists(mainpage), bool))
- self.assertTrue(isinstance(mysite.page_restrictions(mainpage), dict))
- self.assertTrue(isinstance(mysite.page_can_be_edited(mainpage), bool))
- self.assertTrue(isinstance(mysite.page_isredirect(mainpage), bool))
+ self.assertType(mysite.page_exists(mainpage), bool)
+ self.assertType(mysite.page_restrictions(mainpage), dict)
+ self.assertType(mysite.page_can_be_edited(mainpage), bool)
+ self.assertType(mysite.page_isredirect(mainpage), bool)
if mysite.page_isredirect(mainpage):
- self.assertTrue(isinstance(mysite.getredirtarget(mainpage),
- pywikibot.Page))
+ self.assertType(mysite.getredirtarget(mainpage), pywikibot.Page)
else:
self.assertRaises(pywikibot.IsNotRedirectPage,
mysite.getredirtarget, mainpage)
@@ -119,9 +158,22 @@
"""Test ability to get page tokens"""
for ttype in ("edit", "move"): # token types for non-sysops
- self.assertTrue(isinstance(mysite.token(mainpage, ttype),
- basestring))
+ self.assertType(mysite.token(mainpage, ttype), basestring)
+ self.assertRaises(KeyError, mysite.token, mainpage, "invalidtype")
+ def testPreload(self):
+ """Test that preloading works"""
+
+ count = 0
+ for page in mysite.preloadpages(mysite.pagelinks(mainpage)):
+ self.assertType(page, pywikibot.Page)
+ self.assertType(page.exists(), bool)
+ if page.exists():
+ self.assertTrue(hasattr(page, "_text"))
+ count += 1
+ if count >= 5:
+ break
+
def testLinkMethods(self):
"""Test site methods for getting links to and from a page"""
@@ -129,25 +181,41 @@
embedded = set(mysite.page_embeddedin(mainpage, namespaces=[0]))
refs = set(mysite.pagereferences(mainpage, namespaces=[0]))
for bl in backlinks:
- self.assertTrue(isinstance(bl, pywikibot.Page))
+ self.assertType(bl, pywikibot.Page)
self.assertTrue(bl in refs)
for ei in embedded:
- self.assertTrue(isinstance(ei, pywikibot.Page))
+ self.assertType(ei, pywikibot.Page)
self.assertTrue(ei in refs)
for ref in refs:
self.assertTrue(ref in backlinks or ref in embedded)
+ # test backlinks arguments
+ self.assertTrue(backlinks.issubset(
+ set(mysite.pagebacklinks(mainpage,
+ followRedirects=True,
+ namespaces=[0]))))
+ self.assertTrue(backlinks.issuperset(
+ set(mysite.pagebacklinks(mainpage,
+ filterRedirects=True,
+ namespaces=[0]))))
+ self.assertTrue(backlinks.issuperset(
+ set(mysite.pagebacklinks(mainpage,
+ filterRedirects=False,
+ namespaces=[0]))))
+ self.assertTrue(backlinks.issubset(
+ set(mysite.pagebacklinks(mainpage, namespaces=[0, 2]))))
+ #
for pl in mysite.pagelinks(mainpage):
- self.assertTrue(isinstance(pl, pywikibot.Page))
+ self.assertType(pl, pywikibot.Page)
for cat in mysite.pagecategories(mainpage):
- self.assertTrue(isinstance(cat, pywikibot.Category))
+ self.assertType(cat, pywikibot.Category)
for cm in mysite.categorymembers(cat):
- self.assertTrue(isinstance(cat, pywikibot.Page))
+ self.assertType(cat, pywikibot.Page)
self.assertTrue(all(isinstance(im, pywikibot.ImagePage)
for im in mysite.pageimages(mainpage)))
self.assertTrue(all(isinstance(te, pywikibot.Page)
for te in mysite.pagetemplates(mainpage)))
for ll in mysite.pagelanglinks(mainpage):
- self.assertTrue(isinstance(ll, pywikibot.Link))
+ self.assertType(ll, pywikibot.Link)
self.assertTrue(all(isinstance(el, basestring)
for el in mysite.page_extlinks(mainpage)))
@@ -165,7 +233,7 @@
ap = list(mysite.allpages(limit=10))
self.assertTrue(len(ap) <= 10)
for page in ap:
- self.assertTrue(isinstance(page, pywikibot.Page))
+ self.assertType(page, pywikibot.Page)
self.assertTrue(mysite.page_exists(page))
# TODO: test various optional arguments to allpages
@@ -192,7 +260,7 @@
au = list(mysite.allusers(limit=10))
self.assertTrue(len(au) <= 10)
for user in au:
- self.assertTrue(isinstance(user, dict))
+ self.assertType(user, dict)
self.assertTrue(user.has_key("name"))
self.assertTrue(user.has_key("editcount"))
self.assertTrue(user.has_key("registration"))
@@ -291,7 +359,7 @@
us = list(mysite.users([mysite.user()]))
self.assertEqual(len(us), 1)
- self.assertTrue(isinstance(us[0], dict))
+ self.assertType(us[0], dict)
def testRandompages(self):
"""Test the site.randompages() method"""