Skip to content

Commit

Permalink
Add MediaInfo editLabels, AddClaim and removeClaim functions.
Browse files Browse the repository at this point in the history
Added editLabels, addClaim, removeClaims functions to MediaInfo.

Bug: T348422
Change-Id: Ic3822e4b10419fabb26bae9a7756c8c39bbbe7a0
  • Loading branch information
Kimmo Virtanen committed Oct 25, 2023
1 parent 5e2f217 commit 2715217
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 18 deletions.
54 changes: 54 additions & 0 deletions pywikibot/page/_wikibase.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,60 @@ def getID(self, numeric: bool = False):
self._assert_has_id()
return super().getID(numeric=numeric)

def editLabels(self, labels: LANGUAGE_TYPE, **kwargs) -> None:
"""Edit MediaInfo labels (eg. captions).
*labels* should be a dict, with the key as a language or a site
object. The value should be the string to set it to. You can set
it to ``''`` to remove the label.
Usage:
>>> repo = pywikibot.Site('commons','commons')
>>> page = pywikibot.FilePage(repo, 'File:Sandbox-Test.svg')
>>> item = page.data_item()
>>> item.editLabels({'en': 'Test file.'}) # doctest: +SKIP
"""
data = {'labels': labels}
self.editEntity(data, **kwargs)

def addClaim(self, claim, bot: bool = True, **kwargs):
"""
Add a claim to the MediaInfo.
:param claim: The claim to add
:type claim: pywikibot.page.Claim
:param bot: Whether to flag as bot (if possible)
"""
if claim.on_item is not None:
raise ValueError(
'The provided Claim instance is already used in an entity')

self._assert_has_id()
if not hasattr(self, '_revid'):
# workaround for uninitialized mediainfo's
self._revid = self.file.latest_revision_id

self.repo.addClaim(self, claim, bot=bot, **kwargs)
claim.on_item = self

def removeClaims(self, claims, **kwargs) -> None:
"""
Remove the claims from the MediaInfo.
:param claims: list of claims to be removed
:type claims: list or pywikibot.Claim
"""
# this check allows single claims to be removed by pushing them into a
# list of length one.
if isinstance(claims, pywikibot.Claim):
claims = [claims]
data = self.repo.removeClaims(claims, **kwargs)
for claim in claims:
claim.on_item.latest_revision_id = data['pageinfo']['lastrevid']
claim.on_item = None
claim.snak = None


class WikibasePage(BasePage, WikibaseEntity):

Expand Down
147 changes: 129 additions & 18 deletions tests/file_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
NoPageError,
NoWikibaseEntityError,
PageRelatedError,
UserRightsError,
)
from pywikibot import pagegenerators
from tests import join_images_path
Expand Down Expand Up @@ -405,27 +406,31 @@ def test_data_item_when_file_exist_but_without_item(self):
)

# Seek to first page without mediainfo.
for page in gen:
if 'mediainfo' in page.latest_revision.slots:
continue
# Retry loop is for excepting incorrect files
for retry in range(5):
try:
for page in gen:
slots = page.latest_revision.slots
if 'mediainfo' not in slots:
break
break
except ValueError:
pass

item = page.data_item()
self.assertIsInstance(item, pywikibot.MediaInfo)

# Get fails as there is no mediainfo.
with self.assertRaises(NoWikibaseEntityError):
item.get()
item = page.data_item()
self.assertIsInstance(item, pywikibot.MediaInfo)

self.assertFalse(item.exists())
self.assertEqual(f'M{page.pageid}', item.id)
self.assertIsInstance(
item.labels, pywikibot.page._collections.LanguageDict)
self.assertIsInstance(
item.statements,
pywikibot.page._collections.ClaimCollection)
# Get fails as there is no mediainfo.
with self.assertRaises(NoWikibaseEntityError):
item.get()

# break the loop after checking first file
break
self.assertFalse(item.exists())
self.assertEqual(f'M{page.pageid}', item.id)
self.assertIsInstance(
item.labels, pywikibot.page._collections.LanguageDict)
self.assertIsInstance(
item.statements,
pywikibot.page._collections.ClaimCollection)

def test_data_list_to_dict_workaround(self):
"""Test that T222159 workaround converts [] to {}."""
Expand All @@ -441,6 +446,112 @@ def test_data_list_to_dict_workaround(self):
item.statements, pywikibot.page._collections.ClaimCollection)


class TestMediaInfoReadonlyEditing(TestCase):

"""Test writing structured data of FilePage."""

# Create valid API requests which will fail to missing permission.

# commons.wikimedia.beta.wmflabs.org
family = 'commons'
code = 'beta'

def test_edit_label(self):
"""Test label editing without writing rights."""
page = pywikibot.FilePage(self.site, 'File:123_4.jpg')
item = page.data_item()
error_message = 'User "None" does not have required user right "edit"'

data = {}
lang = 'fi'
label = 'Edit label with editEntity and dict()'
data.update({'labels': {lang: label}})
with self.assertRaisesRegex(UserRightsError, error_message):
item.editEntity(data, summary=label)

data = item.get()
label = 'Edit label with editEntity and item.get()'
data.update({'labels': {lang: label}})
with self.assertRaisesRegex(UserRightsError, error_message):
item.editEntity(data, summary=label)

data = item.get(force=True)
label = 'Edit label with editEntity and item.get(force=True)'
data.update({'labels': {lang: label}})
with self.assertRaisesRegex(UserRightsError, error_message):
item.editEntity(data, summary=label)

lang = 'fi'
label = 'Edit label with editLabels and dict()'
data = {lang: label}
with self.assertRaisesRegex(UserRightsError, error_message):
item.editLabels(data, summary=label)

# Test label editing when file doesn't exists
page = pywikibot.FilePage(self.site, 'File:123_4_DOESNT_EXISTS.jpg')
item = page.data_item()

data = {}
lang = 'fi'
label = 'Edit label of missing file with editEntity and dict()'
data.update({'labels': {lang: label}})
with self.assertRaises(UserRightsError):
item.editEntity(data, summary=label)

lang = 'fi'
label = 'Edit label of missing file with editLabels and dict()'
data = {lang: label}
with self.assertRaisesRegex(UserRightsError, error_message):
item.editLabels(data, summary=label)

def test_edit_claims(self):
"""Test claim editing without writing rights."""
error_message = 'User "None" does not have required user right "edit"'
wikidata_site = pywikibot.Site('wikidata', 'wikidata')

# Test adding claim existing file
page = pywikibot.FilePage(self.site, 'File:123_4.jpg')
item = page.data_item()

# Create claim
finna_id = 'test123'
new_claim = pywikibot.Claim(wikidata_site, 'P9478')
new_claim.setTarget(finna_id)

# Do actual edit
with self.assertRaisesRegex(UserRightsError, error_message):
item.addClaim(new_claim)

# Test removing first claim using item.statements
for property_id in item.statements:
for statement in item.statements[property_id]:
with self.assertRaisesRegex(UserRightsError, error_message):
summary = f'Removing {property_id}'
item.removeClaims(statement, summary=summary)
break

# Test removing first claim using item.claims
for property_id in item.claims:
for claim in item.claims[property_id]:
with self.assertRaisesRegex(UserRightsError, error_message):
summary = f'Removing {property_id}'
item.removeClaims(claim, summary=summary)
break

# Test adding claim to non-existing file
page = pywikibot.FilePage(self.site, 'File:123_4_DOESNT_EXISTS.jpg')
item = page.data_item()

# Create claim
finna_id = 'test123'
new_claim = pywikibot.Claim(wikidata_site, 'P9478')
new_claim.setTarget(finna_id)

# Do actual edit
with self.assertRaises(NoWikibaseEntityError):
item.addClaim(new_claim)


if __name__ == '__main__': # pragma: no cover
with suppress(SystemExit):
unittest.main()

0 comments on commit 2715217

Please sign in to comment.