jenkins-bot has submitted this change. (
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1324215?usp=email )
Change subject: login: Reuse retry time snapshot
......................................................................
login: Reuse retry time snapshot
Capture the current time while checking the throttled-login deadline.
Reuse it when calculating the delay so the check and sleep use the same instant.
Change-Id: I7c8a578fb9d4233d985aba6397c5cb6bf8735dda
---
M pywikibot/login.py
M tests/login_tests.py
2 files changed, 45 insertions(+), 4 deletions(-)
Approvals:
jenkins-bot: Verified
Xqt: Looks good to me, approved
diff --git a/pywikibot/login.py b/pywikibot/login.py
index c79acaa..6ae3747 100644
--- a/pywikibot/login.py
+++ b/pywikibot/login.py
@@ -435,8 +435,8 @@
:raises APIError: API login error
"""
if hasattr(self, '_waituntil') \
- and datetime.datetime.now() < self._waituntil:
- diff = self._waituntil - datetime.datetime.now()
+ and (now := datetime.datetime.now()) < self._waituntil:
+ diff = self._waituntil - now
pywikibot.warning(f'Too many tries, waiting {diff.seconds}'
' seconds before retrying.')
pywikibot.sleep(diff.seconds)
diff --git a/tests/login_tests.py b/tests/login_tests.py
index 2304abc..73b776f 100755
--- a/tests/login_tests.py
+++ b/tests/login_tests.py
@@ -11,17 +11,19 @@
from __future__ import annotations
import builtins
+import datetime
import unittest
import uuid
from collections import defaultdict
from io import StringIO
from pathlib import Path
+from types import SimpleNamespace
from unittest import mock
from pywikibot.exceptions import NoUsernameError
-from pywikibot.login import LoginManager
+from pywikibot.login import ClientLoginManager, LoginManager
from pywikibot.tools import PYTHON_VERSION
-from tests.aspects import DefaultSiteTestCase
+from tests.aspects import DefaultSiteTestCase, TestCase
class FakeFamily:
@@ -88,6 +90,45 @@
self.assertEqual(lm.username, FakeUsername)
+class TestClientLoginManager(TestCase):
+
+ """Test offline ClientLoginManager behavior."""
+
+ net = False
+
+ def test_reuses_retry_time(self) -> None:
+ """Test that retry calculation uses one time snapshot."""
+ now = datetime.datetime(2026, 1, 1, 12)
+ manager = object.__new__(ClientLoginManager)
+ manager.site = SimpleNamespace()
+ manager.login_name = None
+ manager.password = None
+ manager._waituntil = now + datetime.timedelta(seconds=10)
+ clock = mock.Mock(side_effect=[
+ now,
+ now + datetime.timedelta(seconds=4),
+ ])
+ # Replacing datetime.datetime mutates the shared datetime module and
+ # breaks PyPy's datetime comparison type check.
+ datetime_module = SimpleNamespace(
+ datetime=SimpleNamespace(now=clock),
+ timedelta=datetime.timedelta,
+ )
+
+ with (
+ mock.patch('pywikibot.login.datetime', datetime_module),
+ mock.patch('pywikibot.login.pywikibot.sleep') as sleep,
+ mock.patch('pywikibot.login.pywikibot.warning') as warning,
+ self.assertRaisesRegex(RuntimeError, 'login_name'),
+ ):
+ manager.login_to_site()
+
+ clock.assert_called_once_with()
+ sleep.assert_called_once_with(10)
+ warning.assert_called_once_with(
+ 'Too many tries, waiting 10 seconds before retrying.')
+
+
@mock.patch('pywikibot.Site', FakeSite)
class TestPasswordFile(DefaultSiteTestCase):
--
To view, visit
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1324215?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: I7c8a578fb9d4233d985aba6397c5cb6bf8735dda
Gerrit-Change-Number: 1324215
Gerrit-PatchSet: 3
Gerrit-Owner: 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]