⚡ Sangsakala Proxy 🏠 Home
Skip to content

Commit 1cd8f44

Browse files
authored
Sync remaining call, buffer and annotation tests for Python 3.15 (#9433)
Run update_lib against final CPython 3.15.0 for four disjoint test sources. Preserve the existing Proactor sendfile override and capability gates. Assisted-by: OpenAI Codex: model version unavailable
1 parent dd32b70 commit 1cd8f44

4 files changed

Lines changed: 136 additions & 15 deletions

File tree

‎Lib/test/test_asyncio/test_sendfile.py‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,12 @@ class SendfileBase:
9898
# 64 KiB page configuration.
9999
DATA = b"x" * (1024 * 17 * 64 + 1)
100100
# Reduce socket buffer size to test on relative small data sets.
101-
BUF_SIZE = 4 * 1024 # 4 KiB
101+
if sys.platform.startswith('dragonfly'):
102+
# A smaller buffer makes every window update wait 100 ms for the
103+
# delayed ACK timer.
104+
BUF_SIZE = 32 * 1024 # 32 KiB
105+
else:
106+
BUF_SIZE = 4 * 1024 # 4 KiB
102107

103108
def create_event_loop(self):
104109
raise NotImplementedError

‎Lib/test/test_buffer.py‎

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@
6666
'?':0, 'c':0, 'b':0, 'B':0,
6767
'h':0, 'H':0, 'i':0, 'I':0,
6868
'l':0, 'L':0, 'n':0, 'N':0,
69-
'e':0, 'f':0, 'd':0, 'P':0
69+
'e':0, 'f':0, 'd':0, 'P':0,
70+
'Zf':0, 'Zd':0,
7071
}
7172

7273
# NumPy does not have 'n' or 'N':
@@ -92,7 +93,9 @@
9293
'l':(-(1<<31), 1<<31), 'L':(0, 1<<32),
9394
'q':(-(1<<63), 1<<63), 'Q':(0, 1<<64),
9495
'e':(-65519, 65520), 'f':(-(1<<63), 1<<63),
95-
'd':(-(1<<1023), 1<<1023)
96+
'd':(-(1<<1023), 1<<1023),
97+
'Zf':(-(1<<63), 1<<63),
98+
'Zd':(-(1<<1023), 1<<1023),
9699
}
97100

98101
def native_type_range(fmt):
@@ -107,6 +110,10 @@ def native_type_range(fmt):
107110
lh = (-(1<<63), 1<<63)
108111
elif fmt == 'd':
109112
lh = (-(1<<1023), 1<<1023)
113+
elif fmt == 'Zf':
114+
lh = (-(1<<63), 1<<63)
115+
elif fmt == 'Zd':
116+
lh = (-(1<<1023), 1<<1023)
110117
else:
111118
for exp in (128, 127, 64, 63, 32, 31, 16, 15, 8, 7):
112119
try:
@@ -136,7 +143,7 @@ def native_type_range(fmt):
136143
# Format codes supported by array.array
137144
ARRAY = NATIVE.copy()
138145
for k in NATIVE:
139-
if not k in "bBhHiIlLfd":
146+
if k not in list("bBhHiIlLefd") + ['Zf', 'Zd']:
140147
del ARRAY[k]
141148

142149
BYTEFMT = NATIVE.copy()
@@ -175,13 +182,28 @@ def randrange_fmt(mode, char, obj):
175182
if char in 'efd':
176183
x = struct.pack(char, x)
177184
x = struct.unpack(char, x)[0]
185+
if char in ('Zf', 'Zd'):
186+
y = randrange(*fmtdict[mode][char])
187+
x = complex(x, y)
188+
x = struct.pack(char, x)
189+
x = struct.unpack(char, x)[0]
178190
return x
179191

192+
def split_format(fmt):
193+
i = 0
194+
while i < len(fmt):
195+
if fmt[i] == 'Z':
196+
n = 2
197+
else:
198+
n = 1
199+
yield fmt[i:i + n]
200+
i += n
201+
180202
def gen_item(fmt, obj):
181203
"""Return single random item."""
182204
mode, chars = fmt.split('#')
183205
x = []
184-
for c in chars:
206+
for c in split_format(chars):
185207
x.append(randrange_fmt(mode, c, obj))
186208
return x[0] if len(x) == 1 else tuple(x)
187209

@@ -242,9 +264,7 @@ def is_byte_format(fmt):
242264

243265
def is_memoryview_format(fmt):
244266
"""format suitable for memoryview"""
245-
x = len(fmt)
246-
return ((x == 1 or (x == 2 and fmt[0] == '@')) and
247-
fmt[x-1] in MEMORYVIEW)
267+
return fmt.removeprefix('@') in MEMORYVIEW
248268

249269
NON_BYTE_FORMAT = [c for c in fmtdict['@'] if not is_byte_format(c)]
250270

@@ -636,14 +656,22 @@ def ndarray_from_structure(items, fmt, t, flags=0):
636656
return ndarray(items, shape=shape, strides=strides, format=fmt,
637657
offset=offset, flags=ND_WRITABLE|flags)
638658

659+
# Convert PEP 3118 formats to numpy dtypes
660+
FORMAT_TO_DTYPE = {
661+
'Zf': 'F',
662+
'Zd': 'D',
663+
}
664+
639665
def numpy_array_from_structure(items, fmt, t):
640666
"""Return numpy_array from the tuple returned by rand_structure()"""
641667
memlen, itemsize, ndim, shape, strides, offset = t
642668
buf = bytearray(memlen)
643669
for j, v in enumerate(items):
644670
struct.pack_into(fmt, buf, j*itemsize, v)
671+
# Replace Zd/Zf formats with D/F dtypes
672+
dtype = FORMAT_TO_DTYPE.get(fmt, fmt)
645673
return numpy_array(buffer=buf, shape=shape, strides=strides,
646-
dtype=fmt, offset=offset)
674+
dtype=dtype, offset=offset)
647675

648676

649677
# ======================================================================
@@ -3015,7 +3043,7 @@ def test_memoryview_assign(self):
30153043
m = memoryview(nd)
30163044
self.assertRaises(TypeError, m.__setitem__, 0, 100)
30173045

3018-
ex = ndarray(list(range(120)), shape=[1,2,3,4,5], flags=ND_WRITABLE)
3046+
ex = ndarray(list(range(144)), shape=[1,2,3,4,6], flags=ND_WRITABLE)
30193047
m1 = memoryview(ex)
30203048

30213049
for fmt, _range in fmtdict['@'].items():
@@ -3025,7 +3053,7 @@ def test_memoryview_assign(self):
30253053
continue
30263054
m2 = m1.cast(fmt)
30273055
lo, hi = _range
3028-
if fmt == 'd' or fmt == 'f':
3056+
if fmt in ("d", "f", "Zd", "Zf"):
30293057
lo, hi = -2**1024, 2**1024
30303058
if fmt != 'P': # PyLong_AsVoidPtr() accepts negative numbers
30313059
self.assertRaises(ValueError, m2.__setitem__, 0, lo-1)
@@ -4447,6 +4475,43 @@ def test_bytearray_release_buffer_read_flag(self):
44474475
with self.assertRaises(SystemError):
44484476
obj.__buffer__(inspect.BufferFlags.WRITE)
44494477

4478+
@support.cpython_only
4479+
@unittest.skipIf(_testcapi is None, "requires _testcapi")
4480+
def test_bytearray_alignment(self):
4481+
# gh-140557: pointer alignment of buffers including empty allocation
4482+
# should be at least to `size_t`.
4483+
align = struct.calcsize("N")
4484+
cases = [
4485+
bytearray(),
4486+
bytearray(1),
4487+
bytearray(b"0123456789abcdef"),
4488+
bytearray(16),
4489+
]
4490+
ptrs = [_testcapi.buffer_pointer_as_int(array) for array in cases]
4491+
self.assertEqual([ptr % align for ptr in ptrs], [0]*len(ptrs))
4492+
4493+
@support.cpython_only
4494+
@unittest.skipIf(_testcapi is None, "requires _testcapi")
4495+
def test_array_alignment(self):
4496+
# gh-140557: pointer alignment of buffers including empty allocation
4497+
# should match the maximum array alignment.
4498+
formats = [fmt for fmt in ARRAY
4499+
if struct.calcsize(fmt) <= struct.calcsize('P')]
4500+
align = max(struct.calcsize(fmt) for fmt in formats)
4501+
cases = [array.array(fmt) for fmt in formats]
4502+
# Empty arrays
4503+
self.assertEqual(
4504+
[_testcapi.buffer_pointer_as_int(case) % align for case in cases],
4505+
[0] * len(cases),
4506+
)
4507+
for case in cases:
4508+
case.append(0)
4509+
# Allocated arrays
4510+
self.assertEqual(
4511+
[_testcapi.buffer_pointer_as_int(case) % align for case in cases],
4512+
[0] * len(cases),
4513+
)
4514+
44504515
@support.cpython_only
44514516
def test_pybuffer_size_from_format(self):
44524517
# basic tests

‎Lib/test/test_call.py‎

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
set_recursion_limit, skip_on_s390x,
44
skip_emscripten_stack_overflow,
55
skip_wasi_stack_overflow, skip_if_sanitizer,
6-
import_helper)
6+
skip_if_huge_c_stack, import_helper)
77
try:
88
import _testcapi
99
except ImportError:
@@ -47,6 +47,54 @@ def fn(**kw):
4747
self.assertIsInstance(res, dict)
4848
self.assertEqual(list(res.items()), expected)
4949

50+
def test_kwargs_order_preserved(self):
51+
# PEP 468: Preserving Keyword Argument Order
52+
def fn(**kw):
53+
return list(kw)
54+
55+
self.assertEqual(fn(b=1, a=2, c=3), ['b', 'a', 'c'])
56+
self.assertEqual(fn(c=3, a=2, b=1), ['c', 'a', 'b'])
57+
# Unpacked mappings are merged in place, keeping their own order.
58+
self.assertEqual(fn(z=0, **{'x': 1, 'a': 2}, y=3),
59+
['z', 'x', 'a', 'y'])
60+
self.assertEqual(fn(**{'b': 1}, **{'a': 2}), ['b', 'a'])
61+
# Named parameters are removed from **kwargs without reordering
62+
# the rest.
63+
def fn2(a, c=None, **kw):
64+
return list(kw)
65+
66+
self.assertEqual(fn2(d=1, a=2, b=3, c=4, e=5), ['d', 'b', 'e'])
67+
68+
def test_kwargs_order_preserved_in_methods(self):
69+
# PEP 468: Preserving Keyword Argument Order
70+
class C:
71+
def __init__(self, **kw):
72+
self.init_kw = list(kw)
73+
74+
def meth(self, **kw):
75+
return list(kw)
76+
77+
@classmethod
78+
def cmeth(cls, **kw):
79+
return list(kw)
80+
81+
@staticmethod
82+
def smeth(**kw):
83+
return list(kw)
84+
85+
c = C(b=1, a=2, c=3)
86+
self.assertEqual(c.init_kw, ['b', 'a', 'c'])
87+
self.assertEqual(c.meth(b=1, a=2, c=3), ['b', 'a', 'c'])
88+
self.assertEqual(C.cmeth(b=1, a=2, c=3), ['b', 'a', 'c'])
89+
self.assertEqual(C.smeth(b=1, a=2, c=3), ['b', 'a', 'c'])
90+
91+
def test_kwargs_order_preserved_in_c_functions(self):
92+
# PEP 468: Preserving Keyword Argument Order
93+
self.assertEqual(list(dict(b=1, a=2, c=3)), ['b', 'a', 'c'])
94+
self.assertEqual(list(dict(**{'b': 1}, a=2)), ['b', 'a'])
95+
self.assertEqual(list(collections.OrderedDict(b=1, a=2, c=3)),
96+
['b', 'a', 'c'])
97+
5098
def test_frames_are_popped_after_failed_calls(self):
5199
# GH-93252: stuff blows up if we don't pop the new frame after
52100
# recovering from failed calls:
@@ -1052,16 +1100,17 @@ def get_sp():
10521100
self.assertLess(lower_sp, this_sp)
10531101
safe_margin = this_sp - lower_sp
10541102
else:
1055-
self.assertLess(this_sp, lower_sp)
1103+
self.assertGreater(lower_sp, this_sp)
10561104
safe_margin = lower_sp - this_sp
1057-
# Add an (arbitrary) extra 20% for safety
1058-
safe_margin *= 6 / 5
1105+
# Add an (arbitrary) extra 25% for safety
1106+
safe_margin = safe_margin * 5 / 4
10591107
self.assertLess(safe_margin, _testinternalcapi.get_stack_margin())
10601108

10611109
@skip_on_s390x
10621110
@unittest.skipIf(is_wasi and Py_DEBUG, "requires deep stack")
10631111
@skip_if_sanitizer("requires deep stack", thread=True)
10641112
@unittest.skipIf(_testcapi is None, "requires _testcapi")
1113+
@skip_if_huge_c_stack(90_000)
10651114
@skip_emscripten_stack_overflow()
10661115
@skip_wasi_stack_overflow()
10671116
def test_super_deep(self):

‎Lib/test/test_future_stmt/test_future.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,8 @@ def test_annotations(self):
349349
eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))")
350350
eq("{i: 0 for i in (1, 2, 3)}")
351351
eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
352+
eq("{**x for x in ()}")
353+
eq("[*x for x in ()]")
352354
eq("[(x, y) for x, y in (a, b)]")
353355
eq("[(x,) for x, in (a,)]")
354356
eq("Python3 > Python2 > COBOL")

0 commit comments

Comments
 (0)