jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1004618?usp=email )
Change subject: [IMPR] Raise APIError if the same error comes twice within submit loop ......................................................................
[IMPR] Raise APIError if the same error comes twice within submit loop
api.Request.submit handles API errors within a loop but in some circumstances the loop will never leaved if the same error comes again and again. Therefore raise APIError with the previous API error if the same error occured twice in the same submit loop-
Bug: T357870 Change-Id: Id9f140c9d8815ef622d47cd90a29518f23665a4a --- M pywikibot/data/api/_requests.py 1 file changed, 42 insertions(+), 1 deletion(-)
Approvals: JJMC89: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/data/api/_requests.py b/pywikibot/data/api/_requests.py index bc40eec..8facad1 100644 --- a/pywikibot/data/api/_requests.py +++ b/pywikibot/data/api/_requests.py @@ -1,6 +1,6 @@ """Objects representing API requests.""" # -# (C) Pywikibot team, 2007-2023 +# (C) Pywikibot team, 2007-2024 # # Distributed under the terms of the MIT license. # @@ -945,18 +945,36 @@ self._params['token'] = tokens return True
+ def wait(self, delay: int | None = None) -> None: + """Determine how long to wait after a failed request. + + Also reset last API error with wait cycles. + + .. versionadded: 9.0 + + :param delay: Minimum time in seconds to wait. Overwrites + ``retry_wait`` variable if given. The delay doubles each + retry until ``retry_max`` seconds is reached. + """ + self.last_error = dict.fromkeys(['code', 'info']) + super().wait(delay) + def submit(self) -> dict: """Submit a query and parse the response.
.. versionchanged:: 8.0.4 in addition to *readapidenied* also try to login when API response is *notloggedin*. + .. versionchanged:: 9.0 + Raise :exc:`pywikibot.exceptions.APIError` if the same error + comes twice in a row within the loop.
:return: a dict containing data retrieved from api.php """ self._add_defaults() use_get = self._use_get() retries = 0 + self.last_error = dict.fromkeys(['code', 'info']) while True: paramstring = self._http_param_string()
@@ -1003,6 +1021,11 @@ code = error.setdefault('code', 'Unknown') info = error.setdefault('info', None)
+ if (code == self.last_error['code'] + and info == self.last_error['info']): + raise pywikibot.exceptions.APIError(**self.last_error) + self.last_error = error + if not self._logged_in(code): continue
@@ -1019,6 +1042,8 @@ lag = float(lag['lag']) if lag else 0.0
self.site.throttle.lag(lag * retries) + # reset last error + self.last_error = dict.fromkeys(['code', 'info']) continue
if code == 'help' and self.action == 'help': @@ -1060,6 +1085,7 @@ pywikibot.error(f'Retrying failed {msg}') continue raise NoUsernameError(f'Failed {msg}') + if code == 'cirrussearch-too-busy-error': # T170647 self.wait() continue
pywikibot-commits@lists.wikimedia.org