John Vandenberg has submitted this change and it was merged.
Change subject: Add Page.contributors() and .revision_count() ......................................................................
Add Page.contributors() and .revision_count()
deprecates: - Page - contributingUsers - checkImagesBot - countEdits - botolist - project - botnick
Change-Id: Iee0fbd7337b70a4091292938e6d81764a5b4ff43 --- M pywikibot/page.py M scripts/checkimages.py M tests/page_tests.py 3 files changed, 118 insertions(+), 33 deletions(-)
Approvals: XZise: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/page.py b/pywikibot/page.py index f38dc5c..6b89b8a 100644 --- a/pywikibot/page.py +++ b/pywikibot/page.py @@ -1425,6 +1425,20 @@ step=step, total=total) ]
+ def contributors(self, step=None, total=None): + """ + Compile contributors of this page with edit counts. + + @param step: limit each API call to this number of revisions + @param total: iterate no more than this number of revisions in total + + @return: number of edits for each username + @rtype: L{collections.Counter} + """ + return Counter(rev.user for rev in + self.revisions(step=step, total=total)) + + @deprecated('contributors()') def contributingUsers(self, step=None, total=None): """Return a set of usernames (or IPs) of users who edited this page.
@@ -1432,8 +1446,23 @@ @param total: iterate no more than this number of revisions in total
""" - return set(entry.user for entry in self.revisions(step=step, - total=total)) + return self.contributors(step=step, total=total).keys() + + def revision_count(self, contributors=None): + """ + Determine number of edits from a set of contributors. + + @param contributors: contributor usernames + @type contributors: iterable of str + + @return: number of edits for all provided usernames + @rtype: int + """ + if not contributors: + return len(list(self.revisions())) + + cnt = self.contributors() + return sum(cnt[username] for username in contributors)
@deprecated('oldest_revision') def getCreator(self): @@ -1446,7 +1475,7 @@ result = self.oldest_revision return result.user, result.timestamp
- @deprecated('revisions') + @deprecated('contributors() or revisions()') @deprecated_args(limit="total") def getLatestEditors(self, total=1): """Get a list of revision informations of the last total edits. diff --git a/scripts/checkimages.py b/scripts/checkimages.py index 41b0aac..9e3377d 100644 --- a/scripts/checkimages.py +++ b/scripts/checkimages.py @@ -93,9 +93,11 @@ import sys
import pywikibot + from pywikibot import pagegenerators as pg -from pywikibot import config, i18n +from pywikibot import i18n from pywikibot.family import Family +from pywikibot.tools import deprecated
if sys.version_info[0] > 2: basestring = (str, ) @@ -312,7 +314,7 @@ }
# This is a list of what bots used this script in your project. -# NOTE: YOUR Botnick is automatically added. It's not required to add it twice. +# NOTE: YOUR Bot username will be automatically added. bot_list = { 'commons': [u'Siebot', u'CommonsDelinker', u'Filbot', u'John Bot', u'Sz-iwbot', u'ABFbot'], @@ -611,20 +613,11 @@ PageWithAllowedTemplates) self.comment = i18n.translate(self.site, msg_comm, fallback=True) # Adding the bot's nickname at the notification text if needed. - botolist = i18n.translate(self.site, bot_list) - project = site.family.name - self.project = project - bot = config.usernames[project] - try: - botnick = bot[self.site.code] - except KeyError: - raise pywikibot.NoUsername( - u"You have to specify an username for your bot in this project " - u"in the user-config.py file.") - - self.botnick = botnick - botolist.append(botnick) - self.botolist = botolist + self.bots = i18n.translate(self.site, bot_list) + if self.bots: + self.bots.append(site.username()) + else: + self.bots = [site.username()]
self.sendemailActive = sendemailActive self.skip_list = [] @@ -633,6 +626,26 @@ self.image_namespace = u"File:" # Load the licenses only once, so do it once self.list_licenses = self.load_licenses() + + @property + @deprecated + def project(self): + return self.site.family.name + + @property + @deprecated + def botolist(self): + return self.bots + + @botolist.setter + @deprecated + def botolist(self, value): + self.bots = value + + @property + @deprecated + def botnick(self): + return self.site.username()
def setParameters(self, imageName): """ @@ -655,10 +668,10 @@ self.notification2 = notification2
if self.notification: - self.notification = re.sub(r'__botnick__', self.botnick, + self.notification = re.sub(r'__botnick__', self.site.username(), notification) if self.notification2: - self.notification2 = re.sub(r'__botnick__', self.botnick, + self.notification2 = re.sub(r'__botnick__', self.site.username(), notification2) self.commTalk = commTalk self.commImage = commImage or self.comment @@ -771,13 +784,12 @@ pywikibot.output( u'The latest user that has written something is: %s' % latest_user) - for i in self.botolist: - if latest_user == i: - second_text = True - # A block to prevent the second message if the bot also - # welcomed users... - if history[0]['timestamp'] == history[-1]['timestamp']: - second_text = False + if latest_user in self.bots: + second_text = True + # A block to prevent the second message if the bot also + # welcomed users... + if history[0]['timestamp'] == history[-1]['timestamp']: + second_text = False except pywikibot.IsRedirectPage: pywikibot.output( u'The user talk is a redirect, trying to get the right talk...') @@ -878,12 +890,13 @@ if not not_the_oldest: return imageName
+ @deprecated('Page.revision_count()') def countEdits(self, pagename, userlist): """Function to count the edit of a user or a list of users in a page.""" if isinstance(userlist, basestring): userlist = [userlist] page = pywikibot.Page(self.site, pagename) - return sum(1 for rev in page.revisions() if rev.user in userlist) + return page.revision_count(userlist)
def checkImageOnCommons(self): """Checking if the file is on commons.""" @@ -1040,8 +1053,8 @@ # (the last) if len(images_to_tag_list) > 1: for image_to_tag in images_to_tag_list[:-1]: - already_reported_in_past = self.countEdits( - u'File:%s' % image_to_tag, self.botolist) + fp = pywikibot.FilePage(self.site, image_to_tag) + already_reported_in_past = fp.revision_count(self.bots) # if you want only one edit, the edit found should be # more than 0 -> num - 1 if already_reported_in_past > duplicates_rollback - 1: @@ -1056,8 +1069,8 @@ commImage=dupComment_image, unver=True)
if len(images_to_tag_list) != 0 and not only_report: - already_reported_in_past = self.countEdits( - u'File:%s' % images_to_tag_list[-1], self.botolist) + fp = pywikibot.FilePage(self.site, images_to_tag_list[-1]) + already_reported_in_past = fp.revision_count(self.bots) from_regex = (r'\n*[[:File:%s]]' % re.escape(self.image.title(asUrl=True))) # Delete the image in the list where we're write on diff --git a/tests/page_tests.py b/tests/page_tests.py index bc77765..4a2facf 100644 --- a/tests/page_tests.py +++ b/tests/page_tests.py @@ -620,6 +620,49 @@ % (page.text, page.botMayEdit(), user))
+class TestPageHistory(DefaultSiteTestCase): + + """Test history related functionality.""" + + cached = True + + def test_revisions(self): + """Test Page.revisions().""" + mp = self.get_mainpage() + revs = mp.revisions() + revs = iter(revs) # implicit assertion + revs = list(revs) + self.assertGreater(len(revs), 1) + + def test_contributors(self): + """Test Page.contributors().""" + mp = self.get_mainpage() + cnt = mp.contributors() + self.assertIsInstance(cnt, dict) + self.assertGreater(len(cnt), 1) + + def test_revision_count(self): + """Test Page.edit_count().""" + mp = self.get_mainpage() + rev_count = len(list(mp.revisions())) + self.assertEqual(rev_count, mp.revision_count()) + cnt = mp.contributors() + self.assertEqual(rev_count, sum(cnt.values())) + + top_two = cnt.most_common(2) + self.assertIsInstance(top_two, list) + self.assertEqual(len(top_two), 2) + self.assertIsInstance(top_two[0], tuple) + self.assertIsInstance(top_two[0][0], basestring) + self.assertIsInstance(top_two[0][1], int) + top_two_usernames = set([top_two[0][0], top_two[1][0]]) + self.assertEqual(len(top_two_usernames), 2) + top_two_counts = ([top_two[0][1], top_two[1][1]]) + top_two_edit_count = mp.revision_count(top_two_usernames) + self.assertIsInstance(top_two_edit_count, int) + self.assertEqual(top_two_edit_count, sum(top_two_counts)) + + class TestPageRedirects(TestCase):
"""Test redirects."""