Xqt has submitted this change. (
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1307599?usp=email )
Change subject: Rename TimeoutError to ApiTimeoutError, keep old name as
deprecated alias
......................................................................
Rename TimeoutError to ApiTimeoutError, keep old name as deprecated alias
Bug: T431174
Change-Id: Ie36effbc761510c1b1a9efffe0d1dbd2087a652b
---
M ROADMAP.rst
M pywikibot/data/__init__.py
M pywikibot/exceptions.py
M pywikibot/page/_toolforge.py
M tests/__init__.py
A tests/exceptions_tests.py
M tests/page_tests.py
M tests/site_generators_tests.py
M tests/sparql_tests.py
9 files changed, 105 insertions(+), 18 deletions(-)
Approvals:
jenkins-bot: Verified
Xqt: Looks good to me, approved
diff --git a/ROADMAP.rst b/ROADMAP.rst
index 7d1d12e..f7d7322 100644
--- a/ROADMAP.rst
+++ b/ROADMAP.rst
@@ -1,6 +1,7 @@
Release 11.5
============
+* Rename :exc:`exceptions.TimeoutError` exception to
:class:`exceptions.ApiTimeoutError` to avoid collision with Python's built-in
exception (:phab:`T431174`)
* Drop :mod:`config` ``textfile_encoding`` variable and use 'utf-8' directly
instead (:phab:`T430454`)
* Use pyclean package with :mod:`make_dist` script.
* Fix redirected link for :class:`pagegenerators.PetScanPageGenerator`
@@ -107,6 +108,7 @@
Pending removal in Pywikibot 14
-------------------------------
+* 11.5.0: :exc:`exceptions.TimeoutError` is deprecated in favour of
:class:`exceptions.ApiTimeoutError`
* 11.5.0: :mod:`config` ``textfile_encoding`` variable will be removed; use
'utf-8' directly instead
(:phab:`T430454`)
* 11.4.0: The signature of :meth:`APISite.allusers()
diff --git a/pywikibot/data/__init__.py b/pywikibot/data/__init__.py
index aa58b00..19270cc 100644
--- a/pywikibot/data/__init__.py
+++ b/pywikibot/data/__init__.py
@@ -44,7 +44,7 @@
self.current_retries += 1
if self.current_retries > self.max_retries:
- raise pywikibot.exceptions.TimeoutError(
+ raise pywikibot.exceptions.ApiTimeoutError(
'Maximum retries attempted without success.')
# double the next wait, but do not exceed config.retry_max seconds
diff --git a/pywikibot/exceptions.py b/pywikibot/exceptions.py
index 7c00ac5..7aa1831 100644
--- a/pywikibot/exceptions.py
+++ b/pywikibot/exceptions.py
@@ -54,7 +54,7 @@
+-- SiteDefinitionError
| +-- UnknownFamilyError
| +-- UnknownSiteError
- +-- TimeoutError
+ +-- ApiTimeoutError
| +-- MaxlagTimeoutError
+-- TranslationError
+-- UserRightsError
@@ -143,7 +143,7 @@
- CoordinateGlobeUnknownError: globe is not implemented yet.
- EntityTypeUnknownError: entity type is not available on the site.
-TimeoutError: request failed with a timeout
+ApiTimeoutError: request failed with a timeout
- MaxlagTimeoutError: request failed with a maxlag timeout
@@ -182,7 +182,10 @@
from typing import Any
import pywikibot
-from pywikibot.tools._deprecate import _NotImplementedWarning
+from pywikibot.tools._deprecate import (
+ ModuleDeprecationWrapper,
+ _NotImplementedWarning,
+)
class NotImplementedWarning(_NotImplementedWarning):
@@ -720,12 +723,12 @@
"""The requested entity type is not recognised on this site."""
-class TimeoutError(Error):
+class ApiTimeoutError(Error):
"""Request failed with a timeout error."""
-class MaxlagTimeoutError(TimeoutError):
+class MaxlagTimeoutError(ApiTimeoutError):
"""Request failed with a maxlag timeout error."""
@@ -733,3 +736,11 @@
class ApiNotAvailableError(Error):
"""API is not available, e.g. due to a network error or configuration."""
+
+
+wrapper = ModuleDeprecationWrapper(__name__)
+wrapper.add_deprecated_attr(
+ 'TimeoutError',
+ replacement=ApiTimeoutError,
+ since='11.5.0',
+)
diff --git a/pywikibot/page/_toolforge.py b/pywikibot/page/_toolforge.py
index 84437b0..1e2426e 100644
--- a/pywikibot/page/_toolforge.py
+++ b/pywikibot/page/_toolforge.py
@@ -72,7 +72,7 @@
:raise NotImplementedError: unsupported site or unsupported
namespace.
:raise NoPageError: The page does not exist.
- :raise TimeoutError: WikiHistory timeout
+ :raise ApiTimeoutError: WikiHistory timeout
"""
return collections.Counter(
{user: int(cnt) for user, (_, cnt) in self.authorship(5).items()})
@@ -166,7 +166,7 @@
:raise NotImplementedError: unsupported site or unsupported
namespace.
:raise NoPageError: The page does not exist.
- :raise TimeoutError: WikiHistory timeout
+ :raise ApiTimeoutError: WikiHistory timeout
"""
if n and n > 5:
warn('Only the first 5 authors can be given.', stacklevel=2)
@@ -190,7 +190,7 @@
pywikibot.sleep(pywikibot.config.retry_wait)
else:
- raise pywikibot.exceptions.TimeoutError('WikiHistory Timeout')
+ raise pywikibot.exceptions.ApiTimeoutError('WikiHistory Timeout')
length = len(self.text)
result: list[list[str]] = []
diff --git a/tests/__init__.py b/tests/__init__.py
index 7c1fb7d..851a402 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -81,6 +81,7 @@
'echo',
'edit',
'edit_failure',
+ 'exceptions',
'eventstreams',
'family',
'file',
diff --git a/tests/exceptions_tests.py b/tests/exceptions_tests.py
new file mode 100755
index 0000000..96d1925
--- /dev/null
+++ b/tests/exceptions_tests.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python3
+#
+# (C) Pywikibot team, 2026
+#
+# Distributed under the terms of the MIT license.
+#
+"""Tests for the exceptions module."""
+from __future__ import annotations
+
+import unittest
+from contextlib import suppress
+
+import pywikibot
+from pywikibot.exceptions import ApiTimeoutError, Error, MaxlagTimeoutError
+from tests.aspects import DeprecationTestCase, TestCase
+
+
+class TestApiTimeoutError(TestCase):
+
+ """Test ApiTimeoutError exceptions."""
+
+ net = False
+
+ def test_hierarchy(self) -> None:
+ """Test inheritance hierarchy."""
+ self.assertTrue(issubclass(ApiTimeoutError, Error))
+ self.assertTrue(issubclass(MaxlagTimeoutError, ApiTimeoutError))
+
+ def test_raise_catch(self) -> None:
+ """Test raising and catching ApiTimeoutError."""
+ with self.assertRaises(ApiTimeoutError):
+ raise ApiTimeoutError('Test timeout')
+
+ with self.assertRaises(ApiTimeoutError):
+ raise MaxlagTimeoutError('Test maxlag timeout')
+
+
+class TestTimeoutErrorDeprecation(DeprecationTestCase):
+
+ """Test deprecation of TimeoutError alias."""
+
+ net = False
+
+ def test_deprecation(self) -> None:
+ """Test that accessing TimeoutError triggers a deprecation warning."""
+ # Accessing the deprecated attribute
+ exc_class = pywikibot.exceptions.TimeoutError
+ self.assertIs(exc_class, ApiTimeoutError)
+ self.assertOneDeprecationParts(
+ 'pywikibot.exceptions.TimeoutError',
+ 'pywikibot.exceptions.ApiTimeoutError'
+ )
+
+ def test_raise_catch_deprecated(self) -> None:
+ """Test raising and catching using the deprecated alias."""
+ # Reset any messages from previous tests
+ self._reset_messages()
+
+ # Catch ApiTimeoutError using the TimeoutError alias
+ try:
+ raise ApiTimeoutError('Test raise')
+ except pywikibot.exceptions.TimeoutError:
+ pass
+
+ self.assertOneDeprecationParts(
+ 'pywikibot.exceptions.TimeoutError',
+ 'pywikibot.exceptions.ApiTimeoutError'
+ )
+
+
+if __name__ == '__main__':
+ with suppress(SystemExit):
+ unittest.main()
diff --git a/tests/page_tests.py b/tests/page_tests.py
index 8309042..2aef677 100755
--- a/tests/page_tests.py
+++ b/tests/page_tests.py
@@ -19,13 +19,13 @@
from pywikibot import config
from pywikibot.exceptions import (
APIError,
+ ApiTimeoutError,
Error,
InvalidTitleError,
IsNotRedirectPageError,
IsRedirectPageError,
NoPageError,
SectionError,
- TimeoutError,
UnknownExtensionError,
)
from pywikibot.tools import suppress_warnings
@@ -523,7 +523,7 @@
for p in mainpage.backlinks(follow_redirects=False, total=10):
self.assertIsInstance(p, pywikibot.Page)
- with skipping(TimeoutError):
+ with skipping(ApiTimeoutError):
for p in mainpage.embeddedin(total=10):
self.assertIsInstance(p, pywikibot.Page)
diff --git a/tests/site_generators_tests.py b/tests/site_generators_tests.py
index 2e8676e..4f4feb3 100755
--- a/tests/site_generators_tests.py
+++ b/tests/site_generators_tests.py
@@ -15,11 +15,11 @@
from pywikibot.data import api
from pywikibot.exceptions import (
APIError,
+ ApiTimeoutError,
Error,
HiddenKeyError,
InvalidTitleError,
NoPageError,
- TimeoutError,
)
from pywikibot.tools import suppress_warnings
from tests import WARN_SITE_CODE, unittest_print
@@ -65,7 +65,7 @@
"""Test Site.pagereferences."""
# pagereferences includes both backlinks and embeddedin
backlinks = set(self.site.pagebacklinks(self.mainpage, namespaces=[0]))
- with skipping(TimeoutError):
+ with skipping(ApiTimeoutError):
embedded = set(self.site.page_embeddedin(self.mainpage,
namespaces=[0]))
refs = set(self.site.pagereferences(self.mainpage, namespaces=[0]))
@@ -105,7 +105,7 @@
def test_embeddedin(self) -> None:
"""Test Site.page_embeddedin."""
- with skipping(TimeoutError):
+ with skipping(ApiTimeoutError):
embedded_ns_0 = set(self.site.page_embeddedin(
self.mainpage, namespaces=[0]))
embedded_ns_0_2 = set(self.site.page_embeddedin(
diff --git a/tests/sparql_tests.py b/tests/sparql_tests.py
index 6ae2d13..ffb985f 100755
--- a/tests/sparql_tests.py
+++ b/tests/sparql_tests.py
@@ -109,7 +109,7 @@
"""Test SELECT query."""
mock_method.return_value = Container(
SQL_RESPONSE_CONTAINER % f'{ITEM_Q498787}, {ITEM_Q677525}')
- with skipping(pywikibot.exceptions.TimeoutError):
+ with skipping(pywikibot.exceptions.ApiTimeoutError):
q = sparql.SparqlQuery()
res = q.select('SELECT * WHERE { ?x ?y ?z }')
self.assertIsInstance(res, list, 'Result is not a list')
@@ -131,7 +131,7 @@
"""Test SELECT query with full data."""
mock_method.return_value = Container(
SQL_RESPONSE_CONTAINER % f'{ITEM_Q498787}, {ITEM_Q677525}')
- with skipping(pywikibot.exceptions.TimeoutError):
+ with skipping(pywikibot.exceptions.ApiTimeoutError):
q = sparql.SparqlQuery()
res = q.select('SELECT * WHERE { ?x ?y ?z }', full_data=True)
self.assertIsInstance(res, list, 'Result is not a list')
@@ -162,7 +162,7 @@
SQL_RESPONSE_CONTAINER % (f'{ITEM_Q498787}, {ITEM_Q677525}, '
f'{ITEM_Q677525}')
)
- with skipping(pywikibot.exceptions.TimeoutError):
+ with skipping(pywikibot.exceptions.ApiTimeoutError):
q = sparql.SparqlQuery()
res = q.get_items('SELECT * WHERE { ?x ?y ?z }', 'cat')
self.assertEqual(res, {'Q498787', 'Q677525'})
@@ -174,7 +174,7 @@
def testQueryAsk(self, mock_method) -> None:
"""Test ASK query."""
mock_method.return_value = Container(RESPONSE_TRUE)
- with skipping(pywikibot.exceptions.TimeoutError):
+ with skipping(pywikibot.exceptions.ApiTimeoutError):
q = sparql.SparqlQuery()
res = q.ask('ASK { ?x ?y ?z }')
--
To view, visit
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1307599?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: Ie36effbc761510c1b1a9efffe0d1dbd2087a652b
Gerrit-Change-Number: 1307599
Gerrit-PatchSet: 2
Gerrit-Owner: Prakhar0804 <[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]