diff --git a/pywikibot/_wbtypes.py b/pywikibot/_wbtypes.py index 4764cfa6d2..66374df215 100644 --- a/pywikibot/_wbtypes.py +++ b/pywikibot/_wbtypes.py @@ -1151,8 +1151,7 @@ def _get_type_specifics(cls, site: DataSite) -> dict[str, Any]: class WbUnknown(WbRepresentation): - """ - A Wikibase representation for unknown data type. + """A Wikibase representation for unknown data type. This will prevent the bot from breaking completely when a new type is introduced. @@ -1160,24 +1159,34 @@ class WbUnknown(WbRepresentation): This data type is just a json container .. versionadded:: 3.0 + .. versionchanged:: 9.4 + *warning* parameter was added """ _items = ('json',) - def __init__(self, json: dict[str, Any]) -> None: + def __init__(self, json: dict[str, Any], warning: str = '') -> None: """ Create a new WbUnknown object. :param json: Wikibase JSON + :param warning: a warning message which is shown once if + :meth:`toWikibase` is called """ self.json = json + self.warning = warning def toWikibase(self) -> dict[str, Any]: - """ - Return the JSON object for the Wikibase API. + """Return the JSON object for the Wikibase API. + + .. versionchanged:: 9.4 + a waning message given by the warning attribute is shown once. :return: Wikibase JSON """ + if self.warning: + pywikibot.warning(self.warning) + self.warning = '' return self.json @classmethod diff --git a/pywikibot/page/_wikibase.py b/pywikibot/page/_wikibase.py index 881f3d3ccd..65c2181b63 100644 --- a/pywikibot/page/_wikibase.py +++ b/pywikibot/page/_wikibase.py @@ -1777,19 +1777,19 @@ def fromJSON(cls, site, data: dict[str, Any]) -> Claim: except NoWikibaseEntityError: claim_type = None - claim.target = None + msg = None if not claim_type: - pywikibot.warning(f'{claim.id} does not exist.') + msg = '{claim.id} does not exist.' elif claim.type in cls.types: # The default covers string, url types claim.target = cls.TARGET_CONVERTER.get( claim.type, lambda value, site: value)(value, site) else: - pywikibot.warning( - f'{claim.type} datatype is not supported yet.') + msg = f'{claim.type} datatype is not supported yet.' - if claim.target is None: + if msg is not None: claim.target = pywikibot.WbUnknown.fromWikibase(value) + claim.target.warning = msg if 'rank' in data: # References/Qualifiers don't have ranks claim.rank = data['rank'] diff --git a/tests/wikibase_tests.py b/tests/wikibase_tests.py index a5c3135491..0a1f9c29b1 100755 --- a/tests/wikibase_tests.py +++ b/tests/wikibase_tests.py @@ -14,7 +14,6 @@ import unittest from contextlib import suppress from decimal import Decimal -from unittest import mock import pywikibot from pywikibot import pagegenerators @@ -1192,12 +1191,11 @@ def setUp(self): def test_load_unknown(self): """Ensure unknown value is loaded but raises a warning.""" - with mock.patch.object(pywikibot, 'warning', autospec=True) as warn: - self.wdp.get() - unknown_value = self.wdp.claims['P99999'][0].getTarget() - self.assertIsInstance(unknown_value, pywikibot.WbUnknown) - warn.assert_called_once_with( - 'foo-unknown-bar datatype is not supported yet.') + self.wdp.get() + unknown_value = self.wdp.claims['P99999'][0].getTarget() + self.assertIsInstance(unknown_value, pywikibot.WbUnknown) + self.assertEqual(unknown_value.warning, + 'foo-unknown-bar datatype is not supported yet.') class TestItemPageExtensibility(TestCase):