]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-128770: raise warnings as errors in test suite - except for test_socket...
authorThomas Grainger <tagrain@gmail.com>
Sat, 29 Mar 2025 19:21:33 +0000 (19:21 +0000)
committerGitHub <noreply@github.com>
Sat, 29 Mar 2025 19:21:33 +0000 (21:21 +0200)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
(cherry picked from commit 8a00c9a4d2ce9d373b13f8f0a2265a65f4523293)

15 files changed:
Lib/test/libregrtest/main.py
Lib/test/support/__init__.py
Lib/test/support/numbers.py [new file with mode: 0644]
Lib/test/support/os_helper.py
Lib/test/test_complex.py
Lib/test/test_decimal.py
Lib/test/test_float.py
Lib/test/test_grammar.py
Lib/test/test_hashlib.py
Lib/test/test_int.py
Lib/test/test_interpreters/utils.py
Lib/test/test_pty.py
Lib/test/test_socket.py
Lib/test/test_support.py
Lib/test/test_tokenize.py

index 36e8d5ad6b2458b7f13b33d290069544670086a9..b6d3131055e0ad6ee1cf64cf60ef661f0c9ed2cd 100644 (file)
@@ -630,9 +630,9 @@ class Regrtest:
         if not sys.stdout.write_through:
             python_opts.append('-u')
 
-        # Add warnings filter 'default'
+        # Add warnings filter 'error'
         if 'default' not in sys.warnoptions:
-            python_opts.extend(('-W', 'default'))
+            python_opts.extend(('-W', 'error'))
 
         # Error on bytes/str comparison
         if sys.flags.bytes_warning < 2:
index 72dcd5e67b318a89244c4b741fce8e937f38e53a..78cf4b3ca8a78834122d296f1842668c8fc879fd 100644 (file)
@@ -6,6 +6,7 @@ if __name__ != 'test.support':
 import contextlib
 import dataclasses
 import functools
+import logging
 import _opcode
 import os
 import re
@@ -386,7 +387,7 @@ def skip_if_buildbot(reason=None):
     try:
         isbuildbot = getpass.getuser().lower() == 'buildbot'
     except (KeyError, OSError) as err:
-        warnings.warn(f'getpass.getuser() failed {err}.', RuntimeWarning)
+        logging.getLogger(__name__).warning('getpass.getuser() failed %s.', err, exc_info=err)
         isbuildbot = False
     return unittest.skipIf(isbuildbot, reason)
 
@@ -1079,8 +1080,7 @@ class _MemoryWatchdog:
         try:
             f = open(self.procfile, 'r')
         except OSError as e:
-            warnings.warn('/proc not available for stats: {}'.format(e),
-                          RuntimeWarning)
+            logging.getLogger(__name__).warning('/proc not available for stats: %s', e, exc_info=e)
             sys.stderr.flush()
             return
 
diff --git a/Lib/test/support/numbers.py b/Lib/test/support/numbers.py
new file mode 100644 (file)
index 0000000..d5dbb41
--- /dev/null
@@ -0,0 +1,80 @@
+# These are shared with test_tokenize and other test modules.
+#
+# Note: since several test cases filter out floats by looking for "e" and ".",
+# don't add hexadecimal literals that contain "e" or "E".
+VALID_UNDERSCORE_LITERALS = [
+    '0_0_0',
+    '4_2',
+    '1_0000_0000',
+    '0b1001_0100',
+    '0xffff_ffff',
+    '0o5_7_7',
+    '1_00_00.5',
+    '1_00_00.5e5',
+    '1_00_00e5_1',
+    '1e1_0',
+    '.1_4',
+    '.1_4e1',
+    '0b_0',
+    '0x_f',
+    '0o_5',
+    '1_00_00j',
+    '1_00_00.5j',
+    '1_00_00e5_1j',
+    '.1_4j',
+    '(1_2.5+3_3j)',
+    '(.5_6j)',
+]
+INVALID_UNDERSCORE_LITERALS = [
+    # Trailing underscores:
+    '0_',
+    '42_',
+    '1.4j_',
+    '0x_',
+    '0b1_',
+    '0xf_',
+    '0o5_',
+    '0 if 1_Else 1',
+    # Underscores in the base selector:
+    '0_b0',
+    '0_xf',
+    '0_o5',
+    # Old-style octal, still disallowed:
+    '0_7',
+    '09_99',
+    # Multiple consecutive underscores:
+    '4_______2',
+    '0.1__4',
+    '0.1__4j',
+    '0b1001__0100',
+    '0xffff__ffff',
+    '0x___',
+    '0o5__77',
+    '1e1__0',
+    '1e1__0j',
+    # Underscore right before a dot:
+    '1_.4',
+    '1_.4j',
+    # Underscore right after a dot:
+    '1._4',
+    '1._4j',
+    '._5',
+    '._5j',
+    # Underscore right after a sign:
+    '1.0e+_1',
+    '1.0e+_1j',
+    # Underscore right before j:
+    '1.4_j',
+    '1.4e5_j',
+    # Underscore right before e:
+    '1_e1',
+    '1.4_e1',
+    '1.4_e1j',
+    # Underscore right after e:
+    '1e_1',
+    '1.4e_1',
+    '1.4e_1j',
+    # Complex cases with parens:
+    '(1+1.5_j_)',
+    '(1+1.5_j)',
+]
index 61e3bc0353707b524b4e67a7f26b95ee88045960..ae016441fdb9a82c235d6f0bf1b1245d83c3da59 100644 (file)
@@ -1,6 +1,7 @@
 import collections.abc
 import contextlib
 import errno
+import logging
 import os
 import re
 import stat
@@ -378,8 +379,12 @@ if sys.platform.startswith("win"):
             # Increase the timeout and try again
             time.sleep(timeout)
             timeout *= 2
-        warnings.warn('tests may fail, delete still pending for ' + pathname,
-                      RuntimeWarning, stacklevel=4)
+        logging.getLogger(__name__).warning(
+            'tests may fail, delete still pending for %s',
+            pathname,
+            stack_info=True,
+            stacklevel=4,
+        )
 
     def _unlink(filename):
         _waitfor(os.unlink, filename)
@@ -494,9 +499,14 @@ def temp_dir(path=None, quiet=False):
         except OSError as exc:
             if not quiet:
                 raise
-            warnings.warn(f'tests may fail, unable to create '
-                          f'temporary directory {path!r}: {exc}',
-                          RuntimeWarning, stacklevel=3)
+            logging.getLogger(__name__).warning(
+                "tests may fail, unable to create temporary directory %r: %s",
+                path,
+                exc,
+                exc_info=exc,
+                stack_info=True,
+                stacklevel=3,
+            )
     if dir_created:
         pid = os.getpid()
     try:
@@ -527,9 +537,15 @@ def change_cwd(path, quiet=False):
     except OSError as exc:
         if not quiet:
             raise
-        warnings.warn(f'tests may fail, unable to change the current working '
-                      f'directory to {path!r}: {exc}',
-                      RuntimeWarning, stacklevel=3)
+        logging.getLogger(__name__).warning(
+            'tests may fail, unable to change the current working directory '
+            'to %r: %s',
+            path,
+            exc,
+            exc_info=exc,
+            stack_info=True,
+            stacklevel=3,
+        )
     try:
         yield os.getcwd()
     finally:
index a991040d811afbec5c97e12a7236dd4e7f81b26e..6ff1a8ab29d0d66d062a54c8e08f9bda170aff03 100644 (file)
@@ -2,8 +2,10 @@ import unittest
 import sys
 from test import support
 from test.support.testcase import ComplexesAreIdenticalMixin
-from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
-                               INVALID_UNDERSCORE_LITERALS)
+from test.support.numbers import (
+    VALID_UNDERSCORE_LITERALS,
+    INVALID_UNDERSCORE_LITERALS,
+)
 
 from random import random
 from math import isnan, copysign
index c4d05f87a8df22294680bd4ca9e65ed8ac62eed9..46c50115aef117c5b2f21c78e10479e433509e38 100644 (file)
@@ -24,6 +24,7 @@ you're working through IDLE, you can import this test module and call test()
 with the corresponding argument.
 """
 
+import logging
 import math
 import os, sys
 import operator
@@ -5932,8 +5933,9 @@ def tearDownModule():
     if C: C.setcontext(ORIGINAL_CONTEXT[C].copy())
     P.setcontext(ORIGINAL_CONTEXT[P].copy())
     if not C:
-        warnings.warn('C tests skipped: no module named _decimal.',
-                      UserWarning)
+        logging.getLogger(__name__).warning(
+            'C tests skipped: no module named _decimal.'
+        )
     if not orig_sys_decimal is sys.modules['decimal']:
         raise TestFailed("Internal error: unbalanced number of changes to "
                          "sys.modules['decimal'].")
index 6b074d537042f8f8367ba4c8ab27d83608b1656f..97f951f12998a32055c38af1ffb29c6fb3436739 100644 (file)
@@ -9,8 +9,10 @@ import unittest
 
 from test import support
 from test.support.testcase import FloatsAreIdenticalMixin
-from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
-                               INVALID_UNDERSCORE_LITERALS)
+from test.support.numbers import (
+    VALID_UNDERSCORE_LITERALS,
+    INVALID_UNDERSCORE_LITERALS,
+)
 from math import isinf, isnan, copysign, ldexp
 import math
 
index 46eb5736fe3a8900bac905c9940379e59fd4f4b2..4f1fc2e86fd689017e589bf8b1911c19346b8ddb 100644 (file)
@@ -16,88 +16,10 @@ import test.typinganndata.ann_module as ann_module
 import typing
 from test.typinganndata import ann_module2
 import test
-
-# These are shared with test_tokenize and other test modules.
-#
-# Note: since several test cases filter out floats by looking for "e" and ".",
-# don't add hexadecimal literals that contain "e" or "E".
-VALID_UNDERSCORE_LITERALS = [
-    '0_0_0',
-    '4_2',
-    '1_0000_0000',
-    '0b1001_0100',
-    '0xffff_ffff',
-    '0o5_7_7',
-    '1_00_00.5',
-    '1_00_00.5e5',
-    '1_00_00e5_1',
-    '1e1_0',
-    '.1_4',
-    '.1_4e1',
-    '0b_0',
-    '0x_f',
-    '0o_5',
-    '1_00_00j',
-    '1_00_00.5j',
-    '1_00_00e5_1j',
-    '.1_4j',
-    '(1_2.5+3_3j)',
-    '(.5_6j)',
-]
-INVALID_UNDERSCORE_LITERALS = [
-    # Trailing underscores:
-    '0_',
-    '42_',
-    '1.4j_',
-    '0x_',
-    '0b1_',
-    '0xf_',
-    '0o5_',
-    '0 if 1_Else 1',
-    # Underscores in the base selector:
-    '0_b0',
-    '0_xf',
-    '0_o5',
-    # Old-style octal, still disallowed:
-    '0_7',
-    '09_99',
-    # Multiple consecutive underscores:
-    '4_______2',
-    '0.1__4',
-    '0.1__4j',
-    '0b1001__0100',
-    '0xffff__ffff',
-    '0x___',
-    '0o5__77',
-    '1e1__0',
-    '1e1__0j',
-    # Underscore right before a dot:
-    '1_.4',
-    '1_.4j',
-    # Underscore right after a dot:
-    '1._4',
-    '1._4j',
-    '._5',
-    '._5j',
-    # Underscore right after a sign:
-    '1.0e+_1',
-    '1.0e+_1j',
-    # Underscore right before j:
-    '1.4_j',
-    '1.4e5_j',
-    # Underscore right before e:
-    '1_e1',
-    '1.4_e1',
-    '1.4_e1j',
-    # Underscore right after e:
-    '1e_1',
-    '1.4e_1',
-    '1.4e_1j',
-    # Complex cases with parens:
-    '(1+1.5_j_)',
-    '(1+1.5_j)',
-]
-
+from test.support.numbers import (
+    VALID_UNDERSCORE_LITERALS,
+    INVALID_UNDERSCORE_LITERALS,
+)
 
 class TokenTests(unittest.TestCase):
 
index 73d758a3631b3a3d4ce1aed5e4584a4d40dfbd7e..a3693f5b8934f7b5ed4fc8a89ab287bfeba45cb2 100644 (file)
@@ -10,6 +10,7 @@ import hashlib
 import importlib
 import io
 import itertools
+import logging
 import os
 import sys
 import sysconfig
@@ -113,7 +114,11 @@ class HashLibTestCase(unittest.TestCase):
             return importlib.import_module(module_name)
         except ModuleNotFoundError as error:
             if self._warn_on_extension_import and module_name in builtin_hashes:
-                warnings.warn(f'Did a C extension fail to compile? {error}')
+                logging.getLogger(__name__).warning(
+                    'Did a C extension fail to compile? %s',
+                    error,
+                    exc_info=error,
+                )
         return None
 
     def __init__(self, *args, **kwargs):
index 8959ffb6dcc236f3e6419afcece6964954a026f2..48825f46911b67abc6e6932fbcc7048552980c4e 100644 (file)
@@ -4,8 +4,10 @@ import time
 import unittest
 from unittest import mock
 from test import support
-from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
-                               INVALID_UNDERSCORE_LITERALS)
+from test.support.numbers import (
+    VALID_UNDERSCORE_LITERALS,
+    INVALID_UNDERSCORE_LITERALS,
+)
 
 try:
     import _pylong
index 312e6fff0ceb176fa806bc0f1879951190d1e3a8..980289f7ee7075f42eddb3adb6dd6030548f420a 100644 (file)
@@ -2,6 +2,7 @@ from collections import namedtuple
 import contextlib
 import json
 import io
+import logging
 import os
 import os.path
 import pickle
@@ -69,8 +70,8 @@ def pack_exception(exc=None):
 def unpack_exception(packed):
     try:
         data = json.loads(packed)
-    except json.decoder.JSONDecodeError:
-        warnings.warn('incomplete exception data', RuntimeWarning)
+    except json.decoder.JSONDecodeError as e:
+        logging.getLogger(__name__).warning('incomplete exception data', exc_info=e)
         print(packed if isinstance(packed, str) else packed.decode('utf-8'))
         return None
     exc = types.SimpleNamespace(**data)
index dee94533c7454910bf2d414389654886ebcd1d01..c1728f5019d042659b7055553ac9dd8485c56911 100644 (file)
@@ -135,8 +135,10 @@ class PtyTest(unittest.TestCase):
                 new_dim = tty.tcgetwinsize(pty.STDIN_FILENO)
                 self.assertEqual(new_dim, target_dim,
                                  "pty.STDIN_FILENO window size unchanged")
-            except OSError:
-                warnings.warn("Failed to set pty.STDIN_FILENO window size.")
+            except OSError as e:
+                logging.getLogger(__name__).warning(
+                    "Failed to set pty.STDIN_FILENO window size.", exc_info=e,
+                )
                 pass
 
         try:
index fefb2d42d558b0808f357829f8c7af0f0f580213..a706c1735b7e0482860f0ae45317011e7b0c3d7e 100644 (file)
@@ -27,6 +27,7 @@ import tempfile
 import threading
 import time
 import traceback
+import warnings
 from weakref import proxy
 try:
     import multiprocessing
@@ -199,6 +200,24 @@ def socket_setdefaulttimeout(timeout):
         socket.setdefaulttimeout(old_timeout)
 
 
+@contextlib.contextmanager
+def downgrade_malformed_data_warning():
+    # This warning happens on macos and win, but does not always happen on linux.
+    if sys.platform not in {"win32", "darwin"}:
+        yield
+        return
+
+    with warnings.catch_warnings():
+        # TODO: gh-110012, we should investigate why this warning is happening
+        # and fix it properly.
+        warnings.filterwarnings(
+            action="always",
+            message="received malformed or improperly-truncated ancillary data",
+            category=RuntimeWarning,
+        )
+        yield
+
+
 HAVE_SOCKET_CAN = _have_socket_can()
 
 HAVE_SOCKET_CAN_ISOTP = _have_socket_can_isotp()
@@ -3943,8 +3962,9 @@ class SCMRightsTest(SendrecvmsgServerTimeoutBase):
         # mindata and maxdata bytes when received with buffer size
         # ancbuf, and that any complete file descriptor numbers are
         # valid.
-        msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock,
-                                                   len(MSG), ancbuf)
+        with downgrade_malformed_data_warning():  # TODO: gh-110012
+            msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock,
+                                                       len(MSG), ancbuf)
         self.assertEqual(msg, MSG)
         self.checkRecvmsgAddress(addr, self.cli_addr)
         self.checkFlags(flags, eor=True, checkset=socket.MSG_CTRUNC)
@@ -4295,8 +4315,9 @@ class RFC3542AncillaryTest(SendrecvmsgServerTimeoutBase):
         self.serv_sock.setsockopt(socket.IPPROTO_IPV6,
                                   socket.IPV6_RECVHOPLIMIT, 1)
         self.misc_event.set()
-        msg, ancdata, flags, addr = self.doRecvmsg(
-            self.serv_sock, len(MSG), socket.CMSG_LEN(SIZEOF_INT) - 1)
+        with downgrade_malformed_data_warning():  # TODO: gh-110012
+            msg, ancdata, flags, addr = self.doRecvmsg(
+                self.serv_sock, len(MSG), socket.CMSG_LEN(SIZEOF_INT) - 1)
 
         self.assertEqual(msg, MSG)
         self.checkRecvmsgAddress(addr, self.cli_addr)
@@ -4399,9 +4420,10 @@ class RFC3542AncillaryTest(SendrecvmsgServerTimeoutBase):
         self.serv_sock.setsockopt(socket.IPPROTO_IPV6,
                                   socket.IPV6_RECVTCLASS, 1)
         self.misc_event.set()
-        msg, ancdata, flags, addr = self.doRecvmsg(
-            self.serv_sock, len(MSG),
-            socket.CMSG_SPACE(SIZEOF_INT) + socket.CMSG_LEN(SIZEOF_INT) - 1)
+        with downgrade_malformed_data_warning():  # TODO: gh-110012
+            msg, ancdata, flags, addr = self.doRecvmsg(
+                self.serv_sock, len(MSG),
+                socket.CMSG_SPACE(SIZEOF_INT) + socket.CMSG_LEN(SIZEOF_INT) - 1)
 
         self.assertEqual(msg, MSG)
         self.checkRecvmsgAddress(addr, self.cli_addr)
index 11670b06fb7664d7df535cba39738d3f9f8a19ad..a47f28424f40b20c3e2e5d525f53bd99445d2275 100644 (file)
@@ -1,6 +1,8 @@
+import contextlib
 import errno
 import importlib
 import io
+import logging
 import os
 import shutil
 import socket
@@ -19,11 +21,37 @@ from test.support import os_helper
 from test.support import script_helper
 from test.support import socket_helper
 from test.support import warnings_helper
+from test.support.testcase import ExtraAssertions
 
 TESTFN = os_helper.TESTFN
 
 
-class TestSupport(unittest.TestCase):
+class LogCaptureHandler(logging.StreamHandler):
+    # Inspired by pytest's caplog
+    def __init__(self):
+        super().__init__(io.StringIO())
+        self.records = []
+
+    def emit(self, record) -> None:
+        self.records.append(record)
+        super().emit(record)
+
+    def handleError(self, record):
+        raise
+
+
+@contextlib.contextmanager
+def _caplog():
+    handler = LogCaptureHandler()
+    root_logger = logging.getLogger()
+    root_logger.addHandler(handler)
+    try:
+        yield handler
+    finally:
+        root_logger.removeHandler(handler)
+
+
+class TestSupport(unittest.TestCase, ExtraAssertions):
     @classmethod
     def setUpClass(cls):
         orig_filter_len = len(warnings.filters)
@@ -186,7 +214,7 @@ class TestSupport(unittest.TestCase):
         path = os.path.realpath(path)
 
         try:
-            with warnings_helper.check_warnings() as recorder:
+            with warnings_helper.check_warnings() as recorder, _caplog() as caplog:
                 with os_helper.temp_dir(path, quiet=True) as temp_path:
                     self.assertEqual(path, temp_path)
                 warnings = [str(w.message) for w in recorder.warnings]
@@ -195,11 +223,14 @@ class TestSupport(unittest.TestCase):
         finally:
             shutil.rmtree(path)
 
-        self.assertEqual(len(warnings), 1, warnings)
-        warn = warnings[0]
-        self.assertTrue(warn.startswith(f'tests may fail, unable to create '
-                                        f'temporary directory {path!r}: '),
-                        warn)
+        self.assertListEqual(warnings, [])
+        self.assertEqual(len(caplog.records), 1)
+        record = caplog.records[0]
+        self.assertStartsWith(
+            record.getMessage(),
+            f'tests may fail, unable to create '
+            f'temporary directory {path!r}: '
+        )
 
     @support.requires_fork()
     def test_temp_dir__forked_child(self):
@@ -259,35 +290,41 @@ class TestSupport(unittest.TestCase):
 
         with os_helper.temp_dir() as parent_dir:
             bad_dir = os.path.join(parent_dir, 'does_not_exist')
-            with warnings_helper.check_warnings() as recorder:
+            with warnings_helper.check_warnings() as recorder, _caplog() as caplog:
                 with os_helper.change_cwd(bad_dir, quiet=True) as new_cwd:
                     self.assertEqual(new_cwd, original_cwd)
                     self.assertEqual(os.getcwd(), new_cwd)
                 warnings = [str(w.message) for w in recorder.warnings]
 
-        self.assertEqual(len(warnings), 1, warnings)
-        warn = warnings[0]
-        self.assertTrue(warn.startswith(f'tests may fail, unable to change '
-                                        f'the current working directory '
-                                        f'to {bad_dir!r}: '),
-                        warn)
+        self.assertListEqual(warnings, [])
+        self.assertEqual(len(caplog.records), 1)
+        record = caplog.records[0]
+        self.assertStartsWith(
+            record.getMessage(),
+            f'tests may fail, unable to change '
+            f'the current working directory '
+            f'to {bad_dir!r}: '
+        )
 
     # Tests for change_cwd()
 
     def test_change_cwd__chdir_warning(self):
         """Check the warning message when os.chdir() fails."""
         path = TESTFN + '_does_not_exist'
-        with warnings_helper.check_warnings() as recorder:
+        with warnings_helper.check_warnings() as recorder, _caplog() as caplog:
             with os_helper.change_cwd(path=path, quiet=True):
                 pass
             messages = [str(w.message) for w in recorder.warnings]
 
-        self.assertEqual(len(messages), 1, messages)
-        msg = messages[0]
-        self.assertTrue(msg.startswith(f'tests may fail, unable to change '
-                                       f'the current working directory '
-                                       f'to {path!r}: '),
-                        msg)
+        self.assertListEqual(messages, [])
+        self.assertEqual(len(caplog.records), 1)
+        record = caplog.records[0]
+        self.assertStartsWith(
+            record.getMessage(),
+            f'tests may fail, unable to change '
+            f'the current working directory '
+            f'to {path!r}: ',
+        )
 
     # Tests for temp_cwd()
 
index 480bff743a9f8a32fa67ecdf004a66b2ea2b7b31..940ea21754ea379530b34efa941d2915bad4e364 100644 (file)
@@ -7,10 +7,13 @@ from io import BytesIO, StringIO
 from textwrap import dedent
 from unittest import TestCase, mock
 from test import support
-from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
-                               INVALID_UNDERSCORE_LITERALS)
 from test.support import os_helper
 from test.support.script_helper import run_test_script, make_script, run_python_until_end
+from test.support.numbers import (
+    VALID_UNDERSCORE_LITERALS,
+    INVALID_UNDERSCORE_LITERALS,
+)
+
 
 # Converts a source string into a list of textual representation
 # of the tokens such as: