Skip to content

Update struct to 3.13.3 and update parts of test.support #5702

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 95 additions & 51 deletions Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,7 @@
#
# The timeout should be long enough for connect(), recv() and send() methods
# of socket.socket.
LOOPBACK_TIMEOUT = 5.0
if sys.platform == 'win32' and ' 32 bit (ARM)' in sys.version:
# bpo-37553: test_socket.SendfileUsingSendTest is taking longer than 2
# seconds on Windows ARM32 buildbot
LOOPBACK_TIMEOUT = 10
elif sys.platform == 'vxworks':
LOOPBACK_TIMEOUT = 10
LOOPBACK_TIMEOUT = 10.0

# Timeout in seconds for network requests going to the internet. The timeout is
# short enough to prevent a test to wait for too long if the internet request
Expand Down Expand Up @@ -113,7 +107,6 @@
STDLIB_DIR = os.path.dirname(TEST_HOME_DIR)
REPO_ROOT = os.path.dirname(STDLIB_DIR)


class Error(Exception):
"""Base class for regression test exceptions."""

Expand Down Expand Up @@ -259,22 +252,16 @@ class USEROBJECTFLAGS(ctypes.Structure):
# process not running under the same user id as the current console
# user. To avoid that, raise an exception if the window manager
# connection is not available.
from ctypes import cdll, c_int, pointer, Structure
from ctypes.util import find_library

app_services = cdll.LoadLibrary(find_library("ApplicationServices"))

if app_services.CGMainDisplayID() == 0:
reason = "gui tests cannot run without OS X window manager"
import subprocess
try:
rc = subprocess.run(["launchctl", "managername"],
capture_output=True, check=True)
managername = rc.stdout.decode("utf-8").strip()
except subprocess.CalledProcessError:
reason = "unable to detect macOS launchd job manager"
else:
class ProcessSerialNumber(Structure):
_fields_ = [("highLongOfPSN", c_int),
("lowLongOfPSN", c_int)]
psn = ProcessSerialNumber()
psn_p = pointer(psn)
if ( (app_services.GetCurrentProcess(psn_p) < 0) or
(app_services.SetFrontProcess(psn_p) < 0) ):
reason = "cannot run without OS X gui process"
if managername != "Aqua":
reason = f"{managername=} -- can only run in a macOS GUI session"

# check on every platform whether tkinter can actually do anything
if not reason:
Expand Down Expand Up @@ -391,11 +378,12 @@ def wrapper(*args, **kw):

def skip_if_buildbot(reason=None):
"""Decorator raising SkipTest if running on a buildbot."""
import getpass
if not reason:
reason = 'not suitable for buildbots'
try:
isbuildbot = getpass.getuser().lower() == 'buildbot'
except (KeyError, EnvironmentError) as err:
except (KeyError, OSError) as err:
warnings.warn(f'getpass.getuser() failed {err}.', RuntimeWarning)
isbuildbot = False
return unittest.skipIf(isbuildbot, reason)
Expand All @@ -409,35 +397,48 @@ def check_sanitizer(*, address=False, memory=False, ub=False, thread=False):
cflags = sysconfig.get_config_var('CFLAGS') or ''
config_args = sysconfig.get_config_var('CONFIG_ARGS') or ''
memory_sanitizer = (
'-fsanitize=memory' in cflags or
'--with-memory-sanitizer' in config_args
'-fsanitize=memory' in cflags or
'--with-memory-sanitizer' in config_args
)
address_sanitizer = (
'-fsanitize=address' in cflags or
'--with-address-sanitizer' in config_args
'-fsanitize=address' in cflags or
'--with-address-sanitizer' in config_args
)
ub_sanitizer = (
'-fsanitize=undefined' in cflags or
'--with-undefined-behavior-sanitizer' in config_args
'-fsanitize=undefined' in cflags or
'--with-undefined-behavior-sanitizer' in config_args
)
thread_sanitizer = (
'-fsanitize=thread' in cflags or
'--with-thread-sanitizer' in config_args
'-fsanitize=thread' in cflags or
'--with-thread-sanitizer' in config_args
)
return (
(memory and memory_sanitizer) or
(address and address_sanitizer) or
(ub and ub_sanitizer) or
(thread and thread_sanitizer)
(memory and memory_sanitizer) or
(address and address_sanitizer) or
(ub and ub_sanitizer) or
(thread and thread_sanitizer)
)


def skip_if_sanitizer(reason=None, *, address=False, memory=False, ub=False, thread=False):
"""Decorator raising SkipTest if running with a sanitizer active."""
if not reason:
reason = 'not working with sanitizers active'
skip = check_sanitizer(address=address, memory=memory, ub=ub)
skip = check_sanitizer(address=address, memory=memory, ub=ub, thread=thread)
return unittest.skipIf(skip, reason)

# gh-89363: True if fork() can hang if Python is built with Address Sanitizer
# (ASAN): libasan race condition, dead lock in pthread_create().
HAVE_ASAN_FORK_BUG = check_sanitizer(address=True)


def set_sanitizer_env_var(env, option):
for name in ('ASAN_OPTIONS', 'MSAN_OPTIONS', 'UBSAN_OPTIONS', 'TSAN_OPTIONS'):
if name in env:
env[name] += f':{option}'
else:
env[name] = option


def system_must_validate_cert(f):
"""Skip the test on TLS certificate validation failures."""
Expand Down Expand Up @@ -510,21 +511,42 @@ def has_no_debug_ranges():
def requires_debug_ranges(reason='requires co_positions / debug_ranges'):
return unittest.skipIf(has_no_debug_ranges(), reason)

def requires_legacy_unicode_capi():
@contextlib.contextmanager
def suppress_immortalization(suppress=True):
"""Suppress immortalization of deferred objects."""
try:
import _testinternalcapi
except ImportError:
yield
return

if not suppress:
yield
return

_testinternalcapi.suppress_immortalization(True)
try:
yield
finally:
_testinternalcapi.suppress_immortalization(False)

def skip_if_suppress_immortalization():
try:
from _testcapi import unicode_legacy_string
import _testinternalcapi
except ImportError:
unicode_legacy_string = None
return
return unittest.skipUnless(_testinternalcapi.get_immortalize_deferred(),
"requires immortalization of deferred objects")


return unittest.skipUnless(unicode_legacy_string,
'requires legacy Unicode C API')
MS_WINDOWS = (sys.platform == 'win32')

# Is not actually used in tests, but is kept for compatibility.
is_jython = sys.platform.startswith('java')

is_android = hasattr(sys, 'getandroidapilevel')
is_android = sys.platform == "android"

if sys.platform not in ('win32', 'vxworks'):
if sys.platform not in {"win32", "vxworks", "ios", "tvos", "watchos"}:
unix_shell = '/system/bin/sh' if is_android else '/bin/sh'
else:
unix_shell = None
Expand All @@ -534,23 +556,44 @@ def requires_legacy_unicode_capi():
is_emscripten = sys.platform == "emscripten"
is_wasi = sys.platform == "wasi"

has_fork_support = hasattr(os, "fork") and not is_emscripten and not is_wasi
is_apple_mobile = sys.platform in {"ios", "tvos", "watchos"}
is_apple = is_apple_mobile or sys.platform == "darwin"

# From python 3.12.6
is_s390x = hasattr(os, 'uname') and os.uname().machine == 's390x'
skip_on_s390x = unittest.skipIf(is_s390x, 'skipped on s390x')
has_fork_support = hasattr(os, "fork") and not (
# WASM and Apple mobile platforms do not support subprocesses.
is_emscripten
or is_wasi
or is_apple_mobile

# Although Android supports fork, it's unsafe to call it from Python because
# all Android apps are multi-threaded.
or is_android
)

def requires_fork():
return unittest.skipUnless(has_fork_support, "requires working os.fork()")

has_subprocess_support = not is_emscripten and not is_wasi
has_subprocess_support = not (
# WASM and Apple mobile platforms do not support subprocesses.
is_emscripten
or is_wasi
or is_apple_mobile

# Although Android supports subproceses, they're almost never useful in
# practice (see PEP 738). And most of the tests that use them are calling
# sys.executable, which won't work when Python is embedded in an Android app.
or is_android
)

def requires_subprocess():
"""Used for subprocess, os.spawn calls, fd inheritance"""
return unittest.skipUnless(has_subprocess_support, "requires subprocess support")

# Emscripten's socket emulation and WASI sockets have limitations.
has_socket_support = not is_emscripten and not is_wasi
has_socket_support = not (
is_emscripten
or is_wasi
)

def requires_working_socket(*, module=False):
"""Skip tests or modules that require working sockets
Expand Down Expand Up @@ -2551,7 +2594,8 @@ def adjust_int_max_str_digits(max_digits):
# The default C recursion limit (from Include/cpython/pystate.h).
C_RECURSION_LIMIT = 1500

#Windows doesn't have os.uname() but it doesn't support s390x.
# Windows doesn't have os.uname() but it doesn't support s390x.
is_s390x = hasattr(os, 'uname') and os.uname().machine == 's390x'
skip_on_s390x = unittest.skipIf(hasattr(os, 'uname') and os.uname().machine == 's390x',
'skipped on s390x')
HAVE_ASAN_FORK_BUG = check_sanitizer(address=True)
Expand Down
12 changes: 0 additions & 12 deletions Lib/test/test_csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,18 +291,6 @@ def test_writerows_errors(self):
self.assertRaises(TypeError, writer.writerows, None)
self.assertRaises(OSError, writer.writerows, BadIterable())

@support.cpython_only
@support.requires_legacy_unicode_capi()
@warnings_helper.ignore_warnings(category=DeprecationWarning)
def test_writerows_legacy_strings(self):
import _testcapi
c = _testcapi.unicode_legacy_string('a')
with TemporaryFile("w+", encoding="utf-8", newline='') as fileobj:
writer = csv.writer(fileobj)
writer.writerows([[c]])
fileobj.seek(0)
self.assertEqual(fileobj.read(), "a\r\n")

def _read_test(self, input, expect, **kwargs):
reader = csv.reader(input, **kwargs)
result = list(reader)
Expand Down
75 changes: 2 additions & 73 deletions Lib/test/test_decimal.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@
import locale
from test.support import (is_resource_enabled,
requires_IEEE_754, requires_docstrings,
requires_legacy_unicode_capi, check_sanitizer)
check_disallow_instantiation)
from test.support import (TestFailed,
run_with_locale, cpython_only,
darwin_malloc_err_warning, is_emscripten)
darwin_malloc_err_warning)
from test.support.import_helper import import_fresh_module
from test.support import threading_helper
from test.support import warnings_helper
Expand Down Expand Up @@ -586,18 +586,6 @@ def test_explicit_from_string(self):
# underscores don't prevent errors
self.assertRaises(InvalidOperation, Decimal, "1_2_\u00003")

@cpython_only
@requires_legacy_unicode_capi()
@warnings_helper.ignore_warnings(category=DeprecationWarning)
def test_from_legacy_strings(self):
import _testcapi
Decimal = self.decimal.Decimal
context = self.decimal.Context()

s = _testcapi.unicode_legacy_string('9.999999')
self.assertEqual(str(Decimal(s)), '9.999999')
self.assertEqual(str(context.create_decimal(s)), '9.999999')

def test_explicit_from_tuples(self):
Decimal = self.decimal.Decimal

Expand Down Expand Up @@ -2928,23 +2916,6 @@ def test_none_args(self):
assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
Overflow])

@cpython_only
@requires_legacy_unicode_capi()
@warnings_helper.ignore_warnings(category=DeprecationWarning)
def test_from_legacy_strings(self):
import _testcapi
c = self.decimal.Context()

for rnd in RoundingModes:
c.rounding = _testcapi.unicode_legacy_string(rnd)
self.assertEqual(c.rounding, rnd)

s = _testcapi.unicode_legacy_string('')
self.assertRaises(TypeError, setattr, c, 'rounding', s)

s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
self.assertRaises(TypeError, setattr, c, 'rounding', s)

def test_pickle(self):

for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Expand Down Expand Up @@ -5654,48 +5625,6 @@ def __abs__(self):
self.assertEqual(Decimal.from_float(cls(101.1)),
Decimal.from_float(101.1))

# Issue 41540:
@unittest.skipIf(sys.platform.startswith("aix"),
"AIX: default ulimit: test is flaky because of extreme over-allocation")
@unittest.skipIf(is_emscripten, "Test is unstable on Emscripten")
@unittest.skipIf(check_sanitizer(address=True, memory=True),
"ASAN/MSAN sanitizer defaults to crashing "
"instead of returning NULL for malloc failure.")
def test_maxcontext_exact_arith(self):

# Make sure that exact operations do not raise MemoryError due
# to huge intermediate values when the context precision is very
# large.

# The following functions fill the available precision and are
# therefore not suitable for large precisions (by design of the
# specification).
MaxContextSkip = ['logical_invert', 'next_minus', 'next_plus',
'logical_and', 'logical_or', 'logical_xor',
'next_toward', 'rotate', 'shift']

Decimal = C.Decimal
Context = C.Context
localcontext = C.localcontext

# Here only some functions that are likely candidates for triggering a
# MemoryError are tested. deccheck.py has an exhaustive test.
maxcontext = Context(prec=C.MAX_PREC, Emin=C.MIN_EMIN, Emax=C.MAX_EMAX)
with localcontext(maxcontext):
self.assertEqual(Decimal(0).exp(), 1)
self.assertEqual(Decimal(1).ln(), 0)
self.assertEqual(Decimal(1).log10(), 0)
self.assertEqual(Decimal(10**2).log10(), 2)
self.assertEqual(Decimal(10**223).log10(), 223)
self.assertEqual(Decimal(10**19).logb(), 19)
self.assertEqual(Decimal(4).sqrt(), 2)
self.assertEqual(Decimal("40E9").sqrt(), Decimal('2.0E+5'))
self.assertEqual(divmod(Decimal(10), 3), (3, 1))
self.assertEqual(Decimal(10) // 3, 3)
self.assertEqual(Decimal(4) / 2, 2)
self.assertEqual(Decimal(400) ** -1, Decimal('0.0025'))


def test_c_signaldict_segfault(self):
# See gh-106263 for details.
SignalDict = type(C.Context().flags)
Expand Down
Loading
Loading