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]

Reply via email to