Salut!
-Cela ressemble à un excellent +
Cette - recipie - déjeuner. + recette + sera sûrement un très bon repas.
diff --git a/Doc/install/index.rst b/Doc/install/index.rst index ab581d785ef7f0..beb34f0cf21b22 100644 --- a/Doc/install/index.rst +++ b/Doc/install/index.rst @@ -696,7 +696,7 @@ is supplied to suppress this behaviour. So you could simply edit import sys sys.path.append('/www/python/') -However, if you reinstall the same major version of Python (perhaps when +However, if you reinstall the same minor version of Python (perhaps when upgrading from 2.2 to 2.2.2, for example) :file:`site.py` will be overwritten by the stock version. You'd have to remember that it was modified and save a copy before doing the installation. diff --git a/Doc/library/array.rst b/Doc/library/array.rst index 1f5810b35d2d86..0afc217642a756 100644 --- a/Doc/library/array.rst +++ b/Doc/library/array.rst @@ -57,7 +57,7 @@ Notes: ``Py_UNICODE``. This change doesn't affect its behavior because ``Py_UNICODE`` is alias of ``wchar_t`` since Python 3.3. - .. deprecated-removed:: 3.3 4.0 + .. deprecated-removed:: 3.3 3.16 Please migrate to ``'w'`` typecode. diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index f3b0bf0c4f7779..530cf30643687f 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -146,6 +146,102 @@ Node classes Snakes at 0x..., file "%s", line %d>)
- MAKE_FUNCTION 0
+ MAKE_FUNCTION
LOAD_FAST 0 (x)
GET_ITER
CALL 0
@@ -443,18 +443,20 @@ def _fstring(a, b, c, d):
%3d RESUME 0
%3d LOAD_FAST 0 (a)
- FORMAT_VALUE 0
+ FORMAT_SIMPLE
LOAD_CONST 1 (' ')
LOAD_FAST 1 (b)
LOAD_CONST 2 ('4')
- FORMAT_VALUE 4 (with format)
+ FORMAT_WITH_SPEC
LOAD_CONST 1 (' ')
LOAD_FAST 2 (c)
- FORMAT_VALUE 2 (repr)
+ CONVERT_VALUE 2 (repr)
+ FORMAT_SIMPLE
LOAD_CONST 1 (' ')
LOAD_FAST 3 (d)
+ CONVERT_VALUE 2 (repr)
LOAD_CONST 2 ('4')
- FORMAT_VALUE 6 (repr, with format)
+ FORMAT_WITH_SPEC
BUILD_STRING 7
RETURN_VALUE
""" % (_fstring.__code__.co_firstlineno, _fstring.__code__.co_firstlineno + 1)
@@ -486,7 +488,8 @@ def _with(c):
%3d >> PUSH_EXC_INFO
WITH_EXCEPT_START
- POP_JUMP_IF_TRUE 1 (to 42)
+ TO_BOOL
+ POP_JUMP_IF_TRUE 1 (to 50)
RERAISE 2
>> POP_TOP
POP_EXCEPT
@@ -527,7 +530,7 @@ async def _asyncwith(c):
>> SEND 3 (to 24)
YIELD_VALUE 2
RESUME 3
- JUMP_BACKWARD_NO_INTERRUPT 5 (to 14)
+ JUMP_BACKWARD_NO_INTERRUPT 5 (to 14)
>> END_SEND
POP_TOP
@@ -543,7 +546,7 @@ async def _asyncwith(c):
>> SEND 3 (to 60)
YIELD_VALUE 2
RESUME 3
- JUMP_BACKWARD_NO_INTERRUPT 5 (to 50)
+ JUMP_BACKWARD_NO_INTERRUPT 5 (to 50)
>> END_SEND
POP_TOP
@@ -562,10 +565,11 @@ async def _asyncwith(c):
>> SEND 4 (to 102)
YIELD_VALUE 3
RESUME 3
- JUMP_BACKWARD_NO_INTERRUPT 5 (to 90)
+ JUMP_BACKWARD_NO_INTERRUPT 5 (to 90)
>> CLEANUP_THROW
>> END_SEND
- POP_JUMP_IF_TRUE 1 (to 108)
+ TO_BOOL
+ POP_JUMP_IF_TRUE 1 (to 116)
RERAISE 2
>> POP_TOP
POP_EXCEPT
@@ -683,10 +687,11 @@ def foo(x):
%3d RESUME 0
-%3d LOAD_CLOSURE 0 (y)
+%3d LOAD_FAST 0 (y)
BUILD_TUPLE 1
LOAD_CONST 1 ()
- MAKE_FUNCTION 8 (closure)
+ MAKE_FUNCTION
+ SET_FUNCTION_ATTRIBUTE 8 (closure)
STORE_FAST 1 (foo)
%3d LOAD_FAST 1 (foo)
@@ -706,10 +711,11 @@ def foo(x):
%3d RESUME 0
%3d LOAD_GLOBAL 1 (NULL + list)
- LOAD_CLOSURE 0 (x)
+ LOAD_FAST 0 (x)
BUILD_TUPLE 1
LOAD_CONST 1 ( at 0x..., file "%s", line %d>)
- MAKE_FUNCTION 8 (closure)
+ MAKE_FUNCTION
+ SET_FUNCTION_ATTRIBUTE 8 (closure)
LOAD_DEREF 1 (y)
GET_ITER
CALL 0
@@ -761,7 +767,7 @@ def load_test(x, y=0):
%3d 0 RESUME 0
%3d 2 LOAD_FAST_LOAD_FAST 1 (x, y)
- 4 STORE_FAST_STORE_FAST 50 (b, a)
+ 4 STORE_FAST_STORE_FAST 50 (b, a)
%3d 6 LOAD_FAST_LOAD_FAST 35 (a, b)
8 BUILD_TUPLE 2
@@ -788,7 +794,7 @@ def loop_test():
%3d LOAD_GLOBAL_MODULE 1 (NULL + load_test)
LOAD_FAST 0 (i)
- CALL_PY_WITH_DEFAULTS 1
+ CALL_PY_WITH_DEFAULTS 1
POP_TOP
JUMP_BACKWARD 16 (to 16)
@@ -1183,7 +1189,7 @@ def test_binary_specialize(self):
co_unicode = compile('a + b', "", "eval")
self.code_quicken(lambda: exec(co_unicode, {}, {'a': 'a', 'b': 'b'}))
got = self.get_disassembly(co_unicode, adaptive=True)
- self.do_disassembly_compare(got, binary_op_quicken % "BINARY_OP_ADD_UNICODE 0 (+)", True)
+ self.do_disassembly_compare(got, binary_op_quicken % "BINARY_OP_ADD_UNICODE 0 (+)", True)
binary_subscr_quicken = """\
0 0 RESUME 0
@@ -1566,213 +1572,238 @@ def jumpy():
def _stringify_instruction(instr):
# Since line numbers and other offsets change a lot for these
# test cases, ignore them.
- return str(instr._replace(positions=None))
+ return f" {instr._replace(positions=None)!r},"
def _prepare_test_cases():
- _instructions = dis.get_instructions(outer, first_line=expected_outer_line)
- print('expected_opinfo_outer = [\n ',
- ',\n '.join(map(_stringify_instruction, _instructions)), ',\n]', sep='')
- _instructions = dis.get_instructions(outer(), first_line=expected_f_line)
- print('expected_opinfo_f = [\n ',
- ',\n '.join(map(_stringify_instruction, _instructions)), ',\n]', sep='')
- _instructions = dis.get_instructions(outer()(), first_line=expected_inner_line)
- print('expected_opinfo_inner = [\n ',
- ',\n '.join(map(_stringify_instruction, _instructions)), ',\n]', sep='')
- _instructions = dis.get_instructions(jumpy, first_line=expected_jumpy_line)
- print('expected_opinfo_jumpy = [\n ',
- ',\n '.join(map(_stringify_instruction, _instructions)), ',\n]', sep='')
- dis.dis(outer)
-
-#_prepare_test_cases()
+ ignore = io.StringIO()
+ with contextlib.redirect_stdout(ignore):
+ f = outer()
+ inner = f()
+ _instructions_outer = dis.get_instructions(outer, first_line=expected_outer_line)
+ _instructions_f = dis.get_instructions(f, first_line=expected_f_line)
+ _instructions_inner = dis.get_instructions(inner, first_line=expected_inner_line)
+ _instructions_jumpy = dis.get_instructions(jumpy, first_line=expected_jumpy_line)
+ result = "\n".join(
+ [
+ "expected_opinfo_outer = [",
+ *map(_stringify_instruction, _instructions_outer),
+ "]",
+ "",
+ "expected_opinfo_f = [",
+ *map(_stringify_instruction, _instructions_f),
+ "]",
+ "",
+ "expected_opinfo_inner = [",
+ *map(_stringify_instruction, _instructions_inner),
+ "]",
+ "",
+ "expected_opinfo_jumpy = [",
+ *map(_stringify_instruction, _instructions_jumpy),
+ "]",
+ ]
+ )
+ result = result.replace(repr(repr(code_object_f)), "repr(code_object_f)")
+ result = result.replace(repr(code_object_f), "code_object_f")
+ result = result.replace(repr(repr(code_object_inner)), "repr(code_object_inner)")
+ result = result.replace(repr(code_object_inner), "code_object_inner")
+ print(result)
+
+# _prepare_test_cases()
Instruction = dis.Instruction
expected_opinfo_outer = [
- Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval='a', argrepr='a', offset=0, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval='b', argrepr='b', offset=2, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=4, starts_line=1, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=(3, 4), argrepr='(3, 4)', offset=6, starts_line=2, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CLOSURE', opcode=136, arg=0, argval='a', argrepr='a', offset=8, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CLOSURE', opcode=136, arg=1, argval='b', argrepr='b', offset=10, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BUILD_TUPLE', opcode=102, arg=2, argval=2, argrepr='', offset=12, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=code_object_f, argrepr=repr(code_object_f), offset=14, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='MAKE_FUNCTION', opcode=132, arg=9, argval=9, argrepr='defaults, closure', offset=16, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='f', argrepr='f', offset=18, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='NULL + print', offset=20, starts_line=7, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='a', argrepr='a', offset=30, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='b', argrepr='b', offset=32, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval='', argrepr="''", offset=34, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=1, argrepr='1', offset=36, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='Hello world!', argrepr="'Hello world!'", offset=42, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=7, argval=7, argrepr='', offset=44, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=52, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=54, starts_line=8, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=56, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval='a', argrepr='a', offset=0, start_offset=0, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval='b', argrepr='b', offset=2, start_offset=2, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=4, start_offset=4, starts_line=1, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=(3, 4), argrepr='(3, 4)', offset=6, start_offset=6, starts_line=2, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='a', argrepr='a', offset=8, start_offset=8, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='b', argrepr='b', offset=10, start_offset=10, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='BUILD_TUPLE', opcode=102, arg=2, argval=2, argrepr='', offset=12, start_offset=12, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=code_object_f, argrepr=repr(code_object_f), offset=14, start_offset=14, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='MAKE_FUNCTION', opcode=24, arg=None, argval=None, argrepr='', offset=16, start_offset=16, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=177, arg=8, argval=8, argrepr='closure', offset=18, start_offset=18, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=177, arg=1, argval=1, argrepr='defaults', offset=20, start_offset=20, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='f', argrepr='f', offset=22, start_offset=22, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='NULL + print', offset=24, start_offset=24, starts_line=7, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='a', argrepr='a', offset=34, start_offset=34, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='b', argrepr='b', offset=36, start_offset=36, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval='', argrepr="''", offset=38, start_offset=38, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=1, argrepr='1', offset=40, start_offset=40, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=42, start_offset=42, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='Hello world!', argrepr="'Hello world!'", offset=46, start_offset=46, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=7, argval=7, argrepr='', offset=48, start_offset=48, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=58, start_offset=58, starts_line=8, is_jump_target=False, positions=None),
+ Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=None, is_jump_target=False, positions=None),
]
expected_opinfo_f = [
- Instruction(opname='COPY_FREE_VARS', opcode=149, arg=2, argval=2, argrepr='', offset=0, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval='c', argrepr='c', offset=2, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval='d', argrepr='d', offset=4, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=6, starts_line=2, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=(5, 6), argrepr='(5, 6)', offset=8, starts_line=3, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CLOSURE', opcode=136, arg=3, argval='a', argrepr='a', offset=10, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CLOSURE', opcode=136, arg=4, argval='b', argrepr='b', offset=12, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CLOSURE', opcode=136, arg=0, argval='c', argrepr='c', offset=14, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CLOSURE', opcode=136, arg=1, argval='d', argrepr='d', offset=16, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BUILD_TUPLE', opcode=102, arg=4, argval=4, argrepr='', offset=18, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=code_object_inner, argrepr=repr(code_object_inner), offset=20, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='MAKE_FUNCTION', opcode=132, arg=9, argval=9, argrepr='defaults, closure', offset=22, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='inner', argrepr='inner', offset=24, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='NULL + print', offset=26, starts_line=5, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='a', argrepr='a', offset=36, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='b', argrepr='b', offset=38, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=40, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=42, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=4, argval=4, argrepr='', offset=44, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=52, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=54, starts_line=6, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=56, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COPY_FREE_VARS', opcode=149, arg=2, argval=2, argrepr='', offset=0, start_offset=0, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval='c', argrepr='c', offset=2, start_offset=2, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval='d', argrepr='d', offset=4, start_offset=4, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=6, start_offset=6, starts_line=2, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=(5, 6), argrepr='(5, 6)', offset=8, start_offset=8, starts_line=3, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=3, argval='a', argrepr='a', offset=10, start_offset=10, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=4, argval='b', argrepr='b', offset=12, start_offset=12, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='c', argrepr='c', offset=14, start_offset=14, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='d', argrepr='d', offset=16, start_offset=16, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='BUILD_TUPLE', opcode=102, arg=4, argval=4, argrepr='', offset=18, start_offset=18, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=code_object_inner, argrepr=repr(code_object_inner), offset=20, start_offset=20, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='MAKE_FUNCTION', opcode=24, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=177, arg=8, argval=8, argrepr='closure', offset=24, start_offset=24, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=177, arg=1, argval=1, argrepr='defaults', offset=26, start_offset=26, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='inner', argrepr='inner', offset=28, start_offset=28, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='NULL + print', offset=30, start_offset=30, starts_line=5, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='a', argrepr='a', offset=40, start_offset=40, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='b', argrepr='b', offset=42, start_offset=42, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=44, start_offset=44, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=46, start_offset=46, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=4, argval=4, argrepr='', offset=48, start_offset=48, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=58, start_offset=58, starts_line=6, is_jump_target=False, positions=None),
+ Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=None, is_jump_target=False, positions=None),
]
expected_opinfo_inner = [
- Instruction(opname='COPY_FREE_VARS', opcode=149, arg=4, argval=4, argrepr='', offset=0, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=2, starts_line=3, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='NULL + print', offset=4, starts_line=4, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=2, argval='a', argrepr='a', offset=14, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='b', argrepr='b', offset=16, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='c', argrepr='c', offset=18, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=5, argval='d', argrepr='d', offset=20, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST_LOAD_FAST', opcode=168, arg=1, argval=('e', 'f'), argrepr='e, f', offset=22, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=6, argval=6, argrepr='', offset=24, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=32, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_CONST', opcode=121, arg=0, argval=None, argrepr='None', offset=34, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COPY_FREE_VARS', opcode=149, arg=4, argval=4, argrepr='', offset=0, start_offset=0, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=2, start_offset=2, starts_line=3, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='NULL + print', offset=4, start_offset=4, starts_line=4, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=2, argval='a', argrepr='a', offset=14, start_offset=14, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='b', argrepr='b', offset=16, start_offset=16, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='c', argrepr='c', offset=18, start_offset=18, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=5, argval='d', argrepr='d', offset=20, start_offset=20, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST_LOAD_FAST', opcode=168, arg=1, argval=('e', 'f'), argrepr='e, f', offset=22, start_offset=22, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=6, argval=6, argrepr='', offset=24, start_offset=24, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=32, start_offset=32, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RETURN_CONST', opcode=121, arg=0, argval=None, argrepr='None', offset=34, start_offset=34, starts_line=None, is_jump_target=False, positions=None),
]
-
expected_opinfo_jumpy = [
- Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, starts_line=1, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='range', argrepr='NULL + range', offset=2, starts_line=3, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=12, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=14, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=22, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='FOR_ITER', opcode=93, arg=28, argval=84, argrepr='to 84', offset=24, starts_line=None, is_jump_target=True, positions=None),
- Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=28, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=30, starts_line=4, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=40, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=52, starts_line=5, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=54, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=2, argval='<', argrepr='<', offset=56, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=2, argval=66, argrepr='to 66', offset=60, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_BACKWARD', opcode=140, arg=21, argval=24, argrepr='to 24', offset=62, starts_line=6, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=66, starts_line=7, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=68, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=68, argval='>', argrepr='>', offset=70, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=2, argval=80, argrepr='to 80', offset=74, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_BACKWARD', opcode=140, arg=28, argval=24, argrepr='to 24', offset=76, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=80, starts_line=8, is_jump_target=True, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=12, argval=108, argrepr='to 108', offset=82, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='END_FOR', opcode=4, arg=None, argval=None, argrepr='', offset=84, starts_line=3, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=86, starts_line=10, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=96, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=98, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=106, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST_CHECK', opcode=127, arg=0, argval='i', argrepr='i', offset=108, starts_line=11, is_jump_target=True, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=33, argval=178, argrepr='to 178', offset=110, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=112, starts_line=12, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=122, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=124, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=134, starts_line=13, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=136, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=138, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=142, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=14, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=146, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=68, argval='>', argrepr='>', offset=148, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=2, argval=158, argrepr='to 158', offset=152, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_BACKWARD', opcode=140, arg=25, argval=108, argrepr='to 108', offset=154, starts_line=15, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=158, starts_line=16, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=160, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=2, argval='<', argrepr='<', offset=162, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=170, argrepr='to 170', offset=166, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=15, argval=200, argrepr='to 200', offset=168, starts_line=17, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=170, starts_line=11, is_jump_target=True, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=2, argval=178, argrepr='to 178', offset=172, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_BACKWARD', opcode=140, arg=33, argval=112, argrepr='to 112', offset=174, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=178, starts_line=19, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=188, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=190, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=198, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=200, starts_line=20, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=202, starts_line=21, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=204, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=206, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=212, starts_line=25, is_jump_target=False, positions=None),
- Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=214, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=216, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=218, starts_line=26, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=228, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=238, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=240, starts_line=25, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=242, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=244, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=246, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=254, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=256, starts_line=28, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=266, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=268, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=276, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_CONST', opcode=121, arg=0, argval=None, argrepr='None', offset=278, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=280, starts_line=25, is_jump_target=False, positions=None),
- Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=282, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=1, argval=288, argrepr='to 288', offset=284, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=286, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=288, starts_line=None, is_jump_target=True, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=290, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=292, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=294, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_BACKWARD', opcode=140, arg=22, argval=256, argrepr='to 256', offset=296, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=300, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=302, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=304, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=306, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=308, starts_line=22, is_jump_target=False, positions=None),
- Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=318, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=15, argval=352, argrepr='to 352', offset=320, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=322, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=324, starts_line=23, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=334, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=336, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=344, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=346, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_BACKWARD', opcode=140, arg=48, argval=256, argrepr='to 256', offset=348, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=352, starts_line=22, is_jump_target=True, positions=None),
- Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=354, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=356, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=358, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=360, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=362, starts_line=28, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=372, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=374, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=382, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=384, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=386, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=388, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=390, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=1, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='range', argrepr='NULL + range', offset=2, start_offset=2, starts_line=3, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=12, start_offset=12, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=14, start_offset=14, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='FOR_ITER', opcode=93, arg=28, argval=84, argrepr='to 84', offset=24, start_offset=24, starts_line=None, is_jump_target=True, positions=None),
+ Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=28, start_offset=28, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=30, start_offset=30, starts_line=4, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=40, start_offset=40, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=42, start_offset=42, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=50, start_offset=50, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=52, start_offset=52, starts_line=5, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=54, start_offset=54, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COMPARE_OP', opcode=107, arg=18, argval='<', argrepr='bool(<)', offset=56, start_offset=56, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=2, argval=66, argrepr='to 66', offset=60, start_offset=60, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=140, arg=21, argval=24, argrepr='to 24', offset=62, start_offset=62, starts_line=6, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=66, start_offset=66, starts_line=7, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=68, start_offset=68, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COMPARE_OP', opcode=107, arg=148, argval='>', argrepr='bool(>)', offset=70, start_offset=70, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=2, argval=80, argrepr='to 80', offset=74, start_offset=74, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=140, arg=28, argval=24, argrepr='to 24', offset=76, start_offset=76, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=80, start_offset=80, starts_line=8, is_jump_target=True, positions=None),
+ Instruction(opname='JUMP_FORWARD', opcode=110, arg=12, argval=108, argrepr='to 108', offset=82, start_offset=82, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='END_FOR', opcode=4, arg=None, argval=None, argrepr='', offset=84, start_offset=84, starts_line=3, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=86, start_offset=86, starts_line=10, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=96, start_offset=96, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=98, start_offset=98, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=106, start_offset=106, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST_CHECK', opcode=127, arg=0, argval='i', argrepr='i', offset=108, start_offset=108, starts_line=11, is_jump_target=True, positions=None),
+ Instruction(opname='TO_BOOL', opcode=6, arg=None, argval=None, argrepr='', offset=110, start_offset=110, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=37, argval=194, argrepr='to 194', offset=118, start_offset=118, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=120, start_offset=120, starts_line=12, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=130, start_offset=130, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=132, start_offset=132, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=140, start_offset=140, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=142, start_offset=142, starts_line=13, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=144, start_offset=144, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=146, start_offset=146, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=150, start_offset=150, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=152, start_offset=152, starts_line=14, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=154, start_offset=154, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COMPARE_OP', opcode=107, arg=148, argval='>', argrepr='bool(>)', offset=156, start_offset=156, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=2, argval=166, argrepr='to 166', offset=160, start_offset=160, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=140, arg=29, argval=108, argrepr='to 108', offset=162, start_offset=162, starts_line=15, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=166, start_offset=166, starts_line=16, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=168, start_offset=168, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COMPARE_OP', opcode=107, arg=18, argval='<', argrepr='bool(<)', offset=170, start_offset=170, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=178, argrepr='to 178', offset=174, start_offset=174, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_FORWARD', opcode=110, arg=19, argval=216, argrepr='to 216', offset=176, start_offset=176, starts_line=17, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=178, start_offset=178, starts_line=11, is_jump_target=True, positions=None),
+ Instruction(opname='TO_BOOL', opcode=6, arg=None, argval=None, argrepr='', offset=180, start_offset=180, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=2, argval=194, argrepr='to 194', offset=188, start_offset=188, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=140, arg=37, argval=120, argrepr='to 120', offset=190, start_offset=190, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=194, start_offset=194, starts_line=19, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=204, start_offset=204, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=206, start_offset=206, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=214, start_offset=214, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=216, start_offset=216, starts_line=20, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=218, start_offset=218, starts_line=21, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=220, start_offset=220, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=222, start_offset=222, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=226, start_offset=226, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=228, start_offset=228, starts_line=25, is_jump_target=False, positions=None),
+ Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=230, start_offset=230, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=232, start_offset=232, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=234, start_offset=234, starts_line=26, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=244, start_offset=244, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=246, start_offset=246, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=254, start_offset=254, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=256, start_offset=256, starts_line=25, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=258, start_offset=258, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=260, start_offset=260, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=262, start_offset=262, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=270, start_offset=270, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=272, start_offset=272, starts_line=28, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=282, start_offset=282, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=284, start_offset=284, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=292, start_offset=292, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RETURN_CONST', opcode=121, arg=0, argval=None, argrepr='None', offset=294, start_offset=294, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=296, start_offset=296, starts_line=25, is_jump_target=False, positions=None),
+ Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=298, start_offset=298, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='TO_BOOL', opcode=6, arg=None, argval=None, argrepr='', offset=300, start_offset=300, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=1, argval=312, argrepr='to 312', offset=308, start_offset=308, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=310, start_offset=310, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=312, start_offset=312, starts_line=None, is_jump_target=True, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=314, start_offset=314, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=316, start_offset=316, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=318, start_offset=318, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=140, arg=26, argval=272, argrepr='to 272', offset=320, start_offset=320, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=324, start_offset=324, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=326, start_offset=326, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=328, start_offset=328, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=330, start_offset=330, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=332, start_offset=332, starts_line=22, is_jump_target=False, positions=None),
+ Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=15, argval=376, argrepr='to 376', offset=344, start_offset=344, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=348, start_offset=348, starts_line=23, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=358, start_offset=358, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=360, start_offset=360, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=370, start_offset=370, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=140, arg=52, argval=272, argrepr='to 272', offset=372, start_offset=372, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=376, start_offset=376, starts_line=22, is_jump_target=True, positions=None),
+ Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=378, start_offset=378, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=380, start_offset=380, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=382, start_offset=382, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=384, start_offset=384, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=386, start_offset=386, starts_line=28, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=396, start_offset=396, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=398, start_offset=398, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=406, start_offset=406, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=408, start_offset=408, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=410, start_offset=410, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=412, start_offset=412, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=414, start_offset=414, starts_line=None, is_jump_target=False, positions=None),
]
# One last piece of inspect fodder to check the default line number handling
def simple(): pass
expected_opinfo_simple = [
- Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, starts_line=simple.__code__.co_firstlineno, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_CONST', opcode=121, arg=0, argval=None, argrepr='None', offset=2, starts_line=None, is_jump_target=False),
+ Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=simple.__code__.co_firstlineno, is_jump_target=False, positions=None),
+ Instruction(opname='RETURN_CONST', opcode=121, arg=0, argval=None, argrepr='None', offset=2, start_offset=2, starts_line=None, is_jump_target=False),
]
@@ -1889,6 +1920,130 @@ def roots(a, b, c):
]
self.assertEqual(co_positions, dis_positions)
+ def test_oparg_alias(self):
+ instruction = Instruction(opname="NOP", opcode=dis.opmap["NOP"], arg=None, argval=None,
+ argrepr='', offset=10, start_offset=10, starts_line=1, is_jump_target=False,
+ positions=None)
+ self.assertEqual(instruction.arg, instruction.oparg)
+
+ def test_baseopname_and_baseopcode(self):
+ # Standard instructions
+ for name, code in dis.opmap.items():
+ instruction = Instruction(opname=name, opcode=code, arg=None, argval=None, argrepr='', offset=0,
+ start_offset=0, starts_line=1, is_jump_target=False, positions=None)
+ baseopname = instruction.baseopname
+ baseopcode = instruction.baseopcode
+ self.assertIsNotNone(baseopname)
+ self.assertIsNotNone(baseopcode)
+ self.assertEqual(name, baseopname)
+ self.assertEqual(code, baseopcode)
+
+ # Specialized instructions
+ for name in opcode._specialized_instructions:
+ instruction = Instruction(opname=name, opcode=dis._all_opmap[name], arg=None, argval=None, argrepr='',
+ offset=0, start_offset=0, starts_line=1, is_jump_target=False, positions=None)
+ baseopname = instruction.baseopname
+ baseopcode = instruction.baseopcode
+ self.assertIn(name, opcode._specializations[baseopname])
+ self.assertEqual(opcode.opmap[baseopname], baseopcode)
+
+ def test_jump_target(self):
+ # Non-jump instructions should return None
+ instruction = Instruction(opname="NOP", opcode=dis.opmap["NOP"], arg=None, argval=None,
+ argrepr='', offset=10, start_offset=10, starts_line=1, is_jump_target=False,
+ positions=None)
+ self.assertIsNone(instruction.jump_target)
+
+ delta = 100
+ instruction = Instruction(opname="JUMP_FORWARD", opcode=dis.opmap["JUMP_FORWARD"], arg=delta, argval=delta,
+ argrepr='', offset=10, start_offset=10, starts_line=1, is_jump_target=False,
+ positions=None)
+ self.assertEqual(10 + 2 + 100*2, instruction.jump_target)
+
+ # Test negative deltas
+ instruction = Instruction(opname="JUMP_BACKWARD", opcode=dis.opmap["JUMP_BACKWARD"], arg=delta, argval=delta,
+ argrepr='', offset=200, start_offset=200, starts_line=1, is_jump_target=False,
+ positions=None)
+ self.assertEqual(200 + 2 - 100*2 + 2*1, instruction.jump_target)
+
+ # Make sure cache entries are handled
+ instruction = Instruction(opname="SEND", opcode=dis.opmap["SEND"], arg=delta, argval=delta,
+ argrepr='', offset=10, start_offset=10, starts_line=1, is_jump_target=False,
+ positions=None)
+ self.assertEqual(10 + 2 + 1*2 + 100*2, instruction.jump_target)
+
+ def test_start_offset(self):
+ # When no extended args are present,
+ # start_offset should be equal to offset
+ instructions = list(dis.Bytecode(_f))
+ for instruction in instructions:
+ self.assertEqual(instruction.offset, instruction.start_offset)
+
+ code = bytes([
+ opcode.opmap["LOAD_FAST"], 0x00,
+ opcode.opmap["EXTENDED_ARG"], 0x01,
+ opcode.opmap["POP_JUMP_IF_TRUE"], 0xFF,
+ ])
+ jump = list(dis._get_instructions_bytes(code))[-1]
+ self.assertEqual(4, jump.offset)
+ self.assertEqual(2, jump.start_offset)
+
+ code = bytes([
+ opcode.opmap["LOAD_FAST"], 0x00,
+ opcode.opmap["EXTENDED_ARG"], 0x01,
+ opcode.opmap["EXTENDED_ARG"], 0x01,
+ opcode.opmap["EXTENDED_ARG"], 0x01,
+ opcode.opmap["POP_JUMP_IF_TRUE"], 0xFF,
+ ])
+ jump = list(dis._get_instructions_bytes(code))[-1]
+ self.assertEqual(8, jump.offset)
+ self.assertEqual(2, jump.start_offset)
+
+ code = bytes([
+ opcode.opmap["LOAD_FAST"], 0x00,
+ opcode.opmap["EXTENDED_ARG"], 0x01,
+ opcode.opmap["POP_JUMP_IF_TRUE"], 0xFF,
+ opcode.opmap["EXTENDED_ARG"], 0x01,
+ opcode.opmap["EXTENDED_ARG"], 0x01,
+ opcode.opmap["EXTENDED_ARG"], 0x01,
+ opcode.opmap["POP_JUMP_IF_TRUE"], 0xFF,
+ ])
+ instructions = list(dis._get_instructions_bytes(code))
+ # 1st jump
+ self.assertEqual(4, instructions[2].offset)
+ self.assertEqual(2, instructions[2].start_offset)
+ # 2nd jump
+ self.assertEqual(12, instructions[6].offset)
+ self.assertEqual(6, instructions[6].start_offset)
+
+ def test_cache_offset_and_end_offset(self):
+ code = bytes([
+ opcode.opmap["LOAD_GLOBAL"], 0x01,
+ opcode.opmap["CACHE"], 0x00,
+ opcode.opmap["CACHE"], 0x00,
+ opcode.opmap["CACHE"], 0x00,
+ opcode.opmap["CACHE"], 0x00,
+ opcode.opmap["LOAD_FAST"], 0x00,
+ opcode.opmap["CALL"], 0x01,
+ opcode.opmap["CACHE"], 0x00,
+ opcode.opmap["CACHE"], 0x00,
+ opcode.opmap["CACHE"], 0x00
+ ])
+ instructions = list(dis._get_instructions_bytes(code))
+ self.assertEqual(2, instructions[0].cache_offset)
+ self.assertEqual(10, instructions[0].end_offset)
+ self.assertEqual(12, instructions[1].cache_offset)
+ self.assertEqual(12, instructions[1].end_offset)
+ self.assertEqual(14, instructions[2].cache_offset)
+ self.assertEqual(20, instructions[2].end_offset)
+
+ # end_offset of the previous instruction should be equal to the
+ # start_offset of the following instruction
+ instructions = list(dis.Bytecode(self.test_cache_offset_and_end_offset))
+ for prev, curr in zip(instructions, instructions[1:]):
+ self.assertEqual(prev.end_offset, curr.start_offset)
+
+
# get_instructions has its own tests above, so can rely on it to validate
# the object oriented API
class BytecodeTests(InstructionTestCase, DisTestBase):
diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py
index 542fcdb5cf6f66..bea52c6de7ec6d 100644
--- a/Lib/test/test_doctest.py
+++ b/Lib/test/test_doctest.py
@@ -1287,14 +1287,14 @@ def optionflags(): r"""
treated as equal:
>>> def f(x):
- ... '>>> print(1, 2, 3)\n 1 2\n 3'
+ ... '\n>>> print(1, 2, 3)\n 1 2\n 3'
>>> # Without the flag:
>>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test)
... # doctest: +ELLIPSIS
**********************************************************************
- File ..., line 2, in f
+ File ..., line 3, in f
Failed example:
print(1, 2, 3)
Expected:
diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
index 44b405740c4403..5238944d6b4788 100644
--- a/Lib/test/test_email/test_email.py
+++ b/Lib/test/test_email/test_email.py
@@ -3319,15 +3319,90 @@ def test_getaddresses(self):
[('Al Person', 'aperson@dom.ain'),
('Bud Person', 'bperson@dom.ain')])
+ def test_getaddresses_parsing_errors(self):
+ """Test for parsing errors from CVE-2023-27043"""
+ eq = self.assertEqual
+ eq(utils.getaddresses(['alice@example.org(']),
+ [('', '')])
+ eq(utils.getaddresses(['alice@example.org)']),
+ [('', '')])
+ eq(utils.getaddresses(['alice@example.org<']),
+ [('', '')])
+ eq(utils.getaddresses(['alice@example.org>']),
+ [('', '')])
+ eq(utils.getaddresses(['alice@example.org@']),
+ [('', '')])
+ eq(utils.getaddresses(['alice@example.org,']),
+ [('', 'alice@example.org'), ('', 'bob@example.com')])
+ eq(utils.getaddresses(['alice@example.org;']),
+ [('', '')])
+ eq(utils.getaddresses(['alice@example.org:']),
+ [('', '')])
+ eq(utils.getaddresses(['alice@example.org.']),
+ [('', '')])
+ eq(utils.getaddresses(['alice@example.org"']),
+ [('', '')])
+ eq(utils.getaddresses(['alice@example.org[']),
+ [('', '')])
+ eq(utils.getaddresses(['alice@example.org]']),
+ [('', '')])
+
+ def test_parseaddr_parsing_errors(self):
+ """Test for parsing errors from CVE-2023-27043"""
+ eq = self.assertEqual
+ eq(utils.parseaddr(['alice@example.org(']),
+ ('', ''))
+ eq(utils.parseaddr(['alice@example.org)']),
+ ('', ''))
+ eq(utils.parseaddr(['alice@example.org<']),
+ ('', ''))
+ eq(utils.parseaddr(['alice@example.org>']),
+ ('', ''))
+ eq(utils.parseaddr(['alice@example.org@']),
+ ('', ''))
+ eq(utils.parseaddr(['alice@example.org,']),
+ ('', ''))
+ eq(utils.parseaddr(['alice@example.org;']),
+ ('', ''))
+ eq(utils.parseaddr(['alice@example.org:']),
+ ('', ''))
+ eq(utils.parseaddr(['alice@example.org.']),
+ ('', ''))
+ eq(utils.parseaddr(['alice@example.org"']),
+ ('', ''))
+ eq(utils.parseaddr(['alice@example.org[']),
+ ('', ''))
+ eq(utils.parseaddr(['alice@example.org]']),
+ ('', ''))
+
def test_getaddresses_nasty(self):
eq = self.assertEqual
eq(utils.getaddresses(['foo: ;']), [('', '')])
- eq(utils.getaddresses(
- ['[]*-- =~$']),
- [('', ''), ('', ''), ('', '*--')])
+ eq(utils.getaddresses(['[]*-- =~$']), [('', '')])
eq(utils.getaddresses(
['foo: ;', '"Jason R. Mastaler" ']),
[('', ''), ('Jason R. Mastaler', 'jason@dom.ain')])
+ eq(utils.getaddresses(
+ [r'Pete(A nice \) chap) ']),
+ [('Pete (A nice ) chap his account his host)', 'pete@silly.test')])
+ eq(utils.getaddresses(
+ ['(Empty list)(start)Undisclosed recipients :(nobody(I know))']),
+ [('', '')])
+ eq(utils.getaddresses(
+ ['Mary <@machine.tld:mary@example.net>, , jdoe@test . example']),
+ [('Mary', 'mary@example.net'), ('', ''), ('', 'jdoe@test.example')])
+ eq(utils.getaddresses(
+ ['John Doe ']),
+ [('John Doe (comment)', 'jdoe@machine.example')])
+ eq(utils.getaddresses(
+ ['"Mary Smith: Personal Account" ']),
+ [('Mary Smith: Personal Account', 'smith@home.example')])
+ eq(utils.getaddresses(
+ ['Undisclosed recipients:;']),
+ [('', '')])
+ eq(utils.getaddresses(
+ [r', "Giant; \"Big\" Box" ']),
+ [('', 'boss@nil.test'), ('Giant; "Big" Box', 'bob@example.net')])
def test_getaddresses_embedded_comment(self):
"""Test proper handling of a nested comment"""
diff --git a/Lib/test/test_email/test_message.py b/Lib/test/test_email/test_message.py
index 4c754bf40fc300..d3f396f02e7a72 100644
--- a/Lib/test/test_email/test_message.py
+++ b/Lib/test/test_email/test_message.py
@@ -696,14 +696,16 @@ def subtype_as_add(self, method, subtype, outcome):
self.assertIsNone(part['Content-Disposition'])
class _TestSetRaisingContentManager:
+ class CustomError(Exception):
+ pass
def set_content(self, msg, content, *args, **kw):
- raise Exception('test')
+ raise self.CustomError('test')
def test_default_content_manager_for_add_comes_from_policy(self):
cm = self._TestSetRaisingContentManager()
m = self.message(policy=self.policy.clone(content_manager=cm))
for method in ('add_related', 'add_alternative', 'add_attachment'):
- with self.assertRaises(Exception) as ar:
+ with self.assertRaises(self._TestSetRaisingContentManager.CustomError) as ar:
getattr(m, method)('')
self.assertEqual(str(ar.exception), 'test')
diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py
index 54b7d18d454151..a286411f7bcf57 100644
--- a/Lib/test/test_enum.py
+++ b/Lib/test/test_enum.py
@@ -804,9 +804,17 @@ def test_copy(self):
TE = self.MainEnum
copied = copy.copy(TE)
self.assertEqual(copied, TE)
+ self.assertIs(copied, TE)
deep = copy.deepcopy(TE)
self.assertEqual(deep, TE)
+ self.assertIs(deep, TE)
+ def test_copy_member(self):
+ TE = self.MainEnum
+ copied = copy.copy(TE.first)
+ self.assertIs(copied, TE.first)
+ deep = copy.deepcopy(TE.first)
+ self.assertIs(deep, TE.first)
class _FlagTests:
@@ -818,6 +826,89 @@ def test_default_missing_with_wrong_type_value(self):
self.MainEnum('RED')
self.assertIs(ctx.exception.__context__, None)
+ def test_closed_invert_expectations(self):
+ class ClosedAB(self.enum_type):
+ A = 1
+ B = 2
+ MASK = 3
+ A, B = ClosedAB
+ AB_MASK = ClosedAB.MASK
+ #
+ self.assertIs(~A, B)
+ self.assertIs(~B, A)
+ self.assertIs(~(A|B), ClosedAB(0))
+ self.assertIs(~AB_MASK, ClosedAB(0))
+ self.assertIs(~ClosedAB(0), (A|B))
+ #
+ class ClosedXYZ(self.enum_type):
+ X = 4
+ Y = 2
+ Z = 1
+ MASK = 7
+ X, Y, Z = ClosedXYZ
+ XYZ_MASK = ClosedXYZ.MASK
+ #
+ self.assertIs(~X, Y|Z)
+ self.assertIs(~Y, X|Z)
+ self.assertIs(~Z, X|Y)
+ self.assertIs(~(X|Y), Z)
+ self.assertIs(~(X|Z), Y)
+ self.assertIs(~(Y|Z), X)
+ self.assertIs(~(X|Y|Z), ClosedXYZ(0))
+ self.assertIs(~XYZ_MASK, ClosedXYZ(0))
+ self.assertIs(~ClosedXYZ(0), (X|Y|Z))
+
+ def test_open_invert_expectations(self):
+ class OpenAB(self.enum_type):
+ A = 1
+ B = 2
+ MASK = 255
+ A, B = OpenAB
+ AB_MASK = OpenAB.MASK
+ #
+ if OpenAB._boundary_ in (EJECT, KEEP):
+ self.assertIs(~A, OpenAB(254))
+ self.assertIs(~B, OpenAB(253))
+ self.assertIs(~(A|B), OpenAB(252))
+ self.assertIs(~AB_MASK, OpenAB(0))
+ self.assertIs(~OpenAB(0), AB_MASK)
+ else:
+ self.assertIs(~A, B)
+ self.assertIs(~B, A)
+ self.assertIs(~(A|B), OpenAB(0))
+ self.assertIs(~AB_MASK, OpenAB(0))
+ self.assertIs(~OpenAB(0), (A|B))
+ #
+ class OpenXYZ(self.enum_type):
+ X = 4
+ Y = 2
+ Z = 1
+ MASK = 31
+ X, Y, Z = OpenXYZ
+ XYZ_MASK = OpenXYZ.MASK
+ #
+ if OpenXYZ._boundary_ in (EJECT, KEEP):
+ self.assertIs(~X, OpenXYZ(27))
+ self.assertIs(~Y, OpenXYZ(29))
+ self.assertIs(~Z, OpenXYZ(30))
+ self.assertIs(~(X|Y), OpenXYZ(25))
+ self.assertIs(~(X|Z), OpenXYZ(26))
+ self.assertIs(~(Y|Z), OpenXYZ(28))
+ self.assertIs(~(X|Y|Z), OpenXYZ(24))
+ self.assertIs(~XYZ_MASK, OpenXYZ(0))
+ self.assertTrue(~OpenXYZ(0), XYZ_MASK)
+ else:
+ self.assertIs(~X, Y|Z)
+ self.assertIs(~Y, X|Z)
+ self.assertIs(~Z, X|Y)
+ self.assertIs(~(X|Y), Z)
+ self.assertIs(~(X|Z), Y)
+ self.assertIs(~(Y|Z), X)
+ self.assertIs(~(X|Y|Z), OpenXYZ(0))
+ self.assertIs(~XYZ_MASK, OpenXYZ(0))
+ self.assertTrue(~OpenXYZ(0), (X|Y|Z))
+
+
class TestPlainEnum(_EnumTests, _PlainOutputTests, unittest.TestCase):
enum_type = Enum
@@ -3045,33 +3136,6 @@ class Color(Flag):
WHITE = RED|GREEN|BLUE
BLANCO = RED|GREEN|BLUE
- class Complete(Flag):
- A = 0x01
- B = 0x02
-
- class Partial(Flag):
- A = 0x01
- B = 0x02
- MASK = 0xff
-
- class CompleteInt(IntFlag):
- A = 0x01
- B = 0x02
-
- class PartialInt(IntFlag):
- A = 0x01
- B = 0x02
- MASK = 0xff
-
- class CompleteIntStrict(IntFlag, boundary=STRICT):
- A = 0x01
- B = 0x02
-
- class PartialIntStrict(IntFlag, boundary=STRICT):
- A = 0x01
- B = 0x02
- MASK = 0xff
-
def test_or(self):
Perm = self.Perm
for i in Perm:
@@ -3115,34 +3179,6 @@ def test_xor(self):
self.assertIs(Open.RO ^ Open.CE, Open.CE)
self.assertIs(Open.CE ^ Open.CE, Open.RO)
- def test_invert(self):
- Perm = self.Perm
- RW = Perm.R | Perm.W
- RX = Perm.R | Perm.X
- WX = Perm.W | Perm.X
- RWX = Perm.R | Perm.W | Perm.X
- values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
- for i in values:
- self.assertIs(type(~i), Perm)
- self.assertEqual(~~i, i)
- for i in Perm:
- self.assertIs(~~i, i)
- Open = self.Open
- self.assertIs(Open.WO & ~Open.WO, Open.RO)
- self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
- Complete = self.Complete
- self.assertIs(~Complete.A, Complete.B)
- Partial = self.Partial
- self.assertIs(~Partial.A, Partial.B)
- CompleteInt = self.CompleteInt
- self.assertIs(~CompleteInt.A, CompleteInt.B)
- PartialInt = self.PartialInt
- self.assertIs(~PartialInt.A, PartialInt(254))
- CompleteIntStrict = self.CompleteIntStrict
- self.assertIs(~CompleteIntStrict.A, CompleteIntStrict.B)
- PartialIntStrict = self.PartialIntStrict
- self.assertIs(~PartialIntStrict.A, PartialIntStrict.B)
-
def test_bool(self):
Perm = self.Perm
for f in Perm:
diff --git a/Lib/test/test_exception_group.py b/Lib/test/test_exception_group.py
index fa159a76ec1aff..2658e027ff3e2b 100644
--- a/Lib/test/test_exception_group.py
+++ b/Lib/test/test_exception_group.py
@@ -294,6 +294,15 @@ def assertMatchesTemplate(self, exc, exc_type, template):
self.assertEqual(type(exc), type(template))
self.assertEqual(exc.args, template.args)
+class Predicate:
+ def __init__(self, func):
+ self.func = func
+
+ def __call__(self, e):
+ return self.func(e)
+
+ def method(self, e):
+ return self.func(e)
class ExceptionGroupSubgroupTests(ExceptionGroupTestBase):
def setUp(self):
@@ -301,10 +310,15 @@ def setUp(self):
self.eg_template = [ValueError(1), TypeError(int), ValueError(2)]
def test_basics_subgroup_split__bad_arg_type(self):
+ class C:
+ pass
+
bad_args = ["bad arg",
+ C,
OSError('instance not type'),
[OSError, TypeError],
- (OSError, 42)]
+ (OSError, 42),
+ ]
for arg in bad_args:
with self.assertRaises(TypeError):
self.eg.subgroup(arg)
@@ -336,10 +350,14 @@ def test_basics_subgroup_by_type__match(self):
self.assertMatchesTemplate(subeg, ExceptionGroup, template)
def test_basics_subgroup_by_predicate__passthrough(self):
- self.assertIs(self.eg, self.eg.subgroup(lambda e: True))
+ f = lambda e: True
+ for callable in [f, Predicate(f), Predicate(f).method]:
+ self.assertIs(self.eg, self.eg.subgroup(callable))
def test_basics_subgroup_by_predicate__no_match(self):
- self.assertIsNone(self.eg.subgroup(lambda e: False))
+ f = lambda e: False
+ for callable in [f, Predicate(f), Predicate(f).method]:
+ self.assertIsNone(self.eg.subgroup(callable))
def test_basics_subgroup_by_predicate__match(self):
eg = self.eg
@@ -350,9 +368,12 @@ def test_basics_subgroup_by_predicate__match(self):
((ValueError, TypeError), self.eg_template)]
for match_type, template in testcases:
- subeg = eg.subgroup(lambda e: isinstance(e, match_type))
- self.assertEqual(subeg.message, eg.message)
- self.assertMatchesTemplate(subeg, ExceptionGroup, template)
+ f = lambda e: isinstance(e, match_type)
+ for callable in [f, Predicate(f), Predicate(f).method]:
+ with self.subTest(callable=callable):
+ subeg = eg.subgroup(f)
+ self.assertEqual(subeg.message, eg.message)
+ self.assertMatchesTemplate(subeg, ExceptionGroup, template)
class ExceptionGroupSplitTests(ExceptionGroupTestBase):
@@ -399,14 +420,18 @@ def test_basics_split_by_type__match(self):
self.assertIsNone(rest)
def test_basics_split_by_predicate__passthrough(self):
- match, rest = self.eg.split(lambda e: True)
- self.assertMatchesTemplate(match, ExceptionGroup, self.eg_template)
- self.assertIsNone(rest)
+ f = lambda e: True
+ for callable in [f, Predicate(f), Predicate(f).method]:
+ match, rest = self.eg.split(callable)
+ self.assertMatchesTemplate(match, ExceptionGroup, self.eg_template)
+ self.assertIsNone(rest)
def test_basics_split_by_predicate__no_match(self):
- match, rest = self.eg.split(lambda e: False)
- self.assertIsNone(match)
- self.assertMatchesTemplate(rest, ExceptionGroup, self.eg_template)
+ f = lambda e: False
+ for callable in [f, Predicate(f), Predicate(f).method]:
+ match, rest = self.eg.split(callable)
+ self.assertIsNone(match)
+ self.assertMatchesTemplate(rest, ExceptionGroup, self.eg_template)
def test_basics_split_by_predicate__match(self):
eg = self.eg
@@ -420,14 +445,16 @@ def test_basics_split_by_predicate__match(self):
]
for match_type, match_template, rest_template in testcases:
- match, rest = eg.split(lambda e: isinstance(e, match_type))
- self.assertEqual(match.message, eg.message)
- self.assertMatchesTemplate(
- match, ExceptionGroup, match_template)
- if rest_template is not None:
- self.assertEqual(rest.message, eg.message)
+ f = lambda e: isinstance(e, match_type)
+ for callable in [f, Predicate(f), Predicate(f).method]:
+ match, rest = eg.split(callable)
+ self.assertEqual(match.message, eg.message)
self.assertMatchesTemplate(
- rest, ExceptionGroup, rest_template)
+ match, ExceptionGroup, match_template)
+ if rest_template is not None:
+ self.assertEqual(rest.message, eg.message)
+ self.assertMatchesTemplate(
+ rest, ExceptionGroup, rest_template)
class DeepRecursionInSplitAndSubgroup(unittest.TestCase):
diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py
index 031b94d8d58a39..cb14bba2602def 100644
--- a/Lib/test/test_fstring.py
+++ b/Lib/test/test_fstring.py
@@ -13,9 +13,10 @@
import types
import decimal
import unittest
+import warnings
from test import support
from test.support.os_helper import temp_cwd
-from test.support.script_helper import assert_python_failure
+from test.support.script_helper import assert_python_failure, assert_python_ok
a_global = 'global variable'
@@ -495,6 +496,24 @@ def test_ast_line_numbers_with_parentheses(self):
self.assertEqual(wat2.end_col_offset, 17)
self.assertEqual(fstring.end_col_offset, 18)
+ def test_ast_fstring_empty_format_spec(self):
+ expr = "f'{expr:}'"
+
+ mod = ast.parse(expr)
+ self.assertEqual(type(mod), ast.Module)
+ self.assertEqual(len(mod.body), 1)
+
+ fstring = mod.body[0].value
+ self.assertEqual(type(fstring), ast.JoinedStr)
+ self.assertEqual(len(fstring.values), 1)
+
+ fv = fstring.values[0]
+ self.assertEqual(type(fv), ast.FormattedValue)
+
+ format_spec = fv.format_spec
+ self.assertEqual(type(format_spec), ast.JoinedStr)
+ self.assertEqual(len(format_spec.values), 0)
+
def test_docstring(self):
def f():
f'''Not a docstring'''
@@ -772,7 +791,7 @@ def __format__(self, format_spec):
self.assertEqual(f'{CustomFormat():\n}', '\n')
self.assertEqual(f'{CustomFormat():\u2603}', '☃')
with self.assertWarns(SyntaxWarning):
- exec('f"{F():¯\_(ツ)_/¯}"', {'F': CustomFormat})
+ exec(r'f"{F():¯\_(ツ)_/¯}"', {'F': CustomFormat})
def test_side_effect_order(self):
class X:
@@ -904,9 +923,12 @@ def test_backslashes_in_string_part(self):
self.assertEqual(f'2\x203', '2 3')
self.assertEqual(f'\x203', ' 3')
- with self.assertWarns(DeprecationWarning): # invalid escape sequence
+ with self.assertWarns(SyntaxWarning): # invalid escape sequence
value = eval(r"f'\{6*7}'")
self.assertEqual(value, '\\42')
+ with self.assertWarns(SyntaxWarning): # invalid escape sequence
+ value = eval(r"f'\g'")
+ self.assertEqual(value, '\\g')
self.assertEqual(f'\\{6*7}', '\\42')
self.assertEqual(fr'\{6*7}', '\\42')
@@ -1034,7 +1056,7 @@ def test_fstring_backslash_before_double_bracket(self):
]
for case, expected_result in deprecated_cases:
with self.subTest(case=case, expected_result=expected_result):
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarns(SyntaxWarning):
result = eval(case)
self.assertEqual(result, expected_result)
self.assertEqual(fr'\{{\}}', '\\{\\}')
@@ -1043,6 +1065,12 @@ def test_fstring_backslash_before_double_bracket(self):
self.assertEqual(fr'\}}{1+1}', '\\}2')
self.assertEqual(fr'{1+1}\}}', '2\\}')
+ def test_fstring_backslash_before_double_bracket_warns_once(self):
+ with self.assertWarns(SyntaxWarning) as w:
+ eval(r"f'\{{'")
+ self.assertEqual(len(w.warnings), 1)
+ self.assertEqual(w.warnings[0].category, SyntaxWarning)
+
def test_fstring_backslash_prefix_raw(self):
self.assertEqual(f'\\', '\\')
self.assertEqual(f'\\\\', '\\\\')
@@ -1632,5 +1660,18 @@ def test_syntax_error_after_debug(self):
"f'{1=}{1;}'",
])
+ def test_debug_in_file(self):
+ with temp_cwd():
+ script = 'script.py'
+ with open('script.py', 'w') as f:
+ f.write(f"""\
+print(f'''{{
+3
+=}}''')""")
+
+ _, stdout, _ = assert_python_ok(script)
+ self.assertEqual(stdout.decode('utf-8').strip().replace('\r\n', '\n').replace('\r', '\n'),
+ "3\n=3")
+
if __name__ == '__main__':
unittest.main()
diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py
index d668fa4c3adf5c..c4eca0f5b79511 100644
--- a/Lib/test/test_functools.py
+++ b/Lib/test/test_functools.py
@@ -3037,6 +3037,25 @@ def test_access_from_class(self):
def test_doc(self):
self.assertEqual(CachedCostItem.cost.__doc__, "The cost of the item.")
+ def test_subclass_with___set__(self):
+ """Caching still works for a subclass defining __set__."""
+ class readonly_cached_property(py_functools.cached_property):
+ def __set__(self, obj, value):
+ raise AttributeError("read only property")
+
+ class Test:
+ def __init__(self, prop):
+ self._prop = prop
+
+ @readonly_cached_property
+ def prop(self):
+ return self._prop
+
+ t = Test(1)
+ self.assertEqual(t.prop, 1)
+ t._prop = 999
+ self.assertEqual(t.prop, 1)
+
if __name__ == '__main__':
unittest.main()
diff --git a/Lib/test/test_future.py b/Lib/test/test_future.py
index b8b591a1bcf2c6..4730bfafbd9cfe 100644
--- a/Lib/test/test_future.py
+++ b/Lib/test/test_future.py
@@ -4,6 +4,7 @@
import ast
import unittest
from test.support import import_helper
+from test.support.script_helper import spawn_python, kill_python
from textwrap import dedent
import os
import re
@@ -121,6 +122,13 @@ def test_unicode_literals_exec(self):
exec("from __future__ import unicode_literals; x = ''", {}, scope)
self.assertIsInstance(scope["x"], str)
+ def test_syntactical_future_repl(self):
+ p = spawn_python('-i')
+ p.stdin.write(b"from __future__ import barry_as_FLUFL\n")
+ p.stdin.write(b"2 <> 3\n")
+ out = kill_python(p)
+ self.assertNotIn(b'SyntaxError: invalid syntax', out)
+
class AnnotationsFutureTestCase(unittest.TestCase):
template = dedent(
"""
diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py
index 311a864a52387d..85009089f21d2f 100644
--- a/Lib/test/test_gdb.py
+++ b/Lib/test/test_gdb.py
@@ -729,13 +729,13 @@ def test_two_abs_args(self):
SAMPLE_WITH_C_CALL = """
-from _testcapi import pyobject_fastcall
+from _testcapi import pyobject_vectorcall
def foo(a, b, c):
bar(a, b, c)
def bar(a, b, c):
- pyobject_fastcall(baz, (a, b, c))
+ pyobject_vectorcall(baz, (a, b, c), None)
def baz(*args):
id(42)
@@ -756,7 +756,7 @@ def test_pyup_command(self):
self.assertMultilineMatches(bt,
r'''^.*
#[0-9]+ Frame 0x-?[0-9a-f]+, for file , line 12, in baz \(args=\(1, 2, 3\)\)
-#[0-9]+
+#[0-9]+
$''')
@unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
@@ -785,7 +785,7 @@ def test_up_then_down(self):
self.assertMultilineMatches(bt,
r'''^.*
#[0-9]+ Frame 0x-?[0-9a-f]+, for file , line 12, in baz \(args=\(1, 2, 3\)\)
-#[0-9]+
+#[0-9]+
#[0-9]+ Frame 0x-?[0-9a-f]+, for file , line 12, in baz \(args=\(1, 2, 3\)\)
$''')
diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py
new file mode 100644
index 00000000000000..ba0e5e8b0f6954
--- /dev/null
+++ b/Lib/test/test_generated_cases.py
@@ -0,0 +1,537 @@
+import tempfile
+import unittest
+import os
+
+from test import test_tools
+
+test_tools.skip_if_missing('cases_generator')
+with test_tools.imports_under_tool('cases_generator'):
+ import generate_cases
+ from parser import StackEffect
+
+
+class TestEffects(unittest.TestCase):
+ def test_effect_sizes(self):
+ input_effects = [
+ x := StackEffect("x", "", "", ""),
+ y := StackEffect("y", "", "", "oparg"),
+ z := StackEffect("z", "", "", "oparg*2"),
+ ]
+ output_effects = [
+ StackEffect("a", "", "", ""),
+ StackEffect("b", "", "", "oparg*4"),
+ StackEffect("c", "", "", ""),
+ ]
+ other_effects = [
+ StackEffect("p", "", "", "oparg<<1"),
+ StackEffect("q", "", "", ""),
+ StackEffect("r", "", "", ""),
+ ]
+ self.assertEqual(generate_cases.effect_size(x), (1, ""))
+ self.assertEqual(generate_cases.effect_size(y), (0, "oparg"))
+ self.assertEqual(generate_cases.effect_size(z), (0, "oparg*2"))
+
+ self.assertEqual(
+ generate_cases.list_effect_size(input_effects),
+ (1, "oparg + oparg*2"),
+ )
+ self.assertEqual(
+ generate_cases.list_effect_size(output_effects),
+ (2, "oparg*4"),
+ )
+ self.assertEqual(
+ generate_cases.list_effect_size(other_effects),
+ (2, "(oparg<<1)"),
+ )
+
+ self.assertEqual(
+ generate_cases.string_effect_size(
+ generate_cases.list_effect_size(input_effects),
+ ), "1 + oparg + oparg*2",
+ )
+ self.assertEqual(
+ generate_cases.string_effect_size(
+ generate_cases.list_effect_size(output_effects),
+ ),
+ "2 + oparg*4",
+ )
+ self.assertEqual(
+ generate_cases.string_effect_size(
+ generate_cases.list_effect_size(other_effects),
+ ),
+ "2 + (oparg<<1)",
+ )
+
+
+class TestGeneratedCases(unittest.TestCase):
+ def setUp(self) -> None:
+ super().setUp()
+
+ self.temp_dir = tempfile.gettempdir()
+ self.temp_input_filename = os.path.join(self.temp_dir, "input.txt")
+ self.temp_output_filename = os.path.join(self.temp_dir, "output.txt")
+ self.temp_metadata_filename = os.path.join(self.temp_dir, "metadata.txt")
+ self.temp_pymetadata_filename = os.path.join(self.temp_dir, "pymetadata.txt")
+ self.temp_executor_filename = os.path.join(self.temp_dir, "executor.txt")
+
+ def tearDown(self) -> None:
+ for filename in [
+ self.temp_input_filename,
+ self.temp_output_filename,
+ self.temp_metadata_filename,
+ self.temp_pymetadata_filename,
+ self.temp_executor_filename,
+ ]:
+ try:
+ os.remove(filename)
+ except:
+ pass
+ super().tearDown()
+
+ def run_cases_test(self, input: str, expected: str):
+ with open(self.temp_input_filename, "w+") as temp_input:
+ temp_input.write(generate_cases.BEGIN_MARKER)
+ temp_input.write(input)
+ temp_input.write(generate_cases.END_MARKER)
+ temp_input.flush()
+
+ a = generate_cases.Analyzer(
+ [self.temp_input_filename],
+ self.temp_output_filename,
+ self.temp_metadata_filename,
+ self.temp_pymetadata_filename,
+ self.temp_executor_filename,
+ )
+ a.parse()
+ a.analyze()
+ if a.errors:
+ raise RuntimeError(f"Found {a.errors} errors")
+ a.write_instructions()
+
+ with open(self.temp_output_filename) as temp_output:
+ lines = temp_output.readlines()
+ while lines and lines[0].startswith("// "):
+ lines.pop(0)
+ actual = "".join(lines)
+ # if actual.rstrip() != expected.rstrip():
+ # print("Actual:")
+ # print(actual)
+ # print("Expected:")
+ # print(expected)
+ # print("End")
+
+ self.assertEqual(actual.rstrip(), expected.rstrip())
+
+ def test_inst_no_args(self):
+ input = """
+ inst(OP, (--)) {
+ spam();
+ }
+ """
+ output = """
+ TARGET(OP) {
+ spam();
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_inst_one_pop(self):
+ input = """
+ inst(OP, (value --)) {
+ spam();
+ }
+ """
+ output = """
+ TARGET(OP) {
+ PyObject *value = stack_pointer[-1];
+ spam();
+ STACK_SHRINK(1);
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_inst_one_push(self):
+ input = """
+ inst(OP, (-- res)) {
+ spam();
+ }
+ """
+ output = """
+ TARGET(OP) {
+ PyObject *res;
+ spam();
+ STACK_GROW(1);
+ stack_pointer[-1] = res;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_inst_one_push_one_pop(self):
+ input = """
+ inst(OP, (value -- res)) {
+ spam();
+ }
+ """
+ output = """
+ TARGET(OP) {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ spam();
+ stack_pointer[-1] = res;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_binary_op(self):
+ input = """
+ inst(OP, (left, right -- res)) {
+ spam();
+ }
+ """
+ output = """
+ TARGET(OP) {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ spam();
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_overlap(self):
+ input = """
+ inst(OP, (left, right -- left, result)) {
+ spam();
+ }
+ """
+ output = """
+ TARGET(OP) {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *result;
+ spam();
+ stack_pointer[-1] = result;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_predictions_and_eval_breaker(self):
+ input = """
+ inst(OP1, (--)) {
+ }
+ inst(OP3, (arg -- res)) {
+ DEOPT_IF(xxx, OP1);
+ CHECK_EVAL_BREAKER();
+ }
+ """
+ output = """
+ TARGET(OP1) {
+ PREDICTED(OP1);
+ DISPATCH();
+ }
+
+ TARGET(OP3) {
+ PyObject *arg = stack_pointer[-1];
+ PyObject *res;
+ DEOPT_IF(xxx, OP1);
+ stack_pointer[-1] = res;
+ CHECK_EVAL_BREAKER();
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_error_if_plain(self):
+ input = """
+ inst(OP, (--)) {
+ ERROR_IF(cond, label);
+ }
+ """
+ output = """
+ TARGET(OP) {
+ if (cond) goto label;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_error_if_plain_with_comment(self):
+ input = """
+ inst(OP, (--)) {
+ ERROR_IF(cond, label); // Comment is ok
+ }
+ """
+ output = """
+ TARGET(OP) {
+ if (cond) goto label;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_error_if_pop(self):
+ input = """
+ inst(OP, (left, right -- res)) {
+ ERROR_IF(cond, label);
+ }
+ """
+ output = """
+ TARGET(OP) {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ if (cond) goto pop_2_label;
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_cache_effect(self):
+ input = """
+ inst(OP, (counter/1, extra/2, value --)) {
+ }
+ """
+ output = """
+ TARGET(OP) {
+ PyObject *value = stack_pointer[-1];
+ uint16_t counter = read_u16(&next_instr[0].cache);
+ uint32_t extra = read_u32(&next_instr[1].cache);
+ STACK_SHRINK(1);
+ next_instr += 3;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_suppress_dispatch(self):
+ input = """
+ inst(OP, (--)) {
+ goto somewhere;
+ }
+ """
+ output = """
+ TARGET(OP) {
+ goto somewhere;
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_macro_instruction(self):
+ input = """
+ inst(OP1, (counter/1, left, right -- left, right)) {
+ op1(left, right);
+ }
+ op(OP2, (extra/2, arg2, left, right -- res)) {
+ res = op2(arg2, left, right);
+ }
+ macro(OP) = OP1 + cache/2 + OP2;
+ inst(OP3, (unused/5, arg2, left, right -- res)) {
+ res = op3(arg2, left, right);
+ }
+ family(OP, INLINE_CACHE_ENTRIES_OP) = { OP3 };
+ """
+ output = """
+ TARGET(OP1) {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ uint16_t counter = read_u16(&next_instr[0].cache);
+ op1(left, right);
+ next_instr += 1;
+ DISPATCH();
+ }
+
+ TARGET(OP) {
+ PyObject *_tmp_1 = stack_pointer[-1];
+ PyObject *_tmp_2 = stack_pointer[-2];
+ PyObject *_tmp_3 = stack_pointer[-3];
+ {
+ PyObject *right = _tmp_1;
+ PyObject *left = _tmp_2;
+ uint16_t counter = read_u16(&next_instr[0].cache);
+ op1(left, right);
+ _tmp_2 = left;
+ _tmp_1 = right;
+ }
+ {
+ PyObject *right = _tmp_1;
+ PyObject *left = _tmp_2;
+ PyObject *arg2 = _tmp_3;
+ PyObject *res;
+ uint32_t extra = read_u32(&next_instr[3].cache);
+ res = op2(arg2, left, right);
+ _tmp_3 = res;
+ }
+ next_instr += 5;
+ static_assert(INLINE_CACHE_ENTRIES_OP == 5, "incorrect cache size");
+ STACK_SHRINK(2);
+ stack_pointer[-1] = _tmp_3;
+ DISPATCH();
+ }
+
+ TARGET(OP3) {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *arg2 = stack_pointer[-3];
+ PyObject *res;
+ res = op3(arg2, left, right);
+ STACK_SHRINK(2);
+ stack_pointer[-1] = res;
+ next_instr += 5;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_array_input(self):
+ input = """
+ inst(OP, (below, values[oparg*2], above --)) {
+ spam();
+ }
+ """
+ output = """
+ TARGET(OP) {
+ PyObject *above = stack_pointer[-1];
+ PyObject **values = (stack_pointer - (1 + oparg*2));
+ PyObject *below = stack_pointer[-(2 + oparg*2)];
+ spam();
+ STACK_SHRINK(oparg*2);
+ STACK_SHRINK(2);
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_array_output(self):
+ input = """
+ inst(OP, (unused, unused -- below, values[oparg*3], above)) {
+ spam(values, oparg);
+ }
+ """
+ output = """
+ TARGET(OP) {
+ PyObject *below;
+ PyObject **values = stack_pointer - (2) + 1;
+ PyObject *above;
+ spam(values, oparg);
+ STACK_GROW(oparg*3);
+ stack_pointer[-1] = above;
+ stack_pointer[-(2 + oparg*3)] = below;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_array_input_output(self):
+ input = """
+ inst(OP, (values[oparg] -- values[oparg], above)) {
+ spam(values, oparg);
+ }
+ """
+ output = """
+ TARGET(OP) {
+ PyObject **values = (stack_pointer - oparg);
+ PyObject *above;
+ spam(values, oparg);
+ STACK_GROW(1);
+ stack_pointer[-1] = above;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_array_error_if(self):
+ input = """
+ inst(OP, (extra, values[oparg] --)) {
+ ERROR_IF(oparg == 0, somewhere);
+ }
+ """
+ output = """
+ TARGET(OP) {
+ PyObject **values = (stack_pointer - oparg);
+ PyObject *extra = stack_pointer[-(1 + oparg)];
+ if (oparg == 0) { STACK_SHRINK(oparg); goto pop_1_somewhere; }
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_cond_effect(self):
+ input = """
+ inst(OP, (aa, input if ((oparg & 1) == 1), cc -- xx, output if (oparg & 2), zz)) {
+ output = spam(oparg, input);
+ }
+ """
+ output = """
+ TARGET(OP) {
+ PyObject *cc = stack_pointer[-1];
+ PyObject *input = ((oparg & 1) == 1) ? stack_pointer[-(1 + (((oparg & 1) == 1) ? 1 : 0))] : NULL;
+ PyObject *aa = stack_pointer[-(2 + (((oparg & 1) == 1) ? 1 : 0))];
+ PyObject *xx;
+ PyObject *output = NULL;
+ PyObject *zz;
+ output = spam(oparg, input);
+ STACK_SHRINK((((oparg & 1) == 1) ? 1 : 0));
+ STACK_GROW(((oparg & 2) ? 1 : 0));
+ stack_pointer[-1] = zz;
+ if (oparg & 2) { stack_pointer[-(1 + ((oparg & 2) ? 1 : 0))] = output; }
+ stack_pointer[-(2 + ((oparg & 2) ? 1 : 0))] = xx;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+ def test_macro_cond_effect(self):
+ input = """
+ op(A, (left, middle, right --)) {
+ # Body of A
+ }
+ op(B, (-- deep, extra if (oparg), res)) {
+ # Body of B
+ }
+ macro(M) = A + B;
+ """
+ output = """
+ TARGET(M) {
+ PyObject *_tmp_1 = stack_pointer[-1];
+ PyObject *_tmp_2 = stack_pointer[-2];
+ PyObject *_tmp_3 = stack_pointer[-3];
+ {
+ PyObject *right = _tmp_1;
+ PyObject *middle = _tmp_2;
+ PyObject *left = _tmp_3;
+ # Body of A
+ }
+ {
+ PyObject *deep;
+ PyObject *extra = NULL;
+ PyObject *res;
+ # Body of B
+ _tmp_3 = deep;
+ if (oparg) { _tmp_2 = extra; }
+ _tmp_1 = res;
+ }
+ STACK_SHRINK(1);
+ STACK_GROW((oparg ? 1 : 0));
+ stack_pointer[-1] = _tmp_1;
+ if (oparg) { stack_pointer[-2] = _tmp_2; }
+ stack_pointer[-3] = _tmp_3;
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py
index 24d4216417521c..bf600a0f4d1834 100644
--- a/Lib/test/test_genericalias.py
+++ b/Lib/test/test_genericalias.py
@@ -209,6 +209,9 @@ class MyList(list):
def test_repr(self):
class MyList(list):
pass
+ class MyGeneric:
+ __class_getitem__ = classmethod(GenericAlias)
+
self.assertEqual(repr(list[str]), 'list[str]')
self.assertEqual(repr(list[()]), 'list[()]')
self.assertEqual(repr(tuple[int, ...]), 'tuple[int, ...]')
@@ -221,6 +224,11 @@ class MyList(list):
self.assertTrue(repr(MyList[int]).endswith('.BaseTest.test_repr..MyList[int]'))
self.assertEqual(repr(list[str]()), '[]') # instances should keep their normal repr
+ # gh-105488
+ self.assertTrue(repr(MyGeneric[int]).endswith('MyGeneric[int]'))
+ self.assertTrue(repr(MyGeneric[[]]).endswith('MyGeneric[[]]'))
+ self.assertTrue(repr(MyGeneric[[int, str]]).endswith('MyGeneric[[int, str]]'))
+
def test_exposed_type(self):
import types
a = types.GenericAlias(list, int)
diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py
index 6de413e5056ef0..b06b3b09411d62 100644
--- a/Lib/test/test_gzip.py
+++ b/Lib/test/test_gzip.py
@@ -16,6 +16,7 @@
from test.support.script_helper import assert_python_ok, assert_python_failure
gzip = import_helper.import_module('gzip')
+zlib = import_helper.import_module('zlib')
data1 = b""" int length=DEFAULTALLOC, err = Z_OK;
PyObject *RetVal;
@@ -616,6 +617,54 @@ def test_issue44439(self):
self.assertEqual(f.write(q), LENGTH)
self.assertEqual(f.tell(), LENGTH)
+ def test_flush_flushes_compressor(self):
+ # See issue GH-105808.
+ b = io.BytesIO()
+ message = b"important message here."
+ with gzip.GzipFile(fileobj=b, mode='w') as f:
+ f.write(message)
+ f.flush()
+ partial_data = b.getvalue()
+ full_data = b.getvalue()
+ self.assertEqual(gzip.decompress(full_data), message)
+ # The partial data should contain the gzip header and the complete
+ # message, but not the end-of-stream markers (so we can't just
+ # decompress it directly).
+ with self.assertRaises(EOFError):
+ gzip.decompress(partial_data)
+ d = zlib.decompressobj(wbits=-zlib.MAX_WBITS)
+ f = io.BytesIO(partial_data)
+ gzip._read_gzip_header(f)
+ read_message = d.decompress(f.read())
+ self.assertEqual(read_message, message)
+
+ def test_flush_modes(self):
+ # Make sure the argument to flush is properly passed to the
+ # zlib.compressobj; see issue GH-105808.
+ class FakeCompressor:
+ def __init__(self):
+ self.modes = []
+ def compress(self, data):
+ return b''
+ def flush(self, mode=-1):
+ self.modes.append(mode)
+ return b''
+ b = io.BytesIO()
+ fc = FakeCompressor()
+ with gzip.GzipFile(fileobj=b, mode='w') as f:
+ f.compress = fc
+ f.flush()
+ f.flush(50)
+ f.flush(zlib_mode=100)
+ # The implicit close will also flush the compressor.
+ expected_modes = [
+ zlib.Z_SYNC_FLUSH,
+ 50,
+ 100,
+ -1,
+ ]
+ self.assertEqual(fc.modes, expected_modes)
+
class TestOpen(BaseTest):
def test_binary_modes(self):
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
index 8955d45fa93dd4..fe8105ee2bb3fa 100644
--- a/Lib/test/test_httplib.py
+++ b/Lib/test/test_httplib.py
@@ -2404,6 +2404,19 @@ def test_proxy_response_headers(self):
headers = self.conn.get_proxy_response_headers()
self.assertIn(expected_header, headers.items())
+ def test_no_proxy_response_headers(self):
+ expected_header = ('X-Dummy', '1')
+ response_text = (
+ 'HTTP/1.0 200 OK\r\n'
+ '{0}\r\n\r\n'.format(':'.join(expected_header))
+ )
+
+ self.conn._create_connection = self._create_connection(response_text)
+
+ self.conn.request('PUT', '/', '')
+ headers = self.conn.get_proxy_response_headers()
+ self.assertIsNone(headers)
+
def test_tunnel_leak(self):
sock = None
diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py
index cdd1bea754a020..cfd8a101dcc1c1 100644
--- a/Lib/test/test_httpservers.py
+++ b/Lib/test/test_httpservers.py
@@ -442,10 +442,10 @@ def test_undecodable_filename(self):
def test_undecodable_parameter(self):
# sanity check using a valid parameter
response = self.request(self.base_url + '/?x=123').read()
- self.assertRegex(response, f'listing for {self.base_url}/\?x=123'.encode('latin1'))
+ self.assertRegex(response, rf'listing for {self.base_url}/\?x=123'.encode('latin1'))
# now the bogus encoding
response = self.request(self.base_url + '/?x=%bb').read()
- self.assertRegex(response, f'listing for {self.base_url}/\?x=\xef\xbf\xbd'.encode('latin1'))
+ self.assertRegex(response, rf'listing for {self.base_url}/\?x=\xef\xbf\xbd'.encode('latin1'))
def test_get_dir_redirect_location_domain_injection_bug(self):
"""Ensure //evil.co/..%2f../../X does not put //evil.co/ in Location.
diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py
index 60f5b671b1da48..2b2f1f76d26db3 100644
--- a/Lib/test/test_imaplib.py
+++ b/Lib/test/test_imaplib.py
@@ -965,100 +965,5 @@ def test_ssl_verified(self):
client.shutdown()
-@unittest.skipUnless(
- support.is_resource_enabled('network'), 'network resource disabled')
-@unittest.skip('cyrus.andrew.cmu.edu blocks connections')
-class RemoteIMAPTest(unittest.TestCase):
- host = 'cyrus.andrew.cmu.edu'
- port = 143
- username = 'anonymous'
- password = 'pass'
- imap_class = imaplib.IMAP4
-
- def setUp(self):
- with socket_helper.transient_internet(self.host):
- self.server = self.imap_class(self.host, self.port)
-
- def tearDown(self):
- if self.server is not None:
- with socket_helper.transient_internet(self.host):
- self.server.logout()
-
- def test_logincapa(self):
- with socket_helper.transient_internet(self.host):
- for cap in self.server.capabilities:
- self.assertIsInstance(cap, str)
- self.assertIn('LOGINDISABLED', self.server.capabilities)
- self.assertIn('AUTH=ANONYMOUS', self.server.capabilities)
- rs = self.server.login(self.username, self.password)
- self.assertEqual(rs[0], 'OK')
-
- def test_logout(self):
- with socket_helper.transient_internet(self.host):
- rs = self.server.logout()
- self.server = None
- self.assertEqual(rs[0], 'BYE', rs)
-
-
-@unittest.skipUnless(ssl, "SSL not available")
-@unittest.skipUnless(
- support.is_resource_enabled('network'), 'network resource disabled')
-@unittest.skip('cyrus.andrew.cmu.edu blocks connections')
-class RemoteIMAP_STARTTLSTest(RemoteIMAPTest):
-
- def setUp(self):
- super().setUp()
- with socket_helper.transient_internet(self.host):
- rs = self.server.starttls()
- self.assertEqual(rs[0], 'OK')
-
- def test_logincapa(self):
- for cap in self.server.capabilities:
- self.assertIsInstance(cap, str)
- self.assertNotIn('LOGINDISABLED', self.server.capabilities)
-
-
-@unittest.skipUnless(ssl, "SSL not available")
-@unittest.skip('cyrus.andrew.cmu.edu blocks connections')
-class RemoteIMAP_SSLTest(RemoteIMAPTest):
- port = 993
- imap_class = IMAP4_SSL
-
- def setUp(self):
- pass
-
- def tearDown(self):
- pass
-
- def create_ssl_context(self):
- ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
- ssl_context.check_hostname = False
- ssl_context.verify_mode = ssl.CERT_NONE
- ssl_context.load_cert_chain(CERTFILE)
- return ssl_context
-
- def check_logincapa(self, server):
- try:
- for cap in server.capabilities:
- self.assertIsInstance(cap, str)
- self.assertNotIn('LOGINDISABLED', server.capabilities)
- self.assertIn('AUTH=PLAIN', server.capabilities)
- rs = server.login(self.username, self.password)
- self.assertEqual(rs[0], 'OK')
- finally:
- server.logout()
-
- def test_logincapa(self):
- with socket_helper.transient_internet(self.host):
- _server = self.imap_class(self.host, self.port)
- self.check_logincapa(_server)
-
- def test_logout(self):
- with socket_helper.transient_internet(self.host):
- _server = self.imap_class(self.host, self.port)
- rs = _server.logout()
- self.assertEqual(rs[0], 'BYE', rs)
-
-
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py
index 227c912bc8c322..ec8ccf0bd78d37 100644
--- a/Lib/test/test_import/__init__.py
+++ b/Lib/test/test_import/__init__.py
@@ -23,6 +23,7 @@
import unittest
from unittest import mock
import _testinternalcapi
+import _imp
from test.support import os_helper
from test.support import (
@@ -106,6 +107,25 @@ def remove_files(name):
rmtree('__pycache__')
+def no_rerun(reason):
+ """Skip rerunning for a particular test.
+
+ WARNING: Use this decorator with care; skipping rerunning makes it
+ impossible to find reference leaks. Provide a clear reason for skipping the
+ test using the 'reason' parameter.
+ """
+ def deco(func):
+ _has_run = False
+ def wrapper(self):
+ nonlocal _has_run
+ if _has_run:
+ self.skipTest(reason)
+ func(self)
+ _has_run = True
+ return wrapper
+ return deco
+
+
@contextlib.contextmanager
def _ready_to_import(name=None, source=""):
# sets up a temporary directory and removes it
@@ -763,6 +783,13 @@ def test_dll_dependency_import(self):
env=env,
cwd=os.path.dirname(pyexe))
+ def test_issue105979(self):
+ # this used to crash
+ with self.assertRaises(ImportError) as cm:
+ _imp.get_frozen_object("x", b"6\'\xd5Cu\x12")
+ self.assertIn("Frozen object named 'x' is invalid",
+ str(cm.exception))
+
@skip_if_dont_write_bytecode
class FilePermissionTests(unittest.TestCase):
@@ -1640,9 +1667,10 @@ class SubinterpImportTests(unittest.TestCase):
)
ISOLATED = dict(
use_main_obmalloc=False,
- own_gil=True,
+ gil=2,
)
NOT_ISOLATED = {k: not v for k, v in ISOLATED.items()}
+ NOT_ISOLATED['gil'] = 1
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
def pipe(self):
@@ -1980,10 +2008,6 @@ class SinglephaseInitTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
- if '-R' in sys.argv or '--huntrleaks' in sys.argv:
- # https://github.com/python/cpython/issues/102251
- raise unittest.SkipTest('unresolved refleaks (see gh-102251)')
-
spec = importlib.util.find_spec(cls.NAME)
from importlib.machinery import ExtensionFileLoader
cls.FILE = spec.origin
@@ -2493,6 +2517,7 @@ def test_basic_multiple_interpreters_main_no_reset(self):
# * m_copy was copied from interp2 (was from interp1)
# * module's global state was updated, not reset
+ @no_rerun(reason="rerun not possible; module state is never cleared (see gh-102251)")
@requires_subinterpreters
def test_basic_multiple_interpreters_deleted_no_reset(self):
# without resetting; already loaded in a deleted interpreter
@@ -2620,6 +2645,30 @@ def test_basic_multiple_interpreters_reset_each(self):
# * module's global state was initialized, not reset
+@cpython_only
+class CAPITests(unittest.TestCase):
+ def test_pyimport_addmodule(self):
+ # gh-105922: Test PyImport_AddModuleRef(), PyImport_AddModule()
+ # and PyImport_AddModuleObject()
+ import _testcapi
+ for name in (
+ 'sys', # frozen module
+ 'test', # package
+ __name__, # package.module
+ ):
+ _testcapi.check_pyimport_addmodule(name)
+
+ def test_pyimport_addmodule_create(self):
+ # gh-105922: Test PyImport_AddModuleRef(), create a new module
+ import _testcapi
+ name = 'dontexist'
+ self.assertNotIn(name, sys.modules)
+ self.addCleanup(unload, name)
+
+ mod = _testcapi.check_pyimport_addmodule(name)
+ self.assertIs(mod, sys.modules[name])
+
+
if __name__ == '__main__':
# Test needs to be a package, so we can do relative imports.
unittest.main()
diff --git a/Lib/test/test_importlib/test_main.py b/Lib/test/test_importlib/test_main.py
index 6469aad7130fce..3b49227255eb58 100644
--- a/Lib/test/test_importlib/test_main.py
+++ b/Lib/test/test_importlib/test_main.py
@@ -68,7 +68,7 @@ def test_abc_enforced(self):
dict(name=''),
)
def test_invalid_inputs_to_from_name(self, name):
- with self.assertRaises(Exception):
+ with self.assertRaises(ValueError):
Distribution.from_name(name)
diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py
index e967adc9451c81..5da72a21f586ee 100644
--- a/Lib/test/test_importlib/test_util.py
+++ b/Lib/test/test_importlib/test_util.py
@@ -655,7 +655,7 @@ def test_magic_number(self):
@unittest.skipIf(_interpreters is None, 'subinterpreters required')
class IncompatibleExtensionModuleRestrictionsTests(unittest.TestCase):
- ERROR = re.compile("^: module (.*) does not support loading in subinterpreters")
+ ERROR = re.compile("^ImportError: module (.*) does not support loading in subinterpreters")
def run_with_own_gil(self, script):
interpid = _interpreters.create(isolated=True)
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index d89953ab60f022..64afeec351b353 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -596,9 +596,40 @@ def test_finddoc(self):
self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
self.assertEqual(finddoc(int.real), int.real.__doc__)
+ cleandoc_testdata = [
+ # first line should have different margin
+ (' An\n indented\n docstring.', 'An\nindented\n docstring.'),
+ # trailing whitespace are not removed.
+ (' An \n \n indented \n docstring. ',
+ 'An \n \nindented \n docstring. '),
+ # NUL is not termination.
+ ('doc\0string\n\n second\0line\n third\0line\0',
+ 'doc\0string\n\nsecond\0line\nthird\0line\0'),
+ # first line is lstrip()-ped. other lines are kept when no margin.[w:
+ (' ', ''),
+ # compiler.cleandoc() doesn't strip leading/trailing newlines
+ # to keep maximum backward compatibility.
+ # inspect.cleandoc() removes them.
+ ('\n\n\n first paragraph\n\n second paragraph\n\n',
+ '\n\n\nfirst paragraph\n\n second paragraph\n\n'),
+ (' \n \n \n ', '\n \n \n '),
+ ]
+
def test_cleandoc(self):
- self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
- 'An\nindented\ndocstring.')
+ func = inspect.cleandoc
+ for i, (input, expected) in enumerate(self.cleandoc_testdata):
+ # only inspect.cleandoc() strip \n
+ expected = expected.strip('\n')
+ with self.subTest(i=i):
+ self.assertEqual(func(input), expected)
+
+ @cpython_only
+ def test_c_cleandoc(self):
+ import _testinternalcapi
+ func = _testinternalcapi.compiler_cleandoc
+ for i, (input, expected) in enumerate(self.cleandoc_testdata):
+ with self.subTest(i=i):
+ self.assertEqual(func(input), expected)
def test_getcomments(self):
self.assertEqual(inspect.getcomments(mod), '# line 1\n')
diff --git a/Lib/test/test_json/__init__.py b/Lib/test/test_json/__init__.py
index 37b2e0d5e26d16..74b64ed86a3183 100644
--- a/Lib/test/test_json/__init__.py
+++ b/Lib/test/test_json/__init__.py
@@ -18,7 +18,6 @@ class PyTest(unittest.TestCase):
json = pyjson
loads = staticmethod(pyjson.loads)
dumps = staticmethod(pyjson.dumps)
- AttrDict = pyjson.AttrDict
JSONDecodeError = staticmethod(pyjson.JSONDecodeError)
@unittest.skipUnless(cjson, 'requires _json')
diff --git a/Lib/test/test_json/test_attrdict.py b/Lib/test/test_json/test_attrdict.py
deleted file mode 100644
index 143ea462d310aa..00000000000000
--- a/Lib/test/test_json/test_attrdict.py
+++ /dev/null
@@ -1,145 +0,0 @@
-from test.test_json import PyTest
-import pickle
-import sys
-import unittest
-
-kepler_dict = {
- "orbital_period": {
- "mercury": 88,
- "venus": 225,
- "earth": 365,
- "mars": 687,
- "jupiter": 4331,
- "saturn": 10_756,
- "uranus": 30_687,
- "neptune": 60_190,
- },
- "dist_from_sun": {
- "mercury": 58,
- "venus": 108,
- "earth": 150,
- "mars": 228,
- "jupiter": 778,
- "saturn": 1_400,
- "uranus": 2_900,
- "neptune": 4_500,
- }
-}
-
-class TestAttrDict(PyTest):
-
- def test_dict_subclass(self):
- self.assertTrue(issubclass(self.AttrDict, dict))
-
- def test_slots(self):
- d = self.AttrDict(x=1, y=2)
- with self.assertRaises(TypeError):
- vars(d)
-
- def test_constructor_signatures(self):
- AttrDict = self.AttrDict
- target = dict(x=1, y=2)
- self.assertEqual(AttrDict(x=1, y=2), target) # kwargs
- self.assertEqual(AttrDict(dict(x=1, y=2)), target) # mapping
- self.assertEqual(AttrDict(dict(x=1, y=0), y=2), target) # mapping, kwargs
- self.assertEqual(AttrDict([('x', 1), ('y', 2)]), target) # iterable
- self.assertEqual(AttrDict([('x', 1), ('y', 0)], y=2), target) # iterable, kwargs
-
- def test_getattr(self):
- d = self.AttrDict(x=1, y=2)
- self.assertEqual(d.x, 1)
- with self.assertRaises(AttributeError):
- d.z
-
- def test_setattr(self):
- d = self.AttrDict(x=1, y=2)
- d.x = 3
- d.z = 5
- self.assertEqual(d, dict(x=3, y=2, z=5))
-
- def test_delattr(self):
- d = self.AttrDict(x=1, y=2)
- del d.x
- self.assertEqual(d, dict(y=2))
- with self.assertRaises(AttributeError):
- del d.z
-
- def test_dir(self):
- d = self.AttrDict(x=1, y=2)
- self.assertTrue(set(dir(d)), set(dir(dict)).union({'x', 'y'}))
-
- def test_repr(self):
- # This repr is doesn't round-trip. It matches a regular dict.
- # That seems to be the norm for AttrDict recipes being used
- # in the wild. Also it supports the design concept that an
- # AttrDict is just like a regular dict but has optional
- # attribute style lookup.
- self.assertEqual(repr(self.AttrDict(x=1, y=2)),
- repr(dict(x=1, y=2)))
-
- def test_overlapping_keys_and_methods(self):
- d = self.AttrDict(items=50)
- self.assertEqual(d['items'], 50)
- self.assertEqual(d.items(), dict(d).items())
-
- def test_invalid_attribute_names(self):
- d = self.AttrDict({
- 'control': 'normal case',
- 'class': 'keyword',
- 'two words': 'contains space',
- 'hypen-ate': 'contains a hyphen'
- })
- self.assertEqual(d.control, dict(d)['control'])
- self.assertEqual(d['class'], dict(d)['class'])
- self.assertEqual(d['two words'], dict(d)['two words'])
- self.assertEqual(d['hypen-ate'], dict(d)['hypen-ate'])
-
- def test_object_hook_use_case(self):
- AttrDict = self.AttrDict
- json_string = self.dumps(kepler_dict)
- kepler_ad = self.loads(json_string, object_hook=AttrDict)
-
- self.assertEqual(kepler_ad, kepler_dict) # Match regular dict
- self.assertIsInstance(kepler_ad, AttrDict) # Verify conversion
- self.assertIsInstance(kepler_ad.orbital_period, AttrDict) # Nested
-
- # Exercise dotted lookups
- self.assertEqual(kepler_ad.orbital_period, kepler_dict['orbital_period'])
- self.assertEqual(kepler_ad.orbital_period.earth,
- kepler_dict['orbital_period']['earth'])
- self.assertEqual(kepler_ad['orbital_period'].earth,
- kepler_dict['orbital_period']['earth'])
-
- # Dict style error handling and Attribute style error handling
- with self.assertRaises(KeyError):
- kepler_ad.orbital_period['pluto']
- with self.assertRaises(AttributeError):
- kepler_ad.orbital_period.Pluto
-
- # Order preservation
- self.assertEqual(list(kepler_ad.items()), list(kepler_dict.items()))
- self.assertEqual(list(kepler_ad.orbital_period.items()),
- list(kepler_dict['orbital_period'].items()))
-
- # Round trip
- self.assertEqual(self.dumps(kepler_ad), json_string)
-
- def test_pickle(self):
- AttrDict = self.AttrDict
- json_string = self.dumps(kepler_dict)
- kepler_ad = self.loads(json_string, object_hook=AttrDict)
-
- # Pickling requires the cached module to be the real module
- cached_module = sys.modules.get('json')
- sys.modules['json'] = self.json
- try:
- for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
- kepler_ad2 = pickle.loads(pickle.dumps(kepler_ad, protocol))
- self.assertEqual(kepler_ad2, kepler_ad)
- self.assertEqual(type(kepler_ad2), AttrDict)
- finally:
- sys.modules['json'] = cached_module
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/Lib/test/test_listcomps.py b/Lib/test/test_listcomps.py
index c2cf058c321fa5..9f28ced32bd26c 100644
--- a/Lib/test/test_listcomps.py
+++ b/Lib/test/test_listcomps.py
@@ -539,6 +539,28 @@ def b():
self._check_in_scopes(code, {"x": True, "y": ["b"]}, scopes=["function"])
self._check_in_scopes(code, raises=NameError, scopes=["class"])
+ def test_iter_var_available_in_locals(self):
+ code = """
+ l = [1, 2]
+ y = 0
+ items = [locals()["x"] for x in l]
+ items2 = [vars()["x"] for x in l]
+ items3 = [("x" in dir()) for x in l]
+ items4 = [eval("x") for x in l]
+ # x is available, and does not overwrite y
+ [exec("y = x") for x in l]
+ """
+ self._check_in_scopes(
+ code,
+ {
+ "items": [1, 2],
+ "items2": [1, 2],
+ "items3": [True, True],
+ "items4": [1, 2],
+ "y": 0
+ }
+ )
+
__test__ = {'doctests' : doctests}
diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py
index 4c592eaf34da23..4977a9369ddf88 100644
--- a/Lib/test/test_mailbox.py
+++ b/Lib/test/test_mailbox.py
@@ -116,10 +116,13 @@ def test_add_nonascii_string_header_raises(self):
self.assertMailboxEmpty()
def test_add_that_raises_leaves_mailbox_empty(self):
+ class CustomError(Exception): ...
+ exc_msg = "a fake error"
+
def raiser(*args, **kw):
- raise Exception("a fake error")
+ raise CustomError(exc_msg)
support.patch(self, email.generator.BytesGenerator, 'flatten', raiser)
- with self.assertRaises(Exception):
+ with self.assertRaisesRegex(CustomError, exc_msg):
self._box.add(email.message_from_string("From: Alphöso"))
self.assertEqual(len(self._box), 0)
self._box.close()
diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py
index 517cbe0cb115ab..bab868600895c1 100644
--- a/Lib/test/test_mmap.py
+++ b/Lib/test/test_mmap.py
@@ -299,6 +299,27 @@ def test_find_end(self):
self.assertEqual(m.find(b'one', 1, -2), -1)
self.assertEqual(m.find(bytearray(b'one')), 0)
+ for i in range(-n-1, n+1):
+ for j in range(-n-1, n+1):
+ for p in [b"o", b"on", b"two", b"ones", b"s"]:
+ expected = data.find(p, i, j)
+ self.assertEqual(m.find(p, i, j), expected, (p, i, j))
+
+ def test_find_does_not_access_beyond_buffer(self):
+ try:
+ flags = mmap.MAP_PRIVATE | mmap.MAP_ANONYMOUS
+ PAGESIZE = mmap.PAGESIZE
+ PROT_NONE = 0
+ PROT_READ = mmap.PROT_READ
+ except AttributeError as e:
+ raise unittest.SkipTest("mmap flags unavailable") from e
+ for i in range(0, 2049):
+ with mmap.mmap(-1, PAGESIZE * (i + 1),
+ flags=flags, prot=PROT_NONE) as guard:
+ with mmap.mmap(-1, PAGESIZE * (i + 2048),
+ flags=flags, prot=PROT_READ) as fm:
+ fm.find(b"fo", -2)
+
def test_rfind(self):
# test the new 'end' parameter works as expected
diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py
index 57fed5d09fd7b8..564dc4745ae64e 100644
--- a/Lib/test/test_opcache.py
+++ b/Lib/test/test_opcache.py
@@ -1,4 +1,8 @@
+import dis
+import threading
+import types
import unittest
+from test.support import threading_helper
class TestLoadSuperAttrCache(unittest.TestCase):
@@ -452,6 +456,543 @@ def f():
self.assertFalse(f())
+class TestCallCache(unittest.TestCase):
+ def test_too_many_defaults_0(self):
+ def f():
+ pass
+
+ f.__defaults__ = (None,)
+ for _ in range(1025):
+ f()
+
+ def test_too_many_defaults_1(self):
+ def f(x):
+ pass
+
+ f.__defaults__ = (None, None)
+ for _ in range(1025):
+ f(None)
+ f()
+
+ def test_too_many_defaults_2(self):
+ def f(x, y):
+ pass
+
+ f.__defaults__ = (None, None, None)
+ for _ in range(1025):
+ f(None, None)
+ f(None)
+ f()
+
+
+@threading_helper.requires_working_threading()
+class TestRacesDoNotCrash(unittest.TestCase):
+ # Careful with these. Bigger numbers have a higher chance of catching bugs,
+ # but you can also burn through a *ton* of type/dict/function versions:
+ ITEMS = 1000
+ LOOPS = 4
+ WARMUPS = 2
+ WRITERS = 2
+
+ def assert_specialized(self, f, opname):
+ instructions = dis.get_instructions(f, adaptive=True)
+ opnames = {instruction.opname for instruction in instructions}
+ self.assertIn(opname, opnames)
+
+ def assert_races_do_not_crash(
+ self, opname, get_items, read, write, *, check_items=False
+ ):
+ # This might need a few dozen loops in some cases:
+ for _ in range(self.LOOPS):
+ items = get_items()
+ # Reset:
+ if check_items:
+ for item in items:
+ item.__code__ = item.__code__.replace()
+ else:
+ read.__code__ = read.__code__.replace()
+ # Specialize:
+ for _ in range(self.WARMUPS):
+ read(items)
+ if check_items:
+ for item in items:
+ self.assert_specialized(item, opname)
+ else:
+ self.assert_specialized(read, opname)
+ # Create writers:
+ writers = []
+ for _ in range(self.WRITERS):
+ writer = threading.Thread(target=write, args=[items])
+ writers.append(writer)
+ # Run:
+ for writer in writers:
+ writer.start()
+ read(items) # BOOM!
+ for writer in writers:
+ writer.join()
+
+ def test_binary_subscr_getitem(self):
+ def get_items():
+ class C:
+ __getitem__ = lambda self, item: None
+
+ items = []
+ for _ in range(self.ITEMS):
+ item = C()
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ try:
+ item[None]
+ except TypeError:
+ pass
+
+ def write(items):
+ for item in items:
+ try:
+ del item.__getitem__
+ except AttributeError:
+ pass
+ type(item).__getitem__ = lambda self, item: None
+
+ opname = "BINARY_SUBSCR_GETITEM"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_binary_subscr_list_int(self):
+ def get_items():
+ items = []
+ for _ in range(self.ITEMS):
+ item = [None]
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ try:
+ item[0]
+ except IndexError:
+ pass
+
+ def write(items):
+ for item in items:
+ item.clear()
+ item.append(None)
+
+ opname = "BINARY_SUBSCR_LIST_INT"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_for_iter_gen(self):
+ def get_items():
+ def g():
+ yield
+ yield
+
+ items = []
+ for _ in range(self.ITEMS):
+ item = g()
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ try:
+ for _ in item:
+ break
+ except ValueError:
+ pass
+
+ def write(items):
+ for item in items:
+ try:
+ for _ in item:
+ break
+ except ValueError:
+ pass
+
+ opname = "FOR_ITER_GEN"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_for_iter_list(self):
+ def get_items():
+ items = []
+ for _ in range(self.ITEMS):
+ item = [None]
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ for item in item:
+ break
+
+ def write(items):
+ for item in items:
+ item.clear()
+ item.append(None)
+
+ opname = "FOR_ITER_LIST"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_load_attr_class(self):
+ def get_items():
+ class C:
+ a = object()
+
+ items = []
+ for _ in range(self.ITEMS):
+ item = C
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ try:
+ item.a
+ except AttributeError:
+ pass
+
+ def write(items):
+ for item in items:
+ try:
+ del item.a
+ except AttributeError:
+ pass
+ item.a = object()
+
+ opname = "LOAD_ATTR_CLASS"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_load_attr_getattribute_overridden(self):
+ def get_items():
+ class C:
+ __getattribute__ = lambda self, name: None
+
+ items = []
+ for _ in range(self.ITEMS):
+ item = C()
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ try:
+ item.a
+ except AttributeError:
+ pass
+
+ def write(items):
+ for item in items:
+ try:
+ del item.__getattribute__
+ except AttributeError:
+ pass
+ type(item).__getattribute__ = lambda self, name: None
+
+ opname = "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_load_attr_instance_value(self):
+ def get_items():
+ class C:
+ pass
+
+ items = []
+ for _ in range(self.ITEMS):
+ item = C()
+ item.a = None
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ item.a
+
+ def write(items):
+ for item in items:
+ item.__dict__[None] = None
+
+ opname = "LOAD_ATTR_INSTANCE_VALUE"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_load_attr_method_lazy_dict(self):
+ def get_items():
+ class C(Exception):
+ m = lambda self: None
+
+ items = []
+ for _ in range(self.ITEMS):
+ item = C()
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ try:
+ item.m()
+ except AttributeError:
+ pass
+
+ def write(items):
+ for item in items:
+ try:
+ del item.m
+ except AttributeError:
+ pass
+ type(item).m = lambda self: None
+
+ opname = "LOAD_ATTR_METHOD_LAZY_DICT"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_load_attr_method_no_dict(self):
+ def get_items():
+ class C:
+ __slots__ = ()
+ m = lambda self: None
+
+ items = []
+ for _ in range(self.ITEMS):
+ item = C()
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ try:
+ item.m()
+ except AttributeError:
+ pass
+
+ def write(items):
+ for item in items:
+ try:
+ del item.m
+ except AttributeError:
+ pass
+ type(item).m = lambda self: None
+
+ opname = "LOAD_ATTR_METHOD_NO_DICT"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_load_attr_method_with_values(self):
+ def get_items():
+ class C:
+ m = lambda self: None
+
+ items = []
+ for _ in range(self.ITEMS):
+ item = C()
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ try:
+ item.m()
+ except AttributeError:
+ pass
+
+ def write(items):
+ for item in items:
+ try:
+ del item.m
+ except AttributeError:
+ pass
+ type(item).m = lambda self: None
+
+ opname = "LOAD_ATTR_METHOD_WITH_VALUES"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_load_attr_module(self):
+ def get_items():
+ items = []
+ for _ in range(self.ITEMS):
+ item = types.ModuleType("- ")
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ try:
+ item.__name__
+ except AttributeError:
+ pass
+
+ def write(items):
+ for item in items:
+ d = item.__dict__.copy()
+ item.__dict__.clear()
+ item.__dict__.update(d)
+
+ opname = "LOAD_ATTR_MODULE"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_load_attr_property(self):
+ def get_items():
+ class C:
+ a = property(lambda self: None)
+
+ items = []
+ for _ in range(self.ITEMS):
+ item = C()
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ try:
+ item.a
+ except AttributeError:
+ pass
+
+ def write(items):
+ for item in items:
+ try:
+ del type(item).a
+ except AttributeError:
+ pass
+ type(item).a = property(lambda self: None)
+
+ opname = "LOAD_ATTR_PROPERTY"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_load_attr_with_hint(self):
+ def get_items():
+ class C:
+ pass
+
+ items = []
+ for _ in range(self.ITEMS):
+ item = C()
+ item.__dict__
+ item.a = None
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ item.a
+
+ def write(items):
+ for item in items:
+ item.__dict__[None] = None
+
+ opname = "LOAD_ATTR_WITH_HINT"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_load_global_module(self):
+ def get_items():
+ items = []
+ for _ in range(self.ITEMS):
+ item = eval("lambda: x", {"x": None})
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ item()
+
+ def write(items):
+ for item in items:
+ item.__globals__[None] = None
+
+ opname = "LOAD_GLOBAL_MODULE"
+ self.assert_races_do_not_crash(
+ opname, get_items, read, write, check_items=True
+ )
+
+ def test_store_attr_instance_value(self):
+ def get_items():
+ class C:
+ pass
+
+ items = []
+ for _ in range(self.ITEMS):
+ item = C()
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ item.a = None
+
+ def write(items):
+ for item in items:
+ item.__dict__[None] = None
+
+ opname = "STORE_ATTR_INSTANCE_VALUE"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_store_attr_with_hint(self):
+ def get_items():
+ class C:
+ pass
+
+ items = []
+ for _ in range(self.ITEMS):
+ item = C()
+ item.__dict__
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ item.a = None
+
+ def write(items):
+ for item in items:
+ item.__dict__[None] = None
+
+ opname = "STORE_ATTR_WITH_HINT"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_store_subscr_list_int(self):
+ def get_items():
+ items = []
+ for _ in range(self.ITEMS):
+ item = [None]
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ try:
+ item[0] = None
+ except IndexError:
+ pass
+
+ def write(items):
+ for item in items:
+ item.clear()
+ item.append(None)
+
+ opname = "STORE_SUBSCR_LIST_INT"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+ def test_unpack_sequence_list(self):
+ def get_items():
+ items = []
+ for _ in range(self.ITEMS):
+ item = [None]
+ items.append(item)
+ return items
+
+ def read(items):
+ for item in items:
+ try:
+ [_] = item
+ except ValueError:
+ pass
+
+ def write(items):
+ for item in items:
+ item.clear()
+ item.append(None)
+
+ opname = "UNPACK_SEQUENCE_LIST"
+ self.assert_races_do_not_crash(opname, get_items, read, write)
+
+
if __name__ == "__main__":
- import unittest
unittest.main()
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 8de4ef7270b754..99e9ed213e5615 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -4647,6 +4647,45 @@ def __fspath__(self):
return ''
self.assertFalse(hasattr(A(), '__dict__'))
+ def test_fspath_set_to_None(self):
+ class Foo:
+ __fspath__ = None
+
+ class Bar:
+ def __fspath__(self):
+ return 'bar'
+
+ class Baz(Bar):
+ __fspath__ = None
+
+ good_error_msg = (
+ r"expected str, bytes or os.PathLike object, not {}".format
+ )
+
+ with self.assertRaisesRegex(TypeError, good_error_msg("Foo")):
+ self.fspath(Foo())
+
+ self.assertEqual(self.fspath(Bar()), 'bar')
+
+ with self.assertRaisesRegex(TypeError, good_error_msg("Baz")):
+ self.fspath(Baz())
+
+ with self.assertRaisesRegex(TypeError, good_error_msg("Foo")):
+ open(Foo())
+
+ with self.assertRaisesRegex(TypeError, good_error_msg("Baz")):
+ open(Baz())
+
+ other_good_error_msg = (
+ r"should be string, bytes or os.PathLike, not {}".format
+ )
+
+ with self.assertRaisesRegex(TypeError, other_good_error_msg("Foo")):
+ os.rename(Foo(), "foooo")
+
+ with self.assertRaisesRegex(TypeError, other_good_error_msg("Baz")):
+ os.rename(Baz(), "bazzz")
+
class TimesTests(unittest.TestCase):
def test_times(self):
times = os.times()
diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py
index 1a008e5cea3f00..eb2b0cfb26e85f 100644
--- a/Lib/test/test_pathlib.py
+++ b/Lib/test/test_pathlib.py
@@ -5,6 +5,7 @@
import errno
import pathlib
import pickle
+import posixpath
import socket
import stat
import tempfile
@@ -23,20 +24,29 @@
grp = pwd = None
-#
-# Tests for the pure classes.
-#
+class UnsupportedOperationTest(unittest.TestCase):
+ def test_is_notimplemented(self):
+ self.assertTrue(issubclass(pathlib.UnsupportedOperation, NotImplementedError))
+ self.assertTrue(isinstance(pathlib.UnsupportedOperation(), NotImplementedError))
+
+
+# Make sure any symbolic links in the base test path are resolved.
+BASE = os.path.realpath(TESTFN)
+join = lambda *x: os.path.join(BASE, *x)
+rel_join = lambda *x: os.path.join(TESTFN, *x)
-class _BasePurePathSubclass(object):
- def __init__(self, *pathsegments, session_id):
- super().__init__(*pathsegments)
- self.session_id = session_id
+only_nt = unittest.skipIf(os.name != 'nt',
+ 'test requires a Windows-compatible system')
+only_posix = unittest.skipIf(os.name == 'nt',
+ 'test requires a POSIX-compatible system')
- def with_segments(self, *pathsegments):
- return type(self)(*pathsegments, session_id=self.session_id)
+#
+# Tests for the pure classes.
+#
-class _BasePurePathTest(object):
+class PurePathTest(unittest.TestCase):
+ cls = pathlib.PurePath
# Keys are canonical paths, values are list of tuples of arguments
# supposed to produce equal paths.
@@ -75,6 +85,37 @@ def test_constructor_common(self):
self.assertEqual(P(P('a'), P('b'), P('c')), P(FakePath("a/b/c")))
self.assertEqual(P(P('./a:b')), P('./a:b'))
+ def test_concrete_class(self):
+ if self.cls is pathlib.PurePath:
+ expected = pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath
+ else:
+ expected = self.cls
+ p = self.cls('a')
+ self.assertIs(type(p), expected)
+
+ def test_different_flavours_unequal(self):
+ p = self.cls('a')
+ if p._flavour is posixpath:
+ q = pathlib.PureWindowsPath('a')
+ else:
+ q = pathlib.PurePosixPath('a')
+ self.assertNotEqual(p, q)
+
+ def test_different_flavours_unordered(self):
+ p = self.cls('a')
+ if p._flavour is posixpath:
+ q = pathlib.PureWindowsPath('a')
+ else:
+ q = pathlib.PurePosixPath('a')
+ with self.assertRaises(TypeError):
+ p < q
+ with self.assertRaises(TypeError):
+ p <= q
+ with self.assertRaises(TypeError):
+ p > q
+ with self.assertRaises(TypeError):
+ p >= q
+
def test_bytes(self):
P = self.cls
message = (r"argument should be a str or an os\.PathLike object "
@@ -122,8 +163,13 @@ def test_str_subclass_common(self):
self._check_str_subclass('/a/b.txt')
def test_with_segments_common(self):
- class P(_BasePurePathSubclass, self.cls):
- pass
+ class P(self.cls):
+ def __init__(self, *pathsegments, session_id):
+ super().__init__(*pathsegments)
+ self.session_id = session_id
+
+ def with_segments(self, *pathsegments):
+ return type(self)(*pathsegments, session_id=self.session_id)
p = P('foo', 'bar', session_id=42)
self.assertEqual(42, (p / 'foo').session_id)
self.assertEqual(42, ('foo' / p).session_id)
@@ -338,6 +384,10 @@ def test_match_common(self):
self.assertTrue(P('A.py').match('a.PY', case_sensitive=False))
self.assertFalse(P('c:/a/B.Py').match('C:/A/*.pY', case_sensitive=True))
self.assertTrue(P('/a/b/c.py').match('/A/*/*.Py', case_sensitive=False))
+ # Matching against empty path
+ self.assertFalse(P().match('*'))
+ self.assertTrue(P().match('**'))
+ self.assertFalse(P().match('**/*'))
def test_ordering_common(self):
# Ordering is tuple-alike.
@@ -723,7 +773,7 @@ def test_pickling_common(self):
self.assertEqual(str(pp), str(p))
-class PurePosixPathTest(_BasePurePathTest, unittest.TestCase):
+class PurePosixPathTest(PurePathTest):
cls = pathlib.PurePosixPath
def test_drive_root_parts(self):
@@ -817,10 +867,10 @@ def test_parse_windows_path(self):
self.assertEqual(p, pp)
-class PureWindowsPathTest(_BasePurePathTest, unittest.TestCase):
+class PureWindowsPathTest(PurePathTest):
cls = pathlib.PureWindowsPath
- equivalences = _BasePurePathTest.equivalences.copy()
+ equivalences = PurePathTest.equivalences.copy()
equivalences.update({
'./a:b': [ ('./a:b',) ],
'c:a': [ ('c:', 'a'), ('c:', 'a/'), ('.', 'c:', 'a') ],
@@ -1491,45 +1541,14 @@ def test_is_reserved(self):
self.assertIs(True, P('c:/baz/con/NUL').is_reserved())
self.assertIs(False, P('c:/NUL/con/baz').is_reserved())
-class PurePathTest(_BasePurePathTest, unittest.TestCase):
- cls = pathlib.PurePath
-
- def test_concrete_class(self):
- p = self.cls('a')
- self.assertIs(type(p),
- pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath)
-
- def test_different_flavours_unequal(self):
- p = pathlib.PurePosixPath('a')
- q = pathlib.PureWindowsPath('a')
- self.assertNotEqual(p, q)
-
- def test_different_flavours_unordered(self):
- p = pathlib.PurePosixPath('a')
- q = pathlib.PureWindowsPath('a')
- with self.assertRaises(TypeError):
- p < q
- with self.assertRaises(TypeError):
- p <= q
- with self.assertRaises(TypeError):
- p > q
- with self.assertRaises(TypeError):
- p >= q
-
-#
-# Tests for the concrete classes.
-#
+class PurePathSubclassTest(PurePathTest):
+ class cls(pathlib.PurePath):
+ pass
-# Make sure any symbolic links in the base test path are resolved.
-BASE = os.path.realpath(TESTFN)
-join = lambda *x: os.path.join(BASE, *x)
-rel_join = lambda *x: os.path.join(TESTFN, *x)
+ # repr() roundtripping is not supported in custom subclass.
+ test_repr_roundtrips = None
-only_nt = unittest.skipIf(os.name != 'nt',
- 'test requires a Windows-compatible system')
-only_posix = unittest.skipIf(os.name == 'nt',
- 'test requires a POSIX-compatible system')
@only_posix
class PosixPathAsPureTest(PurePosixPathTest):
@@ -1541,18 +1560,25 @@ class WindowsPathAsPureTest(PureWindowsPathTest):
def test_owner(self):
P = self.cls
- with self.assertRaises(NotImplementedError):
+ with self.assertRaises(pathlib.UnsupportedOperation):
P('c:/').owner()
def test_group(self):
P = self.cls
- with self.assertRaises(NotImplementedError):
+ with self.assertRaises(pathlib.UnsupportedOperation):
P('c:/').group()
-class _BasePathTest(object):
+#
+# Tests for the concrete classes.
+#
+
+class PathTest(unittest.TestCase):
"""Tests for the FS-accessing functionalities of the Path classes."""
+ cls = pathlib.Path
+ can_symlink = os_helper.can_symlink()
+
# (BASE)
# |
# |-- brokenLink -> non-existing
@@ -1595,30 +1621,17 @@ def cleanup():
with open(join('dirC', 'dirD', 'fileD'), 'wb') as f:
f.write(b"this is file D\n")
os.chmod(join('dirE'), 0)
- if os_helper.can_symlink():
+ if self.can_symlink:
# Relative symlinks.
os.symlink('fileA', join('linkA'))
os.symlink('non-existing', join('brokenLink'))
- self.dirlink('dirB', join('linkB'))
- self.dirlink(os.path.join('..', 'dirB'), join('dirA', 'linkC'))
+ os.symlink('dirB', join('linkB'), target_is_directory=True)
+ os.symlink(os.path.join('..', 'dirB'), join('dirA', 'linkC'), target_is_directory=True)
# This one goes upwards, creating a loop.
- self.dirlink(os.path.join('..', 'dirB'), join('dirB', 'linkD'))
+ os.symlink(os.path.join('..', 'dirB'), join('dirB', 'linkD'), target_is_directory=True)
# Broken symlink (pointing to itself).
os.symlink('brokenLinkLoop', join('brokenLinkLoop'))
- if os.name == 'nt':
- # Workaround for http://bugs.python.org/issue13772.
- def dirlink(self, src, dest):
- os.symlink(src, dest, target_is_directory=True)
- else:
- def dirlink(self, src, dest):
- os.symlink(src, dest)
-
- def assertSame(self, path_a, path_b):
- self.assertTrue(os.path.samefile(str(path_a), str(path_b)),
- "%r and %r don't point to the same file" %
- (path_a, path_b))
-
def assertFileNotFound(self, func, *args, **kwargs):
with self.assertRaises(FileNotFoundError) as cm:
func(*args, **kwargs)
@@ -1627,82 +1640,6 @@ def assertFileNotFound(self, func, *args, **kwargs):
def assertEqualNormCase(self, path_a, path_b):
self.assertEqual(os.path.normcase(path_a), os.path.normcase(path_b))
- def _test_cwd(self, p):
- q = self.cls(os.getcwd())
- self.assertEqual(p, q)
- self.assertEqualNormCase(str(p), str(q))
- self.assertIs(type(p), type(q))
- self.assertTrue(p.is_absolute())
-
- def test_cwd(self):
- p = self.cls.cwd()
- self._test_cwd(p)
-
- def test_absolute_common(self):
- P = self.cls
-
- with mock.patch("os.getcwd") as getcwd:
- getcwd.return_value = BASE
-
- # Simple relative paths.
- self.assertEqual(str(P().absolute()), BASE)
- self.assertEqual(str(P('.').absolute()), BASE)
- self.assertEqual(str(P('a').absolute()), os.path.join(BASE, 'a'))
- self.assertEqual(str(P('a', 'b', 'c').absolute()), os.path.join(BASE, 'a', 'b', 'c'))
-
- # Symlinks should not be resolved.
- self.assertEqual(str(P('linkB', 'fileB').absolute()), os.path.join(BASE, 'linkB', 'fileB'))
- self.assertEqual(str(P('brokenLink').absolute()), os.path.join(BASE, 'brokenLink'))
- self.assertEqual(str(P('brokenLinkLoop').absolute()), os.path.join(BASE, 'brokenLinkLoop'))
-
- # '..' entries should be preserved and not normalised.
- self.assertEqual(str(P('..').absolute()), os.path.join(BASE, '..'))
- self.assertEqual(str(P('a', '..').absolute()), os.path.join(BASE, 'a', '..'))
- self.assertEqual(str(P('..', 'b').absolute()), os.path.join(BASE, '..', 'b'))
-
- def _test_home(self, p):
- q = self.cls(os.path.expanduser('~'))
- self.assertEqual(p, q)
- self.assertEqualNormCase(str(p), str(q))
- self.assertIs(type(p), type(q))
- self.assertTrue(p.is_absolute())
-
- @unittest.skipIf(
- pwd is None, reason="Test requires pwd module to get homedir."
- )
- def test_home(self):
- with os_helper.EnvironmentVarGuard() as env:
- self._test_home(self.cls.home())
-
- env.clear()
- env['USERPROFILE'] = os.path.join(BASE, 'userprofile')
- self._test_home(self.cls.home())
-
- # bpo-38883: ignore `HOME` when set on windows
- env['HOME'] = os.path.join(BASE, 'home')
- self._test_home(self.cls.home())
-
- def test_with_segments(self):
- class P(_BasePurePathSubclass, self.cls):
- pass
- p = P(BASE, session_id=42)
- self.assertEqual(42, p.absolute().session_id)
- self.assertEqual(42, p.resolve().session_id)
- if not is_wasi: # WASI has no user accounts.
- self.assertEqual(42, p.with_segments('~').expanduser().session_id)
- self.assertEqual(42, (p / 'fileA').rename(p / 'fileB').session_id)
- self.assertEqual(42, (p / 'fileB').replace(p / 'fileA').session_id)
- if os_helper.can_symlink():
- self.assertEqual(42, (p / 'linkA').readlink().session_id)
- for path in p.iterdir():
- self.assertEqual(42, path.session_id)
- for path in p.glob('*'):
- self.assertEqual(42, path.session_id)
- for path in p.rglob('*'):
- self.assertEqual(42, path.session_id)
- for dirpath, dirnames, filenames in p.walk():
- self.assertEqual(42, dirpath.session_id)
-
def test_samefile(self):
fileA_path = os.path.join(BASE, 'fileA')
fileB_path = os.path.join(BASE, 'dirB', 'fileB')
@@ -1726,23 +1663,7 @@ def test_samefile(self):
def test_empty_path(self):
# The empty path points to '.'
p = self.cls('')
- self.assertEqual(p.stat(), os.stat('.'))
-
- @unittest.skipIf(is_wasi, "WASI has no user accounts.")
- def test_expanduser_common(self):
- P = self.cls
- p = P('~')
- self.assertEqual(p.expanduser(), P(os.path.expanduser('~')))
- p = P('foo')
- self.assertEqual(p.expanduser(), p)
- p = P('/~')
- self.assertEqual(p.expanduser(), p)
- p = P('../~')
- self.assertEqual(p.expanduser(), p)
- p = P(P('').absolute().anchor) / '~'
- self.assertEqual(p.expanduser(), p)
- p = P('~/a:b')
- self.assertEqual(p.expanduser(), P(os.path.expanduser('~'), './a:b'))
+ self.assertEqual(str(p), '.')
def test_exists(self):
P = self.cls
@@ -1751,7 +1672,7 @@ def test_exists(self):
self.assertIs(True, (p / 'dirA').exists())
self.assertIs(True, (p / 'fileA').exists())
self.assertIs(False, (p / 'fileA' / 'bah').exists())
- if os_helper.can_symlink():
+ if self.can_symlink:
self.assertIs(True, (p / 'linkA').exists())
self.assertIs(True, (p / 'linkB').exists())
self.assertIs(True, (p / 'linkB' / 'fileB').exists())
@@ -1771,9 +1692,6 @@ def test_open_common(self):
with (p / 'fileA').open('rb') as f:
self.assertIsInstance(f, io.BufferedIOBase)
self.assertEqual(f.read().strip(), b"this is file A")
- with (p / 'fileA').open('rb', buffering=0) as f:
- self.assertIsInstance(f, io.RawIOBase)
- self.assertEqual(f.read().strip(), b"this is file A")
def test_read_write_bytes(self):
p = self.cls(BASE)
@@ -1818,12 +1736,13 @@ def test_iterdir(self):
it = p.iterdir()
paths = set(it)
expected = ['dirA', 'dirB', 'dirC', 'dirE', 'fileA']
- if os_helper.can_symlink():
+ if self.can_symlink:
expected += ['linkA', 'linkB', 'brokenLink', 'brokenLinkLoop']
self.assertEqual(paths, { P(BASE, q) for q in expected })
- @os_helper.skip_unless_symlink
def test_iterdir_symlink(self):
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
# __iter__ on a symlink to a directory.
P = self.cls
p = P(BASE, 'linkB')
@@ -1851,27 +1770,32 @@ def _check(glob, expected):
_check(it, ["fileA"])
_check(p.glob("fileB"), [])
_check(p.glob("dir*/file*"), ["dirB/fileB", "dirC/fileC"])
- if not os_helper.can_symlink():
+ if not self.can_symlink:
_check(p.glob("*A"), ['dirA', 'fileA'])
else:
_check(p.glob("*A"), ['dirA', 'fileA', 'linkA'])
- if not os_helper.can_symlink():
+ if not self.can_symlink:
_check(p.glob("*B/*"), ['dirB/fileB'])
else:
_check(p.glob("*B/*"), ['dirB/fileB', 'dirB/linkD',
'linkB/fileB', 'linkB/linkD'])
- if not os_helper.can_symlink():
+ if not self.can_symlink:
_check(p.glob("*/fileB"), ['dirB/fileB'])
else:
_check(p.glob("*/fileB"), ['dirB/fileB', 'linkB/fileB'])
- if os_helper.can_symlink():
+ if self.can_symlink:
_check(p.glob("brokenLink"), ['brokenLink'])
- if not os_helper.can_symlink():
+ if not self.can_symlink:
_check(p.glob("*/"), ["dirA", "dirB", "dirC", "dirE"])
else:
_check(p.glob("*/"), ["dirA", "dirB", "dirC", "dirE", "linkB"])
+ def test_glob_empty_pattern(self):
+ p = self.cls()
+ with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'):
+ list(p.glob(''))
+
def test_glob_case_sensitive(self):
P = self.cls
def _check(path, pattern, case_sensitive, expected):
@@ -1884,8 +1808,9 @@ def _check(path, pattern, case_sensitive, expected):
_check(path, "dirb/file*", True, [])
_check(path, "dirb/file*", False, ["dirB/fileB"])
- @os_helper.skip_unless_symlink
def test_glob_follow_symlinks_common(self):
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
def _check(path, glob, expected):
actual = {path for path in path.glob(glob, follow_symlinks=True)
if "linkD" not in path.parent.parts} # exclude symlink loop.
@@ -1909,8 +1834,9 @@ def _check(path, glob, expected):
_check(p, "dir*/*/../dirD/**/", ["dirC/dirD/../dirD"])
_check(p, "*/dirD/**/", ["dirC/dirD"])
- @os_helper.skip_unless_symlink
def test_glob_no_follow_symlinks_common(self):
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
def _check(path, glob, expected):
actual = {path for path in path.glob(glob, follow_symlinks=False)}
self.assertEqual(actual, { P(BASE, q) for q in expected })
@@ -1942,14 +1868,14 @@ def _check(glob, expected):
_check(p.rglob("fileB"), ["dirB/fileB"])
_check(p.rglob("**/fileB"), ["dirB/fileB"])
_check(p.rglob("*/fileA"), [])
- if not os_helper.can_symlink():
+ if not self.can_symlink:
_check(p.rglob("*/fileB"), ["dirB/fileB"])
else:
_check(p.rglob("*/fileB"), ["dirB/fileB", "dirB/linkD/fileB",
"linkB/fileB", "dirA/linkC/fileB"])
_check(p.rglob("file*"), ["fileA", "dirB/fileB",
"dirC/fileC", "dirC/dirD/fileD"])
- if not os_helper.can_symlink():
+ if not self.can_symlink:
_check(p.rglob("*/"), [
"dirA", "dirB", "dirC", "dirC/dirD", "dirE",
])
@@ -1974,8 +1900,9 @@ def _check(glob, expected):
_check(p.rglob("*.txt"), ["dirC/novel.txt"])
_check(p.rglob("*.*"), ["dirC/novel.txt"])
- @os_helper.skip_unless_symlink
def test_rglob_follow_symlinks_common(self):
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
def _check(path, glob, expected):
actual = {path for path in path.rglob(glob, follow_symlinks=True)
if 'linkD' not in path.parent.parts} # exclude symlink loop.
@@ -2003,8 +1930,9 @@ def _check(path, glob, expected):
_check(p, "*.txt", ["dirC/novel.txt"])
_check(p, "*.*", ["dirC/novel.txt"])
- @os_helper.skip_unless_symlink
def test_rglob_no_follow_symlinks_common(self):
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
def _check(path, glob, expected):
actual = {path for path in path.rglob(glob, follow_symlinks=False)}
self.assertEqual(actual, { P(BASE, q) for q in expected })
@@ -2028,9 +1956,10 @@ def _check(path, glob, expected):
_check(p, "*.txt", ["dirC/novel.txt"])
_check(p, "*.*", ["dirC/novel.txt"])
- @os_helper.skip_unless_symlink
def test_rglob_symlink_loop(self):
# Don't get fooled by symlink loops (Issue #26012).
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
P = self.cls
p = P(BASE)
given = set(p.rglob('*'))
@@ -2077,13 +2006,13 @@ def test_glob_dotdot(self):
self.assertEqual(set(p.glob("xyzzy/..")), set())
self.assertEqual(set(p.glob("/".join([".."] * 50))), { P(BASE, *[".."] * 50)})
- @os_helper.skip_unless_symlink
def test_glob_permissions(self):
# See bpo-38894
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
P = self.cls
base = P(BASE) / 'permissions'
base.mkdir()
- self.addCleanup(os_helper.rmtree, base)
for i in range(100):
link = base / f"link{i}"
@@ -2097,9 +2026,10 @@ def test_glob_permissions(self):
self.assertEqual(len(set(base.glob("*/fileC"))), 50)
self.assertEqual(len(set(base.glob("*/file*"))), 50)
- @os_helper.skip_unless_symlink
def test_glob_long_symlink(self):
# See gh-87695
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
base = self.cls(BASE) / 'long_symlink'
base.mkdir()
bad_link = base / 'bad_link'
@@ -2107,16 +2037,34 @@ def test_glob_long_symlink(self):
self.assertEqual(sorted(base.glob('**/*')), [bad_link])
def test_glob_above_recursion_limit(self):
- recursion_limit = 40
+ recursion_limit = 50
# directory_depth > recursion_limit
directory_depth = recursion_limit + 10
- base = pathlib.Path(os_helper.TESTFN, 'deep')
- path = pathlib.Path(base, *(['d'] * directory_depth))
+ base = self.cls(BASE, 'deep')
+ path = self.cls(base, *(['d'] * directory_depth))
path.mkdir(parents=True)
with set_recursion_limit(recursion_limit):
list(base.glob('**'))
+ def test_readlink(self):
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
+ P = self.cls(BASE)
+ self.assertEqual((P / 'linkA').readlink(), self.cls('fileA'))
+ self.assertEqual((P / 'brokenLink').readlink(),
+ self.cls('non-existing'))
+ self.assertEqual((P / 'linkB').readlink(), self.cls('dirB'))
+ with self.assertRaises(OSError):
+ (P / 'fileA').readlink()
+
+ @unittest.skipIf(hasattr(os, "readlink"), "os.readlink() is present")
+ def test_readlink_unsupported(self):
+ P = self.cls(BASE)
+ p = P / 'fileA'
+ with self.assertRaises(pathlib.UnsupportedOperation):
+ q.readlink(p)
+
def _check_resolve(self, p, expected, strict=True):
q = p.resolve(strict)
self.assertEqual(q, expected)
@@ -2124,8 +2072,9 @@ def _check_resolve(self, p, expected, strict=True):
# This can be used to check both relative and absolute resolutions.
_check_resolve_relative = _check_resolve_absolute = _check_resolve
- @os_helper.skip_unless_symlink
def test_resolve_common(self):
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
P = self.cls
p = P(BASE, 'foo')
with self.assertRaises(OSError) as cm:
@@ -2167,8 +2116,8 @@ def test_resolve_common(self):
d = os_helper._longpath(tempfile.mkdtemp(suffix='-dirD',
dir=os.getcwd()))
self.addCleanup(os_helper.rmtree, d)
- os.symlink(os.path.join(d), join('dirA', 'linkX'))
- os.symlink(join('dirB'), os.path.join(d, 'linkY'))
+ P(BASE, 'dirA', 'linkX').symlink_to(d)
+ P(BASE, str(d), 'linkY').symlink_to(join('dirB'))
p = P(BASE, 'dirA', 'linkX', 'linkY', 'fileB')
self._check_resolve_absolute(p, P(BASE, 'dirB', 'fileB'))
# Non-strict
@@ -2185,13 +2134,14 @@ def test_resolve_common(self):
# resolves to 'dirB/..' first before resolving to parent of dirB.
self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False)
- @os_helper.skip_unless_symlink
def test_resolve_dot(self):
# See http://web.archive.org/web/20200623062557/https://bitbucket.org/pitrou/pathlib/issues/9/
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
p = self.cls(BASE)
- self.dirlink('.', join('0'))
- self.dirlink(os.path.join('0', '0'), join('1'))
- self.dirlink(os.path.join('1', '1'), join('2'))
+ p.joinpath('0').symlink_to('.', target_is_directory=True)
+ p.joinpath('1').symlink_to(os.path.join('0', '0'), target_is_directory=True)
+ p.joinpath('2').symlink_to(os.path.join('1', '1'), target_is_directory=True)
q = p / '2'
self.assertEqual(q.resolve(strict=True), p)
r = q / '3' / '4'
@@ -2199,59 +2149,29 @@ def test_resolve_dot(self):
# Non-strict
self.assertEqual(r.resolve(strict=False), p / '3' / '4')
- def test_resolve_nonexist_relative_issue38671(self):
- p = self.cls('non', 'exist')
-
- old_cwd = os.getcwd()
- os.chdir(BASE)
- try:
- self.assertEqual(p.resolve(), self.cls(BASE, p))
- finally:
- os.chdir(old_cwd)
-
- @os_helper.skip_unless_working_chmod
- def test_chmod(self):
- p = self.cls(BASE) / 'fileA'
- mode = p.stat().st_mode
- # Clear writable bit.
- new_mode = mode & ~0o222
- p.chmod(new_mode)
- self.assertEqual(p.stat().st_mode, new_mode)
- # Set writable bit.
- new_mode = mode | 0o222
- p.chmod(new_mode)
- self.assertEqual(p.stat().st_mode, new_mode)
-
- # On Windows, os.chmod does not follow symlinks (issue #15411)
- @only_posix
- @os_helper.skip_unless_working_chmod
- def test_chmod_follow_symlinks_true(self):
- p = self.cls(BASE) / 'linkA'
- q = p.resolve()
- mode = q.stat().st_mode
- # Clear writable bit.
- new_mode = mode & ~0o222
- p.chmod(new_mode, follow_symlinks=True)
- self.assertEqual(q.stat().st_mode, new_mode)
- # Set writable bit
- new_mode = mode | 0o222
- p.chmod(new_mode, follow_symlinks=True)
- self.assertEqual(q.stat().st_mode, new_mode)
-
- # XXX also need a test for lchmod.
-
- @os_helper.skip_unless_working_chmod
def test_stat(self):
- p = self.cls(BASE) / 'fileA'
- st = p.stat()
- self.assertEqual(p.stat(), st)
- # Change file mode by flipping write bit.
- p.chmod(st.st_mode ^ 0o222)
- self.addCleanup(p.chmod, st.st_mode)
- self.assertNotEqual(p.stat(), st)
+ statA = self.cls(BASE).joinpath('fileA').stat()
+ statB = self.cls(BASE).joinpath('dirB', 'fileB').stat()
+ statC = self.cls(BASE).joinpath('dirC').stat()
+ # st_mode: files are the same, directory differs.
+ self.assertIsInstance(statA.st_mode, int)
+ self.assertEqual(statA.st_mode, statB.st_mode)
+ self.assertNotEqual(statA.st_mode, statC.st_mode)
+ self.assertNotEqual(statB.st_mode, statC.st_mode)
+ # st_ino: all different,
+ self.assertIsInstance(statA.st_ino, int)
+ self.assertNotEqual(statA.st_ino, statB.st_ino)
+ self.assertNotEqual(statA.st_ino, statC.st_ino)
+ self.assertNotEqual(statB.st_ino, statC.st_ino)
+ # st_dev: all the same.
+ self.assertIsInstance(statA.st_dev, int)
+ self.assertEqual(statA.st_dev, statB.st_dev)
+ self.assertEqual(statA.st_dev, statC.st_dev)
+ # other attributes not used by pathlib.
- @os_helper.skip_unless_symlink
def test_stat_no_follow_symlinks(self):
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
p = self.cls(BASE) / 'linkA'
st = p.stat()
self.assertNotEqual(st, p.stat(follow_symlinks=False))
@@ -2261,8 +2181,9 @@ def test_stat_no_follow_symlinks_nosymlink(self):
st = p.stat()
self.assertEqual(st, p.stat(follow_symlinks=False))
- @os_helper.skip_unless_symlink
def test_lstat(self):
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
p = self.cls(BASE)/ 'linkA'
st = p.stat()
self.assertNotEqual(st, p.lstat())
@@ -2272,7 +2193,356 @@ def test_lstat_nosymlink(self):
st = p.stat()
self.assertEqual(st, p.lstat())
- @unittest.skipUnless(pwd, "the pwd module is needed for this test")
+ def test_is_dir(self):
+ P = self.cls(BASE)
+ self.assertTrue((P / 'dirA').is_dir())
+ self.assertFalse((P / 'fileA').is_dir())
+ self.assertFalse((P / 'non-existing').is_dir())
+ self.assertFalse((P / 'fileA' / 'bah').is_dir())
+ if self.can_symlink:
+ self.assertFalse((P / 'linkA').is_dir())
+ self.assertTrue((P / 'linkB').is_dir())
+ self.assertFalse((P/ 'brokenLink').is_dir())
+ self.assertFalse((P / 'dirA\udfff').is_dir())
+ self.assertFalse((P / 'dirA\x00').is_dir())
+
+ def test_is_dir_no_follow_symlinks(self):
+ P = self.cls(BASE)
+ self.assertTrue((P / 'dirA').is_dir(follow_symlinks=False))
+ self.assertFalse((P / 'fileA').is_dir(follow_symlinks=False))
+ self.assertFalse((P / 'non-existing').is_dir(follow_symlinks=False))
+ self.assertFalse((P / 'fileA' / 'bah').is_dir(follow_symlinks=False))
+ if self.can_symlink:
+ self.assertFalse((P / 'linkA').is_dir(follow_symlinks=False))
+ self.assertFalse((P / 'linkB').is_dir(follow_symlinks=False))
+ self.assertFalse((P/ 'brokenLink').is_dir(follow_symlinks=False))
+ self.assertFalse((P / 'dirA\udfff').is_dir(follow_symlinks=False))
+ self.assertFalse((P / 'dirA\x00').is_dir(follow_symlinks=False))
+
+ def test_is_file(self):
+ P = self.cls(BASE)
+ self.assertTrue((P / 'fileA').is_file())
+ self.assertFalse((P / 'dirA').is_file())
+ self.assertFalse((P / 'non-existing').is_file())
+ self.assertFalse((P / 'fileA' / 'bah').is_file())
+ if self.can_symlink:
+ self.assertTrue((P / 'linkA').is_file())
+ self.assertFalse((P / 'linkB').is_file())
+ self.assertFalse((P/ 'brokenLink').is_file())
+ self.assertFalse((P / 'fileA\udfff').is_file())
+ self.assertFalse((P / 'fileA\x00').is_file())
+
+ def test_is_file_no_follow_symlinks(self):
+ P = self.cls(BASE)
+ self.assertTrue((P / 'fileA').is_file(follow_symlinks=False))
+ self.assertFalse((P / 'dirA').is_file(follow_symlinks=False))
+ self.assertFalse((P / 'non-existing').is_file(follow_symlinks=False))
+ self.assertFalse((P / 'fileA' / 'bah').is_file(follow_symlinks=False))
+ if self.can_symlink:
+ self.assertFalse((P / 'linkA').is_file(follow_symlinks=False))
+ self.assertFalse((P / 'linkB').is_file(follow_symlinks=False))
+ self.assertFalse((P/ 'brokenLink').is_file(follow_symlinks=False))
+ self.assertFalse((P / 'fileA\udfff').is_file(follow_symlinks=False))
+ self.assertFalse((P / 'fileA\x00').is_file(follow_symlinks=False))
+
+ def test_is_mount(self):
+ P = self.cls(BASE)
+ self.assertFalse((P / 'fileA').is_mount())
+ self.assertFalse((P / 'dirA').is_mount())
+ self.assertFalse((P / 'non-existing').is_mount())
+ self.assertFalse((P / 'fileA' / 'bah').is_mount())
+ if self.can_symlink:
+ self.assertFalse((P / 'linkA').is_mount())
+
+ def test_is_symlink(self):
+ P = self.cls(BASE)
+ self.assertFalse((P / 'fileA').is_symlink())
+ self.assertFalse((P / 'dirA').is_symlink())
+ self.assertFalse((P / 'non-existing').is_symlink())
+ self.assertFalse((P / 'fileA' / 'bah').is_symlink())
+ if self.can_symlink:
+ self.assertTrue((P / 'linkA').is_symlink())
+ self.assertTrue((P / 'linkB').is_symlink())
+ self.assertTrue((P/ 'brokenLink').is_symlink())
+ self.assertIs((P / 'fileA\udfff').is_file(), False)
+ self.assertIs((P / 'fileA\x00').is_file(), False)
+ if self.can_symlink:
+ self.assertIs((P / 'linkA\udfff').is_file(), False)
+ self.assertIs((P / 'linkA\x00').is_file(), False)
+
+ def test_is_junction_false(self):
+ P = self.cls(BASE)
+ self.assertFalse((P / 'fileA').is_junction())
+ self.assertFalse((P / 'dirA').is_junction())
+ self.assertFalse((P / 'non-existing').is_junction())
+ self.assertFalse((P / 'fileA' / 'bah').is_junction())
+ self.assertFalse((P / 'fileA\udfff').is_junction())
+ self.assertFalse((P / 'fileA\x00').is_junction())
+
+ def test_is_fifo_false(self):
+ P = self.cls(BASE)
+ self.assertFalse((P / 'fileA').is_fifo())
+ self.assertFalse((P / 'dirA').is_fifo())
+ self.assertFalse((P / 'non-existing').is_fifo())
+ self.assertFalse((P / 'fileA' / 'bah').is_fifo())
+ self.assertIs((P / 'fileA\udfff').is_fifo(), False)
+ self.assertIs((P / 'fileA\x00').is_fifo(), False)
+
+ def test_is_socket_false(self):
+ P = self.cls(BASE)
+ self.assertFalse((P / 'fileA').is_socket())
+ self.assertFalse((P / 'dirA').is_socket())
+ self.assertFalse((P / 'non-existing').is_socket())
+ self.assertFalse((P / 'fileA' / 'bah').is_socket())
+ self.assertIs((P / 'fileA\udfff').is_socket(), False)
+ self.assertIs((P / 'fileA\x00').is_socket(), False)
+
+ def test_is_block_device_false(self):
+ P = self.cls(BASE)
+ self.assertFalse((P / 'fileA').is_block_device())
+ self.assertFalse((P / 'dirA').is_block_device())
+ self.assertFalse((P / 'non-existing').is_block_device())
+ self.assertFalse((P / 'fileA' / 'bah').is_block_device())
+ self.assertIs((P / 'fileA\udfff').is_block_device(), False)
+ self.assertIs((P / 'fileA\x00').is_block_device(), False)
+
+ def test_is_char_device_false(self):
+ P = self.cls(BASE)
+ self.assertFalse((P / 'fileA').is_char_device())
+ self.assertFalse((P / 'dirA').is_char_device())
+ self.assertFalse((P / 'non-existing').is_char_device())
+ self.assertFalse((P / 'fileA' / 'bah').is_char_device())
+ self.assertIs((P / 'fileA\udfff').is_char_device(), False)
+ self.assertIs((P / 'fileA\x00').is_char_device(), False)
+
+ def test_pickling_common(self):
+ p = self.cls(BASE, 'fileA')
+ for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
+ dumped = pickle.dumps(p, proto)
+ pp = pickle.loads(dumped)
+ self.assertEqual(pp.stat(), p.stat())
+
+ def test_parts_interning(self):
+ P = self.cls
+ p = P('/usr/bin/foo')
+ q = P('/usr/local/bin')
+ # 'usr'
+ self.assertIs(p.parts[1], q.parts[1])
+ # 'bin'
+ self.assertIs(p.parts[2], q.parts[3])
+
+ def _check_complex_symlinks(self, link0_target):
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
+
+ # Test solving a non-looping chain of symlinks (issue #19887).
+ P = self.cls(BASE)
+ P.joinpath('link1').symlink_to(os.path.join('link0', 'link0'), target_is_directory=True)
+ P.joinpath('link2').symlink_to(os.path.join('link1', 'link1'), target_is_directory=True)
+ P.joinpath('link3').symlink_to(os.path.join('link2', 'link2'), target_is_directory=True)
+ P.joinpath('link0').symlink_to(link0_target, target_is_directory=True)
+
+ # Resolve absolute paths.
+ p = (P / 'link0').resolve()
+ self.assertEqual(p, P)
+ self.assertEqualNormCase(str(p), BASE)
+ p = (P / 'link1').resolve()
+ self.assertEqual(p, P)
+ self.assertEqualNormCase(str(p), BASE)
+ p = (P / 'link2').resolve()
+ self.assertEqual(p, P)
+ self.assertEqualNormCase(str(p), BASE)
+ p = (P / 'link3').resolve()
+ self.assertEqual(p, P)
+ self.assertEqualNormCase(str(p), BASE)
+
+ # Resolve relative paths.
+ old_path = os.getcwd()
+ os.chdir(BASE)
+ try:
+ p = self.cls('link0').resolve()
+ self.assertEqual(p, P)
+ self.assertEqualNormCase(str(p), BASE)
+ p = self.cls('link1').resolve()
+ self.assertEqual(p, P)
+ self.assertEqualNormCase(str(p), BASE)
+ p = self.cls('link2').resolve()
+ self.assertEqual(p, P)
+ self.assertEqualNormCase(str(p), BASE)
+ p = self.cls('link3').resolve()
+ self.assertEqual(p, P)
+ self.assertEqualNormCase(str(p), BASE)
+ finally:
+ os.chdir(old_path)
+
+ def test_complex_symlinks_absolute(self):
+ self._check_complex_symlinks(BASE)
+
+ def test_complex_symlinks_relative(self):
+ self._check_complex_symlinks('.')
+
+ def test_complex_symlinks_relative_dot_dot(self):
+ self._check_complex_symlinks(os.path.join('dirA', '..'))
+
+ def test_concrete_class(self):
+ if self.cls is pathlib.Path:
+ expected = pathlib.WindowsPath if os.name == 'nt' else pathlib.PosixPath
+ else:
+ expected = self.cls
+ p = self.cls('a')
+ self.assertIs(type(p), expected)
+
+ def test_unsupported_flavour(self):
+ if self.cls._flavour is os.path:
+ self.skipTest("path flavour is supported")
+ else:
+ self.assertRaises(pathlib.UnsupportedOperation, self.cls)
+
+ def _test_cwd(self, p):
+ q = self.cls(os.getcwd())
+ self.assertEqual(p, q)
+ self.assertEqualNormCase(str(p), str(q))
+ self.assertIs(type(p), type(q))
+ self.assertTrue(p.is_absolute())
+
+ def test_cwd(self):
+ p = self.cls.cwd()
+ self._test_cwd(p)
+
+ def test_absolute_common(self):
+ P = self.cls
+
+ with mock.patch("os.getcwd") as getcwd:
+ getcwd.return_value = BASE
+
+ # Simple relative paths.
+ self.assertEqual(str(P().absolute()), BASE)
+ self.assertEqual(str(P('.').absolute()), BASE)
+ self.assertEqual(str(P('a').absolute()), os.path.join(BASE, 'a'))
+ self.assertEqual(str(P('a', 'b', 'c').absolute()), os.path.join(BASE, 'a', 'b', 'c'))
+
+ # Symlinks should not be resolved.
+ self.assertEqual(str(P('linkB', 'fileB').absolute()), os.path.join(BASE, 'linkB', 'fileB'))
+ self.assertEqual(str(P('brokenLink').absolute()), os.path.join(BASE, 'brokenLink'))
+ self.assertEqual(str(P('brokenLinkLoop').absolute()), os.path.join(BASE, 'brokenLinkLoop'))
+
+ # '..' entries should be preserved and not normalised.
+ self.assertEqual(str(P('..').absolute()), os.path.join(BASE, '..'))
+ self.assertEqual(str(P('a', '..').absolute()), os.path.join(BASE, 'a', '..'))
+ self.assertEqual(str(P('..', 'b').absolute()), os.path.join(BASE, '..', 'b'))
+
+ def _test_home(self, p):
+ q = self.cls(os.path.expanduser('~'))
+ self.assertEqual(p, q)
+ self.assertEqualNormCase(str(p), str(q))
+ self.assertIs(type(p), type(q))
+ self.assertTrue(p.is_absolute())
+
+ @unittest.skipIf(
+ pwd is None, reason="Test requires pwd module to get homedir."
+ )
+ def test_home(self):
+ with os_helper.EnvironmentVarGuard() as env:
+ self._test_home(self.cls.home())
+
+ env.clear()
+ env['USERPROFILE'] = os.path.join(BASE, 'userprofile')
+ self._test_home(self.cls.home())
+
+ # bpo-38883: ignore `HOME` when set on windows
+ env['HOME'] = os.path.join(BASE, 'home')
+ self._test_home(self.cls.home())
+
+ @unittest.skipIf(is_wasi, "WASI has no user accounts.")
+ def test_expanduser_common(self):
+ P = self.cls
+ p = P('~')
+ self.assertEqual(p.expanduser(), P(os.path.expanduser('~')))
+ p = P('foo')
+ self.assertEqual(p.expanduser(), p)
+ p = P('/~')
+ self.assertEqual(p.expanduser(), p)
+ p = P('../~')
+ self.assertEqual(p.expanduser(), p)
+ p = P(P('').absolute().anchor) / '~'
+ self.assertEqual(p.expanduser(), p)
+ p = P('~/a:b')
+ self.assertEqual(p.expanduser(), P(os.path.expanduser('~'), './a:b'))
+
+ def test_with_segments(self):
+ class P(self.cls):
+ def __init__(self, *pathsegments, session_id):
+ super().__init__(*pathsegments)
+ self.session_id = session_id
+
+ def with_segments(self, *pathsegments):
+ return type(self)(*pathsegments, session_id=self.session_id)
+ p = P(BASE, session_id=42)
+ self.assertEqual(42, p.absolute().session_id)
+ self.assertEqual(42, p.resolve().session_id)
+ if not is_wasi: # WASI has no user accounts.
+ self.assertEqual(42, p.with_segments('~').expanduser().session_id)
+ self.assertEqual(42, (p / 'fileA').rename(p / 'fileB').session_id)
+ self.assertEqual(42, (p / 'fileB').replace(p / 'fileA').session_id)
+ if self.can_symlink:
+ self.assertEqual(42, (p / 'linkA').readlink().session_id)
+ for path in p.iterdir():
+ self.assertEqual(42, path.session_id)
+ for path in p.glob('*'):
+ self.assertEqual(42, path.session_id)
+ for path in p.rglob('*'):
+ self.assertEqual(42, path.session_id)
+ for dirpath, dirnames, filenames in p.walk():
+ self.assertEqual(42, dirpath.session_id)
+
+ def test_open_unbuffered(self):
+ p = self.cls(BASE)
+ with (p / 'fileA').open('rb', buffering=0) as f:
+ self.assertIsInstance(f, io.RawIOBase)
+ self.assertEqual(f.read().strip(), b"this is file A")
+
+ def test_resolve_nonexist_relative_issue38671(self):
+ p = self.cls('non', 'exist')
+
+ old_cwd = os.getcwd()
+ os.chdir(BASE)
+ try:
+ self.assertEqual(p.resolve(), self.cls(BASE, p))
+ finally:
+ os.chdir(old_cwd)
+
+ @os_helper.skip_unless_working_chmod
+ def test_chmod(self):
+ p = self.cls(BASE) / 'fileA'
+ mode = p.stat().st_mode
+ # Clear writable bit.
+ new_mode = mode & ~0o222
+ p.chmod(new_mode)
+ self.assertEqual(p.stat().st_mode, new_mode)
+ # Set writable bit.
+ new_mode = mode | 0o222
+ p.chmod(new_mode)
+ self.assertEqual(p.stat().st_mode, new_mode)
+
+ # On Windows, os.chmod does not follow symlinks (issue #15411)
+ @only_posix
+ @os_helper.skip_unless_working_chmod
+ def test_chmod_follow_symlinks_true(self):
+ p = self.cls(BASE) / 'linkA'
+ q = p.resolve()
+ mode = q.stat().st_mode
+ # Clear writable bit.
+ new_mode = mode & ~0o222
+ p.chmod(new_mode, follow_symlinks=True)
+ self.assertEqual(q.stat().st_mode, new_mode)
+ # Set writable bit
+ new_mode = mode | 0o222
+ p.chmod(new_mode, follow_symlinks=True)
+ self.assertEqual(q.stat().st_mode, new_mode)
+
+ # XXX also need a test for lchmod.
+
+ @unittest.skipUnless(pwd, "the pwd module is needed for this test")
def test_owner(self):
p = self.cls(BASE) / 'fileA'
uid = p.stat().st_uid
@@ -2332,12 +2602,12 @@ def test_hardlink_to(self):
self.assertTrue(link2.exists())
@unittest.skipIf(hasattr(os, "link"), "os.link() is present")
- def test_link_to_not_implemented(self):
+ def test_hardlink_to_unsupported(self):
P = self.cls(BASE)
p = P / 'fileA'
# linking to another path.
q = P / 'dirA' / 'fileAA'
- with self.assertRaises(NotImplementedError):
+ with self.assertRaises(pathlib.UnsupportedOperation):
q.hardlink_to(p)
def test_rename(self):
@@ -2374,16 +2644,6 @@ def test_replace(self):
self.assertEqual(os.stat(r).st_size, size)
self.assertFileNotFound(q.stat)
- @os_helper.skip_unless_symlink
- def test_readlink(self):
- P = self.cls(BASE)
- self.assertEqual((P / 'linkA').readlink(), self.cls('fileA'))
- self.assertEqual((P / 'brokenLink').readlink(),
- self.cls('non-existing'))
- self.assertEqual((P / 'linkB').readlink(), self.cls('dirB'))
- with self.assertRaises(OSError):
- (P / 'fileA').readlink()
-
def test_touch_common(self):
P = self.cls(BASE)
p = P / 'newfileA'
@@ -2551,8 +2811,9 @@ def my_mkdir(path, mode=0o777):
self.assertNotIn(str(p12), concurrently_created)
self.assertTrue(p.exists())
- @os_helper.skip_unless_symlink
def test_symlink_to(self):
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
P = self.cls(BASE)
target = P / 'fileA'
# Symlinking a path target.
@@ -2575,62 +2836,14 @@ def test_symlink_to(self):
self.assertTrue(link.is_dir())
self.assertTrue(list(link.iterdir()))
- def test_is_dir(self):
+ @unittest.skipIf(hasattr(os, "symlink"), "os.symlink() is present")
+ def test_symlink_to_unsupported(self):
P = self.cls(BASE)
- self.assertTrue((P / 'dirA').is_dir())
- self.assertFalse((P / 'fileA').is_dir())
- self.assertFalse((P / 'non-existing').is_dir())
- self.assertFalse((P / 'fileA' / 'bah').is_dir())
- if os_helper.can_symlink():
- self.assertFalse((P / 'linkA').is_dir())
- self.assertTrue((P / 'linkB').is_dir())
- self.assertFalse((P/ 'brokenLink').is_dir(), False)
- self.assertIs((P / 'dirA\udfff').is_dir(), False)
- self.assertIs((P / 'dirA\x00').is_dir(), False)
-
- def test_is_file(self):
- P = self.cls(BASE)
- self.assertTrue((P / 'fileA').is_file())
- self.assertFalse((P / 'dirA').is_file())
- self.assertFalse((P / 'non-existing').is_file())
- self.assertFalse((P / 'fileA' / 'bah').is_file())
- if os_helper.can_symlink():
- self.assertTrue((P / 'linkA').is_file())
- self.assertFalse((P / 'linkB').is_file())
- self.assertFalse((P/ 'brokenLink').is_file())
- self.assertIs((P / 'fileA\udfff').is_file(), False)
- self.assertIs((P / 'fileA\x00').is_file(), False)
-
- def test_is_mount(self):
- P = self.cls(BASE)
- if os.name == 'nt':
- R = self.cls('c:\\')
- else:
- R = self.cls('/')
- self.assertFalse((P / 'fileA').is_mount())
- self.assertFalse((P / 'dirA').is_mount())
- self.assertFalse((P / 'non-existing').is_mount())
- self.assertFalse((P / 'fileA' / 'bah').is_mount())
- self.assertTrue(R.is_mount())
- if os_helper.can_symlink():
- self.assertFalse((P / 'linkA').is_mount())
- self.assertIs((R / '\udfff').is_mount(), False)
-
- def test_is_symlink(self):
- P = self.cls(BASE)
- self.assertFalse((P / 'fileA').is_symlink())
- self.assertFalse((P / 'dirA').is_symlink())
- self.assertFalse((P / 'non-existing').is_symlink())
- self.assertFalse((P / 'fileA' / 'bah').is_symlink())
- if os_helper.can_symlink():
- self.assertTrue((P / 'linkA').is_symlink())
- self.assertTrue((P / 'linkB').is_symlink())
- self.assertTrue((P/ 'brokenLink').is_symlink())
- self.assertIs((P / 'fileA\udfff').is_file(), False)
- self.assertIs((P / 'fileA\x00').is_file(), False)
- if os_helper.can_symlink():
- self.assertIs((P / 'linkA\udfff').is_file(), False)
- self.assertIs((P / 'linkA\x00').is_file(), False)
+ p = P / 'fileA'
+ # linking to another path.
+ q = P / 'dirA' / 'fileAA'
+ with self.assertRaises(pathlib.UnsupportedOperation):
+ q.symlink_to(p)
def test_is_junction(self):
P = self.cls(BASE)
@@ -2639,15 +2852,6 @@ def test_is_junction(self):
self.assertEqual(P.is_junction(), P._flavour.isjunction.return_value)
P._flavour.isjunction.assert_called_once_with(P)
- def test_is_fifo_false(self):
- P = self.cls(BASE)
- self.assertFalse((P / 'fileA').is_fifo())
- self.assertFalse((P / 'dirA').is_fifo())
- self.assertFalse((P / 'non-existing').is_fifo())
- self.assertFalse((P / 'fileA' / 'bah').is_fifo())
- self.assertIs((P / 'fileA\udfff').is_fifo(), False)
- self.assertIs((P / 'fileA\x00').is_fifo(), False)
-
@unittest.skipUnless(hasattr(os, "mkfifo"), "os.mkfifo() required")
@unittest.skipIf(sys.platform == "vxworks",
"fifo requires special path on VxWorks")
@@ -2663,15 +2867,6 @@ def test_is_fifo_true(self):
self.assertIs(self.cls(BASE, 'myfifo\udfff').is_fifo(), False)
self.assertIs(self.cls(BASE, 'myfifo\x00').is_fifo(), False)
- def test_is_socket_false(self):
- P = self.cls(BASE)
- self.assertFalse((P / 'fileA').is_socket())
- self.assertFalse((P / 'dirA').is_socket())
- self.assertFalse((P / 'non-existing').is_socket())
- self.assertFalse((P / 'fileA' / 'bah').is_socket())
- self.assertIs((P / 'fileA\udfff').is_socket(), False)
- self.assertIs((P / 'fileA\x00').is_socket(), False)
-
@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
@unittest.skipIf(
is_emscripten, "Unix sockets are not implemented on Emscripten."
@@ -2695,24 +2890,6 @@ def test_is_socket_true(self):
self.assertIs(self.cls(BASE, 'mysock\udfff').is_socket(), False)
self.assertIs(self.cls(BASE, 'mysock\x00').is_socket(), False)
- def test_is_block_device_false(self):
- P = self.cls(BASE)
- self.assertFalse((P / 'fileA').is_block_device())
- self.assertFalse((P / 'dirA').is_block_device())
- self.assertFalse((P / 'non-existing').is_block_device())
- self.assertFalse((P / 'fileA' / 'bah').is_block_device())
- self.assertIs((P / 'fileA\udfff').is_block_device(), False)
- self.assertIs((P / 'fileA\x00').is_block_device(), False)
-
- def test_is_char_device_false(self):
- P = self.cls(BASE)
- self.assertFalse((P / 'fileA').is_char_device())
- self.assertFalse((P / 'dirA').is_char_device())
- self.assertFalse((P / 'non-existing').is_char_device())
- self.assertFalse((P / 'fileA' / 'bah').is_char_device())
- self.assertIs((P / 'fileA\udfff').is_char_device(), False)
- self.assertIs((P / 'fileA\x00').is_char_device(), False)
-
def test_is_char_device_true(self):
# Under Unix, /dev/null should generally be a char device.
P = self.cls('/dev/null')
@@ -2724,74 +2901,13 @@ def test_is_char_device_true(self):
self.assertIs(self.cls('/dev/null\udfff').is_char_device(), False)
self.assertIs(self.cls('/dev/null\x00').is_char_device(), False)
- def test_pickling_common(self):
- p = self.cls(BASE, 'fileA')
- for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
- dumped = pickle.dumps(p, proto)
- pp = pickle.loads(dumped)
- self.assertEqual(pp.stat(), p.stat())
-
- def test_parts_interning(self):
- P = self.cls
- p = P('/usr/bin/foo')
- q = P('/usr/local/bin')
- # 'usr'
- self.assertIs(p.parts[1], q.parts[1])
- # 'bin'
- self.assertIs(p.parts[2], q.parts[3])
-
- def _check_complex_symlinks(self, link0_target):
- # Test solving a non-looping chain of symlinks (issue #19887).
- P = self.cls(BASE)
- self.dirlink(os.path.join('link0', 'link0'), join('link1'))
- self.dirlink(os.path.join('link1', 'link1'), join('link2'))
- self.dirlink(os.path.join('link2', 'link2'), join('link3'))
- self.dirlink(link0_target, join('link0'))
-
- # Resolve absolute paths.
- p = (P / 'link0').resolve()
- self.assertEqual(p, P)
- self.assertEqualNormCase(str(p), BASE)
- p = (P / 'link1').resolve()
- self.assertEqual(p, P)
- self.assertEqualNormCase(str(p), BASE)
- p = (P / 'link2').resolve()
- self.assertEqual(p, P)
- self.assertEqualNormCase(str(p), BASE)
- p = (P / 'link3').resolve()
- self.assertEqual(p, P)
- self.assertEqualNormCase(str(p), BASE)
-
- # Resolve relative paths.
- old_path = os.getcwd()
- os.chdir(BASE)
- try:
- p = self.cls('link0').resolve()
- self.assertEqual(p, P)
- self.assertEqualNormCase(str(p), BASE)
- p = self.cls('link1').resolve()
- self.assertEqual(p, P)
- self.assertEqualNormCase(str(p), BASE)
- p = self.cls('link2').resolve()
- self.assertEqual(p, P)
- self.assertEqualNormCase(str(p), BASE)
- p = self.cls('link3').resolve()
- self.assertEqual(p, P)
- self.assertEqualNormCase(str(p), BASE)
- finally:
- os.chdir(old_path)
-
- @os_helper.skip_unless_symlink
- def test_complex_symlinks_absolute(self):
- self._check_complex_symlinks(BASE)
-
- @os_helper.skip_unless_symlink
- def test_complex_symlinks_relative(self):
- self._check_complex_symlinks('.')
-
- @os_helper.skip_unless_symlink
- def test_complex_symlinks_relative_dot_dot(self):
- self._check_complex_symlinks(os.path.join('dirA', '..'))
+ def test_is_mount_root(self):
+ if os.name == 'nt':
+ R = self.cls('c:\\')
+ else:
+ R = self.cls('/')
+ self.assertTrue(R.is_mount())
+ self.assertFalse((R / '\udfff').is_mount())
def test_passing_kwargs_deprecated(self):
with self.assertWarns(DeprecationWarning):
@@ -3022,28 +3138,8 @@ def test_walk_above_recursion_limit(self):
list(base.walk(top_down=False))
-class PathTest(_BasePathTest, unittest.TestCase):
- cls = pathlib.Path
-
- def test_concrete_class(self):
- p = self.cls('a')
- self.assertIs(type(p),
- pathlib.WindowsPath if os.name == 'nt' else pathlib.PosixPath)
-
- def test_unsupported_flavour(self):
- if os.name == 'nt':
- self.assertRaises(NotImplementedError, pathlib.PosixPath)
- else:
- self.assertRaises(NotImplementedError, pathlib.WindowsPath)
-
- def test_glob_empty_pattern(self):
- p = self.cls()
- with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'):
- list(p.glob(''))
-
-
@only_posix
-class PosixPathTest(_BasePathTest, unittest.TestCase):
+class PosixPathTest(PathTest):
cls = pathlib.PosixPath
def test_absolute(self):
@@ -3108,8 +3204,9 @@ def test_touch_mode(self):
st = os.stat(join('masked_new_file'))
self.assertEqual(stat.S_IMODE(st.st_mode), 0o750)
- @os_helper.skip_unless_symlink
def test_resolve_loop(self):
+ if not self.can_symlink:
+ self.skipTest("symlinks required")
# Loops with relative symlinks.
os.symlink('linkX/inside', join('linkX'))
self._check_symlink_loop(BASE, 'linkX')
@@ -3227,7 +3324,7 @@ def test_handling_bad_descriptor(self):
@only_nt
-class WindowsPathTest(_BasePathTest, unittest.TestCase):
+class WindowsPathTest(PathTest):
cls = pathlib.WindowsPath
def test_absolute(self):
@@ -3345,15 +3442,8 @@ def check():
check()
-class PurePathSubclassTest(_BasePurePathTest, unittest.TestCase):
- class cls(pathlib.PurePath):
- pass
-
- # repr() roundtripping is not supported in custom subclass.
- test_repr_roundtrips = None
-
-class PathSubclassTest(_BasePathTest, unittest.TestCase):
+class PathSubclassTest(PathTest):
class cls(pathlib.Path):
pass
diff --git a/Lib/test/test_patma.py b/Lib/test/test_patma.py
index 3dbd19dfffd318..dedbc828784184 100644
--- a/Lib/test/test_patma.py
+++ b/Lib/test/test_patma.py
@@ -2460,12 +2460,27 @@ class Eq:
def __eq__(self, other):
return True
x = eq = Eq()
+ # None
y = None
match x:
case None:
y = 0
self.assertIs(x, eq)
self.assertEqual(y, None)
+ # True
+ y = None
+ match x:
+ case True:
+ y = 0
+ self.assertIs(x, eq)
+ self.assertEqual(y, None)
+ # False
+ y = None
+ match x:
+ case False:
+ y = 0
+ self.assertIs(x, eq)
+ self.assertEqual(y, None)
def test_patma_233(self):
x = False
@@ -2668,6 +2683,83 @@ def f(self, x):
setattr(c, "__attr", "spam") # setattr is needed because we're in a class scope
self.assertEqual(Outer().f(c), "spam")
+ def test_patma_250(self):
+ def f(x):
+ match x:
+ case {"foo": y} if y >= 0:
+ return True
+ case {"foo": y} if y < 0:
+ return False
+
+ self.assertIs(f({"foo": 1}), True)
+ self.assertIs(f({"foo": -1}), False)
+
+ def test_patma_251(self):
+ def f(v, x):
+ match v:
+ case x.attr if x.attr >= 0:
+ return True
+ case x.attr if x.attr < 0:
+ return False
+ case _:
+ return None
+
+ class X:
+ def __init__(self, attr):
+ self.attr = attr
+
+ self.assertIs(f(1, X(1)), True)
+ self.assertIs(f(-1, X(-1)), False)
+ self.assertIs(f(1, X(-1)), None)
+
+ def test_patma_252(self):
+ # Side effects must be possible in guards:
+ effects = []
+ def lt(x, y):
+ effects.append((x, y))
+ return x < y
+
+ res = None
+ match {"foo": 1}:
+ case {"foo": x} if lt(x, 0):
+ res = 0
+ case {"foo": x} if lt(x, 1):
+ res = 1
+ case {"foo": x} if lt(x, 2):
+ res = 2
+
+ self.assertEqual(res, 2)
+ self.assertEqual(effects, [(1, 0), (1, 1), (1, 2)])
+
+ def test_patma_253(self):
+ def f(v):
+ match v:
+ case [x] | x:
+ return x
+
+ self.assertEqual(f(1), 1)
+ self.assertEqual(f([1]), 1)
+
+ def test_patma_254(self):
+ def f(v):
+ match v:
+ case {"x": x} | x:
+ return x
+
+ self.assertEqual(f(1), 1)
+ self.assertEqual(f({"x": 1}), 1)
+
+ def test_patma_255(self):
+ x = []
+ match x:
+ case [] as z if z.append(None):
+ y = 0
+ case [None]:
+ y = 1
+ self.assertEqual(x, [None])
+ self.assertEqual(y, 1)
+ self.assertIs(z, x)
+
class TestSyntaxErrors(unittest.TestCase):
@@ -2885,6 +2977,37 @@ def test_real_number_required_in_complex_literal_3(self):
pass
""")
+ def test_real_number_multiple_ops(self):
+ self.assert_syntax_error("""
+ match ...:
+ case 0 + 0j + 0:
+ pass
+ """)
+
+ def test_real_number_wrong_ops(self):
+ for op in ["*", "/", "@", "**", "%", "//"]:
+ with self.subTest(op=op):
+ self.assert_syntax_error(f"""
+ match ...:
+ case 0 {op} 0j:
+ pass
+ """)
+ self.assert_syntax_error(f"""
+ match ...:
+ case 0j {op} 0:
+ pass
+ """)
+ self.assert_syntax_error(f"""
+ match ...:
+ case -0j {op} 0:
+ pass
+ """)
+ self.assert_syntax_error(f"""
+ match ...:
+ case 0j {op} -0:
+ pass
+ """)
+
def test_wildcard_makes_remaining_patterns_unreachable_0(self):
self.assert_syntax_error("""
match ...:
@@ -3067,6 +3190,14 @@ class Class:
self.assertIs(y, None)
self.assertIs(z, None)
+ def test_class_pattern_not_type(self):
+ w = None
+ with self.assertRaises(TypeError):
+ match 1:
+ case max(0, 1):
+ w = 0
+ self.assertIsNone(w)
+
class TestValueErrors(unittest.TestCase):
diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py
index 277400e152476f..a66953557e52dc 100644
--- a/Lib/test/test_pdb.py
+++ b/Lib/test/test_pdb.py
@@ -389,7 +389,7 @@ def test_pdb_breakpoints_preserved_across_interactive_sessions():
1 breakpoint keep yes at ...test_pdb.py:...
2 breakpoint keep yes at ...test_pdb.py:...
(Pdb) break pdb.find_function
- Breakpoint 3 at ...pdb.py:97
+ Breakpoint 3 at ...pdb.py:...
(Pdb) break
Num Type Disp Enb Where
1 breakpoint keep yes at ...test_pdb.py:...
@@ -1589,6 +1589,32 @@ def test_pdb_next_command_subiterator():
(Pdb) continue
"""
+def test_pdb_multiline_statement():
+ """Test for multiline statement
+
+ >>> def test_function():
+ ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
+ ... pass
+
+ >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE
+ ... 'def f(x):',
+ ... ' return x * 2',
+ ... '',
+ ... 'f(2)',
+ ... 'c'
+ ... ]):
+ ... test_function()
+ >
(3)test_function()
+ -> pass
+ (Pdb) def f(x):
+ ... return x * 2
+ ...
+ (Pdb) f(2)
+ 4
+ (Pdb) c
+ """
+
+
def test_pdb_issue_20766():
"""Test for reference leaks when the SIGINT handler is set.
@@ -2362,7 +2388,7 @@ def test_relative_imports_on_plain_module(self):
def test_errors_in_command(self):
commands = "\n".join([
- 'print(',
+ 'print(]',
'debug print(',
'debug doesnotexist',
'c',
@@ -2371,7 +2397,8 @@ def test_errors_in_command(self):
self.assertEqual(stdout.splitlines()[1:], [
'-> pass',
- '(Pdb) *** SyntaxError: \'(\' was never closed',
+ "(Pdb) *** SyntaxError: closing parenthesis ']' does not match opening "
+ "parenthesis '('",
'(Pdb) ENTERING RECURSIVE DEBUGGER',
'*** SyntaxError: \'(\' was never closed',
diff --git a/Lib/test/test_peg_generator/test_c_parser.py b/Lib/test/test_peg_generator/test_c_parser.py
index af39faeba94357..f9105a9f23bd6d 100644
--- a/Lib/test/test_peg_generator/test_c_parser.py
+++ b/Lib/test/test_peg_generator/test_c_parser.py
@@ -74,8 +74,18 @@ def test_parse(self):
@support.requires_subprocess()
class TestCParser(unittest.TestCase):
+ _has_run = False
+
@classmethod
def setUpClass(cls):
+ if cls._has_run:
+ # Since gh-104798 (Use setuptools in peg-generator and reenable
+ # tests), this test case has been producing ref leaks. Initial
+ # debugging points to bug(s) in setuptools and/or importlib.
+ # See gh-105063 for more info.
+ raise unittest.SkipTest("gh-105063: can not rerun because of ref. leaks")
+ cls._has_run = True
+
# When running under regtest, a separate tempdir is used
# as the current directory and watched for left-overs.
# Reusing that as the base for temporary directories
diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py
index cefc71cb5a7f54..ddb5187f90da9b 100644
--- a/Lib/test/test_pydoc.py
+++ b/Lib/test/test_pydoc.py
@@ -24,7 +24,8 @@
from urllib.request import urlopen, urlcleanup
from test.support import import_helper
from test.support import os_helper
-from test.support.script_helper import assert_python_ok, assert_python_failure
+from test.support.script_helper import (assert_python_ok,
+ assert_python_failure, spawn_python)
from test.support import threading_helper
from test.support import (reap_children, captured_output, captured_stdout,
captured_stderr, is_emscripten, is_wasi,
@@ -631,6 +632,21 @@ def test_builtin_on_metaclasses(self):
# Testing that the subclasses section does not appear
self.assertNotIn('Built-in subclasses', text)
+ def test_fail_help_cli(self):
+ elines = (missing_pattern % 'abd').splitlines()
+ with spawn_python("-c" "help()") as proc:
+ out, _ = proc.communicate(b"abd")
+ olines = out.decode().splitlines()[-9:-6]
+ olines[0] = olines[0].removeprefix('help> ')
+ self.assertEqual(elines, olines)
+
+ def test_fail_help_output_redirect(self):
+ with StringIO() as buf:
+ helper = pydoc.Helper(output=buf)
+ helper.help("abd")
+ expected = missing_pattern % "abd"
+ self.assertEqual(expected, buf.getvalue().strip().replace('\n', os.linesep))
+
@unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(),
'trace function introduces __locals__ unexpectedly')
@requires_docstrings
diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py
index 11628a236ade9a..a6f5af17d7d51b 100644
--- a/Lib/test/test_re.py
+++ b/Lib/test/test_re.py
@@ -1,7 +1,7 @@
from test.support import (gc_collect, bigmemtest, _2G,
cpython_only, captured_stdout,
check_disallow_instantiation, is_emscripten, is_wasi,
- SHORT_TIMEOUT)
+ warnings_helper, SHORT_TIMEOUT)
import locale
import re
import string
@@ -1046,33 +1046,6 @@ def test_ignore_case_range(self):
def test_category(self):
self.assertEqual(re.match(r"(\s)", " ").group(1), " ")
- @cpython_only
- def test_case_helpers(self):
- import _sre
- for i in range(128):
- c = chr(i)
- lo = ord(c.lower())
- self.assertEqual(_sre.ascii_tolower(i), lo)
- self.assertEqual(_sre.unicode_tolower(i), lo)
- iscased = c in string.ascii_letters
- self.assertEqual(_sre.ascii_iscased(i), iscased)
- self.assertEqual(_sre.unicode_iscased(i), iscased)
-
- for i in list(range(128, 0x1000)) + [0x10400, 0x10428]:
- c = chr(i)
- self.assertEqual(_sre.ascii_tolower(i), i)
- if i != 0x0130:
- self.assertEqual(_sre.unicode_tolower(i), ord(c.lower()))
- iscased = c != c.lower() or c != c.upper()
- self.assertFalse(_sre.ascii_iscased(i))
- self.assertEqual(_sre.unicode_iscased(i),
- c != c.lower() or c != c.upper())
-
- self.assertEqual(_sre.ascii_tolower(0x0130), 0x0130)
- self.assertEqual(_sre.unicode_tolower(0x0130), ord('i'))
- self.assertFalse(_sre.ascii_iscased(0x0130))
- self.assertTrue(_sre.unicode_iscased(0x0130))
-
def test_not_literal(self):
self.assertEqual(re.search(r"\s([^a])", " b").group(1), "b")
self.assertEqual(re.search(r"\s([^a]*)", " bb").group(1), "bb")
@@ -1522,10 +1495,11 @@ def test_bug_6561(self):
for x in not_decimal_digits:
self.assertIsNone(re.match(r'^\d$', x))
+ @warnings_helper.ignore_warnings(category=DeprecationWarning) # gh-80480 array('u')
def test_empty_array(self):
# SF buf 1647541
import array
- for typecode in 'bBuhHiIlLfd':
+ for typecode in 'bBhuwHiIlLfd':
a = array.array(typecode)
self.assertIsNone(re.compile(b"bla").match(a))
self.assertEqual(re.compile(b"").match(a).groups(), ())
@@ -1769,20 +1743,6 @@ def test_bug_6509(self):
pat = re.compile(b'..')
self.assertEqual(pat.sub(lambda m: b'bytes', b'a5'), b'bytes')
- def test_dealloc(self):
- # issue 3299: check for segfault in debug build
- import _sre
- # the overflow limit is different on wide and narrow builds and it
- # depends on the definition of SRE_CODE (see sre.h).
- # 2**128 should be big enough to overflow on both. For smaller values
- # a RuntimeError is raised instead of OverflowError.
- long_overflow = 2**128
- self.assertRaises(TypeError, re.finditer, "a", {})
- with self.assertRaises(OverflowError):
- _sre.compile("abc", 0, [long_overflow], 0, {}, ())
- with self.assertRaises(TypeError):
- _sre.compile({}, 0, [], 0, [], [])
-
def test_search_dot_unicode(self):
self.assertTrue(re.search("123.*-", '123abc-'))
self.assertTrue(re.search("123.*-", '123\xe9-'))
@@ -1840,21 +1800,6 @@ def test_repeat_minmax_overflow(self):
self.assertRaises(OverflowError, re.compile, r".{%d,}?" % 2**128)
self.assertRaises(OverflowError, re.compile, r".{%d,%d}" % (2**129, 2**128))
- @cpython_only
- def test_repeat_minmax_overflow_maxrepeat(self):
- try:
- from _sre import MAXREPEAT
- except ImportError:
- self.skipTest('requires _sre.MAXREPEAT constant')
- string = "x" * 100000
- self.assertIsNone(re.match(r".{%d}" % (MAXREPEAT - 1), string))
- self.assertEqual(re.match(r".{,%d}" % (MAXREPEAT - 1), string).span(),
- (0, 100000))
- self.assertIsNone(re.match(r".{%d,}?" % (MAXREPEAT - 1), string))
- self.assertRaises(OverflowError, re.compile, r".{%d}" % MAXREPEAT)
- self.assertRaises(OverflowError, re.compile, r".{,%d}" % MAXREPEAT)
- self.assertRaises(OverflowError, re.compile, r".{%d,}?" % MAXREPEAT)
-
def test_backref_group_name_in_exception(self):
# Issue 17341: Poor error message when compiling invalid regex
self.checkPatternError('(?P=)',
@@ -2397,30 +2342,6 @@ def test_bug_gh91616(self):
self.assertTrue(re.fullmatch(r'(?s:(?>.*?\.).*)\Z', "a.txt")) # reproducer
self.assertTrue(re.fullmatch(r'(?s:(?=(?P.*?\.))(?P=g0).*)\Z', "a.txt"))
- def test_template_function_and_flag_is_deprecated(self):
- with self.assertWarns(DeprecationWarning) as cm:
- template_re1 = re.template(r'a')
- self.assertIn('re.template()', str(cm.warning))
- self.assertIn('is deprecated', str(cm.warning))
- self.assertIn('function', str(cm.warning))
- self.assertNotIn('flag', str(cm.warning))
-
- with self.assertWarns(DeprecationWarning) as cm:
- # we deliberately use more flags here to test that that still
- # triggers the warning
- # if paranoid, we could test multiple different combinations,
- # but it's probably not worth it
- template_re2 = re.compile(r'a', flags=re.TEMPLATE|re.UNICODE)
- self.assertIn('re.TEMPLATE', str(cm.warning))
- self.assertIn('is deprecated', str(cm.warning))
- self.assertIn('flag', str(cm.warning))
- self.assertNotIn('function', str(cm.warning))
-
- # while deprecated, is should still function
- self.assertEqual(template_re1, template_re2)
- self.assertTrue(template_re1.match('ahoy'))
- self.assertFalse(template_re1.match('nope'))
-
@unittest.skipIf(multiprocessing is None, 'test requires multiprocessing')
def test_regression_gh94675(self):
pattern = re.compile(r'(?<=[({}])(((//[^\n]*)?[\n])([\000-\040])*)*'
@@ -2502,7 +2423,10 @@ def test_debug_flag(self):
def test_atomic_group(self):
self.assertEqual(get_debug_out(r'(?>ab?)'), '''\
-ATOMIC_GROUP [(LITERAL, 97), (MAX_REPEAT, (0, 1, [(LITERAL, 98)]))]
+ATOMIC_GROUP
+ LITERAL 97
+ MAX_REPEAT 0 1
+ LITERAL 98
0. INFO 4 0b0 1 2 (to 5)
5: ATOMIC_GROUP 11 (to 17)
@@ -2614,11 +2538,11 @@ def test_flags_repr(self):
"re.IGNORECASE|re.DOTALL|re.VERBOSE|0x100000")
self.assertEqual(
repr(~re.I),
- "re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.DOTALL|re.VERBOSE|re.TEMPLATE|re.DEBUG")
+ "re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.DOTALL|re.VERBOSE|re.DEBUG|0x1")
self.assertEqual(repr(~(re.I|re.S|re.X)),
- "re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.TEMPLATE|re.DEBUG")
+ "re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.DEBUG|0x1")
self.assertEqual(repr(~(re.I|re.S|re.X|(1<<20))),
- "re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.TEMPLATE|re.DEBUG|0xffe00")
+ "re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.DEBUG|0xffe01")
class ImplementationTest(unittest.TestCase):
@@ -2686,6 +2610,75 @@ def test_deprecated_modules(self):
self.assertTrue(hasattr(mod, attr))
del sys.modules[name]
+ @cpython_only
+ def test_case_helpers(self):
+ import _sre
+ for i in range(128):
+ c = chr(i)
+ lo = ord(c.lower())
+ self.assertEqual(_sre.ascii_tolower(i), lo)
+ self.assertEqual(_sre.unicode_tolower(i), lo)
+ iscased = c in string.ascii_letters
+ self.assertEqual(_sre.ascii_iscased(i), iscased)
+ self.assertEqual(_sre.unicode_iscased(i), iscased)
+
+ for i in list(range(128, 0x1000)) + [0x10400, 0x10428]:
+ c = chr(i)
+ self.assertEqual(_sre.ascii_tolower(i), i)
+ if i != 0x0130:
+ self.assertEqual(_sre.unicode_tolower(i), ord(c.lower()))
+ iscased = c != c.lower() or c != c.upper()
+ self.assertFalse(_sre.ascii_iscased(i))
+ self.assertEqual(_sre.unicode_iscased(i),
+ c != c.lower() or c != c.upper())
+
+ self.assertEqual(_sre.ascii_tolower(0x0130), 0x0130)
+ self.assertEqual(_sre.unicode_tolower(0x0130), ord('i'))
+ self.assertFalse(_sre.ascii_iscased(0x0130))
+ self.assertTrue(_sre.unicode_iscased(0x0130))
+
+ @cpython_only
+ def test_dealloc(self):
+ # issue 3299: check for segfault in debug build
+ import _sre
+ # the overflow limit is different on wide and narrow builds and it
+ # depends on the definition of SRE_CODE (see sre.h).
+ # 2**128 should be big enough to overflow on both. For smaller values
+ # a RuntimeError is raised instead of OverflowError.
+ long_overflow = 2**128
+ self.assertRaises(TypeError, re.finditer, "a", {})
+ with self.assertRaises(OverflowError):
+ _sre.compile("abc", 0, [long_overflow], 0, {}, ())
+ with self.assertRaises(TypeError):
+ _sre.compile({}, 0, [], 0, [], [])
+
+ @cpython_only
+ def test_repeat_minmax_overflow_maxrepeat(self):
+ try:
+ from _sre import MAXREPEAT
+ except ImportError:
+ self.skipTest('requires _sre.MAXREPEAT constant')
+ string = "x" * 100000
+ self.assertIsNone(re.match(r".{%d}" % (MAXREPEAT - 1), string))
+ self.assertEqual(re.match(r".{,%d}" % (MAXREPEAT - 1), string).span(),
+ (0, 100000))
+ self.assertIsNone(re.match(r".{%d,}?" % (MAXREPEAT - 1), string))
+ self.assertRaises(OverflowError, re.compile, r".{%d}" % MAXREPEAT)
+ self.assertRaises(OverflowError, re.compile, r".{,%d}" % MAXREPEAT)
+ self.assertRaises(OverflowError, re.compile, r".{%d,}?" % MAXREPEAT)
+
+ @cpython_only
+ def test_sre_template_invalid_group_index(self):
+ # see gh-106524
+ import _sre
+ with self.assertRaises(TypeError) as cm:
+ _sre.template("", ["", -1, ""])
+ self.assertIn("invalid template", str(cm.exception))
+ with self.assertRaises(TypeError) as cm:
+ _sre.template("", ["", (), ""])
+ self.assertIn("an integer is required", str(cm.exception))
+
+
class ExternalTests(unittest.TestCase):
def test_re_benchmarks(self):
diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py
index ac49fbae847726..806b932a164df8 100644
--- a/Lib/test/test_regrtest.py
+++ b/Lib/test/test_regrtest.py
@@ -7,6 +7,7 @@
import contextlib
import glob
import io
+import locale
import os.path
import platform
import re
@@ -1551,6 +1552,41 @@ def test_leak_tmp_file(self):
f"files (1): mytmpfile",
output)
+ def test_mp_decode_error(self):
+ # gh-101634: If a worker stdout cannot be decoded, report a failed test
+ # and a non-zero exit code.
+ if sys.platform == 'win32':
+ encoding = locale.getencoding()
+ else:
+ encoding = sys.stdout.encoding
+ if encoding is None:
+ encoding = sys.__stdout__.encoding
+ if encoding is None:
+ self.skipTest(f"cannot get regrtest worker encoding")
+
+ nonascii = b"byte:\xa0\xa9\xff\n"
+ try:
+ nonascii.decode(encoding)
+ except UnicodeDecodeError:
+ pass
+ else:
+ self.skipTest(f"{encoding} can decode non-ASCII bytes {nonascii!a}")
+
+ code = textwrap.dedent(fr"""
+ import sys
+ # bytes which cannot be decoded from UTF-8
+ nonascii = {nonascii!a}
+ sys.stdout.buffer.write(nonascii)
+ sys.stdout.buffer.flush()
+ """)
+ testname = self.create_test(code=code)
+
+ output = self.run_tests("--fail-env-changed", "-v", "-j1", testname,
+ exitcode=EXITCODE_BAD_TEST)
+ self.check_executed_tests(output, [testname],
+ failed=[testname],
+ randomize=True)
+
class TestUtils(unittest.TestCase):
def test_format_duration(self):
diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py
index c2db88c203920a..4545cbadb796fd 100644
--- a/Lib/test/test_selectors.py
+++ b/Lib/test/test_selectors.py
@@ -223,6 +223,8 @@ def test_close(self):
self.assertRaises(RuntimeError, s.get_key, wr)
self.assertRaises(KeyError, mapping.__getitem__, rd)
self.assertRaises(KeyError, mapping.__getitem__, wr)
+ self.assertEqual(mapping.get(rd), None)
+ self.assertEqual(mapping.get(wr), None)
def test_get_key(self):
s = self.SELECTOR()
@@ -241,13 +243,17 @@ def test_get_map(self):
self.addCleanup(s.close)
rd, wr = self.make_socketpair()
+ sentinel = object()
keys = s.get_map()
self.assertFalse(keys)
self.assertEqual(len(keys), 0)
self.assertEqual(list(keys), [])
+ self.assertEqual(keys.get(rd), None)
+ self.assertEqual(keys.get(rd, sentinel), sentinel)
key = s.register(rd, selectors.EVENT_READ, "data")
self.assertIn(rd, keys)
+ self.assertEqual(key, keys.get(rd))
self.assertEqual(key, keys[rd])
self.assertEqual(len(keys), 1)
self.assertEqual(list(keys), [rd.fileno()])
diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py
index 878a21a629f3cc..93f20a6ff41332 100644
--- a/Lib/test/test_shutil.py
+++ b/Lib/test/test_shutil.py
@@ -2738,7 +2738,7 @@ def test_regular_copy(self):
def test_same_file(self):
self.addCleanup(self.reset)
with self.get_files() as (src, dst):
- with self.assertRaises(Exception):
+ with self.assertRaises((OSError, _GiveupOnFastCopy)):
self.zerocopy_fun(src, src)
# Make sure src file is not corrupted.
self.assertEqual(read_file(TESTFN, binary=True), self.FILEDATA)
diff --git a/Lib/test/test_sqlite3/test_backup.py b/Lib/test/test_sqlite3/test_backup.py
index 384dd9229ab341..87ab29c54d65e2 100644
--- a/Lib/test/test_sqlite3/test_backup.py
+++ b/Lib/test/test_sqlite3/test_backup.py
@@ -50,8 +50,6 @@ def test_bad_target_in_transaction(self):
bck.executemany('INSERT INTO bar (key) VALUES (?)', [(3,), (4,)])
with self.assertRaises(sqlite.OperationalError) as cm:
self.cx.backup(bck)
- if sqlite.sqlite_version_info < (3, 8, 8):
- self.assertEqual(str(cm.exception), 'target is in transaction')
def test_keyword_only_args(self):
with self.assertRaises(TypeError):
diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py
index 328b0467e7fa3d..3f9bd0248a8b96 100644
--- a/Lib/test/test_sqlite3/test_dbapi.py
+++ b/Lib/test/test_sqlite3/test_dbapi.py
@@ -165,6 +165,7 @@ def test_module_constants(self):
"SQLITE_INTERNAL",
"SQLITE_INTERRUPT",
"SQLITE_IOERR",
+ "SQLITE_LIMIT_WORKER_THREADS",
"SQLITE_LOCKED",
"SQLITE_MISMATCH",
"SQLITE_MISUSE",
@@ -172,6 +173,7 @@ def test_module_constants(self):
"SQLITE_NOMEM",
"SQLITE_NOTADB",
"SQLITE_NOTFOUND",
+ "SQLITE_NOTICE",
"SQLITE_OK",
"SQLITE_PERM",
"SQLITE_PRAGMA",
@@ -179,6 +181,7 @@ def test_module_constants(self):
"SQLITE_RANGE",
"SQLITE_READ",
"SQLITE_READONLY",
+ "SQLITE_RECURSIVE",
"SQLITE_REINDEX",
"SQLITE_ROW",
"SQLITE_SAVEPOINT",
@@ -187,6 +190,7 @@ def test_module_constants(self):
"SQLITE_TOOBIG",
"SQLITE_TRANSACTION",
"SQLITE_UPDATE",
+ "SQLITE_WARNING",
# Run-time limit categories
"SQLITE_LIMIT_LENGTH",
"SQLITE_LIMIT_SQL_LENGTH",
@@ -200,32 +204,43 @@ def test_module_constants(self):
"SQLITE_LIMIT_VARIABLE_NUMBER",
"SQLITE_LIMIT_TRIGGER_DEPTH",
]
- if sqlite.sqlite_version_info >= (3, 7, 17):
- consts += ["SQLITE_NOTICE", "SQLITE_WARNING"]
- if sqlite.sqlite_version_info >= (3, 8, 3):
- consts.append("SQLITE_RECURSIVE")
- if sqlite.sqlite_version_info >= (3, 8, 7):
- consts.append("SQLITE_LIMIT_WORKER_THREADS")
consts += ["PARSE_DECLTYPES", "PARSE_COLNAMES"]
# Extended result codes
consts += [
"SQLITE_ABORT_ROLLBACK",
+ "SQLITE_AUTH_USER",
"SQLITE_BUSY_RECOVERY",
+ "SQLITE_BUSY_SNAPSHOT",
+ "SQLITE_CANTOPEN_CONVPATH",
"SQLITE_CANTOPEN_FULLPATH",
"SQLITE_CANTOPEN_ISDIR",
"SQLITE_CANTOPEN_NOTEMPDIR",
+ "SQLITE_CONSTRAINT_CHECK",
+ "SQLITE_CONSTRAINT_COMMITHOOK",
+ "SQLITE_CONSTRAINT_FOREIGNKEY",
+ "SQLITE_CONSTRAINT_FUNCTION",
+ "SQLITE_CONSTRAINT_NOTNULL",
+ "SQLITE_CONSTRAINT_PRIMARYKEY",
+ "SQLITE_CONSTRAINT_ROWID",
+ "SQLITE_CONSTRAINT_TRIGGER",
+ "SQLITE_CONSTRAINT_UNIQUE",
+ "SQLITE_CONSTRAINT_VTAB",
"SQLITE_CORRUPT_VTAB",
"SQLITE_IOERR_ACCESS",
+ "SQLITE_IOERR_AUTH",
"SQLITE_IOERR_BLOCKED",
"SQLITE_IOERR_CHECKRESERVEDLOCK",
"SQLITE_IOERR_CLOSE",
+ "SQLITE_IOERR_CONVPATH",
"SQLITE_IOERR_DELETE",
"SQLITE_IOERR_DELETE_NOENT",
"SQLITE_IOERR_DIR_CLOSE",
"SQLITE_IOERR_DIR_FSYNC",
"SQLITE_IOERR_FSTAT",
"SQLITE_IOERR_FSYNC",
+ "SQLITE_IOERR_GETTEMPPATH",
"SQLITE_IOERR_LOCK",
+ "SQLITE_IOERR_MMAP",
"SQLITE_IOERR_NOMEM",
"SQLITE_IOERR_RDLOCK",
"SQLITE_IOERR_READ",
@@ -237,50 +252,18 @@ def test_module_constants(self):
"SQLITE_IOERR_SHORT_READ",
"SQLITE_IOERR_TRUNCATE",
"SQLITE_IOERR_UNLOCK",
+ "SQLITE_IOERR_VNODE",
"SQLITE_IOERR_WRITE",
"SQLITE_LOCKED_SHAREDCACHE",
+ "SQLITE_NOTICE_RECOVER_ROLLBACK",
+ "SQLITE_NOTICE_RECOVER_WAL",
+ "SQLITE_OK_LOAD_PERMANENTLY",
"SQLITE_READONLY_CANTLOCK",
+ "SQLITE_READONLY_DBMOVED",
"SQLITE_READONLY_RECOVERY",
+ "SQLITE_READONLY_ROLLBACK",
+ "SQLITE_WARNING_AUTOINDEX",
]
- if sqlite.sqlite_version_info >= (3, 7, 16):
- consts += [
- "SQLITE_CONSTRAINT_CHECK",
- "SQLITE_CONSTRAINT_COMMITHOOK",
- "SQLITE_CONSTRAINT_FOREIGNKEY",
- "SQLITE_CONSTRAINT_FUNCTION",
- "SQLITE_CONSTRAINT_NOTNULL",
- "SQLITE_CONSTRAINT_PRIMARYKEY",
- "SQLITE_CONSTRAINT_TRIGGER",
- "SQLITE_CONSTRAINT_UNIQUE",
- "SQLITE_CONSTRAINT_VTAB",
- "SQLITE_READONLY_ROLLBACK",
- ]
- if sqlite.sqlite_version_info >= (3, 7, 17):
- consts += [
- "SQLITE_IOERR_MMAP",
- "SQLITE_NOTICE_RECOVER_ROLLBACK",
- "SQLITE_NOTICE_RECOVER_WAL",
- ]
- if sqlite.sqlite_version_info >= (3, 8, 0):
- consts += [
- "SQLITE_BUSY_SNAPSHOT",
- "SQLITE_IOERR_GETTEMPPATH",
- "SQLITE_WARNING_AUTOINDEX",
- ]
- if sqlite.sqlite_version_info >= (3, 8, 1):
- consts += ["SQLITE_CANTOPEN_CONVPATH", "SQLITE_IOERR_CONVPATH"]
- if sqlite.sqlite_version_info >= (3, 8, 2):
- consts.append("SQLITE_CONSTRAINT_ROWID")
- if sqlite.sqlite_version_info >= (3, 8, 3):
- consts.append("SQLITE_READONLY_DBMOVED")
- if sqlite.sqlite_version_info >= (3, 8, 7):
- consts.append("SQLITE_AUTH_USER")
- if sqlite.sqlite_version_info >= (3, 9, 0):
- consts.append("SQLITE_IOERR_VNODE")
- if sqlite.sqlite_version_info >= (3, 10, 0):
- consts.append("SQLITE_IOERR_AUTH")
- if sqlite.sqlite_version_info >= (3, 14, 1):
- consts.append("SQLITE_OK_LOAD_PERMANENTLY")
if sqlite.sqlite_version_info >= (3, 21, 0):
consts += [
"SQLITE_IOERR_BEGIN_ATOMIC",
@@ -330,8 +313,6 @@ def test_error_code_on_exception(self):
self.assertEqual(e.sqlite_errorcode, err_code)
self.assertTrue(e.sqlite_errorname.startswith("SQLITE_CANTOPEN"))
- @unittest.skipIf(sqlite.sqlite_version_info <= (3, 7, 16),
- "Requires SQLite 3.7.16 or newer")
def test_extended_error_code_on_exception(self):
with memory_database() as con:
with con:
diff --git a/Lib/test/test_sqlite3/test_hooks.py b/Lib/test/test_sqlite3/test_hooks.py
index 21042b9bf106f7..89230c08cc9143 100644
--- a/Lib/test/test_sqlite3/test_hooks.py
+++ b/Lib/test/test_sqlite3/test_hooks.py
@@ -323,7 +323,7 @@ def test_trace_expanded_sql(self):
)
def test_trace_too_much_expanded_sql(self):
# If the expanded string is too large, we'll fall back to the
- # unexpanded SQL statement (for SQLite 3.14.0 and newer).
+ # unexpanded SQL statement.
# The resulting string length is limited by the runtime limit
# SQLITE_LIMIT_LENGTH.
template = "select 1 as a where a="
@@ -334,8 +334,6 @@ def test_trace_too_much_expanded_sql(self):
unexpanded_query = template + "?"
expected = [unexpanded_query]
- if sqlite.sqlite_version_info < (3, 14, 0):
- expected = []
with self.check_stmt_trace(cx, expected):
cx.execute(unexpanded_query, (bad_param,))
diff --git a/Lib/test/test_sqlite3/test_types.py b/Lib/test/test_sqlite3/test_types.py
index fde5f888e64009..66d27d21b8dc10 100644
--- a/Lib/test/test_sqlite3/test_types.py
+++ b/Lib/test/test_sqlite3/test_types.py
@@ -371,7 +371,6 @@ def test_cursor_description_insert(self):
self.assertIsNone(self.cur.description)
-@unittest.skipIf(sqlite.sqlite_version_info < (3, 8, 3), "CTEs not supported")
class CommonTableExpressionTests(unittest.TestCase):
def setUp(self):
diff --git a/Lib/test/test_sqlite3/test_userfunctions.py b/Lib/test/test_sqlite3/test_userfunctions.py
index 03d27531666c89..05c2fb3aa6f8f2 100644
--- a/Lib/test/test_sqlite3/test_userfunctions.py
+++ b/Lib/test/test_sqlite3/test_userfunctions.py
@@ -381,38 +381,22 @@ def append_result(arg):
# Regarding deterministic functions:
#
# Between 3.8.3 and 3.15.0, deterministic functions were only used to
- # optimize inner loops, so for those versions we can only test if the
- # sqlite machinery has factored out a call or not. From 3.15.0 and onward,
- # deterministic functions were permitted in WHERE clauses of partial
- # indices, which allows testing based on syntax, iso. the query optimizer.
- @unittest.skipIf(sqlite.sqlite_version_info < (3, 8, 3), "Requires SQLite 3.8.3 or higher")
+ # optimize inner loops. From 3.15.0 and onward, deterministic functions
+ # were permitted in WHERE clauses of partial indices, which allows testing
+ # based on syntax, iso. the query optimizer.
def test_func_non_deterministic(self):
mock = Mock(return_value=None)
self.con.create_function("nondeterministic", 0, mock, deterministic=False)
- if sqlite.sqlite_version_info < (3, 15, 0):
- self.con.execute("select nondeterministic() = nondeterministic()")
- self.assertEqual(mock.call_count, 2)
- else:
- with self.assertRaises(sqlite.OperationalError):
- self.con.execute("create index t on test(t) where nondeterministic() is not null")
+ with self.assertRaises(sqlite.OperationalError):
+ self.con.execute("create index t on test(t) where nondeterministic() is not null")
- @unittest.skipIf(sqlite.sqlite_version_info < (3, 8, 3), "Requires SQLite 3.8.3 or higher")
def test_func_deterministic(self):
mock = Mock(return_value=None)
self.con.create_function("deterministic", 0, mock, deterministic=True)
- if sqlite.sqlite_version_info < (3, 15, 0):
- self.con.execute("select deterministic() = deterministic()")
- self.assertEqual(mock.call_count, 1)
- else:
- try:
- self.con.execute("create index t on test(t) where deterministic() is not null")
- except sqlite.OperationalError:
- self.fail("Unexpected failure while creating partial index")
-
- @unittest.skipIf(sqlite.sqlite_version_info >= (3, 8, 3), "SQLite < 3.8.3 needed")
- def test_func_deterministic_not_supported(self):
- with self.assertRaises(sqlite.NotSupportedError):
- self.con.create_function("deterministic", 0, int, deterministic=True)
+ try:
+ self.con.execute("create index t on test(t) where deterministic() is not null")
+ except sqlite.OperationalError:
+ self.fail("Unexpected failure while creating partial index")
def test_func_deterministic_keyword_only(self):
with self.assertRaises(TypeError):
diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py
index 8cad71c7c34545..e92e986b293377 100644
--- a/Lib/test/test_stable_abi_ctypes.py
+++ b/Lib/test/test_stable_abi_ctypes.py
@@ -328,6 +328,7 @@ def test_windows_feature_macros(self):
"PyGetSetDescr_Type",
"PyImport_AddModule",
"PyImport_AddModuleObject",
+ "PyImport_AddModuleRef",
"PyImport_AppendInittab",
"PyImport_ExecCodeModule",
"PyImport_ExecCodeModuleEx",
@@ -397,6 +398,8 @@ def test_windows_feature_macros(self):
"PyMap_Type",
"PyMapping_Check",
"PyMapping_GetItemString",
+ "PyMapping_GetOptionalItem",
+ "PyMapping_GetOptionalItemString",
"PyMapping_HasKey",
"PyMapping_HasKeyString",
"PyMapping_Items",
@@ -508,6 +511,8 @@ def test_windows_feature_macros(self):
"PyObject_CheckReadBuffer",
"PyObject_ClearWeakRefs",
"PyObject_CopyData",
+ "PyObject_DelAttr",
+ "PyObject_DelAttrString",
"PyObject_DelItem",
"PyObject_DelItemString",
"PyObject_Dir",
@@ -528,6 +533,8 @@ def test_windows_feature_macros(self):
"PyObject_GetBuffer",
"PyObject_GetItem",
"PyObject_GetIter",
+ "PyObject_GetOptionalAttr",
+ "PyObject_GetOptionalAttrString",
"PyObject_GetTypeData",
"PyObject_HasAttr",
"PyObject_HasAttrString",
@@ -793,6 +800,7 @@ def test_windows_feature_macros(self):
"PyVectorcall_Call",
"PyVectorcall_NARGS",
"PyWeakref_GetObject",
+ "PyWeakref_GetRef",
"PyWeakref_NewProxy",
"PyWeakref_NewRef",
"PyWrapperDescr_Type",
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
index 51ba423a0f1c92..817eab0c8a7e19 100644
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -1692,6 +1692,14 @@ def test_run_with_pathlike_path_and_arguments(self):
res = subprocess.run(args)
self.assertEqual(res.returncode, 57)
+ @unittest.skipUnless(mswindows, "Maybe test trigger a leak on Ubuntu")
+ def test_run_with_an_empty_env(self):
+ # gh-105436: fix subprocess.run(..., env={}) broken on Windows
+ args = [sys.executable, "-c", 'pass']
+ # Ignore subprocess errors - we only care that the API doesn't
+ # raise an OSError
+ subprocess.run(args, env={})
+
def test_capture_output(self):
cp = self.run_python(("import sys;"
"sys.stdout.write('BDFL'); "
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py
index 477879db2fd493..f3d6cd7bad0eec 100644
--- a/Lib/test/test_syntax.py
+++ b/Lib/test/test_syntax.py
@@ -1621,6 +1621,22 @@
Traceback (most recent call last):
SyntaxError: Did you mean to use 'from ... import ...' instead?
+>>> import a, b,c from b
+Traceback (most recent call last):
+SyntaxError: Did you mean to use 'from ... import ...' instead?
+
+>>> import a.y.z, b.y.z, c.y.z from b.y.z
+Traceback (most recent call last):
+SyntaxError: Did you mean to use 'from ... import ...' instead?
+
+>>> import a,b,c from b as bar
+Traceback (most recent call last):
+SyntaxError: Did you mean to use 'from ... import ...' instead?
+
+>>> import a.y.z, b.y.z, c.y.z from b.y.z as bar
+Traceback (most recent call last):
+SyntaxError: Did you mean to use 'from ... import ...' instead?
+
# Check that we dont raise the "trailing comma" error if there is more
# input to the left of the valid part that we parsed.
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index d81501f6f1df6a..37f75ad54387a0 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -1557,7 +1557,7 @@ def delx(self): del self.__x
'10P' # PySequenceMethods
'2P' # PyBufferProcs
'6P'
- '1PI' # Specializer cache
+ '1PIP' # Specializer cache
)
class newstyleclass(object): pass
# Separate block for PyDictKeysObject with 8 keys and 5 entries
diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py
index 5603c3cdbf3c5e..4462b5c712d662 100644
--- a/Lib/test/test_sys_settrace.py
+++ b/Lib/test/test_sys_settrace.py
@@ -1614,8 +1614,30 @@ def func():
self.run_and_compare(func, EXPECTED_EVENTS)
- def test_settrace_error(self):
+ def test_correct_tracing_quickened_call_class_init(self):
+
+ class C:
+ def __init__(self):
+ self
+
+ def func():
+ C()
+ EXPECTED_EVENTS = [
+ (0, 'call'),
+ (1, 'line'),
+ (-3, 'call'),
+ (-2, 'line'),
+ (-2, 'return'),
+ (1, 'return')]
+
+ self.run_and_compare(func, EXPECTED_EVENTS)
+ # Quicken
+ for _ in range(100):
+ func()
+ self.run_and_compare(func, EXPECTED_EVENTS)
+
+ def test_settrace_error(self):
raised = False
def error_once(frame, event, arg):
nonlocal raised
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 9e4972ecb640df..4a91eef31c4b8b 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -251,6 +251,14 @@ def f(mutex):
#Issue 29376
self.assertTrue(threading._active[tid].is_alive())
self.assertRegex(repr(threading._active[tid]), '_DummyThread')
+
+ # Issue gh-106236:
+ with self.assertRaises(RuntimeError):
+ threading._active[tid].join()
+ threading._active[tid]._started.clear()
+ with self.assertRaises(RuntimeError):
+ threading._active[tid].is_alive()
+
del threading._active[tid]
# PyThreadState_SetAsyncExc() is a CPython-only gimmick, not (currently)
diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py
index 02cc3f43a66a67..3b5640abdb6b89 100644
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -14,6 +14,10 @@
import _testcapi
except ImportError:
_testcapi = None
+try:
+ import _testinternalcapi
+except ImportError:
+ _testinternalcapi = None
from test.support import skip_if_buggy_ucrt_strfptime
@@ -761,7 +765,8 @@ def test_short_times(self):
self.assertIs(lt.tm_zone, None)
-@unittest.skipIf(_testcapi is None, 'need the _testcapi module')
+@unittest.skipIf(_testcapi is None, 'need the _testinternalcapi module')
+@unittest.skipIf(_testinternalcapi is None, 'need the _testinternalcapi module')
class CPyTimeTestCase:
"""
Base class to test the C _PyTime_t API.
@@ -769,7 +774,7 @@ class CPyTimeTestCase:
OVERFLOW_SECONDS = None
def setUp(self):
- from _testcapi import SIZEOF_TIME_T
+ from _testinternalcapi import SIZEOF_TIME_T
bits = SIZEOF_TIME_T * 8 - 1
self.time_t_min = -2 ** bits
self.time_t_max = 2 ** bits - 1
@@ -897,39 +902,39 @@ class TestCPyTime(CPyTimeTestCase, unittest.TestCase):
OVERFLOW_SECONDS = math.ceil((2**63 + 1) / SEC_TO_NS)
def test_FromSeconds(self):
- from _testcapi import PyTime_FromSeconds
+ from _testinternalcapi import _PyTime_FromSeconds
- # PyTime_FromSeconds() expects a C int, reject values out of range
+ # _PyTime_FromSeconds() expects a C int, reject values out of range
def c_int_filter(secs):
return (_testcapi.INT_MIN <= secs <= _testcapi.INT_MAX)
- self.check_int_rounding(lambda secs, rnd: PyTime_FromSeconds(secs),
+ self.check_int_rounding(lambda secs, rnd: _PyTime_FromSeconds(secs),
lambda secs: secs * SEC_TO_NS,
value_filter=c_int_filter)
# test nan
for time_rnd, _ in ROUNDING_MODES:
with self.assertRaises(TypeError):
- PyTime_FromSeconds(float('nan'))
+ _PyTime_FromSeconds(float('nan'))
def test_FromSecondsObject(self):
- from _testcapi import PyTime_FromSecondsObject
+ from _testinternalcapi import _PyTime_FromSecondsObject
self.check_int_rounding(
- PyTime_FromSecondsObject,
+ _PyTime_FromSecondsObject,
lambda secs: secs * SEC_TO_NS)
self.check_float_rounding(
- PyTime_FromSecondsObject,
+ _PyTime_FromSecondsObject,
lambda ns: self.decimal_round(ns * SEC_TO_NS))
# test nan
for time_rnd, _ in ROUNDING_MODES:
with self.assertRaises(ValueError):
- PyTime_FromSecondsObject(float('nan'), time_rnd)
+ _PyTime_FromSecondsObject(float('nan'), time_rnd)
def test_AsSecondsDouble(self):
- from _testcapi import PyTime_AsSecondsDouble
+ from _testinternalcapi import _PyTime_AsSecondsDouble
def float_converter(ns):
if abs(ns) % SEC_TO_NS == 0:
@@ -937,14 +942,14 @@ def float_converter(ns):
else:
return float(ns) / SEC_TO_NS
- self.check_int_rounding(lambda ns, rnd: PyTime_AsSecondsDouble(ns),
+ self.check_int_rounding(lambda ns, rnd: _PyTime_AsSecondsDouble(ns),
float_converter,
NS_TO_SEC)
# test nan
for time_rnd, _ in ROUNDING_MODES:
with self.assertRaises(TypeError):
- PyTime_AsSecondsDouble(float('nan'))
+ _PyTime_AsSecondsDouble(float('nan'))
def create_decimal_converter(self, denominator):
denom = decimal.Decimal(denominator)
@@ -956,7 +961,7 @@ def converter(value):
return converter
def test_AsTimeval(self):
- from _testcapi import PyTime_AsTimeval
+ from _testinternalcapi import _PyTime_AsTimeval
us_converter = self.create_decimal_converter(US_TO_NS)
@@ -973,28 +978,28 @@ def seconds_filter(secs):
else:
seconds_filter = self.time_t_filter
- self.check_int_rounding(PyTime_AsTimeval,
+ self.check_int_rounding(_PyTime_AsTimeval,
timeval_converter,
NS_TO_SEC,
value_filter=seconds_filter)
- @unittest.skipUnless(hasattr(_testcapi, 'PyTime_AsTimespec'),
- 'need _testcapi.PyTime_AsTimespec')
+ @unittest.skipUnless(hasattr(_testinternalcapi, '_PyTime_AsTimespec'),
+ 'need _testinternalcapi._PyTime_AsTimespec')
def test_AsTimespec(self):
- from _testcapi import PyTime_AsTimespec
+ from _testinternalcapi import _PyTime_AsTimespec
def timespec_converter(ns):
return divmod(ns, SEC_TO_NS)
- self.check_int_rounding(lambda ns, rnd: PyTime_AsTimespec(ns),
+ self.check_int_rounding(lambda ns, rnd: _PyTime_AsTimespec(ns),
timespec_converter,
NS_TO_SEC,
value_filter=self.time_t_filter)
- @unittest.skipUnless(hasattr(_testcapi, 'PyTime_AsTimeval_clamp'),
- 'need _testcapi.PyTime_AsTimeval_clamp')
+ @unittest.skipUnless(hasattr(_testinternalcapi, '_PyTime_AsTimeval_clamp'),
+ 'need _testinternalcapi._PyTime_AsTimeval_clamp')
def test_AsTimeval_clamp(self):
- from _testcapi import PyTime_AsTimeval_clamp
+ from _testinternalcapi import _PyTime_AsTimeval_clamp
if sys.platform == 'win32':
from _testcapi import LONG_MIN, LONG_MAX
@@ -1005,7 +1010,7 @@ def test_AsTimeval_clamp(self):
tv_sec_min = self.time_t_min
for t in (_PyTime_MIN, _PyTime_MAX):
- ts = PyTime_AsTimeval_clamp(t, _PyTime.ROUND_CEILING)
+ ts = _PyTime_AsTimeval_clamp(t, _PyTime.ROUND_CEILING)
with decimal.localcontext() as context:
context.rounding = decimal.ROUND_CEILING
us = self.decimal_round(decimal.Decimal(t) / US_TO_NS)
@@ -1018,13 +1023,13 @@ def test_AsTimeval_clamp(self):
tv_usec = 0
self.assertEqual(ts, (tv_sec, tv_usec))
- @unittest.skipUnless(hasattr(_testcapi, 'PyTime_AsTimespec_clamp'),
- 'need _testcapi.PyTime_AsTimespec_clamp')
+ @unittest.skipUnless(hasattr(_testinternalcapi, '_PyTime_AsTimespec_clamp'),
+ 'need _testinternalcapi._PyTime_AsTimespec_clamp')
def test_AsTimespec_clamp(self):
- from _testcapi import PyTime_AsTimespec_clamp
+ from _testinternalcapi import _PyTime_AsTimespec_clamp
for t in (_PyTime_MIN, _PyTime_MAX):
- ts = PyTime_AsTimespec_clamp(t)
+ ts = _PyTime_AsTimespec_clamp(t)
tv_sec, tv_nsec = divmod(t, NS_TO_SEC)
if self.time_t_max < tv_sec:
tv_sec = self.time_t_max
@@ -1035,16 +1040,16 @@ def test_AsTimespec_clamp(self):
self.assertEqual(ts, (tv_sec, tv_nsec))
def test_AsMilliseconds(self):
- from _testcapi import PyTime_AsMilliseconds
+ from _testinternalcapi import _PyTime_AsMilliseconds
- self.check_int_rounding(PyTime_AsMilliseconds,
+ self.check_int_rounding(_PyTime_AsMilliseconds,
self.create_decimal_converter(MS_TO_NS),
NS_TO_SEC)
def test_AsMicroseconds(self):
- from _testcapi import PyTime_AsMicroseconds
+ from _testinternalcapi import _PyTime_AsMicroseconds
- self.check_int_rounding(PyTime_AsMicroseconds,
+ self.check_int_rounding(_PyTime_AsMicroseconds,
self.create_decimal_converter(US_TO_NS),
NS_TO_SEC)
@@ -1058,13 +1063,13 @@ class TestOldPyTime(CPyTimeTestCase, unittest.TestCase):
OVERFLOW_SECONDS = 2 ** 64
def test_object_to_time_t(self):
- from _testcapi import pytime_object_to_time_t
+ from _testinternalcapi import _PyTime_ObjectToTime_t
- self.check_int_rounding(pytime_object_to_time_t,
+ self.check_int_rounding(_PyTime_ObjectToTime_t,
lambda secs: secs,
value_filter=self.time_t_filter)
- self.check_float_rounding(pytime_object_to_time_t,
+ self.check_float_rounding(_PyTime_ObjectToTime_t,
self.decimal_round,
value_filter=self.time_t_filter)
@@ -1084,36 +1089,36 @@ def converter(secs):
return converter
def test_object_to_timeval(self):
- from _testcapi import pytime_object_to_timeval
+ from _testinternalcapi import _PyTime_ObjectToTimeval
- self.check_int_rounding(pytime_object_to_timeval,
+ self.check_int_rounding(_PyTime_ObjectToTimeval,
lambda secs: (secs, 0),
value_filter=self.time_t_filter)
- self.check_float_rounding(pytime_object_to_timeval,
+ self.check_float_rounding(_PyTime_ObjectToTimeval,
self.create_converter(SEC_TO_US),
value_filter=self.time_t_filter)
# test nan
for time_rnd, _ in ROUNDING_MODES:
with self.assertRaises(ValueError):
- pytime_object_to_timeval(float('nan'), time_rnd)
+ _PyTime_ObjectToTimeval(float('nan'), time_rnd)
def test_object_to_timespec(self):
- from _testcapi import pytime_object_to_timespec
+ from _testinternalcapi import _PyTime_ObjectToTimespec
- self.check_int_rounding(pytime_object_to_timespec,
+ self.check_int_rounding(_PyTime_ObjectToTimespec,
lambda secs: (secs, 0),
value_filter=self.time_t_filter)
- self.check_float_rounding(pytime_object_to_timespec,
+ self.check_float_rounding(_PyTime_ObjectToTimespec,
self.create_converter(SEC_TO_NS),
value_filter=self.time_t_filter)
# test nan
for time_rnd, _ in ROUNDING_MODES:
with self.assertRaises(ValueError):
- pytime_object_to_timespec(float('nan'), time_rnd)
+ _PyTime_ObjectToTimespec(float('nan'), time_rnd)
@unittest.skipUnless(sys.platform == "darwin", "test weak linking on macOS")
class TestTimeWeaklinking(unittest.TestCase):
diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py
index df9c9db322dc94..d1552d8a20808f 100644
--- a/Lib/test/test_tokenize.py
+++ b/Lib/test/test_tokenize.py
@@ -1,20 +1,15 @@
-from test import support
-from test.support import os_helper
-from tokenize import (tokenize, untokenize, NUMBER, NAME, OP,
- STRING, ENDMARKER, ENCODING, tok_name, detect_encoding,
- open as tokenize_open, Untokenizer, generate_tokens,
- NEWLINE, _generate_tokens_from_c_tokenizer, DEDENT, TokenInfo,
- TokenError)
-from io import BytesIO, StringIO
+import os
+import token
+import tokenize
import unittest
+from io import BytesIO, StringIO
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
-import os
-import token
# Converts a source string into a list of textual representation
# of the tokens such as:
@@ -26,12 +21,12 @@ def stringify_tokens_from_source(token_generator, source_string):
missing_trailing_nl = source_string[-1] not in '\r\n'
for type, token, start, end, line in token_generator:
- if type == ENDMARKER:
+ if type == tokenize.ENDMARKER:
break
# Ignore the new line on the last line if the input lacks one
- if missing_trailing_nl and type == NEWLINE and end[0] == num_lines:
+ if missing_trailing_nl and type == tokenize.NEWLINE and end[0] == num_lines:
continue
- type = tok_name[type]
+ type = tokenize.tok_name[type]
result.append(f" {type:10} {token!r:13} {start} {end}")
return result
@@ -47,7 +42,7 @@ def check_tokenize(self, s, expected):
# Format the tokens in s in a table format.
# The ENDMARKER and final NEWLINE are omitted.
f = BytesIO(s.encode('utf-8'))
- result = stringify_tokens_from_source(tokenize(f.readline), s)
+ result = stringify_tokens_from_source(tokenize.tokenize(f.readline), s)
self.assertEqual(result,
[" ENCODING 'utf-8' (0, 0) (0, 0)"] +
expected.rstrip().splitlines())
@@ -57,27 +52,27 @@ def gen():
yield "sdfosdg"
yield "sdfosdg"
with self.assertRaises(TypeError):
- list(tokenize(gen().__next__))
+ list(tokenize.tokenize(gen().__next__))
def gen():
yield b"sdfosdg"
yield b"sdfosdg"
with self.assertRaises(TypeError):
- list(generate_tokens(gen().__next__))
+ list(tokenize.generate_tokens(gen().__next__))
def gen():
yield "sdfosdg"
1/0
with self.assertRaises(ZeroDivisionError):
- list(generate_tokens(gen().__next__))
+ list(tokenize.generate_tokens(gen().__next__))
def test_implicit_newline(self):
# Make sure that the tokenizer puts in an implicit NEWLINE
# when the input lacks a trailing new line.
f = BytesIO("x".encode('utf-8'))
- tokens = list(tokenize(f.readline))
- self.assertEqual(tokens[-2].type, NEWLINE)
- self.assertEqual(tokens[-1].type, ENDMARKER)
+ tokens = list(tokenize.tokenize(f.readline))
+ self.assertEqual(tokens[-2].type, tokenize.NEWLINE)
+ self.assertEqual(tokens[-1].type, tokenize.ENDMARKER)
def test_basic(self):
self.check_tokenize("1 + 1", """\
@@ -139,7 +134,7 @@ def k(x):
with self.assertRaisesRegex(IndentationError,
"unindent does not match any "
"outer indentation level") as e:
- for tok in tokenize(readline):
+ for tok in tokenize.tokenize(readline):
pass
self.assertEqual(e.exception.lineno, 3)
self.assertEqual(e.exception.filename, '')
@@ -275,8 +270,8 @@ def test_float(self):
def test_underscore_literals(self):
def number_token(s):
f = BytesIO(s.encode('utf-8'))
- for toktype, token, start, end, line in tokenize(f.readline):
- if toktype == NUMBER:
+ for toktype, token, start, end, line in tokenize.tokenize(f.readline):
+ if toktype == tokenize.NUMBER:
return token
return 'invalid token'
for lit in VALID_UNDERSCORE_LITERALS:
@@ -292,7 +287,7 @@ def number_token(s):
continue
try:
number_token(lit)
- except TokenError:
+ except tokenize.TokenError:
continue
self.assertNotEqual(number_token(lit), lit)
@@ -558,6 +553,19 @@ def test_string(self):
OP '}' (1, 39) (1, 40)
FSTRING_MIDDLE ' final words' (1, 40) (1, 52)
FSTRING_END "'" (1, 52) (1, 53)
+ """)
+ self.check_tokenize("""\
+f'''{
+3
+=}'''""", """\
+ FSTRING_START "f'''" (1, 0) (1, 4)
+ OP '{' (1, 4) (1, 5)
+ NL '\\n' (1, 5) (1, 6)
+ NUMBER '3' (2, 0) (2, 1)
+ NL '\\n' (2, 1) (2, 2)
+ OP '=' (3, 0) (3, 1)
+ OP '}' (3, 1) (3, 2)
+ FSTRING_END "'''" (3, 2) (3, 5)
""")
def test_function(self):
@@ -1137,24 +1145,24 @@ def check_tokenize(self, s, expected):
# Format the tokens in s in a table format.
# The ENDMARKER and final NEWLINE are omitted.
f = StringIO(s)
- result = stringify_tokens_from_source(generate_tokens(f.readline), s)
+ result = stringify_tokens_from_source(tokenize.generate_tokens(f.readline), s)
self.assertEqual(result, expected.rstrip().splitlines())
def decistmt(s):
result = []
- g = tokenize(BytesIO(s.encode('utf-8')).readline) # tokenize the string
+ g = tokenize.tokenize(BytesIO(s.encode('utf-8')).readline) # tokenize the string
for toknum, tokval, _, _, _ in g:
- if toknum == NUMBER and '.' in tokval: # replace NUMBER tokens
+ if toknum == tokenize.NUMBER and '.' in tokval: # replace NUMBER tokens
result.extend([
- (NAME, 'Decimal'),
- (OP, '('),
- (STRING, repr(tokval)),
- (OP, ')')
+ (tokenize.NAME, 'Decimal'),
+ (tokenize.OP, '('),
+ (tokenize.STRING, repr(tokval)),
+ (tokenize.OP, ')')
])
else:
result.append((toknum, tokval))
- return untokenize(result).decode('utf-8').strip()
+ return tokenize.untokenize(result).decode('utf-8').strip()
class TestMisc(TestCase):
@@ -1178,6 +1186,13 @@ def test_decistmt(self):
self.assertEqual(eval(decistmt(s)),
Decimal('-3.217160342717258261933904529E-7'))
+ def test___all__(self):
+ expected = token.__all__ + [
+ "TokenInfo", "TokenError", "generate_tokens",
+ "detect_encoding", "untokenize", "open", "tokenize",
+ ]
+ self.assertCountEqual(tokenize.__all__, expected)
+
class TestTokenizerAdheresToPep0263(TestCase):
"""
@@ -1232,9 +1247,10 @@ def readline():
yield b''
# skip the initial encoding token and the end tokens
- tokens = list(_generate_tokens_from_c_tokenizer(readline().__next__, encoding='utf-8',
- extra_tokens=True))[:-2]
- expected_tokens = [TokenInfo(3, '"ЉЊЈЁЂ"', (1, 0), (1, 7), '"ЉЊЈЁЂ"')]
+ tokens = list(tokenize._generate_tokens_from_c_tokenizer(readline().__next__,
+ encoding='utf-8',
+ extra_tokens=True))[:-2]
+ expected_tokens = [tokenize.TokenInfo(3, '"ЉЊЈЁЂ"', (1, 0), (1, 7), '"ЉЊЈЁЂ"')]
self.assertEqual(tokens, expected_tokens,
"bytes not decoded with encoding")
@@ -1258,7 +1274,7 @@ def test_no_bom_no_encoding_cookie(self):
b'print(something)\n',
b'do_something(else)\n'
)
- encoding, consumed_lines = detect_encoding(self.get_readline(lines))
+ encoding, consumed_lines = tokenize.detect_encoding(self.get_readline(lines))
self.assertEqual(encoding, 'utf-8')
self.assertEqual(consumed_lines, list(lines[:2]))
@@ -1268,7 +1284,7 @@ def test_bom_no_cookie(self):
b'print(something)\n',
b'do_something(else)\n'
)
- encoding, consumed_lines = detect_encoding(self.get_readline(lines))
+ encoding, consumed_lines = tokenize.detect_encoding(self.get_readline(lines))
self.assertEqual(encoding, 'utf-8-sig')
self.assertEqual(consumed_lines,
[b'# something\n', b'print(something)\n'])
@@ -1279,7 +1295,7 @@ def test_cookie_first_line_no_bom(self):
b'print(something)\n',
b'do_something(else)\n'
)
- encoding, consumed_lines = detect_encoding(self.get_readline(lines))
+ encoding, consumed_lines = tokenize.detect_encoding(self.get_readline(lines))
self.assertEqual(encoding, 'iso-8859-1')
self.assertEqual(consumed_lines, [b'# -*- coding: latin-1 -*-\n'])
@@ -1289,7 +1305,7 @@ def test_matched_bom_and_cookie_first_line(self):
b'print(something)\n',
b'do_something(else)\n'
)
- encoding, consumed_lines = detect_encoding(self.get_readline(lines))
+ encoding, consumed_lines = tokenize.detect_encoding(self.get_readline(lines))
self.assertEqual(encoding, 'utf-8-sig')
self.assertEqual(consumed_lines, [b'# coding=utf-8\n'])
@@ -1300,7 +1316,7 @@ def test_mismatched_bom_and_cookie_first_line_raises_syntaxerror(self):
b'do_something(else)\n'
)
readline = self.get_readline(lines)
- self.assertRaises(SyntaxError, detect_encoding, readline)
+ self.assertRaises(SyntaxError, tokenize.detect_encoding, readline)
def test_cookie_second_line_no_bom(self):
lines = (
@@ -1309,7 +1325,7 @@ def test_cookie_second_line_no_bom(self):
b'print(something)\n',
b'do_something(else)\n'
)
- encoding, consumed_lines = detect_encoding(self.get_readline(lines))
+ encoding, consumed_lines = tokenize.detect_encoding(self.get_readline(lines))
self.assertEqual(encoding, 'ascii')
expected = [b'#! something\n', b'# vim: set fileencoding=ascii :\n']
self.assertEqual(consumed_lines, expected)
@@ -1321,7 +1337,7 @@ def test_matched_bom_and_cookie_second_line(self):
b'print(something)\n',
b'do_something(else)\n'
)
- encoding, consumed_lines = detect_encoding(self.get_readline(lines))
+ encoding, consumed_lines = tokenize.detect_encoding(self.get_readline(lines))
self.assertEqual(encoding, 'utf-8-sig')
self.assertEqual(consumed_lines,
[b'#! something\n', b'f# coding=utf-8\n'])
@@ -1334,7 +1350,7 @@ def test_mismatched_bom_and_cookie_second_line_raises_syntaxerror(self):
b'do_something(else)\n'
)
readline = self.get_readline(lines)
- self.assertRaises(SyntaxError, detect_encoding, readline)
+ self.assertRaises(SyntaxError, tokenize.detect_encoding, readline)
def test_cookie_second_line_noncommented_first_line(self):
lines = (
@@ -1342,7 +1358,7 @@ def test_cookie_second_line_noncommented_first_line(self):
b'# vim: set fileencoding=iso8859-15 :\n',
b"print('\xe2\x82\xac')\n"
)
- encoding, consumed_lines = detect_encoding(self.get_readline(lines))
+ encoding, consumed_lines = tokenize.detect_encoding(self.get_readline(lines))
self.assertEqual(encoding, 'utf-8')
expected = [b"print('\xc2\xa3')\n"]
self.assertEqual(consumed_lines, expected)
@@ -1353,7 +1369,7 @@ def test_cookie_second_line_commented_first_line(self):
b'# vim: set fileencoding=iso8859-15 :\n',
b"print('\xe2\x82\xac')\n"
)
- encoding, consumed_lines = detect_encoding(self.get_readline(lines))
+ encoding, consumed_lines = tokenize.detect_encoding(self.get_readline(lines))
self.assertEqual(encoding, 'iso8859-15')
expected = [b"#print('\xc2\xa3')\n", b'# vim: set fileencoding=iso8859-15 :\n']
self.assertEqual(consumed_lines, expected)
@@ -1364,7 +1380,7 @@ def test_cookie_second_line_empty_first_line(self):
b'# vim: set fileencoding=iso8859-15 :\n',
b"print('\xe2\x82\xac')\n"
)
- encoding, consumed_lines = detect_encoding(self.get_readline(lines))
+ encoding, consumed_lines = tokenize.detect_encoding(self.get_readline(lines))
self.assertEqual(encoding, 'iso8859-15')
expected = [b'\n', b'# vim: set fileencoding=iso8859-15 :\n']
self.assertEqual(consumed_lines, expected)
@@ -1381,7 +1397,7 @@ def test_latin1_normalization(self):
b"print(things)\n",
b"do_something += 4\n")
rl = self.get_readline(lines)
- found, consumed_lines = detect_encoding(rl)
+ found, consumed_lines = tokenize.detect_encoding(rl)
self.assertEqual(found, "iso-8859-1")
def test_syntaxerror_latin1(self):
@@ -1391,7 +1407,7 @@ def test_syntaxerror_latin1(self):
b'print("\xdf")', # Latin-1: LATIN SMALL LETTER SHARP S
)
readline = self.get_readline(lines)
- self.assertRaises(SyntaxError, detect_encoding, readline)
+ self.assertRaises(SyntaxError, tokenize.detect_encoding, readline)
def test_utf8_normalization(self):
@@ -1404,36 +1420,36 @@ def test_utf8_normalization(self):
b"# coding: " + enc.encode("ascii") + b"\n",
b"1 + 3\n")
rl = self.get_readline(lines)
- found, consumed_lines = detect_encoding(rl)
+ found, consumed_lines = tokenize.detect_encoding(rl)
self.assertEqual(found, "utf-8")
def test_short_files(self):
readline = self.get_readline((b'print(something)\n',))
- encoding, consumed_lines = detect_encoding(readline)
+ encoding, consumed_lines = tokenize.detect_encoding(readline)
self.assertEqual(encoding, 'utf-8')
self.assertEqual(consumed_lines, [b'print(something)\n'])
- encoding, consumed_lines = detect_encoding(self.get_readline(()))
+ encoding, consumed_lines = tokenize.detect_encoding(self.get_readline(()))
self.assertEqual(encoding, 'utf-8')
self.assertEqual(consumed_lines, [])
readline = self.get_readline((b'\xef\xbb\xbfprint(something)\n',))
- encoding, consumed_lines = detect_encoding(readline)
+ encoding, consumed_lines = tokenize.detect_encoding(readline)
self.assertEqual(encoding, 'utf-8-sig')
self.assertEqual(consumed_lines, [b'print(something)\n'])
readline = self.get_readline((b'\xef\xbb\xbf',))
- encoding, consumed_lines = detect_encoding(readline)
+ encoding, consumed_lines = tokenize.detect_encoding(readline)
self.assertEqual(encoding, 'utf-8-sig')
self.assertEqual(consumed_lines, [])
readline = self.get_readline((b'# coding: bad\n',))
- self.assertRaises(SyntaxError, detect_encoding, readline)
+ self.assertRaises(SyntaxError, tokenize.detect_encoding, readline)
def test_false_encoding(self):
# Issue 18873: "Encoding" detected in non-comment lines
readline = self.get_readline((b'print("#coding=fake")',))
- encoding, consumed_lines = detect_encoding(readline)
+ encoding, consumed_lines = tokenize.detect_encoding(readline)
self.assertEqual(encoding, 'utf-8')
self.assertEqual(consumed_lines, [b'print("#coding=fake")'])
@@ -1446,14 +1462,14 @@ def test_open(self):
with open(filename, 'w', encoding=encoding) as fp:
print("# coding: %s" % encoding, file=fp)
print("print('euro:\u20ac')", file=fp)
- with tokenize_open(filename) as fp:
+ with tokenize.open(filename) as fp:
self.assertEqual(fp.encoding, encoding)
self.assertEqual(fp.mode, 'r')
# test BOM (no coding cookie)
with open(filename, 'w', encoding='utf-8-sig') as fp:
print("print('euro:\u20ac')", file=fp)
- with tokenize_open(filename) as fp:
+ with tokenize.open(filename) as fp:
self.assertEqual(fp.encoding, 'utf-8-sig')
self.assertEqual(fp.mode, 'r')
@@ -1480,16 +1496,16 @@ def readline(self):
ins = Bunk(lines, path)
# Make sure lacking a name isn't an issue.
del ins.name
- detect_encoding(ins.readline)
+ tokenize.detect_encoding(ins.readline)
with self.assertRaisesRegex(SyntaxError, '.*{}'.format(path)):
ins = Bunk(lines, path)
- detect_encoding(ins.readline)
+ tokenize.detect_encoding(ins.readline)
def test_open_error(self):
# Issue #23840: open() must close the binary file on error
m = BytesIO(b'#coding:xxx')
with mock.patch('tokenize._builtin_open', return_value=m):
- self.assertRaises(SyntaxError, tokenize_open, 'foobar')
+ self.assertRaises(SyntaxError, tokenize.open, 'foobar')
self.assertTrue(m.closed)
@@ -1529,7 +1545,7 @@ def mock_readline():
tokenize_module.detect_encoding = mock_detect_encoding
tokenize_module._generate_tokens_from_c_tokenizer = mock__tokenize
try:
- results = tokenize(mock_readline)
+ results = tokenize.tokenize(mock_readline)
self.assertEqual(list(results)[1:],
[b'first', b'second', b'1', b'2', b'3', b'4'])
finally:
@@ -1546,23 +1562,23 @@ def test_oneline_defs(self):
buf = '\n'.join(buf)
# Test that 500 consequent, one-line defs is OK
- toks = list(tokenize(BytesIO(buf.encode('utf-8')).readline))
+ toks = list(tokenize.tokenize(BytesIO(buf.encode('utf-8')).readline))
self.assertEqual(toks[-3].string, 'OK') # [-1] is always ENDMARKER
# [-2] is always NEWLINE
def assertExactTypeEqual(self, opstr, *optypes):
- tokens = list(tokenize(BytesIO(opstr.encode('utf-8')).readline))
+ tokens = list(tokenize.tokenize(BytesIO(opstr.encode('utf-8')).readline))
num_optypes = len(optypes)
self.assertEqual(len(tokens), 3 + num_optypes)
- self.assertEqual(tok_name[tokens[0].exact_type],
- tok_name[ENCODING])
+ self.assertEqual(tokenize.tok_name[tokens[0].exact_type],
+ tokenize.tok_name[tokenize.ENCODING])
for i in range(num_optypes):
- self.assertEqual(tok_name[tokens[i + 1].exact_type],
- tok_name[optypes[i]])
- self.assertEqual(tok_name[tokens[1 + num_optypes].exact_type],
- tok_name[token.NEWLINE])
- self.assertEqual(tok_name[tokens[2 + num_optypes].exact_type],
- tok_name[token.ENDMARKER])
+ self.assertEqual(tokenize.tok_name[tokens[i + 1].exact_type],
+ tokenize.tok_name[optypes[i]])
+ self.assertEqual(tokenize.tok_name[tokens[1 + num_optypes].exact_type],
+ tokenize.tok_name[token.NEWLINE])
+ self.assertEqual(tokenize.tok_name[tokens[2 + num_optypes].exact_type],
+ tokenize.tok_name[token.ENDMARKER])
def test_exact_type(self):
self.assertExactTypeEqual('()', token.LPAR, token.RPAR)
@@ -1612,11 +1628,11 @@ def test_exact_type(self):
self.assertExactTypeEqual('@=', token.ATEQUAL)
self.assertExactTypeEqual('a**2+b**2==c**2',
- NAME, token.DOUBLESTAR, NUMBER,
+ tokenize.NAME, token.DOUBLESTAR, tokenize.NUMBER,
token.PLUS,
- NAME, token.DOUBLESTAR, NUMBER,
+ tokenize.NAME, token.DOUBLESTAR, tokenize.NUMBER,
token.EQEQUAL,
- NAME, token.DOUBLESTAR, NUMBER)
+ tokenize.NAME, token.DOUBLESTAR, tokenize.NUMBER)
self.assertExactTypeEqual('{1, 2, 3}',
token.LBRACE,
token.NUMBER, token.COMMA,
@@ -1637,32 +1653,32 @@ def test_comment_at_the_end_of_the_source_without_newline(self):
# See http://bugs.python.org/issue44667
source = 'b = 1\n\n#test'
expected_tokens = [
- TokenInfo(type=token.ENCODING, string='utf-8', start=(0, 0), end=(0, 0), line=''),
- TokenInfo(type=token.NAME, string='b', start=(1, 0), end=(1, 1), line='b = 1\n'),
- TokenInfo(type=token.OP, string='=', start=(1, 2), end=(1, 3), line='b = 1\n'),
- TokenInfo(type=token.NUMBER, string='1', start=(1, 4), end=(1, 5), line='b = 1\n'),
- TokenInfo(type=token.NEWLINE, string='\n', start=(1, 5), end=(1, 6), line='b = 1\n'),
- TokenInfo(type=token.NL, string='\n', start=(2, 0), end=(2, 1), line='\n'),
- TokenInfo(type=token.COMMENT, string='#test', start=(3, 0), end=(3, 5), line='#test'),
- TokenInfo(type=token.NL, string='', start=(3, 5), end=(3, 6), line='#test'),
- TokenInfo(type=token.ENDMARKER, string='', start=(4, 0), end=(4, 0), line='')
+ tokenize.TokenInfo(type=token.ENCODING, string='utf-8', start=(0, 0), end=(0, 0), line=''),
+ tokenize.TokenInfo(type=token.NAME, string='b', start=(1, 0), end=(1, 1), line='b = 1\n'),
+ tokenize.TokenInfo(type=token.OP, string='=', start=(1, 2), end=(1, 3), line='b = 1\n'),
+ tokenize.TokenInfo(type=token.NUMBER, string='1', start=(1, 4), end=(1, 5), line='b = 1\n'),
+ tokenize.TokenInfo(type=token.NEWLINE, string='\n', start=(1, 5), end=(1, 6), line='b = 1\n'),
+ tokenize.TokenInfo(type=token.NL, string='\n', start=(2, 0), end=(2, 1), line='\n'),
+ tokenize.TokenInfo(type=token.COMMENT, string='#test', start=(3, 0), end=(3, 5), line='#test'),
+ tokenize.TokenInfo(type=token.NL, string='', start=(3, 5), end=(3, 6), line='#test'),
+ tokenize.TokenInfo(type=token.ENDMARKER, string='', start=(4, 0), end=(4, 0), line='')
]
- tokens = list(tokenize(BytesIO(source.encode('utf-8')).readline))
+ tokens = list(tokenize.tokenize(BytesIO(source.encode('utf-8')).readline))
self.assertEqual(tokens, expected_tokens)
def test_newline_and_space_at_the_end_of_the_source_without_newline(self):
# See https://github.com/python/cpython/issues/105435
source = 'a\n '
expected_tokens = [
- TokenInfo(token.ENCODING, string='utf-8', start=(0, 0), end=(0, 0), line=''),
- TokenInfo(token.NAME, string='a', start=(1, 0), end=(1, 1), line='a\n'),
- TokenInfo(token.NEWLINE, string='\n', start=(1, 1), end=(1, 2), line='a\n'),
- TokenInfo(token.NL, string='', start=(2, 1), end=(2, 2), line=' '),
- TokenInfo(token.ENDMARKER, string='', start=(3, 0), end=(3, 0), line='')
+ tokenize.TokenInfo(token.ENCODING, string='utf-8', start=(0, 0), end=(0, 0), line=''),
+ tokenize.TokenInfo(token.NAME, string='a', start=(1, 0), end=(1, 1), line='a\n'),
+ tokenize.TokenInfo(token.NEWLINE, string='\n', start=(1, 1), end=(1, 2), line='a\n'),
+ tokenize.TokenInfo(token.NL, string='', start=(2, 1), end=(2, 2), line=' '),
+ tokenize.TokenInfo(token.ENDMARKER, string='', start=(3, 0), end=(3, 0), line='')
]
- tokens = list(tokenize(BytesIO(source.encode('utf-8')).readline))
+ tokens = list(tokenize.tokenize(BytesIO(source.encode('utf-8')).readline))
self.assertEqual(tokens, expected_tokens)
def test_invalid_character_in_fstring_middle(self):
@@ -1682,7 +1698,7 @@ class UntokenizeTest(TestCase):
def test_bad_input_order(self):
# raise if previous row
- u = Untokenizer()
+ u = tokenize.Untokenizer()
u.prev_row = 2
u.prev_col = 2
with self.assertRaises(ValueError) as cm:
@@ -1694,7 +1710,7 @@ def test_bad_input_order(self):
def test_backslash_continuation(self):
# The problem is that \ leaves no token
- u = Untokenizer()
+ u = tokenize.Untokenizer()
u.prev_row = 1
u.prev_col = 1
u.tokens = []
@@ -1706,17 +1722,17 @@ def test_backslash_continuation(self):
TestRoundtrip.check_roundtrip(self, 'a\n b\n c\n \\\n c\n')
def test_iter_compat(self):
- u = Untokenizer()
- token = (NAME, 'Hello')
- tokens = [(ENCODING, 'utf-8'), token]
+ u = tokenize.Untokenizer()
+ token = (tokenize.NAME, 'Hello')
+ tokens = [(tokenize.ENCODING, 'utf-8'), token]
u.compat(token, iter([]))
self.assertEqual(u.tokens, ["Hello "])
- u = Untokenizer()
+ u = tokenize.Untokenizer()
self.assertEqual(u.untokenize(iter([token])), 'Hello ')
- u = Untokenizer()
+ u = tokenize.Untokenizer()
self.assertEqual(u.untokenize(iter(tokens)), 'Hello ')
self.assertEqual(u.encoding, 'utf-8')
- self.assertEqual(untokenize(iter(tokens)), b'Hello ')
+ self.assertEqual(tokenize.untokenize(iter(tokens)), b'Hello ')
class TestRoundtrip(TestCase):
@@ -1739,17 +1755,17 @@ def check_roundtrip(self, f):
else:
code = f.read()
readline = iter(code.splitlines(keepends=True)).__next__
- tokens5 = list(tokenize(readline))
+ tokens5 = list(tokenize.tokenize(readline))
tokens2 = [tok[:2] for tok in tokens5]
# Reproduce tokens2 from pairs
- bytes_from2 = untokenize(tokens2)
+ bytes_from2 = tokenize.untokenize(tokens2)
readline2 = iter(bytes_from2.splitlines(keepends=True)).__next__
- tokens2_from2 = [tok[:2] for tok in tokenize(readline2)]
+ tokens2_from2 = [tok[:2] for tok in tokenize.tokenize(readline2)]
self.assertEqual(tokens2_from2, tokens2)
# Reproduce tokens2 from 5-tuples
- bytes_from5 = untokenize(tokens5)
+ bytes_from5 = tokenize.untokenize(tokens5)
readline5 = iter(bytes_from5.splitlines(keepends=True)).__next__
- tokens2_from5 = [tok[:2] for tok in tokenize(readline5)]
+ tokens2_from5 = [tok[:2] for tok in tokenize.tokenize(readline5)]
self.assertEqual(tokens2_from5, tokens2)
def check_line_extraction(self, f):
@@ -1758,8 +1774,8 @@ def check_line_extraction(self, f):
else:
code = f.read()
readline = iter(code.splitlines(keepends=True)).__next__
- for tok in tokenize(readline):
- if tok.type in {ENCODING, ENDMARKER}:
+ for tok in tokenize.tokenize(readline):
+ if tok.type in {tokenize.ENCODING, tokenize.ENDMARKER}:
continue
self.assertEqual(tok.string, tok.line[tok.start[1]: tok.end[1]])
@@ -1865,7 +1881,7 @@ def test_random_files(self):
def roundtrip(self, code):
if isinstance(code, str):
code = code.encode('utf-8')
- return untokenize(tokenize(BytesIO(code).readline)).decode('utf-8')
+ return tokenize.untokenize(tokenize.tokenize(BytesIO(code).readline)).decode('utf-8')
def test_indentation_semantics_retained(self):
"""
@@ -1883,27 +1899,27 @@ def test_number_followed_by_name(self):
# See issue #gh-105549
source = "2sin(x)"
expected_tokens = [
- TokenInfo(type=token.NUMBER, string='2', start=(1, 0), end=(1, 1), line='2sin(x)'),
- TokenInfo(type=token.NAME, string='sin', start=(1, 1), end=(1, 4), line='2sin(x)'),
- TokenInfo(type=token.OP, string='(', start=(1, 4), end=(1, 5), line='2sin(x)'),
- TokenInfo(type=token.NAME, string='x', start=(1, 5), end=(1, 6), line='2sin(x)'),
- TokenInfo(type=token.OP, string=')', start=(1, 6), end=(1, 7), line='2sin(x)'),
- TokenInfo(type=token.NEWLINE, string='', start=(1, 7), end=(1, 8), line='2sin(x)'),
- TokenInfo(type=token.ENDMARKER, string='', start=(2, 0), end=(2, 0), line='')
+ tokenize.TokenInfo(type=token.NUMBER, string='2', start=(1, 0), end=(1, 1), line='2sin(x)'),
+ tokenize.TokenInfo(type=token.NAME, string='sin', start=(1, 1), end=(1, 4), line='2sin(x)'),
+ tokenize.TokenInfo(type=token.OP, string='(', start=(1, 4), end=(1, 5), line='2sin(x)'),
+ tokenize.TokenInfo(type=token.NAME, string='x', start=(1, 5), end=(1, 6), line='2sin(x)'),
+ tokenize.TokenInfo(type=token.OP, string=')', start=(1, 6), end=(1, 7), line='2sin(x)'),
+ tokenize.TokenInfo(type=token.NEWLINE, string='', start=(1, 7), end=(1, 8), line='2sin(x)'),
+ tokenize.TokenInfo(type=token.ENDMARKER, string='', start=(2, 0), end=(2, 0), line='')
]
- tokens = list(generate_tokens(StringIO(source).readline))
+ tokens = list(tokenize.generate_tokens(StringIO(source).readline))
self.assertEqual(tokens, expected_tokens)
def test_number_starting_with_zero(self):
source = "01234"
expected_tokens = [
- TokenInfo(type=token.NUMBER, string='01234', start=(1, 0), end=(1, 5), line='01234'),
- TokenInfo(type=token.NEWLINE, string='', start=(1, 5), end=(1, 6), line='01234'),
- TokenInfo(type=token.ENDMARKER, string='', start=(2, 0), end=(2, 0), line='')
+ tokenize.TokenInfo(type=token.NUMBER, string='01234', start=(1, 0), end=(1, 5), line='01234'),
+ tokenize.TokenInfo(type=token.NEWLINE, string='', start=(1, 5), end=(1, 6), line='01234'),
+ tokenize.TokenInfo(type=token.ENDMARKER, string='', start=(2, 0), end=(2, 0), line='')
]
- tokens = list(generate_tokens(StringIO(source).readline))
+ tokens = list(tokenize.generate_tokens(StringIO(source).readline))
self.assertEqual(tokens, expected_tokens)
class CTokenizeTest(TestCase):
@@ -1913,7 +1929,7 @@ def check_tokenize(self, s, expected):
f = StringIO(s)
with self.subTest(source=s):
result = stringify_tokens_from_source(
- _generate_tokens_from_c_tokenizer(f.readline), s
+ tokenize._generate_tokens_from_c_tokenizer(f.readline), s
)
self.assertEqual(result, expected.rstrip().splitlines())
@@ -1922,15 +1938,15 @@ def readline(encoding):
yield "1+1".encode(encoding)
expected = [
- TokenInfo(type=NUMBER, string='1', start=(1, 0), end=(1, 1), line='1+1'),
- TokenInfo(type=OP, string='+', start=(1, 1), end=(1, 2), line='1+1'),
- TokenInfo(type=NUMBER, string='1', start=(1, 2), end=(1, 3), line='1+1'),
- TokenInfo(type=NEWLINE, string='', start=(1, 3), end=(1, 4), line='1+1'),
- TokenInfo(type=ENDMARKER, string='', start=(2, 0), end=(2, 0), line='')
+ tokenize.TokenInfo(type=tokenize.NUMBER, string='1', start=(1, 0), end=(1, 1), line='1+1'),
+ tokenize.TokenInfo(type=tokenize.OP, string='+', start=(1, 1), end=(1, 2), line='1+1'),
+ tokenize.TokenInfo(type=tokenize.NUMBER, string='1', start=(1, 2), end=(1, 3), line='1+1'),
+ tokenize.TokenInfo(type=tokenize.NEWLINE, string='', start=(1, 3), end=(1, 4), line='1+1'),
+ tokenize.TokenInfo(type=tokenize.ENDMARKER, string='', start=(2, 0), end=(2, 0), line='')
]
for encoding in ["utf-8", "latin-1", "utf-16"]:
with self.subTest(encoding=encoding):
- tokens = list(_generate_tokens_from_c_tokenizer(
+ tokens = list(tokenize._generate_tokens_from_c_tokenizer(
readline(encoding).__next__,
extra_tokens=True,
encoding=encoding,
@@ -2239,6 +2255,16 @@ def test_string(self):
FSTRING_START \'f"\' (1, 0) (1, 2)
FSTRING_MIDDLE 'abc\\\\\\ndef' (1, 2) (2, 3)
FSTRING_END '"' (2, 3) (2, 4)
+ """)
+
+ self.check_tokenize('''\
+f"{
+a}"''', """\
+ FSTRING_START 'f"' (1, 0) (1, 2)
+ LBRACE '{' (1, 2) (1, 3)
+ NAME 'a' (2, 0) (2, 1)
+ RBRACE '}' (2, 1) (2, 2)
+ FSTRING_END '"' (2, 2) (2, 3)
""")
self.check_tokenize(r'Rf"abc\
@@ -2773,7 +2799,7 @@ def test_unicode(self):
def test_invalid_syntax(self):
def get_tokens(string):
the_string = StringIO(string)
- return list(_generate_tokens_from_c_tokenizer(the_string.readline))
+ return list(tokenize._generate_tokens_from_c_tokenizer(the_string.readline))
for case in [
"(1+2]",
@@ -2809,7 +2835,7 @@ def get_tokens(string):
"]",
]:
with self.subTest(case=case):
- self.assertRaises(TokenError, get_tokens, case)
+ self.assertRaises(tokenize.TokenError, get_tokens, case)
def test_max_indent(self):
MAXINDENT = 100
@@ -2821,14 +2847,14 @@ def generate_source(indents):
valid = generate_source(MAXINDENT - 1)
the_input = StringIO(valid)
- tokens = list(_generate_tokens_from_c_tokenizer(the_input.readline))
- self.assertEqual(tokens[-2].type, DEDENT)
- self.assertEqual(tokens[-1].type, ENDMARKER)
+ tokens = list(tokenize._generate_tokens_from_c_tokenizer(the_input.readline))
+ self.assertEqual(tokens[-2].type, tokenize.DEDENT)
+ self.assertEqual(tokens[-1].type, tokenize.ENDMARKER)
compile(valid, "", "exec")
invalid = generate_source(MAXINDENT)
the_input = StringIO(invalid)
- self.assertRaises(IndentationError, lambda: list(_generate_tokens_from_c_tokenizer(the_input.readline)))
+ self.assertRaises(IndentationError, lambda: list(tokenize._generate_tokens_from_c_tokenizer(the_input.readline)))
self.assertRaises(
IndentationError, compile, invalid, "", "exec"
)
@@ -2837,7 +2863,7 @@ def test_continuation_lines_indentation(self):
def get_tokens(string):
the_string = StringIO(string)
return [(kind, string) for (kind, string, *_)
- in _generate_tokens_from_c_tokenizer(the_string.readline)]
+ in tokenize._generate_tokens_from_c_tokenizer(the_string.readline)]
code = dedent("""
def fib(n):
diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py
index 94bcee302fe730..4af4ca3b977236 100644
--- a/Lib/test/test_tracemalloc.py
+++ b/Lib/test/test_tracemalloc.py
@@ -11,8 +11,10 @@
try:
import _testcapi
+ import _testinternalcapi
except ImportError:
_testcapi = None
+ _testinternalcapi = None
EMPTY_STRING_SIZE = sys.getsizeof(b'')
@@ -1008,7 +1010,7 @@ def tearDown(self):
tracemalloc.stop()
def get_traceback(self):
- frames = _testcapi.tracemalloc_get_traceback(self.domain, self.ptr)
+ frames = _testinternalcapi._PyTraceMalloc_GetTraceback(self.domain, self.ptr)
if frames is not None:
return tracemalloc.Traceback(frames)
else:
diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py
index a3067e521e023e..0ce97f57de6860 100644
--- a/Lib/test/test_type_aliases.py
+++ b/Lib/test/test_type_aliases.py
@@ -142,7 +142,16 @@ def test_subscripting(self):
def test_repr(self):
type Simple = int
+ type VeryGeneric[T, *Ts, **P] = Callable[P, tuple[T, *Ts]]
+
self.assertEqual(repr(Simple), "Simple")
+ self.assertEqual(repr(VeryGeneric), "VeryGeneric")
+ self.assertEqual(repr(VeryGeneric[int, bytes, str, [float, object]]),
+ "VeryGeneric[int, bytes, str, [float, object]]")
+ self.assertEqual(repr(VeryGeneric[int, []]),
+ "VeryGeneric[int, []]")
+ self.assertEqual(repr(VeryGeneric[int, [VeryGeneric[int], list[str]]]),
+ "VeryGeneric[int, [VeryGeneric[int], list[str]]]")
def test_recursive_repr(self):
type Recursive = Recursive
@@ -151,6 +160,13 @@ def test_recursive_repr(self):
type X = list[Y]
type Y = list[X]
self.assertEqual(repr(X), "X")
+ self.assertEqual(repr(Y), "Y")
+
+ type GenericRecursive[X] = list[X | GenericRecursive[X]]
+ self.assertEqual(repr(GenericRecursive), "GenericRecursive")
+ self.assertEqual(repr(GenericRecursive[int]), "GenericRecursive[int]")
+ self.assertEqual(repr(GenericRecursive[GenericRecursive[int]]),
+ "GenericRecursive[GenericRecursive[int]]")
class TypeAliasConstructorTest(unittest.TestCase):
@@ -228,8 +244,69 @@ def test_module(self):
self.assertEqual(mod_generics_cache.OldStyle.__module__,
mod_generics_cache.__name__)
+
+# All these type aliases are used for pickling tests:
+T = TypeVar('T')
+type SimpleAlias = int
+type RecursiveAlias = dict[str, RecursiveAlias]
+type GenericAlias[X] = list[X]
+type GenericAliasMultipleTypes[X, Y] = dict[X, Y]
+type RecursiveGenericAlias[X] = dict[str, RecursiveAlias[X]]
+type BoundGenericAlias[X: int] = set[X]
+type ConstrainedGenericAlias[LongName: (str, bytes)] = list[LongName]
+type AllTypesAlias[A, *B, **C] = Callable[C, A] | tuple[*B]
+
+
+class TypeAliasPickleTest(unittest.TestCase):
def test_pickling(self):
- pickled = pickle.dumps(mod_generics_cache.Alias)
- self.assertIs(pickle.loads(pickled), mod_generics_cache.Alias)
- pickled = pickle.dumps(mod_generics_cache.OldStyle)
- self.assertIs(pickle.loads(pickled), mod_generics_cache.OldStyle)
+ things_to_test = [
+ SimpleAlias,
+ RecursiveAlias,
+
+ GenericAlias,
+ GenericAlias[T],
+ GenericAlias[int],
+
+ GenericAliasMultipleTypes,
+ GenericAliasMultipleTypes[str, T],
+ GenericAliasMultipleTypes[T, str],
+ GenericAliasMultipleTypes[int, str],
+
+ RecursiveGenericAlias,
+ RecursiveGenericAlias[T],
+ RecursiveGenericAlias[int],
+
+ BoundGenericAlias,
+ BoundGenericAlias[int],
+ BoundGenericAlias[T],
+
+ ConstrainedGenericAlias,
+ ConstrainedGenericAlias[str],
+ ConstrainedGenericAlias[T],
+
+ AllTypesAlias,
+ AllTypesAlias[int, str, T, [T, object]],
+
+ # Other modules:
+ mod_generics_cache.Alias,
+ mod_generics_cache.OldStyle,
+ ]
+ for thing in things_to_test:
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.subTest(thing=thing, proto=proto):
+ pickled = pickle.dumps(thing, protocol=proto)
+ self.assertEqual(pickle.loads(pickled), thing)
+
+ type ClassLevel = str
+
+ def test_pickling_local(self):
+ type A = int
+ things_to_test = [
+ self.ClassLevel,
+ A,
+ ]
+ for thing in things_to_test:
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.subTest(thing=thing, proto=proto):
+ with self.assertRaises(pickle.PickleError):
+ pickle.dumps(thing, protocol=proto)
diff --git a/Lib/test/test_type_params.py b/Lib/test/test_type_params.py
index 6475df6f5bba43..bced641a9661fd 100644
--- a/Lib/test/test_type_params.py
+++ b/Lib/test/test_type_params.py
@@ -2,6 +2,8 @@
import textwrap
import types
import unittest
+import pickle
+import weakref
from test.support import requires_working_socket, check_syntax_error, run_code
from typing import Generic, Sequence, TypeVar, TypeVarTuple, ParamSpec, get_args
@@ -855,3 +857,98 @@ def func[A]():
ns = run_code(code)
self.assertEqual(ns["func"].__type_params__, ())
+
+
+
+# All these type aliases are used for pickling tests:
+T = TypeVar('T')
+def func1[X](x: X) -> X: ...
+def func2[X, Y](x: X | Y) -> X | Y: ...
+def func3[X, *Y, **Z](x: X, y: tuple[*Y], z: Z) -> X: ...
+def func4[X: int, Y: (bytes, str)](x: X, y: Y) -> X | Y: ...
+
+class Class1[X]: ...
+class Class2[X, Y]: ...
+class Class3[X, *Y, **Z]: ...
+class Class4[X: int, Y: (bytes, str)]: ...
+
+
+class TypeParamsPickleTest(unittest.TestCase):
+ def test_pickling_functions(self):
+ things_to_test = [
+ func1,
+ func2,
+ func3,
+ func4,
+ ]
+ for thing in things_to_test:
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.subTest(thing=thing, proto=proto):
+ pickled = pickle.dumps(thing, protocol=proto)
+ self.assertEqual(pickle.loads(pickled), thing)
+
+ def test_pickling_classes(self):
+ things_to_test = [
+ Class1,
+ Class1[int],
+ Class1[T],
+
+ Class2,
+ Class2[int, T],
+ Class2[T, int],
+ Class2[int, str],
+
+ Class3,
+ Class3[int, T, str, bytes, [float, object, T]],
+
+ Class4,
+ Class4[int, bytes],
+ Class4[T, bytes],
+ Class4[int, T],
+ Class4[T, T],
+ ]
+ for thing in things_to_test:
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.subTest(thing=thing, proto=proto):
+ pickled = pickle.dumps(thing, protocol=proto)
+ self.assertEqual(pickle.loads(pickled), thing)
+
+ for klass in things_to_test:
+ real_class = getattr(klass, '__origin__', klass)
+ thing = klass()
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.subTest(thing=thing, proto=proto):
+ pickled = pickle.dumps(thing, protocol=proto)
+ # These instances are not equal,
+ # but class check is good enough:
+ self.assertIsInstance(pickle.loads(pickled), real_class)
+
+
+class TypeParamsWeakRefTest(unittest.TestCase):
+ def test_weakrefs(self):
+ T = TypeVar('T')
+ P = ParamSpec('P')
+ class OldStyle(Generic[T]):
+ pass
+
+ class NewStyle[T]:
+ pass
+
+ cases = [
+ T,
+ TypeVar('T', bound=int),
+ P,
+ P.args,
+ P.kwargs,
+ TypeVarTuple('Ts'),
+ OldStyle,
+ OldStyle[int],
+ OldStyle(),
+ NewStyle,
+ NewStyle[int],
+ NewStyle(),
+ Generic[T],
+ ]
+ for case in cases:
+ with self.subTest(case=case):
+ weakref.ref(case)
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 432fc88b1c072e..0450a87577ecea 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -24,9 +24,9 @@
from typing import Generic, ClassVar, Final, final, Protocol
from typing import assert_type, cast, runtime_checkable
from typing import get_type_hints
-from typing import get_origin, get_args
+from typing import get_origin, get_args, get_protocol_members
from typing import override
-from typing import is_typeddict
+from typing import is_typeddict, is_protocol
from typing import reveal_type
from typing import dataclass_transform
from typing import no_type_check, no_type_check_decorator
@@ -2759,6 +2759,80 @@ def x(self): ...
with self.assertRaisesRegex(TypeError, only_classes_allowed):
issubclass(1, BadPG)
+ def test_implicit_issubclass_between_two_protocols(self):
+ @runtime_checkable
+ class CallableMembersProto(Protocol):
+ def meth(self): ...
+
+ # All the below protocols should be considered "subclasses"
+ # of CallableMembersProto at runtime,
+ # even though none of them explicitly subclass CallableMembersProto
+
+ class IdenticalProto(Protocol):
+ def meth(self): ...
+
+ class SupersetProto(Protocol):
+ def meth(self): ...
+ def meth2(self): ...
+
+ class NonCallableMembersProto(Protocol):
+ meth: Callable[[], None]
+
+ class NonCallableMembersSupersetProto(Protocol):
+ meth: Callable[[], None]
+ meth2: Callable[[str, int], bool]
+
+ class MixedMembersProto1(Protocol):
+ meth: Callable[[], None]
+ def meth2(self): ...
+
+ class MixedMembersProto2(Protocol):
+ def meth(self): ...
+ meth2: Callable[[str, int], bool]
+
+ for proto in (
+ IdenticalProto, SupersetProto, NonCallableMembersProto,
+ NonCallableMembersSupersetProto, MixedMembersProto1, MixedMembersProto2
+ ):
+ with self.subTest(proto=proto.__name__):
+ self.assertIsSubclass(proto, CallableMembersProto)
+
+ # These two shouldn't be considered subclasses of CallableMembersProto, however,
+ # since they don't have the `meth` protocol member
+
+ class EmptyProtocol(Protocol): ...
+ class UnrelatedProtocol(Protocol):
+ def wut(self): ...
+
+ self.assertNotIsSubclass(EmptyProtocol, CallableMembersProto)
+ self.assertNotIsSubclass(UnrelatedProtocol, CallableMembersProto)
+
+ # These aren't protocols at all (despite having annotations),
+ # so they should only be considered subclasses of CallableMembersProto
+ # if they *actually have an attribute* matching the `meth` member
+ # (just having an annotation is insufficient)
+
+ class AnnotatedButNotAProtocol:
+ meth: Callable[[], None]
+
+ class NotAProtocolButAnImplicitSubclass:
+ def meth(self): pass
+
+ class NotAProtocolButAnImplicitSubclass2:
+ meth: Callable[[], None]
+ def meth(self): pass
+
+ class NotAProtocolButAnImplicitSubclass3:
+ meth: Callable[[], None]
+ meth2: Callable[[int, str], bool]
+ def meth(self): pass
+ def meth(self, x, y): return True
+
+ self.assertNotIsSubclass(AnnotatedButNotAProtocol, CallableMembersProto)
+ self.assertIsSubclass(NotAProtocolButAnImplicitSubclass, CallableMembersProto)
+ self.assertIsSubclass(NotAProtocolButAnImplicitSubclass2, CallableMembersProto)
+ self.assertIsSubclass(NotAProtocolButAnImplicitSubclass3, CallableMembersProto)
+
def test_isinstance_checks_not_at_whim_of_gc(self):
self.addCleanup(gc.enable)
gc.disable()
@@ -3363,6 +3437,18 @@ def meth(self): pass
self.assertNotIn("__callable_proto_members_only__", vars(NonP))
self.assertNotIn("__callable_proto_members_only__", vars(NonPR))
+ self.assertEqual(get_protocol_members(P), {"x"})
+ self.assertEqual(get_protocol_members(PR), {"meth"})
+
+ # the returned object should be immutable,
+ # and should be a different object to the original attribute
+ # to prevent users from (accidentally or deliberately)
+ # mutating the attribute on the original class
+ self.assertIsInstance(get_protocol_members(P), frozenset)
+ self.assertIsNot(get_protocol_members(P), P.__protocol_attrs__)
+ self.assertIsInstance(get_protocol_members(PR), frozenset)
+ self.assertIsNot(get_protocol_members(PR), P.__protocol_attrs__)
+
acceptable_extra_attrs = {
'_is_protocol', '_is_runtime_protocol', '__parameters__',
'__init__', '__annotations__', '__subclasshook__',
@@ -3391,6 +3477,46 @@ def __subclasshook__(cls, other):
self.assertIsSubclass(OKClass, C)
self.assertNotIsSubclass(BadClass, C)
+ def test_custom_subclasshook_2(self):
+ @runtime_checkable
+ class HasX(Protocol):
+ # The presence of a non-callable member
+ # would mean issubclass() checks would fail with TypeError
+ # if it weren't for the custom `__subclasshook__` method
+ x = 1
+
+ @classmethod
+ def __subclasshook__(cls, other):
+ return hasattr(other, 'x')
+
+ class Empty: pass
+
+ class ImplementsHasX:
+ x = 1
+
+ self.assertIsInstance(ImplementsHasX(), HasX)
+ self.assertNotIsInstance(Empty(), HasX)
+ self.assertIsSubclass(ImplementsHasX, HasX)
+ self.assertNotIsSubclass(Empty, HasX)
+
+ # isinstance() and issubclass() checks against this still raise TypeError,
+ # despite the presence of the custom __subclasshook__ method,
+ # as it's not decorated with @runtime_checkable
+ class NotRuntimeCheckable(Protocol):
+ @classmethod
+ def __subclasshook__(cls, other):
+ return hasattr(other, 'x')
+
+ must_be_runtime_checkable = (
+ "Instance and class checks can only be used "
+ "with @runtime_checkable protocols"
+ )
+
+ with self.assertRaisesRegex(TypeError, must_be_runtime_checkable):
+ issubclass(object, NotRuntimeCheckable)
+ with self.assertRaisesRegex(TypeError, must_be_runtime_checkable):
+ isinstance(object(), NotRuntimeCheckable)
+
def test_issubclass_fails_correctly(self):
@runtime_checkable
class P(Protocol):
@@ -3778,6 +3904,59 @@ def __init__(self):
Foo() # Previously triggered RecursionError
+ def test_get_protocol_members(self):
+ with self.assertRaisesRegex(TypeError, "not a Protocol"):
+ get_protocol_members(object)
+ with self.assertRaisesRegex(TypeError, "not a Protocol"):
+ get_protocol_members(object())
+ with self.assertRaisesRegex(TypeError, "not a Protocol"):
+ get_protocol_members(Protocol)
+ with self.assertRaisesRegex(TypeError, "not a Protocol"):
+ get_protocol_members(Generic)
+
+ class P(Protocol):
+ a: int
+ def b(self) -> str: ...
+ @property
+ def c(self) -> int: ...
+
+ self.assertEqual(get_protocol_members(P), {'a', 'b', 'c'})
+ self.assertIsInstance(get_protocol_members(P), frozenset)
+ self.assertIsNot(get_protocol_members(P), P.__protocol_attrs__)
+
+ class Concrete:
+ a: int
+ def b(self) -> str: return "capybara"
+ @property
+ def c(self) -> int: return 5
+
+ with self.assertRaisesRegex(TypeError, "not a Protocol"):
+ get_protocol_members(Concrete)
+ with self.assertRaisesRegex(TypeError, "not a Protocol"):
+ get_protocol_members(Concrete())
+
+ class ConcreteInherit(P):
+ a: int = 42
+ def b(self) -> str: return "capybara"
+ @property
+ def c(self) -> int: return 5
+
+ with self.assertRaisesRegex(TypeError, "not a Protocol"):
+ get_protocol_members(ConcreteInherit)
+ with self.assertRaisesRegex(TypeError, "not a Protocol"):
+ get_protocol_members(ConcreteInherit())
+
+ def test_is_protocol(self):
+ self.assertTrue(is_protocol(Proto))
+ self.assertTrue(is_protocol(Point))
+ self.assertFalse(is_protocol(Concrete))
+ self.assertFalse(is_protocol(Concrete()))
+ self.assertFalse(is_protocol(Generic))
+ self.assertFalse(is_protocol(object))
+
+ # Protocol is not itself a protocol
+ self.assertFalse(is_protocol(Protocol))
+
def test_interaction_with_isinstance_checks_on_superclasses_with_ABCMeta(self):
# Ensure the cache is empty, or this test won't work correctly
collections.abc.Sized._abc_registry_clear()
@@ -5615,10 +5794,14 @@ class F:
get_type_hints(clazz)
def test_meta_no_type_check(self):
-
- @no_type_check_decorator
- def magic_decorator(func):
- return func
+ depr_msg = (
+ "'typing.no_type_check_decorator' is deprecated "
+ "and slated for removal in Python 3.15"
+ )
+ with self.assertWarnsRegex(DeprecationWarning, depr_msg):
+ @no_type_check_decorator
+ def magic_decorator(func):
+ return func
self.assertEqual(magic_decorator.__name__, 'magic_decorator')
@@ -7124,18 +7307,47 @@ class Group(NamedTuple):
self.assertEqual(a, (1, [2]))
def test_namedtuple_keyword_usage(self):
- LocalEmployee = NamedTuple("LocalEmployee", name=str, age=int)
+ with self.assertWarnsRegex(
+ DeprecationWarning,
+ "Creating NamedTuple classes using keyword arguments is deprecated"
+ ):
+ LocalEmployee = NamedTuple("LocalEmployee", name=str, age=int)
+
nick = LocalEmployee('Nick', 25)
self.assertIsInstance(nick, tuple)
self.assertEqual(nick.name, 'Nick')
self.assertEqual(LocalEmployee.__name__, 'LocalEmployee')
self.assertEqual(LocalEmployee._fields, ('name', 'age'))
self.assertEqual(LocalEmployee.__annotations__, dict(name=str, age=int))
- with self.assertRaises(TypeError):
+
+ with self.assertRaisesRegex(
+ TypeError,
+ "Either list of fields or keywords can be provided to NamedTuple, not both"
+ ):
NamedTuple('Name', [('x', int)], y=str)
+ with self.assertRaisesRegex(
+ TypeError,
+ "Either list of fields or keywords can be provided to NamedTuple, not both"
+ ):
+ NamedTuple('Name', [], y=str)
+
+ with self.assertRaisesRegex(
+ TypeError,
+ (
+ r"Cannot pass `None` as the 'fields' parameter "
+ r"and also specify fields using keyword arguments"
+ )
+ ):
+ NamedTuple('Name', None, x=int)
+
def test_namedtuple_special_keyword_names(self):
- NT = NamedTuple("NT", cls=type, self=object, typename=str, fields=list)
+ with self.assertWarnsRegex(
+ DeprecationWarning,
+ "Creating NamedTuple classes using keyword arguments is deprecated"
+ ):
+ NT = NamedTuple("NT", cls=type, self=object, typename=str, fields=list)
+
self.assertEqual(NT.__name__, 'NT')
self.assertEqual(NT._fields, ('cls', 'self', 'typename', 'fields'))
a = NT(cls=str, self=42, typename='foo', fields=[('bar', tuple)])
@@ -7145,12 +7357,32 @@ def test_namedtuple_special_keyword_names(self):
self.assertEqual(a.fields, [('bar', tuple)])
def test_empty_namedtuple(self):
- NT = NamedTuple('NT')
+ expected_warning = re.escape(
+ "Failing to pass a value for the 'fields' parameter is deprecated "
+ "and will be disallowed in Python 3.15. "
+ "To create a NamedTuple class with 0 fields "
+ "using the functional syntax, "
+ "pass an empty list, e.g. `NT1 = NamedTuple('NT1', [])`."
+ )
+ with self.assertWarnsRegex(DeprecationWarning, fr"^{expected_warning}$"):
+ NT1 = NamedTuple('NT1')
+
+ expected_warning = re.escape(
+ "Passing `None` as the 'fields' parameter is deprecated "
+ "and will be disallowed in Python 3.15. "
+ "To create a NamedTuple class with 0 fields "
+ "using the functional syntax, "
+ "pass an empty list, e.g. `NT2 = NamedTuple('NT2', [])`."
+ )
+ with self.assertWarnsRegex(DeprecationWarning, fr"^{expected_warning}$"):
+ NT2 = NamedTuple('NT2', None)
+
+ NT3 = NamedTuple('NT2', [])
class CNT(NamedTuple):
pass # empty body
- for struct in [NT, CNT]:
+ for struct in NT1, NT2, NT3, CNT:
with self.subTest(struct=struct):
self.assertEqual(struct._fields, ())
self.assertEqual(struct._field_defaults, {})
@@ -7160,13 +7392,29 @@ class CNT(NamedTuple):
def test_namedtuple_errors(self):
with self.assertRaises(TypeError):
NamedTuple.__new__()
- with self.assertRaises(TypeError):
+
+ with self.assertRaisesRegex(
+ TypeError,
+ "missing 1 required positional argument"
+ ):
NamedTuple()
- with self.assertRaises(TypeError):
+
+ with self.assertRaisesRegex(
+ TypeError,
+ "takes from 1 to 2 positional arguments but 3 were given"
+ ):
NamedTuple('Emp', [('name', str)], None)
- with self.assertRaises(ValueError):
+
+ with self.assertRaisesRegex(
+ ValueError,
+ "Field names cannot start with an underscore"
+ ):
NamedTuple('Emp', [('_name', str)])
- with self.assertRaises(TypeError):
+
+ with self.assertRaisesRegex(
+ TypeError,
+ "missing 1 required positional argument: 'typename'"
+ ):
NamedTuple(typename='Emp', name=str, id=int)
def test_copy_and_pickle(self):
@@ -7693,6 +7941,40 @@ class MultipleGenericBases(GenericParent[int], GenericParent[float]):
self.assertEqual(MultipleGenericBases.__orig_bases__, (GenericParent[int], GenericParent[float]))
self.assertEqual(CallTypedDict.__orig_bases__, (TypedDict,))
+ def test_zero_fields_typeddicts(self):
+ T1 = TypedDict("T1", {})
+ class T2(TypedDict): pass
+ class T3[tvar](TypedDict): pass
+ S = TypeVar("S")
+ class T4(TypedDict, Generic[S]): pass
+
+ expected_warning = re.escape(
+ "Failing to pass a value for the 'fields' parameter is deprecated "
+ "and will be disallowed in Python 3.15. "
+ "To create a TypedDict class with 0 fields "
+ "using the functional syntax, "
+ "pass an empty dictionary, e.g. `T5 = TypedDict('T5', {})`."
+ )
+ with self.assertWarnsRegex(DeprecationWarning, fr"^{expected_warning}$"):
+ T5 = TypedDict('T5')
+
+ expected_warning = re.escape(
+ "Passing `None` as the 'fields' parameter is deprecated "
+ "and will be disallowed in Python 3.15. "
+ "To create a TypedDict class with 0 fields "
+ "using the functional syntax, "
+ "pass an empty dictionary, e.g. `T6 = TypedDict('T6', {})`."
+ )
+ with self.assertWarnsRegex(DeprecationWarning, fr"^{expected_warning}$"):
+ T6 = TypedDict('T6', None)
+
+ for klass in T1, T2, T3, T4, T5, T6:
+ with self.subTest(klass=klass.__name__):
+ self.assertEqual(klass.__annotations__, {})
+ self.assertEqual(klass.__required_keys__, set())
+ self.assertEqual(klass.__optional_keys__, set())
+ self.assertIsInstance(klass(), dict)
+
class RequiredTests(BaseTestCase):
diff --git a/Lib/test/test_unittest/testmock/testasync.py b/Lib/test/test_unittest/testmock/testasync.py
index e9e1f63e84d4e7..f57b83f457f279 100644
--- a/Lib/test/test_unittest/testmock/testasync.py
+++ b/Lib/test/test_unittest/testmock/testasync.py
@@ -459,9 +459,10 @@ async def addition(self, var): pass
self.assertEqual(output, 10)
async def test_add_side_effect_exception(self):
+ class CustomError(Exception): pass
async def addition(var): pass
- mock = AsyncMock(addition, side_effect=Exception('err'))
- with self.assertRaises(Exception):
+ mock = AsyncMock(addition, side_effect=CustomError('side-effect'))
+ with self.assertRaisesRegex(CustomError, 'side-effect'):
await mock(5)
async def test_add_side_effect_coroutine(self):
diff --git a/Lib/test/test_unittest/testmock/testthreadingmock.py b/Lib/test/test_unittest/testmock/testthreadingmock.py
new file mode 100644
index 00000000000000..b6e12bcb3cda9c
--- /dev/null
+++ b/Lib/test/test_unittest/testmock/testthreadingmock.py
@@ -0,0 +1,280 @@
+import time
+import unittest
+import concurrent.futures
+
+from test.support import threading_helper
+from unittest.mock import patch, ThreadingMock, call
+
+
+threading_helper.requires_working_threading(module=True)
+
+
+class Something:
+ def method_1(self):
+ pass # pragma: no cover
+
+ def method_2(self):
+ pass # pragma: no cover
+
+
+class TestThreadingMock(unittest.TestCase):
+ def _call_after_delay(self, func, /, *args, **kwargs):
+ time.sleep(kwargs.pop("delay"))
+ func(*args, **kwargs)
+
+ def setUp(self):
+ self._executor = concurrent.futures.ThreadPoolExecutor(max_workers=5)
+
+ def tearDown(self):
+ self._executor.shutdown()
+
+ def run_async(self, func, /, *args, delay=0, **kwargs):
+ self._executor.submit(
+ self._call_after_delay, func, *args, **kwargs, delay=delay
+ )
+
+ def _make_mock(self, *args, **kwargs):
+ return ThreadingMock(*args, **kwargs)
+
+ def test_spec(self):
+ waitable_mock = self._make_mock(spec=Something)
+
+ with patch(f"{__name__}.Something", waitable_mock) as m:
+ something = m()
+
+ self.assertIsInstance(something.method_1, ThreadingMock)
+ self.assertIsInstance(something.method_1().method_2(), ThreadingMock)
+
+ with self.assertRaises(AttributeError):
+ m.test
+
+ def test_side_effect(self):
+ waitable_mock = self._make_mock()
+
+ with patch(f"{__name__}.Something", waitable_mock):
+ something = Something()
+ something.method_1.side_effect = [1]
+
+ self.assertEqual(something.method_1(), 1)
+
+ def test_instance_check(self):
+ waitable_mock = self._make_mock()
+
+ with patch(f"{__name__}.Something", waitable_mock):
+ something = Something()
+
+ self.assertIsInstance(something.method_1, ThreadingMock)
+ self.assertIsInstance(something.method_1().method_2(), ThreadingMock)
+
+ def test_dynamic_child_mocks_are_threading_mocks(self):
+ waitable_mock = self._make_mock()
+ self.assertIsInstance(waitable_mock.child, ThreadingMock)
+
+ def test_dynamic_child_mocks_inherit_timeout(self):
+ mock1 = self._make_mock()
+ self.assertIs(mock1._mock_wait_timeout, None)
+ mock2 = self._make_mock(timeout=2)
+ self.assertEqual(mock2._mock_wait_timeout, 2)
+ mock3 = self._make_mock(timeout=3)
+ self.assertEqual(mock3._mock_wait_timeout, 3)
+
+ self.assertIs(mock1.child._mock_wait_timeout, None)
+ self.assertEqual(mock2.child._mock_wait_timeout, 2)
+ self.assertEqual(mock3.child._mock_wait_timeout, 3)
+
+ self.assertEqual(mock2.really().__mul__().complex._mock_wait_timeout, 2)
+
+ def test_no_name_clash(self):
+ waitable_mock = self._make_mock()
+ waitable_mock._event = "myevent"
+ waitable_mock.event = "myevent"
+ waitable_mock.timeout = "mytimeout"
+ waitable_mock("works")
+ waitable_mock.wait_until_called()
+ waitable_mock.wait_until_any_call_with("works")
+
+ def test_wait_success(self):
+ waitable_mock = self._make_mock(spec=Something)
+
+ with patch(f"{__name__}.Something", waitable_mock):
+ something = Something()
+ self.run_async(something.method_1, delay=0.01)
+ something.method_1.wait_until_called()
+ something.method_1.wait_until_any_call_with()
+ something.method_1.assert_called()
+
+ def test_wait_success_with_instance_timeout(self):
+ waitable_mock = self._make_mock(timeout=1)
+
+ with patch(f"{__name__}.Something", waitable_mock):
+ something = Something()
+ self.run_async(something.method_1, delay=0.01)
+ something.method_1.wait_until_called()
+ something.method_1.wait_until_any_call_with()
+ something.method_1.assert_called()
+
+ def test_wait_failed_with_instance_timeout(self):
+ waitable_mock = self._make_mock(timeout=0.01)
+
+ with patch(f"{__name__}.Something", waitable_mock):
+ something = Something()
+ self.run_async(something.method_1, delay=0.5)
+ self.assertRaises(AssertionError, waitable_mock.method_1.wait_until_called)
+ self.assertRaises(
+ AssertionError, waitable_mock.method_1.wait_until_any_call_with
+ )
+
+ def test_wait_success_with_timeout_override(self):
+ waitable_mock = self._make_mock(timeout=0.01)
+
+ with patch(f"{__name__}.Something", waitable_mock):
+ something = Something()
+ self.run_async(something.method_1, delay=0.05)
+ something.method_1.wait_until_called(timeout=1)
+
+ def test_wait_failed_with_timeout_override(self):
+ waitable_mock = self._make_mock(timeout=1)
+
+ with patch(f"{__name__}.Something", waitable_mock):
+ something = Something()
+ self.run_async(something.method_1, delay=0.5)
+ with self.assertRaises(AssertionError):
+ something.method_1.wait_until_called(timeout=0.05)
+
+ def test_wait_success_called_before(self):
+ waitable_mock = self._make_mock()
+
+ with patch(f"{__name__}.Something", waitable_mock):
+ something = Something()
+ something.method_1()
+ something.method_1.wait_until_called()
+ something.method_1.wait_until_any_call_with()
+ something.method_1.assert_called()
+
+ def test_wait_magic_method(self):
+ waitable_mock = self._make_mock()
+
+ with patch(f"{__name__}.Something", waitable_mock):
+ something = Something()
+ self.run_async(something.method_1.__str__, delay=0.01)
+ something.method_1.__str__.wait_until_called()
+ something.method_1.__str__.assert_called()
+
+ def test_wait_until_any_call_with_positional(self):
+ waitable_mock = self._make_mock(spec=Something)
+
+ with patch(f"{__name__}.Something", waitable_mock):
+ something = Something()
+ self.run_async(something.method_1, 1, delay=0.2)
+ self.assertNotIn(call(1), something.method_1.mock_calls)
+ self.run_async(something.method_1, 2, delay=0.5)
+ self.run_async(something.method_1, 3, delay=0.6)
+
+ something.method_1.wait_until_any_call_with(1)
+ something.method_1.assert_called_with(1)
+ self.assertNotIn(call(2), something.method_1.mock_calls)
+ self.assertNotIn(call(3), something.method_1.mock_calls)
+
+ something.method_1.wait_until_any_call_with(3)
+ self.assertIn(call(2), something.method_1.mock_calls)
+ something.method_1.wait_until_any_call_with(2)
+
+ def test_wait_until_any_call_with_keywords(self):
+ waitable_mock = self._make_mock(spec=Something)
+
+ with patch(f"{__name__}.Something", waitable_mock):
+ something = Something()
+ self.run_async(something.method_1, a=1, delay=0.2)
+ self.assertNotIn(call(a=1), something.method_1.mock_calls)
+ self.run_async(something.method_1, b=2, delay=0.5)
+ self.run_async(something.method_1, c=3, delay=0.6)
+
+ something.method_1.wait_until_any_call_with(a=1)
+ something.method_1.assert_called_with(a=1)
+ self.assertNotIn(call(b=2), something.method_1.mock_calls)
+ self.assertNotIn(call(c=3), something.method_1.mock_calls)
+
+ something.method_1.wait_until_any_call_with(c=3)
+ self.assertIn(call(b=2), something.method_1.mock_calls)
+ something.method_1.wait_until_any_call_with(b=2)
+
+ def test_wait_until_any_call_with_no_argument_fails_when_called_with_arg(self):
+ waitable_mock = self._make_mock(timeout=0.01)
+
+ with patch(f"{__name__}.Something", waitable_mock):
+ something = Something()
+ something.method_1(1)
+
+ something.method_1.assert_called_with(1)
+ with self.assertRaises(AssertionError):
+ something.method_1.wait_until_any_call_with()
+
+ something.method_1()
+ something.method_1.wait_until_any_call_with()
+
+ def test_wait_until_any_call_with_global_default(self):
+ with patch.object(ThreadingMock, "DEFAULT_TIMEOUT"):
+ ThreadingMock.DEFAULT_TIMEOUT = 0.01
+ m = self._make_mock()
+ with self.assertRaises(AssertionError):
+ m.wait_until_any_call_with()
+ with self.assertRaises(AssertionError):
+ m.wait_until_called()
+
+ m()
+ m.wait_until_any_call_with()
+ assert ThreadingMock.DEFAULT_TIMEOUT != 0.01
+
+ def test_wait_until_any_call_with_change_global_and_override(self):
+ with patch.object(ThreadingMock, "DEFAULT_TIMEOUT"):
+ ThreadingMock.DEFAULT_TIMEOUT = 0.01
+
+ m1 = self._make_mock()
+ self.run_async(m1, delay=0.1)
+ with self.assertRaises(AssertionError):
+ m1.wait_until_called()
+
+ m2 = self._make_mock(timeout=1)
+ self.run_async(m2, delay=0.1)
+ m2.wait_until_called()
+
+ m3 = self._make_mock()
+ self.run_async(m3, delay=0.1)
+ m3.wait_until_called(timeout=1)
+
+ m4 = self._make_mock()
+ self.run_async(m4, delay=0.1)
+ m4.wait_until_called(timeout=None)
+
+ m5 = self._make_mock(timeout=None)
+ self.run_async(m5, delay=0.1)
+ m5.wait_until_called()
+
+ assert ThreadingMock.DEFAULT_TIMEOUT != 0.01
+
+ def test_reset_mock_resets_wait(self):
+ m = self._make_mock(timeout=0.01)
+
+ with self.assertRaises(AssertionError):
+ m.wait_until_called()
+ with self.assertRaises(AssertionError):
+ m.wait_until_any_call_with()
+ m()
+ m.wait_until_called()
+ m.wait_until_any_call_with()
+ m.assert_called_once()
+
+ m.reset_mock()
+
+ with self.assertRaises(AssertionError):
+ m.wait_until_called()
+ with self.assertRaises(AssertionError):
+ m.wait_until_any_call_with()
+ m()
+ m.wait_until_called()
+ m.wait_until_any_call_with()
+ m.assert_called_once()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/Lib/test/test_unittest/testmock/testwith.py b/Lib/test/test_unittest/testmock/testwith.py
index 8dc8eb1137691f..56cb16394fac40 100644
--- a/Lib/test/test_unittest/testmock/testwith.py
+++ b/Lib/test/test_unittest/testmock/testwith.py
@@ -158,7 +158,7 @@ def test_mock_open_context_manager(self):
f.read()
expected_calls = [call('foo'), call().__enter__(), call().read(),
- call().__exit__(None, None, None)]
+ call().__exit__(None, None, None), call().close()]
self.assertEqual(mock.mock_calls, expected_calls)
self.assertIs(f, handle)
@@ -172,9 +172,9 @@ def test_mock_open_context_manager_multiple_times(self):
expected_calls = [
call('foo'), call().__enter__(), call().read(),
- call().__exit__(None, None, None),
+ call().__exit__(None, None, None), call().close(),
call('bar'), call().__enter__(), call().read(),
- call().__exit__(None, None, None)]
+ call().__exit__(None, None, None), call().close()]
self.assertEqual(mock.mock_calls, expected_calls)
def test_explicit_mock(self):
diff --git a/Lib/test/test_unparse.py b/Lib/test/test_unparse.py
index 88c7c3a0af8771..b3efb61e83049e 100644
--- a/Lib/test/test_unparse.py
+++ b/Lib/test/test_unparse.py
@@ -1,4 +1,4 @@
-"""Tests for the unparse.py script in the Tools/parser directory."""
+"""Tests for ast.unparse."""
import unittest
import test.support
@@ -625,6 +625,78 @@ def test_star_expr_assign_target_multiple(self):
self.check_src_roundtrip("a, b = [c, d] = e, f = g")
+class ManualASTCreationTestCase(unittest.TestCase):
+ """Test that AST nodes created without a type_params field unparse correctly."""
+
+ def test_class(self):
+ node = ast.ClassDef(name="X", bases=[], keywords=[], body=[ast.Pass()], decorator_list=[])
+ ast.fix_missing_locations(node)
+ self.assertEqual(ast.unparse(node), "class X:\n pass")
+
+ def test_class_with_type_params(self):
+ node = ast.ClassDef(name="X", bases=[], keywords=[], body=[ast.Pass()], decorator_list=[],
+ type_params=[ast.TypeVar("T")])
+ ast.fix_missing_locations(node)
+ self.assertEqual(ast.unparse(node), "class X[T]:\n pass")
+
+ def test_function(self):
+ node = ast.FunctionDef(
+ name="f",
+ args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
+ body=[ast.Pass()],
+ decorator_list=[],
+ returns=None,
+ )
+ ast.fix_missing_locations(node)
+ self.assertEqual(ast.unparse(node), "def f():\n pass")
+
+ def test_function_with_type_params(self):
+ node = ast.FunctionDef(
+ name="f",
+ args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
+ body=[ast.Pass()],
+ decorator_list=[],
+ returns=None,
+ type_params=[ast.TypeVar("T")],
+ )
+ ast.fix_missing_locations(node)
+ self.assertEqual(ast.unparse(node), "def f[T]():\n pass")
+
+ def test_function_with_type_params_and_bound(self):
+ node = ast.FunctionDef(
+ name="f",
+ args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
+ body=[ast.Pass()],
+ decorator_list=[],
+ returns=None,
+ type_params=[ast.TypeVar("T", bound=ast.Name("int"))],
+ )
+ ast.fix_missing_locations(node)
+ self.assertEqual(ast.unparse(node), "def f[T: int]():\n pass")
+
+ def test_async_function(self):
+ node = ast.AsyncFunctionDef(
+ name="f",
+ args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
+ body=[ast.Pass()],
+ decorator_list=[],
+ returns=None,
+ )
+ ast.fix_missing_locations(node)
+ self.assertEqual(ast.unparse(node), "async def f():\n pass")
+
+ def test_async_function_with_type_params(self):
+ node = ast.AsyncFunctionDef(
+ name="f",
+ args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
+ body=[ast.Pass()],
+ decorator_list=[],
+ returns=None,
+ type_params=[ast.TypeVar("T")],
+ )
+ ast.fix_missing_locations(node)
+ self.assertEqual(ast.unparse(node), "async def f[T]():\n pass")
+
class DirectoryTestCase(ASTTestCase):
"""Test roundtrip behaviour on all files in Lib and Lib/test."""
@@ -633,7 +705,7 @@ class DirectoryTestCase(ASTTestCase):
test_directories = (lib_dir, lib_dir / "test")
run_always_files = {"test_grammar.py", "test_syntax.py", "test_compile.py",
"test_ast.py", "test_asdl_parser.py", "test_fstring.py",
- "test_patma.py"}
+ "test_patma.py", "test_type_alias.py", "test_type_params.py"}
_files_to_test = None
diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py
index a178e942ecda0f..9cec1e87fd3c2d 100755
--- a/Lib/test/test_uuid.py
+++ b/Lib/test/test_uuid.py
@@ -706,20 +706,23 @@ def test_uuid_weakref(self):
self.assertIs(strong, weak())
@mock.patch.object(sys, "argv", ["", "-u", "uuid3", "-n", "@dns"])
- def test_cli_namespace_required_for_uuid3(self):
+ @mock.patch('sys.stderr', new_callable=io.StringIO)
+ def test_cli_namespace_required_for_uuid3(self, mock_err):
with self.assertRaises(SystemExit) as cm:
self.uuid.main()
# Check that exception code is the same as argparse.ArgumentParser.error
self.assertEqual(cm.exception.code, 2)
+ self.assertIn("error: Incorrect number of arguments", mock_err.getvalue())
@mock.patch.object(sys, "argv", ["", "-u", "uuid3", "-N", "python.org"])
- def test_cli_name_required_for_uuid3(self):
+ @mock.patch('sys.stderr', new_callable=io.StringIO)
+ def test_cli_name_required_for_uuid3(self, mock_err):
with self.assertRaises(SystemExit) as cm:
self.uuid.main()
-
# Check that exception code is the same as argparse.ArgumentParser.error
self.assertEqual(cm.exception.code, 2)
+ self.assertIn("error: Incorrect number of arguments", mock_err.getvalue())
@mock.patch.object(sys, "argv", [""])
def test_cli_uuid4_outputted_with_no_args(self):
diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py
index 9e680c847dab7b..83237f5fe0d1b3 100644
--- a/Lib/test/test_warnings/__init__.py
+++ b/Lib/test/test_warnings/__init__.py
@@ -387,9 +387,13 @@ def test_catchwarnings_with_simplefilter_error(self):
with self.module.catch_warnings(
module=self.module, action="error", category=FutureWarning
):
- self.module.warn("Other types of warnings are not errors")
- self.assertRaises(FutureWarning,
- self.module.warn, FutureWarning("msg"))
+ with support.captured_stderr() as stderr:
+ error_msg = "Other types of warnings are not errors"
+ self.module.warn(error_msg)
+ self.assertRaises(FutureWarning,
+ self.module.warn, FutureWarning("msg"))
+ stderr = stderr.getvalue()
+ self.assertIn(error_msg, stderr)
class CFilterTests(FilterTests, unittest.TestCase):
module = c_warnings
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index 11efee00582e01..b9352cb865d027 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -328,7 +328,7 @@ def test_simpleops(self):
self.serialize_check(element, ' ') # 5
with self.assertRaises(ValueError) as cm:
element.remove(subelement)
- self.assertEqual(str(cm.exception), 'list.remove(x): x not in list')
+ self.assertIn('not in list', str(cm.exception))
self.serialize_check(element, ' ') # 6
element[0:0] = [subelement, subelement, subelement]
self.serialize_check(element[1], ' ')
diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py
index 9ff5545f786a32..edc741dbc60088 100644
--- a/Lib/test/test_xmlrpc.py
+++ b/Lib/test/test_xmlrpc.py
@@ -504,10 +504,16 @@ def test_time_struct(self):
self.assertEqual(str(t), time.strftime("%Y%m%dT%H:%M:%S", d))
def test_datetime_datetime(self):
+ # naive (no tzinfo)
d = datetime.datetime(2007,1,2,3,4,5)
t = xmlrpclib.DateTime(d)
self.assertEqual(str(t), '20070102T03:04:05')
+ # aware (with tzinfo): the timezone is ignored
+ d = datetime.datetime(2023, 6, 12, 13, 30, tzinfo=datetime.UTC)
+ t = xmlrpclib.DateTime(d)
+ self.assertEqual(str(t), '20230612T13:30:00')
+
def test_repr(self):
d = datetime.datetime(2007,1,2,3,4,5)
t = xmlrpclib.DateTime(d)
diff --git a/Lib/test/test_xmlrpc_net.py b/Lib/test/test_xmlrpc_net.py
deleted file mode 100644
index 51167b28bc5a1e..00000000000000
--- a/Lib/test/test_xmlrpc_net.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import collections.abc
-import unittest
-from test import support
-
-import xmlrpc.client as xmlrpclib
-
-
-support.requires("network")
-
-
-@unittest.skip('XXX: buildbot.python.org/all/xmlrpc/ is gone')
-class PythonBuildersTest(unittest.TestCase):
-
- def test_python_builders(self):
- # Get the list of builders from the XMLRPC buildbot interface at
- # python.org.
- server = xmlrpclib.ServerProxy("http://buildbot.python.org/all/xmlrpc/")
- try:
- builders = server.getAllBuilders()
- except OSError as e:
- self.skipTest("network error: %s" % e)
- self.addCleanup(lambda: server('close')())
-
- # Perform a minimal sanity check on the result, just to be sure
- # the request means what we think it means.
- self.assertIsInstance(builders, collections.abc.Sequence)
- self.assertTrue([x for x in builders if "3.x" in x], builders)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/Lib/test/test_zipfile/_path/__init__.py b/Lib/test/test_zipfile/_path/__init__.py
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/Lib/test/test_zipfile/_functools.py b/Lib/test/test_zipfile/_path/_functools.py
similarity index 100%
rename from Lib/test/test_zipfile/_functools.py
rename to Lib/test/test_zipfile/_path/_functools.py
diff --git a/Lib/test/test_zipfile/_itertools.py b/Lib/test/test_zipfile/_path/_itertools.py
similarity index 100%
rename from Lib/test/test_zipfile/_itertools.py
rename to Lib/test/test_zipfile/_path/_itertools.py
diff --git a/Lib/test/test_zipfile/_support.py b/Lib/test/test_zipfile/_path/_support.py
similarity index 100%
rename from Lib/test/test_zipfile/_support.py
rename to Lib/test/test_zipfile/_path/_support.py
diff --git a/Lib/test/test_zipfile/_test_params.py b/Lib/test/test_zipfile/_path/_test_params.py
similarity index 100%
rename from Lib/test/test_zipfile/_test_params.py
rename to Lib/test/test_zipfile/_path/_test_params.py
diff --git a/Lib/test/test_zipfile/_path/test_complexity.py b/Lib/test/test_zipfile/_path/test_complexity.py
new file mode 100644
index 00000000000000..7050937738af18
--- /dev/null
+++ b/Lib/test/test_zipfile/_path/test_complexity.py
@@ -0,0 +1,103 @@
+import io
+import itertools
+import math
+import re
+import string
+import unittest
+import zipfile
+
+from ._functools import compose
+from ._itertools import consume
+
+from ._support import import_or_skip
+
+
+big_o = import_or_skip('big_o')
+pytest = import_or_skip('pytest')
+
+
+class TestComplexity(unittest.TestCase):
+ @pytest.mark.flaky
+ def test_implied_dirs_performance(self):
+ best, others = big_o.big_o(
+ compose(consume, zipfile.CompleteDirs._implied_dirs),
+ lambda size: [
+ '/'.join(string.ascii_lowercase + str(n)) for n in range(size)
+ ],
+ max_n=1000,
+ min_n=1,
+ )
+ assert best <= big_o.complexities.Linear
+
+ def make_zip_path(self, depth=1, width=1) -> zipfile.Path:
+ """
+ Construct a Path with width files at every level of depth.
+ """
+ zf = zipfile.ZipFile(io.BytesIO(), mode='w')
+ pairs = itertools.product(self.make_deep_paths(depth), self.make_names(width))
+ for path, name in pairs:
+ zf.writestr(f"{path}{name}.txt", b'')
+ zf.filename = "big un.zip"
+ return zipfile.Path(zf)
+
+ @classmethod
+ def make_names(cls, width, letters=string.ascii_lowercase):
+ """
+ >>> list(TestComplexity.make_names(2))
+ ['a', 'b']
+ >>> list(TestComplexity.make_names(30))
+ ['aa', 'ab', ..., 'bd']
+ """
+ # determine how many products are needed to produce width
+ n_products = math.ceil(math.log(width, len(letters)))
+ inputs = (letters,) * n_products
+ combinations = itertools.product(*inputs)
+ names = map(''.join, combinations)
+ return itertools.islice(names, width)
+
+ @classmethod
+ def make_deep_paths(cls, depth):
+ return map(cls.make_deep_path, range(depth))
+
+ @classmethod
+ def make_deep_path(cls, depth):
+ return ''.join(('d/',) * depth)
+
+ def test_baseline_regex_complexity(self):
+ best, others = big_o.big_o(
+ lambda path: re.fullmatch(r'[^/]*\\.txt', path),
+ self.make_deep_path,
+ max_n=100,
+ min_n=1,
+ )
+ assert best <= big_o.complexities.Constant
+
+ @pytest.mark.flaky
+ def test_glob_depth(self):
+ best, others = big_o.big_o(
+ lambda path: consume(path.glob('*.txt')),
+ self.make_zip_path,
+ max_n=100,
+ min_n=1,
+ )
+ assert best <= big_o.complexities.Quadratic
+
+ @pytest.mark.flaky
+ def test_glob_width(self):
+ best, others = big_o.big_o(
+ lambda path: consume(path.glob('*.txt')),
+ lambda size: self.make_zip_path(width=size),
+ max_n=100,
+ min_n=1,
+ )
+ assert best <= big_o.complexities.Linear
+
+ @pytest.mark.flaky
+ def test_glob_width_and_depth(self):
+ best, others = big_o.big_o(
+ lambda path: consume(path.glob('*.txt')),
+ lambda size: self.make_zip_path(depth=size, width=size),
+ max_n=10,
+ min_n=1,
+ )
+ assert best <= big_o.complexities.Linear
diff --git a/Lib/test/test_zipfile/test_path.py b/Lib/test/test_zipfile/_path/test_path.py
similarity index 89%
rename from Lib/test/test_zipfile/test_path.py
rename to Lib/test/test_zipfile/_path/test_path.py
index aff91e53995875..c66cb3cba69ebd 100644
--- a/Lib/test/test_zipfile/test_path.py
+++ b/Lib/test/test_zipfile/_path/test_path.py
@@ -41,9 +41,13 @@ def build_alpharep_fixture():
│ ├── d
│ │ └── e.txt
│ └── f.txt
- └── g
- └── h
- └── i.txt
+ ├── g
+ │ └── h
+ │ └── i.txt
+ └── j
+ ├── k.bin
+ ├── l.baz
+ └── m.bar
This fixture has the following key characteristics:
@@ -51,6 +55,7 @@ def build_alpharep_fixture():
- a file two levels deep (b/d/e)
- multiple files in a directory (b/c, b/f)
- a directory containing only a directory (g/h)
+ - a directory with files of different extensions (j/klm)
"alpha" because it uses alphabet
"rep" because it's a representative example
@@ -62,6 +67,9 @@ def build_alpharep_fixture():
zf.writestr("b/d/e.txt", b"content of e")
zf.writestr("b/f.txt", b"content of f")
zf.writestr("g/h/i.txt", b"content of i")
+ zf.writestr("j/k.bin", b"content of k")
+ zf.writestr("j/l.baz", b"content of l")
+ zf.writestr("j/m.bar", b"content of m")
zf.filename = "alpharep.zip"
return zf
@@ -92,7 +100,7 @@ def zipfile_ondisk(self, alpharep):
def test_iterdir_and_types(self, alpharep):
root = zipfile.Path(alpharep)
assert root.is_dir()
- a, b, g = root.iterdir()
+ a, b, g, j = root.iterdir()
assert a.is_file()
assert b.is_dir()
assert g.is_dir()
@@ -112,7 +120,7 @@ def test_is_file_missing(self, alpharep):
@pass_alpharep
def test_iterdir_on_file(self, alpharep):
root = zipfile.Path(alpharep)
- a, b, g = root.iterdir()
+ a, b, g, j = root.iterdir()
with self.assertRaises(ValueError):
a.iterdir()
@@ -127,7 +135,7 @@ def test_subdir_is_dir(self, alpharep):
@pass_alpharep
def test_open(self, alpharep):
root = zipfile.Path(alpharep)
- a, b, g = root.iterdir()
+ a, b, g, j = root.iterdir()
with a.open(encoding="utf-8") as strm:
data = strm.read()
self.assertEqual(data, "content of a")
@@ -229,7 +237,7 @@ def test_open_missing_directory(self):
@pass_alpharep
def test_read(self, alpharep):
root = zipfile.Path(alpharep)
- a, b, g = root.iterdir()
+ a, b, g, j = root.iterdir()
assert a.read_text(encoding="utf-8") == "content of a"
# Also check positional encoding arg (gh-101144).
assert a.read_text("utf-8") == "content of a"
@@ -295,7 +303,7 @@ def test_mutability(self, alpharep):
reflect that change.
"""
root = zipfile.Path(alpharep)
- a, b, g = root.iterdir()
+ a, b, g, j = root.iterdir()
alpharep.writestr('foo.txt', 'foo')
alpharep.writestr('bar/baz.txt', 'baz')
assert any(child.name == 'foo.txt' for child in root.iterdir())
@@ -394,6 +402,13 @@ def test_suffixes(self, alpharep):
e = root / '.hgrc'
assert e.suffixes == []
+ @pass_alpharep
+ def test_suffix_no_filename(self, alpharep):
+ alpharep.filename = None
+ root = zipfile.Path(alpharep)
+ assert root.joinpath('example').suffix == ""
+ assert root.joinpath('example').suffixes == []
+
@pass_alpharep
def test_stem(self, alpharep):
"""
@@ -411,6 +426,8 @@ def test_stem(self, alpharep):
d = root / "d"
assert d.stem == "d"
+ assert (root / ".gitignore").stem == ".gitignore"
+
@pass_alpharep
def test_root_parent(self, alpharep):
root = zipfile.Path(alpharep)
@@ -442,12 +459,49 @@ def test_match_and_glob(self, alpharep):
assert not root.match("*.txt")
assert list(root.glob("b/c.*")) == [zipfile.Path(alpharep, "b/c.txt")]
+ assert list(root.glob("b/*.txt")) == [
+ zipfile.Path(alpharep, "b/c.txt"),
+ zipfile.Path(alpharep, "b/f.txt"),
+ ]
+ @pass_alpharep
+ def test_glob_recursive(self, alpharep):
+ root = zipfile.Path(alpharep)
files = root.glob("**/*.txt")
assert all(each.match("*.txt") for each in files)
assert list(root.glob("**/*.txt")) == list(root.rglob("*.txt"))
+ @pass_alpharep
+ def test_glob_subdirs(self, alpharep):
+ root = zipfile.Path(alpharep)
+
+ assert list(root.glob("*/i.txt")) == []
+ assert list(root.rglob("*/i.txt")) == [zipfile.Path(alpharep, "g/h/i.txt")]
+
+ @pass_alpharep
+ def test_glob_does_not_overmatch_dot(self, alpharep):
+ root = zipfile.Path(alpharep)
+
+ assert list(root.glob("*.xt")) == []
+
+ @pass_alpharep
+ def test_glob_single_char(self, alpharep):
+ root = zipfile.Path(alpharep)
+
+ assert list(root.glob("a?txt")) == [zipfile.Path(alpharep, "a.txt")]
+ assert list(root.glob("a[.]txt")) == [zipfile.Path(alpharep, "a.txt")]
+ assert list(root.glob("a[?]txt")) == []
+
+ @pass_alpharep
+ def test_glob_chars(self, alpharep):
+ root = zipfile.Path(alpharep)
+
+ assert list(root.glob("j/?.b[ai][nz]")) == [
+ zipfile.Path(alpharep, "j/k.bin"),
+ zipfile.Path(alpharep, "j/l.baz"),
+ ]
+
def test_glob_empty(self):
root = zipfile.Path(zipfile.ZipFile(io.BytesIO(), 'w'))
with self.assertRaises(ValueError):
diff --git a/Lib/test/test_zipfile/_path/write-alpharep.py b/Lib/test/test_zipfile/_path/write-alpharep.py
new file mode 100644
index 00000000000000..48c09b537179fd
--- /dev/null
+++ b/Lib/test/test_zipfile/_path/write-alpharep.py
@@ -0,0 +1,4 @@
+from . import test_path
+
+
+__name__ == '__main__' and test_path.build_alpharep_fixture().extractall('alpharep')
diff --git a/Lib/test/test_zipfile/test_complexity.py b/Lib/test/test_zipfile/test_complexity.py
deleted file mode 100644
index 3432dc39e56c4e..00000000000000
--- a/Lib/test/test_zipfile/test_complexity.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import unittest
-import string
-import zipfile
-
-from ._functools import compose
-from ._itertools import consume
-
-from ._support import import_or_skip
-
-
-big_o = import_or_skip('big_o')
-
-
-class TestComplexity(unittest.TestCase):
- def test_implied_dirs_performance(self):
- best, others = big_o.big_o(
- compose(consume, zipfile.CompleteDirs._implied_dirs),
- lambda size: [
- '/'.join(string.ascii_lowercase + str(n)) for n in range(size)
- ],
- max_n=1000,
- min_n=1,
- )
- assert best <= big_o.complexities.Linear
diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py
index 14c19719e260c4..c12798d221e9b7 100644
--- a/Lib/test/test_zipimport.py
+++ b/Lib/test/test_zipimport.py
@@ -520,10 +520,10 @@ def testInvalidateCaches(self):
z.writestr(zinfo, data)
zi = zipimport.zipimporter(TEMP_ZIP)
- self.assertEqual(zi._files.keys(), files.keys())
+ self.assertEqual(zi._get_files().keys(), files.keys())
# Check that the file information remains accurate after reloading
zi.invalidate_caches()
- self.assertEqual(zi._files.keys(), files.keys())
+ self.assertEqual(zi._get_files().keys(), files.keys())
# Add a new file to the ZIP archive
newfile = {"spam2" + pyc_ext: (NOW, test_pyc)}
files.update(newfile)
@@ -535,17 +535,54 @@ def testInvalidateCaches(self):
z.writestr(zinfo, data)
# Check that we can detect the new file after invalidating the cache
zi.invalidate_caches()
- self.assertEqual(zi._files.keys(), files.keys())
+ self.assertEqual(zi._get_files().keys(), files.keys())
spec = zi.find_spec('spam2')
self.assertIsNotNone(spec)
self.assertIsInstance(spec.loader, zipimport.zipimporter)
# Check that the cached data is removed if the file is deleted
os.remove(TEMP_ZIP)
zi.invalidate_caches()
- self.assertFalse(zi._files)
+ self.assertFalse(zi._get_files())
self.assertIsNone(zipimport._zip_directory_cache.get(zi.archive))
self.assertIsNone(zi.find_spec("name_does_not_matter"))
+ def testInvalidateCachesWithMultipleZipimports(self):
+ packdir = TESTPACK + os.sep
+ packdir2 = packdir + TESTPACK2 + os.sep
+ files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
+ packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
+ packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc),
+ "spam" + pyc_ext: (NOW, test_pyc)}
+ self.addCleanup(os_helper.unlink, TEMP_ZIP)
+ with ZipFile(TEMP_ZIP, "w") as z:
+ for name, (mtime, data) in files.items():
+ zinfo = ZipInfo(name, time.localtime(mtime))
+ zinfo.compress_type = self.compression
+ zinfo.comment = b"spam"
+ z.writestr(zinfo, data)
+
+ zi = zipimport.zipimporter(TEMP_ZIP)
+ self.assertEqual(zi._get_files().keys(), files.keys())
+ # Zipimporter for the same path.
+ zi2 = zipimport.zipimporter(TEMP_ZIP)
+ self.assertEqual(zi2._get_files().keys(), files.keys())
+ # Add a new file to the ZIP archive to make the cache wrong.
+ newfile = {"spam2" + pyc_ext: (NOW, test_pyc)}
+ files.update(newfile)
+ with ZipFile(TEMP_ZIP, "a") as z:
+ for name, (mtime, data) in newfile.items():
+ zinfo = ZipInfo(name, time.localtime(mtime))
+ zinfo.compress_type = self.compression
+ zinfo.comment = b"spam"
+ z.writestr(zinfo, data)
+ # Invalidate the cache of the first zipimporter.
+ zi.invalidate_caches()
+ # Check that the second zipimporter detects the new file and isn't using a stale cache.
+ self.assertEqual(zi2._get_files().keys(), files.keys())
+ spec = zi2.find_spec('spam2')
+ self.assertIsNotNone(spec)
+ self.assertIsInstance(spec.loader, zipimport.zipimporter)
+
def testZipImporterMethodsInSubDirectory(self):
packdir = TESTPACK + os.sep
packdir2 = packdir + TESTPACK2 + os.sep
diff --git a/Lib/threading.py b/Lib/threading.py
index df273870fa4273..e036cb891e196d 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -1451,11 +1451,12 @@ def _stop(self):
pass
def is_alive(self):
- assert not self._is_stopped and self._started.is_set()
- return True
+ if not self._is_stopped and self._started.is_set():
+ return True
+ raise RuntimeError("thread is not alive")
def join(self, timeout=None):
- assert False, "cannot join a dummy thread"
+ raise RuntimeError("cannot join a dummy thread")
# Global API functions
diff --git a/Lib/tokenize.py b/Lib/tokenize.py
index 49e8144edddab7..c21876fb403d8f 100644
--- a/Lib/tokenize.py
+++ b/Lib/tokenize.py
@@ -41,7 +41,7 @@
import token
__all__ = token.__all__ + ["tokenize", "generate_tokens", "detect_encoding",
- "untokenize", "TokenInfo"]
+ "untokenize", "TokenInfo", "open", "TokenError"]
del token
class TokenInfo(collections.namedtuple('TokenInfo', 'type string start end line')):
@@ -162,8 +162,6 @@ def _compile(expr):
class TokenError(Exception): pass
-class StopTokenizing(Exception): pass
-
class Untokenizer:
def __init__(self):
diff --git a/Lib/typing.py b/Lib/typing.py
index a531e7d7abbef6..387b4c5ad5284b 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -131,7 +131,9 @@
'get_args',
'get_origin',
'get_overloads',
+ 'get_protocol_members',
'get_type_hints',
+ 'is_protocol',
'is_typeddict',
'LiteralString',
'Never',
@@ -1816,14 +1818,17 @@ def __init__(cls, *args, **kwargs):
def __subclasscheck__(cls, other):
if cls is Protocol:
return type.__subclasscheck__(cls, other)
- if not isinstance(other, type):
- # Same error message as for issubclass(1, int).
- raise TypeError('issubclass() arg 1 must be a class')
if (
getattr(cls, '_is_protocol', False)
and not _allow_reckless_class_checks()
):
- if not cls.__callable_proto_members_only__:
+ if not isinstance(other, type):
+ # Same error message as for issubclass(1, int).
+ raise TypeError('issubclass() arg 1 must be a class')
+ if (
+ not cls.__callable_proto_members_only__
+ and cls.__dict__.get("__subclasshook__") is _proto_hook
+ ):
raise TypeError(
"Protocols with non-method members don't support issubclass()"
)
@@ -1867,6 +1872,30 @@ def __instancecheck__(cls, instance):
return False
+@classmethod
+def _proto_hook(cls, other):
+ if not cls.__dict__.get('_is_protocol', False):
+ return NotImplemented
+
+ for attr in cls.__protocol_attrs__:
+ for base in other.__mro__:
+ # Check if the members appears in the class dictionary...
+ if attr in base.__dict__:
+ if base.__dict__[attr] is None:
+ return NotImplemented
+ break
+
+ # ...or in annotations, if it is a sub-protocol.
+ annotations = getattr(base, '__annotations__', {})
+ if (isinstance(annotations, collections.abc.Mapping) and
+ attr in annotations and
+ issubclass(other, Generic) and getattr(other, '_is_protocol', False)):
+ break
+ else:
+ return NotImplemented
+ return True
+
+
class Protocol(Generic, metaclass=_ProtocolMeta):
"""Base class for protocol classes.
@@ -1912,37 +1941,11 @@ def __init_subclass__(cls, *args, **kwargs):
cls._is_protocol = any(b is Protocol for b in cls.__bases__)
# Set (or override) the protocol subclass hook.
- def _proto_hook(other):
- if not cls.__dict__.get('_is_protocol', False):
- return NotImplemented
-
- for attr in cls.__protocol_attrs__:
- for base in other.__mro__:
- # Check if the members appears in the class dictionary...
- if attr in base.__dict__:
- if base.__dict__[attr] is None:
- return NotImplemented
- break
-
- # ...or in annotations, if it is a sub-protocol.
- annotations = getattr(base, '__annotations__', {})
- if (isinstance(annotations, collections.abc.Mapping) and
- attr in annotations and
- issubclass(other, Generic) and getattr(other, '_is_protocol', False)):
- break
- else:
- return NotImplemented
- return True
-
if '__subclasshook__' not in cls.__dict__:
cls.__subclasshook__ = _proto_hook
- # We have nothing more to do for non-protocols...
- if not cls._is_protocol:
- return
-
- # ... otherwise prohibit instantiation.
- if cls.__init__ is Protocol.__init__:
+ # Prohibit instantiation for protocol classes
+ if cls._is_protocol and cls.__init__ is Protocol.__init__:
cls.__init__ = _no_init_or_replace_init
@@ -2392,6 +2395,8 @@ def no_type_check_decorator(decorator):
This wraps the decorator with something that wraps the decorated
function in @no_type_check.
"""
+ import warnings
+ warnings._deprecated("typing.no_type_check_decorator", remove=(3, 15))
@functools.wraps(decorator)
def wrapped_decorator(*args, **kwds):
func = decorator(*args, **kwds)
@@ -2753,7 +2758,16 @@ def __new__(cls, typename, bases, ns):
return nm_tpl
-def NamedTuple(typename, fields=None, /, **kwargs):
+class _Sentinel:
+ __slots__ = ()
+ def __repr__(self):
+ return ''
+
+
+_sentinel = _Sentinel()
+
+
+def NamedTuple(typename, fields=_sentinel, /, **kwargs):
"""Typed version of namedtuple.
Usage::
@@ -2773,11 +2787,44 @@ class Employee(NamedTuple):
Employee = NamedTuple('Employee', [('name', str), ('id', int)])
"""
- if fields is None:
- fields = kwargs.items()
+ if fields is _sentinel:
+ if kwargs:
+ deprecated_thing = "Creating NamedTuple classes using keyword arguments"
+ deprecation_msg = (
+ "{name} is deprecated and will be disallowed in Python {remove}. "
+ "Use the class-based or functional syntax instead."
+ )
+ else:
+ deprecated_thing = "Failing to pass a value for the 'fields' parameter"
+ example = f"`{typename} = NamedTuple({typename!r}, [])`"
+ deprecation_msg = (
+ "{name} is deprecated and will be disallowed in Python {remove}. "
+ "To create a NamedTuple class with 0 fields "
+ "using the functional syntax, "
+ "pass an empty list, e.g. "
+ ) + example + "."
+ elif fields is None:
+ if kwargs:
+ raise TypeError(
+ "Cannot pass `None` as the 'fields' parameter "
+ "and also specify fields using keyword arguments"
+ )
+ else:
+ deprecated_thing = "Passing `None` as the 'fields' parameter"
+ example = f"`{typename} = NamedTuple({typename!r}, [])`"
+ deprecation_msg = (
+ "{name} is deprecated and will be disallowed in Python {remove}. "
+ "To create a NamedTuple class with 0 fields "
+ "using the functional syntax, "
+ "pass an empty list, e.g. "
+ ) + example + "."
elif kwargs:
raise TypeError("Either list of fields or keywords"
" can be provided to NamedTuple, not both")
+ if fields is _sentinel or fields is None:
+ import warnings
+ warnings._deprecated(deprecated_thing, message=deprecation_msg, remove=(3, 15))
+ fields = kwargs.items()
nt = _make_nmtuple(typename, fields, module=_caller())
nt.__orig_bases__ = (NamedTuple,)
return nt
@@ -2864,7 +2911,7 @@ def __subclasscheck__(cls, other):
__instancecheck__ = __subclasscheck__
-def TypedDict(typename, fields=None, /, *, total=True):
+def TypedDict(typename, fields=_sentinel, /, *, total=True):
"""A simple typed namespace. At runtime it is equivalent to a plain dict.
TypedDict creates a dictionary type such that a type checker will expect all
@@ -2911,7 +2958,22 @@ class Point2D(TypedDict):
See PEP 655 for more details on Required and NotRequired.
"""
- if fields is None:
+ if fields is _sentinel or fields is None:
+ import warnings
+
+ if fields is _sentinel:
+ deprecated_thing = "Failing to pass a value for the 'fields' parameter"
+ else:
+ deprecated_thing = "Passing `None` as the 'fields' parameter"
+
+ example = f"`{typename} = TypedDict({typename!r}, {{{{}}}})`"
+ deprecation_msg = (
+ "{name} is deprecated and will be disallowed in Python {remove}. "
+ "To create a TypedDict class with 0 fields "
+ "using the functional syntax, "
+ "pass an empty dictionary, e.g. "
+ ) + example + "."
+ warnings._deprecated(deprecated_thing, message=deprecation_msg, remove=(3, 15))
fields = {}
ns = {'__annotations__': dict(fields)}
@@ -3337,3 +3399,43 @@ def method(self) -> None:
# read-only property, TypeError if it's a builtin class.
pass
return method
+
+
+def is_protocol(tp: type, /) -> bool:
+ """Return True if the given type is a Protocol.
+
+ Example::
+
+ >>> from typing import Protocol, is_protocol
+ >>> class P(Protocol):
+ ... def a(self) -> str: ...
+ ... b: int
+ >>> is_protocol(P)
+ True
+ >>> is_protocol(int)
+ False
+ """
+ return (
+ isinstance(tp, type)
+ and getattr(tp, '_is_protocol', False)
+ and tp != Protocol
+ )
+
+
+def get_protocol_members(tp: type, /) -> frozenset[str]:
+ """Return the set of members defined in a Protocol.
+
+ Example::
+
+ >>> from typing import Protocol, get_protocol_members
+ >>> class P(Protocol):
+ ... def a(self) -> str: ...
+ ... b: int
+ >>> get_protocol_members(P)
+ frozenset({'a', 'b'})
+
+ Raise a TypeError for arguments that are not Protocols.
+ """
+ if not is_protocol(tp):
+ raise TypeError(f'{tp!r} is not a Protocol')
+ return frozenset(tp.__protocol_attrs__)
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index 4ca7062961a6ba..e8c8360e0ae13e 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -14,6 +14,7 @@
'call',
'create_autospec',
'AsyncMock',
+ 'ThreadingMock',
'FILTER_DIR',
'NonCallableMock',
'NonCallableMagicMock',
@@ -32,6 +33,7 @@
import builtins
import pkgutil
from asyncio import iscoroutinefunction
+import threading
from types import CodeType, ModuleType, MethodType
from unittest.util import safe_repr
from functools import wraps, partial
@@ -210,17 +212,12 @@ def _set_async_signature(mock, original, instance=False, is_async_mock=False):
# signature as the original.
skipfirst = isinstance(original, type)
- result = _get_signature_object(original, instance, skipfirst)
- if result is None:
- return mock
- func, sig = result
+ func, sig = _get_signature_object(original, instance, skipfirst)
def checksig(*args, **kwargs):
sig.bind(*args, **kwargs)
_copy_func_details(func, checksig)
name = original.__name__
- if not name.isidentifier():
- name = 'funcopy'
context = {'_checksig_': checksig, 'mock': mock}
src = """async def %s(*args, **kwargs):
_checksig_(*args, **kwargs)
@@ -2941,6 +2938,9 @@ def _next_side_effect():
return handle.readline.return_value
return next(_state[0])
+ def _exit_side_effect(exctype, excinst, exctb):
+ handle.close()
+
global file_spec
if file_spec is None:
import _io
@@ -2967,6 +2967,7 @@ def _next_side_effect():
handle.readlines.side_effect = _readlines_side_effect
handle.__iter__.side_effect = _iter_side_effect
handle.__next__.side_effect = _next_side_effect
+ handle.__exit__.side_effect = _exit_side_effect
def reset_data(*args, **kwargs):
_state[0] = _to_stream(read_data)
@@ -2999,6 +3000,96 @@ def __set__(self, obj, val):
self(val)
+_timeout_unset = sentinel.TIMEOUT_UNSET
+
+class ThreadingMixin(Base):
+
+ DEFAULT_TIMEOUT = None
+
+ def _get_child_mock(self, /, **kw):
+ if isinstance(kw.get("parent"), ThreadingMixin):
+ kw["timeout"] = kw["parent"]._mock_wait_timeout
+ elif isinstance(kw.get("_new_parent"), ThreadingMixin):
+ kw["timeout"] = kw["_new_parent"]._mock_wait_timeout
+ return super()._get_child_mock(**kw)
+
+ def __init__(self, *args, timeout=_timeout_unset, **kwargs):
+ super().__init__(*args, **kwargs)
+ if timeout is _timeout_unset:
+ timeout = self.DEFAULT_TIMEOUT
+ self.__dict__["_mock_event"] = threading.Event() # Event for any call
+ self.__dict__["_mock_calls_events"] = [] # Events for each of the calls
+ self.__dict__["_mock_calls_events_lock"] = threading.Lock()
+ self.__dict__["_mock_wait_timeout"] = timeout
+
+ def reset_mock(self, /, *args, **kwargs):
+ """
+ See :func:`.Mock.reset_mock()`
+ """
+ super().reset_mock(*args, **kwargs)
+ self.__dict__["_mock_event"] = threading.Event()
+ self.__dict__["_mock_calls_events"] = []
+
+ def __get_event(self, expected_args, expected_kwargs):
+ with self._mock_calls_events_lock:
+ for args, kwargs, event in self._mock_calls_events:
+ if (args, kwargs) == (expected_args, expected_kwargs):
+ return event
+ new_event = threading.Event()
+ self._mock_calls_events.append((expected_args, expected_kwargs, new_event))
+ return new_event
+
+ def _mock_call(self, *args, **kwargs):
+ ret_value = super()._mock_call(*args, **kwargs)
+
+ call_event = self.__get_event(args, kwargs)
+ call_event.set()
+
+ self._mock_event.set()
+
+ return ret_value
+
+ def wait_until_called(self, *, timeout=_timeout_unset):
+ """Wait until the mock object is called.
+
+ `timeout` - time to wait for in seconds, waits forever otherwise.
+ Defaults to the constructor provided timeout.
+ Use None to block undefinetively.
+ """
+ if timeout is _timeout_unset:
+ timeout = self._mock_wait_timeout
+ if not self._mock_event.wait(timeout=timeout):
+ msg = (f"{self._mock_name or 'mock'} was not called before"
+ f" timeout({timeout}).")
+ raise AssertionError(msg)
+
+ def wait_until_any_call_with(self, *args, **kwargs):
+ """Wait until the mock object is called with given args.
+
+ Waits for the timeout in seconds provided in the constructor.
+ """
+ event = self.__get_event(args, kwargs)
+ if not event.wait(timeout=self._mock_wait_timeout):
+ expected_string = self._format_mock_call_signature(args, kwargs)
+ raise AssertionError(f'{expected_string} call not found')
+
+
+class ThreadingMock(ThreadingMixin, MagicMixin, Mock):
+ """
+ A mock that can be used to wait until on calls happening
+ in a different thread.
+
+ The constructor can take a `timeout` argument which
+ controls the timeout in seconds for all `wait` calls of the mock.
+
+ You can change the default timeout of all instances via the
+ `ThreadingMock.DEFAULT_TIMEOUT` attribute.
+
+ If no timeout is set, it will block undefinetively.
+ """
+ pass
+
+
def seal(mock):
"""Disable the automatic generation of child mocks.
diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py
index b73b34428764f7..c129b0d7971d71 100644
--- a/Lib/urllib/parse.py
+++ b/Lib/urllib/parse.py
@@ -52,18 +52,18 @@
uses_relative = ['', 'ftp', 'http', 'gopher', 'nntp', 'imap',
'wais', 'file', 'https', 'shttp', 'mms',
- 'prospero', 'rtsp', 'rtspu', 'sftp',
+ 'prospero', 'rtsp', 'rtsps', 'rtspu', 'sftp',
'svn', 'svn+ssh', 'ws', 'wss']
uses_netloc = ['', 'ftp', 'http', 'gopher', 'nntp', 'telnet',
'imap', 'wais', 'file', 'mms', 'https', 'shttp',
- 'snews', 'prospero', 'rtsp', 'rtspu', 'rsync',
+ 'snews', 'prospero', 'rtsp', 'rtsps', 'rtspu', 'rsync',
'svn', 'svn+ssh', 'sftp', 'nfs', 'git', 'git+ssh',
'ws', 'wss', 'itms-services']
uses_params = ['', 'ftp', 'hdl', 'prospero', 'http', 'imap',
- 'https', 'shttp', 'rtsp', 'rtspu', 'sip', 'sips',
- 'mms', 'sftp', 'tel']
+ 'https', 'shttp', 'rtsp', 'rtsps', 'rtspu', 'sip',
+ 'sips', 'mms', 'sftp', 'tel']
# These are not actually used anymore, but should stay for backwards
# compatibility. (They are undocumented, but have a public-looking name.)
@@ -72,7 +72,7 @@
'telnet', 'wais', 'imap', 'snews', 'sip', 'sips']
uses_query = ['', 'http', 'wais', 'imap', 'https', 'shttp', 'mms',
- 'gopher', 'rtsp', 'rtspu', 'sip', 'sips']
+ 'gopher', 'rtsp', 'rtsps', 'rtspu', 'sip', 'sips']
uses_fragment = ['', 'ftp', 'hdl', 'http', 'gopher', 'news',
'nntp', 'wais', 'https', 'shttp', 'snews',
diff --git a/Lib/venv/scripts/common/Activate.ps1 b/Lib/venv/scripts/common/Activate.ps1
index eeea3583fa130d..d75b8fbcfc7778 100644
--- a/Lib/venv/scripts/common/Activate.ps1
+++ b/Lib/venv/scripts/common/Activate.ps1
@@ -219,6 +219,8 @@ deactivate -nondestructive
# that there is an activated venv.
$env:VIRTUAL_ENV = $VenvDir
+$env:VIRTUAL_ENV_PROMPT = $Prompt
+
if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
Write-Verbose "Setting prompt to '$Prompt'"
@@ -233,7 +235,6 @@ if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
_OLD_VIRTUAL_PROMPT
}
- $env:VIRTUAL_ENV_PROMPT = $Prompt
}
# Clear PYTHONHOME
diff --git a/Lib/venv/scripts/common/activate b/Lib/venv/scripts/common/activate
index 408df5cb93b9e9..458740a35b0d20 100644
--- a/Lib/venv/scripts/common/activate
+++ b/Lib/venv/scripts/common/activate
@@ -52,6 +52,9 @@ _OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
export PATH
+VIRTUAL_ENV_PROMPT="__VENV_PROMPT__"
+export VIRTUAL_ENV_PROMPT
+
# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
@@ -64,8 +67,6 @@ if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
_OLD_VIRTUAL_PS1="${PS1:-}"
PS1="__VENV_PROMPT__${PS1:-}"
export PS1
- VIRTUAL_ENV_PROMPT="__VENV_PROMPT__"
- export VIRTUAL_ENV_PROMPT
fi
# This should detect bash and zsh, which have a hash command that must
diff --git a/Lib/venv/scripts/posix/activate.csh b/Lib/venv/scripts/posix/activate.csh
index 5e8d66fa9e5061..9caf138a919a86 100644
--- a/Lib/venv/scripts/posix/activate.csh
+++ b/Lib/venv/scripts/posix/activate.csh
@@ -13,13 +13,13 @@ setenv VIRTUAL_ENV "__VENV_DIR__"
set _OLD_VIRTUAL_PATH="$PATH"
setenv PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
+setenv VIRTUAL_ENV_PROMPT "__VENV_PROMPT__"
set _OLD_VIRTUAL_PROMPT="$prompt"
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
set prompt = "__VENV_PROMPT__$prompt"
- setenv VIRTUAL_ENV_PROMPT "__VENV_PROMPT__"
endif
alias pydoc python -m pydoc
diff --git a/Lib/venv/scripts/posix/activate.fish b/Lib/venv/scripts/posix/activate.fish
index 91ad6442e05692..565df23d1e2a13 100644
--- a/Lib/venv/scripts/posix/activate.fish
+++ b/Lib/venv/scripts/posix/activate.fish
@@ -37,6 +37,7 @@ set -gx VIRTUAL_ENV "__VENV_DIR__"
set -gx _OLD_VIRTUAL_PATH $PATH
set -gx PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__" $PATH
+set -gx VIRTUAL_ENV_PROMPT "__VENV_PROMPT__"
# Unset PYTHONHOME if set.
if set -q PYTHONHOME
@@ -65,5 +66,4 @@ if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
end
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
- set -gx VIRTUAL_ENV_PROMPT "__VENV_PROMPT__"
end
diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py
index 4fc9470051c1ad..8b0628745c57fc 100755
--- a/Lib/webbrowser.py
+++ b/Lib/webbrowser.py
@@ -390,15 +390,6 @@ def open(self, url, new=0, autoraise=True):
return (p.poll() is None)
- def open(self, url, new=0, autoraise=True):
- sys.audit("webbrowser.open", url)
- if new:
- ok = self._remote("LOADNEW " + url)
- else:
- ok = self._remote("LOAD " + url)
- return ok
-
-
class Edge(UnixBrowser):
"Launcher class for Microsoft Edge browser."
diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py
index ea8da766cb5a7e..f441376d09c4aa 100644
--- a/Lib/xmlrpc/client.py
+++ b/Lib/xmlrpc/client.py
@@ -245,41 +245,15 @@ def __repr__(self):
##
# Backwards compatibility
-
boolean = Boolean = bool
-##
-# Wrapper for XML-RPC DateTime values. This converts a time value to
-# the format used by XML-RPC.
-#
-# The value can be given as a datetime object, as a string in the
-# format "yyyymmddThh:mm:ss", as a 9-item time tuple (as returned by
-# time.localtime()), or an integer value (as returned by time.time()).
-# The wrapper uses time.localtime() to convert an integer to a time
-# tuple.
-#
-# @param value The time, given as a datetime object, an ISO 8601 string,
-# a time tuple, or an integer time value.
-
-# Issue #13305: different format codes across platforms
-_day0 = datetime(1, 1, 1)
-def _try(fmt):
- try:
- return _day0.strftime(fmt) == '0001'
- except ValueError:
- return False
-if _try('%Y'): # Mac OS X
- def _iso8601_format(value):
- return value.strftime("%Y%m%dT%H:%M:%S")
-elif _try('%4Y'): # Linux
- def _iso8601_format(value):
- return value.strftime("%4Y%m%dT%H:%M:%S")
-else:
- def _iso8601_format(value):
- return value.strftime("%Y%m%dT%H:%M:%S").zfill(17)
-del _day0
-del _try
+def _iso8601_format(value):
+ if value.tzinfo is not None:
+ # XML-RPC only uses the naive portion of the datetime
+ value = value.replace(tzinfo=None)
+ # XML-RPC doesn't use '-' separator in the date part
+ return value.isoformat(timespec='seconds').replace('-', '')
def _strftime(value):
diff --git a/Lib/zipapp.py b/Lib/zipapp.py
index d8ebfcb6c73b0c..03a214efa10a20 100644
--- a/Lib/zipapp.py
+++ b/Lib/zipapp.py
@@ -138,7 +138,7 @@ def create_archive(source, target=None, interpreter=None, main=None,
with zipfile.ZipFile(fd, 'w', compression=compression) as z:
for child in sorted(source.rglob('*')):
arcname = child.relative_to(source)
- if filter is None or filter(arcname):
+ if filter is None or filter(arcname) and child.resolve() != arcname.resolve():
z.write(child, arcname.as_posix())
if main_py:
z.writestr('__main__.py', main_py.encode('utf-8'))
diff --git a/Lib/zipfile/_path.py b/Lib/zipfile/_path/__init__.py
similarity index 93%
rename from Lib/zipfile/_path.py
rename to Lib/zipfile/_path/__init__.py
index fd49a3ea91db59..78c413563bb2b1 100644
--- a/Lib/zipfile/_path.py
+++ b/Lib/zipfile/_path/__init__.py
@@ -5,7 +5,8 @@
import contextlib
import pathlib
import re
-import fnmatch
+
+from .glob import translate
__all__ = ['Path']
@@ -296,21 +297,24 @@ def open(self, mode='r', *args, pwd=None, **kwargs):
encoding, args, kwargs = _extract_text_encoding(*args, **kwargs)
return io.TextIOWrapper(stream, encoding, *args, **kwargs)
+ def _base(self):
+ return pathlib.PurePosixPath(self.at or self.root.filename)
+
@property
def name(self):
- return pathlib.Path(self.at).name or self.filename.name
+ return self._base().name
@property
def suffix(self):
- return pathlib.Path(self.at).suffix or self.filename.suffix
+ return self._base().suffix
@property
def suffixes(self):
- return pathlib.Path(self.at).suffixes or self.filename.suffixes
+ return self._base().suffixes
@property
def stem(self):
- return pathlib.Path(self.at).stem or self.filename.stem
+ return self._base().stem
@property
def filename(self):
@@ -347,7 +351,7 @@ def iterdir(self):
return filter(self._is_child, subs)
def match(self, path_pattern):
- return pathlib.Path(self.at).match(path_pattern)
+ return pathlib.PurePosixPath(self.at).match(path_pattern)
def is_symlink(self):
"""
@@ -355,22 +359,13 @@ def is_symlink(self):
"""
return False
- def _descendants(self):
- for child in self.iterdir():
- yield child
- if child.is_dir():
- yield from child._descendants()
-
def glob(self, pattern):
if not pattern:
raise ValueError(f"Unacceptable pattern: {pattern!r}")
- matches = re.compile(fnmatch.translate(pattern)).fullmatch
- return (
- child
- for child in self._descendants()
- if matches(str(child.relative_to(self)))
- )
+ prefix = re.escape(self.at)
+ matches = re.compile(prefix + translate(pattern)).fullmatch
+ return map(self._next, filter(matches, self.root.namelist()))
def rglob(self, pattern):
return self.glob(f'**/{pattern}')
diff --git a/Lib/zipfile/_path/glob.py b/Lib/zipfile/_path/glob.py
new file mode 100644
index 00000000000000..4a2e665e27078a
--- /dev/null
+++ b/Lib/zipfile/_path/glob.py
@@ -0,0 +1,40 @@
+import re
+
+
+def translate(pattern):
+ r"""
+ Given a glob pattern, produce a regex that matches it.
+
+ >>> translate('*.txt')
+ '[^/]*\\.txt'
+ >>> translate('a?txt')
+ 'a.txt'
+ >>> translate('**/*')
+ '.*/[^/]*'
+ """
+ return ''.join(map(replace, separate(pattern)))
+
+
+def separate(pattern):
+ """
+ Separate out character sets to avoid translating their contents.
+
+ >>> [m.group(0) for m in separate('*.txt')]
+ ['*.txt']
+ >>> [m.group(0) for m in separate('a[?]txt')]
+ ['a', '[?]', 'txt']
+ """
+ return re.finditer(r'([^\[]+)|(?P[\[].*?[\]])|([\[][^\]]*$)', pattern)
+
+
+def replace(match):
+ """
+ Perform the replacements for a match from :func:`separate`.
+ """
+
+ return match.group('set') or (
+ re.escape(match.group(0))
+ .replace('\\*\\*', r'.*')
+ .replace('\\*', r'[^/]*')
+ .replace('\\?', r'.')
+ )
diff --git a/Lib/zipimport.py b/Lib/zipimport.py
index a7333a4c4906de..5b9f614f02f7af 100644
--- a/Lib/zipimport.py
+++ b/Lib/zipimport.py
@@ -88,12 +88,8 @@ def __init__(self, path):
raise ZipImportError('not a Zip file', path=path)
break
- try:
- files = _zip_directory_cache[path]
- except KeyError:
- files = _read_directory(path)
- _zip_directory_cache[path] = files
- self._files = files
+ if path not in _zip_directory_cache:
+ _zip_directory_cache[path] = _read_directory(path)
self.archive = path
# a prefix directory following the ZIP file path.
self.prefix = _bootstrap_external._path_join(*prefix[::-1])
@@ -152,7 +148,7 @@ def get_data(self, pathname):
key = pathname[len(self.archive + path_sep):]
try:
- toc_entry = self._files[key]
+ toc_entry = self._get_files()[key]
except KeyError:
raise OSError(0, '', key)
return _get_data(self.archive, toc_entry)
@@ -189,7 +185,7 @@ def get_source(self, fullname):
fullpath = f'{path}.py'
try:
- toc_entry = self._files[fullpath]
+ toc_entry = self._get_files()[fullpath]
except KeyError:
# we have the module, but no source
return None
@@ -268,14 +264,22 @@ def get_resource_reader(self, fullname):
return ZipReader(self, fullname)
- def invalidate_caches(self):
- """Reload the file data of the archive path."""
+ def _get_files(self):
+ """Return the files within the archive path."""
try:
- self._files = _read_directory(self.archive)
- _zip_directory_cache[self.archive] = self._files
- except ZipImportError:
- _zip_directory_cache.pop(self.archive, None)
- self._files = {}
+ files = _zip_directory_cache[self.archive]
+ except KeyError:
+ try:
+ files = _zip_directory_cache[self.archive] = _read_directory(self.archive)
+ except ZipImportError:
+ files = {}
+
+ return files
+
+
+ def invalidate_caches(self):
+ """Invalidates the cache of file data of the archive path."""
+ _zip_directory_cache.pop(self.archive, None)
def __repr__(self):
@@ -305,15 +309,15 @@ def _is_dir(self, path):
# of a namespace package. We test by seeing if the name, with an
# appended path separator, exists.
dirpath = path + path_sep
- # If dirpath is present in self._files, we have a directory.
- return dirpath in self._files
+ # If dirpath is present in self._get_files(), we have a directory.
+ return dirpath in self._get_files()
# Return some information about a module.
def _get_module_info(self, fullname):
path = _get_module_path(self, fullname)
for suffix, isbytecode, ispackage in _zip_searchorder:
fullpath = path + suffix
- if fullpath in self._files:
+ if fullpath in self._get_files():
return ispackage
return None
@@ -656,7 +660,7 @@ def _get_mtime_and_size_of_source(self, path):
# strip 'c' or 'o' from *.py[co]
assert path[-1:] in ('c', 'o')
path = path[:-1]
- toc_entry = self._files[path]
+ toc_entry = self._get_files()[path]
# fetch the time stamp of the .py file for comparison
# with an embedded pyc time stamp
time = toc_entry[5]
@@ -676,7 +680,7 @@ def _get_pyc_source(self, path):
path = path[:-1]
try:
- toc_entry = self._files[path]
+ toc_entry = self._get_files()[path]
except KeyError:
return None
else:
@@ -692,7 +696,7 @@ def _get_module_code(self, fullname):
fullpath = path + suffix
_bootstrap._verbose_message('trying {}{}{}', self.archive, path_sep, fullpath, verbosity=2)
try:
- toc_entry = self._files[fullpath]
+ toc_entry = self._get_files()[fullpath]
except KeyError:
pass
else:
diff --git a/Makefile.pre.in b/Makefile.pre.in
index a9c53bae4bf63c..553b2aa480c184 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1425,6 +1425,7 @@ regen-opcode:
# using Tools/build/generate_opcode_h.py
$(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/generate_opcode_h.py \
$(srcdir)/Lib/opcode.py \
+ $(srcdir)/Lib/_opcode_metadata.py \
$(srcdir)/Include/opcode.h.new \
$(srcdir)/Include/internal/pycore_opcode.h.new \
$(srcdir)/Include/internal/pycore_intrinsics.h.new
@@ -1541,29 +1542,39 @@ regen-opcode-targets:
.PHONY: regen-cases
regen-cases:
- # Regenerate Python/generated_cases.c.h
- # and Python/opcode_metadata.h
- # from Python/bytecodes.c
- # using Tools/cases_generator/generate_cases.py
+ # Regenerate various files from Python/bytecodes.c
+ # Pass CASESFLAG=-l to insert #line directives in the output
PYTHONPATH=$(srcdir)/Tools/cases_generator \
$(PYTHON_FOR_REGEN) \
$(srcdir)/Tools/cases_generator/generate_cases.py \
- --emit-line-directives \
+ $(CASESFLAG) \
-o $(srcdir)/Python/generated_cases.c.h.new \
- -m $(srcdir)/Python/opcode_metadata.h.new \
+ -m $(srcdir)/Include/internal/pycore_opcode_metadata.h.new \
+ -e $(srcdir)/Python/executor_cases.c.h.new \
+ -p $(srcdir)/Lib/_opcode_metadata.py.new \
$(srcdir)/Python/bytecodes.c
$(UPDATE_FILE) $(srcdir)/Python/generated_cases.c.h $(srcdir)/Python/generated_cases.c.h.new
- $(UPDATE_FILE) $(srcdir)/Python/opcode_metadata.h $(srcdir)/Python/opcode_metadata.h.new
+ $(UPDATE_FILE) $(srcdir)/Include/internal/pycore_opcode_metadata.h $(srcdir)/Include/internal/pycore_opcode_metadata.h.new
+ $(UPDATE_FILE) $(srcdir)/Python/executor_cases.c.h $(srcdir)/Python/executor_cases.c.h.new
+ $(UPDATE_FILE) $(srcdir)/Lib/_opcode_metadata.py $(srcdir)/Lib/_opcode_metadata.py.new
-Python/compile.o: $(srcdir)/Python/opcode_metadata.h
+Python/compile.o: $(srcdir)/Include/internal/pycore_opcode_metadata.h
Python/ceval.o: \
$(srcdir)/Python/ceval_macros.h \
$(srcdir)/Python/condvar.h \
$(srcdir)/Python/generated_cases.c.h \
- $(srcdir)/Python/opcode_metadata.h \
+ $(srcdir)/Python/executor_cases.c.h \
+ $(srcdir)/Include/internal/pycore_opcode_metadata.h \
$(srcdir)/Python/opcode_targets.h
+Python/flowgraph.o: \
+ $(srcdir)/Include/internal/pycore_opcode_metadata.h
+
+Python/optimizer.o: \
+ $(srcdir)/Python/executor_cases.c.h \
+ $(srcdir)/Include/internal/pycore_opcode_metadata.h
+
Python/frozen.o: $(FROZEN_FILES_OUT)
# Generate DTrace probe macros, then rename them (PYTHON_ -> PyDTrace_) to
@@ -1660,7 +1671,6 @@ PYTHON_HEADERS= \
$(srcdir)/Include/structseq.h \
$(srcdir)/Include/sysmodule.h \
$(srcdir)/Include/traceback.h \
- $(srcdir)/Include/tracemalloc.h \
$(srcdir)/Include/tupleobject.h \
$(srcdir)/Include/unicodeobject.h \
$(srcdir)/Include/warnings.h \
@@ -1699,6 +1709,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/cpython/object.h \
$(srcdir)/Include/cpython/objimpl.h \
$(srcdir)/Include/cpython/odictobject.h \
+ $(srcdir)/Include/cpython/optimizer.h \
$(srcdir)/Include/cpython/picklebufobject.h \
$(srcdir)/Include/cpython/pthread_stubs.h \
$(srcdir)/Include/cpython/pyctype.h \
@@ -1711,10 +1722,10 @@ PYTHON_HEADERS= \
$(srcdir)/Include/cpython/pystate.h \
$(srcdir)/Include/cpython/pythonrun.h \
$(srcdir)/Include/cpython/pythread.h \
- $(srcdir)/Include/cpython/pytime.h \
$(srcdir)/Include/cpython/setobject.h \
$(srcdir)/Include/cpython/sysmodule.h \
$(srcdir)/Include/cpython/traceback.h \
+ $(srcdir)/Include/cpython/tracemalloc.h \
$(srcdir)/Include/cpython/tupleobject.h \
$(srcdir)/Include/cpython/unicodeobject.h \
$(srcdir)/Include/cpython/warnings.h \
@@ -1734,7 +1745,9 @@ PYTHON_HEADERS= \
$(srcdir)/Include/internal/pycore_ceval.h \
$(srcdir)/Include/internal/pycore_ceval_state.h \
$(srcdir)/Include/internal/pycore_code.h \
+ $(srcdir)/Include/internal/pycore_codecs.h \
$(srcdir)/Include/internal/pycore_compile.h \
+ $(srcdir)/Include/internal/pycore_complexobject.h \
$(srcdir)/Include/internal/pycore_condvar.h \
$(srcdir)/Include/internal/pycore_context.h \
$(srcdir)/Include/internal/pycore_dict.h \
@@ -1761,6 +1774,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/internal/pycore_intrinsics.h \
$(srcdir)/Include/internal/pycore_list.h \
$(srcdir)/Include/internal/pycore_long.h \
+ $(srcdir)/Include/internal/pycore_modsupport.h \
$(srcdir)/Include/internal/pycore_moduleobject.h \
$(srcdir)/Include/internal/pycore_namespace.h \
$(srcdir)/Include/internal/pycore_object.h \
@@ -1799,7 +1813,9 @@ PYTHON_HEADERS= \
$(srcdir)/Include/internal/pycore_unionobject.h \
$(srcdir)/Include/internal/pycore_unicodeobject.h \
$(srcdir)/Include/internal/pycore_unicodeobject_generated.h \
+ $(srcdir)/Include/internal/pycore_uops.h \
$(srcdir)/Include/internal/pycore_warnings.h \
+ $(srcdir)/Include/internal/pycore_weakref.h \
$(DTRACE_HEADERS) \
@PLATFORM_HEADERS@ \
\
@@ -2110,7 +2126,7 @@ LIBSUBDIRS= asyncio \
wsgiref \
$(XMLLIBSUBDIRS) \
xmlrpc \
- zipfile \
+ zipfile zipfile/_path \
zoneinfo \
__phello__
TESTSUBDIRS= idlelib/idle_test \
@@ -2214,6 +2230,7 @@ TESTSUBDIRS= idlelib/idle_test \
test/test_warnings \
test/test_warnings/data \
test/test_zipfile \
+ test/test_zipfile/_path \
test/test_zoneinfo \
test/test_zoneinfo/data \
test/tkinterdata \
diff --git a/Misc/ACKS b/Misc/ACKS
index be8755637ffa3c..645ad5b700baaa 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -226,6 +226,7 @@ Erik Bray
Brian Brazil
Demian Brecht
Dave Brennan
+Christopher Richard James Brett
Tom Bridgman
Anthony Briggs
Keith Briggs
@@ -615,6 +616,7 @@ Marius Gedminas
Jan-Philip Gehrcke
Thomas Gellekum
Gabriel Genellina
+Andrew Geng
Philip Georgi
Christos Georgiou
Elazar (אלעזר) Gershuni
@@ -1946,6 +1948,7 @@ Colin Watson
David Watson
Aaron Watters
Alex Waygood
+James Webber
Russel Webber
Henrik Weber
Leon Weber
diff --git a/Misc/NEWS.d/next/Build/2023-02-03-21-36-42.gh-issue-101538.sF5F6S.rst b/Misc/NEWS.d/next/Build/2023-02-03-21-36-42.gh-issue-101538.sF5F6S.rst
new file mode 100644
index 00000000000000..4b83c303b3d2c5
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2023-02-03-21-36-42.gh-issue-101538.sF5F6S.rst
@@ -0,0 +1 @@
+Add experimental wasi-threads support. Patch by Takashi Yamamoto.
diff --git a/Misc/NEWS.d/next/Build/2023-06-16-23-40-49.gh-issue-105875.naj8v5.rst b/Misc/NEWS.d/next/Build/2023-06-16-23-40-49.gh-issue-105875.naj8v5.rst
new file mode 100644
index 00000000000000..5f60e65a2f6ae8
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2023-06-16-23-40-49.gh-issue-105875.naj8v5.rst
@@ -0,0 +1,2 @@
+SQLite 3.15.2 or newer is required to build the :mod:`sqlite3` extension
+module. Patch by Erlend Aasland.
diff --git a/Misc/NEWS.d/next/Build/2023-06-26-21-56-29.gh-issue-106118.0cCfhl.rst b/Misc/NEWS.d/next/Build/2023-06-26-21-56-29.gh-issue-106118.0cCfhl.rst
new file mode 100644
index 00000000000000..f93cae5d03b539
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2023-06-26-21-56-29.gh-issue-106118.0cCfhl.rst
@@ -0,0 +1,2 @@
+Fix compilation for platforms without :data:`!O_CLOEXEC`. The issue was
+introduced with Python 3.12b1 in :gh:`103295`. Patch by Erlend Aasland.
diff --git a/Misc/NEWS.d/next/C API/2023-06-06-14-14-41.gh-issue-103968.BTO6II.rst b/Misc/NEWS.d/next/C API/2023-06-06-14-14-41.gh-issue-103968.BTO6II.rst
new file mode 100644
index 00000000000000..b73103c4e0ad9e
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-06-06-14-14-41.gh-issue-103968.BTO6II.rst
@@ -0,0 +1,2 @@
+:c:func:`PyType_FromMetaclass` now allows metaclasses with ``tp_new``
+set to ``NULL``.
diff --git a/Misc/NEWS.d/next/C API/2023-06-09-12-35-55.gh-issue-105387.wM_oL-.rst b/Misc/NEWS.d/next/C API/2023-06-09-12-35-55.gh-issue-105387.wM_oL-.rst
new file mode 100644
index 00000000000000..d7ee7d2eb9d908
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-06-09-12-35-55.gh-issue-105387.wM_oL-.rst
@@ -0,0 +1,3 @@
+In the limited C API version 3.12, :c:func:`Py_INCREF` and
+:c:func:`Py_DECREF` functions are now implemented as opaque function calls
+to hide implementation details. Patch by Victor Stinner.
diff --git a/Misc/NEWS.d/next/C API/2023-06-09-19-16-57.gh-issue-105603.-z6G22.rst b/Misc/NEWS.d/next/C API/2023-06-09-19-16-57.gh-issue-105603.-z6G22.rst
new file mode 100644
index 00000000000000..cd3d9bcdd4e285
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-06-09-19-16-57.gh-issue-105603.-z6G22.rst
@@ -0,0 +1,5 @@
+We've renamed the new (in 3.12) ``PyInterpreterConfig.own_gil`` to
+``PyInterpreterConfig.gil`` and changed the meaning of the value from "bool"
+to an integer with supported values of ``PyInterpreterConfig_DEFAULT_GIL``,
+``PyInterpreterConfig_SHARED_GIL``, and ``PyInterpreterConfig_OWN_GIL``. The
+default is "shared".
diff --git a/Misc/NEWS.d/next/C API/2023-06-09-23-34-25.gh-issue-105375.n7amiF.rst b/Misc/NEWS.d/next/C API/2023-06-09-23-34-25.gh-issue-105375.n7amiF.rst
new file mode 100644
index 00000000000000..b9f95496f938ec
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-06-09-23-34-25.gh-issue-105375.n7amiF.rst
@@ -0,0 +1,2 @@
+Fix a bug in :c:func:`PyErr_WarnExplicit` where an exception could end up
+being overwritten if the API failed internally.
diff --git a/Misc/NEWS.d/next/C API/2023-06-13-14-24-55.gh-issue-105227.HDL9aF.rst b/Misc/NEWS.d/next/C API/2023-06-13-14-24-55.gh-issue-105227.HDL9aF.rst
new file mode 100644
index 00000000000000..846663621e8689
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-06-13-14-24-55.gh-issue-105227.HDL9aF.rst
@@ -0,0 +1,5 @@
+The new :c:func:`PyType_GetDict` provides the dictionary for the given type
+object that is normally exposed by ``cls.__dict__``. Normally it's
+sufficient to use :c:member:`~PyTypeObject.tp_dict`, but for the static
+builtin types :c:member:`!tp_dict` is now always ``NULL``. :c:func:`!PyType_GetDict()`
+provides the correct dict object instead.
diff --git a/Misc/NEWS.d/next/C API/2023-06-19-20-02-16.gh-issue-105922.o4T6wO.rst b/Misc/NEWS.d/next/C API/2023-06-19-20-02-16.gh-issue-105922.o4T6wO.rst
new file mode 100644
index 00000000000000..7515d684184e17
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-06-19-20-02-16.gh-issue-105922.o4T6wO.rst
@@ -0,0 +1,3 @@
+Add :c:func:`PyImport_AddModuleRef`: similar to :c:func:`PyImport_AddModule`,
+but return a :term:`strong reference` instead of a :term:`borrowed reference`.
+Patch by Victor Stinner.
diff --git a/Misc/NEWS.d/next/C API/2023-06-20-08-59-05.gh-issue-105927.DfGeEA.rst b/Misc/NEWS.d/next/C API/2023-06-20-08-59-05.gh-issue-105927.DfGeEA.rst
new file mode 100644
index 00000000000000..afa40c8ef5d686
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-06-20-08-59-05.gh-issue-105927.DfGeEA.rst
@@ -0,0 +1,3 @@
+Add :c:func:`PyWeakref_GetRef` function: similar to
+:c:func:`PyWeakref_GetObject` but returns a :term:`strong reference`, or
+``NULL`` if the referent is no longer live. Patch by Victor Stinner.
diff --git a/Misc/NEWS.d/next/C API/2023-06-22-00-25-55.gh-issue-105927.GRxZtI.rst b/Misc/NEWS.d/next/C API/2023-06-22-00-25-55.gh-issue-105927.GRxZtI.rst
new file mode 100644
index 00000000000000..57982dc75e004a
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-06-22-00-25-55.gh-issue-105927.GRxZtI.rst
@@ -0,0 +1,3 @@
+Deprecate the :c:func:`PyWeakref_GetObject` and
+:c:func:`PyWeakref_GET_OBJECT` functions: use the new
+:c:func:`PyWeakref_GetRef` function instead. Patch by Victor Stinner.
diff --git a/Misc/NEWS.d/next/C API/2023-06-25-18-01-27.gh-issue-106084.PEzqU3.rst b/Misc/NEWS.d/next/C API/2023-06-25-18-01-27.gh-issue-106084.PEzqU3.rst
new file mode 100644
index 00000000000000..b430f5f7ae0116
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-06-25-18-01-27.gh-issue-106084.PEzqU3.rst
@@ -0,0 +1,13 @@
+Remove the old aliases to functions calling functions which were kept for
+backward compatibility with Python 3.8 provisional API:
+
+* ``_PyObject_CallMethodNoArgs()``: use ``PyObject_CallMethodNoArgs()``
+* ``_PyObject_CallMethodOneArg()``: use ``PyObject_CallMethodOneArg()``
+* ``_PyObject_CallOneArg()``: use ``PyObject_CallOneArg()``
+* ``_PyObject_FastCallDict()``: use ``PyObject_VectorcallDict()``
+* ``_PyObject_Vectorcall()``: use ``PyObject_Vectorcall()``
+* ``_PyObject_VectorcallMethod()``: use ``PyObject_VectorcallMethod()``
+* ``_PyVectorcall_Function()``: use ``PyVectorcall_Function()``
+
+Just remove the underscore prefix to update your code. Patch by Victor
+Stinner.
diff --git a/Misc/NEWS.d/next/C API/2023-06-28-02-30-50.gh-issue-106168.NFOZPv.rst b/Misc/NEWS.d/next/C API/2023-06-28-02-30-50.gh-issue-106168.NFOZPv.rst
new file mode 100644
index 00000000000000..741d709bf824b8
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-06-28-02-30-50.gh-issue-106168.NFOZPv.rst
@@ -0,0 +1,5 @@
+If Python is built in :ref:`debug mode ` or :option:`with
+assertions <--with-assertions>`, :c:func:`PyTuple_SET_ITEM` and
+:c:func:`PyList_SET_ITEM` now check the index argument with an assertion. If
+the assertion fails, make sure that the size is set before. Patch by Victor
+Stinner.
diff --git a/Misc/NEWS.d/next/C API/2023-06-30-09-33-25.gh-issue-106023.YvYiE4.rst b/Misc/NEWS.d/next/C API/2023-06-30-09-33-25.gh-issue-106023.YvYiE4.rst
new file mode 100644
index 00000000000000..3130febf61120b
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-06-30-09-33-25.gh-issue-106023.YvYiE4.rst
@@ -0,0 +1,2 @@
+Remove private ``_PyObject_FastCall()`` function: use ``PyObject_Vectorcall()``
+which is available since Python 3.8 (:pep:`590`). Patch by Victor Stinner.
diff --git a/Misc/NEWS.d/next/C API/2023-07-01-21-23-33.gh-issue-106316.hp2Ijw.rst b/Misc/NEWS.d/next/C API/2023-07-01-21-23-33.gh-issue-106316.hp2Ijw.rst
new file mode 100644
index 00000000000000..733954eb8614f2
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-07-01-21-23-33.gh-issue-106316.hp2Ijw.rst
@@ -0,0 +1,2 @@
+Remove ``cpython/pytime.h`` header file: it only contained private
+functions. Patch by Victor Stinner.
diff --git a/Misc/NEWS.d/next/C API/2023-07-02-00-00-20.gh-issue-106320.tZWcvG.rst b/Misc/NEWS.d/next/C API/2023-07-02-00-00-20.gh-issue-106320.tZWcvG.rst
new file mode 100644
index 00000000000000..145d2ce7b0ceb1
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-07-02-00-00-20.gh-issue-106320.tZWcvG.rst
@@ -0,0 +1,3 @@
+Remove ``_PyInterpreterState_Get()`` alias to
+:c:func:`PyInterpreterState_Get()` which was kept for backward compatibility
+with Python 3.8. Patch by Victor Stinner.
diff --git a/Misc/NEWS.d/next/C API/2023-07-07-19-14-00.gh-issue-106521.Veh9f3.rst b/Misc/NEWS.d/next/C API/2023-07-07-19-14-00.gh-issue-106521.Veh9f3.rst
new file mode 100644
index 00000000000000..f38fd271e8a440
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-07-07-19-14-00.gh-issue-106521.Veh9f3.rst
@@ -0,0 +1 @@
+Add :c:func:`PyObject_GetOptionalAttr` and :c:func:`PyObject_GetOptionalAttrString` functions.
diff --git a/Misc/NEWS.d/next/C API/2023-07-08-12-24-17.gh-issue-106307.FVnkBw.rst b/Misc/NEWS.d/next/C API/2023-07-08-12-24-17.gh-issue-106307.FVnkBw.rst
new file mode 100644
index 00000000000000..dc1ab8d3e3fb83
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-07-08-12-24-17.gh-issue-106307.FVnkBw.rst
@@ -0,0 +1 @@
+Add :c:func:`PyMapping_GetOptionalItem` function.
diff --git a/Misc/NEWS.d/next/C API/2023-07-11-01-07-39.gh-issue-106572.y1b35X.rst b/Misc/NEWS.d/next/C API/2023-07-11-01-07-39.gh-issue-106572.y1b35X.rst
new file mode 100644
index 00000000000000..140e9fe7b9abf6
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-07-11-01-07-39.gh-issue-106572.y1b35X.rst
@@ -0,0 +1,2 @@
+Convert :c:func:`PyObject_DelAttr` and :c:func:`PyObject_DelAttrString`
+macros to functions. Patch by Victor Stinner.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-11-10-13-04-35.gh-issue-91095.4E3Pwn.rst b/Misc/NEWS.d/next/Core and Builtins/2022-11-10-13-04-35.gh-issue-91095.4E3Pwn.rst
new file mode 100644
index 00000000000000..5633097f4a3fdd
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-11-10-13-04-35.gh-issue-91095.4E3Pwn.rst
@@ -0,0 +1,11 @@
+Specializes calls to most Python classes. Specifically, any class that
+inherits from ``object``, or another Python class, and does not override
+``__new__``.
+
+The specialized instruction does the following:
+
+1. Creates the object (by calling ``object.__new__``)
+2. Pushes a shim frame to the frame stack (to cleanup after ``__init__``)
+3. Pushes the frame for ``__init__`` to the frame stack
+
+Speeds up the instantiation of most Python classes.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-13-11-37-41.gh-issue-101006.fuLvn2.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-13-11-37-41.gh-issue-101006.fuLvn2.rst
new file mode 100644
index 00000000000000..c98670d8c4963d
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-01-13-11-37-41.gh-issue-101006.fuLvn2.rst
@@ -0,0 +1 @@
+Improve error handling when read :mod:`marshal` data.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-15-15-41.gh-issue-104812.dfZiG5.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-15-15-41.gh-issue-104812.dfZiG5.rst
new file mode 100644
index 00000000000000..da29a8cae61839
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-15-15-41.gh-issue-104812.dfZiG5.rst
@@ -0,0 +1,9 @@
+The "pending call" machinery now works for all interpreters, not just the
+main interpreter, and runs in all threads, not just the main thread. Some
+calls are still only done in the main thread, ergo in the main interpreter.
+This change does not affect signal handling nor the existing public C-API
+(``Py_AddPendingCall()``), which both still only target the main thread.
+The new functionality is meant strictly for internal use for now, since
+consequences of its use are not well understood yet outside some very
+restricted cases. This change brings the capability in line with the
+intention when the state was made per-interpreter several years ago.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-19-37-29.gh-issue-105235.fgFGTi.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-19-37-29.gh-issue-105235.fgFGTi.rst
new file mode 100644
index 00000000000000..c28d0101cd4bad
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-19-37-29.gh-issue-105235.fgFGTi.rst
@@ -0,0 +1 @@
+Prevent out-of-bounds memory access during ``mmap.find()`` calls.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-05-08-30-49.gh-issue-33092.hZ0xSI.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-05-08-30-49.gh-issue-33092.hZ0xSI.rst
new file mode 100644
index 00000000000000..736fbac1a86500
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-05-08-30-49.gh-issue-33092.hZ0xSI.rst
@@ -0,0 +1,3 @@
+Simplify and speed up interpreter for f-strings. Removes ``FORMAT_VALUE``
+opcode. Add ``CONVERT_VALUE``, ``FORMAT_SIMPLE`` and ``FORMAT_WITH_SPEC``
+opcode. Compiler emits more efficient sequence for each format expression.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-07-21-27-55.gh-issue-105678.wKOr7F.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-07-21-27-55.gh-issue-105678.wKOr7F.rst
new file mode 100644
index 00000000000000..fd38c14c140414
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-07-21-27-55.gh-issue-105678.wKOr7F.rst
@@ -0,0 +1,4 @@
+Break the ``MAKE_FUNCTION`` instruction into two parts, ``MAKE_FUNCTION``
+which makes the function and ``SET_FUNCTION_ATTRIBUTE`` which sets the
+attributes on the function. This makes the stack effect of ``MAKE_FUNCTION``
+regular to ease optimization and code generation.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105486.dev-WS.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105486.dev-WS.rst
new file mode 100644
index 00000000000000..9f735db3dc89c3
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-10-15.gh-issue-105486.dev-WS.rst
@@ -0,0 +1 @@
+Change the repr of ``ParamSpec`` list of args in ``types.GenericAlias``.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-25-52.gh-issue-105375.ocB7fT.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-25-52.gh-issue-105375.ocB7fT.rst
new file mode 100644
index 00000000000000..24fac2df4d0955
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-09-25-52.gh-issue-105375.ocB7fT.rst
@@ -0,0 +1,2 @@
+Improve error handling in :c:func:`PyUnicode_BuildEncodingMap` where an
+exception could end up being overwritten.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-08-10-10-07.gh-issue-105375.35VGDd.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-10-10-07.gh-issue-105375.35VGDd.rst
new file mode 100644
index 00000000000000..3ab85538f3fc43
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-08-10-10-07.gh-issue-105375.35VGDd.rst
@@ -0,0 +1,2 @@
+Fix bugs in the :mod:`builtins` module where exceptions could end up being
+overwritten.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-09-10-48-17.gh-issue-100987.mK-xny.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-09-10-48-17.gh-issue-100987.mK-xny.rst
new file mode 100644
index 00000000000000..e25789e711c35d
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-09-10-48-17.gh-issue-100987.mK-xny.rst
@@ -0,0 +1,4 @@
+Allow objects other than code objects as the "executable" in internal
+frames. In the long term, this can help tools like Cython and PySpy interact
+more efficiently. In the shorter term, it allows us to perform some
+optimizations more simply.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-09-11-19-51.gh-issue-105588.Y5ovpY.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-09-11-19-51.gh-issue-105588.Y5ovpY.rst
new file mode 100644
index 00000000000000..3981dad7a49dfb
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-09-11-19-51.gh-issue-105588.Y5ovpY.rst
@@ -0,0 +1,2 @@
+Fix an issue that could result in crashes when compiling malformed
+:mod:`ast` nodes.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-10-21-38-49.gh-issue-105587.rL3rzv.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-10-21-38-49.gh-issue-105587.rL3rzv.rst
new file mode 100644
index 00000000000000..488f82c3fb574c
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-10-21-38-49.gh-issue-105587.rL3rzv.rst
@@ -0,0 +1,3 @@
+The runtime can't guarantee that immortal objects will not be mutated by
+Extensions. Thus, this modifies _PyStaticObject_CheckRefcnt to warn
+instead of asserting.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-11-09-14-30.gh-issue-105331.nlZvoW.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-11-09-14-30.gh-issue-105331.nlZvoW.rst
new file mode 100644
index 00000000000000..4a3fee0dd64ae0
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-11-09-14-30.gh-issue-105331.nlZvoW.rst
@@ -0,0 +1,2 @@
+Raise :exc:`ValueError` if the ``delay`` argument to :func:`asyncio.sleep` is a NaN (matching :func:`time.sleep`).
+
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-12-16-38-31.gh-issue-105340._jRHXe.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-12-16-38-31.gh-issue-105340._jRHXe.rst
new file mode 100644
index 00000000000000..f6d4fa8fc4d74e
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-12-16-38-31.gh-issue-105340._jRHXe.rst
@@ -0,0 +1,2 @@
+Include the comprehension iteration variable in ``locals()`` inside a
+module- or class-scope comprehension.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-14-22-52-06.gh-issue-105800.hdpPzZ.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-14-22-52-06.gh-issue-105800.hdpPzZ.rst
new file mode 100644
index 00000000000000..d6ef7b68b833c6
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-14-22-52-06.gh-issue-105800.hdpPzZ.rst
@@ -0,0 +1,2 @@
+Correctly issue :exc:`SyntaxWarning` in f-strings if invalid sequences are
+used. Patch by Pablo Galindo
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-15-15-54-47.gh-issue-105831.-MC9Zs.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-15-15-54-47.gh-issue-105831.-MC9Zs.rst
new file mode 100644
index 00000000000000..407940add56752
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-15-15-54-47.gh-issue-105831.-MC9Zs.rst
@@ -0,0 +1,3 @@
+Fix an f-string bug, where using a debug expression (the ``=`` sign) that
+appears in the last line of a file results to the debug buffer that holds the
+expression text being one character too small.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-15-22-11-43.gh-issue-105840.Fum_g_.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-15-22-11-43.gh-issue-105840.Fum_g_.rst
new file mode 100644
index 00000000000000..5225031292e6c7
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-15-22-11-43.gh-issue-105840.Fum_g_.rst
@@ -0,0 +1,2 @@
+Fix possible crashes when specializing function calls with too many
+``__defaults__``.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-19-11-04-01.gh-issue-105908.7oanny.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-19-11-04-01.gh-issue-105908.7oanny.rst
new file mode 100644
index 00000000000000..03db3f064f503f
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-19-11-04-01.gh-issue-105908.7oanny.rst
@@ -0,0 +1 @@
+Fixed bug where :gh:`99111` breaks future import ``barry_as_FLUFL`` in the Python REPL.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-22-14-19-17.gh-issue-98931.PPgvSF.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-22-14-19-17.gh-issue-98931.PPgvSF.rst
new file mode 100644
index 00000000000000..611660d6286263
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-22-14-19-17.gh-issue-98931.PPgvSF.rst
@@ -0,0 +1,2 @@
+Ensure custom :exc:`SyntaxError` error messages are raised for invalid
+imports with multiple targets. Patch by Pablo Galindo
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-22-17-37-35.gh-issue-106003.2Vc_Tw.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-22-17-37-35.gh-issue-106003.2Vc_Tw.rst
new file mode 100644
index 00000000000000..47143f7eb8f383
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-22-17-37-35.gh-issue-106003.2Vc_Tw.rst
@@ -0,0 +1,5 @@
+Add a new :opcode:`TO_BOOL` instruction, which performs boolean conversions
+for :opcode:`POP_JUMP_IF_TRUE`, :opcode:`POP_JUMP_IF_FALSE`, and
+:opcode:`UNARY_NOT` (which all expect exact :class:`bool` values now). Also,
+modify the oparg of :opcode:`COMPARE_OP` to include an optional "boolean
+conversion" flag.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-22-19-16-24.gh-issue-105979.TDP2CU.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-22-19-16-24.gh-issue-105979.TDP2CU.rst
new file mode 100644
index 00000000000000..be6962afd0c78f
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-22-19-16-24.gh-issue-105979.TDP2CU.rst
@@ -0,0 +1 @@
+Fix crash in :func:`!_imp.get_frozen_object` due to improper exception handling.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-23-16-51-02.gh-issue-105730.16haMe.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-23-16-51-02.gh-issue-105730.16haMe.rst
new file mode 100644
index 00000000000000..fa70ee09ce27a1
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-23-16-51-02.gh-issue-105730.16haMe.rst
@@ -0,0 +1,2 @@
+Allow any callable other than type objects as the condition predicate in
+:meth:`BaseExceptionGroup.split` and :meth:`BaseExceptionGroup.subgroup`.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-24-10-34-27.gh-issue-105775.OqjoGV.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-24-10-34-27.gh-issue-105775.OqjoGV.rst
new file mode 100644
index 00000000000000..27d0e9929794f4
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-24-10-34-27.gh-issue-105775.OqjoGV.rst
@@ -0,0 +1 @@
+:opcode:`LOAD_CLOSURE` is now a pseudo-op.
\ No newline at end of file
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-27-00-58-26.gh-issue-104584.Wu-uXy.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-27-00-58-26.gh-issue-104584.Wu-uXy.rst
new file mode 100644
index 00000000000000..a36490104ba3aa
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-27-00-58-26.gh-issue-104584.Wu-uXy.rst
@@ -0,0 +1 @@
+Added a new, experimental, tracing optimizer and interpreter (a.k.a. "tier 2"). This currently pessimizes, so don't use yet -- this is infrastructure so we can experiment with optimizing passes. To enable it, pass ``-Xuops`` or set ``PYTHONUOPS=1``. To get debug output, set ``PYTHONUOPSDEBUG=N`` where ``N`` is a debug level (0-4, where 0 is no debug output and 4 is excessively verbose).
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-28-13-19-20.gh-issue-106210.oE7VMn.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-28-13-19-20.gh-issue-106210.oE7VMn.rst
new file mode 100644
index 00000000000000..fde549d21e440a
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-28-13-19-20.gh-issue-106210.oE7VMn.rst
@@ -0,0 +1 @@
+Removed Emscripten import trampoline as it was no longer necessary for Pyodide.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-28-15-19-59.gh-issue-106182.cDSFi0.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-28-15-19-59.gh-issue-106182.cDSFi0.rst
new file mode 100644
index 00000000000000..ca2116b00a6659
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-28-15-19-59.gh-issue-106182.cDSFi0.rst
@@ -0,0 +1,2 @@
+:func:`sys.getfilesystemencoding` and :mod:`sys.getfilesystemencodeerrors`
+now return interned Unicode object.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-29-09-46-41.gh-issue-106145.QC6-Kq.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-29-09-46-41.gh-issue-106145.QC6-Kq.rst
new file mode 100644
index 00000000000000..4f9445bbcbe550
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-29-09-46-41.gh-issue-106145.QC6-Kq.rst
@@ -0,0 +1,2 @@
+Make ``end_lineno`` and ``end_col_offset`` required on ``type_param`` ast
+nodes.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-03-11-38-43.gh-issue-106008.HDf1zd.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-03-11-38-43.gh-issue-106008.HDf1zd.rst
new file mode 100644
index 00000000000000..a57b892fd53242
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-03-11-38-43.gh-issue-106008.HDf1zd.rst
@@ -0,0 +1,2 @@
+Fix possible reference leaks when failing to optimize comparisons with
+:const:`None` in the bytecode compiler.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-04-04-50-14.gh-issue-100288.yNQ1ez.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-04-50-14.gh-issue-100288.yNQ1ez.rst
new file mode 100644
index 00000000000000..faf43bd0c2f48e
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-04-50-14.gh-issue-100288.yNQ1ez.rst
@@ -0,0 +1,3 @@
+Specialize :opcode:`LOAD_ATTR` for non-descriptors on the class. Adds
+:opcode:`LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES` and :opcode
+`LOAD_ATTR_NONDESCRIPTOR_NO_DICT`.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst
new file mode 100644
index 00000000000000..c5767e97271d9d
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst
@@ -0,0 +1,3 @@
+When the format specification of an f-string expression is empty, the parser now
+generates an empty :class:`ast.JoinedStr` node for it instead of an one-element
+:class:`ast.JoinedStr` with an empty string :class:`ast.Constant`.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-04-20-42-54.gh-issue-81283.hfh_MD.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-20-42-54.gh-issue-81283.hfh_MD.rst
new file mode 100644
index 00000000000000..f673c665fe3277
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-20-42-54.gh-issue-81283.hfh_MD.rst
@@ -0,0 +1,3 @@
+Compiler now strips indents from docstrings. It reduces ``pyc`` file size 5%
+when the module is heavily documented. This change affects to ``__doc__`` so
+tools like doctest will be affected.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-06-00-35-44.gh-issue-96844.kwvoS-.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-06-00-35-44.gh-issue-96844.kwvoS-.rst
new file mode 100644
index 00000000000000..55334173bc002d
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-06-00-35-44.gh-issue-96844.kwvoS-.rst
@@ -0,0 +1 @@
+Improve error message of :meth:`list.remove`. Patch by Dong-hee Na.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-06-22-46-05.gh-issue-106487.u3KfAD.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-06-22-46-05.gh-issue-106487.u3KfAD.rst
new file mode 100644
index 00000000000000..9e8100022bbd23
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-06-22-46-05.gh-issue-106487.u3KfAD.rst
@@ -0,0 +1,2 @@
+Allow the *count* argument of :meth:`str.replace` to be a keyword. Patch by
+Hugo van Kemenade.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-10-15-30-45.gh-issue-106597.WAZ14y.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-10-15-30-45.gh-issue-106597.WAZ14y.rst
new file mode 100644
index 00000000000000..bbe455d652f50e
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-10-15-30-45.gh-issue-106597.WAZ14y.rst
@@ -0,0 +1,5 @@
+A new debug structure of offsets has been added to the ``_PyRuntimeState``
+that will help out-of-process debuggers and profilers to obtain the offsets
+to relevant interpreter structures in a way that is agnostic of how Python
+was compiled and that doesn't require copying the headers. Patch by Pablo
+Galindo
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-12-10-48-08.gh-issue-104909.sWjcr2.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-12-10-48-08.gh-issue-104909.sWjcr2.rst
new file mode 100644
index 00000000000000..f20226e5c54d16
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-12-10-48-08.gh-issue-104909.sWjcr2.rst
@@ -0,0 +1 @@
+Split :opcode:`LOAD_GLOBAL` specializations into micro-ops.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-12-11-18-55.gh-issue-104909.DRUsuh.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-12-11-18-55.gh-issue-104909.DRUsuh.rst
new file mode 100644
index 00000000000000..e0c1e67515a62c
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-12-11-18-55.gh-issue-104909.DRUsuh.rst
@@ -0,0 +1 @@
+Split :opcode:`LOAD_ATTR_INSTANCE_VALUE` into micro-ops.
diff --git a/Misc/NEWS.d/next/Documentation/2023-06-30-19-28-59.gh-issue-106232.hQ4-tz.rst b/Misc/NEWS.d/next/Documentation/2023-06-30-19-28-59.gh-issue-106232.hQ4-tz.rst
new file mode 100644
index 00000000000000..bc16f92b7d6478
--- /dev/null
+++ b/Misc/NEWS.d/next/Documentation/2023-06-30-19-28-59.gh-issue-106232.hQ4-tz.rst
@@ -0,0 +1,2 @@
+Make timeit doc command lines compatible with Windows by using double quotes
+for arguments. This works on linux and macOS also.
diff --git a/Misc/NEWS.d/next/Library/2019-09-13-13-28-10.bpo-17013.NWcgE3.rst b/Misc/NEWS.d/next/Library/2019-09-13-13-28-10.bpo-17013.NWcgE3.rst
new file mode 100644
index 00000000000000..ac746c45fa9ea8
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-09-13-13-28-10.bpo-17013.NWcgE3.rst
@@ -0,0 +1,3 @@
+Add ``ThreadingMock`` to :mod:`unittest.mock` that can be used to create
+Mock objects that can wait until they are called. Patch by Karthikeyan
+Singaravelan and Mario Corchero.
diff --git a/Misc/NEWS.d/next/Library/2021-06-24-20-45-03.bpo-44185.ZHb8yJ.rst b/Misc/NEWS.d/next/Library/2021-06-24-20-45-03.bpo-44185.ZHb8yJ.rst
new file mode 100644
index 00000000000000..056ab8d93515fb
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-06-24-20-45-03.bpo-44185.ZHb8yJ.rst
@@ -0,0 +1,3 @@
+:func:`unittest.mock.mock_open` will call the :func:`close` method of the file
+handle mock when it is exiting from the context manager.
+Patch by Samet Yaslan.
diff --git a/Misc/NEWS.d/next/Library/2022-07-12-18-45-13.gh-issue-94777.mOybx7.rst b/Misc/NEWS.d/next/Library/2022-07-12-18-45-13.gh-issue-94777.mOybx7.rst
new file mode 100644
index 00000000000000..2c04a35fbfce13
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-07-12-18-45-13.gh-issue-94777.mOybx7.rst
@@ -0,0 +1 @@
+Fix hanging :mod:`multiprocessing` ``ProcessPoolExecutor`` when a child process crashes while data is being written in the call queue.
diff --git a/Misc/NEWS.d/next/Library/2022-08-07-11-10-26.gh-issue-80480.IFccj3.rst b/Misc/NEWS.d/next/Library/2022-08-07-11-10-26.gh-issue-80480.IFccj3.rst
new file mode 100644
index 00000000000000..2d4956ffa08035
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-08-07-11-10-26.gh-issue-80480.IFccj3.rst
@@ -0,0 +1,2 @@
+Emit :exc:`DeprecationWarning` for :mod:`array`'s ``'u'`` type code,
+deprecated in docs since Python 3.3.
diff --git a/Misc/NEWS.d/next/Library/2023-03-12-01-17-15.gh-issue-102541.LK1adc.rst b/Misc/NEWS.d/next/Library/2023-03-12-01-17-15.gh-issue-102541.LK1adc.rst
new file mode 100644
index 00000000000000..45b10679e19e2d
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-03-12-01-17-15.gh-issue-102541.LK1adc.rst
@@ -0,0 +1 @@
+Hide traceback in :func:`help` prompt, when import failed.
diff --git a/Misc/NEWS.d/next/Library/2023-04-03-08-09-40.gh-issue-103200.lq1Etz.rst b/Misc/NEWS.d/next/Library/2023-04-03-08-09-40.gh-issue-103200.lq1Etz.rst
new file mode 100644
index 00000000000000..e264e0c81d3d90
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-04-03-08-09-40.gh-issue-103200.lq1Etz.rst
@@ -0,0 +1 @@
+Fix cache repopulation semantics of zipimport.invalidate_caches(). The cache is now repopulated upon retrieving files with an invalid cache, not when the cache is invalidated.
diff --git a/Misc/NEWS.d/next/Library/2023-04-09-03-53-02.gh-issue-103124.JspiNN.rst b/Misc/NEWS.d/next/Library/2023-04-09-03-53-02.gh-issue-103124.JspiNN.rst
new file mode 100644
index 00000000000000..022524b369aa10
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-04-09-03-53-02.gh-issue-103124.JspiNN.rst
@@ -0,0 +1 @@
+Added multiline statement support for :mod:`pdb`
diff --git a/Misc/NEWS.d/next/Library/2023-04-28-09-31-21.gh-issue-102676.J8qDRa.rst b/Misc/NEWS.d/next/Library/2023-04-28-09-31-21.gh-issue-102676.J8qDRa.rst
new file mode 100644
index 00000000000000..eef89645aa533f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-04-28-09-31-21.gh-issue-102676.J8qDRa.rst
@@ -0,0 +1,3 @@
+Add fields ``start_offset``, ``cache_offset``, ``end_offset``,
+``baseopname``, ``baseopcode``, ``jump_target`` and ``oparg`` to
+:class:`dis.Instruction`.
diff --git a/Misc/NEWS.d/next/Library/2023-05-24-09-55-33.gh-issue-104873.BKQ54y.rst b/Misc/NEWS.d/next/Library/2023-05-24-09-55-33.gh-issue-104873.BKQ54y.rst
new file mode 100644
index 00000000000000..c901d83812f176
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-05-24-09-55-33.gh-issue-104873.BKQ54y.rst
@@ -0,0 +1,3 @@
+Add :func:`typing.get_protocol_members` to return the set of members
+defining a :class:`typing.Protocol`. Add :func:`typing.is_protocol` to
+check whether a class is a :class:`typing.Protocol`. Patch by Jelle Zijlstra.
diff --git a/Misc/NEWS.d/next/Library/2023-06-05-14-43-56.gh-issue-104554.pwfKIo.rst b/Misc/NEWS.d/next/Library/2023-06-05-14-43-56.gh-issue-104554.pwfKIo.rst
new file mode 100644
index 00000000000000..9ef8c67459c406
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-05-14-43-56.gh-issue-104554.pwfKIo.rst
@@ -0,0 +1 @@
+Add RTSPS scheme support in urllib.parse
diff --git a/Misc/NEWS.d/next/Library/2023-06-06-15-32-44.gh-issue-105376.W4oDQp.rst b/Misc/NEWS.d/next/Library/2023-06-06-15-32-44.gh-issue-105376.W4oDQp.rst
index a7d3172ca4c642..2ed6b5e0a7ac0a 100644
--- a/Misc/NEWS.d/next/Library/2023-06-06-15-32-44.gh-issue-105376.W4oDQp.rst
+++ b/Misc/NEWS.d/next/Library/2023-06-06-15-32-44.gh-issue-105376.W4oDQp.rst
@@ -1,4 +1,5 @@
-Remove the undocumented and untested ``logging.Logger.warn()`` method,
-deprecated since Python 3.3, which was an alias to the
-:meth:`logging.Logger.warning` method: use the :meth:`logging.Logger.warning`
-method instead. Patch by Victor Stinner.
+:mod:`logging`: Remove undocumented and untested ``Logger.warn()`` and
+``LoggerAdapter.warn()`` methods and ``logging.warn()`` function. Deprecated
+since Python 3.3, they were aliases to the :meth:`logging.Logger.warning`
+method, :meth:`!logging.LoggerAdapter.warning` method and
+:func:`logging.warning` function. Patch by Victor Stinner.
diff --git a/Misc/NEWS.d/next/Library/2023-06-09-20-34-23.gh-issue-105566.YxlGg1.rst b/Misc/NEWS.d/next/Library/2023-06-09-20-34-23.gh-issue-105566.YxlGg1.rst
new file mode 100644
index 00000000000000..c2c497aee513d3
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-09-20-34-23.gh-issue-105566.YxlGg1.rst
@@ -0,0 +1,10 @@
+Deprecate creating a :class:`typing.NamedTuple` class using keyword
+arguments to denote the fields (``NT = NamedTuple("NT", x=int, y=str)``).
+This will be disallowed in Python 3.15.
+Use the class-based syntax or the functional syntax instead.
+
+Two methods of creating ``NamedTuple`` classes with 0 fields using the
+functional syntax are also deprecated, and will be disallowed in Python 3.15:
+``NT = NamedTuple("NT")`` and ``NT = NamedTuple("NT", None)``. To create a
+``NamedTuple`` class with 0 fields, either use ``class NT(NamedTuple): pass`` or
+``NT = NamedTuple("NT", [])``.
diff --git a/Misc/NEWS.d/next/Library/2023-06-09-21-40-45.gh-issue-105375._sZilh.rst b/Misc/NEWS.d/next/Library/2023-06-09-21-40-45.gh-issue-105375._sZilh.rst
new file mode 100644
index 00000000000000..87db4c2b4e22e3
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-09-21-40-45.gh-issue-105375._sZilh.rst
@@ -0,0 +1 @@
+Fix bugs in :mod:`_ctypes` where exceptions could end up being overwritten.
diff --git a/Misc/NEWS.d/next/Library/2023-06-09-21-46-52.gh-issue-105375.yrJelV.rst b/Misc/NEWS.d/next/Library/2023-06-09-21-46-52.gh-issue-105375.yrJelV.rst
new file mode 100644
index 00000000000000..21aea1b0b4082c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-09-21-46-52.gh-issue-105375.yrJelV.rst
@@ -0,0 +1,2 @@
+Fix a bug in :class:`array.array` where an exception could end up being
+overwritten.
diff --git a/Misc/NEWS.d/next/Library/2023-06-09-22-16-46.gh-issue-105375.EgVJOP.rst b/Misc/NEWS.d/next/Library/2023-06-09-22-16-46.gh-issue-105375.EgVJOP.rst
new file mode 100644
index 00000000000000..49f7df68e927cb
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-09-22-16-46.gh-issue-105375.EgVJOP.rst
@@ -0,0 +1,2 @@
+Fix bugs in :mod:`!_ssl` initialisation which could lead to leaked
+references and overwritten exceptions.
diff --git a/Misc/NEWS.d/next/Library/2023-06-09-22-45-26.gh-issue-105375.9rp6tG.rst b/Misc/NEWS.d/next/Library/2023-06-09-22-45-26.gh-issue-105375.9rp6tG.rst
new file mode 100644
index 00000000000000..352d7b83a71632
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-09-22-45-26.gh-issue-105375.9rp6tG.rst
@@ -0,0 +1,2 @@
+Fix bugs in :mod:`!_datetime` where exceptions could be overwritten in case
+of module initialisation failure.
diff --git a/Misc/NEWS.d/next/Library/2023-06-09-22-52-45.gh-issue-105375.6igkhn.rst b/Misc/NEWS.d/next/Library/2023-06-09-22-52-45.gh-issue-105375.6igkhn.rst
new file mode 100644
index 00000000000000..05e78fdc9b4076
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-09-22-52-45.gh-issue-105375.6igkhn.rst
@@ -0,0 +1 @@
+Fix bug in :mod:`decimal` where an exception could end up being overwritten.
diff --git a/Misc/NEWS.d/next/Library/2023-06-09-23-00-13.gh-issue-105605.YuwqxY.rst b/Misc/NEWS.d/next/Library/2023-06-09-23-00-13.gh-issue-105605.YuwqxY.rst
new file mode 100644
index 00000000000000..5fba6d293a785e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-09-23-00-13.gh-issue-105605.YuwqxY.rst
@@ -0,0 +1,3 @@
+Harden :mod:`pyexpat` error handling during module initialisation to prevent
+exceptions from possibly being overwritten, and objects from being
+dereferenced twice.
diff --git a/Misc/NEWS.d/next/Library/2023-06-09-23-46-23.gh-issue-105375.9KaioS.rst b/Misc/NEWS.d/next/Library/2023-06-09-23-46-23.gh-issue-105375.9KaioS.rst
new file mode 100644
index 00000000000000..b12d7c864e7b86
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-09-23-46-23.gh-issue-105375.9KaioS.rst
@@ -0,0 +1,2 @@
+Fix bugs in :mod:`sys` where exceptions could end up being overwritten
+because of deferred error handling.
diff --git a/Misc/NEWS.d/next/Library/2023-06-10-12-20-17.gh-issue-105626.XyZein.rst b/Misc/NEWS.d/next/Library/2023-06-10-12-20-17.gh-issue-105626.XyZein.rst
new file mode 100644
index 00000000000000..2a48361fa596c9
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-10-12-20-17.gh-issue-105626.XyZein.rst
@@ -0,0 +1,3 @@
+Change the default return value of
+:meth:`http.client.HTTPConnection.get_proxy_response_headers` to be ``None``
+and not ``{}``.
diff --git a/Misc/NEWS.d/next/Library/2023-06-11-22-46-06.gh-issue-105375.YkhSNt.rst b/Misc/NEWS.d/next/Library/2023-06-11-22-46-06.gh-issue-105375.YkhSNt.rst
new file mode 100644
index 00000000000000..dda8f428760ba1
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-11-22-46-06.gh-issue-105375.YkhSNt.rst
@@ -0,0 +1,2 @@
+Fix a bug in :c:func:`!_Unpickler_SetInputStream` where an exception could
+end up being overwritten in case of failure.
diff --git a/Misc/NEWS.d/next/Library/2023-06-12-10-40-38.gh-issue-105684.yiHkFD.rst b/Misc/NEWS.d/next/Library/2023-06-12-10-40-38.gh-issue-105684.yiHkFD.rst
new file mode 100644
index 00000000000000..b0d4eb328a7b34
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-12-10-40-38.gh-issue-105684.yiHkFD.rst
@@ -0,0 +1,3 @@
+Supporting :meth:`asyncio.Task.set_name` is now mandatory for third party task implementations.
+The undocumented :func:`!_set_task_name` function (deprecated since 3.8) has been removed.
+Patch by Kumar Aditya.
diff --git a/Misc/NEWS.d/next/Library/2023-06-12-15-17-34.gh-issue-105687.ZUonKm.rst b/Misc/NEWS.d/next/Library/2023-06-12-15-17-34.gh-issue-105687.ZUonKm.rst
new file mode 100644
index 00000000000000..7966d3a566414e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-12-15-17-34.gh-issue-105687.ZUonKm.rst
@@ -0,0 +1,2 @@
+Remove deprecated ``re.template``, ``re.T``, ``re.TEMPLATE``,
+``sre_constans.SRE_FLAG_TEMPLATE``.
diff --git a/Misc/NEWS.d/next/Library/2023-06-13-19-38-12.gh-issue-105733.WOp0mG.rst b/Misc/NEWS.d/next/Library/2023-06-13-19-38-12.gh-issue-105733.WOp0mG.rst
new file mode 100644
index 00000000000000..20f2ba2bcc5cb1
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-13-19-38-12.gh-issue-105733.WOp0mG.rst
@@ -0,0 +1,2 @@
+:mod:`ctypes`: Deprecate undocumented :func:`!ctypes.SetPointerType` and
+:func:`!ctypes.ARRAY` functions. Patch by Victor Stinner.
diff --git a/Misc/NEWS.d/next/Library/2023-06-14-10-27-34.gh-issue-105745.l1ttOQ.rst b/Misc/NEWS.d/next/Library/2023-06-14-10-27-34.gh-issue-105745.l1ttOQ.rst
new file mode 100644
index 00000000000000..7df7c5a79ec6eb
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-14-10-27-34.gh-issue-105745.l1ttOQ.rst
@@ -0,0 +1 @@
+Fix ``webbrowser.Konqueror.open`` method.
diff --git a/Misc/NEWS.d/next/Library/2023-06-14-14-32-31.gh-issue-105570.sFTtQU.rst b/Misc/NEWS.d/next/Library/2023-06-14-14-32-31.gh-issue-105570.sFTtQU.rst
new file mode 100644
index 00000000000000..e31a8ee256d697
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-14-14-32-31.gh-issue-105570.sFTtQU.rst
@@ -0,0 +1,5 @@
+Deprecate two methods of creating :class:`typing.TypedDict` classes with 0
+fields using the functional syntax: ``TD = TypedDict("TD")`` and
+``TD = TypedDict("TD", None)``. Both will be disallowed in Python 3.15. To create a
+``TypedDict`` class with 0 fields, either use ``class TD(TypedDict): pass``
+or ``TD = TypedDict("TD", {})``.
diff --git a/Misc/NEWS.d/next/Library/2023-06-14-18-41-18.gh-issue-105793.YSoykM.rst b/Misc/NEWS.d/next/Library/2023-06-14-18-41-18.gh-issue-105793.YSoykM.rst
new file mode 100644
index 00000000000000..0e4090ea7eabb9
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-14-18-41-18.gh-issue-105793.YSoykM.rst
@@ -0,0 +1,2 @@
+Add *follow_symlinks* keyword-only argument to :meth:`pathlib.Path.is_dir` and
+:meth:`~pathlib.Path.is_file`, defaulting to ``True``.
diff --git a/Misc/NEWS.d/next/Library/2023-06-15-18-11-47.gh-issue-104799.BcLzbP.rst b/Misc/NEWS.d/next/Library/2023-06-15-18-11-47.gh-issue-104799.BcLzbP.rst
new file mode 100644
index 00000000000000..d0dbff4f1553e2
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-15-18-11-47.gh-issue-104799.BcLzbP.rst
@@ -0,0 +1,3 @@
+Enable :func:`ast.unparse` to unparse function and class definitions created
+without the new ``type_params`` field from :pep:`695`. Patch by Jelle
+Zijlstra.
diff --git a/Misc/NEWS.d/next/Library/2023-06-17-12-13-57.gh-issue-105481.KgBH5w.rst b/Misc/NEWS.d/next/Library/2023-06-17-12-13-57.gh-issue-105481.KgBH5w.rst
new file mode 100644
index 00000000000000..11084ef956dcf3
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-17-12-13-57.gh-issue-105481.KgBH5w.rst
@@ -0,0 +1,4 @@
+:func:`~dis.stack_effect` no longer raises an exception if an ``oparg`` is
+provided for an ``opcode`` that doesn't use its arg, or when it is not
+provided for an ``opcode`` that does use it. In the latter case, the stack
+effect is returned for ``oparg=0``.
diff --git a/Misc/NEWS.d/next/Library/2023-06-19-11-31-55.gh-issue-105808.NL-quu.rst b/Misc/NEWS.d/next/Library/2023-06-19-11-31-55.gh-issue-105808.NL-quu.rst
new file mode 100644
index 00000000000000..8e69fd627c28e8
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-19-11-31-55.gh-issue-105808.NL-quu.rst
@@ -0,0 +1 @@
+Fix a regression introduced in GH-101251 for 3.12, causing :meth:`gzip.GzipFile.flush` to not flush the compressor (nor pass along the ``zip_mode`` argument).
diff --git a/Misc/NEWS.d/next/Library/2023-06-19-22-20-41.gh-issue-89812.z2l_e8.rst b/Misc/NEWS.d/next/Library/2023-06-19-22-20-41.gh-issue-89812.z2l_e8.rst
new file mode 100644
index 00000000000000..f1ef11e26bc5fc
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-19-22-20-41.gh-issue-89812.z2l_e8.rst
@@ -0,0 +1,2 @@
+Add :exc:`pathlib.UnsupportedOperation`, which is raised instead of
+:exc:`NotImplementedError` when a path operation isn't supported.
diff --git a/Misc/NEWS.d/next/Library/2023-06-20-23-18-45.gh-issue-96145.o5dTRM.rst b/Misc/NEWS.d/next/Library/2023-06-20-23-18-45.gh-issue-96145.o5dTRM.rst
new file mode 100644
index 00000000000000..f4fb0e46ce5e57
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-20-23-18-45.gh-issue-96145.o5dTRM.rst
@@ -0,0 +1 @@
+Reverted addition of ``json.AttrDict``.
diff --git a/Misc/NEWS.d/next/Library/2023-06-21-19-04-27.gh-issue-105974.M47n3t.rst b/Misc/NEWS.d/next/Library/2023-06-21-19-04-27.gh-issue-105974.M47n3t.rst
new file mode 100644
index 00000000000000..982192e59e3a50
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-21-19-04-27.gh-issue-105974.M47n3t.rst
@@ -0,0 +1,6 @@
+Fix bug where a :class:`typing.Protocol` class that had one or more
+non-callable members would raise :exc:`TypeError` when :func:`issubclass`
+was called against it, even if it defined a custom ``__subclasshook__``
+method. The behaviour in Python 3.11 and lower -- which has now been
+restored -- was not to raise :exc:`TypeError` in these situations if a
+custom ``__subclasshook__`` method was defined. Patch by Alex Waygood.
diff --git a/Misc/NEWS.d/next/Library/2023-06-22-15-21-11.gh-issue-105987.T7Kzrb.rst b/Misc/NEWS.d/next/Library/2023-06-22-15-21-11.gh-issue-105987.T7Kzrb.rst
new file mode 100644
index 00000000000000..0bc97da4edf0f9
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-22-15-21-11.gh-issue-105987.T7Kzrb.rst
@@ -0,0 +1 @@
+Fix crash due to improper reference counting in :mod:`asyncio` eager task factory internal routines.
diff --git a/Misc/NEWS.d/next/Library/2023-06-23-22-52-24.gh-issue-106046.OdLiLJ.rst b/Misc/NEWS.d/next/Library/2023-06-23-22-52-24.gh-issue-106046.OdLiLJ.rst
new file mode 100644
index 00000000000000..ce10a9d81dc64c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-23-22-52-24.gh-issue-106046.OdLiLJ.rst
@@ -0,0 +1,2 @@
+Improve the error message from :func:`os.fspath` if called on an object
+where ``__fspath__`` is set to ``None``. Patch by Alex Waygood.
diff --git a/Misc/NEWS.d/next/Library/2023-06-25-06-57-24.gh-issue-104527.TJEUkd.rst b/Misc/NEWS.d/next/Library/2023-06-25-06-57-24.gh-issue-104527.TJEUkd.rst
new file mode 100644
index 00000000000000..50b845bcde9bbe
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-25-06-57-24.gh-issue-104527.TJEUkd.rst
@@ -0,0 +1 @@
+Zipapp will now skip over apending an archive to itself.
diff --git a/Misc/NEWS.d/next/Library/2023-06-25-12-28-55.gh-issue-106075.W7tMRb.rst b/Misc/NEWS.d/next/Library/2023-06-25-12-28-55.gh-issue-106075.W7tMRb.rst
new file mode 100644
index 00000000000000..d2687154a58594
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-25-12-28-55.gh-issue-106075.W7tMRb.rst
@@ -0,0 +1 @@
+Added `asyncio.taskgroups.__all__` to `asyncio.__all__` for export in star imports.
diff --git a/Misc/NEWS.d/next/Library/2023-06-27-23-22-37.gh-issue-106152.ya5jBT.rst b/Misc/NEWS.d/next/Library/2023-06-27-23-22-37.gh-issue-106152.ya5jBT.rst
new file mode 100644
index 00000000000000..da9d2605f46294
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-27-23-22-37.gh-issue-106152.ya5jBT.rst
@@ -0,0 +1 @@
+Added PY_THROW event hook for :mod:`cProfile` for generators
diff --git a/Misc/NEWS.d/next/Library/2023-06-29-12-40-52.gh-issue-106238.VulKb9.rst b/Misc/NEWS.d/next/Library/2023-06-29-12-40-52.gh-issue-106238.VulKb9.rst
new file mode 100644
index 00000000000000..52e78382fd618e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-29-12-40-52.gh-issue-106238.VulKb9.rst
@@ -0,0 +1 @@
+Fix rare concurrency bug in lock acquisition by the logging package.
diff --git a/Misc/NEWS.d/next/Library/2023-06-29-15-10-44.gh-issue-106236.EAIX4l.rst b/Misc/NEWS.d/next/Library/2023-06-29-15-10-44.gh-issue-106236.EAIX4l.rst
new file mode 100644
index 00000000000000..036bdb6ef59f6c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-29-15-10-44.gh-issue-106236.EAIX4l.rst
@@ -0,0 +1,2 @@
+Replace ``assert`` statements with ``raise RuntimeError`` in
+:mod:`threading`, so that ``_DummyThread`` cannot be joined even with ``-OO``.
diff --git a/Misc/NEWS.d/next/Library/2023-07-01-16-40-54.gh-issue-102541.C1ahtk.rst b/Misc/NEWS.d/next/Library/2023-07-01-16-40-54.gh-issue-102541.C1ahtk.rst
new file mode 100644
index 00000000000000..efaf5db10f3e1c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-01-16-40-54.gh-issue-102541.C1ahtk.rst
@@ -0,0 +1 @@
+Make pydoc.doc catch bad module ImportError when output stream is not None.
diff --git a/Misc/NEWS.d/next/Library/2023-07-01-16-51-55.gh-issue-106309.hSlB17.rst b/Misc/NEWS.d/next/Library/2023-07-01-16-51-55.gh-issue-106309.hSlB17.rst
new file mode 100644
index 00000000000000..5bd3880520871f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-01-16-51-55.gh-issue-106309.hSlB17.rst
@@ -0,0 +1,2 @@
+Deprecate :func:`typing.no_type_check_decorator`. No major type checker ever
+added support for this decorator. Patch by Alex Waygood.
diff --git a/Misc/NEWS.d/next/Library/2023-07-02-10-56-41.gh-issue-106330.QSkIUH.rst b/Misc/NEWS.d/next/Library/2023-07-02-10-56-41.gh-issue-106330.QSkIUH.rst
new file mode 100644
index 00000000000000..c1f55ab658b517
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-02-10-56-41.gh-issue-106330.QSkIUH.rst
@@ -0,0 +1,2 @@
+Fix incorrect matching of empty paths in :meth:`pathlib.PurePath.match`.
+This bug was introduced in Python 3.12.0 beta 1.
diff --git a/Misc/NEWS.d/next/Library/2023-07-03-15-09-44.gh-issue-106292.3npldV.rst b/Misc/NEWS.d/next/Library/2023-07-03-15-09-44.gh-issue-106292.3npldV.rst
new file mode 100644
index 00000000000000..233509344d509b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-03-15-09-44.gh-issue-106292.3npldV.rst
@@ -0,0 +1,4 @@
+Check for an instance-dict cached value in the :meth:`__get__` method of
+:func:`functools.cached_property`. This better matches the pre-3.12 behavior
+and improves compatibility for users subclassing
+:func:`functools.cached_property` and adding a :meth:`__set__` method.
diff --git a/Misc/NEWS.d/next/Library/2023-07-04-07-25-30.gh-issue-106403.GmefbV.rst b/Misc/NEWS.d/next/Library/2023-07-04-07-25-30.gh-issue-106403.GmefbV.rst
new file mode 100644
index 00000000000000..4fea45f16c4f8e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-04-07-25-30.gh-issue-106403.GmefbV.rst
@@ -0,0 +1,4 @@
+Instances of :class:`typing.TypeVar`, :class:`typing.ParamSpec`,
+:class:`typing.ParamSpecArgs`, :class:`typing.ParamSpecKwargs`, and
+:class:`typing.TypeVarTuple` once again support weak references, fixing a
+regression introduced in Python 3.12.0 beta 1. Patch by Jelle Zijlstra.
diff --git a/Misc/NEWS.d/next/Library/2023-07-05-13-08-23.gh-issue-90876.Qvlkfl.rst b/Misc/NEWS.d/next/Library/2023-07-05-13-08-23.gh-issue-90876.Qvlkfl.rst
new file mode 100644
index 00000000000000..3e062b5add6d89
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-05-13-08-23.gh-issue-90876.Qvlkfl.rst
@@ -0,0 +1,3 @@
+Prevent :mod:`multiprocessing.spawn` from failing to *import* in environments
+where ``sys.executable`` is ``None``. This regressed in 3.11 with the addition
+of support for path-like objects in multiprocessing.
diff --git a/Misc/NEWS.d/next/Library/2023-07-05-14-34-10.gh-issue-105497.HU5u89.rst b/Misc/NEWS.d/next/Library/2023-07-05-14-34-10.gh-issue-105497.HU5u89.rst
new file mode 100644
index 00000000000000..f4f2db08f73f50
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-05-14-34-10.gh-issue-105497.HU5u89.rst
@@ -0,0 +1 @@
+Fix flag mask inversion when unnamed flags exist.
diff --git a/Misc/NEWS.d/next/Library/2023-07-07-03-05-58.gh-issue-106503.ltfeiH.rst b/Misc/NEWS.d/next/Library/2023-07-07-03-05-58.gh-issue-106503.ltfeiH.rst
new file mode 100644
index 00000000000000..b8dd850386e86c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-07-03-05-58.gh-issue-106503.ltfeiH.rst
@@ -0,0 +1,2 @@
+Fix ref cycle in :class:`!asyncio._SelectorSocketTransport` by removing
+``_write_ready`` in ``close``.
diff --git a/Misc/NEWS.d/next/Library/2023-07-07-13-47-28.gh-issue-106510.9n5BdC.rst b/Misc/NEWS.d/next/Library/2023-07-07-13-47-28.gh-issue-106510.9n5BdC.rst
new file mode 100644
index 00000000000000..e0646fa9bc0211
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-07-13-47-28.gh-issue-106510.9n5BdC.rst
@@ -0,0 +1 @@
+Improve debug output for atomic groups in regular expressions.
diff --git a/Misc/NEWS.d/next/Library/2023-07-07-16-19-59.gh-issue-106531.eMfNm8.rst b/Misc/NEWS.d/next/Library/2023-07-07-16-19-59.gh-issue-106531.eMfNm8.rst
new file mode 100644
index 00000000000000..a52107103c4576
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-07-16-19-59.gh-issue-106531.eMfNm8.rst
@@ -0,0 +1,3 @@
+Removed ``_legacy`` and the names it provided from ``importlib.resources``:
+``Resource``, ``contents``, ``is_resource``, ``open_binary``, ``open_text``,
+``path``, ``read_binary``, and ``read_text``.
diff --git a/Misc/NEWS.d/next/Library/2023-07-07-17-44-03.gh-issue-106524.XkBV8h.rst b/Misc/NEWS.d/next/Library/2023-07-07-17-44-03.gh-issue-106524.XkBV8h.rst
new file mode 100644
index 00000000000000..f3fd070e391a66
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-07-17-44-03.gh-issue-106524.XkBV8h.rst
@@ -0,0 +1 @@
+Fix crash in :func:`!_sre.template` with templates containing invalid group indices.
diff --git a/Misc/NEWS.d/next/Library/2023-07-09-01-59-24.gh-issue-106554.37c53J.rst b/Misc/NEWS.d/next/Library/2023-07-09-01-59-24.gh-issue-106554.37c53J.rst
new file mode 100644
index 00000000000000..2136f3aa5a8eb0
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-09-01-59-24.gh-issue-106554.37c53J.rst
@@ -0,0 +1 @@
+:mod:`selectors`: Reduce Selector overhead by using a ``dict.get()`` to lookup file descriptors.
diff --git a/Misc/NEWS.d/next/Library/2023-07-11-09-25-40.gh-issue-106530.VgXrMx.rst b/Misc/NEWS.d/next/Library/2023-07-11-09-25-40.gh-issue-106530.VgXrMx.rst
new file mode 100644
index 00000000000000..09fc647cc01d21
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-11-09-25-40.gh-issue-106530.VgXrMx.rst
@@ -0,0 +1,2 @@
+Revert a change to :func:`colorsys.rgb_to_hls` that caused division by zero
+for certain almost-white inputs. Patch by Terry Jan Reedy.
diff --git a/Misc/NEWS.d/next/Library/2023-07-11-12-34-04.gh-issue-89427.GOkCp9.rst b/Misc/NEWS.d/next/Library/2023-07-11-12-34-04.gh-issue-89427.GOkCp9.rst
new file mode 100644
index 00000000000000..1605920cb8138b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-11-12-34-04.gh-issue-89427.GOkCp9.rst
@@ -0,0 +1,2 @@
+Set the environment variable ``VIRTUAL_ENV_PROMPT`` at :mod:`venv`
+activation, even when ``VIRTUAL_ENV_DISABLE_PROMPT`` is set.
diff --git a/Misc/NEWS.d/next/Library/2023-07-11-16-36-22.gh-issue-106628.Kx8Zvc.rst b/Misc/NEWS.d/next/Library/2023-07-11-16-36-22.gh-issue-106628.Kx8Zvc.rst
new file mode 100644
index 00000000000000..6fa276e901f648
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-11-16-36-22.gh-issue-106628.Kx8Zvc.rst
@@ -0,0 +1,2 @@
+Speed up parsing of emails by about 20% by not compiling a new regular
+expression for every single email.
diff --git a/Misc/NEWS.d/next/Library/2023-07-12-03-04-45.gh-issue-106664.ZeUG78.rst b/Misc/NEWS.d/next/Library/2023-07-12-03-04-45.gh-issue-106664.ZeUG78.rst
new file mode 100644
index 00000000000000..c278cad74bd049
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-12-03-04-45.gh-issue-106664.ZeUG78.rst
@@ -0,0 +1 @@
+:mod:`selectors`: Add ``_SelectorMapping.get()`` method and optimize ``_SelectorMapping.__getitem__()``.
diff --git a/Misc/NEWS.d/next/Library/2023-07-12-04-58-45.gh-issue-106602.dGCcXe.rst b/Misc/NEWS.d/next/Library/2023-07-12-04-58-45.gh-issue-106602.dGCcXe.rst
new file mode 100644
index 00000000000000..d9c122f1d3c723
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-12-04-58-45.gh-issue-106602.dGCcXe.rst
@@ -0,0 +1 @@
+Add __copy__ and __deepcopy__ in :mod:`enum`
diff --git a/Misc/NEWS.d/next/Library/2023-07-13-16-04-15.gh-issue-105481.pYSwMj.rst b/Misc/NEWS.d/next/Library/2023-07-13-16-04-15.gh-issue-105481.pYSwMj.rst
new file mode 100644
index 00000000000000..bc2ba51d31aa9c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-13-16-04-15.gh-issue-105481.pYSwMj.rst
@@ -0,0 +1 @@
+Expose opcode metadata through :mod:`_opcode`.
diff --git a/Misc/NEWS.d/next/Library/2023-07-14-14-53-58.gh-issue-105293.kimf_i.rst b/Misc/NEWS.d/next/Library/2023-07-14-14-53-58.gh-issue-105293.kimf_i.rst
new file mode 100644
index 00000000000000..c263c8524aa962
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-14-14-53-58.gh-issue-105293.kimf_i.rst
@@ -0,0 +1,2 @@
+Remove call to ``SSL_CTX_set_session_id_context`` during client side context
+creation in the :mod:`ssl` module.
diff --git a/Misc/NEWS.d/next/Library/2023-07-14-16-54-13.gh-issue-106752.BT1Yxw.rst b/Misc/NEWS.d/next/Library/2023-07-14-16-54-13.gh-issue-106752.BT1Yxw.rst
new file mode 100644
index 00000000000000..bbc53d76decbc3
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-14-16-54-13.gh-issue-106752.BT1Yxw.rst
@@ -0,0 +1,5 @@
+Fixed several bugs in zipfile.Path, including: in ``Path.match`, Windows
+separators are no longer honored (and never were meant to be); Fixed
+``name``/``suffix``/``suffixes``/``stem`` operations when no filename is
+present and the Path is not at the root of the zipfile; Reworked glob for
+performance and more correct matching behavior.
diff --git a/Misc/NEWS.d/next/Library/2023-07-15-12-52-50.gh-issue-105726.NGthO8.rst b/Misc/NEWS.d/next/Library/2023-07-15-12-52-50.gh-issue-105726.NGthO8.rst
new file mode 100644
index 00000000000000..434f93240eccdf
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-15-12-52-50.gh-issue-105726.NGthO8.rst
@@ -0,0 +1,3 @@
+Added ``__slots__`` to :class:`contextlib.AbstractContextManager` and :class:`contextlib.AbstractAsyncContextManager`
+so that child classes can use ``__slots__``.
+
diff --git a/Misc/NEWS.d/next/Library/2023-07-16-10-40-34.gh-issue-106789.NvyE3C.rst b/Misc/NEWS.d/next/Library/2023-07-16-10-40-34.gh-issue-106789.NvyE3C.rst
new file mode 100644
index 00000000000000..532f8059740daf
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-07-16-10-40-34.gh-issue-106789.NvyE3C.rst
@@ -0,0 +1 @@
+Remove import of :mod:``pprint`` from :mod:``sysconfig``.
diff --git a/Misc/NEWS.d/next/Security/2023-06-13-20-52-24.gh-issue-102988.Kei7Vf.rst b/Misc/NEWS.d/next/Security/2023-06-13-20-52-24.gh-issue-102988.Kei7Vf.rst
new file mode 100644
index 00000000000000..e0434ccd2ccab5
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2023-06-13-20-52-24.gh-issue-102988.Kei7Vf.rst
@@ -0,0 +1,4 @@
+CVE-2023-27043: Prevent :func:`email.utils.parseaddr`
+and :func:`email.utils.getaddresses` from returning the realname portion of an
+invalid RFC2822 email header in the email address portion of the 2-tuple
+returned after being parsed by :class:`email._parseaddr.AddressList`.
diff --git a/Misc/NEWS.d/next/Tests/2023-06-28-02-51-08.gh-issue-101634.Rayczr.rst b/Misc/NEWS.d/next/Tests/2023-06-28-02-51-08.gh-issue-101634.Rayczr.rst
new file mode 100644
index 00000000000000..6fbfc84c19e1b8
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2023-06-28-02-51-08.gh-issue-101634.Rayczr.rst
@@ -0,0 +1,3 @@
+When running the Python test suite with ``-jN`` option, if a worker stdout
+cannot be decoded from the locale encoding report a failed testn so the
+exitcode is non-zero. Patch by Victor Stinner.
diff --git a/Misc/NEWS.d/next/Tests/2023-07-12-14-07-07.gh-issue-106690.NDz-oG.rst b/Misc/NEWS.d/next/Tests/2023-07-12-14-07-07.gh-issue-106690.NDz-oG.rst
new file mode 100644
index 00000000000000..e7dc0ac2220502
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2023-07-12-14-07-07.gh-issue-106690.NDz-oG.rst
@@ -0,0 +1 @@
+Add .coveragerc to cpython repository for use with coverage package.
diff --git a/Misc/NEWS.d/next/Tests/2023-07-14-16-20-06.gh-issue-106752.gd1i6D.rst b/Misc/NEWS.d/next/Tests/2023-07-14-16-20-06.gh-issue-106752.gd1i6D.rst
new file mode 100644
index 00000000000000..ba7257e3610808
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2023-07-14-16-20-06.gh-issue-106752.gd1i6D.rst
@@ -0,0 +1,2 @@
+Moved tests for ``zipfile.Path`` into ``Lib/test/test_zipfile/_path``. Made
+``zipfile._path`` a package.
diff --git a/Misc/NEWS.d/next/Tools-Demos/2023-04-05-07-19-36.gh-issue-103186.yEozgK.rst b/Misc/NEWS.d/next/Tools-Demos/2023-04-05-07-19-36.gh-issue-103186.yEozgK.rst
new file mode 100644
index 00000000000000..7e28ba6963216a
--- /dev/null
+++ b/Misc/NEWS.d/next/Tools-Demos/2023-04-05-07-19-36.gh-issue-103186.yEozgK.rst
@@ -0,0 +1,2 @@
+``freeze`` now fetches ``CONFIG_ARGS`` from the original CPython instance
+the Makefile uses to call utility scripts. Patch by Ijtaba Hussain.
diff --git a/Misc/NEWS.d/next/Tools-Demos/2023-07-03-14-06-19.gh-issue-106359.RfJuR0.rst b/Misc/NEWS.d/next/Tools-Demos/2023-07-03-14-06-19.gh-issue-106359.RfJuR0.rst
new file mode 100644
index 00000000000000..600c265391ec5b
--- /dev/null
+++ b/Misc/NEWS.d/next/Tools-Demos/2023-07-03-14-06-19.gh-issue-106359.RfJuR0.rst
@@ -0,0 +1,2 @@
+Argument Clinic now explicitly forbids "kwarg splats" in function calls used as
+annotations.
diff --git a/Misc/NEWS.d/next/Tools-Demos/2023-07-13-12-08-35.gh-issue-106706.29zp8E.rst b/Misc/NEWS.d/next/Tools-Demos/2023-07-13-12-08-35.gh-issue-106706.29zp8E.rst
new file mode 100644
index 00000000000000..bbd8e8eddda607
--- /dev/null
+++ b/Misc/NEWS.d/next/Tools-Demos/2023-07-13-12-08-35.gh-issue-106706.29zp8E.rst
@@ -0,0 +1,3 @@
+Change bytecode syntax for families
+to remove redundant name matching
+pseudo syntax.
diff --git a/Misc/NEWS.d/next/Windows/2023-06-08-11-30-17.gh-issue-105436.1qlDxw.rst b/Misc/NEWS.d/next/Windows/2023-06-08-11-30-17.gh-issue-105436.1qlDxw.rst
new file mode 100644
index 00000000000000..1e3f298096cdd6
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2023-06-08-11-30-17.gh-issue-105436.1qlDxw.rst
@@ -0,0 +1,2 @@
+Ensure that an empty environment block is terminated by two null characters,
+as is required by Windows.
diff --git a/Misc/NEWS.d/next/Windows/2023-07-11-20-48-17.gh-issue-99079.CIMftz.rst b/Misc/NEWS.d/next/Windows/2023-07-11-20-48-17.gh-issue-99079.CIMftz.rst
new file mode 100644
index 00000000000000..11f411be0f17c5
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2023-07-11-20-48-17.gh-issue-99079.CIMftz.rst
@@ -0,0 +1 @@
+Update Windows build to use OpenSSL 3.0.9
diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml
index f9100054175fc1..8ea8fde68b833a 100644
--- a/Misc/stable_abi.toml
+++ b/Misc/stable_abi.toml
@@ -2428,3 +2428,19 @@
added = '3.12'
[const.Py_TPFLAGS_ITEMS_AT_END]
added = '3.12'
+[function.PyImport_AddModuleRef]
+ added = '3.13'
+[function.PyWeakref_GetRef]
+ added = '3.13'
+[function.PyObject_DelAttr]
+ added = '3.13'
+[function.PyObject_DelAttrString]
+ added = '3.13'
+[function.PyObject_GetOptionalAttr]
+ added = '3.13'
+[function.PyObject_GetOptionalAttrString]
+ added = '3.13'
+[function.PyMapping_GetOptionalItem]
+ added = '3.13'
+[function.PyMapping_GetOptionalItemString]
+ added = '3.13'
diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in
index c228cd5642e75b..11a022e3d2044e 100644
--- a/Modules/Setup.stdlib.in
+++ b/Modules/Setup.stdlib.in
@@ -159,7 +159,7 @@
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c
-@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c _testcapi/getargs.c _testcapi/pytime.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyos.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c
+@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyos.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
# Some testing modules MUST be built as shared libraries.
diff --git a/Modules/_abc.c b/Modules/_abc.c
index d3e405dadb664a..8a3aa9cb88880f 100644
--- a/Modules/_abc.c
+++ b/Modules/_abc.c
@@ -8,6 +8,7 @@
#include "pycore_object.h" // _PyType_GetSubclasses()
#include "pycore_runtime.h" // _Py_ID()
#include "pycore_typeobject.h" // _PyType_GetMRO()
+#include "pycore_weakref.h" // _PyWeakref_GET_REF()
#include "clinic/_abc.c.h"
/*[clinic input]
@@ -150,12 +151,10 @@ _in_weak_set(PyObject *set, PyObject *obj)
static PyObject *
_destroy(PyObject *setweakref, PyObject *objweakref)
{
- PyObject *set;
- set = PyWeakref_GET_OBJECT(setweakref);
- if (set == Py_None) {
+ PyObject *set = _PyWeakref_GET_REF(setweakref);
+ if (set == NULL) {
Py_RETURN_NONE;
}
- Py_INCREF(set);
if (PySet_Discard(set, objweakref) < 0) {
Py_DECREF(set);
return NULL;
@@ -362,7 +361,7 @@ compute_abstract_methods(PyObject *self)
PyObject *item = PyTuple_GET_ITEM(bases, pos); // borrowed
PyObject *base_abstracts, *iter;
- if (_PyObject_LookupAttr(item, &_Py_ID(__abstractmethods__),
+ if (PyObject_GetOptionalAttr(item, &_Py_ID(__abstractmethods__),
&base_abstracts) < 0) {
goto error;
}
@@ -376,7 +375,7 @@ compute_abstract_methods(PyObject *self)
Py_DECREF(base_abstracts);
PyObject *key, *value;
while ((key = PyIter_Next(iter))) {
- if (_PyObject_LookupAttr(self, key, &value) < 0) {
+ if (PyObject_GetOptionalAttr(self, key, &value) < 0) {
Py_DECREF(key);
Py_DECREF(iter);
goto error;
@@ -843,16 +842,16 @@ subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
assert(i == registry_size);
for (i = 0; i < registry_size; i++) {
- PyObject *rkey = PyWeakref_GetObject(copy[i]);
- if (rkey == NULL) {
+ PyObject *rkey;
+ if (PyWeakref_GetRef(copy[i], &rkey) < 0) {
// Someone inject non-weakref type in the registry.
ret = -1;
break;
}
- if (rkey == Py_None) {
+
+ if (rkey == NULL) {
continue;
}
- Py_INCREF(rkey);
int r = PyObject_IsSubclass(subclass, rkey);
Py_DECREF(rkey);
if (r < 0) {
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index 08ce172c6a8fcb..ef9f7f8902e09e 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -3,10 +3,11 @@
#endif
#include "Python.h"
+#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_pyerrors.h" // _PyErr_ClearExcState()
+#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_runtime_init.h" // _Py_ID()
-#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "structmember.h" // PyMemberDef
#include // offsetof()
@@ -119,11 +120,13 @@ typedef enum {
PyObject *prefix##_result; \
PyObject *prefix##_source_tb; \
PyObject *prefix##_cancel_msg; \
+ PyObject *prefix##_cancelled_exc; \
fut_state prefix##_state; \
- int prefix##_log_tb; \
- int prefix##_blocking; \
- PyObject *prefix##_weakreflist; \
- PyObject *prefix##_cancelled_exc;
+ /* These bitfields need to be at the end of the struct
+ so that these and bitfields from TaskObj are contiguous.
+ */ \
+ unsigned prefix##_log_tb: 1; \
+ unsigned prefix##_blocking: 1;
typedef struct {
FutureObj_HEAD(fut)
@@ -131,13 +134,13 @@ typedef struct {
typedef struct {
FutureObj_HEAD(task)
+ unsigned task_must_cancel: 1;
+ unsigned task_log_destroy_pending: 1;
+ int task_num_cancels_requested;
PyObject *task_fut_waiter;
PyObject *task_coro;
PyObject *task_name;
PyObject *task_context;
- int task_must_cancel;
- int task_log_destroy_pending;
- int task_num_cancels_requested;
} TaskObj;
typedef struct {
@@ -245,7 +248,7 @@ get_future_loop(asyncio_state *state, PyObject *fut)
return Py_NewRef(loop);
}
- if (_PyObject_LookupAttr(fut, &_Py_ID(get_loop), &getloop) < 0) {
+ if (PyObject_GetOptionalAttr(fut, &_Py_ID(get_loop), &getloop) < 0) {
return NULL;
}
if (getloop != NULL) {
@@ -524,7 +527,7 @@ future_init(FutureObj *fut, PyObject *loop)
if (is_true < 0) {
return -1;
}
- if (is_true && !_Py_IsInterpreterFinalizing(PyInterpreterState_Get())) {
+ if (is_true && !_Py_IsInterpreterFinalizing(_PyInterpreterState_GET())) {
/* Only try to capture the traceback if the interpreter is not being
finalized. The original motivation to add a `_Py_IsFinalizing()`
call was to prevent SIGSEGV when a Future is created in a __del__
@@ -1498,11 +1501,6 @@ static PyMethodDef FutureType_methods[] = {
{NULL, NULL} /* Sentinel */
};
-static PyMemberDef FutureType_members[] = {
- {"__weaklistoffset__", T_PYSSIZET, offsetof(FutureObj, fut_weakreflist), READONLY},
- {NULL},
-};
-
#define FUTURE_COMMON_GETSETLIST \
{"_state", (getter)FutureObj_get_state, NULL, NULL}, \
{"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
@@ -1533,7 +1531,6 @@ static PyType_Slot Future_slots[] = {
{Py_tp_clear, (inquiry)FutureObj_clear},
{Py_tp_iter, (getiterfunc)future_new_iter},
{Py_tp_methods, FutureType_methods},
- {Py_tp_members, FutureType_members},
{Py_tp_getset, FutureType_getsetlist},
{Py_tp_init, (initproc)_asyncio_Future___init__},
{Py_tp_new, PyType_GenericNew},
@@ -1548,7 +1545,8 @@ static PyType_Spec Future_spec = {
.name = "_asyncio.Future",
.basicsize = sizeof(FutureObj),
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
- Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_DICT),
+ Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_DICT |
+ Py_TPFLAGS_MANAGED_WEAKREF),
.slots = Future_slots,
};
@@ -1565,9 +1563,7 @@ FutureObj_dealloc(PyObject *self)
PyTypeObject *tp = Py_TYPE(fut);
PyObject_GC_UnTrack(self);
- if (fut->fut_weakreflist != NULL) {
- PyObject_ClearWeakRefs(self);
- }
+ PyObject_ClearWeakRefs(self);
(void)FutureObj_clear(fut);
tp->tp_free(fut);
@@ -2044,20 +2040,23 @@ swap_current_task(asyncio_state *state, PyObject *loop, PyObject *task)
}
prev_task = Py_None;
}
+ Py_INCREF(prev_task);
if (task == Py_None) {
if (_PyDict_DelItem_KnownHash(state->current_tasks, loop, hash) == -1) {
- return NULL;
+ goto error;
}
} else {
if (_PyDict_SetItem_KnownHash(state->current_tasks, loop, task, hash) == -1) {
- return NULL;
+ goto error;
}
}
- Py_INCREF(prev_task);
-
return prev_task;
+
+error:
+ Py_DECREF(prev_task);
+ return NULL;
}
/* ----- Task */
@@ -2635,11 +2634,6 @@ static PyMethodDef TaskType_methods[] = {
{NULL, NULL} /* Sentinel */
};
-static PyMemberDef TaskType_members[] = {
- {"__weaklistoffset__", T_PYSSIZET, offsetof(TaskObj, task_weakreflist), READONLY},
- {NULL},
-};
-
static PyGetSetDef TaskType_getsetlist[] = {
FUTURE_COMMON_GETSETLIST
{"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
@@ -2658,7 +2652,6 @@ static PyType_Slot Task_slots[] = {
{Py_tp_clear, (inquiry)TaskObj_clear},
{Py_tp_iter, (getiterfunc)future_new_iter},
{Py_tp_methods, TaskType_methods},
- {Py_tp_members, TaskType_members},
{Py_tp_getset, TaskType_getsetlist},
{Py_tp_init, (initproc)_asyncio_Task___init__},
{Py_tp_new, PyType_GenericNew},
@@ -2673,7 +2666,8 @@ static PyType_Spec Task_spec = {
.name = "_asyncio.Task",
.basicsize = sizeof(TaskObj),
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
- Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_DICT),
+ Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_DICT |
+ Py_TPFLAGS_MANAGED_WEAKREF),
.slots = Task_slots,
};
@@ -2690,9 +2684,7 @@ TaskObj_dealloc(PyObject *self)
PyTypeObject *tp = Py_TYPE(task);
PyObject_GC_UnTrack(self);
- if (task->task_weakreflist != NULL) {
- PyObject_ClearWeakRefs(self);
- }
+ PyObject_ClearWeakRefs(self);
(void)TaskObj_clear(task);
tp->tp_free(task);
@@ -2974,7 +2966,7 @@ task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *resu
}
/* Check if `result` is a Future-compatible object */
- if (_PyObject_LookupAttr(result, &_Py_ID(_asyncio_future_blocking), &o) < 0) {
+ if (PyObject_GetOptionalAttr(result, &_Py_ID(_asyncio_future_blocking), &o) < 0) {
goto fail;
}
if (o != NULL && o != Py_None) {
diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c
index 0773bbd191931d..9e0fd336419b44 100644
--- a/Modules/_bisectmodule.c
+++ b/Modules/_bisectmodule.c
@@ -3,8 +3,12 @@
Converted to C by Dmitry Vasiliev (dima at hlabs.spb.ru).
*/
-#define PY_SSIZE_T_CLEAN
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "Python.h"
+#include "pycore_call.h" // _PyObject_CallMethod()
/*[clinic input]
module _bisect
diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c
index 97bd44b4ac9694..eeefe6034998c8 100644
--- a/Modules/_bz2module.c
+++ b/Modules/_bz2module.c
@@ -1,7 +1,5 @@
/* _bz2 - Low-level Python interface to libbzip2. */
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "structmember.h" // PyMemberDef
diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c
index 777c753bd7c2a9..c31c1b6d6f2bbc 100644
--- a/Modules/_codecsmodule.c
+++ b/Modules/_codecsmodule.c
@@ -30,8 +30,8 @@ Copyright (c) Corporation for National Research Initiatives.
------------------------------------------------------------------------ */
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
+#include "pycore_codecs.h" // _PyCodec_Lookup()
#ifdef MS_WINDOWS
#include
diff --git a/Modules/_csv.c b/Modules/_csv.c
index 5b501af449f18d..c36d9805a12841 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -1450,7 +1450,7 @@ csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args)
Py_DECREF(self);
return NULL;
}
- if (_PyObject_LookupAttr(output_file,
+ if (PyObject_GetOptionalAttr(output_file,
module_state->str_write,
&self->write) < 0) {
Py_DECREF(self);
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 534ef8c1d6cf8f..7624c15ac522da 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -101,7 +101,6 @@ bytes(cdata)
#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
#endif
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
// windows.h must be included before pycore internal headers
@@ -238,20 +237,29 @@ PyDict_SetItemProxy(PyObject *dict, PyObject *key, PyObject *item)
return result;
}
-PyObject *
-PyDict_GetItemProxy(PyObject *dict, PyObject *key)
+static int
+_PyDict_GetItemProxy(PyObject *dict, PyObject *key, PyObject **presult)
{
- PyObject *result;
PyObject *item = PyDict_GetItemWithError(dict, key);
+ if (item == NULL) {
+ if (PyErr_Occurred()) {
+ return -1;
+ }
+ *presult = NULL;
+ return 0;
+ }
- if (item == NULL)
- return NULL;
- if (!PyWeakref_CheckProxy(item))
- return item;
- result = PyWeakref_GET_OBJECT(item);
- if (result == Py_None)
- return NULL;
- return result;
+ if (!PyWeakref_CheckProxy(item)) {
+ *presult = Py_NewRef(item);
+ return 0;
+ }
+ PyObject *ref;
+ if (PyWeakref_GetRef(item, &ref) < 0) {
+ return -1;
+ }
+ // ref is NULL if the referenced object was destroyed
+ *presult = ref;
+ return 0;
}
/******************************************************************/
@@ -843,7 +851,7 @@ CDataType_from_param(PyObject *type, PyObject *value)
return NULL;
}
- if (_PyObject_LookupAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
+ if (PyObject_GetOptionalAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
return NULL;
}
if (as_parameter) {
@@ -1487,7 +1495,7 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
stgdict = NULL;
type_attr = NULL;
- if (_PyObject_LookupAttr((PyObject *)result, &_Py_ID(_length_), &length_attr) < 0) {
+ if (PyObject_GetOptionalAttr((PyObject *)result, &_Py_ID(_length_), &length_attr) < 0) {
goto error;
}
if (!length_attr) {
@@ -1520,7 +1528,7 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
goto error;
}
- if (_PyObject_LookupAttr((PyObject *)result, &_Py_ID(_type_), &type_attr) < 0) {
+ if (PyObject_GetOptionalAttr((PyObject *)result, &_Py_ID(_type_), &type_attr) < 0) {
goto error;
}
if (!type_attr) {
@@ -1712,7 +1720,7 @@ c_wchar_p_from_param(PyObject *type, PyObject *value)
}
}
- if (_PyObject_LookupAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
+ if (PyObject_GetOptionalAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
return NULL;
}
if (as_parameter) {
@@ -1776,7 +1784,7 @@ c_char_p_from_param(PyObject *type, PyObject *value)
}
}
- if (_PyObject_LookupAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
+ if (PyObject_GetOptionalAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
return NULL;
}
if (as_parameter) {
@@ -1911,7 +1919,7 @@ c_void_p_from_param(PyObject *type, PyObject *value)
}
}
- if (_PyObject_LookupAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
+ if (PyObject_GetOptionalAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
return NULL;
}
if (as_parameter) {
@@ -2046,7 +2054,7 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (result == NULL)
return NULL;
- if (_PyObject_LookupAttr((PyObject *)result, &_Py_ID(_type_), &proto) < 0) {
+ if (PyObject_GetOptionalAttr((PyObject *)result, &_Py_ID(_type_), &proto) < 0) {
return NULL;
}
if (!proto) {
@@ -2258,7 +2266,7 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value)
PyObject *exc = PyErr_GetRaisedException();
Py_DECREF(parg);
- if (_PyObject_LookupAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
+ if (PyObject_GetOptionalAttr(value, &_Py_ID(_as_parameter_), &as_parameter) < 0) {
Py_XDECREF(exc);
return NULL;
}
@@ -2421,7 +2429,7 @@ converters_from_argtypes(PyObject *ob)
}
*/
- if (_PyObject_LookupAttr(tp, &_Py_ID(from_param), &cnv) <= 0) {
+ if (PyObject_GetOptionalAttr(tp, &_Py_ID(from_param), &cnv) <= 0) {
Py_DECREF(converters);
Py_DECREF(ob);
if (!PyErr_Occurred()) {
@@ -2481,7 +2489,7 @@ make_funcptrtype_dict(StgDictObject *stgdict)
return -1;
}
stgdict->restype = Py_NewRef(ob);
- if (_PyObject_LookupAttr(ob, &_Py_ID(_check_retval_),
+ if (PyObject_GetOptionalAttr(ob, &_Py_ID(_check_retval_),
&stgdict->checker) < 0)
{
return -1;
@@ -3267,7 +3275,7 @@ PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob, void *Py_UNUSED(ign
"restype must be a type, a callable, or None");
return -1;
}
- if (_PyObject_LookupAttr(ob, &_Py_ID(_check_retval_), &checker) < 0) {
+ if (PyObject_GetOptionalAttr(ob, &_Py_ID(_check_retval_), &checker) < 0) {
return -1;
}
oldchecker = self->checker;
@@ -4832,7 +4840,6 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length)
{
static PyObject *cache;
PyObject *key;
- PyObject *result;
char name[256];
PyObject *len;
@@ -4848,15 +4855,15 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length)
Py_DECREF(len);
if (!key)
return NULL;
- result = PyDict_GetItemProxy(cache, key);
- if (result) {
- Py_INCREF(result);
+
+ PyObject *result;
+ if (_PyDict_GetItemProxy(cache, key, &result) < 0) {
Py_DECREF(key);
- return result;
+ return NULL;
}
- else if (PyErr_Occurred()) {
+ if (result) {
Py_DECREF(key);
- return NULL;
+ return result;
}
if (!PyType_Check(itemtype)) {
diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c
index 8e694ba852c1d4..0d8ecce009a67a 100644
--- a/Modules/_ctypes/callbacks.c
+++ b/Modules/_ctypes/callbacks.c
@@ -416,25 +416,29 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
PyErr_Format(PyExc_NotImplementedError, "ffi_prep_closure_loc() is missing");
goto error;
#else
-#if defined(__clang__)
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#endif
-#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+ // GH-85272, GH-23327, GH-100540: On macOS,
+ // HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME is checked at runtime because the
+ // symbol might not be available at runtime when targeting macOS 10.14
+ // or earlier. Even if ffi_prep_closure_loc() is called in practice,
+ // the deprecated ffi_prep_closure() code path is needed if
+ // HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME is false.
+ //
+ // On non-macOS platforms, even if HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME is
+ // defined as 1 and ffi_prep_closure_loc() is used in practice, this
+ // code path is still compiled and emits a compiler warning. The
+ // deprecated code path is likely to be removed by a simple
+ // optimization pass.
+ //
+ // Ignore the compiler warning on the ffi_prep_closure() deprecation,
+ // rather than using complex #if/#else code paths for the different
+ // platforms.
+ _Py_COMP_DIAG_PUSH
+ _Py_COMP_DIAG_IGNORE_DEPR_DECLS
result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
-
-#if defined(__clang__)
- #pragma clang diagnostic pop
-#endif
-#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))
- #pragma GCC diagnostic pop
-#endif
-
+ _Py_COMP_DIAG_POP
#endif
}
+
if (result != FFI_OK) {
PyErr_Format(PyExc_RuntimeError,
"ffi_prep_closure failed with %d", result);
@@ -479,12 +483,22 @@ long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
PyObject *py_rclsid = PyLong_FromVoidPtr((void *)rclsid);
+ if (py_rclsid == NULL) {
+ Py_DECREF(func);
+ PyErr_WriteUnraisable(context ? context : Py_None);
+ return E_FAIL;
+ }
PyObject *py_riid = PyLong_FromVoidPtr((void *)riid);
+ if (py_riid == NULL) {
+ Py_DECREF(func);
+ Py_DECREF(py_rclsid);
+ PyErr_WriteUnraisable(context ? context : Py_None);
+ return E_FAIL;
+ }
PyObject *py_ppv = PyLong_FromVoidPtr(ppv);
- if (!py_rclsid || !py_riid || !py_ppv) {
- Py_XDECREF(py_rclsid);
- Py_XDECREF(py_riid);
- Py_XDECREF(py_ppv);
+ if (py_ppv == NULL) {
+ Py_DECREF(py_rclsid);
+ Py_DECREF(py_riid);
Py_DECREF(func);
PyErr_WriteUnraisable(context ? context : Py_None);
return E_FAIL;
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index d2fe525dd4d396..b3831ae7119a56 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -727,7 +727,7 @@ static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa)
{
PyObject *arg;
- if (_PyObject_LookupAttr(obj, &_Py_ID(_as_parameter_), &arg) < 0) {
+ if (PyObject_GetOptionalAttr(obj, &_Py_ID(_as_parameter_), &arg) < 0) {
return -1;
}
/* Which types should we exactly allow here?
diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c
index b1b2bac1455e67..3348ebd6593d2f 100644
--- a/Modules/_ctypes/stgdict.c
+++ b/Modules/_ctypes/stgdict.c
@@ -295,7 +295,7 @@ MakeAnonFields(PyObject *type)
PyObject *anon_names;
Py_ssize_t i;
- if (_PyObject_LookupAttr(type, &_Py_ID(_anonymous_), &anon) < 0) {
+ if (PyObject_GetOptionalAttr(type, &_Py_ID(_anonymous_), &anon) < 0) {
return -1;
}
if (anon == NULL) {
@@ -385,7 +385,7 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct
if (fields == NULL)
return 0;
- if (_PyObject_LookupAttr(type, &_Py_ID(_swappedbytes_), &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(type, &_Py_ID(_swappedbytes_), &tmp) < 0) {
return -1;
}
if (tmp) {
@@ -396,7 +396,7 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct
big_endian = PY_BIG_ENDIAN;
}
- if (_PyObject_LookupAttr(type, &_Py_ID(_pack_), &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(type, &_Py_ID(_pack_), &tmp) < 0) {
return -1;
}
if (tmp) {
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 5691a419a32f8e..1f5afa6fcd898d 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -104,8 +104,6 @@ static const char PyCursesVersion[] = "2.2";
# define Py_BUILD_CORE_MODULE 1
#endif
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_structseq.h" // _PyStructSequence_NewType()
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index 57f817dad8f842..b8cb0c012fd537 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -3791,7 +3791,7 @@ tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
PyObject *args, *state;
PyObject *getinitargs;
- if (_PyObject_LookupAttr(self, &_Py_ID(__getinitargs__), &getinitargs) < 0) {
+ if (PyObject_GetOptionalAttr(self, &_Py_ID(__getinitargs__), &getinitargs) < 0) {
return NULL;
}
if (getinitargs != NULL) {
@@ -6862,24 +6862,49 @@ _datetime_exec(PyObject *module)
assert(DI100Y == days_before_year(100+1));
us_per_ms = PyLong_FromLong(1000);
+ if (us_per_ms == NULL) {
+ goto error;
+ }
us_per_second = PyLong_FromLong(1000000);
+ if (us_per_second == NULL) {
+ goto error;
+ }
us_per_minute = PyLong_FromLong(60000000);
+ if (us_per_minute == NULL) {
+ goto error;
+ }
seconds_per_day = PyLong_FromLong(24 * 3600);
- if (us_per_ms == NULL || us_per_second == NULL ||
- us_per_minute == NULL || seconds_per_day == NULL) {
- return -1;
+ if (seconds_per_day == NULL) {
+ goto error;
}
/* The rest are too big for 32-bit ints, but even
* us_per_week fits in 40 bits, so doubles should be exact.
*/
us_per_hour = PyLong_FromDouble(3600000000.0);
+ if (us_per_hour == NULL) {
+ goto error;
+ }
us_per_day = PyLong_FromDouble(86400000000.0);
+ if (us_per_day == NULL) {
+ goto error;
+ }
us_per_week = PyLong_FromDouble(604800000000.0);
- if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL) {
- return -1;
+ if (us_per_week == NULL) {
+ goto error;
}
+
return 0;
+
+error:
+ Py_XDECREF(us_per_ms);
+ Py_XDECREF(us_per_second);
+ Py_XDECREF(us_per_minute);
+ Py_XDECREF(us_per_hour);
+ Py_XDECREF(us_per_day);
+ Py_XDECREF(us_per_week);
+ Py_XDECREF(seconds_per_day);
+ return -1;
}
static struct PyModuleDef datetimemodule = {
diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c
index 9908174c94c450..5be444d53e8da3 100644
--- a/Modules/_dbmmodule.c
+++ b/Modules/_dbmmodule.c
@@ -2,7 +2,6 @@
/* DBM module using dictionary interface */
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c
index c8ff3896ba1a13..e3dc304066b45b 100644
--- a/Modules/_decimal/_decimal.c
+++ b/Modules/_decimal/_decimal.c
@@ -39,6 +39,61 @@
#include "docstrings.h"
+#ifdef EXTRA_FUNCTIONALITY
+ #define _PY_DEC_ROUND_GUARD MPD_ROUND_GUARD
+#else
+ #define _PY_DEC_ROUND_GUARD (MPD_ROUND_GUARD-1)
+#endif
+
+struct PyDecContextObject;
+
+typedef struct {
+ PyTypeObject *PyDecContextManager_Type;
+ PyTypeObject *PyDecContext_Type;
+ PyTypeObject *PyDecSignalDictMixin_Type;
+ PyTypeObject *PyDec_Type;
+ PyTypeObject *PyDecSignalDict_Type;
+ PyTypeObject *DecimalTuple;
+
+ /* Top level Exception; inherits from ArithmeticError */
+ PyObject *DecimalException;
+
+#ifndef WITH_DECIMAL_CONTEXTVAR
+ /* Key for thread state dictionary */
+ PyObject *tls_context_key;
+ /* Invariant: NULL or the most recently accessed thread local context */
+ struct PyDecContextObject *cached_context;
+#else
+ PyObject *current_context_var;
+#endif
+
+ /* Template for creating new thread contexts, calling Context() without
+ * arguments and initializing the module_context on first access. */
+ PyObject *default_context_template;
+
+ /* Basic and extended context templates */
+ PyObject *basic_context_template;
+ PyObject *extended_context_template;
+
+ PyObject *round_map[_PY_DEC_ROUND_GUARD];
+
+ /* Convert rationals for comparison */
+ PyObject *Rational;
+
+ PyObject *SignalTuple;
+
+ /* External C-API functions */
+ binaryfunc _py_long_multiply;
+ binaryfunc _py_long_floor_divide;
+ ternaryfunc _py_long_power;
+ unaryfunc _py_float_abs;
+ PyCFunction _py_long_bit_length;
+ PyCFunction _py_float_as_integer_ratio;
+} decimal_state;
+
+static decimal_state global_state;
+
+#define GLOBAL_STATE() (&global_state)
#if !defined(MPD_VERSION_HEX) || MPD_VERSION_HEX < 0x02050000
#error "libmpdec version >= 2.5.0 required"
@@ -81,7 +136,7 @@ typedef struct {
uint32_t *flags;
} PyDecSignalDictObject;
-typedef struct {
+typedef struct PyDecContextObject {
PyObject_HEAD
mpd_context_t ctx;
PyObject *traps;
@@ -96,17 +151,12 @@ typedef struct {
PyObject *global;
} PyDecContextManagerObject;
-
#undef MPD
#undef CTX
-static PyTypeObject PyDec_Type;
-static PyTypeObject *PyDecSignalDict_Type;
-static PyTypeObject PyDecContext_Type;
-static PyTypeObject PyDecContextManager_Type;
-#define PyDec_CheckExact(v) Py_IS_TYPE(v, &PyDec_Type)
-#define PyDec_Check(v) PyObject_TypeCheck(v, &PyDec_Type)
-#define PyDecSignalDict_Check(v) Py_IS_TYPE(v, PyDecSignalDict_Type)
-#define PyDecContext_Check(v) PyObject_TypeCheck(v, &PyDecContext_Type)
+#define PyDec_CheckExact(st, v) Py_IS_TYPE(v, (st)->PyDec_Type)
+#define PyDec_Check(st, v) PyObject_TypeCheck(v, (st)->PyDec_Type)
+#define PyDecSignalDict_Check(st, v) Py_IS_TYPE(v, (st)->PyDecSignalDict_Type)
+#define PyDecContext_Check(st, v) PyObject_TypeCheck(v, (st)->PyDecContext_Type)
#define MPD(v) (&((PyDecObject *)v)->dec)
#define SdFlagAddr(v) (((PyDecSignalDictObject *)v)->flags)
#define SdFlags(v) (*((PyDecSignalDictObject *)v)->flags)
@@ -126,24 +176,6 @@ incr_false(void)
return Py_NewRef(Py_False);
}
-
-#ifndef WITH_DECIMAL_CONTEXTVAR
-/* Key for thread state dictionary */
-static PyObject *tls_context_key = NULL;
-/* Invariant: NULL or the most recently accessed thread local context */
-static PyDecContextObject *cached_context = NULL;
-#else
-static PyObject *current_context_var = NULL;
-#endif
-
-/* Template for creating new thread contexts, calling Context() without
- * arguments and initializing the module_context on first access. */
-static PyObject *default_context_template = NULL;
-/* Basic and extended context templates */
-static PyObject *basic_context_template = NULL;
-static PyObject *extended_context_template = NULL;
-
-
/* Error codes for functions that return signals or conditions */
#define DEC_INVALID_SIGNALS (MPD_Max_status+1U)
#define DEC_ERR_OCCURRED (DEC_INVALID_SIGNALS<<1)
@@ -156,9 +188,6 @@ typedef struct {
PyObject *ex; /* corresponding exception */
} DecCondMap;
-/* Top level Exception; inherits from ArithmeticError */
-static PyObject *DecimalException = NULL;
-
/* Exceptions that correspond to IEEE signals */
#define SUBNORMAL 5
#define INEXACT 6
@@ -208,13 +237,6 @@ static const char *dec_signal_string[MPD_NUM_FLAGS] = {
"Underflow",
};
-#ifdef EXTRA_FUNCTIONALITY
- #define _PY_DEC_ROUND_GUARD MPD_ROUND_GUARD
-#else
- #define _PY_DEC_ROUND_GUARD (MPD_ROUND_GUARD-1)
-#endif
-static PyObject *round_map[_PY_DEC_ROUND_GUARD];
-
static const char *invalid_rounding_err =
"valid values for rounding are:\n\
[ROUND_CEILING, ROUND_FLOOR, ROUND_UP, ROUND_DOWN,\n\
@@ -512,15 +534,16 @@ static int
getround(PyObject *v)
{
int i;
+ decimal_state *state = GLOBAL_STATE();
if (PyUnicode_Check(v)) {
for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
- if (v == round_map[i]) {
+ if (v == state->round_map[i]) {
return i;
}
}
for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
- if (PyUnicode_Compare(v, round_map[i]) == 0) {
+ if (PyUnicode_Compare(v, state->round_map[i]) == 0) {
return i;
}
}
@@ -553,11 +576,11 @@ signaldict_len(PyObject *self UNUSED)
return SIGNAL_MAP_LEN;
}
-static PyObject *SignalTuple;
static PyObject *
signaldict_iter(PyObject *self UNUSED)
{
- return PyTuple_Type.tp_iter(SignalTuple);
+ decimal_state *state = GLOBAL_STATE();
+ return PyTuple_Type.tp_iter(state->SignalTuple);
}
static PyObject *
@@ -603,6 +626,22 @@ signaldict_setitem(PyObject *self, PyObject *key, PyObject *value)
return 0;
}
+static int
+signaldict_traverse(PyObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT(Py_TYPE(self));
+ return 0;
+}
+
+static void
+signaldict_dealloc(PyObject *self)
+{
+ PyTypeObject *tp = Py_TYPE(self);
+ PyObject_GC_UnTrack(self);
+ tp->tp_free(self);
+ Py_DECREF(tp);
+}
+
static PyObject *
signaldict_repr(PyObject *self)
{
@@ -631,10 +670,11 @@ signaldict_richcompare(PyObject *v, PyObject *w, int op)
{
PyObject *res = Py_NotImplemented;
- assert(PyDecSignalDict_Check(v));
+ decimal_state *state = GLOBAL_STATE();
+ assert(PyDecSignalDict_Check(state, v));
if (op == Py_EQ || op == Py_NE) {
- if (PyDecSignalDict_Check(w)) {
+ if (PyDecSignalDict_Check(state, w)) {
res = (SdFlags(v)==SdFlags(w)) ^ (op==Py_NE) ? Py_True : Py_False;
}
else if (PyDict_Check(w)) {
@@ -664,58 +704,36 @@ signaldict_copy(PyObject *self, PyObject *args UNUSED)
}
-static PyMappingMethods signaldict_as_mapping = {
- (lenfunc)signaldict_len, /* mp_length */
- (binaryfunc)signaldict_getitem, /* mp_subscript */
- (objobjargproc)signaldict_setitem /* mp_ass_subscript */
-};
-
static PyMethodDef signaldict_methods[] = {
{ "copy", (PyCFunction)signaldict_copy, METH_NOARGS, NULL},
{NULL, NULL}
};
-static PyTypeObject PyDecSignalDictMixin_Type =
-{
- PyVarObject_HEAD_INIT(0, 0)
- "decimal.SignalDictMixin", /* tp_name */
- sizeof(PyDecSignalDictObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /* tp_dealloc */
- 0, /* tp_vectorcall_offset */
- (getattrfunc) 0, /* tp_getattr */
- (setattrfunc) 0, /* tp_setattr */
- 0, /* tp_as_async */
- (reprfunc) signaldict_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- &signaldict_as_mapping, /* tp_as_mapping */
- PyObject_HashNotImplemented, /* tp_hash */
- 0, /* tp_call */
- (reprfunc) 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- (setattrofunc) 0, /* tp_setattro */
- (PyBufferProcs *) 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- signaldict_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- (getiterfunc)signaldict_iter, /* tp_iter */
- 0, /* tp_iternext */
- signaldict_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)signaldict_init, /* tp_init */
- 0, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
+static PyType_Slot signaldict_slots[] = {
+ {Py_tp_dealloc, signaldict_dealloc},
+ {Py_tp_traverse, signaldict_traverse},
+ {Py_tp_repr, signaldict_repr},
+ {Py_tp_hash, PyObject_HashNotImplemented},
+ {Py_tp_getattro, PyObject_GenericGetAttr},
+ {Py_tp_richcompare, signaldict_richcompare},
+ {Py_tp_iter, signaldict_iter},
+ {Py_tp_methods, signaldict_methods},
+ {Py_tp_init, signaldict_init},
+
+ // Mapping protocol
+ {Py_mp_length, signaldict_len},
+ {Py_mp_subscript, signaldict_getitem},
+ {Py_mp_ass_subscript, signaldict_setitem},
+ {0, NULL},
+};
+
+static PyType_Spec signaldict_spec = {
+ .name = "decimal.SignalDictMixin",
+ .basicsize = sizeof(PyDecSignalDictObject),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = signaldict_slots,
};
@@ -751,8 +769,9 @@ static PyObject *
context_getround(PyObject *self, void *closure UNUSED)
{
int i = mpd_getround(CTX(self));
+ decimal_state *state = GLOBAL_STATE();
- return Py_NewRef(round_map[i]);
+ return Py_NewRef(state->round_map[i]);
}
static PyObject *
@@ -987,7 +1006,8 @@ context_settraps_dict(PyObject *self, PyObject *value)
mpd_context_t *ctx;
uint32_t flags;
- if (PyDecSignalDict_Check(value)) {
+ decimal_state *state = GLOBAL_STATE();
+ if (PyDecSignalDict_Check(state, value)) {
flags = SdFlags(value);
}
else {
@@ -1051,7 +1071,8 @@ context_setstatus_dict(PyObject *self, PyObject *value)
mpd_context_t *ctx;
uint32_t flags;
- if (PyDecSignalDict_Check(value)) {
+ decimal_state *state = GLOBAL_STATE();
+ if (PyDecSignalDict_Check(state, value)) {
flags = SdFlags(value);
}
else {
@@ -1241,8 +1262,9 @@ context_new(PyTypeObject *type, PyObject *args UNUSED, PyObject *kwds UNUSED)
PyDecContextObject *self = NULL;
mpd_context_t *ctx;
- if (type == &PyDecContext_Type) {
- self = PyObject_New(PyDecContextObject, &PyDecContext_Type);
+ decimal_state *state = GLOBAL_STATE();
+ if (type == state->PyDecContext_Type) {
+ self = PyObject_GC_New(PyDecContextObject, state->PyDecContext_Type);
}
else {
self = (PyDecContextObject *)type->tp_alloc(type, 0);
@@ -1252,13 +1274,13 @@ context_new(PyTypeObject *type, PyObject *args UNUSED, PyObject *kwds UNUSED)
return NULL;
}
- self->traps = PyObject_CallObject((PyObject *)PyDecSignalDict_Type, NULL);
+ self->traps = PyObject_CallObject((PyObject *)state->PyDecSignalDict_Type, NULL);
if (self->traps == NULL) {
self->flags = NULL;
Py_DECREF(self);
return NULL;
}
- self->flags = PyObject_CallObject((PyObject *)PyDecSignalDict_Type, NULL);
+ self->flags = PyObject_CallObject((PyObject *)state->PyDecSignalDict_Type, NULL);
if (self->flags == NULL) {
Py_DECREF(self);
return NULL;
@@ -1266,8 +1288,8 @@ context_new(PyTypeObject *type, PyObject *args UNUSED, PyObject *kwds UNUSED)
ctx = CTX(self);
- if (default_context_template) {
- *ctx = *CTX(default_context_template);
+ if (state->default_context_template) {
+ *ctx = *CTX(state->default_context_template);
}
else {
*ctx = dflt_ctx;
@@ -1282,18 +1304,37 @@ context_new(PyTypeObject *type, PyObject *args UNUSED, PyObject *kwds UNUSED)
return (PyObject *)self;
}
+static int
+context_traverse(PyDecContextObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT(Py_TYPE(self));
+ Py_VISIT(self->traps);
+ Py_VISIT(self->flags);
+ return 0;
+}
+
+static int
+context_clear(PyDecContextObject *self)
+{
+ Py_CLEAR(self->traps);
+ Py_CLEAR(self->flags);
+ return 0;
+}
+
static void
context_dealloc(PyDecContextObject *self)
{
+ PyTypeObject *tp = Py_TYPE(self);
+ PyObject_GC_UnTrack(self);
#ifndef WITH_DECIMAL_CONTEXTVAR
- if (self == cached_context) {
- cached_context = NULL;
+ decimal_state *state = GLOBAL_STATE();
+ if (self == state->cached_context) {
+ state->cached_context = NULL;
}
#endif
-
- Py_XDECREF(self->traps);
- Py_XDECREF(self->flags);
- Py_TYPE(self)->tp_free(self);
+ (void)context_clear(self);
+ tp->tp_free(self);
+ Py_DECREF(tp);
}
static int
@@ -1337,7 +1378,10 @@ context_repr(PyDecContextObject *self)
char traps[MPD_MAX_SIGNAL_LIST];
int n, mem;
- assert(PyDecContext_Check(self));
+#ifdef Py_DEBUG
+ decimal_state *state = GLOBAL_STATE();
+ assert(PyDecContext_Check(state, self));
+#endif
ctx = CTX(self);
mem = MPD_MAX_SIGNAL_LIST;
@@ -1403,7 +1447,8 @@ ieee_context(PyObject *dummy UNUSED, PyObject *v)
goto error;
}
- context = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL);
+ decimal_state *state = GLOBAL_STATE();
+ context = PyObject_CallObject((PyObject *)state->PyDecContext_Type, NULL);
if (context == NULL) {
return NULL;
}
@@ -1425,7 +1470,8 @@ context_copy(PyObject *self, PyObject *args UNUSED)
{
PyObject *copy;
- copy = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL);
+ decimal_state *state = GLOBAL_STATE();
+ copy = PyObject_CallObject((PyObject *)state->PyDecContext_Type, NULL);
if (copy == NULL) {
return NULL;
}
@@ -1487,18 +1533,18 @@ static PyGetSetDef context_getsets [] =
};
-#define CONTEXT_CHECK(obj) \
- if (!PyDecContext_Check(obj)) { \
+#define CONTEXT_CHECK(state, obj) \
+ if (!PyDecContext_Check(state, obj)) { \
PyErr_SetString(PyExc_TypeError, \
"argument must be a context"); \
return NULL; \
}
-#define CONTEXT_CHECK_VA(obj) \
+#define CONTEXT_CHECK_VA(state, obj) \
if (obj == Py_None) { \
CURRENT_CONTEXT(obj); \
} \
- else if (!PyDecContext_Check(obj)) { \
+ else if (!PyDecContext_Check(state, obj)) { \
PyErr_SetString(PyExc_TypeError, \
"optional argument must be a context"); \
return NULL; \
@@ -1522,6 +1568,7 @@ static PyObject *
current_context_from_dict(void)
{
PyThreadState *tstate = _PyThreadState_GET();
+ decimal_state *modstate = GLOBAL_STATE();
#ifdef Py_DEBUG
// The caller must hold the GIL
_Py_EnsureTstateNotNULL(tstate);
@@ -1534,10 +1581,11 @@ current_context_from_dict(void)
return NULL;
}
- PyObject *tl_context = PyDict_GetItemWithError(dict, tls_context_key);
+ PyObject *tl_context;
+ tl_context = PyDict_GetItemWithError(dict, modstate->tls_context_key);
if (tl_context != NULL) {
/* We already have a thread local context. */
- CONTEXT_CHECK(tl_context);
+ CONTEXT_CHECK(modstate, tl_context);
}
else {
if (PyErr_Occurred()) {
@@ -1545,13 +1593,13 @@ current_context_from_dict(void)
}
/* Set up a new thread local context. */
- tl_context = context_copy(default_context_template, NULL);
+ tl_context = context_copy(modstate->default_context_template, NULL);
if (tl_context == NULL) {
return NULL;
}
CTX(tl_context)->status = 0;
- if (PyDict_SetItem(dict, tls_context_key, tl_context) < 0) {
+ if (PyDict_SetItem(dict, modstate->tls_context_key, tl_context) < 0) {
Py_DECREF(tl_context);
return NULL;
}
@@ -1560,8 +1608,8 @@ current_context_from_dict(void)
/* Cache the context of the current thread, assuming that it
* will be accessed several times before a thread switch. */
- cached_context = (PyDecContextObject *)tl_context;
- cached_context->tstate = tstate;
+ modstate->cached_context = (PyDecContextObject *)tl_context;
+ modstate->cached_context->tstate = tstate;
/* Borrowed reference with refcount==1 */
return tl_context;
@@ -1572,8 +1620,9 @@ static PyObject *
current_context(void)
{
PyThreadState *tstate = _PyThreadState_GET();
- if (cached_context && cached_context->tstate == tstate) {
- return (PyObject *)cached_context;
+ decimal_state *modstate = GLOBAL_STATE();
+ if (modstate->cached_context && modstate->cached_context->tstate == tstate) {
+ return (PyObject *)(modstate->cached_context);
}
return current_context_from_dict();
@@ -1606,7 +1655,8 @@ PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
{
PyObject *dict;
- CONTEXT_CHECK(v);
+ decimal_state *state = GLOBAL_STATE();
+ CONTEXT_CHECK(state, v);
dict = PyThreadState_GetDict();
if (dict == NULL) {
@@ -1617,9 +1667,9 @@ PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
/* If the new context is one of the templates, make a copy.
* This is the current behavior of decimal.py. */
- if (v == default_context_template ||
- v == basic_context_template ||
- v == extended_context_template) {
+ if (v == state->default_context_template ||
+ v == state->basic_context_template ||
+ v == state->extended_context_template) {
v = context_copy(v, NULL);
if (v == NULL) {
return NULL;
@@ -1630,8 +1680,8 @@ PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
Py_INCREF(v);
}
- cached_context = NULL;
- if (PyDict_SetItem(dict, tls_context_key, v) < 0) {
+ state->cached_context = NULL;
+ if (PyDict_SetItem(dict, state->tls_context_key, v) < 0) {
Py_DECREF(v);
return NULL;
}
@@ -1643,13 +1693,14 @@ PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
static PyObject *
init_current_context(void)
{
- PyObject *tl_context = context_copy(default_context_template, NULL);
+ decimal_state *state = GLOBAL_STATE();
+ PyObject *tl_context = context_copy(state->default_context_template, NULL);
if (tl_context == NULL) {
return NULL;
}
CTX(tl_context)->status = 0;
- PyObject *tok = PyContextVar_Set(current_context_var, tl_context);
+ PyObject *tok = PyContextVar_Set(state->current_context_var, tl_context);
if (tok == NULL) {
Py_DECREF(tl_context);
return NULL;
@@ -1663,7 +1714,8 @@ static inline PyObject *
current_context(void)
{
PyObject *tl_context;
- if (PyContextVar_Get(current_context_var, NULL, &tl_context) < 0) {
+ decimal_state *state = GLOBAL_STATE();
+ if (PyContextVar_Get(state->current_context_var, NULL, &tl_context) < 0) {
return NULL;
}
@@ -1693,13 +1745,14 @@ PyDec_GetCurrentContext(PyObject *self UNUSED, PyObject *args UNUSED)
static PyObject *
PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
{
- CONTEXT_CHECK(v);
+ decimal_state *state = GLOBAL_STATE();
+ CONTEXT_CHECK(state, v);
/* If the new context is one of the templates, make a copy.
* This is the current behavior of decimal.py. */
- if (v == default_context_template ||
- v == basic_context_template ||
- v == extended_context_template) {
+ if (v == state->default_context_template ||
+ v == state->basic_context_template ||
+ v == state->extended_context_template) {
v = context_copy(v, NULL);
if (v == NULL) {
return NULL;
@@ -1710,7 +1763,7 @@ PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
Py_INCREF(v);
}
- PyObject *tok = PyContextVar_Set(current_context_var, v);
+ PyObject *tok = PyContextVar_Set(state->current_context_var, v);
Py_DECREF(v);
if (tok == NULL) {
return NULL;
@@ -1733,7 +1786,6 @@ ctxmanager_new(PyTypeObject *type UNUSED, PyObject *args, PyObject *kwds)
"clamp", "flags", "traps",
NULL
};
- PyDecContextManagerObject *self;
PyObject *local = Py_None;
PyObject *global;
@@ -1746,6 +1798,7 @@ ctxmanager_new(PyTypeObject *type UNUSED, PyObject *args, PyObject *kwds)
PyObject *flags = Py_None;
PyObject *traps = Py_None;
+ decimal_state *state = GLOBAL_STATE();
CURRENT_CONTEXT(global);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOOOOO", kwlist, &local,
&prec, &rounding, &Emin, &Emax, &capitals, &clamp, &flags, &traps)) {
@@ -1754,46 +1807,68 @@ ctxmanager_new(PyTypeObject *type UNUSED, PyObject *args, PyObject *kwds)
if (local == Py_None) {
local = global;
}
- else if (!PyDecContext_Check(local)) {
+ else if (!PyDecContext_Check(state, local)) {
PyErr_SetString(PyExc_TypeError,
"optional argument must be a context");
return NULL;
}
- self = PyObject_New(PyDecContextManagerObject,
- &PyDecContextManager_Type);
- if (self == NULL) {
- return NULL;
- }
-
- self->local = context_copy(local, NULL);
- if (self->local == NULL) {
- self->global = NULL;
- Py_DECREF(self);
+ PyObject *local_copy = context_copy(local, NULL);
+ if (local_copy == NULL) {
return NULL;
}
- self->global = Py_NewRef(global);
int ret = context_setattrs(
- self->local, prec, rounding,
+ local_copy, prec, rounding,
Emin, Emax, capitals,
clamp, flags, traps
);
-
if (ret < 0) {
- Py_DECREF(self);
+ Py_DECREF(local_copy);
+ return NULL;
+ }
+
+ PyDecContextManagerObject *self;
+ self = PyObject_GC_New(PyDecContextManagerObject,
+ state->PyDecContextManager_Type);
+ if (self == NULL) {
+ Py_DECREF(local_copy);
return NULL;
}
+ self->local = local_copy;
+ self->global = Py_NewRef(global);
+ PyObject_GC_Track(self);
+
return (PyObject *)self;
}
+static int
+ctxmanager_traverse(PyDecContextManagerObject *self, visitproc visit,
+ void *arg)
+{
+ Py_VISIT(Py_TYPE(self));
+ Py_VISIT(self->local);
+ Py_VISIT(self->global);
+ return 0;
+}
+
+static int
+ctxmanager_clear(PyDecContextManagerObject *self)
+{
+ Py_CLEAR(self->local);
+ Py_CLEAR(self->global);
+ return 0;
+}
+
static void
ctxmanager_dealloc(PyDecContextManagerObject *self)
{
- Py_XDECREF(self->local);
- Py_XDECREF(self->global);
- PyObject_Free(self);
+ PyTypeObject *tp = Py_TYPE(self);
+ PyObject_GC_UnTrack(self);
+ (void)ctxmanager_clear(self);
+ tp->tp_free((PyObject *)self);
+ Py_DECREF(tp);
}
static PyObject *
@@ -1832,36 +1907,21 @@ static PyMethodDef ctxmanager_methods[] = {
{NULL, NULL}
};
-static PyTypeObject PyDecContextManager_Type =
-{
- PyVarObject_HEAD_INIT(NULL, 0)
- "decimal.ContextManager", /* tp_name */
- sizeof(PyDecContextManagerObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor) ctxmanager_dealloc, /* tp_dealloc */
- 0, /* tp_vectorcall_offset */
- (getattrfunc) 0, /* tp_getattr */
- (setattrfunc) 0, /* tp_setattr */
- 0, /* tp_as_async */
- (reprfunc) 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- (getattrofunc) PyObject_GenericGetAttr, /* tp_getattro */
- (setattrofunc) 0, /* tp_setattro */
- (PyBufferProcs *) 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- ctxmanager_methods, /* tp_methods */
+static PyType_Slot ctxmanager_slots[] = {
+ {Py_tp_dealloc, ctxmanager_dealloc},
+ {Py_tp_getattro, PyObject_GenericGetAttr},
+ {Py_tp_traverse, ctxmanager_traverse},
+ {Py_tp_clear, ctxmanager_clear},
+ {Py_tp_methods, ctxmanager_methods},
+ {0, NULL},
+};
+
+static PyType_Spec ctxmanager_spec = {
+ .name = "decimal.ContextManager",
+ .basicsize = sizeof(PyDecContextManagerObject),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION),
+ .slots = ctxmanager_slots,
};
@@ -1874,8 +1934,9 @@ PyDecType_New(PyTypeObject *type)
{
PyDecObject *dec;
- if (type == &PyDec_Type) {
- dec = PyObject_New(PyDecObject, &PyDec_Type);
+ decimal_state *state = GLOBAL_STATE();
+ if (type == state->PyDec_Type) {
+ dec = PyObject_GC_New(PyDecObject, state->PyDec_Type);
}
else {
dec = (PyDecObject *)type->tp_alloc(type, 0);
@@ -1895,13 +1956,23 @@ PyDecType_New(PyTypeObject *type)
return (PyObject *)dec;
}
-#define dec_alloc() PyDecType_New(&PyDec_Type)
+#define dec_alloc(st) PyDecType_New((st)->PyDec_Type)
+
+static int
+dec_traverse(PyObject *dec, visitproc visit, void *arg)
+{
+ Py_VISIT(Py_TYPE(dec));
+ return 0;
+}
static void
dec_dealloc(PyObject *dec)
{
+ PyTypeObject *tp = Py_TYPE(dec);
+ PyObject_GC_UnTrack(dec);
mpd_del(MPD(dec));
- Py_TYPE(dec)->tp_free(dec);
+ tp->tp_free(dec);
+ Py_DECREF(tp);
}
@@ -2236,14 +2307,6 @@ PyDecType_FromLongExact(PyTypeObject *type, PyObject *v,
return dec;
}
-/* External C-API functions */
-static binaryfunc _py_long_multiply;
-static binaryfunc _py_long_floor_divide;
-static ternaryfunc _py_long_power;
-static unaryfunc _py_float_abs;
-static PyCFunction _py_long_bit_length;
-static PyCFunction _py_float_as_integer_ratio;
-
/* Return a PyDecObject or a subtype from a PyFloatObject.
Conversion is exact. */
static PyObject *
@@ -2259,9 +2322,10 @@ PyDecType_FromFloatExact(PyTypeObject *type, PyObject *v,
uint32_t status = 0;
mpd_context_t maxctx;
-
- assert(PyType_IsSubtype(type, &PyDec_Type));
-
+ decimal_state *state = GLOBAL_STATE();
+#ifdef Py_DEBUG
+ assert(PyType_IsSubtype(type, state->PyDec_Type));
+#endif
if (PyLong_Check(v)) {
return PyDecType_FromLongExact(type, v, context);
}
@@ -2294,13 +2358,13 @@ PyDecType_FromFloatExact(PyTypeObject *type, PyObject *v,
}
/* absolute value of the float */
- tmp = _py_float_abs(v);
+ tmp = state->_py_float_abs(v);
if (tmp == NULL) {
return NULL;
}
/* float as integer ratio: numerator/denominator */
- n_d = _py_float_as_integer_ratio(tmp, NULL);
+ n_d = state->_py_float_as_integer_ratio(tmp, NULL);
Py_DECREF(tmp);
if (n_d == NULL) {
return NULL;
@@ -2308,7 +2372,7 @@ PyDecType_FromFloatExact(PyTypeObject *type, PyObject *v,
n = PyTuple_GET_ITEM(n_d, 0);
d = PyTuple_GET_ITEM(n_d, 1);
- tmp = _py_long_bit_length(d, NULL);
+ tmp = state->_py_long_bit_length(d, NULL);
if (tmp == NULL) {
Py_DECREF(n_d);
return NULL;
@@ -2395,7 +2459,8 @@ PyDecType_FromDecimalExact(PyTypeObject *type, PyObject *v, PyObject *context)
PyObject *dec;
uint32_t status = 0;
- if (type == &PyDec_Type && PyDec_CheckExact(v)) {
+ decimal_state *state = GLOBAL_STATE();
+ if (type == state->PyDec_Type && PyDec_CheckExact(state, v)) {
return Py_NewRef(v);
}
@@ -2630,37 +2695,37 @@ PyDecType_FromSequenceExact(PyTypeObject *type, PyObject *v,
return dec;
}
-#define PyDec_FromCString(str, context) \
- PyDecType_FromCString(&PyDec_Type, str, context)
-#define PyDec_FromCStringExact(str, context) \
- PyDecType_FromCStringExact(&PyDec_Type, str, context)
+#define PyDec_FromCString(st, str, context) \
+ PyDecType_FromCString((st)->PyDec_Type, str, context)
+#define PyDec_FromCStringExact(st, str, context) \
+ PyDecType_FromCStringExact((st)->PyDec_Type, str, context)
-#define PyDec_FromUnicode(unicode, context) \
- PyDecType_FromUnicode(&PyDec_Type, unicode, context)
-#define PyDec_FromUnicodeExact(unicode, context) \
- PyDecType_FromUnicodeExact(&PyDec_Type, unicode, context)
-#define PyDec_FromUnicodeExactWS(unicode, context) \
- PyDecType_FromUnicodeExactWS(&PyDec_Type, unicode, context)
+#define PyDec_FromUnicode(st, unicode, context) \
+ PyDecType_FromUnicode((st)->PyDec_Type, unicode, context)
+#define PyDec_FromUnicodeExact(st, unicode, context) \
+ PyDecType_FromUnicodeExact((st)->PyDec_Type, unicode, context)
+#define PyDec_FromUnicodeExactWS(st, unicode, context) \
+ PyDecType_FromUnicodeExactWS((st)->PyDec_Type, unicode, context)
-#define PyDec_FromSsize(v, context) \
- PyDecType_FromSsize(&PyDec_Type, v, context)
-#define PyDec_FromSsizeExact(v, context) \
- PyDecType_FromSsizeExact(&PyDec_Type, v, context)
+#define PyDec_FromSsize(st, v, context) \
+ PyDecType_FromSsize((st)->PyDec_Type, v, context)
+#define PyDec_FromSsizeExact(st, v, context) \
+ PyDecType_FromSsizeExact((st)->PyDec_Type, v, context)
-#define PyDec_FromLong(pylong, context) \
- PyDecType_FromLong(&PyDec_Type, pylong, context)
-#define PyDec_FromLongExact(pylong, context) \
- PyDecType_FromLongExact(&PyDec_Type, pylong, context)
+#define PyDec_FromLong(st, pylong, context) \
+ PyDecType_FromLong((st)->PyDec_Type, pylong, context)
+#define PyDec_FromLongExact(st, pylong, context) \
+ PyDecType_FromLongExact((st)->PyDec_Type, pylong, context)
-#define PyDec_FromFloat(pyfloat, context) \
- PyDecType_FromFloat(&PyDec_Type, pyfloat, context)
-#define PyDec_FromFloatExact(pyfloat, context) \
- PyDecType_FromFloatExact(&PyDec_Type, pyfloat, context)
+#define PyDec_FromFloat(st, pyfloat, context) \
+ PyDecType_FromFloat((st)->PyDec_Type, pyfloat, context)
+#define PyDec_FromFloatExact(st, pyfloat, context) \
+ PyDecType_FromFloatExact((st)->PyDec_Type, pyfloat, context)
-#define PyDec_FromSequence(sequence, context) \
- PyDecType_FromSequence(&PyDec_Type, sequence, context)
-#define PyDec_FromSequenceExact(sequence, context) \
- PyDecType_FromSequenceExact(&PyDec_Type, sequence, context)
+#define PyDec_FromSequence(st, sequence, context) \
+ PyDecType_FromSequence((st)->PyDec_Type, sequence, context)
+#define PyDec_FromSequenceExact(st, sequence, context) \
+ PyDecType_FromSequenceExact((st)->PyDec_Type, sequence, context)
/* class method */
static PyObject *
@@ -2670,8 +2735,9 @@ dec_from_float(PyObject *type, PyObject *pyfloat)
PyObject *result;
CURRENT_CONTEXT(context);
- result = PyDecType_FromFloatExact(&PyDec_Type, pyfloat, context);
- if (type != (PyObject *)&PyDec_Type && result != NULL) {
+ decimal_state *state = GLOBAL_STATE();
+ result = PyDecType_FromFloatExact(state->PyDec_Type, pyfloat, context);
+ if (type != (PyObject *)state->PyDec_Type && result != NULL) {
Py_SETREF(result, PyObject_CallFunctionObjArgs(type, result, NULL));
}
@@ -2682,7 +2748,8 @@ dec_from_float(PyObject *type, PyObject *pyfloat)
static PyObject *
ctx_from_float(PyObject *context, PyObject *v)
{
- return PyDec_FromFloat(v, context);
+ decimal_state *state = GLOBAL_STATE();
+ return PyDec_FromFloat(state, v, context);
}
/* Apply the context to the input operand. Return a new PyDecObject. */
@@ -2692,7 +2759,8 @@ dec_apply(PyObject *v, PyObject *context)
PyObject *result;
uint32_t status = 0;
- result = dec_alloc();
+ decimal_state *state = GLOBAL_STATE();
+ result = dec_alloc(state);
if (result == NULL) {
return NULL;
}
@@ -2718,10 +2786,11 @@ dec_apply(PyObject *v, PyObject *context)
static PyObject *
PyDecType_FromObjectExact(PyTypeObject *type, PyObject *v, PyObject *context)
{
+ decimal_state *state = GLOBAL_STATE();
if (v == NULL) {
return PyDecType_FromSsizeExact(type, 0, context);
}
- else if (PyDec_Check(v)) {
+ else if (PyDec_Check(state, v)) {
return PyDecType_FromDecimalExact(type, v, context);
}
else if (PyUnicode_Check(v)) {
@@ -2752,10 +2821,11 @@ PyDecType_FromObjectExact(PyTypeObject *type, PyObject *v, PyObject *context)
static PyObject *
PyDec_FromObject(PyObject *v, PyObject *context)
{
+ decimal_state *state = GLOBAL_STATE();
if (v == NULL) {
- return PyDec_FromSsize(0, context);
+ return PyDec_FromSsize(state, 0, context);
}
- else if (PyDec_Check(v)) {
+ else if (PyDec_Check(state, v)) {
mpd_context_t *ctx = CTX(context);
if (mpd_isnan(MPD(v)) &&
MPD(v)->digits > ctx->prec - ctx->clamp) {
@@ -2764,7 +2834,7 @@ PyDec_FromObject(PyObject *v, PyObject *context)
if (dec_addstatus(context, MPD_Conversion_syntax)) {
return NULL;
}
- result = dec_alloc();
+ result = dec_alloc(state);
if (result == NULL) {
return NULL;
}
@@ -2774,19 +2844,19 @@ PyDec_FromObject(PyObject *v, PyObject *context)
return dec_apply(v, context);
}
else if (PyUnicode_Check(v)) {
- return PyDec_FromUnicode(v, context);
+ return PyDec_FromUnicode(state, v, context);
}
else if (PyLong_Check(v)) {
- return PyDec_FromLong(v, context);
+ return PyDec_FromLong(state, v, context);
}
else if (PyTuple_Check(v) || PyList_Check(v)) {
- return PyDec_FromSequence(v, context);
+ return PyDec_FromSequence(state, v, context);
}
else if (PyFloat_Check(v)) {
if (dec_addstatus(context, MPD_Float_operation)) {
return NULL;
}
- return PyDec_FromFloat(v, context);
+ return PyDec_FromFloat(state, v, context);
}
else {
PyErr_Format(PyExc_TypeError,
@@ -2807,7 +2877,8 @@ dec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
&v, &context)) {
return NULL;
}
- CONTEXT_CHECK_VA(context);
+ decimal_state *state = GLOBAL_STATE();
+ CONTEXT_CHECK_VA(state, context);
return PyDecType_FromObjectExact(type, v, context);
}
@@ -2837,13 +2908,13 @@ ctx_create_decimal(PyObject *context, PyObject *args)
Py_LOCAL_INLINE(int)
convert_op(int type_err, PyObject **conv, PyObject *v, PyObject *context)
{
-
- if (PyDec_Check(v)) {
+ decimal_state *state = GLOBAL_STATE();
+ if (PyDec_Check(state, v)) {
*conv = Py_NewRef(v);
return 1;
}
if (PyLong_Check(v)) {
- *conv = PyDec_FromLongExact(v, context);
+ *conv = PyDec_FromLongExact(state, v, context);
if (*conv == NULL) {
return 0;
}
@@ -2924,8 +2995,6 @@ convert_op(int type_err, PyObject **conv, PyObject *v, PyObject *context)
/* Implicit conversions to Decimal for comparison */
/******************************************************************************/
-/* Convert rationals for comparison */
-static PyObject *Rational = NULL;
static PyObject *
multiply_by_denominator(PyObject *v, PyObject *r, PyObject *context)
{
@@ -2942,7 +3011,8 @@ multiply_by_denominator(PyObject *v, PyObject *r, PyObject *context)
if (tmp == NULL) {
return NULL;
}
- denom = PyDec_FromLongExact(tmp, context);
+ decimal_state *state = GLOBAL_STATE();
+ denom = PyDec_FromLongExact(state, tmp, context);
Py_DECREF(tmp);
if (denom == NULL) {
return NULL;
@@ -2954,7 +3024,7 @@ multiply_by_denominator(PyObject *v, PyObject *r, PyObject *context)
PyErr_NoMemory();
return NULL;
}
- result = dec_alloc();
+ result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(denom);
mpd_del(vv);
@@ -2996,7 +3066,8 @@ numerator_as_decimal(PyObject *r, PyObject *context)
return NULL;
}
- num = PyDec_FromLongExact(tmp, context);
+ decimal_state *state = GLOBAL_STATE();
+ num = PyDec_FromLongExact(state, tmp, context);
Py_DECREF(tmp);
return num;
}
@@ -3014,11 +3085,12 @@ convert_op_cmp(PyObject **vcmp, PyObject **wcmp, PyObject *v, PyObject *w,
*vcmp = v;
- if (PyDec_Check(w)) {
+ decimal_state *state = GLOBAL_STATE();
+ if (PyDec_Check(state, w)) {
*wcmp = Py_NewRef(w);
}
else if (PyLong_Check(w)) {
- *wcmp = PyDec_FromLongExact(w, context);
+ *wcmp = PyDec_FromLongExact(state, w, context);
}
else if (PyFloat_Check(w)) {
if (op != Py_EQ && op != Py_NE &&
@@ -3027,7 +3099,7 @@ convert_op_cmp(PyObject **vcmp, PyObject **wcmp, PyObject *v, PyObject *w,
}
else {
ctx->status |= MPD_Float_operation;
- *wcmp = PyDec_FromFloatExact(w, context);
+ *wcmp = PyDec_FromFloatExact(state, w, context);
}
}
else if (PyComplex_Check(w) && (op == Py_EQ || op == Py_NE)) {
@@ -3042,7 +3114,7 @@ convert_op_cmp(PyObject **vcmp, PyObject **wcmp, PyObject *v, PyObject *w,
}
else {
ctx->status |= MPD_Float_operation;
- *wcmp = PyDec_FromFloatExact(tmp, context);
+ *wcmp = PyDec_FromFloatExact(state, tmp, context);
Py_DECREF(tmp);
}
}
@@ -3051,7 +3123,7 @@ convert_op_cmp(PyObject **vcmp, PyObject **wcmp, PyObject *v, PyObject *w,
}
}
else {
- int is_rational = PyObject_IsInstance(w, Rational);
+ int is_rational = PyObject_IsInstance(w, state->Rational);
if (is_rational < 0) {
*wcmp = NULL;
}
@@ -3556,7 +3628,8 @@ dec_as_integer_ratio(PyObject *self, PyObject *args UNUSED)
CURRENT_CONTEXT(context);
- tmp = dec_alloc();
+ decimal_state *state = GLOBAL_STATE();
+ tmp = dec_alloc(state);
if (tmp == NULL) {
return NULL;
}
@@ -3587,14 +3660,14 @@ dec_as_integer_ratio(PyObject *self, PyObject *args UNUSED)
goto error;
}
- Py_SETREF(exponent, _py_long_power(tmp, exponent, Py_None));
+ Py_SETREF(exponent, state->_py_long_power(tmp, exponent, Py_None));
Py_DECREF(tmp);
if (exponent == NULL) {
goto error;
}
if (exp >= 0) {
- Py_SETREF(numerator, _py_long_multiply(numerator, exponent));
+ Py_SETREF(numerator, state->_py_long_multiply(numerator, exponent));
if (numerator == NULL) {
goto error;
}
@@ -3610,10 +3683,14 @@ dec_as_integer_ratio(PyObject *self, PyObject *args UNUSED)
if (tmp == NULL) {
goto error;
}
- Py_SETREF(numerator, _py_long_floor_divide(numerator, tmp));
- Py_SETREF(denominator, _py_long_floor_divide(denominator, tmp));
+ Py_SETREF(numerator, state->_py_long_floor_divide(numerator, tmp));
+ if (numerator == NULL) {
+ Py_DECREF(tmp);
+ goto error;
+ }
+ Py_SETREF(denominator, state->_py_long_floor_divide(denominator, tmp));
Py_DECREF(tmp);
- if (numerator == NULL || denominator == NULL) {
+ if (denominator == NULL) {
goto error;
}
}
@@ -3642,7 +3719,8 @@ PyDec_ToIntegralValue(PyObject *dec, PyObject *args, PyObject *kwds)
&rounding, &context)) {
return NULL;
}
- CONTEXT_CHECK_VA(context);
+ decimal_state *state = GLOBAL_STATE();
+ CONTEXT_CHECK_VA(state, context);
workctx = *CTX(context);
if (rounding != Py_None) {
@@ -3655,7 +3733,7 @@ PyDec_ToIntegralValue(PyObject *dec, PyObject *args, PyObject *kwds)
}
}
- result = dec_alloc();
+ result = dec_alloc(state);
if (result == NULL) {
return NULL;
}
@@ -3683,7 +3761,8 @@ PyDec_ToIntegralExact(PyObject *dec, PyObject *args, PyObject *kwds)
&rounding, &context)) {
return NULL;
}
- CONTEXT_CHECK_VA(context);
+ decimal_state *state = GLOBAL_STATE();
+ CONTEXT_CHECK_VA(state, context);
workctx = *CTX(context);
if (rounding != Py_None) {
@@ -3696,7 +3775,7 @@ PyDec_ToIntegralExact(PyObject *dec, PyObject *args, PyObject *kwds)
}
}
- result = dec_alloc();
+ result = dec_alloc(state);
if (result == NULL) {
return NULL;
}
@@ -3750,7 +3829,6 @@ PyDec_Round(PyObject *dec, PyObject *args)
uint32_t status = 0;
PyObject *context;
-
CURRENT_CONTEXT(context);
if (!PyArg_ParseTuple(args, "|O", &x)) {
return NULL;
@@ -3771,7 +3849,8 @@ PyDec_Round(PyObject *dec, PyObject *args)
if (y == -1 && PyErr_Occurred()) {
return NULL;
}
- result = dec_alloc();
+ decimal_state *state = GLOBAL_STATE();
+ result = dec_alloc(state);
if (result == NULL) {
return NULL;
}
@@ -3790,7 +3869,6 @@ PyDec_Round(PyObject *dec, PyObject *args)
}
}
-static PyTypeObject *DecimalTuple = NULL;
/* Return the DecimalTuple representation of a PyDecObject. */
static PyObject *
PyDec_AsTuple(PyObject *dec, PyObject *dummy UNUSED)
@@ -3873,7 +3951,8 @@ PyDec_AsTuple(PyObject *dec, PyObject *dummy UNUSED)
}
}
- result = PyObject_CallFunctionObjArgs((PyObject *)DecimalTuple,
+ decimal_state *state = GLOBAL_STATE();
+ result = PyObject_CallFunctionObjArgs((PyObject *)state->DecimalTuple,
sign, coeff, expt, NULL);
out:
@@ -3899,8 +3978,9 @@ nm_##MPDFUNC(PyObject *self) \
PyObject *context; \
uint32_t status = 0; \
\
+ decimal_state *state = GLOBAL_STATE(); \
CURRENT_CONTEXT(context); \
- if ((result = dec_alloc()) == NULL) { \
+ if ((result = dec_alloc(state)) == NULL) { \
return NULL; \
} \
\
@@ -3923,10 +4003,11 @@ nm_##MPDFUNC(PyObject *self, PyObject *other) \
PyObject *context; \
uint32_t status = 0; \
\
+ decimal_state *state = GLOBAL_STATE(); \
CURRENT_CONTEXT(context) ; \
CONVERT_BINOP(&a, &b, self, other, context); \
\
- if ((result = dec_alloc()) == NULL) { \
+ if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
Py_DECREF(b); \
return NULL; \
@@ -3963,7 +4044,8 @@ dec_##MPDFUNC(PyObject *self, PyObject *args, PyObject *kwds) \
&context)) { \
return NULL; \
} \
- CONTEXT_CHECK_VA(context); \
+ decimal_state *state = GLOBAL_STATE(); \
+ CONTEXT_CHECK_VA(state, context); \
\
return MPDFUNC(MPD(self), CTX(context)) ? incr_true() : incr_false(); \
}
@@ -3982,9 +4064,10 @@ dec_##MPDFUNC(PyObject *self, PyObject *args, PyObject *kwds) \
&context)) { \
return NULL; \
} \
- CONTEXT_CHECK_VA(context); \
+ decimal_state *state = GLOBAL_STATE(); \
+ CONTEXT_CHECK_VA(state, context); \
\
- if ((result = dec_alloc()) == NULL) { \
+ if ((result = dec_alloc(state)) == NULL) { \
return NULL; \
} \
\
@@ -4013,10 +4096,11 @@ dec_##MPDFUNC(PyObject *self, PyObject *args, PyObject *kwds) \
&other, &context)) { \
return NULL; \
} \
- CONTEXT_CHECK_VA(context); \
+ decimal_state *state = GLOBAL_STATE(); \
+ CONTEXT_CHECK_VA(state, context); \
CONVERT_BINOP_RAISE(&a, &b, self, other, context); \
\
- if ((result = dec_alloc()) == NULL) { \
+ if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
Py_DECREF(b); \
return NULL; \
@@ -4050,10 +4134,11 @@ dec_##MPDFUNC(PyObject *self, PyObject *args, PyObject *kwds) \
&other, &context)) { \
return NULL; \
} \
- CONTEXT_CHECK_VA(context); \
+ decimal_state *state = GLOBAL_STATE(); \
+ CONTEXT_CHECK_VA(state, context); \
CONVERT_BINOP_RAISE(&a, &b, self, other, context); \
\
- if ((result = dec_alloc()) == NULL) { \
+ if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
Py_DECREF(b); \
return NULL; \
@@ -4082,10 +4167,11 @@ dec_##MPDFUNC(PyObject *self, PyObject *args, PyObject *kwds) \
&other, &third, &context)) { \
return NULL; \
} \
- CONTEXT_CHECK_VA(context); \
+ decimal_state *state = GLOBAL_STATE(); \
+ CONTEXT_CHECK_VA(state, context); \
CONVERT_TERNOP_RAISE(&a, &b, &c, self, other, third, context); \
\
- if ((result = dec_alloc()) == NULL) { \
+ if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
Py_DECREF(b); \
Py_DECREF(c); \
@@ -4147,13 +4233,14 @@ nm_mpd_qdivmod(PyObject *v, PyObject *w)
CURRENT_CONTEXT(context);
CONVERT_BINOP(&a, &b, v, w, context);
- q = dec_alloc();
+ decimal_state *state = GLOBAL_STATE();
+ q = dec_alloc(state);
if (q == NULL) {
Py_DECREF(a);
Py_DECREF(b);
return NULL;
}
- r = dec_alloc();
+ r = dec_alloc(state);
if (r == NULL) {
Py_DECREF(a);
Py_DECREF(b);
@@ -4195,7 +4282,8 @@ nm_mpd_qpow(PyObject *base, PyObject *exp, PyObject *mod)
}
}
- result = dec_alloc();
+ decimal_state *state = GLOBAL_STATE();
+ result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
Py_DECREF(b);
@@ -4296,7 +4384,8 @@ dec_mpd_radix(PyObject *self UNUSED, PyObject *dummy UNUSED)
{
PyObject *result;
- result = dec_alloc();
+ decimal_state *state = GLOBAL_STATE();
+ result = dec_alloc(state);
if (result == NULL) {
return NULL;
}
@@ -4311,7 +4400,8 @@ dec_mpd_qcopy_abs(PyObject *self, PyObject *dummy UNUSED)
PyObject *result;
uint32_t status = 0;
- if ((result = dec_alloc()) == NULL) {
+ decimal_state *state = GLOBAL_STATE();
+ if ((result = dec_alloc(state)) == NULL) {
return NULL;
}
@@ -4331,7 +4421,8 @@ dec_mpd_qcopy_negate(PyObject *self, PyObject *dummy UNUSED)
PyObject *result;
uint32_t status = 0;
- if ((result = dec_alloc()) == NULL) {
+ decimal_state *state = GLOBAL_STATE();
+ if ((result = dec_alloc(state)) == NULL) {
return NULL;
}
@@ -4360,7 +4451,8 @@ dec_mpd_class(PyObject *self, PyObject *args, PyObject *kwds)
&context)) {
return NULL;
}
- CONTEXT_CHECK_VA(context);
+ decimal_state *state = GLOBAL_STATE();
+ CONTEXT_CHECK_VA(state, context);
cp = mpd_class(MPD(self), CTX(context));
return PyUnicode_FromString(cp);
@@ -4379,7 +4471,8 @@ dec_mpd_to_eng(PyObject *self, PyObject *args, PyObject *kwds)
&context)) {
return NULL;
}
- CONTEXT_CHECK_VA(context);
+ decimal_state *state = GLOBAL_STATE();
+ CONTEXT_CHECK_VA(state, context);
size = mpd_to_eng_size(&s, MPD(self), CtxCaps(context));
if (size < 0) {
@@ -4411,10 +4504,11 @@ dec_mpd_qcopy_sign(PyObject *self, PyObject *args, PyObject *kwds)
&other, &context)) {
return NULL;
}
- CONTEXT_CHECK_VA(context);
+ decimal_state *state = GLOBAL_STATE();
+ CONTEXT_CHECK_VA(state, context);
CONVERT_BINOP_RAISE(&a, &b, self, other, context);
- result = dec_alloc();
+ result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
Py_DECREF(b);
@@ -4445,7 +4539,8 @@ dec_mpd_same_quantum(PyObject *self, PyObject *args, PyObject *kwds)
&other, &context)) {
return NULL;
}
- CONTEXT_CHECK_VA(context);
+ decimal_state *state = GLOBAL_STATE();
+ CONTEXT_CHECK_VA(state, context);
CONVERT_BINOP_RAISE(&a, &b, self, other, context);
result = mpd_same_quantum(MPD(a), MPD(b)) ? incr_true() : incr_false();
@@ -4479,7 +4574,8 @@ dec_mpd_qquantize(PyObject *v, PyObject *args, PyObject *kwds)
&w, &rounding, &context)) {
return NULL;
}
- CONTEXT_CHECK_VA(context);
+ decimal_state *state = GLOBAL_STATE();
+ CONTEXT_CHECK_VA(state, context);
workctx = *CTX(context);
if (rounding != Py_None) {
@@ -4494,7 +4590,7 @@ dec_mpd_qquantize(PyObject *v, PyObject *args, PyObject *kwds)
CONVERT_BINOP_RAISE(&a, &b, v, w, context);
- result = dec_alloc();
+ result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
Py_DECREF(b);
@@ -4523,8 +4619,10 @@ dec_richcompare(PyObject *v, PyObject *w, int op)
int a_issnan, b_issnan;
int r;
- assert(PyDec_Check(v));
-
+#ifdef Py_DEBUG
+ decimal_state *state = GLOBAL_STATE();
+ assert(PyDec_Check(state, v));
+#endif
CURRENT_CONTEXT(context);
CONVERT_BINOP_CMP(&a, &b, v, w, op, context);
@@ -4794,7 +4892,8 @@ dec_imag(PyObject *self UNUSED, void *closure UNUSED)
{
PyObject *result;
- result = dec_alloc();
+ decimal_state *state = GLOBAL_STATE();
+ result = dec_alloc(state);
if (result == NULL) {
return NULL;
}
@@ -4811,43 +4910,6 @@ static PyGetSetDef dec_getsets [] =
{NULL}
};
-static PyNumberMethods dec_number_methods =
-{
- (binaryfunc) nm_mpd_qadd,
- (binaryfunc) nm_mpd_qsub,
- (binaryfunc) nm_mpd_qmul,
- (binaryfunc) nm_mpd_qrem,
- (binaryfunc) nm_mpd_qdivmod,
- (ternaryfunc) nm_mpd_qpow,
- (unaryfunc) nm_mpd_qminus,
- (unaryfunc) nm_mpd_qplus,
- (unaryfunc) nm_mpd_qabs,
- (inquiry) nm_nonzero,
- (unaryfunc) 0, /* no bit-complement */
- (binaryfunc) 0, /* no shiftl */
- (binaryfunc) 0, /* no shiftr */
- (binaryfunc) 0, /* no bit-and */
- (binaryfunc) 0, /* no bit-xor */
- (binaryfunc) 0, /* no bit-ior */
- (unaryfunc) nm_dec_as_long,
- 0, /* nb_reserved */
- (unaryfunc) PyDec_AsFloat,
- 0, /* binaryfunc nb_inplace_add; */
- 0, /* binaryfunc nb_inplace_subtract; */
- 0, /* binaryfunc nb_inplace_multiply; */
- 0, /* binaryfunc nb_inplace_remainder; */
- 0, /* ternaryfunc nb_inplace_power; */
- 0, /* binaryfunc nb_inplace_lshift; */
- 0, /* binaryfunc nb_inplace_rshift; */
- 0, /* binaryfunc nb_inplace_and; */
- 0, /* binaryfunc nb_inplace_xor; */
- 0, /* binaryfunc nb_inplace_or; */
- (binaryfunc) nm_mpd_qdivint, /* binaryfunc nb_floor_divide; */
- (binaryfunc) nm_mpd_qdiv, /* binaryfunc nb_true_divide; */
- 0, /* binaryfunc nb_inplace_floor_divide; */
- 0, /* binaryfunc nb_inplace_true_divide; */
-};
-
static PyMethodDef dec_methods [] =
{
/* Unary arithmetic functions, optional context arg */
@@ -4940,48 +5002,44 @@ static PyMethodDef dec_methods [] =
{ NULL, NULL, 1 }
};
-static PyTypeObject PyDec_Type =
-{
- PyVarObject_HEAD_INIT(NULL, 0)
- "decimal.Decimal", /* tp_name */
- sizeof(PyDecObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor) dec_dealloc, /* tp_dealloc */
- 0, /* tp_vectorcall_offset */
- (getattrfunc) 0, /* tp_getattr */
- (setattrfunc) 0, /* tp_setattr */
- 0, /* tp_as_async */
- (reprfunc) dec_repr, /* tp_repr */
- &dec_number_methods, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc) dec_hash, /* tp_hash */
- 0, /* tp_call */
- (reprfunc) dec_str, /* tp_str */
- (getattrofunc) PyObject_GenericGetAttr, /* tp_getattro */
- (setattrofunc) 0, /* tp_setattro */
- (PyBufferProcs *) 0, /* tp_as_buffer */
- (Py_TPFLAGS_DEFAULT|
- Py_TPFLAGS_BASETYPE), /* tp_flags */
- doc_decimal, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- dec_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- dec_methods, /* tp_methods */
- 0, /* tp_members */
- dec_getsets, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- dec_new, /* tp_new */
- PyObject_Del, /* tp_free */
+static PyType_Slot dec_slots[] = {
+ {Py_tp_dealloc, dec_dealloc},
+ {Py_tp_getattro, PyObject_GenericGetAttr},
+ {Py_tp_traverse, dec_traverse},
+ {Py_tp_repr, dec_repr},
+ {Py_tp_hash, dec_hash},
+ {Py_tp_str, dec_str},
+ {Py_tp_doc, (void *)doc_decimal},
+ {Py_tp_richcompare, dec_richcompare},
+ {Py_tp_methods, dec_methods},
+ {Py_tp_getset, dec_getsets},
+ {Py_tp_new, dec_new},
+
+ // Number protocol
+ {Py_nb_add, nm_mpd_qadd},
+ {Py_nb_subtract, nm_mpd_qsub},
+ {Py_nb_multiply, nm_mpd_qmul},
+ {Py_nb_remainder, nm_mpd_qrem},
+ {Py_nb_divmod, nm_mpd_qdivmod},
+ {Py_nb_power, nm_mpd_qpow},
+ {Py_nb_negative, nm_mpd_qminus},
+ {Py_nb_positive, nm_mpd_qplus},
+ {Py_nb_absolute, nm_mpd_qabs},
+ {Py_nb_bool, nm_nonzero},
+ {Py_nb_int, nm_dec_as_long},
+ {Py_nb_float, PyDec_AsFloat},
+ {Py_nb_floor_divide, nm_mpd_qdivint},
+ {Py_nb_true_divide, nm_mpd_qdiv},
+ {0, NULL},
+};
+
+
+static PyType_Spec dec_spec = {
+ .name = "decimal.Decimal",
+ .basicsize = sizeof(PyDecObject),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = dec_slots,
};
@@ -5033,8 +5091,8 @@ ctx_##MPDFUNC(PyObject *context, PyObject *v) \
uint32_t status = 0; \
\
CONVERT_OP_RAISE(&a, v, context); \
- \
- if ((result = dec_alloc()) == NULL) { \
+ decimal_state *state = GLOBAL_STATE(); \
+ if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
return NULL; \
} \
@@ -5064,8 +5122,8 @@ ctx_##MPDFUNC(PyObject *context, PyObject *args) \
} \
\
CONVERT_BINOP_RAISE(&a, &b, v, w, context); \
- \
- if ((result = dec_alloc()) == NULL) { \
+ decimal_state *state = GLOBAL_STATE(); \
+ if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
Py_DECREF(b); \
return NULL; \
@@ -5099,8 +5157,8 @@ ctx_##MPDFUNC(PyObject *context, PyObject *args) \
} \
\
CONVERT_BINOP_RAISE(&a, &b, v, w, context); \
- \
- if ((result = dec_alloc()) == NULL) { \
+ decimal_state *state = GLOBAL_STATE(); \
+ if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
Py_DECREF(b); \
return NULL; \
@@ -5128,8 +5186,8 @@ ctx_##MPDFUNC(PyObject *context, PyObject *args) \
} \
\
CONVERT_TERNOP_RAISE(&a, &b, &c, v, w, x, context); \
- \
- if ((result = dec_alloc()) == NULL) { \
+ decimal_state *state = GLOBAL_STATE(); \
+ if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
Py_DECREF(b); \
Py_DECREF(c); \
@@ -5194,14 +5252,14 @@ ctx_mpd_qdivmod(PyObject *context, PyObject *args)
}
CONVERT_BINOP_RAISE(&a, &b, v, w, context);
-
- q = dec_alloc();
+ decimal_state *state = GLOBAL_STATE();
+ q = dec_alloc(state);
if (q == NULL) {
Py_DECREF(a);
Py_DECREF(b);
return NULL;
}
- r = dec_alloc();
+ r = dec_alloc(state);
if (r == NULL) {
Py_DECREF(a);
Py_DECREF(b);
@@ -5249,7 +5307,8 @@ ctx_mpd_qpow(PyObject *context, PyObject *args, PyObject *kwds)
}
}
- result = dec_alloc();
+ decimal_state *state = GLOBAL_STATE();
+ result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
Py_DECREF(b);
@@ -5300,7 +5359,8 @@ DecCtx_BoolFunc_NO_CTX(mpd_iszero)
static PyObject *
ctx_iscanonical(PyObject *context UNUSED, PyObject *v)
{
- if (!PyDec_Check(v)) {
+ decimal_state *state = GLOBAL_STATE();
+ if (!PyDec_Check(state, v)) {
PyErr_SetString(PyExc_TypeError,
"argument must be a Decimal");
return NULL;
@@ -5325,7 +5385,8 @@ PyDecContext_Apply(PyObject *context, PyObject *v)
static PyObject *
ctx_canonical(PyObject *context UNUSED, PyObject *v)
{
- if (!PyDec_Check(v)) {
+ decimal_state *state = GLOBAL_STATE();
+ if (!PyDec_Check(state, v)) {
PyErr_SetString(PyExc_TypeError,
"argument must be a Decimal");
return NULL;
@@ -5341,8 +5402,8 @@ ctx_mpd_qcopy_abs(PyObject *context, PyObject *v)
uint32_t status = 0;
CONVERT_OP_RAISE(&a, v, context);
-
- result = dec_alloc();
+ decimal_state *state = GLOBAL_STATE();
+ result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
return NULL;
@@ -5374,8 +5435,8 @@ ctx_mpd_qcopy_negate(PyObject *context, PyObject *v)
uint32_t status = 0;
CONVERT_OP_RAISE(&a, v, context);
-
- result = dec_alloc();
+ decimal_state *state = GLOBAL_STATE();
+ result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
return NULL;
@@ -5471,8 +5532,8 @@ ctx_mpd_qcopy_sign(PyObject *context, PyObject *args)
}
CONVERT_BINOP_RAISE(&a, &b, v, w, context);
-
- result = dec_alloc();
+ decimal_state *state = GLOBAL_STATE();
+ result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
Py_DECREF(b);
@@ -5625,47 +5686,27 @@ static PyMethodDef context_methods [] =
{ NULL, NULL, 1 }
};
-static PyTypeObject PyDecContext_Type =
-{
- PyVarObject_HEAD_INIT(NULL, 0)
- "decimal.Context", /* tp_name */
- sizeof(PyDecContextObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor) context_dealloc, /* tp_dealloc */
- 0, /* tp_vectorcall_offset */
- (getattrfunc) 0, /* tp_getattr */
- (setattrfunc) 0, /* tp_setattr */
- 0, /* tp_as_async */
- (reprfunc) context_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc) 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- (getattrofunc) context_getattr, /* tp_getattro */
- (setattrofunc) context_setattr, /* tp_setattro */
- (PyBufferProcs *) 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
- doc_context, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- context_methods, /* tp_methods */
- 0, /* tp_members */
- context_getsets, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- context_init, /* tp_init */
- 0, /* tp_alloc */
- context_new, /* tp_new */
- PyObject_Del, /* tp_free */
+static PyType_Slot context_slots[] = {
+ {Py_tp_dealloc, context_dealloc},
+ {Py_tp_traverse, context_traverse},
+ {Py_tp_clear, context_clear},
+ {Py_tp_repr, context_repr},
+ {Py_tp_getattro, context_getattr},
+ {Py_tp_setattro, context_setattr},
+ {Py_tp_doc, (void *)doc_context},
+ {Py_tp_methods, context_methods},
+ {Py_tp_getset, context_getsets},
+ {Py_tp_init, context_init},
+ {Py_tp_new, context_new},
+ {0, NULL},
+};
+
+static PyType_Spec context_spec = {
+ .name = "decimal.Context",
+ .basicsize = sizeof(PyDecContextObject),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = context_slots,
};
@@ -5790,31 +5831,35 @@ PyInit__decimal(void)
mpd_free = PyMem_Free;
mpd_setminalloc(_Py_DEC_MINALLOC);
+ decimal_state *state = GLOBAL_STATE();
/* Init external C-API functions */
- _py_long_multiply = PyLong_Type.tp_as_number->nb_multiply;
- _py_long_floor_divide = PyLong_Type.tp_as_number->nb_floor_divide;
- _py_long_power = PyLong_Type.tp_as_number->nb_power;
- _py_float_abs = PyFloat_Type.tp_as_number->nb_absolute;
- ASSIGN_PTR(_py_float_as_integer_ratio, cfunc_noargs(&PyFloat_Type,
- "as_integer_ratio"));
- ASSIGN_PTR(_py_long_bit_length, cfunc_noargs(&PyLong_Type, "bit_length"));
+ state->_py_long_multiply = PyLong_Type.tp_as_number->nb_multiply;
+ state->_py_long_floor_divide = PyLong_Type.tp_as_number->nb_floor_divide;
+ state->_py_long_power = PyLong_Type.tp_as_number->nb_power;
+ state->_py_float_abs = PyFloat_Type.tp_as_number->nb_absolute;
+ ASSIGN_PTR(state->_py_float_as_integer_ratio,
+ cfunc_noargs(&PyFloat_Type, "as_integer_ratio"));
+ ASSIGN_PTR(state->_py_long_bit_length,
+ cfunc_noargs(&PyLong_Type, "bit_length"));
/* Init types */
- PyDec_Type.tp_base = &PyBaseObject_Type;
- PyDecContext_Type.tp_base = &PyBaseObject_Type;
- PyDecContextManager_Type.tp_base = &PyBaseObject_Type;
- PyDecSignalDictMixin_Type.tp_base = &PyBaseObject_Type;
+#define CREATE_TYPE(mod, tp, spec) do { \
+ tp = (PyTypeObject *)PyType_FromMetaclass(NULL, mod, spec, NULL); \
+ CHECK_PTR(tp); \
+} while (0)
+
+ CREATE_TYPE(m, state->PyDec_Type, &dec_spec);
+ CREATE_TYPE(m, state->PyDecContext_Type, &context_spec);
+ CREATE_TYPE(m, state->PyDecContextManager_Type, &ctxmanager_spec);
+ CREATE_TYPE(m, state->PyDecSignalDictMixin_Type, &signaldict_spec);
- CHECK_INT(PyType_Ready(&PyDec_Type));
- CHECK_INT(PyType_Ready(&PyDecContext_Type));
- CHECK_INT(PyType_Ready(&PyDecSignalDictMixin_Type));
- CHECK_INT(PyType_Ready(&PyDecContextManager_Type));
+#undef CREATE_TYPE
ASSIGN_PTR(obj, PyUnicode_FromString("decimal"));
- CHECK_INT(PyDict_SetItemString(PyDec_Type.tp_dict, "__module__", obj));
- CHECK_INT(PyDict_SetItemString(PyDecContext_Type.tp_dict,
+ CHECK_INT(PyDict_SetItemString(state->PyDec_Type->tp_dict, "__module__", obj));
+ CHECK_INT(PyDict_SetItemString(state->PyDecContext_Type->tp_dict,
"__module__", obj));
Py_CLEAR(obj);
@@ -5824,22 +5869,22 @@ PyInit__decimal(void)
ASSIGN_PTR(Number, PyObject_GetAttrString(numbers, "Number"));
/* Register Decimal with the Number abstract base class */
ASSIGN_PTR(obj, PyObject_CallMethod(Number, "register", "(O)",
- (PyObject *)&PyDec_Type));
+ (PyObject *)state->PyDec_Type));
Py_CLEAR(obj);
/* Rational is a global variable used for fraction comparisons. */
- ASSIGN_PTR(Rational, PyObject_GetAttrString(numbers, "Rational"));
+ ASSIGN_PTR(state->Rational, PyObject_GetAttrString(numbers, "Rational"));
/* Done with numbers, Number */
Py_CLEAR(numbers);
Py_CLEAR(Number);
/* DecimalTuple */
ASSIGN_PTR(collections, PyImport_ImportModule("collections"));
- ASSIGN_PTR(DecimalTuple, (PyTypeObject *)PyObject_CallMethod(collections,
+ ASSIGN_PTR(state->DecimalTuple, (PyTypeObject *)PyObject_CallMethod(collections,
"namedtuple", "(ss)", "DecimalTuple",
"sign digits exponent"));
ASSIGN_PTR(obj, PyUnicode_FromString("decimal"));
- CHECK_INT(PyDict_SetItemString(DecimalTuple->tp_dict, "__module__", obj));
+ CHECK_INT(PyDict_SetItemString(state->DecimalTuple->tp_dict, "__module__", obj));
Py_CLEAR(obj);
/* MutableMapping */
@@ -5847,10 +5892,10 @@ PyInit__decimal(void)
ASSIGN_PTR(MutableMapping, PyObject_GetAttrString(collections_abc,
"MutableMapping"));
/* Create SignalDict type */
- ASSIGN_PTR(PyDecSignalDict_Type,
+ ASSIGN_PTR(state->PyDecSignalDict_Type,
(PyTypeObject *)PyObject_CallFunction(
(PyObject *)&PyType_Type, "s(OO){}",
- "SignalDict", &PyDecSignalDictMixin_Type,
+ "SignalDict", state->PyDecSignalDictMixin_Type,
MutableMapping));
/* Done with collections, MutableMapping */
@@ -5863,19 +5908,18 @@ PyInit__decimal(void)
ASSIGN_PTR(m, PyModule_Create(&_decimal_module));
/* Add types to the module */
- CHECK_INT(PyModule_AddObject(m, "Decimal", Py_NewRef(&PyDec_Type)));
- CHECK_INT(PyModule_AddObject(m, "Context",
- Py_NewRef(&PyDecContext_Type)));
- CHECK_INT(PyModule_AddObject(m, "DecimalTuple", Py_NewRef(DecimalTuple)));
+ CHECK_INT(PyModule_AddType(m, state->PyDec_Type));
+ CHECK_INT(PyModule_AddType(m, state->PyDecContext_Type));
+ CHECK_INT(PyModule_AddType(m, state->DecimalTuple));
/* Create top level exception */
- ASSIGN_PTR(DecimalException, PyErr_NewException(
+ ASSIGN_PTR(state->DecimalException, PyErr_NewException(
"decimal.DecimalException",
PyExc_ArithmeticError, NULL));
- CHECK_INT(PyModule_AddObject(m, "DecimalException", Py_NewRef(DecimalException)));
+ CHECK_INT(PyModule_AddType(m, (PyTypeObject *)state->DecimalException));
/* Create signal tuple */
- ASSIGN_PTR(SignalTuple, PyTuple_New(SIGNAL_MAP_LEN));
+ ASSIGN_PTR(state->SignalTuple, PyTuple_New(SIGNAL_MAP_LEN));
/* Add exceptions that correspond to IEEE signals */
for (i = SIGNAL_MAP_LEN-1; i >= 0; i--) {
@@ -5885,10 +5929,11 @@ PyInit__decimal(void)
switch (cm->flag) {
case MPD_Float_operation:
- base = PyTuple_Pack(2, DecimalException, PyExc_TypeError);
+ base = PyTuple_Pack(2, state->DecimalException, PyExc_TypeError);
break;
case MPD_Division_by_zero:
- base = PyTuple_Pack(2, DecimalException, PyExc_ZeroDivisionError);
+ base = PyTuple_Pack(2, state->DecimalException,
+ PyExc_ZeroDivisionError);
break;
case MPD_Overflow:
base = PyTuple_Pack(2, signal_map[INEXACT].ex,
@@ -5900,7 +5945,7 @@ PyInit__decimal(void)
signal_map[SUBNORMAL].ex);
break;
default:
- base = PyTuple_Pack(1, DecimalException);
+ base = PyTuple_Pack(1, state->DecimalException);
break;
}
@@ -5915,7 +5960,7 @@ PyInit__decimal(void)
CHECK_INT(PyModule_AddObject(m, cm->name, Py_NewRef(cm->ex)));
/* add to signal tuple */
- PyTuple_SET_ITEM(SignalTuple, i, Py_NewRef(cm->ex));
+ PyTuple_SET_ITEM(state->SignalTuple, i, Py_NewRef(cm->ex));
}
/*
@@ -5946,33 +5991,34 @@ PyInit__decimal(void)
/* Init default context template first */
- ASSIGN_PTR(default_context_template,
- PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL));
+ ASSIGN_PTR(state->default_context_template,
+ PyObject_CallObject((PyObject *)state->PyDecContext_Type, NULL));
CHECK_INT(PyModule_AddObject(m, "DefaultContext",
- Py_NewRef(default_context_template)));
+ Py_NewRef(state->default_context_template)));
#ifndef WITH_DECIMAL_CONTEXTVAR
- ASSIGN_PTR(tls_context_key, PyUnicode_FromString("___DECIMAL_CTX__"));
+ ASSIGN_PTR(state->tls_context_key,
+ PyUnicode_FromString("___DECIMAL_CTX__"));
CHECK_INT(PyModule_AddObject(m, "HAVE_CONTEXTVAR", Py_NewRef(Py_False)));
#else
- ASSIGN_PTR(current_context_var, PyContextVar_New("decimal_context", NULL));
+ ASSIGN_PTR(state->current_context_var, PyContextVar_New("decimal_context", NULL));
CHECK_INT(PyModule_AddObject(m, "HAVE_CONTEXTVAR", Py_NewRef(Py_True)));
#endif
CHECK_INT(PyModule_AddObject(m, "HAVE_THREADS", Py_NewRef(Py_True)));
/* Init basic context template */
- ASSIGN_PTR(basic_context_template,
- PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL));
- init_basic_context(basic_context_template);
+ ASSIGN_PTR(state->basic_context_template,
+ PyObject_CallObject((PyObject *)state->PyDecContext_Type, NULL));
+ init_basic_context(state->basic_context_template);
CHECK_INT(PyModule_AddObject(m, "BasicContext",
- Py_NewRef(basic_context_template)));
+ Py_NewRef(state->basic_context_template)));
/* Init extended context template */
- ASSIGN_PTR(extended_context_template,
- PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL));
- init_extended_context(extended_context_template);
+ ASSIGN_PTR(state->extended_context_template,
+ PyObject_CallObject((PyObject *)state->PyDecContext_Type, NULL));
+ init_extended_context(state->extended_context_template);
CHECK_INT(PyModule_AddObject(m, "ExtendedContext",
- Py_NewRef(extended_context_template)));
+ Py_NewRef(state->extended_context_template)));
/* Init mpd_ssize_t constants */
@@ -5990,8 +6036,8 @@ PyInit__decimal(void)
/* Init string constants */
for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
- ASSIGN_PTR(round_map[i], PyUnicode_InternFromString(mpd_round_string[i]));
- CHECK_INT(PyModule_AddObject(m, mpd_round_string[i], Py_NewRef(round_map[i])));
+ ASSIGN_PTR(state->round_map[i], PyUnicode_InternFromString(mpd_round_string[i]));
+ CHECK_INT(PyModule_AddObject(m, mpd_round_string[i], Py_NewRef(state->round_map[i])));
}
/* Add specification version number */
@@ -6006,20 +6052,20 @@ PyInit__decimal(void)
Py_CLEAR(obj); /* GCOV_NOT_REACHED */
Py_CLEAR(numbers); /* GCOV_NOT_REACHED */
Py_CLEAR(Number); /* GCOV_NOT_REACHED */
- Py_CLEAR(Rational); /* GCOV_NOT_REACHED */
+ Py_CLEAR(state->Rational); /* GCOV_NOT_REACHED */
Py_CLEAR(collections); /* GCOV_NOT_REACHED */
Py_CLEAR(collections_abc); /* GCOV_NOT_REACHED */
Py_CLEAR(MutableMapping); /* GCOV_NOT_REACHED */
- Py_CLEAR(SignalTuple); /* GCOV_NOT_REACHED */
- Py_CLEAR(DecimalTuple); /* GCOV_NOT_REACHED */
- Py_CLEAR(default_context_template); /* GCOV_NOT_REACHED */
+ Py_CLEAR(state->SignalTuple); /* GCOV_NOT_REACHED */
+ Py_CLEAR(state->DecimalTuple); /* GCOV_NOT_REACHED */
+ Py_CLEAR(state->default_context_template); /* GCOV_NOT_REACHED */
#ifndef WITH_DECIMAL_CONTEXTVAR
- Py_CLEAR(tls_context_key); /* GCOV_NOT_REACHED */
+ Py_CLEAR(state->tls_context_key); /* GCOV_NOT_REACHED */
#else
- Py_CLEAR(current_context_var); /* GCOV_NOT_REACHED */
+ Py_CLEAR(state->current_context_var); /* GCOV_NOT_REACHED */
#endif
- Py_CLEAR(basic_context_template); /* GCOV_NOT_REACHED */
- Py_CLEAR(extended_context_template); /* GCOV_NOT_REACHED */
+ Py_CLEAR(state->basic_context_template); /* GCOV_NOT_REACHED */
+ Py_CLEAR(state->extended_context_template); /* GCOV_NOT_REACHED */
Py_CLEAR(m); /* GCOV_NOT_REACHED */
return NULL; /* GCOV_NOT_REACHED */
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 21a6e4e5b20264..a8d68d68420d36 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -11,9 +11,12 @@
*--------------------------------------------------------------------
*/
-#define PY_SSIZE_T_CLEAN
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
#include "Python.h"
+#include "pycore_import.h" // _PyImport_GetModuleAttrString()
#include "structmember.h" // PyMemberDef
#include "expat.h"
#include "pyexpat.h"
@@ -882,7 +885,6 @@ LOCAL(PyObject *)
deepcopy(elementtreestate *st, PyObject *object, PyObject *memo)
{
/* do a deep copy of the given object */
- PyObject *stack[2];
/* Fast paths */
if (object == Py_None || PyUnicode_CheckExact(object)) {
@@ -917,9 +919,8 @@ deepcopy(elementtreestate *st, PyObject *object, PyObject *memo)
return NULL;
}
- stack[0] = object;
- stack[1] = memo;
- return _PyObject_FastCall(st->deepcopy_obj, stack, 2);
+ PyObject *args[2] = {object, memo};
+ return PyObject_Vectorcall(st->deepcopy_obj, args, 2, NULL);
}
@@ -2852,14 +2853,14 @@ treebuilder_handle_pi(TreeBuilderObject* self, PyObject* target, PyObject* text)
{
PyObject* pi;
PyObject* this;
- PyObject* stack[2] = {target, text};
if (treebuilder_flush_data(self) < 0) {
return NULL;
}
if (self->pi_factory) {
- pi = _PyObject_FastCall(self->pi_factory, stack, 2);
+ PyObject* args[2] = {target, text};
+ pi = PyObject_Vectorcall(self->pi_factory, args, 2, NULL);
if (!pi) {
return NULL;
}
@@ -3372,7 +3373,6 @@ expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix_in,
PyObject* res = NULL;
PyObject* uri;
PyObject* prefix;
- PyObject* stack[2];
if (PyErr_Occurred())
return;
@@ -3411,9 +3411,8 @@ expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix_in,
return;
}
- stack[0] = prefix;
- stack[1] = uri;
- res = _PyObject_FastCall(self->handle_start_ns, stack, 2);
+ PyObject* args[2] = {prefix, uri};
+ res = PyObject_Vectorcall(self->handle_start_ns, args, 2, NULL);
Py_DECREF(uri);
Py_DECREF(prefix);
}
@@ -3531,7 +3530,7 @@ expat_start_doctype_handler(XMLParserObject *self,
sysid_obj, NULL);
Py_XDECREF(res);
}
- else if (_PyObject_LookupAttr((PyObject *)self, st->str_doctype, &res) > 0) {
+ else if (PyObject_GetOptionalAttr((PyObject *)self, st->str_doctype, &res) > 0) {
(void)PyErr_WarnEx(PyExc_RuntimeWarning,
"The doctype() method of XMLParser is ignored. "
"Define doctype() method on the TreeBuilder target.",
@@ -3551,7 +3550,6 @@ expat_pi_handler(XMLParserObject* self, const XML_Char* target_in,
PyObject* pi_target;
PyObject* data;
PyObject* res;
- PyObject* stack[2];
if (PyErr_Occurred())
return;
@@ -3581,9 +3579,8 @@ expat_pi_handler(XMLParserObject* self, const XML_Char* target_in,
if (!data)
goto error;
- stack[0] = pi_target;
- stack[1] = data;
- res = _PyObject_FastCall(self->handle_pi, stack, 2);
+ PyObject* args[2] = {pi_target, data};
+ res = PyObject_Vectorcall(self->handle_pi, args, 2, NULL);
Py_XDECREF(res);
Py_DECREF(data);
Py_DECREF(pi_target);
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index a8001d71223fdc..c987485e66a48a 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -276,7 +276,7 @@ partial_vectorcall(partialobject *pto, PyObject *const *args,
static void
partial_setvectorcall(partialobject *pto)
{
- if (_PyVectorcall_Function(pto->fn) == NULL) {
+ if (PyVectorcall_Function(pto->fn) == NULL) {
/* Don't use vectorcall if the underlying function doesn't support it */
pto->vectorcall = NULL;
}
@@ -594,21 +594,15 @@ keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
static PyObject *
keyobject_richcompare(PyObject *ko, PyObject *other, int op)
{
- PyObject *res;
- PyObject *x;
- PyObject *y;
- PyObject *compare;
- PyObject *answer;
- PyObject* stack[2];
-
if (!Py_IS_TYPE(other, Py_TYPE(ko))) {
PyErr_Format(PyExc_TypeError, "other argument must be K instance");
return NULL;
}
- compare = ((keyobject *) ko)->cmp;
+
+ PyObject *compare = ((keyobject *) ko)->cmp;
assert(compare != NULL);
- x = ((keyobject *) ko)->object;
- y = ((keyobject *) other)->object;
+ PyObject *x = ((keyobject *) ko)->object;
+ PyObject *y = ((keyobject *) other)->object;
if (!x || !y){
PyErr_Format(PyExc_AttributeError, "object");
return NULL;
@@ -617,14 +611,13 @@ keyobject_richcompare(PyObject *ko, PyObject *other, int op)
/* Call the user's comparison function and translate the 3-way
* result into true or false (or error).
*/
- stack[0] = x;
- stack[1] = y;
- res = _PyObject_FastCall(compare, stack, 2);
+ PyObject* args[2] = {x, y};
+ PyObject *res = PyObject_Vectorcall(compare, args, 2, NULL);
if (res == NULL) {
return NULL;
}
- answer = PyObject_RichCompare(res, _PyLong_GetZero(), op);
+ PyObject *answer = PyObject_RichCompare(res, _PyLong_GetZero(), op);
Py_DECREF(res);
return answer;
}
diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c
index 4dbb5741b2ede8..bedbdc081425c2 100644
--- a/Modules/_gdbmmodule.c
+++ b/Modules/_gdbmmodule.c
@@ -3,7 +3,6 @@
/* Author: Anthony Baxter, after dbmmodule.c */
/* Doc strings: Mitch Chapman */
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "gdbm.h"
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index c018a76842be8c..011cb765ed82e6 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -22,8 +22,6 @@
# define Py_BUILD_CORE_MODULE 1
#endif
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "pycore_hashtable.h"
#include "hashlib.h"
@@ -383,14 +381,15 @@ py_digest_by_digestmod(PyObject *module, PyObject *digestmod, enum Py_hash_type
} else {
_hashlibstate *state = get_hashlib_state(module);
// borrowed ref
- name_obj = PyDict_GetItem(state->constructs, digestmod);
+ name_obj = PyDict_GetItemWithError(state->constructs, digestmod);
}
if (name_obj == NULL) {
- _hashlibstate *state = get_hashlib_state(module);
- PyErr_Clear();
- PyErr_Format(
- state->unsupported_digestmod_error,
- "Unsupported digestmod %R", digestmod);
+ if (!PyErr_Occurred()) {
+ _hashlibstate *state = get_hashlib_state(module);
+ PyErr_Format(
+ state->unsupported_digestmod_error,
+ "Unsupported digestmod %R", digestmod);
+ }
return NULL;
}
diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c
index 7b06c1bee5a832..1a7920eebe0b61 100644
--- a/Modules/_io/_iomodule.c
+++ b/Modules/_io/_iomodule.c
@@ -7,7 +7,6 @@
Mostly written by Amaury Forgeot d'Arc
*/
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "_iomodule.h"
#include "pycore_pystate.h" // _PyInterpreterState_GET()
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index f30d54a5e11b0a..bfc3d2558c9e36 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -7,10 +7,11 @@
Written by Amaury Forgeot d'Arc and Antoine Pitrou
*/
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_object.h"
+#include "pycore_pyerrors.h" // _Py_FatalErrorFormat()
+#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
#include "structmember.h" // PyMemberDef
#include "_iomodule.h"
@@ -293,7 +294,7 @@ _enter_buffered_busy(buffered *self)
"reentrant call inside %R", self);
return 0;
}
- PyInterpreterState *interp = PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
relax_locking = _Py_IsInterpreterFinalizing(interp);
Py_BEGIN_ALLOW_THREADS
if (!relax_locking)
@@ -1462,7 +1463,7 @@ buffered_repr(buffered *self)
{
PyObject *nameobj, *res;
- if (_PyObject_LookupAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) {
+ if (PyObject_GetOptionalAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) {
if (!PyErr_ExceptionMatches(PyExc_ValueError)) {
return NULL;
}
@@ -1629,7 +1630,7 @@ _bufferedreader_read_all(buffered *self)
}
_bufferedreader_reset_buf(self);
- if (_PyObject_LookupAttr(self->raw, &_Py_ID(readall), &readall) < 0) {
+ if (PyObject_GetOptionalAttr(self->raw, &_Py_ID(readall), &readall) < 0) {
goto cleanup;
}
if (readall) {
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
index 005c9ffe56f71a..39709fd2931315 100644
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -1,6 +1,5 @@
/* Author: Daniel Stutzbach */
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
@@ -1100,7 +1099,7 @@ fileio_repr(fileio *self)
if (self->fd < 0)
return PyUnicode_FromFormat("<_io.FileIO [closed]>");
- if (_PyObject_LookupAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) {
+ if (PyObject_GetOptionalAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) {
return NULL;
}
if (nameobj == NULL) {
diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c
index f98e75ce2d1ed3..e2e8ef46adf901 100644
--- a/Modules/_io/iobase.c
+++ b/Modules/_io/iobase.c
@@ -8,10 +8,10 @@
*/
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
+#include "pycore_call.h" // _PyObject_CallMethod()
#include "pycore_long.h" // _PyLong_GetOne()
-#include "pycore_object.h"
+#include "pycore_object.h" // _PyType_HasFeature()
#include // offsetof()
#include "_iomodule.h"
@@ -148,7 +148,7 @@ iobase_is_closed(PyObject *self)
int ret;
/* This gets the derived attribute, which is *not* __IOBase_closed
in most cases! */
- ret = _PyObject_LookupAttr(self, &_Py_ID(__IOBase_closed), &res);
+ ret = PyObject_GetOptionalAttr(self, &_Py_ID(__IOBase_closed), &res);
Py_XDECREF(res);
return ret;
}
@@ -196,7 +196,7 @@ iobase_check_closed(PyObject *self)
int closed;
/* This gets the derived attribute, which is *not* __IOBase_closed
in most cases! */
- closed = _PyObject_LookupAttr(self, &_Py_ID(closed), &res);
+ closed = PyObject_GetOptionalAttr(self, &_Py_ID(closed), &res);
if (closed > 0) {
closed = PyObject_IsTrue(res);
Py_DECREF(res);
@@ -303,7 +303,7 @@ iobase_finalize(PyObject *self)
/* If `closed` doesn't exist or can't be evaluated as bool, then the
object is probably in an unusable state, so ignore. */
- if (_PyObject_LookupAttr(self, &_Py_ID(closed), &res) <= 0) {
+ if (PyObject_GetOptionalAttr(self, &_Py_ID(closed), &res) <= 0) {
PyErr_Clear();
closed = -1;
}
@@ -571,7 +571,7 @@ _io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit)
PyObject *peek, *buffer, *result;
Py_ssize_t old_size = -1;
- if (_PyObject_LookupAttr(self, &_Py_ID(peek), &peek) < 0) {
+ if (PyObject_GetOptionalAttr(self, &_Py_ID(peek), &peek) < 0) {
return NULL;
}
diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c
index d4028451754cef..1960002d405edf 100644
--- a/Modules/_io/stringio.c
+++ b/Modules/_io/stringio.c
@@ -1,4 +1,3 @@
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include // offsetof()
#include "pycore_object.h"
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 0ea7458df559bb..a5cf9fc397f5fe 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -6,12 +6,13 @@
Written by Amaury Forgeot d'Arc and Antoine Pitrou
*/
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
+#include "pycore_call.h" // _PyObject_CallMethod()
+#include "pycore_codecs.h" // _PyCodecInfo_GetIncrementalDecoder()
#include "pycore_interp.h" // PyInterpreterState.fs_codec
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_fileutils.h" // _Py_GetLocaleEncoding()
-#include "pycore_object.h"
+#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "structmember.h" // PyMemberDef
#include "_iomodule.h"
@@ -945,7 +946,7 @@ _textiowrapper_set_encoder(textio *self, PyObject *codec_info,
return -1;
/* Get the normalized named of the codec */
- if (_PyObject_LookupAttr(codec_info, &_Py_ID(name), &res) < 0) {
+ if (PyObject_GetOptionalAttr(codec_info, &_Py_ID(name), &res) < 0) {
return -1;
}
if (res != NULL && PyUnicode_Check(res)) {
@@ -1201,7 +1202,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
Py_IS_TYPE(buffer, state->PyBufferedWriter_Type) ||
Py_IS_TYPE(buffer, state->PyBufferedRandom_Type))
{
- if (_PyObject_LookupAttr(buffer, &_Py_ID(raw), &raw) < 0)
+ if (PyObject_GetOptionalAttr(buffer, &_Py_ID(raw), &raw) < 0)
goto error;
/* Cache the raw FileIO object to speed up 'closed' checks */
if (raw != NULL) {
@@ -1221,7 +1222,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
goto error;
self->seekable = self->telling = r;
- r = _PyObject_LookupAttr(buffer, &_Py_ID(read1), &res);
+ r = PyObject_GetOptionalAttr(buffer, &_Py_ID(read1), &res);
if (r < 0) {
goto error;
}
@@ -2896,7 +2897,7 @@ textiowrapper_repr(textio *self)
}
goto error;
}
- if (_PyObject_LookupAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) {
+ if (PyObject_GetOptionalAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) {
if (!PyErr_ExceptionMatches(PyExc_ValueError)) {
goto error;
}
@@ -2912,7 +2913,7 @@ textiowrapper_repr(textio *self)
if (res == NULL)
goto error;
}
- if (_PyObject_LookupAttr((PyObject *) self, &_Py_ID(mode), &modeobj) < 0) {
+ if (PyObject_GetOptionalAttr((PyObject *) self, &_Py_ID(mode), &modeobj) < 0) {
goto error;
}
if (modeobj != NULL) {
@@ -3129,7 +3130,7 @@ textiowrapper_newlines_get(textio *self, void *context)
PyObject *res;
CHECK_ATTACHED(self);
if (self->decoder == NULL ||
- _PyObject_LookupAttr(self->decoder, &_Py_ID(newlines), &res) == 0)
+ PyObject_GetOptionalAttr(self->decoder, &_Py_ID(newlines), &res) == 0)
{
Py_RETURN_NONE;
}
diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c
index 15f3053957da61..452b12c138fa8b 100644
--- a/Modules/_io/winconsoleio.c
+++ b/Modules/_io/winconsoleio.c
@@ -6,7 +6,6 @@
Written by Steve Dower
*/
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c
index 1ada7305117bb7..970530facd01b0 100644
--- a/Modules/_localemodule.c
+++ b/Modules/_localemodule.c
@@ -9,7 +9,6 @@ This software comes with no warranty. Use at your own risk.
******************************************************************/
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_fileutils.h"
diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c
index 1c84f66ee6f579..257de4387c0ab9 100644
--- a/Modules/_lsprof.c
+++ b/Modules/_lsprof.c
@@ -678,6 +678,7 @@ static const struct {
} callback_table[] = {
{PY_MONITORING_EVENT_PY_START, "_pystart_callback"},
{PY_MONITORING_EVENT_PY_RESUME, "_pystart_callback"},
+ {PY_MONITORING_EVENT_PY_THROW, "_pystart_callback"},
{PY_MONITORING_EVENT_PY_RETURN, "_pyreturn_callback"},
{PY_MONITORING_EVENT_PY_YIELD, "_pyreturn_callback"},
{PY_MONITORING_EVENT_PY_UNWIND, "_pyreturn_callback"},
diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c
index e34fbad230d51a..02a32ddccb3ed7 100644
--- a/Modules/_lzmamodule.c
+++ b/Modules/_lzmamodule.c
@@ -5,8 +5,6 @@
*/
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "structmember.h" // PyMemberDef
@@ -242,15 +240,10 @@ parse_filter_spec_lzma(_lzma_state *state, PyObject *spec)
/* First, fill in default values for all the options using a preset.
Then, override the defaults with any values given by the caller. */
- preset_obj = PyMapping_GetItemString(spec, "preset");
- if (preset_obj == NULL) {
- if (PyErr_ExceptionMatches(PyExc_KeyError)) {
- PyErr_Clear();
- }
- else {
- return NULL;
- }
- } else {
+ if (PyMapping_GetOptionalItemString(spec, "preset", &preset_obj) < 0) {
+ return NULL;
+ }
+ if (preset_obj != NULL) {
int ok = uint32_converter(preset_obj, &preset);
Py_DECREF(preset_obj);
if (!ok) {
@@ -347,11 +340,12 @@ lzma_filter_converter(_lzma_state *state, PyObject *spec, void *ptr)
"Filter specifier must be a dict or dict-like object");
return 0;
}
- id_obj = PyMapping_GetItemString(spec, "id");
+ if (PyMapping_GetOptionalItemString(spec, "id", &id_obj) < 0) {
+ return 0;
+ }
if (id_obj == NULL) {
- if (PyErr_ExceptionMatches(PyExc_KeyError))
- PyErr_SetString(PyExc_ValueError,
- "Filter specifier must have an \"id\" entry");
+ PyErr_SetString(PyExc_ValueError,
+ "Filter specifier must have an \"id\" entry");
return 0;
}
f->id = PyLong_AsUnsignedLongLong(id_obj);
diff --git a/Modules/_multiprocessing/multiprocessing.h b/Modules/_multiprocessing/multiprocessing.h
index dfc2a8e0799a60..47257fd5d9fb26 100644
--- a/Modules/_multiprocessing/multiprocessing.h
+++ b/Modules/_multiprocessing/multiprocessing.h
@@ -1,8 +1,6 @@
#ifndef MULTIPROCESSING_H
#define MULTIPROCESSING_H
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "structmember.h"
#include "pythread.h"
diff --git a/Modules/_multiprocessing/posixshmem.c b/Modules/_multiprocessing/posixshmem.c
index 88c93fe313785c..debef3267f77d1 100644
--- a/Modules/_multiprocessing/posixshmem.c
+++ b/Modules/_multiprocessing/posixshmem.c
@@ -2,8 +2,6 @@
posixshmem - A Python extension that provides shm_open() and shm_unlink()
*/
-#define PY_SSIZE_T_CLEAN
-
#include
// for shm_open() and shm_unlink()
diff --git a/Modules/_opcode.c b/Modules/_opcode.c
index b70d426fa29bc0..b3b9873d21a5be 100644
--- a/Modules/_opcode.c
+++ b/Modules/_opcode.c
@@ -1,4 +1,5 @@
#include "Python.h"
+#include "compile.h"
#include "opcode.h"
#include "internal/pycore_code.h"
@@ -27,25 +28,16 @@ _opcode_stack_effect_impl(PyObject *module, int opcode, PyObject *oparg,
PyObject *jump)
/*[clinic end generated code: output=64a18f2ead954dbb input=461c9d4a44851898]*/
{
- int effect;
int oparg_int = 0;
int jump_int;
- if (HAS_ARG(opcode)) {
- if (oparg == Py_None) {
- PyErr_SetString(PyExc_ValueError,
- "stack_effect: opcode requires oparg but oparg was not specified");
- return -1;
- }
+
+ if (oparg != Py_None) {
oparg_int = (int)PyLong_AsLong(oparg);
if ((oparg_int == -1) && PyErr_Occurred()) {
return -1;
}
}
- else if (oparg != Py_None) {
- PyErr_SetString(PyExc_ValueError,
- "stack_effect: opcode does not permit oparg but oparg was specified");
- return -1;
- }
+
if (jump == Py_None) {
jump_int = -1;
}
@@ -60,17 +52,101 @@ _opcode_stack_effect_impl(PyObject *module, int opcode, PyObject *oparg,
"stack_effect: jump must be False, True or None");
return -1;
}
- effect = PyCompile_OpcodeStackEffectWithJump(opcode, oparg_int, jump_int);
+ int effect = PyCompile_OpcodeStackEffectWithJump(opcode, oparg_int, jump_int);
if (effect == PY_INVALID_STACK_EFFECT) {
- PyErr_SetString(PyExc_ValueError,
- "invalid opcode or oparg");
- return -1;
+ PyErr_SetString(PyExc_ValueError, "invalid opcode or oparg");
+ return -1;
}
return effect;
}
/*[clinic input]
+_opcode.is_valid -> bool
+
+ opcode: int
+
+Return True if opcode is valid, False otherwise.
+[clinic start generated code]*/
+
+static int
+_opcode_is_valid_impl(PyObject *module, int opcode)
+/*[clinic end generated code: output=b0d918ea1d073f65 input=fe23e0aa194ddae0]*/
+{
+ return PyUnstable_OpcodeIsValid(opcode);
+}
+
+/*[clinic input]
+
+_opcode.has_arg -> bool
+
+ opcode: int
+
+Return True if the opcode uses its oparg, False otherwise.
+[clinic start generated code]*/
+
+static int
+_opcode_has_arg_impl(PyObject *module, int opcode)
+/*[clinic end generated code: output=7a062d3b2dcc0815 input=93d878ba6361db5f]*/
+{
+ return PyUnstable_OpcodeIsValid(opcode) &&
+ PyUnstable_OpcodeHasArg(opcode);
+}
+
+/*[clinic input]
+
+_opcode.has_const -> bool
+
+ opcode: int
+
+Return True if the opcode accesses a constant, False otherwise.
+[clinic start generated code]*/
+
+static int
+_opcode_has_const_impl(PyObject *module, int opcode)
+/*[clinic end generated code: output=c646d5027c634120 input=a6999e4cf13f9410]*/
+{
+ return PyUnstable_OpcodeIsValid(opcode) &&
+ PyUnstable_OpcodeHasConst(opcode);
+}
+
+/*[clinic input]
+
+_opcode.has_name -> bool
+
+ opcode: int
+
+Return True if the opcode accesses an attribute by name, False otherwise.
+[clinic start generated code]*/
+
+static int
+_opcode_has_name_impl(PyObject *module, int opcode)
+/*[clinic end generated code: output=b49a83555c2fa517 input=448aa5e4bcc947ba]*/
+{
+ return PyUnstable_OpcodeIsValid(opcode) &&
+ PyUnstable_OpcodeHasName(opcode);
+}
+
+/*[clinic input]
+
+_opcode.has_jump -> bool
+
+ opcode: int
+
+Return True if the opcode has a jump target, False otherwise.
+[clinic start generated code]*/
+
+static int
+_opcode_has_jump_impl(PyObject *module, int opcode)
+/*[clinic end generated code: output=e9c583c669f1c46a input=35f711274357a0c3]*/
+{
+ return PyUnstable_OpcodeIsValid(opcode) &&
+ PyUnstable_OpcodeHasJump(opcode);
+
+}
+
+/*[clinic input]
+
_opcode.get_specialization_stats
Return the specialization stats
@@ -90,6 +166,11 @@ _opcode_get_specialization_stats_impl(PyObject *module)
static PyMethodDef
opcode_functions[] = {
_OPCODE_STACK_EFFECT_METHODDEF
+ _OPCODE_IS_VALID_METHODDEF
+ _OPCODE_HAS_ARG_METHODDEF
+ _OPCODE_HAS_CONST_METHODDEF
+ _OPCODE_HAS_NAME_METHODDEF
+ _OPCODE_HAS_JUMP_METHODDEF
_OPCODE_GET_SPECIALIZATION_STATS_METHODDEF
{NULL, NULL, 0, NULL}
};
diff --git a/Modules/_operator.c b/Modules/_operator.c
index 153e9e9e2f92c4..108f45fb6dad93 100644
--- a/Modules/_operator.c
+++ b/Modules/_operator.c
@@ -1,7 +1,9 @@
#include "Python.h"
+#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_moduleobject.h" // _PyModule_GetState()
-#include "structmember.h" // PyMemberDef
#include "pycore_runtime.h" // _Py_ID()
+
+#include "structmember.h" // PyMemberDef
#include "clinic/_operator.c.h"
typedef struct {
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index e6eb9c741e1adc..ea44b494cdd7cd 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -9,10 +9,11 @@
#endif
#include "Python.h"
+#include "pycore_bytesobject.h" // _PyBytesWriter
#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
#include "pycore_moduleobject.h" // _PyModule_GetState()
-#include "pycore_runtime.h" // _Py_ID()
#include "pycore_pystate.h" // _PyThreadState_GET()
+#include "pycore_runtime.h" // _Py_ID()
#include "structmember.h" // PyMemberDef
#include // strtol()
@@ -405,7 +406,7 @@ init_method_ref(PyObject *self, PyObject *name,
/* *method_func and *method_self should be consistent. All refcount decrements
should be occurred after setting *method_self and *method_func. */
- ret = _PyObject_LookupAttr(self, name, &func);
+ ret = PyObject_GetOptionalAttr(self, name, &func);
if (func == NULL) {
*method_self = NULL;
Py_CLEAR(*method_func);
@@ -1145,42 +1146,49 @@ _Pickler_Write(PicklerObject *self, const char *s, Py_ssize_t data_len)
static PicklerObject *
_Pickler_New(PickleState *st)
{
- PicklerObject *self;
-
- self = PyObject_GC_New(PicklerObject, st->Pickler_Type);
- if (self == NULL)
+ PyMemoTable *memo = PyMemoTable_New();
+ if (memo == NULL) {
return NULL;
+ }
+
+ const Py_ssize_t max_output_len = WRITE_BUF_SIZE;
+ PyObject *output_buffer = PyBytes_FromStringAndSize(NULL, max_output_len);
+ if (output_buffer == NULL) {
+ goto error;
+ }
+
+ PicklerObject *self = PyObject_GC_New(PicklerObject, st->Pickler_Type);
+ if (self == NULL) {
+ goto error;
+ }
+ self->memo = memo;
self->pers_func = NULL;
+ self->pers_func_self = NULL;
self->dispatch_table = NULL;
- self->buffer_callback = NULL;
+ self->reducer_override = NULL;
self->write = NULL;
+ self->output_buffer = output_buffer;
+ self->output_len = 0;
+ self->max_output_len = max_output_len;
self->proto = 0;
self->bin = 0;
self->framing = 0;
self->frame_start = -1;
+ self->buf_size = 0;
self->fast = 0;
self->fast_nesting = 0;
self->fix_imports = 0;
self->fast_memo = NULL;
- self->max_output_len = WRITE_BUF_SIZE;
- self->output_len = 0;
- self->reducer_override = NULL;
-
- self->memo = PyMemoTable_New();
- if (self->memo == NULL) {
- Py_DECREF(self);
- return NULL;
- }
- self->output_buffer = PyBytes_FromStringAndSize(NULL,
- self->max_output_len);
- if (self->output_buffer == NULL) {
- Py_DECREF(self);
- return NULL;
- }
+ self->buffer_callback = NULL;
PyObject_GC_Track(self);
return self;
+
+error:
+ PyMem_Free(memo);
+ Py_XDECREF(output_buffer);
+ return NULL;
}
static int
@@ -1216,7 +1224,7 @@ static int
_Pickler_SetOutputStream(PicklerObject *self, PyObject *file)
{
assert(file != NULL);
- if (_PyObject_LookupAttr(file, &_Py_ID(write), &self->write) < 0) {
+ if (PyObject_GetOptionalAttr(file, &_Py_ID(write), &self->write) < 0) {
return -1;
}
if (self->write == NULL) {
@@ -1628,14 +1636,31 @@ _Unpickler_MemoCleanup(UnpicklerObject *self)
static UnpicklerObject *
_Unpickler_New(PyObject *module)
{
- UnpicklerObject *self;
+ const int MEMO_SIZE = 32;
+ PyObject **memo = _Unpickler_NewMemo(MEMO_SIZE);
+ if (memo == NULL) {
+ return NULL;
+ }
+
PickleState *st = _Pickle_GetState(module);
+ PyObject *stack = Pdata_New(st);
+ if (stack == NULL) {
+ goto error;
+ }
- self = PyObject_GC_New(UnpicklerObject, st->Unpickler_Type);
- if (self == NULL)
- return NULL;
+ UnpicklerObject *self = PyObject_GC_New(UnpicklerObject,
+ st->Unpickler_Type);
+ if (self == NULL) {
+ goto error;
+ }
+ self->stack = (Pdata *)stack;
+ self->memo = memo;
+ self->memo_size = MEMO_SIZE;
+ self->memo_len = 0;
self->pers_func = NULL;
+ self->pers_func_self = NULL;
+ memset(&self->buffer, 0, sizeof(Py_buffer));
self->input_buffer = NULL;
self->input_line = NULL;
self->input_len = 0;
@@ -1653,22 +1678,14 @@ _Unpickler_New(PyObject *module)
self->marks_size = 0;
self->proto = 0;
self->fix_imports = 0;
- memset(&self->buffer, 0, sizeof(Py_buffer));
- self->memo_size = 32;
- self->memo_len = 0;
- self->memo = _Unpickler_NewMemo(self->memo_size);
- if (self->memo == NULL) {
- Py_DECREF(self);
- return NULL;
- }
- self->stack = (Pdata *)Pdata_New(st);
- if (self->stack == NULL) {
- Py_DECREF(self);
- return NULL;
- }
PyObject_GC_Track(self);
return self;
+
+error:
+ PyMem_Free(memo);
+ Py_XDECREF(stack);
+ return NULL;
}
/* Returns -1 (with an exception set) on failure, 0 on success. This may
@@ -1677,26 +1694,31 @@ static int
_Unpickler_SetInputStream(UnpicklerObject *self, PyObject *file)
{
/* Optional file methods */
- if (_PyObject_LookupAttr(file, &_Py_ID(peek), &self->peek) < 0) {
- return -1;
+ if (PyObject_GetOptionalAttr(file, &_Py_ID(peek), &self->peek) < 0) {
+ goto error;
}
- if (_PyObject_LookupAttr(file, &_Py_ID(readinto), &self->readinto) < 0) {
- return -1;
+ if (PyObject_GetOptionalAttr(file, &_Py_ID(readinto), &self->readinto) < 0) {
+ goto error;
+ }
+ if (PyObject_GetOptionalAttr(file, &_Py_ID(read), &self->read) < 0) {
+ goto error;
+ }
+ if (PyObject_GetOptionalAttr(file, &_Py_ID(readline), &self->readline) < 0) {
+ goto error;
}
- (void)_PyObject_LookupAttr(file, &_Py_ID(read), &self->read);
- (void)_PyObject_LookupAttr(file, &_Py_ID(readline), &self->readline);
if (!self->readline || !self->read) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError,
- "file must have 'read' and 'readline' attributes");
- }
- Py_CLEAR(self->read);
- Py_CLEAR(self->readinto);
- Py_CLEAR(self->readline);
- Py_CLEAR(self->peek);
- return -1;
+ PyErr_SetString(PyExc_TypeError,
+ "file must have 'read' and 'readline' attributes");
+ goto error;
}
return 0;
+
+error:
+ Py_CLEAR(self->read);
+ Py_CLEAR(self->readinto);
+ Py_CLEAR(self->readline);
+ Py_CLEAR(self->peek);
+ return -1;
}
/* Returns -1 (with an exception set) on failure, 0 on success. This may
@@ -1878,7 +1900,7 @@ get_deep_attribute(PyObject *obj, PyObject *names, PyObject **pparent)
for (i = 0; i < n; i++) {
PyObject *name = PyList_GET_ITEM(names, i);
Py_XSETREF(parent, obj);
- (void)_PyObject_LookupAttr(parent, name, &obj);
+ (void)PyObject_GetOptionalAttr(parent, name, &obj);
if (obj == NULL) {
Py_DECREF(parent);
return NULL;
@@ -1905,7 +1927,7 @@ getattribute(PyObject *obj, PyObject *name, int allow_qualname)
Py_DECREF(dotted_path);
}
else {
- (void)_PyObject_LookupAttr(obj, name, &attr);
+ (void)PyObject_GetOptionalAttr(obj, name, &attr);
}
if (attr == NULL && !PyErr_Occurred()) {
PyErr_Format(PyExc_AttributeError,
@@ -1946,7 +1968,7 @@ whichmodule(PyObject *global, PyObject *dotted_path)
Py_ssize_t i;
PyObject *modules;
- if (_PyObject_LookupAttr(global, &_Py_ID(__module__), &module_name) < 0) {
+ if (PyObject_GetOptionalAttr(global, &_Py_ID(__module__), &module_name) < 0) {
return NULL;
}
if (module_name) {
@@ -3634,7 +3656,7 @@ save_global(PickleState *st, PicklerObject *self, PyObject *obj,
global_name = Py_NewRef(name);
}
else {
- if (_PyObject_LookupAttr(obj, &_Py_ID(__qualname__), &global_name) < 0)
+ if (PyObject_GetOptionalAttr(obj, &_Py_ID(__qualname__), &global_name) < 0)
goto error;
if (global_name == NULL) {
global_name = PyObject_GetAttr(obj, &_Py_ID(__name__));
@@ -3957,7 +3979,7 @@ get_class(PyObject *obj)
{
PyObject *cls;
- if (_PyObject_LookupAttr(obj, &_Py_ID(__class__), &cls) == 0) {
+ if (PyObject_GetOptionalAttr(obj, &_Py_ID(__class__), &cls) == 0) {
cls = Py_NewRef(Py_TYPE(obj));
}
return cls;
@@ -4040,7 +4062,7 @@ save_reduce(PickleState *st, PicklerObject *self, PyObject *args,
if (self->proto >= 2) {
PyObject *name;
- if (_PyObject_LookupAttr(callable, &_Py_ID(__name__), &name) < 0) {
+ if (PyObject_GetOptionalAttr(callable, &_Py_ID(__name__), &name) < 0) {
return -1;
}
if (name != NULL && PyUnicode_Check(name)) {
@@ -4416,16 +4438,13 @@ save(PickleState *st, PicklerObject *self, PyObject *obj, int pers_save)
PyObject_GetItem and _PyObject_GetAttrId used below. */
Py_INCREF(reduce_func);
}
- } else {
- reduce_func = PyObject_GetItem(self->dispatch_table,
- (PyObject *)type);
- if (reduce_func == NULL) {
- if (PyErr_ExceptionMatches(PyExc_KeyError))
- PyErr_Clear();
- else
- goto error;
- }
}
+ else if (PyMapping_GetOptionalItem(self->dispatch_table, (PyObject *)type,
+ &reduce_func) < 0)
+ {
+ goto error;
+ }
+
if (reduce_func != NULL) {
reduce_value = _Pickle_FastCall(reduce_func, Py_NewRef(obj));
}
@@ -4443,7 +4462,7 @@ save(PickleState *st, PicklerObject *self, PyObject *obj, int pers_save)
don't actually have to check for a __reduce__ method. */
/* Check for a __reduce_ex__ method. */
- if (_PyObject_LookupAttr(obj, &_Py_ID(__reduce_ex__), &reduce_func) < 0) {
+ if (PyObject_GetOptionalAttr(obj, &_Py_ID(__reduce_ex__), &reduce_func) < 0) {
goto error;
}
if (reduce_func != NULL) {
@@ -4455,7 +4474,7 @@ save(PickleState *st, PicklerObject *self, PyObject *obj, int pers_save)
}
else {
/* Check for a __reduce__ method. */
- if (_PyObject_LookupAttr(obj, &_Py_ID(__reduce__), &reduce_func) < 0) {
+ if (PyObject_GetOptionalAttr(obj, &_Py_ID(__reduce__), &reduce_func) < 0) {
goto error;
}
if (reduce_func != NULL) {
@@ -4507,7 +4526,7 @@ dump(PickleState *state, PicklerObject *self, PyObject *obj)
int status = -1;
PyObject *tmp;
- if (_PyObject_LookupAttr((PyObject *)self, &_Py_ID(reducer_override),
+ if (PyObject_GetOptionalAttr((PyObject *)self, &_Py_ID(reducer_override),
&tmp) < 0) {
goto error;
}
@@ -4777,7 +4796,7 @@ _pickle_Pickler___init___impl(PicklerObject *self, PyObject *file,
if (self->dispatch_table != NULL) {
return 0;
}
- if (_PyObject_LookupAttr((PyObject *)self, &_Py_ID(dispatch_table),
+ if (PyObject_GetOptionalAttr((PyObject *)self, &_Py_ID(dispatch_table),
&self->dispatch_table) < 0) {
return -1;
}
@@ -5778,7 +5797,7 @@ instantiate(PyObject *cls, PyObject *args)
assert(PyTuple_Check(args));
if (!PyTuple_GET_SIZE(args) && PyType_Check(cls)) {
PyObject *func;
- if (_PyObject_LookupAttr(cls, &_Py_ID(__getinitargs__), &func) < 0) {
+ if (PyObject_GetOptionalAttr(cls, &_Py_ID(__getinitargs__), &func) < 0) {
return NULL;
}
if (func == NULL) {
@@ -6432,7 +6451,7 @@ do_append(PickleState *state, UnpicklerObject *self, Py_ssize_t x)
else {
PyObject *extend_func;
- if (_PyObject_LookupAttr(list, &_Py_ID(extend), &extend_func) < 0) {
+ if (PyObject_GetOptionalAttr(list, &_Py_ID(extend), &extend_func) < 0) {
return -1;
}
if (extend_func != NULL) {
@@ -6618,7 +6637,7 @@ load_build(PickleState *st, UnpicklerObject *self)
inst = self->stack->data[Py_SIZE(self->stack) - 1];
- if (_PyObject_LookupAttr(inst, &_Py_ID(__setstate__), &setstate) < 0) {
+ if (PyObject_GetOptionalAttr(inst, &_Py_ID(__setstate__), &setstate) < 0) {
Py_DECREF(state);
return -1;
}
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
index 2d88f5e9ba1601..ac2b0d4f55468c 100644
--- a/Modules/_posixsubprocess.c
+++ b/Modules/_posixsubprocess.c
@@ -6,6 +6,7 @@
#include "Python.h"
#include "pycore_fileutils.h"
#include "pycore_pystate.h"
+#include "pycore_signal.h" // _Py_RestoreSignals()
#if defined(HAVE_PIPE2) && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
#endif
@@ -182,6 +183,88 @@ _is_fd_in_sorted_fd_sequence(int fd, int *fd_sequence,
return 0;
}
+
+// Forward declaration
+static void _Py_FreeCharPArray(char *const array[]);
+
+/*
+ * Flatten a sequence of bytes() objects into a C array of
+ * NULL terminated string pointers with a NULL char* terminating the array.
+ * (ie: an argv or env list)
+ *
+ * Memory allocated for the returned list is allocated using PyMem_Malloc()
+ * and MUST be freed by _Py_FreeCharPArray().
+ */
+static char *const *
+_PySequence_BytesToCharpArray(PyObject* self)
+{
+ char **array;
+ Py_ssize_t i, argc;
+ PyObject *item = NULL;
+ Py_ssize_t size;
+
+ argc = PySequence_Size(self);
+ if (argc == -1)
+ return NULL;
+
+ assert(argc >= 0);
+
+ if ((size_t)argc > (PY_SSIZE_T_MAX-sizeof(char *)) / sizeof(char *)) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ array = PyMem_Malloc((argc + 1) * sizeof(char *));
+ if (array == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ for (i = 0; i < argc; ++i) {
+ char *data;
+ item = PySequence_GetItem(self, i);
+ if (item == NULL) {
+ /* NULL terminate before freeing. */
+ array[i] = NULL;
+ goto fail;
+ }
+ /* check for embedded null bytes */
+ if (PyBytes_AsStringAndSize(item, &data, NULL) < 0) {
+ /* NULL terminate before freeing. */
+ array[i] = NULL;
+ goto fail;
+ }
+ size = PyBytes_GET_SIZE(item) + 1;
+ array[i] = PyMem_Malloc(size);
+ if (!array[i]) {
+ PyErr_NoMemory();
+ goto fail;
+ }
+ memcpy(array[i], data, size);
+ Py_DECREF(item);
+ }
+ array[argc] = NULL;
+
+ return array;
+
+fail:
+ Py_XDECREF(item);
+ _Py_FreeCharPArray(array);
+ return NULL;
+}
+
+
+/* Free's a NULL terminated char** array of C strings. */
+static void
+_Py_FreeCharPArray(char *const array[])
+{
+ Py_ssize_t i;
+ for (i = 0; array[i] != NULL; ++i) {
+ PyMem_Free(array[i]);
+ }
+ PyMem_Free((void*)array);
+}
+
+
/*
* Do all the Python C API calls in the parent process to turn the pass_fds
* "py_fds_to_keep" tuple into a C array. The caller owns allocation and
@@ -657,8 +740,9 @@ child_exec(char *const exec_array[],
if (child_umask >= 0)
umask(child_umask); /* umask() always succeeds. */
- if (restore_signals)
+ if (restore_signals) {
_Py_RestoreSignals();
+ }
#ifdef VFORK_USABLE
if (child_sigmask) {
@@ -943,7 +1027,7 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args,
int *c_fds_to_keep = NULL;
Py_ssize_t fds_to_keep_len = PyTuple_GET_SIZE(py_fds_to_keep);
- PyInterpreterState *interp = PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
if ((preexec_fn != Py_None) && interp->finalizing) {
PyErr_SetString(PyExc_RuntimeError,
"preexec_fn not supported at interpreter shutdown");
diff --git a/Modules/_queuemodule.c b/Modules/_queuemodule.c
index d36a911a57c02c..69cc05135c2a72 100644
--- a/Modules/_queuemodule.c
+++ b/Modules/_queuemodule.c
@@ -4,6 +4,7 @@
#include "Python.h"
#include "pycore_moduleobject.h" // _PyModule_GetState()
+#include "pycore_time.h" // _PyTime_t
#include "structmember.h" // PyMemberDef
#include // offsetof()
@@ -210,6 +211,7 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, PyTypeObject *cls,
PyObject *item;
PyLockStatus r;
PY_TIMEOUT_T microseconds;
+ PyThreadState *tstate = PyThreadState_Get();
if (block == 0) {
/* Non-blocking */
@@ -253,7 +255,7 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, PyTypeObject *cls,
Py_END_ALLOW_THREADS
}
- if (r == PY_LOCK_INTR && Py_MakePendingCalls() < 0) {
+ if (r == PY_LOCK_INTR && _PyEval_MakePendingCalls(tstate) < 0) {
return NULL;
}
if (r == PY_LOCK_FAILURE) {
diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c
index fda5ef267fb470..7daa1f9327966f 100644
--- a/Modules/_randommodule.c
+++ b/Modules/_randommodule.c
@@ -72,6 +72,7 @@
#include "Python.h"
#include "pycore_moduleobject.h" // _PyModule_GetState()
+#include "pycore_pylifecycle.h" // _PyOS_URandomNonblock()
#include "pycore_runtime.h"
#ifdef HAVE_PROCESS_H
# include // getpid()
diff --git a/Modules/_sqlite/blob.c b/Modules/_sqlite/blob.c
index 76d261baf00f38..989d9a83b590ca 100644
--- a/Modules/_sqlite/blob.c
+++ b/Modules/_sqlite/blob.c
@@ -1,5 +1,10 @@
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "blob.h"
#include "util.h"
+#include "pycore_weakref.h" // _PyWeakref_GET_REF()
#define clinic_state() (pysqlite_get_state_by_type(Py_TYPE(self)))
#include "clinic/blob.c.h"
@@ -97,10 +102,12 @@ pysqlite_close_all_blobs(pysqlite_Connection *self)
{
for (int i = 0; i < PyList_GET_SIZE(self->blobs); i++) {
PyObject *weakref = PyList_GET_ITEM(self->blobs, i);
- PyObject *blob = PyWeakref_GetObject(weakref);
- if (!Py_IsNone(blob)) {
- close_blob((pysqlite_Blob *)blob);
+ PyObject *blob = _PyWeakref_GET_REF(weakref);
+ if (blob == NULL) {
+ continue;
}
+ close_blob((pysqlite_Blob *)blob);
+ Py_DECREF(blob);
}
}
@@ -108,14 +115,6 @@ static void
blob_seterror(pysqlite_Blob *self, int rc)
{
assert(self->connection != NULL);
-#if SQLITE_VERSION_NUMBER < 3008008
- // SQLite pre 3.8.8 does not set this blob error on the connection
- if (rc == SQLITE_ABORT) {
- PyErr_SetString(self->connection->OperationalError,
- "Cannot operate on an expired blob handle");
- return;
- }
-#endif
_pysqlite_seterror(self->connection->state, self->connection->db);
}
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 82d23c2c30b798..bab743674b666d 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -21,6 +21,10 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "module.h"
#include "structmember.h" // PyMemberDef
#include "connection.h"
@@ -29,13 +33,12 @@
#include "blob.h"
#include "prepare_protocol.h"
#include "util.h"
+#include "pycore_import.h" // _PyImport_GetModuleAttrString()
+#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
+#include "pycore_weakref.h" // _PyWeakref_IS_DEAD()
#include
-#if SQLITE_VERSION_NUMBER >= 3014000
-#define HAVE_TRACE_V2
-#endif
-
#if SQLITE_VERSION_NUMBER >= 3025000
#define HAVE_WINDOW_FUNCTIONS
#endif
@@ -401,11 +404,7 @@ free_callback_contexts(pysqlite_Connection *self)
static void
remove_callbacks(sqlite3 *db)
{
-#ifdef HAVE_TRACE_V2
sqlite3_trace_v2(db, SQLITE_TRACE_STMT, 0, 0);
-#else
- sqlite3_trace(db, 0, (void*)0);
-#endif
sqlite3_progress_handler(db, 0, 0, (void *)0);
(void)sqlite3_set_authorizer(db, NULL, NULL);
}
@@ -977,10 +976,6 @@ final_callback(sqlite3_context *context)
static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
{
- PyObject* new_list;
- PyObject* weakref;
- int i;
-
/* we only need to do this once in a while */
if (self->created_cursors++ < 200) {
return;
@@ -988,18 +983,19 @@ static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
self->created_cursors = 0;
- new_list = PyList_New(0);
+ PyObject* new_list = PyList_New(0);
if (!new_list) {
return;
}
- for (i = 0; i < PyList_Size(self->cursors); i++) {
- weakref = PyList_GetItem(self->cursors, i);
- if (PyWeakref_GetObject(weakref) != Py_None) {
- if (PyList_Append(new_list, weakref) != 0) {
- Py_DECREF(new_list);
- return;
- }
+ for (Py_ssize_t i = 0; i < PyList_Size(self->cursors); i++) {
+ PyObject* weakref = PyList_GetItem(self->cursors, i);
+ if (_PyWeakref_IS_DEAD(weakref)) {
+ continue;
+ }
+ if (PyList_Append(new_list, weakref) != 0) {
+ Py_DECREF(new_list);
+ return;
}
}
@@ -1086,18 +1082,7 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self,
}
if (deterministic) {
-#if SQLITE_VERSION_NUMBER < 3008003
- PyErr_SetString(self->NotSupportedError,
- "deterministic=True requires SQLite 3.8.3 or higher");
- return NULL;
-#else
- if (sqlite3_libversion_number() < 3008003) {
- PyErr_SetString(self->NotSupportedError,
- "deterministic=True requires SQLite 3.8.3 or higher");
- return NULL;
- }
flags |= SQLITE_DETERMINISTIC;
-#endif
}
callback_context *ctx = create_callback_context(cls, func);
if (ctx == NULL) {
@@ -1376,7 +1361,6 @@ progress_callback(void *ctx)
return rc;
}
-#ifdef HAVE_TRACE_V2
/*
* From https://sqlite.org/c3ref/trace_v2.html:
* The integer return value from the callback is currently ignored, though this
@@ -1385,16 +1369,10 @@ progress_callback(void *ctx)
*/
static int
trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
-#else
-static void
-trace_callback(void *ctx, const char *sql)
-#endif
{
-#ifdef HAVE_TRACE_V2
if (type != SQLITE_TRACE_STMT) {
return 0;
}
-#endif
PyGILState_STATE gilstate = PyGILState_Ensure();
@@ -1403,7 +1381,6 @@ trace_callback(void *ctx, const char *sql)
assert(state != NULL);
PyObject *py_statement = NULL;
-#ifdef HAVE_TRACE_V2
const char *expanded_sql = sqlite3_expanded_sql((sqlite3_stmt *)stmt);
if (expanded_sql == NULL) {
sqlite3 *db = sqlite3_db_handle((sqlite3_stmt *)stmt);
@@ -1423,15 +1400,6 @@ trace_callback(void *ctx, const char *sql)
py_statement = PyUnicode_FromString(expanded_sql);
sqlite3_free((void *)expanded_sql);
}
-#else
- if (sql == NULL) {
- PyErr_SetString(state->DataError,
- "Expanded SQL string exceeds the maximum string length");
- print_or_clear_traceback((callback_context *)ctx);
- goto exit;
- }
- py_statement = PyUnicode_FromString(sql);
-#endif
if (py_statement) {
PyObject *callable = ((callback_context *)ctx)->callable;
PyObject *ret = PyObject_CallOneArg(callable, py_statement);
@@ -1444,9 +1412,7 @@ trace_callback(void *ctx, const char *sql)
exit:
PyGILState_Release(gilstate);
-#ifdef HAVE_TRACE_V2
return 0;
-#endif
}
/*[clinic input]
@@ -1556,11 +1522,7 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self,
* - https://sqlite.org/c3ref/c_trace.html
* - https://sqlite.org/c3ref/trace_v2.html
*/
-#ifdef HAVE_TRACE_V2
sqlite3_trace_v2(self->db, SQLITE_TRACE_STMT, 0, 0);
-#else
- sqlite3_trace(self->db, 0, (void*)0);
-#endif
set_callback_context(&self->trace_ctx, NULL);
}
else {
@@ -1568,11 +1530,7 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self,
if (ctx == NULL) {
return NULL;
}
-#ifdef HAVE_TRACE_V2
sqlite3_trace_v2(self->db, SQLITE_TRACE_STMT, trace_callback, ctx);
-#else
- sqlite3_trace(self->db, trace_callback, ctx);
-#endif
set_callback_context(&self->trace_ctx, ctx);
}
@@ -2000,15 +1958,6 @@ pysqlite_connection_backup_impl(pysqlite_Connection *self,
return NULL;
}
-#if SQLITE_VERSION_NUMBER < 3008008
- /* Since 3.8.8 this is already done, per commit
- https://www.sqlite.org/src/info/169b5505498c0a7e */
- if (!sqlite3_get_autocommit(target->db)) {
- PyErr_SetString(self->OperationalError, "target is in transaction");
- return NULL;
- }
-#endif
-
if (progress != Py_None && !PyCallable_Check(progress)) {
PyErr_SetString(PyExc_TypeError, "progress argument must be a callable");
return NULL;
@@ -2371,12 +2320,8 @@ is_int_config(const int op)
switch (op) {
case SQLITE_DBCONFIG_ENABLE_FKEY:
case SQLITE_DBCONFIG_ENABLE_TRIGGER:
-#if SQLITE_VERSION_NUMBER >= 3012002
case SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER:
-#endif
-#if SQLITE_VERSION_NUMBER >= 3013000
case SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION:
-#endif
#if SQLITE_VERSION_NUMBER >= 3016000
case SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE:
#endif
diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h
index 1df92065a587a2..7a748ee3ea0c58 100644
--- a/Modules/_sqlite/connection.h
+++ b/Modules/_sqlite/connection.h
@@ -23,7 +23,6 @@
#ifndef PYSQLITE_CONNECTION_H
#define PYSQLITE_CONNECTION_H
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pythread.h"
#include "structmember.h"
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index caeedbddb8d88b..dba8ab61e41e70 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -21,11 +21,17 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "cursor.h"
#include "microprotocols.h"
#include "module.h"
#include "util.h"
+#include "pycore_pyerrors.h" // _PyErr_FormatFromCause()
+
typedef enum {
TYPE_LONG,
TYPE_FLOAT,
diff --git a/Modules/_sqlite/cursor.h b/Modules/_sqlite/cursor.h
index 0bcdddc3e29595..42f817af7c54ad 100644
--- a/Modules/_sqlite/cursor.h
+++ b/Modules/_sqlite/cursor.h
@@ -23,7 +23,6 @@
#ifndef PYSQLITE_CURSOR_H
#define PYSQLITE_CURSOR_H
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "statement.h"
diff --git a/Modules/_sqlite/microprotocols.c b/Modules/_sqlite/microprotocols.c
index 148220d0f91f96..92f0148bd4c217 100644
--- a/Modules/_sqlite/microprotocols.c
+++ b/Modules/_sqlite/microprotocols.c
@@ -98,7 +98,7 @@ pysqlite_microprotocols_adapt(pysqlite_state *state, PyObject *obj,
}
/* try to have the protocol adapt this object */
- if (_PyObject_LookupAttr(proto, state->str___adapt__, &adapter) < 0) {
+ if (PyObject_GetOptionalAttr(proto, state->str___adapt__, &adapter) < 0) {
return NULL;
}
if (adapter) {
@@ -117,7 +117,7 @@ pysqlite_microprotocols_adapt(pysqlite_state *state, PyObject *obj,
}
/* and finally try to have the object adapt itself */
- if (_PyObject_LookupAttr(obj, state->str___conform__, &adapter) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->str___conform__, &adapter) < 0) {
return NULL;
}
if (adapter) {
diff --git a/Modules/_sqlite/microprotocols.h b/Modules/_sqlite/microprotocols.h
index 6bde9d01f45299..8a8c33525ee53b 100644
--- a/Modules/_sqlite/microprotocols.h
+++ b/Modules/_sqlite/microprotocols.h
@@ -26,7 +26,6 @@
#ifndef PSYCOPG_MICROPROTOCOLS_H
#define PSYCOPG_MICROPROTOCOLS_H 1
-#define PY_SSIZE_T_CLEAN
#include
/** exported functions **/
diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c
index 27bd42f4595e1c..368e581b4f3355 100644
--- a/Modules/_sqlite/module.c
+++ b/Modules/_sqlite/module.c
@@ -21,6 +21,10 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "connection.h"
#include "statement.h"
#include "cursor.h"
@@ -29,8 +33,10 @@
#include "row.h"
#include "blob.h"
-#if SQLITE_VERSION_NUMBER < 3007015
-#error "SQLite 3.7.15 or higher required"
+#include "pycore_import.h" // _PyImport_GetModuleAttrString()
+
+#if SQLITE_VERSION_NUMBER < 3015002
+#error "SQLite 3.15.2 or higher required"
#endif
#define clinic_state() (pysqlite_get_state(module))
@@ -245,12 +251,6 @@ static PyMethodDef module_methods[] = {
/* SQLite C API result codes. See also:
* - https://www.sqlite.org/c3ref/c_abort_rollback.html
- * - https://sqlite.org/changes.html#version_3_3_8
- * - https://sqlite.org/changes.html#version_3_7_16
- * - https://sqlite.org/changes.html#version_3_7_17
- * - https://sqlite.org/changes.html#version_3_8_0
- * - https://sqlite.org/changes.html#version_3_8_3
- * - https://sqlite.org/changes.html#version_3_14
*
* Note: the SQLite changelogs rarely mention new result codes, so in order to
* keep the 'error_codes' table in sync with SQLite, we must manually inspect
@@ -294,10 +294,8 @@ static const struct {
DECLARE_ERROR_CODE(SQLITE_ROW),
DECLARE_ERROR_CODE(SQLITE_SCHEMA),
DECLARE_ERROR_CODE(SQLITE_TOOBIG),
-#if SQLITE_VERSION_NUMBER >= 3007017
DECLARE_ERROR_CODE(SQLITE_NOTICE),
DECLARE_ERROR_CODE(SQLITE_WARNING),
-#endif
// Extended result code list
DECLARE_ERROR_CODE(SQLITE_ABORT_ROLLBACK),
DECLARE_ERROR_CODE(SQLITE_BUSY_RECOVERY),
@@ -331,7 +329,6 @@ static const struct {
DECLARE_ERROR_CODE(SQLITE_LOCKED_SHAREDCACHE),
DECLARE_ERROR_CODE(SQLITE_READONLY_CANTLOCK),
DECLARE_ERROR_CODE(SQLITE_READONLY_RECOVERY),
-#if SQLITE_VERSION_NUMBER >= 3007016
DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_CHECK),
DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_COMMITHOOK),
DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_FOREIGNKEY),
@@ -342,39 +339,20 @@ static const struct {
DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_UNIQUE),
DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_VTAB),
DECLARE_ERROR_CODE(SQLITE_READONLY_ROLLBACK),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3007017
DECLARE_ERROR_CODE(SQLITE_IOERR_MMAP),
DECLARE_ERROR_CODE(SQLITE_NOTICE_RECOVER_ROLLBACK),
DECLARE_ERROR_CODE(SQLITE_NOTICE_RECOVER_WAL),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3008000
DECLARE_ERROR_CODE(SQLITE_BUSY_SNAPSHOT),
DECLARE_ERROR_CODE(SQLITE_IOERR_GETTEMPPATH),
DECLARE_ERROR_CODE(SQLITE_WARNING_AUTOINDEX),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3008001
DECLARE_ERROR_CODE(SQLITE_CANTOPEN_CONVPATH),
DECLARE_ERROR_CODE(SQLITE_IOERR_CONVPATH),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3008002
DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_ROWID),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3008003
DECLARE_ERROR_CODE(SQLITE_READONLY_DBMOVED),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3008007
DECLARE_ERROR_CODE(SQLITE_AUTH_USER),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3009000
DECLARE_ERROR_CODE(SQLITE_IOERR_VNODE),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3010000
DECLARE_ERROR_CODE(SQLITE_IOERR_AUTH),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3014001
DECLARE_ERROR_CODE(SQLITE_OK_LOAD_PERMANENTLY),
-#endif
#if SQLITE_VERSION_NUMBER >= 3021000
DECLARE_ERROR_CODE(SQLITE_IOERR_BEGIN_ATOMIC),
DECLARE_ERROR_CODE(SQLITE_IOERR_COMMIT_ATOMIC),
@@ -481,9 +459,7 @@ add_integer_constants(PyObject *module) {
ADD_INT(SQLITE_DROP_VTABLE);
ADD_INT(SQLITE_FUNCTION);
ADD_INT(SQLITE_SAVEPOINT);
-#if SQLITE_VERSION_NUMBER >= 3008003
ADD_INT(SQLITE_RECURSIVE);
-#endif
// Run-time limit categories
ADD_INT(SQLITE_LIMIT_LENGTH);
ADD_INT(SQLITE_LIMIT_SQL_LENGTH);
@@ -496,9 +472,7 @@ add_integer_constants(PyObject *module) {
ADD_INT(SQLITE_LIMIT_LIKE_PATTERN_LENGTH);
ADD_INT(SQLITE_LIMIT_VARIABLE_NUMBER);
ADD_INT(SQLITE_LIMIT_TRIGGER_DEPTH);
-#if SQLITE_VERSION_NUMBER >= 3008007
ADD_INT(SQLITE_LIMIT_WORKER_THREADS);
-#endif
/*
* Database connection configuration options.
@@ -506,12 +480,8 @@ add_integer_constants(PyObject *module) {
*/
ADD_INT(SQLITE_DBCONFIG_ENABLE_FKEY);
ADD_INT(SQLITE_DBCONFIG_ENABLE_TRIGGER);
-#if SQLITE_VERSION_NUMBER >= 3012002
ADD_INT(SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER);
-#endif
-#if SQLITE_VERSION_NUMBER >= 3013000
ADD_INT(SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION);
-#endif
#if SQLITE_VERSION_NUMBER >= 3016000
ADD_INT(SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE);
#endif
@@ -678,8 +648,8 @@ do { \
static int
module_exec(PyObject *module)
{
- if (sqlite3_libversion_number() < 3007015) {
- PyErr_SetString(PyExc_ImportError, MODULE_NAME ": SQLite 3.7.15 or higher required");
+ if (sqlite3_libversion_number() < 3015002) {
+ PyErr_SetString(PyExc_ImportError, MODULE_NAME ": SQLite 3.15.2 or higher required");
return -1;
}
diff --git a/Modules/_sqlite/module.h b/Modules/_sqlite/module.h
index daa22091d38ad7..a4ca45cf6326a9 100644
--- a/Modules/_sqlite/module.h
+++ b/Modules/_sqlite/module.h
@@ -23,7 +23,6 @@
#ifndef PYSQLITE_MODULE_H
#define PYSQLITE_MODULE_H
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#define LEGACY_TRANSACTION_CONTROL -1
diff --git a/Modules/_sqlite/row.h b/Modules/_sqlite/row.h
index b51909817584ba..d42b781e493177 100644
--- a/Modules/_sqlite/row.h
+++ b/Modules/_sqlite/row.h
@@ -23,7 +23,6 @@
#ifndef PYSQLITE_ROW_H
#define PYSQLITE_ROW_H
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
typedef struct _Row
diff --git a/Modules/_sqlite/statement.h b/Modules/_sqlite/statement.h
index 11a6464b1a1c2b..b18f170ebb0708 100644
--- a/Modules/_sqlite/statement.h
+++ b/Modules/_sqlite/statement.h
@@ -23,7 +23,6 @@
#ifndef PYSQLITE_STATEMENT_H
#define PYSQLITE_STATEMENT_H
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "connection.h"
diff --git a/Modules/_sqlite/util.h b/Modules/_sqlite/util.h
index a22bcd82d2a05b..68b1a8cb67ace3 100644
--- a/Modules/_sqlite/util.h
+++ b/Modules/_sqlite/util.h
@@ -23,7 +23,6 @@
#ifndef PYSQLITE_UTIL_H
#define PYSQLITE_UTIL_H
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pythread.h"
#include "sqlite3.h"
diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c
index e89e4c77971494..f34a353432dec0 100644
--- a/Modules/_sre/sre.c
+++ b/Modules/_sre/sre.c
@@ -38,8 +38,6 @@
static const char copyright[] =
" SRE 2.2.2 Copyright (c) 1997-2002 by Secret Labs AB ";
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_moduleobject.h" // _PyModule_GetState()
@@ -51,8 +49,14 @@ static const char copyright[] =
#include
-/* defining this one enables tracing */
-#undef VERBOSE
+/* Defining this one controls tracing:
+ * 0 -- disabled
+ * 1 -- only if the DEBUG flag set
+ * 2 -- always
+ */
+#ifndef VERBOSE
+# define VERBOSE 0
+#endif
/* -------------------------------------------------------------------- */
@@ -72,10 +76,21 @@ static const char copyright[] =
#define SRE_ERROR_MEMORY -9 /* out of memory */
#define SRE_ERROR_INTERRUPTED -10 /* signal handler raised exception */
-#if defined(VERBOSE)
-#define TRACE(v) printf v
+#if VERBOSE == 0
+# define INIT_TRACE(state)
+# define TRACE(v)
+#elif VERBOSE == 1
+# define INIT_TRACE(state) int _debug = (state)->debug
+# define TRACE(v) do { \
+ if (_debug) { \
+ printf v; \
+ } \
+ } while (0)
+#elif VERBOSE == 2
+# define INIT_TRACE(state)
+# define TRACE(v) printf v
#else
-#define TRACE(v)
+# error VERBOSE must be 0, 1 or 2
#endif
/* -------------------------------------------------------------------- */
@@ -200,6 +215,7 @@ data_stack_dealloc(SRE_STATE* state)
static int
data_stack_grow(SRE_STATE* state, Py_ssize_t size)
{
+ INIT_TRACE(state);
Py_ssize_t minsize, cursize;
minsize = state->data_stack_base+size;
cursize = state->data_stack_size;
@@ -451,6 +467,7 @@ state_init(SRE_STATE* state, PatternObject* pattern, PyObject* string,
state->charsize = charsize;
state->match_all = 0;
state->must_advance = 0;
+ state->debug = ((pattern->flags & SRE_FLAG_DEBUG) != 0);
state->beginning = ptr;
@@ -643,6 +660,7 @@ _sre_SRE_Pattern_match_impl(PatternObject *self, PyTypeObject *cls,
if (!state_init(&state, (PatternObject *)self, string, pos, endpos))
return NULL;
+ INIT_TRACE(&state);
state.ptr = state.start;
TRACE(("|%p|%p|MATCH\n", PatternObject_GetCode(self), state.ptr));
@@ -686,6 +704,7 @@ _sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyTypeObject *cls,
if (!state_init(&state, self, string, pos, endpos))
return NULL;
+ INIT_TRACE(&state);
state.ptr = state.start;
TRACE(("|%p|%p|FULLMATCH\n", PatternObject_GetCode(self), state.ptr));
@@ -732,6 +751,7 @@ _sre_SRE_Pattern_search_impl(PatternObject *self, PyTypeObject *cls,
if (!state_init(&state, self, string, pos, endpos))
return NULL;
+ INIT_TRACE(&state);
TRACE(("|%p|%p|SEARCH\n", PatternObject_GetCode(self), state.ptr));
status = sre_search(&state, PatternObject_GetCode(self));
@@ -1335,7 +1355,6 @@ pattern_repr(PatternObject *obj)
const char *name;
int value;
} flag_names[] = {
- {"re.TEMPLATE", SRE_FLAG_TEMPLATE},
{"re.IGNORECASE", SRE_FLAG_IGNORECASE},
{"re.LOCALE", SRE_FLAG_LOCALE},
{"re.MULTILINE", SRE_FLAG_MULTILINE},
@@ -1547,10 +1566,12 @@ _sre_template_impl(PyObject *module, PyObject *pattern, PyObject *template)
for (Py_ssize_t i = 0; i < n; i++) {
Py_ssize_t index = PyLong_AsSsize_t(PyList_GET_ITEM(template, 2*i+1));
if (index == -1 && PyErr_Occurred()) {
+ Py_SET_SIZE(self, i);
Py_DECREF(self);
return NULL;
}
if (index < 0) {
+ Py_SET_SIZE(self, i);
goto bad_template;
}
self->items[i].index = index;
diff --git a/Modules/_sre/sre.h b/Modules/_sre/sre.h
index d967d9ea04ba7a..f60078d6bb999b 100644
--- a/Modules/_sre/sre.h
+++ b/Modules/_sre/sre.h
@@ -84,6 +84,7 @@ typedef struct {
int charsize; /* character size */
int match_all;
int must_advance;
+ int debug;
/* marks */
int lastmark;
int lastindex;
diff --git a/Modules/_sre/sre_constants.h b/Modules/_sre/sre_constants.h
index b5692292f65280..bd611b33614509 100644
--- a/Modules/_sre/sre_constants.h
+++ b/Modules/_sre/sre_constants.h
@@ -11,7 +11,7 @@
* See the sre.c file for information on usage and redistribution.
*/
-#define SRE_MAGIC 20221023
+#define SRE_MAGIC 20230612
#define SRE_OP_FAILURE 0
#define SRE_OP_SUCCESS 1
#define SRE_OP_ANY 2
@@ -85,7 +85,6 @@
#define SRE_CATEGORY_UNI_NOT_WORD 15
#define SRE_CATEGORY_UNI_LINEBREAK 16
#define SRE_CATEGORY_UNI_NOT_LINEBREAK 17
-#define SRE_FLAG_TEMPLATE 1
#define SRE_FLAG_IGNORECASE 2
#define SRE_FLAG_LOCALE 4
#define SRE_FLAG_MULTILINE 8
diff --git a/Modules/_sre/sre_lib.h b/Modules/_sre/sre_lib.h
index fb4c18b63d643d..c1a774f69090b3 100644
--- a/Modules/_sre/sre_lib.h
+++ b/Modules/_sre/sre_lib.h
@@ -209,6 +209,7 @@ SRE(count)(SRE_STATE* state, const SRE_CODE* pattern, Py_ssize_t maxcount)
const SRE_CHAR* ptr = (const SRE_CHAR *)state->ptr;
const SRE_CHAR* end = (const SRE_CHAR *)state->end;
Py_ssize_t i;
+ INIT_TRACE(state);
/* adjust end */
if (maxcount < end - ptr && maxcount != SRE_MAXREPEAT)
@@ -567,6 +568,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
SRE(match_context)* ctx;
SRE(match_context)* nextctx;
+ INIT_TRACE(state);
TRACE(("|%p|%p|ENTER\n", pattern, state->ptr));
@@ -1639,6 +1641,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern)
SRE_CODE* charset = NULL;
SRE_CODE* overlap = NULL;
int flags = 0;
+ INIT_TRACE(state);
if (ptr > end)
return 0;
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index de90a4a168d2ed..571de331e92cd9 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -14,6 +14,10 @@
http://bugs.python.org/issue8108#msg102867 ?
*/
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
/* Don't warn about deprecated functions, */
#ifndef OPENSSL_API_COMPAT
// 0x10101000L == 1.1.1, 30000 == 3.0.0
@@ -21,9 +25,8 @@
#endif
#define OPENSSL_NO_DEPRECATED 1
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
+#include "pycore_weakref.h" // _PyWeakref_GET_REF()
/* Include symbols from _socket module */
#include "socketmodule.h"
@@ -378,9 +381,25 @@ typedef enum {
#define ERRSTR1(x,y,z) (x ":" y ": " z)
#define ERRSTR(x) ERRSTR1("_ssl.c", Py_STRINGIFY(__LINE__), x)
-/* Get the socket from a PySSLSocket, if it has one */
-#define GET_SOCKET(obj) ((obj)->Socket ? \
- (PySocketSockObject *) PyWeakref_GetObject((obj)->Socket) : NULL)
+// Get the socket from a PySSLSocket, if it has one.
+// Return a borrowed reference.
+static inline PySocketSockObject* GET_SOCKET(PySSLSocket *obj) {
+ if (obj->Socket) {
+ PyObject *sock = _PyWeakref_GET_REF(obj->Socket);
+ if (sock != NULL) {
+ // GET_SOCKET() returns a borrowed reference
+ Py_DECREF(sock);
+ }
+ else {
+ // dead weak reference
+ sock = Py_None;
+ }
+ return (PySocketSockObject *)sock; // borrowed reference
+ }
+ else {
+ return NULL;
+ }
+}
/* If sock is NULL, use a timeout of 0 second */
#define GET_SOCKET_TIMEOUT(sock) \
@@ -828,6 +847,15 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
_setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__);
return NULL;
}
+
+ if (socket_type == PY_SSL_SERVER) {
+#define SID_CTX "Python"
+ /* Set the session id context (server-side only) */
+ SSL_set_session_id_context(self->ssl, (const unsigned char *) SID_CTX,
+ sizeof(SID_CTX));
+#undef SID_CTX
+ }
+
/* bpo43522 and OpenSSL < 1.1.1l: copy hostflags manually */
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION < 0x101010cf
X509_VERIFY_PARAM *ssl_params = SSL_get0_param(self->ssl);
@@ -2177,13 +2205,14 @@ PyDoc_STRVAR(PySSL_get_server_hostname_doc,
static PyObject *
PySSL_get_owner(PySSLSocket *self, void *c)
{
- PyObject *owner;
-
- if (self->owner == NULL)
+ if (self->owner == NULL) {
Py_RETURN_NONE;
-
- owner = PyWeakref_GetObject(self->owner);
- return Py_NewRef(owner);
+ }
+ PyObject *owner = _PyWeakref_GET_REF(self->owner);
+ if (owner == NULL) {
+ Py_RETURN_NONE;
+ }
+ return owner;
}
static int
@@ -3166,11 +3195,6 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
usage for no cost at all. */
SSL_CTX_set_mode(self->ctx, SSL_MODE_RELEASE_BUFFERS);
-#define SID_CTX "Python"
- SSL_CTX_set_session_id_context(self->ctx, (const unsigned char *) SID_CTX,
- sizeof(SID_CTX));
-#undef SID_CTX
-
params = SSL_CTX_get0_param(self->ctx);
/* Improve trust chain building when cross-signed intermediate
certificates are present. See https://bugs.python.org/issue23476. */
@@ -4393,14 +4417,13 @@ _servername_callback(SSL *s, int *al, void *args)
* will be passed. If both do not exist only then the C-level object is
* passed. */
if (ssl->owner)
- ssl_socket = PyWeakref_GetObject(ssl->owner);
+ ssl_socket = _PyWeakref_GET_REF(ssl->owner);
else if (ssl->Socket)
- ssl_socket = PyWeakref_GetObject(ssl->Socket);
+ ssl_socket = _PyWeakref_GET_REF(ssl->Socket);
else
- ssl_socket = (PyObject *) ssl;
+ ssl_socket = Py_NewRef(ssl);
- Py_INCREF(ssl_socket);
- if (ssl_socket == Py_None)
+ if (ssl_socket == NULL)
goto error;
if (servername == NULL) {
@@ -6001,15 +6024,21 @@ sslmodule_init_errorcodes(PyObject *module)
errcode = error_codes;
while (errcode->mnemonic != NULL) {
- PyObject *mnemo, *key;
- mnemo = PyUnicode_FromString(errcode->mnemonic);
- key = Py_BuildValue("ii", errcode->library, errcode->reason);
- if (mnemo == NULL || key == NULL)
+ PyObject *mnemo = PyUnicode_FromString(errcode->mnemonic);
+ if (mnemo == NULL) {
return -1;
- if (PyDict_SetItem(state->err_codes_to_names, key, mnemo))
+ }
+ PyObject *key = Py_BuildValue("ii", errcode->library, errcode->reason);
+ if (key == NULL) {
+ Py_DECREF(mnemo);
return -1;
+ }
+ int rc = PyDict_SetItem(state->err_codes_to_names, key, mnemo);
Py_DECREF(key);
Py_DECREF(mnemo);
+ if (rc < 0) {
+ return -1;
+ }
errcode++;
}
diff --git a/Modules/_ssl/debughelpers.c b/Modules/_ssl/debughelpers.c
index a81f0aad05a802..07e9ce7a6fce2d 100644
--- a/Modules/_ssl/debughelpers.c
+++ b/Modules/_ssl/debughelpers.c
@@ -15,7 +15,6 @@ _PySSL_msg_callback(int write_p, int version, int content_type,
PyGILState_STATE threadstate;
PyObject *res = NULL;
PySSLSocket *ssl_obj = NULL; /* ssl._SSLSocket, borrowed ref */
- PyObject *ssl_socket = NULL; /* ssl.SSLSocket or ssl.SSLObject */
int msg_type;
threadstate = PyGILState_Ensure();
@@ -27,13 +26,14 @@ _PySSL_msg_callback(int write_p, int version, int content_type,
return;
}
+ PyObject *ssl_socket; /* ssl.SSLSocket or ssl.SSLObject */
if (ssl_obj->owner)
- ssl_socket = PyWeakref_GetObject(ssl_obj->owner);
+ ssl_socket = _PyWeakref_GET_REF(ssl_obj->owner);
else if (ssl_obj->Socket)
- ssl_socket = PyWeakref_GetObject(ssl_obj->Socket);
+ ssl_socket = _PyWeakref_GET_REF(ssl_obj->Socket);
else
- ssl_socket = (PyObject *)ssl_obj;
- Py_INCREF(ssl_socket);
+ ssl_socket = (PyObject *)Py_NewRef(ssl_obj);
+ assert(ssl_socket != NULL); // _PyWeakref_GET_REF() can return NULL
/* assume that OpenSSL verifies all payload and buf len is of sufficient
length */
diff --git a/Modules/_stat.c b/Modules/_stat.c
index 4218799103b59d..9747d848cbacb8 100644
--- a/Modules/_stat.c
+++ b/Modules/_stat.c
@@ -11,7 +11,6 @@
*
*/
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#ifdef __cplusplus
diff --git a/Modules/_struct.c b/Modules/_struct.c
index 4f9478bd98095d..31c94927e91d68 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -7,9 +7,8 @@
# define Py_BUILD_CORE_MODULE 1
#endif
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
+#include "pycore_bytesobject.h" // _PyBytesWriter
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "structmember.h" // PyMemberDef
#include
diff --git a/Modules/_testbuffer.c b/Modules/_testbuffer.c
index 63ed4dc6ca80e1..5101834cfe1387 100644
--- a/Modules/_testbuffer.c
+++ b/Modules/_testbuffer.c
@@ -1,9 +1,6 @@
/* C Extension module to test all aspects of PEP-3118.
Written by Stefan Krah. */
-
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
diff --git a/Modules/_testcapi/clinic/vectorcall.c.h b/Modules/_testcapi/clinic/vectorcall.c.h
index 765afeda9b306c..728c0d382565a7 100644
--- a/Modules/_testcapi/clinic/vectorcall.c.h
+++ b/Modules/_testcapi/clinic/vectorcall.c.h
@@ -8,6 +8,106 @@ preserve
#endif
+PyDoc_STRVAR(_testcapi_pyobject_fastcalldict__doc__,
+"pyobject_fastcalldict($module, func, func_args, kwargs, /)\n"
+"--\n"
+"\n");
+
+#define _TESTCAPI_PYOBJECT_FASTCALLDICT_METHODDEF \
+ {"pyobject_fastcalldict", _PyCFunction_CAST(_testcapi_pyobject_fastcalldict), METH_FASTCALL, _testcapi_pyobject_fastcalldict__doc__},
+
+static PyObject *
+_testcapi_pyobject_fastcalldict_impl(PyObject *module, PyObject *func,
+ PyObject *func_args, PyObject *kwargs);
+
+static PyObject *
+_testcapi_pyobject_fastcalldict(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *func;
+ PyObject *func_args;
+ PyObject *__clinic_kwargs;
+
+ if (!_PyArg_CheckPositional("pyobject_fastcalldict", nargs, 3, 3)) {
+ goto exit;
+ }
+ func = args[0];
+ func_args = args[1];
+ __clinic_kwargs = args[2];
+ return_value = _testcapi_pyobject_fastcalldict_impl(module, func, func_args, __clinic_kwargs);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_testcapi_pyobject_vectorcall__doc__,
+"pyobject_vectorcall($module, func, func_args, kwnames, /)\n"
+"--\n"
+"\n");
+
+#define _TESTCAPI_PYOBJECT_VECTORCALL_METHODDEF \
+ {"pyobject_vectorcall", _PyCFunction_CAST(_testcapi_pyobject_vectorcall), METH_FASTCALL, _testcapi_pyobject_vectorcall__doc__},
+
+static PyObject *
+_testcapi_pyobject_vectorcall_impl(PyObject *module, PyObject *func,
+ PyObject *func_args, PyObject *kwnames);
+
+static PyObject *
+_testcapi_pyobject_vectorcall(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *func;
+ PyObject *func_args;
+ PyObject *__clinic_kwnames;
+
+ if (!_PyArg_CheckPositional("pyobject_vectorcall", nargs, 3, 3)) {
+ goto exit;
+ }
+ func = args[0];
+ func_args = args[1];
+ __clinic_kwnames = args[2];
+ return_value = _testcapi_pyobject_vectorcall_impl(module, func, func_args, __clinic_kwnames);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_testcapi_pyvectorcall_call__doc__,
+"pyvectorcall_call($module, func, argstuple, kwargs=, /)\n"
+"--\n"
+"\n");
+
+#define _TESTCAPI_PYVECTORCALL_CALL_METHODDEF \
+ {"pyvectorcall_call", _PyCFunction_CAST(_testcapi_pyvectorcall_call), METH_FASTCALL, _testcapi_pyvectorcall_call__doc__},
+
+static PyObject *
+_testcapi_pyvectorcall_call_impl(PyObject *module, PyObject *func,
+ PyObject *argstuple, PyObject *kwargs);
+
+static PyObject *
+_testcapi_pyvectorcall_call(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *func;
+ PyObject *argstuple;
+ PyObject *__clinic_kwargs = NULL;
+
+ if (!_PyArg_CheckPositional("pyvectorcall_call", nargs, 2, 3)) {
+ goto exit;
+ }
+ func = args[0];
+ argstuple = args[1];
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ __clinic_kwargs = args[2];
+skip_optional:
+ return_value = _testcapi_pyvectorcall_call_impl(module, func, argstuple, __clinic_kwargs);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(_testcapi_VectorCallClass_set_vectorcall__doc__,
"set_vectorcall($self, type, /)\n"
"--\n"
@@ -110,4 +210,4 @@ _testcapi_has_vectorcall_flag(PyObject *module, PyObject *arg)
exit:
return return_value;
}
-/*[clinic end generated code: output=609569aa9942584f input=a9049054013a1b77]*/
+/*[clinic end generated code: output=beaf6beac3d13c25 input=a9049054013a1b77]*/
diff --git a/Modules/_testcapi/code.c b/Modules/_testcapi/code.c
index 84c668cd6b3b00..cadaf5eb94692e 100644
--- a/Modules/_testcapi/code.c
+++ b/Modules/_testcapi/code.c
@@ -9,7 +9,7 @@ get_code_extra_index(PyInterpreterState* interp) {
PyObject *interp_dict = PyInterpreterState_GetDict(interp); // borrowed
assert(interp_dict); // real users would handle missing dict... somehow
- PyObject *index_obj = PyDict_GetItemString(interp_dict, key); // borrowed
+ PyObject *index_obj = _PyDict_GetItemStringWithError(interp_dict, key); // borrowed
Py_ssize_t index = 0;
if (!index_obj) {
if (PyErr_Occurred()) {
diff --git a/Modules/_testcapi/float.c b/Modules/_testcapi/float.c
index 33cbda83a81af7..cff53fb950fcc6 100644
--- a/Modules/_testcapi/float.c
+++ b/Modules/_testcapi/float.c
@@ -1,5 +1,3 @@
-#define PY_SSIZE_T_CLEAN
-
#include "parts.h"
#include "clinic/float.c.h"
diff --git a/Modules/_testcapi/getargs.c b/Modules/_testcapi/getargs.c
index a473c41f60af3c..10a1c1dd05253d 100644
--- a/Modules/_testcapi/getargs.c
+++ b/Modules/_testcapi/getargs.c
@@ -3,8 +3,6 @@
* APIs that parse and build arguments.
*/
-#define PY_SSIZE_T_CLEAN
-
#include "parts.h"
static PyObject *
diff --git a/Modules/_testcapi/heaptype.c b/Modules/_testcapi/heaptype.c
index 565ab570a42bde..c124871e433431 100644
--- a/Modules/_testcapi/heaptype.c
+++ b/Modules/_testcapi/heaptype.c
@@ -744,6 +744,12 @@ static PyType_Spec HeapCTypeMetaclassCustomNew_spec = {
HeapCTypeMetaclassCustomNew_slots
};
+static PyType_Spec HeapCTypeMetaclassNullNew_spec = {
+ .name = "_testcapi.HeapCTypeMetaclassNullNew",
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
+ .slots = empty_type_slots
+};
+
typedef struct {
PyObject_HEAD
@@ -1231,6 +1237,13 @@ _PyTestCapi_Init_Heaptype(PyObject *m) {
}
PyModule_AddObject(m, "HeapCTypeMetaclassCustomNew", HeapCTypeMetaclassCustomNew);
+ PyObject *HeapCTypeMetaclassNullNew = PyType_FromMetaclass(
+ &PyType_Type, m, &HeapCTypeMetaclassNullNew_spec, (PyObject *) &PyType_Type);
+ if (HeapCTypeMetaclassNullNew == NULL) {
+ return -1;
+ }
+ PyModule_AddObject(m, "HeapCTypeMetaclassNullNew", HeapCTypeMetaclassNullNew);
+
PyObject *HeapCCollection = PyType_FromMetaclass(
NULL, m, &HeapCCollection_spec, NULL);
if (HeapCCollection == NULL) {
diff --git a/Modules/_testcapi/mem.c b/Modules/_testcapi/mem.c
index af32e9668dda2d..16bda66af554af 100644
--- a/Modules/_testcapi/mem.c
+++ b/Modules/_testcapi/mem.c
@@ -655,23 +655,6 @@ tracemalloc_untrack(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
-static PyObject *
-tracemalloc_get_traceback(PyObject *self, PyObject *args)
-{
- unsigned int domain;
- PyObject *ptr_obj;
-
- if (!PyArg_ParseTuple(args, "IO", &domain, &ptr_obj)) {
- return NULL;
- }
- void *ptr = PyLong_AsVoidPtr(ptr_obj);
- if (PyErr_Occurred()) {
- return NULL;
- }
-
- return _PyTraceMalloc_GetTraceback(domain, (uintptr_t)ptr);
-}
-
static PyMethodDef test_methods[] = {
{"check_pyobject_forbidden_bytes_is_freed",
check_pyobject_forbidden_bytes_is_freed, METH_NOARGS},
@@ -697,7 +680,6 @@ static PyMethodDef test_methods[] = {
// Tracemalloc tests
{"tracemalloc_track", tracemalloc_track, METH_VARARGS},
{"tracemalloc_untrack", tracemalloc_untrack, METH_VARARGS},
- {"tracemalloc_get_traceback", tracemalloc_get_traceback, METH_VARARGS},
{NULL},
};
diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h
index d1991ac6b464f2..aaec0a61916948 100644
--- a/Modules/_testcapi/parts.h
+++ b/Modules/_testcapi/parts.h
@@ -28,7 +28,6 @@ int _PyTestCapi_Init_Vectorcall(PyObject *module);
int _PyTestCapi_Init_Heaptype(PyObject *module);
int _PyTestCapi_Init_Unicode(PyObject *module);
int _PyTestCapi_Init_GetArgs(PyObject *module);
-int _PyTestCapi_Init_PyTime(PyObject *module);
int _PyTestCapi_Init_DateTime(PyObject *module);
int _PyTestCapi_Init_Docstring(PyObject *module);
int _PyTestCapi_Init_Mem(PyObject *module);
diff --git a/Modules/_testcapi/pytime.c b/Modules/_testcapi/pytime.c
index 7422bafc30193a..e69de29bb2d1d6 100644
--- a/Modules/_testcapi/pytime.c
+++ b/Modules/_testcapi/pytime.c
@@ -1,274 +0,0 @@
-#include "parts.h"
-
-#ifdef MS_WINDOWS
-# include // struct timeval
-#endif
-
-static PyObject *
-test_pytime_fromseconds(PyObject *self, PyObject *args)
-{
- int seconds;
- if (!PyArg_ParseTuple(args, "i", &seconds)) {
- return NULL;
- }
- _PyTime_t ts = _PyTime_FromSeconds(seconds);
- return _PyTime_AsNanosecondsObject(ts);
-}
-
-static int
-check_time_rounding(int round)
-{
- if (round != _PyTime_ROUND_FLOOR
- && round != _PyTime_ROUND_CEILING
- && round != _PyTime_ROUND_HALF_EVEN
- && round != _PyTime_ROUND_UP)
- {
- PyErr_SetString(PyExc_ValueError, "invalid rounding");
- return -1;
- }
- return 0;
-}
-
-static PyObject *
-test_pytime_fromsecondsobject(PyObject *self, PyObject *args)
-{
- PyObject *obj;
- int round;
- if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
- return NULL;
- }
- if (check_time_rounding(round) < 0) {
- return NULL;
- }
- _PyTime_t ts;
- if (_PyTime_FromSecondsObject(&ts, obj, round) == -1) {
- return NULL;
- }
- return _PyTime_AsNanosecondsObject(ts);
-}
-
-static PyObject *
-test_pytime_assecondsdouble(PyObject *self, PyObject *args)
-{
- PyObject *obj;
- if (!PyArg_ParseTuple(args, "O", &obj)) {
- return NULL;
- }
- _PyTime_t ts;
- if (_PyTime_FromNanosecondsObject(&ts, obj) < 0) {
- return NULL;
- }
- double d = _PyTime_AsSecondsDouble(ts);
- return PyFloat_FromDouble(d);
-}
-
-static PyObject *
-test_PyTime_AsTimeval(PyObject *self, PyObject *args)
-{
- PyObject *obj;
- int round;
- if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
- return NULL;
- }
- if (check_time_rounding(round) < 0) {
- return NULL;
- }
- _PyTime_t t;
- if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
- return NULL;
- }
- struct timeval tv;
- if (_PyTime_AsTimeval(t, &tv, round) < 0) {
- return NULL;
- }
-
- PyObject *seconds = PyLong_FromLongLong(tv.tv_sec);
- if (seconds == NULL) {
- return NULL;
- }
- return Py_BuildValue("Nl", seconds, (long)tv.tv_usec);
-}
-
-static PyObject *
-test_PyTime_AsTimeval_clamp(PyObject *self, PyObject *args)
-{
- PyObject *obj;
- int round;
- if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
- return NULL;
- }
- if (check_time_rounding(round) < 0) {
- return NULL;
- }
- _PyTime_t t;
- if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
- return NULL;
- }
- struct timeval tv;
- _PyTime_AsTimeval_clamp(t, &tv, round);
-
- PyObject *seconds = PyLong_FromLongLong(tv.tv_sec);
- if (seconds == NULL) {
- return NULL;
- }
- return Py_BuildValue("Nl", seconds, (long)tv.tv_usec);
-}
-
-#ifdef HAVE_CLOCK_GETTIME
-static PyObject *
-test_PyTime_AsTimespec(PyObject *self, PyObject *args)
-{
- PyObject *obj;
- if (!PyArg_ParseTuple(args, "O", &obj)) {
- return NULL;
- }
- _PyTime_t t;
- if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
- return NULL;
- }
- struct timespec ts;
- if (_PyTime_AsTimespec(t, &ts) == -1) {
- return NULL;
- }
- return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec);
-}
-
-static PyObject *
-test_PyTime_AsTimespec_clamp(PyObject *self, PyObject *args)
-{
- PyObject *obj;
- if (!PyArg_ParseTuple(args, "O", &obj)) {
- return NULL;
- }
- _PyTime_t t;
- if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
- return NULL;
- }
- struct timespec ts;
- _PyTime_AsTimespec_clamp(t, &ts);
- return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec);
-}
-#endif
-
-static PyObject *
-test_PyTime_AsMilliseconds(PyObject *self, PyObject *args)
-{
- PyObject *obj;
- int round;
- if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
- return NULL;
- }
- _PyTime_t t;
- if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
- return NULL;
- }
- if (check_time_rounding(round) < 0) {
- return NULL;
- }
- _PyTime_t ms = _PyTime_AsMilliseconds(t, round);
- _PyTime_t ns = _PyTime_FromNanoseconds(ms);
- return _PyTime_AsNanosecondsObject(ns);
-}
-
-static PyObject *
-test_PyTime_AsMicroseconds(PyObject *self, PyObject *args)
-{
- PyObject *obj;
- int round;
- if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
- return NULL;
- }
- _PyTime_t t;
- if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
- return NULL;
- }
- if (check_time_rounding(round) < 0) {
- return NULL;
- }
- _PyTime_t us = _PyTime_AsMicroseconds(t, round);
- _PyTime_t ns = _PyTime_FromNanoseconds(us);
- return _PyTime_AsNanosecondsObject(ns);
-}
-
-static PyObject *
-test_pytime_object_to_time_t(PyObject *self, PyObject *args)
-{
- PyObject *obj;
- time_t sec;
- int round;
- if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_time_t", &obj, &round)) {
- return NULL;
- }
- if (check_time_rounding(round) < 0) {
- return NULL;
- }
- if (_PyTime_ObjectToTime_t(obj, &sec, round) == -1) {
- return NULL;
- }
- return _PyLong_FromTime_t(sec);
-}
-
-static PyObject *
-test_pytime_object_to_timeval(PyObject *self, PyObject *args)
-{
- PyObject *obj;
- time_t sec;
- long usec;
- int round;
- if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_timeval", &obj, &round)) {
- return NULL;
- }
- if (check_time_rounding(round) < 0) {
- return NULL;
- }
- if (_PyTime_ObjectToTimeval(obj, &sec, &usec, round) == -1) {
- return NULL;
- }
- return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), usec);
-}
-
-static PyObject *
-test_pytime_object_to_timespec(PyObject *self, PyObject *args)
-{
- PyObject *obj;
- time_t sec;
- long nsec;
- int round;
- if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_timespec", &obj, &round)) {
- return NULL;
- }
- if (check_time_rounding(round) < 0) {
- return NULL;
- }
- if (_PyTime_ObjectToTimespec(obj, &sec, &nsec, round) == -1) {
- return NULL;
- }
- return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec);
-}
-
-static PyMethodDef test_methods[] = {
- {"PyTime_AsMicroseconds", test_PyTime_AsMicroseconds, METH_VARARGS},
- {"PyTime_AsMilliseconds", test_PyTime_AsMilliseconds, METH_VARARGS},
- {"PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS},
-#ifdef HAVE_CLOCK_GETTIME
- {"PyTime_AsTimespec", test_PyTime_AsTimespec, METH_VARARGS},
- {"PyTime_AsTimespec_clamp", test_PyTime_AsTimespec_clamp, METH_VARARGS},
-#endif
- {"PyTime_AsTimeval", test_PyTime_AsTimeval, METH_VARARGS},
- {"PyTime_AsTimeval_clamp", test_PyTime_AsTimeval_clamp, METH_VARARGS},
- {"PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS},
- {"PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS},
- {"pytime_object_to_time_t", test_pytime_object_to_time_t, METH_VARARGS},
- {"pytime_object_to_timespec", test_pytime_object_to_timespec, METH_VARARGS},
- {"pytime_object_to_timeval", test_pytime_object_to_timeval, METH_VARARGS},
- {NULL},
-};
-
-int
-_PyTestCapi_Init_PyTime(PyObject *mod)
-{
- if (PyModule_AddFunctions(mod, test_methods) < 0) {
- return -1;
- }
- return 0;
-}
diff --git a/Modules/_testcapi/structmember.c b/Modules/_testcapi/structmember.c
index 0fb872a4328d60..8522dc962efa40 100644
--- a/Modules/_testcapi/structmember.c
+++ b/Modules/_testcapi/structmember.c
@@ -1,4 +1,3 @@
-#define PY_SSIZE_T_CLEAN
#include "parts.h"
#include // for offsetof()
diff --git a/Modules/_testcapi/unicode.c b/Modules/_testcapi/unicode.c
index 73929eaffc676d..b4c6c4b5e3ce1a 100644
--- a/Modules/_testcapi/unicode.c
+++ b/Modules/_testcapi/unicode.c
@@ -1,6 +1,5 @@
#include // ptrdiff_t
-#define PY_SSIZE_T_CLEAN
#include "parts.h"
static struct PyModuleDef *_testcapimodule = NULL; // set at initialization
@@ -376,6 +375,22 @@ unicode_readchar(PyObject *self, PyObject *args)
return PyLong_FromUnsignedLong(result);
}
+/* Test PyUnicode_FromEncodedObject() */
+static PyObject *
+unicode_fromencodedobject(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ const char *encoding;
+ const char *errors = NULL;
+
+ if (!PyArg_ParseTuple(args, "Oz|z", &obj, &encoding, &errors)) {
+ return NULL;
+ }
+
+ NULLABLE(obj);
+ return PyUnicode_FromEncodedObject(obj, encoding, errors);
+}
+
/* Test PyUnicode_FromObject() */
static PyObject *
unicode_fromobject(PyObject *self, PyObject *arg)
@@ -661,12 +676,76 @@ unicode_getdefaultencoding(PyObject *self, PyObject *Py_UNUSED(ignored))
return PyBytes_FromString(s);
}
-/* Test _PyUnicode_TransformDecimalAndSpaceToASCII() */
+/* Test PyUnicode_Decode() */
+static PyObject *
+unicode_decode(PyObject *self, PyObject *args)
+{
+ const char *s;
+ Py_ssize_t size;
+ const char *encoding;
+ const char *errors = NULL;
+
+ if (!PyArg_ParseTuple(args, "y#z|z", &s, &size, &encoding, &errors))
+ return NULL;
+
+ return PyUnicode_Decode(s, size, encoding, errors);
+}
+
+/* Test PyUnicode_AsEncodedString() */
static PyObject *
-unicode_transformdecimalandspacetoascii(PyObject *self, PyObject *arg)
+unicode_asencodedstring(PyObject *self, PyObject *args)
+{
+ PyObject *unicode;
+ const char *encoding;
+ const char *errors = NULL;
+
+ if (!PyArg_ParseTuple(args, "Oz|z", &unicode, &encoding, &errors))
+ return NULL;
+
+ NULLABLE(unicode);
+ return PyUnicode_AsEncodedString(unicode, encoding, errors);
+}
+
+/* Test PyUnicode_BuildEncodingMap() */
+static PyObject *
+unicode_buildencodingmap(PyObject *self, PyObject *arg)
{
NULLABLE(arg);
- return _PyUnicode_TransformDecimalAndSpaceToASCII(arg);
+ return PyUnicode_BuildEncodingMap(arg);
+}
+
+/* Test PyUnicode_DecodeUTF7() */
+static PyObject *
+unicode_decodeutf7(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+
+ if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors))
+ return NULL;
+
+ return PyUnicode_DecodeUTF7(data, size, errors);
+}
+
+/* Test PyUnicode_DecodeUTF7Stateful() */
+static PyObject *
+unicode_decodeutf7stateful(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+ Py_ssize_t consumed;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors))
+ return NULL;
+
+ result = PyUnicode_DecodeUTF7Stateful(data, size, errors, &consumed);
+ if (!result) {
+ return NULL;
+ }
+ return Py_BuildValue("(Nn)", result, consumed);
}
/* Test PyUnicode_DecodeUTF8() */
@@ -703,6 +782,387 @@ unicode_decodeutf8stateful(PyObject *self, PyObject *args)
return Py_BuildValue("(Nn)", result, consumed);
}
+/* Test PyUnicode_AsUTF8String() */
+static PyObject *
+unicode_asutf8string(PyObject *self, PyObject *arg)
+{
+ NULLABLE(arg);
+ return PyUnicode_AsUTF8String(arg);
+}
+
+/* Test PyUnicode_DecodeUTF32() */
+static PyObject *
+unicode_decodeutf32(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+ int byteorder;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "iy#|z", &byteorder, &data, &size, &errors))
+ return NULL;
+
+ result = PyUnicode_DecodeUTF32(data, size, errors, &byteorder);
+ if (!result) {
+ return NULL;
+ }
+ return Py_BuildValue("(iN)", byteorder, result);
+}
+
+/* Test PyUnicode_DecodeUTF32Stateful() */
+static PyObject *
+unicode_decodeutf32stateful(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+ int byteorder;
+ Py_ssize_t consumed;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "iy#|z", &byteorder, &data, &size, &errors))
+ return NULL;
+
+ result = PyUnicode_DecodeUTF32Stateful(data, size, errors, &byteorder, &consumed);
+ if (!result) {
+ return NULL;
+ }
+ return Py_BuildValue("(iNn)", byteorder, result, consumed);
+}
+
+/* Test PyUnicode_AsUTF32String() */
+static PyObject *
+unicode_asutf32string(PyObject *self, PyObject *arg)
+{
+ NULLABLE(arg);
+ return PyUnicode_AsUTF32String(arg);
+}
+
+/* Test PyUnicode_DecodeUTF16() */
+static PyObject *
+unicode_decodeutf16(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+ int byteorder = 0;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "iy#|z", &byteorder, &data, &size, &errors))
+ return NULL;
+
+ result = PyUnicode_DecodeUTF16(data, size, errors, &byteorder);
+ if (!result) {
+ return NULL;
+ }
+ return Py_BuildValue("(iN)", byteorder, result);
+}
+
+/* Test PyUnicode_DecodeUTF16Stateful() */
+static PyObject *
+unicode_decodeutf16stateful(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+ int byteorder;
+ Py_ssize_t consumed;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "iy#|z", &byteorder, &data, &size, &errors))
+ return NULL;
+
+ result = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder, &consumed);
+ if (!result) {
+ return NULL;
+ }
+ return Py_BuildValue("(iNn)", byteorder, result, consumed);
+}
+
+/* Test PyUnicode_AsUTF16String() */
+static PyObject *
+unicode_asutf16string(PyObject *self, PyObject *arg)
+{
+ NULLABLE(arg);
+ return PyUnicode_AsUTF16String(arg);
+}
+
+/* Test PyUnicode_DecodeUnicodeEscape() */
+static PyObject *
+unicode_decodeunicodeescape(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+
+ if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors))
+ return NULL;
+
+ return PyUnicode_DecodeUnicodeEscape(data, size, errors);
+}
+
+/* Test PyUnicode_AsUnicodeEscapeString() */
+static PyObject *
+unicode_asunicodeescapestring(PyObject *self, PyObject *arg)
+{
+ NULLABLE(arg);
+ return PyUnicode_AsUnicodeEscapeString(arg);
+}
+
+static PyObject *
+unicode_decoderawunicodeescape(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+
+ if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors))
+ return NULL;
+
+ return PyUnicode_DecodeRawUnicodeEscape(data, size, errors);
+}
+
+/* Test PyUnicode_AsRawUnicodeEscapeString() */
+static PyObject *
+unicode_asrawunicodeescapestring(PyObject *self, PyObject *arg)
+{
+ NULLABLE(arg);
+ return PyUnicode_AsRawUnicodeEscapeString(arg);
+}
+
+static PyObject *
+unicode_decodelatin1(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+
+ if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors))
+ return NULL;
+
+ return PyUnicode_DecodeLatin1(data, size, errors);
+}
+
+/* Test PyUnicode_AsLatin1String() */
+static PyObject *
+unicode_aslatin1string(PyObject *self, PyObject *arg)
+{
+ NULLABLE(arg);
+ return PyUnicode_AsLatin1String(arg);
+}
+
+/* Test PyUnicode_DecodeASCII() */
+static PyObject *
+unicode_decodeascii(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+
+ if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors))
+ return NULL;
+
+ return PyUnicode_DecodeASCII(data, size, errors);
+}
+
+/* Test PyUnicode_AsASCIIString() */
+static PyObject *
+unicode_asasciistring(PyObject *self, PyObject *arg)
+{
+ NULLABLE(arg);
+ return PyUnicode_AsASCIIString(arg);
+}
+
+/* Test PyUnicode_DecodeCharmap() */
+static PyObject *
+unicode_decodecharmap(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ PyObject *mapping;
+ const char *errors = NULL;
+
+ if (!PyArg_ParseTuple(args, "y#O|z", &data, &size, &mapping, &errors))
+ return NULL;
+
+ NULLABLE(mapping);
+ return PyUnicode_DecodeCharmap(data, size, mapping, errors);
+}
+
+/* Test PyUnicode_AsCharmapString() */
+static PyObject *
+unicode_ascharmapstring(PyObject *self, PyObject *args)
+{
+ PyObject *unicode;
+ PyObject *mapping;
+
+ if (!PyArg_ParseTuple(args, "OO", &unicode, &mapping))
+ return NULL;
+
+ NULLABLE(unicode);
+ NULLABLE(mapping);
+ return PyUnicode_AsCharmapString(unicode, mapping);
+}
+
+#ifdef MS_WINDOWS
+
+/* Test PyUnicode_DecodeMBCS() */
+static PyObject *
+unicode_decodembcs(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+
+ if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors))
+ return NULL;
+
+ return PyUnicode_DecodeMBCS(data, size, errors);
+}
+
+/* Test PyUnicode_DecodeMBCSStateful() */
+static PyObject *
+unicode_decodembcsstateful(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+ Py_ssize_t consumed;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors))
+ return NULL;
+
+ result = PyUnicode_DecodeMBCSStateful(data, size, errors, &consumed);
+ if (!result) {
+ return NULL;
+ }
+ return Py_BuildValue("(Nn)", result, consumed);
+}
+
+/* Test PyUnicode_DecodeCodePageStateful() */
+static PyObject *
+unicode_decodecodepagestateful(PyObject *self, PyObject *args)
+{
+ int code_page;
+ const char *data;
+ Py_ssize_t size;
+ const char *errors = NULL;
+ Py_ssize_t consumed;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "iy#|z", &code_page, &data, &size, &errors))
+ return NULL;
+
+ result = PyUnicode_DecodeCodePageStateful(code_page, data, size, errors, &consumed);
+ if (!result) {
+ return NULL;
+ }
+ return Py_BuildValue("(Nn)", result, consumed);
+}
+
+/* Test PyUnicode_AsMBCSString() */
+static PyObject *
+unicode_asmbcsstring(PyObject *self, PyObject *arg)
+{
+ NULLABLE(arg);
+ return PyUnicode_AsMBCSString(arg);
+}
+
+/* Test PyUnicode_EncodeCodePage() */
+static PyObject *
+unicode_encodecodepage(PyObject *self, PyObject *args)
+{
+ int code_page;
+ PyObject *unicode;
+ const char *errors;
+
+ if (!PyArg_ParseTuple(args, "iO|z", &code_page, &unicode, &errors))
+ return NULL;
+
+ NULLABLE(unicode);
+ return PyUnicode_EncodeCodePage(code_page, unicode, errors);
+}
+
+#endif /* MS_WINDOWS */
+
+/* Test PyUnicode_DecodeLocaleAndSize() */
+static PyObject *
+unicode_decodelocaleandsize(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors;
+
+ if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors))
+ return NULL;
+
+ return PyUnicode_DecodeLocaleAndSize(data, size, errors);
+}
+
+/* Test PyUnicode_DecodeLocale() */
+static PyObject *
+unicode_decodelocale(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+ const char *errors;
+
+ if (!PyArg_ParseTuple(args, "y#|z", &data, &size, &errors))
+ return NULL;
+
+ return PyUnicode_DecodeLocale(data, errors);
+}
+
+/* Test PyUnicode_EncodeLocale() */
+static PyObject *
+unicode_encodelocale(PyObject *self, PyObject *args)
+{
+ PyObject *unicode;
+ const char *errors;
+
+ if (!PyArg_ParseTuple(args, "O|z", &unicode, &errors))
+ return NULL;
+
+ NULLABLE(unicode);
+ return PyUnicode_EncodeLocale(unicode, errors);
+}
+
+/* Test PyUnicode_DecodeFSDefault() */
+static PyObject *
+unicode_decodefsdefault(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+
+ if (!PyArg_ParseTuple(args, "y#", &data, &size))
+ return NULL;
+
+ return PyUnicode_DecodeFSDefault(data);
+}
+
+/* Test PyUnicode_DecodeFSDefaultAndSize() */
+static PyObject *
+unicode_decodefsdefaultandsize(PyObject *self, PyObject *args)
+{
+ const char *data;
+ Py_ssize_t size;
+
+ if (!PyArg_ParseTuple(args, "y#|n", &data, &size, &size))
+ return NULL;
+
+ return PyUnicode_DecodeFSDefaultAndSize(data, size);
+}
+
+/* Test PyUnicode_EncodeFSDefault() */
+static PyObject *
+unicode_encodefsdefault(PyObject *self, PyObject *arg)
+{
+ NULLABLE(arg);
+ return PyUnicode_EncodeFSDefault(arg);
+}
+
/* Test PyUnicode_Concat() */
static PyObject *
unicode_concat(PyObject *self, PyObject *args)
@@ -1101,7 +1561,7 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored))
} \
else if (result == NULL) \
return NULL; \
- else if (!_PyUnicode_EqualToASCIIString(result, EXPECTED)) { \
+ else if (PyUnicode_CompareWithASCIIString(result, EXPECTED) != 0) { \
PyErr_Format(PyExc_AssertionError, \
"test_string_from_format: failed at \"%s\" " \
"expected \"%s\" got \"%s\"", \
@@ -1528,6 +1988,7 @@ static PyMethodDef TestMethods[] = {
{"unicode_substring", unicode_substring, METH_VARARGS},
{"unicode_getlength", unicode_getlength, METH_O},
{"unicode_readchar", unicode_readchar, METH_VARARGS},
+ {"unicode_fromencodedobject",unicode_fromencodedobject, METH_VARARGS},
{"unicode_fromobject", unicode_fromobject, METH_O},
{"unicode_interninplace", unicode_interninplace, METH_O},
{"unicode_internfromstring", unicode_internfromstring, METH_O},
@@ -1542,10 +2003,44 @@ static PyMethodDef TestMethods[] = {
{"unicode_asutf8", unicode_asutf8, METH_VARARGS},
{"unicode_asutf8andsize", unicode_asutf8andsize, METH_VARARGS},
{"unicode_asutf8andsize_null",unicode_asutf8andsize_null, METH_VARARGS},
+ {"unicode_getdefaultencoding",unicode_getdefaultencoding, METH_NOARGS},
+ {"unicode_decode", unicode_decode, METH_VARARGS},
+ {"unicode_asencodedstring", unicode_asencodedstring, METH_VARARGS},
+ {"unicode_buildencodingmap", unicode_buildencodingmap, METH_O},
+ {"unicode_decodeutf7", unicode_decodeutf7, METH_VARARGS},
+ {"unicode_decodeutf7stateful",unicode_decodeutf7stateful, METH_VARARGS},
{"unicode_decodeutf8", unicode_decodeutf8, METH_VARARGS},
{"unicode_decodeutf8stateful",unicode_decodeutf8stateful, METH_VARARGS},
- {"unicode_getdefaultencoding",unicode_getdefaultencoding, METH_NOARGS},
- {"unicode_transformdecimalandspacetoascii", unicode_transformdecimalandspacetoascii, METH_O},
+ {"unicode_asutf8string", unicode_asutf8string, METH_O},
+ {"unicode_decodeutf16", unicode_decodeutf16, METH_VARARGS},
+ {"unicode_decodeutf16stateful",unicode_decodeutf16stateful, METH_VARARGS},
+ {"unicode_asutf16string", unicode_asutf16string, METH_O},
+ {"unicode_decodeutf32", unicode_decodeutf32, METH_VARARGS},
+ {"unicode_decodeutf32stateful",unicode_decodeutf32stateful, METH_VARARGS},
+ {"unicode_asutf32string", unicode_asutf32string, METH_O},
+ {"unicode_decodeunicodeescape",unicode_decodeunicodeescape, METH_VARARGS},
+ {"unicode_asunicodeescapestring",unicode_asunicodeescapestring,METH_O},
+ {"unicode_decoderawunicodeescape",unicode_decoderawunicodeescape,METH_VARARGS},
+ {"unicode_asrawunicodeescapestring",unicode_asrawunicodeescapestring,METH_O},
+ {"unicode_decodelatin1", unicode_decodelatin1, METH_VARARGS},
+ {"unicode_aslatin1string", unicode_aslatin1string, METH_O},
+ {"unicode_decodeascii", unicode_decodeascii, METH_VARARGS},
+ {"unicode_asasciistring", unicode_asasciistring, METH_O},
+ {"unicode_decodecharmap", unicode_decodecharmap, METH_VARARGS},
+ {"unicode_ascharmapstring", unicode_ascharmapstring, METH_VARARGS},
+#ifdef MS_WINDOWS
+ {"unicode_decodembcs", unicode_decodembcs, METH_VARARGS},
+ {"unicode_decodembcsstateful",unicode_decodembcsstateful, METH_VARARGS},
+ {"unicode_decodecodepagestateful",unicode_decodecodepagestateful,METH_VARARGS},
+ {"unicode_asmbcsstring", unicode_asmbcsstring, METH_O},
+ {"unicode_encodecodepage", unicode_encodecodepage, METH_VARARGS},
+#endif /* MS_WINDOWS */
+ {"unicode_decodelocaleandsize",unicode_decodelocaleandsize, METH_VARARGS},
+ {"unicode_decodelocale", unicode_decodelocale, METH_VARARGS},
+ {"unicode_encodelocale", unicode_encodelocale, METH_VARARGS},
+ {"unicode_decodefsdefault", unicode_decodefsdefault, METH_VARARGS},
+ {"unicode_decodefsdefaultandsize",unicode_decodefsdefaultandsize,METH_VARARGS},
+ {"unicode_encodefsdefault", unicode_encodefsdefault, METH_O},
{"unicode_concat", unicode_concat, METH_VARARGS},
{"unicode_splitlines", unicode_splitlines, METH_VARARGS},
{"unicode_split", unicode_split, METH_VARARGS},
diff --git a/Modules/_testcapi/vectorcall.c b/Modules/_testcapi/vectorcall.c
index dcbc973c9fb991..5ee468bd28c853 100644
--- a/Modules/_testcapi/vectorcall.c
+++ b/Modules/_testcapi/vectorcall.c
@@ -4,6 +4,10 @@
#include "structmember.h" // PyMemberDef
#include // offsetof
+/*[clinic input]
+module _testcapi
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6361033e795369fc]*/
/* Test PEP 590 - Vectorcall */
@@ -25,35 +29,22 @@ fastcall_args(PyObject *args, PyObject ***stack, Py_ssize_t *nargs)
return 0;
}
+/*[clinic input]
+_testcapi.pyobject_fastcalldict
+ func: object
+ func_args: object
+ kwargs: object
+ /
+[clinic start generated code]*/
static PyObject *
-test_pyobject_fastcall(PyObject *self, PyObject *args)
+_testcapi_pyobject_fastcalldict_impl(PyObject *module, PyObject *func,
+ PyObject *func_args, PyObject *kwargs)
+/*[clinic end generated code: output=35902ece94de4418 input=b9c0196ca7d5f9e4]*/
{
- PyObject *func, *func_args;
PyObject **stack;
Py_ssize_t nargs;
- if (!PyArg_ParseTuple(args, "OO", &func, &func_args)) {
- return NULL;
- }
-
- if (fastcall_args(func_args, &stack, &nargs) < 0) {
- return NULL;
- }
- return _PyObject_FastCall(func, stack, nargs);
-}
-
-static PyObject *
-test_pyobject_fastcalldict(PyObject *self, PyObject *args)
-{
- PyObject *func, *func_args, *kwargs;
- PyObject **stack;
- Py_ssize_t nargs;
-
- if (!PyArg_ParseTuple(args, "OOO", &func, &func_args, &kwargs)) {
- return NULL;
- }
-
if (fastcall_args(func_args, &stack, &nargs) < 0) {
return NULL;
}
@@ -69,17 +60,22 @@ test_pyobject_fastcalldict(PyObject *self, PyObject *args)
return PyObject_VectorcallDict(func, stack, nargs, kwargs);
}
+/*[clinic input]
+_testcapi.pyobject_vectorcall
+ func: object
+ func_args: object
+ kwnames: object
+ /
+[clinic start generated code]*/
+
static PyObject *
-test_pyobject_vectorcall(PyObject *self, PyObject *args)
+_testcapi_pyobject_vectorcall_impl(PyObject *module, PyObject *func,
+ PyObject *func_args, PyObject *kwnames)
+/*[clinic end generated code: output=ff77245bc6afe0d8 input=a0668dfef625764c]*/
{
- PyObject *func, *func_args, *kwnames = NULL;
PyObject **stack;
Py_ssize_t nargs, nkw;
- if (!PyArg_ParseTuple(args, "OOO", &func, &func_args, &kwnames)) {
- return NULL;
- }
-
if (fastcall_args(func_args, &stack, &nargs) < 0) {
return NULL;
}
@@ -120,17 +116,19 @@ function_setvectorcall(PyObject *self, PyObject *func)
Py_RETURN_NONE;
}
+/*[clinic input]
+_testcapi.pyvectorcall_call
+ func: object
+ argstuple: object
+ kwargs: object = NULL
+ /
+[clinic start generated code]*/
+
static PyObject *
-test_pyvectorcall_call(PyObject *self, PyObject *args)
+_testcapi_pyvectorcall_call_impl(PyObject *module, PyObject *func,
+ PyObject *argstuple, PyObject *kwargs)
+/*[clinic end generated code: output=809046fe78511306 input=4376ee7cabd698ce]*/
{
- PyObject *func;
- PyObject *argstuple;
- PyObject *kwargs = NULL;
-
- if (!PyArg_ParseTuple(args, "OO|O", &func, &argstuple, &kwargs)) {
- return NULL;
- }
-
if (!PyTuple_Check(argstuple)) {
PyErr_SetString(PyExc_TypeError, "args must be a tuple");
return NULL;
@@ -259,11 +257,10 @@ _testcapi_has_vectorcall_flag_impl(PyObject *module, PyTypeObject *type)
}
static PyMethodDef TestMethods[] = {
- {"pyobject_fastcall", test_pyobject_fastcall, METH_VARARGS},
- {"pyobject_fastcalldict", test_pyobject_fastcalldict, METH_VARARGS},
- {"pyobject_vectorcall", test_pyobject_vectorcall, METH_VARARGS},
+ _TESTCAPI_PYOBJECT_FASTCALLDICT_METHODDEF
+ _TESTCAPI_PYOBJECT_VECTORCALL_METHODDEF
{"function_setvectorcall", function_setvectorcall, METH_O},
- {"pyvectorcall_call", test_pyvectorcall_call, METH_VARARGS},
+ _TESTCAPI_PYVECTORCALL_CALL_METHODDEF
_TESTCAPI_MAKE_VECTORCALL_CLASS_METHODDEF
_TESTCAPI_HAS_VECTORCALL_FLAG_METHODDEF
{NULL},
diff --git a/Modules/_testcapi/watchers.c b/Modules/_testcapi/watchers.c
index d2c71fb401d36a..7167943fffab39 100644
--- a/Modules/_testcapi/watchers.c
+++ b/Modules/_testcapi/watchers.c
@@ -432,9 +432,9 @@ allocate_too_many_code_watchers(PyObject *self, PyObject *args)
// Test function watchers
-#define NUM_FUNC_WATCHERS 2
-static PyObject *pyfunc_watchers[NUM_FUNC_WATCHERS];
-static int func_watcher_ids[NUM_FUNC_WATCHERS] = {-1, -1};
+#define NUM_TEST_FUNC_WATCHERS 2
+static PyObject *pyfunc_watchers[NUM_TEST_FUNC_WATCHERS];
+static int func_watcher_ids[NUM_TEST_FUNC_WATCHERS] = {-1, -1};
static PyObject *
get_id(PyObject *obj)
@@ -508,7 +508,7 @@ second_func_watcher_callback(PyFunction_WatchEvent event,
return call_pyfunc_watcher(pyfunc_watchers[1], event, func, new_value);
}
-static PyFunction_WatchCallback func_watcher_callbacks[NUM_FUNC_WATCHERS] = {
+static PyFunction_WatchCallback func_watcher_callbacks[NUM_TEST_FUNC_WATCHERS] = {
first_func_watcher_callback,
second_func_watcher_callback
};
@@ -533,26 +533,25 @@ add_func_watcher(PyObject *self, PyObject *func)
return NULL;
}
int idx = -1;
- for (int i = 0; i < NUM_FUNC_WATCHERS; i++) {
+ for (int i = 0; i < NUM_TEST_FUNC_WATCHERS; i++) {
if (func_watcher_ids[i] == -1) {
idx = i;
break;
}
}
if (idx == -1) {
- PyErr_SetString(PyExc_RuntimeError, "no free watchers");
- return NULL;
- }
- PyObject *result = PyLong_FromLong(idx);
- if (result == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "no free test watchers");
return NULL;
}
func_watcher_ids[idx] = PyFunction_AddWatcher(func_watcher_callbacks[idx]);
if (func_watcher_ids[idx] < 0) {
- Py_DECREF(result);
return NULL;
}
pyfunc_watchers[idx] = Py_NewRef(func);
+ PyObject *result = PyLong_FromLong(func_watcher_ids[idx]);
+ if (result == NULL) {
+ return NULL;
+ }
return result;
}
@@ -569,7 +568,7 @@ clear_func_watcher(PyObject *self, PyObject *watcher_id_obj)
return NULL;
}
int idx = -1;
- for (int i = 0; i < NUM_FUNC_WATCHERS; i++) {
+ for (int i = 0; i < NUM_TEST_FUNC_WATCHERS; i++) {
if (func_watcher_ids[i] == wid) {
idx = i;
break;
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 3acc7575cfe8db..dd2c9c72e53787 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -17,8 +17,6 @@
/* Always enable assertions */
#undef NDEBUG
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "frameobject.h" // PyFrame_New
#include "marshal.h" // PyMarshal_WriteLongToFile
@@ -640,6 +638,30 @@ test_get_type_qualname(PyObject *self, PyObject *Py_UNUSED(ignored))
Py_RETURN_NONE;
}
+static PyObject *
+test_get_type_dict(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ /* Test for PyType_GetDict */
+
+ // Assert ints have a `to_bytes` method
+ PyObject *long_dict = PyType_GetDict(&PyLong_Type);
+ assert(long_dict);
+ assert(PyDict_GetItemString(long_dict, "to_bytes")); // borrowed ref
+ Py_DECREF(long_dict);
+
+ // Make a new type, add an attribute to it and assert it's there
+ PyObject *HeapTypeNameType = PyType_FromSpec(&HeapTypeNameType_Spec);
+ assert(HeapTypeNameType);
+ assert(PyObject_SetAttrString(
+ HeapTypeNameType, "new_attr", Py_NewRef(Py_None)) >= 0);
+ PyObject *type_dict = PyType_GetDict((PyTypeObject*)HeapTypeNameType);
+ assert(type_dict);
+ assert(PyDict_GetItemString(type_dict, "new_attr")); // borrowed ref
+ Py_DECREF(HeapTypeNameType);
+ Py_DECREF(type_dict);
+ Py_RETURN_NONE;
+}
+
static PyObject *
pyobject_repr_from_null(PyObject *self, PyObject *Py_UNUSED(ignored))
{
@@ -1269,9 +1291,15 @@ test_pep3118_obsolete_write_locks(PyObject* self, PyObject *Py_UNUSED(ignored))
if (ret != -1 || match == 0)
goto error;
+ PyObject *mod_io = PyImport_ImportModule("_io");
+ if (mod_io == NULL) {
+ return NULL;
+ }
+
/* bytesiobuf_getbuffer() */
- PyTypeObject *type = (PyTypeObject *)_PyImport_GetModuleAttrString(
- "_io", "_BytesIOBuffer");
+ PyTypeObject *type = (PyTypeObject *)PyObject_GetAttrString(
+ mod_io, "_BytesIOBuffer");
+ Py_DECREF(mod_io);
if (type == NULL) {
return NULL;
}
@@ -1426,7 +1454,7 @@ run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
int allow_threads = -1;
int allow_daemon_threads = -1;
int check_multi_interp_extensions = -1;
- int own_gil = -1;
+ int gil = -1;
int r;
PyThreadState *substate, *mainstate;
/* only initialise 'cflags.cf_flags' to test backwards compatibility */
@@ -1439,15 +1467,15 @@ run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
"allow_threads",
"allow_daemon_threads",
"check_multi_interp_extensions",
- "own_gil",
+ "gil",
NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "s$ppppppp:run_in_subinterp_with_config", kwlist,
+ "s$ppppppi:run_in_subinterp_with_config", kwlist,
&code, &use_main_obmalloc,
&allow_fork, &allow_exec,
&allow_threads, &allow_daemon_threads,
&check_multi_interp_extensions,
- &own_gil)) {
+ &gil)) {
return NULL;
}
if (use_main_obmalloc < 0) {
@@ -1466,8 +1494,8 @@ run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
PyErr_SetString(PyExc_ValueError, "missing allow_threads");
return NULL;
}
- if (own_gil < 0) {
- PyErr_SetString(PyExc_ValueError, "missing own_gil");
+ if (gil < 0) {
+ PyErr_SetString(PyExc_ValueError, "missing gil");
return NULL;
}
if (allow_daemon_threads < 0) {
@@ -1490,7 +1518,7 @@ run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
.allow_threads = allow_threads,
.allow_daemon_threads = allow_daemon_threads,
.check_multi_interp_extensions = check_multi_interp_extensions,
- .own_gil = own_gil,
+ .gil = gil,
};
PyStatus status = Py_NewInterpreterFromConfig(&substate, &config);
if (PyStatus_Exception(status)) {
@@ -2714,11 +2742,6 @@ test_tstate_capi(PyObject *self, PyObject *Py_UNUSED(args))
assert(PyDict_Check(dict));
// dict is a borrowed reference
- // private _PyThreadState_GetDict()
- PyObject *dict2 = _PyThreadState_GetDict(tstate);
- assert(dict2 == dict);
- // dict2 is a borrowed reference
-
// PyThreadState_GetInterpreter()
PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate);
assert(interp != NULL);
@@ -3294,34 +3317,150 @@ function_set_kw_defaults(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
-struct atexit_data {
- int called;
-};
-
-static void
-callback(void *data)
+static PyObject *
+check_pyimport_addmodule(PyObject *self, PyObject *args)
{
- ((struct atexit_data *)data)->called += 1;
+ const char *name;
+ if (!PyArg_ParseTuple(args, "s", &name)) {
+ return NULL;
+ }
+
+ // test PyImport_AddModuleRef()
+ PyObject *module = PyImport_AddModuleRef(name);
+ if (module == NULL) {
+ return NULL;
+ }
+ assert(PyModule_Check(module));
+ // module is a strong reference
+
+ // test PyImport_AddModule()
+ PyObject *module2 = PyImport_AddModule(name);
+ if (module2 == NULL) {
+ goto error;
+ }
+ assert(PyModule_Check(module2));
+ assert(module2 == module);
+ // module2 is a borrowed ref
+
+ // test PyImport_AddModuleObject()
+ PyObject *name_obj = PyUnicode_FromString(name);
+ if (name_obj == NULL) {
+ goto error;
+ }
+ PyObject *module3 = PyImport_AddModuleObject(name_obj);
+ Py_DECREF(name_obj);
+ if (module3 == NULL) {
+ goto error;
+ }
+ assert(PyModule_Check(module3));
+ assert(module3 == module);
+ // module3 is a borrowed ref
+
+ return module;
+
+error:
+ Py_DECREF(module);
+ return NULL;
}
+
static PyObject *
-test_atexit(PyObject *self, PyObject *Py_UNUSED(args))
+test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
- PyThreadState *oldts = PyThreadState_Swap(NULL);
- PyThreadState *tstate = Py_NewInterpreter();
+ // Ignore PyWeakref_GetObject() deprecation, we test it on purpose
+ _Py_COMP_DIAG_PUSH
+ _Py_COMP_DIAG_IGNORE_DEPR_DECLS
- struct atexit_data data = {0};
- int res = _Py_AtExit(tstate->interp, callback, (void *)&data);
- Py_EndInterpreter(tstate);
- PyThreadState_Swap(oldts);
- if (res < 0) {
+ // Create a new heap type, create an instance of this type, and delete the
+ // type. This object supports weak references.
+ PyObject *new_type = PyObject_CallFunction((PyObject*)&PyType_Type,
+ "s(){}", "TypeName");
+ if (new_type == NULL) {
return NULL;
}
- if (data.called == 0) {
- PyErr_SetString(PyExc_RuntimeError, "atexit callback not called");
+ PyObject *obj = PyObject_CallNoArgs(new_type);
+ Py_DECREF(new_type);
+ if (obj == NULL) {
+ return NULL;
+ }
+ Py_ssize_t refcnt = Py_REFCNT(obj);
+
+ // test PyWeakref_NewRef(), reference is alive
+ PyObject *weakref = PyWeakref_NewRef(obj, NULL);
+ if (weakref == NULL) {
+ Py_DECREF(obj);
return NULL;
}
+
+ // test PyWeakref_Check(), valid weakref object
+ assert(PyWeakref_Check(weakref));
+ assert(PyWeakref_CheckRefExact(weakref));
+ assert(PyWeakref_CheckRefExact(weakref));
+ assert(Py_REFCNT(obj) == refcnt);
+
+ // test PyWeakref_GetRef(), reference is alive
+ PyObject *ref = Py_True; // marker to check that value was set
+ assert(PyWeakref_GetRef(weakref, &ref) == 1);
+ assert(ref == obj);
+ assert(Py_REFCNT(obj) == (refcnt + 1));
+ Py_DECREF(ref);
+
+ // test PyWeakref_GetObject(), reference is alive
+ ref = PyWeakref_GetObject(weakref); // borrowed ref
+ assert(ref == obj);
+
+ // test PyWeakref_GET_OBJECT(), reference is alive
+ ref = PyWeakref_GET_OBJECT(weakref); // borrowed ref
+ assert(ref == obj);
+
+ // delete the referenced object: clear the weakref
+ assert(Py_REFCNT(obj) == 1);
+ Py_DECREF(obj);
+
+ // test PyWeakref_GET_OBJECT(), reference is dead
+ assert(PyWeakref_GET_OBJECT(weakref) == Py_None);
+
+ // test PyWeakref_GetRef(), reference is dead
+ ref = Py_True;
+ assert(PyWeakref_GetRef(weakref, &ref) == 0);
+ assert(ref == NULL);
+
+ // test PyWeakref_Check(), not a weakref object
+ PyObject *invalid_weakref = Py_None;
+ assert(!PyWeakref_Check(invalid_weakref));
+ assert(!PyWeakref_CheckRefExact(invalid_weakref));
+ assert(!PyWeakref_CheckRefExact(invalid_weakref));
+
+ // test PyWeakref_GetRef(), invalid type
+ assert(!PyErr_Occurred());
+ ref = Py_True;
+ assert(PyWeakref_GetRef(invalid_weakref, &ref) == -1);
+ assert(PyErr_ExceptionMatches(PyExc_TypeError));
+ PyErr_Clear();
+ assert(ref == NULL);
+
+ // test PyWeakref_GetObject(), invalid type
+ assert(PyWeakref_GetObject(invalid_weakref) == NULL);
+ assert(PyErr_ExceptionMatches(PyExc_SystemError));
+ PyErr_Clear();
+
+ // test PyWeakref_GetRef(NULL)
+ ref = Py_True; // marker to check that value was set
+ assert(PyWeakref_GetRef(NULL, &ref) == -1);
+ assert(PyErr_ExceptionMatches(PyExc_SystemError));
+ assert(ref == NULL);
+ PyErr_Clear();
+
+ // test PyWeakref_GetObject(NULL)
+ assert(PyWeakref_GetObject(NULL) == NULL);
+ assert(PyErr_ExceptionMatches(PyExc_SystemError));
+ PyErr_Clear();
+
+ Py_DECREF(weakref);
+
Py_RETURN_NONE;
+
+ _Py_COMP_DIAG_POP
}
@@ -3357,6 +3496,7 @@ static PyMethodDef TestMethods[] = {
{"test_get_statictype_slots", test_get_statictype_slots, METH_NOARGS},
{"test_get_type_name", test_get_type_name, METH_NOARGS},
{"test_get_type_qualname", test_get_type_qualname, METH_NOARGS},
+ {"test_get_type_dict", test_get_type_dict, METH_NOARGS},
{"_test_thread_state", test_thread_state, METH_VARARGS},
#ifndef MS_WINDOWS
{"_spawn_pthread_waiter", spawn_pthread_waiter, METH_NOARGS},
@@ -3467,7 +3607,8 @@ static PyMethodDef TestMethods[] = {
{"function_set_defaults", function_set_defaults, METH_VARARGS, NULL},
{"function_get_kw_defaults", function_get_kw_defaults, METH_O, NULL},
{"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL},
- {"test_atexit", test_atexit, METH_NOARGS},
+ {"check_pyimport_addmodule", check_pyimport_addmodule, METH_VARARGS},
+ {"test_weakref_capi", test_weakref_capi, METH_NOARGS},
{NULL, NULL} /* sentinel */
};
@@ -4067,9 +4208,6 @@ PyInit__testcapi(void)
if (_PyTestCapi_Init_GetArgs(m) < 0) {
return NULL;
}
- if (_PyTestCapi_Init_PyTime(m) < 0) {
- return NULL;
- }
if (_PyTestCapi_Init_DateTime(m) < 0) {
return NULL;
}
diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c
index 6ff55a2755cf5a..26cdb4371ca24c 100644
--- a/Modules/_testclinic.c
+++ b/Modules/_testclinic.c
@@ -5,8 +5,6 @@
/* Always enable assertions */
#undef NDEBUG
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index b43dc7fbf3236c..271ad6cfcaee32 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -9,26 +9,31 @@
/* Always enable assertions */
#undef NDEBUG
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "frameobject.h"
+#include "interpreteridobject.h" // _PyInterpreterID_LookUp()
#include "pycore_atomic_funcs.h" // _Py_atomic_int_get()
#include "pycore_bitutils.h" // _Py_bswap32()
-#include "pycore_compile.h" // _PyCompile_CodeGen, _PyCompile_OptimizeCfg, _PyCompile_Assemble
+#include "pycore_bytesobject.h" // _PyBytes_Find()
+#include "pycore_compile.h" // _PyCompile_CodeGen, _PyCompile_OptimizeCfg, _PyCompile_Assemble, _PyCompile_CleanDoc
+#include "pycore_ceval.h" // _PyEval_AddPendingCall
#include "pycore_fileutils.h" // _Py_normpath
#include "pycore_frame.h" // _PyInterpreterFrame
#include "pycore_gc.h" // PyGC_Head
#include "pycore_hashtable.h" // _Py_hashtable_new()
#include "pycore_initconfig.h" // _Py_GetConfigsAsDict()
-#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
#include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy()
+#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
#include "pycore_pyerrors.h" // _Py_UTF8_Edit_Cost()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "osdefs.h" // MAXPATHLEN
#include "clinic/_testinternalcapi.c.h"
+#ifdef MS_WINDOWS
+# include // struct timeval
+#endif
+
#define MODULE_NAME "_testinternalcapi"
@@ -439,6 +444,118 @@ test_edit_cost(PyObject *self, PyObject *Py_UNUSED(args))
}
+static int
+check_bytes_find(const char *haystack0, const char *needle0,
+ int offset, Py_ssize_t expected)
+{
+ Py_ssize_t len_haystack = strlen(haystack0);
+ Py_ssize_t len_needle = strlen(needle0);
+ Py_ssize_t result_1 = _PyBytes_Find(haystack0, len_haystack,
+ needle0, len_needle, offset);
+ if (result_1 != expected) {
+ PyErr_Format(PyExc_AssertionError,
+ "Incorrect result_1: '%s' in '%s' (offset=%zd)",
+ needle0, haystack0, offset);
+ return -1;
+ }
+ // Allocate new buffer with no NULL terminator.
+ char *haystack = PyMem_Malloc(len_haystack);
+ if (haystack == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ char *needle = PyMem_Malloc(len_needle);
+ if (needle == NULL) {
+ PyMem_Free(haystack);
+ PyErr_NoMemory();
+ return -1;
+ }
+ memcpy(haystack, haystack0, len_haystack);
+ memcpy(needle, needle0, len_needle);
+ Py_ssize_t result_2 = _PyBytes_Find(haystack, len_haystack,
+ needle, len_needle, offset);
+ PyMem_Free(haystack);
+ PyMem_Free(needle);
+ if (result_2 != expected) {
+ PyErr_Format(PyExc_AssertionError,
+ "Incorrect result_2: '%s' in '%s' (offset=%zd)",
+ needle0, haystack0, offset);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+check_bytes_find_large(Py_ssize_t len_haystack, Py_ssize_t len_needle,
+ const char *needle)
+{
+ char *zeros = PyMem_RawCalloc(len_haystack, 1);
+ if (zeros == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ Py_ssize_t res = _PyBytes_Find(zeros, len_haystack, needle, len_needle, 0);
+ PyMem_RawFree(zeros);
+ if (res != -1) {
+ PyErr_Format(PyExc_AssertionError,
+ "check_bytes_find_large(%zd, %zd) found %zd",
+ len_haystack, len_needle, res);
+ return -1;
+ }
+ return 0;
+}
+
+static PyObject *
+test_bytes_find(PyObject *self, PyObject *Py_UNUSED(args))
+{
+ #define CHECK(H, N, O, E) do { \
+ if (check_bytes_find(H, N, O, E) < 0) { \
+ return NULL; \
+ } \
+ } while (0)
+
+ CHECK("", "", 0, 0);
+ CHECK("Python", "", 0, 0);
+ CHECK("Python", "", 3, 3);
+ CHECK("Python", "", 6, 6);
+ CHECK("Python", "yth", 0, 1);
+ CHECK("ython", "yth", 1, 1);
+ CHECK("thon", "yth", 2, -1);
+ CHECK("Python", "thon", 0, 2);
+ CHECK("ython", "thon", 1, 2);
+ CHECK("thon", "thon", 2, 2);
+ CHECK("hon", "thon", 3, -1);
+ CHECK("Pytho", "zz", 0, -1);
+ CHECK("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "ab", 0, -1);
+ CHECK("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "ba", 0, -1);
+ CHECK("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bb", 0, -1);
+ CHECK("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", "ab", 0, 30);
+ CHECK("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaba", "ba", 0, 30);
+ CHECK("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabb", "bb", 0, 30);
+ #undef CHECK
+
+ // Hunt for segfaults
+ // n, m chosen here so that (n - m) % (m + 1) == 0
+ // This would make default_find in fastsearch.h access haystack[n].
+ if (check_bytes_find_large(2048, 2, "ab") < 0) {
+ return NULL;
+ }
+ if (check_bytes_find_large(4096, 16, "0123456789abcdef") < 0) {
+ return NULL;
+ }
+ if (check_bytes_find_large(8192, 2, "ab") < 0) {
+ return NULL;
+ }
+ if (check_bytes_find_large(16384, 4, "abcd") < 0) {
+ return NULL;
+ }
+ if (check_bytes_find_large(32768, 2, "ab") < 0) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+
static PyObject *
normalize_path(PyObject *self, PyObject *filename)
{
@@ -555,7 +672,7 @@ static PyObject *
set_eval_frame_default(PyObject *self, PyObject *Py_UNUSED(args))
{
module_state *state = get_module_state(self);
- _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), _PyEval_EvalFrameDefault);
+ _PyInterpreterState_SetEvalFrameFunc(_PyInterpreterState_GET(), _PyEval_EvalFrameDefault);
Py_CLEAR(state->record_list);
Py_RETURN_NONE;
}
@@ -583,10 +700,27 @@ set_eval_frame_record(PyObject *self, PyObject *list)
return NULL;
}
Py_XSETREF(state->record_list, Py_NewRef(list));
- _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), record_eval);
+ _PyInterpreterState_SetEvalFrameFunc(_PyInterpreterState_GET(), record_eval);
Py_RETURN_NONE;
}
+/*[clinic input]
+
+_testinternalcapi.compiler_cleandoc -> object
+
+ doc: unicode
+
+C implementation of inspect.cleandoc().
+[clinic start generated code]*/
+
+static PyObject *
+_testinternalcapi_compiler_cleandoc_impl(PyObject *module, PyObject *doc)
+/*[clinic end generated code: output=2dd203a80feff5bc input=2de03fab931d9cdc]*/
+{
+ return _PyCompile_CleanDoc(doc);
+}
+
+
/*[clinic input]
_testinternalcapi.compiler_codegen -> object
@@ -828,6 +962,12 @@ get_counter_optimizer(PyObject *self, PyObject *arg)
return PyUnstable_Optimizer_NewCounter();
}
+static PyObject *
+get_uop_optimizer(PyObject *self, PyObject *arg)
+{
+ return PyUnstable_Optimizer_NewUOpOptimizer();
+}
+
static PyObject *
set_optimizer(PyObject *self, PyObject *opt)
{
@@ -838,6 +978,474 @@ set_optimizer(PyObject *self, PyObject *opt)
Py_RETURN_NONE;
}
+static PyObject *
+get_optimizer(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ PyObject *opt = (PyObject *)PyUnstable_GetOptimizer();
+ if (opt == NULL) {
+ Py_RETURN_NONE;
+ }
+ return opt;
+}
+
+static PyObject *
+get_executor(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+
+ if (!_PyArg_CheckPositional("get_executor", nargs, 2, 2)) {
+ return NULL;
+ }
+ PyObject *code = args[0];
+ PyObject *offset = args[1];
+ long ioffset = PyLong_AsLong(offset);
+ if (ioffset == -1 && PyErr_Occurred()) {
+ return NULL;
+ }
+ if (!PyCode_Check(code)) {
+ PyErr_SetString(PyExc_TypeError, "first argument must be a code object");
+ return NULL;
+ }
+ return (PyObject *)PyUnstable_GetExecutor((PyCodeObject *)code, ioffset);
+}
+
+static int _pending_callback(void *arg)
+{
+ /* we assume the argument is callable object to which we own a reference */
+ PyObject *callable = (PyObject *)arg;
+ PyObject *r = PyObject_CallNoArgs(callable);
+ Py_DECREF(callable);
+ Py_XDECREF(r);
+ return r != NULL ? 0 : -1;
+}
+
+/* The following requests n callbacks to _pending_callback. It can be
+ * run from any python thread.
+ */
+static PyObject *
+pending_threadfunc(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ PyObject *callable;
+ int ensure_added = 0;
+ static char *kwlist[] = {"", "ensure_added", NULL};
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O|$p:pending_threadfunc", kwlist,
+ &callable, &ensure_added))
+ {
+ return NULL;
+ }
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+
+ /* create the reference for the callbackwhile we hold the lock */
+ Py_INCREF(callable);
+
+ int r;
+ Py_BEGIN_ALLOW_THREADS
+ r = _PyEval_AddPendingCall(interp, &_pending_callback, callable, 0);
+ Py_END_ALLOW_THREADS
+ if (r < 0) {
+ /* unsuccessful add */
+ if (!ensure_added) {
+ Py_DECREF(callable);
+ Py_RETURN_FALSE;
+ }
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ r = _PyEval_AddPendingCall(interp, &_pending_callback, callable, 0);
+ Py_END_ALLOW_THREADS
+ } while (r < 0);
+ }
+
+ Py_RETURN_TRUE;
+}
+
+
+static struct {
+ int64_t interpid;
+} pending_identify_result;
+
+static int
+_pending_identify_callback(void *arg)
+{
+ PyThread_type_lock mutex = (PyThread_type_lock)arg;
+ assert(pending_identify_result.interpid == -1);
+ PyThreadState *tstate = PyThreadState_Get();
+ pending_identify_result.interpid = PyInterpreterState_GetID(tstate->interp);
+ PyThread_release_lock(mutex);
+ return 0;
+}
+
+static PyObject *
+pending_identify(PyObject *self, PyObject *args)
+{
+ PyObject *interpid;
+ if (!PyArg_ParseTuple(args, "O:pending_identify", &interpid)) {
+ return NULL;
+ }
+ PyInterpreterState *interp = _PyInterpreterID_LookUp(interpid);
+ if (interp == NULL) {
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_ValueError, "interpreter not found");
+ }
+ return NULL;
+ }
+
+ pending_identify_result.interpid = -1;
+
+ PyThread_type_lock mutex = PyThread_allocate_lock();
+ if (mutex == NULL) {
+ return NULL;
+ }
+ PyThread_acquire_lock(mutex, WAIT_LOCK);
+ /* It gets released in _pending_identify_callback(). */
+
+ int r;
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ r = _PyEval_AddPendingCall(interp,
+ &_pending_identify_callback, (void *)mutex,
+ 0);
+ Py_END_ALLOW_THREADS
+ } while (r < 0);
+
+ /* Wait for the pending call to complete. */
+ PyThread_acquire_lock(mutex, WAIT_LOCK);
+ PyThread_release_lock(mutex);
+ PyThread_free_lock(mutex);
+
+ PyObject *res = PyLong_FromLongLong(pending_identify_result.interpid);
+ pending_identify_result.interpid = -1;
+ if (res == NULL) {
+ return NULL;
+ }
+ return res;
+}
+
+
+static PyObject *
+test_pytime_fromseconds(PyObject *self, PyObject *args)
+{
+ int seconds;
+ if (!PyArg_ParseTuple(args, "i", &seconds)) {
+ return NULL;
+ }
+ _PyTime_t ts = _PyTime_FromSeconds(seconds);
+ return _PyTime_AsNanosecondsObject(ts);
+}
+
+static int
+check_time_rounding(int round)
+{
+ if (round != _PyTime_ROUND_FLOOR
+ && round != _PyTime_ROUND_CEILING
+ && round != _PyTime_ROUND_HALF_EVEN
+ && round != _PyTime_ROUND_UP)
+ {
+ PyErr_SetString(PyExc_ValueError, "invalid rounding");
+ return -1;
+ }
+ return 0;
+}
+
+static PyObject *
+test_pytime_fromsecondsobject(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ int round;
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+ return NULL;
+ }
+ if (check_time_rounding(round) < 0) {
+ return NULL;
+ }
+ _PyTime_t ts;
+ if (_PyTime_FromSecondsObject(&ts, obj, round) == -1) {
+ return NULL;
+ }
+ return _PyTime_AsNanosecondsObject(ts);
+}
+
+static PyObject *
+test_pytime_assecondsdouble(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ if (!PyArg_ParseTuple(args, "O", &obj)) {
+ return NULL;
+ }
+ _PyTime_t ts;
+ if (_PyTime_FromNanosecondsObject(&ts, obj) < 0) {
+ return NULL;
+ }
+ double d = _PyTime_AsSecondsDouble(ts);
+ return PyFloat_FromDouble(d);
+}
+
+static PyObject *
+test_PyTime_AsTimeval(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ int round;
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+ return NULL;
+ }
+ if (check_time_rounding(round) < 0) {
+ return NULL;
+ }
+ _PyTime_t t;
+ if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+ return NULL;
+ }
+ struct timeval tv;
+ if (_PyTime_AsTimeval(t, &tv, round) < 0) {
+ return NULL;
+ }
+
+ PyObject *seconds = PyLong_FromLongLong(tv.tv_sec);
+ if (seconds == NULL) {
+ return NULL;
+ }
+ return Py_BuildValue("Nl", seconds, (long)tv.tv_usec);
+}
+
+static PyObject *
+test_PyTime_AsTimeval_clamp(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ int round;
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+ return NULL;
+ }
+ if (check_time_rounding(round) < 0) {
+ return NULL;
+ }
+ _PyTime_t t;
+ if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+ return NULL;
+ }
+ struct timeval tv;
+ _PyTime_AsTimeval_clamp(t, &tv, round);
+
+ PyObject *seconds = PyLong_FromLongLong(tv.tv_sec);
+ if (seconds == NULL) {
+ return NULL;
+ }
+ return Py_BuildValue("Nl", seconds, (long)tv.tv_usec);
+}
+
+#ifdef HAVE_CLOCK_GETTIME
+static PyObject *
+test_PyTime_AsTimespec(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ if (!PyArg_ParseTuple(args, "O", &obj)) {
+ return NULL;
+ }
+ _PyTime_t t;
+ if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+ return NULL;
+ }
+ struct timespec ts;
+ if (_PyTime_AsTimespec(t, &ts) == -1) {
+ return NULL;
+ }
+ return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec);
+}
+
+static PyObject *
+test_PyTime_AsTimespec_clamp(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ if (!PyArg_ParseTuple(args, "O", &obj)) {
+ return NULL;
+ }
+ _PyTime_t t;
+ if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+ return NULL;
+ }
+ struct timespec ts;
+ _PyTime_AsTimespec_clamp(t, &ts);
+ return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec);
+}
+#endif
+
+static PyObject *
+test_PyTime_AsMilliseconds(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ int round;
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+ return NULL;
+ }
+ _PyTime_t t;
+ if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+ return NULL;
+ }
+ if (check_time_rounding(round) < 0) {
+ return NULL;
+ }
+ _PyTime_t ms = _PyTime_AsMilliseconds(t, round);
+ _PyTime_t ns = _PyTime_FromNanoseconds(ms);
+ return _PyTime_AsNanosecondsObject(ns);
+}
+
+static PyObject *
+test_PyTime_AsMicroseconds(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ int round;
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+ return NULL;
+ }
+ _PyTime_t t;
+ if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+ return NULL;
+ }
+ if (check_time_rounding(round) < 0) {
+ return NULL;
+ }
+ _PyTime_t us = _PyTime_AsMicroseconds(t, round);
+ _PyTime_t ns = _PyTime_FromNanoseconds(us);
+ return _PyTime_AsNanosecondsObject(ns);
+}
+
+static PyObject *
+test_pytime_object_to_time_t(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ time_t sec;
+ int round;
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+ return NULL;
+ }
+ if (check_time_rounding(round) < 0) {
+ return NULL;
+ }
+ if (_PyTime_ObjectToTime_t(obj, &sec, round) == -1) {
+ return NULL;
+ }
+ return _PyLong_FromTime_t(sec);
+}
+
+static PyObject *
+test_pytime_object_to_timeval(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ time_t sec;
+ long usec;
+ int round;
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+ return NULL;
+ }
+ if (check_time_rounding(round) < 0) {
+ return NULL;
+ }
+ if (_PyTime_ObjectToTimeval(obj, &sec, &usec, round) == -1) {
+ return NULL;
+ }
+ return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), usec);
+}
+
+static PyObject *
+test_pytime_object_to_timespec(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ time_t sec;
+ long nsec;
+ int round;
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+ return NULL;
+ }
+ if (check_time_rounding(round) < 0) {
+ return NULL;
+ }
+ if (_PyTime_ObjectToTimespec(obj, &sec, &nsec, round) == -1) {
+ return NULL;
+ }
+ return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec);
+}
+
+
+static PyObject *
+tracemalloc_get_traceback(PyObject *self, PyObject *args)
+{
+ unsigned int domain;
+ PyObject *ptr_obj;
+
+ if (!PyArg_ParseTuple(args, "IO", &domain, &ptr_obj)) {
+ return NULL;
+ }
+ void *ptr = PyLong_AsVoidPtr(ptr_obj);
+ if (PyErr_Occurred()) {
+ return NULL;
+ }
+
+ return _PyTraceMalloc_GetTraceback(domain, (uintptr_t)ptr);
+}
+
+
+// Test PyThreadState C API
+static PyObject *
+test_tstate_capi(PyObject *self, PyObject *Py_UNUSED(args))
+{
+ // PyThreadState_Get()
+ PyThreadState *tstate = PyThreadState_Get();
+ assert(tstate != NULL);
+
+ // test _PyThreadState_GetDict()
+ PyObject *dict = PyThreadState_GetDict();
+ assert(dict != NULL);
+ // dict is a borrowed reference
+
+ PyObject *dict2 = _PyThreadState_GetDict(tstate);
+ assert(dict2 == dict);
+ // dict2 is a borrowed reference
+
+ Py_RETURN_NONE;
+}
+
+
+/* Test _PyUnicode_TransformDecimalAndSpaceToASCII() */
+static PyObject *
+unicode_transformdecimalandspacetoascii(PyObject *self, PyObject *arg)
+{
+ if (arg == Py_None) {
+ arg = NULL;
+ }
+ return _PyUnicode_TransformDecimalAndSpaceToASCII(arg);
+}
+
+
+struct atexit_data {
+ int called;
+};
+
+static void
+callback(void *data)
+{
+ ((struct atexit_data *)data)->called += 1;
+}
+
+static PyObject *
+test_atexit(PyObject *self, PyObject *Py_UNUSED(args))
+{
+ PyThreadState *oldts = PyThreadState_Swap(NULL);
+ PyThreadState *tstate = Py_NewInterpreter();
+
+ struct atexit_data data = {0};
+ int res = _Py_AtExit(tstate->interp, callback, (void *)&data);
+ Py_EndInterpreter(tstate);
+ PyThreadState_Swap(oldts);
+ if (res < 0) {
+ return NULL;
+ }
+
+ if (data.called == 0) {
+ PyErr_SetString(PyExc_RuntimeError, "atexit callback not called");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+
static PyMethodDef module_functions[] = {
{"get_configs", get_configs, METH_NOARGS},
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
@@ -850,12 +1458,14 @@ static PyMethodDef module_functions[] = {
{"reset_path_config", test_reset_path_config, METH_NOARGS},
{"test_atomic_funcs", test_atomic_funcs, METH_NOARGS},
{"test_edit_cost", test_edit_cost, METH_NOARGS},
+ {"test_bytes_find", test_bytes_find, METH_NOARGS},
{"normalize_path", normalize_path, METH_O, NULL},
{"get_getpath_codeobject", get_getpath_codeobject, METH_NOARGS, NULL},
{"EncodeLocaleEx", encode_locale_ex, METH_VARARGS},
{"DecodeLocaleEx", decode_locale_ex, METH_VARARGS},
{"set_eval_frame_default", set_eval_frame_default, METH_NOARGS, NULL},
{"set_eval_frame_record", set_eval_frame_record, METH_O, NULL},
+ _TESTINTERNALCAPI_COMPILER_CLEANDOC_METHODDEF
_TESTINTERNALCAPI_COMPILER_CODEGEN_METHODDEF
_TESTINTERNALCAPI_OPTIMIZE_CFG_METHODDEF
_TESTINTERNALCAPI_ASSEMBLE_CODE_OBJECT_METHODDEF
@@ -866,8 +1476,32 @@ static PyMethodDef module_functions[] = {
{"iframe_getcode", iframe_getcode, METH_O, NULL},
{"iframe_getline", iframe_getline, METH_O, NULL},
{"iframe_getlasti", iframe_getlasti, METH_O, NULL},
+ {"get_optimizer", get_optimizer, METH_NOARGS, NULL},
{"set_optimizer", set_optimizer, METH_O, NULL},
+ {"get_executor", _PyCFunction_CAST(get_executor), METH_FASTCALL, NULL},
{"get_counter_optimizer", get_counter_optimizer, METH_NOARGS, NULL},
+ {"get_uop_optimizer", get_uop_optimizer, METH_NOARGS, NULL},
+ {"pending_threadfunc", _PyCFunction_CAST(pending_threadfunc),
+ METH_VARARGS | METH_KEYWORDS},
+ {"pending_identify", pending_identify, METH_VARARGS, NULL},
+ {"_PyTime_AsMicroseconds", test_PyTime_AsMicroseconds, METH_VARARGS},
+ {"_PyTime_AsMilliseconds", test_PyTime_AsMilliseconds, METH_VARARGS},
+ {"_PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS},
+#ifdef HAVE_CLOCK_GETTIME
+ {"_PyTime_AsTimespec", test_PyTime_AsTimespec, METH_VARARGS},
+ {"_PyTime_AsTimespec_clamp", test_PyTime_AsTimespec_clamp, METH_VARARGS},
+#endif
+ {"_PyTime_AsTimeval", test_PyTime_AsTimeval, METH_VARARGS},
+ {"_PyTime_AsTimeval_clamp", test_PyTime_AsTimeval_clamp, METH_VARARGS},
+ {"_PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS},
+ {"_PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS},
+ {"_PyTime_ObjectToTime_t", test_pytime_object_to_time_t, METH_VARARGS},
+ {"_PyTime_ObjectToTimespec", test_pytime_object_to_timespec, METH_VARARGS},
+ {"_PyTime_ObjectToTimeval", test_pytime_object_to_timeval, METH_VARARGS},
+ {"_PyTraceMalloc_GetTraceback", tracemalloc_get_traceback, METH_VARARGS},
+ {"test_tstate_capi", test_tstate_capi, METH_NOARGS, NULL},
+ {"_PyUnicode_TransformDecimalAndSpaceToASCII", unicode_transformdecimalandspacetoascii, METH_O},
+ {"test_atexit", test_atexit, METH_NOARGS},
{NULL, NULL} /* sentinel */
};
@@ -882,6 +1516,11 @@ module_exec(PyObject *module)
return 1;
}
+ if (PyModule_AddObject(module, "SIZEOF_TIME_T",
+ PyLong_FromSsize_t(sizeof(time_t))) < 0) {
+ return 1;
+ }
+
return 0;
}
diff --git a/Modules/_testsinglephase.c b/Modules/_testsinglephase.c
index dca7abff89146e..922b41005e8419 100644
--- a/Modules/_testsinglephase.c
+++ b/Modules/_testsinglephase.c
@@ -8,6 +8,7 @@
//#include
#include "Python.h"
#include "pycore_namespace.h" // _PyNamespace_New()
+#include "pycore_time.h" // _PyTime_t
typedef struct {
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index b6f878e07526db..82393309b67039 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -7,6 +7,7 @@
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_pylifecycle.h"
#include "pycore_pystate.h" // _PyThreadState_SetCurrent()
+#include "pycore_weakref.h" // _PyWeakref_GET_REF()
#include // offsetof()
#include "structmember.h" // PyMemberDef
@@ -81,6 +82,7 @@ lock_dealloc(lockobject *self)
static PyLockStatus
acquire_timed(PyThread_type_lock lock, _PyTime_t timeout)
{
+ PyThreadState *tstate = _PyThreadState_GET();
_PyTime_t endtime = 0;
if (timeout > 0) {
endtime = _PyDeadline_Init(timeout);
@@ -103,7 +105,7 @@ acquire_timed(PyThread_type_lock lock, _PyTime_t timeout)
/* Run signal handlers if we were interrupted. Propagate
* exceptions from signal handlers, such as KeyboardInterrupt, by
* passing up PY_LOCK_INTR. */
- if (Py_MakePendingCalls() < 0) {
+ if (_PyEval_MakePendingCalls(tstate) < 0) {
return PY_LOCK_INTR;
}
@@ -1023,15 +1025,13 @@ local_getattro(localobject *self, PyObject *name)
static PyObject *
_localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
{
- assert(PyWeakref_CheckRef(localweakref));
- PyObject *obj = PyWeakref_GET_OBJECT(localweakref);
- if (obj == Py_None) {
+ localobject *self = (localobject *)_PyWeakref_GET_REF(localweakref);
+ if (self == NULL) {
Py_RETURN_NONE;
}
/* If the thread-local object is still alive and not being cleared,
remove the corresponding local dict */
- localobject *self = (localobject *)Py_NewRef(obj);
if (self->dummies != NULL) {
PyObject *ldict;
ldict = PyDict_GetItemWithError(self->dummies, dummyweakref);
@@ -1039,9 +1039,9 @@ _localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
PyDict_DelItem(self->dummies, dummyweakref);
}
if (PyErr_Occurred())
- PyErr_WriteUnraisable(obj);
+ PyErr_WriteUnraisable((PyObject*)self);
}
- Py_DECREF(obj);
+ Py_DECREF(self);
Py_RETURN_NONE;
}
@@ -1104,7 +1104,7 @@ thread_run(void *boot_raw)
static PyObject *
thread_daemon_threads_allowed(PyObject *module, PyObject *Py_UNUSED(ignored))
{
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
if (interp->feature_flags & Py_RTFLAGS_DAEMON_THREADS) {
Py_RETURN_TRUE;
}
@@ -1313,24 +1313,25 @@ This function is meant for internal and specialized purposes only.\n\
In most applications `threading.enumerate()` should be used instead.");
static void
-release_sentinel(void *wr_raw)
+release_sentinel(void *weakref_raw)
{
- PyObject *wr = _PyObject_CAST(wr_raw);
+ PyObject *weakref = _PyObject_CAST(weakref_raw);
+
/* Tricky: this function is called when the current thread state
is being deleted. Therefore, only simple C code can safely
execute here. */
- PyObject *obj = PyWeakref_GET_OBJECT(wr);
- lockobject *lock;
- if (obj != Py_None) {
- lock = (lockobject *) obj;
+ lockobject *lock = (lockobject *)_PyWeakref_GET_REF(weakref);
+ if (lock != NULL) {
if (lock->locked) {
PyThread_release_lock(lock->lock_lock);
lock->locked = 0;
}
+ Py_DECREF(lock);
}
+
/* Deallocating a weakref with a NULL callback only calls
PyObject_GC_Del(), which can't call any Python code. */
- Py_DECREF(wr);
+ Py_DECREF(weakref);
}
static PyObject *
@@ -1437,7 +1438,7 @@ thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
PyObject *name = NULL;
if (thread != Py_None) {
- if (_PyObject_LookupAttr(thread, &_Py_ID(name), &name) < 0) {
+ if (PyObject_GetOptionalAttr(thread, &_Py_ID(name), &name) < 0) {
return -1;
}
}
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 97e5b2f738aa2a..76af803bd6eefb 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -21,7 +21,6 @@ Copyright (C) 1994 Steen Lumholt.
*/
-#define PY_SSIZE_T_CLEAN
#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
#endif
diff --git a/Modules/_typingmodule.c b/Modules/_typingmodule.c
index 39a124a26adf31..59d3a80a9305db 100644
--- a/Modules/_typingmodule.c
+++ b/Modules/_typingmodule.c
@@ -5,8 +5,9 @@
#endif
#include "Python.h"
-#include "internal/pycore_interp.h"
-#include "internal/pycore_typevarobject.h"
+#include "pycore_interp.h"
+#include "pycore_pystate.h" // _PyInterpreterState_GET()
+#include "pycore_typevarobject.h"
#include "clinic/_typingmodule.c.h"
/*[clinic input]
@@ -44,7 +45,7 @@ PyDoc_STRVAR(typing_doc,
static int
_typing_exec(PyObject *m)
{
- PyInterpreterState *interp = PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
#define EXPORT_TYPE(name, typename) \
if (PyModule_AddObjectRef(m, name, \
diff --git a/Modules/_uuidmodule.c b/Modules/_uuidmodule.c
index ed3b2fedfd4d88..2f5be1c5144d83 100644
--- a/Modules/_uuidmodule.c
+++ b/Modules/_uuidmodule.c
@@ -3,8 +3,6 @@
* DCE compatible Universally Unique Identifier library.
*/
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#if defined(HAVE_UUID_H)
// AIX, FreeBSD, libuuid with pkgconf
diff --git a/Modules/_weakref.c b/Modules/_weakref.c
index 387b8fa9d0a6f1..b5d80cbd731a28 100644
--- a/Modules/_weakref.c
+++ b/Modules/_weakref.c
@@ -1,5 +1,6 @@
#include "Python.h"
-#include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR
+#include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR
+#include "pycore_weakref.h" // _PyWeakref_IS_DEAD()
#define GET_WEAKREFS_LISTPTR(o) \
@@ -43,7 +44,7 @@ is_dead_weakref(PyObject *value)
PyErr_SetString(PyExc_TypeError, "not a weakref");
return -1;
}
- return PyWeakref_GET_OBJECT(value) == Py_None;
+ return _PyWeakref_IS_DEAD(value);
}
/*[clinic input]
@@ -88,25 +89,22 @@ static PyObject *
_weakref_getweakrefs(PyObject *module, PyObject *object)
/*[clinic end generated code: output=25c7731d8e011824 input=00c6d0e5d3206693]*/
{
- PyObject *result = NULL;
-
- if (_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) {
- PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
- Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list);
-
- result = PyList_New(count);
- if (result != NULL) {
- PyWeakReference *current = *list;
- Py_ssize_t i;
- for (i = 0; i < count; ++i) {
- PyList_SET_ITEM(result, i, (PyObject *) current);
- Py_INCREF(current);
- current = current->wr_next;
- }
- }
+ if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) {
+ return PyList_New(0);
}
- else {
- result = PyList_New(0);
+
+ PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
+ Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list);
+
+ PyObject *result = PyList_New(count);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ PyWeakReference *current = *list;
+ for (Py_ssize_t i = 0; i < count; ++i) {
+ PyList_SET_ITEM(result, i, Py_NewRef(current));
+ current = current->wr_next;
}
return result;
}
diff --git a/Modules/_winapi.c b/Modules/_winapi.c
index af13014bf201b0..313c12a34c6725 100644
--- a/Modules/_winapi.c
+++ b/Modules/_winapi.c
@@ -36,6 +36,8 @@
#include "Python.h"
#include "pycore_moduleobject.h" // _PyModule_GetState()
+#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
+#include "pycore_pystate.h" // _PyInterpreterState_GET
#include "structmember.h" // PyMemberDef
@@ -133,7 +135,7 @@ overlapped_dealloc(OverlappedObject *self)
{
/* The operation is no longer pending -- nothing to do. */
}
- else if (_Py_IsInterpreterFinalizing(PyInterpreterState_Get()))
+ else if (_Py_IsInterpreterFinalizing(_PyInterpreterState_GET()))
{
/* The operation is still pending -- give a warning. This
will probably only happen on Windows XP. */
@@ -796,6 +798,17 @@ getenvironment(PyObject* environment)
}
envsize = PyList_GET_SIZE(keys);
+
+ if (envsize == 0) {
+ // A environment block must be terminated by two null characters --
+ // one for the last string and one for the block.
+ buffer = PyMem_Calloc(2, sizeof(wchar_t));
+ if (!buffer) {
+ PyErr_NoMemory();
+ }
+ goto cleanup;
+ }
+
if (PyList_GET_SIZE(values) != envsize) {
PyErr_SetString(PyExc_RuntimeError,
"environment changed size during iteration");
@@ -869,7 +882,8 @@ getenvironment(PyObject* environment)
*p++ = L'\0';
assert(p == end);
- error:
+cleanup:
+error:
Py_XDECREF(keys);
Py_XDECREF(values);
return buffer;
diff --git a/Modules/_xxinterpchannelsmodule.c b/Modules/_xxinterpchannelsmodule.c
index 1d7e7f1d71af3e..82472555ec7d62 100644
--- a/Modules/_xxinterpchannelsmodule.c
+++ b/Modules/_xxinterpchannelsmodule.c
@@ -1,9 +1,13 @@
-
/* interpreters module */
/* low-level access to interpreter primitives */
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "Python.h"
#include "interpreteridobject.h"
+#include "pycore_atexit.h" // _Py_AtExit()
/*
diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c
index 4801f37d6f6c5f..d2e0593872c5f0 100644
--- a/Modules/_xxsubinterpretersmodule.c
+++ b/Modules/_xxsubinterpretersmodule.c
@@ -1,8 +1,12 @@
-
/* interpreters module */
/* low-level access to interpreter primitives */
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "Python.h"
+#include "pycore_interp.h" // _PyInterpreterState_GetMainModule()
#include "interpreteridobject.h"
@@ -269,7 +273,7 @@ _sharedexception_bind(PyObject *exc, _sharedexception *sharedexc)
assert(exc != NULL);
const char *failure = NULL;
- PyObject *nameobj = PyUnicode_FromFormat("%S", Py_TYPE(exc));
+ PyObject *nameobj = PyUnicode_FromString(Py_TYPE(exc)->tp_name);
if (nameobj == NULL) {
failure = "unable to format exception type name";
goto error;
diff --git a/Modules/_xxtestfuzz/_xxtestfuzz.c b/Modules/_xxtestfuzz/_xxtestfuzz.c
index e0694de6719df0..a2dbabce71ed67 100644
--- a/Modules/_xxtestfuzz/_xxtestfuzz.c
+++ b/Modules/_xxtestfuzz/_xxtestfuzz.c
@@ -1,4 +1,3 @@
-#define PY_SSIZE_T_CLEAN
#include
#include
#include
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 16e3739eb26fc3..0000a8d637eb56 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -7,8 +7,8 @@
# define Py_BUILD_CORE_MODULE 1
#endif
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
+#include "pycore_call.h" // _PyObject_CallMethod()
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_bytesobject.h" // _PyBytes_Repeat
#include "structmember.h" // PyMemberDef
@@ -767,10 +767,12 @@ array_richcompare(PyObject *v, PyObject *w, int op)
k = 1;
for (i = 0; i < Py_SIZE(va) && i < Py_SIZE(wa); i++) {
vi = getarrayitem(v, i);
+ if (vi == NULL) {
+ return NULL;
+ }
wi = getarrayitem(w, i);
- if (vi == NULL || wi == NULL) {
- Py_XDECREF(vi);
- Py_XDECREF(wi);
+ if (wi == NULL) {
+ Py_DECREF(vi);
return NULL;
}
k = PyObject_RichCompareBool(vi, wi, Py_EQ);
@@ -2266,7 +2268,7 @@ array_array___reduce_ex___impl(arrayobject *self, PyTypeObject *cls,
if (protocol == -1 && PyErr_Occurred())
return NULL;
- if (_PyObject_LookupAttr((PyObject *)self, state->str___dict__, &dict) < 0) {
+ if (PyObject_GetOptionalAttr((PyObject *)self, state->str___dict__, &dict) < 0) {
return NULL;
}
if (dict == NULL) {
@@ -2679,6 +2681,15 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
}
+ if (c == 'u') {
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "The 'u' type code is deprecated and "
+ "will be removed in Python 3.16",
+ 1)) {
+ return NULL;
+ }
+ }
+
bool is_unicode = c == 'u' || c == 'w';
if (initial && !is_unicode) {
diff --git a/Modules/binascii.c b/Modules/binascii.c
index 356947d43e43a9..cf9328795c2bcc 100644
--- a/Modules/binascii.c
+++ b/Modules/binascii.c
@@ -57,8 +57,6 @@
# define Py_BUILD_CORE_MODULE 1
#endif
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "pycore_long.h" // _PyLong_DigitValue
#include "pycore_strhex.h" // _Py_strhex_bytes_with_sep()
diff --git a/Modules/cjkcodecs/cjkcodecs.h b/Modules/cjkcodecs/cjkcodecs.h
index 36bc7024df9acc..ee588785e7403f 100644
--- a/Modules/cjkcodecs/cjkcodecs.h
+++ b/Modules/cjkcodecs/cjkcodecs.h
@@ -7,9 +7,13 @@
#ifndef _CJKCODECS_H_
#define _CJKCODECS_H_
-#define PY_SSIZE_T_CLEAN
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "Python.h"
#include "multibytecodec.h"
+#include "pycore_import.h" // _PyImport_GetModuleAttrString()
/* a unicode "undefined" code point */
diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c
index 2b98bb5ae58bc6..3febd1a832f9cc 100644
--- a/Modules/cjkcodecs/multibytecodec.c
+++ b/Modules/cjkcodecs/multibytecodec.c
@@ -4,7 +4,10 @@
* Written by Hye-Shik Chang
*/
-#define PY_SSIZE_T_CLEAN
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "Python.h"
#include "structmember.h" // PyMemberDef
#include "multibytecodec.h"
@@ -1715,7 +1718,7 @@ mbstreamwriter_iwrite(MultibyteStreamWriterObject *self,
if (str == NULL)
return -1;
- wr = _PyObject_CallMethodOneArg(self->stream, str_write, str);
+ wr = PyObject_CallMethodOneArg(self->stream, str_write, str);
Py_DECREF(str);
if (wr == NULL)
return -1;
@@ -1826,7 +1829,7 @@ _multibytecodec_MultibyteStreamWriter_reset_impl(MultibyteStreamWriterObject *se
if (PyBytes_Size(pwrt) > 0) {
PyObject *wr;
- wr = _PyObject_CallMethodOneArg(self->stream, state->str_write, pwrt);
+ wr = PyObject_CallMethodOneArg(self->stream, state->str_write, pwrt);
if (wr == NULL) {
Py_DECREF(pwrt);
return NULL;
diff --git a/Modules/cjkcodecs/multibytecodec.h b/Modules/cjkcodecs/multibytecodec.h
index f59362205d26fc..5b85e2e3de316d 100644
--- a/Modules/cjkcodecs/multibytecodec.h
+++ b/Modules/cjkcodecs/multibytecodec.h
@@ -10,6 +10,8 @@
extern "C" {
#endif
+#include "pycore_unicodeobject.h" // _PyUnicodeWriter
+
#ifdef uint16_t
typedef uint16_t ucs2_t, DBCHAR;
#else
diff --git a/Modules/clinic/_opcode.c.h b/Modules/clinic/_opcode.c.h
index 3bd3ba02387435..3eb050e470c343 100644
--- a/Modules/clinic/_opcode.c.h
+++ b/Modules/clinic/_opcode.c.h
@@ -86,6 +86,321 @@ _opcode_stack_effect(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
return return_value;
}
+PyDoc_STRVAR(_opcode_is_valid__doc__,
+"is_valid($module, /, opcode)\n"
+"--\n"
+"\n"
+"Return True if opcode is valid, False otherwise.");
+
+#define _OPCODE_IS_VALID_METHODDEF \
+ {"is_valid", _PyCFunction_CAST(_opcode_is_valid), METH_FASTCALL|METH_KEYWORDS, _opcode_is_valid__doc__},
+
+static int
+_opcode_is_valid_impl(PyObject *module, int opcode);
+
+static PyObject *
+_opcode_is_valid(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(opcode), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"opcode", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "is_valid",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[1];
+ int opcode;
+ int _return_value;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ opcode = _PyLong_AsInt(args[0]);
+ if (opcode == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ _return_value = _opcode_is_valid_impl(module, opcode);
+ if ((_return_value == -1) && PyErr_Occurred()) {
+ goto exit;
+ }
+ return_value = PyBool_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_opcode_has_arg__doc__,
+"has_arg($module, /, opcode)\n"
+"--\n"
+"\n"
+"Return True if the opcode uses its oparg, False otherwise.");
+
+#define _OPCODE_HAS_ARG_METHODDEF \
+ {"has_arg", _PyCFunction_CAST(_opcode_has_arg), METH_FASTCALL|METH_KEYWORDS, _opcode_has_arg__doc__},
+
+static int
+_opcode_has_arg_impl(PyObject *module, int opcode);
+
+static PyObject *
+_opcode_has_arg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(opcode), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"opcode", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "has_arg",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[1];
+ int opcode;
+ int _return_value;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ opcode = _PyLong_AsInt(args[0]);
+ if (opcode == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ _return_value = _opcode_has_arg_impl(module, opcode);
+ if ((_return_value == -1) && PyErr_Occurred()) {
+ goto exit;
+ }
+ return_value = PyBool_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_opcode_has_const__doc__,
+"has_const($module, /, opcode)\n"
+"--\n"
+"\n"
+"Return True if the opcode accesses a constant, False otherwise.");
+
+#define _OPCODE_HAS_CONST_METHODDEF \
+ {"has_const", _PyCFunction_CAST(_opcode_has_const), METH_FASTCALL|METH_KEYWORDS, _opcode_has_const__doc__},
+
+static int
+_opcode_has_const_impl(PyObject *module, int opcode);
+
+static PyObject *
+_opcode_has_const(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(opcode), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"opcode", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "has_const",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[1];
+ int opcode;
+ int _return_value;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ opcode = _PyLong_AsInt(args[0]);
+ if (opcode == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ _return_value = _opcode_has_const_impl(module, opcode);
+ if ((_return_value == -1) && PyErr_Occurred()) {
+ goto exit;
+ }
+ return_value = PyBool_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_opcode_has_name__doc__,
+"has_name($module, /, opcode)\n"
+"--\n"
+"\n"
+"Return True if the opcode accesses an attribute by name, False otherwise.");
+
+#define _OPCODE_HAS_NAME_METHODDEF \
+ {"has_name", _PyCFunction_CAST(_opcode_has_name), METH_FASTCALL|METH_KEYWORDS, _opcode_has_name__doc__},
+
+static int
+_opcode_has_name_impl(PyObject *module, int opcode);
+
+static PyObject *
+_opcode_has_name(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(opcode), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"opcode", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "has_name",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[1];
+ int opcode;
+ int _return_value;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ opcode = _PyLong_AsInt(args[0]);
+ if (opcode == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ _return_value = _opcode_has_name_impl(module, opcode);
+ if ((_return_value == -1) && PyErr_Occurred()) {
+ goto exit;
+ }
+ return_value = PyBool_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_opcode_has_jump__doc__,
+"has_jump($module, /, opcode)\n"
+"--\n"
+"\n"
+"Return True if the opcode has a jump target, False otherwise.");
+
+#define _OPCODE_HAS_JUMP_METHODDEF \
+ {"has_jump", _PyCFunction_CAST(_opcode_has_jump), METH_FASTCALL|METH_KEYWORDS, _opcode_has_jump__doc__},
+
+static int
+_opcode_has_jump_impl(PyObject *module, int opcode);
+
+static PyObject *
+_opcode_has_jump(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(opcode), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"opcode", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "has_jump",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[1];
+ int opcode;
+ int _return_value;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ opcode = _PyLong_AsInt(args[0]);
+ if (opcode == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ _return_value = _opcode_has_jump_impl(module, opcode);
+ if ((_return_value == -1) && PyErr_Occurred()) {
+ goto exit;
+ }
+ return_value = PyBool_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(_opcode_get_specialization_stats__doc__,
"get_specialization_stats($module, /)\n"
"--\n"
@@ -103,4 +418,4 @@ _opcode_get_specialization_stats(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return _opcode_get_specialization_stats_impl(module);
}
-/*[clinic end generated code: output=21e3d53a659c651a input=a9049054013a1b77]*/
+/*[clinic end generated code: output=ae2b2ef56d582180 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_testinternalcapi.c.h b/Modules/clinic/_testinternalcapi.c.h
index f5124125874503..9419dcd751a0e9 100644
--- a/Modules/clinic/_testinternalcapi.c.h
+++ b/Modules/clinic/_testinternalcapi.c.h
@@ -8,6 +8,65 @@ preserve
#endif
+PyDoc_STRVAR(_testinternalcapi_compiler_cleandoc__doc__,
+"compiler_cleandoc($module, /, doc)\n"
+"--\n"
+"\n"
+"C implementation of inspect.cleandoc().");
+
+#define _TESTINTERNALCAPI_COMPILER_CLEANDOC_METHODDEF \
+ {"compiler_cleandoc", _PyCFunction_CAST(_testinternalcapi_compiler_cleandoc), METH_FASTCALL|METH_KEYWORDS, _testinternalcapi_compiler_cleandoc__doc__},
+
+static PyObject *
+_testinternalcapi_compiler_cleandoc_impl(PyObject *module, PyObject *doc);
+
+static PyObject *
+_testinternalcapi_compiler_cleandoc(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(doc), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"doc", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "compiler_cleandoc",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[1];
+ PyObject *doc;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!PyUnicode_Check(args[0])) {
+ _PyArg_BadArgument("compiler_cleandoc", "argument 'doc'", "str", args[0]);
+ goto exit;
+ }
+ doc = args[0];
+ return_value = _testinternalcapi_compiler_cleandoc_impl(module, doc);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(_testinternalcapi_compiler_codegen__doc__,
"compiler_codegen($module, /, ast, filename, optimize, compile_mode=0)\n"
"--\n"
@@ -206,4 +265,4 @@ _testinternalcapi_assemble_code_object(PyObject *module, PyObject *const *args,
exit:
return return_value;
}
-/*[clinic end generated code: output=2965f1578b986218 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=811d50772c8f285a input=a9049054013a1b77]*/
diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c
index 1a31bdc824bb03..db8b321e72e8ce 100644
--- a/Modules/cmathmodule.c
+++ b/Modules/cmathmodule.c
@@ -7,6 +7,7 @@
#endif
#include "Python.h"
+#include "pycore_complexobject.h" // _Py_c_neg()
#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
/* we need DBL_MAX, DBL_MIN, DBL_EPSILON, DBL_MANT_DIG and FLT_RADIX from
float.h. We assume that FLT_RADIX is either 2 or 16. */
diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c
index 6ca0b62bc5dca8..e530621fd269a1 100644
--- a/Modules/fcntlmodule.c
+++ b/Modules/fcntlmodule.c
@@ -1,8 +1,5 @@
-
/* fcntl module */
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#ifdef HAVE_SYS_FILE_H
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index c51c100be8361d..97644a7cee774f 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -30,6 +30,7 @@
#include "pycore_object.h"
#include "pycore_pyerrors.h"
#include "pycore_pystate.h" // _PyThreadState_GET()
+#include "pycore_weakref.h" // _PyWeakref_ClearRef()
#include "pydtrace.h"
typedef struct _gc_runtime_state GCState;
diff --git a/Modules/getbuildinfo.c b/Modules/getbuildinfo.c
index a24750b76c09bc..8d553d106c6ab5 100644
--- a/Modules/getbuildinfo.c
+++ b/Modules/getbuildinfo.c
@@ -1,4 +1,9 @@
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "Python.h"
+#include "pycore_pylifecycle.h" // _Py_gitidentifier()
#ifndef DONT_HAVE_STDIO_H
#include
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index ae63bae79d5d07..f5f7bf33bf8f4b 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -1,4 +1,3 @@
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_long.h" // _PyLong_GetZero()
@@ -1147,7 +1146,7 @@ itertools_tee_impl(PyObject *module, PyObject *iterable, Py_ssize_t n)
return NULL;
}
- if (_PyObject_LookupAttr(it, &_Py_ID(__copy__), ©func) < 0) {
+ if (PyObject_GetOptionalAttr(it, &_Py_ID(__copy__), ©func) < 0) {
Py_DECREF(it);
Py_DECREF(result);
return NULL;
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index 6bde9939eaa2ca..c1cd5b0efaa3d2 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -22,7 +22,6 @@
# define Py_BUILD_CORE_MODULE 1
#endif
-#define PY_SSIZE_T_CLEAN
#include
#include "pycore_bytesobject.h" // _PyBytes_Find()
#include "pycore_fileutils.h" // _Py_stat_struct
@@ -343,12 +342,17 @@ mmap_gfind(mmap_object *self,
Py_ssize_t res;
CHECK_VALID_OR_RELEASE(NULL, view);
- if (reverse) {
+ if (end < start) {
+ res = -1;
+ }
+ else if (reverse) {
+ assert(0 <= start && start <= end && end <= self->size);
res = _PyBytes_ReverseFind(
self->data + start, end - start,
view.buf, view.len, start);
}
else {
+ assert(0 <= start && start <= end && end <= self->size);
res = _PyBytes_Find(
self->data + start, end - start,
view.buf, view.len, start);
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 694cff19d2286c..aef802c232c6ce 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -7,8 +7,6 @@
of the compiler used. Different compilers define their own feature
test macro, e.g. '_MSC_VER'. */
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#ifdef __VXWORKS__
@@ -21,6 +19,7 @@
#include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_object.h" // _PyObject_LookupSpecial()
+#include "pycore_pylifecycle.h" // _PyOS_URandom()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_signal.h" // Py_NSIG
@@ -1197,7 +1196,7 @@ path_converter(PyObject *o, void *p)
PyObject *func, *res;
func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
- if (NULL == func) {
+ if ((NULL == func) || (func == Py_None)) {
goto error_format;
}
res = _PyObject_CallNoArgs(func);
@@ -15430,7 +15429,7 @@ PyOS_FSPath(PyObject *path)
}
func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
- if (NULL == func) {
+ if ((NULL == func) || (func == Py_None)) {
return PyErr_Format(PyExc_TypeError,
"expected str, bytes or os.PathLike object, "
"not %.200s",
diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c
index 27f2d0a6a0f68d..5721ed4412be57 100644
--- a/Modules/pyexpat.c
+++ b/Modules/pyexpat.c
@@ -1,4 +1,9 @@
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "Python.h"
+#include "pycore_import.h" // _PyImport_SetModule()
#include
#include "structmember.h" // PyMemberDef
@@ -827,7 +832,7 @@ pyexpat_xmlparser_ParseFile_impl(xmlparseobject *self, PyTypeObject *cls,
pyexpat_state *state = PyType_GetModuleState(cls);
- if (_PyObject_LookupAttr(file, state->str_read, &readmethod) < 0) {
+ if (PyObject_GetOptionalAttr(file, state->str_read, &readmethod) < 0) {
return NULL;
}
if (readmethod == NULL) {
@@ -1775,14 +1780,18 @@ add_error(PyObject *errors_module, PyObject *codes_dict,
static int
add_errors_module(PyObject *mod)
{
+ // add_submodule() returns a borrowed ref.
PyObject *errors_module = add_submodule(mod, MODULE_NAME ".errors");
if (errors_module == NULL) {
return -1;
}
PyObject *codes_dict = PyDict_New();
+ if (codes_dict == NULL) {
+ return -1;
+ }
PyObject *rev_codes_dict = PyDict_New();
- if (codes_dict == NULL || rev_codes_dict == NULL) {
+ if (rev_codes_dict == NULL) {
goto error;
}
@@ -1803,17 +1812,17 @@ add_errors_module(PyObject *mod)
goto error;
}
- if (PyModule_AddObject(errors_module, "codes", Py_NewRef(codes_dict)) < 0) {
- Py_DECREF(codes_dict);
+ int rc = PyModule_AddObjectRef(errors_module, "codes", codes_dict);
+ Py_CLEAR(codes_dict);
+ if (rc < 0) {
goto error;
}
- Py_CLEAR(codes_dict);
- if (PyModule_AddObject(errors_module, "messages", Py_NewRef(rev_codes_dict)) < 0) {
- Py_DECREF(rev_codes_dict);
+ rc = PyModule_AddObjectRef(errors_module, "messages", rev_codes_dict);
+ Py_CLEAR(rev_codes_dict);
+ if (rc < 0) {
goto error;
}
- Py_CLEAR(rev_codes_dict);
return 0;
diff --git a/Modules/readline.c b/Modules/readline.c
index ff7075c6822e27..a592919692cb83 100644
--- a/Modules/readline.c
+++ b/Modules/readline.c
@@ -4,8 +4,13 @@
* recently, it was largely rewritten by Guido van Rossum.
*/
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
/* Standard definitions */
#include "Python.h"
+#include "pycore_pylifecycle.h" // _Py_SetLocaleFromEnv()
#include
#include
diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c
index 9a4943c9eb2f75..7ab0804ad27233 100644
--- a/Modules/selectmodule.c
+++ b/Modules/selectmodule.c
@@ -14,6 +14,7 @@
#include "Python.h"
#include "pycore_fileutils.h" // _Py_set_inheritable()
+#include "pycore_time.h" // _PyTime_t
#include "structmember.h" // PyMemberDef
#ifdef HAVE_SYS_DEVPOLL_H
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index 2350236ad46b25..3adb2e8dfe58d8 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -13,7 +13,7 @@
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_pyerrors.h" // _PyErr_SetString()
#include "pycore_pystate.h" // _PyThreadState_GET()
-#include "pycore_signal.h" // Py_NSIG
+#include "pycore_signal.h" // _Py_RestoreSignals()
#ifndef MS_WINDOWS
# include "posixmodule.h"
@@ -314,7 +314,8 @@ trip_signal(int sig_num)
still use it for this exceptional case. */
_PyEval_AddPendingCall(interp,
report_wakeup_send_error,
- (void *)(intptr_t) last_error);
+ (void *)(intptr_t) last_error,
+ 1);
}
}
}
@@ -333,7 +334,8 @@ trip_signal(int sig_num)
still use it for this exceptional case. */
_PyEval_AddPendingCall(interp,
report_wakeup_write_error,
- (void *)(intptr_t)errno);
+ (void *)(intptr_t)errno,
+ 1);
}
}
}
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 3add80233522b9..1d3f34b857a1d2 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -105,7 +105,6 @@ Local naming conventions:
# pragma weak inet_aton
#endif
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_fileutils.h" // _Py_set_inheritable()
#include "pycore_moduleobject.h" // _PyModule_GetState
diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h
index f5ca00450ee92a..663ae3d6e0dd6c 100644
--- a/Modules/socketmodule.h
+++ b/Modules/socketmodule.h
@@ -1,5 +1,7 @@
/* Socket module header file */
+#include "pycore_time.h" // _PyTime_t
+
/* Includes needed for the sockaddr_* symbols below */
#ifndef MS_WINDOWS
#ifdef __VMS
diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c
index 7be4d83c6f070f..b6e50528a23c86 100644
--- a/Modules/unicodedata.c
+++ b/Modules/unicodedata.c
@@ -16,8 +16,6 @@
# define Py_BUILD_CORE_MODULE 1
#endif
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
#include "structmember.h" // PyMemberDef
diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
index 534d065765f0f9..c0f6b96f51baba 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -3,8 +3,6 @@
/* Windows users: read Python's PCbuild\readme.txt */
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "structmember.h" // PyMemberDef
#include "zlib.h"
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 00087bd86624ee..b4edcec6007710 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -182,7 +182,7 @@ PyObject_GetItem(PyObject *o, PyObject *key)
return Py_GenericAlias(o, key);
}
- if (_PyObject_LookupAttr(o, &_Py_ID(__class_getitem__), &meth) < 0) {
+ if (PyObject_GetOptionalAttr(o, &_Py_ID(__class_getitem__), &meth) < 0) {
return NULL;
}
if (meth && meth != Py_None) {
@@ -199,6 +199,30 @@ PyObject_GetItem(PyObject *o, PyObject *key)
return type_error("'%.200s' object is not subscriptable", o);
}
+int
+PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result)
+{
+ if (PyDict_CheckExact(obj)) {
+ *result = PyDict_GetItemWithError(obj, key); /* borrowed */
+ if (*result) {
+ Py_INCREF(*result);
+ return 1;
+ }
+ return PyErr_Occurred() ? -1 : 0;
+ }
+
+ *result = PyObject_GetItem(obj, key);
+ if (*result) {
+ return 1;
+ }
+ assert(PyErr_Occurred());
+ if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
+ return -1;
+ }
+ PyErr_Clear();
+ return 0;
+}
+
int
PyObject_SetItem(PyObject *o, PyObject *key, PyObject *value)
{
@@ -517,7 +541,7 @@ PyBuffer_GetPointer(const Py_buffer *view, const Py_ssize_t *indices)
}
-void
+static void
_Py_add_one_to_index_F(int nd, Py_ssize_t *index, const Py_ssize_t *shape)
{
int k;
@@ -533,7 +557,7 @@ _Py_add_one_to_index_F(int nd, Py_ssize_t *index, const Py_ssize_t *shape)
}
}
-void
+static void
_Py_add_one_to_index_C(int nd, Py_ssize_t *index, const Py_ssize_t *shape)
{
int k;
@@ -2366,6 +2390,22 @@ PyMapping_GetItemString(PyObject *o, const char *key)
return r;
}
+int
+PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result)
+{
+ if (key == NULL) {
+ null_error();
+ return -1;
+ }
+ PyObject *okey = PyUnicode_FromString(key);
+ if (okey == NULL) {
+ return -1;
+ }
+ int rc = PyMapping_GetOptionalItem(obj, okey, result);
+ Py_DECREF(okey);
+ return rc;
+}
+
int
PyMapping_SetItemString(PyObject *o, const char *key, PyObject *value)
{
@@ -2512,7 +2552,7 @@ abstract_get_bases(PyObject *cls)
{
PyObject *bases;
- (void)_PyObject_LookupAttr(cls, &_Py_ID(__bases__), &bases);
+ (void)PyObject_GetOptionalAttr(cls, &_Py_ID(__bases__), &bases);
if (bases != NULL && !PyTuple_Check(bases)) {
Py_DECREF(bases);
return NULL;
@@ -2596,7 +2636,7 @@ object_isinstance(PyObject *inst, PyObject *cls)
if (PyType_Check(cls)) {
retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls);
if (retval == 0) {
- retval = _PyObject_LookupAttr(inst, &_Py_ID(__class__), &icls);
+ retval = PyObject_GetOptionalAttr(inst, &_Py_ID(__class__), &icls);
if (icls != NULL) {
if (icls != (PyObject *)(Py_TYPE(inst)) && PyType_Check(icls)) {
retval = PyType_IsSubtype(
@@ -2614,7 +2654,7 @@ object_isinstance(PyObject *inst, PyObject *cls)
if (!check_class(cls,
"isinstance() arg 2 must be a type, a tuple of types, or a union"))
return -1;
- retval = _PyObject_LookupAttr(inst, &_Py_ID(__class__), &icls);
+ retval = PyObject_GetOptionalAttr(inst, &_Py_ID(__class__), &icls);
if (icls != NULL) {
retval = abstract_issubclass(icls, cls);
Py_DECREF(icls);
@@ -2906,80 +2946,3 @@ PyIter_Send(PyObject *iter, PyObject *arg, PyObject **result)
}
return PYGEN_ERROR;
}
-
-/*
- * Flatten a sequence of bytes() objects into a C array of
- * NULL terminated string pointers with a NULL char* terminating the array.
- * (ie: an argv or env list)
- *
- * Memory allocated for the returned list is allocated using PyMem_Malloc()
- * and MUST be freed by _Py_FreeCharPArray().
- */
-char *const *
-_PySequence_BytesToCharpArray(PyObject* self)
-{
- char **array;
- Py_ssize_t i, argc;
- PyObject *item = NULL;
- Py_ssize_t size;
-
- argc = PySequence_Size(self);
- if (argc == -1)
- return NULL;
-
- assert(argc >= 0);
-
- if ((size_t)argc > (PY_SSIZE_T_MAX-sizeof(char *)) / sizeof(char *)) {
- PyErr_NoMemory();
- return NULL;
- }
-
- array = PyMem_Malloc((argc + 1) * sizeof(char *));
- if (array == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- for (i = 0; i < argc; ++i) {
- char *data;
- item = PySequence_GetItem(self, i);
- if (item == NULL) {
- /* NULL terminate before freeing. */
- array[i] = NULL;
- goto fail;
- }
- /* check for embedded null bytes */
- if (PyBytes_AsStringAndSize(item, &data, NULL) < 0) {
- /* NULL terminate before freeing. */
- array[i] = NULL;
- goto fail;
- }
- size = PyBytes_GET_SIZE(item) + 1;
- array[i] = PyMem_Malloc(size);
- if (!array[i]) {
- PyErr_NoMemory();
- goto fail;
- }
- memcpy(array[i], data, size);
- Py_DECREF(item);
- }
- array[argc] = NULL;
-
- return array;
-
-fail:
- Py_XDECREF(item);
- _Py_FreeCharPArray(array);
- return NULL;
-}
-
-
-/* Free's a NULL terminated char** array of C strings. */
-void
-_Py_FreeCharPArray(char *const array[])
-{
- Py_ssize_t i;
- for (i = 0; array[i] != NULL; ++i) {
- PyMem_Free(array[i]);
- }
- PyMem_Free((void*)array);
-}
diff --git a/Objects/boolobject.c b/Objects/boolobject.c
index f43e26f3f24e77..bbb187cb7121e7 100644
--- a/Objects/boolobject.c
+++ b/Objects/boolobject.c
@@ -1,8 +1,9 @@
/* Boolean type, a subtype of int */
#include "Python.h"
-#include "pycore_object.h" // _Py_FatalRefcountError()
-#include "pycore_long.h" // FALSE_TAG TRUE_TAG
+#include "pycore_long.h" // FALSE_TAG TRUE_TAG
+#include "pycore_modsupport.h" // _PyArg_NoKwnames()
+#include "pycore_object.h" // _Py_FatalRefcountError()
#include "pycore_runtime.h" // _Py_ID()
#include
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index c36db59baaa10d..18a24a369a64c1 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -1,6 +1,5 @@
/* PyByteArray (bytearray) implementation */
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_bytes_methods.h"
@@ -1377,7 +1376,7 @@ bytearray.maketrans
to: Py_buffer
/
-Return a translation table useable for the bytes or bytearray translate method.
+Return a translation table usable for the bytes or bytearray translate method.
The returned table will be one where each byte in frm is mapped to the byte at
the same position in to.
@@ -1387,7 +1386,7 @@ The bytes objects frm and to must be of the same length.
static PyObject *
bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to)
-/*[clinic end generated code: output=1df267d99f56b15e input=5925a81d2fbbf151]*/
+/*[clinic end generated code: output=1df267d99f56b15e input=b10de38c85950a63]*/
{
return _Py_bytes_maketrans(frm, to);
}
diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c
index 33aa9c3db6e805..c1bc6383df30ce 100644
--- a/Objects/bytes_methods.c
+++ b/Objects/bytes_methods.c
@@ -1,4 +1,3 @@
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_bytes_methods.h"
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 1b67e02025c424..6b9231a9fa7693 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -1,7 +1,5 @@
/* bytes object implementation */
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_bytesobject.h" // _PyBytes_Find(), _PyBytes_Repeat()
@@ -1274,8 +1272,25 @@ _PyBytes_Find(const char *haystack, Py_ssize_t len_haystack,
const char *needle, Py_ssize_t len_needle,
Py_ssize_t offset)
{
- return stringlib_find(haystack, len_haystack,
- needle, len_needle, offset);
+ assert(len_haystack >= 0);
+ assert(len_needle >= 0);
+ // Extra checks because stringlib_find accesses haystack[len_haystack].
+ if (len_needle == 0) {
+ return offset;
+ }
+ if (len_needle > len_haystack) {
+ return -1;
+ }
+ assert(len_haystack >= 1);
+ Py_ssize_t res = stringlib_find(haystack, len_haystack - 1,
+ needle, len_needle, offset);
+ if (res == -1) {
+ Py_ssize_t last_align = len_haystack - len_needle;
+ if (memcmp(haystack + last_align, needle, len_needle) == 0) {
+ return offset + last_align;
+ }
+ }
+ return res;
}
Py_ssize_t
@@ -2154,7 +2169,7 @@ bytes.maketrans
to: Py_buffer
/
-Return a translation table useable for the bytes or bytearray translate method.
+Return a translation table usable for the bytes or bytearray translate method.
The returned table will be one where each byte in frm is mapped to the byte at
the same position in to.
@@ -2164,7 +2179,7 @@ The bytes objects frm and to must be of the same length.
static PyObject *
bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to)
-/*[clinic end generated code: output=a36f6399d4b77f6f input=de7a8fc5632bb8f1]*/
+/*[clinic end generated code: output=a36f6399d4b77f6f input=a3bd00d430a0979f]*/
{
return _Py_bytes_maketrans(frm, to);
}
diff --git a/Objects/call.c b/Objects/call.c
index 40eccefb4a6c8d..396552d85cfca0 100644
--- a/Objects/call.c
+++ b/Objects/call.c
@@ -2,6 +2,7 @@
#include "pycore_call.h" // _PyObject_CallNoArgsTstate()
#include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
#include "pycore_dict.h" // _PyDict_FromItems()
+#include "pycore_modsupport.h" // _Py_VaBuildStack()
#include "pycore_object.h" // _PyCFunctionWithKeywords_TrampolineCall()
#include "pycore_pyerrors.h" // _PyErr_Occurred()
#include "pycore_pystate.h" // _PyThreadState_GET()
@@ -106,9 +107,9 @@ PyObject_CallNoArgs(PyObject *func)
PyObject *
-_PyObject_FastCallDictTstate(PyThreadState *tstate, PyObject *callable,
- PyObject *const *args, size_t nargsf,
- PyObject *kwargs)
+_PyObject_VectorcallDictTstate(PyThreadState *tstate, PyObject *callable,
+ PyObject *const *args, size_t nargsf,
+ PyObject *kwargs)
{
assert(callable != NULL);
@@ -122,7 +123,7 @@ _PyObject_FastCallDictTstate(PyThreadState *tstate, PyObject *callable,
assert(nargs == 0 || args != NULL);
assert(kwargs == NULL || PyDict_Check(kwargs));
- vectorcallfunc func = _PyVectorcall_Function(callable);
+ vectorcallfunc func = PyVectorcall_Function(callable);
if (func == NULL) {
/* Use tp_call instead */
return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwargs);
@@ -154,7 +155,7 @@ PyObject_VectorcallDict(PyObject *callable, PyObject *const *args,
size_t nargsf, PyObject *kwargs)
{
PyThreadState *tstate = _PyThreadState_GET();
- return _PyObject_FastCallDictTstate(tstate, callable, args, nargsf, kwargs);
+ return _PyObject_VectorcallDictTstate(tstate, callable, args, nargsf, kwargs);
}
static void
@@ -172,7 +173,7 @@ object_is_not_callable(PyThreadState *tstate, PyObject *callable)
goto basic_type_error;
}
PyObject *attr;
- int res = _PyObject_LookupAttr(callable, name, &attr);
+ int res = PyObject_GetOptionalAttr(callable, name, &attr);
if (res < 0) {
_PyErr_Clear(tstate);
}
@@ -327,14 +328,6 @@ PyObject_Vectorcall(PyObject *callable, PyObject *const *args,
}
-PyObject *
-_PyObject_FastCall(PyObject *func, PyObject *const *args, Py_ssize_t nargs)
-{
- PyThreadState *tstate = _PyThreadState_GET();
- return _PyObject_FastCallTstate(tstate, func, args, nargs);
-}
-
-
PyObject *
_PyObject_Call(PyThreadState *tstate, PyObject *callable,
PyObject *args, PyObject *kwargs)
@@ -349,7 +342,7 @@ _PyObject_Call(PyThreadState *tstate, PyObject *callable,
assert(PyTuple_Check(args));
assert(kwargs == NULL || PyDict_Check(kwargs));
EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, callable);
- vectorcallfunc vector_func = _PyVectorcall_Function(callable);
+ vectorcallfunc vector_func = PyVectorcall_Function(callable);
if (vector_func != NULL) {
return _PyVectorcall_Call(tstate, vector_func, callable, args, kwargs);
}
@@ -453,7 +446,8 @@ PyEval_CallObjectWithKeywords(PyObject *callable,
}
if (args == NULL) {
- return _PyObject_FastCallDictTstate(tstate, callable, NULL, 0, kwargs);
+ return _PyObject_VectorcallDictTstate(tstate, callable,
+ NULL, 0, kwargs);
}
else {
return _PyObject_Call(tstate, callable, args, kwargs);
@@ -506,9 +500,9 @@ _PyObject_Call_Prepend(PyThreadState *tstate, PyObject *callable,
_PyTuple_ITEMS(args),
argcount * sizeof(PyObject *));
- PyObject *result = _PyObject_FastCallDictTstate(tstate, callable,
- stack, argcount + 1,
- kwargs);
+ PyObject *result = _PyObject_VectorcallDictTstate(tstate, callable,
+ stack, argcount + 1,
+ kwargs);
if (stack != small_stack) {
PyMem_Free(stack);
}
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 71c4a4e5d0f8ab..548b8672f86321 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -275,9 +275,9 @@ method_repr(PyMethodObject *a)
PyObject *funcname, *result;
const char *defname = "?";
- if (_PyObject_LookupAttr(func, &_Py_ID(__qualname__), &funcname) < 0 ||
+ if (PyObject_GetOptionalAttr(func, &_Py_ID(__qualname__), &funcname) < 0 ||
(funcname == NULL &&
- _PyObject_LookupAttr(func, &_Py_ID(__name__), &funcname) < 0))
+ PyObject_GetOptionalAttr(func, &_Py_ID(__name__), &funcname) < 0))
{
return NULL;
}
@@ -479,7 +479,7 @@ instancemethod_repr(PyObject *self)
return NULL;
}
- if (_PyObject_LookupAttr(func, &_Py_ID(__name__), &funcname) < 0) {
+ if (PyObject_GetOptionalAttr(func, &_Py_ID(__name__), &funcname) < 0) {
return NULL;
}
if (funcname != NULL && !PyUnicode_Check(funcname)) {
diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h
index b847597c64b3f1..33caca28224565 100644
--- a/Objects/clinic/bytearrayobject.c.h
+++ b/Objects/clinic/bytearrayobject.c.h
@@ -289,7 +289,7 @@ PyDoc_STRVAR(bytearray_maketrans__doc__,
"maketrans(frm, to, /)\n"
"--\n"
"\n"
-"Return a translation table useable for the bytes or bytearray translate method.\n"
+"Return a translation table usable for the bytes or bytearray translate method.\n"
"\n"
"The returned table will be one where each byte in frm is mapped to the byte at\n"
"the same position in to.\n"
@@ -1284,4 +1284,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
{
return bytearray_sizeof_impl(self);
}
-/*[clinic end generated code: output=99fb3e3b9c1f4b15 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=0817195f176cd8e3 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h
index 4b4a4b39a1fa96..1ec0c95485a209 100644
--- a/Objects/clinic/bytesobject.c.h
+++ b/Objects/clinic/bytesobject.c.h
@@ -476,7 +476,7 @@ PyDoc_STRVAR(bytes_maketrans__doc__,
"maketrans(frm, to, /)\n"
"--\n"
"\n"
-"Return a translation table useable for the bytes or bytearray translate method.\n"
+"Return a translation table usable for the bytes or bytearray translate method.\n"
"\n"
"The returned table will be one where each byte in frm is mapped to the byte at\n"
"the same position in to.\n"
@@ -1060,4 +1060,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
exit:
return return_value;
}
-/*[clinic end generated code: output=7b6e4e8b5bc4eb57 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=bc4801bf1fa628f4 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/unicodeobject.c.h b/Objects/clinic/unicodeobject.c.h
index 70c7fe17501716..b9127e428f4c99 100644
--- a/Objects/clinic/unicodeobject.c.h
+++ b/Objects/clinic/unicodeobject.c.h
@@ -736,7 +736,7 @@ unicode_rstrip(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
}
PyDoc_STRVAR(unicode_replace__doc__,
-"replace($self, old, new, count=-1, /)\n"
+"replace($self, old, new, /, count=-1)\n"
"--\n"
"\n"
"Return a copy with all occurrences of substring old replaced by new.\n"
@@ -749,21 +749,49 @@ PyDoc_STRVAR(unicode_replace__doc__,
"replaced.");
#define UNICODE_REPLACE_METHODDEF \
- {"replace", _PyCFunction_CAST(unicode_replace), METH_FASTCALL, unicode_replace__doc__},
+ {"replace", _PyCFunction_CAST(unicode_replace), METH_FASTCALL|METH_KEYWORDS, unicode_replace__doc__},
static PyObject *
unicode_replace_impl(PyObject *self, PyObject *old, PyObject *new,
Py_ssize_t count);
static PyObject *
-unicode_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+unicode_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(count), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"", "", "count", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "replace",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
PyObject *old;
PyObject *new;
Py_ssize_t count = -1;
- if (!_PyArg_CheckPositional("replace", nargs, 2, 3)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf);
+ if (!args) {
goto exit;
}
if (!PyUnicode_Check(args[0])) {
@@ -776,8 +804,8 @@ unicode_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit;
}
new = args[1];
- if (nargs < 3) {
- goto skip_optional;
+ if (!noptargs) {
+ goto skip_optional_pos;
}
{
Py_ssize_t ival = -1;
@@ -791,7 +819,7 @@ unicode_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
}
count = ival;
}
-skip_optional:
+skip_optional_pos:
return_value = unicode_replace_impl(self, old, new, count);
exit:
@@ -1476,4 +1504,4 @@ unicode_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
exit:
return return_value;
}
-/*[clinic end generated code: output=0a71c4aeffdf0bc5 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=ee76a1b49cd4cbb3 input=a9049054013a1b77]*/
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index cf087e8d3fbeb9..d2670c71caa44a 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -1465,12 +1465,28 @@ PyCode_GetFreevars(PyCodeObject *code)
return _PyCode_GetFreevars(code);
}
+static void
+clear_executors(PyCodeObject *co)
+{
+ for (int i = 0; i < co->co_executors->size; i++) {
+ Py_CLEAR(co->co_executors->executors[i]);
+ }
+ PyMem_Free(co->co_executors);
+ co->co_executors = NULL;
+}
+
static void
deopt_code(PyCodeObject *code, _Py_CODEUNIT *instructions)
{
Py_ssize_t len = Py_SIZE(code);
for (int i = 0; i < len; i++) {
int opcode = _Py_GetBaseOpcode(code, i);
+ if (opcode == ENTER_EXECUTOR) {
+ _PyExecutorObject *exec = code->co_executors->executors[instructions[i].op.arg];
+ opcode = exec->vm_data.opcode;
+ instructions[i].op.arg = exec->vm_data.oparg;
+ }
+ assert(opcode != ENTER_EXECUTOR);
int caches = _PyOpcode_Caches[opcode];
instructions[i].op.code = opcode;
for (int j = 1; j <= caches; j++) {
@@ -1679,10 +1695,7 @@ code_dealloc(PyCodeObject *co)
PyMem_Free(co_extra);
}
if (co->co_executors != NULL) {
- for (int i = 0; i < co->co_executors->size; i++) {
- Py_CLEAR(co->co_executors->executors[i]);
- }
- PyMem_Free(co->co_executors);
+ clear_executors(co);
}
Py_XDECREF(co->co_consts);
@@ -2022,6 +2035,7 @@ code_replace_impl(PyCodeObject *self, int co_argcount,
co_code, co_filename, co_name, co_argcount,
co_posonlyargcount, co_kwonlyargcount, co_nlocals,
co_stacksize, co_flags) < 0) {
+ Py_XDECREF(code);
return NULL;
}
@@ -2278,6 +2292,9 @@ void
_PyStaticCode_Fini(PyCodeObject *co)
{
deopt_code(co, _PyCode_CODE(co));
+ if (co->co_executors != NULL) {
+ clear_executors(co);
+ }
PyMem_Free(co->co_extra);
if (co->_co_cached != NULL) {
Py_CLEAR(co->_co_cached->_co_code);
@@ -2316,76 +2333,3 @@ _PyStaticCode_Init(PyCodeObject *co)
}
#define MAX_CODE_UNITS_PER_LOC_ENTRY 8
-
-PyCodeObject *
-_Py_MakeShimCode(const _PyShimCodeDef *codedef)
-{
- PyObject *name = NULL;
- PyObject *co_code = NULL;
- PyObject *lines = NULL;
- PyCodeObject *codeobj = NULL;
- uint8_t *loc_table = NULL;
-
- name = _PyUnicode_FromASCII(codedef->cname, strlen(codedef->cname));
- if (name == NULL) {
- goto cleanup;
- }
- co_code = PyBytes_FromStringAndSize(
- (const char *)codedef->code, codedef->codelen);
- if (co_code == NULL) {
- goto cleanup;
- }
- int code_units = codedef->codelen / sizeof(_Py_CODEUNIT);
- int loc_entries = (code_units + MAX_CODE_UNITS_PER_LOC_ENTRY - 1) /
- MAX_CODE_UNITS_PER_LOC_ENTRY;
- loc_table = PyMem_Malloc(loc_entries);
- if (loc_table == NULL) {
- PyErr_NoMemory();
- goto cleanup;
- }
- for (int i = 0; i < loc_entries-1; i++) {
- loc_table[i] = 0x80 | (PY_CODE_LOCATION_INFO_NONE << 3) | 7;
- code_units -= MAX_CODE_UNITS_PER_LOC_ENTRY;
- }
- assert(loc_entries > 0);
- assert(code_units > 0 && code_units <= MAX_CODE_UNITS_PER_LOC_ENTRY);
- loc_table[loc_entries-1] = 0x80 |
- (PY_CODE_LOCATION_INFO_NONE << 3) | (code_units-1);
- lines = PyBytes_FromStringAndSize((const char *)loc_table, loc_entries);
- PyMem_Free(loc_table);
- if (lines == NULL) {
- goto cleanup;
- }
- _Py_DECLARE_STR(shim_name, "");
- struct _PyCodeConstructor con = {
- .filename = &_Py_STR(shim_name),
- .name = name,
- .qualname = name,
- .flags = CO_NEWLOCALS | CO_OPTIMIZED,
-
- .code = co_code,
- .firstlineno = 1,
- .linetable = lines,
-
- .consts = (PyObject *)&_Py_SINGLETON(tuple_empty),
- .names = (PyObject *)&_Py_SINGLETON(tuple_empty),
-
- .localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty),
- .localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty),
-
- .argcount = 0,
- .posonlyargcount = 0,
- .kwonlyargcount = 0,
-
- .stacksize = codedef->stacksize,
-
- .exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty),
- };
-
- codeobj = _PyCode_New(&con);
-cleanup:
- Py_XDECREF(name);
- Py_XDECREF(co_code);
- Py_XDECREF(lines);
- return codeobj;
-}
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index aee03ddfb07aec..12968a63cd6fdd 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -7,6 +7,7 @@
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs()
+#include "pycore_complexobject.h" // _PyComplex_FormatAdvancedWriter()
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_object.h" // _PyObject_Init()
#include "pycore_pymath.h" // _Py_ADJUST_ERANGE2()
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 72ac4703949262..810bd196e8f7e7 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -1,6 +1,8 @@
/* Descriptors -- a new, flexible way to describe attributes */
#include "Python.h"
+#include "pycore_abstract.h" // _PyObject_RealIsSubclass()
+#include "pycore_call.h" // _PyStack_AsDict()
#include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_pystate.h" // _PyThreadState_GET()
@@ -1110,9 +1112,9 @@ mappingproxy_get(mappingproxyobject *pp, PyObject *const *args, Py_ssize_t nargs
{
return NULL;
}
- return _PyObject_VectorcallMethod(&_Py_ID(get), newargs,
- 3 | PY_VECTORCALL_ARGUMENTS_OFFSET,
- NULL);
+ return PyObject_VectorcallMethod(&_Py_ID(get), newargs,
+ 3 | PY_VECTORCALL_ARGUMENTS_OFFSET,
+ NULL);
}
static PyObject *
@@ -1790,7 +1792,7 @@ property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
}
/* if no docstring given and the getter has one, use that one */
else if (fget != NULL) {
- int rc = _PyObject_LookupAttr(fget, &_Py_ID(__doc__), &prop_doc);
+ int rc = PyObject_GetOptionalAttr(fget, &_Py_ID(__doc__), &prop_doc);
if (rc <= 0) {
return rc;
}
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 254cd9ad2f9bda..013c21884032aa 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -2664,7 +2664,7 @@ dict_update_arg(PyObject *self, PyObject *arg)
return PyDict_Merge(self, arg, 1);
}
PyObject *func;
- if (_PyObject_LookupAttr(arg, &_Py_ID(keys), &func) < 0) {
+ if (PyObject_GetOptionalAttr(arg, &_Py_ID(keys), &func) < 0) {
return -1;
}
if (func != NULL) {
@@ -5334,11 +5334,10 @@ _PyDict_NewKeysForClass(void)
#define CACHED_KEYS(tp) (((PyHeapTypeObject*)tp)->ht_cached_keys)
-static int
-init_inline_values(PyObject *obj, PyTypeObject *tp)
+int
+_PyObject_InitInlineValues(PyObject *obj, PyTypeObject *tp)
{
assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
- // assert(type->tp_dictoffset > 0); -- TO DO Update this assert.
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
PyDictKeysObject *keys = CACHED_KEYS(tp);
assert(keys != NULL);
@@ -5370,7 +5369,7 @@ _PyObject_InitializeDict(PyObject *obj)
}
if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
OBJECT_STAT_INC(new_values);
- return init_inline_values(obj, tp);
+ return _PyObject_InitInlineValues(obj, tp);
}
PyObject *dict;
if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
diff --git a/Objects/enumobject.c b/Objects/enumobject.c
index c9d90584c26b7d..556666779d8522 100644
--- a/Objects/enumobject.c
+++ b/Objects/enumobject.c
@@ -3,6 +3,7 @@
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_long.h" // _PyLong_GetOne()
+#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_object.h" // _PyObject_GC_TRACK()
#include "clinic/enumobject.c.h"
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index e2a3f89b177ff6..42c5317d83d0c9 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -4,9 +4,9 @@
* Thanks go to Tim Peters and Michael Hudson for debugging.
*/
-#define PY_SSIZE_T_CLEAN
#include
#include
+#include "pycore_abstract.h" // _PyObject_RealIsSubclass()
#include "pycore_ceval.h" // _Py_EnterRecursiveCall
#include "pycore_pyerrors.h" // struct _PyErr_SetRaisedException
#include "pycore_exceptions.h" // struct _Py_exc_state
@@ -207,22 +207,21 @@ BaseException_add_note(PyObject *self, PyObject *note)
return NULL;
}
- if (!PyObject_HasAttr(self, &_Py_ID(__notes__))) {
- PyObject *new_notes = PyList_New(0);
- if (new_notes == NULL) {
+ PyObject *notes;
+ if (PyObject_GetOptionalAttr(self, &_Py_ID(__notes__), ¬es) < 0) {
+ return NULL;
+ }
+ if (notes == NULL) {
+ notes = PyList_New(0);
+ if (notes == NULL) {
return NULL;
}
- if (PyObject_SetAttr(self, &_Py_ID(__notes__), new_notes) < 0) {
- Py_DECREF(new_notes);
+ if (PyObject_SetAttr(self, &_Py_ID(__notes__), notes) < 0) {
+ Py_DECREF(notes);
return NULL;
}
- Py_DECREF(new_notes);
}
- PyObject *notes = PyObject_GetAttr(self, &_Py_ID(__notes__));
- if (notes == NULL) {
- return NULL;
- }
- if (!PyList_Check(notes)) {
+ else if (!PyList_Check(notes)) {
Py_DECREF(notes);
PyErr_SetString(PyExc_TypeError, "Cannot add note: __notes__ is not a list");
return NULL;
@@ -941,11 +940,11 @@ exceptiongroup_subset(
PyException_SetContext(eg, PyException_GetContext(orig));
PyException_SetCause(eg, PyException_GetCause(orig));
- if (PyObject_HasAttr(orig, &_Py_ID(__notes__))) {
- PyObject *notes = PyObject_GetAttr(orig, &_Py_ID(__notes__));
- if (notes == NULL) {
- goto error;
- }
+ PyObject *notes;
+ if (PyObject_GetOptionalAttr(orig, &_Py_ID(__notes__), ¬es) < 0) {
+ goto error;
+ }
+ if (notes) {
if (PySequence_Check(notes)) {
/* Make a copy so the parts have independent notes lists. */
PyObject *notes_copy = PySequence_List(notes);
@@ -993,7 +992,7 @@ get_matcher_type(PyObject *value,
{
assert(value);
- if (PyFunction_Check(value)) {
+ if (PyCallable_Check(value) && !PyType_Check(value)) {
*type = EXCEPTION_GROUP_MATCH_BY_PREDICATE;
return 0;
}
@@ -1017,7 +1016,7 @@ get_matcher_type(PyObject *value,
error:
PyErr_SetString(
PyExc_TypeError,
- "expected a function, exception type or tuple of exception types");
+ "expected an exception type, a tuple of exception types, or a callable (other than a class)");
return -1;
}
@@ -1033,7 +1032,7 @@ exceptiongroup_split_check_match(PyObject *exc,
return PyErr_GivenExceptionMatches(exc, matcher_value);
}
case EXCEPTION_GROUP_MATCH_BY_PREDICATE: {
- assert(PyFunction_Check(matcher_value));
+ assert(PyCallable_Check(matcher_value) && !PyType_Check(matcher_value));
PyObject *exc_matches = PyObject_CallOneArg(matcher_value, exc);
if (exc_matches == NULL) {
return -1;
@@ -1464,7 +1463,7 @@ PyUnstable_Exc_PrepReraiseStar(PyObject *orig, PyObject *excs)
}
/* Make sure that orig has something as traceback, in the interpreter
- * it always does becuase it's a raised exception.
+ * it always does because it's a raised exception.
*/
PyObject *tb = PyException_GetTraceback(orig);
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index e99e155f2b8c98..751fb69d0891cf 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -1,6 +1,5 @@
/* File object implementation (what's left of it -- see io.py) */
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_runtime.h" // _PyRuntime
@@ -177,7 +176,7 @@ PyObject_AsFileDescriptor(PyObject *o)
if (PyLong_Check(o)) {
fd = _PyLong_AsInt(o);
}
- else if (_PyObject_LookupAttr(o, &_Py_ID(fileno), &meth) < 0) {
+ else if (PyObject_GetOptionalAttr(o, &_Py_ID(fileno), &meth) < 0) {
return -1;
}
else if (meth != NULL) {
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 83a263c0d9c67e..fa55481f09dec0 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -9,6 +9,7 @@
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_interp.h" // _PyInterpreterState.float_state
#include "pycore_long.h" // _PyLong_GetOne()
+#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_object.h" // _PyObject_Init()
#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
#include "pycore_pystate.h" // _PyInterpreterState_GET()
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index f2061e6a18fa40..18820551a0547e 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -642,6 +642,7 @@ _PyFrame_GetState(PyFrameObject *frame)
static int
frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignored))
{
+ PyCodeObject *code = _PyFrame_GetCode(f->f_frame);
if (p_new_lineno == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
@@ -719,7 +720,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
}
new_lineno = (int)l_new_lineno;
- if (new_lineno < f->f_frame->f_code->co_firstlineno) {
+ if (new_lineno < code->co_firstlineno) {
PyErr_Format(PyExc_ValueError,
"line %d comes before the current code block",
new_lineno);
@@ -728,8 +729,8 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
/* PyCode_NewWithPosOnlyArgs limits co_code to be under INT_MAX so this
* should never overflow. */
- int len = (int)Py_SIZE(f->f_frame->f_code);
- int *lines = marklines(f->f_frame->f_code, len);
+ int len = (int)Py_SIZE(code);
+ int *lines = marklines(code, len);
if (lines == NULL) {
return -1;
}
@@ -743,7 +744,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
return -1;
}
- int64_t *stacks = mark_stacks(f->f_frame->f_code, len);
+ int64_t *stacks = mark_stacks(code, len);
if (stacks == NULL) {
PyMem_Free(lines);
return -1;
@@ -788,7 +789,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
// in the new location. Rather than crashing or changing co_code, just bind
// None instead:
int unbound = 0;
- for (int i = 0; i < f->f_frame->f_code->co_nlocalsplus; i++) {
+ for (int i = 0; i < code->co_nlocalsplus; i++) {
// Counting every unbound local is overly-cautious, but a full flow
// analysis (like we do in the compiler) is probably too expensive:
unbound += f->f_frame->localsplus[i] == NULL;
@@ -801,7 +802,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
}
// Do this in a second pass to avoid writing a bunch of Nones when
// warnings are being treated as errors and the previous bit raises:
- for (int i = 0; i < f->f_frame->f_code->co_nlocalsplus; i++) {
+ for (int i = 0; i < code->co_nlocalsplus; i++) {
if (f->f_frame->localsplus[i] == NULL) {
f->f_frame->localsplus[i] = Py_NewRef(Py_None);
unbound--;
@@ -832,7 +833,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
}
/* Finally set the new lasti and return OK. */
f->f_lineno = 0;
- f->f_frame->prev_instr = _PyCode_CODE(f->f_frame->f_code) + best_addr;
+ f->f_frame->prev_instr = _PyCode_CODE(code) + best_addr;
return 0;
}
@@ -886,15 +887,15 @@ frame_dealloc(PyFrameObject *f)
}
Py_TRASHCAN_BEGIN(f, frame_dealloc);
- PyCodeObject *co = NULL;
+ PyObject *co = NULL;
/* Kill all local variables including specials, if we own them */
if (f->f_frame->owner == FRAME_OWNED_BY_FRAME_OBJECT) {
assert(f->f_frame == (_PyInterpreterFrame *)f->_f_frame_data);
_PyInterpreterFrame *frame = (_PyInterpreterFrame *)f->_f_frame_data;
/* Don't clear code object until the end */
- co = frame->f_code;
- frame->f_code = NULL;
+ co = frame->f_executable;
+ frame->f_executable = NULL;
Py_CLEAR(frame->f_funcobj);
Py_CLEAR(frame->f_locals);
PyObject **locals = _PyFrame_GetLocalsArray(frame);
@@ -968,7 +969,7 @@ frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored))
{
Py_ssize_t res;
res = offsetof(PyFrameObject, _f_frame_data) + offsetof(_PyInterpreterFrame, localsplus);
- PyCodeObject *code = f->f_frame->f_code;
+ PyCodeObject *code = _PyFrame_GetCode(f->f_frame);
res += _PyFrame_NumSlotsForCodeObject(code) * sizeof(PyObject *);
return PyLong_FromSsize_t(res);
}
@@ -980,7 +981,7 @@ static PyObject *
frame_repr(PyFrameObject *f)
{
int lineno = PyFrame_GetLineNumber(f);
- PyCodeObject *code = f->f_frame->f_code;
+ PyCodeObject *code = _PyFrame_GetCode(f->f_frame);
return PyUnicode_FromFormat(
"",
f, code->co_filename, lineno, code->co_name);
@@ -1102,7 +1103,7 @@ _PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg)
// This only works when opcode is a non-quickened form:
assert(_PyOpcode_Deopt[opcode] == opcode);
int check_oparg = 0;
- for (_Py_CODEUNIT *instruction = _PyCode_CODE(frame->f_code);
+ for (_Py_CODEUNIT *instruction = _PyCode_CODE(_PyFrame_GetCode(frame));
instruction < frame->prev_instr; instruction++)
{
int check_opcode = _PyOpcode_Deopt[instruction->op.code];
@@ -1128,7 +1129,7 @@ frame_init_get_vars(_PyInterpreterFrame *frame)
{
// COPY_FREE_VARS has no quickened forms, so no need to use _PyOpcode_Deopt
// here:
- PyCodeObject *co = frame->f_code;
+ PyCodeObject *co = _PyFrame_GetCode(frame);
int lasti = _PyInterpreterFrame_LASTI(frame);
if (!(lasti < 0 && _PyCode_CODE(co)->op.code == COPY_FREE_VARS
&& PyFunction_Check(frame->f_funcobj)))
@@ -1145,7 +1146,7 @@ frame_init_get_vars(_PyInterpreterFrame *frame)
frame->localsplus[offset + i] = Py_NewRef(o);
}
// COPY_FREE_VARS doesn't have inline CACHEs, either:
- frame->prev_instr = _PyCode_CODE(frame->f_code);
+ frame->prev_instr = _PyCode_CODE(_PyFrame_GetCode(frame));
}
@@ -1185,7 +1186,7 @@ frame_get_var(_PyInterpreterFrame *frame, PyCodeObject *co, int i,
// (likely) MAKE_CELL must have executed already.
value = PyCell_GET(value);
}
- // (likely) Otherwise it it is an arg (kind & CO_FAST_LOCAL),
+ // (likely) Otherwise it is an arg (kind & CO_FAST_LOCAL),
// with the initial value set when the frame was created...
// (unlikely) ...or it was set to some initial value by
// an earlier call to PyFrame_LocalsToFast().
@@ -1199,21 +1200,34 @@ frame_get_var(_PyInterpreterFrame *frame, PyCodeObject *co, int i,
return 1;
}
-int
-_PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame)
+
+PyObject *
+_PyFrame_GetLocals(_PyInterpreterFrame *frame, int include_hidden)
{
/* Merge fast locals into f->f_locals */
PyObject *locals = frame->f_locals;
if (locals == NULL) {
locals = frame->f_locals = PyDict_New();
if (locals == NULL) {
- return -1;
+ return NULL;
+ }
+ }
+ PyObject *hidden = NULL;
+
+ /* If include_hidden, "hidden" fast locals (from inlined comprehensions in
+ module/class scopes) will be included in the returned dict, but not in
+ frame->f_locals; the returned dict will be a modified copy. Non-hidden
+ locals will still be updated in frame->f_locals. */
+ if (include_hidden) {
+ hidden = PyDict_New();
+ if (hidden == NULL) {
+ return NULL;
}
}
frame_init_get_vars(frame);
- PyCodeObject *co = frame->f_code;
+ PyCodeObject *co = _PyFrame_GetCode(frame);
for (int i = 0; i < co->co_nlocalsplus; i++) {
PyObject *value; // borrowed reference
if (!frame_get_var(frame, co, i, &value)) {
@@ -1223,6 +1237,11 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame)
PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
_PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
if (kind & CO_FAST_HIDDEN) {
+ if (include_hidden && value != NULL) {
+ if (PyObject_SetItem(hidden, name, value) != 0) {
+ goto error;
+ }
+ }
continue;
}
if (value == NULL) {
@@ -1231,16 +1250,53 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame)
PyErr_Clear();
}
else {
- return -1;
+ goto error;
}
}
}
else {
if (PyObject_SetItem(locals, name, value) != 0) {
- return -1;
+ goto error;
}
}
}
+
+ if (include_hidden && PyDict_Size(hidden)) {
+ PyObject *innerlocals = PyDict_New();
+ if (innerlocals == NULL) {
+ goto error;
+ }
+ if (PyDict_Merge(innerlocals, locals, 1) != 0) {
+ Py_DECREF(innerlocals);
+ goto error;
+ }
+ if (PyDict_Merge(innerlocals, hidden, 1) != 0) {
+ Py_DECREF(innerlocals);
+ goto error;
+ }
+ locals = innerlocals;
+ }
+ else {
+ Py_INCREF(locals);
+ }
+ Py_CLEAR(hidden);
+
+ return locals;
+
+ error:
+ Py_XDECREF(hidden);
+ return NULL;
+}
+
+
+int
+_PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame)
+{
+ PyObject *locals = _PyFrame_GetLocals(frame, 0);
+ if (locals == NULL) {
+ return -1;
+ }
+ Py_DECREF(locals);
return 0;
}
@@ -1257,7 +1313,7 @@ PyFrame_GetVar(PyFrameObject *frame_obj, PyObject *name)
_PyInterpreterFrame *frame = frame_obj->f_frame;
frame_init_get_vars(frame);
- PyCodeObject *co = frame->f_code;
+ PyCodeObject *co = _PyFrame_GetCode(frame);
for (int i = 0; i < co->co_nlocalsplus; i++) {
PyObject *var_name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
if (!_PyUnicode_Equal(var_name, name)) {
@@ -1331,7 +1387,7 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear)
return;
}
fast = _PyFrame_GetLocalsArray(frame);
- co = frame->f_code;
+ co = _PyFrame_GetCode(frame);
PyObject *exc = PyErr_GetRaisedException();
for (int i = 0; i < co->co_nlocalsplus; i++) {
@@ -1417,7 +1473,7 @@ PyFrame_GetCode(PyFrameObject *frame)
{
assert(frame != NULL);
assert(!_PyFrame_IsIncomplete(frame->f_frame));
- PyCodeObject *code = frame->f_frame->f_code;
+ PyCodeObject *code = _PyFrame_GetCode(frame->f_frame);
assert(code != NULL);
return (PyCodeObject*)Py_NewRef(code);
}
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 753038600aa858..0c69bf4ebcfed5 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -106,9 +106,14 @@ PyFunction_ClearWatcher(int watcher_id)
PyFunctionObject *
_PyFunction_FromConstructor(PyFrameConstructor *constr)
{
+ PyObject *module = Py_XNewRef(PyDict_GetItemWithError(constr->fc_globals, &_Py_ID(__name__)));
+ if (!module && PyErr_Occurred()) {
+ return NULL;
+ }
PyFunctionObject *op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type);
if (op == NULL) {
+ Py_XDECREF(module);
return NULL;
}
op->func_globals = Py_NewRef(constr->fc_globals);
@@ -122,10 +127,7 @@ _PyFunction_FromConstructor(PyFrameConstructor *constr)
op->func_doc = Py_NewRef(Py_None);
op->func_dict = NULL;
op->func_weakreflist = NULL;
- op->func_module = Py_XNewRef(PyDict_GetItem(op->func_globals, &_Py_ID(__name__)));
- if (!op->func_module) {
- PyErr_Clear();
- }
+ op->func_module = module;
op->func_annotations = NULL;
op->func_typeparams = NULL;
op->vectorcall = _PyFunction_Vectorcall;
@@ -940,17 +942,12 @@ PyTypeObject PyFunction_Type = {
static int
functools_copy_attr(PyObject *wrapper, PyObject *wrapped, PyObject *name)
{
- PyObject *value = PyObject_GetAttr(wrapped, name);
- if (value == NULL) {
- if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
- PyErr_Clear();
- return 0;
- }
- return -1;
+ PyObject *value;
+ int res = PyObject_GetOptionalAttr(wrapped, name, &value);
+ if (value != NULL) {
+ res = PyObject_SetAttr(wrapper, name, value);
+ Py_DECREF(value);
}
-
- int res = PyObject_SetAttr(wrapper, name, value);
- Py_DECREF(value);
return res;
}
diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c
index 888cb16edd1b46..0c478f3717e036 100644
--- a/Objects/genericaliasobject.c
+++ b/Objects/genericaliasobject.c
@@ -63,12 +63,12 @@ ga_repr_item(_PyUnicodeWriter *writer, PyObject *p)
goto done;
}
- if (_PyObject_LookupAttr(p, &_Py_ID(__origin__), &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(p, &_Py_ID(__origin__), &tmp) < 0) {
goto done;
}
if (tmp != NULL) {
Py_DECREF(tmp);
- if (_PyObject_LookupAttr(p, &_Py_ID(__args__), &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(p, &_Py_ID(__args__), &tmp) < 0) {
goto done;
}
if (tmp != NULL) {
@@ -78,13 +78,13 @@ ga_repr_item(_PyUnicodeWriter *writer, PyObject *p)
}
}
- if (_PyObject_LookupAttr(p, &_Py_ID(__qualname__), &qualname) < 0) {
+ if (PyObject_GetOptionalAttr(p, &_Py_ID(__qualname__), &qualname) < 0) {
goto done;
}
if (qualname == NULL) {
goto use_repr;
}
- if (_PyObject_LookupAttr(p, &_Py_ID(__module__), &module) < 0) {
+ if (PyObject_GetOptionalAttr(p, &_Py_ID(__module__), &module) < 0) {
goto done;
}
if (module == NULL || module == Py_None) {
@@ -121,6 +121,36 @@ ga_repr_item(_PyUnicodeWriter *writer, PyObject *p)
return err;
}
+static int
+ga_repr_items_list(_PyUnicodeWriter *writer, PyObject *p)
+{
+ assert(PyList_CheckExact(p));
+
+ Py_ssize_t len = PyList_GET_SIZE(p);
+
+ if (_PyUnicodeWriter_WriteASCIIString(writer, "[", 1) < 0) {
+ return -1;
+ }
+
+ for (Py_ssize_t i = 0; i < len; i++) {
+ if (i > 0) {
+ if (_PyUnicodeWriter_WriteASCIIString(writer, ", ", 2) < 0) {
+ return -1;
+ }
+ }
+ PyObject *item = PyList_GET_ITEM(p, i);
+ if (ga_repr_item(writer, item) < 0) {
+ return -1;
+ }
+ }
+
+ if (_PyUnicodeWriter_WriteASCIIString(writer, "]", 1) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
static PyObject *
ga_repr(PyObject *self)
{
@@ -148,7 +178,13 @@ ga_repr(PyObject *self)
}
}
PyObject *p = PyTuple_GET_ITEM(alias->args, i);
- if (ga_repr_item(&writer, p) < 0) {
+ if (PyList_CheckExact(p)) {
+ // Looks like we are working with ParamSpec's list of type args:
+ if (ga_repr_items_list(&writer, p) < 0) {
+ goto error;
+ }
+ }
+ else if (ga_repr_item(&writer, p) < 0) {
goto error;
}
}
@@ -221,7 +257,7 @@ _Py_make_parameters(PyObject *args)
if (PyType_Check(t)) {
continue;
}
- if (_PyObject_LookupAttr(t, &_Py_ID(__typing_subst__), &subst) < 0) {
+ if (PyObject_GetOptionalAttr(t, &_Py_ID(__typing_subst__), &subst) < 0) {
Py_DECREF(parameters);
return NULL;
}
@@ -231,7 +267,7 @@ _Py_make_parameters(PyObject *args)
}
else {
PyObject *subparams;
- if (_PyObject_LookupAttr(t, &_Py_ID(__parameters__),
+ if (PyObject_GetOptionalAttr(t, &_Py_ID(__parameters__),
&subparams) < 0) {
Py_DECREF(parameters);
return NULL;
@@ -274,7 +310,7 @@ subs_tvars(PyObject *obj, PyObject *params,
PyObject **argitems, Py_ssize_t nargs)
{
PyObject *subparams;
- if (_PyObject_LookupAttr(obj, &_Py_ID(__parameters__), &subparams) < 0) {
+ if (PyObject_GetOptionalAttr(obj, &_Py_ID(__parameters__), &subparams) < 0) {
return NULL;
}
if (subparams && PyTuple_Check(subparams) && PyTuple_GET_SIZE(subparams)) {
@@ -325,7 +361,7 @@ _is_unpacked_typevartuple(PyObject *arg)
if (PyType_Check(arg)) { // TODO: Add test
return 0;
}
- int res = _PyObject_LookupAttr(arg, &_Py_ID(__typing_is_unpacked_typevartuple__), &tmp);
+ int res = PyObject_GetOptionalAttr(arg, &_Py_ID(__typing_is_unpacked_typevartuple__), &tmp);
if (res > 0) {
res = PyObject_IsTrue(tmp);
Py_DECREF(tmp);
@@ -347,7 +383,7 @@ _unpacked_tuple_args(PyObject *arg)
return Py_NewRef(result);
}
- if (_PyObject_LookupAttr(arg, &_Py_ID(__typing_unpacked_tuple_args__), &result) > 0) {
+ if (PyObject_GetOptionalAttr(arg, &_Py_ID(__typing_unpacked_tuple_args__), &result) > 0) {
if (result == Py_None) {
Py_DECREF(result);
return NULL;
@@ -412,7 +448,7 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
for (Py_ssize_t i = 0; i < nparams; i++) {
PyObject *param = PyTuple_GET_ITEM(parameters, i);
PyObject *prepare, *tmp;
- if (_PyObject_LookupAttr(param, &_Py_ID(__typing_prepare_subst__), &prepare) < 0) {
+ if (PyObject_GetOptionalAttr(param, &_Py_ID(__typing_prepare_subst__), &prepare) < 0) {
Py_DECREF(item);
return NULL;
}
@@ -467,7 +503,7 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
return NULL;
}
PyObject *subst;
- if (_PyObject_LookupAttr(arg, &_Py_ID(__typing_subst__), &subst) < 0) {
+ if (PyObject_GetOptionalAttr(arg, &_Py_ID(__typing_subst__), &subst) < 0) {
Py_DECREF(newargs);
Py_DECREF(item);
return NULL;
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 5c93ef49583b1e..103e8b8bb882f6 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -29,7 +29,7 @@ static const char *ASYNC_GEN_IGNORED_EXIT_MSG =
static inline PyCodeObject *
_PyGen_GetCode(PyGenObject *gen) {
_PyInterpreterFrame *frame = (_PyInterpreterFrame *)(gen->gi_iframe);
- return frame->f_code;
+ return _PyFrame_GetCode(frame);
}
PyCodeObject *
@@ -317,7 +317,7 @@ gen_close_iter(PyObject *yf)
}
else {
PyObject *meth;
- if (_PyObject_LookupAttr(yf, &_Py_ID(close), &meth) < 0) {
+ if (PyObject_GetOptionalAttr(yf, &_Py_ID(close), &meth) < 0) {
PyErr_WriteUnraisable(yf);
}
if (meth) {
@@ -492,7 +492,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
} else {
/* `yf` is an iterator or a coroutine-like object. */
PyObject *meth;
- if (_PyObject_LookupAttr(yf, &_Py_ID(throw), &meth) < 0) {
+ if (PyObject_GetOptionalAttr(yf, &_Py_ID(throw), &meth) < 0) {
Py_DECREF(yf);
return NULL;
}
@@ -957,7 +957,7 @@ static PyObject *
gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
PyObject *name, PyObject *qualname)
{
- PyCodeObject *code = f->f_frame->f_code;
+ PyCodeObject *code = _PyFrame_GetCode(f->f_frame);
int size = code->co_nlocalsplus + code->co_stacksize;
PyGenObject *gen = PyObject_GC_NewVar(PyGenObject, type, size);
if (gen == NULL) {
@@ -1339,7 +1339,7 @@ compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame)
}
frame = current_frame;
for (int i = 0; i < frame_count; ++i) {
- PyCodeObject *code = frame->f_code;
+ PyCodeObject *code = _PyFrame_GetCode(frame);
int line = PyUnstable_InterpreterFrame_GetLine(frame);
PyObject *frameinfo = Py_BuildValue("OiO", code->co_filename, line,
code->co_name);
diff --git a/Objects/iterobject.c b/Objects/iterobject.c
index 7cb17a6ca4ab56..cf7cb8af52a274 100644
--- a/Objects/iterobject.c
+++ b/Objects/iterobject.c
@@ -1,6 +1,7 @@
/* Iterator objects */
#include "Python.h"
+#include "pycore_abstract.h" // _PyObject_HasLen()
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_object.h" // _PyObject_GC_TRACK()
diff --git a/Objects/listobject.c b/Objects/listobject.c
index f1edfb3a9a039d..144ede6351e03c 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -5,6 +5,7 @@
#include "pycore_interp.h" // PyInterpreterState.list
#include "pycore_list.h" // struct _Py_list_state, _PyListIterObject
#include "pycore_long.h" // _PyLong_DigitCount
+#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_object.h" // _PyObject_GC_TRACK()
#include "pycore_tuple.h" // _PyTuple_FromArray()
#include
@@ -953,8 +954,9 @@ list_extend(PyListObject *self, PyObject *iterable)
}
if (Py_SIZE(self) < self->allocated) {
/* steals ref */
- PyList_SET_ITEM(self, Py_SIZE(self), item);
- Py_SET_SIZE(self, Py_SIZE(self) + 1);
+ Py_ssize_t len = Py_SIZE(self);
+ Py_SET_SIZE(self, len + 1);
+ PyList_SET_ITEM(self, len, item);
}
else {
if (_PyList_AppendTakeRef(self, item) < 0)
@@ -2692,7 +2694,7 @@ list_remove(PyListObject *self, PyObject *value)
else if (cmp < 0)
return NULL;
}
- PyErr_SetString(PyExc_ValueError, "list.remove(x): x not in list");
+ PyErr_Format(PyExc_ValueError, "%R is not in list", value);
return NULL;
}
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 51752dec3dd08c..fe081992d51fda 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -2,6 +2,7 @@
/* Method object implementation */
#include "Python.h"
+#include "pycore_call.h" // _Py_CheckFunctionResult()
#include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
#include "pycore_object.h"
#include "pycore_pyerrors.h"
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index 985be58d02c784..4071b5a3f1a62c 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -4,9 +4,11 @@
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_interp.h" // PyInterpreterState.importlib
+#include "pycore_modsupport.h" // _PyModule_CreateInitialized()
+#include "pycore_moduleobject.h" // _PyModule_GetDef()
#include "pycore_object.h" // _PyType_AllocNoTrack
+#include "pycore_pyerrors.h" // _PyErr_FormatFromCause()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
-#include "pycore_moduleobject.h" // _PyModule_GetDef()
#include "structmember.h" // PyMemberDef
@@ -504,7 +506,7 @@ PyModule_GetDict(PyObject *m)
PyErr_BadInternalCall();
return NULL;
}
- return _PyModule_GetDict(m);
+ return _PyModule_GetDict(m); // borrowed reference
}
PyObject*
@@ -740,7 +742,7 @@ _PyModuleSpec_IsInitializing(PyObject *spec)
{
if (spec != NULL) {
PyObject *value;
- int ok = _PyObject_LookupAttr(spec, &_Py_ID(_initializing), &value);
+ int ok = PyObject_GetOptionalAttr(spec, &_Py_ID(_initializing), &value);
if (ok == 0) {
return 0;
}
diff --git a/Objects/object.c b/Objects/object.c
index b20e87ef3fb23d..d30e048335ab63 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -692,7 +692,7 @@ _PyObject_FunctionStr(PyObject *x)
{
assert(!PyErr_Occurred());
PyObject *qualname;
- int ret = _PyObject_LookupAttr(x, &_Py_ID(__qualname__), &qualname);
+ int ret = PyObject_GetOptionalAttr(x, &_Py_ID(__qualname__), &qualname);
if (qualname == NULL) {
if (ret < 0) {
return NULL;
@@ -701,7 +701,7 @@ _PyObject_FunctionStr(PyObject *x)
}
PyObject *module;
PyObject *result = NULL;
- ret = _PyObject_LookupAttr(x, &_Py_ID(__module__), &module);
+ ret = PyObject_GetOptionalAttr(x, &_Py_ID(__module__), &module);
if (module != NULL && module != Py_None) {
ret = PyObject_RichCompareBool(module, &_Py_ID(builtins), Py_NE);
if (ret < 0) {
@@ -942,6 +942,12 @@ PyObject_SetAttrString(PyObject *v, const char *name, PyObject *w)
return res;
}
+int
+PyObject_DelAttrString(PyObject *v, const char *name)
+{
+ return PyObject_SetAttrString(v, name, NULL);
+}
+
int
_PyObject_IsAbstract(PyObject *obj)
{
@@ -951,7 +957,7 @@ _PyObject_IsAbstract(PyObject *obj)
if (obj == NULL)
return 0;
- res = _PyObject_LookupAttr(obj, &_Py_ID(__isabstractmethod__), &isabstract);
+ res = PyObject_GetOptionalAttr(obj, &_Py_ID(__isabstractmethod__), &isabstract);
if (res > 0) {
res = PyObject_IsTrue(isabstract);
Py_DECREF(isabstract);
@@ -1043,7 +1049,7 @@ PyObject_GetAttr(PyObject *v, PyObject *name)
}
int
-_PyObject_LookupAttr(PyObject *v, PyObject *name, PyObject **result)
+PyObject_GetOptionalAttr(PyObject *v, PyObject *name, PyObject **result)
{
PyTypeObject *tp = Py_TYPE(v);
@@ -1111,21 +1117,35 @@ _PyObject_LookupAttr(PyObject *v, PyObject *name, PyObject **result)
}
int
-_PyObject_LookupAttrId(PyObject *v, _Py_Identifier *name, PyObject **result)
+PyObject_GetOptionalAttrString(PyObject *obj, const char *name, PyObject **result)
{
- PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
- if (!oname) {
- *result = NULL;
+ if (Py_TYPE(obj)->tp_getattr == NULL) {
+ PyObject *oname = PyUnicode_FromString(name);
+ if (oname == NULL) {
+ *result = NULL;
+ return -1;
+ }
+ int rc = PyObject_GetOptionalAttr(obj, oname, result);
+ Py_DECREF(oname);
+ return rc;
+ }
+
+ *result = (*Py_TYPE(obj)->tp_getattr)(obj, (char*)name);
+ if (*result != NULL) {
+ return 1;
+ }
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
return -1;
}
- return _PyObject_LookupAttr(v, oname, result);
+ PyErr_Clear();
+ return 0;
}
int
PyObject_HasAttr(PyObject *v, PyObject *name)
{
PyObject *res;
- if (_PyObject_LookupAttr(v, name, &res) < 0) {
+ if (PyObject_GetOptionalAttr(v, name, &res) < 0) {
PyErr_Clear();
return 0;
}
@@ -1185,6 +1205,12 @@ PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
return -1;
}
+int
+PyObject_DelAttr(PyObject *v, PyObject *name)
+{
+ return PyObject_SetAttr(v, name, NULL);
+}
+
PyObject **
_PyObject_ComputedDictPointer(PyObject *obj)
{
@@ -1690,13 +1716,15 @@ _dir_locals(void)
PyObject *names;
PyObject *locals;
- locals = PyEval_GetLocals();
+ locals = _PyEval_GetFrameLocals();
if (locals == NULL)
return NULL;
names = PyMapping_Keys(locals);
- if (!names)
+ Py_DECREF(locals);
+ if (!names) {
return NULL;
+ }
if (!PyList_Check(names)) {
PyErr_Format(PyExc_TypeError,
"dir(): expected keys() of locals to be a list, "
@@ -1708,7 +1736,6 @@ _dir_locals(void)
Py_DECREF(names);
return NULL;
}
- /* the locals don't need to be DECREF'd */
return names;
}
diff --git a/Objects/object_layout.md b/Objects/object_layout.md
index 9380b57938c8e3..4430790f4f0f36 100644
--- a/Objects/object_layout.md
+++ b/Objects/object_layout.md
@@ -45,7 +45,7 @@ pointers are combined into a single tagged pointer:
If the object has no physical dictionary, then the ``dict_or_values``
has its low bit set to one, and points to the values array.
-If the object has a physical dictioanry, then the ``dict_or_values``
+If the object has a physical dictionary, then the ``dict_or_values``
has its low bit set to zero, and points to the dictionary.
The untagged form is chosen for the dictionary pointer, rather than
diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c
index 9620a8fbb44cac..eb68d7c030d293 100644
--- a/Objects/obmalloc.c
+++ b/Objects/obmalloc.c
@@ -2,10 +2,10 @@
#include "Python.h"
#include "pycore_code.h" // stats
-#include "pycore_pystate.h" // _PyInterpreterState_GET
-
#include "pycore_obmalloc.h"
+#include "pycore_pyerrors.h" // _Py_FatalErrorFormat()
#include "pycore_pymem.h"
+#include "pycore_pystate.h" // _PyInterpreterState_GET
#include // malloc()
#include
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
index 39b0f684510578..e76d2ded61cf74 100644
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -2154,7 +2154,7 @@ mutablemapping_update_arg(PyObject *self, PyObject *arg)
return res;
}
PyObject *func;
- if (_PyObject_LookupAttr(arg, &_Py_ID(keys), &func) < 0) {
+ if (PyObject_GetOptionalAttr(arg, &_Py_ID(keys), &func) < 0) {
return -1;
}
if (func != NULL) {
@@ -2186,7 +2186,7 @@ mutablemapping_update_arg(PyObject *self, PyObject *arg)
}
return 0;
}
- if (_PyObject_LookupAttr(arg, &_Py_ID(items), &func) < 0) {
+ if (PyObject_GetOptionalAttr(arg, &_Py_ID(items), &func) < 0) {
return -1;
}
if (func != NULL) {
diff --git a/Objects/picklebufobject.c b/Objects/picklebufobject.c
index aaa852cfbb05b0..ca83a0a0806ce1 100644
--- a/Objects/picklebufobject.c
+++ b/Objects/picklebufobject.c
@@ -1,6 +1,5 @@
/* PickleBuffer object implementation */
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include
diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c
index beb86b9623bdbc..6dc41d71287cab 100644
--- a/Objects/rangeobject.c
+++ b/Objects/rangeobject.c
@@ -2,8 +2,9 @@
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
-#include "pycore_range.h"
#include "pycore_long.h" // _PyLong_GetZero()
+#include "pycore_modsupport.h" // _PyArg_NoKwnames()
+#include "pycore_range.h"
#include "pycore_tuple.h" // _PyTuple_ITEMS()
#include "structmember.h" // PyMemberDef
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 58f0ae73c0c403..4ac541b9509752 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -32,6 +32,7 @@
*/
#include "Python.h"
+#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include // offsetof()
diff --git a/Objects/stringlib/unicode_format.h b/Objects/stringlib/unicode_format.h
index f4ba0a92776a97..91c71ab5736c25 100644
--- a/Objects/stringlib/unicode_format.h
+++ b/Objects/stringlib/unicode_format.h
@@ -2,6 +2,7 @@
unicode_format.h -- implementation of str.format().
*/
+#include "pycore_complexobject.h" // _PyComplex_FormatAdvancedWriter()
#include "pycore_floatobject.h" // _PyFloat_FormatAdvancedWriter()
/************************************************************************/
diff --git a/Objects/structseq.c b/Objects/structseq.c
index 8b1895957101a4..49011139b66534 100644
--- a/Objects/structseq.c
+++ b/Objects/structseq.c
@@ -74,15 +74,28 @@ PyStructSequence_New(PyTypeObject *type)
}
void
-PyStructSequence_SetItem(PyObject* op, Py_ssize_t i, PyObject* v)
+PyStructSequence_SetItem(PyObject *op, Py_ssize_t index, PyObject *value)
{
- PyStructSequence_SET_ITEM(op, i, v);
+ PyTupleObject *tuple = _PyTuple_CAST(op);
+ assert(0 <= index);
+#ifndef NDEBUG
+ Py_ssize_t n_fields = REAL_SIZE(op);
+ assert(n_fields >= 0);
+ assert(index < n_fields);
+#endif
+ tuple->ob_item[index] = value;
}
PyObject*
-PyStructSequence_GetItem(PyObject* op, Py_ssize_t i)
+PyStructSequence_GetItem(PyObject *op, Py_ssize_t index)
{
- return PyStructSequence_GET_ITEM(op, i);
+ assert(0 <= index);
+#ifndef NDEBUG
+ Py_ssize_t n_fields = REAL_SIZE(op);
+ assert(n_fields >= 0);
+ assert(index < n_fields);
+#endif
+ return PyTuple_GET_ITEM(op, index);
}
@@ -287,7 +300,7 @@ structseq_repr(PyStructSequence *obj)
goto error;
}
- PyObject *value = PyStructSequence_GET_ITEM(obj, i);
+ PyObject *value = PyStructSequence_GetItem((PyObject*)obj, i);
assert(value != NULL);
PyObject *repr = PyObject_Repr(value);
if (repr == NULL) {
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 991edcc86677de..e85af2b75e4738 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -5,6 +5,7 @@
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_gc.h" // _PyObject_GC_IS_TRACKED()
#include "pycore_initconfig.h" // _PyStatus_OK()
+#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_object.h" // _PyObject_GC_TRACK(), _Py_FatalRefcountError()
/*[clinic input]
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 0a57991d26251d..b1f9f1280fd04d 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1,20 +1,22 @@
/* Type object implementation */
#include "Python.h"
-#include "pycore_call.h"
+#include "pycore_abstract.h" // _PySequence_IterSearch()
+#include "pycore_call.h" // _PyObject_VectorcallTstate()
#include "pycore_code.h" // CO_FAST_FREE
-#include "pycore_symtable.h" // _Py_Mangle()
#include "pycore_dict.h" // _PyDict_KeysSize()
-#include "pycore_initconfig.h" // _PyStatus_OK()
+#include "pycore_frame.h" // _PyInterpreterFrame
+#include "pycore_long.h" // _PyLong_IsNegative()
#include "pycore_memoryobject.h" // _PyMemoryView_FromBufferProc()
+#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_moduleobject.h" // _PyModule_GetDef()
#include "pycore_object.h" // _PyType_HasFeature()
-#include "pycore_long.h" // _PyLong_IsNegative()
#include "pycore_pyerrors.h" // _PyErr_Occurred()
#include "pycore_pystate.h" // _PyThreadState_GET()
+#include "pycore_symtable.h" // _Py_Mangle()
#include "pycore_typeobject.h" // struct type_cache
#include "pycore_unionobject.h" // _Py_union_type_or
-#include "pycore_frame.h" // _PyInterpreterFrame
+#include "pycore_weakref.h" // _PyWeakref_GET_REF()
#include "opcode.h" // MAKE_CELL
#include "structmember.h" // PyMemberDef
@@ -75,13 +77,10 @@ slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value);
static inline PyTypeObject *
type_from_ref(PyObject *ref)
{
- assert(PyWeakref_CheckRef(ref));
- PyObject *obj = PyWeakref_GET_OBJECT(ref); // borrowed ref
- assert(obj != NULL);
- if (obj == Py_None) {
+ PyObject *obj = _PyWeakref_GET_REF(ref);
+ if (obj == NULL) {
return NULL;
}
- assert(PyType_Check(obj));
return _PyType_CAST(obj);
}
@@ -238,6 +237,13 @@ _PyType_GetDict(PyTypeObject *self)
return lookup_tp_dict(self);
}
+PyObject *
+PyType_GetDict(PyTypeObject *self)
+{
+ PyObject *dict = lookup_tp_dict(self);
+ return _Py_XNewRef(dict);
+}
+
static inline void
set_tp_dict(PyTypeObject *self, PyObject *dict)
{
@@ -450,15 +456,17 @@ _PyType_GetSubclasses(PyTypeObject *self)
Py_ssize_t i = 0;
PyObject *ref; // borrowed ref
while (PyDict_Next(subclasses, &i, NULL, &ref)) {
- PyTypeObject *subclass = type_from_ref(ref); // borrowed
+ PyTypeObject *subclass = type_from_ref(ref);
if (subclass == NULL) {
continue;
}
if (PyList_Append(list, _PyObject_CAST(subclass)) < 0) {
Py_DECREF(list);
+ Py_DECREF(subclass);
return NULL;
}
+ Py_DECREF(subclass);
}
return list;
}
@@ -778,11 +786,12 @@ PyType_Modified(PyTypeObject *type)
Py_ssize_t i = 0;
PyObject *ref;
while (PyDict_Next(subclasses, &i, NULL, &ref)) {
- PyTypeObject *subclass = type_from_ref(ref); // borrowed
+ PyTypeObject *subclass = type_from_ref(ref);
if (subclass == NULL) {
continue;
}
PyType_Modified(subclass);
+ Py_DECREF(subclass);
}
}
@@ -1507,11 +1516,14 @@ type_set_annotations(PyTypeObject *type, PyObject *value, void *context)
static PyObject *
type_get_type_params(PyTypeObject *type, void *context)
{
- PyObject *params = PyDict_GetItem(lookup_tp_dict(type), &_Py_ID(__type_params__));
+ PyObject *params = PyDict_GetItemWithError(lookup_tp_dict(type), &_Py_ID(__type_params__));
if (params) {
return Py_NewRef(params);
}
+ if (PyErr_Occurred()) {
+ return NULL;
+ }
return PyTuple_New(0);
}
@@ -1680,6 +1692,26 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
return obj;
}
+PyObject *
+_PyType_NewManagedObject(PyTypeObject *type)
+{
+ assert(type->tp_flags & Py_TPFLAGS_MANAGED_DICT);
+ assert(_PyType_IS_GC(type));
+ assert(type->tp_new == PyBaseObject_Type.tp_new);
+ assert(type->tp_alloc == PyType_GenericAlloc);
+ assert(type->tp_itemsize == 0);
+ PyObject *obj = PyType_GenericAlloc(type, 0);
+ if (obj == NULL) {
+ return PyErr_NoMemory();
+ }
+ _PyObject_DictOrValuesPointer(obj)->dict = NULL;
+ if (_PyObject_InitInlineValues(obj, type)) {
+ Py_DECREF(obj);
+ return NULL;
+ }
+ return obj;
+}
+
PyObject *
_PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems)
{
@@ -2327,7 +2359,7 @@ static PyObject *
class_name(PyObject *cls)
{
PyObject *name;
- if (_PyObject_LookupAttr(cls, &_Py_ID(__name__), &name) == 0) {
+ if (PyObject_GetOptionalAttr(cls, &_Py_ID(__name__), &name) == 0) {
name = PyObject_Repr(cls);
}
return name;
@@ -3833,7 +3865,7 @@ type_new_get_bases(type_new_ctx *ctx, PyObject **type)
continue;
}
PyObject *mro_entries;
- if (_PyObject_LookupAttr(base, &_Py_ID(__mro_entries__),
+ if (PyObject_GetOptionalAttr(base, &_Py_ID(__mro_entries__),
&mro_entries) < 0) {
return -1;
}
@@ -4236,7 +4268,7 @@ _PyType_FromMetaclass_impl(
metaclass);
goto finally;
}
- if (metaclass->tp_new != PyType_Type.tp_new) {
+ if (metaclass->tp_new && metaclass->tp_new != PyType_Type.tp_new) {
if (_allow_tp_new) {
if (PyErr_WarnFormat(
PyExc_DeprecationWarning, 1,
@@ -4985,17 +5017,20 @@ clear_static_tp_subclasses(PyTypeObject *type)
going to leak. This mostly only affects embedding scenarios.
*/
+#ifndef NDEBUG
// For now we just do a sanity check and then clear tp_subclasses.
Py_ssize_t i = 0;
PyObject *key, *ref; // borrowed ref
while (PyDict_Next(subclasses, &i, &key, &ref)) {
- PyTypeObject *subclass = type_from_ref(ref); // borrowed
+ PyTypeObject *subclass = type_from_ref(ref);
if (subclass == NULL) {
continue;
}
// All static builtin subtypes should have been finalized already.
assert(!(subclass->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN));
+ Py_DECREF(subclass);
}
+#endif
clear_tp_subclasses(type);
}
@@ -5112,7 +5147,7 @@ merge_class_dict(PyObject *dict, PyObject *aclass)
assert(aclass);
/* Merge in the type's dict (if any). */
- if (_PyObject_LookupAttr(aclass, &_Py_ID(__dict__), &classdict) < 0) {
+ if (PyObject_GetOptionalAttr(aclass, &_Py_ID(__dict__), &classdict) < 0) {
return -1;
}
if (classdict != NULL) {
@@ -5123,7 +5158,7 @@ merge_class_dict(PyObject *dict, PyObject *aclass)
}
/* Recursively merge in the base types' (if any) dicts. */
- if (_PyObject_LookupAttr(aclass, &_Py_ID(__bases__), &bases) < 0) {
+ if (PyObject_GetOptionalAttr(aclass, &_Py_ID(__bases__), &bases) < 0) {
return -1;
}
if (bases != NULL) {
@@ -5949,7 +5984,7 @@ object_getstate_default(PyObject *obj, int required)
PyObject *name, *value;
name = Py_NewRef(PyList_GET_ITEM(slotnames, i));
- if (_PyObject_LookupAttr(obj, name, &value) < 0) {
+ if (PyObject_GetOptionalAttr(obj, name, &value) < 0) {
Py_DECREF(name);
goto error;
}
@@ -6335,7 +6370,7 @@ object___reduce_ex___impl(PyObject *self, int protocol)
/*[clinic end generated code: output=2e157766f6b50094 input=f326b43fb8a4c5ff]*/
{
#define objreduce \
- (_Py_INTERP_CACHED_OBJECT(_PyInterpreterState_Get(), objreduce))
+ (_Py_INTERP_CACHED_OBJECT(_PyInterpreterState_GET(), objreduce))
PyObject *reduce, *res;
if (objreduce == NULL) {
@@ -6346,7 +6381,7 @@ object___reduce_ex___impl(PyObject *self, int protocol)
}
}
- if (_PyObject_LookupAttr(self, &_Py_ID(__reduce__), &reduce) < 0) {
+ if (PyObject_GetOptionalAttr(self, &_Py_ID(__reduce__), &reduce) < 0) {
return NULL;
}
if (reduce != NULL) {
@@ -6465,7 +6500,7 @@ object___dir___impl(PyObject *self)
PyObject *itsclass = NULL;
/* Get __dict__ (which may or may not be a real dict...) */
- if (_PyObject_LookupAttr(self, &_Py_ID(__dict__), &dict) < 0) {
+ if (PyObject_GetOptionalAttr(self, &_Py_ID(__dict__), &dict) < 0) {
return NULL;
}
if (dict == NULL) {
@@ -6485,7 +6520,7 @@ object___dir___impl(PyObject *self)
goto error;
/* Merge in attrs reachable from its class. */
- if (_PyObject_LookupAttr(self, &_Py_ID(__class__), &itsclass) < 0) {
+ if (PyObject_GetOptionalAttr(self, &_Py_ID(__class__), &itsclass) < 0) {
goto error;
}
/* XXX(tomer): Perhaps fall back to Py_TYPE(obj) if no
@@ -7636,10 +7671,15 @@ get_subclasses_key(PyTypeObject *type, PyTypeObject *base)
PyObject *subclasses = lookup_tp_subclasses(base);
if (subclasses != NULL) {
while (PyDict_Next(subclasses, &i, &key, &ref)) {
- PyTypeObject *subclass = type_from_ref(ref); // borrowed
+ PyTypeObject *subclass = type_from_ref(ref);
+ if (subclass == NULL) {
+ continue;
+ }
if (subclass == type) {
+ Py_DECREF(subclass);
return Py_NewRef(key);
}
+ Py_DECREF(subclass);
}
}
/* It wasn't found. */
@@ -8353,7 +8393,7 @@ method_is_overloaded(PyObject *left, PyObject *right, PyObject *name)
PyObject *a, *b;
int ok;
- if (_PyObject_LookupAttr((PyObject *)(Py_TYPE(right)), name, &b) < 0) {
+ if (PyObject_GetOptionalAttr((PyObject *)(Py_TYPE(right)), name, &b) < 0) {
return -1;
}
if (b == NULL) {
@@ -8361,7 +8401,7 @@ method_is_overloaded(PyObject *left, PyObject *right, PyObject *name)
return 0;
}
- if (_PyObject_LookupAttr((PyObject *)(Py_TYPE(left)), name, &a) < 0) {
+ if (PyObject_GetOptionalAttr((PyObject *)(Py_TYPE(left)), name, &a) < 0) {
Py_DECREF(b);
return -1;
}
@@ -9656,7 +9696,7 @@ resolve_slotdups(PyTypeObject *type, PyObject *name)
/* XXX Maybe this could be optimized more -- but is it worth it? */
/* pname and ptrs act as a little cache */
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
#define pname _Py_INTERP_CACHED_OBJECT(interp, type_slots_pname)
#define ptrs _Py_INTERP_CACHED_OBJECT(interp, type_slots_ptrs)
pytype_slotdef *p, **pp;
@@ -9983,7 +10023,8 @@ static int
type_new_init_subclass(PyTypeObject *type, PyObject *kwds)
{
PyObject *args[2] = {(PyObject *)type, (PyObject *)type};
- PyObject *super = _PyObject_FastCall((PyObject *)&PySuper_Type, args, 2);
+ PyObject *super = PyObject_Vectorcall((PyObject *)&PySuper_Type,
+ args, 2, NULL);
if (super == NULL) {
return -1;
}
@@ -10035,7 +10076,7 @@ recurse_down_subclasses(PyTypeObject *type, PyObject *attr_name,
Py_ssize_t i = 0;
PyObject *ref;
while (PyDict_Next(subclasses, &i, NULL, &ref)) {
- PyTypeObject *subclass = type_from_ref(ref); // borrowed
+ PyTypeObject *subclass = type_from_ref(ref);
if (subclass == NULL) {
continue;
}
@@ -10045,16 +10086,20 @@ recurse_down_subclasses(PyTypeObject *type, PyObject *attr_name,
if (dict != NULL && PyDict_Check(dict)) {
int r = PyDict_Contains(dict, attr_name);
if (r < 0) {
+ Py_DECREF(subclass);
return -1;
}
if (r > 0) {
+ Py_DECREF(subclass);
continue;
}
}
if (update_subclasses(subclass, attr_name, callback, data) < 0) {
+ Py_DECREF(subclass);
return -1;
}
+ Py_DECREF(subclass);
}
return 0;
}
@@ -10328,7 +10373,7 @@ supercheck(PyTypeObject *type, PyObject *obj)
/* Try the slow way */
PyObject *class_attr;
- if (_PyObject_LookupAttr(obj, &_Py_ID(__class__), &class_attr) < 0) {
+ if (PyObject_GetOptionalAttr(obj, &_Py_ID(__class__), &class_attr) < 0) {
return NULL;
}
if (class_attr != NULL &&
@@ -10405,7 +10450,7 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co,
return -1;
}
- assert(cframe->f_code->co_nlocalsplus > 0);
+ assert(_PyFrame_GetCode(cframe)->co_nlocalsplus > 0);
PyObject *firstarg = _PyFrame_GetLocalsArray(cframe)[0];
// The first argument might be a cell.
if (firstarg != NULL && (_PyLocals_GetKind(co->co_localspluskinds, 0) & CO_FAST_CELL)) {
@@ -10498,7 +10543,7 @@ super_init_impl(PyObject *self, PyTypeObject *type, PyObject *obj) {
"super(): no current frame");
return -1;
}
- int res = super_init_without_args(frame, frame->f_code, &type, &obj);
+ int res = super_init_without_args(frame, _PyFrame_GetCode(frame), &type, &obj);
if (res < 0) {
return -1;
diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c
index 406a6eb76e3a8a..5605662f0e6d5e 100644
--- a/Objects/typevarobject.c
+++ b/Objects/typevarobject.c
@@ -1,6 +1,6 @@
// TypeVar, TypeVarTuple, and ParamSpec
#include "Python.h"
-#include "pycore_object.h" // _PyObject_GC_TRACK/UNTRACK
+#include "pycore_object.h" // _PyObject_GC_TRACK/UNTRACK
#include "pycore_typevarobject.h"
#include "pycore_unionobject.h" // _Py_union_type_or
#include "structmember.h"
@@ -144,7 +144,7 @@ static int
contains_typevartuple(PyTupleObject *params)
{
Py_ssize_t n = PyTuple_GET_SIZE(params);
- PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.typevartuple_type;
+ PyTypeObject *tp = _PyInterpreterState_GET()->cached_objects.typevartuple_type;
for (Py_ssize_t i = 0; i < n; i++) {
PyObject *param = PyTuple_GET_ITEM(params, i);
if (Py_IS_TYPE(param, tp)) {
@@ -165,7 +165,7 @@ unpack_typevartuples(PyObject *params)
if (new_params == NULL) {
return NULL;
}
- PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.typevartuple_type;
+ PyTypeObject *tp = _PyInterpreterState_GET()->cached_objects.typevartuple_type;
for (Py_ssize_t i = 0; i < n; i++) {
PyObject *param = PyTuple_GET_ITEM(params, i);
if (Py_IS_TYPE(param, tp)) {
@@ -291,7 +291,7 @@ typevar_alloc(PyObject *name, PyObject *bound, PyObject *evaluate_bound,
bool covariant, bool contravariant, bool infer_variance,
PyObject *module)
{
- PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.typevar_type;
+ PyTypeObject *tp = _PyInterpreterState_GET()->cached_objects.typevar_type;
assert(tp != NULL);
typevarobject *tv = PyObject_GC_New(typevarobject, tp);
if (tv == NULL) {
@@ -500,7 +500,7 @@ PyType_Spec typevar_spec = {
.name = "typing.TypeVar",
.basicsize = sizeof(typevarobject),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE
- | Py_TPFLAGS_MANAGED_DICT,
+ | Py_TPFLAGS_MANAGED_DICT | Py_TPFLAGS_MANAGED_WEAKREF,
.slots = typevar_slots,
};
@@ -576,7 +576,7 @@ paramspecargs_repr(PyObject *self)
{
paramspecattrobject *psa = (paramspecattrobject *)self;
- PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.paramspec_type;
+ PyTypeObject *tp = _PyInterpreterState_GET()->cached_objects.paramspec_type;
if (Py_IS_TYPE(psa->__origin__, tp)) {
return PyUnicode_FromFormat("%U.args",
((paramspecobject *)psa->__origin__)->name);
@@ -647,7 +647,8 @@ static PyType_Slot paramspecargs_slots[] = {
PyType_Spec paramspecargs_spec = {
.name = "typing.ParamSpecArgs",
.basicsize = sizeof(paramspecattrobject),
- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE,
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE
+ | Py_TPFLAGS_MANAGED_WEAKREF,
.slots = paramspecargs_slots,
};
@@ -656,7 +657,7 @@ paramspeckwargs_repr(PyObject *self)
{
paramspecattrobject *psk = (paramspecattrobject *)self;
- PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.paramspec_type;
+ PyTypeObject *tp = _PyInterpreterState_GET()->cached_objects.paramspec_type;
if (Py_IS_TYPE(psk->__origin__, tp)) {
return PyUnicode_FromFormat("%U.kwargs",
((paramspecobject *)psk->__origin__)->name);
@@ -726,7 +727,8 @@ static PyType_Slot paramspeckwargs_slots[] = {
PyType_Spec paramspeckwargs_spec = {
.name = "typing.ParamSpecKwargs",
.basicsize = sizeof(paramspecattrobject),
- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE,
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE
+ | Py_TPFLAGS_MANAGED_WEAKREF,
.slots = paramspeckwargs_slots,
};
@@ -789,14 +791,14 @@ static PyMemberDef paramspec_members[] = {
static PyObject *
paramspec_args(PyObject *self, void *unused)
{
- PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.paramspecargs_type;
+ PyTypeObject *tp = _PyInterpreterState_GET()->cached_objects.paramspecargs_type;
return (PyObject *)paramspecattr_new(tp, self);
}
static PyObject *
paramspec_kwargs(PyObject *self, void *unused)
{
- PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.paramspeckwargs_type;
+ PyTypeObject *tp = _PyInterpreterState_GET()->cached_objects.paramspeckwargs_type;
return (PyObject *)paramspecattr_new(tp, self);
}
@@ -810,7 +812,7 @@ static paramspecobject *
paramspec_alloc(PyObject *name, PyObject *bound, bool covariant,
bool contravariant, bool infer_variance, PyObject *module)
{
- PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.paramspec_type;
+ PyTypeObject *tp = _PyInterpreterState_GET()->cached_objects.paramspec_type;
paramspecobject *ps = PyObject_GC_New(paramspecobject, tp);
if (ps == NULL) {
return NULL;
@@ -1007,7 +1009,7 @@ PyType_Spec paramspec_spec = {
.name = "typing.ParamSpec",
.basicsize = sizeof(paramspecobject),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE
- | Py_TPFLAGS_MANAGED_DICT,
+ | Py_TPFLAGS_MANAGED_DICT | Py_TPFLAGS_MANAGED_WEAKREF,
.slots = paramspec_slots,
};
@@ -1059,7 +1061,7 @@ static PyMemberDef typevartuple_members[] = {
static typevartupleobject *
typevartuple_alloc(PyObject *name, PyObject *module)
{
- PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.typevartuple_type;
+ PyTypeObject *tp = _PyInterpreterState_GET()->cached_objects.typevartuple_type;
typevartupleobject *tvt = PyObject_GC_New(typevartupleobject, tp);
if (tvt == NULL) {
return NULL;
@@ -1228,7 +1230,7 @@ PyType_Spec typevartuple_spec = {
.name = "typing.TypeVarTuple",
.basicsize = sizeof(typevartupleobject),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_DICT
- | Py_TPFLAGS_HAVE_GC,
+ | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_WEAKREF,
.slots = typevartuple_slots,
};
@@ -1598,7 +1600,7 @@ _Py_subscript_generic(PyThreadState* unused, PyObject *params)
{
params = unpack_typevartuples(params);
- PyInterpreterState *interp = PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
if (interp->cached_objects.generic_type == NULL) {
PyErr_SetString(PyExc_SystemError, "Cannot find Generic type");
return NULL;
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index ffb4a87d4b9265..f543c0a65b49f6 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -38,18 +38,19 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_atomic_funcs.h" // _Py_atomic_size_get()
-#include "pycore_bytesobject.h" // _PyBytes_Repeat()
#include "pycore_bytes_methods.h" // _Py_bytes_lower()
+#include "pycore_bytesobject.h" // _PyBytes_Repeat()
+#include "pycore_codecs.h" // _PyCodec_Lookup()
#include "pycore_format.h" // F_LJUST
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_interp.h" // PyInterpreterState.fs_codec
#include "pycore_long.h" // _PyLong_FormatWriter()
#include "pycore_object.h" // _PyObject_GC_TRACK(), _Py_FatalRefcountError()
#include "pycore_pathconfig.h" // _Py_DumpPathConfig()
+#include "pycore_pyerrors.h" // _PyUnicodeTranslateError_Create()
#include "pycore_pylifecycle.h" // _Py_SetFileSystemEncoding()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
@@ -5830,7 +5831,7 @@ _PyUnicode_DecodeUnicodeEscapeInternal(const char *s,
PyObject *errorHandler = NULL;
PyObject *exc = NULL;
_PyUnicode_Name_CAPI *ucnhash_capi;
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
// so we can remember if we've seen an invalid escape char or not
*first_invalid_escape = NULL;
@@ -7934,25 +7935,30 @@ PyUnicode_BuildEncodingMap(PyObject* string)
if (need_dict) {
PyObject *result = PyDict_New();
- PyObject *key, *value;
if (!result)
return NULL;
for (i = 0; i < length; i++) {
- key = PyLong_FromLong(PyUnicode_READ(kind, data, i));
- value = PyLong_FromLong(i);
- if (!key || !value)
- goto failed1;
- if (PyDict_SetItem(result, key, value) == -1)
- goto failed1;
+ Py_UCS4 c = PyUnicode_READ(kind, data, i);
+ PyObject *key = PyLong_FromLong(c);
+ if (key == NULL) {
+ Py_DECREF(result);
+ return NULL;
+ }
+ PyObject *value = PyLong_FromLong(i);
+ if (value == NULL) {
+ Py_DECREF(key);
+ Py_DECREF(result);
+ return NULL;
+ }
+ int rc = PyDict_SetItem(result, key, value);
Py_DECREF(key);
Py_DECREF(value);
+ if (rc < 0) {
+ Py_DECREF(result);
+ return NULL;
+ }
}
return result;
- failed1:
- Py_XDECREF(key);
- Py_XDECREF(value);
- Py_DECREF(result);
- return NULL;
}
/* Create a three-level trie */
@@ -12019,10 +12025,10 @@ str.replace as unicode_replace
old: unicode
new: unicode
+ /
count: Py_ssize_t = -1
Maximum number of occurrences to replace.
-1 (the default value) means replace all occurrences.
- /
Return a copy with all occurrences of substring old replaced by new.
@@ -12033,7 +12039,7 @@ replaced.
static PyObject *
unicode_replace_impl(PyObject *self, PyObject *old, PyObject *new,
Py_ssize_t count)
-/*[clinic end generated code: output=b63f1a8b5eebf448 input=147d12206276ebeb]*/
+/*[clinic end generated code: output=b63f1a8b5eebf448 input=3345c455d60a5499]*/
{
return replace(self, old, new, count);
}
diff --git a/Objects/unionobject.c b/Objects/unionobject.c
index f509a161bb9564..269f46914f263d 100644
--- a/Objects/unionobject.c
+++ b/Objects/unionobject.c
@@ -194,13 +194,13 @@ union_repr_item(_PyUnicodeWriter *writer, PyObject *p)
return _PyUnicodeWriter_WriteASCIIString(writer, "None", 4);
}
- if (_PyObject_LookupAttr(p, &_Py_ID(__origin__), &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(p, &_Py_ID(__origin__), &tmp) < 0) {
goto exit;
}
if (tmp) {
Py_DECREF(tmp);
- if (_PyObject_LookupAttr(p, &_Py_ID(__args__), &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(p, &_Py_ID(__args__), &tmp) < 0) {
goto exit;
}
if (tmp) {
@@ -210,13 +210,13 @@ union_repr_item(_PyUnicodeWriter *writer, PyObject *p)
}
}
- if (_PyObject_LookupAttr(p, &_Py_ID(__qualname__), &qualname) < 0) {
+ if (PyObject_GetOptionalAttr(p, &_Py_ID(__qualname__), &qualname) < 0) {
goto exit;
}
if (qualname == NULL) {
goto use_repr;
}
- if (_PyObject_LookupAttr(p, &_Py_ID(__module__), &module) < 0) {
+ if (PyObject_GetOptionalAttr(p, &_Py_ID(__module__), &module) < 0) {
goto exit;
}
if (module == NULL || module == Py_None) {
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
index aee79fc1410b29..e9563729bf82ba 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -1,5 +1,7 @@
#include "Python.h"
+#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR()
+#include "pycore_weakref.h" // _PyWeakref_GET_REF()
#include "structmember.h" // PyMemberDef
@@ -19,7 +21,7 @@ _PyWeakref_GetWeakrefCount(PyWeakReference *head)
return count;
}
-static PyObject *weakref_vectorcall(PyWeakReference *self, PyObject *const *args, size_t nargsf, PyObject *kwnames);
+static PyObject *weakref_vectorcall(PyObject *self, PyObject *const *args, size_t nargsf, PyObject *kwnames);
static void
init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
@@ -29,7 +31,7 @@ init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
self->wr_prev = NULL;
self->wr_next = NULL;
self->wr_callback = Py_XNewRef(callback);
- self->vectorcall = (vectorcallfunc)weakref_vectorcall;
+ self->vectorcall = weakref_vectorcall;
}
static PyWeakReference *
@@ -129,7 +131,7 @@ gc_clear(PyWeakReference *self)
static PyObject *
-weakref_vectorcall(PyWeakReference *self, PyObject *const *args,
+weakref_vectorcall(PyObject *self, PyObject *const *args,
size_t nargsf, PyObject *kwnames)
{
if (!_PyArg_NoKwnames("weakref", kwnames)) {
@@ -139,7 +141,11 @@ weakref_vectorcall(PyWeakReference *self, PyObject *const *args,
if (!_PyArg_CheckPositional("weakref", nargs, 0, 0)) {
return NULL;
}
- return Py_NewRef(PyWeakref_GET_OBJECT(self));
+ PyObject *obj = _PyWeakref_GET_REF(self);
+ if (obj == NULL) {
+ Py_RETURN_NONE;
+ }
+ return obj;
}
static Py_hash_t
@@ -147,12 +153,11 @@ weakref_hash(PyWeakReference *self)
{
if (self->hash != -1)
return self->hash;
- PyObject* obj = PyWeakref_GET_OBJECT(self);
- if (obj == Py_None) {
+ PyObject* obj = _PyWeakref_GET_REF((PyObject*)self);
+ if (obj == NULL) {
PyErr_SetString(PyExc_TypeError, "weak object has gone away");
return -1;
}
- Py_INCREF(obj);
self->hash = PyObject_Hash(obj);
Py_DECREF(obj);
return self->hash;
@@ -160,31 +165,24 @@ weakref_hash(PyWeakReference *self)
static PyObject *
-weakref_repr(PyWeakReference *self)
+weakref_repr(PyObject *self)
{
- PyObject *name, *repr;
- PyObject* obj = PyWeakref_GET_OBJECT(self);
-
- if (obj == Py_None) {
+ PyObject* obj = _PyWeakref_GET_REF(self);
+ if (obj == NULL) {
return PyUnicode_FromFormat("", self);
}
- Py_INCREF(obj);
- name = _PyObject_LookupSpecial(obj, &_Py_ID(__name__));
+ PyObject *name = _PyObject_LookupSpecial(obj, &_Py_ID(__name__));
+ PyObject *repr;
if (name == NULL || !PyUnicode_Check(name)) {
repr = PyUnicode_FromFormat(
"",
- self,
- Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
- obj);
+ self, Py_TYPE(obj)->tp_name, obj);
}
else {
repr = PyUnicode_FromFormat(
"",
- self,
- Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
- obj,
- name);
+ self, Py_TYPE(obj)->tp_name, obj, name);
}
Py_DECREF(obj);
Py_XDECREF(name);
@@ -196,15 +194,18 @@ weakref_repr(PyWeakReference *self)
gone away, they are equal if they are identical. */
static PyObject *
-weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
+weakref_richcompare(PyObject* self, PyObject* other, int op)
{
if ((op != Py_EQ && op != Py_NE) ||
!PyWeakref_Check(self) ||
!PyWeakref_Check(other)) {
Py_RETURN_NOTIMPLEMENTED;
}
- if (PyWeakref_GET_OBJECT(self) == Py_None
- || PyWeakref_GET_OBJECT(other) == Py_None) {
+ PyObject* obj = _PyWeakref_GET_REF(self);
+ PyObject* other_obj = _PyWeakref_GET_REF(other);
+ if (obj == NULL || other_obj == NULL) {
+ Py_XDECREF(obj);
+ Py_XDECREF(other_obj);
int res = (self == other);
if (op == Py_NE)
res = !res;
@@ -213,10 +214,6 @@ weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
else
Py_RETURN_FALSE;
}
- PyObject* obj = PyWeakref_GET_OBJECT(self);
- PyObject* other_obj = PyWeakref_GET_OBJECT(other);
- Py_INCREF(obj);
- Py_INCREF(other_obj);
PyObject* res = PyObject_RichCompare(obj, other_obj, op);
Py_DECREF(obj);
Py_DECREF(other_obj);
@@ -372,13 +369,13 @@ _PyWeakref_RefType = {
.tp_dealloc = weakref_dealloc,
.tp_vectorcall_offset = offsetof(PyWeakReference, vectorcall),
.tp_call = PyVectorcall_Call,
- .tp_repr = (reprfunc)weakref_repr,
+ .tp_repr = weakref_repr,
.tp_hash = (hashfunc)weakref_hash,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_BASETYPE,
.tp_traverse = (traverseproc)gc_traverse,
.tp_clear = (inquiry)gc_clear,
- .tp_richcompare = (richcmpfunc)weakref_richcompare,
+ .tp_richcompare = weakref_richcompare,
.tp_methods = weakref_methods,
.tp_members = weakref_members,
.tp_init = weakref___init__,
@@ -388,15 +385,15 @@ _PyWeakref_RefType = {
};
-static int
-proxy_checkref(PyWeakReference *proxy)
+static bool
+proxy_check_ref(PyObject *obj)
{
- if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
+ if (obj == NULL) {
PyErr_SetString(PyExc_ReferenceError,
"weakly-referenced object no longer exists");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
@@ -406,16 +403,19 @@ proxy_checkref(PyWeakReference *proxy)
*/
#define UNWRAP(o) \
if (PyWeakref_CheckProxy(o)) { \
- if (!proxy_checkref((PyWeakReference *)o)) \
+ o = _PyWeakref_GET_REF(o); \
+ if (!proxy_check_ref(o)) { \
return NULL; \
- o = PyWeakref_GET_OBJECT(o); \
+ } \
+ } \
+ else { \
+ Py_INCREF(o); \
}
#define WRAP_UNARY(method, generic) \
static PyObject * \
method(PyObject *proxy) { \
UNWRAP(proxy); \
- Py_INCREF(proxy); \
PyObject* res = generic(proxy); \
Py_DECREF(proxy); \
return res; \
@@ -426,8 +426,6 @@ proxy_checkref(PyWeakReference *proxy)
method(PyObject *x, PyObject *y) { \
UNWRAP(x); \
UNWRAP(y); \
- Py_INCREF(x); \
- Py_INCREF(y); \
PyObject* res = generic(x, y); \
Py_DECREF(x); \
Py_DECREF(y); \
@@ -442,11 +440,9 @@ proxy_checkref(PyWeakReference *proxy)
method(PyObject *proxy, PyObject *v, PyObject *w) { \
UNWRAP(proxy); \
UNWRAP(v); \
- if (w != NULL) \
+ if (w != NULL) { \
UNWRAP(w); \
- Py_INCREF(proxy); \
- Py_INCREF(v); \
- Py_XINCREF(w); \
+ } \
PyObject* res = generic(proxy, v, w); \
Py_DECREF(proxy); \
Py_DECREF(v); \
@@ -458,7 +454,6 @@ proxy_checkref(PyWeakReference *proxy)
static PyObject * \
method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
UNWRAP(proxy); \
- Py_INCREF(proxy); \
PyObject* res = PyObject_CallMethodNoArgs(proxy, &_Py_ID(SPECIAL)); \
Py_DECREF(proxy); \
return res; \
@@ -472,23 +467,24 @@ WRAP_UNARY(proxy_str, PyObject_Str)
WRAP_TERNARY(proxy_call, PyObject_Call)
static PyObject *
-proxy_repr(PyWeakReference *proxy)
+proxy_repr(PyObject *proxy)
{
- return PyUnicode_FromFormat(
+ PyObject *obj = _PyWeakref_GET_REF(proxy);
+ PyObject *repr = PyUnicode_FromFormat(
"",
- proxy,
- Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
- PyWeakref_GET_OBJECT(proxy));
+ proxy, Py_TYPE(obj)->tp_name, obj);
+ Py_DECREF(obj);
+ return repr;
}
static int
-proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
+proxy_setattr(PyObject *proxy, PyObject *name, PyObject *value)
{
- if (!proxy_checkref(proxy))
+ PyObject *obj = _PyWeakref_GET_REF(proxy);
+ if (!proxy_check_ref(obj)) {
return -1;
- PyObject *obj = PyWeakref_GET_OBJECT(proxy);
- Py_INCREF(obj);
+ }
int res = PyObject_SetAttr(obj, name, value);
Py_DECREF(obj);
return res;
@@ -499,7 +495,10 @@ proxy_richcompare(PyObject *proxy, PyObject *v, int op)
{
UNWRAP(proxy);
UNWRAP(v);
- return PyObject_RichCompare(proxy, v, op);
+ PyObject* res = PyObject_RichCompare(proxy, v, op);
+ Py_DECREF(proxy);
+ Py_DECREF(v);
+ return res;
}
/* number slots */
@@ -539,13 +538,12 @@ WRAP_BINARY(proxy_matmul, PyNumber_MatrixMultiply)
WRAP_BINARY(proxy_imatmul, PyNumber_InPlaceMatrixMultiply)
static int
-proxy_bool(PyWeakReference *proxy)
+proxy_bool(PyObject *proxy)
{
- PyObject *o = PyWeakref_GET_OBJECT(proxy);
- if (!proxy_checkref(proxy)) {
+ PyObject *o = _PyWeakref_GET_REF(proxy);
+ if (!proxy_check_ref(o)) {
return -1;
}
- Py_INCREF(o);
int res = PyObject_IsTrue(o);
Py_DECREF(o);
return res;
@@ -564,13 +562,12 @@ proxy_dealloc(PyWeakReference *self)
/* sequence slots */
static int
-proxy_contains(PyWeakReference *proxy, PyObject *value)
+proxy_contains(PyObject *proxy, PyObject *value)
{
- if (!proxy_checkref(proxy))
+ PyObject *obj = _PyWeakref_GET_REF(proxy);
+ if (!proxy_check_ref(obj)) {
return -1;
-
- PyObject *obj = PyWeakref_GET_OBJECT(proxy);
- Py_INCREF(obj);
+ }
int res = PySequence_Contains(obj, value);
Py_DECREF(obj);
return res;
@@ -579,13 +576,12 @@ proxy_contains(PyWeakReference *proxy, PyObject *value)
/* mapping slots */
static Py_ssize_t
-proxy_length(PyWeakReference *proxy)
+proxy_length(PyObject *proxy)
{
- if (!proxy_checkref(proxy))
+ PyObject *obj = _PyWeakref_GET_REF(proxy);
+ if (!proxy_check_ref(obj)) {
return -1;
-
- PyObject *obj = PyWeakref_GET_OBJECT(proxy);
- Py_INCREF(obj);
+ }
Py_ssize_t res = PyObject_Length(obj);
Py_DECREF(obj);
return res;
@@ -594,13 +590,12 @@ proxy_length(PyWeakReference *proxy)
WRAP_BINARY(proxy_getitem, PyObject_GetItem)
static int
-proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
+proxy_setitem(PyObject *proxy, PyObject *key, PyObject *value)
{
- if (!proxy_checkref(proxy))
+ PyObject *obj = _PyWeakref_GET_REF(proxy);
+ if (!proxy_check_ref(obj)) {
return -1;
-
- PyObject *obj = PyWeakref_GET_OBJECT(proxy);
- Py_INCREF(obj);
+ }
int res;
if (value == NULL) {
res = PyObject_DelItem(obj, key);
@@ -614,31 +609,31 @@ proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
/* iterator slots */
static PyObject *
-proxy_iter(PyWeakReference *proxy)
+proxy_iter(PyObject *proxy)
{
- if (!proxy_checkref(proxy))
+ PyObject *obj = _PyWeakref_GET_REF(proxy);
+ if (!proxy_check_ref(obj)) {
return NULL;
- PyObject *obj = PyWeakref_GET_OBJECT(proxy);
- Py_INCREF(obj);
+ }
PyObject* res = PyObject_GetIter(obj);
Py_DECREF(obj);
return res;
}
static PyObject *
-proxy_iternext(PyWeakReference *proxy)
+proxy_iternext(PyObject *proxy)
{
- if (!proxy_checkref(proxy))
+ PyObject *obj = _PyWeakref_GET_REF(proxy);
+ if (!proxy_check_ref(obj)) {
return NULL;
-
- PyObject *obj = PyWeakref_GET_OBJECT(proxy);
+ }
if (!PyIter_Check(obj)) {
PyErr_Format(PyExc_TypeError,
"Weakref proxy referenced a non-iterator '%.200s' object",
Py_TYPE(obj)->tp_name);
+ Py_DECREF(obj);
return NULL;
}
- Py_INCREF(obj);
PyObject* res = PyIter_Next(obj);
Py_DECREF(obj);
return res;
@@ -666,7 +661,7 @@ static PyNumberMethods proxy_as_number = {
proxy_neg, /*nb_negative*/
proxy_pos, /*nb_positive*/
proxy_abs, /*nb_absolute*/
- (inquiry)proxy_bool, /*nb_bool*/
+ proxy_bool, /*nb_bool*/
proxy_invert, /*nb_invert*/
proxy_lshift, /*nb_lshift*/
proxy_rshift, /*nb_rshift*/
@@ -696,20 +691,20 @@ static PyNumberMethods proxy_as_number = {
};
static PySequenceMethods proxy_as_sequence = {
- (lenfunc)proxy_length, /*sq_length*/
+ proxy_length, /*sq_length*/
0, /*sq_concat*/
0, /*sq_repeat*/
0, /*sq_item*/
0, /*sq_slice*/
0, /*sq_ass_item*/
- 0, /*sq_ass_slice*/
- (objobjproc)proxy_contains, /* sq_contains */
+ 0, /*sq_ass_slice*/
+ proxy_contains, /* sq_contains */
};
static PyMappingMethods proxy_as_mapping = {
- (lenfunc)proxy_length, /*mp_length*/
+ proxy_length, /*mp_length*/
proxy_getitem, /*mp_subscript*/
- (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
+ proxy_setitem, /*mp_ass_subscript*/
};
@@ -725,7 +720,7 @@ _PyWeakref_ProxyType = {
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
- (reprfunc)proxy_repr, /* tp_repr */
+ proxy_repr, /* tp_repr */
&proxy_as_number, /* tp_as_number */
&proxy_as_sequence, /* tp_as_sequence */
&proxy_as_mapping, /* tp_as_mapping */
@@ -734,7 +729,7 @@ _PyWeakref_ProxyType = {
0, /* tp_call */
proxy_str, /* tp_str */
proxy_getattr, /* tp_getattro */
- (setattrofunc)proxy_setattr, /* tp_setattro */
+ proxy_setattr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
@@ -742,9 +737,9 @@ _PyWeakref_ProxyType = {
(inquiry)gc_clear, /* tp_clear */
proxy_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
- (getiterfunc)proxy_iter, /* tp_iter */
- (iternextfunc)proxy_iternext, /* tp_iternext */
- proxy_methods, /* tp_methods */
+ proxy_iter, /* tp_iter */
+ proxy_iternext, /* tp_iternext */
+ proxy_methods, /* tp_methods */
};
@@ -760,7 +755,7 @@ _PyWeakref_CallableProxyType = {
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
- (unaryfunc)proxy_repr, /* tp_repr */
+ proxy_repr, /* tp_repr */
&proxy_as_number, /* tp_as_number */
&proxy_as_sequence, /* tp_as_sequence */
&proxy_as_mapping, /* tp_as_mapping */
@@ -768,7 +763,7 @@ _PyWeakref_CallableProxyType = {
proxy_call, /* tp_call */
proxy_str, /* tp_str */
proxy_getattr, /* tp_getattro */
- (setattrofunc)proxy_setattr, /* tp_setattro */
+ proxy_setattr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
@@ -776,8 +771,8 @@ _PyWeakref_CallableProxyType = {
(inquiry)gc_clear, /* tp_clear */
proxy_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
- (getiterfunc)proxy_iter, /* tp_iter */
- (iternextfunc)proxy_iternext, /* tp_iternext */
+ proxy_iter, /* tp_iter */
+ proxy_iternext, /* tp_iternext */
};
@@ -904,6 +899,24 @@ PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
}
+int
+PyWeakref_GetRef(PyObject *ref, PyObject **pobj)
+{
+ if (ref == NULL) {
+ *pobj = NULL;
+ PyErr_BadInternalCall();
+ return -1;
+ }
+ if (!PyWeakref_Check(ref)) {
+ *pobj = NULL;
+ PyErr_SetString(PyExc_TypeError, "expected a weakref");
+ return -1;
+ }
+ *pobj = _PyWeakref_GET_REF(ref);
+ return (*pobj != NULL);
+}
+
+
PyObject *
PyWeakref_GetObject(PyObject *ref)
{
@@ -911,7 +924,12 @@ PyWeakref_GetObject(PyObject *ref)
PyErr_BadInternalCall();
return NULL;
}
- return PyWeakref_GET_OBJECT(ref);
+ PyObject *obj = _PyWeakref_GET_REF(ref);
+ if (obj == NULL) {
+ return Py_None;
+ }
+ Py_DECREF(obj);
+ return obj; // borrowed reference
}
/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
diff --git a/PC/launcher.c b/PC/launcher.c
index dc265533740b67..8e60ab9303cb95 100644
--- a/PC/launcher.c
+++ b/PC/launcher.c
@@ -1270,6 +1270,7 @@ static PYC_MAGIC magic_values[] = {
/* Allow 50 magic numbers per version from here on */
{ 3450, 3499, L"3.11" },
{ 3500, 3549, L"3.12" },
+ { 3550, 3599, L"3.13" },
{ 0 }
};
diff --git a/PC/python3dll.c b/PC/python3dll.c
index 505feef4b986c4..8f2df6950cfc05 100755
--- a/PC/python3dll.c
+++ b/PC/python3dll.c
@@ -288,6 +288,7 @@ EXPORT_FUNC(PyGILState_GetThisThreadState)
EXPORT_FUNC(PyGILState_Release)
EXPORT_FUNC(PyImport_AddModule)
EXPORT_FUNC(PyImport_AddModuleObject)
+EXPORT_FUNC(PyImport_AddModuleRef)
EXPORT_FUNC(PyImport_AppendInittab)
EXPORT_FUNC(PyImport_ExecCodeModule)
EXPORT_FUNC(PyImport_ExecCodeModuleEx)
@@ -351,6 +352,8 @@ EXPORT_FUNC(PyLong_FromVoidPtr)
EXPORT_FUNC(PyLong_GetInfo)
EXPORT_FUNC(PyMapping_Check)
EXPORT_FUNC(PyMapping_GetItemString)
+EXPORT_FUNC(PyMapping_GetOptionalItem)
+EXPORT_FUNC(PyMapping_GetOptionalItemString)
EXPORT_FUNC(PyMapping_HasKey)
EXPORT_FUNC(PyMapping_HasKeyString)
EXPORT_FUNC(PyMapping_Items)
@@ -446,6 +449,8 @@ EXPORT_FUNC(PyObject_CheckBuffer)
EXPORT_FUNC(PyObject_CheckReadBuffer)
EXPORT_FUNC(PyObject_ClearWeakRefs)
EXPORT_FUNC(PyObject_CopyData)
+EXPORT_FUNC(PyObject_DelAttr)
+EXPORT_FUNC(PyObject_DelAttrString)
EXPORT_FUNC(PyObject_DelItem)
EXPORT_FUNC(PyObject_DelItemString)
EXPORT_FUNC(PyObject_Dir)
@@ -466,6 +471,8 @@ EXPORT_FUNC(PyObject_GetAttrString)
EXPORT_FUNC(PyObject_GetBuffer)
EXPORT_FUNC(PyObject_GetItem)
EXPORT_FUNC(PyObject_GetIter)
+EXPORT_FUNC(PyObject_GetOptionalAttr)
+EXPORT_FUNC(PyObject_GetOptionalAttrString)
EXPORT_FUNC(PyObject_GetTypeData)
EXPORT_FUNC(PyObject_HasAttr)
EXPORT_FUNC(PyObject_HasAttrString)
@@ -734,6 +741,7 @@ EXPORT_FUNC(PyUnicodeTranslateError_SetStart)
EXPORT_FUNC(PyVectorcall_Call)
EXPORT_FUNC(PyVectorcall_NARGS)
EXPORT_FUNC(PyWeakref_GetObject)
+EXPORT_FUNC(PyWeakref_GetRef)
EXPORT_FUNC(PyWeakref_NewProxy)
EXPORT_FUNC(PyWeakref_NewRef)
EXPORT_FUNC(PyWrapper_New)
diff --git a/PC/winreg.c b/PC/winreg.c
index 279d48f792b96a..aa2055c7e619d2 100644
--- a/PC/winreg.c
+++ b/PC/winreg.c
@@ -12,7 +12,6 @@
*/
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_object.h" // _PyObject_Init()
#include "pycore_moduleobject.h"
diff --git a/PCbuild/_testcapi.vcxproj b/PCbuild/_testcapi.vcxproj
index 3db9426d1a25ff..de17d74c52e56f 100644
--- a/PCbuild/_testcapi.vcxproj
+++ b/PCbuild/_testcapi.vcxproj
@@ -100,7 +100,6 @@
-
@@ -131,4 +130,4 @@
-
\ No newline at end of file
+
diff --git a/PCbuild/_testcapi.vcxproj.filters b/PCbuild/_testcapi.vcxproj.filters
index 8df4874659fa1c..637f7178d39d0e 100644
--- a/PCbuild/_testcapi.vcxproj.filters
+++ b/PCbuild/_testcapi.vcxproj.filters
@@ -30,9 +30,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -75,4 +72,4 @@
Resource Files
-
\ No newline at end of file
+
diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat
index 3a6f616f279220..257b360ba3506f 100644
--- a/PCbuild/get_externals.bat
+++ b/PCbuild/get_externals.bat
@@ -53,7 +53,7 @@ echo.Fetching external libraries...
set libraries=
set libraries=%libraries% bzip2-1.0.8
if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.4.4
-if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1u
+if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-3.0.9
set libraries=%libraries% sqlite-3.42.0.0
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.13.0
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.13.0
@@ -76,7 +76,7 @@ echo.Fetching external binaries...
set binaries=
if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.4.4
-if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1u
+if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-3.0.9
if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.13.0
if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06
diff --git a/PCbuild/openssl.props b/PCbuild/openssl.props
index 7071bb57c06cd7..5fd708b211e42d 100644
--- a/PCbuild/openssl.props
+++ b/PCbuild/openssl.props
@@ -10,10 +10,10 @@
- <_DLLSuffix>-1_1
+ <_DLLSuffix>-3
<_DLLSuffix Condition="$(Platform) == 'ARM'">$(_DLLSuffix)-arm
<_DLLSuffix Condition="$(Platform) == 'ARM64'">$(_DLLSuffix)-arm64
- $(_DLLSuffix)
+ $(_DLLSuffix)
<_SSLDLL Include="$(opensslOutDir)\libcrypto$(_DLLSuffix).dll" />
diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props
index 36c4c269d05da9..fd928cafd77aaa 100644
--- a/PCbuild/pyproject.props
+++ b/PCbuild/pyproject.props
@@ -25,7 +25,7 @@
<_VCToolsVersion>$([System.Version]::Parse(`$(VCToolsVersion)`).Major).$([System.Version]::Parse(`$(VCToolsVersion)`).Minor)
- true
+ true
diff --git a/PCbuild/python.props b/PCbuild/python.props
index 68052ef668aa6c..d3586235c82652 100644
--- a/PCbuild/python.props
+++ b/PCbuild/python.props
@@ -74,8 +74,8 @@
$(ExternalsDir)libffi-3.4.4\
$(libffiDir)$(ArchName)\
$(libffiOutDir)include
- $(ExternalsDir)openssl-1.1.1u\
- $(ExternalsDir)openssl-bin-1.1.1u\$(ArchName)\
+ $(ExternalsDir)openssl-3.0.9\
+ $(ExternalsDir)openssl-bin-3.0.9\$(ArchName)\
$(opensslOutDir)include
$(ExternalsDir)\nasm-2.11.06\
$(ExternalsDir)\zlib-1.2.13\
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 72d869efb9db67..760962e4c4b6a9 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -162,6 +162,7 @@
+
@@ -175,10 +176,10 @@
-
+
@@ -209,7 +210,9 @@
+
+
@@ -238,6 +241,7 @@
+
@@ -275,6 +279,7 @@
+
@@ -318,7 +323,6 @@
-
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index 5d8b7196c14e6a..aaebe1908e30da 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -219,9 +219,6 @@
Include
-
- Include
-
Include
@@ -393,6 +390,9 @@
Include
+
+ Include
+
Include\cpython
@@ -444,15 +444,15 @@
Include\cpython
-
- Include\cpython
-
Include\cpython
Include\cpython
+
+ Include
+
Include\cpython
@@ -492,6 +492,9 @@
Include\internal
+
+ Include\internal
+
Include\internal
@@ -534,9 +537,15 @@
Include\internal
+
+ Include\internal
+
Include\internal
+
+ Include\internal
+
Include\internal
@@ -618,6 +627,9 @@
Include\internal
+
+ Include\internal
+
Include\internal
diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt
index 88b04a749e3b28..f0de142f0573b9 100644
--- a/PCbuild/readme.txt
+++ b/PCbuild/readme.txt
@@ -168,7 +168,7 @@ _lzma
Homepage:
https://tukaani.org/xz/
_ssl
- Python wrapper for version 1.1.1u of the OpenSSL secure sockets
+ Python wrapper for version 3.0 of the OpenSSL secure sockets
library, which is downloaded from our binaries repository at
https://github.com/python/cpython-bin-deps.
diff --git a/PCbuild/regen.targets b/PCbuild/regen.targets
index 15f3d1375a10a2..2dd786e5e82e36 100644
--- a/PCbuild/regen.targets
+++ b/PCbuild/regen.targets
@@ -59,7 +59,7 @@
Inputs="@(_OpcodeSources)" Outputs="@(_OpcodeOutputs)"
DependsOnTargets="FindPythonForBuild">
-
@@ -104,8 +104,9 @@
<_LicenseSources Include="$(PySourcePath)LICENSE;
$(PySourcePath)PC\crtlicense.txt;
$(bz2Dir)LICENSE;
- $(opensslOutDir)LICENSE;
$(libffiDir)LICENSE;" />
+ <_LicenseSources Include="$(opensslOutDir)LICENSE.txt" Condition="Exists('$(opensslOutDir)LICENSE.txt')" />
+ <_LicenseSources Include="$(opensslOutDir)LICENSE" Condition="!Exists('$(opensslOutDir)LICENSE.txt')" />
<_LicenseSources Include="$(tcltkDir)tcllicense.terms;
$(tcltkDir)tklicense.terms" Condition="$(IncludeTkinter)" />
diff --git a/Parser/Python.asdl b/Parser/Python.asdl
index 93632a09f0959b..0d154867276c36 100644
--- a/Parser/Python.asdl
+++ b/Parser/Python.asdl
@@ -148,5 +148,5 @@ module Python
type_param = TypeVar(identifier name, expr? bound)
| ParamSpec(identifier name)
| TypeVarTuple(identifier name)
- attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
+ attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
}
diff --git a/Parser/action_helpers.c b/Parser/action_helpers.c
index 7786124fde82d0..36e0750220a30d 100644
--- a/Parser/action_helpers.c
+++ b/Parser/action_helpers.c
@@ -997,6 +997,18 @@ _PyPegen_setup_full_format_spec(Parser *p, Token *colon, asdl_expr_seq *spec, in
if (!spec) {
return NULL;
}
+
+ // This is needed to keep compatibility with 3.11, where an empty format spec is parsed
+ // as an *empty* JoinedStr node, instead of having an empty constant in it.
+ if (asdl_seq_LEN(spec) == 1) {
+ expr_ty e = asdl_seq_GET(spec, 0);
+ if (e->kind == Constant_kind
+ && PyUnicode_Check(e->v.Constant.value)
+ && PyUnicode_GetLength(e->v.Constant.value) == 0) {
+ spec = _Py_asdl_expr_seq_new(0, arena);
+ }
+ }
+
expr_ty res = _PyAST_JoinedStr(spec, lineno, col_offset, end_lineno, end_col_offset, p->arena);
if (!res) {
return NULL;
@@ -1225,7 +1237,7 @@ _PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq
// Fstring stuff
static expr_ty
-_PyPegen_decode_fstring_part(Parser* p, int is_raw, expr_ty constant) {
+_PyPegen_decode_fstring_part(Parser* p, int is_raw, expr_ty constant, Token* token) {
assert(PyUnicode_CheckExact(constant->v.Constant.value));
const char* bstr = PyUnicode_AsUTF8(constant->v.Constant.value);
@@ -1241,7 +1253,7 @@ _PyPegen_decode_fstring_part(Parser* p, int is_raw, expr_ty constant) {
}
is_raw = is_raw || strchr(bstr, '\\') == NULL;
- PyObject *str = _PyPegen_decode_string(p, is_raw, bstr, len, NULL);
+ PyObject *str = _PyPegen_decode_string(p, is_raw, bstr, len, token);
if (str == NULL) {
_Pypegen_raise_decode_error(p);
return NULL;
@@ -1315,7 +1327,7 @@ _PyPegen_joined_str(Parser *p, Token* a, asdl_expr_seq* raw_expressions, Token*b
for (Py_ssize_t i = 0; i < n_items; i++) {
expr_ty item = asdl_seq_GET(expr, i);
if (item->kind == Constant_kind) {
- item = _PyPegen_decode_fstring_part(p, is_raw, item);
+ item = _PyPegen_decode_fstring_part(p, is_raw, item, b);
if (item == NULL) {
return NULL;
}
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py
index cb312796f89e04..e9665dd808af39 100755
--- a/Parser/asdl_c.py
+++ b/Parser/asdl_c.py
@@ -601,6 +601,7 @@ def visitProduct(self, prod, name):
args = [f.name for f in prod.fields]
args.extend([a.name for a in prod.attributes])
self.emit("*out = %s(%s);" % (ast_func_name(name), self.buildArgs(args)), 1)
+ self.emit("if (*out == NULL) goto failed;", 1)
self.emit("return 0;", 1)
self.emit("failed:", 0)
self.emit("Py_XDECREF(tmp);", 1)
@@ -628,7 +629,7 @@ def isSimpleType(self, field):
def visitField(self, field, name, sum=None, prod=None, depth=0):
ctype = get_c_type(field.type)
- line = "if (_PyObject_LookupAttr(obj, state->%s, &tmp) < 0) {"
+ line = "if (PyObject_GetOptionalAttr(obj, state->%s, &tmp) < 0) {"
self.emit(line % field.name, depth)
self.emit("return 1;", depth+1)
self.emit("}", depth)
@@ -812,7 +813,7 @@ def visitModule(self, mod):
Py_ssize_t i, numfields = 0;
int res = -1;
PyObject *key, *value, *fields;
- if (_PyObject_LookupAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) {
+ if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) {
goto cleanup;
}
if (fields) {
@@ -886,7 +887,7 @@ def visitModule(self, mod):
}
PyObject *dict;
- if (_PyObject_LookupAttr(self, state->__dict__, &dict) < 0) {
+ if (PyObject_GetOptionalAttr(self, state->__dict__, &dict) < 0) {
return NULL;
}
if (dict) {
diff --git a/Parser/parser.c b/Parser/parser.c
index 006ee297974a61..f2ea8f59b00567 100644
--- a/Parser/parser.c
+++ b/Parser/parser.c
@@ -532,14 +532,14 @@ static char *soft_keywords[] = {
#define _gather_207_type 1451
#define _loop0_210_type 1452
#define _gather_209_type 1453
-#define _tmp_211_type 1454
-#define _loop0_212_type 1455
-#define _loop1_213_type 1456
-#define _tmp_214_type 1457
-#define _loop0_215_type 1458
-#define _loop1_216_type 1459
-#define _tmp_217_type 1460
-#define _tmp_218_type 1461
+#define _loop0_212_type 1454
+#define _gather_211_type 1455
+#define _tmp_213_type 1456
+#define _loop0_214_type 1457
+#define _loop1_215_type 1458
+#define _tmp_216_type 1459
+#define _loop0_217_type 1460
+#define _loop1_218_type 1461
#define _tmp_219_type 1462
#define _tmp_220_type 1463
#define _tmp_221_type 1464
@@ -548,10 +548,10 @@ static char *soft_keywords[] = {
#define _tmp_224_type 1467
#define _tmp_225_type 1468
#define _tmp_226_type 1469
-#define _loop0_228_type 1470
-#define _gather_227_type 1471
-#define _tmp_229_type 1472
-#define _tmp_230_type 1473
+#define _tmp_227_type 1470
+#define _tmp_228_type 1471
+#define _loop0_230_type 1472
+#define _gather_229_type 1473
#define _tmp_231_type 1474
#define _tmp_232_type 1475
#define _tmp_233_type 1476
@@ -563,9 +563,9 @@ static char *soft_keywords[] = {
#define _tmp_239_type 1482
#define _tmp_240_type 1483
#define _tmp_241_type 1484
-#define _loop0_242_type 1485
+#define _tmp_242_type 1485
#define _tmp_243_type 1486
-#define _tmp_244_type 1487
+#define _loop0_244_type 1487
#define _tmp_245_type 1488
#define _tmp_246_type 1489
#define _tmp_247_type 1490
@@ -596,6 +596,8 @@ static char *soft_keywords[] = {
#define _tmp_272_type 1515
#define _tmp_273_type 1516
#define _tmp_274_type 1517
+#define _tmp_275_type 1518
+#define _tmp_276_type 1519
static mod_ty file_rule(Parser *p);
static mod_ty interactive_rule(Parser *p);
@@ -1051,14 +1053,14 @@ static asdl_seq *_loop0_208_rule(Parser *p);
static asdl_seq *_gather_207_rule(Parser *p);
static asdl_seq *_loop0_210_rule(Parser *p);
static asdl_seq *_gather_209_rule(Parser *p);
-static void *_tmp_211_rule(Parser *p);
static asdl_seq *_loop0_212_rule(Parser *p);
-static asdl_seq *_loop1_213_rule(Parser *p);
-static void *_tmp_214_rule(Parser *p);
-static asdl_seq *_loop0_215_rule(Parser *p);
-static asdl_seq *_loop1_216_rule(Parser *p);
-static void *_tmp_217_rule(Parser *p);
-static void *_tmp_218_rule(Parser *p);
+static asdl_seq *_gather_211_rule(Parser *p);
+static void *_tmp_213_rule(Parser *p);
+static asdl_seq *_loop0_214_rule(Parser *p);
+static asdl_seq *_loop1_215_rule(Parser *p);
+static void *_tmp_216_rule(Parser *p);
+static asdl_seq *_loop0_217_rule(Parser *p);
+static asdl_seq *_loop1_218_rule(Parser *p);
static void *_tmp_219_rule(Parser *p);
static void *_tmp_220_rule(Parser *p);
static void *_tmp_221_rule(Parser *p);
@@ -1067,10 +1069,10 @@ static void *_tmp_223_rule(Parser *p);
static void *_tmp_224_rule(Parser *p);
static void *_tmp_225_rule(Parser *p);
static void *_tmp_226_rule(Parser *p);
-static asdl_seq *_loop0_228_rule(Parser *p);
-static asdl_seq *_gather_227_rule(Parser *p);
-static void *_tmp_229_rule(Parser *p);
-static void *_tmp_230_rule(Parser *p);
+static void *_tmp_227_rule(Parser *p);
+static void *_tmp_228_rule(Parser *p);
+static asdl_seq *_loop0_230_rule(Parser *p);
+static asdl_seq *_gather_229_rule(Parser *p);
static void *_tmp_231_rule(Parser *p);
static void *_tmp_232_rule(Parser *p);
static void *_tmp_233_rule(Parser *p);
@@ -1082,9 +1084,9 @@ static void *_tmp_238_rule(Parser *p);
static void *_tmp_239_rule(Parser *p);
static void *_tmp_240_rule(Parser *p);
static void *_tmp_241_rule(Parser *p);
-static asdl_seq *_loop0_242_rule(Parser *p);
+static void *_tmp_242_rule(Parser *p);
static void *_tmp_243_rule(Parser *p);
-static void *_tmp_244_rule(Parser *p);
+static asdl_seq *_loop0_244_rule(Parser *p);
static void *_tmp_245_rule(Parser *p);
static void *_tmp_246_rule(Parser *p);
static void *_tmp_247_rule(Parser *p);
@@ -1115,6 +1117,8 @@ static void *_tmp_271_rule(Parser *p);
static void *_tmp_272_rule(Parser *p);
static void *_tmp_273_rule(Parser *p);
static void *_tmp_274_rule(Parser *p);
+static void *_tmp_275_rule(Parser *p);
+static void *_tmp_276_rule(Parser *p);
// file: statements? $
@@ -22648,7 +22652,7 @@ invalid_group_rule(Parser *p)
return _res;
}
-// invalid_import: 'import' dotted_name 'from' dotted_name
+// invalid_import: 'import' ','.dotted_name+ 'from' dotted_name
static void *
invalid_import_rule(Parser *p)
{
@@ -22662,27 +22666,27 @@ invalid_import_rule(Parser *p)
}
void * _res = NULL;
int _mark = p->mark;
- { // 'import' dotted_name 'from' dotted_name
+ { // 'import' ','.dotted_name+ 'from' dotted_name
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> invalid_import[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import' dotted_name 'from' dotted_name"));
+ D(fprintf(stderr, "%*c> invalid_import[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import' ','.dotted_name+ 'from' dotted_name"));
+ asdl_seq * _gather_203_var;
Token * _keyword;
Token * a;
expr_ty dotted_name_var;
- expr_ty dotted_name_var_1;
if (
(a = _PyPegen_expect_token(p, 607)) // token='import'
&&
- (dotted_name_var = dotted_name_rule(p)) // dotted_name
+ (_gather_203_var = _gather_203_rule(p)) // ','.dotted_name+
&&
(_keyword = _PyPegen_expect_token(p, 608)) // token='from'
&&
- (dotted_name_var_1 = dotted_name_rule(p)) // dotted_name
+ (dotted_name_var = dotted_name_rule(p)) // dotted_name
)
{
- D(fprintf(stderr, "%*c+ invalid_import[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import' dotted_name 'from' dotted_name"));
+ D(fprintf(stderr, "%*c+ invalid_import[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import' ','.dotted_name+ 'from' dotted_name"));
_res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "Did you mean to use 'from ... import ...' instead?" );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -22693,7 +22697,7 @@ invalid_import_rule(Parser *p)
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s invalid_import[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'import' dotted_name 'from' dotted_name"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'import' ','.dotted_name+ 'from' dotted_name"));
}
_res = NULL;
done:
@@ -22773,7 +22777,7 @@ invalid_with_stmt_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ NEWLINE"));
- asdl_seq * _gather_203_var;
+ asdl_seq * _gather_205_var;
Token * _keyword;
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
@@ -22783,7 +22787,7 @@ invalid_with_stmt_rule(Parser *p)
&&
(_keyword = _PyPegen_expect_token(p, 615)) // token='with'
&&
- (_gather_203_var = _gather_203_rule(p)) // ','.(expression ['as' star_target])+
+ (_gather_205_var = _gather_205_rule(p)) // ','.(expression ['as' star_target])+
&&
(newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE'
)
@@ -22807,7 +22811,7 @@ invalid_with_stmt_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE"));
- asdl_seq * _gather_205_var;
+ asdl_seq * _gather_207_var;
Token * _keyword;
Token * _literal;
Token * _literal_1;
@@ -22823,7 +22827,7 @@ invalid_with_stmt_rule(Parser *p)
&&
(_literal = _PyPegen_expect_token(p, 7)) // token='('
&&
- (_gather_205_var = _gather_205_rule(p)) // ','.(expressions ['as' star_target])+
+ (_gather_207_var = _gather_207_rule(p)) // ','.(expressions ['as' star_target])+
&&
(_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','?
&&
@@ -22873,7 +22877,7 @@ invalid_with_stmt_indent_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT"));
- asdl_seq * _gather_207_var;
+ asdl_seq * _gather_209_var;
Token * _literal;
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
@@ -22884,7 +22888,7 @@ invalid_with_stmt_indent_rule(Parser *p)
&&
(a = _PyPegen_expect_token(p, 615)) // token='with'
&&
- (_gather_207_var = _gather_207_rule(p)) // ','.(expression ['as' star_target])+
+ (_gather_209_var = _gather_209_rule(p)) // ','.(expression ['as' star_target])+
&&
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
&&
@@ -22912,7 +22916,7 @@ invalid_with_stmt_indent_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT"));
- asdl_seq * _gather_209_var;
+ asdl_seq * _gather_211_var;
Token * _literal;
Token * _literal_1;
Token * _literal_2;
@@ -22929,7 +22933,7 @@ invalid_with_stmt_indent_rule(Parser *p)
&&
(_literal = _PyPegen_expect_token(p, 7)) // token='('
&&
- (_gather_209_var = _gather_209_rule(p)) // ','.(expressions ['as' star_target])+
+ (_gather_211_var = _gather_211_rule(p)) // ','.(expressions ['as' star_target])+
&&
(_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','?
&&
@@ -23027,7 +23031,7 @@ invalid_try_stmt_rule(Parser *p)
&&
(block_var = block_rule(p)) // block
&&
- _PyPegen_lookahead(0, _tmp_211_rule, p)
+ _PyPegen_lookahead(0, _tmp_213_rule, p)
)
{
D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')"));
@@ -23052,8 +23056,8 @@ invalid_try_stmt_rule(Parser *p)
Token * _keyword;
Token * _literal;
Token * _literal_1;
- asdl_seq * _loop0_212_var;
- asdl_seq * _loop1_213_var;
+ asdl_seq * _loop0_214_var;
+ asdl_seq * _loop1_215_var;
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
Token * a;
@@ -23064,9 +23068,9 @@ invalid_try_stmt_rule(Parser *p)
&&
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
&&
- (_loop0_212_var = _loop0_212_rule(p)) // block*
+ (_loop0_214_var = _loop0_214_rule(p)) // block*
&&
- (_loop1_213_var = _loop1_213_rule(p)) // except_block+
+ (_loop1_215_var = _loop1_215_rule(p)) // except_block+
&&
(a = _PyPegen_expect_token(p, 637)) // token='except'
&&
@@ -23074,7 +23078,7 @@ invalid_try_stmt_rule(Parser *p)
&&
(expression_var = expression_rule(p)) // expression
&&
- (_opt_var = _tmp_214_rule(p), !p->error_indicator) // ['as' NAME]
+ (_opt_var = _tmp_216_rule(p), !p->error_indicator) // ['as' NAME]
&&
(_literal_1 = _PyPegen_expect_token(p, 11)) // token=':'
)
@@ -23101,8 +23105,8 @@ invalid_try_stmt_rule(Parser *p)
Token * _keyword;
Token * _literal;
Token * _literal_1;
- asdl_seq * _loop0_215_var;
- asdl_seq * _loop1_216_var;
+ asdl_seq * _loop0_217_var;
+ asdl_seq * _loop1_218_var;
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
Token * a;
@@ -23111,13 +23115,13 @@ invalid_try_stmt_rule(Parser *p)
&&
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
&&
- (_loop0_215_var = _loop0_215_rule(p)) // block*
+ (_loop0_217_var = _loop0_217_rule(p)) // block*
&&
- (_loop1_216_var = _loop1_216_rule(p)) // except_star_block+
+ (_loop1_218_var = _loop1_218_rule(p)) // except_star_block+
&&
(a = _PyPegen_expect_token(p, 637)) // token='except'
&&
- (_opt_var = _tmp_217_rule(p), !p->error_indicator) // [expression ['as' NAME]]
+ (_opt_var = _tmp_219_rule(p), !p->error_indicator) // [expression ['as' NAME]]
&&
(_literal_1 = _PyPegen_expect_token(p, 11)) // token=':'
)
@@ -23185,7 +23189,7 @@ invalid_except_stmt_rule(Parser *p)
&&
(expressions_var = expressions_rule(p)) // expressions
&&
- (_opt_var_1 = _tmp_218_rule(p), !p->error_indicator) // ['as' NAME]
+ (_opt_var_1 = _tmp_220_rule(p), !p->error_indicator) // ['as' NAME]
&&
(_literal_1 = _PyPegen_expect_token(p, 11)) // token=':'
)
@@ -23223,7 +23227,7 @@ invalid_except_stmt_rule(Parser *p)
&&
(expression_var = expression_rule(p)) // expression
&&
- (_opt_var_1 = _tmp_219_rule(p), !p->error_indicator) // ['as' NAME]
+ (_opt_var_1 = _tmp_221_rule(p), !p->error_indicator) // ['as' NAME]
&&
(newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE'
)
@@ -23275,14 +23279,14 @@ invalid_except_stmt_rule(Parser *p)
}
D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')"));
Token * _literal;
- void *_tmp_220_var;
+ void *_tmp_222_var;
Token * a;
if (
(a = _PyPegen_expect_token(p, 637)) // token='except'
&&
(_literal = _PyPegen_expect_token(p, 16)) // token='*'
&&
- (_tmp_220_var = _tmp_220_rule(p)) // NEWLINE | ':'
+ (_tmp_222_var = _tmp_222_rule(p)) // NEWLINE | ':'
)
{
D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')"));
@@ -23389,7 +23393,7 @@ invalid_except_stmt_indent_rule(Parser *p)
&&
(expression_var = expression_rule(p)) // expression
&&
- (_opt_var = _tmp_221_rule(p), !p->error_indicator) // ['as' NAME]
+ (_opt_var = _tmp_223_rule(p), !p->error_indicator) // ['as' NAME]
&&
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
&&
@@ -23484,7 +23488,7 @@ invalid_except_star_stmt_indent_rule(Parser *p)
&&
(expression_var = expression_rule(p)) // expression
&&
- (_opt_var = _tmp_222_rule(p), !p->error_indicator) // ['as' NAME]
+ (_opt_var = _tmp_224_rule(p), !p->error_indicator) // ['as' NAME]
&&
(_literal_1 = _PyPegen_expect_token(p, 11)) // token=':'
&&
@@ -23853,7 +23857,7 @@ invalid_class_argument_pattern_rule(Parser *p)
asdl_pattern_seq* a;
asdl_seq* keyword_patterns_var;
if (
- (_opt_var = _tmp_223_rule(p), !p->error_indicator) // [positional_patterns ',']
+ (_opt_var = _tmp_225_rule(p), !p->error_indicator) // [positional_patterns ',']
&&
(keyword_patterns_var = keyword_patterns_rule(p)) // keyword_patterns
&&
@@ -24347,7 +24351,7 @@ invalid_def_raw_rule(Parser *p)
&&
(_literal_1 = _PyPegen_expect_token(p, 8)) // token=')'
&&
- (_opt_var_2 = _tmp_224_rule(p), !p->error_indicator) // ['->' expression]
+ (_opt_var_2 = _tmp_226_rule(p), !p->error_indicator) // ['->' expression]
&&
(_literal_2 = _PyPegen_expect_token(p, 11)) // token=':'
&&
@@ -24407,7 +24411,7 @@ invalid_class_def_raw_rule(Parser *p)
&&
(name_var = _PyPegen_name_token(p)) // NAME
&&
- (_opt_var = _tmp_225_rule(p), !p->error_indicator) // ['(' arguments? ')']
+ (_opt_var = _tmp_227_rule(p), !p->error_indicator) // ['(' arguments? ')']
&&
(newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE'
)
@@ -24442,7 +24446,7 @@ invalid_class_def_raw_rule(Parser *p)
&&
(name_var = _PyPegen_name_token(p)) // NAME
&&
- (_opt_var = _tmp_226_rule(p), !p->error_indicator) // ['(' arguments? ')']
+ (_opt_var = _tmp_228_rule(p), !p->error_indicator) // ['(' arguments? ')']
&&
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
&&
@@ -24493,11 +24497,11 @@ invalid_double_starred_kvpairs_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair"));
- asdl_seq * _gather_227_var;
+ asdl_seq * _gather_229_var;
Token * _literal;
void *invalid_kvpair_var;
if (
- (_gather_227_var = _gather_227_rule(p)) // ','.double_starred_kvpair+
+ (_gather_229_var = _gather_229_rule(p)) // ','.double_starred_kvpair+
&&
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
@@ -24505,7 +24509,7 @@ invalid_double_starred_kvpairs_rule(Parser *p)
)
{
D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair"));
- _res = _PyPegen_dummy_name(p, _gather_227_var, _literal, invalid_kvpair_var);
+ _res = _PyPegen_dummy_name(p, _gather_229_var, _literal, invalid_kvpair_var);
goto done;
}
p->mark = _mark;
@@ -24558,7 +24562,7 @@ invalid_double_starred_kvpairs_rule(Parser *p)
&&
(a = _PyPegen_expect_token(p, 11)) // token=':'
&&
- _PyPegen_lookahead(1, _tmp_229_rule, p)
+ _PyPegen_lookahead(1, _tmp_231_rule, p)
)
{
D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')"));
@@ -24669,7 +24673,7 @@ invalid_kvpair_rule(Parser *p)
&&
(a = _PyPegen_expect_token(p, 11)) // token=':'
&&
- _PyPegen_lookahead(1, _tmp_230_rule, p)
+ _PyPegen_lookahead(1, _tmp_232_rule, p)
)
{
D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')"));
@@ -24887,7 +24891,7 @@ invalid_replacement_field_rule(Parser *p)
if (
(_literal = _PyPegen_expect_token(p, 25)) // token='{'
&&
- _PyPegen_lookahead(0, _tmp_231_rule, p)
+ _PyPegen_lookahead(0, _tmp_233_rule, p)
)
{
D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' !(yield_expr | star_expressions)"));
@@ -24910,13 +24914,13 @@ invalid_replacement_field_rule(Parser *p)
}
D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}')"));
Token * _literal;
- void *_tmp_232_var;
+ void *_tmp_234_var;
if (
(_literal = _PyPegen_expect_token(p, 25)) // token='{'
&&
- (_tmp_232_var = _tmp_232_rule(p)) // yield_expr | star_expressions
+ (_tmp_234_var = _tmp_234_rule(p)) // yield_expr | star_expressions
&&
- _PyPegen_lookahead(0, _tmp_233_rule, p)
+ _PyPegen_lookahead(0, _tmp_235_rule, p)
)
{
D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}')"));
@@ -24940,15 +24944,15 @@ invalid_replacement_field_rule(Parser *p)
D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '=' !('!' | ':' | '}')"));
Token * _literal;
Token * _literal_1;
- void *_tmp_234_var;
+ void *_tmp_236_var;
if (
(_literal = _PyPegen_expect_token(p, 25)) // token='{'
&&
- (_tmp_234_var = _tmp_234_rule(p)) // yield_expr | star_expressions
+ (_tmp_236_var = _tmp_236_rule(p)) // yield_expr | star_expressions
&&
(_literal_1 = _PyPegen_expect_token(p, 22)) // token='='
&&
- _PyPegen_lookahead(0, _tmp_235_rule, p)
+ _PyPegen_lookahead(0, _tmp_237_rule, p)
)
{
D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '=' !('!' | ':' | '}')"));
@@ -24973,12 +24977,12 @@ invalid_replacement_field_rule(Parser *p)
Token * _literal;
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
- void *_tmp_236_var;
+ void *_tmp_238_var;
void *invalid_conversion_character_var;
if (
(_literal = _PyPegen_expect_token(p, 25)) // token='{'
&&
- (_tmp_236_var = _tmp_236_rule(p)) // yield_expr | star_expressions
+ (_tmp_238_var = _tmp_238_rule(p)) // yield_expr | star_expressions
&&
(_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='?
&&
@@ -24986,7 +24990,7 @@ invalid_replacement_field_rule(Parser *p)
)
{
D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? invalid_conversion_character"));
- _res = _PyPegen_dummy_name(p, _literal, _tmp_236_var, _opt_var, invalid_conversion_character_var);
+ _res = _PyPegen_dummy_name(p, _literal, _tmp_238_var, _opt_var, invalid_conversion_character_var);
goto done;
}
p->mark = _mark;
@@ -25004,17 +25008,17 @@ invalid_replacement_field_rule(Parser *p)
UNUSED(_opt_var); // Silence compiler warnings
void *_opt_var_1;
UNUSED(_opt_var_1); // Silence compiler warnings
- void *_tmp_237_var;
+ void *_tmp_239_var;
if (
(_literal = _PyPegen_expect_token(p, 25)) // token='{'
&&
- (_tmp_237_var = _tmp_237_rule(p)) // yield_expr | star_expressions
+ (_tmp_239_var = _tmp_239_rule(p)) // yield_expr | star_expressions
&&
(_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='?
&&
- (_opt_var_1 = _tmp_238_rule(p), !p->error_indicator) // ['!' NAME]
+ (_opt_var_1 = _tmp_240_rule(p), !p->error_indicator) // ['!' NAME]
&&
- _PyPegen_lookahead(0, _tmp_239_rule, p)
+ _PyPegen_lookahead(0, _tmp_241_rule, p)
)
{
D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] !(':' | '}')"));
@@ -25038,24 +25042,24 @@ invalid_replacement_field_rule(Parser *p)
D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] ':' fstring_format_spec* !'}'"));
Token * _literal;
Token * _literal_1;
- asdl_seq * _loop0_242_var;
+ asdl_seq * _loop0_244_var;
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
void *_opt_var_1;
UNUSED(_opt_var_1); // Silence compiler warnings
- void *_tmp_240_var;
+ void *_tmp_242_var;
if (
(_literal = _PyPegen_expect_token(p, 25)) // token='{'
&&
- (_tmp_240_var = _tmp_240_rule(p)) // yield_expr | star_expressions
+ (_tmp_242_var = _tmp_242_rule(p)) // yield_expr | star_expressions
&&
(_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='?
&&
- (_opt_var_1 = _tmp_241_rule(p), !p->error_indicator) // ['!' NAME]
+ (_opt_var_1 = _tmp_243_rule(p), !p->error_indicator) // ['!' NAME]
&&
(_literal_1 = _PyPegen_expect_token(p, 11)) // token=':'
&&
- (_loop0_242_var = _loop0_242_rule(p)) // fstring_format_spec*
+ (_loop0_244_var = _loop0_244_rule(p)) // fstring_format_spec*
&&
_PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 26) // token='}'
)
@@ -25084,15 +25088,15 @@ invalid_replacement_field_rule(Parser *p)
UNUSED(_opt_var); // Silence compiler warnings
void *_opt_var_1;
UNUSED(_opt_var_1); // Silence compiler warnings
- void *_tmp_243_var;
+ void *_tmp_245_var;
if (
(_literal = _PyPegen_expect_token(p, 25)) // token='{'
&&
- (_tmp_243_var = _tmp_243_rule(p)) // yield_expr | star_expressions
+ (_tmp_245_var = _tmp_245_rule(p)) // yield_expr | star_expressions
&&
(_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='?
&&
- (_opt_var_1 = _tmp_244_rule(p), !p->error_indicator) // ['!' NAME]
+ (_opt_var_1 = _tmp_246_rule(p), !p->error_indicator) // ['!' NAME]
&&
_PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 26) // token='}'
)
@@ -25140,7 +25144,7 @@ invalid_conversion_character_rule(Parser *p)
if (
(_literal = _PyPegen_expect_token(p, 54)) // token='!'
&&
- _PyPegen_lookahead(1, _tmp_245_rule, p)
+ _PyPegen_lookahead(1, _tmp_247_rule, p)
)
{
D(fprintf(stderr, "%*c+ invalid_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' &(':' | '}')"));
@@ -26085,12 +26089,12 @@ _loop1_15_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
- void *_tmp_246_var;
+ void *_tmp_248_var;
while (
- (_tmp_246_var = _tmp_246_rule(p)) // star_targets '='
+ (_tmp_248_var = _tmp_248_rule(p)) // star_targets '='
)
{
- _res = _tmp_246_var;
+ _res = _tmp_248_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -26664,12 +26668,12 @@ _loop0_25_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')"));
- void *_tmp_247_var;
+ void *_tmp_249_var;
while (
- (_tmp_247_var = _tmp_247_rule(p)) // '.' | '...'
+ (_tmp_249_var = _tmp_249_rule(p)) // '.' | '...'
)
{
- _res = _tmp_247_var;
+ _res = _tmp_249_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -26732,12 +26736,12 @@ _loop1_26_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_26[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')"));
- void *_tmp_248_var;
+ void *_tmp_250_var;
while (
- (_tmp_248_var = _tmp_248_rule(p)) // '.' | '...'
+ (_tmp_250_var = _tmp_250_rule(p)) // '.' | '...'
)
{
- _res = _tmp_248_var;
+ _res = _tmp_250_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -27137,12 +27141,12 @@ _loop1_33_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_33[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)"));
- void *_tmp_249_var;
+ void *_tmp_251_var;
while (
- (_tmp_249_var = _tmp_249_rule(p)) // '@' named_expression NEWLINE
+ (_tmp_251_var = _tmp_251_rule(p)) // '@' named_expression NEWLINE
)
{
- _res = _tmp_249_var;
+ _res = _tmp_251_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -30317,12 +30321,12 @@ _loop1_83_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)"));
- void *_tmp_250_var;
+ void *_tmp_252_var;
while (
- (_tmp_250_var = _tmp_250_rule(p)) // ',' expression
+ (_tmp_252_var = _tmp_252_rule(p)) // ',' expression
)
{
- _res = _tmp_250_var;
+ _res = _tmp_252_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -30390,12 +30394,12 @@ _loop1_84_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)"));
- void *_tmp_251_var;
+ void *_tmp_253_var;
while (
- (_tmp_251_var = _tmp_251_rule(p)) // ',' star_expression
+ (_tmp_253_var = _tmp_253_rule(p)) // ',' star_expression
)
{
- _res = _tmp_251_var;
+ _res = _tmp_253_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -30582,12 +30586,12 @@ _loop1_87_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)"));
- void *_tmp_252_var;
+ void *_tmp_254_var;
while (
- (_tmp_252_var = _tmp_252_rule(p)) // 'or' conjunction
+ (_tmp_254_var = _tmp_254_rule(p)) // 'or' conjunction
)
{
- _res = _tmp_252_var;
+ _res = _tmp_254_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -30655,12 +30659,12 @@ _loop1_88_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)"));
- void *_tmp_253_var;
+ void *_tmp_255_var;
while (
- (_tmp_253_var = _tmp_253_rule(p)) // 'and' inversion
+ (_tmp_255_var = _tmp_255_rule(p)) // 'and' inversion
)
{
- _res = _tmp_253_var;
+ _res = _tmp_255_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -30850,7 +30854,7 @@ _loop0_92_rule(Parser *p)
while (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (elem = _tmp_254_rule(p)) // slice | starred_expression
+ (elem = _tmp_256_rule(p)) // slice | starred_expression
)
{
_res = elem;
@@ -30916,7 +30920,7 @@ _gather_91_rule(Parser *p)
void *elem;
asdl_seq * seq;
if (
- (elem = _tmp_254_rule(p)) // slice | starred_expression
+ (elem = _tmp_256_rule(p)) // slice | starred_expression
&&
(seq = _loop0_92_rule(p)) // _loop0_92
)
@@ -32471,12 +32475,12 @@ _loop1_115_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(fstring | string)"));
- void *_tmp_255_var;
+ void *_tmp_257_var;
while (
- (_tmp_255_var = _tmp_255_rule(p)) // fstring | string
+ (_tmp_257_var = _tmp_257_rule(p)) // fstring | string
)
{
- _res = _tmp_255_var;
+ _res = _tmp_257_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -32786,12 +32790,12 @@ _loop0_120_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)"));
- void *_tmp_256_var;
+ void *_tmp_258_var;
while (
- (_tmp_256_var = _tmp_256_rule(p)) // 'if' disjunction
+ (_tmp_258_var = _tmp_258_rule(p)) // 'if' disjunction
)
{
- _res = _tmp_256_var;
+ _res = _tmp_258_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -32854,12 +32858,12 @@ _loop0_121_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)"));
- void *_tmp_257_var;
+ void *_tmp_259_var;
while (
- (_tmp_257_var = _tmp_257_rule(p)) // 'if' disjunction
+ (_tmp_259_var = _tmp_259_rule(p)) // 'if' disjunction
)
{
- _res = _tmp_257_var;
+ _res = _tmp_259_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -32987,7 +32991,7 @@ _loop0_124_rule(Parser *p)
while (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (elem = _tmp_258_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'='
+ (elem = _tmp_260_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'='
)
{
_res = elem;
@@ -33054,7 +33058,7 @@ _gather_123_rule(Parser *p)
void *elem;
asdl_seq * seq;
if (
- (elem = _tmp_258_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'='
+ (elem = _tmp_260_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'='
&&
(seq = _loop0_124_rule(p)) // _loop0_124
)
@@ -33625,12 +33629,12 @@ _loop0_134_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)"));
- void *_tmp_259_var;
+ void *_tmp_261_var;
while (
- (_tmp_259_var = _tmp_259_rule(p)) // ',' star_target
+ (_tmp_261_var = _tmp_261_rule(p)) // ',' star_target
)
{
- _res = _tmp_259_var;
+ _res = _tmp_261_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -33812,12 +33816,12 @@ _loop1_137_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)"));
- void *_tmp_260_var;
+ void *_tmp_262_var;
while (
- (_tmp_260_var = _tmp_260_rule(p)) // ',' star_target
+ (_tmp_262_var = _tmp_262_rule(p)) // ',' star_target
)
{
- _res = _tmp_260_var;
+ _res = _tmp_262_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -35338,12 +35342,12 @@ _loop0_162_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
- void *_tmp_261_var;
+ void *_tmp_263_var;
while (
- (_tmp_261_var = _tmp_261_rule(p)) // star_targets '='
+ (_tmp_263_var = _tmp_263_rule(p)) // star_targets '='
)
{
- _res = _tmp_261_var;
+ _res = _tmp_263_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -35406,12 +35410,12 @@ _loop0_163_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
- void *_tmp_262_var;
+ void *_tmp_264_var;
while (
- (_tmp_262_var = _tmp_262_rule(p)) // star_targets '='
+ (_tmp_264_var = _tmp_264_rule(p)) // star_targets '='
)
{
- _res = _tmp_262_var;
+ _res = _tmp_264_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -36454,15 +36458,15 @@ _tmp_179_rule(Parser *p)
}
D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
Token * _literal;
- void *_tmp_263_var;
+ void *_tmp_265_var;
if (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (_tmp_263_var = _tmp_263_rule(p)) // ')' | '**'
+ (_tmp_265_var = _tmp_265_rule(p)) // ')' | '**'
)
{
D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
- _res = _PyPegen_dummy_name(p, _literal, _tmp_263_var);
+ _res = _PyPegen_dummy_name(p, _literal, _tmp_265_var);
goto done;
}
p->mark = _mark;
@@ -37628,15 +37632,15 @@ _tmp_197_rule(Parser *p)
}
D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
Token * _literal;
- void *_tmp_264_var;
+ void *_tmp_266_var;
if (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (_tmp_264_var = _tmp_264_rule(p)) // ':' | '**'
+ (_tmp_266_var = _tmp_266_rule(p)) // ':' | '**'
)
{
D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
- _res = _PyPegen_dummy_name(p, _literal, _tmp_264_var);
+ _res = _PyPegen_dummy_name(p, _literal, _tmp_266_var);
goto done;
}
p->mark = _mark;
@@ -37987,7 +37991,7 @@ _tmp_202_rule(Parser *p)
return _res;
}
-// _loop0_204: ',' (expression ['as' star_target])
+// _loop0_204: ',' dotted_name
static asdl_seq *
_loop0_204_rule(Parser *p)
{
@@ -38010,18 +38014,18 @@ _loop0_204_rule(Parser *p)
}
Py_ssize_t _children_capacity = 1;
Py_ssize_t _n = 0;
- { // ',' (expression ['as' star_target])
+ { // ',' dotted_name
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])"));
+ D(fprintf(stderr, "%*c> _loop0_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_name"));
Token * _literal;
- void *elem;
+ expr_ty elem;
while (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (elem = _tmp_265_rule(p)) // expression ['as' star_target]
+ (elem = dotted_name_rule(p)) // dotted_name
)
{
_res = elem;
@@ -38048,7 +38052,7 @@ _loop0_204_rule(Parser *p)
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s _loop0_204[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' dotted_name"));
}
asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
if (!_seq) {
@@ -38064,7 +38068,7 @@ _loop0_204_rule(Parser *p)
return _seq;
}
-// _gather_203: (expression ['as' star_target]) _loop0_204
+// _gather_203: dotted_name _loop0_204
static asdl_seq *
_gather_203_rule(Parser *p)
{
@@ -38078,27 +38082,27 @@ _gather_203_rule(Parser *p)
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // (expression ['as' star_target]) _loop0_204
+ { // dotted_name _loop0_204
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_204"));
- void *elem;
+ D(fprintf(stderr, "%*c> _gather_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_204"));
+ expr_ty elem;
asdl_seq * seq;
if (
- (elem = _tmp_265_rule(p)) // expression ['as' star_target]
+ (elem = dotted_name_rule(p)) // dotted_name
&&
(seq = _loop0_204_rule(p)) // _loop0_204
)
{
- D(fprintf(stderr, "%*c+ _gather_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_204"));
+ D(fprintf(stderr, "%*c+ _gather_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_204"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s _gather_203[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_204"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dotted_name _loop0_204"));
}
_res = NULL;
done:
@@ -38106,7 +38110,7 @@ _gather_203_rule(Parser *p)
return _res;
}
-// _loop0_206: ',' (expressions ['as' star_target])
+// _loop0_206: ',' (expression ['as' star_target])
static asdl_seq *
_loop0_206_rule(Parser *p)
{
@@ -38129,18 +38133,18 @@ _loop0_206_rule(Parser *p)
}
Py_ssize_t _children_capacity = 1;
Py_ssize_t _n = 0;
- { // ',' (expressions ['as' star_target])
+ { // ',' (expression ['as' star_target])
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])"));
+ D(fprintf(stderr, "%*c> _loop0_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])"));
Token * _literal;
void *elem;
while (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (elem = _tmp_266_rule(p)) // expressions ['as' star_target]
+ (elem = _tmp_267_rule(p)) // expression ['as' star_target]
)
{
_res = elem;
@@ -38167,7 +38171,7 @@ _loop0_206_rule(Parser *p)
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s _loop0_206[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])"));
}
asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
if (!_seq) {
@@ -38183,7 +38187,7 @@ _loop0_206_rule(Parser *p)
return _seq;
}
-// _gather_205: (expressions ['as' star_target]) _loop0_206
+// _gather_205: (expression ['as' star_target]) _loop0_206
static asdl_seq *
_gather_205_rule(Parser *p)
{
@@ -38197,27 +38201,27 @@ _gather_205_rule(Parser *p)
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // (expressions ['as' star_target]) _loop0_206
+ { // (expression ['as' star_target]) _loop0_206
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_206"));
+ D(fprintf(stderr, "%*c> _gather_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_206"));
void *elem;
asdl_seq * seq;
if (
- (elem = _tmp_266_rule(p)) // expressions ['as' star_target]
+ (elem = _tmp_267_rule(p)) // expression ['as' star_target]
&&
(seq = _loop0_206_rule(p)) // _loop0_206
)
{
- D(fprintf(stderr, "%*c+ _gather_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_206"));
+ D(fprintf(stderr, "%*c+ _gather_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_206"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s _gather_205[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_206"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_206"));
}
_res = NULL;
done:
@@ -38225,7 +38229,7 @@ _gather_205_rule(Parser *p)
return _res;
}
-// _loop0_208: ',' (expression ['as' star_target])
+// _loop0_208: ',' (expressions ['as' star_target])
static asdl_seq *
_loop0_208_rule(Parser *p)
{
@@ -38248,18 +38252,18 @@ _loop0_208_rule(Parser *p)
}
Py_ssize_t _children_capacity = 1;
Py_ssize_t _n = 0;
- { // ',' (expression ['as' star_target])
+ { // ',' (expressions ['as' star_target])
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])"));
+ D(fprintf(stderr, "%*c> _loop0_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])"));
Token * _literal;
void *elem;
while (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (elem = _tmp_267_rule(p)) // expression ['as' star_target]
+ (elem = _tmp_268_rule(p)) // expressions ['as' star_target]
)
{
_res = elem;
@@ -38286,7 +38290,7 @@ _loop0_208_rule(Parser *p)
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s _loop0_208[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])"));
}
asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
if (!_seq) {
@@ -38302,7 +38306,7 @@ _loop0_208_rule(Parser *p)
return _seq;
}
-// _gather_207: (expression ['as' star_target]) _loop0_208
+// _gather_207: (expressions ['as' star_target]) _loop0_208
static asdl_seq *
_gather_207_rule(Parser *p)
{
@@ -38316,27 +38320,27 @@ _gather_207_rule(Parser *p)
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // (expression ['as' star_target]) _loop0_208
+ { // (expressions ['as' star_target]) _loop0_208
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_208"));
+ D(fprintf(stderr, "%*c> _gather_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_208"));
void *elem;
asdl_seq * seq;
if (
- (elem = _tmp_267_rule(p)) // expression ['as' star_target]
+ (elem = _tmp_268_rule(p)) // expressions ['as' star_target]
&&
(seq = _loop0_208_rule(p)) // _loop0_208
)
{
- D(fprintf(stderr, "%*c+ _gather_207[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_208"));
+ D(fprintf(stderr, "%*c+ _gather_207[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_208"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s _gather_207[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_208"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_208"));
}
_res = NULL;
done:
@@ -38344,7 +38348,7 @@ _gather_207_rule(Parser *p)
return _res;
}
-// _loop0_210: ',' (expressions ['as' star_target])
+// _loop0_210: ',' (expression ['as' star_target])
static asdl_seq *
_loop0_210_rule(Parser *p)
{
@@ -38367,18 +38371,18 @@ _loop0_210_rule(Parser *p)
}
Py_ssize_t _children_capacity = 1;
Py_ssize_t _n = 0;
- { // ',' (expressions ['as' star_target])
+ { // ',' (expression ['as' star_target])
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_210[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])"));
+ D(fprintf(stderr, "%*c> _loop0_210[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])"));
Token * _literal;
void *elem;
while (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (elem = _tmp_268_rule(p)) // expressions ['as' star_target]
+ (elem = _tmp_269_rule(p)) // expression ['as' star_target]
)
{
_res = elem;
@@ -38405,7 +38409,7 @@ _loop0_210_rule(Parser *p)
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s _loop0_210[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])"));
}
asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
if (!_seq) {
@@ -38421,7 +38425,7 @@ _loop0_210_rule(Parser *p)
return _seq;
}
-// _gather_209: (expressions ['as' star_target]) _loop0_210
+// _gather_209: (expression ['as' star_target]) _loop0_210
static asdl_seq *
_gather_209_rule(Parser *p)
{
@@ -38435,27 +38439,27 @@ _gather_209_rule(Parser *p)
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // (expressions ['as' star_target]) _loop0_210
+ { // (expression ['as' star_target]) _loop0_210
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_210"));
+ D(fprintf(stderr, "%*c> _gather_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_210"));
void *elem;
asdl_seq * seq;
if (
- (elem = _tmp_268_rule(p)) // expressions ['as' star_target]
+ (elem = _tmp_269_rule(p)) // expression ['as' star_target]
&&
(seq = _loop0_210_rule(p)) // _loop0_210
)
{
- D(fprintf(stderr, "%*c+ _gather_209[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_210"));
+ D(fprintf(stderr, "%*c+ _gather_209[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_210"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s _gather_209[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_210"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_210"));
}
_res = NULL;
done:
@@ -38463,65 +38467,7 @@ _gather_209_rule(Parser *p)
return _res;
}
-// _tmp_211: 'except' | 'finally'
-static void *
-_tmp_211_rule(Parser *p)
-{
- if (p->level++ == MAXSTACK) {
- p->error_indicator = 1;
- PyErr_NoMemory();
- }
- if (p->error_indicator) {
- p->level--;
- return NULL;
- }
- void * _res = NULL;
- int _mark = p->mark;
- { // 'except'
- if (p->error_indicator) {
- p->level--;
- return NULL;
- }
- D(fprintf(stderr, "%*c> _tmp_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'"));
- Token * _keyword;
- if (
- (_keyword = _PyPegen_expect_token(p, 637)) // token='except'
- )
- {
- D(fprintf(stderr, "%*c+ _tmp_211[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'"));
- _res = _keyword;
- goto done;
- }
- p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_211[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'"));
- }
- { // 'finally'
- if (p->error_indicator) {
- p->level--;
- return NULL;
- }
- D(fprintf(stderr, "%*c> _tmp_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'"));
- Token * _keyword;
- if (
- (_keyword = _PyPegen_expect_token(p, 633)) // token='finally'
- )
- {
- D(fprintf(stderr, "%*c+ _tmp_211[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'"));
- _res = _keyword;
- goto done;
- }
- p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_211[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'"));
- }
- _res = NULL;
- done:
- p->level--;
- return _res;
-}
-
-// _loop0_212: block
+// _loop0_212: ',' (expressions ['as' star_target])
static asdl_seq *
_loop0_212_rule(Parser *p)
{
@@ -38544,18 +38490,27 @@ _loop0_212_rule(Parser *p)
}
Py_ssize_t _children_capacity = 1;
Py_ssize_t _n = 0;
- { // block
+ { // ',' (expressions ['as' star_target])
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_212[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block"));
- asdl_stmt_seq* block_var;
+ D(fprintf(stderr, "%*c> _loop0_212[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])"));
+ Token * _literal;
+ void *elem;
while (
- (block_var = block_rule(p)) // block
+ (_literal = _PyPegen_expect_token(p, 12)) // token=','
+ &&
+ (elem = _tmp_270_rule(p)) // expressions ['as' star_target]
)
{
- _res = block_var;
+ _res = elem;
+ if (_res == NULL && PyErr_Occurred()) {
+ p->error_indicator = 1;
+ PyMem_Free(_children);
+ p->level--;
+ return NULL;
+ }
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -38573,7 +38528,7 @@ _loop0_212_rule(Parser *p)
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s _loop0_212[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])"));
}
asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
if (!_seq) {
@@ -38589,9 +38544,9 @@ _loop0_212_rule(Parser *p)
return _seq;
}
-// _loop1_213: except_block
+// _gather_211: (expressions ['as' star_target]) _loop0_212
static asdl_seq *
-_loop1_213_rule(Parser *p)
+_gather_211_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -38601,70 +38556,39 @@ _loop1_213_rule(Parser *p)
p->level--;
return NULL;
}
- void *_res = NULL;
+ asdl_seq * _res = NULL;
int _mark = p->mark;
- void **_children = PyMem_Malloc(sizeof(void *));
- if (!_children) {
- p->error_indicator = 1;
- PyErr_NoMemory();
- p->level--;
- return NULL;
- }
- Py_ssize_t _children_capacity = 1;
- Py_ssize_t _n = 0;
- { // except_block
+ { // (expressions ['as' star_target]) _loop0_212
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block"));
- excepthandler_ty except_block_var;
- while (
- (except_block_var = except_block_rule(p)) // except_block
+ D(fprintf(stderr, "%*c> _gather_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_212"));
+ void *elem;
+ asdl_seq * seq;
+ if (
+ (elem = _tmp_270_rule(p)) // expressions ['as' star_target]
+ &&
+ (seq = _loop0_212_rule(p)) // _loop0_212
)
{
- _res = except_block_var;
- if (_n == _children_capacity) {
- _children_capacity *= 2;
- void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
- if (!_new_children) {
- PyMem_Free(_children);
- p->error_indicator = 1;
- PyErr_NoMemory();
- p->level--;
- return NULL;
- }
- _children = _new_children;
- }
- _children[_n++] = _res;
- _mark = p->mark;
+ D(fprintf(stderr, "%*c+ _gather_211[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_212"));
+ _res = _PyPegen_seq_insert_in_front(p, elem, seq);
+ goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_213[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_block"));
- }
- if (_n == 0 || p->error_indicator) {
- PyMem_Free(_children);
- p->level--;
- return NULL;
- }
- asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
- if (!_seq) {
- PyMem_Free(_children);
- p->error_indicator = 1;
- PyErr_NoMemory();
- p->level--;
- return NULL;
+ D(fprintf(stderr, "%*c%s _gather_211[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_212"));
}
- for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]);
- PyMem_Free(_children);
+ _res = NULL;
+ done:
p->level--;
- return _seq;
+ return _res;
}
-// _tmp_214: 'as' NAME
+// _tmp_213: 'except' | 'finally'
static void *
-_tmp_214_rule(Parser *p)
+_tmp_213_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -38676,27 +38600,43 @@ _tmp_214_rule(Parser *p)
}
void * _res = NULL;
int _mark = p->mark;
- { // 'as' NAME
+ { // 'except'
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ D(fprintf(stderr, "%*c> _tmp_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'"));
Token * _keyword;
- expr_ty name_var;
if (
- (_keyword = _PyPegen_expect_token(p, 640)) // token='as'
- &&
- (name_var = _PyPegen_name_token(p)) // NAME
+ (_keyword = _PyPegen_expect_token(p, 637)) // token='except'
)
{
- D(fprintf(stderr, "%*c+ _tmp_214[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
- _res = _PyPegen_dummy_name(p, _keyword, name_var);
+ D(fprintf(stderr, "%*c+ _tmp_213[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'"));
+ _res = _keyword;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_214[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME"));
+ D(fprintf(stderr, "%*c%s _tmp_213[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'"));
+ }
+ { // 'finally'
+ if (p->error_indicator) {
+ p->level--;
+ return NULL;
+ }
+ D(fprintf(stderr, "%*c> _tmp_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'"));
+ Token * _keyword;
+ if (
+ (_keyword = _PyPegen_expect_token(p, 633)) // token='finally'
+ )
+ {
+ D(fprintf(stderr, "%*c+ _tmp_213[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'"));
+ _res = _keyword;
+ goto done;
+ }
+ p->mark = _mark;
+ D(fprintf(stderr, "%*c%s _tmp_213[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'"));
}
_res = NULL;
done:
@@ -38704,9 +38644,9 @@ _tmp_214_rule(Parser *p)
return _res;
}
-// _loop0_215: block
+// _loop0_214: block
static asdl_seq *
-_loop0_215_rule(Parser *p)
+_loop0_214_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -38732,7 +38672,7 @@ _loop0_215_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_215[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block"));
+ D(fprintf(stderr, "%*c> _loop0_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block"));
asdl_stmt_seq* block_var;
while (
(block_var = block_rule(p)) // block
@@ -38755,7 +38695,7 @@ _loop0_215_rule(Parser *p)
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_215[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_214[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block"));
}
asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
@@ -38772,9 +38712,9 @@ _loop0_215_rule(Parser *p)
return _seq;
}
-// _loop1_216: except_star_block
+// _loop1_215: except_block
static asdl_seq *
-_loop1_216_rule(Parser *p)
+_loop1_215_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -38795,18 +38735,18 @@ _loop1_216_rule(Parser *p)
}
Py_ssize_t _children_capacity = 1;
Py_ssize_t _n = 0;
- { // except_star_block
+ { // except_block
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block"));
- excepthandler_ty except_star_block_var;
+ D(fprintf(stderr, "%*c> _loop1_215[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block"));
+ excepthandler_ty except_block_var;
while (
- (except_star_block_var = except_star_block_rule(p)) // except_star_block
+ (except_block_var = except_block_rule(p)) // except_block
)
{
- _res = except_star_block_var;
+ _res = except_block_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -38823,8 +38763,8 @@ _loop1_216_rule(Parser *p)
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_216[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_star_block"));
+ D(fprintf(stderr, "%*c%s _loop1_215[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_block"));
}
if (_n == 0 || p->error_indicator) {
PyMem_Free(_children);
@@ -38845,9 +38785,192 @@ _loop1_216_rule(Parser *p)
return _seq;
}
-// _tmp_217: expression ['as' NAME]
+// _tmp_216: 'as' NAME
static void *
-_tmp_217_rule(Parser *p)
+_tmp_216_rule(Parser *p)
+{
+ if (p->level++ == MAXSTACK) {
+ p->error_indicator = 1;
+ PyErr_NoMemory();
+ }
+ if (p->error_indicator) {
+ p->level--;
+ return NULL;
+ }
+ void * _res = NULL;
+ int _mark = p->mark;
+ { // 'as' NAME
+ if (p->error_indicator) {
+ p->level--;
+ return NULL;
+ }
+ D(fprintf(stderr, "%*c> _tmp_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ Token * _keyword;
+ expr_ty name_var;
+ if (
+ (_keyword = _PyPegen_expect_token(p, 640)) // token='as'
+ &&
+ (name_var = _PyPegen_name_token(p)) // NAME
+ )
+ {
+ D(fprintf(stderr, "%*c+ _tmp_216[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ _res = _PyPegen_dummy_name(p, _keyword, name_var);
+ goto done;
+ }
+ p->mark = _mark;
+ D(fprintf(stderr, "%*c%s _tmp_216[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME"));
+ }
+ _res = NULL;
+ done:
+ p->level--;
+ return _res;
+}
+
+// _loop0_217: block
+static asdl_seq *
+_loop0_217_rule(Parser *p)
+{
+ if (p->level++ == MAXSTACK) {
+ p->error_indicator = 1;
+ PyErr_NoMemory();
+ }
+ if (p->error_indicator) {
+ p->level--;
+ return NULL;
+ }
+ void *_res = NULL;
+ int _mark = p->mark;
+ void **_children = PyMem_Malloc(sizeof(void *));
+ if (!_children) {
+ p->error_indicator = 1;
+ PyErr_NoMemory();
+ p->level--;
+ return NULL;
+ }
+ Py_ssize_t _children_capacity = 1;
+ Py_ssize_t _n = 0;
+ { // block
+ if (p->error_indicator) {
+ p->level--;
+ return NULL;
+ }
+ D(fprintf(stderr, "%*c> _loop0_217[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block"));
+ asdl_stmt_seq* block_var;
+ while (
+ (block_var = block_rule(p)) // block
+ )
+ {
+ _res = block_var;
+ if (_n == _children_capacity) {
+ _children_capacity *= 2;
+ void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+ if (!_new_children) {
+ PyMem_Free(_children);
+ p->error_indicator = 1;
+ PyErr_NoMemory();
+ p->level--;
+ return NULL;
+ }
+ _children = _new_children;
+ }
+ _children[_n++] = _res;
+ _mark = p->mark;
+ }
+ p->mark = _mark;
+ D(fprintf(stderr, "%*c%s _loop0_217[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block"));
+ }
+ asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
+ if (!_seq) {
+ PyMem_Free(_children);
+ p->error_indicator = 1;
+ PyErr_NoMemory();
+ p->level--;
+ return NULL;
+ }
+ for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]);
+ PyMem_Free(_children);
+ p->level--;
+ return _seq;
+}
+
+// _loop1_218: except_star_block
+static asdl_seq *
+_loop1_218_rule(Parser *p)
+{
+ if (p->level++ == MAXSTACK) {
+ p->error_indicator = 1;
+ PyErr_NoMemory();
+ }
+ if (p->error_indicator) {
+ p->level--;
+ return NULL;
+ }
+ void *_res = NULL;
+ int _mark = p->mark;
+ void **_children = PyMem_Malloc(sizeof(void *));
+ if (!_children) {
+ p->error_indicator = 1;
+ PyErr_NoMemory();
+ p->level--;
+ return NULL;
+ }
+ Py_ssize_t _children_capacity = 1;
+ Py_ssize_t _n = 0;
+ { // except_star_block
+ if (p->error_indicator) {
+ p->level--;
+ return NULL;
+ }
+ D(fprintf(stderr, "%*c> _loop1_218[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block"));
+ excepthandler_ty except_star_block_var;
+ while (
+ (except_star_block_var = except_star_block_rule(p)) // except_star_block
+ )
+ {
+ _res = except_star_block_var;
+ if (_n == _children_capacity) {
+ _children_capacity *= 2;
+ void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+ if (!_new_children) {
+ PyMem_Free(_children);
+ p->error_indicator = 1;
+ PyErr_NoMemory();
+ p->level--;
+ return NULL;
+ }
+ _children = _new_children;
+ }
+ _children[_n++] = _res;
+ _mark = p->mark;
+ }
+ p->mark = _mark;
+ D(fprintf(stderr, "%*c%s _loop1_218[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_star_block"));
+ }
+ if (_n == 0 || p->error_indicator) {
+ PyMem_Free(_children);
+ p->level--;
+ return NULL;
+ }
+ asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
+ if (!_seq) {
+ PyMem_Free(_children);
+ p->error_indicator = 1;
+ PyErr_NoMemory();
+ p->level--;
+ return NULL;
+ }
+ for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]);
+ PyMem_Free(_children);
+ p->level--;
+ return _seq;
+}
+
+// _tmp_219: expression ['as' NAME]
+static void *
+_tmp_219_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -38864,22 +38987,22 @@ _tmp_217_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_217[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]"));
+ D(fprintf(stderr, "%*c> _tmp_219[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]"));
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
expr_ty expression_var;
if (
(expression_var = expression_rule(p)) // expression
&&
- (_opt_var = _tmp_269_rule(p), !p->error_indicator) // ['as' NAME]
+ (_opt_var = _tmp_271_rule(p), !p->error_indicator) // ['as' NAME]
)
{
- D(fprintf(stderr, "%*c+ _tmp_217[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]"));
+ D(fprintf(stderr, "%*c+ _tmp_219[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]"));
_res = _PyPegen_dummy_name(p, expression_var, _opt_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_217[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_219[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' NAME]"));
}
_res = NULL;
@@ -38888,9 +39011,9 @@ _tmp_217_rule(Parser *p)
return _res;
}
-// _tmp_218: 'as' NAME
+// _tmp_220: 'as' NAME
static void *
-_tmp_218_rule(Parser *p)
+_tmp_220_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -38907,7 +39030,7 @@ _tmp_218_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_218[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ D(fprintf(stderr, "%*c> _tmp_220[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
Token * _keyword;
expr_ty name_var;
if (
@@ -38916,12 +39039,12 @@ _tmp_218_rule(Parser *p)
(name_var = _PyPegen_name_token(p)) // NAME
)
{
- D(fprintf(stderr, "%*c+ _tmp_218[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ D(fprintf(stderr, "%*c+ _tmp_220[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
_res = _PyPegen_dummy_name(p, _keyword, name_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_218[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_220[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME"));
}
_res = NULL;
@@ -38930,9 +39053,9 @@ _tmp_218_rule(Parser *p)
return _res;
}
-// _tmp_219: 'as' NAME
+// _tmp_221: 'as' NAME
static void *
-_tmp_219_rule(Parser *p)
+_tmp_221_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -38949,7 +39072,7 @@ _tmp_219_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_219[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ D(fprintf(stderr, "%*c> _tmp_221[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
Token * _keyword;
expr_ty name_var;
if (
@@ -38958,12 +39081,12 @@ _tmp_219_rule(Parser *p)
(name_var = _PyPegen_name_token(p)) // NAME
)
{
- D(fprintf(stderr, "%*c+ _tmp_219[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ D(fprintf(stderr, "%*c+ _tmp_221[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
_res = _PyPegen_dummy_name(p, _keyword, name_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_219[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_221[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME"));
}
_res = NULL;
@@ -38972,9 +39095,9 @@ _tmp_219_rule(Parser *p)
return _res;
}
-// _tmp_220: NEWLINE | ':'
+// _tmp_222: NEWLINE | ':'
static void *
-_tmp_220_rule(Parser *p)
+_tmp_222_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -38991,18 +39114,18 @@ _tmp_220_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_220[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE"));
+ D(fprintf(stderr, "%*c> _tmp_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE"));
Token * newline_var;
if (
(newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE'
)
{
- D(fprintf(stderr, "%*c+ _tmp_220[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE"));
+ D(fprintf(stderr, "%*c+ _tmp_222[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE"));
_res = newline_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_220[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_222[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE"));
}
{ // ':'
@@ -39010,18 +39133,18 @@ _tmp_220_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_220[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c> _tmp_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
)
{
- D(fprintf(stderr, "%*c+ _tmp_220[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c+ _tmp_222[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_220[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_222[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'"));
}
_res = NULL;
@@ -39030,9 +39153,9 @@ _tmp_220_rule(Parser *p)
return _res;
}
-// _tmp_221: 'as' NAME
+// _tmp_223: 'as' NAME
static void *
-_tmp_221_rule(Parser *p)
+_tmp_223_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39049,7 +39172,7 @@ _tmp_221_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_221[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ D(fprintf(stderr, "%*c> _tmp_223[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
Token * _keyword;
expr_ty name_var;
if (
@@ -39058,12 +39181,12 @@ _tmp_221_rule(Parser *p)
(name_var = _PyPegen_name_token(p)) // NAME
)
{
- D(fprintf(stderr, "%*c+ _tmp_221[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ D(fprintf(stderr, "%*c+ _tmp_223[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
_res = _PyPegen_dummy_name(p, _keyword, name_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_221[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_223[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME"));
}
_res = NULL;
@@ -39072,9 +39195,9 @@ _tmp_221_rule(Parser *p)
return _res;
}
-// _tmp_222: 'as' NAME
+// _tmp_224: 'as' NAME
static void *
-_tmp_222_rule(Parser *p)
+_tmp_224_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39091,7 +39214,7 @@ _tmp_222_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ D(fprintf(stderr, "%*c> _tmp_224[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
Token * _keyword;
expr_ty name_var;
if (
@@ -39100,12 +39223,12 @@ _tmp_222_rule(Parser *p)
(name_var = _PyPegen_name_token(p)) // NAME
)
{
- D(fprintf(stderr, "%*c+ _tmp_222[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ D(fprintf(stderr, "%*c+ _tmp_224[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
_res = _PyPegen_dummy_name(p, _keyword, name_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_222[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_224[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME"));
}
_res = NULL;
@@ -39114,9 +39237,9 @@ _tmp_222_rule(Parser *p)
return _res;
}
-// _tmp_223: positional_patterns ','
+// _tmp_225: positional_patterns ','
static void *
-_tmp_223_rule(Parser *p)
+_tmp_225_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39133,7 +39256,7 @@ _tmp_223_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_223[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','"));
+ D(fprintf(stderr, "%*c> _tmp_225[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','"));
Token * _literal;
asdl_pattern_seq* positional_patterns_var;
if (
@@ -39142,12 +39265,12 @@ _tmp_223_rule(Parser *p)
(_literal = _PyPegen_expect_token(p, 12)) // token=','
)
{
- D(fprintf(stderr, "%*c+ _tmp_223[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','"));
+ D(fprintf(stderr, "%*c+ _tmp_225[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','"));
_res = _PyPegen_dummy_name(p, positional_patterns_var, _literal);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_223[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_225[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','"));
}
_res = NULL;
@@ -39156,9 +39279,9 @@ _tmp_223_rule(Parser *p)
return _res;
}
-// _tmp_224: '->' expression
+// _tmp_226: '->' expression
static void *
-_tmp_224_rule(Parser *p)
+_tmp_226_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39175,7 +39298,7 @@ _tmp_224_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_224[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression"));
+ D(fprintf(stderr, "%*c> _tmp_226[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression"));
Token * _literal;
expr_ty expression_var;
if (
@@ -39184,12 +39307,12 @@ _tmp_224_rule(Parser *p)
(expression_var = expression_rule(p)) // expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_224[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression"));
+ D(fprintf(stderr, "%*c+ _tmp_226[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression"));
_res = _PyPegen_dummy_name(p, _literal, expression_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_224[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_226[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression"));
}
_res = NULL;
@@ -39198,9 +39321,9 @@ _tmp_224_rule(Parser *p)
return _res;
}
-// _tmp_225: '(' arguments? ')'
+// _tmp_227: '(' arguments? ')'
static void *
-_tmp_225_rule(Parser *p)
+_tmp_227_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39217,7 +39340,7 @@ _tmp_225_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_225[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'"));
+ D(fprintf(stderr, "%*c> _tmp_227[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'"));
Token * _literal;
Token * _literal_1;
void *_opt_var;
@@ -39230,12 +39353,12 @@ _tmp_225_rule(Parser *p)
(_literal_1 = _PyPegen_expect_token(p, 8)) // token=')'
)
{
- D(fprintf(stderr, "%*c+ _tmp_225[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'"));
+ D(fprintf(stderr, "%*c+ _tmp_227[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'"));
_res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_225[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_227[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'"));
}
_res = NULL;
@@ -39244,9 +39367,9 @@ _tmp_225_rule(Parser *p)
return _res;
}
-// _tmp_226: '(' arguments? ')'
+// _tmp_228: '(' arguments? ')'
static void *
-_tmp_226_rule(Parser *p)
+_tmp_228_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39263,7 +39386,7 @@ _tmp_226_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_226[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'"));
+ D(fprintf(stderr, "%*c> _tmp_228[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'"));
Token * _literal;
Token * _literal_1;
void *_opt_var;
@@ -39276,12 +39399,12 @@ _tmp_226_rule(Parser *p)
(_literal_1 = _PyPegen_expect_token(p, 8)) // token=')'
)
{
- D(fprintf(stderr, "%*c+ _tmp_226[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'"));
+ D(fprintf(stderr, "%*c+ _tmp_228[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'"));
_res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_226[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_228[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'"));
}
_res = NULL;
@@ -39290,9 +39413,9 @@ _tmp_226_rule(Parser *p)
return _res;
}
-// _loop0_228: ',' double_starred_kvpair
+// _loop0_230: ',' double_starred_kvpair
static asdl_seq *
-_loop0_228_rule(Parser *p)
+_loop0_230_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39318,7 +39441,7 @@ _loop0_228_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_228[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair"));
+ D(fprintf(stderr, "%*c> _loop0_230[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair"));
Token * _literal;
KeyValuePair* elem;
while (
@@ -39350,7 +39473,7 @@ _loop0_228_rule(Parser *p)
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_228[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_230[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair"));
}
asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
@@ -39367,9 +39490,9 @@ _loop0_228_rule(Parser *p)
return _seq;
}
-// _gather_227: double_starred_kvpair _loop0_228
+// _gather_229: double_starred_kvpair _loop0_230
static asdl_seq *
-_gather_227_rule(Parser *p)
+_gather_229_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39381,27 +39504,27 @@ _gather_227_rule(Parser *p)
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // double_starred_kvpair _loop0_228
+ { // double_starred_kvpair _loop0_230
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_227[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_228"));
+ D(fprintf(stderr, "%*c> _gather_229[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_230"));
KeyValuePair* elem;
asdl_seq * seq;
if (
(elem = double_starred_kvpair_rule(p)) // double_starred_kvpair
&&
- (seq = _loop0_228_rule(p)) // _loop0_228
+ (seq = _loop0_230_rule(p)) // _loop0_230
)
{
- D(fprintf(stderr, "%*c+ _gather_227[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_228"));
+ D(fprintf(stderr, "%*c+ _gather_229[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_230"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_227[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_228"));
+ D(fprintf(stderr, "%*c%s _gather_229[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_230"));
}
_res = NULL;
done:
@@ -39409,9 +39532,9 @@ _gather_227_rule(Parser *p)
return _res;
}
-// _tmp_229: '}' | ','
+// _tmp_231: '}' | ','
static void *
-_tmp_229_rule(Parser *p)
+_tmp_231_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39428,18 +39551,18 @@ _tmp_229_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_229[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'"));
+ D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 26)) // token='}'
)
{
- D(fprintf(stderr, "%*c+ _tmp_229[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'"));
+ D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_229[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'"));
}
{ // ','
@@ -39447,18 +39570,18 @@ _tmp_229_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_229[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','"));
+ D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
)
{
- D(fprintf(stderr, "%*c+ _tmp_229[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','"));
+ D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_229[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','"));
}
_res = NULL;
@@ -39467,9 +39590,9 @@ _tmp_229_rule(Parser *p)
return _res;
}
-// _tmp_230: '}' | ','
+// _tmp_232: '}' | ','
static void *
-_tmp_230_rule(Parser *p)
+_tmp_232_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39486,18 +39609,18 @@ _tmp_230_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_230[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'"));
+ D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 26)) // token='}'
)
{
- D(fprintf(stderr, "%*c+ _tmp_230[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'"));
+ D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_230[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'"));
}
{ // ','
@@ -39505,18 +39628,18 @@ _tmp_230_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_230[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','"));
+ D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
)
{
- D(fprintf(stderr, "%*c+ _tmp_230[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','"));
+ D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_230[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','"));
}
_res = NULL;
@@ -39525,9 +39648,9 @@ _tmp_230_rule(Parser *p)
return _res;
}
-// _tmp_231: yield_expr | star_expressions
+// _tmp_233: yield_expr | star_expressions
static void *
-_tmp_231_rule(Parser *p)
+_tmp_233_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39544,18 +39667,18 @@ _tmp_231_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
expr_ty yield_expr_var;
if (
(yield_expr_var = yield_expr_rule(p)) // yield_expr
)
{
- D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
_res = yield_expr_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr"));
}
{ // star_expressions
@@ -39563,18 +39686,18 @@ _tmp_231_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
expr_ty star_expressions_var;
if (
(star_expressions_var = star_expressions_rule(p)) // star_expressions
)
{
- D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
_res = star_expressions_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions"));
}
_res = NULL;
@@ -39583,9 +39706,9 @@ _tmp_231_rule(Parser *p)
return _res;
}
-// _tmp_232: yield_expr | star_expressions
+// _tmp_234: yield_expr | star_expressions
static void *
-_tmp_232_rule(Parser *p)
+_tmp_234_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39602,18 +39725,18 @@ _tmp_232_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
expr_ty yield_expr_var;
if (
(yield_expr_var = yield_expr_rule(p)) // yield_expr
)
{
- D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
_res = yield_expr_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr"));
}
{ // star_expressions
@@ -39621,18 +39744,18 @@ _tmp_232_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
expr_ty star_expressions_var;
if (
(star_expressions_var = star_expressions_rule(p)) // star_expressions
)
{
- D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
_res = star_expressions_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions"));
}
_res = NULL;
@@ -39641,9 +39764,9 @@ _tmp_232_rule(Parser *p)
return _res;
}
-// _tmp_233: '=' | '!' | ':' | '}'
+// _tmp_235: '=' | '!' | ':' | '}'
static void *
-_tmp_233_rule(Parser *p)
+_tmp_235_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39660,18 +39783,18 @@ _tmp_233_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='"));
+ D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 22)) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='"));
+ D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='"));
}
{ // '!'
@@ -39679,18 +39802,18 @@ _tmp_233_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'"));
+ D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 54)) // token='!'
)
{
- D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'"));
+ D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'"));
}
{ // ':'
@@ -39698,18 +39821,18 @@ _tmp_233_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
)
{
- D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'"));
}
{ // '}'
@@ -39717,18 +39840,18 @@ _tmp_233_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'"));
+ D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 26)) // token='}'
)
{
- D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'"));
+ D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'"));
}
_res = NULL;
@@ -39737,9 +39860,9 @@ _tmp_233_rule(Parser *p)
return _res;
}
-// _tmp_234: yield_expr | star_expressions
+// _tmp_236: yield_expr | star_expressions
static void *
-_tmp_234_rule(Parser *p)
+_tmp_236_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39756,18 +39879,18 @@ _tmp_234_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
expr_ty yield_expr_var;
if (
(yield_expr_var = yield_expr_rule(p)) // yield_expr
)
{
- D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
_res = yield_expr_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr"));
}
{ // star_expressions
@@ -39775,18 +39898,18 @@ _tmp_234_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
expr_ty star_expressions_var;
if (
(star_expressions_var = star_expressions_rule(p)) // star_expressions
)
{
- D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
_res = star_expressions_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions"));
}
_res = NULL;
@@ -39795,9 +39918,9 @@ _tmp_234_rule(Parser *p)
return _res;
}
-// _tmp_235: '!' | ':' | '}'
+// _tmp_237: '!' | ':' | '}'
static void *
-_tmp_235_rule(Parser *p)
+_tmp_237_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39814,18 +39937,18 @@ _tmp_235_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'"));
+ D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 54)) // token='!'
)
{
- D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'"));
+ D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'"));
}
{ // ':'
@@ -39833,18 +39956,18 @@ _tmp_235_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
)
{
- D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'"));
}
{ // '}'
@@ -39852,18 +39975,18 @@ _tmp_235_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'"));
+ D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 26)) // token='}'
)
{
- D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'"));
+ D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'"));
}
_res = NULL;
@@ -39872,9 +39995,9 @@ _tmp_235_rule(Parser *p)
return _res;
}
-// _tmp_236: yield_expr | star_expressions
+// _tmp_238: yield_expr | star_expressions
static void *
-_tmp_236_rule(Parser *p)
+_tmp_238_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39891,18 +40014,18 @@ _tmp_236_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
expr_ty yield_expr_var;
if (
(yield_expr_var = yield_expr_rule(p)) // yield_expr
)
{
- D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
_res = yield_expr_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr"));
}
{ // star_expressions
@@ -39910,18 +40033,18 @@ _tmp_236_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
expr_ty star_expressions_var;
if (
(star_expressions_var = star_expressions_rule(p)) // star_expressions
)
{
- D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
_res = star_expressions_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions"));
}
_res = NULL;
@@ -39930,9 +40053,9 @@ _tmp_236_rule(Parser *p)
return _res;
}
-// _tmp_237: yield_expr | star_expressions
+// _tmp_239: yield_expr | star_expressions
static void *
-_tmp_237_rule(Parser *p)
+_tmp_239_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -39949,18 +40072,18 @@ _tmp_237_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
expr_ty yield_expr_var;
if (
(yield_expr_var = yield_expr_rule(p)) // yield_expr
)
{
- D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
_res = yield_expr_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr"));
}
{ // star_expressions
@@ -39968,18 +40091,18 @@ _tmp_237_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
expr_ty star_expressions_var;
if (
(star_expressions_var = star_expressions_rule(p)) // star_expressions
)
{
- D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
_res = star_expressions_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions"));
}
_res = NULL;
@@ -39988,9 +40111,9 @@ _tmp_237_rule(Parser *p)
return _res;
}
-// _tmp_238: '!' NAME
+// _tmp_240: '!' NAME
static void *
-_tmp_238_rule(Parser *p)
+_tmp_240_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40007,7 +40130,7 @@ _tmp_238_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME"));
+ D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME"));
Token * _literal;
expr_ty name_var;
if (
@@ -40016,12 +40139,12 @@ _tmp_238_rule(Parser *p)
(name_var = _PyPegen_name_token(p)) // NAME
)
{
- D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME"));
+ D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME"));
_res = _PyPegen_dummy_name(p, _literal, name_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME"));
}
_res = NULL;
@@ -40030,9 +40153,9 @@ _tmp_238_rule(Parser *p)
return _res;
}
-// _tmp_239: ':' | '}'
+// _tmp_241: ':' | '}'
static void *
-_tmp_239_rule(Parser *p)
+_tmp_241_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40049,18 +40172,18 @@ _tmp_239_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
)
{
- D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'"));
}
{ // '}'
@@ -40068,18 +40191,18 @@ _tmp_239_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'"));
+ D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 26)) // token='}'
)
{
- D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'"));
+ D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'"));
}
_res = NULL;
@@ -40088,9 +40211,9 @@ _tmp_239_rule(Parser *p)
return _res;
}
-// _tmp_240: yield_expr | star_expressions
+// _tmp_242: yield_expr | star_expressions
static void *
-_tmp_240_rule(Parser *p)
+_tmp_242_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40107,18 +40230,18 @@ _tmp_240_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
expr_ty yield_expr_var;
if (
(yield_expr_var = yield_expr_rule(p)) // yield_expr
)
{
- D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
_res = yield_expr_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr"));
}
{ // star_expressions
@@ -40126,18 +40249,18 @@ _tmp_240_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
expr_ty star_expressions_var;
if (
(star_expressions_var = star_expressions_rule(p)) // star_expressions
)
{
- D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
_res = star_expressions_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions"));
}
_res = NULL;
@@ -40146,9 +40269,9 @@ _tmp_240_rule(Parser *p)
return _res;
}
-// _tmp_241: '!' NAME
+// _tmp_243: '!' NAME
static void *
-_tmp_241_rule(Parser *p)
+_tmp_243_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40165,7 +40288,7 @@ _tmp_241_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME"));
+ D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME"));
Token * _literal;
expr_ty name_var;
if (
@@ -40174,12 +40297,12 @@ _tmp_241_rule(Parser *p)
(name_var = _PyPegen_name_token(p)) // NAME
)
{
- D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME"));
+ D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME"));
_res = _PyPegen_dummy_name(p, _literal, name_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME"));
}
_res = NULL;
@@ -40188,9 +40311,9 @@ _tmp_241_rule(Parser *p)
return _res;
}
-// _loop0_242: fstring_format_spec
+// _loop0_244: fstring_format_spec
static asdl_seq *
-_loop0_242_rule(Parser *p)
+_loop0_244_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40216,7 +40339,7 @@ _loop0_242_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec"));
+ D(fprintf(stderr, "%*c> _loop0_244[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec"));
expr_ty fstring_format_spec_var;
while (
(fstring_format_spec_var = fstring_format_spec_rule(p)) // fstring_format_spec
@@ -40239,7 +40362,7 @@ _loop0_242_rule(Parser *p)
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_242[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_244[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_format_spec"));
}
asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
@@ -40256,9 +40379,9 @@ _loop0_242_rule(Parser *p)
return _seq;
}
-// _tmp_243: yield_expr | star_expressions
+// _tmp_245: yield_expr | star_expressions
static void *
-_tmp_243_rule(Parser *p)
+_tmp_245_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40275,18 +40398,18 @@ _tmp_243_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
expr_ty yield_expr_var;
if (
(yield_expr_var = yield_expr_rule(p)) // yield_expr
)
{
- D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
_res = yield_expr_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr"));
}
{ // star_expressions
@@ -40294,18 +40417,18 @@ _tmp_243_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
expr_ty star_expressions_var;
if (
(star_expressions_var = star_expressions_rule(p)) // star_expressions
)
{
- D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
_res = star_expressions_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions"));
}
_res = NULL;
@@ -40314,9 +40437,9 @@ _tmp_243_rule(Parser *p)
return _res;
}
-// _tmp_244: '!' NAME
+// _tmp_246: '!' NAME
static void *
-_tmp_244_rule(Parser *p)
+_tmp_246_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40333,7 +40456,7 @@ _tmp_244_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_244[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME"));
+ D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME"));
Token * _literal;
expr_ty name_var;
if (
@@ -40342,12 +40465,12 @@ _tmp_244_rule(Parser *p)
(name_var = _PyPegen_name_token(p)) // NAME
)
{
- D(fprintf(stderr, "%*c+ _tmp_244[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME"));
+ D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME"));
_res = _PyPegen_dummy_name(p, _literal, name_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_244[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME"));
}
_res = NULL;
@@ -40356,9 +40479,9 @@ _tmp_244_rule(Parser *p)
return _res;
}
-// _tmp_245: ':' | '}'
+// _tmp_247: ':' | '}'
static void *
-_tmp_245_rule(Parser *p)
+_tmp_247_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40375,18 +40498,18 @@ _tmp_245_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c> _tmp_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
)
{
- D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c+ _tmp_247[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_247[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'"));
}
{ // '}'
@@ -40394,18 +40517,18 @@ _tmp_245_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'"));
+ D(fprintf(stderr, "%*c> _tmp_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 26)) // token='}'
)
{
- D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'"));
+ D(fprintf(stderr, "%*c+ _tmp_247[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_247[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'"));
}
_res = NULL;
@@ -40414,9 +40537,9 @@ _tmp_245_rule(Parser *p)
return _res;
}
-// _tmp_246: star_targets '='
+// _tmp_248: star_targets '='
static void *
-_tmp_246_rule(Parser *p)
+_tmp_248_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40433,7 +40556,7 @@ _tmp_246_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
Token * _literal;
expr_ty z;
if (
@@ -40442,7 +40565,7 @@ _tmp_246_rule(Parser *p)
(_literal = _PyPegen_expect_token(p, 22)) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
_res = z;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -40452,7 +40575,7 @@ _tmp_246_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='"));
}
_res = NULL;
@@ -40461,9 +40584,9 @@ _tmp_246_rule(Parser *p)
return _res;
}
-// _tmp_247: '.' | '...'
+// _tmp_249: '.' | '...'
static void *
-_tmp_247_rule(Parser *p)
+_tmp_249_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40480,18 +40603,18 @@ _tmp_247_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
+ D(fprintf(stderr, "%*c> _tmp_249[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 23)) // token='.'
)
{
- D(fprintf(stderr, "%*c+ _tmp_247[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
+ D(fprintf(stderr, "%*c+ _tmp_249[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_247[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_249[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'"));
}
{ // '...'
@@ -40499,18 +40622,18 @@ _tmp_247_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
+ D(fprintf(stderr, "%*c> _tmp_249[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 52)) // token='...'
)
{
- D(fprintf(stderr, "%*c+ _tmp_247[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
+ D(fprintf(stderr, "%*c+ _tmp_249[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_247[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_249[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'"));
}
_res = NULL;
@@ -40519,9 +40642,9 @@ _tmp_247_rule(Parser *p)
return _res;
}
-// _tmp_248: '.' | '...'
+// _tmp_250: '.' | '...'
static void *
-_tmp_248_rule(Parser *p)
+_tmp_250_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40538,18 +40661,18 @@ _tmp_248_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
+ D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 23)) // token='.'
)
{
- D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
+ D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'"));
}
{ // '...'
@@ -40557,18 +40680,18 @@ _tmp_248_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
+ D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 52)) // token='...'
)
{
- D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
+ D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'"));
}
_res = NULL;
@@ -40577,9 +40700,9 @@ _tmp_248_rule(Parser *p)
return _res;
}
-// _tmp_249: '@' named_expression NEWLINE
+// _tmp_251: '@' named_expression NEWLINE
static void *
-_tmp_249_rule(Parser *p)
+_tmp_251_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40596,7 +40719,7 @@ _tmp_249_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_249[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
+ D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
Token * _literal;
expr_ty f;
Token * newline_var;
@@ -40608,7 +40731,7 @@ _tmp_249_rule(Parser *p)
(newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE'
)
{
- D(fprintf(stderr, "%*c+ _tmp_249[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
+ D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
_res = f;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -40618,7 +40741,7 @@ _tmp_249_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_249[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE"));
}
_res = NULL;
@@ -40627,9 +40750,9 @@ _tmp_249_rule(Parser *p)
return _res;
}
-// _tmp_250: ',' expression
+// _tmp_252: ',' expression
static void *
-_tmp_250_rule(Parser *p)
+_tmp_252_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40646,7 +40769,7 @@ _tmp_250_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression"));
+ D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression"));
Token * _literal;
expr_ty c;
if (
@@ -40655,7 +40778,7 @@ _tmp_250_rule(Parser *p)
(c = expression_rule(p)) // expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression"));
+ D(fprintf(stderr, "%*c+ _tmp_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -40665,7 +40788,7 @@ _tmp_250_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_252[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression"));
}
_res = NULL;
@@ -40674,9 +40797,9 @@ _tmp_250_rule(Parser *p)
return _res;
}
-// _tmp_251: ',' star_expression
+// _tmp_253: ',' star_expression
static void *
-_tmp_251_rule(Parser *p)
+_tmp_253_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40693,7 +40816,7 @@ _tmp_251_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
+ D(fprintf(stderr, "%*c> _tmp_253[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
Token * _literal;
expr_ty c;
if (
@@ -40702,7 +40825,7 @@ _tmp_251_rule(Parser *p)
(c = star_expression_rule(p)) // star_expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
+ D(fprintf(stderr, "%*c+ _tmp_253[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -40712,7 +40835,7 @@ _tmp_251_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_253[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression"));
}
_res = NULL;
@@ -40721,9 +40844,9 @@ _tmp_251_rule(Parser *p)
return _res;
}
-// _tmp_252: 'or' conjunction
+// _tmp_254: 'or' conjunction
static void *
-_tmp_252_rule(Parser *p)
+_tmp_254_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40740,7 +40863,7 @@ _tmp_252_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
+ D(fprintf(stderr, "%*c> _tmp_254[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
Token * _keyword;
expr_ty c;
if (
@@ -40749,7 +40872,7 @@ _tmp_252_rule(Parser *p)
(c = conjunction_rule(p)) // conjunction
)
{
- D(fprintf(stderr, "%*c+ _tmp_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
+ D(fprintf(stderr, "%*c+ _tmp_254[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -40759,7 +40882,7 @@ _tmp_252_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_252[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_254[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction"));
}
_res = NULL;
@@ -40768,9 +40891,9 @@ _tmp_252_rule(Parser *p)
return _res;
}
-// _tmp_253: 'and' inversion
+// _tmp_255: 'and' inversion
static void *
-_tmp_253_rule(Parser *p)
+_tmp_255_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40787,7 +40910,7 @@ _tmp_253_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_253[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
+ D(fprintf(stderr, "%*c> _tmp_255[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
Token * _keyword;
expr_ty c;
if (
@@ -40796,7 +40919,7 @@ _tmp_253_rule(Parser *p)
(c = inversion_rule(p)) // inversion
)
{
- D(fprintf(stderr, "%*c+ _tmp_253[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
+ D(fprintf(stderr, "%*c+ _tmp_255[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -40806,7 +40929,7 @@ _tmp_253_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_253[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion"));
}
_res = NULL;
@@ -40815,9 +40938,9 @@ _tmp_253_rule(Parser *p)
return _res;
}
-// _tmp_254: slice | starred_expression
+// _tmp_256: slice | starred_expression
static void *
-_tmp_254_rule(Parser *p)
+_tmp_256_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40834,18 +40957,18 @@ _tmp_254_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_254[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice"));
+ D(fprintf(stderr, "%*c> _tmp_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice"));
expr_ty slice_var;
if (
(slice_var = slice_rule(p)) // slice
)
{
- D(fprintf(stderr, "%*c+ _tmp_254[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice"));
+ D(fprintf(stderr, "%*c+ _tmp_256[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice"));
_res = slice_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_254[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_256[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slice"));
}
{ // starred_expression
@@ -40853,18 +40976,18 @@ _tmp_254_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_254[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression"));
+ D(fprintf(stderr, "%*c> _tmp_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression"));
expr_ty starred_expression_var;
if (
(starred_expression_var = starred_expression_rule(p)) // starred_expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_254[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression"));
+ D(fprintf(stderr, "%*c+ _tmp_256[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression"));
_res = starred_expression_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_254[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_256[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression"));
}
_res = NULL;
@@ -40873,9 +40996,9 @@ _tmp_254_rule(Parser *p)
return _res;
}
-// _tmp_255: fstring | string
+// _tmp_257: fstring | string
static void *
-_tmp_255_rule(Parser *p)
+_tmp_257_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40892,18 +41015,18 @@ _tmp_255_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_255[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring"));
+ D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring"));
expr_ty fstring_var;
if (
(fstring_var = fstring_rule(p)) // fstring
)
{
- D(fprintf(stderr, "%*c+ _tmp_255[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring"));
+ D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring"));
_res = fstring_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring"));
}
{ // string
@@ -40911,18 +41034,18 @@ _tmp_255_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_255[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "string"));
+ D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "string"));
expr_ty string_var;
if (
(string_var = string_rule(p)) // string
)
{
- D(fprintf(stderr, "%*c+ _tmp_255[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "string"));
+ D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "string"));
_res = string_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "string"));
}
_res = NULL;
@@ -40931,9 +41054,9 @@ _tmp_255_rule(Parser *p)
return _res;
}
-// _tmp_256: 'if' disjunction
+// _tmp_258: 'if' disjunction
static void *
-_tmp_256_rule(Parser *p)
+_tmp_258_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40950,7 +41073,7 @@ _tmp_256_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+ D(fprintf(stderr, "%*c> _tmp_258[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
Token * _keyword;
expr_ty z;
if (
@@ -40959,7 +41082,7 @@ _tmp_256_rule(Parser *p)
(z = disjunction_rule(p)) // disjunction
)
{
- D(fprintf(stderr, "%*c+ _tmp_256[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+ D(fprintf(stderr, "%*c+ _tmp_258[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
_res = z;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -40969,7 +41092,7 @@ _tmp_256_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_256[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_258[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction"));
}
_res = NULL;
@@ -40978,9 +41101,9 @@ _tmp_256_rule(Parser *p)
return _res;
}
-// _tmp_257: 'if' disjunction
+// _tmp_259: 'if' disjunction
static void *
-_tmp_257_rule(Parser *p)
+_tmp_259_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -40997,7 +41120,7 @@ _tmp_257_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+ D(fprintf(stderr, "%*c> _tmp_259[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
Token * _keyword;
expr_ty z;
if (
@@ -41006,7 +41129,7 @@ _tmp_257_rule(Parser *p)
(z = disjunction_rule(p)) // disjunction
)
{
- D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+ D(fprintf(stderr, "%*c+ _tmp_259[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
_res = z;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -41016,7 +41139,7 @@ _tmp_257_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_259[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction"));
}
_res = NULL;
@@ -41025,9 +41148,9 @@ _tmp_257_rule(Parser *p)
return _res;
}
-// _tmp_258: starred_expression | (assignment_expression | expression !':=') !'='
+// _tmp_260: starred_expression | (assignment_expression | expression !':=') !'='
static void *
-_tmp_258_rule(Parser *p)
+_tmp_260_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41044,18 +41167,18 @@ _tmp_258_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_258[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression"));
+ D(fprintf(stderr, "%*c> _tmp_260[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression"));
expr_ty starred_expression_var;
if (
(starred_expression_var = starred_expression_rule(p)) // starred_expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_258[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression"));
+ D(fprintf(stderr, "%*c+ _tmp_260[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression"));
_res = starred_expression_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_258[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_260[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression"));
}
{ // (assignment_expression | expression !':=') !'='
@@ -41063,20 +41186,20 @@ _tmp_258_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_258[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='"));
- void *_tmp_270_var;
+ D(fprintf(stderr, "%*c> _tmp_260[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='"));
+ void *_tmp_272_var;
if (
- (_tmp_270_var = _tmp_270_rule(p)) // assignment_expression | expression !':='
+ (_tmp_272_var = _tmp_272_rule(p)) // assignment_expression | expression !':='
&&
_PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_258[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='"));
- _res = _tmp_270_var;
+ D(fprintf(stderr, "%*c+ _tmp_260[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='"));
+ _res = _tmp_272_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_258[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_260[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='"));
}
_res = NULL;
@@ -41085,9 +41208,9 @@ _tmp_258_rule(Parser *p)
return _res;
}
-// _tmp_259: ',' star_target
+// _tmp_261: ',' star_target
static void *
-_tmp_259_rule(Parser *p)
+_tmp_261_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41104,7 +41227,7 @@ _tmp_259_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_259[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+ D(fprintf(stderr, "%*c> _tmp_261[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
Token * _literal;
expr_ty c;
if (
@@ -41113,7 +41236,7 @@ _tmp_259_rule(Parser *p)
(c = star_target_rule(p)) // star_target
)
{
- D(fprintf(stderr, "%*c+ _tmp_259[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+ D(fprintf(stderr, "%*c+ _tmp_261[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -41123,7 +41246,7 @@ _tmp_259_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_259[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_261[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target"));
}
_res = NULL;
@@ -41132,9 +41255,9 @@ _tmp_259_rule(Parser *p)
return _res;
}
-// _tmp_260: ',' star_target
+// _tmp_262: ',' star_target
static void *
-_tmp_260_rule(Parser *p)
+_tmp_262_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41151,7 +41274,7 @@ _tmp_260_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_260[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+ D(fprintf(stderr, "%*c> _tmp_262[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
Token * _literal;
expr_ty c;
if (
@@ -41160,7 +41283,7 @@ _tmp_260_rule(Parser *p)
(c = star_target_rule(p)) // star_target
)
{
- D(fprintf(stderr, "%*c+ _tmp_260[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+ D(fprintf(stderr, "%*c+ _tmp_262[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -41170,7 +41293,7 @@ _tmp_260_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_260[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_262[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target"));
}
_res = NULL;
@@ -41179,9 +41302,9 @@ _tmp_260_rule(Parser *p)
return _res;
}
-// _tmp_261: star_targets '='
+// _tmp_263: star_targets '='
static void *
-_tmp_261_rule(Parser *p)
+_tmp_263_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41198,7 +41321,7 @@ _tmp_261_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_261[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c> _tmp_263[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
Token * _literal;
expr_ty star_targets_var;
if (
@@ -41207,12 +41330,12 @@ _tmp_261_rule(Parser *p)
(_literal = _PyPegen_expect_token(p, 22)) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_261[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c+ _tmp_263[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
_res = _PyPegen_dummy_name(p, star_targets_var, _literal);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_261[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_263[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='"));
}
_res = NULL;
@@ -41221,9 +41344,9 @@ _tmp_261_rule(Parser *p)
return _res;
}
-// _tmp_262: star_targets '='
+// _tmp_264: star_targets '='
static void *
-_tmp_262_rule(Parser *p)
+_tmp_264_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41240,7 +41363,7 @@ _tmp_262_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_262[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c> _tmp_264[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
Token * _literal;
expr_ty star_targets_var;
if (
@@ -41249,12 +41372,12 @@ _tmp_262_rule(Parser *p)
(_literal = _PyPegen_expect_token(p, 22)) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_262[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c+ _tmp_264[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
_res = _PyPegen_dummy_name(p, star_targets_var, _literal);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_262[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_264[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='"));
}
_res = NULL;
@@ -41263,9 +41386,9 @@ _tmp_262_rule(Parser *p)
return _res;
}
-// _tmp_263: ')' | '**'
+// _tmp_265: ')' | '**'
static void *
-_tmp_263_rule(Parser *p)
+_tmp_265_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41282,18 +41405,18 @@ _tmp_263_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_263[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
+ D(fprintf(stderr, "%*c> _tmp_265[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 8)) // token=')'
)
{
- D(fprintf(stderr, "%*c+ _tmp_263[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
+ D(fprintf(stderr, "%*c+ _tmp_265[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_263[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_265[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'"));
}
{ // '**'
@@ -41301,18 +41424,18 @@ _tmp_263_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_263[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
+ D(fprintf(stderr, "%*c> _tmp_265[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 35)) // token='**'
)
{
- D(fprintf(stderr, "%*c+ _tmp_263[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
+ D(fprintf(stderr, "%*c+ _tmp_265[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_263[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_265[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'"));
}
_res = NULL;
@@ -41321,9 +41444,9 @@ _tmp_263_rule(Parser *p)
return _res;
}
-// _tmp_264: ':' | '**'
+// _tmp_266: ':' | '**'
static void *
-_tmp_264_rule(Parser *p)
+_tmp_266_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41340,18 +41463,18 @@ _tmp_264_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_264[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c> _tmp_266[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
)
{
- D(fprintf(stderr, "%*c+ _tmp_264[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c+ _tmp_266[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_264[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_266[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'"));
}
{ // '**'
@@ -41359,18 +41482,18 @@ _tmp_264_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_264[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
+ D(fprintf(stderr, "%*c> _tmp_266[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 35)) // token='**'
)
{
- D(fprintf(stderr, "%*c+ _tmp_264[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
+ D(fprintf(stderr, "%*c+ _tmp_266[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_264[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_266[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'"));
}
_res = NULL;
@@ -41379,9 +41502,9 @@ _tmp_264_rule(Parser *p)
return _res;
}
-// _tmp_265: expression ['as' star_target]
+// _tmp_267: expression ['as' star_target]
static void *
-_tmp_265_rule(Parser *p)
+_tmp_267_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41398,22 +41521,22 @@ _tmp_265_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_265[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]"));
+ D(fprintf(stderr, "%*c> _tmp_267[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]"));
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
expr_ty expression_var;
if (
(expression_var = expression_rule(p)) // expression
&&
- (_opt_var = _tmp_271_rule(p), !p->error_indicator) // ['as' star_target]
+ (_opt_var = _tmp_273_rule(p), !p->error_indicator) // ['as' star_target]
)
{
- D(fprintf(stderr, "%*c+ _tmp_265[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]"));
+ D(fprintf(stderr, "%*c+ _tmp_267[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]"));
_res = _PyPegen_dummy_name(p, expression_var, _opt_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_265[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_267[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]"));
}
_res = NULL;
@@ -41422,9 +41545,9 @@ _tmp_265_rule(Parser *p)
return _res;
}
-// _tmp_266: expressions ['as' star_target]
+// _tmp_268: expressions ['as' star_target]
static void *
-_tmp_266_rule(Parser *p)
+_tmp_268_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41441,22 +41564,22 @@ _tmp_266_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_266[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]"));
+ D(fprintf(stderr, "%*c> _tmp_268[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]"));
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
expr_ty expressions_var;
if (
(expressions_var = expressions_rule(p)) // expressions
&&
- (_opt_var = _tmp_272_rule(p), !p->error_indicator) // ['as' star_target]
+ (_opt_var = _tmp_274_rule(p), !p->error_indicator) // ['as' star_target]
)
{
- D(fprintf(stderr, "%*c+ _tmp_266[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]"));
+ D(fprintf(stderr, "%*c+ _tmp_268[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]"));
_res = _PyPegen_dummy_name(p, expressions_var, _opt_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_266[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_268[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]"));
}
_res = NULL;
@@ -41465,9 +41588,9 @@ _tmp_266_rule(Parser *p)
return _res;
}
-// _tmp_267: expression ['as' star_target]
+// _tmp_269: expression ['as' star_target]
static void *
-_tmp_267_rule(Parser *p)
+_tmp_269_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41484,22 +41607,22 @@ _tmp_267_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_267[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]"));
+ D(fprintf(stderr, "%*c> _tmp_269[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]"));
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
expr_ty expression_var;
if (
(expression_var = expression_rule(p)) // expression
&&
- (_opt_var = _tmp_273_rule(p), !p->error_indicator) // ['as' star_target]
+ (_opt_var = _tmp_275_rule(p), !p->error_indicator) // ['as' star_target]
)
{
- D(fprintf(stderr, "%*c+ _tmp_267[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]"));
+ D(fprintf(stderr, "%*c+ _tmp_269[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]"));
_res = _PyPegen_dummy_name(p, expression_var, _opt_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_267[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_269[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]"));
}
_res = NULL;
@@ -41508,9 +41631,9 @@ _tmp_267_rule(Parser *p)
return _res;
}
-// _tmp_268: expressions ['as' star_target]
+// _tmp_270: expressions ['as' star_target]
static void *
-_tmp_268_rule(Parser *p)
+_tmp_270_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41527,22 +41650,22 @@ _tmp_268_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_268[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]"));
+ D(fprintf(stderr, "%*c> _tmp_270[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]"));
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
expr_ty expressions_var;
if (
(expressions_var = expressions_rule(p)) // expressions
&&
- (_opt_var = _tmp_274_rule(p), !p->error_indicator) // ['as' star_target]
+ (_opt_var = _tmp_276_rule(p), !p->error_indicator) // ['as' star_target]
)
{
- D(fprintf(stderr, "%*c+ _tmp_268[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]"));
+ D(fprintf(stderr, "%*c+ _tmp_270[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]"));
_res = _PyPegen_dummy_name(p, expressions_var, _opt_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_268[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_270[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]"));
}
_res = NULL;
@@ -41551,9 +41674,9 @@ _tmp_268_rule(Parser *p)
return _res;
}
-// _tmp_269: 'as' NAME
+// _tmp_271: 'as' NAME
static void *
-_tmp_269_rule(Parser *p)
+_tmp_271_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41570,7 +41693,7 @@ _tmp_269_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_269[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ D(fprintf(stderr, "%*c> _tmp_271[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
Token * _keyword;
expr_ty name_var;
if (
@@ -41579,12 +41702,12 @@ _tmp_269_rule(Parser *p)
(name_var = _PyPegen_name_token(p)) // NAME
)
{
- D(fprintf(stderr, "%*c+ _tmp_269[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
+ D(fprintf(stderr, "%*c+ _tmp_271[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME"));
_res = _PyPegen_dummy_name(p, _keyword, name_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_269[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_271[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME"));
}
_res = NULL;
@@ -41593,9 +41716,9 @@ _tmp_269_rule(Parser *p)
return _res;
}
-// _tmp_270: assignment_expression | expression !':='
+// _tmp_272: assignment_expression | expression !':='
static void *
-_tmp_270_rule(Parser *p)
+_tmp_272_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41612,18 +41735,18 @@ _tmp_270_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_270[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression"));
+ D(fprintf(stderr, "%*c> _tmp_272[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression"));
expr_ty assignment_expression_var;
if (
(assignment_expression_var = assignment_expression_rule(p)) // assignment_expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_270[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression"));
+ D(fprintf(stderr, "%*c+ _tmp_272[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression"));
_res = assignment_expression_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_270[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_272[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression"));
}
{ // expression !':='
@@ -41631,7 +41754,7 @@ _tmp_270_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_270[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='"));
+ D(fprintf(stderr, "%*c> _tmp_272[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='"));
expr_ty expression_var;
if (
(expression_var = expression_rule(p)) // expression
@@ -41639,12 +41762,12 @@ _tmp_270_rule(Parser *p)
_PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':='
)
{
- D(fprintf(stderr, "%*c+ _tmp_270[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='"));
+ D(fprintf(stderr, "%*c+ _tmp_272[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='"));
_res = expression_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_270[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_272[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='"));
}
_res = NULL;
@@ -41653,9 +41776,9 @@ _tmp_270_rule(Parser *p)
return _res;
}
-// _tmp_271: 'as' star_target
+// _tmp_273: 'as' star_target
static void *
-_tmp_271_rule(Parser *p)
+_tmp_273_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41672,7 +41795,7 @@ _tmp_271_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_271[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
+ D(fprintf(stderr, "%*c> _tmp_273[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
Token * _keyword;
expr_ty star_target_var;
if (
@@ -41681,12 +41804,12 @@ _tmp_271_rule(Parser *p)
(star_target_var = star_target_rule(p)) // star_target
)
{
- D(fprintf(stderr, "%*c+ _tmp_271[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
+ D(fprintf(stderr, "%*c+ _tmp_273[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
_res = _PyPegen_dummy_name(p, _keyword, star_target_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_271[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_273[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target"));
}
_res = NULL;
@@ -41695,9 +41818,9 @@ _tmp_271_rule(Parser *p)
return _res;
}
-// _tmp_272: 'as' star_target
+// _tmp_274: 'as' star_target
static void *
-_tmp_272_rule(Parser *p)
+_tmp_274_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41714,7 +41837,7 @@ _tmp_272_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_272[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
+ D(fprintf(stderr, "%*c> _tmp_274[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
Token * _keyword;
expr_ty star_target_var;
if (
@@ -41723,12 +41846,12 @@ _tmp_272_rule(Parser *p)
(star_target_var = star_target_rule(p)) // star_target
)
{
- D(fprintf(stderr, "%*c+ _tmp_272[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
+ D(fprintf(stderr, "%*c+ _tmp_274[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
_res = _PyPegen_dummy_name(p, _keyword, star_target_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_272[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_274[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target"));
}
_res = NULL;
@@ -41737,9 +41860,9 @@ _tmp_272_rule(Parser *p)
return _res;
}
-// _tmp_273: 'as' star_target
+// _tmp_275: 'as' star_target
static void *
-_tmp_273_rule(Parser *p)
+_tmp_275_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41756,7 +41879,7 @@ _tmp_273_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_273[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
+ D(fprintf(stderr, "%*c> _tmp_275[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
Token * _keyword;
expr_ty star_target_var;
if (
@@ -41765,12 +41888,12 @@ _tmp_273_rule(Parser *p)
(star_target_var = star_target_rule(p)) // star_target
)
{
- D(fprintf(stderr, "%*c+ _tmp_273[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
+ D(fprintf(stderr, "%*c+ _tmp_275[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
_res = _PyPegen_dummy_name(p, _keyword, star_target_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_273[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_275[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target"));
}
_res = NULL;
@@ -41779,9 +41902,9 @@ _tmp_273_rule(Parser *p)
return _res;
}
-// _tmp_274: 'as' star_target
+// _tmp_276: 'as' star_target
static void *
-_tmp_274_rule(Parser *p)
+_tmp_276_rule(Parser *p)
{
if (p->level++ == MAXSTACK) {
p->error_indicator = 1;
@@ -41798,7 +41921,7 @@ _tmp_274_rule(Parser *p)
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_274[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
+ D(fprintf(stderr, "%*c> _tmp_276[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
Token * _keyword;
expr_ty star_target_var;
if (
@@ -41807,12 +41930,12 @@ _tmp_274_rule(Parser *p)
(star_target_var = star_target_rule(p)) // star_target
)
{
- D(fprintf(stderr, "%*c+ _tmp_274[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
+ D(fprintf(stderr, "%*c+ _tmp_276[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target"));
_res = _PyPegen_dummy_name(p, _keyword, star_target_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_274[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_276[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target"));
}
_res = NULL;
diff --git a/Parser/pegen.c b/Parser/pegen.c
index b9894dd0acc546..885d423fca66a9 100644
--- a/Parser/pegen.c
+++ b/Parser/pegen.c
@@ -465,7 +465,6 @@ _PyPegen_new_identifier(Parser *p, const char *n)
identifier; if so, normalize to NFKC. */
if (!PyUnicode_IS_ASCII(id))
{
- PyObject *id2;
if (!init_normalization(p))
{
Py_DECREF(id);
@@ -478,12 +477,13 @@ _PyPegen_new_identifier(Parser *p, const char *n)
goto error;
}
PyObject *args[2] = {form, id};
- id2 = _PyObject_FastCall(p->normalize, args, 2);
+ PyObject *id2 = PyObject_Vectorcall(p->normalize, args, 2, NULL);
Py_DECREF(id);
Py_DECREF(form);
if (!id2) {
goto error;
}
+
if (!PyUnicode_Check(id2))
{
PyErr_Format(PyExc_TypeError,
diff --git a/Parser/pegen.h b/Parser/pegen.h
index fe13d10e6b83e3..5f29285951e812 100644
--- a/Parser/pegen.h
+++ b/Parser/pegen.h
@@ -1,7 +1,6 @@
#ifndef PEGEN_H
#define PEGEN_H
-#define PY_SSIZE_T_CLEAN
#include
#include
#include
diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c
index af529057f50e70..e543d40ccd8ab7 100644
--- a/Parser/pegen_errors.c
+++ b/Parser/pegen_errors.c
@@ -1,6 +1,7 @@
#include
#include
+#include "pycore_pyerrors.h" // _PyErr_ProgramDecodedTextObject()
#include "tokenizer.h"
#include "pegen.h"
diff --git a/Parser/string_parser.c b/Parser/string_parser.c
index d4ce33850f7c58..bc1f99d607ae4d 100644
--- a/Parser/string_parser.c
+++ b/Parser/string_parser.c
@@ -1,6 +1,7 @@
#include
#include
+#include "pycore_unicodeobject.h" // _PyUnicode_DecodeUnicodeEscapeInternal()
#include "tokenizer.h"
#include "pegen.h"
@@ -12,6 +13,11 @@ static int
warn_invalid_escape_sequence(Parser *p, const char *first_invalid_escape, Token *t)
{
unsigned char c = *first_invalid_escape;
+ if ((t->type == FSTRING_MIDDLE || t->type == FSTRING_END) && (c == '{' || c == '}')) { // in this case the tokenizer has already emitted a warning,
+ // see tokenizer.c:warn_invalid_escape_sequence
+ return 0;
+ }
+
int octal = ('4' <= c && c <= '7');
PyObject *msg =
octal
@@ -31,7 +37,7 @@ warn_invalid_escape_sequence(Parser *p, const char *first_invalid_escape, Token
if (PyErr_WarnExplicitObject(category, msg, p->tok->filename,
t->lineno, NULL, NULL) < 0) {
if (PyErr_ExceptionMatches(category)) {
- /* Replace the DeprecationWarning exception with a SyntaxError
+ /* Replace the Syntax/DeprecationWarning exception with a SyntaxError
to get a more accurate error report */
PyErr_Clear();
diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c
index bf6bfd92d3a47d..f19198600fa018 100644
--- a/Parser/tokenizer.c
+++ b/Parser/tokenizer.c
@@ -1,7 +1,6 @@
/* Tokenizer implementation */
-#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs()
@@ -1039,9 +1038,6 @@ tok_readline_raw(struct tok_state *tok)
if (line == NULL) {
return 1;
}
- if (tok->tok_mode_stack_index && !update_fstring_expr(tok, 0)) {
- return 0;
- }
if (tok->fp_interactive &&
tok_concatenate_interactive_new_line(tok, line) == -1) {
return 0;
@@ -1106,11 +1102,7 @@ tok_readline_string(struct tok_state* tok) {
tok->inp += buflen;
*tok->inp = '\0';
- if (tok->start == NULL) {
- tok->buf = tok->cur;
- }
tok->line_start = tok->cur;
-
Py_DECREF(line);
return 1;
error:
@@ -1274,6 +1266,10 @@ tok_underflow_file(struct tok_state *tok) {
tok->implicit_newline = 1;
}
+ if (tok->tok_mode_stack_index && !update_fstring_expr(tok, 0)) {
+ return 0;
+ }
+
ADVANCE_LINENO();
if (tok->decoding_state != STATE_NORMAL) {
if (tok->lineno > 2) {
@@ -1318,6 +1314,10 @@ tok_underflow_readline(struct tok_state* tok) {
tok->implicit_newline = 1;
}
+ if (tok->tok_mode_stack_index && !update_fstring_expr(tok, 0)) {
+ return 0;
+ }
+
ADVANCE_LINENO();
/* The default encoding is UTF-8, so make sure we don't have any
non-UTF-8 sequences in it. */
@@ -1558,12 +1558,12 @@ warn_invalid_escape_sequence(struct tok_state *tok, int first_invalid_escape_cha
return -1;
}
- if (PyErr_WarnExplicitObject(PyExc_DeprecationWarning, msg, tok->filename,
+ if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, tok->filename,
tok->lineno, NULL, NULL) < 0) {
Py_DECREF(msg);
- if (PyErr_ExceptionMatches(PyExc_DeprecationWarning)) {
- /* Replace the DeprecationWarning exception with a SyntaxError
+ if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
+ /* Replace the SyntaxWarning exception with a SyntaxError
to get a more accurate error report */
PyErr_Clear();
return syntaxerror(tok, "invalid escape sequence '\\%c'", (char) first_invalid_escape_char);
diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h
index 16e919a8931edd..cb44845c1d306e 100644
--- a/Parser/tokenizer.h
+++ b/Parser/tokenizer.h
@@ -68,7 +68,7 @@ typedef struct _tokenizer_mode {
struct tok_state {
/* Input state; buf <= cur <= inp <= end */
/* NB an entire line is held in the buffer */
- char *buf; /* Input buffer, or NULL; malloc'ed if fp != NULL */
+ char *buf; /* Input buffer, or NULL; malloc'ed if fp != NULL or readline != NULL */
char *cur; /* Next character in buffer */
char *inp; /* End of data in buffer */
int fp_interactive; /* If the file descriptor is interactive */
diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h
index 51d65533cbda9f..9058327e846dc3 100644
--- a/Programs/test_frozenmain.h
+++ b/Programs/test_frozenmain.h
@@ -9,8 +9,8 @@ unsigned char M_test_frozenmain[] = {
1,0,2,0,101,1,106,8,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,171,0,0,0,0,0,
0,0,100,4,25,0,0,0,90,5,100,5,68,0,93,20,
- 0,0,90,6,2,0,101,2,100,6,101,6,155,0,100,7,
- 101,5,101,6,25,0,0,0,155,0,157,4,171,1,0,0,
+ 0,0,90,6,2,0,101,2,100,6,101,6,40,0,100,7,
+ 101,5,101,6,25,0,0,0,40,0,157,4,171,1,0,0,
0,0,0,0,1,0,140,22,0,0,4,0,121,1,41,8,
233,0,0,0,0,78,122,18,70,114,111,122,101,110,32,72,
101,108,108,111,32,87,111,114,108,100,122,8,115,121,115,46,
diff --git a/Python/Python-ast.c b/Python/Python-ast.c
index 84bce59e271471..55a1370fbd038b 100644
--- a/Python/Python-ast.c
+++ b/Python/Python-ast.c
@@ -839,7 +839,7 @@ ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
Py_ssize_t i, numfields = 0;
int res = -1;
PyObject *key, *value, *fields;
- if (_PyObject_LookupAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) {
+ if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) {
goto cleanup;
}
if (fields) {
@@ -913,7 +913,7 @@ ast_type_reduce(PyObject *self, PyObject *unused)
}
PyObject *dict;
- if (_PyObject_LookupAttr(self, state->__dict__, &dict) < 0) {
+ if (PyObject_GetOptionalAttr(self, state->__dict__, &dict) < 0) {
return NULL;
}
if (dict) {
@@ -1902,12 +1902,6 @@ init_types(struct ast_state *state)
if (!state->type_param_type) return 0;
if (!add_attributes(state, state->type_param_type, type_param_attributes,
4)) return 0;
- if (PyObject_SetAttr(state->type_param_type, state->end_lineno, Py_None) ==
- -1)
- return 0;
- if (PyObject_SetAttr(state->type_param_type, state->end_col_offset,
- Py_None) == -1)
- return 0;
state->TypeVar_type = make_type(state, "TypeVar", state->type_param_type,
TypeVar_fields, 2,
"TypeVar(identifier name, expr? bound)");
@@ -5756,7 +5750,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena)
asdl_stmt_seq* body;
asdl_type_ignore_seq* type_ignores;
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -5794,7 +5788,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_ignores, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_ignores, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -5844,7 +5838,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena)
if (isinstance) {
asdl_stmt_seq* body;
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -5894,7 +5888,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena)
if (isinstance) {
expr_ty body;
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -5924,7 +5918,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena)
asdl_expr_seq* argtypes;
expr_ty returns;
- if (_PyObject_LookupAttr(obj, state->argtypes, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->argtypes, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -5962,7 +5956,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->returns, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->returns, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6007,7 +6001,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
*out = NULL;
return 0;
}
- if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6024,7 +6018,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6041,7 +6035,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -6058,7 +6052,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -6089,7 +6083,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
string type_comment;
asdl_type_param_seq* type_params;
- if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6106,7 +6100,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->args, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6123,7 +6117,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6161,7 +6155,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->decorator_list, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->decorator_list, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6199,7 +6193,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->returns, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->returns, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -6216,7 +6210,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -6233,7 +6227,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_params, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6292,7 +6286,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
string type_comment;
asdl_type_param_seq* type_params;
- if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6309,7 +6303,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->args, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6326,7 +6320,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6364,7 +6358,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->decorator_list, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->decorator_list, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6402,7 +6396,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->returns, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->returns, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -6419,7 +6413,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -6436,7 +6430,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_params, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6494,7 +6488,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
asdl_expr_seq* decorator_list;
asdl_type_param_seq* type_params;
- if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6511,7 +6505,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->bases, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->bases, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6549,7 +6543,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->keywords, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->keywords, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6587,7 +6581,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6625,7 +6619,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->decorator_list, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->decorator_list, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6663,7 +6657,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_params, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6715,7 +6709,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (isinstance) {
expr_ty value;
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -6745,7 +6739,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (isinstance) {
asdl_expr_seq* targets;
- if (_PyObject_LookupAttr(obj, state->targets, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->targets, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6798,7 +6792,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
expr_ty value;
string type_comment;
- if (_PyObject_LookupAttr(obj, state->targets, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->targets, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6836,7 +6830,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6853,7 +6847,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -6885,7 +6879,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
asdl_type_param_seq* type_params;
expr_ty value;
- if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6902,7 +6896,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_params, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6940,7 +6934,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6972,7 +6966,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
operator_ty op;
expr_ty value;
- if (_PyObject_LookupAttr(obj, state->target, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->target, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -6989,7 +6983,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->op, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->op, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7006,7 +7000,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7039,7 +7033,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
expr_ty value;
int simple;
- if (_PyObject_LookupAttr(obj, state->target, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->target, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7056,7 +7050,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->annotation, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->annotation, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7073,7 +7067,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -7090,7 +7084,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->simple, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->simple, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7124,7 +7118,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
asdl_stmt_seq* orelse;
string type_comment;
- if (_PyObject_LookupAttr(obj, state->target, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->target, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7141,7 +7135,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->iter, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->iter, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7158,7 +7152,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7196,7 +7190,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7234,7 +7228,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -7268,7 +7262,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
asdl_stmt_seq* orelse;
string type_comment;
- if (_PyObject_LookupAttr(obj, state->target, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->target, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7285,7 +7279,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->iter, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->iter, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7302,7 +7296,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7340,7 +7334,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7378,7 +7372,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -7411,7 +7405,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
asdl_stmt_seq* body;
asdl_stmt_seq* orelse;
- if (_PyObject_LookupAttr(obj, state->test, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->test, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7428,7 +7422,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7466,7 +7460,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7519,7 +7513,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
asdl_stmt_seq* body;
asdl_stmt_seq* orelse;
- if (_PyObject_LookupAttr(obj, state->test, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->test, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7536,7 +7530,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7574,7 +7568,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7627,7 +7621,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
asdl_stmt_seq* body;
string type_comment;
- if (_PyObject_LookupAttr(obj, state->items, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->items, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7665,7 +7659,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7703,7 +7697,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -7735,7 +7729,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
asdl_stmt_seq* body;
string type_comment;
- if (_PyObject_LookupAttr(obj, state->items, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->items, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7773,7 +7767,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7811,7 +7805,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -7842,7 +7836,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
expr_ty subject;
asdl_match_case_seq* cases;
- if (_PyObject_LookupAttr(obj, state->subject, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->subject, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7859,7 +7853,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->cases, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->cases, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7911,7 +7905,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
expr_ty exc;
expr_ty cause;
- if (_PyObject_LookupAttr(obj, state->exc, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->exc, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -7928,7 +7922,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->cause, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->cause, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -7961,7 +7955,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
asdl_stmt_seq* orelse;
asdl_stmt_seq* finalbody;
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -7999,7 +7993,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->handlers, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->handlers, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8037,7 +8031,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8075,7 +8069,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->finalbody, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->finalbody, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8129,7 +8123,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
asdl_stmt_seq* orelse;
asdl_stmt_seq* finalbody;
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8167,7 +8161,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->handlers, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->handlers, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8205,7 +8199,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8243,7 +8237,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->finalbody, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->finalbody, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8295,7 +8289,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
expr_ty test;
expr_ty msg;
- if (_PyObject_LookupAttr(obj, state->test, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->test, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8312,7 +8306,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->msg, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->msg, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -8342,7 +8336,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (isinstance) {
asdl_alias_seq* names;
- if (_PyObject_LookupAttr(obj, state->names, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->names, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8395,7 +8389,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
asdl_alias_seq* names;
int level;
- if (_PyObject_LookupAttr(obj, state->module, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->module, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -8412,7 +8406,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->names, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->names, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8450,7 +8444,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->level, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->level, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -8480,7 +8474,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (isinstance) {
asdl_identifier_seq* names;
- if (_PyObject_LookupAttr(obj, state->names, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->names, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8531,7 +8525,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (isinstance) {
asdl_identifier_seq* names;
- if (_PyObject_LookupAttr(obj, state->names, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->names, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8582,7 +8576,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (isinstance) {
expr_ty value;
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8664,7 +8658,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
*out = NULL;
return 0;
}
- if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8681,7 +8675,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8698,7 +8692,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -8715,7 +8709,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -8741,7 +8735,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
boolop_ty op;
asdl_expr_seq* values;
- if (_PyObject_LookupAttr(obj, state->op, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->op, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8758,7 +8752,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->values, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->values, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8810,7 +8804,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
expr_ty target;
expr_ty value;
- if (_PyObject_LookupAttr(obj, state->target, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->target, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8827,7 +8821,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8859,7 +8853,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
operator_ty op;
expr_ty right;
- if (_PyObject_LookupAttr(obj, state->left, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->left, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8876,7 +8870,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->op, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->op, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8893,7 +8887,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->right, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->right, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8924,7 +8918,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
unaryop_ty op;
expr_ty operand;
- if (_PyObject_LookupAttr(obj, state->op, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->op, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8941,7 +8935,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->operand, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->operand, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8972,7 +8966,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
arguments_ty args;
expr_ty body;
- if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->args, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -8989,7 +8983,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9021,7 +9015,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
expr_ty body;
expr_ty orelse;
- if (_PyObject_LookupAttr(obj, state->test, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->test, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9038,7 +9032,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9055,7 +9049,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->orelse, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9086,7 +9080,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
asdl_expr_seq* keys;
asdl_expr_seq* values;
- if (_PyObject_LookupAttr(obj, state->keys, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->keys, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9124,7 +9118,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->values, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->values, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9175,7 +9169,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (isinstance) {
asdl_expr_seq* elts;
- if (_PyObject_LookupAttr(obj, state->elts, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->elts, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9227,7 +9221,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
expr_ty elt;
asdl_comprehension_seq* generators;
- if (_PyObject_LookupAttr(obj, state->elt, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->elt, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9244,7 +9238,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->generators, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->generators, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9296,7 +9290,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
expr_ty elt;
asdl_comprehension_seq* generators;
- if (_PyObject_LookupAttr(obj, state->elt, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->elt, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9313,7 +9307,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->generators, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->generators, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9366,7 +9360,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
expr_ty value;
asdl_comprehension_seq* generators;
- if (_PyObject_LookupAttr(obj, state->key, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->key, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9383,7 +9377,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9400,7 +9394,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->generators, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->generators, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9452,7 +9446,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
expr_ty elt;
asdl_comprehension_seq* generators;
- if (_PyObject_LookupAttr(obj, state->elt, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->elt, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9469,7 +9463,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->generators, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->generators, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9520,7 +9514,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (isinstance) {
expr_ty value;
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9550,7 +9544,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (isinstance) {
expr_ty value;
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -9580,7 +9574,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (isinstance) {
expr_ty value;
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9612,7 +9606,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
asdl_int_seq* ops;
asdl_expr_seq* comparators;
- if (_PyObject_LookupAttr(obj, state->left, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->left, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9629,7 +9623,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->ops, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->ops, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9667,7 +9661,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->comparators, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->comparators, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9720,7 +9714,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
asdl_expr_seq* args;
asdl_keyword_seq* keywords;
- if (_PyObject_LookupAttr(obj, state->func, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->func, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9737,7 +9731,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->args, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9775,7 +9769,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->keywords, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->keywords, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9828,7 +9822,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
int conversion;
expr_ty format_spec;
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9845,7 +9839,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->conversion, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->conversion, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9862,7 +9856,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->format_spec, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->format_spec, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -9893,7 +9887,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (isinstance) {
asdl_expr_seq* values;
- if (_PyObject_LookupAttr(obj, state->values, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->values, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9945,7 +9939,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
constant value;
string kind;
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -9962,7 +9956,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->kind, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->kind, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -9994,7 +9988,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
identifier attr;
expr_context_ty ctx;
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10011,7 +10005,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->attr, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->attr, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10028,7 +10022,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->ctx, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->ctx, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10060,7 +10054,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
expr_ty slice;
expr_context_ty ctx;
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10077,7 +10071,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->slice, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->slice, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10094,7 +10088,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->ctx, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->ctx, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10125,7 +10119,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
expr_ty value;
expr_context_ty ctx;
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10142,7 +10136,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->ctx, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->ctx, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10173,7 +10167,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
identifier id;
expr_context_ty ctx;
- if (_PyObject_LookupAttr(obj, state->id, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->id, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10190,7 +10184,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->ctx, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->ctx, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10221,7 +10215,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
asdl_expr_seq* elts;
expr_context_ty ctx;
- if (_PyObject_LookupAttr(obj, state->elts, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->elts, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10259,7 +10253,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->ctx, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->ctx, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10290,7 +10284,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
asdl_expr_seq* elts;
expr_context_ty ctx;
- if (_PyObject_LookupAttr(obj, state->elts, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->elts, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10328,7 +10322,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->ctx, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->ctx, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10360,7 +10354,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
expr_ty upper;
expr_ty step;
- if (_PyObject_LookupAttr(obj, state->lower, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->lower, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -10377,7 +10371,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->upper, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->upper, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -10394,7 +10388,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->step, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->step, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -10744,7 +10738,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty*
asdl_expr_seq* ifs;
int is_async;
- if (_PyObject_LookupAttr(obj, state->target, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->target, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10761,7 +10755,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->iter, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->iter, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10778,7 +10772,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->ifs, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->ifs, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10816,7 +10810,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty*
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->is_async, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->is_async, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10834,6 +10828,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty*
Py_CLEAR(tmp);
}
*out = _PyAST_comprehension(target, iter, ifs, is_async, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -10857,7 +10852,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty*
*out = NULL;
return 0;
}
- if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10874,7 +10869,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -10891,7 +10886,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -10908,7 +10903,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -10935,7 +10930,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty*
identifier name;
asdl_stmt_seq* body;
- if (_PyObject_LookupAttr(obj, state->type, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -10952,7 +10947,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -10969,7 +10964,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11032,7 +11027,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out,
arg_ty kwarg;
asdl_expr_seq* defaults;
- if (_PyObject_LookupAttr(obj, state->posonlyargs, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->posonlyargs, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11070,7 +11065,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out,
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->args, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11108,7 +11103,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out,
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->vararg, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->vararg, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11125,7 +11120,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->kwonlyargs, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->kwonlyargs, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11163,7 +11158,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out,
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->kw_defaults, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->kw_defaults, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11201,7 +11196,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out,
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->kwarg, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->kwarg, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11218,7 +11213,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->defaults, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->defaults, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11258,6 +11253,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out,
}
*out = _PyAST_arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults,
kwarg, defaults, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -11276,7 +11272,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena)
int end_lineno;
int end_col_offset;
- if (_PyObject_LookupAttr(obj, state->arg, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->arg, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11293,7 +11289,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->annotation, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->annotation, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11310,7 +11306,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->type_comment, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11327,7 +11323,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11344,7 +11340,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11361,7 +11357,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11378,7 +11374,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11397,6 +11393,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena)
}
*out = _PyAST_arg(arg, annotation, type_comment, lineno, col_offset,
end_lineno, end_col_offset, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -11415,7 +11412,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out,
int end_lineno;
int end_col_offset;
- if (_PyObject_LookupAttr(obj, state->arg, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->arg, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11432,7 +11429,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11449,7 +11446,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11466,7 +11463,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11483,7 +11480,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11500,7 +11497,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11519,6 +11516,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out,
}
*out = _PyAST_keyword(arg, value, lineno, col_offset, end_lineno,
end_col_offset, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -11537,7 +11535,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena*
int end_lineno;
int end_col_offset;
- if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11554,7 +11552,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->asname, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->asname, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11571,7 +11569,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11588,7 +11586,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11605,7 +11603,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11622,7 +11620,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11641,6 +11639,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena*
}
*out = _PyAST_alias(name, asname, lineno, col_offset, end_lineno,
end_col_offset, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -11655,7 +11654,7 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out,
expr_ty context_expr;
expr_ty optional_vars;
- if (_PyObject_LookupAttr(obj, state->context_expr, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->context_expr, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11672,7 +11671,7 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->optional_vars, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->optional_vars, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11690,6 +11689,7 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out,
Py_CLEAR(tmp);
}
*out = _PyAST_withitem(context_expr, optional_vars, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -11705,7 +11705,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out,
expr_ty guard;
asdl_stmt_seq* body;
- if (_PyObject_LookupAttr(obj, state->pattern, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->pattern, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11722,7 +11722,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->guard, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->guard, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -11739,7 +11739,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->body, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11778,6 +11778,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out,
Py_CLEAR(tmp);
}
*out = _PyAST_match_case(pattern, guard, body, arena);
+ if (*out == NULL) goto failed;
return 0;
failed:
Py_XDECREF(tmp);
@@ -11801,7 +11802,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
*out = NULL;
return 0;
}
- if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11818,7 +11819,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11835,7 +11836,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11852,7 +11853,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11877,7 +11878,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
if (isinstance) {
expr_ty value;
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11907,7 +11908,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
if (isinstance) {
constant value;
- if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11937,7 +11938,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
if (isinstance) {
asdl_pattern_seq* patterns;
- if (_PyObject_LookupAttr(obj, state->patterns, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->patterns, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -11990,7 +11991,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
asdl_pattern_seq* patterns;
identifier rest;
- if (_PyObject_LookupAttr(obj, state->keys, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->keys, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12028,7 +12029,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->patterns, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->patterns, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12066,7 +12067,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->rest, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->rest, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -12099,7 +12100,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
asdl_identifier_seq* kwd_attrs;
asdl_pattern_seq* kwd_patterns;
- if (_PyObject_LookupAttr(obj, state->cls, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->cls, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12116,7 +12117,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->patterns, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->patterns, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12154,7 +12155,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->kwd_attrs, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->kwd_attrs, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12192,7 +12193,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
}
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->kwd_patterns, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->kwd_patterns, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12244,7 +12245,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
if (isinstance) {
identifier name;
- if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -12275,7 +12276,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
pattern_ty pattern;
identifier name;
- if (_PyObject_LookupAttr(obj, state->pattern, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->pattern, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -12292,7 +12293,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -12322,7 +12323,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,
if (isinstance) {
asdl_pattern_seq* patterns;
- if (_PyObject_LookupAttr(obj, state->patterns, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->patterns, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12394,7 +12395,7 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty*
int lineno;
string tag;
- if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12411,7 +12412,7 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->tag, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->tag, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12456,7 +12457,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out,
*out = NULL;
return 0;
}
- if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12473,7 +12474,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->col_offset, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12490,12 +12491,12 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_lineno, &tmp) < 0) {
return 1;
}
- if (tmp == NULL || tmp == Py_None) {
- Py_CLEAR(tmp);
- end_lineno = lineno;
+ if (tmp == NULL) {
+ PyErr_SetString(PyExc_TypeError, "required field \"end_lineno\" missing from type_param");
+ return 1;
}
else {
int res;
@@ -12507,12 +12508,12 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->end_col_offset, &tmp) < 0) {
return 1;
}
- if (tmp == NULL || tmp == Py_None) {
- Py_CLEAR(tmp);
- end_col_offset = col_offset;
+ if (tmp == NULL) {
+ PyErr_SetString(PyExc_TypeError, "required field \"end_col_offset\" missing from type_param");
+ return 1;
}
else {
int res;
@@ -12533,7 +12534,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out,
identifier name;
expr_ty bound;
- if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12550,7 +12551,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out,
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->bound, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->bound, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
@@ -12580,7 +12581,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out,
if (isinstance) {
identifier name;
- if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
@@ -12610,7 +12611,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out,
if (isinstance) {
identifier name;
- if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(obj, state->name, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
diff --git a/Python/_warnings.c b/Python/_warnings.c
index 69fa04e6befe18..82e621243a0c15 100644
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -1,10 +1,11 @@
#include "Python.h"
+#include "pycore_frame.h"
#include "pycore_initconfig.h"
#include "pycore_interp.h" // PyInterpreterState.warnings
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_pyerrors.h"
+#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
#include "pycore_pystate.h" // _PyThreadState_GET()
-#include "pycore_frame.h"
#include "clinic/_warnings.c.h"
#define MODULE_NAME "_warnings"
@@ -222,7 +223,7 @@ get_warnings_attr(PyInterpreterState *interp, PyObject *attr, int try_import)
return NULL;
}
- (void)_PyObject_LookupAttr(warnings_module, attr, &obj);
+ (void)PyObject_GetOptionalAttr(warnings_module, attr, &obj);
Py_DECREF(warnings_module);
return obj;
}
@@ -898,7 +899,7 @@ setup_context(Py_ssize_t stack_level,
}
else {
globals = f->f_frame->f_globals;
- *filename = Py_NewRef(f->f_frame->f_code->co_filename);
+ *filename = Py_NewRef(_PyFrame_GetCode(f->f_frame)->co_filename);
*lineno = PyFrame_GetLineNumber(f);
Py_DECREF(f);
}
@@ -1068,7 +1069,7 @@ get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno
Py_INCREF(module_name);
/* Make sure the loader implements the optional get_source() method. */
- (void)_PyObject_LookupAttr(loader, &_Py_ID(get_source), &get_source);
+ (void)PyObject_GetOptionalAttr(loader, &_Py_ID(get_source), &get_source);
Py_DECREF(loader);
if (!get_source) {
Py_DECREF(module_name);
@@ -1298,25 +1299,29 @@ PyErr_WarnExplicit(PyObject *category, const char *text,
const char *module_str, PyObject *registry)
{
PyObject *message = PyUnicode_FromString(text);
+ if (message == NULL) {
+ return -1;
+ }
PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
+ if (filename == NULL) {
+ Py_DECREF(message);
+ return -1;
+ }
PyObject *module = NULL;
- int ret = -1;
-
- if (message == NULL || filename == NULL)
- goto exit;
if (module_str != NULL) {
module = PyUnicode_FromString(module_str);
- if (module == NULL)
- goto exit;
+ if (module == NULL) {
+ Py_DECREF(filename);
+ Py_DECREF(message);
+ return -1;
+ }
}
- ret = PyErr_WarnExplicitObject(category, message, filename, lineno,
- module, registry);
-
- exit:
- Py_XDECREF(message);
+ int ret = PyErr_WarnExplicitObject(category, message, filename, lineno,
+ module, registry);
Py_XDECREF(module);
- Py_XDECREF(filename);
+ Py_DECREF(filename);
+ Py_DECREF(message);
return ret;
}
diff --git a/Python/assemble.c b/Python/assemble.c
index 24ecc717eff1ce..b7012534d6cc4e 100644
--- a/Python/assemble.c
+++ b/Python/assemble.c
@@ -1,9 +1,11 @@
#include
#include "Python.h"
-#include "pycore_code.h" // write_location_entry_start()
+#include "pycore_code.h" // write_location_entry_start()
#include "pycore_compile.h"
-#include "pycore_opcode.h" // _PyOpcode_Caches[] and opcode category macros
+#include "pycore_opcode.h" // _PyOpcode_Caches[] and opcode category macros
+#include "pycore_opcode_utils.h" // IS_BACKWARDS_JUMP_OPCODE
+#include "pycore_opcode_metadata.h" // IS_PSEUDO_INSTR
#define DEFAULT_CODE_SIZE 128
@@ -33,6 +35,18 @@ same_location(location a, location b)
a.end_col_offset == b.end_col_offset;
}
+static int
+instr_size(instruction *instr)
+{
+ int opcode = instr->i_opcode;
+ int oparg = instr->i_oparg;
+ assert(!IS_PSEUDO_INSTR(opcode));
+ assert(OPCODE_HAS_ARG(opcode) || oparg == 0);
+ int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg);
+ int caches = _PyOpcode_Caches[opcode];
+ return extended_args + 1 + caches;
+}
+
struct assembler {
PyObject *a_bytecode; /* bytes containing bytecode */
int a_offset; /* offset into bytecode */
@@ -117,6 +131,7 @@ assemble_emit_exception_table_item(struct assembler *a, int value, int msb)
static int
assemble_emit_exception_table_entry(struct assembler *a, int start, int end,
+ int handler_offset,
_PyCompile_ExceptHandlerInfo *handler)
{
Py_ssize_t len = PyBytes_GET_SIZE(a->a_except_table);
@@ -125,7 +140,7 @@ assemble_emit_exception_table_entry(struct assembler *a, int start, int end,
}
int size = end-start;
assert(end > start);
- int target = handler->h_offset;
+ int target = handler_offset;
int depth = handler->h_startdepth - 1;
if (handler->h_preserve_lasti > 0) {
depth -= 1;
@@ -144,24 +159,30 @@ assemble_exception_table(struct assembler *a, instr_sequence *instrs)
{
int ioffset = 0;
_PyCompile_ExceptHandlerInfo handler;
- handler.h_offset = -1;
+ handler.h_label = -1;
handler.h_startdepth = -1;
handler.h_preserve_lasti = -1;
int start = -1;
for (int i = 0; i < instrs->s_used; i++) {
instruction *instr = &instrs->s_instrs[i];
- if (instr->i_except_handler_info.h_offset != handler.h_offset) {
- if (handler.h_offset >= 0) {
+ if (instr->i_except_handler_info.h_label != handler.h_label) {
+ if (handler.h_label >= 0) {
+ int handler_offset = instrs->s_instrs[handler.h_label].i_offset;
RETURN_IF_ERROR(
- assemble_emit_exception_table_entry(a, start, ioffset, &handler));
+ assemble_emit_exception_table_entry(a, start, ioffset,
+ handler_offset,
+ &handler));
}
start = ioffset;
handler = instr->i_except_handler_info;
}
- ioffset += _PyCompile_InstrSize(instr->i_opcode, instr->i_oparg);
+ ioffset += instr_size(instr);
}
- if (handler.h_offset >= 0) {
- RETURN_IF_ERROR(assemble_emit_exception_table_entry(a, start, ioffset, &handler));
+ if (handler.h_label >= 0) {
+ int handler_offset = instrs->s_instrs[handler.h_label].i_offset;
+ RETURN_IF_ERROR(assemble_emit_exception_table_entry(a, start, ioffset,
+ handler_offset,
+ &handler));
}
return SUCCESS;
}
@@ -328,7 +349,7 @@ assemble_location_info(struct assembler *a, instr_sequence *instrs,
loc = instr->i_loc;
size = 0;
}
- size += _PyCompile_InstrSize(instr->i_opcode, instr->i_oparg);
+ size += instr_size(instr);
}
RETURN_IF_ERROR(assemble_emit_location(a, loc, size));
return SUCCESS;
@@ -338,9 +359,9 @@ static void
write_instr(_Py_CODEUNIT *codestr, instruction *instr, int ilen)
{
int opcode = instr->i_opcode;
- assert(!IS_PSEUDO_OPCODE(opcode));
+ assert(!IS_PSEUDO_INSTR(opcode));
int oparg = instr->i_oparg;
- assert(HAS_ARG(opcode) || oparg == 0);
+ assert(OPCODE_HAS_ARG(opcode) || oparg == 0);
int caches = _PyOpcode_Caches[opcode];
switch (ilen - caches) {
case 4:
@@ -384,7 +405,7 @@ assemble_emit_instr(struct assembler *a, instruction *instr)
Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode);
_Py_CODEUNIT *code;
- int size = _PyCompile_InstrSize(instr->i_opcode, instr->i_oparg);
+ int size = instr_size(instr);
if (a->a_offset + size >= len / (int)sizeof(_Py_CODEUNIT)) {
if (len > PY_SSIZE_T_MAX / 2) {
return ERROR;
@@ -584,12 +605,117 @@ makecode(_PyCompile_CodeUnitMetadata *umd, struct assembler *a, PyObject *const_
return co;
}
+static int
+resolve_jump_offsets(instr_sequence *instrs)
+{
+ /* Compute the size of each instruction and fixup jump args.
+ * Replace instruction index with position in bytecode.
+ */
+
+ for (int i = 0; i < instrs->s_used; i++) {
+ instruction *instr = &instrs->s_instrs[i];
+ if (OPCODE_HAS_JUMP(instr->i_opcode)) {
+ instr->i_target = instr->i_oparg;
+ }
+ }
+
+ int extended_arg_recompile;
+
+ do {
+ int totsize = 0;
+ for (int i = 0; i < instrs->s_used; i++) {
+ instruction *instr = &instrs->s_instrs[i];
+ instr->i_offset = totsize;
+ int isize = instr_size(instr);
+ totsize += isize;
+ }
+ extended_arg_recompile = 0;
+
+ int offset = 0;
+ for (int i = 0; i < instrs->s_used; i++) {
+ instruction *instr = &instrs->s_instrs[i];
+ int isize = instr_size(instr);
+ /* jump offsets are computed relative to
+ * the instruction pointer after fetching
+ * the jump instruction.
+ */
+ offset += isize;
+ if (OPCODE_HAS_JUMP(instr->i_opcode)) {
+ instruction *target = &instrs->s_instrs[instr->i_target];
+ instr->i_oparg = target->i_offset;
+ if (instr->i_oparg < offset) {
+ assert(IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
+ instr->i_oparg = offset - instr->i_oparg;
+ }
+ else {
+ assert(!IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
+ instr->i_oparg = instr->i_oparg - offset;
+ }
+ if (instr_size(instr) != isize) {
+ extended_arg_recompile = 1;
+ }
+ }
+ }
+ /* XXX: This is an awful hack that could hurt performance, but
+ on the bright side it should work until we come up
+ with a better solution.
+
+ The issue is that in the first loop instr_size() is
+ called, and it requires i_oparg be set appropriately.
+ There is a bootstrap problem because i_oparg is
+ calculated in the second loop above.
+
+ So we loop until we stop seeing new EXTENDED_ARGs.
+ The only EXTENDED_ARGs that could be popping up are
+ ones in jump instructions. So this should converge
+ fairly quickly.
+ */
+ } while (extended_arg_recompile);
+ return SUCCESS;
+}
+
+static int
+resolve_unconditional_jumps(instr_sequence *instrs)
+{
+ /* Resolve directions of unconditional jumps */
+
+ for (int i = 0; i < instrs->s_used; i++) {
+ instruction *instr = &instrs->s_instrs[i];
+ bool is_forward = (instr->i_oparg > i);
+ switch(instr->i_opcode) {
+ case JUMP:
+ assert(SAME_OPCODE_METADATA(JUMP, JUMP_FORWARD));
+ assert(SAME_OPCODE_METADATA(JUMP, JUMP_BACKWARD));
+ instr->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
+ break;
+ case JUMP_NO_INTERRUPT:
+ assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_FORWARD));
+ assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
+ instr->i_opcode = is_forward ?
+ JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
+ break;
+ default:
+ if (OPCODE_HAS_JUMP(instr->i_opcode) &&
+ IS_PSEUDO_INSTR(instr->i_opcode)) {
+ Py_UNREACHABLE();
+ }
+ }
+ }
+ return SUCCESS;
+}
PyCodeObject *
_PyAssemble_MakeCodeObject(_PyCompile_CodeUnitMetadata *umd, PyObject *const_cache,
PyObject *consts, int maxdepth, instr_sequence *instrs,
int nlocalsplus, int code_flags, PyObject *filename)
{
+
+ if (resolve_unconditional_jumps(instrs) < 0) {
+ return NULL;
+ }
+ if (resolve_jump_offsets(instrs) < 0) {
+ return NULL;
+ }
PyCodeObject *co = NULL;
struct assembler a;
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 96a7ddd283a39b..7d77fd5c0c328e 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -4,13 +4,14 @@
#include
#include "pycore_ast.h" // _PyAST_Validate()
#include "pycore_call.h" // _PyObject_CallNoArgs()
+#include "pycore_ceval.h" // _PyEval_Vector()
#include "pycore_compile.h" // _PyAST_Compile()
#include "pycore_long.h" // _PyLong_CompactValue
+#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_object.h" // _Py_AddToAllObjects()
#include "pycore_pyerrors.h" // _PyErr_NoMemory()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_tuple.h" // _PyTuple_FromArray()
-#include "pycore_ceval.h" // _PyEval_Vector()
#include "clinic/bltinmodule.c.h"
@@ -33,7 +34,7 @@ update_bases(PyObject *bases, PyObject *const *args, Py_ssize_t nargs)
}
continue;
}
- if (_PyObject_LookupAttr(base, &_Py_ID(__mro_entries__), &meth) < 0) {
+ if (PyObject_GetOptionalAttr(base, &_Py_ID(__mro_entries__), &meth) < 0) {
goto error;
}
if (!meth) {
@@ -174,7 +175,7 @@ builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs,
}
/* else: meta is not a class, so we cannot do the metaclass
calculation, so we will use the explicitly given object as it is */
- if (_PyObject_LookupAttr(meta, &_Py_ID(__prepare__), &prep) < 0) {
+ if (PyObject_GetOptionalAttr(meta, &_Py_ID(__prepare__), &prep) < 0) {
ns = NULL;
}
else if (prep == NULL) {
@@ -907,7 +908,7 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
PyObject *locals)
/*[clinic end generated code: output=0a0824aa70093116 input=11ee718a8640e527]*/
{
- PyObject *result, *source_copy;
+ PyObject *result = NULL, *source_copy;
const char *str;
if (locals != Py_None && !PyMapping_Check(locals)) {
@@ -923,19 +924,25 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
if (globals == Py_None) {
globals = PyEval_GetGlobals();
if (locals == Py_None) {
- locals = PyEval_GetLocals();
+ locals = _PyEval_GetFrameLocals();
if (locals == NULL)
return NULL;
}
+ else {
+ Py_INCREF(locals);
+ }
}
else if (locals == Py_None)
- locals = globals;
+ locals = Py_NewRef(globals);
+ else {
+ Py_INCREF(locals);
+ }
if (globals == NULL || locals == NULL) {
PyErr_SetString(PyExc_TypeError,
"eval must be given globals and locals "
"when called without a frame");
- return NULL;
+ goto error;
}
int r = PyDict_Contains(globals, &_Py_ID(__builtins__));
@@ -943,34 +950,38 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
r = PyDict_SetItem(globals, &_Py_ID(__builtins__), PyEval_GetBuiltins());
}
if (r < 0) {
- return NULL;
+ goto error;
}
if (PyCode_Check(source)) {
if (PySys_Audit("exec", "O", source) < 0) {
- return NULL;
+ goto error;
}
if (PyCode_GetNumFree((PyCodeObject *)source) > 0) {
PyErr_SetString(PyExc_TypeError,
"code object passed to eval() may not contain free variables");
- return NULL;
+ goto error;
}
- return PyEval_EvalCode(source, globals, locals);
+ result = PyEval_EvalCode(source, globals, locals);
}
+ else {
+ PyCompilerFlags cf = _PyCompilerFlags_INIT;
+ cf.cf_flags = PyCF_SOURCE_IS_UTF8;
+ str = _Py_SourceAsString(source, "eval", "string, bytes or code", &cf, &source_copy);
+ if (str == NULL)
+ goto error;
- PyCompilerFlags cf = _PyCompilerFlags_INIT;
- cf.cf_flags = PyCF_SOURCE_IS_UTF8;
- str = _Py_SourceAsString(source, "eval", "string, bytes or code", &cf, &source_copy);
- if (str == NULL)
- return NULL;
+ while (*str == ' ' || *str == '\t')
+ str++;
- while (*str == ' ' || *str == '\t')
- str++;
+ (void)PyEval_MergeCompilerFlags(&cf);
+ result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf);
+ Py_XDECREF(source_copy);
+ }
- (void)PyEval_MergeCompilerFlags(&cf);
- result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf);
- Py_XDECREF(source_copy);
+ error:
+ Py_XDECREF(locals);
return result;
}
@@ -1005,36 +1016,43 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
if (globals == Py_None) {
globals = PyEval_GetGlobals();
if (locals == Py_None) {
- locals = PyEval_GetLocals();
+ locals = _PyEval_GetFrameLocals();
if (locals == NULL)
return NULL;
}
+ else {
+ Py_INCREF(locals);
+ }
if (!globals || !locals) {
PyErr_SetString(PyExc_SystemError,
"globals and locals cannot be NULL");
return NULL;
}
}
- else if (locals == Py_None)
- locals = globals;
+ else if (locals == Py_None) {
+ locals = Py_NewRef(globals);
+ }
+ else {
+ Py_INCREF(locals);
+ }
if (!PyDict_Check(globals)) {
PyErr_Format(PyExc_TypeError, "exec() globals must be a dict, not %.100s",
Py_TYPE(globals)->tp_name);
- return NULL;
+ goto error;
}
if (!PyMapping_Check(locals)) {
PyErr_Format(PyExc_TypeError,
"locals must be a mapping or None, not %.100s",
Py_TYPE(locals)->tp_name);
- return NULL;
+ goto error;
}
int r = PyDict_Contains(globals, &_Py_ID(__builtins__));
if (r == 0) {
r = PyDict_SetItem(globals, &_Py_ID(__builtins__), PyEval_GetBuiltins());
}
if (r < 0) {
- return NULL;
+ goto error;
}
if (closure == Py_None) {
@@ -1047,7 +1065,7 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
if (closure) {
PyErr_SetString(PyExc_TypeError,
"cannot use a closure with this code object");
- return NULL;
+ goto error;
}
} else {
int closure_is_ok =
@@ -1067,12 +1085,12 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
PyErr_Format(PyExc_TypeError,
"code object requires a closure of exactly length %zd",
num_free);
- return NULL;
+ goto error;
}
}
if (PySys_Audit("exec", "O", source) < 0) {
- return NULL;
+ goto error;
}
if (!closure) {
@@ -1099,7 +1117,7 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
"string, bytes or code", &cf,
&source_copy);
if (str == NULL)
- return NULL;
+ goto error;
if (PyEval_MergeCompilerFlags(&cf))
v = PyRun_StringFlags(str, Py_file_input, globals,
locals, &cf);
@@ -1108,9 +1126,14 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
Py_XDECREF(source_copy);
}
if (v == NULL)
- return NULL;
+ goto error;
+ Py_DECREF(locals);
Py_DECREF(v);
Py_RETURN_NONE;
+
+ error:
+ Py_XDECREF(locals);
+ return NULL;
}
@@ -1137,7 +1160,7 @@ builtin_getattr_impl(PyObject *module, PyObject *object, PyObject *name,
PyObject *result;
if (default_value != NULL) {
- if (_PyObject_LookupAttr(object, name, &result) == 0) {
+ if (PyObject_GetOptionalAttr(object, name, &result) == 0) {
return Py_NewRef(default_value);
}
}
@@ -1186,7 +1209,7 @@ builtin_hasattr_impl(PyObject *module, PyObject *obj, PyObject *name)
{
PyObject *v;
- if (_PyObject_LookupAttr(obj, name, &v) < 0) {
+ if (PyObject_GetOptionalAttr(obj, name, &v) < 0) {
return NULL;
}
if (v == NULL) {
@@ -1544,8 +1567,9 @@ static PyObject *
builtin_delattr_impl(PyObject *module, PyObject *obj, PyObject *name)
/*[clinic end generated code: output=85134bc58dff79fa input=164865623abe7216]*/
{
- if (PyObject_SetAttr(obj, name, (PyObject *)NULL) != 0)
+ if (PyObject_DelAttr(obj, name) < 0) {
return NULL;
+ }
Py_RETURN_NONE;
}
@@ -1720,10 +1744,7 @@ static PyObject *
builtin_locals_impl(PyObject *module)
/*[clinic end generated code: output=b46c94015ce11448 input=7874018d478d5c4b]*/
{
- PyObject *d;
-
- d = PyEval_GetLocals();
- return Py_XNewRef(d);
+ return _PyEval_GetFrameLocals();
}
@@ -2162,17 +2183,29 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
/* stdin is a text stream, so it must have an encoding. */
stdin_encoding = PyObject_GetAttr(fin, &_Py_ID(encoding));
+ if (stdin_encoding == NULL) {
+ tty = 0;
+ goto _readline_errors;
+ }
stdin_errors = PyObject_GetAttr(fin, &_Py_ID(errors));
- if (!stdin_encoding || !stdin_errors ||
- !PyUnicode_Check(stdin_encoding) ||
- !PyUnicode_Check(stdin_errors)) {
+ if (stdin_errors == NULL) {
+ tty = 0;
+ goto _readline_errors;
+ }
+ if (!PyUnicode_Check(stdin_encoding) ||
+ !PyUnicode_Check(stdin_errors))
+ {
tty = 0;
goto _readline_errors;
}
stdin_encoding_str = PyUnicode_AsUTF8(stdin_encoding);
+ if (stdin_encoding_str == NULL) {
+ goto _readline_errors;
+ }
stdin_errors_str = PyUnicode_AsUTF8(stdin_errors);
- if (!stdin_encoding_str || !stdin_errors_str)
+ if (stdin_errors_str == NULL) {
goto _readline_errors;
+ }
tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(flush));
if (tmp == NULL)
PyErr_Clear();
@@ -2183,17 +2216,29 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
const char *stdout_encoding_str, *stdout_errors_str;
PyObject *stringpo;
stdout_encoding = PyObject_GetAttr(fout, &_Py_ID(encoding));
+ if (stdout_encoding == NULL) {
+ tty = 0;
+ goto _readline_errors;
+ }
stdout_errors = PyObject_GetAttr(fout, &_Py_ID(errors));
- if (!stdout_encoding || !stdout_errors ||
- !PyUnicode_Check(stdout_encoding) ||
- !PyUnicode_Check(stdout_errors)) {
+ if (stdout_errors == NULL) {
+ tty = 0;
+ goto _readline_errors;
+ }
+ if (!PyUnicode_Check(stdout_encoding) ||
+ !PyUnicode_Check(stdout_errors))
+ {
tty = 0;
goto _readline_errors;
}
stdout_encoding_str = PyUnicode_AsUTF8(stdout_encoding);
+ if (stdout_encoding_str == NULL) {
+ goto _readline_errors;
+ }
stdout_errors_str = PyUnicode_AsUTF8(stdout_errors);
- if (!stdout_encoding_str || !stdout_errors_str)
+ if (stdout_errors_str == NULL) {
goto _readline_errors;
+ }
stringpo = PyObject_Str(prompt);
if (stringpo == NULL)
goto _readline_errors;
@@ -2417,10 +2462,10 @@ builtin_vars_impl(PyObject *module, PyObject *object)
PyObject *d;
if (object == NULL) {
- d = Py_XNewRef(PyEval_GetLocals());
+ d = _PyEval_GetFrameLocals();
}
else {
- if (_PyObject_LookupAttr(object, &_Py_ID(__dict__), &d) == 0) {
+ if (PyObject_GetOptionalAttr(object, &_Py_ID(__dict__), &d) == 0) {
PyErr_SetString(PyExc_TypeError,
"vars() argument must have __dict__ attribute");
}
diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c
index 587063ef1ab29a..ef693e5df1fcc4 100644
--- a/Python/bootstrap_hash.c
+++ b/Python/bootstrap_hash.c
@@ -1,6 +1,7 @@
#include "Python.h"
-#include "pycore_initconfig.h"
#include "pycore_fileutils.h" // _Py_fstat_noraise()
+#include "pycore_initconfig.h"
+#include "pycore_pylifecycle.h" // _PyOS_URandomNonblock()
#include "pycore_runtime.h" // _PyRuntime
#ifdef MS_WINDOWS
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index e7f7c1a96f8dcb..3c3992c068b063 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -8,7 +8,6 @@
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
-#include "pycore_call.h" // _PyObject_FastCallDictTstate()
#include "pycore_ceval.h" // _PyEval_SignalAsyncExc()
#include "pycore_code.h"
#include "pycore_function.h"
@@ -18,6 +17,7 @@
#include "pycore_object.h" // _PyObject_GC_TRACK()
#include "pycore_moduleobject.h" // PyModuleObject
#include "pycore_opcode.h" // EXTRA_CASES
+#include "pycore_opcode_metadata.h" // uop names
#include "pycore_opcode_utils.h" // MAKE_FUNCTION_*
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
@@ -50,18 +50,20 @@
#define macro(name) static int MACRO_##name
#define super(name) static int SUPER_##name
#define family(name, ...) static int family_##name
+#define pseudo(name) static int pseudo_##name
// Dummy variables for stack effects.
static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub;
static PyObject *container, *start, *stop, *v, *lhs, *rhs, *res2;
static PyObject *list, *tuple, *dict, *owner, *set, *str, *tup, *map, *keys;
-static PyObject *exit_func, *lasti, *val, *retval, *obj, *iter;
+static PyObject *exit_func, *lasti, *val, *retval, *obj, *iter, *exhausted;
static PyObject *aiter, *awaitable, *iterable, *w, *exc_value, *bc, *locals;
static PyObject *orig, *excs, *update, *b, *fromlist, *level, *from;
static PyObject **pieces, **values;
static size_t jump;
// Dummy variables for cache effects
static uint16_t invert, counter, index, hint;
+#define unused 0 // Used in a macro def, can't be static
static uint32_t type_version;
static PyObject *
@@ -82,15 +84,14 @@ dummy_func(
// Dummy labels.
pop_1_error:
// Dummy locals.
- PyObject *annotations;
+ PyObject *dummy;
+ PyObject *attr;
PyObject *attrs;
PyObject *bottom;
PyObject *callable;
PyObject *callargs;
- PyObject *closure;
PyObject *codeobj;
PyObject *cond;
- PyObject *defaults;
PyObject *descr;
_PyInterpreterFrame entry_frame;
PyObject *exc;
@@ -137,13 +138,13 @@ dummy_func(
assert(tstate->cframe == &cframe);
assert(frame == cframe.current_frame);
/* Possibly combine this with eval breaker */
- if (frame->f_code->_co_instrumentation_version != tstate->interp->monitoring_version) {
- int err = _Py_Instrument(frame->f_code, tstate->interp);
+ if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) {
+ int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
ERROR_IF(err, error);
next_instr--;
}
- else if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker) && oparg < 2) {
- goto handle_eval_breaker;
+ else if (oparg < 2) {
+ CHECK_EVAL_BREAKER();
}
}
@@ -152,13 +153,16 @@ dummy_func(
* We need to check the eval breaker anyway, can we
* combine the instrument verison check and the eval breaker test?
*/
- if (frame->f_code->_co_instrumentation_version != tstate->interp->monitoring_version) {
- if (_Py_Instrument(frame->f_code, tstate->interp)) {
+ if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) {
+ if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) {
goto error;
}
next_instr--;
}
else {
+ if (oparg < 2) {
+ CHECK_EVAL_BREAKER();
+ }
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation(
tstate, oparg > 0, frame, next_instr-1);
@@ -169,18 +173,12 @@ dummy_func(
next_instr = frame->prev_instr;
DISPATCH();
}
- if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker) && oparg < 2) {
- goto handle_eval_breaker;
- }
}
}
- inst(LOAD_CLOSURE, (-- value)) {
- /* We keep LOAD_CLOSURE so that the bytecode stays more readable. */
- value = GETLOCAL(oparg);
- ERROR_IF(value == NULL, unbound_local_error);
- Py_INCREF(value);
- }
+ pseudo(LOAD_CLOSURE) = {
+ LOAD_FAST,
+ };
inst(LOAD_FAST_CHECK, (-- value)) {
value = GETLOCAL(oparg);
@@ -210,7 +208,7 @@ dummy_func(
}
inst(LOAD_CONST, (-- value)) {
- value = GETITEM(frame->f_code->co_consts, oparg);
+ value = GETITEM(FRAME_CO_CONSTS, oparg);
Py_INCREF(value);
}
@@ -218,6 +216,10 @@ dummy_func(
SETLOCAL(oparg, value);
}
+ pseudo(STORE_FAST_MAYBE_NULL) = {
+ STORE_FAST,
+ };
+
inst(STORE_FAST_LOAD_FAST, (value1 -- value2)) {
uint32_t oparg1 = oparg >> 4;
uint32_t oparg2 = oparg & 15;
@@ -278,15 +280,89 @@ dummy_func(
}
inst(UNARY_NOT, (value -- res)) {
+ assert(PyBool_Check(value));
+ res = Py_IsFalse(value) ? Py_True : Py_False;
+ }
+
+ family(TO_BOOL, INLINE_CACHE_ENTRIES_TO_BOOL) = {
+ TO_BOOL_ALWAYS_TRUE,
+ TO_BOOL_BOOL,
+ TO_BOOL_INT,
+ TO_BOOL_LIST,
+ TO_BOOL_NONE,
+ TO_BOOL_STR,
+ };
+
+ inst(TO_BOOL, (unused/1, unused/2, value -- res)) {
+ #if ENABLE_SPECIALIZATION
+ _PyToBoolCache *cache = (_PyToBoolCache *)next_instr;
+ if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
+ next_instr--;
+ _Py_Specialize_ToBool(value, next_instr);
+ DISPATCH_SAME_OPARG();
+ }
+ STAT_INC(TO_BOOL, deferred);
+ DECREMENT_ADAPTIVE_COUNTER(cache->counter);
+ #endif /* ENABLE_SPECIALIZATION */
int err = PyObject_IsTrue(value);
DECREF_INPUTS();
ERROR_IF(err < 0, error);
- if (err == 0) {
- res = Py_True;
+ res = err ? Py_True : Py_False;
+ }
+
+ inst(TO_BOOL_BOOL, (unused/1, unused/2, value -- value)) {
+ DEOPT_IF(!PyBool_Check(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ }
+
+ inst(TO_BOOL_INT, (unused/1, unused/2, value -- res)) {
+ DEOPT_IF(!PyLong_CheckExact(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ if (_PyLong_IsZero((PyLongObject *)value)) {
+ assert(_Py_IsImmortal(value));
+ res = Py_False;
}
else {
+ DECREF_INPUTS();
+ res = Py_True;
+ }
+ }
+
+ inst(TO_BOOL_LIST, (unused/1, unused/2, value -- res)) {
+ DEOPT_IF(!PyList_CheckExact(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ res = Py_SIZE(value) ? Py_True : Py_False;
+ DECREF_INPUTS();
+ }
+
+ inst(TO_BOOL_NONE, (unused/1, unused/2, value -- res)) {
+ // This one is a bit weird, because we expect *some* failures:
+ DEOPT_IF(!Py_IsNone(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ res = Py_False;
+ }
+
+ inst(TO_BOOL_STR, (unused/1, unused/2, value -- res)) {
+ DEOPT_IF(!PyUnicode_CheckExact(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ if (value == &_Py_STR(empty)) {
+ assert(_Py_IsImmortal(value));
res = Py_False;
}
+ else {
+ assert(Py_SIZE(value));
+ DECREF_INPUTS();
+ res = Py_True;
+ }
+ }
+
+ inst(TO_BOOL_ALWAYS_TRUE, (unused/1, version/2, value -- res)) {
+ // This one is a bit weird, because we expect *some* failures:
+ assert(version);
+ DEOPT_IF(Py_TYPE(value)->tp_version_tag != version, TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ DECREF_INPUTS();
+ res = Py_True;
}
inst(UNARY_INVERT, (value -- res)) {
@@ -295,8 +371,7 @@ dummy_func(
ERROR_IF(res == NULL, error);
}
- family(binary_op, INLINE_CACHE_ENTRIES_BINARY_OP) = {
- BINARY_OP,
+ family(BINARY_OP, INLINE_CACHE_ENTRIES_BINARY_OP) = {
BINARY_OP_MULTIPLY_INT,
BINARY_OP_ADD_INT,
BINARY_OP_SUBTRACT_INT,
@@ -424,14 +499,13 @@ dummy_func(
_Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
ERROR_IF(*target_local == NULL, error);
// The STORE_FAST is already done.
- JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP + 1);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_BINARY_OP + 1);
}
macro(BINARY_OP_INPLACE_ADD_UNICODE) =
_GUARD_BOTH_UNICODE + _BINARY_OP_INPLACE_ADD_UNICODE;
- family(binary_subscr, INLINE_CACHE_ENTRIES_BINARY_SUBSCR) = {
- BINARY_SUBSCR,
+ family(BINARY_SUBSCR, INLINE_CACHE_ENTRIES_BINARY_SUBSCR) = {
BINARY_SUBSCR_DICT,
BINARY_SUBSCR_GETITEM,
BINARY_SUBSCR_LIST_INT,
@@ -551,7 +625,7 @@ dummy_func(
STACK_SHRINK(2);
new_frame->localsplus[0] = container;
new_frame->localsplus[1] = sub;
- JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
}
@@ -566,8 +640,7 @@ dummy_func(
ERROR_IF(err, error);
}
- family(store_subscr, INLINE_CACHE_ENTRIES_STORE_SUBSCR) = {
- STORE_SUBSCR,
+ family(STORE_SUBSCR, INLINE_CACHE_ENTRIES_STORE_SUBSCR) = {
STORE_SUBSCR_DICT,
STORE_SUBSCR_LIST_INT,
};
@@ -662,8 +735,6 @@ dummy_func(
inst(INTERPRETER_EXIT, (retval --)) {
assert(frame == &entry_frame);
assert(_PyFrame_IsIncomplete(frame));
- STACK_SHRINK(1); // Since we're not going to DISPATCH()
- assert(EMPTY());
/* Restore previous cframe and return. */
tstate->cframe = cframe.previous;
assert(tstate->cframe->current_frame == frame->previous);
@@ -707,7 +778,7 @@ dummy_func(
}
inst(RETURN_CONST, (--)) {
- PyObject *retval = GETITEM(frame->f_code->co_consts, oparg);
+ PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg);
Py_INCREF(retval);
assert(EMPTY());
_PyFrame_SetStackPointer(frame, stack_pointer);
@@ -723,7 +794,7 @@ dummy_func(
}
inst(INSTRUMENTED_RETURN_CONST, (--)) {
- PyObject *retval = GETITEM(frame->f_code->co_consts, oparg);
+ PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg);
int err = _Py_call_instrumentation_arg(
tstate, PY_MONITORING_EVENT_PY_RETURN,
frame, next_instr-1, retval);
@@ -846,8 +917,7 @@ dummy_func(
ERROR_IF(iter == NULL, error);
}
- family(send, INLINE_CACHE_ENTRIES_SEND) = {
- SEND,
+ family(SEND, INLINE_CACHE_ENTRIES_SEND) = {
SEND_GEN,
};
@@ -875,7 +945,7 @@ dummy_func(
gen->gi_frame_state = FRAME_EXECUTING;
gen->gi_exc_state.previous_item = tstate->exc_info;
tstate->exc_info = &gen->gi_exc_state;
- JUMPBY(INLINE_CACHE_ENTRIES_SEND);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_SEND);
DISPATCH_INLINED(gen_frame);
}
if (Py_IsNone(v) && PyIter_Check(receiver)) {
@@ -914,12 +984,13 @@ dummy_func(
gen->gi_frame_state = FRAME_EXECUTING;
gen->gi_exc_state.previous_item = tstate->exc_info;
tstate->exc_info = &gen->gi_exc_state;
- JUMPBY(INLINE_CACHE_ENTRIES_SEND);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_SEND);
DISPATCH_INLINED(gen_frame);
}
inst(INSTRUMENTED_YIELD_VALUE, (retval -- unused)) {
assert(frame != &entry_frame);
+ assert(oparg >= 0); /* make the generator identify this as HAS_ARG */
PyGenObject *gen = _PyFrame_GetGenerator(frame);
gen->gi_frame_state = FRAME_SUSPENDED;
_PyFrame_SetStackPointer(frame, stack_pointer - 1);
@@ -941,6 +1012,7 @@ dummy_func(
// NOTE: It's important that YIELD_VALUE never raises an exception!
// The compiler treats any exception raised here as a failed close()
// or throw() call.
+ assert(oparg >= 0); /* make the generator identify this as HAS_ARG */
assert(frame != &entry_frame);
PyGenObject *gen = _PyFrame_GetGenerator(frame);
gen->gi_frame_state = FRAME_SUSPENDED;
@@ -965,7 +1037,7 @@ dummy_func(
if (oparg) {
PyObject *lasti = values[0];
if (PyLong_Check(lasti)) {
- frame->prev_instr = _PyCode_CODE(frame->f_code) + PyLong_AsLong(lasti);
+ frame->prev_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + PyLong_AsLong(lasti);
assert(!_PyErr_Occurred(tstate));
}
else {
@@ -1011,32 +1083,17 @@ dummy_func(
}
inst(LOAD_BUILD_CLASS, ( -- bc)) {
- if (PyDict_CheckExact(BUILTINS())) {
- bc = _PyDict_GetItemWithError(BUILTINS(),
- &_Py_ID(__build_class__));
- if (bc == NULL) {
- if (!_PyErr_Occurred(tstate)) {
- _PyErr_SetString(tstate, PyExc_NameError,
- "__build_class__ not found");
- }
- ERROR_IF(true, error);
- }
- Py_INCREF(bc);
- }
- else {
- bc = PyObject_GetItem(BUILTINS(), &_Py_ID(__build_class__));
- if (bc == NULL) {
- if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError))
- _PyErr_SetString(tstate, PyExc_NameError,
- "__build_class__ not found");
- ERROR_IF(true, error);
- }
+ ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc) < 0, error);
+ if (bc == NULL) {
+ _PyErr_SetString(tstate, PyExc_NameError,
+ "__build_class__ not found");
+ ERROR_IF(true, error);
}
}
inst(STORE_NAME, (v -- )) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
PyObject *ns = LOCALS();
int err;
if (ns == NULL) {
@@ -1054,7 +1111,7 @@ dummy_func(
}
inst(DELETE_NAME, (--)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
PyObject *ns = LOCALS();
int err;
if (ns == NULL) {
@@ -1072,8 +1129,7 @@ dummy_func(
}
}
- family(unpack_sequence, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = {
- UNPACK_SEQUENCE,
+ family(UNPACK_SEQUENCE, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = {
UNPACK_SEQUENCE_TWO_TUPLE,
UNPACK_SEQUENCE_TUPLE,
UNPACK_SEQUENCE_LIST,
@@ -1136,8 +1192,7 @@ dummy_func(
ERROR_IF(res == 0, error);
}
- family(store_attr, INLINE_CACHE_ENTRIES_STORE_ATTR) = {
- STORE_ATTR,
+ family(STORE_ATTR, INLINE_CACHE_ENTRIES_STORE_ATTR) = {
STORE_ATTR_INSTANCE_VALUE,
STORE_ATTR_SLOT,
STORE_ATTR_WITH_HINT,
@@ -1146,7 +1201,7 @@ dummy_func(
inst(STORE_ATTR, (counter/1, unused/3, v, owner --)) {
#if ENABLE_SPECIALIZATION
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
next_instr--;
_Py_Specialize_StoreAttr(owner, next_instr, name);
DISPATCH_SAME_OPARG();
@@ -1157,28 +1212,28 @@ dummy_func(
#else
(void)counter; // Unused.
#endif /* ENABLE_SPECIALIZATION */
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
int err = PyObject_SetAttr(owner, name, v);
DECREF_INPUTS();
ERROR_IF(err, error);
}
inst(DELETE_ATTR, (owner --)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
- int err = PyObject_SetAttr(owner, name, (PyObject *)NULL);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ int err = PyObject_DelAttr(owner, name);
DECREF_INPUTS();
ERROR_IF(err, error);
}
inst(STORE_GLOBAL, (v --)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
int err = PyDict_SetItem(GLOBALS(), name, v);
DECREF_INPUTS();
ERROR_IF(err, error);
}
inst(DELETE_GLOBAL, (--)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
int err;
err = PyDict_DelItem(GLOBALS(), name);
// Can't use ERROR_IF here.
@@ -1204,26 +1259,10 @@ dummy_func(
macro(LOAD_LOCALS) = _LOAD_LOCALS;
op(_LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
- if (PyDict_CheckExact(mod_or_class_dict)) {
- v = PyDict_GetItemWithError(mod_or_class_dict, name);
- if (v != NULL) {
- Py_INCREF(v);
- }
- else if (_PyErr_Occurred(tstate)) {
- Py_DECREF(mod_or_class_dict);
- goto error;
- }
- }
- else {
- v = PyObject_GetItem(mod_or_class_dict, name);
- if (v == NULL) {
- if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
- Py_DECREF(mod_or_class_dict);
- goto error;
- }
- _PyErr_Clear(tstate);
- }
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) {
+ Py_DECREF(mod_or_class_dict);
+ goto error;
}
Py_DECREF(mod_or_class_dict);
if (v == NULL) {
@@ -1235,28 +1274,14 @@ dummy_func(
goto error;
}
else {
- if (PyDict_CheckExact(BUILTINS())) {
- v = PyDict_GetItemWithError(BUILTINS(), name);
- if (v == NULL) {
- if (!_PyErr_Occurred(tstate)) {
- format_exc_check_arg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- }
- goto error;
- }
- Py_INCREF(v);
+ if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) {
+ goto error;
}
- else {
- v = PyObject_GetItem(BUILTINS(), name);
- if (v == NULL) {
- if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
- format_exc_check_arg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- }
- goto error;
- }
+ if (v == NULL) {
+ format_exc_check_arg(
+ tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ goto error;
}
}
}
@@ -1266,8 +1291,7 @@ dummy_func(
macro(LOAD_FROM_DICT_OR_GLOBALS) = _LOAD_FROM_DICT_OR_GLOBALS;
- family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = {
- LOAD_GLOBAL,
+ family(LOAD_GLOBAL, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = {
LOAD_GLOBAL_MODULE,
LOAD_GLOBAL_BUILTIN,
};
@@ -1276,7 +1300,7 @@ dummy_func(
#if ENABLE_SPECIALIZATION
_PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
next_instr--;
_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name);
DISPATCH_SAME_OPARG();
@@ -1284,7 +1308,7 @@ dummy_func(
STAT_INC(LOAD_GLOBAL, deferred);
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
#endif /* ENABLE_SPECIALIZATION */
- PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
if (PyDict_CheckExact(GLOBALS())
&& PyDict_CheckExact(BUILTINS()))
{
@@ -1306,19 +1330,14 @@ dummy_func(
/* Slow-path if globals or builtins is not a dict */
/* namespace 1: globals */
- v = PyObject_GetItem(GLOBALS(), name);
+ ERROR_IF(PyMapping_GetOptionalItem(GLOBALS(), name, &v) < 0, error);
if (v == NULL) {
- ERROR_IF(!_PyErr_ExceptionMatches(tstate, PyExc_KeyError), error);
- _PyErr_Clear(tstate);
-
/* namespace 2: builtins */
- v = PyObject_GetItem(BUILTINS(), name);
+ ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0, error);
if (v == NULL) {
- if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
- format_exc_check_arg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- }
+ format_exc_check_arg(
+ tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
ERROR_IF(true, error);
}
}
@@ -1326,11 +1345,25 @@ dummy_func(
null = NULL;
}
- inst(LOAD_GLOBAL_MODULE, (unused/1, index/1, version/1, unused/1 -- null if (oparg & 1), res)) {
- DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
+ op(_SKIP_CACHE, (unused/1 -- )) {
+ }
+
+ op(_GUARD_GLOBALS_VERSION, (version/1 --)) {
PyDictObject *dict = (PyDictObject *)GLOBALS();
+ DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL);
DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
assert(DK_IS_UNICODE(dict->ma_keys));
+ }
+
+ op(_GUARD_BUILTINS_VERSION, (version/1 --)) {
+ PyDictObject *dict = (PyDictObject *)BUILTINS();
+ DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL);
+ DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
+ assert(DK_IS_UNICODE(dict->ma_keys));
+ }
+
+ op(_LOAD_GLOBAL_MODULE, (index/1 -- null if (oparg & 1), res)) {
+ PyDictObject *dict = (PyDictObject *)GLOBALS();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
res = entries[index].me_value;
DEOPT_IF(res == NULL, LOAD_GLOBAL);
@@ -1339,15 +1372,8 @@ dummy_func(
null = NULL;
}
- inst(LOAD_GLOBAL_BUILTIN, (unused/1, index/1, mod_version/1, bltn_version/1 -- null if (oparg & 1), res)) {
- DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
- DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL);
- PyDictObject *mdict = (PyDictObject *)GLOBALS();
+ op(_LOAD_GLOBAL_BUILTINS, (index/1 -- null if (oparg & 1), res)) {
PyDictObject *bdict = (PyDictObject *)BUILTINS();
- assert(opcode == LOAD_GLOBAL_BUILTIN);
- DEOPT_IF(mdict->ma_keys->dk_version != mod_version, LOAD_GLOBAL);
- DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL);
- assert(DK_IS_UNICODE(bdict->ma_keys));
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys);
res = entries[index].me_value;
DEOPT_IF(res == NULL, LOAD_GLOBAL);
@@ -1356,6 +1382,18 @@ dummy_func(
null = NULL;
}
+ macro(LOAD_GLOBAL_MODULE) =
+ _SKIP_CACHE + // Skip over the counter
+ _GUARD_GLOBALS_VERSION +
+ _SKIP_CACHE + // Skip over the builtins version
+ _LOAD_GLOBAL_MODULE;
+
+ macro(LOAD_GLOBAL_BUILTIN) =
+ _SKIP_CACHE + // Skip over the counter
+ _GUARD_GLOBALS_VERSION +
+ _GUARD_BUILTINS_VERSION +
+ _LOAD_GLOBAL_BUILTINS;
+
inst(DELETE_FAST, (--)) {
PyObject *v = GETLOCAL(oparg);
ERROR_IF(v == NULL, unbound_local_error);
@@ -1379,7 +1417,7 @@ dummy_func(
// Can't use ERROR_IF here.
// Fortunately we don't need its superpower.
if (oldobj == NULL) {
- format_exc_unbound(tstate, frame->f_code, oparg);
+ format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
goto error;
}
PyCell_SET(cell, NULL);
@@ -1389,34 +1427,18 @@ dummy_func(
inst(LOAD_FROM_DICT_OR_DEREF, (class_dict -- value)) {
PyObject *name;
assert(class_dict);
- assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus);
- name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg);
- if (PyDict_CheckExact(class_dict)) {
- value = PyDict_GetItemWithError(class_dict, name);
- if (value != NULL) {
- Py_INCREF(value);
- }
- else if (_PyErr_Occurred(tstate)) {
- Py_DECREF(class_dict);
- goto error;
- }
- }
- else {
- value = PyObject_GetItem(class_dict, name);
- if (value == NULL) {
- if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
- Py_DECREF(class_dict);
- goto error;
- }
- _PyErr_Clear(tstate);
- }
+ assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus);
+ name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg);
+ if (PyMapping_GetOptionalItem(class_dict, name, &value) < 0) {
+ Py_DECREF(class_dict);
+ goto error;
}
Py_DECREF(class_dict);
if (!value) {
PyObject *cell = GETLOCAL(oparg);
value = PyCell_GET(cell);
if (value == NULL) {
- format_exc_unbound(tstate, frame->f_code, oparg);
+ format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
goto error;
}
Py_INCREF(value);
@@ -1427,7 +1449,7 @@ dummy_func(
PyObject *cell = GETLOCAL(oparg);
value = PyCell_GET(cell);
if (value == NULL) {
- format_exc_unbound(tstate, frame->f_code, oparg);
+ format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
ERROR_IF(true, error);
}
Py_INCREF(value);
@@ -1442,7 +1464,7 @@ dummy_func(
inst(COPY_FREE_VARS, (--)) {
/* Copy closure variables to free variables */
- PyCodeObject *co = frame->f_code;
+ PyCodeObject *co = _PyFrame_GetCode(frame);
assert(PyFunction_Check(frame->f_funcobj));
PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
assert(oparg == co->co_nfreevars);
@@ -1547,10 +1569,8 @@ dummy_func(
}
else {
/* do the same if locals() is not a dict */
- ann_dict = PyObject_GetItem(LOCALS(), &_Py_ID(__annotations__));
+ ERROR_IF(PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0, error);
if (ann_dict == NULL) {
- ERROR_IF(!_PyErr_ExceptionMatches(tstate, PyExc_KeyError), error);
- _PyErr_Clear(tstate);
ann_dict = PyDict_New();
ERROR_IF(ann_dict == NULL, error);
err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__),
@@ -1619,14 +1639,13 @@ dummy_func(
GO_TO_INSTRUCTION(LOAD_SUPER_ATTR);
}
- family(load_super_attr, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
- LOAD_SUPER_ATTR,
+ family(LOAD_SUPER_ATTR, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
LOAD_SUPER_ATTR_ATTR,
LOAD_SUPER_ATTR_METHOD,
};
inst(LOAD_SUPER_ATTR, (unused/1, global_super, class, self -- res2 if (oparg & 1), res)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
int load_method = oparg & 1;
#if ENABLE_SPECIALIZATION
_PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr;
@@ -1674,12 +1693,24 @@ dummy_func(
ERROR_IF(res == NULL, error);
}
+ pseudo(LOAD_SUPER_METHOD) = {
+ LOAD_SUPER_ATTR,
+ };
+
+ pseudo(LOAD_ZERO_SUPER_METHOD) = {
+ LOAD_SUPER_ATTR,
+ };
+
+ pseudo(LOAD_ZERO_SUPER_ATTR) = {
+ LOAD_SUPER_ATTR,
+ };
+
inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super, class, self -- res2 if (oparg & 1), res)) {
assert(!(oparg & 1));
DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
STAT_INC(LOAD_SUPER_ATTR, hit);
- PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
res = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL);
DECREF_INPUTS();
ERROR_IF(res == NULL, error);
@@ -1690,7 +1721,7 @@ dummy_func(
DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
STAT_INC(LOAD_SUPER_ATTR, hit);
- PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
PyTypeObject *cls = (PyTypeObject *)class;
int method_found = 0;
res2 = _PySuper_Lookup(cls, self, name,
@@ -1710,8 +1741,7 @@ dummy_func(
}
}
- family(load_attr, INLINE_CACHE_ENTRIES_LOAD_ATTR) = {
- LOAD_ATTR,
+ family(LOAD_ATTR, INLINE_CACHE_ENTRIES_LOAD_ATTR) = {
LOAD_ATTR_INSTANCE_VALUE,
LOAD_ATTR_MODULE,
LOAD_ATTR_WITH_HINT,
@@ -1722,13 +1752,15 @@ dummy_func(
LOAD_ATTR_METHOD_WITH_VALUES,
LOAD_ATTR_METHOD_NO_DICT,
LOAD_ATTR_METHOD_LAZY_DICT,
+ LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES,
+ LOAD_ATTR_NONDESCRIPTOR_NO_DICT,
};
inst(LOAD_ATTR, (unused/9, owner -- res2 if (oparg & 1), res)) {
#if ENABLE_SPECIALIZATION
_PyAttrCache *cache = (_PyAttrCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
next_instr--;
_Py_Specialize_LoadAttr(owner, next_instr, name);
DISPATCH_SAME_OPARG();
@@ -1736,7 +1768,7 @@ dummy_func(
STAT_INC(LOAD_ATTR, deferred);
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
#endif /* ENABLE_SPECIALIZATION */
- PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
if (oparg & 1) {
/* Designed to work in tandem with CALL, pushes two values. */
PyObject* meth = NULL;
@@ -1772,14 +1804,25 @@ dummy_func(
}
}
- inst(LOAD_ATTR_INSTANCE_VALUE, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) {
+ pseudo(LOAD_METHOD) = {
+ LOAD_ATTR,
+ };
+
+ op(_GUARD_TYPE_VERSION, (type_version/2, owner -- owner)) {
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
- assert(tp->tp_dictoffset < 0);
- assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
+ }
+
+ op(_CHECK_MANAGED_OBJECT_HAS_VALUES, (owner -- owner)) {
+ assert(Py_TYPE(owner)->tp_dictoffset < 0);
+ assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);
+ }
+
+ op(_LOAD_ATTR_INSTANCE_VALUE, (index/1, unused/5, owner -- res2 if (oparg & 1), res)) {
+ PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
res = _PyDictOrValues_GetValues(dorv)->values[index];
DEOPT_IF(res == NULL, LOAD_ATTR);
STAT_INC(LOAD_ATTR, hit);
@@ -1788,6 +1831,12 @@ dummy_func(
DECREF_INPUTS();
}
+ macro(LOAD_ATTR_INSTANCE_VALUE) =
+ _SKIP_CACHE + // Skip over the counter
+ _GUARD_TYPE_VERSION +
+ _CHECK_MANAGED_OBJECT_HAS_VALUES +
+ _LOAD_ATTR_INSTANCE_VALUE;
+
inst(LOAD_ATTR_MODULE, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) {
DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR);
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
@@ -1814,7 +1863,7 @@ dummy_func(
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
DEOPT_IF(dict == NULL, LOAD_ATTR);
assert(PyDict_CheckExact((PyObject *)dict));
- PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
uint16_t hint = index;
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR);
if (DK_IS_UNICODE(dict->ma_keys)) {
@@ -1883,7 +1932,7 @@ dummy_func(
int shrink_stack = !(oparg & 1);
STACK_SHRINK(shrink_stack);
new_frame->localsplus[0] = owner;
- JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_LOAD_ATTR);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
}
@@ -1902,7 +1951,7 @@ dummy_func(
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);
STAT_INC(LOAD_ATTR, hit);
- PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
Py_INCREF(f);
_PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2);
// Manipulate stack directly because we exit with DISPATCH_INLINED().
@@ -1911,7 +1960,7 @@ dummy_func(
STACK_SHRINK(shrink_stack);
new_frame->localsplus[0] = owner;
new_frame->localsplus[1] = Py_NewRef(name);
- JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_LOAD_ATTR);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
}
@@ -1946,7 +1995,7 @@ dummy_func(
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
DEOPT_IF(dict == NULL, STORE_ATTR);
assert(PyDict_CheckExact((PyObject *)dict));
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR);
PyObject *old_value;
uint64_t new_version;
@@ -1989,8 +2038,7 @@ dummy_func(
Py_DECREF(owner);
}
- family(compare_op, INLINE_CACHE_ENTRIES_COMPARE_OP) = {
- COMPARE_OP,
+ family(COMPARE_OP, INLINE_CACHE_ENTRIES_COMPARE_OP) = {
COMPARE_OP_FLOAT,
COMPARE_OP_INT,
COMPARE_OP_STR,
@@ -2007,10 +2055,16 @@ dummy_func(
STAT_INC(COMPARE_OP, deferred);
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
#endif /* ENABLE_SPECIALIZATION */
- assert((oparg >> 4) <= Py_GE);
- res = PyObject_RichCompare(left, right, oparg>>4);
+ assert((oparg >> 5) <= Py_GE);
+ res = PyObject_RichCompare(left, right, oparg >> 5);
DECREF_INPUTS();
ERROR_IF(res == NULL, error);
+ if (oparg & 16) {
+ int res_bool = PyObject_IsTrue(res);
+ Py_DECREF(res);
+ ERROR_IF(res_bool < 0, error);
+ res = res_bool ? Py_True : Py_False;
+ }
}
inst(COMPARE_OP_FLOAT, (unused/1, left, right -- res)) {
@@ -2024,6 +2078,7 @@ dummy_func(
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
res = (sign_ish & oparg) ? Py_True : Py_False;
+ // It's always a bool, so we don't care about oparg & 16.
}
// Similar to COMPARE_OP_FLOAT
@@ -2042,6 +2097,7 @@ dummy_func(
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
res = (sign_ish & oparg) ? Py_True : Py_False;
+ // It's always a bool, so we don't care about oparg & 16.
}
// Similar to COMPARE_OP_FLOAT, but for ==, != only
@@ -2050,13 +2106,14 @@ dummy_func(
DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP);
STAT_INC(COMPARE_OP, hit);
int eq = _PyUnicode_Equal(left, right);
- assert((oparg >>4) == Py_EQ || (oparg >>4) == Py_NE);
+ assert((oparg >> 5) == Py_EQ || (oparg >> 5) == Py_NE);
_Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
_Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
assert(eq == 0 || eq == 1);
assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS);
assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS);
res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False;
+ // It's always a bool, so we don't care about oparg & 16.
}
inst(IS_OP, (left, right -- b)) {
@@ -2106,14 +2163,14 @@ dummy_func(
}
inst(IMPORT_NAME, (level, fromlist -- res)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
res = import_name(tstate, frame, name, fromlist, level);
DECREF_INPUTS();
ERROR_IF(res == NULL, error);
}
inst(IMPORT_FROM, (from -- from, res)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
res = import_from(tstate, from, name);
ERROR_IF(res == NULL, error);
}
@@ -2123,6 +2180,7 @@ dummy_func(
}
inst(JUMP_BACKWARD, (--)) {
+ CHECK_EVAL_BREAKER();
_Py_CODEUNIT *here = next_instr - 1;
assert(oparg <= INSTR_OFFSET());
JUMPBY(1-oparg);
@@ -2133,74 +2191,66 @@ dummy_func(
frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);
if (frame == NULL) {
frame = cframe.current_frame;
- goto error;
+ goto resume_with_error;
}
+ assert(frame == cframe.current_frame);
here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1);
goto resume_frame;
}
#endif /* ENABLE_SPECIALIZATION */
- CHECK_EVAL_BREAKER();
}
+ pseudo(JUMP) = {
+ JUMP_FORWARD,
+ JUMP_BACKWARD,
+ };
+
+ pseudo(JUMP_NO_INTERRUPT) = {
+ JUMP_FORWARD,
+ JUMP_BACKWARD_NO_INTERRUPT,
+ };
+
inst(ENTER_EXECUTOR, (--)) {
- _PyExecutorObject *executor = (_PyExecutorObject *)frame->f_code->co_executors->executors[oparg];
+ CHECK_EVAL_BREAKER();
+
+ PyCodeObject *code = _PyFrame_GetCode(frame);
+ _PyExecutorObject *executor = (_PyExecutorObject *)code->co_executors->executors[oparg&255];
+ int original_oparg = executor->vm_data.oparg | (oparg & 0xfffff00);
+ JUMPBY(1-original_oparg);
+ frame->prev_instr = next_instr - 1;
Py_INCREF(executor);
frame = executor->execute(executor, frame, stack_pointer);
if (frame == NULL) {
frame = cframe.current_frame;
- goto error;
+ goto resume_with_error;
}
goto resume_frame;
}
inst(POP_JUMP_IF_FALSE, (cond -- )) {
- if (Py_IsFalse(cond)) {
- JUMPBY(oparg);
- }
- else if (!Py_IsTrue(cond)) {
- int err = PyObject_IsTrue(cond);
- DECREF_INPUTS();
- if (err == 0) {
- JUMPBY(oparg);
- }
- else {
- ERROR_IF(err < 0, error);
- }
- }
+ assert(PyBool_Check(cond));
+ JUMPBY(oparg * Py_IsFalse(cond));
}
inst(POP_JUMP_IF_TRUE, (cond -- )) {
- if (Py_IsTrue(cond)) {
- JUMPBY(oparg);
- }
- else if (!Py_IsFalse(cond)) {
- int err = PyObject_IsTrue(cond);
- DECREF_INPUTS();
- if (err > 0) {
- JUMPBY(oparg);
- }
- else {
- ERROR_IF(err < 0, error);
- }
- }
+ assert(PyBool_Check(cond));
+ JUMPBY(oparg * Py_IsTrue(cond));
}
- inst(POP_JUMP_IF_NOT_NONE, (value -- )) {
- if (!Py_IsNone(value)) {
- DECREF_INPUTS();
- JUMPBY(oparg);
- }
- }
-
- inst(POP_JUMP_IF_NONE, (value -- )) {
+ op(IS_NONE, (value -- b)) {
if (Py_IsNone(value)) {
- JUMPBY(oparg);
+ b = Py_True;
}
else {
+ b = Py_False;
DECREF_INPUTS();
}
}
+ macro(POP_JUMP_IF_NONE) = IS_NONE + POP_JUMP_IF_TRUE;
+
+ macro(POP_JUMP_IF_NOT_NONE) = IS_NONE + POP_JUMP_IF_FALSE;
+
inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) {
/* This bytecode is used in the `yield from` or `await` loop.
* If there is an interrupt, we want it handled in the innermost
@@ -2260,7 +2310,7 @@ dummy_func(
/* before: [obj]; after [getiter(obj)] */
if (PyCoro_CheckExact(iterable)) {
/* `iterable` is a coroutine */
- if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
+ if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
/* and it is used in a 'yield from' expression of a
regular generator. */
_PyErr_SetString(tstate, PyExc_TypeError,
@@ -2289,8 +2339,7 @@ dummy_func(
// This is optimized by skipping that instruction and combining
// its effect (popping 'iter' instead of pushing 'next'.)
- family(for_iter, INLINE_CACHE_ENTRIES_FOR_ITER) = {
- FOR_ITER,
+ family(FOR_ITER, INLINE_CACHE_ENTRIES_FOR_ITER) = {
FOR_ITER_LIST,
FOR_ITER_TUPLE,
FOR_ITER_RANGE,
@@ -2323,8 +2372,9 @@ dummy_func(
next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == INSTRUMENTED_END_FOR);
Py_DECREF(iter);
STACK_SHRINK(1);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
/* Jump forward oparg, then skip following END_FOR instruction */
- JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
+ JUMPBY(oparg + 1);
DISPATCH();
}
// Common case: no jump, leave it to the code generator
@@ -2358,70 +2408,161 @@ dummy_func(
INSTRUMENTED_JUMP(here, target, PY_MONITORING_EVENT_BRANCH);
}
- inst(FOR_ITER_LIST, (unused/1, iter -- iter, next)) {
+ op(_ITER_CHECK_LIST, (iter -- iter)) {
DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER);
+ }
+
+ op(_ITER_JUMP_LIST, (iter -- iter)) {
_PyListIterObject *it = (_PyListIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyListIter_Type);
STAT_INC(FOR_ITER, hit);
PyListObject *seq = it->it_seq;
- if (seq) {
- if (it->it_index < PyList_GET_SIZE(seq)) {
- next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++));
- goto end_for_iter_list; // End of this instruction
+ if (seq == NULL || it->it_index >= PyList_GET_SIZE(seq)) {
+ if (seq != NULL) {
+ it->it_seq = NULL;
+ Py_DECREF(seq);
}
- it->it_seq = NULL;
+ Py_DECREF(iter);
+ STACK_SHRINK(1);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
+ /* Jump forward oparg, then skip following END_FOR instruction */
+ JUMPBY(oparg + 1);
+ DISPATCH();
+ }
+ }
+
+ // Only used by Tier 2
+ op(_IS_ITER_EXHAUSTED_LIST, (iter -- iter, exhausted)) {
+ _PyListIterObject *it = (_PyListIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyListIter_Type);
+ PyListObject *seq = it->it_seq;
+ if (seq == NULL) {
+ exhausted = Py_True;
+ }
+ else if (it->it_index >= PyList_GET_SIZE(seq)) {
Py_DECREF(seq);
+ it->it_seq = NULL;
+ exhausted = Py_True;
}
- Py_DECREF(iter);
- STACK_SHRINK(1);
- /* Jump forward oparg, then skip following END_FOR instruction */
- JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
- DISPATCH();
- end_for_iter_list:
- // Common case: no jump, leave it to the code generator
+ else {
+ exhausted = Py_False;
+ }
+ }
+
+ op(_ITER_NEXT_LIST, (iter -- iter, next)) {
+ _PyListIterObject *it = (_PyListIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyListIter_Type);
+ PyListObject *seq = it->it_seq;
+ assert(seq);
+ assert(it->it_index < PyList_GET_SIZE(seq));
+ next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++));
}
- inst(FOR_ITER_TUPLE, (unused/1, iter -- iter, next)) {
+ macro(FOR_ITER_LIST) =
+ unused/1 + // Skip over the counter
+ _ITER_CHECK_LIST +
+ _ITER_JUMP_LIST +
+ _ITER_NEXT_LIST;
+
+ op(_ITER_CHECK_TUPLE, (iter -- iter)) {
+ DEOPT_IF(Py_TYPE(iter) != &PyTupleIter_Type, FOR_ITER);
+ }
+
+ op(_ITER_JUMP_TUPLE, (iter -- iter)) {
_PyTupleIterObject *it = (_PyTupleIterObject *)iter;
- DEOPT_IF(Py_TYPE(it) != &PyTupleIter_Type, FOR_ITER);
+ assert(Py_TYPE(iter) == &PyTupleIter_Type);
STAT_INC(FOR_ITER, hit);
PyTupleObject *seq = it->it_seq;
- if (seq) {
- if (it->it_index < PyTuple_GET_SIZE(seq)) {
- next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++));
- goto end_for_iter_tuple; // End of this instruction
+ if (seq == NULL || it->it_index >= PyTuple_GET_SIZE(seq)) {
+ if (seq != NULL) {
+ it->it_seq = NULL;
+ Py_DECREF(seq);
}
- it->it_seq = NULL;
+ Py_DECREF(iter);
+ STACK_SHRINK(1);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
+ /* Jump forward oparg, then skip following END_FOR instruction */
+ JUMPBY(oparg + 1);
+ DISPATCH();
+ }
+ }
+
+ // Only used by Tier 2
+ op(_IS_ITER_EXHAUSTED_TUPLE, (iter -- iter, exhausted)) {
+ _PyTupleIterObject *it = (_PyTupleIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyTupleIter_Type);
+ PyTupleObject *seq = it->it_seq;
+ if (seq == NULL) {
+ exhausted = Py_True;
+ }
+ else if (it->it_index >= PyTuple_GET_SIZE(seq)) {
Py_DECREF(seq);
+ it->it_seq = NULL;
+ exhausted = Py_True;
+ }
+ else {
+ exhausted = Py_False;
}
- Py_DECREF(iter);
- STACK_SHRINK(1);
- /* Jump forward oparg, then skip following END_FOR instruction */
- JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
- DISPATCH();
- end_for_iter_tuple:
- // Common case: no jump, leave it to the code generator
}
- inst(FOR_ITER_RANGE, (unused/1, iter -- iter, next)) {
+ op(_ITER_NEXT_TUPLE, (iter -- iter, next)) {
+ _PyTupleIterObject *it = (_PyTupleIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyTupleIter_Type);
+ PyTupleObject *seq = it->it_seq;
+ assert(seq);
+ assert(it->it_index < PyTuple_GET_SIZE(seq));
+ next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++));
+ }
+
+ macro(FOR_ITER_TUPLE) =
+ unused/1 + // Skip over the counter
+ _ITER_CHECK_TUPLE +
+ _ITER_JUMP_TUPLE +
+ _ITER_NEXT_TUPLE;
+
+ op(_ITER_CHECK_RANGE, (iter -- iter)) {
_PyRangeIterObject *r = (_PyRangeIterObject *)iter;
DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER);
+ }
+
+ op(_ITER_JUMP_RANGE, (iter -- iter)) {
+ _PyRangeIterObject *r = (_PyRangeIterObject *)iter;
+ assert(Py_TYPE(r) == &PyRangeIter_Type);
STAT_INC(FOR_ITER, hit);
if (r->len <= 0) {
STACK_SHRINK(1);
Py_DECREF(r);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
// Jump over END_FOR instruction.
- JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
+ JUMPBY(oparg + 1);
DISPATCH();
}
+ }
+
+ // Only used by Tier 2
+ op(_IS_ITER_EXHAUSTED_RANGE, (iter -- iter, exhausted)) {
+ _PyRangeIterObject *r = (_PyRangeIterObject *)iter;
+ assert(Py_TYPE(r) == &PyRangeIter_Type);
+ exhausted = r->len <= 0 ? Py_True : Py_False;
+ }
+
+ op(_ITER_NEXT_RANGE, (iter -- iter, next)) {
+ _PyRangeIterObject *r = (_PyRangeIterObject *)iter;
+ assert(Py_TYPE(r) == &PyRangeIter_Type);
+ assert(r->len > 0);
long value = r->start;
r->start = value + r->step;
r->len--;
next = PyLong_FromLong(value);
- if (next == NULL) {
- goto error;
- }
+ ERROR_IF(next == NULL, error);
}
+ macro(FOR_ITER_RANGE) =
+ unused/1 + // Skip over the counter
+ _ITER_CHECK_RANGE +
+ _ITER_JUMP_RANGE +
+ _ITER_NEXT_RANGE;
+
inst(FOR_ITER_GEN, (unused/1, iter -- iter, unused)) {
DEOPT_IF(tstate->interp->eval_frame, FOR_ITER);
PyGenObject *gen = (PyGenObject *)iter;
@@ -2434,7 +2575,7 @@ dummy_func(
gen->gi_frame_state = FRAME_EXECUTING;
gen->gi_exc_state.previous_item = tstate->exc_info;
tstate->exc_info = &gen->gi_exc_state;
- JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
assert(next_instr[oparg].op.code == END_FOR ||
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
DISPATCH_INLINED(gen_frame);
@@ -2530,6 +2671,22 @@ dummy_func(
ERROR_IF(res == NULL, error);
}
+ pseudo(SETUP_FINALLY) = {
+ NOP,
+ };
+
+ pseudo(SETUP_CLEANUP) = {
+ NOP,
+ };
+
+ pseudo(SETUP_WITH) = {
+ NOP,
+ };
+
+ pseudo(POP_BLOCK) = {
+ NOP,
+ };
+
inst(PUSH_EXC_INFO, (new_exc -- prev_exc, new_exc)) {
_PyErr_StackItem *exc_info = tstate->exc_info;
if (exc_info->exc_value != NULL) {
@@ -2542,7 +2699,8 @@ dummy_func(
exc_info->exc_value = Py_NewRef(new_exc);
}
- inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (oparg & 1), res)) {
+ inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (1), res)) {
+ assert(oparg & 1);
/* Cached method object */
PyTypeObject *self_cls = Py_TYPE(self);
assert(type_version != 0);
@@ -2558,10 +2716,10 @@ dummy_func(
res2 = Py_NewRef(descr);
assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR));
res = self;
- assert(oparg & 1);
}
- inst(LOAD_ATTR_METHOD_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (oparg & 1), res)) {
+ inst(LOAD_ATTR_METHOD_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (1), res)) {
+ assert(oparg & 1);
PyTypeObject *self_cls = Py_TYPE(self);
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
assert(self_cls->tp_dictoffset == 0);
@@ -2570,10 +2728,39 @@ dummy_func(
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
res2 = Py_NewRef(descr);
res = self;
- assert(oparg & 1);
}
- inst(LOAD_ATTR_METHOD_LAZY_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (oparg & 1), res)) {
+ inst(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (0), res)) {
+ assert((oparg & 1) == 0);
+ PyTypeObject *self_cls = Py_TYPE(self);
+ assert(type_version != 0);
+ DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
+ assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
+ PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(self);
+ DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);
+ PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls;
+ DEOPT_IF(self_heap_type->ht_cached_keys->dk_version !=
+ keys_version, LOAD_ATTR);
+ STAT_INC(LOAD_ATTR, hit);
+ assert(descr != NULL);
+ DECREF_INPUTS();
+ res = Py_NewRef(descr);
+ }
+
+ inst(LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (0), res)) {
+ assert((oparg & 1) == 0);
+ PyTypeObject *self_cls = Py_TYPE(self);
+ assert(type_version != 0);
+ DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
+ assert(self_cls->tp_dictoffset == 0);
+ STAT_INC(LOAD_ATTR, hit);
+ assert(descr != NULL);
+ DECREF_INPUTS();
+ res = Py_NewRef(descr);
+ }
+
+ inst(LOAD_ATTR_METHOD_LAZY_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (1), res)) {
+ assert(oparg & 1);
PyTypeObject *self_cls = Py_TYPE(self);
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
Py_ssize_t dictoffset = self_cls->tp_dictoffset;
@@ -2586,13 +2773,12 @@ dummy_func(
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
res2 = Py_NewRef(descr);
res = self;
- assert(oparg & 1);
}
inst(KW_NAMES, (--)) {
assert(kwnames == NULL);
- assert(oparg < PyTuple_GET_SIZE(frame->f_code->co_consts));
- kwnames = GETITEM(frame->f_code->co_consts, oparg);
+ assert(oparg < PyTuple_GET_SIZE(FRAME_CO_CONSTS));
+ kwnames = GETITEM(FRAME_CO_CONSTS, oparg);
}
inst(INSTRUMENTED_CALL, ( -- )) {
@@ -2612,8 +2798,7 @@ dummy_func(
// Cache layout: counter/1, func_version/2
// Neither CALL_INTRINSIC_1/2 nor CALL_FUNCTION_EX are members!
- family(call, INLINE_CACHE_ENTRIES_CALL) = {
- CALL,
+ family(CALL, INLINE_CACHE_ENTRIES_CALL) = {
CALL_BOUND_METHOD_EXACT_ARGS,
CALL_PY_EXACT_ARGS,
CALL_PY_WITH_DEFAULTS,
@@ -2631,6 +2816,7 @@ dummy_func(
CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
+ CALL_NO_KW_ALLOC_AND_ENTER_INIT,
};
// On entry, the stack is either
@@ -2689,7 +2875,7 @@ dummy_func(
if (new_frame == NULL) {
goto error;
}
- JUMPBY(INLINE_CACHE_ENTRIES_CALL);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_CALL);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
}
@@ -2763,7 +2949,7 @@ dummy_func(
}
// Manipulate stack directly since we leave using DISPATCH_INLINED().
STACK_SHRINK(oparg + 2);
- JUMPBY(INLINE_CACHE_ENTRIES_CALL);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_CALL);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
}
@@ -2801,7 +2987,7 @@ dummy_func(
}
// Manipulate stack and cache directly since we leave using DISPATCH_INLINED().
STACK_SHRINK(oparg + 2);
- JUMPBY(INLINE_CACHE_ENTRIES_CALL);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_CALL);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
}
@@ -2846,6 +3032,69 @@ dummy_func(
CHECK_EVAL_BREAKER();
}
+ inst(CALL_NO_KW_ALLOC_AND_ENTER_INIT, (unused/1, unused/2, null, callable, args[oparg] -- unused)) {
+ /* This instruction does the following:
+ * 1. Creates the object (by calling ``object.__new__``)
+ * 2. Pushes a shim frame to the frame stack (to cleanup after ``__init__``)
+ * 3. Pushes the frame for ``__init__`` to the frame stack
+ * */
+ assert(kwnames == NULL);
+ _PyCallCache *cache = (_PyCallCache *)next_instr;
+ DEOPT_IF(null != NULL, CALL);
+ DEOPT_IF(!PyType_Check(callable), CALL);
+ PyTypeObject *tp = (PyTypeObject *)callable;
+ DEOPT_IF(tp->tp_version_tag != read_u32(cache->func_version), CALL);
+ PyHeapTypeObject *cls = (PyHeapTypeObject *)callable;
+ PyFunctionObject *init = (PyFunctionObject *)cls->_spec_cache.init;
+ PyCodeObject *code = (PyCodeObject *)init->func_code;
+ DEOPT_IF(code->co_argcount != oparg+1, CALL);
+ DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize + _Py_InitCleanup.co_framesize), CALL);
+ STAT_INC(CALL, hit);
+ PyObject *self = _PyType_NewManagedObject(tp);
+ if (self == NULL) {
+ goto error;
+ }
+ Py_DECREF(tp);
+ _PyInterpreterFrame *shim = _PyFrame_PushTrampolineUnchecked(
+ tstate, (PyCodeObject *)&_Py_InitCleanup, 1, 0);
+ assert(_PyCode_CODE((PyCodeObject *)shim->f_executable)[1].op.code == EXIT_INIT_CHECK);
+ /* Push self onto stack of shim */
+ Py_INCREF(self);
+ shim->localsplus[0] = self;
+ Py_INCREF(init);
+ _PyInterpreterFrame *init_frame = _PyFrame_PushUnchecked(tstate, init, oparg+1);
+ /* Copy self followed by args to __init__ frame */
+ init_frame->localsplus[0] = self;
+ for (int i = 0; i < oparg; i++) {
+ init_frame->localsplus[i+1] = args[i];
+ }
+ SKIP_OVER(INLINE_CACHE_ENTRIES_CALL);
+ frame->prev_instr = next_instr - 1;
+ frame->return_offset = 0;
+ STACK_SHRINK(oparg+2);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ /* Link frames */
+ init_frame->previous = shim;
+ shim->previous = frame;
+ frame = cframe.current_frame = init_frame;
+ CALL_STAT_INC(inlined_py_calls);
+ /* Account for pushing the extra frame.
+ * We don't check recursion depth here,
+ * as it will be checked after start_frame */
+ tstate->py_recursion_remaining--;
+ goto start_frame;
+ }
+
+ inst(EXIT_INIT_CHECK, (should_be_none -- )) {
+ assert(STACK_LEVEL() == 2);
+ if (should_be_none != Py_None) {
+ PyErr_Format(PyExc_TypeError,
+ "__init__() should return None, not '%.200s'",
+ Py_TYPE(should_be_none)->tp_name);
+ goto error;
+ }
+ }
+
inst(CALL_BUILTIN_CLASS, (unused/1, unused/2, method, callable, args[oparg] -- res)) {
int is_meth = method != NULL;
int total_args = oparg;
@@ -3044,7 +3293,7 @@ dummy_func(
Py_DECREF(method);
STACK_SHRINK(3);
// CALL + POP_TOP
- JUMPBY(INLINE_CACHE_ENTRIES_CALL + 1);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_CALL + 1);
assert(next_instr[-1].op.code == POP_TOP);
DISPATCH();
}
@@ -3250,11 +3499,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}
- inst(MAKE_FUNCTION, (defaults if (oparg & MAKE_FUNCTION_DEFAULTS),
- kwdefaults if (oparg & MAKE_FUNCTION_KWDEFAULTS),
- annotations if (oparg & MAKE_FUNCTION_ANNOTATIONS),
- closure if (oparg & MAKE_FUNCTION_CLOSURE),
- codeobj -- func)) {
+ inst(MAKE_FUNCTION, (codeobj -- func)) {
PyFunctionObject *func_obj = (PyFunctionObject *)
PyFunction_New(codeobj, GLOBALS());
@@ -3264,27 +3509,37 @@ dummy_func(
goto error;
}
- if (oparg & MAKE_FUNCTION_CLOSURE) {
- assert(PyTuple_CheckExact(closure));
- func_obj->func_closure = closure;
- }
- if (oparg & MAKE_FUNCTION_ANNOTATIONS) {
- assert(PyTuple_CheckExact(annotations));
- func_obj->func_annotations = annotations;
- }
- if (oparg & MAKE_FUNCTION_KWDEFAULTS) {
- assert(PyDict_CheckExact(kwdefaults));
- func_obj->func_kwdefaults = kwdefaults;
- }
- if (oparg & MAKE_FUNCTION_DEFAULTS) {
- assert(PyTuple_CheckExact(defaults));
- func_obj->func_defaults = defaults;
- }
-
func_obj->func_version = ((PyCodeObject *)codeobj)->co_version;
func = (PyObject *)func_obj;
}
+ inst(SET_FUNCTION_ATTRIBUTE, (attr, func -- func)) {
+ assert(PyFunction_Check(func));
+ PyFunctionObject *func_obj = (PyFunctionObject *)func;
+ switch(oparg) {
+ case MAKE_FUNCTION_CLOSURE:
+ assert(func_obj->func_closure == NULL);
+ func_obj->func_closure = attr;
+ break;
+ case MAKE_FUNCTION_ANNOTATIONS:
+ assert(func_obj->func_annotations == NULL);
+ func_obj->func_annotations = attr;
+ break;
+ case MAKE_FUNCTION_KWDEFAULTS:
+ assert(PyDict_CheckExact(attr));
+ assert(func_obj->func_kwdefaults == NULL);
+ func_obj->func_kwdefaults = attr;
+ break;
+ case MAKE_FUNCTION_DEFAULTS:
+ assert(PyTuple_CheckExact(attr));
+ assert(func_obj->func_defaults == NULL);
+ func_obj->func_defaults = attr;
+ break;
+ default:
+ Py_UNREACHABLE();
+ }
+ }
+
inst(RETURN_GENERATOR, (--)) {
assert(PyFunction_Check(frame->f_funcobj));
PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;
@@ -3314,41 +3569,33 @@ dummy_func(
ERROR_IF(slice == NULL, error);
}
- inst(FORMAT_VALUE, (value, fmt_spec if ((oparg & FVS_MASK) == FVS_HAVE_SPEC) -- result)) {
- /* Handles f-string value formatting. */
- PyObject *(*conv_fn)(PyObject *);
- int which_conversion = oparg & FVC_MASK;
-
- /* See if any conversion is specified. */
- switch (which_conversion) {
- case FVC_NONE: conv_fn = NULL; break;
- case FVC_STR: conv_fn = PyObject_Str; break;
- case FVC_REPR: conv_fn = PyObject_Repr; break;
- case FVC_ASCII: conv_fn = PyObject_ASCII; break;
- default:
- _PyErr_Format(tstate, PyExc_SystemError,
- "unexpected conversion flag %d",
- which_conversion);
- goto error;
- }
+ inst(CONVERT_VALUE, (value -- result)) {
+ convertion_func_ptr conv_fn;
+ assert(oparg >= FVC_STR && oparg <= FVC_ASCII);
+ conv_fn = CONVERSION_FUNCTIONS[oparg];
+ result = conv_fn(value);
+ Py_DECREF(value);
+ ERROR_IF(result == NULL, error);
+ }
- /* If there's a conversion function, call it and replace
- value with that result. Otherwise, just use value,
- without conversion. */
- if (conv_fn != NULL) {
- result = conv_fn(value);
+ inst(FORMAT_SIMPLE, (value -- res)) {
+ /* If value is a unicode object, then we know the result
+ * of format(value) is value itself. */
+ if (!PyUnicode_CheckExact(value)) {
+ res = PyObject_Format(value, NULL);
Py_DECREF(value);
- if (result == NULL) {
- Py_XDECREF(fmt_spec);
- ERROR_IF(true, error);
- }
- value = result;
+ ERROR_IF(res == NULL, error);
+ }
+ else {
+ res = value;
}
+ }
- result = PyObject_Format(value, fmt_spec);
+ inst(FORMAT_WITH_SPEC, (value, fmt_spec -- res)) {
+ res = PyObject_Format(value, fmt_spec);
Py_DECREF(value);
- Py_XDECREF(fmt_spec);
- ERROR_IF(result == NULL, error);
+ Py_DECREF(fmt_spec);
+ ERROR_IF(res == NULL, error);
}
inst(COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) {
@@ -3399,29 +3646,23 @@ dummy_func(
}
inst(INSTRUMENTED_JUMP_BACKWARD, ( -- )) {
- INSTRUMENTED_JUMP(next_instr-1, next_instr+1-oparg, PY_MONITORING_EVENT_JUMP);
CHECK_EVAL_BREAKER();
+ INSTRUMENTED_JUMP(next_instr-1, next_instr+1-oparg, PY_MONITORING_EVENT_JUMP);
}
inst(INSTRUMENTED_POP_JUMP_IF_TRUE, ( -- )) {
PyObject *cond = POP();
- int err = PyObject_IsTrue(cond);
- Py_DECREF(cond);
- ERROR_IF(err < 0, error);
- _Py_CODEUNIT *here = next_instr-1;
- assert(err == 0 || err == 1);
- int offset = err*oparg;
+ assert(PyBool_Check(cond));
+ _Py_CODEUNIT *here = next_instr - 1;
+ int offset = Py_IsTrue(cond) * oparg;
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
}
inst(INSTRUMENTED_POP_JUMP_IF_FALSE, ( -- )) {
PyObject *cond = POP();
- int err = PyObject_IsTrue(cond);
- Py_DECREF(cond);
- ERROR_IF(err < 0, error);
- _Py_CODEUNIT *here = next_instr-1;
- assert(err == 0 || err == 1);
- int offset = (1-err)*oparg;
+ assert(PyBool_Check(cond));
+ _Py_CODEUNIT *here = next_instr - 1;
+ int offset = Py_IsFalse(cond) * oparg;
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
}
@@ -3448,7 +3689,7 @@ dummy_func(
}
else {
Py_DECREF(value);
- offset = oparg;
+ offset = oparg;
}
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
}
@@ -3471,6 +3712,36 @@ dummy_func(
Py_UNREACHABLE();
}
+ ///////// Tier-2 only opcodes /////////
+
+ op(_POP_JUMP_IF_FALSE, (flag -- )) {
+ if (Py_IsFalse(flag)) {
+ pc = oparg;
+ }
+ }
+
+ op(_POP_JUMP_IF_TRUE, (flag -- )) {
+ if (Py_IsTrue(flag)) {
+ pc = oparg;
+ }
+ }
+
+ op(JUMP_TO_TOP, (--)) {
+ pc = 0;
+ CHECK_EVAL_BREAKER();
+ }
+
+ op(SAVE_IP, (--)) {
+ frame->prev_instr = ip_offset + oparg;
+ }
+
+ op(EXIT_TRACE, (--)) {
+ frame->prev_instr--; // Back up to just before destination
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ Py_DECREF(self);
+ return frame;
+ }
+
// END BYTECODES //
diff --git a/Python/ceval.c b/Python/ceval.c
index e81b6beedfcee1..d6c72fa3ff386c 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -4,7 +4,7 @@
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
-#include "pycore_call.h" // _PyObject_FastCallDictTstate()
+#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_ceval.h" // _PyEval_SignalAsyncExc()
#include "pycore_code.h"
#include "pycore_function.h"
@@ -14,6 +14,7 @@
#include "pycore_object.h" // _PyObject_GC_TRACK()
#include "pycore_moduleobject.h" // PyModuleObject
#include "pycore_opcode.h" // EXTRA_CASES
+#include "pycore_opcode_metadata.h"
#include "pycore_opcode_utils.h" // MAKE_FUNCTION_*
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
@@ -22,6 +23,7 @@
#include "pycore_sysmodule.h" // _PySys_Audit()
#include "pycore_tuple.h" // _PyTuple_ITEMS()
#include "pycore_typeobject.h" // _PySuper_Lookup()
+#include "pycore_uops.h" // _PyUOpExecutorObject
#include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS
#include "pycore_dict.h"
@@ -129,6 +131,9 @@ lltrace_instruction(_PyInterpreterFrame *frame,
PyObject **stack_pointer,
_Py_CODEUNIT *next_instr)
{
+ if (frame->owner == FRAME_OWNED_BY_CSTACK) {
+ return;
+ }
/* This dump_stack() operation is risky, since the repr() of some
objects enters the interpreter recursively. It is also slow.
So you might want to comment it out. */
@@ -137,8 +142,8 @@ lltrace_instruction(_PyInterpreterFrame *frame,
int opcode = next_instr->op.code;
const char *opname = _PyOpcode_OpName[opcode];
assert(opname != NULL);
- int offset = (int)(next_instr - _PyCode_CODE(frame->f_code));
- if (HAS_ARG((int)_PyOpcode_Deopt[opcode])) {
+ int offset = (int)(next_instr - _PyCode_CODE(_PyFrame_GetCode(frame)));
+ if (OPCODE_HAS_ARG((int)_PyOpcode_Deopt[opcode])) {
printf("%d: %s %d\n", offset * 2, opname, oparg);
}
else {
@@ -150,7 +155,7 @@ static void
lltrace_resume_frame(_PyInterpreterFrame *frame)
{
PyObject *fobj = frame->f_funcobj;
- if (frame->owner == FRAME_OWNED_BY_CSTACK ||
+ if (!PyCode_Check(frame->f_executable) ||
fobj == NULL ||
!PyFunction_Check(fobj)
) {
@@ -413,10 +418,8 @@ match_class_attr(PyThreadState *tstate, PyObject *subject, PyObject *type,
}
return NULL;
}
- PyObject *attr = PyObject_GetAttr(subject, name);
- if (attr == NULL && _PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {
- _PyErr_Clear(tstate);
- }
+ PyObject *attr;
+ (void)PyObject_GetOptionalAttr(subject, name, &attr);
return attr;
}
@@ -451,7 +454,9 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type,
// First, the positional subpatterns:
if (nargs) {
int match_self = 0;
- match_args = PyObject_GetAttrString(type, "__match_args__");
+ if (PyObject_GetOptionalAttr(type, &_Py_ID(__match_args__), &match_args) < 0) {
+ goto fail;
+ }
if (match_args) {
if (!PyTuple_CheckExact(match_args)) {
const char *e = "%s.__match_args__ must be a tuple (got %s)";
@@ -461,8 +466,7 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type,
goto fail;
}
}
- else if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {
- _PyErr_Clear(tstate);
+ else {
// _Py_TPFLAGS_MATCH_SELF is only acknowledged if the type does not
// define __match_args__. This is natural behavior for subclasses:
// it's as if __match_args__ is some "magic" value that is lost as
@@ -471,9 +475,6 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type,
match_self = PyType_HasFeature((PyTypeObject*)type,
_Py_TPFLAGS_MATCH_SELF);
}
- else {
- goto fail;
- }
assert(PyTuple_CheckExact(match_args));
Py_ssize_t allowed = match_self ? 1 : PyTuple_GET_SIZE(match_args);
if (allowed < nargs) {
@@ -621,6 +622,15 @@ static inline void _Py_LeaveRecursiveCallPy(PyThreadState *tstate) {
tstate->py_recursion_remaining++;
}
+static const _Py_CODEUNIT _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS[] = {
+ /* Put a NOP at the start, so that the IP points into
+ * the code, rather than before it */
+ { .op.code = NOP, .op.arg = 0 },
+ { .op.code = INTERPRETER_EXIT, .op.arg = 0 },
+ { .op.code = RESUME, .op.arg = 0 }
+};
+
+extern const struct _PyCode_DEF(8) _Py_InitCleanup;
/* Disable unused label warnings. They are handy for debugging, even
if computed gotos aren't used. */
@@ -668,7 +678,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
cframe.previous = prev_cframe;
tstate->cframe = &cframe;
- assert(tstate->interp->interpreter_trampoline != NULL);
#ifdef Py_DEBUG
/* Set these to invalid but identifiable values for debugging. */
entry_frame.f_funcobj = (PyObject*)0xaaa0;
@@ -677,9 +686,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
entry_frame.f_globals = (PyObject*)0xaaa3;
entry_frame.f_builtins = (PyObject*)0xaaa4;
#endif
- entry_frame.f_code = tstate->interp->interpreter_trampoline;
- entry_frame.prev_instr =
- _PyCode_CODE(tstate->interp->interpreter_trampoline);
+ entry_frame.f_executable = Py_None;
+ entry_frame.prev_instr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS;
entry_frame.stacktop = 0;
entry_frame.owner = FRAME_OWNED_BY_CSTACK;
entry_frame.return_offset = 0;
@@ -701,7 +709,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
}
/* Because this avoids the RESUME,
* we need to update instrumentation */
- _Py_Instrument(frame->f_code, tstate->interp);
+ _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
monitor_throw(tstate, frame, frame->prev_instr);
/* TO DO -- Monitor throw entry. */
goto resume_with_error;
@@ -715,7 +723,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
/* Sets the above local variables from the frame */
#define SET_LOCALS_FROM_FRAME() \
- assert(_PyInterpreterFrame_LASTI(frame) >= -1); \
/* Jump back to the last instruction executed... */ \
next_instr = frame->prev_instr + 1; \
stack_pointer = _PyFrame_GetStackPointer(frame);
@@ -730,7 +737,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
#ifdef LLTRACE
{
- if (frame != &entry_frame) {
+ if (frame != &entry_frame && GLOBALS()) {
int r = PyDict_Contains(GLOBALS(), &_Py_ID(__lltrace__));
if (r < 0) {
goto exit_unwind;
@@ -752,18 +759,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
-handle_eval_breaker:
-
- /* Do periodic things, like check for signals and async I/0.
- * We need to do reasonably frequently, but not too frequently.
- * All loops should include a check of the eval breaker.
- * We also check on return from any builtin function.
- */
- if (_Py_HandlePending(tstate) != 0) {
- goto error;
- }
- DISPATCH();
-
{
/* Start instructions */
#if !USE_COMPUTED_GOTOS
@@ -812,14 +807,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
#if USE_COMPUTED_GOTOS
_unknown_opcode:
#else
- EXTRA_CASES // From opcode.h, a 'case' for each unused opcode
+ EXTRA_CASES // From pycore_opcode.h, a 'case' for each unused opcode
#endif
/* Tell C compilers not to hold the opcode variable in the loop.
next_instr points the current instruction without TARGET(). */
opcode = next_instr->op.code;
_PyErr_Format(tstate, PyExc_SystemError,
"%U:%d: unknown opcode %d",
- frame->f_code->co_filename,
+ _PyFrame_GetCode(frame)->co_filename,
PyUnstable_InterpreterFrame_GetLine(frame),
opcode);
goto error;
@@ -834,7 +829,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
{
format_exc_check_arg(tstate, PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG,
- PyTuple_GetItem(frame->f_code->co_localsplusnames, oparg)
+ PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg)
);
goto error;
}
@@ -874,7 +869,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
/* We can't use frame->f_lasti here, as RERAISE may have set it */
int offset = INSTR_OFFSET()-1;
int level, handler, lasti;
- if (get_exception_handler(frame->f_code, offset, &level, &handler, &lasti) == 0) {
+ if (get_exception_handler(_PyFrame_GetCode(frame), offset, &level, &handler, &lasti) == 0) {
// No handlers, so exit.
assert(_PyErr_Occurred(tstate));
@@ -1468,12 +1463,12 @@ clear_thread_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
assert(frame->owner == FRAME_OWNED_BY_THREAD);
// Make sure that this is, indeed, the top frame. We can't check this in
// _PyThreadState_PopFrame, since f_code is already cleared at that point:
- assert((PyObject **)frame + frame->f_code->co_framesize ==
+ assert((PyObject **)frame + _PyFrame_GetCode(frame)->co_framesize ==
tstate->datastack_top);
tstate->c_recursion_remaining--;
assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
_PyFrame_ClearExceptCode(frame);
- Py_DECREF(frame->f_code);
+ Py_DECREF(frame->f_executable);
tstate->c_recursion_remaining++;
_PyThreadState_PopFrame(tstate, frame);
}
@@ -1958,7 +1953,7 @@ do_monitor_exc(PyThreadState *tstate, _PyInterpreterFrame *frame,
static inline int
no_tools_for_event(PyThreadState *tstate, _PyInterpreterFrame *frame, int event)
{
- _PyCoMonitoringData *data = frame->f_code->_co_monitoring;
+ _PyCoMonitoringData *data = _PyFrame_GetCode(frame)->_co_monitoring;
if (data) {
if (data->active_monitors.tools[event] == 0) {
return 1;
@@ -2257,6 +2252,19 @@ PyEval_GetLocals(void)
return locals;
}
+PyObject *
+_PyEval_GetFrameLocals(void)
+{
+ PyThreadState *tstate = _PyThreadState_GET();
+ _PyInterpreterFrame *current_frame = _PyThreadState_GetFrame(tstate);
+ if (current_frame == NULL) {
+ _PyErr_SetString(tstate, PyExc_SystemError, "frame does not exist");
+ return NULL;
+ }
+
+ return _PyFrame_GetLocals(current_frame, 1);
+}
+
PyObject *
PyEval_GetGlobals(void)
{
@@ -2276,7 +2284,7 @@ PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
int result = cf->cf_flags != 0;
if (current_frame != NULL) {
- const int codeflags = current_frame->f_code->co_flags;
+ const int codeflags = _PyFrame_GetCode(current_frame)->co_flags;
const int compilerflags = codeflags & PyCF_MASK;
if (compilerflags) {
result = 1;
@@ -2365,40 +2373,37 @@ static PyObject *
import_name(PyThreadState *tstate, _PyInterpreterFrame *frame,
PyObject *name, PyObject *fromlist, PyObject *level)
{
- PyObject *import_func, *res;
- PyObject* stack[5];
-
- import_func = _PyDict_GetItemWithError(frame->f_builtins, &_Py_ID(__import__));
+ PyObject *import_func = _PyDict_GetItemWithError(frame->f_builtins,
+ &_Py_ID(__import__));
if (import_func == NULL) {
if (!_PyErr_Occurred(tstate)) {
_PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found");
}
return NULL;
}
+
PyObject *locals = frame->f_locals;
+ if (locals == NULL) {
+ locals = Py_None;
+ }
+
/* Fast path for not overloaded __import__. */
if (_PyImport_IsDefaultImportFunc(tstate->interp, import_func)) {
int ilevel = _PyLong_AsInt(level);
if (ilevel == -1 && _PyErr_Occurred(tstate)) {
return NULL;
}
- res = PyImport_ImportModuleLevelObject(
+ return PyImport_ImportModuleLevelObject(
name,
frame->f_globals,
- locals == NULL ? Py_None :locals,
+ locals,
fromlist,
ilevel);
- return res;
}
+ PyObject* args[5] = {name, frame->f_globals, locals, fromlist, level};
Py_INCREF(import_func);
-
- stack[0] = name;
- stack[1] = frame->f_globals;
- stack[2] = locals == NULL ? Py_None : locals;
- stack[3] = fromlist;
- stack[4] = level;
- res = _PyObject_FastCall(import_func, stack, 5);
+ PyObject *res = PyObject_Vectorcall(import_func, args, 5, NULL);
Py_DECREF(import_func);
return res;
}
@@ -2409,7 +2414,7 @@ import_from(PyThreadState *tstate, PyObject *v, PyObject *name)
PyObject *x;
PyObject *fullmodname, *pkgname, *pkgpath, *pkgname_or_unknown, *errmsg;
- if (_PyObject_LookupAttr(v, name, &x) != 0) {
+ if (PyObject_GetOptionalAttr(v, name, &x) != 0) {
return x;
}
/* Issue #17636: in case this failed because of a circular relative
@@ -2698,3 +2703,105 @@ void Py_LeaveRecursiveCall(void)
{
_Py_LeaveRecursiveCall();
}
+
+///////////////////// Experimental UOp Interpreter /////////////////////
+
+#undef DEOPT_IF
+#define DEOPT_IF(COND, INSTNAME) \
+ if ((COND)) { \
+ goto deoptimize; \
+ }
+
+_PyInterpreterFrame *
+_PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **stack_pointer)
+{
+#ifdef Py_DEBUG
+ char *uop_debug = Py_GETENV("PYTHONUOPSDEBUG");
+ int lltrace = 0;
+ if (uop_debug != NULL && *uop_debug >= '0') {
+ lltrace = *uop_debug - '0'; // TODO: Parse an int and all that
+ }
+#define DPRINTF(level, ...) \
+ if (lltrace >= (level)) { fprintf(stderr, __VA_ARGS__); }
+#else
+#define DPRINTF(level, ...)
+#endif
+
+ DPRINTF(3,
+ "Entering _PyUopExecute for %s (%s:%d) at byte offset %ld\n",
+ PyUnicode_AsUTF8(_PyFrame_GetCode(frame)->co_qualname),
+ PyUnicode_AsUTF8(_PyFrame_GetCode(frame)->co_filename),
+ _PyFrame_GetCode(frame)->co_firstlineno,
+ 2 * (long)(frame->prev_instr + 1 -
+ (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive));
+
+ PyThreadState *tstate = _PyThreadState_GET();
+ _PyUOpExecutorObject *self = (_PyUOpExecutorObject *)executor;
+
+ CHECK_EVAL_BREAKER();
+
+ OBJECT_STAT_INC(optimization_traces_executed);
+ _Py_CODEUNIT *ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive;
+ int pc = 0;
+ int opcode;
+ uint64_t operand;
+ int oparg;
+ for (;;) {
+ opcode = self->trace[pc].opcode;
+ operand = self->trace[pc].operand;
+ oparg = (int)operand;
+ DPRINTF(3,
+ "%4d: uop %s, operand %" PRIu64 ", stack_level %d\n",
+ pc,
+ opcode < 256 ? _PyOpcode_OpName[opcode] : _PyOpcode_uop_name[opcode],
+ operand,
+ (int)(stack_pointer - _PyFrame_Stackbase(frame)));
+ pc++;
+ OBJECT_STAT_INC(optimization_uops_executed);
+ switch (opcode) {
+
+#undef ENABLE_SPECIALIZATION
+#define ENABLE_SPECIALIZATION 0
+#include "executor_cases.c.h"
+
+ default:
+ {
+ fprintf(stderr, "Unknown uop %d, operand %" PRIu64 "\n", opcode, operand);
+ Py_FatalError("Unknown uop");
+ }
+
+ }
+ }
+
+unbound_local_error:
+ format_exc_check_arg(tstate, PyExc_UnboundLocalError,
+ UNBOUNDLOCAL_ERROR_MSG,
+ PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg)
+ );
+ goto error;
+
+pop_4_error:
+ STACK_SHRINK(1);
+pop_3_error:
+ STACK_SHRINK(1);
+pop_2_error:
+ STACK_SHRINK(1);
+pop_1_error:
+ STACK_SHRINK(1);
+error:
+ // On ERROR_IF we return NULL as the frame.
+ // The caller recovers the frame from cframe.current_frame.
+ DPRINTF(2, "Error: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ Py_DECREF(self);
+ return NULL;
+
+deoptimize:
+ // On DEOPT_IF we just repeat the last instruction.
+ // This presumes nothing was popped from the stack (nor pushed).
+ DPRINTF(2, "DEOPT: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand);
+ frame->prev_instr--; // Back up to just before destination
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ Py_DECREF(self);
+ return frame;
+}
diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c
index 723cf0f4df94d0..7c9ad07cc7207b 100644
--- a/Python/ceval_gil.c
+++ b/Python/ceval_gil.c
@@ -68,8 +68,9 @@ COMPUTE_EVAL_BREAKER(PyInterpreterState *interp,
_Py_atomic_load_relaxed_int32(&ceval2->gil_drop_request)
| (_Py_atomic_load_relaxed_int32(&ceval->signals_pending)
&& _Py_ThreadCanHandleSignals(interp))
- | (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do)
- && _Py_ThreadCanHandlePendingCalls())
+ | (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do))
+ | (_Py_IsMainThread() && _Py_IsMainInterpreter(interp)
+ &&_Py_atomic_load_relaxed_int32(&ceval->pending_mainthread.calls_to_do))
| ceval2->pending.async_exc
| _Py_atomic_load_relaxed_int32(&ceval2->gc_scheduled));
}
@@ -95,11 +96,11 @@ RESET_GIL_DROP_REQUEST(PyInterpreterState *interp)
static inline void
-SIGNAL_PENDING_CALLS(PyInterpreterState *interp)
+SIGNAL_PENDING_CALLS(struct _pending_calls *pending, PyInterpreterState *interp)
{
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _ceval_state *ceval2 = &interp->ceval;
- _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 1);
+ _Py_atomic_store_relaxed(&pending->calls_to_do, 1);
COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
}
@@ -109,6 +110,9 @@ UNSIGNAL_PENDING_CALLS(PyInterpreterState *interp)
{
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _ceval_state *ceval2 = &interp->ceval;
+ if (_Py_IsMainThread() && _Py_IsMainInterpreter(interp)) {
+ _Py_atomic_store_relaxed(&ceval->pending_mainthread.calls_to_do, 0);
+ }
_Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 0);
COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
}
@@ -487,7 +491,7 @@ take_gil(PyThreadState *tstate)
void _PyEval_SetSwitchInterval(unsigned long microseconds)
{
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
struct _gil_runtime_state *gil = interp->ceval.gil;
assert(gil != NULL);
gil->interval = microseconds;
@@ -495,7 +499,7 @@ void _PyEval_SetSwitchInterval(unsigned long microseconds)
unsigned long _PyEval_GetSwitchInterval(void)
{
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
struct _gil_runtime_state *gil = interp->ceval.gil;
assert(gil != NULL);
return gil->interval;
@@ -803,19 +807,31 @@ _push_pending_call(struct _pending_calls *pending,
return 0;
}
-/* Pop one item off the queue while holding the lock. */
-static void
-_pop_pending_call(struct _pending_calls *pending,
- int (**func)(void *), void **arg)
+static int
+_next_pending_call(struct _pending_calls *pending,
+ int (**func)(void *), void **arg)
{
int i = pending->first;
if (i == pending->last) {
- return; /* Queue empty */
+ /* Queue empty */
+ assert(pending->calls[i].func == NULL);
+ return -1;
}
-
*func = pending->calls[i].func;
*arg = pending->calls[i].arg;
- pending->first = (i + 1) % NPENDINGCALLS;
+ return i;
+}
+
+/* Pop one item off the queue while holding the lock. */
+static void
+_pop_pending_call(struct _pending_calls *pending,
+ int (**func)(void *), void **arg)
+{
+ int i = _next_pending_call(pending, func, arg);
+ if (i >= 0) {
+ pending->calls[i] = (struct _pending_call){0};
+ pending->first = (i + 1) % NPENDINGCALLS;
+ }
}
/* This implementation is thread-safe. It allows
@@ -825,9 +841,16 @@ _pop_pending_call(struct _pending_calls *pending,
int
_PyEval_AddPendingCall(PyInterpreterState *interp,
- int (*func)(void *), void *arg)
+ int (*func)(void *), void *arg,
+ int mainthreadonly)
{
+ assert(!mainthreadonly || _Py_IsMainInterpreter(interp));
struct _pending_calls *pending = &interp->ceval.pending;
+ if (mainthreadonly) {
+ /* The main thread only exists in the main interpreter. */
+ assert(_Py_IsMainInterpreter(interp));
+ pending = &_PyRuntime.ceval.pending_mainthread;
+ }
/* Ensure that _PyEval_InitState() was called
and that _PyEval_FiniState() is not called yet. */
assert(pending->lock != NULL);
@@ -837,39 +860,17 @@ _PyEval_AddPendingCall(PyInterpreterState *interp,
PyThread_release_lock(pending->lock);
/* signal main loop */
- SIGNAL_PENDING_CALLS(interp);
+ SIGNAL_PENDING_CALLS(pending, interp);
return result;
}
int
Py_AddPendingCall(int (*func)(void *), void *arg)
{
- /* Best-effort to support subinterpreters and calls with the GIL released.
-
- First attempt _PyThreadState_GET() since it supports subinterpreters.
-
- If the GIL is released, _PyThreadState_GET() returns NULL . In this
- case, use PyGILState_GetThisThreadState() which works even if the GIL
- is released.
-
- Sadly, PyGILState_GetThisThreadState() doesn't support subinterpreters:
- see bpo-10915 and bpo-15751.
-
- Py_AddPendingCall() doesn't require the caller to hold the GIL. */
- PyThreadState *tstate = _PyThreadState_GET();
- if (tstate == NULL) {
- tstate = PyGILState_GetThisThreadState();
- }
-
- PyInterpreterState *interp;
- if (tstate != NULL) {
- interp = tstate->interp;
- }
- else {
- /* Last resort: use the main interpreter */
- interp = _PyInterpreterState_Main();
- }
- return _PyEval_AddPendingCall(interp, func, arg);
+ /* Legacy users of this API will continue to target the main thread
+ (of the main interpreter). */
+ PyInterpreterState *interp = _PyInterpreterState_Main();
+ return _PyEval_AddPendingCall(interp, func, arg, 1);
}
static int
@@ -889,27 +890,24 @@ handle_signals(PyThreadState *tstate)
return 0;
}
-static int
-make_pending_calls(PyInterpreterState *interp)
+static inline int
+maybe_has_pending_calls(PyInterpreterState *interp)
{
- /* only execute pending calls on main thread */
- if (!_Py_ThreadCanHandlePendingCalls()) {
- return 0;
+ struct _pending_calls *pending = &interp->ceval.pending;
+ if (_Py_atomic_load_relaxed_int32(&pending->calls_to_do)) {
+ return 1;
}
-
- /* don't perform recursive pending calls */
- if (interp->ceval.pending.busy) {
+ if (!_Py_IsMainThread() || !_Py_IsMainInterpreter(interp)) {
return 0;
}
- interp->ceval.pending.busy = 1;
-
- /* unsignal before starting to call callbacks, so that any callback
- added in-between re-signals */
- UNSIGNAL_PENDING_CALLS(interp);
- int res = 0;
+ pending = &_PyRuntime.ceval.pending_mainthread;
+ return _Py_atomic_load_relaxed_int32(&pending->calls_to_do);
+}
+static int
+_make_pending_calls(struct _pending_calls *pending)
+{
/* perform a bounded number of calls, in case of recursion */
- struct _pending_calls *pending = &interp->ceval.pending;
for (int i=0; iceval.pending;
+ struct _pending_calls *pending_main = &_PyRuntime.ceval.pending_mainthread;
+
+ /* Only one thread (per interpreter) may run the pending calls
+ at once. In the same way, we don't do recursive pending calls. */
+ PyThread_acquire_lock(pending->lock, WAIT_LOCK);
+ if (pending->busy) {
+ /* A pending call was added after another thread was already
+ handling the pending calls (and had already "unsignaled").
+ Once that thread is done, it may have taken care of all the
+ pending calls, or there might be some still waiting.
+ Regardless, this interpreter's pending calls will stay
+ "signaled" until that first thread has finished. At that
+ point the next thread to trip the eval breaker will take
+ care of any remaining pending calls. Until then, though,
+ all the interpreter's threads will be tripping the eval
+ breaker every time it's checked. */
+ PyThread_release_lock(pending->lock);
+ return 0;
+ }
+ pending->busy = 1;
+ PyThread_release_lock(pending->lock);
- interp->ceval.pending.busy = 0;
- return res;
+ /* unsignal before starting to call callbacks, so that any callback
+ added in-between re-signals */
+ UNSIGNAL_PENDING_CALLS(interp);
-error:
- interp->ceval.pending.busy = 0;
- SIGNAL_PENDING_CALLS(interp);
- return res;
+ if (_make_pending_calls(pending) != 0) {
+ pending->busy = 0;
+ /* There might not be more calls to make, but we play it safe. */
+ SIGNAL_PENDING_CALLS(pending, interp);
+ return -1;
+ }
+
+ if (_Py_IsMainThread() && _Py_IsMainInterpreter(interp)) {
+ if (_make_pending_calls(pending_main) != 0) {
+ pending->busy = 0;
+ /* There might not be more calls to make, but we play it safe. */
+ SIGNAL_PENDING_CALLS(pending_main, interp);
+ return -1;
+ }
+ }
+
+ pending->busy = 0;
+ return 0;
}
void
@@ -944,12 +984,6 @@ _Py_FinishPendingCalls(PyThreadState *tstate)
assert(PyGILState_Check());
assert(is_tstate_valid(tstate));
- struct _pending_calls *pending = &tstate->interp->ceval.pending;
-
- if (!_Py_atomic_load_relaxed_int32(&(pending->calls_to_do))) {
- return;
- }
-
if (make_pending_calls(tstate->interp) < 0) {
PyObject *exc = _PyErr_GetRaisedException(tstate);
PyErr_BadInternalCall();
@@ -958,6 +992,29 @@ _Py_FinishPendingCalls(PyThreadState *tstate)
}
}
+int
+_PyEval_MakePendingCalls(PyThreadState *tstate)
+{
+ int res;
+
+ if (_Py_IsMainThread() && _Py_IsMainInterpreter(tstate->interp)) {
+ /* Python signal handler doesn't really queue a callback:
+ it only signals that a signal was received,
+ see _PyEval_SignalReceived(). */
+ res = handle_signals(tstate);
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ res = make_pending_calls(tstate->interp);
+ if (res != 0) {
+ return res;
+ }
+
+ return 0;
+}
+
/* Py_MakePendingCalls() is a simple wrapper for the sake
of backward-compatibility. */
int
@@ -968,19 +1025,11 @@ Py_MakePendingCalls(void)
PyThreadState *tstate = _PyThreadState_GET();
assert(is_tstate_valid(tstate));
- /* Python signal handler doesn't really queue a callback: it only signals
- that a signal was received, see _PyEval_SignalReceived(). */
- int res = handle_signals(tstate);
- if (res != 0) {
- return res;
- }
-
- res = make_pending_calls(tstate->interp);
- if (res != 0) {
- return res;
+ /* Only execute pending calls on the main thread. */
+ if (!_Py_IsMainThread() || !_Py_IsMainInterpreter(tstate->interp)) {
+ return 0;
}
-
- return 0;
+ return _PyEval_MakePendingCalls(tstate);
}
void
@@ -1003,8 +1052,65 @@ _PyEval_FiniState(struct _ceval_state *ceval)
}
}
-/* Handle signals, pending calls, GIL drop request
- and asynchronous exception */
+
+/* Do periodic things, like check for signals and async I/0.
+* We need to do reasonably frequently, but not too frequently.
+* All loops should include a check of the eval breaker.
+* We also check on return from any builtin function.
+*
+* ## More Details ###
+*
+* The eval loop (this function) normally executes the instructions
+* of a code object sequentially. However, the runtime supports a
+* number of out-of-band execution scenarios that may pause that
+* sequential execution long enough to do that out-of-band work
+* in the current thread using the current PyThreadState.
+*
+* The scenarios include:
+*
+* - cyclic garbage collection
+* - GIL drop requests
+* - "async" exceptions
+* - "pending calls" (some only in the main thread)
+* - signal handling (only in the main thread)
+*
+* When the need for one of the above is detected, the eval loop
+* pauses long enough to handle the detected case. Then, if doing
+* so didn't trigger an exception, the eval loop resumes executing
+* the sequential instructions.
+*
+* To make this work, the eval loop periodically checks if any
+* of the above needs to happen. The individual checks can be
+* expensive if computed each time, so a while back we switched
+* to using pre-computed, per-interpreter variables for the checks,
+* and later consolidated that to a single "eval breaker" variable
+* (now a PyInterpreterState field).
+*
+* For the longest time, the eval breaker check would happen
+* frequently, every 5 or so times through the loop, regardless
+* of what instruction ran last or what would run next. Then, in
+* early 2021 (gh-18334, commit 4958f5d), we switched to checking
+* the eval breaker less frequently, by hard-coding the check to
+* specific places in the eval loop (e.g. certain instructions).
+* The intent then was to check after returning from calls
+* and on the back edges of loops.
+*
+* In addition to being more efficient, that approach keeps
+* the eval loop from running arbitrary code between instructions
+* that don't handle that well. (See gh-74174.)
+*
+* Currently, the eval breaker check happens on back edges in
+* the control flow graph, which pretty much applies to all loops,
+* and most calls.
+* (See bytecodes.c for exact information.)
+*
+* One consequence of this approach is that it might not be obvious
+* how to force any specific thread to pick up the eval breaker,
+* or for any specific thread to not pick it up. Mostly this
+* involves judicious uses of locks and careful ordering of code,
+* while avoiding code that might trigger the eval breaker
+* until so desired.
+*/
int
_Py_HandlePending(PyThreadState *tstate)
{
@@ -1020,7 +1126,7 @@ _Py_HandlePending(PyThreadState *tstate)
}
/* Pending calls */
- if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->pending.calls_to_do)) {
+ if (maybe_has_pending_calls(tstate->interp)) {
if (make_pending_calls(tstate->interp) != 0) {
return -1;
}
diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
index 44d6ee8656924a..72800aaaaa2ac4 100644
--- a/Python/ceval_macros.h
+++ b/Python/ceval_macros.h
@@ -1,4 +1,4 @@
-// Macros needed by ceval.c and bytecodes.c
+// Macros and other things needed by ceval.c and bytecodes.c
/* Computed GOTOs, or
the-optimization-commonly-but-improperly-known-as-"threaded code"
@@ -117,7 +117,9 @@
#define CHECK_EVAL_BREAKER() \
_Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); \
if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker)) { \
- goto handle_eval_breaker; \
+ if (_Py_HandlePending(tstate) != 0) { \
+ goto error; \
+ } \
}
@@ -138,14 +140,20 @@ GETITEM(PyObject *v, Py_ssize_t i) {
/* Code access macros */
/* The integer overflow is checked by an assertion below. */
-#define INSTR_OFFSET() ((int)(next_instr - _PyCode_CODE(frame->f_code)))
+#define INSTR_OFFSET() ((int)(next_instr - _PyCode_CODE(_PyFrame_GetCode(frame))))
#define NEXTOPARG() do { \
_Py_CODEUNIT word = *next_instr; \
opcode = word.op.code; \
oparg = word.op.arg; \
} while (0)
-#define JUMPTO(x) (next_instr = _PyCode_CODE(frame->f_code) + (x))
+#define JUMPTO(x) (next_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + (x))
+
+/* JUMPBY makes the generator identify the instruction as a jump. SKIP_OVER is
+ * for advancing to the next instruction, taking into account cache entries
+ * and skipped instructions.
+ */
#define JUMPBY(x) (next_instr += (x))
+#define SKIP_OVER(x) (next_instr += (x))
/* OpCode prediction macros
Some opcodes tend to come in pairs thus making it possible to
@@ -182,7 +190,7 @@ GETITEM(PyObject *v, Py_ssize_t i) {
/* The stack can grow at most MAXINT deep, as co_nlocals and
co_stacksize are ints. */
#define STACK_LEVEL() ((int)(stack_pointer - _PyFrame_Stackbase(frame)))
-#define STACK_SIZE() (frame->f_code->co_stacksize)
+#define STACK_SIZE() (_PyFrame_GetCode(frame)->co_stacksize)
#define EMPTY() (STACK_LEVEL() == 0)
#define TOP() (stack_pointer[-1])
#define SECOND() (stack_pointer[-2])
@@ -219,6 +227,11 @@ GETITEM(PyObject *v, Py_ssize_t i) {
#define STACK_SHRINK(n) BASIC_STACKADJ(-(n))
#endif
+
+/* Data access macros */
+#define FRAME_CO_CONSTS (_PyFrame_GetCode(frame)->co_consts)
+#define FRAME_CO_NAMES (_PyFrame_GetCode(frame)->co_names)
+
/* Local variable macros */
#define GETLOCAL(i) (frame->localsplus[i])
@@ -265,6 +278,8 @@ GETITEM(PyObject *v, Py_ssize_t i) {
#define GLOBALS() frame->f_globals
#define BUILTINS() frame->f_builtins
#define LOCALS() frame->f_locals
+#define CONSTS() _PyFrame_GetCode(frame)->co_consts
+#define NAMES() _PyFrame_GetCode(frame)->co_names
#define DTRACE_FUNCTION_ENTRY() \
if (PyDTrace_FUNCTION_ENTRY_ENABLED()) { \
@@ -326,3 +341,11 @@ do { \
goto error; \
} \
} while (0);
+
+typedef PyObject *(*convertion_func_ptr)(PyObject *);
+
+static const convertion_func_ptr CONVERSION_FUNCTIONS[4] = {
+ [FVC_STR] = PyObject_Str,
+ [FVC_REPR] = PyObject_Repr,
+ [FVC_ASCII] = PyObject_ASCII
+};
diff --git a/Python/codecs.c b/Python/codecs.c
index 1983f56ba204c1..4e47ff93a3691b 100644
--- a/Python/codecs.c
+++ b/Python/codecs.c
@@ -11,7 +11,7 @@ Copyright (c) Corporation for National Research Initiatives.
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_interp.h" // PyInterpreterState.codec_search_path
-#include "pycore_pyerrors.h" // _PyErr_FormatNote()
+#include "pycore_pyerrors.h" // _PyErr_FormatNote()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
#include
@@ -55,7 +55,7 @@ int PyCodec_Register(PyObject *search_function)
int
PyCodec_Unregister(PyObject *search_function)
{
- PyInterpreterState *interp = PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
PyObject *codec_search_path = interp->codec_search_path;
/* Do nothing if codec_search_path is not created yet or was cleared. */
if (codec_search_path == NULL) {
@@ -516,7 +516,7 @@ PyObject * _PyCodec_LookupTextEncoding(const char *encoding,
* attribute.
*/
if (!PyTuple_CheckExact(codec)) {
- if (_PyObject_LookupAttr(codec, &_Py_ID(_is_text_encoding), &attr) < 0) {
+ if (PyObject_GetOptionalAttr(codec, &_Py_ID(_is_text_encoding), &attr) < 0) {
Py_DECREF(codec);
return NULL;
}
diff --git a/Python/compile.c b/Python/compile.c
index e3a76236f5723a..b80f7c01bcd90e 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -33,9 +33,12 @@
#include "pycore_compile.h"
#include "pycore_intrinsics.h"
#include "pycore_long.h" // _PyLong_GetZero()
+#include "pycore_pystate.h" // _Py_GetConfig()
#include "pycore_symtable.h" // PySTEntryObject, _PyFuture_FromAST()
-#include "opcode_metadata.h" // _PyOpcode_opcode_metadata, _PyOpcode_num_popped/pushed
+#define NEED_OPCODE_METADATA
+#include "pycore_opcode_metadata.h" // _PyOpcode_opcode_metadata, _PyOpcode_num_popped/pushed
+#undef NEED_OPCODE_METADATA
#define COMP_GENEXP 0
#define COMP_LISTCOMP 1
@@ -131,16 +134,6 @@ enum {
};
-int
-_PyCompile_InstrSize(int opcode, int oparg)
-{
- assert(!IS_PSEUDO_OPCODE(opcode));
- assert(HAS_ARG(opcode) || oparg == 0);
- int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg);
- int caches = _PyOpcode_Caches[opcode];
- return extended_args + 1 + caches;
-}
-
typedef _PyCompile_Instruction instruction;
typedef _PyCompile_InstructionSequence instr_sequence;
@@ -241,11 +234,15 @@ instr_sequence_use_label(instr_sequence *seq, int lbl) {
return SUCCESS;
}
+
+#define MAX_OPCODE 511
+
static int
instr_sequence_addop(instr_sequence *seq, int opcode, int oparg, location loc)
{
+ assert(0 <= opcode && opcode <= MAX_OPCODE);
assert(IS_WITHIN_OPCODE_RANGE(opcode));
- assert(HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
+ assert(OPCODE_HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
assert(0 <= oparg && oparg < (1 << 30));
int idx = instr_sequence_next_inst(seq);
@@ -490,8 +487,10 @@ static PyCodeObject *optimize_and_assemble(struct compiler *, int addNone);
static int
compiler_setup(struct compiler *c, mod_ty mod, PyObject *filename,
- PyCompilerFlags flags, int optimize, PyArena *arena)
+ PyCompilerFlags *flags, int optimize, PyArena *arena)
{
+ PyCompilerFlags local_flags = _PyCompilerFlags_INIT;
+
c->c_const_cache = PyDict_New();
if (!c->c_const_cache) {
return ERROR;
@@ -507,10 +506,13 @@ compiler_setup(struct compiler *c, mod_ty mod, PyObject *filename,
if (!_PyFuture_FromAST(mod, filename, &c->c_future)) {
return ERROR;
}
- int merged = c->c_future.ff_features | flags.cf_flags;
+ if (!flags) {
+ flags = &local_flags;
+ }
+ int merged = c->c_future.ff_features | flags->cf_flags;
c->c_future.ff_features = merged;
- flags.cf_flags = merged;
- c->c_flags = flags;
+ flags->cf_flags = merged;
+ c->c_flags = *flags;
c->c_optimize = (optimize == -1) ? _Py_GetConfig()->optimization_level : optimize;
c->c_nestlevel = 0;
@@ -531,12 +533,11 @@ static struct compiler*
new_compiler(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
int optimize, PyArena *arena)
{
- PyCompilerFlags flags = pflags ? *pflags : _PyCompilerFlags_INIT;
struct compiler *c = PyMem_Calloc(1, sizeof(struct compiler));
if (c == NULL) {
return NULL;
}
- if (compiler_setup(c, mod, filename, flags, optimize, arena) < 0) {
+ if (compiler_setup(c, mod, filename, pflags, optimize, arena) < 0) {
compiler_free(c);
return NULL;
}
@@ -817,6 +818,9 @@ stack_effect(int opcode, int oparg, int jump)
case JUMP_NO_INTERRUPT:
return 0;
+ case EXIT_INIT_CHECK:
+ return -1;
+
/* Exception handling pseudo-instructions */
case SETUP_FINALLY:
/* 0 in the normal flow.
@@ -835,6 +839,8 @@ stack_effect(int opcode, int oparg, int jump)
case STORE_FAST_MAYBE_NULL:
return -1;
+ case LOAD_CLOSURE:
+ return 1;
case LOAD_METHOD:
return 1;
case LOAD_SUPER_METHOD:
@@ -860,10 +866,40 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
return stack_effect(opcode, oparg, -1);
}
+int
+PyUnstable_OpcodeIsValid(int opcode)
+{
+ return IS_VALID_OPCODE(opcode);
+}
+
+int
+PyUnstable_OpcodeHasArg(int opcode)
+{
+ return OPCODE_HAS_ARG(opcode);
+}
+
+int
+PyUnstable_OpcodeHasConst(int opcode)
+{
+ return OPCODE_HAS_CONST(opcode);
+}
+
+int
+PyUnstable_OpcodeHasName(int opcode)
+{
+ return OPCODE_HAS_NAME(opcode);
+}
+
+int
+PyUnstable_OpcodeHasJump(int opcode)
+{
+ return OPCODE_HAS_JUMP(opcode);
+}
+
static int
codegen_addop_noarg(instr_sequence *seq, int opcode, location loc)
{
- assert(!HAS_ARG(opcode));
+ assert(!OPCODE_HAS_ARG(opcode));
assert(!IS_ASSEMBLER_OPCODE(opcode));
return instr_sequence_addop(seq, opcode, 0, loc);
}
@@ -1055,6 +1091,7 @@ compiler_addop_name(struct compiler_unit *u, location loc,
arg <<= 1;
}
if (opcode == LOAD_METHOD) {
+ assert(SAME_OPCODE_METADATA(LOAD_METHOD, LOAD_ATTR));
opcode = LOAD_ATTR;
arg <<= 1;
arg |= 1;
@@ -1064,15 +1101,18 @@ compiler_addop_name(struct compiler_unit *u, location loc,
arg |= 2;
}
if (opcode == LOAD_SUPER_METHOD) {
+ assert(SAME_OPCODE_METADATA(LOAD_SUPER_METHOD, LOAD_SUPER_ATTR));
opcode = LOAD_SUPER_ATTR;
arg <<= 2;
arg |= 3;
}
if (opcode == LOAD_ZERO_SUPER_ATTR) {
+ assert(SAME_OPCODE_METADATA(LOAD_ZERO_SUPER_ATTR, LOAD_SUPER_ATTR));
opcode = LOAD_SUPER_ATTR;
arg <<= 2;
}
if (opcode == LOAD_ZERO_SUPER_METHOD) {
+ assert(SAME_OPCODE_METADATA(LOAD_ZERO_SUPER_METHOD, LOAD_SUPER_ATTR));
opcode = LOAD_SUPER_ATTR;
arg <<= 2;
arg |= 1;
@@ -1102,7 +1142,7 @@ codegen_addop_j(instr_sequence *seq, location loc,
int opcode, jump_target_label target)
{
assert(IS_LABEL(target));
- assert(IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode));
+ assert(OPCODE_HAS_JUMP(opcode) || IS_BLOCK_PUSH_OPCODE(opcode));
assert(!IS_ASSEMBLER_OPCODE(opcode));
return instr_sequence_addop(seq, opcode, target.id, loc);
}
@@ -1136,7 +1176,7 @@ codegen_addop_j(instr_sequence *seq, location loc,
}
#define ADDOP_N(C, LOC, OP, O, TYPE) { \
- assert(!HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
+ assert(!OPCODE_HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
if (compiler_addop_o((C)->u, (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)) < 0) { \
Py_DECREF((O)); \
return ERROR; \
@@ -1664,10 +1704,16 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
if (c->c_optimize < 2) {
docstring = _PyAST_GetDocString(stmts);
if (docstring) {
+ PyObject *cleandoc = _PyCompile_CleanDoc(docstring);
+ if (cleandoc == NULL) {
+ return ERROR;
+ }
i = 1;
st = (stmt_ty)asdl_seq_GET(stmts, 0);
assert(st->kind == Expr_kind);
- VISIT(c, expr, st->v.Expr.value);
+ location loc = LOC(st->v.Expr.value);
+ ADDOP_LOAD_CONST(c, loc, cleandoc);
+ Py_DECREF(cleandoc);
RETURN_IF_ERROR(compiler_nameop(c, NO_LOCATION, &_Py_ID(__doc__), Store));
}
}
@@ -1813,7 +1859,21 @@ compiler_make_closure(struct compiler *c, location loc,
ADDOP_I(c, loc, BUILD_TUPLE, co->co_nfreevars);
}
ADDOP_LOAD_CONST(c, loc, (PyObject*)co);
- ADDOP_I(c, loc, MAKE_FUNCTION, flags);
+
+ ADDOP(c, loc, MAKE_FUNCTION);
+
+ if (flags & MAKE_FUNCTION_CLOSURE) {
+ ADDOP_I(c, loc, SET_FUNCTION_ATTRIBUTE, MAKE_FUNCTION_CLOSURE);
+ }
+ if (flags & MAKE_FUNCTION_ANNOTATIONS) {
+ ADDOP_I(c, loc, SET_FUNCTION_ATTRIBUTE, MAKE_FUNCTION_ANNOTATIONS);
+ }
+ if (flags & MAKE_FUNCTION_KWDEFAULTS) {
+ ADDOP_I(c, loc, SET_FUNCTION_ATTRIBUTE, MAKE_FUNCTION_KWDEFAULTS);
+ }
+ if (flags & MAKE_FUNCTION_DEFAULTS) {
+ ADDOP_I(c, loc, SET_FUNCTION_ATTRIBUTE, MAKE_FUNCTION_DEFAULTS);
+ }
return SUCCESS;
}
@@ -2198,11 +2258,19 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
/* if not -OO mode, add docstring */
if (c->c_optimize < 2) {
docstring = _PyAST_GetDocString(body);
+ if (docstring) {
+ docstring = _PyCompile_CleanDoc(docstring);
+ if (docstring == NULL) {
+ compiler_exit_scope(c);
+ return ERROR;
+ }
+ }
}
if (compiler_add_const(c->c_const_cache, c->u, docstring ? docstring : Py_None) < 0) {
compiler_exit_scope(c);
return ERROR;
}
+ Py_XDECREF(docstring);
c->u->u_metadata.u_argcount = asdl_seq_LEN(args->args);
c->u->u_metadata.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);
@@ -2769,9 +2837,11 @@ static int compiler_addcompare(struct compiler *c, location loc,
default:
Py_UNREACHABLE();
}
- /* cmp goes in top bits of the oparg, while the low bits are used by quickened
- * versions of this opcode to store the comparison mask. */
- ADDOP_I(c, loc, COMPARE_OP, (cmp << 4) | compare_masks[cmp]);
+ // cmp goes in top three bits of the oparg, while the low four bits are used
+ // by quickened versions of this opcode to store the comparison mask. The
+ // fifth-lowest bit indicates whether the result should be converted to bool
+ // and is set later):
+ ADDOP_I(c, loc, COMPARE_OP, (cmp << 5) | compare_masks[cmp]);
return SUCCESS;
}
@@ -2837,10 +2907,12 @@ compiler_jump_if(struct compiler *c, location loc,
ADDOP_I(c, LOC(e), SWAP, 2);
ADDOP_I(c, LOC(e), COPY, 2);
ADDOP_COMPARE(c, LOC(e), asdl_seq_GET(e->v.Compare.ops, i));
+ ADDOP(c, LOC(e), TO_BOOL);
ADDOP_JUMP(c, LOC(e), POP_JUMP_IF_FALSE, cleanup);
}
VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));
ADDOP_COMPARE(c, LOC(e), asdl_seq_GET(e->v.Compare.ops, n));
+ ADDOP(c, LOC(e), TO_BOOL);
ADDOP_JUMP(c, LOC(e), cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
NEW_JUMP_TARGET_LABEL(c, end);
ADDOP_JUMP(c, NO_LOCATION, JUMP, end);
@@ -2864,6 +2936,7 @@ compiler_jump_if(struct compiler *c, location loc,
/* general implementation */
VISIT(c, expr, e);
+ ADDOP(c, LOC(e), TO_BOOL);
ADDOP_JUMP(c, LOC(e), cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
return SUCCESS;
}
@@ -3995,8 +4068,6 @@ unaryop(unaryop_ty op)
switch (op) {
case Invert:
return UNARY_INVERT;
- case Not:
- return UNARY_NOT;
case USub:
return UNARY_NEGATIVE;
default:
@@ -4226,6 +4297,7 @@ compiler_boolop(struct compiler *c, expr_ty e)
for (i = 0; i < n; ++i) {
VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i));
ADDOP_I(c, loc, COPY, 1);
+ ADDOP(c, loc, TO_BOOL);
ADDOP_JUMP(c, loc, jumpi, end);
ADDOP(c, loc, POP_TOP);
}
@@ -4533,6 +4605,7 @@ compiler_compare(struct compiler *c, expr_ty e)
ADDOP_I(c, loc, COPY, 2);
ADDOP_COMPARE(c, loc, asdl_seq_GET(e->v.Compare.ops, i));
ADDOP_I(c, loc, COPY, 1);
+ ADDOP(c, loc, TO_BOOL);
ADDOP_JUMP(c, loc, POP_JUMP_IF_FALSE, cleanup);
ADDOP(c, loc, POP_TOP);
}
@@ -4959,26 +5032,26 @@ compiler_formatted_value(struct compiler *c, expr_ty e)
/* The expression to be formatted. */
VISIT(c, expr, e->v.FormattedValue.value);
- switch (conversion) {
- case 's': oparg = FVC_STR; break;
- case 'r': oparg = FVC_REPR; break;
- case 'a': oparg = FVC_ASCII; break;
- case -1: oparg = FVC_NONE; break;
- default:
- PyErr_Format(PyExc_SystemError,
+ location loc = LOC(e);
+ if (conversion != -1) {
+ switch (conversion) {
+ case 's': oparg = FVC_STR; break;
+ case 'r': oparg = FVC_REPR; break;
+ case 'a': oparg = FVC_ASCII; break;
+ default:
+ PyErr_Format(PyExc_SystemError,
"Unrecognized conversion character %d", conversion);
- return ERROR;
+ return ERROR;
+ }
+ ADDOP_I(c, loc, CONVERT_VALUE, oparg);
}
if (e->v.FormattedValue.format_spec) {
/* Evaluate the format spec, and update our opcode arg. */
VISIT(c, expr, e->v.FormattedValue.format_spec);
- oparg |= FVS_HAVE_SPEC;
+ ADDOP(c, loc, FORMAT_WITH_SPEC);
+ } else {
+ ADDOP(c, loc, FORMAT_SIMPLE);
}
-
- /* And push our opcode and oparg */
- location loc = LOC(e);
- ADDOP_I(c, loc, FORMAT_VALUE, oparg);
-
return SUCCESS;
}
@@ -5768,6 +5841,7 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k)
static int
compiler_with_except_finish(struct compiler *c, jump_target_label cleanup) {
NEW_JUMP_TARGET_LABEL(c, suppress);
+ ADDOP(c, NO_LOCATION, TO_BOOL);
ADDOP_JUMP(c, NO_LOCATION, POP_JUMP_IF_TRUE, suppress);
ADDOP_I(c, NO_LOCATION, RERAISE, 2);
@@ -6001,6 +6075,10 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
if (e->v.UnaryOp.op == UAdd) {
ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_UNARY_POSITIVE);
}
+ else if (e->v.UnaryOp.op == Not) {
+ ADDOP(c, loc, TO_BOOL);
+ ADDOP(c, loc, UNARY_NOT);
+ }
else {
ADDOP(c, loc, unaryop(e->v.UnaryOp.op));
}
@@ -7176,6 +7254,7 @@ compiler_pattern_value(struct compiler *c, pattern_ty p, pattern_context *pc)
}
VISIT(c, expr, value);
ADDOP_COMPARE(c, LOC(p), Eq);
+ ADDOP(c, LOC(p), TO_BOOL);
RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));
return SUCCESS;
}
@@ -7688,17 +7767,20 @@ cfg_to_instr_sequence(cfg_builder *g, instr_sequence *seq)
RETURN_IF_ERROR(instr_sequence_use_label(seq, b->b_label.id));
for (int i = 0; i < b->b_iused; i++) {
cfg_instr *instr = &b->b_instr[i];
+ if (OPCODE_HAS_JUMP(instr->i_opcode)) {
+ instr->i_oparg = instr->i_target->b_label.id;
+ }
RETURN_IF_ERROR(
instr_sequence_addop(seq, instr->i_opcode, instr->i_oparg, instr->i_loc));
_PyCompile_ExceptHandlerInfo *hi = &seq->s_instrs[seq->s_used-1].i_except_handler_info;
if (instr->i_except != NULL) {
- hi->h_offset = instr->i_except->b_offset;
+ hi->h_label = instr->i_except->b_label.id;
hi->h_startdepth = instr->i_except->b_startdepth;
hi->h_preserve_lasti = instr->i_except->b_preserve_lasti;
}
else {
- hi->h_offset = -1;
+ hi->h_label = -1;
}
}
}
@@ -7769,7 +7851,7 @@ instructions_to_instr_sequence(PyObject *instructions, instr_sequence *seq)
goto error;
}
int oparg;
- if (HAS_ARG(opcode)) {
+ if (OPCODE_HAS_ARG(opcode)) {
oparg = PyLong_AsLong(PyTuple_GET_ITEM(item, 1));
if (PyErr_Occurred()) {
goto error;
@@ -7899,6 +7981,89 @@ cfg_to_instructions(cfg_builder *g)
return NULL;
}
+// C implementation of inspect.cleandoc()
+//
+// Difference from inspect.cleandoc():
+// - Do not remove leading and trailing blank lines to keep lineno.
+PyObject *
+_PyCompile_CleanDoc(PyObject *doc)
+{
+ doc = PyObject_CallMethod(doc, "expandtabs", NULL);
+ if (doc == NULL) {
+ return NULL;
+ }
+
+ Py_ssize_t doc_size;
+ const char *doc_utf8 = PyUnicode_AsUTF8AndSize(doc, &doc_size);
+ if (doc_utf8 == NULL) {
+ Py_DECREF(doc);
+ return NULL;
+ }
+ const char *p = doc_utf8;
+ const char *pend = p + doc_size;
+
+ // First pass: find minimum indentation of any non-blank lines
+ // after first line.
+ while (p < pend && *p++ != '\n') {
+ }
+
+ Py_ssize_t margin = PY_SSIZE_T_MAX;
+ while (p < pend) {
+ const char *s = p;
+ while (*p == ' ') p++;
+ if (p < pend && *p != '\n') {
+ margin = Py_MIN(margin, p - s);
+ }
+ while (p < pend && *p++ != '\n') {
+ }
+ }
+ if (margin == PY_SSIZE_T_MAX) {
+ margin = 0;
+ }
+
+ // Second pass: write cleandoc into buff.
+
+ // copy first line without leading spaces.
+ p = doc_utf8;
+ while (*p == ' ') {
+ p++;
+ }
+ if (p == doc_utf8 && margin == 0 ) {
+ // doc is already clean.
+ return doc;
+ }
+
+ char *buff = PyMem_Malloc(doc_size);
+ char *w = buff;
+
+ while (p < pend) {
+ int ch = *w++ = *p++;
+ if (ch == '\n') {
+ break;
+ }
+ }
+
+ // copy subsequent lines without margin.
+ while (p < pend) {
+ for (Py_ssize_t i = 0; i < margin; i++, p++) {
+ if (*p != ' ') {
+ assert(*p == '\n' || *p == '\0');
+ break;
+ }
+ }
+ while (p < pend) {
+ int ch = *w++ = *p++;
+ if (ch == '\n') {
+ break;
+ }
+ }
+ }
+
+ Py_DECREF(doc);
+ return PyUnicode_FromStringAndSize(buff, w - buff);
+}
+
+
PyObject *
_PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags,
int optimize, int compile_mode)
diff --git a/Python/errors.c b/Python/errors.c
index eab6503046b5cc..916958c9a0ab00 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -1485,7 +1485,7 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type,
}
/* Explicitly call file.flush() */
- PyObject *res = _PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
+ PyObject *res = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
if (!res) {
return -1;
}
@@ -1748,7 +1748,7 @@ PyErr_SyntaxLocationObjectEx(PyObject *filename, int lineno, int col_offset,
}
}
if ((PyObject *)Py_TYPE(exc) != PyExc_SyntaxError) {
- if (_PyObject_LookupAttr(exc, &_Py_ID(msg), &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(exc, &_Py_ID(msg), &tmp) < 0) {
_PyErr_Clear(tstate);
}
else if (tmp) {
@@ -1767,7 +1767,7 @@ PyErr_SyntaxLocationObjectEx(PyObject *filename, int lineno, int col_offset,
}
}
- if (_PyObject_LookupAttr(exc, &_Py_ID(print_file_and_line), &tmp) < 0) {
+ if (PyObject_GetOptionalAttr(exc, &_Py_ID(print_file_and_line), &tmp) < 0) {
_PyErr_Clear(tstate);
}
else if (tmp) {
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
new file mode 100644
index 00000000000000..ae21ffad94d801
--- /dev/null
+++ b/Python/executor_cases.c.h
@@ -0,0 +1,2109 @@
+// This file is generated by Tools/cases_generator/generate_cases.py
+// from:
+// Python/bytecodes.c
+// Do not edit!
+
+ case NOP: {
+ break;
+ }
+
+ case LOAD_FAST_CHECK: {
+ PyObject *value;
+ value = GETLOCAL(oparg);
+ if (value == NULL) goto unbound_local_error;
+ Py_INCREF(value);
+ STACK_GROW(1);
+ stack_pointer[-1] = value;
+ break;
+ }
+
+ case LOAD_FAST: {
+ PyObject *value;
+ value = GETLOCAL(oparg);
+ assert(value != NULL);
+ Py_INCREF(value);
+ STACK_GROW(1);
+ stack_pointer[-1] = value;
+ break;
+ }
+
+ case LOAD_FAST_AND_CLEAR: {
+ PyObject *value;
+ value = GETLOCAL(oparg);
+ // do not use SETLOCAL here, it decrefs the old value
+ GETLOCAL(oparg) = NULL;
+ STACK_GROW(1);
+ stack_pointer[-1] = value;
+ break;
+ }
+
+ case LOAD_CONST: {
+ PyObject *value;
+ value = GETITEM(FRAME_CO_CONSTS, oparg);
+ Py_INCREF(value);
+ STACK_GROW(1);
+ stack_pointer[-1] = value;
+ break;
+ }
+
+ case STORE_FAST: {
+ PyObject *value = stack_pointer[-1];
+ SETLOCAL(oparg, value);
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case POP_TOP: {
+ PyObject *value = stack_pointer[-1];
+ Py_DECREF(value);
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case PUSH_NULL: {
+ PyObject *res;
+ res = NULL;
+ STACK_GROW(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case END_SEND: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *receiver = stack_pointer[-2];
+ Py_DECREF(receiver);
+ STACK_SHRINK(1);
+ stack_pointer[-1] = value;
+ break;
+ }
+
+ case UNARY_NEGATIVE: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ res = PyNumber_Negative(value);
+ Py_DECREF(value);
+ if (res == NULL) goto pop_1_error;
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case UNARY_NOT: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ assert(PyBool_Check(value));
+ res = Py_IsFalse(value) ? Py_True : Py_False;
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case TO_BOOL: {
+ static_assert(INLINE_CACHE_ENTRIES_TO_BOOL == 3, "incorrect cache size");
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ #if ENABLE_SPECIALIZATION
+ _PyToBoolCache *cache = (_PyToBoolCache *)next_instr;
+ if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
+ next_instr--;
+ _Py_Specialize_ToBool(value, next_instr);
+ DISPATCH_SAME_OPARG();
+ }
+ STAT_INC(TO_BOOL, deferred);
+ DECREMENT_ADAPTIVE_COUNTER(cache->counter);
+ #endif /* ENABLE_SPECIALIZATION */
+ int err = PyObject_IsTrue(value);
+ Py_DECREF(value);
+ if (err < 0) goto pop_1_error;
+ res = err ? Py_True : Py_False;
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case TO_BOOL_BOOL: {
+ PyObject *value = stack_pointer[-1];
+ DEOPT_IF(!PyBool_Check(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ break;
+ }
+
+ case TO_BOOL_INT: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ DEOPT_IF(!PyLong_CheckExact(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ if (_PyLong_IsZero((PyLongObject *)value)) {
+ assert(_Py_IsImmortal(value));
+ res = Py_False;
+ }
+ else {
+ Py_DECREF(value);
+ res = Py_True;
+ }
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case TO_BOOL_LIST: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ DEOPT_IF(!PyList_CheckExact(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ res = Py_SIZE(value) ? Py_True : Py_False;
+ Py_DECREF(value);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case TO_BOOL_NONE: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ // This one is a bit weird, because we expect *some* failures:
+ DEOPT_IF(!Py_IsNone(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ res = Py_False;
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case TO_BOOL_STR: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ DEOPT_IF(!PyUnicode_CheckExact(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ if (value == &_Py_STR(empty)) {
+ assert(_Py_IsImmortal(value));
+ res = Py_False;
+ }
+ else {
+ assert(Py_SIZE(value));
+ Py_DECREF(value);
+ res = Py_True;
+ }
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case TO_BOOL_ALWAYS_TRUE: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ uint32_t version = (uint32_t)operand;
+ // This one is a bit weird, because we expect *some* failures:
+ assert(version);
+ DEOPT_IF(Py_TYPE(value)->tp_version_tag != version, TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ Py_DECREF(value);
+ res = Py_True;
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case UNARY_INVERT: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ res = PyNumber_Invert(value);
+ Py_DECREF(value);
+ if (res == NULL) goto pop_1_error;
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case _GUARD_BOTH_INT: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
+ DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
+ break;
+ }
+
+ case _BINARY_OP_MULTIPLY_INT: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ STAT_INC(BINARY_OP, hit);
+ res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
+ _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
+ _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+ if (res == NULL) goto pop_2_error;
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case _BINARY_OP_ADD_INT: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ STAT_INC(BINARY_OP, hit);
+ res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
+ _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
+ _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+ if (res == NULL) goto pop_2_error;
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case _BINARY_OP_SUBTRACT_INT: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ STAT_INC(BINARY_OP, hit);
+ res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);
+ _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
+ _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+ if (res == NULL) goto pop_2_error;
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case _GUARD_BOTH_FLOAT: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
+ DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
+ break;
+ }
+
+ case _BINARY_OP_MULTIPLY_FLOAT: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ STAT_INC(BINARY_OP, hit);
+ double dres =
+ ((PyFloatObject *)left)->ob_fval *
+ ((PyFloatObject *)right)->ob_fval;
+ DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case _BINARY_OP_ADD_FLOAT: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ STAT_INC(BINARY_OP, hit);
+ double dres =
+ ((PyFloatObject *)left)->ob_fval +
+ ((PyFloatObject *)right)->ob_fval;
+ DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case _BINARY_OP_SUBTRACT_FLOAT: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ STAT_INC(BINARY_OP, hit);
+ double dres =
+ ((PyFloatObject *)left)->ob_fval -
+ ((PyFloatObject *)right)->ob_fval;
+ DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case _GUARD_BOTH_UNICODE: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);
+ DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP);
+ break;
+ }
+
+ case _BINARY_OP_ADD_UNICODE: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ STAT_INC(BINARY_OP, hit);
+ res = PyUnicode_Concat(left, right);
+ _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
+ _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
+ if (res == NULL) goto pop_2_error;
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case BINARY_SUBSCR: {
+ static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
+ PyObject *sub = stack_pointer[-1];
+ PyObject *container = stack_pointer[-2];
+ PyObject *res;
+ #if ENABLE_SPECIALIZATION
+ _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr;
+ if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
+ next_instr--;
+ _Py_Specialize_BinarySubscr(container, sub, next_instr);
+ DISPATCH_SAME_OPARG();
+ }
+ STAT_INC(BINARY_SUBSCR, deferred);
+ DECREMENT_ADAPTIVE_COUNTER(cache->counter);
+ #endif /* ENABLE_SPECIALIZATION */
+ res = PyObject_GetItem(container, sub);
+ Py_DECREF(container);
+ Py_DECREF(sub);
+ if (res == NULL) goto pop_2_error;
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case BINARY_SLICE: {
+ PyObject *stop = stack_pointer[-1];
+ PyObject *start = stack_pointer[-2];
+ PyObject *container = stack_pointer[-3];
+ PyObject *res;
+ PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop);
+ // Can't use ERROR_IF() here, because we haven't
+ // DECREF'ed container yet, and we still own slice.
+ if (slice == NULL) {
+ res = NULL;
+ }
+ else {
+ res = PyObject_GetItem(container, slice);
+ Py_DECREF(slice);
+ }
+ Py_DECREF(container);
+ if (res == NULL) goto pop_3_error;
+ STACK_SHRINK(2);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case STORE_SLICE: {
+ PyObject *stop = stack_pointer[-1];
+ PyObject *start = stack_pointer[-2];
+ PyObject *container = stack_pointer[-3];
+ PyObject *v = stack_pointer[-4];
+ PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop);
+ int err;
+ if (slice == NULL) {
+ err = 1;
+ }
+ else {
+ err = PyObject_SetItem(container, slice, v);
+ Py_DECREF(slice);
+ }
+ Py_DECREF(v);
+ Py_DECREF(container);
+ if (err) goto pop_4_error;
+ STACK_SHRINK(4);
+ break;
+ }
+
+ case BINARY_SUBSCR_LIST_INT: {
+ PyObject *sub = stack_pointer[-1];
+ PyObject *list = stack_pointer[-2];
+ PyObject *res;
+ DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);
+ DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR);
+
+ // Deopt unless 0 <= sub < PyList_Size(list)
+ DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR);
+ Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
+ DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR);
+ STAT_INC(BINARY_SUBSCR, hit);
+ res = PyList_GET_ITEM(list, index);
+ assert(res != NULL);
+ Py_INCREF(res);
+ _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+ Py_DECREF(list);
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case BINARY_SUBSCR_TUPLE_INT: {
+ PyObject *sub = stack_pointer[-1];
+ PyObject *tuple = stack_pointer[-2];
+ PyObject *res;
+ DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);
+ DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR);
+
+ // Deopt unless 0 <= sub < PyTuple_Size(list)
+ DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR);
+ Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
+ DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR);
+ STAT_INC(BINARY_SUBSCR, hit);
+ res = PyTuple_GET_ITEM(tuple, index);
+ assert(res != NULL);
+ Py_INCREF(res);
+ _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+ Py_DECREF(tuple);
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case BINARY_SUBSCR_DICT: {
+ PyObject *sub = stack_pointer[-1];
+ PyObject *dict = stack_pointer[-2];
+ PyObject *res;
+ DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR);
+ STAT_INC(BINARY_SUBSCR, hit);
+ res = PyDict_GetItemWithError(dict, sub);
+ if (res == NULL) {
+ if (!_PyErr_Occurred(tstate)) {
+ _PyErr_SetKeyError(sub);
+ }
+ Py_DECREF(dict);
+ Py_DECREF(sub);
+ if (true) goto pop_2_error;
+ }
+ Py_INCREF(res); // Do this before DECREF'ing dict, sub
+ Py_DECREF(dict);
+ Py_DECREF(sub);
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case LIST_APPEND: {
+ PyObject *v = stack_pointer[-1];
+ PyObject *list = stack_pointer[-(2 + (oparg-1))];
+ if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto pop_1_error;
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case SET_ADD: {
+ PyObject *v = stack_pointer[-1];
+ PyObject *set = stack_pointer[-(2 + (oparg-1))];
+ int err = PySet_Add(set, v);
+ Py_DECREF(v);
+ if (err) goto pop_1_error;
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case STORE_SUBSCR: {
+ static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, "incorrect cache size");
+ PyObject *sub = stack_pointer[-1];
+ PyObject *container = stack_pointer[-2];
+ PyObject *v = stack_pointer[-3];
+ uint16_t counter = (uint16_t)operand;
+ #if ENABLE_SPECIALIZATION
+ if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
+ next_instr--;
+ _Py_Specialize_StoreSubscr(container, sub, next_instr);
+ DISPATCH_SAME_OPARG();
+ }
+ STAT_INC(STORE_SUBSCR, deferred);
+ _PyStoreSubscrCache *cache = (_PyStoreSubscrCache *)next_instr;
+ DECREMENT_ADAPTIVE_COUNTER(cache->counter);
+ #else
+ (void)counter; // Unused.
+ #endif /* ENABLE_SPECIALIZATION */
+ /* container[sub] = v */
+ int err = PyObject_SetItem(container, sub, v);
+ Py_DECREF(v);
+ Py_DECREF(container);
+ Py_DECREF(sub);
+ if (err) goto pop_3_error;
+ STACK_SHRINK(3);
+ break;
+ }
+
+ case STORE_SUBSCR_LIST_INT: {
+ PyObject *sub = stack_pointer[-1];
+ PyObject *list = stack_pointer[-2];
+ PyObject *value = stack_pointer[-3];
+ DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR);
+ DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR);
+
+ // Ensure nonnegative, zero-or-one-digit ints.
+ DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), STORE_SUBSCR);
+ Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
+ // Ensure index < len(list)
+ DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR);
+ STAT_INC(STORE_SUBSCR, hit);
+
+ PyObject *old_value = PyList_GET_ITEM(list, index);
+ PyList_SET_ITEM(list, index, value);
+ assert(old_value != NULL);
+ Py_DECREF(old_value);
+ _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+ Py_DECREF(list);
+ STACK_SHRINK(3);
+ break;
+ }
+
+ case STORE_SUBSCR_DICT: {
+ PyObject *sub = stack_pointer[-1];
+ PyObject *dict = stack_pointer[-2];
+ PyObject *value = stack_pointer[-3];
+ DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR);
+ STAT_INC(STORE_SUBSCR, hit);
+ int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value);
+ Py_DECREF(dict);
+ if (err) goto pop_3_error;
+ STACK_SHRINK(3);
+ break;
+ }
+
+ case DELETE_SUBSCR: {
+ PyObject *sub = stack_pointer[-1];
+ PyObject *container = stack_pointer[-2];
+ /* del container[sub] */
+ int err = PyObject_DelItem(container, sub);
+ Py_DECREF(container);
+ Py_DECREF(sub);
+ if (err) goto pop_2_error;
+ STACK_SHRINK(2);
+ break;
+ }
+
+ case CALL_INTRINSIC_1: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ assert(oparg <= MAX_INTRINSIC_1);
+ res = _PyIntrinsics_UnaryFunctions[oparg](tstate, value);
+ Py_DECREF(value);
+ if (res == NULL) goto pop_1_error;
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case CALL_INTRINSIC_2: {
+ PyObject *value1 = stack_pointer[-1];
+ PyObject *value2 = stack_pointer[-2];
+ PyObject *res;
+ assert(oparg <= MAX_INTRINSIC_2);
+ res = _PyIntrinsics_BinaryFunctions[oparg](tstate, value2, value1);
+ Py_DECREF(value2);
+ Py_DECREF(value1);
+ if (res == NULL) goto pop_2_error;
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case GET_AITER: {
+ PyObject *obj = stack_pointer[-1];
+ PyObject *iter;
+ unaryfunc getter = NULL;
+ PyTypeObject *type = Py_TYPE(obj);
+
+ if (type->tp_as_async != NULL) {
+ getter = type->tp_as_async->am_aiter;
+ }
+
+ if (getter == NULL) {
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "'async for' requires an object with "
+ "__aiter__ method, got %.100s",
+ type->tp_name);
+ Py_DECREF(obj);
+ if (true) goto pop_1_error;
+ }
+
+ iter = (*getter)(obj);
+ Py_DECREF(obj);
+ if (iter == NULL) goto pop_1_error;
+
+ if (Py_TYPE(iter)->tp_as_async == NULL ||
+ Py_TYPE(iter)->tp_as_async->am_anext == NULL) {
+
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "'async for' received an object from __aiter__ "
+ "that does not implement __anext__: %.100s",
+ Py_TYPE(iter)->tp_name);
+ Py_DECREF(iter);
+ if (true) goto pop_1_error;
+ }
+ stack_pointer[-1] = iter;
+ break;
+ }
+
+ case GET_ANEXT: {
+ PyObject *aiter = stack_pointer[-1];
+ PyObject *awaitable;
+ unaryfunc getter = NULL;
+ PyObject *next_iter = NULL;
+ PyTypeObject *type = Py_TYPE(aiter);
+
+ if (PyAsyncGen_CheckExact(aiter)) {
+ awaitable = type->tp_as_async->am_anext(aiter);
+ if (awaitable == NULL) {
+ goto error;
+ }
+ } else {
+ if (type->tp_as_async != NULL){
+ getter = type->tp_as_async->am_anext;
+ }
+
+ if (getter != NULL) {
+ next_iter = (*getter)(aiter);
+ if (next_iter == NULL) {
+ goto error;
+ }
+ }
+ else {
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "'async for' requires an iterator with "
+ "__anext__ method, got %.100s",
+ type->tp_name);
+ goto error;
+ }
+
+ awaitable = _PyCoro_GetAwaitableIter(next_iter);
+ if (awaitable == NULL) {
+ _PyErr_FormatFromCause(
+ PyExc_TypeError,
+ "'async for' received an invalid object "
+ "from __anext__: %.100s",
+ Py_TYPE(next_iter)->tp_name);
+
+ Py_DECREF(next_iter);
+ goto error;
+ } else {
+ Py_DECREF(next_iter);
+ }
+ }
+ STACK_GROW(1);
+ stack_pointer[-1] = awaitable;
+ break;
+ }
+
+ case GET_AWAITABLE: {
+ PyObject *iterable = stack_pointer[-1];
+ PyObject *iter;
+ iter = _PyCoro_GetAwaitableIter(iterable);
+
+ if (iter == NULL) {
+ format_awaitable_error(tstate, Py_TYPE(iterable), oparg);
+ }
+
+ Py_DECREF(iterable);
+
+ if (iter != NULL && PyCoro_CheckExact(iter)) {
+ PyObject *yf = _PyGen_yf((PyGenObject*)iter);
+ if (yf != NULL) {
+ /* `iter` is a coroutine object that is being
+ awaited, `yf` is a pointer to the current awaitable
+ being awaited on. */
+ Py_DECREF(yf);
+ Py_CLEAR(iter);
+ _PyErr_SetString(tstate, PyExc_RuntimeError,
+ "coroutine is being awaited already");
+ /* The code below jumps to `error` if `iter` is NULL. */
+ }
+ }
+
+ if (iter == NULL) goto pop_1_error;
+ stack_pointer[-1] = iter;
+ break;
+ }
+
+ case POP_EXCEPT: {
+ PyObject *exc_value = stack_pointer[-1];
+ _PyErr_StackItem *exc_info = tstate->exc_info;
+ Py_XSETREF(exc_info->exc_value, exc_value);
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case LOAD_ASSERTION_ERROR: {
+ PyObject *value;
+ value = Py_NewRef(PyExc_AssertionError);
+ STACK_GROW(1);
+ stack_pointer[-1] = value;
+ break;
+ }
+
+ case LOAD_BUILD_CLASS: {
+ PyObject *bc;
+ if (PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc) < 0) goto error;
+ if (bc == NULL) {
+ _PyErr_SetString(tstate, PyExc_NameError,
+ "__build_class__ not found");
+ if (true) goto error;
+ }
+ STACK_GROW(1);
+ stack_pointer[-1] = bc;
+ break;
+ }
+
+ case STORE_NAME: {
+ PyObject *v = stack_pointer[-1];
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *ns = LOCALS();
+ int err;
+ if (ns == NULL) {
+ _PyErr_Format(tstate, PyExc_SystemError,
+ "no locals found when storing %R", name);
+ Py_DECREF(v);
+ if (true) goto pop_1_error;
+ }
+ if (PyDict_CheckExact(ns))
+ err = PyDict_SetItem(ns, name, v);
+ else
+ err = PyObject_SetItem(ns, name, v);
+ Py_DECREF(v);
+ if (err) goto pop_1_error;
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case DELETE_NAME: {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *ns = LOCALS();
+ int err;
+ if (ns == NULL) {
+ _PyErr_Format(tstate, PyExc_SystemError,
+ "no locals when deleting %R", name);
+ goto error;
+ }
+ err = PyObject_DelItem(ns, name);
+ // Can't use ERROR_IF here.
+ if (err != 0) {
+ format_exc_check_arg(tstate, PyExc_NameError,
+ NAME_ERROR_MSG,
+ name);
+ goto error;
+ }
+ break;
+ }
+
+ case UNPACK_SEQUENCE: {
+ static_assert(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE == 1, "incorrect cache size");
+ PyObject *seq = stack_pointer[-1];
+ #if ENABLE_SPECIALIZATION
+ _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr;
+ if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
+ next_instr--;
+ _Py_Specialize_UnpackSequence(seq, next_instr, oparg);
+ DISPATCH_SAME_OPARG();
+ }
+ STAT_INC(UNPACK_SEQUENCE, deferred);
+ DECREMENT_ADAPTIVE_COUNTER(cache->counter);
+ #endif /* ENABLE_SPECIALIZATION */
+ PyObject **top = stack_pointer + oparg - 1;
+ int res = unpack_iterable(tstate, seq, oparg, -1, top);
+ Py_DECREF(seq);
+ if (res == 0) goto pop_1_error;
+ STACK_SHRINK(1);
+ STACK_GROW(oparg);
+ break;
+ }
+
+ case UNPACK_SEQUENCE_TWO_TUPLE: {
+ PyObject *seq = stack_pointer[-1];
+ PyObject **values = stack_pointer - (1);
+ DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE);
+ DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE);
+ assert(oparg == 2);
+ STAT_INC(UNPACK_SEQUENCE, hit);
+ values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1));
+ values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0));
+ Py_DECREF(seq);
+ STACK_SHRINK(1);
+ STACK_GROW(oparg);
+ break;
+ }
+
+ case UNPACK_SEQUENCE_TUPLE: {
+ PyObject *seq = stack_pointer[-1];
+ PyObject **values = stack_pointer - (1);
+ DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE);
+ DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE);
+ STAT_INC(UNPACK_SEQUENCE, hit);
+ PyObject **items = _PyTuple_ITEMS(seq);
+ for (int i = oparg; --i >= 0; ) {
+ *values++ = Py_NewRef(items[i]);
+ }
+ Py_DECREF(seq);
+ STACK_SHRINK(1);
+ STACK_GROW(oparg);
+ break;
+ }
+
+ case UNPACK_SEQUENCE_LIST: {
+ PyObject *seq = stack_pointer[-1];
+ PyObject **values = stack_pointer - (1);
+ DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE);
+ DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE);
+ STAT_INC(UNPACK_SEQUENCE, hit);
+ PyObject **items = _PyList_ITEMS(seq);
+ for (int i = oparg; --i >= 0; ) {
+ *values++ = Py_NewRef(items[i]);
+ }
+ Py_DECREF(seq);
+ STACK_SHRINK(1);
+ STACK_GROW(oparg);
+ break;
+ }
+
+ case UNPACK_EX: {
+ PyObject *seq = stack_pointer[-1];
+ int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8);
+ PyObject **top = stack_pointer + totalargs - 1;
+ int res = unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, top);
+ Py_DECREF(seq);
+ if (res == 0) goto pop_1_error;
+ STACK_GROW((oparg & 0xFF) + (oparg >> 8));
+ break;
+ }
+
+ case DELETE_ATTR: {
+ PyObject *owner = stack_pointer[-1];
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ int err = PyObject_DelAttr(owner, name);
+ Py_DECREF(owner);
+ if (err) goto pop_1_error;
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case STORE_GLOBAL: {
+ PyObject *v = stack_pointer[-1];
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ int err = PyDict_SetItem(GLOBALS(), name, v);
+ Py_DECREF(v);
+ if (err) goto pop_1_error;
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case DELETE_GLOBAL: {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ int err;
+ err = PyDict_DelItem(GLOBALS(), name);
+ // Can't use ERROR_IF here.
+ if (err != 0) {
+ if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
+ format_exc_check_arg(tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ }
+ goto error;
+ }
+ break;
+ }
+
+ case _LOAD_LOCALS: {
+ PyObject *locals;
+ locals = LOCALS();
+ if (locals == NULL) {
+ _PyErr_SetString(tstate, PyExc_SystemError,
+ "no locals found");
+ if (true) goto error;
+ }
+ Py_INCREF(locals);
+ STACK_GROW(1);
+ stack_pointer[-1] = locals;
+ break;
+ }
+
+ case _LOAD_FROM_DICT_OR_GLOBALS: {
+ PyObject *mod_or_class_dict = stack_pointer[-1];
+ PyObject *v;
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) {
+ Py_DECREF(mod_or_class_dict);
+ goto error;
+ }
+ Py_DECREF(mod_or_class_dict);
+ if (v == NULL) {
+ v = PyDict_GetItemWithError(GLOBALS(), name);
+ if (v != NULL) {
+ Py_INCREF(v);
+ }
+ else if (_PyErr_Occurred(tstate)) {
+ goto error;
+ }
+ else {
+ if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) {
+ goto error;
+ }
+ if (v == NULL) {
+ format_exc_check_arg(
+ tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ goto error;
+ }
+ }
+ }
+ stack_pointer[-1] = v;
+ break;
+ }
+
+ case LOAD_GLOBAL: {
+ static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size");
+ PyObject *null = NULL;
+ PyObject *v;
+ #if ENABLE_SPECIALIZATION
+ _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
+ if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ next_instr--;
+ _Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name);
+ DISPATCH_SAME_OPARG();
+ }
+ STAT_INC(LOAD_GLOBAL, deferred);
+ DECREMENT_ADAPTIVE_COUNTER(cache->counter);
+ #endif /* ENABLE_SPECIALIZATION */
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ if (PyDict_CheckExact(GLOBALS())
+ && PyDict_CheckExact(BUILTINS()))
+ {
+ v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(),
+ (PyDictObject *)BUILTINS(),
+ name);
+ if (v == NULL) {
+ if (!_PyErr_Occurred(tstate)) {
+ /* _PyDict_LoadGlobal() returns NULL without raising
+ * an exception if the key doesn't exist */
+ format_exc_check_arg(tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ }
+ if (true) goto error;
+ }
+ Py_INCREF(v);
+ }
+ else {
+ /* Slow-path if globals or builtins is not a dict */
+
+ /* namespace 1: globals */
+ if (PyMapping_GetOptionalItem(GLOBALS(), name, &v) < 0) goto error;
+ if (v == NULL) {
+ /* namespace 2: builtins */
+ if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) goto error;
+ if (v == NULL) {
+ format_exc_check_arg(
+ tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ if (true) goto error;
+ }
+ }
+ }
+ null = NULL;
+ STACK_GROW(1);
+ STACK_GROW(((oparg & 1) ? 1 : 0));
+ stack_pointer[-1] = v;
+ if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = null; }
+ break;
+ }
+
+ case _SKIP_CACHE: {
+ break;
+ }
+
+ case _GUARD_GLOBALS_VERSION: {
+ uint16_t version = (uint16_t)operand;
+ PyDictObject *dict = (PyDictObject *)GLOBALS();
+ DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL);
+ DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
+ assert(DK_IS_UNICODE(dict->ma_keys));
+ break;
+ }
+
+ case _GUARD_BUILTINS_VERSION: {
+ uint16_t version = (uint16_t)operand;
+ PyDictObject *dict = (PyDictObject *)BUILTINS();
+ DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL);
+ DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
+ assert(DK_IS_UNICODE(dict->ma_keys));
+ break;
+ }
+
+ case DELETE_FAST: {
+ PyObject *v = GETLOCAL(oparg);
+ if (v == NULL) goto unbound_local_error;
+ SETLOCAL(oparg, NULL);
+ break;
+ }
+
+ case DELETE_DEREF: {
+ PyObject *cell = GETLOCAL(oparg);
+ PyObject *oldobj = PyCell_GET(cell);
+ // Can't use ERROR_IF here.
+ // Fortunately we don't need its superpower.
+ if (oldobj == NULL) {
+ format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
+ goto error;
+ }
+ PyCell_SET(cell, NULL);
+ Py_DECREF(oldobj);
+ break;
+ }
+
+ case LOAD_FROM_DICT_OR_DEREF: {
+ PyObject *class_dict = stack_pointer[-1];
+ PyObject *value;
+ PyObject *name;
+ assert(class_dict);
+ assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus);
+ name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg);
+ if (PyMapping_GetOptionalItem(class_dict, name, &value) < 0) {
+ Py_DECREF(class_dict);
+ goto error;
+ }
+ Py_DECREF(class_dict);
+ if (!value) {
+ PyObject *cell = GETLOCAL(oparg);
+ value = PyCell_GET(cell);
+ if (value == NULL) {
+ format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
+ goto error;
+ }
+ Py_INCREF(value);
+ }
+ stack_pointer[-1] = value;
+ break;
+ }
+
+ case LOAD_DEREF: {
+ PyObject *value;
+ PyObject *cell = GETLOCAL(oparg);
+ value = PyCell_GET(cell);
+ if (value == NULL) {
+ format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
+ if (true) goto error;
+ }
+ Py_INCREF(value);
+ STACK_GROW(1);
+ stack_pointer[-1] = value;
+ break;
+ }
+
+ case STORE_DEREF: {
+ PyObject *v = stack_pointer[-1];
+ PyObject *cell = GETLOCAL(oparg);
+ PyObject *oldobj = PyCell_GET(cell);
+ PyCell_SET(cell, v);
+ Py_XDECREF(oldobj);
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case COPY_FREE_VARS: {
+ /* Copy closure variables to free variables */
+ PyCodeObject *co = _PyFrame_GetCode(frame);
+ assert(PyFunction_Check(frame->f_funcobj));
+ PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
+ assert(oparg == co->co_nfreevars);
+ int offset = co->co_nlocalsplus - oparg;
+ for (int i = 0; i < oparg; ++i) {
+ PyObject *o = PyTuple_GET_ITEM(closure, i);
+ frame->localsplus[offset + i] = Py_NewRef(o);
+ }
+ break;
+ }
+
+ case BUILD_STRING: {
+ PyObject **pieces = (stack_pointer - oparg);
+ PyObject *str;
+ str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg);
+ for (int _i = oparg; --_i >= 0;) {
+ Py_DECREF(pieces[_i]);
+ }
+ if (str == NULL) { STACK_SHRINK(oparg); goto error; }
+ STACK_SHRINK(oparg);
+ STACK_GROW(1);
+ stack_pointer[-1] = str;
+ break;
+ }
+
+ case BUILD_TUPLE: {
+ PyObject **values = (stack_pointer - oparg);
+ PyObject *tup;
+ tup = _PyTuple_FromArraySteal(values, oparg);
+ if (tup == NULL) { STACK_SHRINK(oparg); goto error; }
+ STACK_SHRINK(oparg);
+ STACK_GROW(1);
+ stack_pointer[-1] = tup;
+ break;
+ }
+
+ case BUILD_LIST: {
+ PyObject **values = (stack_pointer - oparg);
+ PyObject *list;
+ list = _PyList_FromArraySteal(values, oparg);
+ if (list == NULL) { STACK_SHRINK(oparg); goto error; }
+ STACK_SHRINK(oparg);
+ STACK_GROW(1);
+ stack_pointer[-1] = list;
+ break;
+ }
+
+ case LIST_EXTEND: {
+ PyObject *iterable = stack_pointer[-1];
+ PyObject *list = stack_pointer[-(2 + (oparg-1))];
+ PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable);
+ if (none_val == NULL) {
+ if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&
+ (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable)))
+ {
+ _PyErr_Clear(tstate);
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "Value after * must be an iterable, not %.200s",
+ Py_TYPE(iterable)->tp_name);
+ }
+ Py_DECREF(iterable);
+ if (true) goto pop_1_error;
+ }
+ assert(Py_IsNone(none_val));
+ Py_DECREF(iterable);
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case SET_UPDATE: {
+ PyObject *iterable = stack_pointer[-1];
+ PyObject *set = stack_pointer[-(2 + (oparg-1))];
+ int err = _PySet_Update(set, iterable);
+ Py_DECREF(iterable);
+ if (err < 0) goto pop_1_error;
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case BUILD_SET: {
+ PyObject **values = (stack_pointer - oparg);
+ PyObject *set;
+ set = PySet_New(NULL);
+ if (set == NULL)
+ goto error;
+ int err = 0;
+ for (int i = 0; i < oparg; i++) {
+ PyObject *item = values[i];
+ if (err == 0)
+ err = PySet_Add(set, item);
+ Py_DECREF(item);
+ }
+ if (err != 0) {
+ Py_DECREF(set);
+ if (true) { STACK_SHRINK(oparg); goto error; }
+ }
+ STACK_SHRINK(oparg);
+ STACK_GROW(1);
+ stack_pointer[-1] = set;
+ break;
+ }
+
+ case BUILD_MAP: {
+ PyObject **values = (stack_pointer - oparg*2);
+ PyObject *map;
+ map = _PyDict_FromItems(
+ values, 2,
+ values+1, 2,
+ oparg);
+ if (map == NULL)
+ goto error;
+
+ for (int _i = oparg*2; --_i >= 0;) {
+ Py_DECREF(values[_i]);
+ }
+ if (map == NULL) { STACK_SHRINK(oparg*2); goto error; }
+ STACK_SHRINK(oparg*2);
+ STACK_GROW(1);
+ stack_pointer[-1] = map;
+ break;
+ }
+
+ case SETUP_ANNOTATIONS: {
+ int err;
+ PyObject *ann_dict;
+ if (LOCALS() == NULL) {
+ _PyErr_Format(tstate, PyExc_SystemError,
+ "no locals found when setting up annotations");
+ if (true) goto error;
+ }
+ /* check if __annotations__ in locals()... */
+ if (PyDict_CheckExact(LOCALS())) {
+ ann_dict = _PyDict_GetItemWithError(LOCALS(),
+ &_Py_ID(__annotations__));
+ if (ann_dict == NULL) {
+ if (_PyErr_Occurred(tstate)) goto error;
+ /* ...if not, create a new one */
+ ann_dict = PyDict_New();
+ if (ann_dict == NULL) goto error;
+ err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__),
+ ann_dict);
+ Py_DECREF(ann_dict);
+ if (err) goto error;
+ }
+ }
+ else {
+ /* do the same if locals() is not a dict */
+ if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error;
+ if (ann_dict == NULL) {
+ ann_dict = PyDict_New();
+ if (ann_dict == NULL) goto error;
+ err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__),
+ ann_dict);
+ Py_DECREF(ann_dict);
+ if (err) goto error;
+ }
+ else {
+ Py_DECREF(ann_dict);
+ }
+ }
+ break;
+ }
+
+ case BUILD_CONST_KEY_MAP: {
+ PyObject *keys = stack_pointer[-1];
+ PyObject **values = (stack_pointer - (1 + oparg));
+ PyObject *map;
+ if (!PyTuple_CheckExact(keys) ||
+ PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) {
+ _PyErr_SetString(tstate, PyExc_SystemError,
+ "bad BUILD_CONST_KEY_MAP keys argument");
+ goto error; // Pop the keys and values.
+ }
+ map = _PyDict_FromItems(
+ &PyTuple_GET_ITEM(keys, 0), 1,
+ values, 1, oparg);
+ for (int _i = oparg; --_i >= 0;) {
+ Py_DECREF(values[_i]);
+ }
+ Py_DECREF(keys);
+ if (map == NULL) { STACK_SHRINK(oparg); goto pop_1_error; }
+ STACK_SHRINK(oparg);
+ stack_pointer[-1] = map;
+ break;
+ }
+
+ case DICT_UPDATE: {
+ PyObject *update = stack_pointer[-1];
+ PyObject *dict = PEEK(oparg + 1); // update is still on the stack
+ if (PyDict_Update(dict, update) < 0) {
+ if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "'%.200s' object is not a mapping",
+ Py_TYPE(update)->tp_name);
+ }
+ Py_DECREF(update);
+ if (true) goto pop_1_error;
+ }
+ Py_DECREF(update);
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case DICT_MERGE: {
+ PyObject *update = stack_pointer[-1];
+ PyObject *dict = PEEK(oparg + 1); // update is still on the stack
+
+ if (_PyDict_MergeEx(dict, update, 2) < 0) {
+ format_kwargs_error(tstate, PEEK(3 + oparg), update);
+ Py_DECREF(update);
+ if (true) goto pop_1_error;
+ }
+ Py_DECREF(update);
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case MAP_ADD: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *key = stack_pointer[-2];
+ PyObject *dict = PEEK(oparg + 2); // key, value are still on the stack
+ assert(PyDict_CheckExact(dict));
+ /* dict[key] = value */
+ // Do not DECREF INPUTS because the function steals the references
+ if (_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0) goto pop_2_error;
+ STACK_SHRINK(2);
+ break;
+ }
+
+ case LOAD_SUPER_ATTR_ATTR: {
+ PyObject *self = stack_pointer[-1];
+ PyObject *class = stack_pointer[-2];
+ PyObject *global_super = stack_pointer[-3];
+ PyObject *res2 = NULL;
+ PyObject *res;
+ assert(!(oparg & 1));
+ DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
+ DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
+ STAT_INC(LOAD_SUPER_ATTR, hit);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
+ res = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL);
+ Py_DECREF(global_super);
+ Py_DECREF(class);
+ Py_DECREF(self);
+ if (res == NULL) goto pop_3_error;
+ STACK_SHRINK(2);
+ STACK_GROW(((oparg & 1) ? 1 : 0));
+ stack_pointer[-1] = res;
+ if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }
+ break;
+ }
+
+ case LOAD_SUPER_ATTR_METHOD: {
+ PyObject *self = stack_pointer[-1];
+ PyObject *class = stack_pointer[-2];
+ PyObject *global_super = stack_pointer[-3];
+ PyObject *res2;
+ PyObject *res;
+ assert(oparg & 1);
+ DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
+ DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
+ STAT_INC(LOAD_SUPER_ATTR, hit);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
+ PyTypeObject *cls = (PyTypeObject *)class;
+ int method_found = 0;
+ res2 = _PySuper_Lookup(cls, self, name,
+ cls->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL);
+ Py_DECREF(global_super);
+ Py_DECREF(class);
+ if (res2 == NULL) {
+ Py_DECREF(self);
+ if (true) goto pop_3_error;
+ }
+ if (method_found) {
+ res = self; // transfer ownership
+ } else {
+ Py_DECREF(self);
+ res = res2;
+ res2 = NULL;
+ }
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ stack_pointer[-2] = res2;
+ break;
+ }
+
+ case LOAD_ATTR: {
+ static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
+ PyObject *owner = stack_pointer[-1];
+ PyObject *res2 = NULL;
+ PyObject *res;
+ #if ENABLE_SPECIALIZATION
+ _PyAttrCache *cache = (_PyAttrCache *)next_instr;
+ if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ next_instr--;
+ _Py_Specialize_LoadAttr(owner, next_instr, name);
+ DISPATCH_SAME_OPARG();
+ }
+ STAT_INC(LOAD_ATTR, deferred);
+ DECREMENT_ADAPTIVE_COUNTER(cache->counter);
+ #endif /* ENABLE_SPECIALIZATION */
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
+ if (oparg & 1) {
+ /* Designed to work in tandem with CALL, pushes two values. */
+ PyObject* meth = NULL;
+ if (_PyObject_GetMethod(owner, name, &meth)) {
+ /* We can bypass temporary bound method object.
+ meth is unbound method and obj is self.
+
+ meth | self | arg1 | ... | argN
+ */
+ assert(meth != NULL); // No errors on this branch
+ res2 = meth;
+ res = owner; // Transfer ownership
+ }
+ else {
+ /* meth is not an unbound method (but a regular attr, or
+ something was returned by a descriptor protocol). Set
+ the second element of the stack to NULL, to signal
+ CALL that it's not a method call.
+
+ NULL | meth | arg1 | ... | argN
+ */
+ Py_DECREF(owner);
+ if (meth == NULL) goto pop_1_error;
+ res2 = NULL;
+ res = meth;
+ }
+ }
+ else {
+ /* Classic, pushes one value. */
+ res = PyObject_GetAttr(owner, name);
+ Py_DECREF(owner);
+ if (res == NULL) goto pop_1_error;
+ }
+ STACK_GROW(((oparg & 1) ? 1 : 0));
+ stack_pointer[-1] = res;
+ if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }
+ break;
+ }
+
+ case _GUARD_TYPE_VERSION: {
+ PyObject *owner = stack_pointer[-1];
+ uint32_t type_version = (uint32_t)operand;
+ PyTypeObject *tp = Py_TYPE(owner);
+ assert(type_version != 0);
+ DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
+ break;
+ }
+
+ case _CHECK_MANAGED_OBJECT_HAS_VALUES: {
+ PyObject *owner = stack_pointer[-1];
+ assert(Py_TYPE(owner)->tp_dictoffset < 0);
+ assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
+ PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
+ DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);
+ break;
+ }
+
+ case COMPARE_OP: {
+ static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size");
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ #if ENABLE_SPECIALIZATION
+ _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
+ if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
+ next_instr--;
+ _Py_Specialize_CompareOp(left, right, next_instr, oparg);
+ DISPATCH_SAME_OPARG();
+ }
+ STAT_INC(COMPARE_OP, deferred);
+ DECREMENT_ADAPTIVE_COUNTER(cache->counter);
+ #endif /* ENABLE_SPECIALIZATION */
+ assert((oparg >> 5) <= Py_GE);
+ res = PyObject_RichCompare(left, right, oparg >> 5);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ if (res == NULL) goto pop_2_error;
+ if (oparg & 16) {
+ int res_bool = PyObject_IsTrue(res);
+ Py_DECREF(res);
+ if (res_bool < 0) goto pop_2_error;
+ res = res_bool ? Py_True : Py_False;
+ }
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case COMPARE_OP_FLOAT: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP);
+ DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP);
+ STAT_INC(COMPARE_OP, hit);
+ double dleft = PyFloat_AS_DOUBLE(left);
+ double dright = PyFloat_AS_DOUBLE(right);
+ // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg
+ int sign_ish = COMPARISON_BIT(dleft, dright);
+ _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
+ _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
+ res = (sign_ish & oparg) ? Py_True : Py_False;
+ // It's always a bool, so we don't care about oparg & 16.
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case COMPARE_OP_INT: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP);
+ DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP);
+ DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP);
+ DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_OP);
+ STAT_INC(COMPARE_OP, hit);
+ assert(_PyLong_DigitCount((PyLongObject *)left) <= 1 &&
+ _PyLong_DigitCount((PyLongObject *)right) <= 1);
+ Py_ssize_t ileft = _PyLong_CompactValue((PyLongObject *)left);
+ Py_ssize_t iright = _PyLong_CompactValue((PyLongObject *)right);
+ // 2 if <, 4 if >, 8 if ==; this matches the low 4 bits of the oparg
+ int sign_ish = COMPARISON_BIT(ileft, iright);
+ _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+ _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
+ res = (sign_ish & oparg) ? Py_True : Py_False;
+ // It's always a bool, so we don't care about oparg & 16.
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case COMPARE_OP_STR: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *res;
+ DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);
+ DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP);
+ STAT_INC(COMPARE_OP, hit);
+ int eq = _PyUnicode_Equal(left, right);
+ assert((oparg >> 5) == Py_EQ || (oparg >> 5) == Py_NE);
+ _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
+ _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
+ assert(eq == 0 || eq == 1);
+ assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS);
+ assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS);
+ res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False;
+ // It's always a bool, so we don't care about oparg & 16.
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case IS_OP: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *b;
+ int res = Py_Is(left, right) ^ oparg;
+ Py_DECREF(left);
+ Py_DECREF(right);
+ b = res ? Py_True : Py_False;
+ STACK_SHRINK(1);
+ stack_pointer[-1] = b;
+ break;
+ }
+
+ case CONTAINS_OP: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *b;
+ int res = PySequence_Contains(right, left);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ if (res < 0) goto pop_2_error;
+ b = (res ^ oparg) ? Py_True : Py_False;
+ STACK_SHRINK(1);
+ stack_pointer[-1] = b;
+ break;
+ }
+
+ case CHECK_EG_MATCH: {
+ PyObject *match_type = stack_pointer[-1];
+ PyObject *exc_value = stack_pointer[-2];
+ PyObject *rest;
+ PyObject *match;
+ if (check_except_star_type_valid(tstate, match_type) < 0) {
+ Py_DECREF(exc_value);
+ Py_DECREF(match_type);
+ if (true) goto pop_2_error;
+ }
+
+ match = NULL;
+ rest = NULL;
+ int res = exception_group_match(exc_value, match_type,
+ &match, &rest);
+ Py_DECREF(exc_value);
+ Py_DECREF(match_type);
+ if (res < 0) goto pop_2_error;
+
+ assert((match == NULL) == (rest == NULL));
+ if (match == NULL) goto pop_2_error;
+
+ if (!Py_IsNone(match)) {
+ PyErr_SetHandledException(match);
+ }
+ stack_pointer[-1] = match;
+ stack_pointer[-2] = rest;
+ break;
+ }
+
+ case CHECK_EXC_MATCH: {
+ PyObject *right = stack_pointer[-1];
+ PyObject *left = stack_pointer[-2];
+ PyObject *b;
+ assert(PyExceptionInstance_Check(left));
+ if (check_except_type_valid(tstate, right) < 0) {
+ Py_DECREF(right);
+ if (true) goto pop_1_error;
+ }
+
+ int res = PyErr_GivenExceptionMatches(left, right);
+ Py_DECREF(right);
+ b = res ? Py_True : Py_False;
+ stack_pointer[-1] = b;
+ break;
+ }
+
+ case IS_NONE: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *b;
+ if (Py_IsNone(value)) {
+ b = Py_True;
+ }
+ else {
+ b = Py_False;
+ Py_DECREF(value);
+ }
+ stack_pointer[-1] = b;
+ break;
+ }
+
+ case GET_LEN: {
+ PyObject *obj = stack_pointer[-1];
+ PyObject *len_o;
+ // PUSH(len(TOS))
+ Py_ssize_t len_i = PyObject_Length(obj);
+ if (len_i < 0) goto error;
+ len_o = PyLong_FromSsize_t(len_i);
+ if (len_o == NULL) goto error;
+ STACK_GROW(1);
+ stack_pointer[-1] = len_o;
+ break;
+ }
+
+ case MATCH_CLASS: {
+ PyObject *names = stack_pointer[-1];
+ PyObject *type = stack_pointer[-2];
+ PyObject *subject = stack_pointer[-3];
+ PyObject *attrs;
+ // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or
+ // None on failure.
+ assert(PyTuple_CheckExact(names));
+ attrs = match_class(tstate, subject, type, oparg, names);
+ Py_DECREF(subject);
+ Py_DECREF(type);
+ Py_DECREF(names);
+ if (attrs) {
+ assert(PyTuple_CheckExact(attrs)); // Success!
+ }
+ else {
+ if (_PyErr_Occurred(tstate)) goto pop_3_error;
+ attrs = Py_None; // Failure!
+ }
+ STACK_SHRINK(2);
+ stack_pointer[-1] = attrs;
+ break;
+ }
+
+ case MATCH_MAPPING: {
+ PyObject *subject = stack_pointer[-1];
+ PyObject *res;
+ int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING;
+ res = match ? Py_True : Py_False;
+ STACK_GROW(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case MATCH_SEQUENCE: {
+ PyObject *subject = stack_pointer[-1];
+ PyObject *res;
+ int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE;
+ res = match ? Py_True : Py_False;
+ STACK_GROW(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case MATCH_KEYS: {
+ PyObject *keys = stack_pointer[-1];
+ PyObject *subject = stack_pointer[-2];
+ PyObject *values_or_none;
+ // On successful match, PUSH(values). Otherwise, PUSH(None).
+ values_or_none = match_keys(tstate, subject, keys);
+ if (values_or_none == NULL) goto error;
+ STACK_GROW(1);
+ stack_pointer[-1] = values_or_none;
+ break;
+ }
+
+ case GET_ITER: {
+ PyObject *iterable = stack_pointer[-1];
+ PyObject *iter;
+ /* before: [obj]; after [getiter(obj)] */
+ iter = PyObject_GetIter(iterable);
+ Py_DECREF(iterable);
+ if (iter == NULL) goto pop_1_error;
+ stack_pointer[-1] = iter;
+ break;
+ }
+
+ case GET_YIELD_FROM_ITER: {
+ PyObject *iterable = stack_pointer[-1];
+ PyObject *iter;
+ /* before: [obj]; after [getiter(obj)] */
+ if (PyCoro_CheckExact(iterable)) {
+ /* `iterable` is a coroutine */
+ if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
+ /* and it is used in a 'yield from' expression of a
+ regular generator. */
+ _PyErr_SetString(tstate, PyExc_TypeError,
+ "cannot 'yield from' a coroutine object "
+ "in a non-coroutine generator");
+ goto error;
+ }
+ iter = iterable;
+ }
+ else if (PyGen_CheckExact(iterable)) {
+ iter = iterable;
+ }
+ else {
+ /* `iterable` is not a generator. */
+ iter = PyObject_GetIter(iterable);
+ if (iter == NULL) {
+ goto error;
+ }
+ Py_DECREF(iterable);
+ }
+ stack_pointer[-1] = iter;
+ break;
+ }
+
+ case _ITER_CHECK_LIST: {
+ PyObject *iter = stack_pointer[-1];
+ DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER);
+ break;
+ }
+
+ case _IS_ITER_EXHAUSTED_LIST: {
+ PyObject *iter = stack_pointer[-1];
+ PyObject *exhausted;
+ _PyListIterObject *it = (_PyListIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyListIter_Type);
+ PyListObject *seq = it->it_seq;
+ if (seq == NULL) {
+ exhausted = Py_True;
+ }
+ else if (it->it_index >= PyList_GET_SIZE(seq)) {
+ Py_DECREF(seq);
+ it->it_seq = NULL;
+ exhausted = Py_True;
+ }
+ else {
+ exhausted = Py_False;
+ }
+ STACK_GROW(1);
+ stack_pointer[-1] = exhausted;
+ break;
+ }
+
+ case _ITER_NEXT_LIST: {
+ PyObject *iter = stack_pointer[-1];
+ PyObject *next;
+ _PyListIterObject *it = (_PyListIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyListIter_Type);
+ PyListObject *seq = it->it_seq;
+ assert(seq);
+ assert(it->it_index < PyList_GET_SIZE(seq));
+ next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++));
+ STACK_GROW(1);
+ stack_pointer[-1] = next;
+ break;
+ }
+
+ case _ITER_CHECK_TUPLE: {
+ PyObject *iter = stack_pointer[-1];
+ DEOPT_IF(Py_TYPE(iter) != &PyTupleIter_Type, FOR_ITER);
+ break;
+ }
+
+ case _IS_ITER_EXHAUSTED_TUPLE: {
+ PyObject *iter = stack_pointer[-1];
+ PyObject *exhausted;
+ _PyTupleIterObject *it = (_PyTupleIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyTupleIter_Type);
+ PyTupleObject *seq = it->it_seq;
+ if (seq == NULL) {
+ exhausted = Py_True;
+ }
+ else if (it->it_index >= PyTuple_GET_SIZE(seq)) {
+ Py_DECREF(seq);
+ it->it_seq = NULL;
+ exhausted = Py_True;
+ }
+ else {
+ exhausted = Py_False;
+ }
+ STACK_GROW(1);
+ stack_pointer[-1] = exhausted;
+ break;
+ }
+
+ case _ITER_NEXT_TUPLE: {
+ PyObject *iter = stack_pointer[-1];
+ PyObject *next;
+ _PyTupleIterObject *it = (_PyTupleIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyTupleIter_Type);
+ PyTupleObject *seq = it->it_seq;
+ assert(seq);
+ assert(it->it_index < PyTuple_GET_SIZE(seq));
+ next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++));
+ STACK_GROW(1);
+ stack_pointer[-1] = next;
+ break;
+ }
+
+ case _ITER_CHECK_RANGE: {
+ PyObject *iter = stack_pointer[-1];
+ _PyRangeIterObject *r = (_PyRangeIterObject *)iter;
+ DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER);
+ break;
+ }
+
+ case _IS_ITER_EXHAUSTED_RANGE: {
+ PyObject *iter = stack_pointer[-1];
+ PyObject *exhausted;
+ _PyRangeIterObject *r = (_PyRangeIterObject *)iter;
+ assert(Py_TYPE(r) == &PyRangeIter_Type);
+ exhausted = r->len <= 0 ? Py_True : Py_False;
+ STACK_GROW(1);
+ stack_pointer[-1] = exhausted;
+ break;
+ }
+
+ case _ITER_NEXT_RANGE: {
+ PyObject *iter = stack_pointer[-1];
+ PyObject *next;
+ _PyRangeIterObject *r = (_PyRangeIterObject *)iter;
+ assert(Py_TYPE(r) == &PyRangeIter_Type);
+ assert(r->len > 0);
+ long value = r->start;
+ r->start = value + r->step;
+ r->len--;
+ next = PyLong_FromLong(value);
+ if (next == NULL) goto error;
+ STACK_GROW(1);
+ stack_pointer[-1] = next;
+ break;
+ }
+
+ case WITH_EXCEPT_START: {
+ PyObject *val = stack_pointer[-1];
+ PyObject *lasti = stack_pointer[-3];
+ PyObject *exit_func = stack_pointer[-4];
+ PyObject *res;
+ /* At the top of the stack are 4 values:
+ - val: TOP = exc_info()
+ - unused: SECOND = previous exception
+ - lasti: THIRD = lasti of exception in exc_info()
+ - exit_func: FOURTH = the context.__exit__ bound method
+ We call FOURTH(type(TOP), TOP, GetTraceback(TOP)).
+ Then we push the __exit__ return value.
+ */
+ PyObject *exc, *tb;
+
+ assert(val && PyExceptionInstance_Check(val));
+ exc = PyExceptionInstance_Class(val);
+ tb = PyException_GetTraceback(val);
+ Py_XDECREF(tb);
+ assert(PyLong_Check(lasti));
+ (void)lasti; // Shut up compiler warning if asserts are off
+ PyObject *stack[4] = {NULL, exc, val, tb};
+ res = PyObject_Vectorcall(exit_func, stack + 1,
+ 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
+ if (res == NULL) goto error;
+ STACK_GROW(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case PUSH_EXC_INFO: {
+ PyObject *new_exc = stack_pointer[-1];
+ PyObject *prev_exc;
+ _PyErr_StackItem *exc_info = tstate->exc_info;
+ if (exc_info->exc_value != NULL) {
+ prev_exc = exc_info->exc_value;
+ }
+ else {
+ prev_exc = Py_None;
+ }
+ assert(PyExceptionInstance_Check(new_exc));
+ exc_info->exc_value = Py_NewRef(new_exc);
+ STACK_GROW(1);
+ stack_pointer[-1] = new_exc;
+ stack_pointer[-2] = prev_exc;
+ break;
+ }
+
+ case EXIT_INIT_CHECK: {
+ PyObject *should_be_none = stack_pointer[-1];
+ assert(STACK_LEVEL() == 2);
+ if (should_be_none != Py_None) {
+ PyErr_Format(PyExc_TypeError,
+ "__init__() should return None, not '%.200s'",
+ Py_TYPE(should_be_none)->tp_name);
+ goto error;
+ }
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case MAKE_FUNCTION: {
+ PyObject *codeobj = stack_pointer[-1];
+ PyObject *func;
+
+ PyFunctionObject *func_obj = (PyFunctionObject *)
+ PyFunction_New(codeobj, GLOBALS());
+
+ Py_DECREF(codeobj);
+ if (func_obj == NULL) {
+ goto error;
+ }
+
+ func_obj->func_version = ((PyCodeObject *)codeobj)->co_version;
+ func = (PyObject *)func_obj;
+ stack_pointer[-1] = func;
+ break;
+ }
+
+ case SET_FUNCTION_ATTRIBUTE: {
+ PyObject *func = stack_pointer[-1];
+ PyObject *attr = stack_pointer[-2];
+ assert(PyFunction_Check(func));
+ PyFunctionObject *func_obj = (PyFunctionObject *)func;
+ switch(oparg) {
+ case MAKE_FUNCTION_CLOSURE:
+ assert(func_obj->func_closure == NULL);
+ func_obj->func_closure = attr;
+ break;
+ case MAKE_FUNCTION_ANNOTATIONS:
+ assert(func_obj->func_annotations == NULL);
+ func_obj->func_annotations = attr;
+ break;
+ case MAKE_FUNCTION_KWDEFAULTS:
+ assert(PyDict_CheckExact(attr));
+ assert(func_obj->func_kwdefaults == NULL);
+ func_obj->func_kwdefaults = attr;
+ break;
+ case MAKE_FUNCTION_DEFAULTS:
+ assert(PyTuple_CheckExact(attr));
+ assert(func_obj->func_defaults == NULL);
+ func_obj->func_defaults = attr;
+ break;
+ default:
+ Py_UNREACHABLE();
+ }
+ STACK_SHRINK(1);
+ stack_pointer[-1] = func;
+ break;
+ }
+
+ case BUILD_SLICE: {
+ PyObject *step = (oparg == 3) ? stack_pointer[-(((oparg == 3) ? 1 : 0))] : NULL;
+ PyObject *stop = stack_pointer[-(1 + ((oparg == 3) ? 1 : 0))];
+ PyObject *start = stack_pointer[-(2 + ((oparg == 3) ? 1 : 0))];
+ PyObject *slice;
+ slice = PySlice_New(start, stop, step);
+ Py_DECREF(start);
+ Py_DECREF(stop);
+ Py_XDECREF(step);
+ if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error; }
+ STACK_SHRINK(((oparg == 3) ? 1 : 0));
+ STACK_SHRINK(1);
+ stack_pointer[-1] = slice;
+ break;
+ }
+
+ case CONVERT_VALUE: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *result;
+ convertion_func_ptr conv_fn;
+ assert(oparg >= FVC_STR && oparg <= FVC_ASCII);
+ conv_fn = CONVERSION_FUNCTIONS[oparg];
+ result = conv_fn(value);
+ Py_DECREF(value);
+ if (result == NULL) goto pop_1_error;
+ stack_pointer[-1] = result;
+ break;
+ }
+
+ case FORMAT_SIMPLE: {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ /* If value is a unicode object, then we know the result
+ * of format(value) is value itself. */
+ if (!PyUnicode_CheckExact(value)) {
+ res = PyObject_Format(value, NULL);
+ Py_DECREF(value);
+ if (res == NULL) goto pop_1_error;
+ }
+ else {
+ res = value;
+ }
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case FORMAT_WITH_SPEC: {
+ PyObject *fmt_spec = stack_pointer[-1];
+ PyObject *value = stack_pointer[-2];
+ PyObject *res;
+ res = PyObject_Format(value, fmt_spec);
+ Py_DECREF(value);
+ Py_DECREF(fmt_spec);
+ if (res == NULL) goto pop_2_error;
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case COPY: {
+ PyObject *bottom = stack_pointer[-(1 + (oparg-1))];
+ PyObject *top;
+ assert(oparg > 0);
+ top = Py_NewRef(bottom);
+ STACK_GROW(1);
+ stack_pointer[-1] = top;
+ break;
+ }
+
+ case BINARY_OP: {
+ static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
+ PyObject *rhs = stack_pointer[-1];
+ PyObject *lhs = stack_pointer[-2];
+ PyObject *res;
+ #if ENABLE_SPECIALIZATION
+ _PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr;
+ if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
+ next_instr--;
+ _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, &GETLOCAL(0));
+ DISPATCH_SAME_OPARG();
+ }
+ STAT_INC(BINARY_OP, deferred);
+ DECREMENT_ADAPTIVE_COUNTER(cache->counter);
+ #endif /* ENABLE_SPECIALIZATION */
+ assert(0 <= oparg);
+ assert((unsigned)oparg < Py_ARRAY_LENGTH(binary_ops));
+ assert(binary_ops[oparg]);
+ res = binary_ops[oparg](lhs, rhs);
+ Py_DECREF(lhs);
+ Py_DECREF(rhs);
+ if (res == NULL) goto pop_2_error;
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ break;
+ }
+
+ case SWAP: {
+ PyObject *top = stack_pointer[-1];
+ PyObject *bottom = stack_pointer[-(2 + (oparg-2))];
+ assert(oparg >= 2);
+ stack_pointer[-1] = bottom;
+ stack_pointer[-(2 + (oparg-2))] = top;
+ break;
+ }
+
+ case _POP_JUMP_IF_FALSE: {
+ PyObject *flag = stack_pointer[-1];
+ if (Py_IsFalse(flag)) {
+ pc = oparg;
+ }
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case _POP_JUMP_IF_TRUE: {
+ PyObject *flag = stack_pointer[-1];
+ if (Py_IsTrue(flag)) {
+ pc = oparg;
+ }
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case JUMP_TO_TOP: {
+ pc = 0;
+ break;
+ }
+
+ case SAVE_IP: {
+ frame->prev_instr = ip_offset + oparg;
+ break;
+ }
+
+ case EXIT_TRACE: {
+ frame->prev_instr--; // Back up to just before destination
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ Py_DECREF(self);
+ return frame;
+ break;
+ }
diff --git a/Python/flowgraph.c b/Python/flowgraph.c
index a144057cd9383a..e485ed103147a1 100644
--- a/Python/flowgraph.c
+++ b/Python/flowgraph.c
@@ -7,9 +7,7 @@
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
#include "pycore_opcode_utils.h"
-#define NEED_OPCODE_METADATA
-#include "opcode_metadata.h" // _PyOpcode_opcode_metadata, _PyOpcode_num_popped/pushed
-#undef NEED_OPCODE_METADATA
+#include "pycore_opcode_metadata.h" // OPCODE_HAS_ARG, etc
#undef SUCCESS
@@ -45,13 +43,13 @@ is_block_push(cfg_instr *i)
static inline int
is_jump(cfg_instr *i)
{
- return IS_JUMP_OPCODE(i->i_opcode);
+ return OPCODE_HAS_JUMP(i->i_opcode);
}
/* One arg*/
#define INSTR_SET_OP1(I, OP, ARG) \
do { \
- assert(HAS_ARG(OP)); \
+ assert(OPCODE_HAS_ARG(OP)); \
_PyCfgInstruction *_instr__ptr_ = (I); \
_instr__ptr_->i_opcode = (OP); \
_instr__ptr_->i_oparg = (ARG); \
@@ -60,7 +58,7 @@ is_jump(cfg_instr *i)
/* No args*/
#define INSTR_SET_OP0(I, OP) \
do { \
- assert(!HAS_ARG(OP)); \
+ assert(!OPCODE_HAS_ARG(OP)); \
_PyCfgInstruction *_instr__ptr_ = (I); \
_instr__ptr_->i_opcode = (OP); \
_instr__ptr_->i_oparg = 0; \
@@ -110,7 +108,7 @@ basicblock_addop(basicblock *b, int opcode, int oparg, location loc)
{
assert(IS_WITHIN_OPCODE_RANGE(opcode));
assert(!IS_ASSEMBLER_OPCODE(opcode));
- assert(HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
+ assert(OPCODE_HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
assert(0 <= oparg && oparg < (1 << 30));
int off = basicblock_next_instr(b);
@@ -166,22 +164,6 @@ _PyBasicblock_InsertInstruction(basicblock *block, int pos, cfg_instr *instr) {
return SUCCESS;
}
-static int
-instr_size(cfg_instr *instruction)
-{
- return _PyCompile_InstrSize(instruction->i_opcode, instruction->i_oparg);
-}
-
-static int
-blocksize(basicblock *b)
-{
- int size = 0;
- for (int i = 0; i < b->b_iused; i++) {
- size += instr_size(&b->b_instr[i]);
- }
- return size;
-}
-
/* For debugging purposes only */
#if 0
static void
@@ -192,7 +174,7 @@ dump_instr(cfg_instr *i)
char arg[128];
*arg = '\0';
- if (HAS_ARG(i->i_opcode)) {
+ if (OPCODE_HAS_ARG(i->i_opcode)) {
sprintf(arg, "arg: %d ", i->i_oparg);
}
if (HAS_TARGET(i->i_opcode)) {
@@ -212,9 +194,9 @@ static void
dump_basicblock(const basicblock *b)
{
const char *b_return = basicblock_returns(b) ? "return " : "";
- fprintf(stderr, "%d: [EH=%d CLD=%d WRM=%d NO_FT=%d %p] used: %d, depth: %d, offset: %d %s\n",
+ fprintf(stderr, "%d: [EH=%d CLD=%d WRM=%d NO_FT=%d %p] used: %d, depth: %d, %s\n",
b->b_label.id, b->b_except_handler, b->b_cold, b->b_warm, BB_NO_FALLTHROUGH(b), b, b->b_iused,
- b->b_startdepth, b->b_offset, b_return);
+ b->b_startdepth, b_return);
if (b->b_instr) {
int i;
for (i = 0; i < b->b_iused; i++) {
@@ -409,20 +391,17 @@ no_redundant_jumps(cfg_builder *g) {
static int
normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
cfg_instr *last = _PyCfg_BasicblockLastInstr(b);
- if (last == NULL || !is_jump(last)) {
+ if (last == NULL || !is_jump(last) ||
+ IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {
return SUCCESS;
}
assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
+
bool is_forward = last->i_target->b_visited == 0;
- switch(last->i_opcode) {
- case JUMP:
- last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
- return SUCCESS;
- case JUMP_NO_INTERRUPT:
- last->i_opcode = is_forward ?
- JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
- return SUCCESS;
+ if (is_forward) {
+ return SUCCESS;
}
+
int reversed_opcode = 0;
switch(last->i_opcode) {
case POP_JUMP_IF_NOT_NONE:
@@ -438,9 +417,6 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
reversed_opcode = POP_JUMP_IF_FALSE;
break;
}
- if (is_forward) {
- return SUCCESS;
- }
/* transform 'conditional jump T' to
* 'reversed_jump b_next' followed by 'jump_backwards T'
*/
@@ -476,71 +452,11 @@ normalize_jumps(_PyCfgBuilder *g)
return SUCCESS;
}
-static void
-resolve_jump_offsets(basicblock *entryblock)
-{
- int bsize, totsize, extended_arg_recompile;
-
- /* Compute the size of each block and fixup jump args.
- Replace block pointer with position in bytecode. */
- do {
- totsize = 0;
- for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
- bsize = blocksize(b);
- b->b_offset = totsize;
- totsize += bsize;
- }
- extended_arg_recompile = 0;
- for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
- bsize = b->b_offset;
- for (int i = 0; i < b->b_iused; i++) {
- cfg_instr *instr = &b->b_instr[i];
- int isize = instr_size(instr);
- /* jump offsets are computed relative to
- * the instruction pointer after fetching
- * the jump instruction.
- */
- bsize += isize;
- if (is_jump(instr)) {
- instr->i_oparg = instr->i_target->b_offset;
- if (instr->i_oparg < bsize) {
- assert(IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
- instr->i_oparg = bsize - instr->i_oparg;
- }
- else {
- assert(!IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
- instr->i_oparg -= bsize;
- }
- if (instr_size(instr) != isize) {
- extended_arg_recompile = 1;
- }
- }
- }
- }
-
- /* XXX: This is an awful hack that could hurt performance, but
- on the bright side it should work until we come up
- with a better solution.
-
- The issue is that in the first loop blocksize() is called
- which calls instr_size() which requires i_oparg be set
- appropriately. There is a bootstrap problem because
- i_oparg is calculated in the second loop above.
-
- So we loop until we stop seeing new EXTENDED_ARGs.
- The only EXTENDED_ARGs that could be popping up are
- ones in jump instructions. So this should converge
- fairly quickly.
- */
- } while (extended_arg_recompile);
-}
-
int
_PyCfg_ResolveJumps(_PyCfgBuilder *g)
{
RETURN_IF_ERROR(normalize_jumps(g));
assert(no_redundant_jumps(g));
- resolve_jump_offsets(g->g_entryblock);
return SUCCESS;
}
@@ -1103,7 +1019,7 @@ static PyObject*
get_const_value(int opcode, int oparg, PyObject *co_consts)
{
PyObject *constant = NULL;
- assert(HAS_CONST(opcode));
+ assert(OPCODE_HAS_CONST(opcode));
if (opcode == LOAD_CONST) {
constant = PyList_GET_ITEM(co_consts, oparg);
}
@@ -1116,6 +1032,36 @@ get_const_value(int opcode, int oparg, PyObject *co_consts)
return Py_NewRef(constant);
}
+// Steals a reference to newconst.
+static int
+add_const(PyObject *newconst, PyObject *consts, PyObject *const_cache)
+{
+ if (_PyCompile_ConstCacheMergeOne(const_cache, &newconst) < 0) {
+ Py_DECREF(newconst);
+ return -1;
+ }
+
+ Py_ssize_t index;
+ for (index = 0; index < PyList_GET_SIZE(consts); index++) {
+ if (PyList_GET_ITEM(consts, index) == newconst) {
+ break;
+ }
+ }
+ if (index == PyList_GET_SIZE(consts)) {
+ if ((size_t)index >= (size_t)INT_MAX - 1) {
+ PyErr_SetString(PyExc_OverflowError, "too many constants");
+ Py_DECREF(newconst);
+ return -1;
+ }
+ if (PyList_Append(consts, newconst)) {
+ Py_DECREF(newconst);
+ return -1;
+ }
+ }
+ Py_DECREF(newconst);
+ return (int)index;
+}
+
/* Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cn, BUILD_TUPLE n
with LOAD_CONST (c1, c2, ... cn).
The consts table must still be in list form so that the
@@ -1134,7 +1080,7 @@ fold_tuple_on_constants(PyObject *const_cache,
assert(inst[n].i_oparg == n);
for (int i = 0; i < n; i++) {
- if (!HAS_CONST(inst[i].i_opcode)) {
+ if (!OPCODE_HAS_CONST(inst[i].i_opcode)) {
return SUCCESS;
}
}
@@ -1153,33 +1099,14 @@ fold_tuple_on_constants(PyObject *const_cache,
}
PyTuple_SET_ITEM(newconst, i, constant);
}
- if (_PyCompile_ConstCacheMergeOne(const_cache, &newconst) < 0) {
- Py_DECREF(newconst);
+ int index = add_const(newconst, consts, const_cache);
+ if (index < 0) {
return ERROR;
}
-
- Py_ssize_t index;
- for (index = 0; index < PyList_GET_SIZE(consts); index++) {
- if (PyList_GET_ITEM(consts, index) == newconst) {
- break;
- }
- }
- if (index == PyList_GET_SIZE(consts)) {
- if ((size_t)index >= (size_t)INT_MAX - 1) {
- Py_DECREF(newconst);
- PyErr_SetString(PyExc_OverflowError, "too many constants");
- return ERROR;
- }
- if (PyList_Append(consts, newconst)) {
- Py_DECREF(newconst);
- return ERROR;
- }
- }
- Py_DECREF(newconst);
for (int i = 0; i < n; i++) {
INSTR_SET_OP0(&inst[i], NOP);
}
- INSTR_SET_OP1(&inst[n], LOAD_CONST, (int)index);
+ INSTR_SET_OP1(&inst[n], LOAD_CONST, index);
return SUCCESS;
}
@@ -1433,24 +1360,71 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
}
break;
case IS_OP:
+ // Fold to POP_JUMP_IF_NONE:
+ // - LOAD_CONST(None) IS_OP(0) POP_JUMP_IF_TRUE
+ // - LOAD_CONST(None) IS_OP(1) POP_JUMP_IF_FALSE
+ // - LOAD_CONST(None) IS_OP(0) TO_BOOL POP_JUMP_IF_TRUE
+ // - LOAD_CONST(None) IS_OP(1) TO_BOOL POP_JUMP_IF_FALSE
+ // Fold to POP_JUMP_IF_NOT_NONE:
+ // - LOAD_CONST(None) IS_OP(0) POP_JUMP_IF_FALSE
+ // - LOAD_CONST(None) IS_OP(1) POP_JUMP_IF_TRUE
+ // - LOAD_CONST(None) IS_OP(0) TO_BOOL POP_JUMP_IF_FALSE
+ // - LOAD_CONST(None) IS_OP(1) TO_BOOL POP_JUMP_IF_TRUE
cnt = get_const_value(opcode, oparg, consts);
if (cnt == NULL) {
goto error;
}
- int jump_op = i+2 < bb->b_iused ? bb->b_instr[i+2].i_opcode : 0;
- if (Py_IsNone(cnt) && (jump_op == POP_JUMP_IF_FALSE || jump_op == POP_JUMP_IF_TRUE)) {
- unsigned char nextarg = bb->b_instr[i+1].i_oparg;
- INSTR_SET_OP0(inst, NOP);
- INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);
- bb->b_instr[i+2].i_opcode = nextarg ^ (jump_op == POP_JUMP_IF_FALSE) ?
- POP_JUMP_IF_NOT_NONE : POP_JUMP_IF_NONE;
+ if (!Py_IsNone(cnt)) {
+ Py_DECREF(cnt);
+ break;
}
- Py_DECREF(cnt);
+ if (bb->b_iused <= i + 2) {
+ break;
+ }
+ cfg_instr *is_instr = &bb->b_instr[i + 1];
+ cfg_instr *jump_instr = &bb->b_instr[i + 2];
+ // Get rid of TO_BOOL regardless:
+ if (jump_instr->i_opcode == TO_BOOL) {
+ INSTR_SET_OP0(jump_instr, NOP);
+ if (bb->b_iused <= i + 3) {
+ break;
+ }
+ jump_instr = &bb->b_instr[i + 3];
+ }
+ bool invert = is_instr->i_oparg;
+ if (jump_instr->i_opcode == POP_JUMP_IF_FALSE) {
+ invert = !invert;
+ }
+ else if (jump_instr->i_opcode != POP_JUMP_IF_TRUE) {
+ break;
+ }
+ INSTR_SET_OP0(inst, NOP);
+ INSTR_SET_OP0(is_instr, NOP);
+ jump_instr->i_opcode = invert ? POP_JUMP_IF_NOT_NONE
+ : POP_JUMP_IF_NONE;
break;
case RETURN_VALUE:
INSTR_SET_OP0(inst, NOP);
INSTR_SET_OP1(&bb->b_instr[++i], RETURN_CONST, oparg);
break;
+ case TO_BOOL:
+ cnt = get_const_value(opcode, oparg, consts);
+ if (cnt == NULL) {
+ goto error;
+ }
+ is_true = PyObject_IsTrue(cnt);
+ Py_DECREF(cnt);
+ if (is_true == -1) {
+ goto error;
+ }
+ cnt = PyBool_FromLong(is_true);
+ int index = add_const(cnt, consts, const_cache);
+ if (index < 0) {
+ return ERROR;
+ }
+ INSTR_SET_OP0(inst, NOP);
+ INSTR_SET_OP1(&bb->b_instr[i + 1], LOAD_CONST, index);
+ break;
}
break;
}
@@ -1536,9 +1510,42 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
inst[1].i_oparg |= 1;
}
break;
+ case COMPARE_OP:
+ if (nextop == TO_BOOL) {
+ INSTR_SET_OP0(inst, NOP);
+ INSTR_SET_OP1(&bb->b_instr[i + 1], COMPARE_OP, oparg | 16);
+ continue;
+ }
+ break;
+ case CONTAINS_OP:
+ case IS_OP:
+ if (nextop == TO_BOOL) {
+ INSTR_SET_OP0(inst, NOP);
+ INSTR_SET_OP1(&bb->b_instr[i + 1], opcode, oparg);
+ continue;
+ }
+ break;
+ case TO_BOOL:
+ if (nextop == TO_BOOL) {
+ INSTR_SET_OP0(inst, NOP);
+ continue;
+ }
+ break;
+ case UNARY_NOT:
+ if (nextop == TO_BOOL) {
+ INSTR_SET_OP0(inst, NOP);
+ INSTR_SET_OP0(&bb->b_instr[i + 1], UNARY_NOT);
+ continue;
+ }
+ if (nextop == UNARY_NOT) {
+ INSTR_SET_OP0(inst, NOP);
+ INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);
+ continue;
+ }
+ break;
default:
- /* All HAS_CONST opcodes should be handled with LOAD_CONST */
- assert (!HAS_CONST(inst->i_opcode));
+ /* All OPCODE_HAS_CONST opcodes should be handled with LOAD_CONST */
+ assert (!OPCODE_HAS_CONST(inst->i_opcode));
}
}
@@ -1788,7 +1795,7 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)
/* mark used consts */
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
for (int i = 0; i < b->b_iused; i++) {
- if (HAS_CONST(b->b_instr[i].i_opcode)) {
+ if (OPCODE_HAS_CONST(b->b_instr[i].i_opcode)) {
int index = b->b_instr[i].i_oparg;
index_map[index] = index;
}
@@ -1841,7 +1848,7 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
for (int i = 0; i < b->b_iused; i++) {
- if (HAS_CONST(b->b_instr[i].i_opcode)) {
+ if (OPCODE_HAS_CONST(b->b_instr[i].i_opcode)) {
int index = b->b_instr[i].i_oparg;
assert(reverse_index_map[index] >= 0);
assert(reverse_index_map[index] < n_used_consts);
@@ -2071,9 +2078,15 @@ _PyCfg_ConvertPseudoOps(basicblock *entryblock)
for (int i = 0; i < b->b_iused; i++) {
cfg_instr *instr = &b->b_instr[i];
if (is_block_push(instr) || instr->i_opcode == POP_BLOCK) {
+ assert(SAME_OPCODE_METADATA(instr->i_opcode, NOP));
INSTR_SET_OP0(instr, NOP);
}
+ else if (instr->i_opcode == LOAD_CLOSURE) {
+ assert(SAME_OPCODE_METADATA(LOAD_CLOSURE, LOAD_FAST));
+ instr->i_opcode = LOAD_FAST;
+ }
else if (instr->i_opcode == STORE_FAST_MAYBE_NULL) {
+ assert(SAME_OPCODE_METADATA(STORE_FAST_MAYBE_NULL, STORE_FAST));
instr->i_opcode = STORE_FAST;
}
}
diff --git a/Python/frame.c b/Python/frame.c
index b84fd9b6a9380a..581e4f95710fe2 100644
--- a/Python/frame.c
+++ b/Python/frame.c
@@ -14,7 +14,7 @@ _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg)
Py_VISIT(frame->frame_obj);
Py_VISIT(frame->f_locals);
Py_VISIT(frame->f_funcobj);
- Py_VISIT(frame->f_code);
+ Py_VISIT(_PyFrame_GetCode(frame));
/* locals */
PyObject **locals = _PyFrame_GetLocalsArray(frame);
int i = 0;
@@ -31,7 +31,7 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
assert(frame->frame_obj == NULL);
PyObject *exc = PyErr_GetRaisedException();
- PyFrameObject *f = _PyFrame_New_NoTrack(frame->f_code);
+ PyFrameObject *f = _PyFrame_New_NoTrack(_PyFrame_GetCode(frame));
if (f == NULL) {
Py_XDECREF(exc);
return NULL;
@@ -65,7 +65,7 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
void
_PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
{
- assert(src->stacktop >= src->f_code->co_nlocalsplus);
+ assert(src->stacktop >= _PyFrame_GetCode(src)->co_nlocalsplus);
Py_ssize_t size = ((char*)&src->localsplus[src->stacktop]) - (char *)src;
memcpy(dest, src, size);
// Don't leave a dangling pointer to the old frame when creating generators
@@ -81,7 +81,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
assert(frame->owner != FRAME_CLEARED);
Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame;
- Py_INCREF(frame->f_code);
+ Py_INCREF(_PyFrame_GetCode(frame));
memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);
frame = (_PyInterpreterFrame *)f->_f_frame_data;
f->f_frame = frame;
@@ -89,7 +89,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
if (_PyFrame_IsIncomplete(frame)) {
// This may be a newly-created generator or coroutine frame. Since it's
// dead anyways, just pretend that the first RESUME ran:
- PyCodeObject *code = frame->f_code;
+ PyCodeObject *code = _PyFrame_GetCode(frame);
frame->prev_instr = _PyCode_CODE(code) + code->_co_firsttraceable;
}
assert(!_PyFrame_IsIncomplete(frame));
@@ -149,7 +149,7 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
PyObject *
PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)
{
- PyObject *code = (PyObject *)frame->f_code;
+ PyObject *code = frame->f_executable;
Py_INCREF(code);
return code;
}
@@ -164,5 +164,13 @@ int
PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame)
{
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
- return PyCode_Addr2Line(frame->f_code, addr);
+ return PyCode_Addr2Line(_PyFrame_GetCode(frame), addr);
}
+
+const PyTypeObject *const PyUnstable_ExecutableKinds[PY_EXECUTABLE_KINDS+1] = {
+ [PY_EXECUTABLE_KIND_SKIP] = &_PyNone_Type,
+ [PY_EXECUTABLE_KIND_PY_FUNCTION] = &PyCode_Type,
+ [PY_EXECUTABLE_KIND_BUILTIN_FUNCTION] = &PyMethod_Type,
+ [PY_EXECUTABLE_KIND_METHOD_DESCRIPTOR] = &PyMethodDescr_Type,
+ [PY_EXECUTABLE_KINDS] = NULL,
+};
diff --git a/Python/frozenmain.c b/Python/frozenmain.c
index f8be165f7671df..767f9804903a9e 100644
--- a/Python/frozenmain.c
+++ b/Python/frozenmain.c
@@ -1,7 +1,8 @@
/* Python interpreter main program for frozen scripts */
#include "Python.h"
-#include "pycore_runtime.h" // _PyRuntime_Initialize()
+#include "pycore_pystate.h" // _Py_GetConfig()
+#include "pycore_runtime.h" // _PyRuntime_Initialize()
#include
#ifdef MS_WINDOWS
diff --git a/Python/future.c b/Python/future.c
index d56f7330964684..0dbc7ede20f324 100644
--- a/Python/future.c
+++ b/Python/future.c
@@ -1,5 +1,6 @@
#include "Python.h"
#include "pycore_ast.h" // _PyAST_GetDocString()
+#include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString()
#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 5f54c8655b9aa2..392914c0521e9d 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -8,35 +8,35 @@
}
TARGET(RESUME) {
- #line 137 "Python/bytecodes.c"
assert(tstate->cframe == &cframe);
assert(frame == cframe.current_frame);
/* Possibly combine this with eval breaker */
- if (frame->f_code->_co_instrumentation_version != tstate->interp->monitoring_version) {
- int err = _Py_Instrument(frame->f_code, tstate->interp);
+ if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) {
+ int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
if (err) goto error;
next_instr--;
}
- else if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker) && oparg < 2) {
- goto handle_eval_breaker;
+ else if (oparg < 2) {
+ CHECK_EVAL_BREAKER();
}
- #line 24 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_RESUME) {
- #line 151 "Python/bytecodes.c"
/* Possible performance enhancement:
* We need to check the eval breaker anyway, can we
* combine the instrument verison check and the eval breaker test?
*/
- if (frame->f_code->_co_instrumentation_version != tstate->interp->monitoring_version) {
- if (_Py_Instrument(frame->f_code, tstate->interp)) {
+ if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) {
+ if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) {
goto error;
}
next_instr--;
}
else {
+ if (oparg < 2) {
+ CHECK_EVAL_BREAKER();
+ }
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation(
tstate, oparg > 0, frame, next_instr-1);
@@ -47,34 +47,15 @@
next_instr = frame->prev_instr;
DISPATCH();
}
- if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker) && oparg < 2) {
- goto handle_eval_breaker;
- }
}
- #line 55 "Python/generated_cases.c.h"
- DISPATCH();
- }
-
- TARGET(LOAD_CLOSURE) {
- PyObject *value;
- #line 179 "Python/bytecodes.c"
- /* We keep LOAD_CLOSURE so that the bytecode stays more readable. */
- value = GETLOCAL(oparg);
- if (value == NULL) goto unbound_local_error;
- Py_INCREF(value);
- #line 66 "Python/generated_cases.c.h"
- STACK_GROW(1);
- stack_pointer[-1] = value;
DISPATCH();
}
TARGET(LOAD_FAST_CHECK) {
PyObject *value;
- #line 186 "Python/bytecodes.c"
value = GETLOCAL(oparg);
if (value == NULL) goto unbound_local_error;
Py_INCREF(value);
- #line 78 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = value;
DISPATCH();
@@ -82,11 +63,9 @@
TARGET(LOAD_FAST) {
PyObject *value;
- #line 192 "Python/bytecodes.c"
value = GETLOCAL(oparg);
assert(value != NULL);
Py_INCREF(value);
- #line 90 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = value;
DISPATCH();
@@ -94,11 +73,9 @@
TARGET(LOAD_FAST_AND_CLEAR) {
PyObject *value;
- #line 198 "Python/bytecodes.c"
value = GETLOCAL(oparg);
// do not use SETLOCAL here, it decrefs the old value
GETLOCAL(oparg) = NULL;
- #line 102 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = value;
DISPATCH();
@@ -107,14 +84,12 @@
TARGET(LOAD_FAST_LOAD_FAST) {
PyObject *value1;
PyObject *value2;
- #line 204 "Python/bytecodes.c"
uint32_t oparg1 = oparg >> 4;
uint32_t oparg2 = oparg & 15;
value1 = GETLOCAL(oparg1);
value2 = GETLOCAL(oparg2);
Py_INCREF(value1);
Py_INCREF(value2);
- #line 118 "Python/generated_cases.c.h"
STACK_GROW(2);
stack_pointer[-1] = value2;
stack_pointer[-2] = value1;
@@ -123,10 +98,8 @@
TARGET(LOAD_CONST) {
PyObject *value;
- #line 213 "Python/bytecodes.c"
- value = GETITEM(frame->f_code->co_consts, oparg);
+ value = GETITEM(FRAME_CO_CONSTS, oparg);
Py_INCREF(value);
- #line 130 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = value;
DISPATCH();
@@ -134,9 +107,7 @@
TARGET(STORE_FAST) {
PyObject *value = stack_pointer[-1];
- #line 218 "Python/bytecodes.c"
SETLOCAL(oparg, value);
- #line 140 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
@@ -144,13 +115,11 @@
TARGET(STORE_FAST_LOAD_FAST) {
PyObject *value1 = stack_pointer[-1];
PyObject *value2;
- #line 222 "Python/bytecodes.c"
uint32_t oparg1 = oparg >> 4;
uint32_t oparg2 = oparg & 15;
SETLOCAL(oparg1, value1);
value2 = GETLOCAL(oparg2);
Py_INCREF(value2);
- #line 154 "Python/generated_cases.c.h"
stack_pointer[-1] = value2;
DISPATCH();
}
@@ -158,20 +127,16 @@
TARGET(STORE_FAST_STORE_FAST) {
PyObject *value1 = stack_pointer[-1];
PyObject *value2 = stack_pointer[-2];
- #line 230 "Python/bytecodes.c"
uint32_t oparg1 = oparg >> 4;
uint32_t oparg2 = oparg & 15;
SETLOCAL(oparg1, value1);
SETLOCAL(oparg2, value2);
- #line 167 "Python/generated_cases.c.h"
STACK_SHRINK(2);
DISPATCH();
}
TARGET(POP_TOP) {
PyObject *value = stack_pointer[-1];
- #line 237 "Python/bytecodes.c"
- #line 175 "Python/generated_cases.c.h"
Py_DECREF(value);
STACK_SHRINK(1);
DISPATCH();
@@ -179,9 +144,7 @@
TARGET(PUSH_NULL) {
PyObject *res;
- #line 241 "Python/bytecodes.c"
res = NULL;
- #line 185 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
DISPATCH();
@@ -192,14 +155,10 @@
PyObject *_tmp_2 = stack_pointer[-2];
{
PyObject *value = _tmp_1;
- #line 237 "Python/bytecodes.c"
- #line 197 "Python/generated_cases.c.h"
Py_DECREF(value);
}
{
PyObject *value = _tmp_2;
- #line 237 "Python/bytecodes.c"
- #line 203 "Python/generated_cases.c.h"
Py_DECREF(value);
}
STACK_SHRINK(2);
@@ -209,7 +168,6 @@
TARGET(INSTRUMENTED_END_FOR) {
PyObject *value = stack_pointer[-1];
PyObject *receiver = stack_pointer[-2];
- #line 247 "Python/bytecodes.c"
/* Need to create a fake StopIteration error here,
* to conform to PEP 380 */
if (PyGen_Check(receiver)) {
@@ -219,7 +177,6 @@
}
PyErr_SetRaisedException(NULL);
}
- #line 223 "Python/generated_cases.c.h"
Py_DECREF(receiver);
Py_DECREF(value);
STACK_SHRINK(2);
@@ -229,9 +186,7 @@
TARGET(END_SEND) {
PyObject *value = stack_pointer[-1];
PyObject *receiver = stack_pointer[-2];
- #line 260 "Python/bytecodes.c"
Py_DECREF(receiver);
- #line 235 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = value;
DISPATCH();
@@ -240,7 +195,6 @@
TARGET(INSTRUMENTED_END_SEND) {
PyObject *value = stack_pointer[-1];
PyObject *receiver = stack_pointer[-2];
- #line 264 "Python/bytecodes.c"
if (PyGen_Check(receiver) || PyCoro_CheckExact(receiver)) {
PyErr_SetObject(PyExc_StopIteration, value);
if (monitor_stop_iteration(tstate, frame, next_instr-1)) {
@@ -249,7 +203,6 @@
PyErr_SetRaisedException(NULL);
}
Py_DECREF(receiver);
- #line 253 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = value;
DISPATCH();
@@ -258,13 +211,9 @@
TARGET(UNARY_NEGATIVE) {
PyObject *value = stack_pointer[-1];
PyObject *res;
- #line 275 "Python/bytecodes.c"
res = PyNumber_Negative(value);
- #line 264 "Python/generated_cases.c.h"
Py_DECREF(value);
- #line 277 "Python/bytecodes.c"
if (res == NULL) goto pop_1_error;
- #line 268 "Python/generated_cases.c.h"
stack_pointer[-1] = res;
DISPATCH();
}
@@ -272,33 +221,126 @@
TARGET(UNARY_NOT) {
PyObject *value = stack_pointer[-1];
PyObject *res;
- #line 281 "Python/bytecodes.c"
+ assert(PyBool_Check(value));
+ res = Py_IsFalse(value) ? Py_True : Py_False;
+ stack_pointer[-1] = res;
+ DISPATCH();
+ }
+
+ TARGET(TO_BOOL) {
+ PREDICTED(TO_BOOL);
+ static_assert(INLINE_CACHE_ENTRIES_TO_BOOL == 3, "incorrect cache size");
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ #if ENABLE_SPECIALIZATION
+ _PyToBoolCache *cache = (_PyToBoolCache *)next_instr;
+ if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
+ next_instr--;
+ _Py_Specialize_ToBool(value, next_instr);
+ DISPATCH_SAME_OPARG();
+ }
+ STAT_INC(TO_BOOL, deferred);
+ DECREMENT_ADAPTIVE_COUNTER(cache->counter);
+ #endif /* ENABLE_SPECIALIZATION */
int err = PyObject_IsTrue(value);
- #line 278 "Python/generated_cases.c.h"
Py_DECREF(value);
- #line 283 "Python/bytecodes.c"
if (err < 0) goto pop_1_error;
- if (err == 0) {
- res = Py_True;
+ res = err ? Py_True : Py_False;
+ stack_pointer[-1] = res;
+ next_instr += 3;
+ DISPATCH();
+ }
+
+ TARGET(TO_BOOL_BOOL) {
+ PyObject *value = stack_pointer[-1];
+ DEOPT_IF(!PyBool_Check(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ next_instr += 3;
+ DISPATCH();
+ }
+
+ TARGET(TO_BOOL_INT) {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ DEOPT_IF(!PyLong_CheckExact(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ if (_PyLong_IsZero((PyLongObject *)value)) {
+ assert(_Py_IsImmortal(value));
+ res = Py_False;
}
else {
+ Py_DECREF(value);
+ res = Py_True;
+ }
+ stack_pointer[-1] = res;
+ next_instr += 3;
+ DISPATCH();
+ }
+
+ TARGET(TO_BOOL_LIST) {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ DEOPT_IF(!PyList_CheckExact(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ res = Py_SIZE(value) ? Py_True : Py_False;
+ Py_DECREF(value);
+ stack_pointer[-1] = res;
+ next_instr += 3;
+ DISPATCH();
+ }
+
+ TARGET(TO_BOOL_NONE) {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ // This one is a bit weird, because we expect *some* failures:
+ DEOPT_IF(!Py_IsNone(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ res = Py_False;
+ stack_pointer[-1] = res;
+ next_instr += 3;
+ DISPATCH();
+ }
+
+ TARGET(TO_BOOL_STR) {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ DEOPT_IF(!PyUnicode_CheckExact(value), TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ if (value == &_Py_STR(empty)) {
+ assert(_Py_IsImmortal(value));
res = Py_False;
}
- #line 288 "Python/generated_cases.c.h"
+ else {
+ assert(Py_SIZE(value));
+ Py_DECREF(value);
+ res = Py_True;
+ }
stack_pointer[-1] = res;
+ next_instr += 3;
+ DISPATCH();
+ }
+
+ TARGET(TO_BOOL_ALWAYS_TRUE) {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ uint32_t version = read_u32(&next_instr[1].cache);
+ // This one is a bit weird, because we expect *some* failures:
+ assert(version);
+ DEOPT_IF(Py_TYPE(value)->tp_version_tag != version, TO_BOOL);
+ STAT_INC(TO_BOOL, hit);
+ Py_DECREF(value);
+ res = Py_True;
+ stack_pointer[-1] = res;
+ next_instr += 3;
DISPATCH();
}
TARGET(UNARY_INVERT) {
PyObject *value = stack_pointer[-1];
PyObject *res;
- #line 293 "Python/bytecodes.c"
res = PyNumber_Invert(value);
- #line 298 "Python/generated_cases.c.h"
Py_DECREF(value);
- #line 295 "Python/bytecodes.c"
if (res == NULL) goto pop_1_error;
- #line 302 "Python/generated_cases.c.h"
stack_pointer[-1] = res;
DISPATCH();
}
@@ -309,10 +351,8 @@
{
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
- #line 311 "Python/bytecodes.c"
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
- #line 316 "Python/generated_cases.c.h"
_tmp_2 = left;
_tmp_1 = right;
}
@@ -320,13 +360,11 @@
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
PyObject *res;
- #line 316 "Python/bytecodes.c"
STAT_INC(BINARY_OP, hit);
res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
if (res == NULL) goto pop_2_error;
- #line 330 "Python/generated_cases.c.h"
_tmp_2 = res;
}
next_instr += 1;
@@ -341,10 +379,8 @@
{
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
- #line 311 "Python/bytecodes.c"
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
- #line 348 "Python/generated_cases.c.h"
_tmp_2 = left;
_tmp_1 = right;
}
@@ -352,13 +388,11 @@
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
PyObject *res;
- #line 324 "Python/bytecodes.c"
STAT_INC(BINARY_OP, hit);
res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
if (res == NULL) goto pop_2_error;
- #line 362 "Python/generated_cases.c.h"
_tmp_2 = res;
}
next_instr += 1;
@@ -373,10 +407,8 @@
{
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
- #line 311 "Python/bytecodes.c"
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
- #line 380 "Python/generated_cases.c.h"
_tmp_2 = left;
_tmp_1 = right;
}
@@ -384,13 +416,11 @@
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
PyObject *res;
- #line 332 "Python/bytecodes.c"
STAT_INC(BINARY_OP, hit);
res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
if (res == NULL) goto pop_2_error;
- #line 394 "Python/generated_cases.c.h"
_tmp_2 = res;
}
next_instr += 1;
@@ -405,10 +435,8 @@
{
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
- #line 347 "Python/bytecodes.c"
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
- #line 412 "Python/generated_cases.c.h"
_tmp_2 = left;
_tmp_1 = right;
}
@@ -416,13 +444,11 @@
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
PyObject *res;
- #line 352 "Python/bytecodes.c"
STAT_INC(BINARY_OP, hit);
double dres =
((PyFloatObject *)left)->ob_fval *
((PyFloatObject *)right)->ob_fval;
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
- #line 426 "Python/generated_cases.c.h"
_tmp_2 = res;
}
next_instr += 1;
@@ -437,10 +463,8 @@
{
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
- #line 347 "Python/bytecodes.c"
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
- #line 444 "Python/generated_cases.c.h"
_tmp_2 = left;
_tmp_1 = right;
}
@@ -448,13 +472,11 @@
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
PyObject *res;
- #line 360 "Python/bytecodes.c"
STAT_INC(BINARY_OP, hit);
double dres =
((PyFloatObject *)left)->ob_fval +
((PyFloatObject *)right)->ob_fval;
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
- #line 458 "Python/generated_cases.c.h"
_tmp_2 = res;
}
next_instr += 1;
@@ -469,10 +491,8 @@
{
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
- #line 347 "Python/bytecodes.c"
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
- #line 476 "Python/generated_cases.c.h"
_tmp_2 = left;
_tmp_1 = right;
}
@@ -480,13 +500,11 @@
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
PyObject *res;
- #line 368 "Python/bytecodes.c"
STAT_INC(BINARY_OP, hit);
double dres =
((PyFloatObject *)left)->ob_fval -
((PyFloatObject *)right)->ob_fval;
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
- #line 490 "Python/generated_cases.c.h"
_tmp_2 = res;
}
next_instr += 1;
@@ -501,10 +519,8 @@
{
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
- #line 383 "Python/bytecodes.c"
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);
DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP);
- #line 508 "Python/generated_cases.c.h"
_tmp_2 = left;
_tmp_1 = right;
}
@@ -512,13 +528,11 @@
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
PyObject *res;
- #line 388 "Python/bytecodes.c"
STAT_INC(BINARY_OP, hit);
res = PyUnicode_Concat(left, right);
_Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
_Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
if (res == NULL) goto pop_2_error;
- #line 522 "Python/generated_cases.c.h"
_tmp_2 = res;
}
next_instr += 1;
@@ -533,17 +547,14 @@
{
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
- #line 383 "Python/bytecodes.c"
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);
DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP);
- #line 540 "Python/generated_cases.c.h"
_tmp_2 = left;
_tmp_1 = right;
}
{
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
- #line 405 "Python/bytecodes.c"
_Py_CODEUNIT true_next = next_instr[INLINE_CACHE_ENTRIES_BINARY_OP];
assert(true_next.op.code == STORE_FAST);
PyObject **target_local = &GETLOCAL(true_next.op.arg);
@@ -566,8 +577,7 @@
_Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
if (*target_local == NULL) goto pop_2_error;
// The STORE_FAST is already done.
- JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP + 1);
- #line 571 "Python/generated_cases.c.h"
+ SKIP_OVER(INLINE_CACHE_ENTRIES_BINARY_OP + 1);
}
STACK_SHRINK(2);
DISPATCH();
@@ -579,7 +589,6 @@
PyObject *sub = stack_pointer[-1];
PyObject *container = stack_pointer[-2];
PyObject *res;
- #line 442 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -591,12 +600,9 @@
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
#endif /* ENABLE_SPECIALIZATION */
res = PyObject_GetItem(container, sub);
- #line 595 "Python/generated_cases.c.h"
Py_DECREF(container);
Py_DECREF(sub);
- #line 454 "Python/bytecodes.c"
if (res == NULL) goto pop_2_error;
- #line 600 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -608,7 +614,6 @@
PyObject *start = stack_pointer[-2];
PyObject *container = stack_pointer[-3];
PyObject *res;
- #line 458 "Python/bytecodes.c"
PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop);
// Can't use ERROR_IF() here, because we haven't
// DECREF'ed container yet, and we still own slice.
@@ -621,7 +626,6 @@
}
Py_DECREF(container);
if (res == NULL) goto pop_3_error;
- #line 625 "Python/generated_cases.c.h"
STACK_SHRINK(2);
stack_pointer[-1] = res;
DISPATCH();
@@ -632,7 +636,6 @@
PyObject *start = stack_pointer[-2];
PyObject *container = stack_pointer[-3];
PyObject *v = stack_pointer[-4];
- #line 473 "Python/bytecodes.c"
PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop);
int err;
if (slice == NULL) {
@@ -645,7 +648,6 @@
Py_DECREF(v);
Py_DECREF(container);
if (err) goto pop_4_error;
- #line 649 "Python/generated_cases.c.h"
STACK_SHRINK(4);
DISPATCH();
}
@@ -654,7 +656,6 @@
PyObject *sub = stack_pointer[-1];
PyObject *list = stack_pointer[-2];
PyObject *res;
- #line 488 "Python/bytecodes.c"
DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);
DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR);
@@ -668,7 +669,6 @@
Py_INCREF(res);
_Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
Py_DECREF(list);
- #line 672 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -679,7 +679,6 @@
PyObject *sub = stack_pointer[-1];
PyObject *tuple = stack_pointer[-2];
PyObject *res;
- #line 504 "Python/bytecodes.c"
DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);
DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR);
@@ -693,7 +692,6 @@
Py_INCREF(res);
_Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
Py_DECREF(tuple);
- #line 697 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -704,7 +702,6 @@
PyObject *sub = stack_pointer[-1];
PyObject *dict = stack_pointer[-2];
PyObject *res;
- #line 520 "Python/bytecodes.c"
DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR);
STAT_INC(BINARY_SUBSCR, hit);
res = PyDict_GetItemWithError(dict, sub);
@@ -712,14 +709,11 @@
if (!_PyErr_Occurred(tstate)) {
_PyErr_SetKeyError(sub);
}
- #line 716 "Python/generated_cases.c.h"
Py_DECREF(dict);
Py_DECREF(sub);
- #line 528 "Python/bytecodes.c"
if (true) goto pop_2_error;
}
Py_INCREF(res); // Do this before DECREF'ing dict, sub
- #line 723 "Python/generated_cases.c.h"
Py_DECREF(dict);
Py_DECREF(sub);
STACK_SHRINK(1);
@@ -731,7 +725,6 @@
TARGET(BINARY_SUBSCR_GETITEM) {
PyObject *sub = stack_pointer[-1];
PyObject *container = stack_pointer[-2];
- #line 535 "Python/bytecodes.c"
DEOPT_IF(tstate->interp->eval_frame, BINARY_SUBSCR);
PyTypeObject *tp = Py_TYPE(container);
DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE), BINARY_SUBSCR);
@@ -751,18 +744,15 @@
STACK_SHRINK(2);
new_frame->localsplus[0] = container;
new_frame->localsplus[1] = sub;
- JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 758 "Python/generated_cases.c.h"
}
TARGET(LIST_APPEND) {
PyObject *v = stack_pointer[-1];
PyObject *list = stack_pointer[-(2 + (oparg-1))];
- #line 560 "Python/bytecodes.c"
if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto pop_1_error;
- #line 766 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
@@ -770,13 +760,9 @@
TARGET(SET_ADD) {
PyObject *v = stack_pointer[-1];
PyObject *set = stack_pointer[-(2 + (oparg-1))];
- #line 564 "Python/bytecodes.c"
int err = PySet_Add(set, v);
- #line 776 "Python/generated_cases.c.h"
Py_DECREF(v);
- #line 566 "Python/bytecodes.c"
if (err) goto pop_1_error;
- #line 780 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
@@ -788,7 +774,6 @@
PyObject *container = stack_pointer[-2];
PyObject *v = stack_pointer[-3];
uint16_t counter = read_u16(&next_instr[0].cache);
- #line 576 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
next_instr--;
@@ -803,13 +788,10 @@
#endif /* ENABLE_SPECIALIZATION */
/* container[sub] = v */
int err = PyObject_SetItem(container, sub, v);
- #line 807 "Python/generated_cases.c.h"
Py_DECREF(v);
Py_DECREF(container);
Py_DECREF(sub);
- #line 591 "Python/bytecodes.c"
if (err) goto pop_3_error;
- #line 813 "Python/generated_cases.c.h"
STACK_SHRINK(3);
next_instr += 1;
DISPATCH();
@@ -819,7 +801,6 @@
PyObject *sub = stack_pointer[-1];
PyObject *list = stack_pointer[-2];
PyObject *value = stack_pointer[-3];
- #line 595 "Python/bytecodes.c"
DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR);
DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR);
@@ -836,7 +817,6 @@
Py_DECREF(old_value);
_Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
Py_DECREF(list);
- #line 840 "Python/generated_cases.c.h"
STACK_SHRINK(3);
next_instr += 1;
DISPATCH();
@@ -846,13 +826,11 @@
PyObject *sub = stack_pointer[-1];
PyObject *dict = stack_pointer[-2];
PyObject *value = stack_pointer[-3];
- #line 614 "Python/bytecodes.c"
DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR);
STAT_INC(STORE_SUBSCR, hit);
int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value);
Py_DECREF(dict);
if (err) goto pop_3_error;
- #line 856 "Python/generated_cases.c.h"
STACK_SHRINK(3);
next_instr += 1;
DISPATCH();
@@ -861,15 +839,11 @@
TARGET(DELETE_SUBSCR) {
PyObject *sub = stack_pointer[-1];
PyObject *container = stack_pointer[-2];
- #line 622 "Python/bytecodes.c"
/* del container[sub] */
int err = PyObject_DelItem(container, sub);
- #line 868 "Python/generated_cases.c.h"
Py_DECREF(container);
Py_DECREF(sub);
- #line 625 "Python/bytecodes.c"
if (err) goto pop_2_error;
- #line 873 "Python/generated_cases.c.h"
STACK_SHRINK(2);
DISPATCH();
}
@@ -877,14 +851,10 @@
TARGET(CALL_INTRINSIC_1) {
PyObject *value = stack_pointer[-1];
PyObject *res;
- #line 629 "Python/bytecodes.c"
assert(oparg <= MAX_INTRINSIC_1);
res = _PyIntrinsics_UnaryFunctions[oparg](tstate, value);
- #line 884 "Python/generated_cases.c.h"
Py_DECREF(value);
- #line 632 "Python/bytecodes.c"
if (res == NULL) goto pop_1_error;
- #line 888 "Python/generated_cases.c.h"
stack_pointer[-1] = res;
DISPATCH();
}
@@ -893,15 +863,11 @@
PyObject *value1 = stack_pointer[-1];
PyObject *value2 = stack_pointer[-2];
PyObject *res;
- #line 636 "Python/bytecodes.c"
assert(oparg <= MAX_INTRINSIC_2);
res = _PyIntrinsics_BinaryFunctions[oparg](tstate, value2, value1);
- #line 900 "Python/generated_cases.c.h"
Py_DECREF(value2);
Py_DECREF(value1);
- #line 639 "Python/bytecodes.c"
if (res == NULL) goto pop_2_error;
- #line 905 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
DISPATCH();
@@ -909,7 +875,6 @@
TARGET(RAISE_VARARGS) {
PyObject **args = (stack_pointer - oparg);
- #line 643 "Python/bytecodes.c"
PyObject *cause = NULL, *exc = NULL;
switch (oparg) {
case 2:
@@ -927,28 +892,22 @@
break;
}
if (true) { STACK_SHRINK(oparg); goto error; }
- #line 931 "Python/generated_cases.c.h"
}
TARGET(INTERPRETER_EXIT) {
PyObject *retval = stack_pointer[-1];
- #line 663 "Python/bytecodes.c"
assert(frame == &entry_frame);
assert(_PyFrame_IsIncomplete(frame));
- STACK_SHRINK(1); // Since we're not going to DISPATCH()
- assert(EMPTY());
/* Restore previous cframe and return. */
tstate->cframe = cframe.previous;
assert(tstate->cframe->current_frame == frame->previous);
assert(!_PyErr_Occurred(tstate));
_Py_LeaveRecursiveCallTstate(tstate);
return retval;
- #line 947 "Python/generated_cases.c.h"
}
TARGET(RETURN_VALUE) {
PyObject *retval = stack_pointer[-1];
- #line 676 "Python/bytecodes.c"
STACK_SHRINK(1);
assert(EMPTY());
_PyFrame_SetStackPointer(frame, stack_pointer);
@@ -961,12 +920,10 @@
frame->prev_instr += frame->return_offset;
_PyFrame_StackPush(frame, retval);
goto resume_frame;
- #line 965 "Python/generated_cases.c.h"
}
TARGET(INSTRUMENTED_RETURN_VALUE) {
PyObject *retval = stack_pointer[-1];
- #line 691 "Python/bytecodes.c"
int err = _Py_call_instrumentation_arg(
tstate, PY_MONITORING_EVENT_PY_RETURN,
frame, next_instr-1, retval);
@@ -983,12 +940,10 @@
frame->prev_instr += frame->return_offset;
_PyFrame_StackPush(frame, retval);
goto resume_frame;
- #line 987 "Python/generated_cases.c.h"
}
TARGET(RETURN_CONST) {
- #line 710 "Python/bytecodes.c"
- PyObject *retval = GETITEM(frame->f_code->co_consts, oparg);
+ PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg);
Py_INCREF(retval);
assert(EMPTY());
_PyFrame_SetStackPointer(frame, stack_pointer);
@@ -1001,12 +956,10 @@
frame->prev_instr += frame->return_offset;
_PyFrame_StackPush(frame, retval);
goto resume_frame;
- #line 1005 "Python/generated_cases.c.h"
}
TARGET(INSTRUMENTED_RETURN_CONST) {
- #line 726 "Python/bytecodes.c"
- PyObject *retval = GETITEM(frame->f_code->co_consts, oparg);
+ PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg);
int err = _Py_call_instrumentation_arg(
tstate, PY_MONITORING_EVENT_PY_RETURN,
frame, next_instr-1, retval);
@@ -1023,13 +976,11 @@
frame->prev_instr += frame->return_offset;
_PyFrame_StackPush(frame, retval);
goto resume_frame;
- #line 1027 "Python/generated_cases.c.h"
}
TARGET(GET_AITER) {
PyObject *obj = stack_pointer[-1];
PyObject *iter;
- #line 746 "Python/bytecodes.c"
unaryfunc getter = NULL;
PyTypeObject *type = Py_TYPE(obj);
@@ -1042,16 +993,12 @@
"'async for' requires an object with "
"__aiter__ method, got %.100s",
type->tp_name);
- #line 1046 "Python/generated_cases.c.h"
Py_DECREF(obj);
- #line 759 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
iter = (*getter)(obj);
- #line 1053 "Python/generated_cases.c.h"
Py_DECREF(obj);
- #line 764 "Python/bytecodes.c"
if (iter == NULL) goto pop_1_error;
if (Py_TYPE(iter)->tp_as_async == NULL ||
@@ -1064,7 +1011,6 @@
Py_DECREF(iter);
if (true) goto pop_1_error;
}
- #line 1068 "Python/generated_cases.c.h"
stack_pointer[-1] = iter;
DISPATCH();
}
@@ -1072,7 +1018,6 @@
TARGET(GET_ANEXT) {
PyObject *aiter = stack_pointer[-1];
PyObject *awaitable;
- #line 779 "Python/bytecodes.c"
unaryfunc getter = NULL;
PyObject *next_iter = NULL;
PyTypeObject *type = Py_TYPE(aiter);
@@ -1115,7 +1060,6 @@
Py_DECREF(next_iter);
}
}
- #line 1119 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = awaitable;
DISPATCH();
@@ -1124,16 +1068,13 @@
TARGET(GET_AWAITABLE) {
PyObject *iterable = stack_pointer[-1];
PyObject *iter;
- #line 824 "Python/bytecodes.c"
iter = _PyCoro_GetAwaitableIter(iterable);
if (iter == NULL) {
format_awaitable_error(tstate, Py_TYPE(iterable), oparg);
}
- #line 1135 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 831 "Python/bytecodes.c"
if (iter != NULL && PyCoro_CheckExact(iter)) {
PyObject *yf = _PyGen_yf((PyGenObject*)iter);
@@ -1150,7 +1091,6 @@
}
if (iter == NULL) goto pop_1_error;
- #line 1154 "Python/generated_cases.c.h"
stack_pointer[-1] = iter;
DISPATCH();
}
@@ -1161,7 +1101,6 @@
PyObject *v = stack_pointer[-1];
PyObject *receiver = stack_pointer[-2];
PyObject *retval;
- #line 855 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PySendCache *cache = (_PySendCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -1185,7 +1124,7 @@
gen->gi_frame_state = FRAME_EXECUTING;
gen->gi_exc_state.previous_item = tstate->exc_info;
tstate->exc_info = &gen->gi_exc_state;
- JUMPBY(INLINE_CACHE_ENTRIES_SEND);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_SEND);
DISPATCH_INLINED(gen_frame);
}
if (Py_IsNone(v) && PyIter_Check(receiver)) {
@@ -1208,7 +1147,6 @@
}
}
Py_DECREF(v);
- #line 1212 "Python/generated_cases.c.h"
stack_pointer[-1] = retval;
next_instr += 1;
DISPATCH();
@@ -1217,7 +1155,6 @@
TARGET(SEND_GEN) {
PyObject *v = stack_pointer[-1];
PyObject *receiver = stack_pointer[-2];
- #line 904 "Python/bytecodes.c"
DEOPT_IF(tstate->interp->eval_frame, SEND);
PyGenObject *gen = (PyGenObject *)receiver;
DEOPT_IF(Py_TYPE(gen) != &PyGen_Type &&
@@ -1231,15 +1168,14 @@
gen->gi_frame_state = FRAME_EXECUTING;
gen->gi_exc_state.previous_item = tstate->exc_info;
tstate->exc_info = &gen->gi_exc_state;
- JUMPBY(INLINE_CACHE_ENTRIES_SEND);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_SEND);
DISPATCH_INLINED(gen_frame);
- #line 1237 "Python/generated_cases.c.h"
}
TARGET(INSTRUMENTED_YIELD_VALUE) {
PyObject *retval = stack_pointer[-1];
- #line 922 "Python/bytecodes.c"
assert(frame != &entry_frame);
+ assert(oparg >= 0); /* make the generator identify this as HAS_ARG */
PyGenObject *gen = _PyFrame_GetGenerator(frame);
gen->gi_frame_state = FRAME_SUSPENDED;
_PyFrame_SetStackPointer(frame, stack_pointer - 1);
@@ -1255,15 +1191,14 @@
gen_frame->previous = NULL;
_PyFrame_StackPush(frame, retval);
goto resume_frame;
- #line 1259 "Python/generated_cases.c.h"
}
TARGET(YIELD_VALUE) {
PyObject *retval = stack_pointer[-1];
- #line 941 "Python/bytecodes.c"
// NOTE: It's important that YIELD_VALUE never raises an exception!
// The compiler treats any exception raised here as a failed close()
// or throw() call.
+ assert(oparg >= 0); /* make the generator identify this as HAS_ARG */
assert(frame != &entry_frame);
PyGenObject *gen = _PyFrame_GetGenerator(frame);
gen->gi_frame_state = FRAME_SUSPENDED;
@@ -1276,15 +1211,12 @@
gen_frame->previous = NULL;
_PyFrame_StackPush(frame, retval);
goto resume_frame;
- #line 1280 "Python/generated_cases.c.h"
}
TARGET(POP_EXCEPT) {
PyObject *exc_value = stack_pointer[-1];
- #line 959 "Python/bytecodes.c"
_PyErr_StackItem *exc_info = tstate->exc_info;
Py_XSETREF(exc_info->exc_value, exc_value);
- #line 1288 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
@@ -1292,12 +1224,11 @@
TARGET(RERAISE) {
PyObject *exc = stack_pointer[-1];
PyObject **values = (stack_pointer - (1 + oparg));
- #line 964 "Python/bytecodes.c"
assert(oparg >= 0 && oparg <= 2);
if (oparg) {
PyObject *lasti = values[0];
if (PyLong_Check(lasti)) {
- frame->prev_instr = _PyCode_CODE(frame->f_code) + PyLong_AsLong(lasti);
+ frame->prev_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + PyLong_AsLong(lasti);
assert(!_PyErr_Occurred(tstate));
}
else {
@@ -1310,26 +1241,21 @@
Py_INCREF(exc);
_PyErr_SetRaisedException(tstate, exc);
goto exception_unwind;
- #line 1314 "Python/generated_cases.c.h"
}
TARGET(END_ASYNC_FOR) {
PyObject *exc = stack_pointer[-1];
PyObject *awaitable = stack_pointer[-2];
- #line 984 "Python/bytecodes.c"
assert(exc && PyExceptionInstance_Check(exc));
if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) {
- #line 1323 "Python/generated_cases.c.h"
Py_DECREF(awaitable);
Py_DECREF(exc);
- #line 987 "Python/bytecodes.c"
}
else {
Py_INCREF(exc);
_PyErr_SetRaisedException(tstate, exc);
goto exception_unwind;
}
- #line 1333 "Python/generated_cases.c.h"
STACK_SHRINK(2);
DISPATCH();
}
@@ -1340,23 +1266,19 @@
PyObject *sub_iter = stack_pointer[-3];
PyObject *none;
PyObject *value;
- #line 996 "Python/bytecodes.c"
assert(throwflag);
assert(exc_value && PyExceptionInstance_Check(exc_value));
if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) {
value = Py_NewRef(((PyStopIterationObject *)exc_value)->value);
- #line 1349 "Python/generated_cases.c.h"
Py_DECREF(sub_iter);
Py_DECREF(last_sent_val);
Py_DECREF(exc_value);
- #line 1001 "Python/bytecodes.c"
none = Py_None;
}
else {
_PyErr_SetRaisedException(tstate, Py_NewRef(exc_value));
goto exception_unwind;
}
- #line 1360 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = value;
stack_pointer[-2] = none;
@@ -1365,9 +1287,7 @@
TARGET(LOAD_ASSERTION_ERROR) {
PyObject *value;
- #line 1010 "Python/bytecodes.c"
value = Py_NewRef(PyExc_AssertionError);
- #line 1371 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = value;
DISPATCH();
@@ -1375,29 +1295,12 @@
TARGET(LOAD_BUILD_CLASS) {
PyObject *bc;
- #line 1014 "Python/bytecodes.c"
- if (PyDict_CheckExact(BUILTINS())) {
- bc = _PyDict_GetItemWithError(BUILTINS(),
- &_Py_ID(__build_class__));
- if (bc == NULL) {
- if (!_PyErr_Occurred(tstate)) {
- _PyErr_SetString(tstate, PyExc_NameError,
- "__build_class__ not found");
- }
- if (true) goto error;
- }
- Py_INCREF(bc);
- }
- else {
- bc = PyObject_GetItem(BUILTINS(), &_Py_ID(__build_class__));
- if (bc == NULL) {
- if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError))
- _PyErr_SetString(tstate, PyExc_NameError,
- "__build_class__ not found");
- if (true) goto error;
- }
+ if (PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc) < 0) goto error;
+ if (bc == NULL) {
+ _PyErr_SetString(tstate, PyExc_NameError,
+ "__build_class__ not found");
+ if (true) goto error;
}
- #line 1401 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = bc;
DISPATCH();
@@ -1405,34 +1308,27 @@
TARGET(STORE_NAME) {
PyObject *v = stack_pointer[-1];
- #line 1039 "Python/bytecodes.c"
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
PyObject *ns = LOCALS();
int err;
if (ns == NULL) {
_PyErr_Format(tstate, PyExc_SystemError,
"no locals found when storing %R", name);
- #line 1416 "Python/generated_cases.c.h"
Py_DECREF(v);
- #line 1046 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
if (PyDict_CheckExact(ns))
err = PyDict_SetItem(ns, name, v);
else
err = PyObject_SetItem(ns, name, v);
- #line 1425 "Python/generated_cases.c.h"
Py_DECREF(v);
- #line 1053 "Python/bytecodes.c"
if (err) goto pop_1_error;
- #line 1429 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(DELETE_NAME) {
- #line 1057 "Python/bytecodes.c"
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
PyObject *ns = LOCALS();
int err;
if (ns == NULL) {
@@ -1448,7 +1344,6 @@
name);
goto error;
}
- #line 1452 "Python/generated_cases.c.h"
DISPATCH();
}
@@ -1456,7 +1351,6 @@
PREDICTED(UNPACK_SEQUENCE);
static_assert(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE == 1, "incorrect cache size");
PyObject *seq = stack_pointer[-1];
- #line 1083 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -1469,11 +1363,8 @@
#endif /* ENABLE_SPECIALIZATION */
PyObject **top = stack_pointer + oparg - 1;
int res = unpack_iterable(tstate, seq, oparg, -1, top);
- #line 1473 "Python/generated_cases.c.h"
Py_DECREF(seq);
- #line 1096 "Python/bytecodes.c"
if (res == 0) goto pop_1_error;
- #line 1477 "Python/generated_cases.c.h"
STACK_SHRINK(1);
STACK_GROW(oparg);
next_instr += 1;
@@ -1483,14 +1374,12 @@
TARGET(UNPACK_SEQUENCE_TWO_TUPLE) {
PyObject *seq = stack_pointer[-1];
PyObject **values = stack_pointer - (1);
- #line 1100 "Python/bytecodes.c"
DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE);
DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE);
assert(oparg == 2);
STAT_INC(UNPACK_SEQUENCE, hit);
values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1));
values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0));
- #line 1494 "Python/generated_cases.c.h"
Py_DECREF(seq);
STACK_SHRINK(1);
STACK_GROW(oparg);
@@ -1501,7 +1390,6 @@
TARGET(UNPACK_SEQUENCE_TUPLE) {
PyObject *seq = stack_pointer[-1];
PyObject **values = stack_pointer - (1);
- #line 1110 "Python/bytecodes.c"
DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE);
DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE);
STAT_INC(UNPACK_SEQUENCE, hit);
@@ -1509,7 +1397,6 @@
for (int i = oparg; --i >= 0; ) {
*values++ = Py_NewRef(items[i]);
}
- #line 1513 "Python/generated_cases.c.h"
Py_DECREF(seq);
STACK_SHRINK(1);
STACK_GROW(oparg);
@@ -1520,7 +1407,6 @@
TARGET(UNPACK_SEQUENCE_LIST) {
PyObject *seq = stack_pointer[-1];
PyObject **values = stack_pointer - (1);
- #line 1121 "Python/bytecodes.c"
DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE);
DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE);
STAT_INC(UNPACK_SEQUENCE, hit);
@@ -1528,7 +1414,6 @@
for (int i = oparg; --i >= 0; ) {
*values++ = Py_NewRef(items[i]);
}
- #line 1532 "Python/generated_cases.c.h"
Py_DECREF(seq);
STACK_SHRINK(1);
STACK_GROW(oparg);
@@ -1538,15 +1423,11 @@
TARGET(UNPACK_EX) {
PyObject *seq = stack_pointer[-1];
- #line 1132 "Python/bytecodes.c"
int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8);
PyObject **top = stack_pointer + totalargs - 1;
int res = unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, top);
- #line 1546 "Python/generated_cases.c.h"
Py_DECREF(seq);
- #line 1136 "Python/bytecodes.c"
if (res == 0) goto pop_1_error;
- #line 1550 "Python/generated_cases.c.h"
STACK_GROW((oparg & 0xFF) + (oparg >> 8));
DISPATCH();
}
@@ -1557,10 +1438,9 @@
PyObject *owner = stack_pointer[-1];
PyObject *v = stack_pointer[-2];
uint16_t counter = read_u16(&next_instr[0].cache);
- #line 1147 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
next_instr--;
_Py_Specialize_StoreAttr(owner, next_instr, name);
DISPATCH_SAME_OPARG();
@@ -1571,14 +1451,11 @@
#else
(void)counter; // Unused.
#endif /* ENABLE_SPECIALIZATION */
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
int err = PyObject_SetAttr(owner, name, v);
- #line 1577 "Python/generated_cases.c.h"
Py_DECREF(v);
Py_DECREF(owner);
- #line 1163 "Python/bytecodes.c"
if (err) goto pop_2_error;
- #line 1582 "Python/generated_cases.c.h"
STACK_SHRINK(2);
next_instr += 4;
DISPATCH();
@@ -1586,35 +1463,26 @@
TARGET(DELETE_ATTR) {
PyObject *owner = stack_pointer[-1];
- #line 1167 "Python/bytecodes.c"
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
- int err = PyObject_SetAttr(owner, name, (PyObject *)NULL);
- #line 1593 "Python/generated_cases.c.h"
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ int err = PyObject_DelAttr(owner, name);
Py_DECREF(owner);
- #line 1170 "Python/bytecodes.c"
if (err) goto pop_1_error;
- #line 1597 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(STORE_GLOBAL) {
PyObject *v = stack_pointer[-1];
- #line 1174 "Python/bytecodes.c"
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
int err = PyDict_SetItem(GLOBALS(), name, v);
- #line 1607 "Python/generated_cases.c.h"
Py_DECREF(v);
- #line 1177 "Python/bytecodes.c"
if (err) goto pop_1_error;
- #line 1611 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(DELETE_GLOBAL) {
- #line 1181 "Python/bytecodes.c"
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
int err;
err = PyDict_DelItem(GLOBALS(), name);
// Can't use ERROR_IF here.
@@ -1625,7 +1493,6 @@
}
goto error;
}
- #line 1629 "Python/generated_cases.c.h"
DISPATCH();
}
@@ -1633,7 +1500,6 @@
PyObject *_tmp_1;
{
PyObject *locals;
- #line 1195 "Python/bytecodes.c"
locals = LOCALS();
if (locals == NULL) {
_PyErr_SetString(tstate, PyExc_SystemError,
@@ -1641,7 +1507,6 @@
if (true) goto error;
}
Py_INCREF(locals);
- #line 1645 "Python/generated_cases.c.h"
_tmp_1 = locals;
}
STACK_GROW(1);
@@ -1653,7 +1518,6 @@
PyObject *_tmp_1;
{
PyObject *locals;
- #line 1195 "Python/bytecodes.c"
locals = LOCALS();
if (locals == NULL) {
_PyErr_SetString(tstate, PyExc_SystemError,
@@ -1661,33 +1525,15 @@
if (true) goto error;
}
Py_INCREF(locals);
- #line 1665 "Python/generated_cases.c.h"
_tmp_1 = locals;
}
{
PyObject *mod_or_class_dict = _tmp_1;
PyObject *v;
- #line 1207 "Python/bytecodes.c"
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
- if (PyDict_CheckExact(mod_or_class_dict)) {
- v = PyDict_GetItemWithError(mod_or_class_dict, name);
- if (v != NULL) {
- Py_INCREF(v);
- }
- else if (_PyErr_Occurred(tstate)) {
- Py_DECREF(mod_or_class_dict);
- goto error;
- }
- }
- else {
- v = PyObject_GetItem(mod_or_class_dict, name);
- if (v == NULL) {
- if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
- Py_DECREF(mod_or_class_dict);
- goto error;
- }
- _PyErr_Clear(tstate);
- }
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) {
+ Py_DECREF(mod_or_class_dict);
+ goto error;
}
Py_DECREF(mod_or_class_dict);
if (v == NULL) {
@@ -1699,32 +1545,17 @@
goto error;
}
else {
- if (PyDict_CheckExact(BUILTINS())) {
- v = PyDict_GetItemWithError(BUILTINS(), name);
- if (v == NULL) {
- if (!_PyErr_Occurred(tstate)) {
- format_exc_check_arg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- }
- goto error;
- }
- Py_INCREF(v);
+ if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) {
+ goto error;
}
- else {
- v = PyObject_GetItem(BUILTINS(), name);
- if (v == NULL) {
- if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
- format_exc_check_arg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- }
- goto error;
- }
+ if (v == NULL) {
+ format_exc_check_arg(
+ tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ goto error;
}
}
}
- #line 1728 "Python/generated_cases.c.h"
_tmp_1 = v;
}
STACK_GROW(1);
@@ -1737,27 +1568,10 @@
{
PyObject *mod_or_class_dict = _tmp_1;
PyObject *v;
- #line 1207 "Python/bytecodes.c"
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
- if (PyDict_CheckExact(mod_or_class_dict)) {
- v = PyDict_GetItemWithError(mod_or_class_dict, name);
- if (v != NULL) {
- Py_INCREF(v);
- }
- else if (_PyErr_Occurred(tstate)) {
- Py_DECREF(mod_or_class_dict);
- goto error;
- }
- }
- else {
- v = PyObject_GetItem(mod_or_class_dict, name);
- if (v == NULL) {
- if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
- Py_DECREF(mod_or_class_dict);
- goto error;
- }
- _PyErr_Clear(tstate);
- }
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) {
+ Py_DECREF(mod_or_class_dict);
+ goto error;
}
Py_DECREF(mod_or_class_dict);
if (v == NULL) {
@@ -1769,32 +1583,17 @@
goto error;
}
else {
- if (PyDict_CheckExact(BUILTINS())) {
- v = PyDict_GetItemWithError(BUILTINS(), name);
- if (v == NULL) {
- if (!_PyErr_Occurred(tstate)) {
- format_exc_check_arg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- }
- goto error;
- }
- Py_INCREF(v);
+ if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) {
+ goto error;
}
- else {
- v = PyObject_GetItem(BUILTINS(), name);
- if (v == NULL) {
- if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
- format_exc_check_arg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- }
- goto error;
- }
+ if (v == NULL) {
+ format_exc_check_arg(
+ tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ goto error;
}
}
}
- #line 1798 "Python/generated_cases.c.h"
_tmp_1 = v;
}
stack_pointer[-1] = _tmp_1;
@@ -1806,11 +1605,10 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size");
PyObject *null = NULL;
PyObject *v;
- #line 1276 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
next_instr--;
_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name);
DISPATCH_SAME_OPARG();
@@ -1818,7 +1616,7 @@
STAT_INC(LOAD_GLOBAL, deferred);
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
#endif /* ENABLE_SPECIALIZATION */
- PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
if (PyDict_CheckExact(GLOBALS())
&& PyDict_CheckExact(BUILTINS()))
{
@@ -1840,25 +1638,19 @@
/* Slow-path if globals or builtins is not a dict */
/* namespace 1: globals */
- v = PyObject_GetItem(GLOBALS(), name);
+ if (PyMapping_GetOptionalItem(GLOBALS(), name, &v) < 0) goto error;
if (v == NULL) {
- if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) goto error;
- _PyErr_Clear(tstate);
-
/* namespace 2: builtins */
- v = PyObject_GetItem(BUILTINS(), name);
+ if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) goto error;
if (v == NULL) {
- if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
- format_exc_check_arg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- }
+ format_exc_check_arg(
+ tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
if (true) goto error;
}
}
}
null = NULL;
- #line 1862 "Python/generated_cases.c.h"
STACK_GROW(1);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = v;
@@ -1868,71 +1660,90 @@
}
TARGET(LOAD_GLOBAL_MODULE) {
- PyObject *null = NULL;
- PyObject *res;
- uint16_t index = read_u16(&next_instr[1].cache);
- uint16_t version = read_u16(&next_instr[2].cache);
- #line 1330 "Python/bytecodes.c"
- DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
- PyDictObject *dict = (PyDictObject *)GLOBALS();
- DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
- assert(DK_IS_UNICODE(dict->ma_keys));
- PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
- res = entries[index].me_value;
- DEOPT_IF(res == NULL, LOAD_GLOBAL);
- Py_INCREF(res);
- STAT_INC(LOAD_GLOBAL, hit);
- null = NULL;
- #line 1887 "Python/generated_cases.c.h"
+ PyObject *_tmp_1;
+ PyObject *_tmp_2;
+ {
+ }
+ {
+ uint16_t version = read_u16(&next_instr[1].cache);
+ PyDictObject *dict = (PyDictObject *)GLOBALS();
+ DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL);
+ DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
+ assert(DK_IS_UNICODE(dict->ma_keys));
+ }
+ {
+ }
+ {
+ PyObject *null = NULL;
+ PyObject *res;
+ uint16_t index = read_u16(&next_instr[3].cache);
+ PyDictObject *dict = (PyDictObject *)GLOBALS();
+ PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
+ res = entries[index].me_value;
+ DEOPT_IF(res == NULL, LOAD_GLOBAL);
+ Py_INCREF(res);
+ STAT_INC(LOAD_GLOBAL, hit);
+ null = NULL;
+ if (oparg & 1) { _tmp_2 = null; }
+ _tmp_1 = res;
+ }
+ next_instr += 4;
STACK_GROW(1);
STACK_GROW(((oparg & 1) ? 1 : 0));
- stack_pointer[-1] = res;
- if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = null; }
- next_instr += 4;
+ stack_pointer[-1] = _tmp_1;
+ if (oparg & 1) { stack_pointer[-2] = _tmp_2; }
DISPATCH();
}
TARGET(LOAD_GLOBAL_BUILTIN) {
- PyObject *null = NULL;
- PyObject *res;
- uint16_t index = read_u16(&next_instr[1].cache);
- uint16_t mod_version = read_u16(&next_instr[2].cache);
- uint16_t bltn_version = read_u16(&next_instr[3].cache);
- #line 1343 "Python/bytecodes.c"
- DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
- DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL);
- PyDictObject *mdict = (PyDictObject *)GLOBALS();
- PyDictObject *bdict = (PyDictObject *)BUILTINS();
- assert(opcode == LOAD_GLOBAL_BUILTIN);
- DEOPT_IF(mdict->ma_keys->dk_version != mod_version, LOAD_GLOBAL);
- DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL);
- assert(DK_IS_UNICODE(bdict->ma_keys));
- PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys);
- res = entries[index].me_value;
- DEOPT_IF(res == NULL, LOAD_GLOBAL);
- Py_INCREF(res);
- STAT_INC(LOAD_GLOBAL, hit);
- null = NULL;
- #line 1917 "Python/generated_cases.c.h"
+ PyObject *_tmp_1;
+ PyObject *_tmp_2;
+ {
+ }
+ {
+ uint16_t version = read_u16(&next_instr[1].cache);
+ PyDictObject *dict = (PyDictObject *)GLOBALS();
+ DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL);
+ DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
+ assert(DK_IS_UNICODE(dict->ma_keys));
+ }
+ {
+ uint16_t version = read_u16(&next_instr[2].cache);
+ PyDictObject *dict = (PyDictObject *)BUILTINS();
+ DEOPT_IF(!PyDict_CheckExact(dict), LOAD_GLOBAL);
+ DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
+ assert(DK_IS_UNICODE(dict->ma_keys));
+ }
+ {
+ PyObject *null = NULL;
+ PyObject *res;
+ uint16_t index = read_u16(&next_instr[3].cache);
+ PyDictObject *bdict = (PyDictObject *)BUILTINS();
+ PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys);
+ res = entries[index].me_value;
+ DEOPT_IF(res == NULL, LOAD_GLOBAL);
+ Py_INCREF(res);
+ STAT_INC(LOAD_GLOBAL, hit);
+ null = NULL;
+ if (oparg & 1) { _tmp_2 = null; }
+ _tmp_1 = res;
+ }
+ next_instr += 4;
STACK_GROW(1);
STACK_GROW(((oparg & 1) ? 1 : 0));
- stack_pointer[-1] = res;
- if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = null; }
- next_instr += 4;
+ stack_pointer[-1] = _tmp_1;
+ if (oparg & 1) { stack_pointer[-2] = _tmp_2; }
DISPATCH();
}
TARGET(DELETE_FAST) {
- #line 1360 "Python/bytecodes.c"
PyObject *v = GETLOCAL(oparg);
if (v == NULL) goto unbound_local_error;
SETLOCAL(oparg, NULL);
- #line 1931 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(MAKE_CELL) {
- #line 1366 "Python/bytecodes.c"
// "initial" is probably NULL but not if it's an arg (or set
// via PyFrame_LocalsToFast() before MAKE_CELL has run).
PyObject *initial = GETLOCAL(oparg);
@@ -1941,80 +1752,57 @@
goto resume_with_error;
}
SETLOCAL(oparg, cell);
- #line 1945 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(DELETE_DEREF) {
- #line 1377 "Python/bytecodes.c"
PyObject *cell = GETLOCAL(oparg);
PyObject *oldobj = PyCell_GET(cell);
// Can't use ERROR_IF here.
// Fortunately we don't need its superpower.
if (oldobj == NULL) {
- format_exc_unbound(tstate, frame->f_code, oparg);
+ format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
goto error;
}
PyCell_SET(cell, NULL);
Py_DECREF(oldobj);
- #line 1961 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(LOAD_FROM_DICT_OR_DEREF) {
PyObject *class_dict = stack_pointer[-1];
PyObject *value;
- #line 1390 "Python/bytecodes.c"
PyObject *name;
assert(class_dict);
- assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus);
- name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg);
- if (PyDict_CheckExact(class_dict)) {
- value = PyDict_GetItemWithError(class_dict, name);
- if (value != NULL) {
- Py_INCREF(value);
- }
- else if (_PyErr_Occurred(tstate)) {
- Py_DECREF(class_dict);
- goto error;
- }
- }
- else {
- value = PyObject_GetItem(class_dict, name);
- if (value == NULL) {
- if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
- Py_DECREF(class_dict);
- goto error;
- }
- _PyErr_Clear(tstate);
- }
+ assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus);
+ name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg);
+ if (PyMapping_GetOptionalItem(class_dict, name, &value) < 0) {
+ Py_DECREF(class_dict);
+ goto error;
}
Py_DECREF(class_dict);
if (!value) {
PyObject *cell = GETLOCAL(oparg);
value = PyCell_GET(cell);
if (value == NULL) {
- format_exc_unbound(tstate, frame->f_code, oparg);
+ format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
goto error;
}
Py_INCREF(value);
}
- #line 2003 "Python/generated_cases.c.h"
stack_pointer[-1] = value;
DISPATCH();
}
TARGET(LOAD_DEREF) {
PyObject *value;
- #line 1427 "Python/bytecodes.c"
PyObject *cell = GETLOCAL(oparg);
value = PyCell_GET(cell);
if (value == NULL) {
- format_exc_unbound(tstate, frame->f_code, oparg);
+ format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
if (true) goto error;
}
Py_INCREF(value);
- #line 2018 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = value;
DISPATCH();
@@ -2022,20 +1810,17 @@
TARGET(STORE_DEREF) {
PyObject *v = stack_pointer[-1];
- #line 1437 "Python/bytecodes.c"
PyObject *cell = GETLOCAL(oparg);
PyObject *oldobj = PyCell_GET(cell);
PyCell_SET(cell, v);
Py_XDECREF(oldobj);
- #line 2031 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(COPY_FREE_VARS) {
- #line 1444 "Python/bytecodes.c"
/* Copy closure variables to free variables */
- PyCodeObject *co = frame->f_code;
+ PyCodeObject *co = _PyFrame_GetCode(frame);
assert(PyFunction_Check(frame->f_funcobj));
PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
assert(oparg == co->co_nfreevars);
@@ -2044,22 +1829,17 @@
PyObject *o = PyTuple_GET_ITEM(closure, i);
frame->localsplus[offset + i] = Py_NewRef(o);
}
- #line 2048 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(BUILD_STRING) {
PyObject **pieces = (stack_pointer - oparg);
PyObject *str;
- #line 1457 "Python/bytecodes.c"
str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg);
- #line 2057 "Python/generated_cases.c.h"
for (int _i = oparg; --_i >= 0;) {
Py_DECREF(pieces[_i]);
}
- #line 1459 "Python/bytecodes.c"
if (str == NULL) { STACK_SHRINK(oparg); goto error; }
- #line 2063 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_GROW(1);
stack_pointer[-1] = str;
@@ -2069,10 +1849,8 @@
TARGET(BUILD_TUPLE) {
PyObject **values = (stack_pointer - oparg);
PyObject *tup;
- #line 1463 "Python/bytecodes.c"
tup = _PyTuple_FromArraySteal(values, oparg);
if (tup == NULL) { STACK_SHRINK(oparg); goto error; }
- #line 2076 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_GROW(1);
stack_pointer[-1] = tup;
@@ -2082,10 +1860,8 @@
TARGET(BUILD_LIST) {
PyObject **values = (stack_pointer - oparg);
PyObject *list;
- #line 1468 "Python/bytecodes.c"
list = _PyList_FromArraySteal(values, oparg);
if (list == NULL) { STACK_SHRINK(oparg); goto error; }
- #line 2089 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_GROW(1);
stack_pointer[-1] = list;
@@ -2095,7 +1871,6 @@
TARGET(LIST_EXTEND) {
PyObject *iterable = stack_pointer[-1];
PyObject *list = stack_pointer[-(2 + (oparg-1))];
- #line 1473 "Python/bytecodes.c"
PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable);
if (none_val == NULL) {
if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&
@@ -2106,13 +1881,10 @@
"Value after * must be an iterable, not %.200s",
Py_TYPE(iterable)->tp_name);
}
- #line 2110 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 1484 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
assert(Py_IsNone(none_val));
- #line 2116 "Python/generated_cases.c.h"
Py_DECREF(iterable);
STACK_SHRINK(1);
DISPATCH();
@@ -2121,13 +1893,9 @@
TARGET(SET_UPDATE) {
PyObject *iterable = stack_pointer[-1];
PyObject *set = stack_pointer[-(2 + (oparg-1))];
- #line 1491 "Python/bytecodes.c"
int err = _PySet_Update(set, iterable);
- #line 2127 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 1493 "Python/bytecodes.c"
if (err < 0) goto pop_1_error;
- #line 2131 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
@@ -2135,7 +1903,6 @@
TARGET(BUILD_SET) {
PyObject **values = (stack_pointer - oparg);
PyObject *set;
- #line 1497 "Python/bytecodes.c"
set = PySet_New(NULL);
if (set == NULL)
goto error;
@@ -2150,7 +1917,6 @@
Py_DECREF(set);
if (true) { STACK_SHRINK(oparg); goto error; }
}
- #line 2154 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_GROW(1);
stack_pointer[-1] = set;
@@ -2160,7 +1926,6 @@
TARGET(BUILD_MAP) {
PyObject **values = (stack_pointer - oparg*2);
PyObject *map;
- #line 1514 "Python/bytecodes.c"
map = _PyDict_FromItems(
values, 2,
values+1, 2,
@@ -2168,13 +1933,10 @@
if (map == NULL)
goto error;
- #line 2172 "Python/generated_cases.c.h"
for (int _i = oparg*2; --_i >= 0;) {
Py_DECREF(values[_i]);
}
- #line 1522 "Python/bytecodes.c"
if (map == NULL) { STACK_SHRINK(oparg*2); goto error; }
- #line 2178 "Python/generated_cases.c.h"
STACK_SHRINK(oparg*2);
STACK_GROW(1);
stack_pointer[-1] = map;
@@ -2182,7 +1944,6 @@
}
TARGET(SETUP_ANNOTATIONS) {
- #line 1526 "Python/bytecodes.c"
int err;
PyObject *ann_dict;
if (LOCALS() == NULL) {
@@ -2207,10 +1968,8 @@
}
else {
/* do the same if locals() is not a dict */
- ann_dict = PyObject_GetItem(LOCALS(), &_Py_ID(__annotations__));
+ if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error;
if (ann_dict == NULL) {
- if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) goto error;
- _PyErr_Clear(tstate);
ann_dict = PyDict_New();
if (ann_dict == NULL) goto error;
err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__),
@@ -2222,7 +1981,6 @@
Py_DECREF(ann_dict);
}
}
- #line 2226 "Python/generated_cases.c.h"
DISPATCH();
}
@@ -2230,7 +1988,6 @@
PyObject *keys = stack_pointer[-1];
PyObject **values = (stack_pointer - (1 + oparg));
PyObject *map;
- #line 1568 "Python/bytecodes.c"
if (!PyTuple_CheckExact(keys) ||
PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) {
_PyErr_SetString(tstate, PyExc_SystemError,
@@ -2240,14 +1997,11 @@
map = _PyDict_FromItems(
&PyTuple_GET_ITEM(keys, 0), 1,
values, 1, oparg);
- #line 2244 "Python/generated_cases.c.h"
for (int _i = oparg; --_i >= 0;) {
Py_DECREF(values[_i]);
}
Py_DECREF(keys);
- #line 1578 "Python/bytecodes.c"
if (map == NULL) { STACK_SHRINK(oparg); goto pop_1_error; }
- #line 2251 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
stack_pointer[-1] = map;
DISPATCH();
@@ -2255,7 +2009,6 @@
TARGET(DICT_UPDATE) {
PyObject *update = stack_pointer[-1];
- #line 1582 "Python/bytecodes.c"
PyObject *dict = PEEK(oparg + 1); // update is still on the stack
if (PyDict_Update(dict, update) < 0) {
if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {
@@ -2263,12 +2016,9 @@
"'%.200s' object is not a mapping",
Py_TYPE(update)->tp_name);
}
- #line 2267 "Python/generated_cases.c.h"
Py_DECREF(update);
- #line 1590 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
- #line 2272 "Python/generated_cases.c.h"
Py_DECREF(update);
STACK_SHRINK(1);
DISPATCH();
@@ -2276,17 +2026,13 @@
TARGET(DICT_MERGE) {
PyObject *update = stack_pointer[-1];
- #line 1596 "Python/bytecodes.c"
PyObject *dict = PEEK(oparg + 1); // update is still on the stack
if (_PyDict_MergeEx(dict, update, 2) < 0) {
format_kwargs_error(tstate, PEEK(3 + oparg), update);
- #line 2285 "Python/generated_cases.c.h"
Py_DECREF(update);
- #line 1601 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
- #line 2290 "Python/generated_cases.c.h"
Py_DECREF(update);
STACK_SHRINK(1);
DISPATCH();
@@ -2295,25 +2041,21 @@
TARGET(MAP_ADD) {
PyObject *value = stack_pointer[-1];
PyObject *key = stack_pointer[-2];
- #line 1607 "Python/bytecodes.c"
PyObject *dict = PEEK(oparg + 2); // key, value are still on the stack
assert(PyDict_CheckExact(dict));
/* dict[key] = value */
// Do not DECREF INPUTS because the function steals the references
if (_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0) goto pop_2_error;
- #line 2305 "Python/generated_cases.c.h"
STACK_SHRINK(2);
DISPATCH();
}
TARGET(INSTRUMENTED_LOAD_SUPER_ATTR) {
- #line 1615 "Python/bytecodes.c"
_PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr;
// cancel out the decrement that will happen in LOAD_SUPER_ATTR; we
// don't want to specialize instrumented instructions
INCREMENT_ADAPTIVE_COUNTER(cache->counter);
GO_TO_INSTRUCTION(LOAD_SUPER_ATTR);
- #line 2317 "Python/generated_cases.c.h"
}
TARGET(LOAD_SUPER_ATTR) {
@@ -2324,8 +2066,7 @@
PyObject *global_super = stack_pointer[-3];
PyObject *res2 = NULL;
PyObject *res;
- #line 1629 "Python/bytecodes.c"
- PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
int load_method = oparg & 1;
#if ENABLE_SPECIALIZATION
_PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr;
@@ -2366,16 +2107,13 @@
}
}
}
- #line 2370 "Python/generated_cases.c.h"
Py_DECREF(global_super);
Py_DECREF(class);
Py_DECREF(self);
- #line 1671 "Python/bytecodes.c"
if (super == NULL) goto pop_3_error;
res = PyObject_GetAttr(super, name);
Py_DECREF(super);
if (res == NULL) goto pop_3_error;
- #line 2379 "Python/generated_cases.c.h"
STACK_SHRINK(2);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2390,20 +2128,16 @@
PyObject *global_super = stack_pointer[-3];
PyObject *res2 = NULL;
PyObject *res;
- #line 1678 "Python/bytecodes.c"
assert(!(oparg & 1));
DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
STAT_INC(LOAD_SUPER_ATTR, hit);
- PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
res = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL);
- #line 2401 "Python/generated_cases.c.h"
Py_DECREF(global_super);
Py_DECREF(class);
Py_DECREF(self);
- #line 1685 "Python/bytecodes.c"
if (res == NULL) goto pop_3_error;
- #line 2407 "Python/generated_cases.c.h"
STACK_SHRINK(2);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2418,12 +2152,11 @@
PyObject *global_super = stack_pointer[-3];
PyObject *res2;
PyObject *res;
- #line 1689 "Python/bytecodes.c"
assert(oparg & 1);
DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
STAT_INC(LOAD_SUPER_ATTR, hit);
- PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
PyTypeObject *cls = (PyTypeObject *)class;
int method_found = 0;
res2 = _PySuper_Lookup(cls, self, name,
@@ -2441,7 +2174,6 @@
res = res2;
res2 = NULL;
}
- #line 2445 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
stack_pointer[-2] = res2;
@@ -2455,11 +2187,10 @@
PyObject *owner = stack_pointer[-1];
PyObject *res2 = NULL;
PyObject *res;
- #line 1728 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyAttrCache *cache = (_PyAttrCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
- PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
next_instr--;
_Py_Specialize_LoadAttr(owner, next_instr, name);
DISPATCH_SAME_OPARG();
@@ -2467,7 +2198,7 @@
STAT_INC(LOAD_ATTR, deferred);
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
#endif /* ENABLE_SPECIALIZATION */
- PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
if (oparg & 1) {
/* Designed to work in tandem with CALL, pushes two values. */
PyObject* meth = NULL;
@@ -2489,9 +2220,7 @@
NULL | meth | arg1 | ... | argN
*/
- #line 2493 "Python/generated_cases.c.h"
Py_DECREF(owner);
- #line 1762 "Python/bytecodes.c"
if (meth == NULL) goto pop_1_error;
res2 = NULL;
res = meth;
@@ -2500,12 +2229,9 @@
else {
/* Classic, pushes one value. */
res = PyObject_GetAttr(owner, name);
- #line 2504 "Python/generated_cases.c.h"
Py_DECREF(owner);
- #line 1771 "Python/bytecodes.c"
if (res == NULL) goto pop_1_error;
}
- #line 2509 "Python/generated_cases.c.h"
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }
@@ -2514,30 +2240,45 @@
}
TARGET(LOAD_ATTR_INSTANCE_VALUE) {
- PyObject *owner = stack_pointer[-1];
- PyObject *res2 = NULL;
- PyObject *res;
- uint32_t type_version = read_u32(&next_instr[1].cache);
- uint16_t index = read_u16(&next_instr[3].cache);
- #line 1776 "Python/bytecodes.c"
- PyTypeObject *tp = Py_TYPE(owner);
- assert(type_version != 0);
- DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
- assert(tp->tp_dictoffset < 0);
- assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
- PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
- DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);
- res = _PyDictOrValues_GetValues(dorv)->values[index];
- DEOPT_IF(res == NULL, LOAD_ATTR);
- STAT_INC(LOAD_ATTR, hit);
- Py_INCREF(res);
- res2 = NULL;
- #line 2536 "Python/generated_cases.c.h"
- Py_DECREF(owner);
- STACK_GROW(((oparg & 1) ? 1 : 0));
- stack_pointer[-1] = res;
- if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }
+ PyObject *_tmp_1;
+ PyObject *_tmp_2 = stack_pointer[-1];
+ {
+ }
+ {
+ PyObject *owner = _tmp_2;
+ uint32_t type_version = read_u32(&next_instr[1].cache);
+ PyTypeObject *tp = Py_TYPE(owner);
+ assert(type_version != 0);
+ DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
+ _tmp_2 = owner;
+ }
+ {
+ PyObject *owner = _tmp_2;
+ assert(Py_TYPE(owner)->tp_dictoffset < 0);
+ assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
+ PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
+ DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);
+ _tmp_2 = owner;
+ }
+ {
+ PyObject *owner = _tmp_2;
+ PyObject *res2 = NULL;
+ PyObject *res;
+ uint16_t index = read_u16(&next_instr[3].cache);
+ PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
+ res = _PyDictOrValues_GetValues(dorv)->values[index];
+ DEOPT_IF(res == NULL, LOAD_ATTR);
+ STAT_INC(LOAD_ATTR, hit);
+ Py_INCREF(res);
+ res2 = NULL;
+ Py_DECREF(owner);
+ if (oparg & 1) { _tmp_2 = res2; }
+ _tmp_1 = res;
+ }
next_instr += 9;
+ STACK_GROW(((oparg & 1) ? 1 : 0));
+ stack_pointer[-1] = _tmp_1;
+ if (oparg & 1) { stack_pointer[-2] = _tmp_2; }
DISPATCH();
}
@@ -2547,7 +2288,6 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1792 "Python/bytecodes.c"
DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR);
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
assert(dict != NULL);
@@ -2560,7 +2300,6 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(res);
res2 = NULL;
- #line 2564 "Python/generated_cases.c.h"
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2575,7 +2314,6 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1808 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
@@ -2585,7 +2323,7 @@
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
DEOPT_IF(dict == NULL, LOAD_ATTR);
assert(PyDict_CheckExact((PyObject *)dict));
- PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
uint16_t hint = index;
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR);
if (DK_IS_UNICODE(dict->ma_keys)) {
@@ -2602,7 +2340,6 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(res);
res2 = NULL;
- #line 2606 "Python/generated_cases.c.h"
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2617,7 +2354,6 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1838 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
@@ -2627,7 +2363,6 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(res);
res2 = NULL;
- #line 2631 "Python/generated_cases.c.h"
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2642,7 +2377,6 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
PyObject *descr = read_obj(&next_instr[5].cache);
- #line 1851 "Python/bytecodes.c"
DEOPT_IF(!PyType_Check(cls), LOAD_ATTR);
DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version,
@@ -2654,7 +2388,6 @@
res = descr;
assert(res != NULL);
Py_INCREF(res);
- #line 2658 "Python/generated_cases.c.h"
Py_DECREF(cls);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2668,7 +2401,6 @@
uint32_t type_version = read_u32(&next_instr[1].cache);
uint32_t func_version = read_u32(&next_instr[3].cache);
PyObject *fget = read_obj(&next_instr[5].cache);
- #line 1866 "Python/bytecodes.c"
DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);
PyTypeObject *cls = Py_TYPE(owner);
@@ -2689,10 +2421,9 @@
int shrink_stack = !(oparg & 1);
STACK_SHRINK(shrink_stack);
new_frame->localsplus[0] = owner;
- JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_LOAD_ATTR);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 2696 "Python/generated_cases.c.h"
}
TARGET(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) {
@@ -2700,7 +2431,6 @@
uint32_t type_version = read_u32(&next_instr[1].cache);
uint32_t func_version = read_u32(&next_instr[3].cache);
PyObject *getattribute = read_obj(&next_instr[5].cache);
- #line 1892 "Python/bytecodes.c"
DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);
PyTypeObject *cls = Py_TYPE(owner);
DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR);
@@ -2714,7 +2444,7 @@
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);
STAT_INC(LOAD_ATTR, hit);
- PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
Py_INCREF(f);
_PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2);
// Manipulate stack directly because we exit with DISPATCH_INLINED().
@@ -2723,10 +2453,9 @@
STACK_SHRINK(shrink_stack);
new_frame->localsplus[0] = owner;
new_frame->localsplus[1] = Py_NewRef(name);
- JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_LOAD_ATTR);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 2730 "Python/generated_cases.c.h"
}
TARGET(STORE_ATTR_INSTANCE_VALUE) {
@@ -2734,7 +2463,6 @@
PyObject *value = stack_pointer[-2];
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1920 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
@@ -2752,7 +2480,6 @@
Py_DECREF(old_value);
}
Py_DECREF(owner);
- #line 2756 "Python/generated_cases.c.h"
STACK_SHRINK(2);
next_instr += 4;
DISPATCH();
@@ -2763,7 +2490,6 @@
PyObject *value = stack_pointer[-2];
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t hint = read_u16(&next_instr[3].cache);
- #line 1940 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
@@ -2773,7 +2499,7 @@
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
DEOPT_IF(dict == NULL, STORE_ATTR);
assert(PyDict_CheckExact((PyObject *)dict));
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR);
PyObject *old_value;
uint64_t new_version;
@@ -2802,7 +2528,6 @@
/* PEP 509 */
dict->ma_version_tag = new_version;
Py_DECREF(owner);
- #line 2806 "Python/generated_cases.c.h"
STACK_SHRINK(2);
next_instr += 4;
DISPATCH();
@@ -2813,7 +2538,6 @@
PyObject *value = stack_pointer[-2];
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1981 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
@@ -2823,7 +2547,6 @@
*(PyObject **)addr = value;
Py_XDECREF(old_value);
Py_DECREF(owner);
- #line 2827 "Python/generated_cases.c.h"
STACK_SHRINK(2);
next_instr += 4;
DISPATCH();
@@ -2835,7 +2558,6 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *res;
- #line 2000 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -2846,14 +2568,17 @@
STAT_INC(COMPARE_OP, deferred);
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
#endif /* ENABLE_SPECIALIZATION */
- assert((oparg >> 4) <= Py_GE);
- res = PyObject_RichCompare(left, right, oparg>>4);
- #line 2852 "Python/generated_cases.c.h"
+ assert((oparg >> 5) <= Py_GE);
+ res = PyObject_RichCompare(left, right, oparg >> 5);
Py_DECREF(left);
Py_DECREF(right);
- #line 2013 "Python/bytecodes.c"
if (res == NULL) goto pop_2_error;
- #line 2857 "Python/generated_cases.c.h"
+ if (oparg & 16) {
+ int res_bool = PyObject_IsTrue(res);
+ Py_DECREF(res);
+ if (res_bool < 0) goto pop_2_error;
+ res = res_bool ? Py_True : Py_False;
+ }
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -2864,7 +2589,6 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *res;
- #line 2017 "Python/bytecodes.c"
DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP);
DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP);
STAT_INC(COMPARE_OP, hit);
@@ -2875,7 +2599,7 @@
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
res = (sign_ish & oparg) ? Py_True : Py_False;
- #line 2879 "Python/generated_cases.c.h"
+ // It's always a bool, so we don't care about oparg & 16.
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -2886,7 +2610,6 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *res;
- #line 2031 "Python/bytecodes.c"
DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP);
DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP);
DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP);
@@ -2901,7 +2624,7 @@
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
res = (sign_ish & oparg) ? Py_True : Py_False;
- #line 2905 "Python/generated_cases.c.h"
+ // It's always a bool, so we don't care about oparg & 16.
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -2912,19 +2635,18 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *res;
- #line 2049 "Python/bytecodes.c"
DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);
DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP);
STAT_INC(COMPARE_OP, hit);
int eq = _PyUnicode_Equal(left, right);
- assert((oparg >>4) == Py_EQ || (oparg >>4) == Py_NE);
+ assert((oparg >> 5) == Py_EQ || (oparg >> 5) == Py_NE);
_Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
_Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
assert(eq == 0 || eq == 1);
assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS);
assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS);
res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False;
- #line 2928 "Python/generated_cases.c.h"
+ // It's always a bool, so we don't care about oparg & 16.
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -2935,14 +2657,10 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *b;
- #line 2063 "Python/bytecodes.c"
int res = Py_Is(left, right) ^ oparg;
- #line 2941 "Python/generated_cases.c.h"
Py_DECREF(left);
Py_DECREF(right);
- #line 2065 "Python/bytecodes.c"
b = res ? Py_True : Py_False;
- #line 2946 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = b;
DISPATCH();
@@ -2952,15 +2670,11 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *b;
- #line 2069 "Python/bytecodes.c"
int res = PySequence_Contains(right, left);
- #line 2958 "Python/generated_cases.c.h"
Py_DECREF(left);
Py_DECREF(right);
- #line 2071 "Python/bytecodes.c"
if (res < 0) goto pop_2_error;
b = (res ^ oparg) ? Py_True : Py_False;
- #line 2964 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = b;
DISPATCH();
@@ -2971,12 +2685,9 @@
PyObject *exc_value = stack_pointer[-2];
PyObject *rest;
PyObject *match;
- #line 2076 "Python/bytecodes.c"
if (check_except_star_type_valid(tstate, match_type) < 0) {
- #line 2977 "Python/generated_cases.c.h"
Py_DECREF(exc_value);
Py_DECREF(match_type);
- #line 2078 "Python/bytecodes.c"
if (true) goto pop_2_error;
}
@@ -2984,10 +2695,8 @@
rest = NULL;
int res = exception_group_match(exc_value, match_type,
&match, &rest);
- #line 2988 "Python/generated_cases.c.h"
Py_DECREF(exc_value);
Py_DECREF(match_type);
- #line 2086 "Python/bytecodes.c"
if (res < 0) goto pop_2_error;
assert((match == NULL) == (rest == NULL));
@@ -2996,7 +2705,6 @@
if (!Py_IsNone(match)) {
PyErr_SetHandledException(match);
}
- #line 3000 "Python/generated_cases.c.h"
stack_pointer[-1] = match;
stack_pointer[-2] = rest;
DISPATCH();
@@ -3006,21 +2714,15 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *b;
- #line 2097 "Python/bytecodes.c"
assert(PyExceptionInstance_Check(left));
if (check_except_type_valid(tstate, right) < 0) {
- #line 3013 "Python/generated_cases.c.h"
Py_DECREF(right);
- #line 2100 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
int res = PyErr_GivenExceptionMatches(left, right);
- #line 3020 "Python/generated_cases.c.h"
Py_DECREF(right);
- #line 2105 "Python/bytecodes.c"
b = res ? Py_True : Py_False;
- #line 3024 "Python/generated_cases.c.h"
stack_pointer[-1] = b;
DISPATCH();
}
@@ -3029,15 +2731,11 @@
PyObject *fromlist = stack_pointer[-1];
PyObject *level = stack_pointer[-2];
PyObject *res;
- #line 2109 "Python/bytecodes.c"
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
res = import_name(tstate, frame, name, fromlist, level);
- #line 3036 "Python/generated_cases.c.h"
Py_DECREF(level);
Py_DECREF(fromlist);
- #line 2112 "Python/bytecodes.c"
if (res == NULL) goto pop_2_error;
- #line 3041 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
DISPATCH();
@@ -3046,25 +2744,21 @@
TARGET(IMPORT_FROM) {
PyObject *from = stack_pointer[-1];
PyObject *res;
- #line 2116 "Python/bytecodes.c"
- PyObject *name = GETITEM(frame->f_code->co_names, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
res = import_from(tstate, from, name);
if (res == NULL) goto error;
- #line 3054 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
DISPATCH();
}
TARGET(JUMP_FORWARD) {
- #line 2122 "Python/bytecodes.c"
JUMPBY(oparg);
- #line 3063 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(JUMP_BACKWARD) {
- #line 2126 "Python/bytecodes.c"
+ CHECK_EVAL_BREAKER();
_Py_CODEUNIT *here = next_instr - 1;
assert(oparg <= INSTR_OFFSET());
JUMPBY(1-oparg);
@@ -3075,128 +2769,113 @@
frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);
if (frame == NULL) {
frame = cframe.current_frame;
- goto error;
+ goto resume_with_error;
}
+ assert(frame == cframe.current_frame);
here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1);
goto resume_frame;
}
#endif /* ENABLE_SPECIALIZATION */
- #line 3085 "Python/generated_cases.c.h"
- CHECK_EVAL_BREAKER();
DISPATCH();
}
TARGET(ENTER_EXECUTOR) {
- #line 2146 "Python/bytecodes.c"
- _PyExecutorObject *executor = (_PyExecutorObject *)frame->f_code->co_executors->executors[oparg];
+ CHECK_EVAL_BREAKER();
+
+ PyCodeObject *code = _PyFrame_GetCode(frame);
+ _PyExecutorObject *executor = (_PyExecutorObject *)code->co_executors->executors[oparg&255];
+ int original_oparg = executor->vm_data.oparg | (oparg & 0xfffff00);
+ JUMPBY(1-original_oparg);
+ frame->prev_instr = next_instr - 1;
Py_INCREF(executor);
frame = executor->execute(executor, frame, stack_pointer);
if (frame == NULL) {
frame = cframe.current_frame;
- goto error;
+ goto resume_with_error;
}
goto resume_frame;
- #line 3100 "Python/generated_cases.c.h"
}
TARGET(POP_JUMP_IF_FALSE) {
PyObject *cond = stack_pointer[-1];
- #line 2157 "Python/bytecodes.c"
- if (Py_IsFalse(cond)) {
- JUMPBY(oparg);
- }
- else if (!Py_IsTrue(cond)) {
- int err = PyObject_IsTrue(cond);
- #line 3111 "Python/generated_cases.c.h"
- Py_DECREF(cond);
- #line 2163 "Python/bytecodes.c"
- if (err == 0) {
- JUMPBY(oparg);
- }
- else {
- if (err < 0) goto pop_1_error;
- }
- }
- #line 3121 "Python/generated_cases.c.h"
+ assert(PyBool_Check(cond));
+ JUMPBY(oparg * Py_IsFalse(cond));
STACK_SHRINK(1);
DISPATCH();
}
TARGET(POP_JUMP_IF_TRUE) {
PyObject *cond = stack_pointer[-1];
- #line 2173 "Python/bytecodes.c"
- if (Py_IsTrue(cond)) {
- JUMPBY(oparg);
- }
- else if (!Py_IsFalse(cond)) {
- int err = PyObject_IsTrue(cond);
- #line 3134 "Python/generated_cases.c.h"
- Py_DECREF(cond);
- #line 2179 "Python/bytecodes.c"
- if (err > 0) {
- JUMPBY(oparg);
- }
- else {
- if (err < 0) goto pop_1_error;
- }
- }
- #line 3144 "Python/generated_cases.c.h"
+ assert(PyBool_Check(cond));
+ JUMPBY(oparg * Py_IsTrue(cond));
STACK_SHRINK(1);
DISPATCH();
}
- TARGET(POP_JUMP_IF_NOT_NONE) {
- PyObject *value = stack_pointer[-1];
- #line 2189 "Python/bytecodes.c"
- if (!Py_IsNone(value)) {
- #line 3153 "Python/generated_cases.c.h"
- Py_DECREF(value);
- #line 2191 "Python/bytecodes.c"
- JUMPBY(oparg);
+ TARGET(POP_JUMP_IF_NONE) {
+ PyObject *_tmp_1 = stack_pointer[-1];
+ {
+ PyObject *value = _tmp_1;
+ PyObject *b;
+ if (Py_IsNone(value)) {
+ b = Py_True;
+ }
+ else {
+ b = Py_False;
+ Py_DECREF(value);
+ }
+ _tmp_1 = b;
+ }
+ {
+ PyObject *cond = _tmp_1;
+ assert(PyBool_Check(cond));
+ JUMPBY(oparg * Py_IsTrue(cond));
}
- #line 3158 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
- TARGET(POP_JUMP_IF_NONE) {
- PyObject *value = stack_pointer[-1];
- #line 2196 "Python/bytecodes.c"
- if (Py_IsNone(value)) {
- JUMPBY(oparg);
+ TARGET(POP_JUMP_IF_NOT_NONE) {
+ PyObject *_tmp_1 = stack_pointer[-1];
+ {
+ PyObject *value = _tmp_1;
+ PyObject *b;
+ if (Py_IsNone(value)) {
+ b = Py_True;
+ }
+ else {
+ b = Py_False;
+ Py_DECREF(value);
+ }
+ _tmp_1 = b;
}
- else {
- #line 3170 "Python/generated_cases.c.h"
- Py_DECREF(value);
- #line 2201 "Python/bytecodes.c"
+ {
+ PyObject *cond = _tmp_1;
+ assert(PyBool_Check(cond));
+ JUMPBY(oparg * Py_IsFalse(cond));
}
- #line 3174 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(JUMP_BACKWARD_NO_INTERRUPT) {
- #line 2205 "Python/bytecodes.c"
/* This bytecode is used in the `yield from` or `await` loop.
* If there is an interrupt, we want it handled in the innermost
* generator or coroutine, so we deliberately do not check it here.
* (see bpo-30039).
*/
JUMPBY(-oparg);
- #line 3187 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(GET_LEN) {
PyObject *obj = stack_pointer[-1];
PyObject *len_o;
- #line 2214 "Python/bytecodes.c"
// PUSH(len(TOS))
Py_ssize_t len_i = PyObject_Length(obj);
if (len_i < 0) goto error;
len_o = PyLong_FromSsize_t(len_i);
if (len_o == NULL) goto error;
- #line 3200 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = len_o;
DISPATCH();
@@ -3207,16 +2886,13 @@
PyObject *type = stack_pointer[-2];
PyObject *subject = stack_pointer[-3];
PyObject *attrs;
- #line 2222 "Python/bytecodes.c"
// Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or
// None on failure.
assert(PyTuple_CheckExact(names));
attrs = match_class(tstate, subject, type, oparg, names);
- #line 3216 "Python/generated_cases.c.h"
Py_DECREF(subject);
Py_DECREF(type);
Py_DECREF(names);
- #line 2227 "Python/bytecodes.c"
if (attrs) {
assert(PyTuple_CheckExact(attrs)); // Success!
}
@@ -3224,7 +2900,6 @@
if (_PyErr_Occurred(tstate)) goto pop_3_error;
attrs = Py_None; // Failure!
}
- #line 3228 "Python/generated_cases.c.h"
STACK_SHRINK(2);
stack_pointer[-1] = attrs;
DISPATCH();
@@ -3233,10 +2908,8 @@
TARGET(MATCH_MAPPING) {
PyObject *subject = stack_pointer[-1];
PyObject *res;
- #line 2237 "Python/bytecodes.c"
int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING;
res = match ? Py_True : Py_False;
- #line 3240 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
DISPATCH();
@@ -3245,10 +2918,8 @@
TARGET(MATCH_SEQUENCE) {
PyObject *subject = stack_pointer[-1];
PyObject *res;
- #line 2242 "Python/bytecodes.c"
int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE;
res = match ? Py_True : Py_False;
- #line 3252 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
DISPATCH();
@@ -3258,11 +2929,9 @@
PyObject *keys = stack_pointer[-1];
PyObject *subject = stack_pointer[-2];
PyObject *values_or_none;
- #line 2247 "Python/bytecodes.c"
// On successful match, PUSH(values). Otherwise, PUSH(None).
values_or_none = match_keys(tstate, subject, keys);
if (values_or_none == NULL) goto error;
- #line 3266 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = values_or_none;
DISPATCH();
@@ -3271,14 +2940,10 @@
TARGET(GET_ITER) {
PyObject *iterable = stack_pointer[-1];
PyObject *iter;
- #line 2253 "Python/bytecodes.c"
/* before: [obj]; after [getiter(obj)] */
iter = PyObject_GetIter(iterable);
- #line 3278 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 2256 "Python/bytecodes.c"
if (iter == NULL) goto pop_1_error;
- #line 3282 "Python/generated_cases.c.h"
stack_pointer[-1] = iter;
DISPATCH();
}
@@ -3286,11 +2951,10 @@
TARGET(GET_YIELD_FROM_ITER) {
PyObject *iterable = stack_pointer[-1];
PyObject *iter;
- #line 2260 "Python/bytecodes.c"
/* before: [obj]; after [getiter(obj)] */
if (PyCoro_CheckExact(iterable)) {
/* `iterable` is a coroutine */
- if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
+ if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
/* and it is used in a 'yield from' expression of a
regular generator. */
_PyErr_SetString(tstate, PyExc_TypeError,
@@ -3309,11 +2973,8 @@
if (iter == NULL) {
goto error;
}
- #line 3313 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 2283 "Python/bytecodes.c"
}
- #line 3317 "Python/generated_cases.c.h"
stack_pointer[-1] = iter;
DISPATCH();
}
@@ -3323,7 +2984,6 @@
static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size");
PyObject *iter = stack_pointer[-1];
PyObject *next;
- #line 2301 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyForIterCache *cache = (_PyForIterCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -3349,12 +3009,12 @@
next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == INSTRUMENTED_END_FOR);
Py_DECREF(iter);
STACK_SHRINK(1);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
/* Jump forward oparg, then skip following END_FOR instruction */
- JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
+ JUMPBY(oparg + 1);
DISPATCH();
}
// Common case: no jump, leave it to the code generator
- #line 3358 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = next;
next_instr += 1;
@@ -3362,7 +3022,6 @@
}
TARGET(INSTRUMENTED_FOR_ITER) {
- #line 2334 "Python/bytecodes.c"
_Py_CODEUNIT *here = next_instr-1;
_Py_CODEUNIT *target;
PyObject *iter = TOP();
@@ -3388,101 +3047,150 @@
target = next_instr + INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1;
}
INSTRUMENTED_JUMP(here, target, PY_MONITORING_EVENT_BRANCH);
- #line 3392 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(FOR_ITER_LIST) {
- PyObject *iter = stack_pointer[-1];
- PyObject *next;
- #line 2362 "Python/bytecodes.c"
- DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER);
- _PyListIterObject *it = (_PyListIterObject *)iter;
- STAT_INC(FOR_ITER, hit);
- PyListObject *seq = it->it_seq;
- if (seq) {
- if (it->it_index < PyList_GET_SIZE(seq)) {
- next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++));
- goto end_for_iter_list; // End of this instruction
+ PyObject *_tmp_1;
+ PyObject *_tmp_2 = stack_pointer[-1];
+ {
+ PyObject *iter = _tmp_2;
+ DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER);
+ _tmp_2 = iter;
+ }
+ {
+ PyObject *iter = _tmp_2;
+ _PyListIterObject *it = (_PyListIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyListIter_Type);
+ STAT_INC(FOR_ITER, hit);
+ PyListObject *seq = it->it_seq;
+ if (seq == NULL || it->it_index >= PyList_GET_SIZE(seq)) {
+ if (seq != NULL) {
+ it->it_seq = NULL;
+ Py_DECREF(seq);
+ }
+ Py_DECREF(iter);
+ STACK_SHRINK(1);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
+ /* Jump forward oparg, then skip following END_FOR instruction */
+ JUMPBY(oparg + 1);
+ DISPATCH();
}
- it->it_seq = NULL;
- Py_DECREF(seq);
+ _tmp_2 = iter;
+ }
+ {
+ PyObject *iter = _tmp_2;
+ PyObject *next;
+ _PyListIterObject *it = (_PyListIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyListIter_Type);
+ PyListObject *seq = it->it_seq;
+ assert(seq);
+ assert(it->it_index < PyList_GET_SIZE(seq));
+ next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++));
+ _tmp_2 = iter;
+ _tmp_1 = next;
}
- Py_DECREF(iter);
- STACK_SHRINK(1);
- /* Jump forward oparg, then skip following END_FOR instruction */
- JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
- DISPATCH();
- end_for_iter_list:
- // Common case: no jump, leave it to the code generator
- #line 3419 "Python/generated_cases.c.h"
- STACK_GROW(1);
- stack_pointer[-1] = next;
next_instr += 1;
+ STACK_GROW(1);
+ stack_pointer[-1] = _tmp_1;
+ stack_pointer[-2] = _tmp_2;
DISPATCH();
}
TARGET(FOR_ITER_TUPLE) {
- PyObject *iter = stack_pointer[-1];
- PyObject *next;
- #line 2384 "Python/bytecodes.c"
- _PyTupleIterObject *it = (_PyTupleIterObject *)iter;
- DEOPT_IF(Py_TYPE(it) != &PyTupleIter_Type, FOR_ITER);
- STAT_INC(FOR_ITER, hit);
- PyTupleObject *seq = it->it_seq;
- if (seq) {
- if (it->it_index < PyTuple_GET_SIZE(seq)) {
- next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++));
- goto end_for_iter_tuple; // End of this instruction
+ PyObject *_tmp_1;
+ PyObject *_tmp_2 = stack_pointer[-1];
+ {
+ PyObject *iter = _tmp_2;
+ DEOPT_IF(Py_TYPE(iter) != &PyTupleIter_Type, FOR_ITER);
+ _tmp_2 = iter;
+ }
+ {
+ PyObject *iter = _tmp_2;
+ _PyTupleIterObject *it = (_PyTupleIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyTupleIter_Type);
+ STAT_INC(FOR_ITER, hit);
+ PyTupleObject *seq = it->it_seq;
+ if (seq == NULL || it->it_index >= PyTuple_GET_SIZE(seq)) {
+ if (seq != NULL) {
+ it->it_seq = NULL;
+ Py_DECREF(seq);
+ }
+ Py_DECREF(iter);
+ STACK_SHRINK(1);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
+ /* Jump forward oparg, then skip following END_FOR instruction */
+ JUMPBY(oparg + 1);
+ DISPATCH();
}
- it->it_seq = NULL;
- Py_DECREF(seq);
+ _tmp_2 = iter;
+ }
+ {
+ PyObject *iter = _tmp_2;
+ PyObject *next;
+ _PyTupleIterObject *it = (_PyTupleIterObject *)iter;
+ assert(Py_TYPE(iter) == &PyTupleIter_Type);
+ PyTupleObject *seq = it->it_seq;
+ assert(seq);
+ assert(it->it_index < PyTuple_GET_SIZE(seq));
+ next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++));
+ _tmp_2 = iter;
+ _tmp_1 = next;
}
- Py_DECREF(iter);
- STACK_SHRINK(1);
- /* Jump forward oparg, then skip following END_FOR instruction */
- JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
- DISPATCH();
- end_for_iter_tuple:
- // Common case: no jump, leave it to the code generator
- #line 3449 "Python/generated_cases.c.h"
- STACK_GROW(1);
- stack_pointer[-1] = next;
next_instr += 1;
+ STACK_GROW(1);
+ stack_pointer[-1] = _tmp_1;
+ stack_pointer[-2] = _tmp_2;
DISPATCH();
}
TARGET(FOR_ITER_RANGE) {
- PyObject *iter = stack_pointer[-1];
- PyObject *next;
- #line 2406 "Python/bytecodes.c"
- _PyRangeIterObject *r = (_PyRangeIterObject *)iter;
- DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER);
- STAT_INC(FOR_ITER, hit);
- if (r->len <= 0) {
- STACK_SHRINK(1);
- Py_DECREF(r);
- // Jump over END_FOR instruction.
- JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
- DISPATCH();
+ PyObject *_tmp_1;
+ PyObject *_tmp_2 = stack_pointer[-1];
+ {
+ PyObject *iter = _tmp_2;
+ _PyRangeIterObject *r = (_PyRangeIterObject *)iter;
+ DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER);
+ _tmp_2 = iter;
}
- long value = r->start;
- r->start = value + r->step;
- r->len--;
- next = PyLong_FromLong(value);
- if (next == NULL) {
- goto error;
+ {
+ PyObject *iter = _tmp_2;
+ _PyRangeIterObject *r = (_PyRangeIterObject *)iter;
+ assert(Py_TYPE(r) == &PyRangeIter_Type);
+ STAT_INC(FOR_ITER, hit);
+ if (r->len <= 0) {
+ STACK_SHRINK(1);
+ Py_DECREF(r);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
+ // Jump over END_FOR instruction.
+ JUMPBY(oparg + 1);
+ DISPATCH();
+ }
+ _tmp_2 = iter;
+ }
+ {
+ PyObject *iter = _tmp_2;
+ PyObject *next;
+ _PyRangeIterObject *r = (_PyRangeIterObject *)iter;
+ assert(Py_TYPE(r) == &PyRangeIter_Type);
+ assert(r->len > 0);
+ long value = r->start;
+ r->start = value + r->step;
+ r->len--;
+ next = PyLong_FromLong(value);
+ if (next == NULL) goto error;
+ _tmp_2 = iter;
+ _tmp_1 = next;
}
- #line 3477 "Python/generated_cases.c.h"
- STACK_GROW(1);
- stack_pointer[-1] = next;
next_instr += 1;
+ STACK_GROW(1);
+ stack_pointer[-1] = _tmp_1;
+ stack_pointer[-2] = _tmp_2;
DISPATCH();
}
TARGET(FOR_ITER_GEN) {
PyObject *iter = stack_pointer[-1];
- #line 2426 "Python/bytecodes.c"
DEOPT_IF(tstate->interp->eval_frame, FOR_ITER);
PyGenObject *gen = (PyGenObject *)iter;
DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER);
@@ -3494,18 +3202,16 @@
gen->gi_frame_state = FRAME_EXECUTING;
gen->gi_exc_state.previous_item = tstate->exc_info;
tstate->exc_info = &gen->gi_exc_state;
- JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
assert(next_instr[oparg].op.code == END_FOR ||
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
DISPATCH_INLINED(gen_frame);
- #line 3502 "Python/generated_cases.c.h"
}
TARGET(BEFORE_ASYNC_WITH) {
PyObject *mgr = stack_pointer[-1];
PyObject *exit;
PyObject *res;
- #line 2444 "Python/bytecodes.c"
PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__));
if (enter == NULL) {
if (!_PyErr_Occurred(tstate)) {
@@ -3528,16 +3234,13 @@
Py_DECREF(enter);
goto error;
}
- #line 3532 "Python/generated_cases.c.h"
Py_DECREF(mgr);
- #line 2467 "Python/bytecodes.c"
res = _PyObject_CallNoArgs(enter);
Py_DECREF(enter);
if (res == NULL) {
Py_DECREF(exit);
if (true) goto pop_1_error;
}
- #line 3541 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
stack_pointer[-2] = exit;
@@ -3548,7 +3251,6 @@
PyObject *mgr = stack_pointer[-1];
PyObject *exit;
PyObject *res;
- #line 2476 "Python/bytecodes.c"
/* pop the context manager, push its __exit__ and the
* value returned from calling its __enter__
*/
@@ -3574,16 +3276,13 @@
Py_DECREF(enter);
goto error;
}
- #line 3578 "Python/generated_cases.c.h"
Py_DECREF(mgr);
- #line 2502 "Python/bytecodes.c"
res = _PyObject_CallNoArgs(enter);
Py_DECREF(enter);
if (res == NULL) {
Py_DECREF(exit);
if (true) goto pop_1_error;
}
- #line 3587 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
stack_pointer[-2] = exit;
@@ -3595,7 +3294,6 @@
PyObject *lasti = stack_pointer[-3];
PyObject *exit_func = stack_pointer[-4];
PyObject *res;
- #line 2511 "Python/bytecodes.c"
/* At the top of the stack are 4 values:
- val: TOP = exc_info()
- unused: SECOND = previous exception
@@ -3616,7 +3314,6 @@
res = PyObject_Vectorcall(exit_func, stack + 1,
3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
if (res == NULL) goto error;
- #line 3620 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
DISPATCH();
@@ -3625,7 +3322,6 @@
TARGET(PUSH_EXC_INFO) {
PyObject *new_exc = stack_pointer[-1];
PyObject *prev_exc;
- #line 2534 "Python/bytecodes.c"
_PyErr_StackItem *exc_info = tstate->exc_info;
if (exc_info->exc_value != NULL) {
prev_exc = exc_info->exc_value;
@@ -3635,7 +3331,6 @@
}
assert(PyExceptionInstance_Check(new_exc));
exc_info->exc_value = Py_NewRef(new_exc);
- #line 3639 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = new_exc;
stack_pointer[-2] = prev_exc;
@@ -3649,7 +3344,7 @@
uint32_t type_version = read_u32(&next_instr[1].cache);
uint32_t keys_version = read_u32(&next_instr[3].cache);
PyObject *descr = read_obj(&next_instr[5].cache);
- #line 2546 "Python/bytecodes.c"
+ assert(oparg & 1);
/* Cached method object */
PyTypeObject *self_cls = Py_TYPE(self);
assert(type_version != 0);
@@ -3665,11 +3360,9 @@
res2 = Py_NewRef(descr);
assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR));
res = self;
- assert(oparg & 1);
- #line 3670 "Python/generated_cases.c.h"
- STACK_GROW(((oparg & 1) ? 1 : 0));
+ STACK_GROW(1);
stack_pointer[-1] = res;
- if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }
+ stack_pointer[-(1 + 1)] = res2;
next_instr += 9;
DISPATCH();
}
@@ -3680,7 +3373,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
PyObject *descr = read_obj(&next_instr[5].cache);
- #line 2565 "Python/bytecodes.c"
+ assert(oparg & 1);
PyTypeObject *self_cls = Py_TYPE(self);
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
assert(self_cls->tp_dictoffset == 0);
@@ -3689,11 +3382,55 @@
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
res2 = Py_NewRef(descr);
res = self;
- assert(oparg & 1);
- #line 3694 "Python/generated_cases.c.h"
- STACK_GROW(((oparg & 1) ? 1 : 0));
+ STACK_GROW(1);
+ stack_pointer[-1] = res;
+ stack_pointer[-(1 + 1)] = res2;
+ next_instr += 9;
+ DISPATCH();
+ }
+
+ TARGET(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES) {
+ PyObject *self = stack_pointer[-1];
+ PyObject *res;
+ uint32_t type_version = read_u32(&next_instr[1].cache);
+ uint32_t keys_version = read_u32(&next_instr[3].cache);
+ PyObject *descr = read_obj(&next_instr[5].cache);
+ assert((oparg & 1) == 0);
+ PyTypeObject *self_cls = Py_TYPE(self);
+ assert(type_version != 0);
+ DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
+ assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
+ PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(self);
+ DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);
+ PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls;
+ DEOPT_IF(self_heap_type->ht_cached_keys->dk_version !=
+ keys_version, LOAD_ATTR);
+ STAT_INC(LOAD_ATTR, hit);
+ assert(descr != NULL);
+ Py_DECREF(self);
+ res = Py_NewRef(descr);
+ STACK_GROW(0);
+ stack_pointer[-1] = res;
+ next_instr += 9;
+ DISPATCH();
+ }
+
+ TARGET(LOAD_ATTR_NONDESCRIPTOR_NO_DICT) {
+ PyObject *self = stack_pointer[-1];
+ PyObject *res;
+ uint32_t type_version = read_u32(&next_instr[1].cache);
+ PyObject *descr = read_obj(&next_instr[5].cache);
+ assert((oparg & 1) == 0);
+ PyTypeObject *self_cls = Py_TYPE(self);
+ assert(type_version != 0);
+ DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
+ assert(self_cls->tp_dictoffset == 0);
+ STAT_INC(LOAD_ATTR, hit);
+ assert(descr != NULL);
+ Py_DECREF(self);
+ res = Py_NewRef(descr);
+ STACK_GROW(0);
stack_pointer[-1] = res;
- if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }
next_instr += 9;
DISPATCH();
}
@@ -3704,7 +3441,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
PyObject *descr = read_obj(&next_instr[5].cache);
- #line 2577 "Python/bytecodes.c"
+ assert(oparg & 1);
PyTypeObject *self_cls = Py_TYPE(self);
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
Py_ssize_t dictoffset = self_cls->tp_dictoffset;
@@ -3717,26 +3454,21 @@
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
res2 = Py_NewRef(descr);
res = self;
- assert(oparg & 1);
- #line 3722 "Python/generated_cases.c.h"
- STACK_GROW(((oparg & 1) ? 1 : 0));
+ STACK_GROW(1);
stack_pointer[-1] = res;
- if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }
+ stack_pointer[-(1 + 1)] = res2;
next_instr += 9;
DISPATCH();
}
TARGET(KW_NAMES) {
- #line 2593 "Python/bytecodes.c"
assert(kwnames == NULL);
- assert(oparg < PyTuple_GET_SIZE(frame->f_code->co_consts));
- kwnames = GETITEM(frame->f_code->co_consts, oparg);
- #line 3735 "Python/generated_cases.c.h"
+ assert(oparg < PyTuple_GET_SIZE(FRAME_CO_CONSTS));
+ kwnames = GETITEM(FRAME_CO_CONSTS, oparg);
DISPATCH();
}
TARGET(INSTRUMENTED_CALL) {
- #line 2599 "Python/bytecodes.c"
int is_meth = PEEK(oparg+2) != NULL;
int total_args = oparg + is_meth;
PyObject *function = PEEK(total_args + 1);
@@ -3749,7 +3481,6 @@
_PyCallCache *cache = (_PyCallCache *)next_instr;
INCREMENT_ADAPTIVE_COUNTER(cache->counter);
GO_TO_INSTRUCTION(CALL);
- #line 3753 "Python/generated_cases.c.h"
}
TARGET(CALL) {
@@ -3759,7 +3490,6 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2644 "Python/bytecodes.c"
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
@@ -3808,7 +3538,7 @@
if (new_frame == NULL) {
goto error;
}
- JUMPBY(INLINE_CACHE_ENTRIES_CALL);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_CALL);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
}
@@ -3841,7 +3571,6 @@
Py_DECREF(args[i]);
}
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 3845 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -3853,7 +3582,6 @@
TARGET(CALL_BOUND_METHOD_EXACT_ARGS) {
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
- #line 2732 "Python/bytecodes.c"
DEOPT_IF(method != NULL, CALL);
DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL);
STAT_INC(CALL, hit);
@@ -3863,7 +3591,6 @@
PEEK(oparg + 2) = Py_NewRef(meth); // method
Py_DECREF(callable);
GO_TO_INSTRUCTION(CALL_PY_EXACT_ARGS);
- #line 3867 "Python/generated_cases.c.h"
}
TARGET(CALL_PY_EXACT_ARGS) {
@@ -3872,7 +3599,6 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
uint32_t func_version = read_u32(&next_instr[1].cache);
- #line 2744 "Python/bytecodes.c"
assert(kwnames == NULL);
DEOPT_IF(tstate->interp->eval_frame, CALL);
int is_meth = method != NULL;
@@ -3895,10 +3621,9 @@
}
// Manipulate stack directly since we leave using DISPATCH_INLINED().
STACK_SHRINK(oparg + 2);
- JUMPBY(INLINE_CACHE_ENTRIES_CALL);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_CALL);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 3902 "Python/generated_cases.c.h"
}
TARGET(CALL_PY_WITH_DEFAULTS) {
@@ -3906,7 +3631,6 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
uint32_t func_version = read_u32(&next_instr[1].cache);
- #line 2772 "Python/bytecodes.c"
assert(kwnames == NULL);
DEOPT_IF(tstate->interp->eval_frame, CALL);
int is_meth = method != NULL;
@@ -3939,10 +3663,9 @@
}
// Manipulate stack and cache directly since we leave using DISPATCH_INLINED().
STACK_SHRINK(oparg + 2);
- JUMPBY(INLINE_CACHE_ENTRIES_CALL);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_CALL);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 3946 "Python/generated_cases.c.h"
}
TARGET(CALL_NO_KW_TYPE_1) {
@@ -3950,7 +3673,6 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *null = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2810 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
@@ -3960,7 +3682,6 @@
res = Py_NewRef(Py_TYPE(obj));
Py_DECREF(obj);
Py_DECREF(&PyType_Type); // I.e., callable
- #line 3964 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -3973,7 +3694,6 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *null = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2822 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
@@ -3984,7 +3704,6 @@
Py_DECREF(arg);
Py_DECREF(&PyUnicode_Type); // I.e., callable
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 3988 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -3998,7 +3717,6 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *null = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2836 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
@@ -4009,7 +3727,6 @@
Py_DECREF(arg);
Py_DECREF(&PyTuple_Type); // I.e., tuple
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4013 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4018,12 +3735,80 @@
DISPATCH();
}
+ TARGET(CALL_NO_KW_ALLOC_AND_ENTER_INIT) {
+ PyObject **args = (stack_pointer - oparg);
+ PyObject *callable = stack_pointer[-(1 + oparg)];
+ PyObject *null = stack_pointer[-(2 + oparg)];
+ /* This instruction does the following:
+ * 1. Creates the object (by calling ``object.__new__``)
+ * 2. Pushes a shim frame to the frame stack (to cleanup after ``__init__``)
+ * 3. Pushes the frame for ``__init__`` to the frame stack
+ * */
+ assert(kwnames == NULL);
+ _PyCallCache *cache = (_PyCallCache *)next_instr;
+ DEOPT_IF(null != NULL, CALL);
+ DEOPT_IF(!PyType_Check(callable), CALL);
+ PyTypeObject *tp = (PyTypeObject *)callable;
+ DEOPT_IF(tp->tp_version_tag != read_u32(cache->func_version), CALL);
+ PyHeapTypeObject *cls = (PyHeapTypeObject *)callable;
+ PyFunctionObject *init = (PyFunctionObject *)cls->_spec_cache.init;
+ PyCodeObject *code = (PyCodeObject *)init->func_code;
+ DEOPT_IF(code->co_argcount != oparg+1, CALL);
+ DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize + _Py_InitCleanup.co_framesize), CALL);
+ STAT_INC(CALL, hit);
+ PyObject *self = _PyType_NewManagedObject(tp);
+ if (self == NULL) {
+ goto error;
+ }
+ Py_DECREF(tp);
+ _PyInterpreterFrame *shim = _PyFrame_PushTrampolineUnchecked(
+ tstate, (PyCodeObject *)&_Py_InitCleanup, 1, 0);
+ assert(_PyCode_CODE((PyCodeObject *)shim->f_executable)[1].op.code == EXIT_INIT_CHECK);
+ /* Push self onto stack of shim */
+ Py_INCREF(self);
+ shim->localsplus[0] = self;
+ Py_INCREF(init);
+ _PyInterpreterFrame *init_frame = _PyFrame_PushUnchecked(tstate, init, oparg+1);
+ /* Copy self followed by args to __init__ frame */
+ init_frame->localsplus[0] = self;
+ for (int i = 0; i < oparg; i++) {
+ init_frame->localsplus[i+1] = args[i];
+ }
+ SKIP_OVER(INLINE_CACHE_ENTRIES_CALL);
+ frame->prev_instr = next_instr - 1;
+ frame->return_offset = 0;
+ STACK_SHRINK(oparg+2);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ /* Link frames */
+ init_frame->previous = shim;
+ shim->previous = frame;
+ frame = cframe.current_frame = init_frame;
+ CALL_STAT_INC(inlined_py_calls);
+ /* Account for pushing the extra frame.
+ * We don't check recursion depth here,
+ * as it will be checked after start_frame */
+ tstate->py_recursion_remaining--;
+ goto start_frame;
+ }
+
+ TARGET(EXIT_INIT_CHECK) {
+ PyObject *should_be_none = stack_pointer[-1];
+ assert(STACK_LEVEL() == 2);
+ if (should_be_none != Py_None) {
+ PyErr_Format(PyExc_TypeError,
+ "__init__() should return None, not '%.200s'",
+ Py_TYPE(should_be_none)->tp_name);
+ goto error;
+ }
+ STACK_SHRINK(1);
+ DISPATCH();
+ }
+
TARGET(CALL_BUILTIN_CLASS) {
PyObject **args = (stack_pointer - oparg);
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2850 "Python/bytecodes.c"
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
@@ -4045,7 +3830,6 @@
}
Py_DECREF(tp);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4049 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4059,7 +3843,6 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2875 "Python/bytecodes.c"
/* Builtin METH_O functions */
assert(kwnames == NULL);
int is_meth = method != NULL;
@@ -4087,7 +3870,6 @@
Py_DECREF(arg);
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4091 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4101,7 +3883,6 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2906 "Python/bytecodes.c"
/* Builtin METH_FASTCALL functions, without keywords */
assert(kwnames == NULL);
int is_meth = method != NULL;
@@ -4133,7 +3914,6 @@
'invalid'). In those cases an exception is set, so we must
handle it.
*/
- #line 4137 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4147,7 +3927,6 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2941 "Python/bytecodes.c"
/* Builtin METH_FASTCALL | METH_KEYWORDS functions */
int is_meth = method != NULL;
int total_args = oparg;
@@ -4179,7 +3958,6 @@
}
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4183 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4193,7 +3971,6 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2976 "Python/bytecodes.c"
assert(kwnames == NULL);
/* len(o) */
int is_meth = method != NULL;
@@ -4218,7 +3995,6 @@
Py_DECREF(callable);
Py_DECREF(arg);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4222 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4231,7 +4007,6 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3003 "Python/bytecodes.c"
assert(kwnames == NULL);
/* isinstance(o, o2) */
int is_meth = method != NULL;
@@ -4258,7 +4033,6 @@
Py_DECREF(cls);
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4262 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4270,7 +4044,6 @@
PyObject **args = (stack_pointer - oparg);
PyObject *self = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
- #line 3033 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 1);
assert(method != NULL);
@@ -4285,17 +4058,15 @@
Py_DECREF(method);
STACK_SHRINK(3);
// CALL + POP_TOP
- JUMPBY(INLINE_CACHE_ENTRIES_CALL + 1);
+ SKIP_OVER(INLINE_CACHE_ENTRIES_CALL + 1);
assert(next_instr[-1].op.code == POP_TOP);
DISPATCH();
- #line 4292 "Python/generated_cases.c.h"
}
TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_O) {
PyObject **args = (stack_pointer - oparg);
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3053 "Python/bytecodes.c"
assert(kwnames == NULL);
int is_meth = method != NULL;
int total_args = oparg;
@@ -4326,7 +4097,6 @@
Py_DECREF(arg);
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4330 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4339,7 +4109,6 @@
PyObject **args = (stack_pointer - oparg);
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3087 "Python/bytecodes.c"
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
@@ -4368,7 +4137,6 @@
}
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4372 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4381,7 +4149,6 @@
PyObject **args = (stack_pointer - oparg);
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3119 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 0 || oparg == 1);
int is_meth = method != NULL;
@@ -4410,7 +4177,6 @@
Py_DECREF(self);
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4414 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4423,7 +4189,6 @@
PyObject **args = (stack_pointer - oparg);
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3151 "Python/bytecodes.c"
assert(kwnames == NULL);
int is_meth = method != NULL;
int total_args = oparg;
@@ -4451,7 +4216,6 @@
}
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4455 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4461,9 +4225,7 @@
}
TARGET(INSTRUMENTED_CALL_FUNCTION_EX) {
- #line 3182 "Python/bytecodes.c"
GO_TO_INSTRUCTION(CALL_FUNCTION_EX);
- #line 4467 "Python/generated_cases.c.h"
}
TARGET(CALL_FUNCTION_EX) {
@@ -4472,7 +4234,6 @@
PyObject *callargs = stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))];
PyObject *func = stack_pointer[-(2 + ((oparg & 1) ? 1 : 0))];
PyObject *result;
- #line 3186 "Python/bytecodes.c"
// DICT_MERGE is called before this opcode if there are kwargs.
// It converts all dict subtypes in kwargs into regular dicts.
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
@@ -4534,14 +4295,11 @@
}
result = PyObject_Call(func, callargs, kwargs);
}
- #line 4538 "Python/generated_cases.c.h"
Py_DECREF(func);
Py_DECREF(callargs);
Py_XDECREF(kwargs);
- #line 3248 "Python/bytecodes.c"
assert(PEEK(3 + (oparg & 1)) == NULL);
if (result == NULL) { STACK_SHRINK(((oparg & 1) ? 1 : 0)); goto pop_3_error; }
- #line 4545 "Python/generated_cases.c.h"
STACK_SHRINK(((oparg & 1) ? 1 : 0));
STACK_SHRINK(2);
stack_pointer[-1] = result;
@@ -4551,12 +4309,7 @@
TARGET(MAKE_FUNCTION) {
PyObject *codeobj = stack_pointer[-1];
- PyObject *closure = (oparg & MAKE_FUNCTION_CLOSURE) ? stack_pointer[-(1 + ((oparg & MAKE_FUNCTION_CLOSURE) ? 1 : 0))] : NULL;
- PyObject *annotations = (oparg & MAKE_FUNCTION_ANNOTATIONS) ? stack_pointer[-(1 + ((oparg & MAKE_FUNCTION_CLOSURE) ? 1 : 0) + ((oparg & MAKE_FUNCTION_ANNOTATIONS) ? 1 : 0))] : NULL;
- PyObject *kwdefaults = (oparg & MAKE_FUNCTION_KWDEFAULTS) ? stack_pointer[-(1 + ((oparg & MAKE_FUNCTION_CLOSURE) ? 1 : 0) + ((oparg & MAKE_FUNCTION_ANNOTATIONS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_KWDEFAULTS) ? 1 : 0))] : NULL;
- PyObject *defaults = (oparg & MAKE_FUNCTION_DEFAULTS) ? stack_pointer[-(1 + ((oparg & MAKE_FUNCTION_CLOSURE) ? 1 : 0) + ((oparg & MAKE_FUNCTION_ANNOTATIONS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_KWDEFAULTS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_DEFAULTS) ? 1 : 0))] : NULL;
PyObject *func;
- #line 3258 "Python/bytecodes.c"
PyFunctionObject *func_obj = (PyFunctionObject *)
PyFunction_New(codeobj, GLOBALS());
@@ -4566,33 +4319,45 @@
goto error;
}
- if (oparg & MAKE_FUNCTION_CLOSURE) {
- assert(PyTuple_CheckExact(closure));
- func_obj->func_closure = closure;
- }
- if (oparg & MAKE_FUNCTION_ANNOTATIONS) {
- assert(PyTuple_CheckExact(annotations));
- func_obj->func_annotations = annotations;
- }
- if (oparg & MAKE_FUNCTION_KWDEFAULTS) {
- assert(PyDict_CheckExact(kwdefaults));
- func_obj->func_kwdefaults = kwdefaults;
- }
- if (oparg & MAKE_FUNCTION_DEFAULTS) {
- assert(PyTuple_CheckExact(defaults));
- func_obj->func_defaults = defaults;
- }
-
func_obj->func_version = ((PyCodeObject *)codeobj)->co_version;
func = (PyObject *)func_obj;
- #line 4589 "Python/generated_cases.c.h"
- STACK_SHRINK(((oparg & MAKE_FUNCTION_DEFAULTS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_KWDEFAULTS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_ANNOTATIONS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_CLOSURE) ? 1 : 0));
+ stack_pointer[-1] = func;
+ DISPATCH();
+ }
+
+ TARGET(SET_FUNCTION_ATTRIBUTE) {
+ PyObject *func = stack_pointer[-1];
+ PyObject *attr = stack_pointer[-2];
+ assert(PyFunction_Check(func));
+ PyFunctionObject *func_obj = (PyFunctionObject *)func;
+ switch(oparg) {
+ case MAKE_FUNCTION_CLOSURE:
+ assert(func_obj->func_closure == NULL);
+ func_obj->func_closure = attr;
+ break;
+ case MAKE_FUNCTION_ANNOTATIONS:
+ assert(func_obj->func_annotations == NULL);
+ func_obj->func_annotations = attr;
+ break;
+ case MAKE_FUNCTION_KWDEFAULTS:
+ assert(PyDict_CheckExact(attr));
+ assert(func_obj->func_kwdefaults == NULL);
+ func_obj->func_kwdefaults = attr;
+ break;
+ case MAKE_FUNCTION_DEFAULTS:
+ assert(PyTuple_CheckExact(attr));
+ assert(func_obj->func_defaults == NULL);
+ func_obj->func_defaults = attr;
+ break;
+ default:
+ Py_UNREACHABLE();
+ }
+ STACK_SHRINK(1);
stack_pointer[-1] = func;
DISPATCH();
}
TARGET(RETURN_GENERATOR) {
- #line 3289 "Python/bytecodes.c"
assert(PyFunction_Check(frame->f_funcobj));
PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;
PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);
@@ -4613,7 +4378,6 @@
frame = cframe.current_frame = prev;
_PyFrame_StackPush(frame, (PyObject *)gen);
goto resume_frame;
- #line 4617 "Python/generated_cases.c.h"
}
TARGET(BUILD_SLICE) {
@@ -4621,73 +4385,65 @@
PyObject *stop = stack_pointer[-(1 + ((oparg == 3) ? 1 : 0))];
PyObject *start = stack_pointer[-(2 + ((oparg == 3) ? 1 : 0))];
PyObject *slice;
- #line 3312 "Python/bytecodes.c"
slice = PySlice_New(start, stop, step);
- #line 4627 "Python/generated_cases.c.h"
Py_DECREF(start);
Py_DECREF(stop);
Py_XDECREF(step);
- #line 3314 "Python/bytecodes.c"
if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error; }
- #line 4633 "Python/generated_cases.c.h"
STACK_SHRINK(((oparg == 3) ? 1 : 0));
STACK_SHRINK(1);
stack_pointer[-1] = slice;
DISPATCH();
}
- TARGET(FORMAT_VALUE) {
- PyObject *fmt_spec = ((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? stack_pointer[-((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0))] : NULL;
- PyObject *value = stack_pointer[-(1 + (((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0))];
+ TARGET(CONVERT_VALUE) {
+ PyObject *value = stack_pointer[-1];
PyObject *result;
- #line 3318 "Python/bytecodes.c"
- /* Handles f-string value formatting. */
- PyObject *(*conv_fn)(PyObject *);
- int which_conversion = oparg & FVC_MASK;
-
- /* See if any conversion is specified. */
- switch (which_conversion) {
- case FVC_NONE: conv_fn = NULL; break;
- case FVC_STR: conv_fn = PyObject_Str; break;
- case FVC_REPR: conv_fn = PyObject_Repr; break;
- case FVC_ASCII: conv_fn = PyObject_ASCII; break;
- default:
- _PyErr_Format(tstate, PyExc_SystemError,
- "unexpected conversion flag %d",
- which_conversion);
- goto error;
- }
+ convertion_func_ptr conv_fn;
+ assert(oparg >= FVC_STR && oparg <= FVC_ASCII);
+ conv_fn = CONVERSION_FUNCTIONS[oparg];
+ result = conv_fn(value);
+ Py_DECREF(value);
+ if (result == NULL) goto pop_1_error;
+ stack_pointer[-1] = result;
+ DISPATCH();
+ }
- /* If there's a conversion function, call it and replace
- value with that result. Otherwise, just use value,
- without conversion. */
- if (conv_fn != NULL) {
- result = conv_fn(value);
+ TARGET(FORMAT_SIMPLE) {
+ PyObject *value = stack_pointer[-1];
+ PyObject *res;
+ /* If value is a unicode object, then we know the result
+ * of format(value) is value itself. */
+ if (!PyUnicode_CheckExact(value)) {
+ res = PyObject_Format(value, NULL);
Py_DECREF(value);
- if (result == NULL) {
- Py_XDECREF(fmt_spec);
- if (true) { STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0)); goto pop_1_error; }
- }
- value = result;
+ if (res == NULL) goto pop_1_error;
+ }
+ else {
+ res = value;
}
+ stack_pointer[-1] = res;
+ DISPATCH();
+ }
- result = PyObject_Format(value, fmt_spec);
+ TARGET(FORMAT_WITH_SPEC) {
+ PyObject *fmt_spec = stack_pointer[-1];
+ PyObject *value = stack_pointer[-2];
+ PyObject *res;
+ res = PyObject_Format(value, fmt_spec);
Py_DECREF(value);
- Py_XDECREF(fmt_spec);
- if (result == NULL) { STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0)); goto pop_1_error; }
- #line 4679 "Python/generated_cases.c.h"
- STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0));
- stack_pointer[-1] = result;
+ Py_DECREF(fmt_spec);
+ if (res == NULL) goto pop_2_error;
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
DISPATCH();
}
TARGET(COPY) {
PyObject *bottom = stack_pointer[-(1 + (oparg-1))];
PyObject *top;
- #line 3355 "Python/bytecodes.c"
assert(oparg > 0);
top = Py_NewRef(bottom);
- #line 4691 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = top;
DISPATCH();
@@ -4699,7 +4455,6 @@
PyObject *rhs = stack_pointer[-1];
PyObject *lhs = stack_pointer[-2];
PyObject *res;
- #line 3360 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -4714,12 +4469,9 @@
assert((unsigned)oparg < Py_ARRAY_LENGTH(binary_ops));
assert(binary_ops[oparg]);
res = binary_ops[oparg](lhs, rhs);
- #line 4718 "Python/generated_cases.c.h"
Py_DECREF(lhs);
Py_DECREF(rhs);
- #line 3375 "Python/bytecodes.c"
if (res == NULL) goto pop_2_error;
- #line 4723 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -4729,16 +4481,13 @@
TARGET(SWAP) {
PyObject *top = stack_pointer[-1];
PyObject *bottom = stack_pointer[-(2 + (oparg-2))];
- #line 3380 "Python/bytecodes.c"
assert(oparg >= 2);
- #line 4735 "Python/generated_cases.c.h"
stack_pointer[-1] = bottom;
stack_pointer[-(2 + (oparg-2))] = top;
DISPATCH();
}
TARGET(INSTRUMENTED_INSTRUCTION) {
- #line 3384 "Python/bytecodes.c"
int next_opcode = _Py_call_instrumentation_instruction(
tstate, frame, next_instr-1);
if (next_opcode < 0) goto error;
@@ -4750,54 +4499,38 @@
assert(next_opcode > 0 && next_opcode < 256);
opcode = next_opcode;
DISPATCH_GOTO();
- #line 4754 "Python/generated_cases.c.h"
}
TARGET(INSTRUMENTED_JUMP_FORWARD) {
- #line 3398 "Python/bytecodes.c"
INSTRUMENTED_JUMP(next_instr-1, next_instr+oparg, PY_MONITORING_EVENT_JUMP);
- #line 4760 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_JUMP_BACKWARD) {
- #line 3402 "Python/bytecodes.c"
- INSTRUMENTED_JUMP(next_instr-1, next_instr+1-oparg, PY_MONITORING_EVENT_JUMP);
- #line 4767 "Python/generated_cases.c.h"
CHECK_EVAL_BREAKER();
+ INSTRUMENTED_JUMP(next_instr-1, next_instr+1-oparg, PY_MONITORING_EVENT_JUMP);
DISPATCH();
}
TARGET(INSTRUMENTED_POP_JUMP_IF_TRUE) {
- #line 3407 "Python/bytecodes.c"
PyObject *cond = POP();
- int err = PyObject_IsTrue(cond);
- Py_DECREF(cond);
- if (err < 0) goto error;
- _Py_CODEUNIT *here = next_instr-1;
- assert(err == 0 || err == 1);
- int offset = err*oparg;
+ assert(PyBool_Check(cond));
+ _Py_CODEUNIT *here = next_instr - 1;
+ int offset = Py_IsTrue(cond) * oparg;
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
- #line 4782 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_POP_JUMP_IF_FALSE) {
- #line 3418 "Python/bytecodes.c"
PyObject *cond = POP();
- int err = PyObject_IsTrue(cond);
- Py_DECREF(cond);
- if (err < 0) goto error;
- _Py_CODEUNIT *here = next_instr-1;
- assert(err == 0 || err == 1);
- int offset = (1-err)*oparg;
+ assert(PyBool_Check(cond));
+ _Py_CODEUNIT *here = next_instr - 1;
+ int offset = Py_IsFalse(cond) * oparg;
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
- #line 4796 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_POP_JUMP_IF_NONE) {
- #line 3429 "Python/bytecodes.c"
PyObject *value = POP();
_Py_CODEUNIT *here = next_instr-1;
int offset;
@@ -4809,12 +4542,10 @@
offset = 0;
}
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
- #line 4813 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_POP_JUMP_IF_NOT_NONE) {
- #line 3443 "Python/bytecodes.c"
PyObject *value = POP();
_Py_CODEUNIT *here = next_instr-1;
int offset;
@@ -4823,33 +4554,26 @@
}
else {
Py_DECREF(value);
- offset = oparg;
+ offset = oparg;
}
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
- #line 4830 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(EXTENDED_ARG) {
- #line 3457 "Python/bytecodes.c"
assert(oparg);
opcode = next_instr->op.code;
oparg = oparg << 8 | next_instr->op.arg;
PRE_DISPATCH_GOTO();
DISPATCH_GOTO();
- #line 4841 "Python/generated_cases.c.h"
}
TARGET(CACHE) {
- #line 3465 "Python/bytecodes.c"
assert(0 && "Executing a cache.");
Py_UNREACHABLE();
- #line 4848 "Python/generated_cases.c.h"
}
TARGET(RESERVED) {
- #line 3470 "Python/bytecodes.c"
assert(0 && "Executing RESERVED instruction.");
Py_UNREACHABLE();
- #line 4855 "Python/generated_cases.c.h"
}
diff --git a/Python/hamt.c b/Python/hamt.c
index 8cb94641bef251..c78b5a7fab94f0 100644
--- a/Python/hamt.c
+++ b/Python/hamt.c
@@ -2425,7 +2425,7 @@ hamt_alloc(void)
}
#define _empty_hamt \
- (&_Py_INTERP_SINGLETON(_PyInterpreterState_Get(), hamt_empty))
+ (&_Py_INTERP_SINGLETON(_PyInterpreterState_GET(), hamt_empty))
PyHamtObject *
_PyHamt_New(void)
diff --git a/Python/import.c b/Python/import.c
index 71cce8e4f623dd..3e52a4e4eb1450 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -12,6 +12,7 @@
#include "pycore_pymem.h" // _PyMem_SetDefaultAllocator()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_sysmodule.h" // _PySys_Audit()
+#include "pycore_weakref.h" // _PyWeakref_GET_REF()
#include "marshal.h" // PyMarshal_ReadObjectFromString()
#include "importdl.h" // _PyImport_DynLoadFiletab
#include "pydtrace.h" // PyDTrace_IMPORT_FIND_LOAD_START_ENABLED()
@@ -248,16 +249,7 @@ import_get_module(PyThreadState *tstate, PyObject *name)
PyObject *m;
Py_INCREF(modules);
- if (PyDict_CheckExact(modules)) {
- m = PyDict_GetItemWithError(modules, name); /* borrowed */
- Py_XINCREF(m);
- }
- else {
- m = PyObject_GetItem(modules, name);
- if (m == NULL && _PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
- _PyErr_Clear(tstate);
- }
- }
+ (void)PyMapping_GetOptionalItem(modules, name, &m);
Py_DECREF(modules);
return m;
}
@@ -277,7 +269,7 @@ import_ensure_initialized(PyInterpreterState *interp, PyObject *mod, PyObject *n
Py_XDECREF(spec);
if (busy) {
/* Wait until module is done importing. */
- PyObject *value = _PyObject_CallMethodOneArg(
+ PyObject *value = PyObject_CallMethodOneArg(
IMPORTLIB(interp), &_Py_ID(_lock_unlock_module), name);
if (value == NULL) {
return -1;
@@ -321,18 +313,7 @@ import_add_module(PyThreadState *tstate, PyObject *name)
}
PyObject *m;
- if (PyDict_CheckExact(modules)) {
- m = Py_XNewRef(PyDict_GetItemWithError(modules, name));
- }
- else {
- m = PyObject_GetItem(modules, name);
- // For backward-compatibility we copy the behavior
- // of PyDict_GetItemWithError().
- if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
- _PyErr_Clear(tstate);
- }
- }
- if (_PyErr_Occurred(tstate)) {
+ if (PyMapping_GetOptionalItem(modules, name, &m) < 0) {
return NULL;
}
if (m != NULL && PyModule_Check(m)) {
@@ -350,19 +331,52 @@ import_add_module(PyThreadState *tstate, PyObject *name)
return m;
}
+PyObject *
+PyImport_AddModuleRef(const char *name)
+{
+ PyObject *name_obj = PyUnicode_FromString(name);
+ if (name_obj == NULL) {
+ return NULL;
+ }
+ PyThreadState *tstate = _PyThreadState_GET();
+ PyObject *module = import_add_module(tstate, name_obj);
+ Py_DECREF(name_obj);
+ return module;
+}
+
+
PyObject *
PyImport_AddModuleObject(PyObject *name)
{
PyThreadState *tstate = _PyThreadState_GET();
PyObject *mod = import_add_module(tstate, name);
- if (mod) {
- PyObject *ref = PyWeakref_NewRef(mod, NULL);
- Py_DECREF(mod);
- if (ref == NULL) {
- return NULL;
- }
- mod = PyWeakref_GetObject(ref);
- Py_DECREF(ref);
+ if (!mod) {
+ return NULL;
+ }
+
+ // gh-86160: PyImport_AddModuleObject() returns a borrowed reference.
+ // Create a weak reference to produce a borrowed reference, since it can
+ // become NULL. sys.modules type can be different than dict and it is not
+ // guaranteed that it keeps a strong reference to the module. It can be a
+ // custom mapping with __getitem__() which returns a new object or removes
+ // returned object, or __setitem__ which does nothing. There is so much
+ // unknown. With weakref we can be sure that we get either a reference to
+ // live object or NULL.
+ //
+ // Use PyImport_AddModuleRef() to avoid these issues.
+ PyObject *ref = PyWeakref_NewRef(mod, NULL);
+ Py_DECREF(mod);
+ if (ref == NULL) {
+ return NULL;
+ }
+ mod = _PyWeakref_GET_REF(ref);
+ Py_DECREF(ref);
+ Py_XDECREF(mod);
+
+ if (mod == NULL && !PyErr_Occurred()) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "sys.modules does not hold a strong reference "
+ "to the module");
}
return mod; /* borrowed reference */
}
@@ -703,10 +717,19 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp)
_PyRuntime.imports.pkgcontext, and PyModule_Create*() will
substitute this (if the name actually matches).
*/
+
+#ifdef HAVE_THREAD_LOCAL
+_Py_thread_local const char *pkgcontext = NULL;
+# undef PKGCONTEXT
+# define PKGCONTEXT pkgcontext
+#endif
+
const char *
_PyImport_ResolveNameWithPackageContext(const char *name)
{
+#ifndef HAVE_THREAD_LOCAL
PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK);
+#endif
if (PKGCONTEXT != NULL) {
const char *p = strrchr(PKGCONTEXT, '.');
if (p != NULL && strcmp(name, p+1) == 0) {
@@ -714,17 +737,23 @@ _PyImport_ResolveNameWithPackageContext(const char *name)
PKGCONTEXT = NULL;
}
}
+#ifndef HAVE_THREAD_LOCAL
PyThread_release_lock(EXTENSIONS.mutex);
+#endif
return name;
}
const char *
_PyImport_SwapPackageContext(const char *newcontext)
{
+#ifndef HAVE_THREAD_LOCAL
PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK);
+#endif
const char *oldcontext = PKGCONTEXT;
PKGCONTEXT = newcontext;
+#ifndef HAVE_THREAD_LOCAL
PyThread_release_lock(EXTENSIONS.mutex);
+#endif
return oldcontext;
}
@@ -790,16 +819,6 @@ _PyImport_ClearExtension(PyObject *name, PyObject *filename)
}
-/*******************/
-
-#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
-#include
-EM_JS(PyObject*, _PyImport_InitFunc_TrampolineCall, (PyModInitFunction func), {
- return wasmTable.get(func)();
-});
-#endif // __EMSCRIPTEN__ && PY_CALL_TRAMPOLINE
-
-
/*****************************/
/* single-phase init modules */
/*****************************/
@@ -1084,7 +1103,7 @@ check_multi_interp_extensions(PyInterpreterState *interp)
int
_PyImport_CheckSubinterpIncompatibleExtensionAllowed(const char *name)
{
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
if (check_multi_interp_extensions(interp)) {
assert(!_Py_IsMainInterpreter(interp));
PyErr_Format(PyExc_ImportError,
@@ -1236,7 +1255,7 @@ import_find_extension(PyThreadState *tstate, PyObject *name,
else {
if (def->m_base.m_init == NULL)
return NULL;
- mod = _PyImport_InitFunc_TrampolineCall(def->m_base.m_init);
+ mod = def->m_base.m_init();
if (mod == NULL)
return NULL;
if (PyObject_SetItem(modules, name, mod) == -1) {
@@ -1349,10 +1368,9 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
if (_PyUnicode_EqualToASCIIString(name, p->name)) {
if (p->initfunc == NULL) {
/* Cannot re-init internal module ("sys" or "builtins") */
- mod = PyImport_AddModuleObject(name);
- return Py_XNewRef(mod);
+ return import_add_module(tstate, name);
}
- mod = _PyImport_InitFunc_TrampolineCall(*p->initfunc);
+ mod = (*p->initfunc)();
if (mod == NULL) {
return NULL;
}
@@ -1612,7 +1630,7 @@ PyImport_ExecCodeModuleWithPathnames(const char *name, PyObject *co,
external= PyObject_GetAttrString(IMPORTLIB(interp),
"_bootstrap_external");
if (external != NULL) {
- pathobj = _PyObject_CallMethodOneArg(
+ pathobj = PyObject_CallMethodOneArg(
external, &_Py_ID(_get_sourcefile), cpathobj);
Py_DECREF(external);
}
@@ -2038,6 +2056,7 @@ unmarshal_frozen_code(PyInterpreterState *interp, struct frozen_info *info)
PyObject *co = PyMarshal_ReadObjectFromString(info->data, info->size);
if (co == NULL) {
/* Does not contain executable code. */
+ PyErr_Clear();
set_frozen_error(FROZEN_INVALID, info->nameobj);
return NULL;
}
@@ -2225,11 +2244,12 @@ init_importlib(PyThreadState *tstate, PyObject *sysmod)
if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
return -1;
}
- PyObject *importlib = PyImport_AddModule("_frozen_importlib"); // borrowed
+
+ PyObject *importlib = PyImport_AddModuleRef("_frozen_importlib");
if (importlib == NULL) {
return -1;
}
- IMPORTLIB(interp) = Py_NewRef(importlib);
+ IMPORTLIB(interp) = importlib;
// Import the _imp module
if (verbose) {
@@ -2858,7 +2878,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
}
else {
PyObject *path;
- if (_PyObject_LookupAttr(mod, &_Py_ID(__path__), &path) < 0) {
+ if (PyObject_GetOptionalAttr(mod, &_Py_ID(__path__), &path) < 0) {
goto error;
}
if (path) {
diff --git a/Python/importdl.c b/Python/importdl.c
index 3a3a30ddbdcdb5..9ab0a5ad33aaac 100644
--- a/Python/importdl.c
+++ b/Python/importdl.c
@@ -4,6 +4,7 @@
#include "Python.h"
#include "pycore_call.h"
#include "pycore_import.h"
+#include "pycore_pyerrors.h" // _PyErr_FormatFromCause()
#include "pycore_pystate.h"
#include "pycore_runtime.h"
@@ -166,7 +167,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp)
/* Package context is needed for single-phase init */
oldcontext = _PyImport_SwapPackageContext(newcontext);
- m = _PyImport_InitFunc_TrampolineCall(p0);
+ m = p0();
_PyImport_SwapPackageContext(oldcontext);
if (m == NULL) {
diff --git a/Python/importdl.h b/Python/importdl.h
index 26d18b626df052..9171adc2770689 100644
--- a/Python/importdl.h
+++ b/Python/importdl.h
@@ -12,12 +12,6 @@ extern PyObject *_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *);
typedef PyObject *(*PyModInitFunction)(void);
-#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
-extern PyObject *_PyImport_InitFunc_TrampolineCall(PyModInitFunction func);
-#else
-#define _PyImport_InitFunc_TrampolineCall(func) (func)()
-#endif
-
/* Max length of module suffix searched for -- accommodates "module.slb" */
#define MAXSUFFIXSIZE 12
diff --git a/Python/initconfig.c b/Python/initconfig.c
index 1dcefd478eefea..787e583262406c 100644
--- a/Python/initconfig.c
+++ b/Python/initconfig.c
@@ -49,7 +49,7 @@ Options (and corresponding environment variables):\n\
.pyc extension; also PYTHONOPTIMIZE=x\n\
-OO : do -O changes and also discard docstrings; add .opt-2 before\n\
.pyc extension\n\
--P : don't prepend a potentially unsafe path to sys.path\n\
+-P : don't prepend a potentially unsafe path to sys.path; also PYTHONSAFEPATH\n\
-q : don't print version and copyright messages on interactive startup\n\
-s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\
-S : don't imply 'import site' on initialization\n\
@@ -144,7 +144,6 @@ static const char usage_envvars[] =
"PYTHONSTARTUP: file executed on interactive startup (no default)\n"
"PYTHONPATH : '%lc'-separated list of directories prefixed to the\n"
" default module search path. The result is sys.path.\n"
-"PYTHONSAFEPATH: don't prepend a potentially unsafe path to sys.path.\n"
"PYTHONHOME : alternate directory (or %lc).\n"
" The default module search path uses %s.\n"
"PYTHONPLATLIBDIR : override sys.platlibdir.\n"
@@ -184,6 +183,7 @@ static const char usage_envvars[] =
" (-X int_max_str_digits=number)\n"
"PYTHONNOUSERSITE : disable user site directory (-s)\n"
"PYTHONOPTIMIZE : enable level 1 optimizations (-O)\n"
+"PYTHONSAFEPATH : don't prepend a potentially unsafe path to sys.path (-P)\n"
"PYTHONUNBUFFERED : disable stdout/stderr buffering (-u)\n"
"PYTHONVERBOSE : trace import statements (-v)\n"
"PYTHONWARNINGS=arg : warning control (-W arg)\n";
@@ -538,7 +538,7 @@ _Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv)
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
// XXX _PyRuntime.orig_argv only gets cleared by Py_Main(),
- // so it it currently leaks for embedders.
+ // so it currently leaks for embedders.
res = _PyWideStringList_Copy(&_PyRuntime.orig_argv, &argv_list);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
diff --git a/Python/instrumentation.c b/Python/instrumentation.c
index e144272fe2b82e..e29748f0ad9872 100644
--- a/Python/instrumentation.c
+++ b/Python/instrumentation.c
@@ -1,15 +1,14 @@
-
-
#include "Python.h"
#include "pycore_call.h"
#include "pycore_frame.h"
#include "pycore_interp.h"
#include "pycore_long.h"
+#include "pycore_modsupport.h" // _PyModule_CreateInitialized()
#include "pycore_namespace.h"
#include "pycore_object.h"
#include "pycore_opcode.h"
#include "pycore_pyerrors.h"
-#include "pycore_pystate.h"
+#include "pycore_pystate.h" // _PyInterpreterState_GET()
/* Uncomment this to dump debugging output when assertions fail */
// #define INSTRUMENT_DEBUG 1
@@ -390,7 +389,7 @@ dump_instrumentation_data(PyCodeObject *code, int star, FILE*out)
fprintf(out, "NULL\n");
return;
}
- dump_monitors("Global", PyInterpreterState_Get()->monitors, out);
+ dump_monitors("Global", _PyInterpreterState_GET()->monitors, out);
dump_monitors("Code", data->local_monitors, out);
dump_monitors("Active", data->active_monitors, out);
int code_len = (int)Py_SIZE(code);
@@ -449,7 +448,7 @@ sanity_check_instrumentation(PyCodeObject *code)
if (data == NULL) {
return;
}
- _Py_Monitors active_monitors = PyInterpreterState_Get()->monitors;
+ _Py_Monitors active_monitors = _PyInterpreterState_GET()->monitors;
if (code->_co_monitoring) {
_Py_Monitors local_monitors = code->_co_monitoring->local_monitors;
active_monitors = monitors_or(active_monitors, local_monitors);
@@ -740,7 +739,7 @@ remove_tools(PyCodeObject * code, int offset, int event, int tools)
static bool
tools_is_subset_for_event(PyCodeObject * code, int event, int tools)
{
- int global_tools = PyInterpreterState_Get()->monitors.tools[event];
+ int global_tools = _PyInterpreterState_GET()->monitors.tools[event];
int local_tools = code->_co_monitoring->local_monitors.tools[event];
return tools == ((global_tools | local_tools) & tools);
}
@@ -903,26 +902,34 @@ instrumentation_cross_checks(PyInterpreterState *interp, PyCodeObject *code)
#endif
static inline uint8_t
-get_tools_for_instruction(PyCodeObject * code, int i, int event)
+get_tools_for_instruction(PyCodeObject *code, PyInterpreterState *interp, int i, int event)
{
uint8_t tools;
assert(event != PY_MONITORING_EVENT_LINE);
assert(event != PY_MONITORING_EVENT_INSTRUCTION);
- assert(instrumentation_cross_checks(PyThreadState_GET()->interp, code));
- _PyCoMonitoringData *monitoring = code->_co_monitoring;
if (event >= PY_MONITORING_UNGROUPED_EVENTS) {
assert(event == PY_MONITORING_EVENT_C_RAISE ||
event == PY_MONITORING_EVENT_C_RETURN);
event = PY_MONITORING_EVENT_CALL;
}
- if (event < PY_MONITORING_INSTRUMENTED_EVENTS && monitoring->tools) {
- tools = monitoring->tools[i];
+ if (event < PY_MONITORING_INSTRUMENTED_EVENTS) {
+ CHECK(is_version_up_to_date(code, interp));
+ CHECK(instrumentation_cross_checks(interp, code));
+ if (code->_co_monitoring->tools) {
+ tools = code->_co_monitoring->tools[i];
+ }
+ else {
+ tools = code->_co_monitoring->active_monitors.tools[event];
+ }
}
else {
- tools = code->_co_monitoring->active_monitors.tools[event];
+ if (code->_co_monitoring) {
+ tools = code->_co_monitoring->active_monitors.tools[event];
+ }
+ else {
+ tools = interp->monitors.tools[event];
+ }
}
- CHECK(tools_is_subset_for_event(code, event, tools));
- CHECK((tools & code->_co_monitoring->active_monitors.tools[event]) == tools);
return tools;
}
@@ -936,10 +943,7 @@ call_instrumentation_vector(
}
assert(!_PyErr_Occurred(tstate));
assert(args[0] == NULL);
- PyCodeObject *code = frame->f_code;
- assert(code->_co_instrumentation_version == tstate->interp->monitoring_version);
- assert(is_version_up_to_date(code, tstate->interp));
- assert(instrumentation_cross_checks(tstate->interp, code));
+ PyCodeObject *code = _PyFrame_GetCode(frame);
assert(args[1] == NULL);
args[1] = (PyObject *)code;
int offset = (int)(instr - _PyCode_CODE(code));
@@ -952,11 +956,11 @@ call_instrumentation_vector(
}
assert(args[2] == NULL);
args[2] = offset_obj;
- uint8_t tools = get_tools_for_instruction(code, offset, event);
+ PyInterpreterState *interp = tstate->interp;
+ uint8_t tools = get_tools_for_instruction(code, interp, offset, event);
Py_ssize_t nargsf = nargs | PY_VECTORCALL_ARGUMENTS_OFFSET;
PyObject **callargs = &args[1];
int err = 0;
- PyInterpreterState *interp = tstate->interp;
while (tools) {
int tool = most_significant_bit(tools);
assert(tool >= 0 && tool < 8);
@@ -1017,7 +1021,7 @@ _Py_call_instrumentation_jump(
assert(frame->prev_instr == instr);
/* Event should occur after the jump */
frame->prev_instr = target;
- PyCodeObject *code = frame->f_code;
+ PyCodeObject *code = _PyFrame_GetCode(frame);
int to = (int)(target - _PyCode_CODE(code));
PyObject *to_obj = PyLong_FromLong(to * (int)sizeof(_Py_CODEUNIT));
if (to_obj == NULL) {
@@ -1094,7 +1098,7 @@ int
_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)
{
frame->prev_instr = instr;
- PyCodeObject *code = frame->f_code;
+ PyCodeObject *code = _PyFrame_GetCode(frame);
assert(is_version_up_to_date(code, tstate->interp));
assert(instrumentation_cross_checks(tstate->interp, code));
int i = (int)(instr - _PyCode_CODE(code));
@@ -1162,7 +1166,7 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame,
int
_Py_call_instrumentation_instruction(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr)
{
- PyCodeObject *code = frame->f_code;
+ PyCodeObject *code = _PyFrame_GetCode(frame);
assert(is_version_up_to_date(code, tstate->interp));
assert(instrumentation_cross_checks(tstate->interp, code));
int offset = (int)(instr - _PyCode_CODE(code));
@@ -1214,7 +1218,7 @@ _Py_call_instrumentation_instruction(PyThreadState *tstate, _PyInterpreterFrame*
PyObject *
_PyMonitoring_RegisterCallback(int tool_id, int event_id, PyObject *obj)
{
- PyInterpreterState *is = _PyInterpreterState_Get();
+ PyInterpreterState *is = _PyInterpreterState_GET();
assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);
assert(0 <= event_id && event_id < PY_MONITORING_EVENTS);
PyObject *callback = is->monitoring_callables[tool_id][event_id];
@@ -1526,7 +1530,7 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp)
return 0;
}
/* Insert instrumentation */
- for (int i = 0; i < code_len; i+= _PyInstruction_GetLength(code, i)) {
+ for (int i = code->_co_firsttraceable; i < code_len; i+= _PyInstruction_GetLength(code, i)) {
_Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];
CHECK(instr->op.code != 0);
int base_opcode = _Py_GetBaseOpcode(code, i);
@@ -1632,7 +1636,7 @@ instrument_all_executing_code_objects(PyInterpreterState *interp) {
_PyInterpreterFrame *frame = ts->cframe->current_frame;
while (frame) {
if (frame->owner != FRAME_OWNED_BY_CSTACK) {
- if (_Py_Instrument(frame->f_code, interp)) {
+ if (_Py_Instrument(_PyFrame_GetCode(frame), interp)) {
return -1;
}
}
@@ -1673,7 +1677,7 @@ int
_PyMonitoring_SetEvents(int tool_id, _PyMonitoringEventSet events)
{
assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
assert(events < (1 << PY_MONITORING_UNGROUPED_EVENTS));
if (check_tool(interp, tool_id)) {
return -1;
@@ -1691,7 +1695,7 @@ int
_PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEventSet events)
{
assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
assert(events < (1 << PY_MONITORING_UNGROUPED_EVENTS));
if (check_tool(interp, tool_id)) {
return -1;
@@ -1753,7 +1757,7 @@ monitoring_use_tool_id_impl(PyObject *module, int tool_id, PyObject *name)
PyErr_SetString(PyExc_ValueError, "tool name must be a str");
return NULL;
}
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
if (interp->monitoring_tool_names[tool_id] != NULL) {
PyErr_Format(PyExc_ValueError, "tool %d is already in use", tool_id);
return NULL;
@@ -1777,7 +1781,7 @@ monitoring_free_tool_id_impl(PyObject *module, int tool_id)
if (check_valid_tool(tool_id)) {
return NULL;
}
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
Py_CLEAR(interp->monitoring_tool_names[tool_id]);
Py_RETURN_NONE;
}
@@ -1799,7 +1803,7 @@ monitoring_get_tool_impl(PyObject *module, int tool_id)
if (check_valid_tool(tool_id)) {
return NULL;
}
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
PyObject *name = interp->monitoring_tool_names[tool_id];
if (name == NULL) {
Py_RETURN_NONE;
@@ -1860,7 +1864,7 @@ monitoring_get_events_impl(PyObject *module, int tool_id)
if (check_valid_tool(tool_id)) {
return -1;
}
- _Py_Monitors *m = &_PyInterpreterState_Get()->monitors;
+ _Py_Monitors *m = &_PyInterpreterState_GET()->monitors;
_PyMonitoringEventSet event_set = get_events(m, tool_id);
return event_set;
}
@@ -1985,7 +1989,7 @@ monitoring_restart_events_impl(PyObject *module)
* last restart version > instrumented version for all code objects
* last restart version < current version
*/
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
interp->last_restart_version = interp->monitoring_version + 1;
interp->monitoring_version = interp->last_restart_version + 1;
if (instrument_all_executing_code_objects(interp)) {
@@ -2033,7 +2037,7 @@ static PyObject *
monitoring__all_events_impl(PyObject *module)
/*[clinic end generated code: output=6b7581e2dbb690f6 input=62ee9672c17b7f0e]*/
{
- PyInterpreterState *interp = _PyInterpreterState_Get();
+ PyInterpreterState *interp = _PyInterpreterState_GET();
PyObject *res = PyDict_New();
if (res == NULL) {
return NULL;
diff --git a/Python/intrinsics.c b/Python/intrinsics.c
index e34a856d2f3587..037b74ca820fab 100644
--- a/Python/intrinsics.c
+++ b/Python/intrinsics.c
@@ -40,11 +40,11 @@ import_all_from(PyThreadState *tstate, PyObject *locals, PyObject *v)
int skip_leading_underscores = 0;
int pos, err;
- if (_PyObject_LookupAttr(v, &_Py_ID(__all__), &all) < 0) {
+ if (PyObject_GetOptionalAttr(v, &_Py_ID(__all__), &all) < 0) {
return -1; /* Unexpected error */
}
if (all == NULL) {
- if (_PyObject_LookupAttr(v, &_Py_ID(__dict__), &dict) < 0) {
+ if (PyObject_GetOptionalAttr(v, &_Py_ID(__dict__), &dict) < 0) {
return -1;
}
if (dict == NULL) {
@@ -148,14 +148,14 @@ stopiteration_error(PyThreadState* tstate, PyObject *exc)
const char *msg = NULL;
if (PyErr_GivenExceptionMatches(exc, PyExc_StopIteration)) {
msg = "generator raised StopIteration";
- if (frame->f_code->co_flags & CO_ASYNC_GENERATOR) {
+ if (_PyFrame_GetCode(frame)->co_flags & CO_ASYNC_GENERATOR) {
msg = "async generator raised StopIteration";
}
- else if (frame->f_code->co_flags & CO_COROUTINE) {
+ else if (_PyFrame_GetCode(frame)->co_flags & CO_COROUTINE) {
msg = "coroutine raised StopIteration";
}
}
- else if ((frame->f_code->co_flags & CO_ASYNC_GENERATOR) &&
+ else if ((_PyFrame_GetCode(frame)->co_flags & CO_ASYNC_GENERATOR) &&
PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration))
{
/* code in `gen` raised a StopAsyncIteration error:
diff --git a/Python/legacy_tracing.c b/Python/legacy_tracing.c
index 5143b79b0864d8..9cc48fc9493a05 100644
--- a/Python/legacy_tracing.c
+++ b/Python/legacy_tracing.c
@@ -244,7 +244,7 @@ sys_trace_line_func(
"Missing frame when calling trace function.");
return NULL;
}
- assert(args[0] == (PyObject *)frame->f_frame->f_code);
+ assert(args[0] == (PyObject *)_PyFrame_GetCode(frame->f_frame));
return trace_line(tstate, self, frame, line);
}
@@ -286,7 +286,6 @@ sys_trace_jump_func(
"Missing frame when calling trace function.");
return NULL;
}
- assert(code == frame->f_frame->f_code);
if (!frame->f_trace_lines) {
Py_RETURN_NONE;
}
diff --git a/Python/makeopcodetargets.py b/Python/makeopcodetargets.py
index 2b402ae0b6a031..5843079b729936 100755
--- a/Python/makeopcodetargets.py
+++ b/Python/makeopcodetargets.py
@@ -25,12 +25,13 @@ def write_contents(f):
"""Write C code contents to the target file object.
"""
opcode = find_module('opcode')
+ _opcode_metadata = find_module('_opcode_metadata')
targets = ['_unknown_opcode'] * 256
for opname, op in opcode.opmap.items():
if not opcode.is_pseudo(op):
targets[op] = "TARGET_%s" % opname
next_op = 1
- for opname in opcode._specialized_instructions:
+ for opname in _opcode_metadata._specialized_instructions:
while targets[next_op] != '_unknown_opcode':
next_op += 1
targets[next_op] = "TARGET_%s" % opname
diff --git a/Python/marshal.c b/Python/marshal.c
index 352976b1d69f04..517220a4463cf3 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -6,8 +6,6 @@
Version 3 of this protocol properly supports circular links
and sharing. */
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_code.h" // _PyCode_New()
@@ -751,23 +749,28 @@ r_string(Py_ssize_t n, RFILE *p)
static int
r_byte(RFILE *p)
{
- int c = EOF;
-
if (p->ptr != NULL) {
- if (p->ptr < p->end)
- c = (unsigned char) *p->ptr++;
- return c;
+ if (p->ptr < p->end) {
+ return (unsigned char) *p->ptr++;
+ }
}
- if (!p->readable) {
+ else if (!p->readable) {
assert(p->fp);
- c = getc(p->fp);
+ int c = getc(p->fp);
+ if (c != EOF) {
+ return c;
+ }
}
else {
const char *ptr = r_string(1, p);
- if (ptr != NULL)
- c = *(const unsigned char *) ptr;
+ if (ptr != NULL) {
+ return *(const unsigned char *) ptr;
+ }
+ return EOF;
}
- return c;
+ PyErr_SetString(PyExc_EOFError,
+ "EOF read where not expected");
+ return EOF;
}
static int
@@ -828,10 +831,11 @@ r_PyLong(RFILE *p)
digit d;
n = r_long(p);
- if (PyErr_Occurred())
- return NULL;
if (n == 0)
return (PyObject *)_PyLong_New(0);
+ if (n == -1 && PyErr_Occurred()) {
+ return NULL;
+ }
if (n < -SIZE32_MAX || n > SIZE32_MAX) {
PyErr_SetString(PyExc_ValueError,
"bad marshal data (long size out of range)");
@@ -850,10 +854,6 @@ r_PyLong(RFILE *p)
d = 0;
for (j=0; j < PyLong_MARSHAL_RATIO; j++) {
md = r_short(p);
- if (PyErr_Occurred()) {
- Py_DECREF(ob);
- return NULL;
- }
if (md < 0 || md > PyLong_MARSHAL_BASE)
goto bad_digit;
d += (digit)md << j*PyLong_MARSHAL_SHIFT;
@@ -864,10 +864,6 @@ r_PyLong(RFILE *p)
d = 0;
for (j=0; j < shorts_in_top_digit; j++) {
md = r_short(p);
- if (PyErr_Occurred()) {
- Py_DECREF(ob);
- return NULL;
- }
if (md < 0 || md > PyLong_MARSHAL_BASE)
goto bad_digit;
/* topmost marshal digit should be nonzero */
@@ -879,18 +875,17 @@ r_PyLong(RFILE *p)
}
d += (digit)md << j*PyLong_MARSHAL_SHIFT;
}
- if (PyErr_Occurred()) {
- Py_DECREF(ob);
- return NULL;
- }
+ assert(!PyErr_Occurred());
/* top digit should be nonzero, else the resulting PyLong won't be
normalized */
ob->long_value.ob_digit[size-1] = d;
return (PyObject *)ob;
bad_digit:
Py_DECREF(ob);
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (digit out of range in long)");
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_ValueError,
+ "bad marshal data (digit out of range in long)");
+ }
return NULL;
}
@@ -913,8 +908,6 @@ r_float_str(RFILE *p)
const char *ptr;
n = r_byte(p);
if (n == EOF) {
- PyErr_SetString(PyExc_EOFError,
- "EOF read where object expected");
return -1;
}
ptr = r_string(n, p);
@@ -992,8 +985,10 @@ r_object(RFILE *p)
PyObject *retval = NULL;
if (code == EOF) {
- PyErr_SetString(PyExc_EOFError,
- "EOF read where object expected");
+ if (PyErr_ExceptionMatches(PyExc_EOFError)) {
+ PyErr_SetString(PyExc_EOFError,
+ "EOF read where object expected");
+ }
return NULL;
}
@@ -1040,7 +1035,10 @@ r_object(RFILE *p)
case TYPE_INT:
n = r_long(p);
- retval = PyErr_Occurred() ? NULL : PyLong_FromLong(n);
+ if (n == -1 && PyErr_Occurred()) {
+ break;
+ }
+ retval = PyLong_FromLong(n);
R_REF(retval);
break;
@@ -1106,10 +1104,11 @@ r_object(RFILE *p)
{
const char *ptr;
n = r_long(p);
- if (PyErr_Occurred())
- break;
if (n < 0 || n > SIZE32_MAX) {
- PyErr_SetString(PyExc_ValueError, "bad marshal data (bytes object size out of range)");
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_ValueError,
+ "bad marshal data (bytes object size out of range)");
+ }
break;
}
v = PyBytes_FromStringAndSize((char *)NULL, n);
@@ -1131,10 +1130,11 @@ r_object(RFILE *p)
/* fall through */
case TYPE_ASCII:
n = r_long(p);
- if (PyErr_Occurred())
- break;
if (n < 0 || n > SIZE32_MAX) {
- PyErr_SetString(PyExc_ValueError, "bad marshal data (string size out of range)");
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_ValueError,
+ "bad marshal data (string size out of range)");
+ }
break;
}
goto _read_ascii;
@@ -1145,8 +1145,6 @@ r_object(RFILE *p)
case TYPE_SHORT_ASCII:
n = r_byte(p);
if (n == EOF) {
- PyErr_SetString(PyExc_EOFError,
- "EOF read where object expected");
break;
}
_read_ascii:
@@ -1173,10 +1171,11 @@ r_object(RFILE *p)
const char *buffer;
n = r_long(p);
- if (PyErr_Occurred())
- break;
if (n < 0 || n > SIZE32_MAX) {
- PyErr_SetString(PyExc_ValueError, "bad marshal data (string size out of range)");
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_ValueError,
+ "bad marshal data (string size out of range)");
+ }
break;
}
if (n != 0) {
@@ -1198,16 +1197,18 @@ r_object(RFILE *p)
}
case TYPE_SMALL_TUPLE:
- n = (unsigned char) r_byte(p);
- if (PyErr_Occurred())
+ n = r_byte(p);
+ if (n == EOF) {
break;
+ }
goto _read_tuple;
case TYPE_TUPLE:
n = r_long(p);
- if (PyErr_Occurred())
- break;
if (n < 0 || n > SIZE32_MAX) {
- PyErr_SetString(PyExc_ValueError, "bad marshal data (tuple size out of range)");
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_ValueError,
+ "bad marshal data (tuple size out of range)");
+ }
break;
}
_read_tuple:
@@ -1232,10 +1233,11 @@ r_object(RFILE *p)
case TYPE_LIST:
n = r_long(p);
- if (PyErr_Occurred())
- break;
if (n < 0 || n > SIZE32_MAX) {
- PyErr_SetString(PyExc_ValueError, "bad marshal data (list size out of range)");
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_ValueError,
+ "bad marshal data (list size out of range)");
+ }
break;
}
v = PyList_New(n);
@@ -1288,10 +1290,11 @@ r_object(RFILE *p)
case TYPE_SET:
case TYPE_FROZENSET:
n = r_long(p);
- if (PyErr_Occurred())
- break;
if (n < 0 || n > SIZE32_MAX) {
- PyErr_SetString(PyExc_ValueError, "bad marshal data (set size out of range)");
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_ValueError,
+ "bad marshal data (set size out of range)");
+ }
break;
}
@@ -1368,20 +1371,20 @@ r_object(RFILE *p)
/* XXX ignore long->int overflows for now */
argcount = (int)r_long(p);
- if (PyErr_Occurred())
+ if (argcount == -1 && PyErr_Occurred())
goto code_error;
posonlyargcount = (int)r_long(p);
- if (PyErr_Occurred()) {
+ if (posonlyargcount == -1 && PyErr_Occurred()) {
goto code_error;
}
kwonlyargcount = (int)r_long(p);
- if (PyErr_Occurred())
+ if (kwonlyargcount == -1 && PyErr_Occurred())
goto code_error;
stacksize = (int)r_long(p);
- if (PyErr_Occurred())
+ if (stacksize == -1 && PyErr_Occurred())
goto code_error;
flags = (int)r_long(p);
- if (PyErr_Occurred())
+ if (flags == -1 && PyErr_Occurred())
goto code_error;
code = r_object(p);
if (code == NULL)
@@ -1454,6 +1457,10 @@ r_object(RFILE *p)
v = r_ref_insert(v, idx, flag, p);
code_error:
+ if (v == NULL && !PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError,
+ "NULL object in marshal data for code object");
+ }
Py_XDECREF(code);
Py_XDECREF(consts);
Py_XDECREF(names);
@@ -1471,9 +1478,10 @@ r_object(RFILE *p)
case TYPE_REF:
n = r_long(p);
if (n < 0 || n >= PyList_GET_SIZE(p->refs)) {
- if (n == -1 && PyErr_Occurred())
- break;
- PyErr_SetString(PyExc_ValueError, "bad marshal data (invalid reference)");
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_ValueError,
+ "bad marshal data (invalid reference)");
+ }
break;
}
v = PyList_GET_ITEM(p->refs, n);
@@ -1707,7 +1715,7 @@ marshal_dump_impl(PyObject *module, PyObject *value, PyObject *file,
s = PyMarshal_WriteObjectToString(value, version);
if (s == NULL)
return NULL;
- res = _PyObject_CallMethodOneArg(file, &_Py_ID(write), s);
+ res = PyObject_CallMethodOneArg(file, &_Py_ID(write), s);
Py_DECREF(s);
return res;
}
diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h
deleted file mode 100644
index 2c4d1aac115d51..00000000000000
--- a/Python/opcode_metadata.h
+++ /dev/null
@@ -1,996 +0,0 @@
-// This file is generated by Tools/cases_generator/generate_cases.py
-// from:
-// Python/bytecodes.c
-// Do not edit!
-
-#ifndef NEED_OPCODE_METADATA
-extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
-#else
-int
-_PyOpcode_num_popped(int opcode, int oparg, bool jump) {
- switch(opcode) {
- case NOP:
- return 0;
- case RESUME:
- return 0;
- case INSTRUMENTED_RESUME:
- return 0;
- case LOAD_CLOSURE:
- return 0;
- case LOAD_FAST_CHECK:
- return 0;
- case LOAD_FAST:
- return 0;
- case LOAD_FAST_AND_CLEAR:
- return 0;
- case LOAD_FAST_LOAD_FAST:
- return 0;
- case LOAD_CONST:
- return 0;
- case STORE_FAST:
- return 1;
- case STORE_FAST_LOAD_FAST:
- return 1;
- case STORE_FAST_STORE_FAST:
- return 2;
- case POP_TOP:
- return 1;
- case PUSH_NULL:
- return 0;
- case END_FOR:
- return 2;
- case INSTRUMENTED_END_FOR:
- return 2;
- case END_SEND:
- return 2;
- case INSTRUMENTED_END_SEND:
- return 2;
- case UNARY_NEGATIVE:
- return 1;
- case UNARY_NOT:
- return 1;
- case UNARY_INVERT:
- return 1;
- case BINARY_OP_MULTIPLY_INT:
- return 2;
- case BINARY_OP_ADD_INT:
- return 2;
- case BINARY_OP_SUBTRACT_INT:
- return 2;
- case BINARY_OP_MULTIPLY_FLOAT:
- return 2;
- case BINARY_OP_ADD_FLOAT:
- return 2;
- case BINARY_OP_SUBTRACT_FLOAT:
- return 2;
- case BINARY_OP_ADD_UNICODE:
- return 2;
- case BINARY_OP_INPLACE_ADD_UNICODE:
- return 2;
- case BINARY_SUBSCR:
- return 2;
- case BINARY_SLICE:
- return 3;
- case STORE_SLICE:
- return 4;
- case BINARY_SUBSCR_LIST_INT:
- return 2;
- case BINARY_SUBSCR_TUPLE_INT:
- return 2;
- case BINARY_SUBSCR_DICT:
- return 2;
- case BINARY_SUBSCR_GETITEM:
- return 2;
- case LIST_APPEND:
- return (oparg-1) + 2;
- case SET_ADD:
- return (oparg-1) + 2;
- case STORE_SUBSCR:
- return 3;
- case STORE_SUBSCR_LIST_INT:
- return 3;
- case STORE_SUBSCR_DICT:
- return 3;
- case DELETE_SUBSCR:
- return 2;
- case CALL_INTRINSIC_1:
- return 1;
- case CALL_INTRINSIC_2:
- return 2;
- case RAISE_VARARGS:
- return oparg;
- case INTERPRETER_EXIT:
- return 1;
- case RETURN_VALUE:
- return 1;
- case INSTRUMENTED_RETURN_VALUE:
- return 1;
- case RETURN_CONST:
- return 0;
- case INSTRUMENTED_RETURN_CONST:
- return 0;
- case GET_AITER:
- return 1;
- case GET_ANEXT:
- return 1;
- case GET_AWAITABLE:
- return 1;
- case SEND:
- return 2;
- case SEND_GEN:
- return 2;
- case INSTRUMENTED_YIELD_VALUE:
- return 1;
- case YIELD_VALUE:
- return 1;
- case POP_EXCEPT:
- return 1;
- case RERAISE:
- return oparg + 1;
- case END_ASYNC_FOR:
- return 2;
- case CLEANUP_THROW:
- return 3;
- case LOAD_ASSERTION_ERROR:
- return 0;
- case LOAD_BUILD_CLASS:
- return 0;
- case STORE_NAME:
- return 1;
- case DELETE_NAME:
- return 0;
- case UNPACK_SEQUENCE:
- return 1;
- case UNPACK_SEQUENCE_TWO_TUPLE:
- return 1;
- case UNPACK_SEQUENCE_TUPLE:
- return 1;
- case UNPACK_SEQUENCE_LIST:
- return 1;
- case UNPACK_EX:
- return 1;
- case STORE_ATTR:
- return 2;
- case DELETE_ATTR:
- return 1;
- case STORE_GLOBAL:
- return 1;
- case DELETE_GLOBAL:
- return 0;
- case LOAD_LOCALS:
- return 0;
- case LOAD_NAME:
- return 0;
- case LOAD_FROM_DICT_OR_GLOBALS:
- return 1;
- case LOAD_GLOBAL:
- return 0;
- case LOAD_GLOBAL_MODULE:
- return 0;
- case LOAD_GLOBAL_BUILTIN:
- return 0;
- case DELETE_FAST:
- return 0;
- case MAKE_CELL:
- return 0;
- case DELETE_DEREF:
- return 0;
- case LOAD_FROM_DICT_OR_DEREF:
- return 1;
- case LOAD_DEREF:
- return 0;
- case STORE_DEREF:
- return 1;
- case COPY_FREE_VARS:
- return 0;
- case BUILD_STRING:
- return oparg;
- case BUILD_TUPLE:
- return oparg;
- case BUILD_LIST:
- return oparg;
- case LIST_EXTEND:
- return (oparg-1) + 2;
- case SET_UPDATE:
- return (oparg-1) + 2;
- case BUILD_SET:
- return oparg;
- case BUILD_MAP:
- return oparg*2;
- case SETUP_ANNOTATIONS:
- return 0;
- case BUILD_CONST_KEY_MAP:
- return oparg + 1;
- case DICT_UPDATE:
- return 1;
- case DICT_MERGE:
- return 1;
- case MAP_ADD:
- return 2;
- case INSTRUMENTED_LOAD_SUPER_ATTR:
- return 3;
- case LOAD_SUPER_ATTR:
- return 3;
- case LOAD_SUPER_ATTR_ATTR:
- return 3;
- case LOAD_SUPER_ATTR_METHOD:
- return 3;
- case LOAD_ATTR:
- return 1;
- case LOAD_ATTR_INSTANCE_VALUE:
- return 1;
- case LOAD_ATTR_MODULE:
- return 1;
- case LOAD_ATTR_WITH_HINT:
- return 1;
- case LOAD_ATTR_SLOT:
- return 1;
- case LOAD_ATTR_CLASS:
- return 1;
- case LOAD_ATTR_PROPERTY:
- return 1;
- case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN:
- return 1;
- case STORE_ATTR_INSTANCE_VALUE:
- return 2;
- case STORE_ATTR_WITH_HINT:
- return 2;
- case STORE_ATTR_SLOT:
- return 2;
- case COMPARE_OP:
- return 2;
- case COMPARE_OP_FLOAT:
- return 2;
- case COMPARE_OP_INT:
- return 2;
- case COMPARE_OP_STR:
- return 2;
- case IS_OP:
- return 2;
- case CONTAINS_OP:
- return 2;
- case CHECK_EG_MATCH:
- return 2;
- case CHECK_EXC_MATCH:
- return 2;
- case IMPORT_NAME:
- return 2;
- case IMPORT_FROM:
- return 1;
- case JUMP_FORWARD:
- return 0;
- case JUMP_BACKWARD:
- return 0;
- case ENTER_EXECUTOR:
- return 0;
- case POP_JUMP_IF_FALSE:
- return 1;
- case POP_JUMP_IF_TRUE:
- return 1;
- case POP_JUMP_IF_NOT_NONE:
- return 1;
- case POP_JUMP_IF_NONE:
- return 1;
- case JUMP_BACKWARD_NO_INTERRUPT:
- return 0;
- case GET_LEN:
- return 1;
- case MATCH_CLASS:
- return 3;
- case MATCH_MAPPING:
- return 1;
- case MATCH_SEQUENCE:
- return 1;
- case MATCH_KEYS:
- return 2;
- case GET_ITER:
- return 1;
- case GET_YIELD_FROM_ITER:
- return 1;
- case FOR_ITER:
- return 1;
- case INSTRUMENTED_FOR_ITER:
- return 0;
- case FOR_ITER_LIST:
- return 1;
- case FOR_ITER_TUPLE:
- return 1;
- case FOR_ITER_RANGE:
- return 1;
- case FOR_ITER_GEN:
- return 1;
- case BEFORE_ASYNC_WITH:
- return 1;
- case BEFORE_WITH:
- return 1;
- case WITH_EXCEPT_START:
- return 4;
- case PUSH_EXC_INFO:
- return 1;
- case LOAD_ATTR_METHOD_WITH_VALUES:
- return 1;
- case LOAD_ATTR_METHOD_NO_DICT:
- return 1;
- case LOAD_ATTR_METHOD_LAZY_DICT:
- return 1;
- case KW_NAMES:
- return 0;
- case INSTRUMENTED_CALL:
- return 0;
- case CALL:
- return oparg + 2;
- case CALL_BOUND_METHOD_EXACT_ARGS:
- return oparg + 2;
- case CALL_PY_EXACT_ARGS:
- return oparg + 2;
- case CALL_PY_WITH_DEFAULTS:
- return oparg + 2;
- case CALL_NO_KW_TYPE_1:
- return oparg + 2;
- case CALL_NO_KW_STR_1:
- return oparg + 2;
- case CALL_NO_KW_TUPLE_1:
- return oparg + 2;
- case CALL_BUILTIN_CLASS:
- return oparg + 2;
- case CALL_NO_KW_BUILTIN_O:
- return oparg + 2;
- case CALL_NO_KW_BUILTIN_FAST:
- return oparg + 2;
- case CALL_BUILTIN_FAST_WITH_KEYWORDS:
- return oparg + 2;
- case CALL_NO_KW_LEN:
- return oparg + 2;
- case CALL_NO_KW_ISINSTANCE:
- return oparg + 2;
- case CALL_NO_KW_LIST_APPEND:
- return oparg + 2;
- case CALL_NO_KW_METHOD_DESCRIPTOR_O:
- return oparg + 2;
- case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS:
- return oparg + 2;
- case CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS:
- return oparg + 2;
- case CALL_NO_KW_METHOD_DESCRIPTOR_FAST:
- return oparg + 2;
- case INSTRUMENTED_CALL_FUNCTION_EX:
- return 0;
- case CALL_FUNCTION_EX:
- return ((oparg & 1) ? 1 : 0) + 3;
- case MAKE_FUNCTION:
- return ((oparg & MAKE_FUNCTION_DEFAULTS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_KWDEFAULTS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_ANNOTATIONS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_CLOSURE) ? 1 : 0) + 1;
- case RETURN_GENERATOR:
- return 0;
- case BUILD_SLICE:
- return ((oparg == 3) ? 1 : 0) + 2;
- case FORMAT_VALUE:
- return (((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0) + 1;
- case COPY:
- return (oparg-1) + 1;
- case BINARY_OP:
- return 2;
- case SWAP:
- return (oparg-2) + 2;
- case INSTRUMENTED_INSTRUCTION:
- return 0;
- case INSTRUMENTED_JUMP_FORWARD:
- return 0;
- case INSTRUMENTED_JUMP_BACKWARD:
- return 0;
- case INSTRUMENTED_POP_JUMP_IF_TRUE:
- return 0;
- case INSTRUMENTED_POP_JUMP_IF_FALSE:
- return 0;
- case INSTRUMENTED_POP_JUMP_IF_NONE:
- return 0;
- case INSTRUMENTED_POP_JUMP_IF_NOT_NONE:
- return 0;
- case EXTENDED_ARG:
- return 0;
- case CACHE:
- return 0;
- case RESERVED:
- return 0;
- default:
- return -1;
- }
-}
-#endif
-
-#ifndef NEED_OPCODE_METADATA
-extern int _PyOpcode_num_pushed(int opcode, int oparg, bool jump);
-#else
-int
-_PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
- switch(opcode) {
- case NOP:
- return 0;
- case RESUME:
- return 0;
- case INSTRUMENTED_RESUME:
- return 0;
- case LOAD_CLOSURE:
- return 1;
- case LOAD_FAST_CHECK:
- return 1;
- case LOAD_FAST:
- return 1;
- case LOAD_FAST_AND_CLEAR:
- return 1;
- case LOAD_FAST_LOAD_FAST:
- return 2;
- case LOAD_CONST:
- return 1;
- case STORE_FAST:
- return 0;
- case STORE_FAST_LOAD_FAST:
- return 1;
- case STORE_FAST_STORE_FAST:
- return 0;
- case POP_TOP:
- return 0;
- case PUSH_NULL:
- return 1;
- case END_FOR:
- return 0;
- case INSTRUMENTED_END_FOR:
- return 0;
- case END_SEND:
- return 1;
- case INSTRUMENTED_END_SEND:
- return 1;
- case UNARY_NEGATIVE:
- return 1;
- case UNARY_NOT:
- return 1;
- case UNARY_INVERT:
- return 1;
- case BINARY_OP_MULTIPLY_INT:
- return 1;
- case BINARY_OP_ADD_INT:
- return 1;
- case BINARY_OP_SUBTRACT_INT:
- return 1;
- case BINARY_OP_MULTIPLY_FLOAT:
- return 1;
- case BINARY_OP_ADD_FLOAT:
- return 1;
- case BINARY_OP_SUBTRACT_FLOAT:
- return 1;
- case BINARY_OP_ADD_UNICODE:
- return 1;
- case BINARY_OP_INPLACE_ADD_UNICODE:
- return 0;
- case BINARY_SUBSCR:
- return 1;
- case BINARY_SLICE:
- return 1;
- case STORE_SLICE:
- return 0;
- case BINARY_SUBSCR_LIST_INT:
- return 1;
- case BINARY_SUBSCR_TUPLE_INT:
- return 1;
- case BINARY_SUBSCR_DICT:
- return 1;
- case BINARY_SUBSCR_GETITEM:
- return 1;
- case LIST_APPEND:
- return (oparg-1) + 1;
- case SET_ADD:
- return (oparg-1) + 1;
- case STORE_SUBSCR:
- return 0;
- case STORE_SUBSCR_LIST_INT:
- return 0;
- case STORE_SUBSCR_DICT:
- return 0;
- case DELETE_SUBSCR:
- return 0;
- case CALL_INTRINSIC_1:
- return 1;
- case CALL_INTRINSIC_2:
- return 1;
- case RAISE_VARARGS:
- return 0;
- case INTERPRETER_EXIT:
- return 0;
- case RETURN_VALUE:
- return 0;
- case INSTRUMENTED_RETURN_VALUE:
- return 0;
- case RETURN_CONST:
- return 0;
- case INSTRUMENTED_RETURN_CONST:
- return 0;
- case GET_AITER:
- return 1;
- case GET_ANEXT:
- return 2;
- case GET_AWAITABLE:
- return 1;
- case SEND:
- return 2;
- case SEND_GEN:
- return 2;
- case INSTRUMENTED_YIELD_VALUE:
- return 1;
- case YIELD_VALUE:
- return 1;
- case POP_EXCEPT:
- return 0;
- case RERAISE:
- return oparg;
- case END_ASYNC_FOR:
- return 0;
- case CLEANUP_THROW:
- return 2;
- case LOAD_ASSERTION_ERROR:
- return 1;
- case LOAD_BUILD_CLASS:
- return 1;
- case STORE_NAME:
- return 0;
- case DELETE_NAME:
- return 0;
- case UNPACK_SEQUENCE:
- return oparg;
- case UNPACK_SEQUENCE_TWO_TUPLE:
- return oparg;
- case UNPACK_SEQUENCE_TUPLE:
- return oparg;
- case UNPACK_SEQUENCE_LIST:
- return oparg;
- case UNPACK_EX:
- return (oparg & 0xFF) + (oparg >> 8) + 1;
- case STORE_ATTR:
- return 0;
- case DELETE_ATTR:
- return 0;
- case STORE_GLOBAL:
- return 0;
- case DELETE_GLOBAL:
- return 0;
- case LOAD_LOCALS:
- return 1;
- case LOAD_NAME:
- return 1;
- case LOAD_FROM_DICT_OR_GLOBALS:
- return 1;
- case LOAD_GLOBAL:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_GLOBAL_MODULE:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_GLOBAL_BUILTIN:
- return ((oparg & 1) ? 1 : 0) + 1;
- case DELETE_FAST:
- return 0;
- case MAKE_CELL:
- return 0;
- case DELETE_DEREF:
- return 0;
- case LOAD_FROM_DICT_OR_DEREF:
- return 1;
- case LOAD_DEREF:
- return 1;
- case STORE_DEREF:
- return 0;
- case COPY_FREE_VARS:
- return 0;
- case BUILD_STRING:
- return 1;
- case BUILD_TUPLE:
- return 1;
- case BUILD_LIST:
- return 1;
- case LIST_EXTEND:
- return (oparg-1) + 1;
- case SET_UPDATE:
- return (oparg-1) + 1;
- case BUILD_SET:
- return 1;
- case BUILD_MAP:
- return 1;
- case SETUP_ANNOTATIONS:
- return 0;
- case BUILD_CONST_KEY_MAP:
- return 1;
- case DICT_UPDATE:
- return 0;
- case DICT_MERGE:
- return 0;
- case MAP_ADD:
- return 0;
- case INSTRUMENTED_LOAD_SUPER_ATTR:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_SUPER_ATTR:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_SUPER_ATTR_ATTR:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_SUPER_ATTR_METHOD:
- return 2;
- case LOAD_ATTR:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_ATTR_INSTANCE_VALUE:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_ATTR_MODULE:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_ATTR_WITH_HINT:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_ATTR_SLOT:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_ATTR_CLASS:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_ATTR_PROPERTY:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN:
- return ((oparg & 1) ? 1 : 0) + 1;
- case STORE_ATTR_INSTANCE_VALUE:
- return 0;
- case STORE_ATTR_WITH_HINT:
- return 0;
- case STORE_ATTR_SLOT:
- return 0;
- case COMPARE_OP:
- return 1;
- case COMPARE_OP_FLOAT:
- return 1;
- case COMPARE_OP_INT:
- return 1;
- case COMPARE_OP_STR:
- return 1;
- case IS_OP:
- return 1;
- case CONTAINS_OP:
- return 1;
- case CHECK_EG_MATCH:
- return 2;
- case CHECK_EXC_MATCH:
- return 2;
- case IMPORT_NAME:
- return 1;
- case IMPORT_FROM:
- return 2;
- case JUMP_FORWARD:
- return 0;
- case JUMP_BACKWARD:
- return 0;
- case ENTER_EXECUTOR:
- return 0;
- case POP_JUMP_IF_FALSE:
- return 0;
- case POP_JUMP_IF_TRUE:
- return 0;
- case POP_JUMP_IF_NOT_NONE:
- return 0;
- case POP_JUMP_IF_NONE:
- return 0;
- case JUMP_BACKWARD_NO_INTERRUPT:
- return 0;
- case GET_LEN:
- return 2;
- case MATCH_CLASS:
- return 1;
- case MATCH_MAPPING:
- return 2;
- case MATCH_SEQUENCE:
- return 2;
- case MATCH_KEYS:
- return 3;
- case GET_ITER:
- return 1;
- case GET_YIELD_FROM_ITER:
- return 1;
- case FOR_ITER:
- return 2;
- case INSTRUMENTED_FOR_ITER:
- return 0;
- case FOR_ITER_LIST:
- return 2;
- case FOR_ITER_TUPLE:
- return 2;
- case FOR_ITER_RANGE:
- return 2;
- case FOR_ITER_GEN:
- return 2;
- case BEFORE_ASYNC_WITH:
- return 2;
- case BEFORE_WITH:
- return 2;
- case WITH_EXCEPT_START:
- return 5;
- case PUSH_EXC_INFO:
- return 2;
- case LOAD_ATTR_METHOD_WITH_VALUES:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_ATTR_METHOD_NO_DICT:
- return ((oparg & 1) ? 1 : 0) + 1;
- case LOAD_ATTR_METHOD_LAZY_DICT:
- return ((oparg & 1) ? 1 : 0) + 1;
- case KW_NAMES:
- return 0;
- case INSTRUMENTED_CALL:
- return 0;
- case CALL:
- return 1;
- case CALL_BOUND_METHOD_EXACT_ARGS:
- return 1;
- case CALL_PY_EXACT_ARGS:
- return 1;
- case CALL_PY_WITH_DEFAULTS:
- return 1;
- case CALL_NO_KW_TYPE_1:
- return 1;
- case CALL_NO_KW_STR_1:
- return 1;
- case CALL_NO_KW_TUPLE_1:
- return 1;
- case CALL_BUILTIN_CLASS:
- return 1;
- case CALL_NO_KW_BUILTIN_O:
- return 1;
- case CALL_NO_KW_BUILTIN_FAST:
- return 1;
- case CALL_BUILTIN_FAST_WITH_KEYWORDS:
- return 1;
- case CALL_NO_KW_LEN:
- return 1;
- case CALL_NO_KW_ISINSTANCE:
- return 1;
- case CALL_NO_KW_LIST_APPEND:
- return 1;
- case CALL_NO_KW_METHOD_DESCRIPTOR_O:
- return 1;
- case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS:
- return 1;
- case CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS:
- return 1;
- case CALL_NO_KW_METHOD_DESCRIPTOR_FAST:
- return 1;
- case INSTRUMENTED_CALL_FUNCTION_EX:
- return 0;
- case CALL_FUNCTION_EX:
- return 1;
- case MAKE_FUNCTION:
- return 1;
- case RETURN_GENERATOR:
- return 0;
- case BUILD_SLICE:
- return 1;
- case FORMAT_VALUE:
- return 1;
- case COPY:
- return (oparg-1) + 2;
- case BINARY_OP:
- return 1;
- case SWAP:
- return (oparg-2) + 2;
- case INSTRUMENTED_INSTRUCTION:
- return 0;
- case INSTRUMENTED_JUMP_FORWARD:
- return 0;
- case INSTRUMENTED_JUMP_BACKWARD:
- return 0;
- case INSTRUMENTED_POP_JUMP_IF_TRUE:
- return 0;
- case INSTRUMENTED_POP_JUMP_IF_FALSE:
- return 0;
- case INSTRUMENTED_POP_JUMP_IF_NONE:
- return 0;
- case INSTRUMENTED_POP_JUMP_IF_NOT_NONE:
- return 0;
- case EXTENDED_ARG:
- return 0;
- case CACHE:
- return 0;
- case RESERVED:
- return 0;
- default:
- return -1;
- }
-}
-#endif
-
-enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC00, INSTR_FMT_IBC000, INSTR_FMT_IBC00000000, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 };
-struct opcode_metadata {
- bool valid_entry;
- enum InstructionFormat instr_format;
-};
-
-#ifndef NEED_OPCODE_METADATA
-extern const struct opcode_metadata _PyOpcode_opcode_metadata[256];
-#else
-const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
- [NOP] = { true, INSTR_FMT_IX },
- [RESUME] = { true, INSTR_FMT_IB },
- [INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB },
- [LOAD_CLOSURE] = { true, INSTR_FMT_IB },
- [LOAD_FAST_CHECK] = { true, INSTR_FMT_IB },
- [LOAD_FAST] = { true, INSTR_FMT_IB },
- [LOAD_FAST_AND_CLEAR] = { true, INSTR_FMT_IB },
- [LOAD_FAST_LOAD_FAST] = { true, INSTR_FMT_IB },
- [LOAD_CONST] = { true, INSTR_FMT_IB },
- [STORE_FAST] = { true, INSTR_FMT_IB },
- [STORE_FAST_LOAD_FAST] = { true, INSTR_FMT_IB },
- [STORE_FAST_STORE_FAST] = { true, INSTR_FMT_IB },
- [POP_TOP] = { true, INSTR_FMT_IX },
- [PUSH_NULL] = { true, INSTR_FMT_IX },
- [END_FOR] = { true, INSTR_FMT_IB },
- [INSTRUMENTED_END_FOR] = { true, INSTR_FMT_IX },
- [END_SEND] = { true, INSTR_FMT_IX },
- [INSTRUMENTED_END_SEND] = { true, INSTR_FMT_IX },
- [UNARY_NEGATIVE] = { true, INSTR_FMT_IX },
- [UNARY_NOT] = { true, INSTR_FMT_IX },
- [UNARY_INVERT] = { true, INSTR_FMT_IX },
- [BINARY_OP_MULTIPLY_INT] = { true, INSTR_FMT_IBC },
- [BINARY_OP_ADD_INT] = { true, INSTR_FMT_IBC },
- [BINARY_OP_SUBTRACT_INT] = { true, INSTR_FMT_IBC },
- [BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IBC },
- [BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IBC },
- [BINARY_OP_SUBTRACT_FLOAT] = { true, INSTR_FMT_IBC },
- [BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IBC },
- [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IB },
- [BINARY_SUBSCR] = { true, INSTR_FMT_IXC },
- [BINARY_SLICE] = { true, INSTR_FMT_IX },
- [STORE_SLICE] = { true, INSTR_FMT_IX },
- [BINARY_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC },
- [BINARY_SUBSCR_TUPLE_INT] = { true, INSTR_FMT_IXC },
- [BINARY_SUBSCR_DICT] = { true, INSTR_FMT_IXC },
- [BINARY_SUBSCR_GETITEM] = { true, INSTR_FMT_IXC },
- [LIST_APPEND] = { true, INSTR_FMT_IB },
- [SET_ADD] = { true, INSTR_FMT_IB },
- [STORE_SUBSCR] = { true, INSTR_FMT_IXC },
- [STORE_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC },
- [STORE_SUBSCR_DICT] = { true, INSTR_FMT_IXC },
- [DELETE_SUBSCR] = { true, INSTR_FMT_IX },
- [CALL_INTRINSIC_1] = { true, INSTR_FMT_IB },
- [CALL_INTRINSIC_2] = { true, INSTR_FMT_IB },
- [RAISE_VARARGS] = { true, INSTR_FMT_IB },
- [INTERPRETER_EXIT] = { true, INSTR_FMT_IX },
- [RETURN_VALUE] = { true, INSTR_FMT_IX },
- [INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX },
- [RETURN_CONST] = { true, INSTR_FMT_IB },
- [INSTRUMENTED_RETURN_CONST] = { true, INSTR_FMT_IB },
- [GET_AITER] = { true, INSTR_FMT_IX },
- [GET_ANEXT] = { true, INSTR_FMT_IX },
- [GET_AWAITABLE] = { true, INSTR_FMT_IB },
- [SEND] = { true, INSTR_FMT_IBC },
- [SEND_GEN] = { true, INSTR_FMT_IBC },
- [INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IX },
- [YIELD_VALUE] = { true, INSTR_FMT_IX },
- [POP_EXCEPT] = { true, INSTR_FMT_IX },
- [RERAISE] = { true, INSTR_FMT_IB },
- [END_ASYNC_FOR] = { true, INSTR_FMT_IX },
- [CLEANUP_THROW] = { true, INSTR_FMT_IX },
- [LOAD_ASSERTION_ERROR] = { true, INSTR_FMT_IX },
- [LOAD_BUILD_CLASS] = { true, INSTR_FMT_IX },
- [STORE_NAME] = { true, INSTR_FMT_IB },
- [DELETE_NAME] = { true, INSTR_FMT_IB },
- [UNPACK_SEQUENCE] = { true, INSTR_FMT_IBC },
- [UNPACK_SEQUENCE_TWO_TUPLE] = { true, INSTR_FMT_IBC },
- [UNPACK_SEQUENCE_TUPLE] = { true, INSTR_FMT_IBC },
- [UNPACK_SEQUENCE_LIST] = { true, INSTR_FMT_IBC },
- [UNPACK_EX] = { true, INSTR_FMT_IB },
- [STORE_ATTR] = { true, INSTR_FMT_IBC000 },
- [DELETE_ATTR] = { true, INSTR_FMT_IB },
- [STORE_GLOBAL] = { true, INSTR_FMT_IB },
- [DELETE_GLOBAL] = { true, INSTR_FMT_IB },
- [LOAD_LOCALS] = { true, INSTR_FMT_IB },
- [LOAD_NAME] = { true, INSTR_FMT_IB },
- [LOAD_FROM_DICT_OR_GLOBALS] = { true, INSTR_FMT_IB },
- [LOAD_GLOBAL] = { true, INSTR_FMT_IBC000 },
- [LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IBC000 },
- [LOAD_GLOBAL_BUILTIN] = { true, INSTR_FMT_IBC000 },
- [DELETE_FAST] = { true, INSTR_FMT_IB },
- [MAKE_CELL] = { true, INSTR_FMT_IB },
- [DELETE_DEREF] = { true, INSTR_FMT_IB },
- [LOAD_FROM_DICT_OR_DEREF] = { true, INSTR_FMT_IB },
- [LOAD_DEREF] = { true, INSTR_FMT_IB },
- [STORE_DEREF] = { true, INSTR_FMT_IB },
- [COPY_FREE_VARS] = { true, INSTR_FMT_IB },
- [BUILD_STRING] = { true, INSTR_FMT_IB },
- [BUILD_TUPLE] = { true, INSTR_FMT_IB },
- [BUILD_LIST] = { true, INSTR_FMT_IB },
- [LIST_EXTEND] = { true, INSTR_FMT_IB },
- [SET_UPDATE] = { true, INSTR_FMT_IB },
- [BUILD_SET] = { true, INSTR_FMT_IB },
- [BUILD_MAP] = { true, INSTR_FMT_IB },
- [SETUP_ANNOTATIONS] = { true, INSTR_FMT_IX },
- [BUILD_CONST_KEY_MAP] = { true, INSTR_FMT_IB },
- [DICT_UPDATE] = { true, INSTR_FMT_IB },
- [DICT_MERGE] = { true, INSTR_FMT_IB },
- [MAP_ADD] = { true, INSTR_FMT_IB },
- [INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC00000000 },
- [LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC },
- [LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC },
- [LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC },
- [LOAD_ATTR] = { true, INSTR_FMT_IBC00000000 },
- [LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC00000000 },
- [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000 },
- [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000 },
- [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000 },
- [LOAD_ATTR_CLASS] = { true, INSTR_FMT_IBC00000000 },
- [LOAD_ATTR_PROPERTY] = { true, INSTR_FMT_IBC00000000 },
- [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000 },
- [STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000 },
- [STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000 },
- [STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000 },
- [COMPARE_OP] = { true, INSTR_FMT_IBC },
- [COMPARE_OP_FLOAT] = { true, INSTR_FMT_IBC },
- [COMPARE_OP_INT] = { true, INSTR_FMT_IBC },
- [COMPARE_OP_STR] = { true, INSTR_FMT_IBC },
- [IS_OP] = { true, INSTR_FMT_IB },
- [CONTAINS_OP] = { true, INSTR_FMT_IB },
- [CHECK_EG_MATCH] = { true, INSTR_FMT_IX },
- [CHECK_EXC_MATCH] = { true, INSTR_FMT_IX },
- [IMPORT_NAME] = { true, INSTR_FMT_IB },
- [IMPORT_FROM] = { true, INSTR_FMT_IB },
- [JUMP_FORWARD] = { true, INSTR_FMT_IB },
- [JUMP_BACKWARD] = { true, INSTR_FMT_IB },
- [ENTER_EXECUTOR] = { true, INSTR_FMT_IB },
- [POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB },
- [POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB },
- [POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IB },
- [POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB },
- [JUMP_BACKWARD_NO_INTERRUPT] = { true, INSTR_FMT_IB },
- [GET_LEN] = { true, INSTR_FMT_IX },
- [MATCH_CLASS] = { true, INSTR_FMT_IB },
- [MATCH_MAPPING] = { true, INSTR_FMT_IX },
- [MATCH_SEQUENCE] = { true, INSTR_FMT_IX },
- [MATCH_KEYS] = { true, INSTR_FMT_IX },
- [GET_ITER] = { true, INSTR_FMT_IX },
- [GET_YIELD_FROM_ITER] = { true, INSTR_FMT_IX },
- [FOR_ITER] = { true, INSTR_FMT_IBC },
- [INSTRUMENTED_FOR_ITER] = { true, INSTR_FMT_IB },
- [FOR_ITER_LIST] = { true, INSTR_FMT_IBC },
- [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC },
- [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC },
- [FOR_ITER_GEN] = { true, INSTR_FMT_IBC },
- [BEFORE_ASYNC_WITH] = { true, INSTR_FMT_IX },
- [BEFORE_WITH] = { true, INSTR_FMT_IX },
- [WITH_EXCEPT_START] = { true, INSTR_FMT_IX },
- [PUSH_EXC_INFO] = { true, INSTR_FMT_IX },
- [LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC00000000 },
- [LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000 },
- [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000 },
- [KW_NAMES] = { true, INSTR_FMT_IB },
- [INSTRUMENTED_CALL] = { true, INSTR_FMT_IB },
- [CALL] = { true, INSTR_FMT_IBC00 },
- [CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00 },
- [CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00 },
- [CALL_PY_WITH_DEFAULTS] = { true, INSTR_FMT_IBC00 },
- [CALL_NO_KW_TYPE_1] = { true, INSTR_FMT_IBC00 },
- [CALL_NO_KW_STR_1] = { true, INSTR_FMT_IBC00 },
- [CALL_NO_KW_TUPLE_1] = { true, INSTR_FMT_IBC00 },
- [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00 },
- [CALL_NO_KW_BUILTIN_O] = { true, INSTR_FMT_IBC00 },
- [CALL_NO_KW_BUILTIN_FAST] = { true, INSTR_FMT_IBC00 },
- [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00 },
- [CALL_NO_KW_LEN] = { true, INSTR_FMT_IBC00 },
- [CALL_NO_KW_ISINSTANCE] = { true, INSTR_FMT_IBC00 },
- [CALL_NO_KW_LIST_APPEND] = { true, INSTR_FMT_IBC00 },
- [CALL_NO_KW_METHOD_DESCRIPTOR_O] = { true, INSTR_FMT_IBC00 },
- [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00 },
- [CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00 },
- [CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00 },
- [INSTRUMENTED_CALL_FUNCTION_EX] = { true, INSTR_FMT_IX },
- [CALL_FUNCTION_EX] = { true, INSTR_FMT_IB },
- [MAKE_FUNCTION] = { true, INSTR_FMT_IB },
- [RETURN_GENERATOR] = { true, INSTR_FMT_IX },
- [BUILD_SLICE] = { true, INSTR_FMT_IB },
- [FORMAT_VALUE] = { true, INSTR_FMT_IB },
- [COPY] = { true, INSTR_FMT_IB },
- [BINARY_OP] = { true, INSTR_FMT_IBC },
- [SWAP] = { true, INSTR_FMT_IB },
- [INSTRUMENTED_INSTRUCTION] = { true, INSTR_FMT_IX },
- [INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB },
- [INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IB },
- [INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB },
- [INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB },
- [INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB },
- [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IB },
- [EXTENDED_ARG] = { true, INSTR_FMT_IB },
- [CACHE] = { true, INSTR_FMT_IX },
- [RESERVED] = { true, INSTR_FMT_IX },
-};
-#endif
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h
index 02e6033867d661..d84d253c912a28 100644
--- a/Python/opcode_targets.h
+++ b/Python/opcode_targets.h
@@ -5,49 +5,49 @@ static void *opcode_targets[256] = {
&&TARGET_INTERPRETER_EXIT,
&&TARGET_END_FOR,
&&TARGET_END_SEND,
- &&TARGET_BINARY_OP_ADD_FLOAT,
- &&TARGET_BINARY_OP_ADD_INT,
- &&TARGET_BINARY_OP_ADD_UNICODE,
+ &&TARGET_TO_BOOL,
+ &&TARGET_TO_BOOL_ALWAYS_TRUE,
+ &&TARGET_TO_BOOL_BOOL,
&&TARGET_NOP,
- &&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
+ &&TARGET_TO_BOOL_INT,
&&TARGET_UNARY_NEGATIVE,
&&TARGET_UNARY_NOT,
- &&TARGET_BINARY_OP_MULTIPLY_FLOAT,
- &&TARGET_BINARY_OP_MULTIPLY_INT,
+ &&TARGET_TO_BOOL_LIST,
+ &&TARGET_TO_BOOL_NONE,
&&TARGET_UNARY_INVERT,
- &&TARGET_BINARY_OP_SUBTRACT_FLOAT,
+ &&TARGET_EXIT_INIT_CHECK,
&&TARGET_RESERVED,
+ &&TARGET_TO_BOOL_STR,
+ &&TARGET_BINARY_OP_MULTIPLY_INT,
+ &&TARGET_BINARY_OP_ADD_INT,
&&TARGET_BINARY_OP_SUBTRACT_INT,
- &&TARGET_BINARY_SUBSCR_DICT,
- &&TARGET_BINARY_SUBSCR_GETITEM,
- &&TARGET_BINARY_SUBSCR_LIST_INT,
- &&TARGET_BINARY_SUBSCR_TUPLE_INT,
- &&TARGET_CALL_PY_EXACT_ARGS,
- &&TARGET_CALL_PY_WITH_DEFAULTS,
+ &&TARGET_BINARY_OP_MULTIPLY_FLOAT,
+ &&TARGET_BINARY_OP_ADD_FLOAT,
+ &&TARGET_MAKE_FUNCTION,
&&TARGET_BINARY_SUBSCR,
&&TARGET_BINARY_SLICE,
&&TARGET_STORE_SLICE,
- &&TARGET_CALL_BOUND_METHOD_EXACT_ARGS,
- &&TARGET_CALL_BUILTIN_CLASS,
+ &&TARGET_BINARY_OP_SUBTRACT_FLOAT,
+ &&TARGET_BINARY_OP_ADD_UNICODE,
&&TARGET_GET_LEN,
&&TARGET_MATCH_MAPPING,
&&TARGET_MATCH_SEQUENCE,
&&TARGET_MATCH_KEYS,
- &&TARGET_CALL_BUILTIN_FAST_WITH_KEYWORDS,
+ &&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
&&TARGET_PUSH_EXC_INFO,
&&TARGET_CHECK_EXC_MATCH,
&&TARGET_CHECK_EG_MATCH,
- &&TARGET_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
- &&TARGET_CALL_NO_KW_BUILTIN_FAST,
- &&TARGET_CALL_NO_KW_BUILTIN_O,
- &&TARGET_CALL_NO_KW_ISINSTANCE,
- &&TARGET_CALL_NO_KW_LEN,
- &&TARGET_CALL_NO_KW_LIST_APPEND,
- &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
- &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
- &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O,
- &&TARGET_CALL_NO_KW_STR_1,
- &&TARGET_CALL_NO_KW_TUPLE_1,
+ &&TARGET_BINARY_SUBSCR_DICT,
+ &&TARGET_BINARY_SUBSCR_GETITEM,
+ &&TARGET_FORMAT_SIMPLE,
+ &&TARGET_FORMAT_WITH_SPEC,
+ &&TARGET_BINARY_SUBSCR_LIST_INT,
+ &&TARGET_BINARY_SUBSCR_TUPLE_INT,
+ &&TARGET_STORE_SUBSCR_DICT,
+ &&TARGET_STORE_SUBSCR_LIST_INT,
+ &&TARGET_SEND_GEN,
+ &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE,
+ &&TARGET_UNPACK_SEQUENCE_TUPLE,
&&TARGET_WITH_EXCEPT_START,
&&TARGET_GET_AITER,
&&TARGET_GET_ANEXT,
@@ -55,39 +55,39 @@ static void *opcode_targets[256] = {
&&TARGET_BEFORE_WITH,
&&TARGET_END_ASYNC_FOR,
&&TARGET_CLEANUP_THROW,
- &&TARGET_CALL_NO_KW_TYPE_1,
- &&TARGET_COMPARE_OP_FLOAT,
- &&TARGET_COMPARE_OP_INT,
- &&TARGET_COMPARE_OP_STR,
+ &&TARGET_UNPACK_SEQUENCE_LIST,
+ &&TARGET_STORE_ATTR_INSTANCE_VALUE,
+ &&TARGET_STORE_ATTR_SLOT,
+ &&TARGET_STORE_ATTR_WITH_HINT,
&&TARGET_STORE_SUBSCR,
&&TARGET_DELETE_SUBSCR,
- &&TARGET_FOR_ITER_LIST,
- &&TARGET_FOR_ITER_TUPLE,
- &&TARGET_FOR_ITER_RANGE,
- &&TARGET_FOR_ITER_GEN,
+ &&TARGET_LOAD_GLOBAL_MODULE,
+ &&TARGET_LOAD_GLOBAL_BUILTIN,
&&TARGET_LOAD_SUPER_ATTR_ATTR,
&&TARGET_LOAD_SUPER_ATTR_METHOD,
+ &&TARGET_LOAD_ATTR_INSTANCE_VALUE,
+ &&TARGET_LOAD_ATTR_MODULE,
&&TARGET_GET_ITER,
&&TARGET_GET_YIELD_FROM_ITER,
- &&TARGET_LOAD_ATTR_CLASS,
+ &&TARGET_LOAD_ATTR_WITH_HINT,
&&TARGET_LOAD_BUILD_CLASS,
- &&TARGET_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN,
- &&TARGET_LOAD_ATTR_INSTANCE_VALUE,
+ &&TARGET_LOAD_ATTR_SLOT,
+ &&TARGET_LOAD_ATTR_CLASS,
&&TARGET_LOAD_ASSERTION_ERROR,
&&TARGET_RETURN_GENERATOR,
- &&TARGET_LOAD_ATTR_MODULE,
&&TARGET_LOAD_ATTR_PROPERTY,
- &&TARGET_LOAD_ATTR_SLOT,
- &&TARGET_LOAD_ATTR_WITH_HINT,
- &&TARGET_LOAD_ATTR_METHOD_LAZY_DICT,
- &&TARGET_LOAD_ATTR_METHOD_NO_DICT,
+ &&TARGET_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN,
&&TARGET_LOAD_ATTR_METHOD_WITH_VALUES,
+ &&TARGET_LOAD_ATTR_METHOD_NO_DICT,
+ &&TARGET_LOAD_ATTR_METHOD_LAZY_DICT,
+ &&TARGET_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES,
+ &&TARGET_LOAD_ATTR_NONDESCRIPTOR_NO_DICT,
&&TARGET_RETURN_VALUE,
- &&TARGET_LOAD_GLOBAL_BUILTIN,
+ &&TARGET_COMPARE_OP_FLOAT,
&&TARGET_SETUP_ANNOTATIONS,
- &&TARGET_LOAD_GLOBAL_MODULE,
+ &&TARGET_COMPARE_OP_INT,
&&TARGET_LOAD_LOCALS,
- &&TARGET_STORE_ATTR_INSTANCE_VALUE,
+ &&TARGET_COMPARE_OP_STR,
&&TARGET_POP_EXCEPT,
&&TARGET_STORE_NAME,
&&TARGET_DELETE_NAME,
@@ -110,9 +110,9 @@ static void *opcode_targets[256] = {
&&TARGET_IMPORT_NAME,
&&TARGET_IMPORT_FROM,
&&TARGET_JUMP_FORWARD,
- &&TARGET_STORE_ATTR_SLOT,
- &&TARGET_STORE_ATTR_WITH_HINT,
- &&TARGET_STORE_SUBSCR_DICT,
+ &&TARGET_FOR_ITER_LIST,
+ &&TARGET_FOR_ITER_TUPLE,
+ &&TARGET_FOR_ITER_RANGE,
&&TARGET_POP_JUMP_IF_FALSE,
&&TARGET_POP_JUMP_IF_TRUE,
&&TARGET_LOAD_GLOBAL,
@@ -131,11 +131,11 @@ static void *opcode_targets[256] = {
&&TARGET_POP_JUMP_IF_NONE,
&&TARGET_RAISE_VARARGS,
&&TARGET_GET_AWAITABLE,
- &&TARGET_MAKE_FUNCTION,
+ &&TARGET_FOR_ITER_GEN,
&&TARGET_BUILD_SLICE,
&&TARGET_JUMP_BACKWARD_NO_INTERRUPT,
&&TARGET_MAKE_CELL,
- &&TARGET_LOAD_CLOSURE,
+ &&TARGET_CALL_BOUND_METHOD_EXACT_ARGS,
&&TARGET_LOAD_DEREF,
&&TARGET_STORE_DEREF,
&&TARGET_DELETE_DEREF,
@@ -147,26 +147,26 @@ static void *opcode_targets[256] = {
&&TARGET_LIST_APPEND,
&&TARGET_SET_ADD,
&&TARGET_MAP_ADD,
- &&TARGET_STORE_SUBSCR_LIST_INT,
+ &&TARGET_CALL_PY_EXACT_ARGS,
&&TARGET_COPY_FREE_VARS,
&&TARGET_YIELD_VALUE,
&&TARGET_RESUME,
&&TARGET_MATCH_CLASS,
- &&TARGET_UNPACK_SEQUENCE_LIST,
- &&TARGET_UNPACK_SEQUENCE_TUPLE,
- &&TARGET_FORMAT_VALUE,
+ &&TARGET_CALL_PY_WITH_DEFAULTS,
+ &&TARGET_CALL_NO_KW_TYPE_1,
+ &&TARGET_CALL_NO_KW_STR_1,
&&TARGET_BUILD_CONST_KEY_MAP,
&&TARGET_BUILD_STRING,
- &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE,
- &&TARGET_SEND_GEN,
- &&_unknown_opcode,
- &&_unknown_opcode,
+ &&TARGET_CONVERT_VALUE,
+ &&TARGET_CALL_NO_KW_TUPLE_1,
+ &&TARGET_CALL_BUILTIN_CLASS,
+ &&TARGET_CALL_NO_KW_BUILTIN_O,
&&TARGET_LIST_EXTEND,
&&TARGET_SET_UPDATE,
&&TARGET_DICT_MERGE,
&&TARGET_DICT_UPDATE,
- &&_unknown_opcode,
- &&_unknown_opcode,
+ &&TARGET_CALL_NO_KW_BUILTIN_FAST,
+ &&TARGET_CALL_BUILTIN_FAST_WITH_KEYWORDS,
&&TARGET_LOAD_FAST_LOAD_FAST,
&&TARGET_STORE_FAST_LOAD_FAST,
&&TARGET_STORE_FAST_STORE_FAST,
@@ -176,15 +176,15 @@ static void *opcode_targets[256] = {
&&TARGET_CALL_INTRINSIC_2,
&&TARGET_LOAD_FROM_DICT_OR_GLOBALS,
&&TARGET_LOAD_FROM_DICT_OR_DEREF,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
+ &&TARGET_SET_FUNCTION_ATTRIBUTE,
+ &&TARGET_CALL_NO_KW_LEN,
+ &&TARGET_CALL_NO_KW_ISINSTANCE,
+ &&TARGET_CALL_NO_KW_LIST_APPEND,
+ &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O,
+ &&TARGET_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
+ &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
+ &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
+ &&TARGET_CALL_NO_KW_ALLOC_AND_ENTER_INIT,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
diff --git a/Python/optimizer.c b/Python/optimizer.c
index d721bfa2b2dea4..289b202f806ae1 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -1,28 +1,43 @@
-
#include "Python.h"
#include "opcode.h"
#include "pycore_interp.h"
#include "pycore_opcode.h"
-#include "pycore_pystate.h"
+#include "pycore_opcode_metadata.h"
+#include "pycore_opcode_utils.h"
+#include "pycore_pystate.h" // _PyInterpreterState_GET()
+#include "pycore_uops.h"
#include "cpython/optimizer.h"
#include
#include