jenkins-bot has submitted this change. (
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1322836?usp=email )
Change subject: [FIX] Prevent infinite recursion loop in
fix_moved_broken_redirects
......................................................................
[FIX] Prevent infinite recursion loop in fix_moved_broken_redirects
Add visited set to track checked target pages during recursive lookup
to prevent cyclic move target loops.
Bug: T432620
Change-Id: Ib4e1a4f8954938b4f14bc660aa8f58d7a19ea5f5
---
M scripts/redirect.py
M tests/redirect_bot_tests.py
2 files changed, 44 insertions(+), 2 deletions(-)
Approvals:
jenkins-bot: Verified
Mahveotm: Looks good to me, approved
diff --git a/scripts/redirect.py b/scripts/redirect.py
index cb19913..44eec6c 100755
--- a/scripts/redirect.py
+++ b/scripts/redirect.py
@@ -490,18 +490,36 @@
pywikibot.info(f'{page} is on another site, skipping.')
return None
- def fix_moved_broken_redirects(self, target: pywikibot.Page) -> None:
+ def fix_moved_broken_redirects(
+ self,
+ target: pywikibot.Page,
+ visited: set[pywikibot.Page] | None = None,
+ ) -> None:
"""Try to fix a deleted redirect using moved_target method."""
redir_page = self.current_page
done = not self.opt.delete
movedTarget = None
+ if visited is None:
+ visited = {redir_page}
+
+ if target in visited:
+ pywikibot.info(f'Redirect target {target} forms a redirect loop')
+ return
+
+ visited.add(target)
+
with suppress(NoMoveTargetError):
movedTarget = target.moved_target()
if movedTarget:
+ if movedTarget in visited:
+ pywikibot.info(
+ f'Redirect target {movedTarget} forms a redirect loop')
+ return
+
if not movedTarget.exists():
- self.fix_moved_broken_redirects(movedTarget)
+ self.fix_moved_broken_redirects(movedTarget, visited=visited)
# process other cases within recursive loop
return
diff --git a/tests/redirect_bot_tests.py b/tests/redirect_bot_tests.py
index defa8be..9edf82c 100755
--- a/tests/redirect_bot_tests.py
+++ b/tests/redirect_bot_tests.py
@@ -71,6 +71,30 @@
w.assert_called_with('No speedy deletion template "n" available.')
+class TestFixMovedBrokenRedirects(DefaultSiteTestCase):
+
+ """Test fix_moved_broken_redirects() loop handling."""
+
+ def test_cyclic_move_chain_terminates_without_editing_or_deleting(
+ self) -> None:
+ """Move chain A -> B -> C -> A must terminate without edits."""
+ page_a, page_b, page_c = Mock(), Mock(), Mock()
+ page_a.moved_target.return_value = page_b
+ page_b.moved_target.return_value = page_c
+ page_c.moved_target.return_value = page_a # closes the loop
+ page_b.exists.return_value = False
+ page_c.exists.return_value = False
+
+ bot = RedirectTestRobot('broken', delete=True)
+ bot.delete_redirect = Mock()
+ bot.userPut = Mock(return_value=True)
+
+ bot.fix_moved_broken_redirects(page_a) # must not hang/recurse
+
+ bot.delete_redirect.assert_not_called()
+ bot.userPut.assert_not_called()
+
+
if __name__ == '__main__':
with suppress(SystemExit):
unittest.main()
--
To view, visit
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1322836?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: Ib4e1a4f8954938b4f14bc660aa8f58d7a19ea5f5
Gerrit-Change-Number: 1322836
Gerrit-PatchSet: 3
Gerrit-Owner: Raushan 31 <[email protected]>
Gerrit-Reviewer: Mahveotm <[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]