diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 36e8d5ad6b2458..b6d3131055e0ad 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -630,9 +630,9 @@ def _add_ci_python_opts(self, python_opts, keep_environ): 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: diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 72dcd5e67b318a..78cf4b3ca8a788 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -6,6 +6,7 @@ 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 @@ def start(self): 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 index 00000000000000..d5dbb41acebc38 --- /dev/null +++ b/Lib/test/support/numbers.py @@ -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)', +] diff --git a/Lib/test/support/os_helper.py b/Lib/test/support/os_helper.py index 61e3bc0353707b..ae016441fdb9a8 100644 --- a/Lib/test/support/os_helper.py +++ b/Lib/test/support/os_helper.py @@ -1,6 +1,7 @@ import collections.abc import contextlib import errno +import logging import os import re import stat @@ -378,8 +379,12 @@ def _waitfor(func, pathname, waitall=False): # 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: diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index a991040d811afb..6ff1a8ab29d0d6 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -2,8 +2,10 @@ 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 diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index c4d05f87a8df22..46c50115aef117 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -24,6 +24,7 @@ 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'].") diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 6b074d537042f8..97f951f12998a3 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -9,8 +9,10 @@ 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 diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 46eb5736fe3a89..4f1fc2e86fd689 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -16,88 +16,10 @@ 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): diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 73d758a3631b3a..a3693f5b8934f7 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -10,6 +10,7 @@ import importlib import io import itertools +import logging import os import sys import sysconfig @@ -113,7 +114,11 @@ def _conditional_import_module(self, module_name): 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): diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py index 8959ffb6dcc236..48825f46911b67 100644 --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -4,8 +4,10 @@ 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 diff --git a/Lib/test/test_interpreters/utils.py b/Lib/test/test_interpreters/utils.py index 312e6fff0ceb17..980289f7ee7075 100644 --- a/Lib/test/test_interpreters/utils.py +++ b/Lib/test/test_interpreters/utils.py @@ -2,6 +2,7 @@ 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) diff --git a/Lib/test/test_pty.py b/Lib/test/test_pty.py index dee94533c74549..c1728f5019d042 100644 --- a/Lib/test/test_pty.py +++ b/Lib/test/test_pty.py @@ -135,8 +135,10 @@ def test_openpty(self): 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: diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index fefb2d42d558b0..a706c1735b7e04 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -27,6 +27,7 @@ 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 @@ def checkTruncatedArray(self, ancbuf, maxdata, mindata=0): # 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 @@ def testSingleCmsgTruncInData(self): 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 @@ def testSecondCmsgTruncInData(self): 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) diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index 11670b06fb7664..a47f28424f40b2 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -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 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 @@ def test_temp_dir__existing_dir__quiet_true(self): 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 @@ def test_temp_dir__existing_dir__quiet_true(self): 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 @@ def test_change_cwd__non_existent_dir__quiet_true(self): 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() diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py index 480bff743a9f8a..940ea21754ea37 100644 --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -7,10 +7,13 @@ 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: pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy