jenkins-bot has submitted this change. ( 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1361188?usp=email )

Change subject: [IMPR]: merge nested with-statements
......................................................................

[IMPR]: merge nested with-statements

Also use parenthesized context managers introduced in Python 3.10

Change-Id: I96dd277eeeeb7dc092d39b7507fc3637162ce607
---
M scripts/category.py
M tests/api_tests.py
M tests/archivebot_tests.py
M tests/bot_tests.py
M tests/config_tests.py
M tests/dry_api_tests.py
M tests/dry_site_tests.py
M tests/edit_failure_tests.py
M tests/editor_tests.py
M tests/http_tests.py
M tests/login_tests.py
M tests/page_tests.py
M tests/redirect_bot_tests.py
M tests/setup_tests.py
M tests/site_generators_tests.py
M tests/site_tests.py
M tests/solve_disambiguation_tests.py
M tests/time_tests.py
M tests/tools_threading_tests.py
M tests/uploadbot_tests.py
M tests/user_tests.py
M tests/wikibase_tests.py
22 files changed, 264 insertions(+), 156 deletions(-)

Approvals:
  Mahveotm: Looks good to me, approved
  jenkins-bot: Verified




diff --git a/scripts/category.py b/scripts/category.py
index 8ab7bdc..3dc44a2 100755
--- a/scripts/category.py
+++ b/scripts/category.py
@@ -447,8 +447,10 @@
                 'superclass_db': self.superclass_db
             }
             # store dump to disk in binary format
-            with open_archive(filename, 'wb') as f, \
-                    suppress(pickle.PicklingError):
+            with (
+                open_archive(filename, 'wb') as f,
+                suppress(pickle.PicklingError)
+            ):
                 pickle.dump(databases, f, protocol=config.pickle_protocol)
         else:
             with suppress(OSError):
diff --git a/tests/api_tests.py b/tests/api_tests.py
index 3fe7b14..8e93cfc 100755
--- a/tests/api_tests.py
+++ b/tests/api_tests.py
@@ -257,8 +257,10 @@
             self.assertEqual(mod[6:], pi[mod]['name'])
             self.assertEqual(mod, pi[mod]['path'])

-        with patch.object(pywikibot, 'warning') as w, \
-                self.assertRaises(KeyError):
+        with (
+            patch.object(pywikibot, 'warning') as w,
+            self.assertRaises(KeyError)
+        ):
             pi.__getitem__('query+foobar')

         self.assertIn('API warning (paraminfo): ', w.call_args[0][0])
@@ -482,8 +484,10 @@
     def test_namespace(self) -> None:
         """Test PageGenerator set_namespace."""
         for namespace in (0, 1, None):
-            with self.subTest(namespace=namespace), \
-                    self.assertRaisesRegex(TypeError, SET_NAMESPACE_MODULE):
+            with (
+                self.subTest(namespace=namespace),
+                self.assertRaisesRegex(TypeError, SET_NAMESPACE_MODULE)
+            ):
                 self.gen.set_namespace(namespace)


@@ -639,8 +643,10 @@
                                      generator='links',
                                      parameters={'titles': 'test'})
         for namespace in (0, 1, None):
-            with self.subTest(namespace=namespace), \
-                    self.assertRaisesRegex(TypeError, SET_NAMESPACE_MODULE):
+            with (
+                self.subTest(namespace=namespace),
+                self.assertRaisesRegex(TypeError, SET_NAMESPACE_MODULE)
+            ):
                 self.gen.set_namespace(namespace)

     def test_namespace_param_is_not_settable(self) -> None:
diff --git a/tests/archivebot_tests.py b/tests/archivebot_tests.py
index 50b4091..fd80403 100755
--- a/tests/archivebot_tests.py
+++ b/tests/archivebot_tests.py
@@ -87,12 +87,13 @@

     def _run_main(self, option: str) -> None:
         """Run main with site-dependent work bypassed."""
-        with patch.object(archivebot.pywikibot, 'handle_args',
-                          return_value=[option]):
-            with patch.object(archivebot.pywikibot, 'Site'):
-                with patch.object(archivebot, 'show_md5_key',
-                                  return_value=True):
-                    archivebot.main(option)
+        with (
+            patch.object(
+                archivebot.pywikibot, 'handle_args', return_value=[option]),
+            patch.object(archivebot.pywikibot, 'Site'),
+            patch.object(archivebot, 'show_md5_key', return_value=True)
+        ):
+            archivebot.main(option)

     def test_locale_option(self) -> None:
         """Test that the locale option passes a string to setlocale."""
@@ -104,9 +105,11 @@
     def test_timezone_option(self) -> None:
         """Test that the timezone option sets the TZ environment variable."""
         environ = {}
-        with patch.object(archivebot.os, 'environ', environ):
-            with patch.object(archivebot.time, 'tzset', create=True) as tzset:
-                self._run_main('-timezone:UTC')
+        with (
+            patch.object(archivebot.os, 'environ', environ),
+            patch.object(archivebot.time, 'tzset', create=True) as tzset
+        ):
+            self._run_main('-timezone:UTC')

         self.assertEqual(environ['TZ'], 'UTC')
         tzset.assert_called_once_with()
diff --git a/tests/bot_tests.py b/tests/bot_tests.py
index 66062f4..ab65325 100755
--- a/tests/bot_tests.py
+++ b/tests/bot_tests.py
@@ -93,11 +93,13 @@
            return_value='generate_user_files')
     def test_user_override(self, *unused) -> None:
         """Test that an explicit username override is retained."""
-        with patch.object(config, 'family', 'wikipedia'), \
-             patch.object(config, 'mylang', 'test'), \
-             patch.object(pywikibot.bot, '_user_override', None), \
-             patch.object(pywikibot, '_sites', {}), \
-             patch.dict(config.usernames['wikipedia'], {}, clear=True):
+        with (
+            patch.object(config, 'family', 'wikipedia'),
+            patch.object(config, 'mylang', 'test'),
+            patch.object(pywikibot.bot, '_user_override', None),
+            patch.object(pywikibot, '_sites', {}),
+            patch.dict(config.usernames['wikipedia'], {}, clear=True)
+        ):
             result = pywikibot.handle_args(['-user:Xqt'], do_help=False)

             self.assertIsEmpty(result)
diff --git a/tests/config_tests.py b/tests/config_tests.py
index 91b7043..3e1978d 100755
--- a/tests/config_tests.py
+++ b/tests/config_tests.py
@@ -28,11 +28,13 @@

     def test_register_families_zip(self) -> None:
         """Discover and load archived families without duplicate paths."""
-        with TemporaryDirectory() as tmp, \
-                patch.dict(config.family_files, {}, clear=True), \
-                patch.dict(Family._families, {}, clear=True), \
-                patch.dict(sys.modules), \
-                patch.object(sys, 'path', sys.path.copy()):
+        with (
+            TemporaryDirectory() as tmp,
+            patch.dict(config.family_files, {}, clear=True),
+            patch.dict(Family._families, {}, clear=True),
+            patch.dict(sys.modules),
+            patch.object(sys, 'path', sys.path.copy())
+        ):
             archive = Path(tmp) / 'families.zip'
             folder = archive / 'families'
             expected = {}
@@ -60,8 +62,10 @@

     def test_register_families_missing_folder(self) -> None:
         """Retain missing-folder and non-directory error handling."""
-        with TemporaryDirectory() as tmp, \
-                patch.dict(config.family_files, {}, clear=True):
+        with (
+            TemporaryDirectory() as tmp,
+            patch.dict(config.family_files, {}, clear=True)
+        ):
             archive = Path(tmp) / 'families.zip'
             with ZipFile(archive, 'w') as zip_file:
                 zip_file.writestr('families/example_family.py', '')
@@ -110,9 +114,11 @@
         )

         for path_type, base, child, sibling, relative_child in cases:
-            with self.subTest(path_type=path_type, base=base), \
-                    patch.object(config, 'Path', path_type), \
-                    patch.object(config, 'base_dir', base):
+            with (
+                self.subTest(path_type=path_type, base=base),
+                patch.object(config, 'Path', path_type),
+                patch.object(config, 'base_dir', base)
+            ):
                 self.assertEqual(config.shortpath(base), '')
                 self.assertEqual(config.shortpath(child), relative_child)
                 self.assertEqual(config.shortpath(sibling), sibling)
@@ -121,8 +127,10 @@
         """Test paths on another Windows drive are not shortened."""
         base = r'C:\Users\bot\pywikibot'
         path = r'D:\pywikibot\file.txt'
-        with patch.object(config, 'Path', PureWindowsPath), \
-                patch.object(config, 'base_dir', base):
+        with (
+            patch.object(config, 'Path', PureWindowsPath),
+            patch.object(config, 'base_dir', base)
+        ):
             self.assertEqual(config.shortpath(path), path)


diff --git a/tests/dry_api_tests.py b/tests/dry_api_tests.py
index 9e6b6a8..63d4f46 100755
--- a/tests/dry_api_tests.py
+++ b/tests/dry_api_tests.py
@@ -226,14 +226,18 @@
     def test_no_user(self) -> None:
         """Test Request object when not a user."""
         self.site._userinfo = {}
-        with self.subTest(userinfo=self.site._userinfo), \
+        with (
+            self.subTest(userinfo=self.site._userinfo),
             self.assertRaisesRegex(Error,
-                                   'API write action attempted without user'):
+                                   'API write action attempted without user')
+        ):
             Request(site=self.site, parameters={'action': 'edit'})

         self.site._userinfo = {'name': '1.2.3.4', 'groups': [], 'anon': ''}
-        with self.subTest(userinfo=self.site._userinfo), \
-                self.assertRaisesRegex(Error, " as IP '1.2.3.4'"):
+        with (
+            self.subTest(userinfo=self.site._userinfo),
+            self.assertRaisesRegex(Error, " as IP '1.2.3.4'")
+        ):
             Request(site=self.site, parameters={'action': 'edit'})

     def test_unexpected_user(self) -> None:
diff --git a/tests/dry_site_tests.py b/tests/dry_site_tests.py
index 956ca41..8d0da6a 100755
--- a/tests/dry_site_tests.py
+++ b/tests/dry_site_tests.py
@@ -238,9 +238,12 @@
             patch.object(Request, 'submit', autospec=True) as submit,
         ):
             for inputs, message in cases:
-                with self.subTest(inputs=inputs):
-                    with self.assertRaisesRegex(ValueError, message):
-                        list(self.site.geosearch(**inputs))
+                with (
+                    self.subTest(inputs=inputs),
+                    self.assertRaisesRegex(ValueError, message)
+                ):
+                    list(self.site.geosearch(**inputs))
+
             submit.assert_not_called()

             other_page = pywikibot.Page(
diff --git a/tests/edit_failure_tests.py b/tests/edit_failure_tests.py
index 435a898..19fa803 100755
--- a/tests/edit_failure_tests.py
+++ b/tests/edit_failure_tests.py
@@ -43,8 +43,10 @@
     def test_nobots(self) -> None:
         """Test that {{nobots}} raise the appropriate exception."""
         page = pywikibot.Page(self.site, 'User:John Vandenberg/nobots')
-        with patch.object(config, 'ignore_bot_templates', False), \
-                self.assertRaisesRegex(OtherPageSaveError, 'nobots'):
+        with (
+            patch.object(config, 'ignore_bot_templates', False),
+            self.assertRaisesRegex(OtherPageSaveError, 'nobots')
+        ):
             page.save()

     def test_touch(self) -> None:
diff --git a/tests/editor_tests.py b/tests/editor_tests.py
index c792838..5332d24 100755
--- a/tests/editor_tests.py
+++ b/tests/editor_tests.py
@@ -70,9 +70,11 @@
                 os.fstat(handle)
             self.assertEqual(cm.exception.errno, errno.EBADF)

-        with patch.object(editor.tempfile, 'mkstemp', side_effect=mkstemp):
-            with patch.object(editor.subprocess, 'run', side_effect=run):
-                self.assertIsNone(editor.TextEditor().edit('text'))
+        with (
+            patch.object(editor.tempfile, 'mkstemp', side_effect=mkstemp),
+            patch.object(editor.subprocess, 'run', side_effect=run)
+        ):
+            self.assertIsNone(editor.TextEditor().edit('text'))


 if __name__ == '__main__':
diff --git a/tests/http_tests.py b/tests/http_tests.py
index 081107c..b10f986 100755
--- a/tests/http_tests.py
+++ b/tests/http_tests.py
@@ -269,14 +269,18 @@
                 response.encoding = 'utf-8'
                 response.raw = BytesIO(content)

-                with patch.object(http.session, 'request',
-                                  return_value=response):
-                    with http.fetch('https://example.test', stream=True,
-                                    charset=charset) as result:
-                        self.assertEqual(response.raw.tell(), 0)
-                        self.assertEqual(result.encoding, charset or 'utf-8')
-                        self.assertEqual(b''.join(result.iter_content(8)),
-                                         content)
+                with (
+                    patch.object(
+                        http.session, 'request', return_value=response),
+                    http.fetch(
+                        'https://example.test',
+                        stream=True,
+                        charset=charset
+                    ) as result
+                ):
+                    self.assertEqual(response.raw.tell(), 0)
+                    self.assertEqual(result.encoding, charset or 'utf-8')
+                    self.assertEqual(b''.join(result.iter_content(8)), content)

     def test_inputs_are_not_modified(self) -> None:
         """Test that headers and callbacks remain unchanged."""
diff --git a/tests/login_tests.py b/tests/login_tests.py
index 77554b7..6b63c27 100755
--- a/tests/login_tests.py
+++ b/tests/login_tests.py
@@ -241,9 +241,10 @@
             ".__setitem__('exploit_value', True)"
         )

-        with self.subTest(test='Test ValueError'), \
-             self.assertRaisesRegex(ValueError,
-                                    'Invalid password line format'):
+        with (
+            self.subTest(test='Test ValueError'),
+            self.assertRaisesRegex(ValueError, 'Invalid password line format')
+        ):
             self._test_pwfile(f"""
                 ('en', 'wikipedia', 'victim', {exploit_code})
                 """, None)
diff --git a/tests/page_tests.py b/tests/page_tests.py
index f92a502..3ed0e4c 100755
--- a/tests/page_tests.py
+++ b/tests/page_tests.py
@@ -292,11 +292,13 @@
         request = mock.Mock()
         request.submit.return_value = data

-        with mock.patch.object(self.site, 'simple_request',
-                               return_value=request):
-            with mock.patch.object(
-                    pywikibot.Page, '_check_section') as check_section:
-                target = page.getRedirectTarget(ignore_section=False)
+        with (
+            mock.patch.object(
+                self.site, 'simple_request', return_value=request),
+            mock.patch.object(
+                pywikibot.Page, '_check_section') as check_section
+        ):
+            target = page.getRedirectTarget(ignore_section=False)

         self.assertEqual(target.title(), 'Target#Section')
         check_section.assert_called_once_with()
@@ -400,12 +402,15 @@
             'File:Example',  # no file extension
             'File:Example #3.jpg',  # file extension in section
         ):
-            with self.subTest(title=title), \
-                    self.assertRaisesRegex(
-                        ValueError,
-                        r'(not.*valid.*file'
-                        r'|not in the file namespace'
-                        r'|does not have a valid extension)'):
+            with (
+                self.subTest(title=title),
+                self.assertRaisesRegex(
+                    ValueError,
+                    r'(not.*valid.*file'
+                    r'|not in the file namespace'
+                    r'|does not have a valid extension)'
+                )
+            ):
                 pywikibot.FilePage(site, title)

     def testImageAndDataRepository(self) -> None:
@@ -1637,15 +1642,21 @@
         site = self.get_site()
         p1 = pywikibot.Page(site, 'User:Framawiki/pwb_tests/shortlink')

-        with self.subTest(parameters='defaulted'), \
-             skipping(APIError, code='urlshortener-ratelimit'):
+        with (
+            self.subTest(parameters='defaulted'),
+            skipping(APIError, code='urlshortener-ratelimit')
+        ):
             self.assertEqual(p1.create_short_link(), 'https://w.wiki/3Cy')
-        with self.subTest(with_protocol=True), \
-             skipping(APIError, code='urlshortener-ratelimit'):
+        with (
+            self.subTest(with_protocol=True),
+            skipping(APIError, code='urlshortener-ratelimit')
+        ):
             self.assertEqual(p1.create_short_link(with_protocol=True),
                              'https://w.wiki/3Cy')
-        with self.subTest(permalink=True), \
-             skipping(APIError, code='urlshortener-ratelimit'):
+        with (
+            self.subTest(permalink=True),
+            skipping(APIError, code='urlshortener-ratelimit')
+        ):
             self.assertEqual(p1.create_short_link(permalink=True,
                                                   with_protocol=False),
                              'w.wiki/3Cz')
diff --git a/tests/redirect_bot_tests.py b/tests/redirect_bot_tests.py
index 08e20fc..452fe6b 100755
--- a/tests/redirect_bot_tests.py
+++ b/tests/redirect_bot_tests.py
@@ -100,8 +100,10 @@
         """Test with delete and non-existing sdtemplate."""
         options = {'delete': True, 'sdtemplate': 'txt {{n|a}} txt'}
         bot = RedirectTestRobot('broken', **options)
-        with patch.object(Page, 'exists', new=Mock(return_value=False)), \
-                patch.object(pywikibot, 'warning') as w:
+        with (
+            patch.object(Page, 'exists', new=Mock(return_value=False)),
+            patch.object(pywikibot, 'warning') as w
+        ):
             self.assertEqual(bot.sdtemplate, '')
         w.assert_called_with('No speedy deletion template "n" available.')

diff --git a/tests/setup_tests.py b/tests/setup_tests.py
index 38db87d..9a38dd8 100755
--- a/tests/setup_tests.py
+++ b/tests/setup_tests.py
@@ -46,12 +46,13 @@
             f'not-a-version\n{newer_version}\n{older_version}\n'
         )

-        with patch.object(sys, 'argv', ['setup.py', 'sdist']):
-            with patch('builtins.print') as mock_print:
-                with self.assertRaisesRegex(
-                        SystemExit,
-                        r'Build of distribution package canceled'):
-                    setup.get_validated_version('pywikibot')
+        with (
+            patch.object(sys, 'argv', ['setup.py', 'sdist']),
+            patch('builtins.print') as mock_print,
+            self.assertRaisesRegex(
+                SystemExit, r'Build of distribution package canceled')
+        ):
+            setup.get_validated_version('pywikibot')

         mock_print.assert_any_call(
             f'\n\nNew version {str(version)!r} is not higher than last '
diff --git a/tests/site_generators_tests.py b/tests/site_generators_tests.py
index b4be09e..1b6bc08 100755
--- a/tests/site_generators_tests.py
+++ b/tests/site_generators_tests.py
@@ -667,13 +667,17 @@
                     self.assertIn(prop, block)

         # starttime earlier than endtime
-        with self.subTest(starttime=low, endtime=high, reverse=False), \
-                self.assertRaises(ValueError):
+        with (
+            self.subTest(starttime=low, endtime=high, reverse=False),
+            self.assertRaises(ValueError)
+        ):
             mysite.blocks(total=5, starttime=low, endtime=high)

         # reverse: endtime earlier than starttime
-        with self.subTest(starttime=high, endtime=low, reverse=True), \
-                self.assertRaises(ValueError):
+        with (
+            self.subTest(starttime=high, endtime=low, reverse=True),
+            self.assertRaises(ValueError)
+        ):
             mysite.blocks(total=5, starttime=high, endtime=low, reverse=True)

     def test_blocks_show(self) -> None:
diff --git a/tests/site_tests.py b/tests/site_tests.py
index ed8ef56..eacca73 100755
--- a/tests/site_tests.py
+++ b/tests/site_tests.py
@@ -89,8 +89,10 @@
         """Keep OAuth when its identity matches the explicit username."""
         site = _OAuthLoginSite('Xqt', None)
         override = ('wikipedia', 'test', 'Xqt')
-        with patch.object(pywikibot.bot, '_user_override', override), \
-             patch.object(pywikibot, 'info') as info:
+        with (
+            patch.object(pywikibot.bot, '_user_override', override),
+            patch.object(pywikibot, 'info') as info
+        ):
             site.login(cookie_only=True)

         self.assertFalse(site._oauth_disabled)
@@ -101,8 +103,10 @@
         """Bypass OAuth when ``-user`` requests another identity."""
         site = _OAuthLoginSite('Pywikibot-oauth', 'Xqt')
         override = ('wikipedia', 'test', 'Xqt')
-        with patch.object(pywikibot.bot, '_user_override', override), \
-             patch.object(pywikibot, 'info') as info:
+        with (
+            patch.object(pywikibot.bot, '_user_override', override),
+            patch.object(pywikibot, 'info') as info
+        ):
             site.login(cookie_only=True)

         self.assertTrue(site._oauth_disabled)
@@ -114,9 +118,11 @@
     def test_mismatching_configured_oauth_user(self) -> None:
         """Reject an OAuth mismatch without an explicit user override."""
         site = _OAuthLoginSite('Pywikibot-oauth', 'Xqt')
-        with patch.object(pywikibot.bot, '_user_override', None), \
-             self.assertRaisesRegex(NoUsernameError,
-                                    'via OAuth as Pywikibot-oauth'):
+        with (
+            patch.object(pywikibot.bot, '_user_override', None),
+            self.assertRaisesRegex(
+                NoUsernameError, 'via OAuth as Pywikibot-oauth')
+        ):
             site.login(cookie_only=True)

         self.assertFalse(site._oauth_disabled)
@@ -793,14 +799,18 @@
         site = self.get_site()
         page = pywikibot.Page(site, 'User:Unicodesnowman/ProtectTest')

-        with self.subTest(test='anInvalidType'), \
+        with (
+            self.subTest(test='anInvalidType'),
             self.assertRaisesRegex(APIError,
-                                   'Invalid protection type "anInvalidType"'):
+                                   'Invalid protection type "anInvalidType"')
+        ):
             site.protect(protections={'anInvalidType': 'sysop'},
                          page=page, summary='Pywikibot unit test')

-        with self.subTest(test='anInvalidLevel'), \
-                self.assertRaisesRegex(Error, 'Invalid protection level'):
+        with (
+            self.subTest(test='anInvalidLevel'),
+            self.assertRaisesRegex(Error, 'Invalid protection level')
+        ):
             site.protect(protections={'edit': 'anInvalidLevel'},
                          page=page, summary='Pywikibot unit test')

diff --git a/tests/solve_disambiguation_tests.py 
b/tests/solve_disambiguation_tests.py
index fff4b55..6c61f7d 100755
--- a/tests/solve_disambiguation_tests.py
+++ b/tests/solve_disambiguation_tests.py
@@ -39,11 +39,13 @@
             self.fail(
                 'References were consumed before yielding the first page')

-        with patch('scripts.solve_disambiguation.ignore_title', {}), \
-                patch.object(page, 'getReferences',
-                             return_value=references()) as get_refs, \
-                patch('scripts.solve_disambiguation.PrimaryIgnoreManager'
-                      '.isIgnored', side_effect=lambda page: page == ignored):
+        with (
+            patch('scripts.solve_disambiguation.ignore_title', {}),
+            patch.object(
+                page, 'getReferences', return_value=references()) as get_refs,
+            patch('scripts.solve_disambiguation.PrimaryIgnoreManager'
+                  '.isIgnored', side_effect=lambda page: page == ignored)
+        ):
             gen = iter(ReferringPageGeneratorWithIgnore(page, main_only=True))
             self.assertEqual(next(gen), ref)
             get_refs.assert_called_once_with(with_template_inclusion=False,
@@ -63,12 +65,14 @@
                 consumed.append(ref)
                 yield ref

-        with patch('scripts.solve_disambiguation.ignore_title',
-                   {'wikipedia': {'de': ['Ignored']}}), \
-                patch.object(page, 'getReferences',
-                             side_effect=lambda **kwargs: references()), \
-                patch('scripts.solve_disambiguation.PrimaryIgnoreManager'
-                      '.isIgnored', side_effect=lambda ref: ref == refs[1]):
+        with (
+            patch('scripts.solve_disambiguation.ignore_title',
+                  {'wikipedia': {'de': ['Ignored']}}),
+            patch.object(page, 'getReferences',
+                         side_effect=lambda **kwargs: references()),
+            patch('scripts.solve_disambiguation.PrimaryIgnoreManager'
+                  '.isIgnored', side_effect=lambda ref: ref == refs[1])
+        ):
             gen = iter(ReferringPageGeneratorWithIgnore(page, minimum=2))
             self.assertEqual(next(gen), refs[2])
             self.assertEqual(consumed, refs[:4])
diff --git a/tests/time_tests.py b/tests/time_tests.py
index 91d7b63..1da5641 100755
--- a/tests/time_tests.py
+++ b/tests/time_tests.py
@@ -127,8 +127,10 @@
         """Test failure creating instance from invalid string."""
         for timestr, _posix in self.test_results['INVALID']:
             regex = "time data '[^']*?' does not match"
-            with self.subTest(timestr), \
-                    self.assertRaisesRegex(ValueError, regex):
+            with (
+                self.subTest(timestr),
+                self.assertRaisesRegex(ValueError, regex)
+            ):
                 Timestamp.set_timestamp(timestr)

     def test_instantiate_from_instance(self) -> None:
@@ -309,8 +311,10 @@
             '4000@': 'Time period qualifier is unrecognized: 4000@',
         }
         for invalid_value, pattern in cases.items():
-            with self.subTest(value=invalid_value), \
-                    self.assertRaisesRegex(ValueError, pattern):
+            with (
+                self.subTest(value=invalid_value),
+                self.assertRaisesRegex(ValueError, pattern)
+            ):
                 parse_duration(invalid_value)


diff --git a/tests/tools_threading_tests.py b/tests/tools_threading_tests.py
index 96c8761..9dac5c1 100755
--- a/tests/tools_threading_tests.py
+++ b/tests/tools_threading_tests.py
@@ -208,11 +208,15 @@
                 ThreadPoolExecutor, max_bound=1, max_workers=1
             ) as pool:
                 failure = error('submission failed')
-                with patch.object(ThreadPoolExecutor, 'submit',
-                                  side_effect=failure):
-                    with self.assertRaisesRegex(
-                            error, 'submission failed') as caught:
-                        pool.submit(pow, 2, 3)
+
+                with (
+                    patch.object(
+                        ThreadPoolExecutor, 'submit', side_effect=failure),
+                    self.assertRaisesRegex(
+                        error, 'submission failed') as caught
+                ):
+                    pool.submit(pow, 2, 3)
+
                 self.assertIs(caught.exception, failure)
                 self.assertTrue(
                     pool._bound_semaphore.acquire(blocking=False)
diff --git a/tests/uploadbot_tests.py b/tests/uploadbot_tests.py
index 29aed5b..f086756 100755
--- a/tests/uploadbot_tests.py
+++ b/tests/uploadbot_tests.py
@@ -139,8 +139,10 @@
         )

         for outcome, expected in cases:
-            with self.subTest(outcome=outcome), \
-                    tempfile.TemporaryDirectory() as directory:
+            with (
+                self.subTest(outcome=outcome),
+                tempfile.TemporaryDirectory() as directory
+            ):
                 temp_path = Path(directory) / 'download'
                 temp_path.write_bytes(b'content')
                 site = mock.Mock()
diff --git a/tests/user_tests.py b/tests/user_tests.py
index bad3d36..2dfe2d2 100755
--- a/tests/user_tests.py
+++ b/tests/user_tests.py
@@ -251,10 +251,12 @@
             ('192.0.2.1/24', 'bgip', [{'id': 2}]),
             ('Example', 'bgtargets', [{'id': 3}]),
         )
-        with patch.object(self.site, 'has_extension', return_value=True), \
-                patch.object(self.site._paraminfo, 'parameter',
-                             return_value={'name': 'targets'}), \
-                patch.object(self.site, 'simple_request') as request:
+        with (
+            patch.object(self.site, 'has_extension', return_value=True),
+            patch.object(self.site._paraminfo, 'parameter',
+                         return_value={'name': 'targets'}),
+            patch.object(self.site, 'simple_request') as request
+        ):
             for target, parameter, blocks in cases:
                 with self.subTest(target=target):
                     request.return_value.submit.return_value = {
@@ -279,10 +281,11 @@

     def test_unsupported_account_query(self) -> None:
         """Do not send an account filter that an older API would ignore."""
-        with patch.object(self.site, 'has_extension', return_value=True), \
-                patch.object(self.site._paraminfo, 'parameter',
-                             return_value=None), \
-                patch.object(self.site, 'simple_request') as request:
+        with (
+            patch.object(self.site, 'has_extension', return_value=True),
+            patch.object(self.site._paraminfo, 'parameter', return_value=None),
+            patch.object(self.site, 'simple_request') as request
+        ):
             with self.assertRaisesRegex(NotImplementedError,
                                         'global account block queries'):
                 User(self.site, 'Example').is_globally_blocked()
@@ -294,15 +297,19 @@
         with self.assertRaisesRegex(UnknownExtensionError, 'GlobalBlocking'):
             user.is_globally_blocked()

-        with patch.object(self.site, 'has_extension', return_value=True), \
-                patch.object(self.site, 'simple_request') as request:
+        with (
+            patch.object(self.site, 'has_extension', return_value=True),
+            patch.object(self.site, 'simple_request') as request
+        ):
             with self.assertRaisesRegex(ValueError, 'must not be empty'):
                 self.site.is_globally_blocked('')

             for target in ('Example|Other', '\x1fExample\x1fOther'):
-                with self.subTest(target=target):
-                    with self.assertRaisesRegex(ValueError, 'list separators'):
-                        self.site.is_globally_blocked(target)
+                with (
+                    self.subTest(target=target),
+                    self.assertRaisesRegex(ValueError, 'list separators')
+                ):
+                    self.site.is_globally_blocked(target)
             request.assert_not_called()

             request.return_value.submit.side_effect = APIError(
@@ -365,8 +372,10 @@

     def get_request(self, user: str) -> dict:
         """Return the request parameters set by usercontribs()."""
-        with patch.object(self.site, '_generator') as generator, \
-                patch('pywikibot.data.api.OptionSet'):
+        with (
+            patch.object(self.site, '_generator') as generator,
+            patch('pywikibot.data.api.OptionSet')
+        ):
             generator.return_value.request = {}
             self.site.usercontribs(user=user)
         return generator.return_value.request
diff --git a/tests/wikibase_tests.py b/tests/wikibase_tests.py
index eb0c6f9..01edf3d 100755
--- a/tests/wikibase_tests.py
+++ b/tests/wikibase_tests.py
@@ -1172,9 +1172,11 @@
                               case='first-letter',
                               defaultcontentmodel='wikibase-lexeme')
         namespaces = NamespacesDict({**repo.namespaces, 146: namespace})
-        with patch.object(repo, '_namespaces', namespaces), \
-                patch.object(repo, '_entity_namespaces',
-                             {'lexeme': namespace}, create=True):
+        with (
+            patch.object(repo, '_namespaces', namespaces),
+            patch.object(repo, '_entity_namespaces',
+                         {'lexeme': namespace}, create=True)
+        ):
             lexeme = LexemePage(repo)
         lexeme.lemmas = LanguageDict({'en': 'colour'})
         self.assertIsEmpty(lexeme.forms)
@@ -1322,19 +1324,27 @@
         """Rejected edits preserve changes; failed reloads prevent writes."""
         lexeme = self.lexeme
         lexeme.lemmas['en'] = 'changed'
-        with patch.object(self.repo, 'editEntity',
-                          side_effect=ValueError('rejected')):
-            with self.assertRaisesRegex(ValueError, 'rejected'):
-                lexeme.editEntity({'lemmas': {'en': 'changed'}})
+        with (
+            patch.object(
+                self.repo, 'editEntity', side_effect=ValueError('rejected')),
+            self.assertRaisesRegex(ValueError, 'rejected')
+        ):
+            lexeme.editEntity({'lemmas': {'en': 'changed'}})
         self.assertEqual(lexeme.lemmas['en'], 'changed')
         self.assertEqual(lexeme.latest_revision_id, 1)
         lexeme._update_from_edit_response({'lastrevid': 2}, True)
-        with patch.object(self.repo, 'loadcontent',
-                          side_effect=ValueError('reload failed')), \
-                patch.object(self.repo, 'editEntity') as save:
+        with (
+            patch.object(
+                self.repo,
+                'loadcontent',
+                side_effect=ValueError('reload failed')
+            ),
+            patch.object(self.repo, 'editEntity') as save
+        ):
             with self.assertRaisesRegex(ValueError, 'reload failed'):
                 lexeme.editEntity()
             save.assert_not_called()
+
         self.assertTrue(lexeme._needs_reload)

     def test_create(self) -> None:
@@ -1348,11 +1358,15 @@
         lexeme.forms.append(form)
         response = copy.deepcopy(self.content)
         response['forms'] = [dict(form.toJSON(), id='L1-F1')]
-        with patch.object(self.repo, '_tokens', {'csrf': 'token'}), \
-                patch.object(self.repo, 'simple_request') as request, \
-                patch.object(self.repo, 'loadcontent',
-                             side_effect=lambda *args: {
-                                 'L1': copy.deepcopy(response)}):
+        with (
+            patch.object(self.repo, '_tokens', {'csrf': 'token'}),
+            patch.object(self.repo, 'simple_request') as request,
+            patch.object(
+                self.repo,
+                'loadcontent',
+                side_effect=lambda *args: {'L1': copy.deepcopy(response)}
+            )
+        ):
             request.return_value.submit.return_value = {'entity': response}
             lexeme.editEntity()
             params = request.call_args.kwargs
@@ -1384,11 +1398,15 @@
                 'lexicalCategory': 'Q1084'}
         original = copy.deepcopy(data)
         callback = MagicMock()
-        with patch.object(self.repo, '_tokens', {'csrf': 'token'}), \
-                patch.object(self.repo, 'simple_request') as request, \
-                patch.object(pywikibot, 'async_request',
-                             side_effect=lambda func, *args, **kwargs:
-                             func(*args, **kwargs)):
+        with (
+            patch.object(self.repo, '_tokens', {'csrf': 'token'}),
+            patch.object(self.repo, 'simple_request') as request,
+            patch.object(
+                pywikibot,
+                'async_request',
+                side_effect=lambda func, *args, **kwargs: func(*args, **kwargs)
+            )
+        ):
             request.return_value.submit.return_value = {'entity': self.content}
             lexeme.editEntity(data, asynchronous=True, callback=callback)
         self.assertEqual(request.call_args.kwargs['new'], 'lexeme')
@@ -1405,8 +1423,10 @@
         lexeme.lemmas['en'] = 'colour'
         error = APIError('missing-field', 'language is required')
         callback = MagicMock()
-        with patch.object(self.repo, '_tokens', {'csrf': 'token'}), \
-                patch.object(self.repo, 'simple_request') as request:
+        with (
+            patch.object(self.repo, '_tokens', {'csrf': 'token'}),
+            patch.object(self.repo, 'simple_request') as request
+        ):
             request.return_value.submit.side_effect = error
             lexeme.editEntity(callback=callback)
         self.assertEqual(lexeme.id, '-1')

--
To view, visit 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1361188?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: I96dd277eeeeb7dc092d39b7507fc3637162ce607
Gerrit-Change-Number: 1361188
Gerrit-PatchSet: 4
Gerrit-Owner: Xqt <[email protected]>
Gerrit-Reviewer: Mahveotm <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to