jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1108093?usp=email )
Change subject: [IMPR] Improvements for require_version decorator
......................................................................
[IMPR] Improvements for require_version decorator
- version_needed is a positional only parameter
- TypeError and ValueError are used for validation fails instead of
unspecific Exception
- try/except with re.split to detect unpack errors and raise a
ValueError('There is no valid operator given with version...')
- remove test for empty op which cannot happen with re.split()
- raise ValueError if the left part of re.split() is not empty
- do not pass arguments to called method because a TypeError is
raised already for such cases
- add tests for this decorator
Change-Id: I5d3e14aac05dbf66229fd2c897796740d7f6ec5e
---
M tests/aspects.py
M tests/tests_tests.py
2 files changed, 111 insertions(+), 14 deletions(-)
Approvals:
Xqt: Looks good to me, approved
jenkins-bot: Verified
diff --git a/tests/aspects.py b/tests/aspects.py
index 084cd29..8c71a21 100644
--- a/tests/aspects.py
+++ b/tests/aspects.py
@@ -284,7 +284,7 @@
return test_requirement
-def require_version(version_needed: str, reason: str = ''):
+def require_version(version_needed: str, /, reason: str = ''):
"""Require minimum MediaWiki version to be queried.
The version needed for the test; must be given with a preleading rich
@@ -298,9 +298,17 @@
.. versionadded:: 8.0
+ .. versionchanged:: 10.0
+ TypeError and ValueError are used for validation fails.
+ *version_needed* parameter is positional only.
+
:param version_needed: The version needed
:param reason: A reason for skipping the test.
- :raises Exception: Usage validation fails
+ :raises TypeError: self.site is not a BaseSite or the decorated
+ method has parameters.
+ :raises ValueError: The given *version_needed* parameter is invalid
+ or an operand is given on the left or the version number is
+ invalid
"""
def test_requirement(method):
"""Test the requirement and return an optionally decorated object."""
@@ -309,26 +317,33 @@
"""Validate environment."""
if not isinstance(self.site, BaseSite) \
or isinstance(self.site, DrySite):
- raise Exception( # pragma: no cover
+ raise TypeError(
f'{type(self).__name__}.site must be a BaseSite not '
f'{type(self.site).__name__}.')
if args or kwargs:
- raise Exception( # pragma: no cover
+ raise TypeError(
f'Test method {method.__name__!r} has parameters which is '
- f'not supported with require_version decorator.')
+ f'not supported with require_version decorator.'
+ )
- _, op, version = re.split('([<>]=?)', version_needed)
- if not op: # pragma: no cover
- raise Exception(f'There is no valid operator given with '
- f'version {version_needed!r}')
+ try:
+ site_vers, op, version = re.split('([<>]=?)', version_needed)
+ except ValueError:
+ raise ValueError(f'There is no valid operator given with '
+ f'version {version_needed!r}')
+
+ if site_vers:
+ raise ValueError(
+ f'first operand {site_vers} should not be set')
skip = not eval(
f'self.site.mw_version {op} MediaWikiVersion(version)')
- if not skip:
- return method(self, *args, **kwargs)
- myreason = ' to ' + reason if reason else '' # pragma: no cover
+ if not skip:
+ return method(self)
+
+ myreason = ' to ' + reason if reason else ''
raise unittest.SkipTest(
f'MediaWiki {op} v{version} required{myreason}.')
diff --git a/tests/tests_tests.py b/tests/tests_tests.py
index 4ccd012..749aab1 100755
--- a/tests/tests_tests.py
+++ b/tests/tests_tests.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""Tests for the tests package."""
#
-# (C) Pywikibot team, 2014-2023
+# (C) Pywikibot team, 2014-2025
#
# Distributed under the terms of the MIT license.
from __future__ import annotations
@@ -10,7 +10,7 @@
from contextlib import suppress
from tests import utils
-from tests.aspects import TestCase
+from tests.aspects import DefaultSiteTestCase, TestCase, require_version
class HttpServerProblemTestCase(TestCase):
@@ -78,6 +78,88 @@
self.assertLength(None, self.seq)
+class TestRequireVersionDry(DefaultSiteTestCase):
+
+ """Test require_version decorator."""
+
+ dry = True
+
+ @require_version('')
+ def method(self):
+ """Test method for decorator."""
+
+ def test_require_version(self):
+ """Test require_version for DrySite."""
+ with self.assertRaisesRegex(
+ TypeError,
+ f'{type(self).__name__}.site must be a BaseSite not DrySite'):
+ self.method()
+
+
+class TestRequireVersion(DefaultSiteTestCase):
+
+ """Test require_version decorator."""
+
+ @require_version('')
+ def method_with_params(self, key):
+ """Test method for decorated methods with unsupported arguments."""
+
+ def method_failing(self):
+ """Test method for decorator with invalid parameter."""
+ self.assertTrue(False, 'should never happen')
+
+ @require_version('>=1.31')
+ def method_succeed(self):
+ """Test that decorator passes."""
+ self.assertTrue(False, 'intentional fail for method_succeed test')
+
+ @require_version('<1.31')
+ def method_fail(self):
+ """Test that decorator skips."""
+ self.assertTrue(False, 'intentional fail for test')
+
+ def test_unsupported_methods(self):
+ """Test require_version with unsupported methods."""
+ with self.assertRaisesRegex(
+ TypeError, "Test method 'method_with_params' has parameters"):
+ self.method_with_params('42')
+ with self.assertRaisesRegex(
+ TypeError, "Test method 'method_with_params' has parameters"):
+ self.method_with_params(key='42')
+ with self.assertRaisesRegex(ValueError,
+ 'There is no valid operator given '):
+ self.method_with_params()
+
+ def test_version_needed(self):
+ """Test for invalid decorator parameters."""
+ with self.assertRaisesRegex(ValueError,
+ 'There is no valid operator given '):
+ require_version('foo')(self.method_failing)(self)
+ with self.assertRaisesRegex(ValueError,
+ 'first operand foo should not be set'):
+ require_version('foo>bar')(self.method_failing)(self)
+ with self.assertRaisesRegex(ValueError, 'Invalid version number'):
+ require_version('>bar')(self.method_failing)(self)
+ with self.assertRaisesRegex(unittest.SkipTest,
+ r'MediaWiki < v1\.31 required'):
+ require_version('<1.31')(self.method_failing)(self)
+ with self.assertRaisesRegex(
+ unittest.SkipTest,
+ r'MediaWiki < v1\.31 required to run this test'):
+ require_version('<1.31',
+ 'run this test')(self.method_failing)(self)
+
+ def test_decorator(self):
+ """Test that decorator passes or skips."""
+ with self.assertRaisesRegex(
+ AssertionError,
+ 'intentional fail for method_succeed test'):
+ self.method_succeed()
+ with self.assertRaisesRegex(unittest.SkipTest,
+ r'MediaWiki < v1\.31 required'):
+ self.method_fail()
+
+
class UtilsTests(TestCase):
"""Tests for tests.utils."""
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1108093?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: I5d3e14aac05dbf66229fd2c897796740d7f6ec5e
Gerrit-Change-Number: 1108093
Gerrit-PatchSet: 4
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot
jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1108042?usp=email )
Change subject: [IMPR] use default timeout uf 30 s in MementoClient.request_head
......................................................................
[IMPR] use default timeout uf 30 s in MementoClient.request_head
Memento requests needs 17-22 seconds. Therefore increase the default
timeout. Also:
- add a timeout parameter to get_closest_memento_url function
- update documentation
- update tests/memento_tests.py
Bug: T382943
Change-Id: I659c850add79d569cea7ee81bb2981088a7a1078
---
M pywikibot/data/memento.py
M tests/memento_tests.py
2 files changed, 28 insertions(+), 9 deletions(-)
Approvals:
Xqt: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/data/memento.py b/pywikibot/data/memento.py
index 9bd5110..337f36c 100644
--- a/pywikibot/data/memento.py
+++ b/pywikibot/data/memento.py
@@ -9,7 +9,7 @@
# Parts of MementoClient class codes are
# licensed under the BSD open source software license.
#
-# (C) Pywikibot team, 2015-2024
+# (C) Pywikibot team, 2015-2025
#
# Distributed under the terms of the MIT license.
#
@@ -263,13 +263,17 @@
timeout: int | None = None) -> requests.Response:
"""Makes HEAD requests.
+ .. versionchanged:: 10.0
+ The default timout was increased from 9 to 30 seconds.
+
:param uri: the uri for the request.
:param accept_datetime: the accept-datetime in the http format.
:param follow_redirects: Toggle to follow redirects. False by
default, so does not follow any redirects.
:param session: the request session object to avoid opening new
connections for every request.
- :param timeout: the timeout for the HTTP requests.
+ :param timeout: the timeout for the HTTP requests. Default is
+ 30 s.
:return: the response object.
:raises ValueError: Only HTTP URIs are supported
"""
@@ -285,7 +289,7 @@
response = session.head(uri,
headers=headers,
allow_redirects=follow_redirects,
- timeout=timeout or 9)
+ timeout=timeout or 30)
except (InvalidSchema, MissingSchema):
raise ValueError(
f'Only HTTP URIs are supported, URI {uri} unrecognized.')
@@ -308,8 +312,23 @@
def get_closest_memento_url(url: str,
when: datetime | None = None,
- timegate_uri: str | None = None):
- """Get most recent memento for url."""
+ timegate_uri: str | None = None,
+ *,
+ timeout: int | None = None):
+ """Get most recent memento for url.
+
+ .. versionadded:: 10.0
+ The *timeout* parameter.
+
+ :param url: The input http url.
+ :param when: The datetime object of the accept datetime. The current
+ datetime is used if none is provided.
+ :param timegate_uri: A valid HTTP base uri for a timegate. Must
+ start with http(s):// and end with a /. Default value is
+ http://timetravel.mementoweb.org/timegate/.
+ :param timeout: The timeout value for the HTTP connection. If None,
+ a default value is used in :meth:`MementoClient.request_head`.
+ """
if not when:
when = datetime.now()
@@ -320,7 +339,7 @@
retry_count = 0
while retry_count <= config.max_retries:
try:
- memento_info = mc.get_memento_info(url, when)
+ memento_info = mc.get_memento_info(url, when, timeout)
break
except (requests.ConnectionError, MementoClientException) as e:
error = e
diff --git a/tests/memento_tests.py b/tests/memento_tests.py
index 2a56d80..fdeb5e4 100755
--- a/tests/memento_tests.py
+++ b/tests/memento_tests.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""memento client test module."""
#
-# (C) Pywikibot team, 2015-2022
+# (C) Pywikibot team, 2015-2025
#
# Distributed under the terms of the MIT license.
#
@@ -46,13 +46,13 @@
hostname = timegate_uri.replace('gate/', 'map/json/http://google.com')
def test_newest(self):
- """Test Archive for newest https://google.com."""
+ """Test Archive for an old https://google.com."""
dt = '20220715'
archivedversion = self._get_archive_url('https://google.com',
date_string=dt)
parsed = urlparse(archivedversion)
self.assertIn(parsed.scheme, ['http', 'https'])
- self.assertEqual(parsed.netloc, 'arquivo.pt')
+ self.assertEqual(parsed.netloc, 'wayback.library.yorku.ca')
class TestMementoDefault(MementoTestCase):
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1108042?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: I659c850add79d569cea7ee81bb2981088a7a1078
Gerrit-Change-Number: 1108042
Gerrit-PatchSet: 1
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot
jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/i18n/+/1107943?usp=email )
Change subject: Localisation updates from https://translatewiki.net.
......................................................................
Localisation updates from https://translatewiki.net.
Change-Id: I50ae56c0bbaa13af5fc1c442b1b51298c58014c8
---
M redirect/br.json
1 file changed, 4 insertions(+), 3 deletions(-)
Approvals:
jenkins-bot: Verified
L10n-bot: Looks good to me, approved
diff --git a/redirect/br.json b/redirect/br.json
index 23bd67d..1d0a2fa 100644
--- a/redirect/br.json
+++ b/redirect/br.json
@@ -5,12 +5,13 @@
"Fohanno",
"Fulup",
"Gwenn-Ael",
+ "Huñvreüs",
"Y-M D"
]
},
- "redirect-fix-broken-moved": "O reizhañ an adkasoù torret war-zu ar bajenn bal %(to)s",
- "redirect-fix-double": "Dresañ an adkas doubl da %(to)s",
- "redirect-fix-loop": "O tresañ al lagadenn adkas war-zu %(to)s",
+ "redirect-fix-broken-moved": "Reizhet adkas torret eus %(from)s war-zu ar bajenn bal %(to)s",
+ "redirect-fix-double": "Dreset adkas doubl eus %(from)s da %(to)s",
+ "redirect-fix-loop": "Reizhet ar boukl adkas eus %(from)s da %(to)s",
"redirect-remove-broken": "Adkas war-zu ur bajenn n'eus ket anezhi pe a zo bet dilamet",
"redirect-remove-loop": "Stumm ur c'helc'h-tro born zo gant an [[Wikipedia:Redirect|adkas]]"
}
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/i18n/+/1107943?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/i18n
Gerrit-Branch: master
Gerrit-Change-Id: I50ae56c0bbaa13af5fc1c442b1b51298c58014c8
Gerrit-Change-Number: 1107943
Gerrit-PatchSet: 1
Gerrit-Owner: L10n-bot <l10n-bot(a)translatewiki.net>
Gerrit-Reviewer: L10n-bot <l10n-bot(a)translatewiki.net>
Gerrit-Reviewer: jenkins-bot
jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1107560?usp=email )
Change subject: backports: remove deprecation and declare not public API
......................................................................
backports: remove deprecation and declare not public API
Change-Id: I809b5e582d9d3d74bb775c420b061ea7810a3bbf
---
M pywikibot/backports.py
1 file changed, 2 insertions(+), 16 deletions(-)
Approvals:
Xqt: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/backports.py b/pywikibot/backports.py
index d93b8a0..d981548 100644
--- a/pywikibot/backports.py
+++ b/pywikibot/backports.py
@@ -1,8 +1,7 @@
"""This module contains backports to support older Python versions.
-.. deprecated:: 9.0
- The *nullcontext* context manager; use ``contextlib.nullcontext``
- instead. The *SimpleQueue* queue; use ``queue.SimpleQueue`` instead.
+This module is not part of the public pywikibot API. Breaking changes may be
+made at any time, and the module is not subject to deprecation requirements.
"""
#
# (C) Pywikibot team, 2014-2024
@@ -203,16 +202,3 @@
yield group
else:
from itertools import batched # type: ignore[no-redef]
-
-
-# import ModuleDeprecationWrapper here to prevent circular import
-from pywikibot.tools import ModuleDeprecationWrapper # noqa: E402
-
-
-wrapper = ModuleDeprecationWrapper(__name__)
-wrapper.add_deprecated_attr('nullcontext',
- replacement_name='contextlib.nullcontext',
- since='9.0.0')
-wrapper.add_deprecated_attr('SimpleQueue',
- replacement_name='queue.SimpleQueue',
- since='9.0.0')
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1107560?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: I809b5e582d9d3d74bb775c420b061ea7810a3bbf
Gerrit-Change-Number: 1107560
Gerrit-PatchSet: 1
Gerrit-Owner: JJMC89 <JJMC89.Wikimedia(a)gmail.com>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot