Page MenuHomePhabricator

ItemPage fails for double redirects
Open, HighPublicBUG REPORT

Description

I'm not 100% sure what the circumstances of failure are, but I'm only seeing it with undeleted items that are now redirects.

This code:

import pywikibot
site = pywikibot.Site("wikidata", "wikidata")
qid = "Q124382633"
item = pywikibot.ItemPage(site, qid)
print(item.exists(), item.isRedirectPage())

prints False False, but it should return True True because Q124382633 exists and is a redirect. It works as expected for Q119442711 which is also an undeleted redirect.

Event Timeline

Xqt triaged this task as High priority.Jan 9 2025, 7:29 AM
Xqt changed the subtype of this task from "Task" to "Bug Report".

Strange, gerRedirectTarget works:

item.getRedirectTarget()
ItemPage('Q119442711')

but get() fails:

x = item.get()
Traceback (most recent call last):
  File "C:\pwb\GIT\core\pywikibot\page\_wikibase.py", line 734, in get
    data = WikibaseEntity.get(self, force=force)
  File "C:\pwb\GIT\core\pywikibot\page\_wikibase.py", line 267, in get
    raise NoWikibaseEntityError(self)
pywikibot.exceptions.NoWikibaseEntityError: Entity 'Q124382633' doesn't exist on wikidata:wikidata

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    x = item.get()
  File "C:\pwb\GIT\core\pywikibot\page\_wikibase.py", line 1152, in get
    data = super().get(force, *args, **kwargs)
  File "C:\pwb\GIT\core\pywikibot\page\_wikibase.py", line 741, in get
    raise NoPageError(self)
pywikibot.exceptions.NoPageError: Page [[wikidata:Q124382633]] doesn't exist.

I guess this an upstream issue. The releated query is
https://www.wikidata.org/w/api.php?ids=Q124382633&action=wbgetentities
and returns

{
    "entities": {
        "Q124382633": {
            "id": "Q124382633",
            "missing": ""
        }
    },
    "success": 1
}

whereas https://www.wikidata.org/w/api.php?ids=Q119442711&action=wbgetentities gives the content.

Maybe this is caused by the double redirect?

We could use getRedirectTarget to test for redirects:

>>> import pywikibot
>>> site = pywikibot.Site('wikidata')
>>> item = pywikibot.ItemPage(site, 'Q124382633')
>>> item.getRedirectTarget()
ItemPage('Q119442711')
>>> item = pywikibot.ItemPage(site, 'Q119442711')
>>> item.getRedirectTarget()
ItemPage('Q116896444')
>>> item = pywikibot.ItemPage(site, 'Q116896444')
>>> item.getRedirectTarget()
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    item.getRedirectTarget()
  File "C:\pwb\GIT\core\pywikibot\page\_wikibase.py", line 1185, in getRedirectTarget
    target = super().getRedirectTarget(ignore_section=ignore_section)
  File "C:\pwb\GIT\core\pywikibot\page\_basepage.py", line 1827, in getRedirectTarget
    return self.site.getredirtarget(self, ignore_section=ignore_section)
  File "C:\pwb\GIT\core\pywikibot\site\_apisite.py", line 1603, in getredirtarget
    raise IsNotRedirectPageError(page)
pywikibot.exceptions.IsNotRedirectPageError: Page [[wikidata:Q116896444]] is not a redirect page.
>>> item = pywikibot.ItemPage(site, 'Q1168964449999')
>>> item.getRedirectTarget()
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    item.getRedirectTarget()
  File "C:\pwb\GIT\core\pywikibot\page\_wikibase.py", line 1185, in getRedirectTarget
    target = super().getRedirectTarget(ignore_section=ignore_section)
  File "C:\pwb\GIT\core\pywikibot\page\_basepage.py", line 1827, in getRedirectTarget
    return self.site.getredirtarget(self, ignore_section=ignore_section)
  File "C:\pwb\GIT\core\pywikibot\site\_apisite.py", line 1603, in getredirtarget
    raise IsNotRedirectPageError(page)
pywikibot.exceptions.IsNotRedirectPageError: Page [[wikidata:Q1168964449999]] is not a redirect page.

Solved upstream with redirect change. The problem exists for double redirects I guess.

Xqt renamed this task from ItemPage fails for undelete redirects to ItemPage fails for double redirects.Jan 11 2025, 10:45 AM

Lets look at the example of Q192393 → Q213543 → Q7 on test.wikidata.

Behavior of pywikibot :

pywikibot.Page(site, "Q192393").exists() # True
pywikibot.Page(site, "Q192393").isRedirectPage() # True
pywikibot.Page(site, "Q192393").getRedirectTarget() # [[test:Q213543]]

print(page:=pywikibot.ItemPage(repo, "Q192393"), page.exists(), page.isRedirectPage()) # [[test:Q192393]] False False
pywikibot.ItemPage(repo, "Q192393").exists() # False
pywikibot.ItemPage(repo, "Q192393").isRedirectPage() # True! (because exists() has never been called on the instance)
pywikibot.ItemPage(repo, "Q192393").getRedirectTarget() # [[test:Q213543]] (because super().getRedirectTarget() is called)

The inconstant return value of isRedirectPage is due to the implementation in WikibaseEntity (_content is initialized when we call exists()) :

def isRedirectPage(self):
        """Return True if item is a redirect, False if not or not existing."""
        if hasattr(self, '_content') and not hasattr(self, '_isredir'):
            self._isredir = self.id != self._content.get('id', self.id)
            return self._isredir
        return super().isRedirectPage()

Behavior of API:
If redirects=yes (default), the function getEntityRevision catches the first redirection and try to resolve it (but not recursively, setting redirects=no).
Test with redirects=no : https://test.wikidata.org/w/api.php?action=wbgetentities&ids=Q192393%7CQ213543&redirects=no (neither of them "exists" in the repository)
Test with redirects=yes : https://test.wikidata.org/w/api.php?action=wbgetentities&ids=Q192393%7CQ213543&redirects=yes

Suggestions

  • Refactor Wikibase.isRedirectPage() for consistant behavior
  • Add documentation for Wikibase.exists() to make clear that page may exists but not item.