jenkins-bot has submitted this change. ( 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1358195?usp=email )

Change subject: [bugfix] Always set the comment of a Contribution
......................................................................

[bugfix] Always set the comment of a Contribution

The API omits the comment of an edit if it is hidden, so the attribute
access in User.contributions() raised a KeyError. Set an empty comment
by default in Contribution.normalize(), as Revision.normalize() does.

Bug: T442114
Change-Id: I5ad87e25b58fb5986f37550d44c06bce4acaaa9b
---
M pywikibot/page/_user.py
M tests/user_tests.py
2 files changed, 60 insertions(+), 0 deletions(-)

Approvals:
  jenkins-bot: Verified
  JJMC89: Looks good to me, approved




diff --git a/pywikibot/page/_user.py b/pywikibot/page/_user.py
index d37c930..3d838e0 100644
--- a/pywikibot/page/_user.py
+++ b/pywikibot/page/_user.py
@@ -37,11 +37,15 @@
     for the current Site and Page object of the contribution.

     .. version-added:: 11.6
+    .. version-changed:: 11.10
+       The *comment* is always set. It is an empty string if the API
+       does not return a comment, for example if it is hidden.
     """

     @staticmethod
     def normalize(data: dict[str, Any]) -> None:
         """Upcast dictionary values."""
+        data.setdefault('comment', '')
         if 'timestamp' in data:
             data['timestamp'] = Timestamp.fromISOformat(data['timestamp'])
         if 'title' in data:
diff --git a/tests/user_tests.py b/tests/user_tests.py
index 0d496bd..bad3d36 100755
--- a/tests/user_tests.py
+++ b/tests/user_tests.py
@@ -390,6 +390,62 @@
                 self.assertNotIn('uciprange', request)


+class TestUserContributionsWithoutComment(TestCase):
+
+    """Test User.contributions() with API data lacking a comment."""
+
+    family = 'wikipedia'
+    code = 'test'
+    dry = True
+
+    @staticmethod
+    def get_records() -> list[dict]:
+        """Return usercontribs data; the API omits a hidden comment."""
+        return [
+            {'user': 'Example', 'ns': 0, 'title': 'Foo', 'revid': 2,
+             'timestamp': '2026-10-02T12:00:00Z', 'commenthidden': True},
+            {'user': 'Example', 'ns': 0, 'title': 'Bar', 'revid': 1,
+             'timestamp': '2026-10-01T12:00:00Z', 'comment': 'A summary'},
+        ]
+
+    def test_contributions(self) -> None:
+        """Test that a missing comment is yielded as empty string."""
+        user = User(self.site, 'Example')
+        with patch.object(self.site, 'usercontribs',
+                          return_value=iter(self.get_records())):
+            contribs = list(user.contributions(total=2))
+
+        self.assertLength(contribs, 2)
+        page, revid, timestamp, comment = contribs[0]
+        self.assertEqual(page, Page(self.site, 'Foo'))
+        self.assertEqual(revid, 2)
+        self.assertIsInstance(timestamp, Timestamp)
+        self.assertEqual(comment, '')
+        self.assertEqual(contribs[1][3], 'A summary')
+
+    def test_contribs(self) -> None:
+        """Test that a Contribution always has a comment attribute."""
+        user = User(self.site, 'Example')
+        with patch.object(self.site, 'usercontribs',
+                          return_value=iter(self.get_records())):
+            contribs = list(user.contribs(total=2))
+
+        self.assertEqual(contribs[0].comment, '')
+        self.assertTrue(contribs[0].commenthidden)
+        self.assertEqual(contribs[1].comment, 'A summary')
+
+    def test_last_and_first_edit(self) -> None:
+        """Test that last_edit and first_edit accept a missing comment."""
+        user = User(self.site, 'Example')
+        for prop, revid in (('last_edit', 2), ('first_edit', 2)):
+            with self.subTest(prop=prop), patch.object(
+                    self.site, 'usercontribs',
+                    return_value=iter(self.get_records()[:1])):
+                edit = getattr(user, prop)
+                self.assertEqual(edit[1], revid)
+                self.assertEqual(edit[3], '')
+
+
 class TestUserRefreshParameter(DeprecationTestCase):

     """Test the rename of the *force* parameter to *refresh*."""

--
To view, visit 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1358195?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: I5ad87e25b58fb5986f37550d44c06bce4acaaa9b
Gerrit-Change-Number: 1358195
Gerrit-PatchSet: 4
Gerrit-Owner: AkashKumar7902 <[email protected]>
Gerrit-Reviewer: JJMC89 <[email protected]>
Gerrit-Reviewer: jenkins-bot
Gerrit-CC: Xqt <[email protected]>
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to