jenkins-bot has submitted this change and it was merged.
Change subject: Implement wbsetclaim function ......................................................................
Implement wbsetclaim function
wbsetclaim lets us add a claim and reference in one edit, but requires us to create the serialized object ourselves.
Also added in proper handling of ranks.
Code based on Aude's PHP implementation
Change-Id: I599bd354c3e201149fd799b71937be0d7cc79f8e --- M pywikibot/page.py M pywikibot/site.py 2 files changed, 119 insertions(+), 13 deletions(-)
Approvals: Ladsgroup: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/page.py b/pywikibot/page.py index 52e792a..bee1461 100644 --- a/pywikibot/page.py +++ b/pywikibot/page.py @@ -2693,6 +2693,7 @@ self.qualifiers = {} self.target = None self.snaktype = 'value' + self.rank = 'normal' self.on_item = None # The item it's on
@staticmethod @@ -2722,6 +2723,7 @@ else: #This covers string type claim.target = data['mainsnak']['datavalue']['value'] + claim.rank = data['rank'] if 'references' in data: for source in data['references']: claim.sources.append(Claim.referenceFromJSON(site, source)) @@ -2755,7 +2757,6 @@ """ wrap = {'mainsnak': data} return Claim.fromJSON(site, wrap) -
def setTarget(self, value): """ @@ -2792,6 +2793,12 @@ """ return self.target
+ def getRank(self): + return self.rank + + def setRank(self): + raise NotImplementedError + def getSnakType(self): """ Returns the "snaktype" @@ -2822,8 +2829,9 @@
def addSource(self, source, **kwargs): """ - source is a Claim. - adds it as a reference. + Adds a reference to the current claim + @param source: reference to add + @type source: pywikibot.Claim """ data = self.repo.editSource(self, source, new=True, **kwargs) source.hash = data['reference']['hash'] @@ -2833,6 +2841,7 @@ def _formatDataValue(self): """ Format the target into the proper JSON datavalue that Wikibase wants + @return: dict|basestring """ if self.getType() == 'wikibase-item': value = {'entity-type': 'item', @@ -2847,6 +2856,32 @@ raise NotImplementedError('%s datatype is not supported yet.' % self.getType()) return value
+ def _buildMainSnak(self): + """ + Builds the full mainsnak that Wikibase wants + @return: dict + """ + if self.getType() == 'wikibase-item': + datavalue = { + 'type': 'wikibase-entityid', + 'value': self._formatDataValue() + } + elif self.getType() in ['string', 'commonsMedia']: + datavalue = { + 'type': 'string', + 'value': self._formatDataValue() + } + elif self.getType() == 'globecoordinate': + datavalue = { + 'type': 'globecoordinate', + 'value': self._formatDataValue() + } + else: + raise NotImplementedError('%s datatype is not supported yet.' % self.getType()) + return datavalue + + +
diff --git a/pywikibot/site.py b/pywikibot/site.py index bca3feb..31ce3d5 100644 --- a/pywikibot/site.py +++ b/pywikibot/site.py @@ -17,6 +17,7 @@ import datetime import itertools import os +from random import randint import re import sys import threading @@ -3460,6 +3461,85 @@ item.claims[claim.getID()] = [claim] item.lastrevid = data['pageinfo']['lastrevid']
+ def setClaim(self, item, claim, bot=True, **kwargs): + """ + Implementation of wbsetclaim + The advantage of using this is that we can create + the reference in the same edit as adding the claim + @param item: Item to add a claim on + @type item: pywikibot.ItemPage + @param claim: Claim to add. This claim can have references + @type claim: pywikibot.Claim + @param bot: Mark edit as bot + @type bot: bool + @return: dict + """ + if claim.getSnakType() != 'value': + raise NotImplementedError + # Assemble the claim thingy + data = { + 'id': self.generateGUID(item), + 'mainsnak': { + 'snaktype': claim.getSnakType(), + 'property': claim.getID(), + 'datavalue': claim._buildMainSnak(), + }, + 'type': 'statement', + 'rank': claim.getRank(), + 'references': [], + } + if claim.sources: + # FIXME: Only the first ref will be added + ref = claim.sources[0] + data['references'].append({ + 'snaks': { + ref.getID(): [{ + 'snaktype': 'value', # FIXME: Support multiple snaktypes + 'property': ref.getID(), + 'datavalue': ref._buildMainSnak(), + }] + } + }) + + params = { + 'action': 'wbsetclaim', + 'claim': json.dumps(data), + 'token': self.token(item, 'edit'), + 'baserevid': item.lastrevid, + } + if bot: + params['bot'] = 1 + + req = api.Request(site=self, **params) + data = req.submit() + if claim.getID() in item.claims: + item.claims[claim.getID()].append(claim) + else: + item.claims[claim.getID()] = [claim] + item.lastrevid = data['pageinfo']['lastrevid'] + claim.on_item = item + + def generateGUID(self, item): + """ + Function to generate a random GUID, converted from the + one in Wikibase in PHP + @param item: item the guid is for + @type item: pywikibot.ItemPage + @return: str + """ + fmt = '{0:04X}{0:04X}-{0:04X}-{0:04X}-{0:04X}-{0:04X}{0:04X}{0:04X}' + string = fmt.format( + randint(0, 65535), + randint(0, 65535), + randint(0, 65535), + randint(16384, 20479), + randint(32768, 49151), + randint(0, 65535), + randint(0, 65535), + randint(0, 65535), + ) + return item.getID() + '$' + string + @must_be(group='user') def changeClaimTarget(self, claim, snaktype='value', bot=True, **kwargs): """ @@ -3510,16 +3590,7 @@ if not new and hasattr(source, 'hash'): params['reference'] = source.hash #build up the snak - if source.getType() == 'wikibase-item': - datavalue = {'type': 'wikibase-entityid', - 'value': source._formatDataValue(), - } - elif source.getType() == 'string': - datavalue = {'type': 'string', - 'value': source._formatDataValue(), - } - else: - raise NotImplementedError('%s datatype is not supported yet.' % claim.getType()) + datavalue = source._buildMainSnak() snak = {source.getID(): [{'snaktype': 'value', 'property': source.getID(), 'datavalue': datavalue,
pywikibot-commits@lists.wikimedia.org