Skip to content

Commit d990073

Browse files
committed
Merge branch 'main' into fix-mac-jit-ci
2 parents add0953 + 2a6b6b3 commit d990073

14 files changed

+198
-119
lines changed

InternalDocs/parser.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Therefore, changes to the Python language are made by modifying the
1717
[grammar file](../Grammar/python.gram).
1818
Developers rarely need to modify the generator itself.
1919

20-
See the devguide's [Changing CPython's grammar](https://devguide.python.org/developer-workflow/grammar/#grammar)
20+
See [Changing CPython's grammar](./changing_grammar.md)
2121
for a detailed description of the grammar and the process for changing it.
2222

2323
How PEG parsers work

Lib/contextvars.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
import _collections_abc
12
from _contextvars import Context, ContextVar, Token, copy_context
23

34

45
__all__ = ('Context', 'ContextVar', 'Token', 'copy_context')
6+
7+
8+
_collections_abc.Mapping.register(Context)

Lib/pickle.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -548,10 +548,11 @@ def save(self, obj, save_persistent_id=True):
548548
self.framer.commit_frame()
549549

550550
# Check for persistent id (defined by a subclass)
551-
pid = self.persistent_id(obj)
552-
if pid is not None and save_persistent_id:
553-
self.save_pers(pid)
554-
return
551+
if save_persistent_id:
552+
pid = self.persistent_id(obj)
553+
if pid is not None:
554+
self.save_pers(pid)
555+
return
555556

556557
# Check the memo
557558
x = self.memo.get(id(obj))

Lib/test/test_context.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import collections.abc
12
import concurrent.futures
23
import contextvars
34
import functools
@@ -350,6 +351,19 @@ def ctx2_fun():
350351

351352
ctx1.run(ctx1_fun)
352353

354+
def test_context_isinstance(self):
355+
ctx = contextvars.Context()
356+
self.assertIsInstance(ctx, collections.abc.Mapping)
357+
self.assertTrue(issubclass(contextvars.Context, collections.abc.Mapping))
358+
359+
mapping_methods = (
360+
'__contains__', '__eq__', '__getitem__', '__iter__', '__len__',
361+
'__ne__', 'get', 'items', 'keys', 'values',
362+
)
363+
for name in mapping_methods:
364+
with self.subTest(name=name):
365+
self.assertTrue(callable(getattr(ctx, name)))
366+
353367
@isolated_context
354368
@threading_helper.requires_working_threading()
355369
def test_context_threads_1(self):

Lib/test/test_dis.py

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
import types
1111
import unittest
1212
from test.support import (captured_stdout, requires_debug_ranges,
13-
requires_specialization, requires_specialization_ft,
14-
cpython_only)
13+
requires_specialization, cpython_only)
1514
from test.support.bytecode_helper import BytecodeTestCase
1615

1716
import opcode
@@ -1261,27 +1260,6 @@ def test_super_instructions(self):
12611260
got = self.get_disassembly(load_test, adaptive=True)
12621261
self.do_disassembly_compare(got, dis_load_test_quickened_code)
12631262

1264-
@cpython_only
1265-
@requires_specialization_ft
1266-
def test_binary_specialize(self):
1267-
binary_op_quicken = """\
1268-
0 RESUME_CHECK 0
1269-
1270-
1 LOAD_NAME 0 (a)
1271-
LOAD_NAME 1 (b)
1272-
%s
1273-
RETURN_VALUE
1274-
"""
1275-
co_int = compile('a + b', "<int>", "eval")
1276-
self.code_quicken(lambda: exec(co_int, {}, {'a': 1, 'b': 2}))
1277-
got = self.get_disassembly(co_int, adaptive=True)
1278-
self.do_disassembly_compare(got, binary_op_quicken % "BINARY_OP_ADD_INT 0 (+)")
1279-
1280-
co_unicode = compile('a + b', "<unicode>", "eval")
1281-
self.code_quicken(lambda: exec(co_unicode, {}, {'a': 'a', 'b': 'b'}))
1282-
got = self.get_disassembly(co_unicode, adaptive=True)
1283-
self.do_disassembly_compare(got, binary_op_quicken % "BINARY_OP_ADD_UNICODE 0 (+)")
1284-
12851263
@cpython_only
12861264
@requires_specialization
12871265
def test_binary_subscr_specialize(self):
@@ -1335,27 +1313,6 @@ def test_call_specialize(self):
13351313
got = self.get_disassembly(co, adaptive=True)
13361314
self.do_disassembly_compare(got, call_quicken)
13371315

1338-
@cpython_only
1339-
@requires_specialization_ft
1340-
def test_contains_specialize(self):
1341-
contains_op_quicken = """\
1342-
0 RESUME_CHECK 0
1343-
1344-
1 LOAD_NAME 0 (a)
1345-
LOAD_NAME 1 (b)
1346-
%s
1347-
RETURN_VALUE
1348-
"""
1349-
co_dict = compile('a in b', "<dict>", "eval")
1350-
self.code_quicken(lambda: exec(co_dict, {}, {'a': 1, 'b': {1: 5}}))
1351-
got = self.get_disassembly(co_dict, adaptive=True)
1352-
self.do_disassembly_compare(got, contains_op_quicken % "CONTAINS_OP_DICT 0 (in)")
1353-
1354-
co_set = compile('a in b', "<set>", "eval")
1355-
self.code_quicken(lambda: exec(co_set, {}, {'a': 1.0, 'b': {1, 2, 3}}))
1356-
got = self.get_disassembly(co_set, adaptive=True)
1357-
self.do_disassembly_compare(got, contains_op_quicken % "CONTAINS_OP_SET 0 (in)")
1358-
13591316
@cpython_only
13601317
@requires_specialization
13611318
def test_loop_quicken(self):

Lib/test/test_opcache.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import threading
55
import types
66
import unittest
7-
from test.support import threading_helper, check_impl_detail, requires_specialization
7+
from test.support import (threading_helper, check_impl_detail,
8+
requires_specialization, requires_specialization_ft,
9+
cpython_only)
810
from test.support.import_helper import import_module
911

1012
# Skip this module on other interpreters, it is cpython specific:
@@ -34,6 +36,11 @@ def assert_specialized(self, f, opname):
3436
opnames = {instruction.opname for instruction in instructions}
3537
self.assertIn(opname, opnames)
3638

39+
def assert_no_opcode(self, f, opname):
40+
instructions = dis.get_instructions(f, adaptive=True)
41+
opnames = {instruction.opname for instruction in instructions}
42+
self.assertNotIn(opname, opnames)
43+
3744

3845
class TestLoadSuperAttrCache(unittest.TestCase):
3946
def test_descriptor_not_double_executed_on_spec_fail(self):
@@ -1200,5 +1207,55 @@ def f(o, n):
12001207
self.assertEqual(test_obj.b, 0)
12011208

12021209

1210+
class TestSpecializer(TestBase):
1211+
1212+
@cpython_only
1213+
@requires_specialization_ft
1214+
def test_binary_op(self):
1215+
def f():
1216+
for _ in range(100):
1217+
a, b = 1, 2
1218+
c = a + b
1219+
self.assertEqual(c, 3)
1220+
1221+
f()
1222+
self.assert_specialized(f, "BINARY_OP_ADD_INT")
1223+
self.assert_no_opcode(f, "BINARY_OP")
1224+
1225+
def g():
1226+
for _ in range(100):
1227+
a, b = "foo", "bar"
1228+
c = a + b
1229+
self.assertEqual(c, "foobar")
1230+
1231+
g()
1232+
self.assert_specialized(g, "BINARY_OP_ADD_UNICODE")
1233+
self.assert_no_opcode(g, "BINARY_OP")
1234+
1235+
@cpython_only
1236+
@requires_specialization_ft
1237+
def test_contain_op(self):
1238+
def f():
1239+
for _ in range(100):
1240+
a, b = 1, {1: 2, 2: 5}
1241+
self.assertTrue(a in b)
1242+
self.assertFalse(3 in b)
1243+
1244+
f()
1245+
self.assert_specialized(f, "CONTAINS_OP_DICT")
1246+
self.assert_no_opcode(f, "CONTAINS_OP")
1247+
1248+
def g():
1249+
for _ in range(100):
1250+
a, b = 1, {1, 2}
1251+
self.assertTrue(a in b)
1252+
self.assertFalse(3 in b)
1253+
1254+
g()
1255+
self.assert_specialized(g, "CONTAINS_OP_SET")
1256+
self.assert_no_opcode(g, "CONTAINS_OP")
1257+
1258+
1259+
12031260
if __name__ == "__main__":
12041261
unittest.main()

Lib/test/test_pickle.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,25 +224,31 @@ def persistent_load(pid):
224224
def test_pickler_super(self):
225225
class PersPickler(self.pickler):
226226
def persistent_id(subself, obj):
227+
called.append(obj)
227228
self.assertIsNone(super().persistent_id(obj))
228229
return obj
229230

230231
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
231232
f = io.BytesIO()
232233
pickler = PersPickler(f, proto)
234+
called = []
233235
pickler.dump('abc')
236+
self.assertEqual(called, ['abc'])
234237
self.assertEqual(self.loads(f.getvalue()), 'abc')
235238

236239
def test_unpickler_super(self):
237240
class PersUnpickler(self.unpickler):
238241
def persistent_load(subself, pid):
242+
called.append(pid)
239243
with self.assertRaises(self.persistent_load_error):
240244
super().persistent_load(pid)
241245
return pid
242246

243247
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
244248
unpickler = PersUnpickler(io.BytesIO(self.dumps('abc', proto)))
249+
called = []
245250
self.assertEqual(unpickler.load(), 'abc')
251+
self.assertEqual(called, ['abc'])
246252

247253
class PyPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests, unittest.TestCase):
248254

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Disable SIMD support for HACL under WASI.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Register the :class:`contextvars.Context` type to
2+
:class:`collections.abc.Mapping`.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
The Python implementation of :mod:`pickle` no longer calls
2+
:meth:`pickle.Pickler.persistent_id` for the result of
3+
:meth:`!persistent_id`.

0 commit comments

Comments
 (0)