jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/507234 )
Change subject: pywikibot: Add support for property creation ......................................................................
pywikibot: Add support for property creation
Changed PropertyPages constructor to accept empty title and added 'datatype' parameter. Added method 'get_data_for_new_entity' to PropertyPage. PropertyPage can now have id '-1'. Changed DataSite.editEntity method to accept WikibasePage as first argument. Renamed argument 'identification' to 'entity'.
Bug: T160402 Change-Id: Ieac6dfc0d44d6f6e47217168f77b01bd468c3282 --- M pywikibot/page.py M pywikibot/site.py M tests/wikibase_edit_tests.py M tests/wikibase_tests.py 4 files changed, 92 insertions(+), 20 deletions(-)
Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/page.py b/pywikibot/page.py index b4cfd5f..48a88f6 100644 --- a/pywikibot/page.py +++ b/pywikibot/page.py @@ -3983,6 +3983,16 @@ 'claims': self.claims, }
+ def get_data_for_new_entity(self): + """ + Return data required for creation of new page. + + Override it if you need. + + @rtype: dict + """ + return {} + def _diff_to(self, type_key, key_name, value_name, diffto, data): assert type_key not in data, 'Key type must be defined in data' source = self._normalizeLanguages(getattr(self, type_key)).copy() @@ -4213,7 +4223,7 @@ else: data = WikibasePage._normalizeData(data)
- updates = self.repo.editEntity(self._defined_by(singular=True), data, + updates = self.repo.editEntity(self, data, baserevid=baserevid, **kwargs) self.latest_revision_id = updates['entity']['lastrevid']
@@ -4778,29 +4788,43 @@ A Wikibase entity in the property namespace.
Should be created as:: - PropertyPage(DataSite, 'P21') + or + PropertyPage(DataSite, datatype='url') """
_cache_attrs = WikibasePage._cache_attrs + ('_type',) entity_type = 'property' - title_pattern = r'^P[1-9]\d*$' + title_pattern = r'^(P[1-9]\d*|-1)$'
- def __init__(self, source, title=''): + def __init__(self, source, title=None, datatype=None): """ Initializer.
@param source: data repository property is on @type source: pywikibot.site.DataSite - @param title: page name of property, like "P##" + @param title: page name of property, like "P##", + "-1" or None for an empty property. @type title: str + @param datatype: Datatype for a new property. + @type datatype: str """ - if not title: - raise pywikibot.InvalidTitle("Property's title cannot be empty") + # Special case for new property. + if title is None or title == '-1': + if not datatype: + raise TypeError('"datatype" is required for new property.') + WikibasePage.__init__(self, source, '-1', + ns=source.property_namespace) + Property.__init__(self, source, '-1', datatype=datatype) + assert self.id == '-1' + else: + if not title: + raise pywikibot.InvalidTitle( + "Property's title cannot be empty")
- WikibasePage.__init__(self, source, title, - ns=source.property_namespace) - Property.__init__(self, source, self.id) + WikibasePage.__init__(self, source, title, + ns=source.property_namespace) + Property.__init__(self, source, self.id)
def get(self, force=False, *args, **kwargs): """ @@ -4829,6 +4853,10 @@ return Claim(self.site, self.getID(), datatype=self.type, *args, **kwargs)
+ def get_data_for_new_entity(self): + """Return data required for creation of new property.""" + return {'datatype': self.type} +
# Add PropertyPage to the class attribute "types" after its declaration. Property.types['wikibase-property'] = PropertyPage diff --git a/pywikibot/site.py b/pywikibot/site.py index 12de127..6729954 100644 --- a/pywikibot/site.py +++ b/pywikibot/site.py @@ -7801,13 +7801,17 @@
return dtype
+ @deprecated_args(identification='entity') @must_be(group='user') - def editEntity(self, identification, data, bot=True, **kwargs): + def editEntity(self, entity, data, bot=True, **kwargs): """ Edit entity.
- @param identification: API parameters to use for entity identification - @type identification: dict + Note: This method is unable to create entities other than 'item' + if dict with API parameters was passed to 'entity' parameter. + @param entity: Page to edit, or dict with API parameters + to use for entity identification + @type entity: WikibasePage or dict @param data: data updates @type data: dict @param bot: Whether to mark the edit as a bot edit @@ -7815,11 +7819,23 @@ @return: New entity data @rtype: dict """ - if 'id' in identification and identification['id'] == '-1': - del identification['id'] - params = dict(**identification) - if not params: # If no identification was provided - params['new'] = 'item' # TODO create properties+queries + # this changes the reference to a new object + data = dict(data) + if isinstance(entity, pywikibot.page.WikibasePage): + params = entity._defined_by(singular=True) + if 'id' in params and params['id'] == '-1': + del params['id'] + if not params: + params['new'] = entity.entity_type + data_for_new_entity = entity.get_data_for_new_entity() + data.update(data_for_new_entity) + else: + if 'id' in entity and entity['id'] == '-1': + del entity['id'] + params = dict(entity) + if not params: # If no identification was provided + params['new'] = 'item' + params['action'] = 'wbeditentity' if bot: params['bot'] = 1 @@ -7828,7 +7844,7 @@ params['token'] = self.tokens['edit']
for arg in kwargs: - if arg in ['clear', 'data', 'summary']: + if arg in ['clear', 'summary']: params[arg] = kwargs[arg] elif arg != 'baserevid': warn('Unknown wbeditentity parameter {0} ignored'.format(arg), diff --git a/tests/wikibase_edit_tests.py b/tests/wikibase_edit_tests.py index 69e61e8..13a5a6b 100644 --- a/tests/wikibase_edit_tests.py +++ b/tests/wikibase_edit_tests.py @@ -128,6 +128,27 @@ item = pywikibot.ItemPage(testsite) item.editEntity(data)
+ def test_edit_entity_new_property(self): + """Test creating a new property using C{PropertyPage.editEntity}.""" + testsite = self.get_repo() + ts = str(time.time()) + data = { + 'labels': { + 'en': { + 'language': 'en', + 'value': 'Pywikibot test new property', + } + }, + 'descriptions': { + 'en': { + 'language': 'en', + 'value': 'Pywikibot test new property - ' + ts, + } + } + } + prop = pywikibot.PropertyPage(testsite, datatype='string') + prop.editEntity(data) + def test_edit_entity_new_linked_item(self): """Test linking a page using a new item.""" ts = str(time.time()) diff --git a/tests/wikibase_tests.py b/tests/wikibase_tests.py index 25e0c71..95ae131 100644 --- a/tests/wikibase_tests.py +++ b/tests/wikibase_tests.py @@ -1343,11 +1343,18 @@ """Test PropertyPage."""
def test_property_empty_property(self): + """Test creating a PropertyPage without a title and datatype.""" + wikidata = self.get_repo() + regex = r'^"datatype" is required for new property.$' + with self.assertRaisesRegex(TypeError, regex): + PropertyPage(wikidata) + + def test_property_empty_title(self): """Test creating a PropertyPage without a title.""" wikidata = self.get_repo() regex = r"^Property's title cannot be empty$" with self.assertRaisesRegex(pywikibot.InvalidTitle, regex): - PropertyPage(wikidata) + PropertyPage(wikidata, title='')
@suppress_warnings('pywikibot.page.Property.getType is deprecated') def test_globe_coordinate(self):
pywikibot-commits@lists.wikimedia.org