Skip to content

Commit d43446e

Browse files
authored
Merge branch 'main' into gh-109812
2 parents 84e3ee2 + 4091deb commit d43446e

16 files changed

+132
-56
lines changed

Doc/library/types.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,12 @@ Standard names are defined for the following types:
472472

473473
.. versionadded:: 3.12
474474

475+
.. class:: CapsuleType
476+
477+
The type of :ref:`capsule objects <capsules>`.
478+
479+
.. versionadded:: 3.13
480+
475481

476482
Additional Utility Classes and Functions
477483
----------------------------------------

Lib/test/libregrtest/main.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
StrPath, StrJSON, TestName, TestList, TestTuple, FilterTuple,
2121
strip_py_suffix, count, format_duration,
2222
printlist, get_temp_dir, get_work_dir, exit_timeout,
23-
display_header, cleanup_temp_dir)
23+
display_header, cleanup_temp_dir,
24+
MS_WINDOWS)
2425

2526

2627
class Regrtest:
@@ -435,7 +436,15 @@ def _run_tests(self, selected: TestTuple, tests: TestList | None) -> int:
435436

436437
setup_process()
437438

438-
self.logger.start_load_tracker()
439+
if self.hunt_refleak and not self.num_workers:
440+
# gh-109739: WindowsLoadTracker thread interfers with refleak check
441+
use_load_tracker = False
442+
else:
443+
# WindowsLoadTracker is only needed on Windows
444+
use_load_tracker = MS_WINDOWS
445+
446+
if use_load_tracker:
447+
self.logger.start_load_tracker()
439448
try:
440449
if self.num_workers:
441450
self._run_tests_mp(runtests, self.num_workers)
@@ -448,7 +457,8 @@ def _run_tests(self, selected: TestTuple, tests: TestList | None) -> int:
448457
if self.want_rerun and self.results.need_rerun():
449458
self.rerun_failed_tests(runtests)
450459
finally:
451-
self.logger.stop_load_tracker()
460+
if use_load_tracker:
461+
self.logger.stop_load_tracker()
452462

453463
self.display_summary()
454464
self.finalize_tests(tracer)

Lib/test/lock_tests.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,13 +1014,15 @@ def test_default_timeout(self):
10141014
"""
10151015
Test the barrier's default timeout
10161016
"""
1017-
# create a barrier with a low default timeout
1018-
barrier = self.barriertype(self.N, timeout=0.3)
1017+
# gh-109401: Barrier timeout should be long enough
1018+
# to create 4 threads on a slow CI.
1019+
timeout = 1.0
1020+
barrier = self.barriertype(self.N, timeout=timeout)
10191021
def f():
10201022
i = barrier.wait()
10211023
if i == self.N // 2:
1022-
# One thread is later than the default timeout of 0.3s.
1023-
time.sleep(1.0)
1024+
# One thread is later than the default timeout.
1025+
time.sleep(timeout * 2)
10241026
self.assertRaises(threading.BrokenBarrierError, barrier.wait)
10251027
self.run_threads(f)
10261028

Lib/test/test_compile.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,6 +1272,11 @@ def f():
12721272
else:
12731273
1 if 1 else 1
12741274

1275+
def test_remove_empty_basic_block_with_jump_target_label(self):
1276+
# See gh-109823
1277+
def f(x):
1278+
while x:
1279+
0 if 1 else 0
12751280

12761281
@requires_debug_ranges()
12771282
class TestSourcePositions(unittest.TestCase):

Lib/test/test_sys.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import builtins
22
import codecs
3+
import _datetime
34
import gc
45
import locale
56
import operator
@@ -1581,7 +1582,7 @@ def delx(self): del self.__x
15811582
x = property(getx, setx, delx, "")
15821583
check(x, size('5Pi'))
15831584
# PyCapsule
1584-
# XXX
1585+
check(_datetime.datetime_CAPI, size('6P'))
15851586
# rangeiterator
15861587
check(iter(range(1)), size('3l'))
15871588
check(iter(range(2**65)), size('3P'))

Lib/test/test_types.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import collections.abc
55
from collections import namedtuple
66
import copy
7+
import _datetime
78
import gc
89
import inspect
910
import pickle
@@ -636,6 +637,9 @@ def test_traceback_and_frame_types(self):
636637
self.assertIsInstance(exc.__traceback__, types.TracebackType)
637638
self.assertIsInstance(exc.__traceback__.tb_frame, types.FrameType)
638639

640+
def test_capsule_type(self):
641+
self.assertIsInstance(_datetime.datetime_CAPI, types.CapsuleType)
642+
639643

640644
class UnionTests(unittest.TestCase):
641645

Lib/test/test_venv.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,13 @@ def test_zippath_from_non_installed_posix(self):
559559
platlibdir,
560560
stdlib_zip)
561561
additional_pythonpath_for_non_installed = []
562+
563+
# gh-109748: Don't copy __pycache__/ sub-directories, because they can
564+
# be modified by other Python tests running in parallel.
565+
ignored_names = {'__pycache__'}
566+
def ignore_pycache(src, names):
567+
return ignored_names
568+
562569
# Copy stdlib files to the non-installed python so venv can
563570
# correctly calculate the prefix.
564571
for eachpath in sys.path:
@@ -575,7 +582,8 @@ def test_zippath_from_non_installed_posix(self):
575582
if os.path.isfile(fn):
576583
shutil.copy(fn, libdir)
577584
elif os.path.isdir(fn):
578-
shutil.copytree(fn, os.path.join(libdir, name))
585+
shutil.copytree(fn, os.path.join(libdir, name),
586+
ignore=ignore_pycache)
579587
else:
580588
additional_pythonpath_for_non_installed.append(
581589
eachpath)

Lib/test/test_zipfile/test_core.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3203,53 +3203,53 @@ def test_no_data(self):
32033203
b = s.pack(2, 0)
32043204
c = s.pack(3, 0)
32053205

3206-
self.assertEqual(b'', zipfile._strip_extra(a, (self.ZIP64_EXTRA,)))
3207-
self.assertEqual(b, zipfile._strip_extra(b, (self.ZIP64_EXTRA,)))
3206+
self.assertEqual(b'', zipfile._Extra.strip(a, (self.ZIP64_EXTRA,)))
3207+
self.assertEqual(b, zipfile._Extra.strip(b, (self.ZIP64_EXTRA,)))
32083208
self.assertEqual(
3209-
b+b"z", zipfile._strip_extra(b+b"z", (self.ZIP64_EXTRA,)))
3209+
b+b"z", zipfile._Extra.strip(b+b"z", (self.ZIP64_EXTRA,)))
32103210

3211-
self.assertEqual(b+c, zipfile._strip_extra(a+b+c, (self.ZIP64_EXTRA,)))
3212-
self.assertEqual(b+c, zipfile._strip_extra(b+a+c, (self.ZIP64_EXTRA,)))
3213-
self.assertEqual(b+c, zipfile._strip_extra(b+c+a, (self.ZIP64_EXTRA,)))
3211+
self.assertEqual(b+c, zipfile._Extra.strip(a+b+c, (self.ZIP64_EXTRA,)))
3212+
self.assertEqual(b+c, zipfile._Extra.strip(b+a+c, (self.ZIP64_EXTRA,)))
3213+
self.assertEqual(b+c, zipfile._Extra.strip(b+c+a, (self.ZIP64_EXTRA,)))
32143214

32153215
def test_with_data(self):
32163216
s = struct.Struct("<HH")
32173217
a = s.pack(self.ZIP64_EXTRA, 1) + b"a"
32183218
b = s.pack(2, 2) + b"bb"
32193219
c = s.pack(3, 3) + b"ccc"
32203220

3221-
self.assertEqual(b"", zipfile._strip_extra(a, (self.ZIP64_EXTRA,)))
3222-
self.assertEqual(b, zipfile._strip_extra(b, (self.ZIP64_EXTRA,)))
3221+
self.assertEqual(b"", zipfile._Extra.strip(a, (self.ZIP64_EXTRA,)))
3222+
self.assertEqual(b, zipfile._Extra.strip(b, (self.ZIP64_EXTRA,)))
32233223
self.assertEqual(
3224-
b+b"z", zipfile._strip_extra(b+b"z", (self.ZIP64_EXTRA,)))
3224+
b+b"z", zipfile._Extra.strip(b+b"z", (self.ZIP64_EXTRA,)))
32253225

3226-
self.assertEqual(b+c, zipfile._strip_extra(a+b+c, (self.ZIP64_EXTRA,)))
3227-
self.assertEqual(b+c, zipfile._strip_extra(b+a+c, (self.ZIP64_EXTRA,)))
3228-
self.assertEqual(b+c, zipfile._strip_extra(b+c+a, (self.ZIP64_EXTRA,)))
3226+
self.assertEqual(b+c, zipfile._Extra.strip(a+b+c, (self.ZIP64_EXTRA,)))
3227+
self.assertEqual(b+c, zipfile._Extra.strip(b+a+c, (self.ZIP64_EXTRA,)))
3228+
self.assertEqual(b+c, zipfile._Extra.strip(b+c+a, (self.ZIP64_EXTRA,)))
32293229

32303230
def test_multiples(self):
32313231
s = struct.Struct("<HH")
32323232
a = s.pack(self.ZIP64_EXTRA, 1) + b"a"
32333233
b = s.pack(2, 2) + b"bb"
32343234

3235-
self.assertEqual(b"", zipfile._strip_extra(a+a, (self.ZIP64_EXTRA,)))
3236-
self.assertEqual(b"", zipfile._strip_extra(a+a+a, (self.ZIP64_EXTRA,)))
3235+
self.assertEqual(b"", zipfile._Extra.strip(a+a, (self.ZIP64_EXTRA,)))
3236+
self.assertEqual(b"", zipfile._Extra.strip(a+a+a, (self.ZIP64_EXTRA,)))
32373237
self.assertEqual(
3238-
b"z", zipfile._strip_extra(a+a+b"z", (self.ZIP64_EXTRA,)))
3238+
b"z", zipfile._Extra.strip(a+a+b"z", (self.ZIP64_EXTRA,)))
32393239
self.assertEqual(
3240-
b+b"z", zipfile._strip_extra(a+a+b+b"z", (self.ZIP64_EXTRA,)))
3240+
b+b"z", zipfile._Extra.strip(a+a+b+b"z", (self.ZIP64_EXTRA,)))
32413241

3242-
self.assertEqual(b, zipfile._strip_extra(a+a+b, (self.ZIP64_EXTRA,)))
3243-
self.assertEqual(b, zipfile._strip_extra(a+b+a, (self.ZIP64_EXTRA,)))
3244-
self.assertEqual(b, zipfile._strip_extra(b+a+a, (self.ZIP64_EXTRA,)))
3242+
self.assertEqual(b, zipfile._Extra.strip(a+a+b, (self.ZIP64_EXTRA,)))
3243+
self.assertEqual(b, zipfile._Extra.strip(a+b+a, (self.ZIP64_EXTRA,)))
3244+
self.assertEqual(b, zipfile._Extra.strip(b+a+a, (self.ZIP64_EXTRA,)))
32453245

32463246
def test_too_short(self):
3247-
self.assertEqual(b"", zipfile._strip_extra(b"", (self.ZIP64_EXTRA,)))
3248-
self.assertEqual(b"z", zipfile._strip_extra(b"z", (self.ZIP64_EXTRA,)))
3247+
self.assertEqual(b"", zipfile._Extra.strip(b"", (self.ZIP64_EXTRA,)))
3248+
self.assertEqual(b"z", zipfile._Extra.strip(b"z", (self.ZIP64_EXTRA,)))
32493249
self.assertEqual(
3250-
b"zz", zipfile._strip_extra(b"zz", (self.ZIP64_EXTRA,)))
3250+
b"zz", zipfile._Extra.strip(b"zz", (self.ZIP64_EXTRA,)))
32513251
self.assertEqual(
3252-
b"zzz", zipfile._strip_extra(b"zzz", (self.ZIP64_EXTRA,)))
3252+
b"zzz", zipfile._Extra.strip(b"zzz", (self.ZIP64_EXTRA,)))
32533253

32543254

32553255
if __name__ == "__main__":

Lib/types.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
Define names for built-in types that aren't directly accessible as a builtin.
33
"""
4+
45
import sys
56

67
# Iterators in Python aren't a matter of type but of protocol. A large
@@ -330,4 +331,11 @@ def wrapped(*args, **kwargs):
330331
NoneType = type(None)
331332
NotImplementedType = type(NotImplemented)
332333

334+
def __getattr__(name):
335+
if name == 'CapsuleType':
336+
import _socket
337+
return type(_socket.CAPI)
338+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
339+
333340
__all__ = [n for n in globals() if n[:1] != '_']
341+
__all__ += ['CapsuleType']

Lib/zipfile/__init__.py

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -188,28 +188,42 @@ class LargeZipFile(Exception):
188188

189189
_DD_SIGNATURE = 0x08074b50
190190

191-
_EXTRA_FIELD_STRUCT = struct.Struct('<HH')
192-
193-
def _strip_extra(extra, xids):
194-
# Remove Extra Fields with specified IDs.
195-
unpack = _EXTRA_FIELD_STRUCT.unpack
196-
modified = False
197-
buffer = []
198-
start = i = 0
199-
while i + 4 <= len(extra):
200-
xid, xlen = unpack(extra[i : i + 4])
201-
j = i + 4 + xlen
202-
if xid in xids:
203-
if i != start:
204-
buffer.append(extra[start : i])
205-
start = j
206-
modified = True
207-
i = j
208-
if not modified:
209-
return extra
210-
if start != len(extra):
211-
buffer.append(extra[start:])
212-
return b''.join(buffer)
191+
192+
class _Extra(bytes):
193+
FIELD_STRUCT = struct.Struct('<HH')
194+
195+
def __new__(cls, val, id=None):
196+
return super().__new__(cls, val)
197+
198+
def __init__(self, val, id=None):
199+
self.id = id
200+
201+
@classmethod
202+
def read_one(cls, raw):
203+
try:
204+
xid, xlen = cls.FIELD_STRUCT.unpack(raw[:4])
205+
except struct.error:
206+
xid = None
207+
xlen = 0
208+
return cls(raw[:4+xlen], xid), raw[4+xlen:]
209+
210+
@classmethod
211+
def split(cls, data):
212+
# use memoryview for zero-copy slices
213+
rest = memoryview(data)
214+
while rest:
215+
extra, rest = _Extra.read_one(rest)
216+
yield extra
217+
218+
@classmethod
219+
def strip(cls, data, xids):
220+
"""Remove Extra fields with specified IDs."""
221+
return b''.join(
222+
ex
223+
for ex in cls.split(data)
224+
if ex.id not in xids
225+
)
226+
213227

214228
def _check_zipfile(fp):
215229
try:
@@ -1963,7 +1977,7 @@ def _write_end_record(self):
19631977
min_version = 0
19641978
if extra:
19651979
# Append a ZIP64 field to the extra's
1966-
extra_data = _strip_extra(extra_data, (1,))
1980+
extra_data = _Extra.strip(extra_data, (1,))
19671981
extra_data = struct.pack(
19681982
'<HH' + 'Q'*len(extra),
19691983
1, 8*len(extra), *extra) + extra_data
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix bug where compiler does not adjust labels when removing an empty basic
2+
block which is a jump target.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Refactored ``zipfile._strip_extra`` to use higher level abstactions for
2+
extras instead of a heavy-state loop.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Expose the type of PyCapsule objects as ``types.CapsuleType``.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
regrtest: Fix reference leak check on Windows. Disable the load tracker on
2+
Windows in the reference leak check mode (-R option). Patch by Victor
3+
Stinner.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix ``test_zippath_from_non_installed_posix()`` of test_venv: don't copy
2+
``__pycache__/`` sub-directories, because they can be modified by other Python
3+
tests running in parallel. Patch by Victor Stinner.

Python/flowgraph.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,7 @@ eliminate_empty_basic_blocks(cfg_builder *g) {
960960
while(g->g_entryblock && g->g_entryblock->b_iused == 0) {
961961
g->g_entryblock = g->g_entryblock->b_next;
962962
}
963+
int next_lbl = get_max_label(g->g_entryblock) + 1;
963964
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
964965
assert(b->b_iused > 0);
965966
for (int i = 0; i < b->b_iused; i++) {
@@ -969,7 +970,13 @@ eliminate_empty_basic_blocks(cfg_builder *g) {
969970
while (target->b_iused == 0) {
970971
target = target->b_next;
971972
}
972-
instr->i_target = target;
973+
if (instr->i_target != target) {
974+
if (!IS_LABEL(target->b_label)) {
975+
target->b_label.id = next_lbl++;
976+
}
977+
instr->i_target = target;
978+
instr->i_oparg = target->b_label.id;
979+
}
973980
assert(instr->i_target && instr->i_target->b_iused > 0);
974981
}
975982
}

0 commit comments

Comments
 (0)