From 5b4f3d735c88683b8c14ceb01548417f3ad08c91 Mon Sep 17 00:00:00 2001 From: xqt Date: Wed, 18 Sep 2024 14:33:16 +0200 Subject: [PATCH] [IMPR] Check whether Claim exists within Claim.fromJSON() method - If a Claim type is not given to the initializer, the type is fetched from wikibase. This can fail if it does not exist. Try to get the type and if NoWikibaseEntityError write a warning instead raising a KeyError - add a new exists() method to Property class - raise NoWikibaseEntityError in Property.type property instead of KeyError Bug: T374681 Change-Id: Id9047cfe688c9a13c9ccc4c4ee1aebe5628abe4c --- pywikibot/page/_wikibase.py | 57 ++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/pywikibot/page/_wikibase.py b/pywikibot/page/_wikibase.py index 5ebe25dd6c..881f3d3ccd 100644 --- a/pywikibot/page/_wikibase.py +++ b/pywikibot/page/_wikibase.py @@ -1428,11 +1428,34 @@ def __init__(self, site, id: str, datatype: str | None = None) -> None: if datatype: self._type = datatype + def exists(self): + """Determine if the property exists in the data repository. + + .. versionadded:: 9.4 + """ + try: + self._type = self.repo.getPropertyType(self) + except KeyError: + return False + return True + @property @cached def type(self) -> str: - """Return the type of this property.""" - return self.repo.getPropertyType(self) + """Return the type of this property. + + .. versionchanged:: 9.4 + raises :exc:`NoWikibaseEntityError` if property does not + exist. + + :raises NoWikibaseEntityError: property does not exist + """ + try: + prop_type = self.repo.getPropertyType(self) + except KeyError as e: + raise NoWikibaseEntityError(e) + + return prop_type def getID(self, numeric: bool = False): """ @@ -1727,14 +1750,14 @@ def copy(self): return copy @classmethod - def fromJSON(cls, site, data): - """ - Create a claim object from JSON returned in the API call. + def fromJSON(cls, site, data: dict[str, Any]) -> Claim: + """Create a claim object from JSON returned in the API call. - :param data: JSON containing claim data - :type data: dict + .. versionchanged:: 9.4 + print a warning if the Claim.type is not given and missing in + the wikibase. - :rtype: pywikibot.page.Claim + :param data: JSON containing claim data """ claim_repo = site.get_repo_for_entity_type('property') claim = cls(claim_repo, data['mainsnak']['property'], @@ -1743,17 +1766,31 @@ def fromJSON(cls, site, data): claim.snak = data['id'] elif 'hash' in data: claim.hash = data['hash'] + claim.snaktype = data['mainsnak']['snaktype'] if claim.getSnakType() == 'value': value = data['mainsnak']['datavalue']['value'] - # The default covers string, url types - if claim.type in cls.types: + + # note: claim.type could be set during claim initialization + try: + claim_type = claim.type + except NoWikibaseEntityError: + claim_type = None + + claim.target = None + if not claim_type: + pywikibot.warning(f'{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.') + + if claim.target is None: claim.target = pywikibot.WbUnknown.fromWikibase(value) + if 'rank' in data: # References/Qualifiers don't have ranks claim.rank = data['rank'] if 'references' in data: