jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1051686?usp=email )
Change subject: [lint] Fix lint checks, mainly use f-string instead of .format() ......................................................................
[lint] Fix lint checks, mainly use f-string instead of .format()
Change-Id: Icf4d99358380194546e1497588cd67cd16790251 --- M pyproject.toml M tests/__init__.py M tests/archivebot_tests.py M tests/aspects.py M tests/basesite_tests.py M tests/bot_tests.py M tests/category_bot_tests.py M tests/data/fixes.py M tests/data/set-fixes.py M tests/date_tests.py M tests/djvu_tests.py M tests/edit_tests.py M tests/eventstreams_tests.py M tests/family_tests.py M tests/file_tests.py M tests/flow_edit_tests.py M tests/flow_thanks_tests.py M tests/generate_family_file_tests.py M tests/i18n_tests.py M tests/l10n_tests.py M tests/link_tests.py M tests/namespace_tests.py M tests/page_tests.py M tests/pagegenerators_tests.py M tests/patrolbot_tests.py M tests/pwb_tests.py M tests/replacebot_tests.py M tests/script_tests.py M tests/site_generators_tests.py M tests/site_tests.py M tests/sparql_tests.py M tests/textlib_tests.py M tests/thanks_tests.py M tests/timestripper_tests.py M tests/tools_deprecate_tests.py M tests/ui_options_tests.py M tests/ui_tests.py M tests/upload_tests.py M tests/user_tests.py M tests/utils.py M tests/wikistats_tests.py 41 files changed, 191 insertions(+), 209 deletions(-)
Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
diff --git a/pyproject.toml b/pyproject.toml index 3c8eb7f..f1ac0a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -125,3 +125,26 @@ Download = "https://www.pywikibot.org" Changelog = "https://doc.wikimedia.org/pywikibot/master/changelog.html" Tracker = "https://phabricator.wikimedia.org/tag/pywikibot/" + +[tool.ruff] +line-length = 80 + +[tool.ruff.format] +quote-style = "single" +docstring-code-format = true + +[tool.ruff.lint] +select = [ + # pycodestyle + "E", + # Pyflakes + "F", + # pyupgrade + "UP", + # flake8-bugbear + "B", + # flake8-simplify + "SIM", + # isort + "I", +] \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py index 0660f96..34944b3 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -6,7 +6,6 @@ # from __future__ import annotations
- __all__ = ( 'create_path_func', 'join_cache_path', 'join_data_path', 'join_html_data_path', 'join_images_path', 'join_pages_path', @@ -34,7 +33,6 @@ from pywikibot.data.api import CachedRequest from pywikibot.data.api import Request as _original_Request
- _root_dir = os.path.split(os.path.split(__file__)[0])[0]
WARN_SITE_CODE = '^Site .*:.* instantiated using different code *' # T234147 diff --git a/tests/archivebot_tests.py b/tests/archivebot_tests.py index 20a6052..a5f8db2 100755 --- a/tests/archivebot_tests.py +++ b/tests/archivebot_tests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Tests for archivebot scripts.""" # -# (C) Pywikibot team, 2014-2023 +# (C) Pywikibot team, 2014-2024 # # Distributed under the terms of the MIT license. # @@ -17,7 +17,6 @@ from scripts import archivebot from tests.aspects import TestCase
- THREADS = { 'als': 4, 'ar': 1, 'bar': 0, 'bg': 0, 'bjn': 1, 'bs': 0, 'ca': 5, 'ckb': 2, 'cs': 0, 'de': 1, 'en': 25, 'eo': 2, 'es': 13, 'fa': 2, 'fr': 25, 'frr': 2, @@ -130,8 +129,9 @@ self.assertIsInstance(talk.threads, list) self.assertGreaterEqual( len(talk.threads), THREADS[code], - '{} Threads found on {},\n{} or more expected' - .format(len(talk.threads), talk, THREADS[code])) + f'{len(talk.threads)} Threads found on {talk},\n{THREADS[code]} or' + ' more expected' + )
for thread in talk.threads: with self.subTest(thread=thread.title, @@ -188,9 +188,9 @@ self.assertIsInstance(talk.threads, list) self.assertGreaterEqual( len(talk.threads), THREADS_WITH_UPDATED_FORMAT[code], - '{} Threads found on {},\n{} or more expected' - .format(len(talk.threads), talk, - THREADS_WITH_UPDATED_FORMAT[code])) + f'{len(talk.threads)} Threads found on {talk},\n' + f'{THREADS_WITH_UPDATED_FORMAT[code]} or more expected' + )
for thread in talk.threads: with self.subTest(thread=thread.title, diff --git a/tests/aspects.py b/tests/aspects.py index a64d9b9..3ffb41b 100644 --- a/tests/aspects.py +++ b/tests/aspects.py @@ -36,8 +36,10 @@ ) from pywikibot.family import WikimediaFamily from pywikibot.site import BaseSite -from pywikibot.tools import MediaWikiVersion # noqa: F401 (used by f-string) -from pywikibot.tools import suppress_warnings +from pywikibot.tools import ( # noqa: F401 (used by eval()) + MediaWikiVersion, + suppress_warnings, +) from tests import ( WARN_SITE_CODE, patch_request, @@ -53,7 +55,6 @@ skipping, )
- OSWIN32 = (sys.platform == 'win32') pywikibot.bot.set_interface('buffer')
@@ -456,12 +457,12 @@ if hostname in cls._checked_hostnames: if isinstance(cls._checked_hostnames[hostname], Exception): raise unittest.SkipTest( - '{}: hostname {} failed (cached): {}' - .format(cls.__name__, hostname, - cls._checked_hostnames[hostname])) + f'{cls.__name__}: hostname {hostname} failed ' + f'(cached): {cls._checked_hostnames[hostname]}' + ) if cls._checked_hostnames[hostname] is False: - raise unittest.SkipTest('{}: hostname {} failed (cached)' - .format(cls.__name__, hostname)) + raise unittest.SkipTest( + f'{cls.__name__}: hostname {hostname} failed (cached)') continue
try: @@ -476,16 +477,15 @@ HTTPStatus.SEE_OTHER, HTTPStatus.TEMPORARY_REDIRECT, HTTPStatus.PERMANENT_REDIRECT}: - raise ServerError( - 'HTTP status: {} - {}'.format( - r.status_code, HTTPStatus(r.status_code).phrase)) + raise ServerError(f'HTTP status: {r.status_code} - ' + f'{HTTPStatus(r.status_code).phrase}') except Exception as e: - pywikibot.exception('{}: accessing {} caused exception:' - .format(cls.__name__, hostname)) + pywikibot.exception( + f'{cls.__name__}: accessing {hostname} caused exception:')
cls._checked_hostnames[hostname] = e - raise unittest.SkipTest( - f'{cls.__name__}: hostname {hostname} failed: {e}') + raise unittest.SkipTest(f'{cls.__name__}: hostname {hostname}' + ' failed: {e}') from None
cls._checked_hostnames[hostname] = True
@@ -758,9 +758,9 @@ # check that the script invoked by pwb will not load a site. if dct.get('pwb') and 'site' not in dct: raise Exception( - '{}: Test classes using pwb must set "site"; add ' - 'site=False if the test script will not use a site' - .format(name)) + f'{name}: Test classes using pwb must set "site";' + ' add site=False if the test script will not use a site' + )
# If the 'site' attribute is a false value, # remove it so it matches 'not site' in pytest. @@ -822,9 +822,9 @@ # A multi-site test method only accepts 'self' and the site-key if test_func.__code__.co_argcount != 2: raise Exception( - '{}: Test method {} must accept either 1 or 2 arguments; ' - ' {} found' - .format(name, test, test_func.__code__.co_argcount)) + f'{name}: Test method {test} must accept either 1 or 2 ' + f'arguments; {test_func.__code__.co_argcount} found' + )
# create test methods processed by unittest for (key, sitedata) in dct['sites'].items(): @@ -1077,8 +1077,7 @@ :type site: BaseSite """ unittest_print( - '{cls.__name__} using {site} instead of {cls.family}:{cls.code}.' - .format(cls=cls, site=site)) + f'{cls.__name__} using {site} instead of {cls.family}:{cls.code}.') cls.site = site cls.family = site.family.name cls.code = site.code @@ -1180,9 +1179,8 @@
if (hasattr(cls, 'repo') and cls.repo != site.data_repository()): - raise Exception( - '{}: sites do not all have the same data repository' - .format(cls.__name__)) + raise Exception(f'{cls.__name__}: sites do not all have' + ' the same data repository')
cls.repo = site.data_repository()
@@ -1429,8 +1427,8 @@ or msg is None): break else: - self.fail('No generic deprecation message match found in {}' - .format(deprecation_messages)) + self.fail('No generic deprecation message match found in ' + f'{deprecation_messages}') else: head, _, tail = msg.partition('; ') for message in self.deprecation_messages: @@ -1438,8 +1436,8 @@ and message.endswith(tail): break else: - self.fail("'{}' not found in {} (ignoring since)" - .format(msg, self.deprecation_messages)) + self.fail(f"'{msg}' not found in {self.deprecation_messages}" + '(ignoring since)') if self._do_test_warning_filename: self.assertDeprecationFile(self.expect_warning_filename)
diff --git a/tests/basesite_tests.py b/tests/basesite_tests.py index 4b6e138..0e66123 100755 --- a/tests/basesite_tests.py +++ b/tests/basesite_tests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Tests for the site module.""" # -# (C) Pywikibot team, 2008-2022 +# (C) Pywikibot team, 2008-2024 # # Distributed under the terms of the MIT license. # @@ -13,7 +13,6 @@ from pywikibot.exceptions import Error from tests.aspects import DefaultSiteTestCase, TestCase, unittest
- WARN_SELF_CALL = (r'Referencing this attribute like a function ' r'is deprecated .+; use it directly instead')
@@ -99,11 +98,11 @@ self.assertIn('No disambiguation category name found', str(e)) except AssertionError: self.assertIn( - 'No {repo} qualifier found for disambiguation category ' - 'name in {fam}_family file'.format( - repo=mysite.data_repository().family.name, - fam=mysite.family.name), - str(e)) + f'No {mysite.data_repository().family.name} qualifier' + ' found for disambiguation category name in ' + f'{mysite.family.name}_family file', + str(e) + ) else: self.assertIsInstance(dabcat, pywikibot.Category)
diff --git a/tests/bot_tests.py b/tests/bot_tests.py index ab8a5cc..44e57d7 100755 --- a/tests/bot_tests.py +++ b/tests/bot_tests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Bot tests.""" # -# (C) Pywikibot team, 2015-2022 +# (C) Pywikibot team, 2015-2024 # # Distributed under the terms of the MIT license. # @@ -29,8 +29,9 @@ def setUpClass(cls): """Verify that the translations are available.""" if not i18n.messages_available(): - raise unittest.SkipTest("i18n messages package '{}' not available." - .format(i18n._messages_package_name)) + raise unittest.SkipTest( + f'i18n messages package {i18n._messages_package_name!r} not' + ' available.') super().setUpClass()
diff --git a/tests/category_bot_tests.py b/tests/category_bot_tests.py index 0ce04ce..c0fbc89 100755 --- a/tests/category_bot_tests.py +++ b/tests/category_bot_tests.py @@ -16,7 +16,6 @@ from scripts.category import CategoryMoveRobot, CategoryPreprocess from tests.aspects import DefaultSiteTestCase, TestCase
- MOCKED_USERNAME = Mock(return_value='FakeUsername')
diff --git a/tests/data/fixes.py b/tests/data/fixes.py index 9708107..8b625c8 100644 --- a/tests/data/fixes.py +++ b/tests/data/fixes.py @@ -6,7 +6,6 @@ # from __future__ import annotations
- # flake8 cannot detect that fixes is defined via pywikibot.fixes if 'fixes' not in globals(): fixes = {} diff --git a/tests/data/set-fixes.py b/tests/data/set-fixes.py index 0800174..32e4cd0 100644 --- a/tests/data/set-fixes.py +++ b/tests/data/set-fixes.py @@ -6,6 +6,5 @@ # from __future__ import annotations
- # Just kill the old value suffices fixes = {} diff --git a/tests/date_tests.py b/tests/date_tests.py index b3dfa7e..b1959ea 100755 --- a/tests/date_tests.py +++ b/tests/date_tests.py @@ -37,15 +37,16 @@ for value in range(start, stop, step): self.assertTrue( predicate(value), - "date.formats['{}']['{}']:\ninvalid value {}" - .format(formatname, code, value)) + f"date.formats['{formatname}']['{code}']:\n" + f'invalid value {value}' + )
new_value = convert(convert(value)) self.assertEqual( new_value, value, - "date.formats['{}']['{}']:\n" - 'value {} does not match {}' - .format(formatname, code, new_value, value)) + f"date.formats['{formatname}']['{code}']:\n" + f'value {new_value} does not match {value}' + ) return testMapEntry
for formatname in date.formats: @@ -78,15 +79,16 @@ with self.subTest(code=code, month=value): self.assertTrue( predicate(value), - "date.formats['{}']['{}']:\ninvalid value {}" - .format(formatname, code, value)) + f"date.formats['{formatname}']['{code}']:\n" + f'invalid value {value}' + )
new_value = convert(convert(value)) self.assertEqual( new_value, value, - "date.formats['{}']['{}']:\n" - 'value {} does not match {}' - .format(formatname, code, new_value, value)) + f"date.formats['{formatname}']['{code}']:\n" + f'value {new_value} does not match {value}' + )
def test_month_name(self): """Test some MonthName results.""" diff --git a/tests/djvu_tests.py b/tests/djvu_tests.py index fc0f951..ffc5303 100755 --- a/tests/djvu_tests.py +++ b/tests/djvu_tests.py @@ -18,7 +18,6 @@ from tests.aspects import TestCase from tests.utils import skipping
- join_djvu_data_path = create_path_func(join_data_path, 'djvu') file_djvu = join_djvu_data_path('myfilé.djvu') # test non-ASCII name
diff --git a/tests/edit_tests.py b/tests/edit_tests.py index bc1c108..01d71a1 100755 --- a/tests/edit_tests.py +++ b/tests/edit_tests.py @@ -16,7 +16,6 @@ from pywikibot.exceptions import Error from tests.aspects import TestCase, require_version
- called_back = False
diff --git a/tests/eventstreams_tests.py b/tests/eventstreams_tests.py index 1573fbc..0eacee6 100755 --- a/tests/eventstreams_tests.py +++ b/tests/eventstreams_tests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Tests for the eventstreams module.""" # -# (C) Pywikibot team, 2017-2023 +# (C) Pywikibot team, 2017-2024 # # Distributed under the terms of the MIT license. # @@ -245,12 +245,12 @@ self.es.register_filter(lambda x: all_type, ftype='all') if any_type is not None: self.es.register_filter(lambda x: any_type, ftype='any') - self.assertEqual(self.es.streamfilter(self.data), result, - 'Test EventStreams filter mixed function failed for\n' - "'none': {}, 'all': {}, 'any': {}\n" - '(expected {}, given {})' - .format(none_type, all_type, any_type, - result, not result)) + self.assertEqual( + self.es.streamfilter(self.data), result, + 'Test EventStreams filter mixed function failed for\n' + f"'none': {none_type}, 'all': {all_type}, 'any': {any_type}\n" + f'(expected {result}, given {not result})' + )
def test_filter_mixed_function(self): """Test EventStreams filter mixed function.""" @@ -283,9 +283,9 @@ self.source.resp.close() # close SSLSocket del self.source raise ValueError( - '{error}\n\nEvent no {number}: ' - 'Could not load json data from source\n${event}$' - .format(number=n, event=event, error=e)) + f'{e}\n\nEvent no {n}: ' + f'Could not load json data from source\n${event}$' + ) from e yield element del self.source
diff --git a/tests/family_tests.py b/tests/family_tests.py index 18ed841..68e52ba 100755 --- a/tests/family_tests.py +++ b/tests/family_tests.py @@ -218,9 +218,8 @@ family = Family.load(family) for code in family.codes: self.current_code = code - url = '{}://{}{}/$1'.format(family.protocol(code), - family.hostname(code), - family.path(code)) + url = (f'{family.protocol(code)}://{family.hostname(code)}' + f'{family.path(code)}/$1') with self.subTest(url=url): self.assertEqual(family.from_url(url), code)
diff --git a/tests/file_tests.py b/tests/file_tests.py index 6650bcc..dc710ad 100755 --- a/tests/file_tests.py +++ b/tests/file_tests.py @@ -74,8 +74,7 @@ self.assertIn('/wikipedia/commons/', itwp_file.get_file_url()) with self.assertRaisesRegex( NoPageError, - r'Page [[(wikipedia:|)it:{}]] doesn't exist.' - .format(title)): + rf'Page [[(wikipedia:|)it:{title}]] doesn't exist.'): itwp_file.get()
def test_local_only(self): diff --git a/tests/flow_edit_tests.py b/tests/flow_edit_tests.py index 8e6f303..5f305e1 100755 --- a/tests/flow_edit_tests.py +++ b/tests/flow_edit_tests.py @@ -15,7 +15,6 @@ from tests.aspects import TestCase from tests.utils import skipping
- MODERATION_REASON = 'Pywikibot test'
diff --git a/tests/flow_thanks_tests.py b/tests/flow_thanks_tests.py index 258f837..2f875af 100755 --- a/tests/flow_thanks_tests.py +++ b/tests/flow_thanks_tests.py @@ -13,7 +13,6 @@ from pywikibot.flow import Topic from tests.aspects import TestCase
- NO_THANKABLE_POSTS = 'There is no recent post which can be test thanked.'
diff --git a/tests/generate_family_file_tests.py b/tests/generate_family_file_tests.py index 844a535..e6f875d 100755 --- a/tests/generate_family_file_tests.py +++ b/tests/generate_family_file_tests.py @@ -114,15 +114,11 @@ f'{wiki_parse.netloc}')
site = Site(url=url) - + msg = (f'url has lang "{lang}" but Site {site} has lang ' + f'"{site.lang}"') with skipping(AssertionError, - msg='KNOWN BUG (T194138): url has lang "{lang}" ' - 'but Site {site} has lang "{site.lang}"' - .format(site=site, lang=lang)): - self.assertEqual(site.lang, lang, - 'url has lang "{lang}" ' - 'but Site {site} has lang "{site.lang}"' - .format(site=site, lang=lang)) + msg='KNOWN BUG (T194138): ' + msg): + self.assertEqual(site.lang, lang, msg)
if __name__ == '__main__': diff --git a/tests/i18n_tests.py b/tests/i18n_tests.py index c57a196..528e734 100755 --- a/tests/i18n_tests.py +++ b/tests/i18n_tests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Test i18n module.""" # -# (C) Pywikibot team, 2007-2023 +# (C) Pywikibot team, 2007-2024 # # Distributed under the terms of the MIT license. # @@ -236,8 +236,8 @@ def setUpClass(cls): """Verify that the test translations are not empty.""" if not isinstance(cls.message_package, str): - raise TypeError('{}.message_package must be a package name' - .format(cls.__name__)) # pragma: no cover + raise TypeError( # pragma: no cover + f'{cls.__name__}.message_package must be a package name') # The call to set_messages_package below exists only to confirm # that the package exists and messages are available, so # that tests can be skipped if the i18n data doesn't exist. @@ -246,8 +246,8 @@ has_messages = i18n.messages_available() i18n._messages_package_name = cls.orig_messages_package_name if not has_messages: - raise unittest.SkipTest("i18n messages package '{}' not available." - .format(cls.message_package)) + raise unittest.SkipTest('i18n messages package ' + f"'{cls.message_package}' not available.") super().setUpClass()
@@ -380,8 +380,8 @@ self.assertFalse(config.cosmetic_changes_mylang_only)
if page.content_model != 'wikitext': - self.skipTest('Wrong content model {!r} for cosmetic_changes' - .format(page.content_model)) + self.skipTest(f'Wrong content model {page.content_model!r}' + ' for cosmetic_changes')
summary = f'Working on Test page at site {self.site}' msg = page._cosmetic_changes_hook(summary) diff --git a/tests/l10n_tests.py b/tests/l10n_tests.py index e725493..83c1958 100755 --- a/tests/l10n_tests.py +++ b/tests/l10n_tests.py @@ -16,7 +16,6 @@ from pywikibot.textlib import extract_templates_and_params_regex_simple from tests.aspects import MetaTestCaseClass, TestCase
- PACKAGES = ( 'redirect-broken-redirect-template', # speedy deletion template 'archivebot-archiveheader', # archive header template @@ -51,20 +50,20 @@ if (package == PACKAGES[0] and site.code in ['simple', 'test2'] or package == PACKAGES[1] and site.code == 'test'): raise unittest.SkipTest( - "{site} wiki has '{site.lang}' language code but " - "missing template for package '{package}'. Must be " + f"{site} wiki has '{site.lang}' language code but " + f"missing template for package '{package}'. Must be " 'solved by the corresponding script.' - .format(site=site, package=package)) + )
# check whether template exists title = templates[0][0] page = pywikibot.Page(site, title, ns=10) self.assertTrue( page.exists(), - msg='Invalid L10N in package "{package}"\n' - 'template "{title}" does not exist for lang ' - '"{site.lang}" on site "{site}"' - .format(package=package, title=title, site=site)) + msg=f'Invalid L10N in package "{package}"\n' + f'template "{title}" does not exist for lang ' + f'"{site.lang}" on site "{site}"' + )
return test_template
@@ -96,8 +95,9 @@ """Skip test gracefully if i18n package is missing.""" super().setUpClass() if not i18n.messages_available(): - raise unittest.SkipTest("i18n messages package '{}' not available." - .format(i18n._messages_package_name)) + raise unittest.SkipTest( + f'i18n messages package {i18n._messages_package_name!r} not' + ' available.')
class TestPackages(TestCase): @@ -126,7 +126,7 @@ bundle = i18n._get_bundle(lang, dirname) if lang in ('en', 'qqq'): self.assertIsNotEmpty(bundle) - for key in bundle.keys(): + for key in bundle: if key == '@metadata': continue self.assertTrue( diff --git a/tests/link_tests.py b/tests/link_tests.py index 5816fef..65a26ee 100755 --- a/tests/link_tests.py +++ b/tests/link_tests.py @@ -123,33 +123,29 @@ """Test that invalid titles raise InvalidTitleError.""" # Bad characters forbidden regardless of wgLegalTitleChars def generate_contains_illegal_chars_exc_regex(text): - exc_regex = ( - r'^(u|)'{}' contains illegal char(s) (u|)'{}'$' - .format(re.escape(text), re.escape(text[2]))) + exc_regex = (rf'^(u|)'{re.escape(text)}' contains illegal char' + rf'(s) (u|)'{re.escape(text[2])}'$') return exc_regex
# Directory navigation def generate_contains_dot_combinations_exc_regex(text): - exc_regex = (r'^(contains . / combinations): (u|)'{}'$' - .format(re.escape(text))) + exc_regex = (rf'^(contains . / combinations): (u|)' + rf''{re.escape(text)}'$') return exc_regex
# Tilde def generate_contains_tilde_exc_regex(text): - exc_regex = r'^(contains ~~~): (u|)'{}'$' \ - .format(re.escape(text)) + exc_regex = rf'^(contains ~~~): (u|)'{re.escape(text)}'$' return exc_regex
# Overlength def generate_overlength_exc_regex(text): - exc_regex = r'^(over 255 bytes): (u|)'{}'$' \ - .format(re.escape(text)) + exc_regex = rf'^(over 255 bytes): (u|)'{re.escape(text)}'$' return exc_regex
# Namespace prefix without actual title def generate_has_no_title_exc_regex(text): - exc_regex = r'^(u|)'{}' has no title.$'.format( - re.escape(text.strip())) + exc_regex = rf'^(u|)'{re.escape(text.strip())}' has no title.$' return exc_regex
title_tests = [ diff --git a/tests/namespace_tests.py b/tests/namespace_tests.py index 28f6cf9..23d11c2 100755 --- a/tests/namespace_tests.py +++ b/tests/namespace_tests.py @@ -14,7 +14,6 @@ from pywikibot.site._namespace import BuiltinNamespace from tests.aspects import TestCase, unittest
- # Default namespaces which should work in any MW wiki _base_builtin_ns = { 'Media': -2, diff --git a/tests/page_tests.py b/tests/page_tests.py index 6b56914..49070de 100755 --- a/tests/page_tests.py +++ b/tests/page_tests.py @@ -37,7 +37,6 @@ ) from tests.utils import skipping
- EMPTY_TITLE_RE = r'Title must be specified and not empty if source is a Site.' INVALID_TITLE_RE = r'The link [[.*]] does not contain a page title' NO_PAGE_RE = r"doesn't exist." @@ -190,9 +189,8 @@ family_name = (site.family.name + ':' if pywikibot.config.family != site.family.name else '') - self.assertEqual(str(mainpage), '[[{}{}:{}]]' - .format(family_name, site.code, - mainpage.title())) + self.assertEqual(str(mainpage), + f'[[{family_name}{site.code}:{mainpage.title()}]]') self.assertLess(mainpage, maintalk)
def testHelpTitle(self): @@ -702,9 +700,8 @@ self.page = pywikibot.Page(self.site, 'not_existent_page_for_pywikibot_tests') if self.page.exists(): - self.skipTest( - 'Page {} exists! Change page name in tests/page_tests.py' - .format(self.page.title())) + self.skipTest(f'Page {self.page.title()} exists! Change page name' + ' in tests/page_tests.py')
def tearDown(self): """Cleanup cache.""" @@ -985,8 +982,8 @@ 'testing suite.') self.assertEqual(p1.get(), text) with self.assertRaisesRegex(IsRedirectPageError, - r'{} is a redirect page.' - .format(re.escape(str(p2)))): + rf'{re.escape(str(p2))} is a redirect ' + rf'page.'): p2.get()
try: @@ -1019,8 +1016,8 @@
text = p2.get(get_redirect=True) with self.assertRaisesRegex(IsNotRedirectPageError, - r'{} is not a redirect page.' - .format(re.escape(str(p1)))): + rf'{re.escape(str(p1))} is not a redirect ' + rf'page.'): p1.set_redirect_target(p2) with self.assertRaisesRegex(NoPageError, NO_PAGE_RE): p3.set_redirect_target(p2) diff --git a/tests/pagegenerators_tests.py b/tests/pagegenerators_tests.py index ecb4946..a705b4b 100755 --- a/tests/pagegenerators_tests.py +++ b/tests/pagegenerators_tests.py @@ -39,7 +39,6 @@ from tests.tools_tests import GeneratorIntersectTestCase from tests.utils import skipping
- en_wp_page_titles = ( # just a bunch of randomly selected titles for English Wikipedia tests 'Eastern Sayan', @@ -1394,10 +1393,10 @@
newpages_url = self.site.base_url( self.site.path() + '?title=Special:NewPages&uselang=en') - failure_message = 'No new pages returned by -newpages. ' \ - 'If this is the only failure, check whether {url} contains any ' \ + failure_message = 'No new pages returned by -newpages. If this is ' \ + f'the only failure, check whether {newpages_url} contains any ' \ 'pages. If not, create a new page on the site to make the test ' \ - 'pass again.'.format(url=newpages_url) + 'pass again.'
self.assertIsNotEmpty(pages, msg=failure_message)
diff --git a/tests/patrolbot_tests.py b/tests/patrolbot_tests.py index b957695..28f8a69 100755 --- a/tests/patrolbot_tests.py +++ b/tests/patrolbot_tests.py @@ -12,7 +12,6 @@ from scripts.patrol import PatrolBot from tests.aspects import DefaultDrySiteTestCase, unittest
- DUMMY_PAGE_TUPLES = """ This is some text above the entries:
diff --git a/tests/pwb_tests.py b/tests/pwb_tests.py index 6cd561b..b2a39c7 100755 --- a/tests/pwb_tests.py +++ b/tests/pwb_tests.py @@ -15,7 +15,6 @@ from tests.aspects import PwbTestCase from tests.utils import execute, execute_pwb
- join_pwb_tests_path = create_path_func(join_tests_path, 'pwb')
diff --git a/tests/replacebot_tests.py b/tests/replacebot_tests.py index a1e7eaf..b9b6bfc 100755 --- a/tests/replacebot_tests.py +++ b/tests/replacebot_tests.py @@ -17,7 +17,6 @@ from tests.bot_tests import TWNBotTestCase from tests.utils import empty_sites
- # Load only the custom fixes fixes.fixes.clear() fixes._load_file(join_data_path('fixes.py')) diff --git a/tests/script_tests.py b/tests/script_tests.py index a936e1b..6330641 100755 --- a/tests/script_tests.py +++ b/tests/script_tests.py @@ -18,7 +18,6 @@ from tests.aspects import DefaultSiteTestCase, MetaTestCaseClass, PwbTestCase from tests.utils import execute_pwb
- ci_test_run = os.environ.get('PYWIKIBOT_TEST_RUNNING', '0') == '1' scripts_path = join_root_path('scripts')
@@ -147,8 +146,8 @@ to fallback to its own discover() ordering of unit tests. """ if unrunnable_script_set: # pragma: no cover - unittest_print('Skipping execution of unrunnable scripts:\n {!r}' - .format(unrunnable_script_set)) + unittest_print('Skipping execution of unrunnable scripts:\n' + f'{unrunnable_script_set!r}')
test_pattern = 'tests.script_tests.TestScript{}.test_{}'
@@ -258,14 +257,14 @@ exit_codes = [0, 1, -9] if not out_result and not err_result: unittest_print(' auto-run script unresponsive after ' - '{} seconds'.format(timeout), end=' ') + f'{timeout} seconds', end=' ') elif 'SIMULATION: edit action blocked' in err_result: unittest_print(' auto-run script simulated edit ' 'blocked', end=' ') else: - unittest_print( - ' auto-run script stderr within {} seconds: {!r}' - .format(timeout, err_result), end=' ') + unittest_print(' auto-run script stderr within ' + f'{timeout} seconds: {err_result!r}', + end=' ') unittest_print(f" exit code: {result['exit_code']}", end=' ')
diff --git a/tests/site_generators_tests.py b/tests/site_generators_tests.py index 189943c..91ea577 100755 --- a/tests/site_generators_tests.py +++ b/tests/site_generators_tests.py @@ -25,7 +25,6 @@ from tests.aspects import DefaultSiteTestCase, DeprecationTestCase, TestCase from tests.utils import skipping
- global_expected_params = { 'action': ['query'], 'continue': [True], @@ -660,8 +659,8 @@
site = self.site.data_repository() pattern = (r'Page ' - r'[[({site.sitename}:|{site.code}:)-1]]' - r" doesn't exist.".format(site=site)) + rf'[[({site.sitename}:|{site.code}:)-1]]' + r" doesn't exist.") for page in pages: with self.assertRaisesRegex(NoPageError, pattern): page.data_item() diff --git a/tests/site_tests.py b/tests/site_tests.py index 415dcd4..b0b86ac 100755 --- a/tests/site_tests.py +++ b/tests/site_tests.py @@ -391,7 +391,7 @@ if not mysite.has_right('deletedhistory'): self.skipTest( "You don't have permission to view the deleted revisions " - 'on {}.'.format(mysite)) + f'on {mysite}.') mainpage = self.get_mainpage() gen = mysite.deletedrevs(total=10, titles=mainpage)
@@ -491,7 +491,7 @@ if not mysite.has_right('deletedhistory'): self.skipTest( "You don't have permission to view the deleted revisions " - 'on {}.'.format(mysite)) + f'on {mysite}.') prop = ['ids', 'timestamp', 'flags', 'user', 'comment'] gen = mysite.alldeletedrevisions(total=10, prop=prop)
diff --git a/tests/sparql_tests.py b/tests/sparql_tests.py index 2b65988..2037ada 100755 --- a/tests/sparql_tests.py +++ b/tests/sparql_tests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Test cases for the SPARQL API.""" # -# (C) Pywikibot team, 2016-2022 +# (C) Pywikibot team, 2016-2024 # # Distributed under the terms of the MIT license. # @@ -18,7 +18,6 @@ from tests.aspects import TestCase, WikidataTestCase from tests.utils import skipping
- # See: https://www.w3.org/TR/2013/REC-sparql11-results-json-20130321/
SQL_RESPONSE_CONTAINER = """ @@ -157,8 +156,9 @@ def testGetItems(self, mock_method): """Test item list retrieval via SPARQL.""" mock_method.return_value = Container( - SQL_RESPONSE_CONTAINER % '{0}, {1}, {1}'.format(ITEM_Q498787, - ITEM_Q677525)) + SQL_RESPONSE_CONTAINER % (f'{ITEM_Q498787}, {ITEM_Q677525}, ' + f'{ITEM_Q677525}') + ) with skipping(pywikibot.exceptions.TimeoutError): q = sparql.SparqlQuery() res = q.get_items('SELECT * WHERE { ?x ?y ?z }', 'cat') diff --git a/tests/textlib_tests.py b/tests/textlib_tests.py index 5acd756..742a317 100755 --- a/tests/textlib_tests.py +++ b/tests/textlib_tests.py @@ -29,7 +29,6 @@ require_modules, )
- files = {} dirname = os.path.join(os.path.dirname(__file__), 'pages')
diff --git a/tests/thanks_tests.py b/tests/thanks_tests.py index f0300a0..2f8910b 100755 --- a/tests/thanks_tests.py +++ b/tests/thanks_tests.py @@ -13,7 +13,6 @@ from pywikibot.page import Page, User from tests.aspects import TestCase
- NO_THANKABLE_REVS = 'There is no recent change which can be test thanked.'
diff --git a/tests/timestripper_tests.py b/tests/timestripper_tests.py index 2b768f1..39d1b47 100755 --- a/tests/timestripper_tests.py +++ b/tests/timestripper_tests.py @@ -15,7 +15,6 @@ from pywikibot.time import TZoneFixedOffset from tests.aspects import TestCase, unittest
- MatchObject = type(re.search('', ''))
diff --git a/tests/tools_deprecate_tests.py b/tests/tools_deprecate_tests.py index c54dc84..335f3b8 100755 --- a/tests/tools_deprecate_tests.py +++ b/tests/tools_deprecate_tests.py @@ -497,43 +497,38 @@
def test_function_remove_last_args(self): """Test @remove_last_args on functions.""" + msg_foo = ("The trailing arguments ('foo', 'bar') of " + f'{__name__}.deprecated_all are deprecated. The value(s)' + " provided for 'foo' have been dropped.") + msg_f_b = ("The trailing arguments ('foo', 'bar') of " + f'{__name__}.deprecated_all are deprecated. The value(s)' + " provided for 'foo', 'bar' have been dropped.") + rv = deprecated_all() self.assertIsNone(rv) self.assertNoDeprecation()
rv = deprecated_all(foo=42) self.assertIsNone(rv) - self.assertDeprecation( - "The trailing arguments ('foo', 'bar') of {}.deprecated_all are " - "deprecated. The value(s) provided for 'foo' have been " - 'dropped.'.format(__name__)) + self.assertDeprecation(msg_foo)
self._reset_messages()
rv = deprecated_all(42) self.assertIsNone(rv) - self.assertDeprecation( - "The trailing arguments ('foo', 'bar') of {}.deprecated_all are " - "deprecated. The value(s) provided for 'foo' have been " - 'dropped.'.format(__name__)) + self.assertDeprecation(msg_foo)
self._reset_messages()
rv = deprecated_all(foo=42, bar=47) self.assertIsNone(rv) - self.assertDeprecation( - "The trailing arguments ('foo', 'bar') of {}.deprecated_all are " - "deprecated. The value(s) provided for 'foo', 'bar' have been " - 'dropped.'.format(__name__)) + self.assertDeprecation(msg_f_b)
self._reset_messages()
rv = deprecated_all(42, 47) self.assertIsNone(rv) - self.assertDeprecation( - "The trailing arguments ('foo', 'bar') of {}.deprecated_all are " - "deprecated. The value(s) provided for 'foo', 'bar' have been " - 'dropped.'.format(__name__)) + self.assertDeprecation(msg_f_b)
self._reset_messages()
@@ -548,9 +543,8 @@ rv = deprecated_all2(42, bar=47) self.assertEqual(rv, 42) self.assertDeprecation( - "The trailing arguments ('bar') of {}.deprecated_all2 are " - "deprecated. The value(s) provided for 'bar' have been " - 'dropped.'.format(__name__)) + f"The trailing arguments ('bar') of {__name__}.deprecated_all2 are" + " deprecated. The value(s) provided for 'bar' have been dropped.")
self._reset_messages()
@@ -566,9 +560,9 @@ self.assertIsNone(rv) self.assertDeprecation( "The trailing arguments ('foo', 'bar') of " - '{}.DeprecatedMethodClass.deprecated_all are deprecated. ' + f'{__name__}.DeprecatedMethodClass.deprecated_all are deprecated. ' "The value(s) provided for 'foo' have been dropped." - .format(__name__)) + )
self._reset_messages()
@@ -576,9 +570,9 @@ self.assertIsNone(rv) self.assertDeprecation( "The trailing arguments ('foo', 'bar') of " - '{}.DeprecatedMethodClass.deprecated_all are deprecated. ' + f'{__name__}.DeprecatedMethodClass.deprecated_all are deprecated. ' "The value(s) provided for 'foo' have been dropped." - .format(__name__)) + )
self._reset_messages()
@@ -586,9 +580,9 @@ self.assertIsNone(rv) self.assertDeprecation( "The trailing arguments ('foo', 'bar') of " - '{}.DeprecatedMethodClass.deprecated_all are deprecated. The ' - "value(s) provided for 'foo', 'bar' have been dropped." - .format(__name__)) + f'{__name__}.DeprecatedMethodClass.deprecated_all are deprecated.' + " The value(s) provided for 'foo', 'bar' have been dropped." + )
self._reset_messages()
@@ -596,9 +590,9 @@ self.assertIsNone(rv) self.assertDeprecation( "The trailing arguments ('foo', 'bar') of " - '{}.DeprecatedMethodClass.deprecated_all are deprecated. The ' - "value(s) provided for 'foo', 'bar' have been dropped." - .format(__name__)) + f'{__name__}.DeprecatedMethodClass.deprecated_all are deprecated.' + " The value(s) provided for 'foo', 'bar' have been dropped." + )
self._reset_messages()
@@ -611,12 +605,13 @@ self.assertNoDeprecation()
rv = f.deprecated_all2(42, bar=47) - self.assertEqual(rv, 42) + self.assertEqual(rv, 42 + ) self.assertDeprecation( "The trailing arguments ('bar') of " - '{}.DeprecatedMethodClass.deprecated_all2 are deprecated. ' - "The value(s) provided for 'bar' have been dropped." - .format(__name__)) + f'{__name__}.DeprecatedMethodClass.deprecated_all2 are deprecated.' + " The value(s) provided for 'bar' have been dropped." + )
def test_deprecate_positionals(self): """Test deprecation of positional parameters.""" diff --git a/tests/ui_options_tests.py b/tests/ui_options_tests.py index d9f2f07..bb6793b 100755 --- a/tests/ui_options_tests.py +++ b/tests/ui_options_tests.py @@ -14,7 +14,6 @@ from pywikibot.bot_choice import ChoiceException, QuitKeyboardInterrupt from tests.aspects import TestCase
- message = bot.Option.formatted
diff --git a/tests/ui_tests.py b/tests/ui_tests.py index d688b0c..d8706ef 100755 --- a/tests/ui_tests.py +++ b/tests/ui_tests.py @@ -33,7 +33,6 @@ from pywikibot.userinterfaces.transliteration import NON_LATIN_DIGITS, _trans from tests.aspects import TestCase, TestCaseBase
- logger = logging.getLogger('pywiki') loggingcontext = {'caller_name': 'ui_tests', 'caller_file': 'ui_tests', diff --git a/tests/upload_tests.py b/tests/upload_tests.py index 3a41724..66cd0e8 100755 --- a/tests/upload_tests.py +++ b/tests/upload_tests.py @@ -61,10 +61,7 @@ self._file_key = warnings[0].file_key self._offset = warnings[0].offset
- if chunk_size: - expected_warns = ['exists'] - else: - expected_warns = ['duplicate', 'exists'] + expected_warns = ['exists'] if chunk_size else ['duplicate', 'exists']
# First upload the warning with warnings enabled page = pywikibot.FilePage(self.site, 'MP_sounds-pwb.png') @@ -105,8 +102,8 @@ with self.assertAPIError('siiinvalidsessiondata') as cm: self.site.stash_info(self._file_key) self.assertTrue(cm.exception.info.startswith('File not found'), - 'info ({}) did not start with ' - '"File not found"'.format(cm.exception.info)) + f'info ({cm.exception.info}) did not start with ' + '"File not found"')
@unittest.expectedFailure # T367314 def test_continue_filekey_once(self): @@ -126,9 +123,9 @@ self._finish_upload(1024, self.arrow_png) self.assertEqual( str(cm.exception), - 'The SHA1 of 1024 bytes of the stashed "{}" is ' + f'The SHA1 of 1024 bytes of the stashed "{self._file_key}" is ' '3503db342c8dfb0a38db0682b7370ddd271fa163 while the local file is ' - '3dd334f11aa1e780d636416dc0649b96b67588b6'.format(self._file_key)) + '3dd334f11aa1e780d636416dc0649b96b67588b6') self._verify_stash()
@unittest.expectedFailure # T367316 @@ -140,8 +137,9 @@ self._finish_upload(1024, self.sounds_png) self.assertEqual( str(cm.exception), - 'For the file key "{}" the server reported a size 1024 while the ' - 'offset was 0'.format(self._file_key)) + f'For the file key "{self._file_key}" the server reported a size' + ' 1024 while the offset was 0' + ) self._verify_stash()
@unittest.expectedFailure # T367317 @@ -153,8 +151,9 @@ self._finish_upload(1024, self.sounds_png) self.assertEqual( str(cm.exception), - 'For the file key "{}" the offset was set to 2000 while the file ' - 'is only 1276 bytes large.'.format(self._file_key)) + f'For the file key "{self._file_key}" the offset was set to 2000' + ' while the file is only 1276 bytes large.' + ) self._verify_stash()
diff --git a/tests/user_tests.py b/tests/user_tests.py index 9242e8b..3dc36ab 100755 --- a/tests/user_tests.py +++ b/tests/user_tests.py @@ -181,8 +181,8 @@ user = User(mysite, mysite.user()) uc = list(user.contributions(total=total)) if not uc: - self.skipTest('User {} has no contributions on site {}.' - .format(mysite.user(), mysite)) + self.skipTest( + f'User {mysite.user()} has no contributions on site {mysite}.') self.assertLessEqual(len(uc), total) self.assertEqual(uc[0], user.last_edit) first_edit = uc[-1] if len(uc) < total else list( diff --git a/tests/utils.py b/tests/utils.py index 209ac34..31aea38 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -26,7 +26,6 @@ from pywikibot.tools.collections import EMPTY_DEFAULT from tests import _pwb_py
- OSWIN32 = (sys.platform == 'win32')
diff --git a/tests/wikistats_tests.py b/tests/wikistats_tests.py index 762de32..d94e6e9 100755 --- a/tests/wikistats_tests.py +++ b/tests/wikistats_tests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Test cases for the WikiStats dataset.""" # -# (C) Pywikibot team, 2014-2022 +# (C) Pywikibot team, 2014-2024 # # Distributed under the terms of the MIT license. # @@ -87,7 +87,7 @@ self.assertGreater(int(data['en']['total']), int(data['en']['good'])) data = data['en'] self.assertTrue(all(isinstance(key, str) - for key in data.keys() if key is not None)) + for key in data if key is not None)) self.assertIsInstance(data['total'], str) self.assertIn('prefix', data) self.assertIn('total', data) @@ -102,7 +102,7 @@ self.assertGreater(int(data['fr']['total']), int(data['fr']['good'])) data = data['fr'] self.assertTrue(all(isinstance(key, str) - for key in data.keys() if key is not None)) + for key in data if key is not None)) self.assertIsInstance(data['total'], str) self.assertIn('prefix', data) self.assertIn('total', data)