jenkins-bot has submitted this change. (
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1350193?usp=email )
Change subject: MediaInfo: map claims for wbeditentity
......................................................................
MediaInfo: map claims for wbeditentity
Commons returns MediaInfo under "statements", but wbeditentity expects
"claims". Accept either key on write, emit "claims" from toJSON, and keep
diffing against _content["statements"].
Bug: T376955
Change-Id: Iab8a86f3cdc9d64b29e62a4bcad58e1aa2e55444
---
M pywikibot/page/_wikibase.py
M tests/wikibase_tests.py
2 files changed, 121 insertions(+), 1 deletion(-)
Approvals:
jenkins-bot: Verified
Xqt: Looks good to me, approved
diff --git a/pywikibot/page/_wikibase.py b/pywikibot/page/_wikibase.py
index 7778ca3..d80fee4 100644
--- a/pywikibot/page/_wikibase.py
+++ b/pywikibot/page/_wikibase.py
@@ -388,6 +388,39 @@
return super().__getattr__(name)
+ def toJSON(self, diffto: dict | None = None) -> dict:
+ """Create JSON suitable for Wikibase API.
+
+ When diffto is provided, JSON representing differences to the
+ provided data is created.
+
+ :param diffto: JSON containing entity data
+ """
+ data = super().toJSON(diffto=diffto)
+ if 'statements' in data:
+ data['claims'] = data.pop('statements')
+ return data
+
+ @classmethod
+ def _normalizeData(cls, data: dict) -> dict:
+ """Helper function to expand data into the Wikibase API structure.
+
+ :param data: The dict to normalize
+ :return: The dict with normalized data
+ :raise ValueError: If both 'claims' and 'statements' are present
+ """
+ if 'claims' in data and 'statements' in data:
+ raise ValueError(
+ "Cannot specify both 'claims' and 'statements' in data")
+
+ data = dict(data)
+ if 'claims' in data:
+ data['statements'] = data.pop('claims')
+ norm_data = super()._normalizeData(data)
+ if 'statements' in norm_data:
+ norm_data['claims'] = norm_data.pop('statements')
+ return norm_data
+
def _assert_has_id(self) -> None:
if self.id != '-1':
return
diff --git a/tests/wikibase_tests.py b/tests/wikibase_tests.py
index 37c5556..7e1e0ed 100755
--- a/tests/wikibase_tests.py
+++ b/tests/wikibase_tests.py
@@ -11,6 +11,7 @@
import json
import unittest
from contextlib import suppress
+from unittest.mock import MagicMock
import pywikibot
from pywikibot import pagegenerators
@@ -21,7 +22,14 @@
NoPageError,
WikiBaseError,
)
-from pywikibot.page import ItemPage, PropertyPage, WikibasePage
+from pywikibot.page import (
+ Claim,
+ ItemPage,
+ MediaInfo,
+ PropertyPage,
+ WikibasePage,
+)
+from pywikibot.page._collections import ClaimCollection, LanguageDict
from pywikibot.site import Namespace, NamespacesDict
from pywikibot.tools import suppress_warnings
from tests import WARN_SITE_CODE, join_pages_path
@@ -1147,6 +1155,85 @@
ItemPage._normalizeData(data)
+class TestMediaInfoNormalizeData(TestCase):
+
+ """Test cases for MediaInfo._normalizeData and MediaInfo.toJSON."""
+
+ net = False
+
+ def setUp(self) -> None:
+ """Set up tests."""
+ super().setUp()
+ self.claim_dict = {
+ 'mainsnak': {
+ 'snaktype': 'value',
+ 'property': 'P7384',
+ 'datavalue': {'value': '2295284', 'type': 'string'},
+ },
+ 'type': 'statement',
+ 'rank': 'normal',
+ }
+
+ def test_both_claims_and_statements_raises_value_error(self) -> None:
+ """Test _normalizeData raises ValueError if both keys are present."""
+ data_in = {
+ 'claims': [self.claim_dict],
+ 'statements': [self.claim_dict],
+ }
+ with self.assertRaisesRegex(
+ ValueError,
+ "Cannot specify both 'claims' and 'statements' in data"):
+ MediaInfo._normalizeData(data_in)
+
+ def test_claims_input(self) -> None:
+ """Test _normalizeData with claims input produces claims out."""
+ data_in = {'claims': [self.claim_dict]}
+ response = MediaInfo._normalizeData(data_in)
+ self.assertEqual(response, {'claims': [self.claim_dict]})
+ self.assertIn('claims', data_in)
+ self.assertNotIn('statements', data_in)
+
+ def test_statements_input(self) -> None:
+ """Test _normalizeData with statements input produces claims out."""
+ data_in = {'statements': [self.claim_dict]}
+ response = MediaInfo._normalizeData(data_in)
+ self.assertEqual(response, {'claims': [self.claim_dict]})
+
+ def test_labels_and_claims_preserved(self) -> None:
+ """Test _normalizeData with labels and claims preserves both."""
+ data_in = {
+ 'labels': {'en': 'Test label'},
+ 'claims': [self.claim_dict],
+ }
+ expected = {
+ 'labels': {'en': {'language': 'en', 'value': 'Test label'}},
+ 'claims': [self.claim_dict],
+ }
+ response = MediaInfo._normalizeData(data_in)
+ self.assertEqual(response, expected)
+
+ def test_to_json_key_is_claims(self) -> None:
+ """Test MediaInfo.toJSON returns 'claims' instead of 'statements'."""
+ repo = MagicMock()
+ item = MediaInfo(repo, 'M123')
+ item.labels = LanguageDict.new_empty(repo)
+ col = ClaimCollection(repo)
+ claim = Claim(repo, 'P123', datatype='string')
+ claim.setTarget('foo')
+ col['P123'] = [claim]
+ item.statements = col
+
+ json_data = item.toJSON()
+ self.assertIn('claims', json_data)
+ self.assertNotIn('statements', json_data)
+ self.assertEqual(json_data['claims'], {'P123': [claim.toJSON()]})
+
+ # Test diffing against _content with statements
+ claim.snak = 'M123$guid'
+ diffto = {'statements': {'P123': [claim.toJSON()]}}
+ self.assertEqual(item.toJSON(diffto=diffto), {})
+
+
class TestPreloadingEntityGenerator(TestCase):
"""Test preloading item generator."""
--
To view, visit
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1350193?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.wikimedia.org/r/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: Iab8a86f3cdc9d64b29e62a4bcad58e1aa2e55444
Gerrit-Change-Number: 1350193
Gerrit-PatchSet: 2
Gerrit-Owner: Zaidusyy <[email protected]>
Gerrit-Reviewer: Matěj Suchánek <[email protected]>
Gerrit-Reviewer: Multichill <[email protected]>
Gerrit-Reviewer: Xqt <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]