From 28bc162e92c342f0ca4fc94fe9d0a9ea0fbb3b57 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Wed, 27 May 2026 16:15:52 -0500 Subject: [PATCH 01/20] feat: update magic int from 3655 (CPython 3.15-dev) to 3666. --- xdis/magics.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xdis/magics.py b/xdis/magics.py index 4ed736d7..93790965 100755 --- a/xdis/magics.py +++ b/xdis/magics.py @@ -687,7 +687,7 @@ def __by_version(magic_versions: Dict[bytes, str]) -> dict: # Fix miscompilation of some module-level annotations. # add_magic_from_int(3655, "3.15a1e") # NOTE: this will change on release! -add_magic_from_int(3655, "3.15-dev") +add_magic_from_int(3666, "3.15") # Python 3.16 will start with 3700 @@ -871,8 +871,8 @@ def add_canonic_versions(release_versions: str, canonic: str) -> None: add_canonic_versions("3.14 3.14.0 3.14.1, 3.14.2 3.14.3 3.14.4", "3.14rc3") add_canonic_versions( - "3.15 3.15.0 3.15.0a1 3.15.0a0", - "3.15-dev", + "3.15 3.15.0 3.15.0a1 3.15.0a0 3.15-dev 3.15.0b1", + "3.15", ) # The canonic version for a canonic version is itself From 203fa1a8690da8d1896b1ea086897d563667e35f Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Wed, 27 May 2026 16:16:18 -0500 Subject: [PATCH 02/20] feat: added support for new opcodes from CPython 3.15.0b1 --- xdis/op_imports.py | 3 + xdis/opcodes/__init__.py | 2 + xdis/opcodes/opcode_3x/opcode_315.py | 404 +++++++++++++++++++++++++++ 3 files changed, 409 insertions(+) create mode 100644 xdis/opcodes/opcode_3x/opcode_315.py diff --git a/xdis/op_imports.py b/xdis/op_imports.py index 51541b7f..a3725982 100644 --- a/xdis/op_imports.py +++ b/xdis/op_imports.py @@ -61,6 +61,7 @@ opcode_312, opcode_313, opcode_314, + opcode_315, opcode_3531rust, opcode_12897rust, opcode_24481rust, @@ -200,6 +201,8 @@ "3.14": opcode_314, "3.14rc3": opcode_314, 3.14: opcode_314, + "3.15": opcode_315, + 3.15: opcode_315, } for k, v in canonic_python_version.items(): diff --git a/xdis/opcodes/__init__.py b/xdis/opcodes/__init__.py index 0737617a..56ab993c 100644 --- a/xdis/opcodes/__init__.py +++ b/xdis/opcodes/__init__.py @@ -54,6 +54,7 @@ opcode_312, opcode_313, opcode_314, + opcode_315 ) from xdis.opcodes.opcode_pypy import ( opcode_26pypy, @@ -103,6 +104,7 @@ "opcode_312", "opcode_313", "opcode_314", + "opcode_315", "opcode_32", "opcode_33", "opcode_34", diff --git a/xdis/opcodes/opcode_3x/opcode_315.py b/xdis/opcodes/opcode_3x/opcode_315.py new file mode 100644 index 00000000..0ce00b1b --- /dev/null +++ b/xdis/opcodes/opcode_3x/opcode_315.py @@ -0,0 +1,404 @@ +# (C) Copyright 2026 by Rocky Bernstein +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" +CPython 3.15 bytecode opcodes + +This is like Python 3.15's opcode.py with some classification +of stack usage and information for formatting instructions. +of stack usage. +""" + +import xdis.opcodes.opcode_3x.opcode_314 as opcode_314 +from xdis.opcodes.base import ( + VARYING_STACK_INT, + binary_op, + call_op, + compare_op, + const_op, + cpython_implementation, + def_op, + finalize_opcodes, + free_op, + init_opdata, + jrel_op, + local_op, + name_op, + nargs_op, + store_op, + unary_op, + update_pj3, + varargs_op, +) +from xdis.opcodes.format.extended import extended_format_binary_op + +version_tuple = (3, 15) +python_implementation = cpython_implementation + +loc = locals() + +init_opdata(loc, None, version_tuple) + +# extend opcodes to cover pseudo ops +loc["opname"].extend([f"<{i}>" for i in range(256, 267)]) +loc["oppop"].extend([0] * 11) +loc["oppush"].extend([0] * 11) + +# fmt: off +# OP NAME OPCODE POP PUSH +# --------------------------------------------------------------------------- +def_op(loc, "CACHE", 0, 0, 0) +def_op(loc, "BINARY_SLICE", 1, 3, 1) +def_op(loc, "BUILD_TEMPLATE", 2, 2, 1) +local_op(loc, "BINARY_OP_INPLACE_ADD_UNICODE", 3, 2, 0) +def_op(loc, "CALL_FUNCTION_EX", 4, 4, 1) +def_op(loc, "CHECK_EG_MATCH", 5, 2, 2) +def_op(loc, "CHECK_EXC_MATCH", 6, 2, 2) +def_op(loc, "CLEANUP_THROW", 7, 3, 2) +def_op(loc, "DELETE_SUBSCR", 8, 2, 0) +def_op(loc, "END_FOR", 9, 1, 0) +def_op(loc, "END_SEND", 10, 2, 0) +def_op(loc, "EXIT_INIT_CHECK", 11, 1, 0) +def_op(loc, "FORMAT_SIMPLE", 12, 1, 1) +def_op(loc, "FORMAT_WITH_SPEC", 13, 2, 1) +def_op(loc, "GET_AITER", 14, 1, 1) +def_op(loc, "GET_ANEXT", 15, 1, 2) +def_op(loc, "GET_LEN", 16, 1, 2) +def_op(loc, "RESERVED", 17, 0, 0) +def_op(loc, "INTERPRETER_EXIT", 18, 1, 0) +def_op(loc, "LOAD_BUILD_CLASS", 19, 0, 1) +def_op(loc, "LOAD_LOCALS", 20, 0, 1) # Pushes a reference to the locals of the current scope. + # This is not a name op. +nargs_op(loc, "MAKE_FUNCTION", 21, VARYING_STACK_INT, 1) +def_op(loc, "MATCH_KEYS", 22, 2, 3) +def_op(loc, "MATCH_MAPPING", 23, 1, 2) +def_op(loc, "MATCH_SEQUENCE", 24, 1, 2) +def_op(loc, "NOP", 25, 0, 0) +def_op(loc, "NOT_TAKEN", 26, 0, 0) +def_op(loc, "POP_EXCEPT", 27, 1, 0) +def_op(loc, "POP_ITER", 28, 2, 0) +def_op(loc, "POP_TOP", 29, 1, 0) +def_op(loc, "PUSH_EXC_INFO", 30, 1, 2) +def_op(loc, "PUSH_NULL", 31, 0, 1) +def_op(loc, "RETURN_GENERATOR", 32, 0, 1) +def_op(loc, "RETURN_VALUE", 33, 1, 1) +def_op(loc, "SETUP_ANNOTATIONS", 34, 0, 0) +store_op(loc, "STORE_SLICE", 35, 4, 0) +store_op(loc, "STORE_SUBSCR", 36, 3, 0) +unary_op(loc, "TO_BOOL", 37, 1, 1) +unary_op(loc, "UNARY_INVERT", 38, 1, 1) +unary_op(loc, "UNARY_NEGATIVE", 39, 1, 1) +unary_op(loc, "UNARY_NOT", 40, 1, 1) +def_op(loc, "WITH_EXCEPT_START", 41, 5, 6) +binary_op(loc, "BINARY_OP", 42, 2, 1) +def_op(loc, "BUILD_INTERPOLATION", 43, VARYING_STACK_INT, 1) # Either -1 or -2: pops 2 + (oparg & 1) and pushes result +varargs_op(loc, "BUILD_LIST", 44, -1, 1) # TOS is count of list items +varargs_op(loc, "BUILD_MAP", 45, 0, 1) # argument is dictionary count to be popped +varargs_op(loc, "BUILD_SET", 46, -1, 1) # TOS is count of set items +varargs_op(loc, "BUILD_SLICE", 47, -1, 1) # TOS is slice +varargs_op(loc, "BUILD_STRING", 48, -1, 1) # TOS is concatenated strings +varargs_op(loc, "BUILD_TUPLE", 49, -1, 1) # TOS is count of tuple items +call_op(loc, "CALL", 50, VARYING_STACK_INT, 2) # pops 2 + oparg; TOS is return value +def_op(loc, "CALL_INTRINSIC_1", 51, 1, 1) +def_op(loc, "CALL_INTRINSIC_2", 52, 2, 1) +call_op(loc, "CALL_KW", 53, -3, 1) # pops 3 + oparg; TOS is return value +compare_op(loc, "COMPARE_OP", 54, 2, 1) +binary_op(loc, "CONTAINS_OP", 55, 2, 1) +def_op(loc, "CONVERT_VALUE", 56, 1, 1) +def_op(loc, "COPY", 57, 0, 1) +def_op(loc, "COPY_FREE_VARS", 58, 0, 0) +name_op(loc, "DELETE_ATTR", 59, 1, 0) +free_op(loc, "DELETE_DEREF", 60, 0, 0) +local_op(loc, "DELETE_FAST", 61, 0, 0) +name_op(loc, "DELETE_GLOBAL", 62, 0, 0) +name_op(loc, "DELETE_NAME", 63, 0, 0) +def_op(loc, "DICT_MERGE", 64, 1, 0) +def_op(loc, "DICT_UPDATE", 65, 1, 0) +jrel_op(loc, "END_ASYNC_FOR", 66, 2, 0, conditional=True) +def_op(loc, "EXTENDED_ARG", 67, 0, 0) +jrel_op(loc, "FOR_ITER", 68, 0, 1, conditional=True) +def_op(loc, "GET_AWAITABLE", 69, 1, 1) +def_op(loc, "GET_ITER", 70, 0, 1) +name_op(loc, "IMPORT_FROM", 71, 1, 2) +name_op(loc, "IMPORT_NAME", 72, 2, 1) +compare_op(loc, "IS_OP", 73, 2, 1) +jrel_op(loc, "JUMP_BACKWARD", 74, 0, 0, conditional=False) +jrel_op(loc, "JUMP_BACKWARD_NO_INTERRUPT", 75, 0, 0, conditional=False) +jrel_op(loc, "JUMP_FORWARD", 76, 0, 0, conditional=False) +def_op(loc, "LIST_APPEND", 77, 1, 0) +def_op(loc, "LIST_EXTEND", 78, 1, 0) +name_op(loc, "LOAD_ATTR", 79, 1, 1) # pops 1 + (oparg & 1) +def_op(loc, "LOAD_COMMON_CONSTANT", 80, 0, 1) +const_op(loc, "LOAD_CONST", 81, 0, 1) +local_op(loc, "LOAD_DEREF", 82, 0, 1) +local_op(loc, "LOAD_FAST", 83, 0, 1) +local_op(loc, "LOAD_FAST_AND_CLEAR", 84, 0, 1) +local_op(loc, "LOAD_FAST_BORROW", 85, 0, 1) +local_op(loc, "LOAD_FAST_BORROW_LOAD_FAST_BORROW", 86, 0, 2) +local_op(loc, "LOAD_FAST_CHECK", 87, 0, 1) +local_op(loc, "LOAD_FAST_LOAD_FAST", 88, 0, 2) +free_op(loc, "LOAD_FROM_DICT_OR_DEREF", 89, 1, 1) +name_op(loc, "LOAD_FROM_DICT_OR_GLOBALS", 90, 1, 1) +name_op(loc, "LOAD_GLOBAL", 91, 0, 1) # pops 1 + (oparg & 1) +name_op(loc, "LOAD_NAME", 92, 0, 1) +def_op(loc, "LOAD_SMALL_INT", 93, 0, 1) +def_op(loc, "LOAD_SPECIAL", 94, 1, 2) +name_op(loc, "LOAD_SUPER_ATTR", 95, 3, 1) # pops 1 + (oparg & 1) +free_op(loc, "MAKE_CELL", 96, 0, 0) +def_op(loc, "MAP_ADD", 97, 2, 0) +def_op(loc, "MATCH_CLASS", 98, 3, 1) +jrel_op(loc, "POP_JUMP_IF_FALSE", 99, 1, 0, conditional=True) +jrel_op(loc, "POP_JUMP_IF_NONE", 100, 1, 0, conditional=True) +jrel_op(loc, "POP_JUMP_IF_NOT_NONE", 101, 1, 0, conditional=True) +jrel_op(loc, "POP_JUMP_IF_TRUE", 102, 1, 0, conditional=True) +varargs_op(loc, "RAISE_VARARGS", 103, -1, 0) +def_op(loc, "RERAISE", 104, 1, 0) +jrel_op(loc, "SEND", 105, 2, 2, conditional=True) +def_op(loc, "SET_ADD", 106, 1, 0) +def_op(loc, "SET_FUNCTION_ATTRIBUTE", 107, 2, 1) +def_op(loc, "SET_UPDATE", 108, 1, 0) +store_op(loc, "STORE_ATTR", 109, 2, 0, is_type="name") +store_op(loc, "STORE_DEREF", 110, 1, 0, is_type="free") +store_op(loc, "STORE_FAST", 111, 1, 0, is_type="local") +local_op(loc, "STORE_FAST_LOAD_FAST", 112, 1, 1) +store_op(loc, "STORE_FAST_STORE_FAST", 113, 2, 0, is_type="local") +store_op(loc, "STORE_GLOBAL", 114, 1, 0, is_type="name") +store_op(loc, "STORE_NAME", 115, 1, 0, is_type="name") +def_op(loc, "SWAP", 116, 0, 0) +varargs_op(loc, "UNPACK_EX", 117, VARYING_STACK_INT, VARYING_STACK_INT) # pushes 1 + (oparg & 0xFF) + (oparg >> 8) +varargs_op(loc, "UNPACK_SEQUENCE", 118, 1, VARYING_STACK_INT) # unpacks TOS, arg is the count +def_op(loc, "YIELD_VALUE", 119, 1, 1) +def_op(loc, "RESUME", 128, 0, 0) + +# Specialized opcodes (>128) +binary_op(loc, "BINARY_OP_ADD_FLOAT", 129, 2, 1) +binary_op(loc, "BINARY_OP_ADD_INT", 130, 2, 1) +binary_op(loc, "BINARY_OP_ADD_UNICODE", 131, 2, 1) +binary_op(loc, "BINARY_OP_EXTEND", 132, 2, 1) +binary_op(loc, "BINARY_OP_MULTIPLY_FLOAT", 133, 2, 1) +binary_op(loc, "BINARY_OP_MULTIPLY_INT", 134, 2, 1) +binary_op(loc, "BINARY_OP_SUBSCR_DICT", 135, 2, 1) +binary_op(loc, "BINARY_OP_SUBSCR_GETITEM", 136, 2, 0) +binary_op(loc, "BINARY_OP_SUBSCR_LIST_INT", 137, 2, 1) +binary_op(loc, "BINARY_OP_SUBSCR_LIST_SLICE", 138, 2, 1) +binary_op(loc, "BINARY_OP_SUBSCR_STR_INT", 139, 2, 1) +binary_op(loc, "BINARY_OP_SUBSCR_TUPLE_INT", 140, 2, 1) +binary_op(loc, "BINARY_OP_SUBTRACT_FLOAT", 141, 2, 1) +binary_op(loc, "BINARY_OP_SUBTRACT_INT", 142, 2, 1) +call_op(loc, "CALL_ALLOC_AND_ENTER_INIT", 143, -2, 0) # pops 2 + oparg +call_op(loc, "CALL_BOUND_METHOD_EXACT_ARGS", 144, -2, 0) # pops 2 + oparg +call_op(loc, "CALL_BOUND_METHOD_GENERAL", 145, -2, 0) # pops 2 + oparg +call_op(loc, "CALL_BUILTIN_CLASS", 146, -2, 1) # pops 2 + oparg +call_op(loc, "CALL_BUILTIN_FAST", 147, -2, 1) # pops 2 + oparg +call_op(loc, "CALL_BUILTIN_FAST_WITH_KEYWORDS", 148, -2, 1) # pops 2 + oparg +call_op(loc, "CALL_BUILTIN_O", 149, -2, 1) # pops 2 + oparg +def_op(loc, "CALL_ISINSTANCE", 150, 4, 1) +call_op(loc, "CALL_KW_BOUND_METHOD", 151, -3, 0) # pops 3 + oparg +call_op(loc, "CALL_KW_NON_PY", 152, -3, 1) # pops 3 + oparg +call_op(loc, "CALL_KW_PY", 153, -3, 0) # pops 3 + oparg +def_op(loc, "CALL_LEN", 154, 3, 1) +def_op(loc, "CALL_LIST_APPEND", 155, 3, 0) +call_op(loc, "CALL_METHOD_DESCRIPTOR_FAST", 156, -2, 1) # pops 2 + oparg +call_op(loc, "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", 157, -2, 1) # pops 2 + oparg +call_op(loc, "CALL_METHOD_DESCRIPTOR_NOARGS", 158, -2, 1) # pops 2 + oparg +call_op(loc, "CALL_METHOD_DESCRIPTOR_O", 159, -2, 1) # pops 2 + oparg +call_op(loc, "CALL_NON_PY_GENERAL", 160, -2, 1) # pops 2 + oparg +call_op(loc, "CALL_PY_EXACT_ARGS", 161, -2, 0) # pops 2 + oparg +call_op(loc, "CALL_PY_GENERAL", 162, -2, 0) # pops 2 + oparg +def_op(loc, "CALL_STR_1", 163, 3, 1) +def_op(loc, "CALL_TUPLE_1", 164, 3, 1) +def_op(loc, "CALL_TYPE_1", 165, 3, 1) +compare_op(loc, "COMPARE_OP_FLOAT", 166, 2, 1) +compare_op(loc, "COMPARE_OP_INT", 167, 2, 1) +compare_op(loc, "COMPARE_OP_STR", 168, 2, 1) +def_op(loc, "CONTAINS_OP_DICT", 169, 2, 1) +def_op(loc, "CONTAINS_OP_SET", 170, 2, 1) +jrel_op(loc, "FOR_ITER_GEN", 171, 2, 2, conditional=True) +jrel_op(loc, "FOR_ITER_LIST", 172, 2, 3, conditional=True) +jrel_op(loc, "FOR_ITER_RANGE", 173, 2, 3, conditional=True) +jrel_op(loc, "FOR_ITER_TUPLE", 174, 2, 3, conditional=True) +jrel_op(loc, "JUMP_BACKWARD_JIT", 175, 0, 0, conditional=False) +jrel_op(loc, "JUMP_BACKWARD_NO_JIT", 176, 0, 0, conditional=False) +def_op(loc, "LOAD_ATTR_CLASS", 177, 1, 1) # pushes 1 + (oparg & 1) +def_op(loc, "LOAD_ATTR_CLASS_WITH_METACLASS_CHECK", 178, 1, 1) # pushes 1 + (oparg & 1) +name_op(loc, "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN", 179, 1, 1) +def_op(loc, "LOAD_ATTR_INSTANCE_VALUE", 180, 1, 1) # pushes 1 + (oparg & 1) +def_op(loc, "LOAD_ATTR_METHOD_LAZY_DICT", 181, 1, 2) +def_op(loc, "LOAD_ATTR_METHOD_NO_DICT", 182, 1, 2) +def_op(loc, "LOAD_ATTR_METHOD_WITH_VALUES", 183, 1, 2) +def_op(loc, "LOAD_ATTR_MODULE", 184, 1, 1) # pushes 1 + (oparg & 1) +def_op(loc, "LOAD_ATTR_NONDESCRIPTOR_NO_DICT", 185, 1, 1) +def_op(loc, "LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", 186, 1, 1) +def_op(loc, "LOAD_ATTR_PROPERTY", 187, 1, 0) +def_op(loc, "LOAD_ATTR_SLOT", 188, 1, 1) # pushes 1 + (oparg & 1) +name_op(loc, "LOAD_ATTR_WITH_HINT", 189, 1, 1) # pushes 1 + (oparg & 1) +def_op(loc, "LOAD_GLOBAL_BUILTIN", 190, 0, 1) # pushes 1 + (oparg & 1) +def_op(loc, "LOAD_GLOBAL_MODULE", 191, 0, 1) # pushes 1 + (oparg & 1) +name_op(loc, "LOAD_SUPER_ATTR_ATTR", 192, 3, 1) +name_op(loc, "LOAD_SUPER_ATTR_METHOD", 193, 3, 2) +def_op(loc, "RESUME_CHECK", 194, 0, 0) +def_op(loc, "SEND_GEN", 195, 2, 1) +def_op(loc, "STORE_ATTR_INSTANCE_VALUE", 196, 2, 0) +def_op(loc, "STORE_ATTR_SLOT", 197, 2, 0) +store_op(loc, "STORE_ATTR_WITH_HINT", 198, 2, 0, is_type="name") +def_op(loc, "STORE_SUBSCR_DICT", 199, 3, 0) +def_op(loc, "STORE_SUBSCR_LIST_INT", 200, 3, 0) +def_op(loc, "TO_BOOL_ALWAYS_TRUE", 201, 1, 1) +def_op(loc, "TO_BOOL_BOOL", 202, 1, 1) +def_op(loc, "TO_BOOL_INT", 203, 1, 1) +def_op(loc, "TO_BOOL_LIST", 204, 1, 1) +def_op(loc, "TO_BOOL_NONE", 205, 1, 1) +def_op(loc, "TO_BOOL_STR", 206, 1, 1) +varargs_op(loc, "UNPACK_SEQUENCE_LIST", 207, 1, -1) +varargs_op(loc, "UNPACK_SEQUENCE_TUPLE", 208, 1, -1) +def_op(loc, "UNPACK_SEQUENCE_TWO_TUPLE", 209, 1, 2) +def_op(loc, "INSTRUMENTED_END_FOR", 233, 3, 2) +def_op(loc, "INSTRUMENTED_POP_ITER", 234, 1, 0) +def_op(loc, "INSTRUMENTED_END_SEND", 235, 2, 1) +jrel_op(loc, "INSTRUMENTED_FOR_ITER", 236, 2, 1, conditional=True) +def_op(loc, "INSTRUMENTED_INSTRUCTION", 237, 0, 1) +jrel_op(loc, "INSTRUMENTED_JUMP_FORWARD", 238, 0, 0, conditional=False) +def_op(loc, "INSTRUMENTED_NOT_TAKEN", 239, 0, 0) +jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_TRUE", 240, 0, 0, conditional=True) # dunno why it's not 1, 0. +jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_FALSE", 241, 1, 0, conditional=True) +jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_NONE", 242, 1, 0, conditional=True) +jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_NOT_NONE", 243, 1, 0, conditional=True) +def_op(loc, "INSTRUMENTED_RESUME", 244, 1, 0) # dunno why it's not 0, 0. +def_op(loc, "INSTRUMENTED_RETURN_VALUE", 245, 1, 1) +def_op(loc, "INSTRUMENTED_YIELD_VALUE", 246, 1, 1) +jrel_op(loc, "INSTRUMENTED_END_ASYNC_FOR", 247, 0, 0, conditional=True) # dunnow why it's not 2, 0 +name_op(loc, "INSTRUMENTED_LOAD_SUPER_ATTR", 248, VARYING_STACK_INT, 1) # pushes 1 + (oparg & 1) +call_op(loc, "INSTRUMENTED_CALL", 249, -2, 1) +call_op(loc, "INSTRUMENTED_CALL_KW", 250, -3, 1) +call_op(loc, "INSTRUMENTED_CALL_FUNCTION_EX", 251, 4, 1) +jrel_op(loc, "INSTRUMENTED_JUMP_BACKWARD", 252, 0, 0, conditional=False) +def_op(loc, "INSTRUMENTED_LINE", 253, 0, 0) +def_op(loc, "ENTER_EXECUTOR", 254, 0, 0) +def_op(loc, "TRACE_RECORD", 255, 0, 0) +def_op(loc, "ANNOTATIONS_PLACEHOLDER", 256, 0, 0) +jrel_op(loc, "JUMP", 257, 0, 0, conditional=False) +jrel_op(loc, "JUMP_IF_FALSE", 258, 1, 1, conditional=True) +jrel_op(loc, "JUMP_IF_TRUE", 259, 1, 1, conditional=True) +jrel_op(loc, "JUMP_NO_INTERRUPT", 260, 0, 0, conditional=False) +local_op(loc, "LOAD_CLOSURE", 261, 0, 1) +def_op(loc, "POP_BLOCK", 262, 0, 0) +def_op(loc, "SETUP_CLEANUP", 263, 0, 2) +def_op(loc, "SETUP_FINALLY", 264, 0, 1) +def_op(loc, "SETUP_WITH", 265, 0, 1) +def_op(loc, "STORE_FAST_MAYBE_NULL", 266, 1, 0) + +# ops >= 42 have args +HAVE_ARGUMENT = 42 + +loc["hasarg"] = [42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 128, 143, 144, 145, 146, 147, 148, 149, 151, 152, 153, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 195, 198, 207, 208, 209, 236, 238, 240, 241, 242, 243, 244, 246, 247, 248, 249, 250, 252, 254, 255, 257, 258, 259, 260, 261, 263, 264, 265, 266] +# hasconst table populated by const_op definitions +# hasname table populated by name_op and store_op definitions +# jrel table populated by jrel_op definitions +loc["hasjabs"] = [] +loc["hasjump"] = loc["hasjrel"] +# hasfree table populated by free_op and store_op definitions +# haslocal table populated by local_op and store_op definitions +loc["hasexc"] = [263, 264, 265] + +# fmt: on + +### update formatting + +_nb_ops = [ + ("NB_ADD", "+"), + ("NB_AND", "&"), + ("NB_FLOOR_DIVIDE", "//"), + ("NB_LSHIFT", "<<"), + ("NB_MATRIX_MULTIPLY", "@"), + ("NB_MULTIPLY", "*"), + ("NB_REMAINDER", "%"), + ("NB_OR", "|"), + ("NB_POWER", "**"), + ("NB_RSHIFT", ">>"), + ("NB_SUBTRACT", "-"), + ("NB_TRUE_DIVIDE", "/"), + ("NB_XOR", "^"), + ("NB_INPLACE_ADD", "+="), + ("NB_INPLACE_AND", "&="), + ("NB_INPLACE_FLOOR_DIVIDE", "//="), + ("NB_INPLACE_LSHIFT", "<<="), + ("NB_INPLACE_MATRIX_MULTIPLY", "@="), + ("NB_INPLACE_MULTIPLY", "*="), + ("NB_INPLACE_REMAINDER", "%="), + ("NB_INPLACE_OR", "|="), + ("NB_INPLACE_POWER", "**="), + ("NB_INPLACE_RSHIFT", ">>="), + ("NB_INPLACE_SUBTRACT", "-="), + ("NB_INPLACE_TRUE_DIVIDE", "/="), + ("NB_INPLACE_XOR", "^="), + ("NB_SUBSCR", "[]"), +] + + +def format_BINARY_OP_315(arg: int): + return _nb_ops[arg][1] + + +def extended_BINARY_OP_315(opc, instructions): + opname = _nb_ops[instructions[0].argval][1] + + if opname == "%": + # Make sure to escape % below. + opname = "%%" + + fmt_str = "%s[%s]" if opname == "[]" else f"%s {opname} %s" + return extended_format_binary_op(opc, instructions, fmt_str) + + +_common_constants = ( + "AssertionError", + "NotImplementedError", + "tuple", + "all", + "any", + "list", + "set", + "None", # <--- There is your oparg 7! + '""', + "True", + "False", + "-1", + "frozenset", + "()", +) + + +def format_LOAD_COMMON_CONSTANT_315(arg: int): + return _common_constants[arg] + + +opcode_arg_fmt = opcode_arg_fmt315 = { + **opcode_314.opcode_arg_fmt314, + **{"BINARY_OP": format_BINARY_OP_315}, + **{"LOAD_COMMON_CONSTANT": format_LOAD_COMMON_CONSTANT_315}, +} + +opcode_extended_fmt = opcode_extended_fmt315 = { + **opcode_314.opcode_extended_fmt314, + **{"BINARY_OP": extended_BINARY_OP_315}, +} + +# CALL_FUNCTION_EX no longer takes an argument in 3.14/3.15, so it no longer needs to be formatted +opcode_arg_fmt.pop("CALL_FUNCTION_EX", None) + +findlinestarts = opcode_314.findlinestarts + +update_pj3(globals(), loc) +finalize_opcodes(loc) From 13f45d8678b4126c23ff121f60663c1692848fc2 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Wed, 27 May 2026 16:17:18 -0500 Subject: [PATCH 03/20] feat: implemented frozendict unmarshal for CPython 3.15+ --- xdis/unmarshal.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/xdis/unmarshal.py b/xdis/unmarshal.py index 69582723..ea928596 100644 --- a/xdis/unmarshal.py +++ b/xdis/unmarshal.py @@ -33,7 +33,7 @@ from typing import Any, Dict, Tuple, Union from xdis.codetype import to_portable -from xdis.cross_types import LongTypeForPython3, UnicodeForPython3 +from xdis.cross_types import LongTypeForPython3, UnicodeForPython3, FrozenDictPrePython315 from xdis.magics import GRAAL3_MAGICS, PYPY3_MAGICS, RUSTPYTHON_MAGICS, magic_int2tuple @@ -60,6 +60,7 @@ def long(n: int) -> LongTypeForPython3: TYPE_CODE_OLD = "C" # used in Python 1.0 - 1.2. Graal Python uses this too. TYPE_COMPLEX = "x" # Version 0 only. Not in use after Python 2.4 TYPE_DICT = "{" +TYPE_FROZENDICT = "}" TYPE_ELLIPSIS = "." TYPE_FALSE = "F" TYPE_FLOAT = "f" # Version 0 only. Not in use after Python 2.4 @@ -105,6 +106,7 @@ def long(n: int) -> LongTypeForPython3: TYPE_CODE_OLD: "code_old", # Older Python TYPE_COMPLEX: "complex", TYPE_DICT: "dict", + TYPE_FROZENDICT: "frozendict", TYPE_ELLIPSIS: "Ellipsis", TYPE_FALSE: "False", TYPE_FLOAT: "float", @@ -487,6 +489,24 @@ def t_set(self, save_ref, bytes_for_s: bool = False) -> set: setsize -= 1 return self.r_ref_insert(set(ret), i) + def t_frozendict(self, save_ref, bytes_for_s: bool = False): + d, i = self.r_ref_reserve(dict(), save_ref) + # dictionary + while True: + key = self.r_object(bytes_for_s=bytes_for_s) + if key is None: + break + val = self.r_object(bytes_for_s=bytes_for_s) + d[key] = val + pass + + try: + final_frozendict = frozendict(d) + except NameError: + final_frozendict = FrozenDictPrePython315(d) + + return self.r_ref_insert(final_frozendict, i) + def t_dict(self, save_ref, bytes_for_s: bool = False) -> dict: ret = self.r_ref(dict(), save_ref) # dictionary From 5eea3e237ad13628c4d03f057e9881e794bc80b4 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Wed, 27 May 2026 16:17:53 -0500 Subject: [PATCH 04/20] feat: added frozendict polyfill type to allow unmarshalling CPython 3.15+ bytecode on pre-3.15 versions --- xdis/cross_types.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xdis/cross_types.py b/xdis/cross_types.py index 763db4fc..981e87aa 100644 --- a/xdis/cross_types.py +++ b/xdis/cross_types.py @@ -89,3 +89,14 @@ def __str__(self) -> str: return f"""u'{str(self.value)[1:]}'""" return f"""{utf8_value}""" + +class FrozenDictPrePython315(dict): + """ + Defines a frozendict type which was newly added in + Python 3.15 and doesn't exist on previous versions + """ + def __repr__(self): + return f"frozendict({super().__repr__()})" + + def __hash__(self): + return hash(tuple(self.items())) From 7836e73197b2c31498f501dd6e38b2c0d44e10c8 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Wed, 27 May 2026 16:17:57 -0500 Subject: [PATCH 05/20] feat: implemented 3.15 lazy/eager import instruction decoding and offset --- xdis/bytecode.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/xdis/bytecode.py b/xdis/bytecode.py index 675174e2..948b8c5b 100644 --- a/xdis/bytecode.py +++ b/xdis/bytecode.py @@ -330,7 +330,13 @@ def get_logical_instruction_at_offset( if op in opc.CONST_OPS: argval, argrepr = _get_const_info(arg, constants) elif op in opc.NAME_OPS: - if opc.version_tuple >= (3, 11) and opname == "LOAD_GLOBAL": + if opc.version_tuple >= (3, 15) and opname == "IMPORT_NAME": + argval, argrepr = get_name_info(arg >> 2, names) + if arg & 1: + argrepr = argrepr + " + lazy" + elif arg & 2: + argrepr = argrepr + " + eager" + elif opc.version_tuple >= (3, 11) and opname == "LOAD_GLOBAL": argval, argrepr = get_name_info(arg >> 1, names) if arg & 1: argrepr = "NULL + " + argrepr From dd8d9b745ff41e1d2899220e402962af0fb72fe1 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Wed, 27 May 2026 16:18:01 -0500 Subject: [PATCH 06/20] fix: updated test to skip 1: None requirement on 3.15+ due to movement of None out of co_consts and into LOAD_COMMON_CONSTS --- pytest/test_std.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pytest/test_std.py b/pytest/test_std.py index 0f51ff0b..518ba07e 100644 --- a/pytest/test_std.py +++ b/pytest/test_std.py @@ -58,8 +58,12 @@ # First Line: 1 # Constants: # 0: 10 -# 1: None -# Names: +""" + + ("# 1: None\n" if PYTHON_VERSION_TRIPLE < (3, 15) else "") + # In Python 3.15+, None is no longer in co_consts; it is loaded via + # LOAD_COMMON_CONSTANT(7) instead, so the implicit "return None" does + # not produce a constant entry. + + """# Names: # 0: a""" ).format( flags="0x00000000 (0x0)" From bb477df7f2b418e744809dd67c42f5b1943e1b4c Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Wed, 27 May 2026 16:18:23 -0500 Subject: [PATCH 07/20] fix: configurable lib_prefix via env variable --- test/test_pythonlib.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_pythonlib.py b/test/test_pythonlib.py index 00862cc2..8dbefe94 100755 --- a/test/test_pythonlib.py +++ b/test/test_pythonlib.py @@ -51,7 +51,8 @@ def get_srcdir(): # ----- configure this for your needs -lib_prefix = "/usr/lib" +lib_prefix = os.environ.get("XDIS_LIB_PREFIX", "/usr/lib") +# lib_prefix = "/usr/lib" # lib_prefix = [src_dir, '/usr/lib/', '/usr/local/lib/'] target_base = tempfile.mkdtemp(prefix="py-dis-") From 89bc9b005c5d703329adb69ca86ca8631c9706c5 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Wed, 27 May 2026 16:18:27 -0500 Subject: [PATCH 08/20] chore: added 3.15 to version list --- test/test_pythonlib.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_pythonlib.py b/test/test_pythonlib.py index 8dbefe94..073dbc82 100755 --- a/test/test_pythonlib.py +++ b/test/test_pythonlib.py @@ -111,6 +111,7 @@ def get_srcdir(): "3.12", "3.13", "3.14", + "3.15", ): bytecode = f"bytecode_{vers}" key = f"bytecode-{vers}" From 248cc13ee3df4769acd49aff249f4ddadfc5ab23 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Wed, 27 May 2026 16:18:31 -0500 Subject: [PATCH 09/20] feat: created frozendict unmarshalling test --- .../315_frozendict/make_01_frozendict.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/version_specific/315_frozendict/make_01_frozendict.py diff --git a/test/version_specific/315_frozendict/make_01_frozendict.py b/test/version_specific/315_frozendict/make_01_frozendict.py new file mode 100644 index 00000000..fcebec03 --- /dev/null +++ b/test/version_specific/315_frozendict/make_01_frozendict.py @@ -0,0 +1,41 @@ +# Generates a frozendict object to test the unmarshal.py implementation for frozen dicts. +# +# Justification: Python 3.15 does not currently statically optimize frozendict() invocations +# because users can name any function `frozendict`. As a result, py_compile can never emit +# TYPE_FROZENDICT, so manually inserting the frozendict object is the only way to test this +# functionality currently. +# +# This must be run in Python 3.15 to correctly generate the pyc file used for testing. + +import importlib.util +import marshal +import struct +import time + +# 1. Compile a simple dummy script +source = "print('Testing frozendict cross-version support!')" +code_obj = compile(source, "01_frozendict.py", "exec") + +# 2. Create a native 3.15 frozendict +fd = frozendict({"hello": "cross-version-world"}) + +# 3. Inject it into the code object's constants +# We use the `.replace()` method (added in Python 3.8) to make a new code obj +new_consts = code_obj.co_consts + (fd,) +new_code_obj = code_obj.replace(co_consts=new_consts) + +# 4. Write the .pyc file manually +magic = importlib.util.MAGIC_NUMBER +bitfield = 0 +timestamp = int(time.time()) +file_size = len(source) + +with open("01_frozendict.pyc", "wb") as f: + # Write the 16-byte header (Magic, Bitfield, Timestamp, Size) + f.write(magic) + f.write(struct.pack(" Date: Wed, 27 May 2026 16:18:54 -0500 Subject: [PATCH 10/20] fix: t_long now uses read_int32 instead of read_uint32 --- xdis/unmarshal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xdis/unmarshal.py b/xdis/unmarshal.py index ea928596..67ca170e 100644 --- a/xdis/unmarshal.py +++ b/xdis/unmarshal.py @@ -325,7 +325,7 @@ def t_int32(self, save_ref, bytes_for_s: bool = False): return self.r_ref(self.read_int32(), save_ref) def t_long(self, save_ref, bytes_for_s: bool = False): - n = self.read_uint32() + n = self.read_int32() if n == 0: return long(0) size = abs(n) From bbade0866517ac4d051ae76d65e45130fd5cb20b Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Wed, 27 May 2026 16:19:10 -0500 Subject: [PATCH 11/20] fix: t_dict can no longer terminate on null values, only null keys --- xdis/unmarshal.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/xdis/unmarshal.py b/xdis/unmarshal.py index 67ca170e..727a7852 100644 --- a/xdis/unmarshal.py +++ b/xdis/unmarshal.py @@ -515,8 +515,6 @@ def t_dict(self, save_ref, bytes_for_s: bool = False) -> dict: if key is None: break val = self.r_object(bytes_for_s=bytes_for_s) - if val is None: - break ret[key] = val pass return ret From b9f70e9fcb2849aed1686cc239d56942588934a1 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Wed, 27 May 2026 16:20:08 -0500 Subject: [PATCH 12/20] fix: t_unicode now unmarshalls with surrogatepass enabled, as Python 3 supports surrogate code points --- xdis/unmarshal.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xdis/unmarshal.py b/xdis/unmarshal.py index 727a7852..036bd717 100644 --- a/xdis/unmarshal.py +++ b/xdis/unmarshal.py @@ -438,7 +438,12 @@ def t_unicode(self, save_ref, bytes_for_s: bool = False): if self.version_triple < (3, 0): string = UnicodeForPython3(unicodestring) else: - string = unicodestring.decode() + # surrogatepass is needed because Python 3 supports surrogate + # code points in strings. CPython 3.15+ pulls in Pygments as a + # dependency (for colored CLI/REPL output), and its source + # contains surrogate code points that cause stdlib test + # disassembly to fail without this error handler. + string = unicodestring.decode("utf-8", "surrogatepass") return self.r_ref(string, save_ref) From e8d33d0dda7e03fe95c004cd7fa3783c3a4589f7 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Wed, 27 May 2026 16:22:58 -0500 Subject: [PATCH 13/20] chore: generated pyc test cases for CPython 3.15.0b1 --- test/bytecode_3.15/00_assign.pyc | Bin 0 -> 235 bytes test/bytecode_3.15/00_import.pyc | Bin 0 -> 469 bytes test/bytecode_3.15/01_dead_code.pyc | Bin 0 -> 270 bytes test/bytecode_3.15/01_extended_arg.pyc | Bin 0 -> 183 bytes test/bytecode_3.15/01_frozendict.pyc | Bin 0 -> 210 bytes test/bytecode_3.15/01_hexstring.pyc | Bin 0 -> 359 bytes test/bytecode_3.15/01_unicode.pyc | Bin 0 -> 172 bytes test/bytecode_3.15/02_complex.pyc | Bin 0 -> 160 bytes test/bytecode_3.15/03_big_dict.pyc | Bin 0 -> 5496 bytes test/bytecode_3.15/03_build_map.pyc | Bin 0 -> 683 bytes test/bytecode_3.15/04_pypy_lambda.pyc | Bin 0 -> 406 bytes test/bytecode_3.15/04_raise.pyc | Bin 0 -> 336 bytes test/bytecode_3.15/05_24_float.pyc | Bin 0 -> 300 bytes test/bytecode_3.15/06_py34_ref.pyc | Bin 0 -> 235 bytes test/bytecode_3.15/11_classbug.pyc | Bin 0 -> 702 bytes test/bytecode_3.15/pydisasm-example.pyc | Bin 0 -> 634 bytes 16 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/bytecode_3.15/00_assign.pyc create mode 100644 test/bytecode_3.15/00_import.pyc create mode 100644 test/bytecode_3.15/01_dead_code.pyc create mode 100644 test/bytecode_3.15/01_extended_arg.pyc create mode 100644 test/bytecode_3.15/01_frozendict.pyc create mode 100644 test/bytecode_3.15/01_hexstring.pyc create mode 100644 test/bytecode_3.15/01_unicode.pyc create mode 100644 test/bytecode_3.15/02_complex.pyc create mode 100644 test/bytecode_3.15/03_big_dict.pyc create mode 100644 test/bytecode_3.15/03_build_map.pyc create mode 100644 test/bytecode_3.15/04_pypy_lambda.pyc create mode 100644 test/bytecode_3.15/04_raise.pyc create mode 100644 test/bytecode_3.15/05_24_float.pyc create mode 100644 test/bytecode_3.15/06_py34_ref.pyc create mode 100644 test/bytecode_3.15/11_classbug.pyc create mode 100644 test/bytecode_3.15/pydisasm-example.pyc diff --git a/test/bytecode_3.15/00_assign.pyc b/test/bytecode_3.15/00_assign.pyc new file mode 100644 index 0000000000000000000000000000000000000000..823e84d48611cef58da386f165cfa566d22ee3ed GIT binary patch literal 235 zcmWIIyc4v^6R#DNUO3<2!LjDd{BOfd{Gj4@1x%z;d1 z5ey7zK($f~0SxJk0qlwln#{LY{POcsU+OS1069gBK)rrNKsHE*G4U2-(k;g1l?$EnHd=wKX5UyayKyEVBr7}>_CEpv%|0>v7z#Ui24Bb5Qb;(mJd%L2;oBwK}(1^?jW&36RV?CD+|blk0W4!yWB2`bR>3G{tbJ7 zh=mqzBor3LlJEzdJ;W7_zyJ{+b0xD%nn?~TELJu zq(v=-DJ7|uRt90WDPG9`3RgRH2(a!7>;>UH@DNvf5sP}zbB#bv&Nn}YK3)DaO`O`*EX z6#FC2J-t5}J2Nh#AvI}+TAesE5x4E(c;eW$h;;Ry-WQ}N2-bl(W_&&z8hQY8hx!f; z5#6~V>meI2u$500W$rLuW8^H>d7kK5;JnLp(3PiJ4e7 uDk0<>v=wB(Aiak23Qj)N=PO4oI8&DU>;$mSS@sXL4k?}q=_eUlMRwt&9%nU3%MJzyZ0EHnX-~a#s literal 0 HcmV?d00001 diff --git a/test/bytecode_3.15/01_frozendict.pyc b/test/bytecode_3.15/01_frozendict.pyc new file mode 100644 index 0000000000000000000000000000000000000000..38290c008ba65da806392bd558dff421c34a751d GIT binary patch literal 210 zcmWII2_T~Zh+`P!83GxM7$M@a3<2zl3@e#_X@;a0 zmt^LpE2I_WSEc5qWG0s=Bp2lu7weX#78Pga=P4AI78K+cl_>tb#hQ_tlav2T7)4&U zJijO>#b71lE!Kjf%)FA744*+(+~PJ$kGKd2M%uvQ>9U!9thyxi!8HyQV7~~lO8I2ervVlxy5ey7z zK($f~0SxJk0qlwln#{>iS+E)=APF+-vkH)C0OC-fNm@V}1_Bw8c|iS4rK~`?x5rf}GU&;{4L0;6#UNZP1SA?6ZgBH-)LrG4UBGsgTkQgi+Gn6B!!72-q~uaiAOLBwjfa{v z8NphMK#neA2N59W+~Tmw%}*)KNwq8D1ad(xDV75gADI~$89(tbGOB;%VBp~F5N)oQ RU~`3C{sM#iC3bnRegL!XM92UD literal 0 HcmV?d00001 diff --git a/test/bytecode_3.15/01_unicode.pyc b/test/bytecode_3.15/01_unicode.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee5a7f1b85d03c75a4341f7a7fa077911842c33d GIT binary patch literal 172 zcmWIIPO4oID^LT-(qfQ>ADI~$89zuc@G3WP7BK?_0AH~v+W-In literal 0 HcmV?d00001 diff --git a/test/bytecode_3.15/02_complex.pyc b/test/bytecode_3.15/02_complex.pyc new file mode 100644 index 0000000000000000000000000000000000000000..419da437fbcb08c9e94401cb10e6095a185e1b96 GIT binary patch literal 160 zcmWIIh!MiEjj=3*Ok{+lTnR5Swv#kT z(>9Bmr6p~e?n~0WP4|88qaOM0Q(t)-J8%BF{pXx}h1~M_```0B=giDGGk2~PuJ^bs z`1`QEvH`TjGbi%V&yb8TvycVLc7FUP@i}k+ATfTEd>;1WG-i z4!t0L0gZ`YLKnyrC(okz6+8*?Yv@I_w%;n2#0TPO@f(p8zZI9n@5HkBy-0~ah!yci zkrsav8S!V46@L-Wh`;u_{nngix_Yn0_cz@&GBM>3pNaa%#`Ffmo|zqqg#DwDvSV^K z7@3$3p3yx<#@NKEiLrp*Zs4Rp5}r66EvGdb{z!N>5H)gJ4BvP#6bhS8bH2&Y*laMQ z*BLp}p{D}j@?yc6;}heNGKLw;g-?y?wZ^zmxZKZa*zSp`>7ai!K+QFpQ0}hmDc9X$ z=KOC%^=80q#^lNlTTSOZEtZEGJ$lS6Zn7LUx-7HN=2j2r(`AmWY>qlzNTy@jwP@mM zR@3We=|rbPGZT@CQvs8w0>}KsbsV3VIu!^<3ig}cxb9lr8eYqGI+NEuY{oO`%Ly&7 z*DNLS(PTcM=~cN@GM+eOJo}C3fbl$xou8Zzg(K1NaA;DmO=V(>(O5pO>9xU-e=Iug zpNSaelz$Qhl6N%dpP3{1Vf|#;EVwngD!OUSRfdP1bAu_ zXflrxF{bk@CQ^xfBAQ!W$i+3?V{Dv(_4nX_UYE;fv~sd*CK3u8YZx{yQOAB`1ve8{ zT(z3c#^TF*13#lzqS=_1Nau97;YcNOdA)97HJMtB=2x?+!~pgSKHldVGB0K{y_%gD zb+=(e)d5wf;?af7;x)ZCo>|GV>B-@gDsU;0uE6@mWV|w570cz4OKIH|TU}zazrr5S zU5g1752`ZlvGk%|tzmj)I3NSM4YgG%7oKjsD2vH_GLw#_^o9zEXsZdmMrA3dUSAPX zUDTNo>Z!RR8coGk78YZ=2N|nc+Qe$r9`;eMiKA<^A=m)J>fbU4^y-VN>G)y-yJi@R ziFihLtt>Obc5m5-^tyNodw_gO^Hfs5?p(eS)0XrqdgSzaWa3iLl~c_(RI=Ki#;lf1 z(>bo>qPhG^UT>-Nq*Ls4Z8`NCw$mxo%A-K`dO(_$(5XLTfVH@moE?a zth)7pl3pdX|9AIyTy>s8u~SiyGWh|-}Um9kICnv(O%dElthUea#TVbVUO z_C9`iy+qxVU_Ww%XlRHM_mQrVosj>`yMfZ`z43$Ix&C>>!^w@XKwyWy>I`7U}d}pY7u_Dcp~c;PP-aQhP~Bk@iTpd0%VrYEJL7m09eZ5P12YOK?BI?FR@Rv^aOKUz1*f zeHLe1F)8;GbaA0Rf^Lg*=lThGfS`xddI=7y+Rn&6f7*7CO zi}Ug%V-VO-YTPR)nWw;>mv71tGEc0n_bMZ-ehVd-0vDCC* z&M}`;T-+n)8P6LSWxN1vD`sSjaRI32iZd<(n~Hrh!FbV#E-^k$7?MfGOA1RZ-Ex^Z zW$>L9<}|pq)Yc<2%vt6>`3$qh+$(d;d2m~){h(ZBz6@?DwR+_h=Br>;+%?96f!7(= zR5niJ2IEbjYU~!{u#NV3zx2}ulOy2vQpbQCWgZ8kmmYbH`8XJBACeQyL2zSnhn!@b z0ydPI`ecZC8eCs$d{7GJFu1wYI&f!(IiljlYB|ez8rWFukY^ar0$bPJa*pwwf%A;# zfo-L2J{e_R0ONHzDC5i*!A+&+9=XJPiFr^iGpCsM$ra`_*i~xlmKo+OxW3fUBcEZ` z!0zI*%rWMHwWT(nTxGrt_LR2w$}7xQ!Dw|%USlqR+e_PqkSO z3b(fz}rhZpOB->W8hYNOahGKK*y{rp96c;*~~Lv0OJ+!z8zy;0JoQR^ldn>Wdj=yH2#qK_#fGDpvg|9P5m2= nrcw)n&;uKe)>3=VhNGtB-nHSVE!FM5eTAlazD|1=|C9U|_X0&9 literal 0 HcmV?d00001 diff --git a/test/bytecode_3.15/03_build_map.pyc b/test/bytecode_3.15/03_build_map.pyc new file mode 100644 index 0000000000000000000000000000000000000000..64fa63819a93e340d3d404edd0f5403cc141936c GIT binary patch literal 683 zcma)&yKmZ16o>CG24jp3B!ov^5Spq|hBQ^^W2q`7eZO<)yV4bc#8Oj%f-nr-qD~!I zDlum5TJ?{q&XlzqQT~A*U(>x;@~7`wpO1BKGwZub)~{0e^LHq95N-ag+DtBfik!%^ zrL-cnq0=-cTp&xhLJ1)#DRjve7APfLB}X_%X<>$3;UZ;(Yvc(n@`WB{g+caf?(l7{z+u>2K-wj&f@n~=m zY+q}%I-{fRVXN2fU+sTk=XUS-aMTU%46evGa{nsK3(qY8Q`^nkzZ1!maB4;7XUA4- z#qy*OTXp?(!`PYWlG2@dQD@9_#!MI4)K*DbCZ=NdbJEVdRFSDOuhnI)aVPH6QST_z t&)oDgH@$H;?lV#Entt4z6egY14Re%ldt)nl@t>RXg3S5q4KB;g`~|85v=IOR literal 0 HcmV?d00001 diff --git a/test/bytecode_3.15/04_pypy_lambda.pyc b/test/bytecode_3.15/04_pypy_lambda.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0def3acfcc523aa5ac4f04f392077239ed832bf0 GIT binary patch literal 406 zcmWIIU=m+YSx_0DlbD;7lBicud5gma!nV651!L*i zUMfKT83L1|SY)2xKs`0vZk!m0}3sQiNz{Ob5z=!Ab^A##@|4skw=nd6{|X z#URtvZYh?e7MJK3XXX~KmBG8=1tX<>V)p=oM7nVopyjDPjYvW(DG6 zkTV+@Zmc4B32-`2xu>Z zCgUyclGKV4$Gnt~#Ps5o44;9547U_ZQj1IUi!*Zza#G`q^Gl18Q}qqZ;tMK`P2!7E r)AR}|Z*kb<=BJeAq}mmMd;)S%G043inHd=wKWMP>iZyW;aR3DX*daH} literal 0 HcmV?d00001 diff --git a/test/bytecode_3.15/11_classbug.pyc b/test/bytecode_3.15/11_classbug.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b66f6a416908b06b79426da991652293a272581d GIT binary patch literal 702 zcmZXSON-P%5P+-m(6~Ay`xq6($07*1>@bTLMP%K(V$^uqmD)_Em1rh2c6APWn>~5( z4|w$I&4UO3h9Djq|AdUso7J5}5DQZ8uKK#k{eEu+Sl*vG`|K6l+yB>qA`t_49#N2Z z6sCfXrEp!4o#&f1d?=^$GSl*o)LC9;M0wE8wZ_shL$usx=Z4#`XY)?>Is!-mPXatz zOZ|@c0ytuEmzRW8&!tkf+eC;(RcORGG=5%^394)=O*qa-lJO_GHYX4r2qM|_S6LQj zQ%llADi~HG&1#j);b_z}j_ape^Fw8u&H4W?wAHP&05o9r>j=I?y-)qiZ?1fdhVOz8 z4?ah?mt26i5J#5LLLr(J#OZ8O^GY(_Kx6aO2UkLHd^Te)rz3~IAb%*`{ DT?nQK literal 0 HcmV?d00001 diff --git a/test/bytecode_3.15/pydisasm-example.pyc b/test/bytecode_3.15/pydisasm-example.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9bf28079723cdaf9822d30a91048883d4e384ce9 GIT binary patch literal 634 zcmYjNzi-n(6n^I)v73ZOph82S;@Sa}h_q4%kPt$!K$+TfPGqI_g}SwUmd|PGPU!?A zV;3Y=cK!%P5GkZ5F)((F@(=LrIwkLP_kP@W-}~O}F5V~t+SfbF2QLYLohCEW^I-Z7 zgCXt~2+PFHTk?FmvH*)qg6Gq!;sZTMoO8~V@Q|r3d3aVbsc3nGp_bQ<5xa)@=qcNvq zpARVS_2^C#@AKf1z{{8g4s)pEimnjM-}937;%+~9M#Chl`Ly}^8rIxPVkW3?W7f=h z*Tcjv)`=`1u}HW)u-u@>Pj0_Ol;8C{8u9^)uqllPyslg-DEl(~g1RXU%W}AFSyB~= zh|&qA9!72uOCu+fs>cGU``rT`$#OJ@lJc8=j zEd4gCKg{ac&2#hKP#;&8&h*dZ)53XWZCDfH-%;d^oQm$o)hL90b&?C}p= Cf|mFI literal 0 HcmV?d00001 From 7de2f0ae812cc9a58dfb2a875c2090fde2411909 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Thu, 28 May 2026 14:13:00 -0500 Subject: [PATCH 14/20] feat: updated opcodes to match new dis hastable behavior --- xdis/opcodes/base.py | 66 +++++----- xdis/opcodes/opcode_3x/opcode_315.py | 174 ++++++++++++++------------- 2 files changed, 129 insertions(+), 111 deletions(-) diff --git a/xdis/opcodes/base.py b/xdis/opcodes/base.py index a8aafb62..b2c3ad6e 100644 --- a/xdis/opcodes/base.py +++ b/xdis/opcodes/base.py @@ -183,22 +183,23 @@ def binary_op(loc: dict, name: str, opcode: int, pop: int = 2, push: int = 1) -> def call_op( - loc: dict, name: str, opcode: int, pop: int = -2, push: int = 1, fallthrough: bool=True + loc: dict, name: str, opcode: int, pop: int = -2, push: int = 1, fallthrough: bool=True, include_in_dis_has_table: bool=True ) -> None: """ Put opcode in the class of instructions that perform calls. """ loc["callop"].add(opcode) - if "hasarg" in loc: + if "hasarg" in loc and include_in_dis_has_table: loc["hasarg"].append(opcode) - nargs_op(loc, name, opcode, pop, push, fallthrough) + nargs_op(loc, name, opcode, pop, push, fallthrough, include_in_dis_has_table=include_in_dis_has_table) -def compare_op(loc: dict, name: str, opcode: int, pop: int = 2, push: int = 1) -> None: +def compare_op(loc: dict, name: str, opcode: int, pop: int = 2, push: int = 1, include_in_dis_has_table: bool=True) -> None: def_op(loc, name, opcode, pop, push) - if "hasarg" in loc: + if "hasarg" in loc and include_in_dis_has_table: loc["hasarg"].append(opcode) - loc["hascompare"].append(opcode) + if include_in_dis_has_table: + loc["hascompare"].append(opcode) loc["binaryop"].add(opcode) @@ -206,11 +207,12 @@ def conditional_op(loc: dict, name: str, opcode: int) -> None: loc["hascompare"].append(opcode) -def const_op(loc: dict, name: str, opcode: int, pop: int = 0, push: int = 1) -> None: +def const_op(loc: dict, name: str, opcode: int, pop: int = 0, push: int = 1, include_in_dis_has_table: bool=True) -> None: def_op(loc, name, opcode, pop, push) - if "hasarg" in loc: + if "hasarg" in loc and include_in_dis_has_table: loc["hasarg"].append(opcode) - loc["hasconst"].append(opcode) + if include_in_dis_has_table: + loc["hasconst"].append(opcode) loc["nullaryop"].add(opcode) @@ -230,11 +232,12 @@ def def_op( loc["nofollow"].append(opcode) -def free_op(loc: dict, name: str, opcode: int, pop: int = 0, push: int = 1) -> None: +def free_op(loc: dict, name: str, opcode: int, pop: int = 0, push: int = 1, include_in_dis_has_table: bool=True) -> None: def_op(loc, name, opcode, pop, push) - if "hasarg" in loc: + if "hasarg" in loc and include_in_dis_has_table: loc["hasarg"].append(opcode) - loc["hasfree"].append(opcode) + if include_in_dis_has_table: + loc["hasfree"].append(opcode) def jabs_op( @@ -245,57 +248,62 @@ def jabs_op( push: int = 0, conditional: bool = False, fallthrough: bool = True, + include_in_dis_has_table: bool=True, ) -> None: """ Put opcode in the class of instructions that can perform an absolute jump. """ def_op(loc, name, opcode, pop, push, fallthrough=fallthrough) - loc["hasjabs"].append(opcode) - if "hasarg" in loc: + if include_in_dis_has_table: + loc["hasjabs"].append(opcode) + if "hasarg" in loc and include_in_dis_has_table: loc["hasarg"].append(opcode) if conditional: loc["hascondition"].append(opcode) -def jrel_op(loc, name: str, opcode: int, pop: int=0, push: int=0, conditional=False, fallthrough=True) -> None: +def jrel_op(loc, name: str, opcode: int, pop: int=0, push: int=0, conditional: bool=False, fallthrough: bool=True, include_in_dis_has_table: bool=True) -> None: """ Put opcode in the class of instructions that can perform a relative jump. """ def_op(loc, name, opcode, pop, push, fallthrough) - loc["hasjrel"].append(opcode) - if "hasarg" in loc: + if include_in_dis_has_table: + loc["hasjrel"].append(opcode) + if "hasarg" in loc and include_in_dis_has_table: loc["hasarg"].append(opcode) if conditional: loc["hascondition"].append(opcode) -def local_op(loc, name, opcode: int, pop=0, push=1) -> None: +def local_op(loc, name, opcode: int, pop=0, push=1, include_in_dis_has_table: bool=True) -> None: def_op(loc, name, opcode, pop, push) - if "hasarg" in loc: + if "hasarg" in loc and include_in_dis_has_table: loc["hasarg"].append(opcode) - loc["haslocal"].append(opcode) + if include_in_dis_has_table: + loc["haslocal"].append(opcode) loc["nullaryop"].add(opcode) -def name_op(loc: dict, op_name, opcode: int, pop=-2, push=-2) -> None: +def name_op(loc: dict, op_name, opcode: int, pop=-2, push=-2, include_in_dis_has_table: bool=True) -> None: """ Put opcode in the class of instructions that index into the "name" table. """ def_op(loc, op_name, opcode, pop, push) - loc["hasname"].append(opcode) - if "hasarg" in loc: + if include_in_dis_has_table: + loc["hasname"].append(opcode) + if "hasarg" in loc and include_in_dis_has_table: loc["hasarg"].append(opcode) loc["nullaryop"].add(opcode) def nargs_op( - loc, name: str, opcode: int, pop: int = -2, push: int = -1, fallthrough=True + loc, name: str, opcode: int, pop: int = -2, push: int = -1, fallthrough=True, include_in_dis_has_table: bool=True ) -> None: """ Put opcode in the class of instructions that have a variable number of (or *n*) arguments """ def_op(loc, name, opcode, pop, push, fallthrough=fallthrough) - if "hasarg" in loc: + if "hasarg" in loc and include_in_dis_has_table: loc["hasarg"].append(opcode) loc["hasnargs"].append(opcode) @@ -367,15 +375,15 @@ def rm_op(loc, name, op) -> None: del loc["opmap"][name] -def store_op(loc: dict, name: str, op, pop=0, push=1, is_type="def") -> None: +def store_op(loc: dict, name: str, op, pop=0, push=1, is_type="def", include_in_dis_has_table: bool=True) -> None: if is_type == "name": - name_op(loc, name, op, pop, push) + name_op(loc, name, op, pop, push, include_in_dis_has_table=include_in_dis_has_table) loc["nullaryop"].remove(op) elif is_type == "local": - local_op(loc, name, op, pop, push) + local_op(loc, name, op, pop, push, include_in_dis_has_table=include_in_dis_has_table) loc["nullaryop"].remove(op) elif is_type == "free": - free_op(loc, name, op, pop, push) + free_op(loc, name, op, pop, push, include_in_dis_has_table=include_in_dis_has_table) else: assert is_type == "def" def_op(loc, name, op, pop, push) diff --git a/xdis/opcodes/opcode_3x/opcode_315.py b/xdis/opcodes/opcode_3x/opcode_315.py index 0ce00b1b..79b6e181 100644 --- a/xdis/opcodes/opcode_3x/opcode_315.py +++ b/xdis/opcodes/opcode_3x/opcode_315.py @@ -62,7 +62,7 @@ def_op(loc, "CACHE", 0, 0, 0) def_op(loc, "BINARY_SLICE", 1, 3, 1) def_op(loc, "BUILD_TEMPLATE", 2, 2, 1) -local_op(loc, "BINARY_OP_INPLACE_ADD_UNICODE", 3, 2, 0) +local_op(loc, "BINARY_OP_INPLACE_ADD_UNICODE", 3, 2, 0, include_in_dis_has_table=False) def_op(loc, "CALL_FUNCTION_EX", 4, 4, 1) def_op(loc, "CHECK_EG_MATCH", 5, 2, 2) def_op(loc, "CHECK_EXC_MATCH", 6, 2, 2) @@ -133,7 +133,7 @@ def_op(loc, "GET_ITER", 70, 0, 1) name_op(loc, "IMPORT_FROM", 71, 1, 2) name_op(loc, "IMPORT_NAME", 72, 2, 1) -compare_op(loc, "IS_OP", 73, 2, 1) +compare_op(loc, "IS_OP", 73, 2, 1, include_in_dis_has_table=False) jrel_op(loc, "JUMP_BACKWARD", 74, 0, 0, conditional=False) jrel_op(loc, "JUMP_BACKWARD_NO_INTERRUPT", 75, 0, 0, conditional=False) jrel_op(loc, "JUMP_FORWARD", 76, 0, 0, conditional=False) @@ -182,6 +182,7 @@ def_op(loc, "YIELD_VALUE", 119, 1, 1) def_op(loc, "RESUME", 128, 0, 0) + # Specialized opcodes (>128) binary_op(loc, "BINARY_OP_ADD_FLOAT", 129, 2, 1) binary_op(loc, "BINARY_OP_ADD_INT", 130, 2, 1) @@ -195,86 +196,95 @@ binary_op(loc, "BINARY_OP_SUBSCR_LIST_SLICE", 138, 2, 1) binary_op(loc, "BINARY_OP_SUBSCR_STR_INT", 139, 2, 1) binary_op(loc, "BINARY_OP_SUBSCR_TUPLE_INT", 140, 2, 1) -binary_op(loc, "BINARY_OP_SUBTRACT_FLOAT", 141, 2, 1) -binary_op(loc, "BINARY_OP_SUBTRACT_INT", 142, 2, 1) -call_op(loc, "CALL_ALLOC_AND_ENTER_INIT", 143, -2, 0) # pops 2 + oparg -call_op(loc, "CALL_BOUND_METHOD_EXACT_ARGS", 144, -2, 0) # pops 2 + oparg -call_op(loc, "CALL_BOUND_METHOD_GENERAL", 145, -2, 0) # pops 2 + oparg -call_op(loc, "CALL_BUILTIN_CLASS", 146, -2, 1) # pops 2 + oparg -call_op(loc, "CALL_BUILTIN_FAST", 147, -2, 1) # pops 2 + oparg -call_op(loc, "CALL_BUILTIN_FAST_WITH_KEYWORDS", 148, -2, 1) # pops 2 + oparg -call_op(loc, "CALL_BUILTIN_O", 149, -2, 1) # pops 2 + oparg -def_op(loc, "CALL_ISINSTANCE", 150, 4, 1) -call_op(loc, "CALL_KW_BOUND_METHOD", 151, -3, 0) # pops 3 + oparg -call_op(loc, "CALL_KW_NON_PY", 152, -3, 1) # pops 3 + oparg -call_op(loc, "CALL_KW_PY", 153, -3, 0) # pops 3 + oparg -def_op(loc, "CALL_LEN", 154, 3, 1) -def_op(loc, "CALL_LIST_APPEND", 155, 3, 0) -call_op(loc, "CALL_METHOD_DESCRIPTOR_FAST", 156, -2, 1) # pops 2 + oparg -call_op(loc, "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", 157, -2, 1) # pops 2 + oparg -call_op(loc, "CALL_METHOD_DESCRIPTOR_NOARGS", 158, -2, 1) # pops 2 + oparg -call_op(loc, "CALL_METHOD_DESCRIPTOR_O", 159, -2, 1) # pops 2 + oparg -call_op(loc, "CALL_NON_PY_GENERAL", 160, -2, 1) # pops 2 + oparg -call_op(loc, "CALL_PY_EXACT_ARGS", 161, -2, 0) # pops 2 + oparg -call_op(loc, "CALL_PY_GENERAL", 162, -2, 0) # pops 2 + oparg -def_op(loc, "CALL_STR_1", 163, 3, 1) -def_op(loc, "CALL_TUPLE_1", 164, 3, 1) -def_op(loc, "CALL_TYPE_1", 165, 3, 1) -compare_op(loc, "COMPARE_OP_FLOAT", 166, 2, 1) -compare_op(loc, "COMPARE_OP_INT", 167, 2, 1) -compare_op(loc, "COMPARE_OP_STR", 168, 2, 1) -def_op(loc, "CONTAINS_OP_DICT", 169, 2, 1) -def_op(loc, "CONTAINS_OP_SET", 170, 2, 1) -jrel_op(loc, "FOR_ITER_GEN", 171, 2, 2, conditional=True) -jrel_op(loc, "FOR_ITER_LIST", 172, 2, 3, conditional=True) -jrel_op(loc, "FOR_ITER_RANGE", 173, 2, 3, conditional=True) -jrel_op(loc, "FOR_ITER_TUPLE", 174, 2, 3, conditional=True) -jrel_op(loc, "JUMP_BACKWARD_JIT", 175, 0, 0, conditional=False) -jrel_op(loc, "JUMP_BACKWARD_NO_JIT", 176, 0, 0, conditional=False) -def_op(loc, "LOAD_ATTR_CLASS", 177, 1, 1) # pushes 1 + (oparg & 1) -def_op(loc, "LOAD_ATTR_CLASS_WITH_METACLASS_CHECK", 178, 1, 1) # pushes 1 + (oparg & 1) -name_op(loc, "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN", 179, 1, 1) -def_op(loc, "LOAD_ATTR_INSTANCE_VALUE", 180, 1, 1) # pushes 1 + (oparg & 1) -def_op(loc, "LOAD_ATTR_METHOD_LAZY_DICT", 181, 1, 2) -def_op(loc, "LOAD_ATTR_METHOD_NO_DICT", 182, 1, 2) -def_op(loc, "LOAD_ATTR_METHOD_WITH_VALUES", 183, 1, 2) -def_op(loc, "LOAD_ATTR_MODULE", 184, 1, 1) # pushes 1 + (oparg & 1) -def_op(loc, "LOAD_ATTR_NONDESCRIPTOR_NO_DICT", 185, 1, 1) -def_op(loc, "LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", 186, 1, 1) -def_op(loc, "LOAD_ATTR_PROPERTY", 187, 1, 0) -def_op(loc, "LOAD_ATTR_SLOT", 188, 1, 1) # pushes 1 + (oparg & 1) -name_op(loc, "LOAD_ATTR_WITH_HINT", 189, 1, 1) # pushes 1 + (oparg & 1) -def_op(loc, "LOAD_GLOBAL_BUILTIN", 190, 0, 1) # pushes 1 + (oparg & 1) -def_op(loc, "LOAD_GLOBAL_MODULE", 191, 0, 1) # pushes 1 + (oparg & 1) -name_op(loc, "LOAD_SUPER_ATTR_ATTR", 192, 3, 1) -name_op(loc, "LOAD_SUPER_ATTR_METHOD", 193, 3, 2) -def_op(loc, "RESUME_CHECK", 194, 0, 0) -def_op(loc, "SEND_GEN", 195, 2, 1) -def_op(loc, "STORE_ATTR_INSTANCE_VALUE", 196, 2, 0) -def_op(loc, "STORE_ATTR_SLOT", 197, 2, 0) -store_op(loc, "STORE_ATTR_WITH_HINT", 198, 2, 0, is_type="name") -def_op(loc, "STORE_SUBSCR_DICT", 199, 3, 0) -def_op(loc, "STORE_SUBSCR_LIST_INT", 200, 3, 0) -def_op(loc, "TO_BOOL_ALWAYS_TRUE", 201, 1, 1) -def_op(loc, "TO_BOOL_BOOL", 202, 1, 1) -def_op(loc, "TO_BOOL_INT", 203, 1, 1) -def_op(loc, "TO_BOOL_LIST", 204, 1, 1) -def_op(loc, "TO_BOOL_NONE", 205, 1, 1) -def_op(loc, "TO_BOOL_STR", 206, 1, 1) -varargs_op(loc, "UNPACK_SEQUENCE_LIST", 207, 1, -1) -varargs_op(loc, "UNPACK_SEQUENCE_TUPLE", 208, 1, -1) -def_op(loc, "UNPACK_SEQUENCE_TWO_TUPLE", 209, 1, 2) +binary_op(loc, "BINARY_OP_SUBSCR_USTR_INT", 141, 2, 1) +binary_op(loc, "BINARY_OP_SUBTRACT_FLOAT", 142, 2, 1) +binary_op(loc, "BINARY_OP_SUBTRACT_INT", 143, 2, 1) +call_op(loc, "CALL_ALLOC_AND_ENTER_INIT", 144, -2, 0, include_in_dis_has_table=False) # pops 2 + oparg +call_op(loc, "CALL_BOUND_METHOD_EXACT_ARGS", 145, -2, 0, include_in_dis_has_table=False) # pops 2 + oparg +call_op(loc, "CALL_BOUND_METHOD_GENERAL", 146, -2, 0, include_in_dis_has_table=False) # pops 2 + oparg +call_op(loc, "CALL_BUILTIN_CLASS", 147, -2, 1, include_in_dis_has_table=False) # pops 2 + oparg +call_op(loc, "CALL_BUILTIN_FAST", 148, -2, 1, include_in_dis_has_table=False) # pops 2 + oparg +call_op(loc, "CALL_BUILTIN_FAST_WITH_KEYWORDS", 149, -2, 1, include_in_dis_has_table=False) # pops 2 + oparg +call_op(loc, "CALL_BUILTIN_O", 150, -2, 1, include_in_dis_has_table=False) # pops 2 + oparg +def_op(loc, "CALL_EX_NON_PY_GENERAL", 151, 4, 1) +def_op(loc, "CALL_EX_PY", 152, 4, 0) +def_op(loc, "CALL_ISINSTANCE", 153, 4, 1) +call_op(loc, "CALL_KW_BOUND_METHOD", 154, -3, 0, include_in_dis_has_table=False) # pops 3 + oparg +call_op(loc, "CALL_KW_NON_PY", 155, -3, 1, include_in_dis_has_table=False) # pops 3 + oparg +call_op(loc, "CALL_KW_PY", 156, -3, 0, include_in_dis_has_table=False) # pops 3 + oparg +def_op(loc, "CALL_LEN", 157, 3, 1) +def_op(loc, "CALL_LIST_APPEND", 158, 3, 1) +call_op(loc, "CALL_METHOD_DESCRIPTOR_FAST", 159, -2, 1, include_in_dis_has_table=False) # pops 2 + oparg +call_op(loc, "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", 160, -2, 1, include_in_dis_has_table=False) # pops 2 + oparg +call_op(loc, "CALL_METHOD_DESCRIPTOR_NOARGS", 161, -2, 1, include_in_dis_has_table=False) # pops 2 + oparg +call_op(loc, "CALL_METHOD_DESCRIPTOR_O", 162, -2, 1, include_in_dis_has_table=False) # pops 2 + oparg +call_op(loc, "CALL_NON_PY_GENERAL", 163, -2, 1, include_in_dis_has_table=False) # pops 2 + oparg +call_op(loc, "CALL_PY_EXACT_ARGS", 164, -2, 0, include_in_dis_has_table=False) # pops 2 + oparg +call_op(loc, "CALL_PY_GENERAL", 165, -2, 0, include_in_dis_has_table=False) # pops 2 + oparg +def_op(loc, "CALL_STR_1", 166, 3, 1) +def_op(loc, "CALL_TUPLE_1", 167, 3, 1) +def_op(loc, "CALL_TYPE_1", 168, 3, 1) +compare_op(loc, "COMPARE_OP_FLOAT", 169, 2, 1, include_in_dis_has_table=False) +compare_op(loc, "COMPARE_OP_INT", 170, 2, 1, include_in_dis_has_table=False) +compare_op(loc, "COMPARE_OP_STR", 171, 2, 1, include_in_dis_has_table=False) +def_op(loc, "CONTAINS_OP_DICT", 172, 2, 1) +def_op(loc, "CONTAINS_OP_SET", 173, 2, 1) +jrel_op(loc, "FOR_ITER_GEN", 174, 2, 2, conditional=True, include_in_dis_has_table=False) +jrel_op(loc, "FOR_ITER_LIST", 175, 2, 3, conditional=True, include_in_dis_has_table=False) +jrel_op(loc, "FOR_ITER_RANGE", 176, 2, 3, conditional=True, include_in_dis_has_table=False) +jrel_op(loc, "FOR_ITER_TUPLE", 177, 2, 3, conditional=True, include_in_dis_has_table=False) +jrel_op(loc, "FOR_ITER_VIRTUAL", 178, 2, 3, conditional=True, include_in_dis_has_table=False) +def_op(loc, "GET_ITER_SELF", 179, 1, 2) +def_op(loc, "GET_ITER_VIRTUAL", 180, 1, 2) +jrel_op(loc, "JUMP_BACKWARD_JIT", 181, 0, 0, conditional=False, include_in_dis_has_table=False) +jrel_op(loc, "JUMP_BACKWARD_NO_JIT", 182, 0, 0, conditional=False, include_in_dis_has_table=False) +def_op(loc, "LOAD_ATTR_CLASS", 183, 1, 1) # pushes 1 + (oparg & 1) +def_op(loc, "LOAD_ATTR_CLASS_WITH_METACLASS_CHECK", 184, 1, 1) # pushes 1 + (oparg & 1) +name_op(loc, "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN", 185, 1, 0, include_in_dis_has_table=False) +def_op(loc, "LOAD_ATTR_INSTANCE_VALUE", 186, 1, 1) # pushes 1 + (oparg & 1) +def_op(loc, "LOAD_ATTR_METHOD_LAZY_DICT", 187, 1, 2) +def_op(loc, "LOAD_ATTR_METHOD_NO_DICT", 188, 1, 2) +def_op(loc, "LOAD_ATTR_METHOD_WITH_VALUES", 189, 1, 2) +def_op(loc, "LOAD_ATTR_MODULE", 190, 1, 1) # pushes 1 + (oparg & 1) +def_op(loc, "LOAD_ATTR_NONDESCRIPTOR_NO_DICT", 191, 1, 1) +def_op(loc, "LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", 192, 1, 1) +def_op(loc, "LOAD_ATTR_PROPERTY", 193, 1, 0) +def_op(loc, "LOAD_ATTR_SLOT", 194, 1, 1) # pushes 1 + (oparg & 1) +name_op(loc, "LOAD_ATTR_WITH_HINT", 195, 1, 1, include_in_dis_has_table=False) # pushes 1 + (oparg & 1) +def_op(loc, "LOAD_GLOBAL_BUILTIN", 196, 0, 1) # pushes 1 + (oparg & 1) +def_op(loc, "LOAD_GLOBAL_MODULE", 197, 0, 1) # pushes 1 + (oparg & 1) +name_op(loc, "LOAD_SUPER_ATTR_ATTR", 198, 3, 1, include_in_dis_has_table=False) +name_op(loc, "LOAD_SUPER_ATTR_METHOD", 199, 3, 2, include_in_dis_has_table=False) +def_op(loc, "RESUME_CHECK", 200, 0, 0) +def_op(loc, "RESUME_CHECK_JIT", 201, 0, 0) +def_op(loc, "SEND_ASYNC_GEN", 202, 3, 3) +def_op(loc, "SEND_GEN", 203, 3, 2) +def_op(loc, "SEND_VIRTUAL", 204, 3, 3) +def_op(loc, "STORE_ATTR_INSTANCE_VALUE", 205, 2, 0) +def_op(loc, "STORE_ATTR_SLOT", 206, 2, 0) +store_op(loc, "STORE_ATTR_WITH_HINT", 207, 2, 0, is_type="name", include_in_dis_has_table=False) +def_op(loc, "STORE_SUBSCR_DICT", 208, 3, 0) +def_op(loc, "STORE_SUBSCR_LIST_INT", 209, 3, 0) +def_op(loc, "TO_BOOL_ALWAYS_TRUE", 210, 1, 1) +def_op(loc, "TO_BOOL_BOOL", 211, 1, 1) +def_op(loc, "TO_BOOL_INT", 212, 1, 1) +def_op(loc, "TO_BOOL_LIST", 213, 1, 1) +def_op(loc, "TO_BOOL_NONE", 214, 1, 1) +def_op(loc, "TO_BOOL_STR", 215, 1, 1) +varargs_op(loc, "UNPACK_SEQUENCE_LIST", 216, 1, -1) +varargs_op(loc, "UNPACK_SEQUENCE_TUPLE", 217, 1, -1) +def_op(loc, "UNPACK_SEQUENCE_TWO_TUPLE", 218, 1, 2) def_op(loc, "INSTRUMENTED_END_FOR", 233, 3, 2) def_op(loc, "INSTRUMENTED_POP_ITER", 234, 1, 0) def_op(loc, "INSTRUMENTED_END_SEND", 235, 2, 1) jrel_op(loc, "INSTRUMENTED_FOR_ITER", 236, 2, 1, conditional=True) def_op(loc, "INSTRUMENTED_INSTRUCTION", 237, 0, 1) -jrel_op(loc, "INSTRUMENTED_JUMP_FORWARD", 238, 0, 0, conditional=False) +jrel_op(loc, "INSTRUMENTED_JUMP_FORWARD", 238, 0, 0, conditional=False, include_in_dis_has_table=False) def_op(loc, "INSTRUMENTED_NOT_TAKEN", 239, 0, 0) -jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_TRUE", 240, 0, 0, conditional=True) # dunno why it's not 1, 0. -jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_FALSE", 241, 1, 0, conditional=True) -jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_NONE", 242, 1, 0, conditional=True) -jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_NOT_NONE", 243, 1, 0, conditional=True) +jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_TRUE", 240, 0, 0, conditional=True, include_in_dis_has_table=False) # dunno why it's not 1, 0. +jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_FALSE", 241, 1, 0, conditional=True, include_in_dis_has_table=False) +jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_NONE", 242, 1, 0, conditional=True, include_in_dis_has_table=False) +jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_NOT_NONE", 243, 1, 0, conditional=True, include_in_dis_has_table=False) def_op(loc, "INSTRUMENTED_RESUME", 244, 1, 0) # dunno why it's not 0, 0. def_op(loc, "INSTRUMENTED_RETURN_VALUE", 245, 1, 1) def_op(loc, "INSTRUMENTED_YIELD_VALUE", 246, 1, 1) @@ -282,8 +292,8 @@ name_op(loc, "INSTRUMENTED_LOAD_SUPER_ATTR", 248, VARYING_STACK_INT, 1) # pushes 1 + (oparg & 1) call_op(loc, "INSTRUMENTED_CALL", 249, -2, 1) call_op(loc, "INSTRUMENTED_CALL_KW", 250, -3, 1) -call_op(loc, "INSTRUMENTED_CALL_FUNCTION_EX", 251, 4, 1) -jrel_op(loc, "INSTRUMENTED_JUMP_BACKWARD", 252, 0, 0, conditional=False) +call_op(loc, "INSTRUMENTED_CALL_FUNCTION_EX", 251, 4, 1, include_in_dis_has_table=False) +jrel_op(loc, "INSTRUMENTED_JUMP_BACKWARD", 252, 0, 0, conditional=False, include_in_dis_has_table=False) def_op(loc, "INSTRUMENTED_LINE", 253, 0, 0) def_op(loc, "ENTER_EXECUTOR", 254, 0, 0) def_op(loc, "TRACE_RECORD", 255, 0, 0) @@ -297,12 +307,13 @@ def_op(loc, "SETUP_CLEANUP", 263, 0, 2) def_op(loc, "SETUP_FINALLY", 264, 0, 1) def_op(loc, "SETUP_WITH", 265, 0, 1) -def_op(loc, "STORE_FAST_MAYBE_NULL", 266, 1, 0) +local_op(loc, "STORE_FAST_MAYBE_NULL", 266, 1, 0) + # ops >= 42 have args HAVE_ARGUMENT = 42 -loc["hasarg"] = [42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 128, 143, 144, 145, 146, 147, 148, 149, 151, 152, 153, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 195, 198, 207, 208, 209, 236, 238, 240, 241, 242, 243, 244, 246, 247, 248, 249, 250, 252, 254, 255, 257, 258, 259, 260, 261, 263, 264, 265, 266] +loc["hasarg"] = [42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 128, 236, 238, 240, 241, 242, 243, 244, 246, 247, 248, 249, 250, 252, 254, 255, 257, 258, 259, 260, 261, 263, 264, 265, 266] # hasconst table populated by const_op definitions # hasname table populated by name_op and store_op definitions # jrel table populated by jrel_op definitions @@ -311,9 +322,9 @@ # hasfree table populated by free_op and store_op definitions # haslocal table populated by local_op and store_op definitions loc["hasexc"] = [263, 264, 265] +loc["hascompare"] = [loc["opmap"]["COMPARE_OP"]] # fmt: on - ### update formatting _nb_ops = [ @@ -346,7 +357,6 @@ ("NB_SUBSCR", "[]"), ] - def format_BINARY_OP_315(arg: int): return _nb_ops[arg][1] From 4ca26a146b6c819258d009e5da1d4246606e426e Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Thu, 28 May 2026 14:13:43 -0500 Subject: [PATCH 15/20] chore: added 3.15 tests to test infrastructure --- pytest/test_disasm.py | 3 ++- test/Makefile | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pytest/test_disasm.py b/pytest/test_disasm.py index a771188a..f3a68783 100644 --- a/pytest/test_disasm.py +++ b/pytest/test_disasm.py @@ -103,7 +103,8 @@ def run_check_disasm(test_tuple, function_to_test): ("03_big_dict", "3.3", ["classic", "xasm"]), ("03_big_dict", "3.5", ["classic", "xasm"]), ("03_big_dict", "3.6", ["classic", "xasm"]), - ("03_big_dict", "3.6", ["classic", "xasm"]), + ("03_big_dict", "3.15", ["classic", "xasm"]), + ("01_frozendict", "3.15", ["classic", "xasm"]), ("03_annotations", "3.7", ["classic", "xasm"]), ("test_nested_scopes", "2.1", ["extended-bytes"]), # ("01_augmented_assign", "3.7", ["extended-bytes"]), diff --git a/test/Makefile b/test/Makefile index 87661f3f..de2e7423 100644 --- a/test/Makefile +++ b/test/Makefile @@ -23,7 +23,7 @@ check: check-short check-roundtrip --bytecode-3.6 --bytecode-3.7 --bytecode-3.8 \ --bytecode-3.9 --bytecode-3.10 \ --bytecode-3.11 --bytecode-3.12 --bytecode-3.13 \ - --bytecode-3.14 \ + --bytecode-3.14 --bytecode-3.15 \ --bytecode-2.7pypy --bytecode-3.2pypy \ --bytecode-pypy35 --bytecode-pypy36 --bytecode-pypy37 \ --bytecode-pypy38 --bytecode-pypy39 --bytecode-pypy310 \ From b6f218b580f8d36376e38b47209f35903e350084 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Thu, 28 May 2026 14:13:48 -0500 Subject: [PATCH 16/20] feat: added 3.15 frozendict marshalling test. --- test_unit/test_marsh.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/test_unit/test_marsh.py b/test_unit/test_marsh.py index c2fde03c..cb2b3441 100644 --- a/test_unit/test_marsh.py +++ b/test_unit/test_marsh.py @@ -3,6 +3,7 @@ import os, unittest from xdis.load import load_module +from xdis.cross_types import FrozenDictPrePython315 def get_srcdir(): filename = os.path.normcase(os.path.dirname(os.path.abspath(__file__))) @@ -19,18 +20,32 @@ def test_basic(self): '02_complex.pyc') (version, timestamp, magic_int, co, is_pypy, - source_size) = load_module(mod_file) - self.assertEqual(version, 2.5, + source_size, *_) = load_module(mod_file) + self.assertEqual(version, (2, 5), "Should have picked up Python version properly") assert co.co_consts == (5j, None), "Code should have a complex constant" mod_file = os.path.join(get_srcdir(), '..', 'test', 'bytecode_3.3', '06_frozenset.pyc') (version, timestamp, magic_int, co, is_pypy, - source_size) = load_module(mod_file) + source_size, *_) = load_module(mod_file) expect = (0, None, 'attlist', 'linktype', 'link', 'element', 'Yep', frozenset(['linktype', 'attlist', 'element', 'link'])) self.assertEqual(co.co_consts, expect, "Should handle frozenset") + mod_file = os.path.join(get_srcdir(), '..', 'test', 'bytecode_3.15', + '01_frozendict.pyc') + (version, timestamp, magic_int, co, is_pypy, + source_size, *_) = load_module(mod_file) + self.assertEqual(version, (3, 15), + "Should have picked up Python version properly") + self.assertEqual(co.co_consts[0], 'Testing frozendict cross-version support!') + fd = co.co_consts[1] + if version < (3, 15): + self.assertIsInstance(fd, FrozenDictPrePython315) + else: + self.assertIsInstance(fd, frozendict) + self.assertEqual(dict(fd), {'hello': 'cross-version-world'}) + if __name__ == '__main__': unittest.main() From af9fb41d5fa6d9994954b8002f47192c7f0d86f1 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Thu, 28 May 2026 14:13:52 -0500 Subject: [PATCH 17/20] fix: updated get_opcode_module() to use sys.version_info and PythonImplementation.CPython --- test_unit/test_modules.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_unit/test_modules.py b/test_unit/test_modules.py index bf70fd05..66e40a87 100644 --- a/test_unit/test_modules.py +++ b/test_unit/test_modules.py @@ -2,7 +2,7 @@ import dis import unittest import xdis.std as xdis -from xdis.version_info import version_tuple_to_str +from xdis.version_info import version_tuple_to_str, PythonImplementation class TestModules(unittest.TestCase): @@ -25,7 +25,7 @@ def test_basic(self): raise ae # test "has.." tables - xmod = xdis.get_opcode_module() + xmod = xdis.get_opcode_module(sys.version_info, PythonImplementation.CPython) attrs = (attr for attr in dir(dis) if attr.startswith("has")) for attr in attrs: try: From 93a897fe57308ea85b748b09af2db1520dc87e11 Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Thu, 28 May 2026 15:08:22 -0500 Subject: [PATCH 18/20] chore: added verified 3.15 .right test data files Frozendict and big_dict disassembly reference files for 3.15. --- pytest/testdata/01_frozendict-3.15.right | 26 + pytest/testdata/01_frozendict-xasm-3.15.right | 29 + pytest/testdata/03_big_dict-3.15.right | 776 ++++++++++++++ pytest/testdata/03_big_dict-xasm-3.15.right | 995 ++++++++++++++++++ 4 files changed, 1826 insertions(+) create mode 100644 pytest/testdata/01_frozendict-3.15.right create mode 100644 pytest/testdata/01_frozendict-xasm-3.15.right create mode 100644 pytest/testdata/03_big_dict-3.15.right create mode 100644 pytest/testdata/03_big_dict-xasm-3.15.right diff --git a/pytest/testdata/01_frozendict-3.15.right b/pytest/testdata/01_frozendict-3.15.right new file mode 100644 index 00000000..59a70ad1 --- /dev/null +++ b/pytest/testdata/01_frozendict-3.15.right @@ -0,0 +1,26 @@ +# Source code size mod 2**32: 50 bytes +# Method Name: +# Filename: dummy.py +# Argument count: 0 +# Position-only argument count: 0 +# Keyword-only arguments: 0 +# Number of locals: 0 +# Stack size: 3 +# Flags: 0x00000000 (0x0) +# First Line: 1 +# Constants: +# 0: 'Testing frozendict cross-version support!' +# 1: frozendict({'hello': 'cross-version-world'}) +# Names: +# 0: print + + 0: 0 RESUME 0 + + 1: 4 LOAD_NAME (print) + 6 PUSH_NULL + 8 LOAD_CONST ("Testing frozendict cross-version support!") + 10 CALL (1 positional) + 18 POP_TOP + 20 LOAD_COMMON_CONSTANT (None) + 22 RETURN_VALUE + diff --git a/pytest/testdata/01_frozendict-xasm-3.15.right b/pytest/testdata/01_frozendict-xasm-3.15.right new file mode 100644 index 00000000..75fdc525 --- /dev/null +++ b/pytest/testdata/01_frozendict-xasm-3.15.right @@ -0,0 +1,29 @@ +# Source code size mod 2**32: 50 bytes + +# Method Name: +# Filename: dummy.py +# Argument count: 0 +# Position-only argument count: 0 +# Keyword-only arguments: 0 +# Number of locals: 0 +# Stack size: 3 +# Flags: 0x00000000 (0x0) +# First Line: 1 +# Constants: +# 0: 'Testing frozendict cross-version support!' +# 1: frozendict({'hello': 'cross-version-world'}) +# Names: +# 0: print + + 0: + RESUME 0 + + 1: + LOAD_NAME 0 (print) + PUSH_NULL + LOAD_CONST 0 ("Testing frozendict cross-version support!") + CALL 1 (1 positional) + POP_TOP + LOAD_COMMON_CONSTANT 7 (None) + RETURN_VALUE + diff --git a/pytest/testdata/03_big_dict-3.15.right b/pytest/testdata/03_big_dict-3.15.right new file mode 100644 index 00000000..cdd5945e --- /dev/null +++ b/pytest/testdata/03_big_dict-3.15.right @@ -0,0 +1,776 @@ +# Source code size mod 2**32: 4714 bytes +# Method Name: +# Filename: test/simple_source/03_big_dict.py +# Argument count: 0 +# Position-only argument count: 0 +# Keyword-only arguments: 0 +# Number of locals: 0 +# Stack size: 23 +# Flags: 0x00000000 (0x0) +# First Line: 1 +# Constants: +# 0: 'BINARY_ADD' +# 1: 'BINARY_SUBTRACT' +# 2: 'BINARY_MULTIPLY' +# 3: 'BINARY_DIVIDE' +# 4: 'BINARY_MATRIX_MULTIPLY' +# 5: 'BINARY_TRUE_DIVIDE' +# 6: 'BINARY_FLOOR_DIVIDE' +# 7: 'BINARY_MODULO' +# 8: 'BINARY_POWER' +# 9: 'BINARY_LSHIFT' +# 10: 'BINARY_RSHIFT' +# 11: 'BINARY_AND' +# 12: 'BINARY_OR' +# 13: 'BINARY_XOR' +# 14: 'INPLACE_ADD' +# 15: 'INPLACE_SUBTRACT' +# 16: 'INPLACE_MULTIPLY' +# 17: 'INPLACE_MATRIX_MULTIPLY' +# 18: 'INPLACE_DIVIDE' +# 19: 'INPLACE_TRUE_DIVIDE' +# 20: 'INPLACE_FLOOR_DIVIDE' +# 21: 'INPLACE_MODULO' +# 22: 'INPLACE_POWER' +# 23: 'INPLACE_LSHIFT' +# 24: 'INPLACE_RSHIFT' +# 25: 'INPLACE_AND' +# 26: 'INPLACE_OR' +# 27: 'INPLACE_XOR' +# 28: 'binary_expr' +# 29: 'UNARY_POSITIVE' +# 30: 'UNARY_NEGATIVE' +# 31: 'UNARY_INVERT' +# 32: '~%c' +# 33: 'unary_expr' +# 34: 'unary_not' +# 35: 'unary_convert' +# 36: 'get_iter' +# 37: 'slice0' +# 38: 'slice1' +# 39: 'slice2' +# 40: 'slice3' +# 41: 'IMPORT_FROM' +# 42: 'load_attr' +# 43: 'LOAD_FAST' +# 44: 'LOAD_NAME' +# 45: 'LOAD_CLASSNAME' +# 46: 'LOAD_GLOBAL' +# 47: 'LOAD_DEREF' +# 48: 'LOAD_LOCALS' +# 49: 'LOAD_ASSERT' +# 50: 'DELETE_FAST' +# 51: 'DELETE_NAME' +# 52: 'DELETE_GLOBAL' +# 53: 'delete_subscr' +# 54: 'binary_subscr' +# 55: 'binary_subscr2' +# 56: 'store_subscr' +# 57: 'STORE_FAST' +# 58: 'STORE_NAME' +# 59: 'STORE_GLOBAL' +# 60: 'STORE_DEREF' +# 61: 'unpack' +# 62: 'unpack_w_parens' +# 63: 'unpack_list' +# 64: 'build_tuple2' +# 65: 'list_iter' +# 66: 'list_for' +# 67: 'list_if' +# 68: 'list_if_not' +# 69: 'lc_body' +# 70: 'comp_body' +# 71: 'set_comp_body' +# 72: 'gen_comp_body' +# 73: 'dict_comp_body' +# 74: 'assign' +# 75: 'augassign1' +# 76: 'augassign2' +# 77: 'designList' +# 78: 'and' +# 79: 'ret_and' +# 80: 'and2' +# 81: 'or' +# 82: 'ret_or' +# 83: 'conditional' +# 84: 'conditionalTrue' +# 85: 'ret_cond' +# 86: 'conditionalnot' +# 87: 'ret_cond_not' +# 88: 'conditional_lambda' +# 89: 'return_lambda' +# 90: 'compare' +# 91: 'cmp_list' +# 92: 'cmp_list1' +# 93: 'cmp_list2' +# 94: 'funcdef' +# 95: 'funcdefdeco' +# 96: 'mkfuncdeco' +# 97: 'mkfuncdeco0' +# 98: 'classdefdeco' +# 99: 'classdefdeco1' +# 100: 'kwarg' +# 101: 'kwargs' +# 102: 'assert_expr_or' +# 103: 'assert_expr_and' +# 104: 'print_items_stmt' +# 105: 'print_items_nl_stmt' +# 106: 'print_item' +# 107: 'print_nl' +# 108: 'print_to' +# 109: 'print_to_nl' +# 110: 'print_nl_to' +# 111: 'print_to_items' +# 112: 'kv' +# 113: 'kv2' +# 114: ('+',) +# 115: ('-',) +# 116: ('*',) +# 117: ('/',) +# 118: ('@',) +# 119: ('//',) +# 120: ('%%',) +# 121: ('**',) +# 122: ('<<',) +# 123: ('>>',) +# 124: ('&',) +# 125: ('|',) +# 126: ('^',) +# 127: ('+=',) +# 128: ('-=',) +# 129: ('*=',) +# 130: ('@=',) +# 131: ('/=',) +# 132: ('//=',) +# 133: ('%%=',) +# 134: ('**=',) +# 135: ('<<=',) +# 136: ('>>=',) +# 137: ('&=',) +# 138: ('|=',) +# 139: ('^=',) +# 140: ('%c %c %c', 0, -1, 1) +# 141: ('%c%c', 1, 0) +# 142: ('not %c', 0) +# 143: ('`%c`', 0) +# 144: ('iter(%c)', 0) +# 145: ('%c[:]', 0) +# 146: ('%c[%p:]', 0, (1, 100)) +# 147: ('%c[:%p]', 0, (1, 100)) +# 148: ('%c[%p:%p]', 0, (1, 100), (2, 100)) +# 149: ('%{pattr}',) +# 150: ('%c.%[1]{pattr}', 0) +# 151: ('locals()',) +# 152: ('%|del %{pattr}\n',) +# 153: ('%|del %c[%c]\n', 0, 1) +# 154: ('%c[%p]', 0, (1, 100)) +# 155: ('%c[%c]', 0, 1) +# 156: ('%C%,', (1, 5, ', ')) +# 157: ('(%C%,)', (1, 10, ', ')) +# 158: ('[%C]', (1, 15, ', ')) +# 159: ('%P', (0, -1, ', ', 100)) +# 160: ('%c', 0) +# 161: (' for %c in %c%c', 2, 0, 3) +# 162: (' if %c%c', 0, 2) +# 163: (' if not %p%c', (0, 22), 2) +# 164: ('',) +# 165: ('%c:%c', 1, 0) +# 166: ('%|%c = %p\n', -1, (0, 200)) +# 167: ('%|%c %c %c\n', 0, 2, 1) +# 168: ('%|%c.%[2]{pattr} %c %c\n', 0, -3, -4) +# 169: ('%c = %c', 0, -1) +# 170: ('%c and %c', 0, 2) +# 171: ('%c', 3) +# 172: ('%c or %c', 0, 2) +# 173: ('%p if %p else %p', (2, 27), (0, 27), (4, 27)) +# 174: ('%p if 1 else %p', (0, 27), (2, 27)) +# 175: ('%p if %p else %p', (2, 27), (0, 27), (-1, 27)) +# 176: ('%p if not %p else %p', (2, 27), (0, 22), (4, 27)) +# 177: ('%p if not %p else %p', (2, 27), (0, 22), (-1, 27)) +# 178: ('(%c if %c else %c)', 2, 0, 3) +# 179: ('%p %[-1]{pattr} %p', (0, 19), (1, 19)) +# 180: ('%p %p', (0, 29), (1, 30)) +# 181: ('%[3]{pattr} %p %p', (0, 19), (-2, 19)) +# 182: ('%[1]{pattr} %p', (0, 19)) +# 183: ('\n\n%|def %c\n', -2) +# 184: ('\n\n%c', 0) +# 185: ('%|@%c\n%c', 0, 1) +# 186: ('%|def %c\n', 0) +# 187: ('%[0]{pattr}=%c', 1) +# 188: ('%D', (0, 10000, ', ')) +# 189: ('%|print %c%c,\n', 0, 2) +# 190: ('%|print %c%c\n', 0, 2) +# 191: (', %c', 0) +# 192: ('%|print\n',) +# 193: ('%|print >> %c, %c,\n', 0, 1) +# 194: ('%|print >> %c, %c\n', 0, 1) +# 195: ('%|print >> %c\n', 0) +# 196: ('%C', (0, 2, ', ')) +# 197: ('%c: %c', 3, 1) +# 198: ('%c: %c', 1, 2) +# Names: +# 0: TABLE_DIRECT + + 0: 0 RESUME 0 + + 1: 4 BUILD_MAP 0 + + 2: 6 LOAD_CONST ("BINARY_ADD") + 8 LOAD_CONST (('+',)) + + 1: 10 MAP_ADD 1 + + 3: 12 LOAD_CONST ("BINARY_SUBTRACT") + 14 LOAD_CONST (('-',)) + + 1: 16 MAP_ADD 1 + + 4: 18 LOAD_CONST ("BINARY_MULTIPLY") + 20 LOAD_CONST (('*',)) + + 1: 22 MAP_ADD 1 + + 5: 24 LOAD_CONST ("BINARY_DIVIDE") + 26 LOAD_CONST (('/',)) + + 1: 28 MAP_ADD 1 + + 6: 30 LOAD_CONST ("BINARY_MATRIX_MULTIPLY") + 32 LOAD_CONST (('@',)) + + 1: 34 MAP_ADD 1 + + 7: 36 LOAD_CONST ("BINARY_TRUE_DIVIDE") + 38 LOAD_CONST (('/',)) + + 1: 40 MAP_ADD 1 + + 8: 42 LOAD_CONST ("BINARY_FLOOR_DIVIDE") + 44 LOAD_CONST (('//',)) + + 1: 46 MAP_ADD 1 + + 9: 48 LOAD_CONST ("BINARY_MODULO") + 50 LOAD_CONST (('%%',)) + + 1: 52 MAP_ADD 1 + + 10: 54 LOAD_CONST ("BINARY_POWER") + 56 LOAD_CONST (('**',)) + + 1: 58 MAP_ADD 1 + + 11: 60 LOAD_CONST ("BINARY_LSHIFT") + 62 LOAD_CONST (('<<',)) + + 1: 64 MAP_ADD 1 + + 12: 66 LOAD_CONST ("BINARY_RSHIFT") + 68 LOAD_CONST (('>>',)) + + 1: 70 MAP_ADD 1 + + 13: 72 LOAD_CONST ("BINARY_AND") + 74 LOAD_CONST (('&',)) + + 1: 76 MAP_ADD 1 + + 14: 78 LOAD_CONST ("BINARY_OR") + 80 LOAD_CONST (('|',)) + + 1: 82 MAP_ADD 1 + + 15: 84 LOAD_CONST ("BINARY_XOR") + 86 LOAD_CONST (('^',)) + + 1: 88 MAP_ADD 1 + + 16: 90 LOAD_CONST ("INPLACE_ADD") + 92 LOAD_CONST (('+=',)) + + 1: 94 MAP_ADD 1 + + 17: 96 LOAD_CONST ("INPLACE_SUBTRACT") + 98 LOAD_CONST (('-=',)) + + 1: 100 MAP_ADD 1 + + 18: 102 LOAD_CONST ("INPLACE_MULTIPLY") + 104 LOAD_CONST (('*=',)) + + 1: 106 MAP_ADD 1 + 108 BUILD_MAP 0 + + 19: 110 LOAD_CONST ("INPLACE_MATRIX_MULTIPLY") + 112 LOAD_CONST (('@=',)) + + 1: 114 MAP_ADD 1 + + 20: 116 LOAD_CONST ("INPLACE_DIVIDE") + 118 LOAD_CONST (('/=',)) + + 1: 120 MAP_ADD 1 + + 21: 122 LOAD_CONST ("INPLACE_TRUE_DIVIDE") + 124 LOAD_CONST (('/=',)) + + 1: 126 MAP_ADD 1 + + 22: 128 LOAD_CONST ("INPLACE_FLOOR_DIVIDE") + 130 LOAD_CONST (('//=',)) + + 1: 132 MAP_ADD 1 + + 23: 134 LOAD_CONST ("INPLACE_MODULO") + 136 LOAD_CONST (('%%=',)) + + 1: 138 MAP_ADD 1 + + 24: 140 LOAD_CONST ("INPLACE_POWER") + 142 LOAD_CONST (('**=',)) + + 1: 144 MAP_ADD 1 + + 25: 146 LOAD_CONST ("INPLACE_LSHIFT") + 148 LOAD_CONST (('<<=',)) + + 1: 150 MAP_ADD 1 + + 26: 152 LOAD_CONST ("INPLACE_RSHIFT") + 154 LOAD_CONST (('>>=',)) + + 1: 156 MAP_ADD 1 + + 27: 158 LOAD_CONST ("INPLACE_AND") + 160 LOAD_CONST (('&=',)) + + 1: 162 MAP_ADD 1 + + 28: 164 LOAD_CONST ("INPLACE_OR") + 166 LOAD_CONST (('|=',)) + + 1: 168 MAP_ADD 1 + + 29: 170 LOAD_CONST ("INPLACE_XOR") + 172 LOAD_CONST (('^=',)) + + 1: 174 MAP_ADD 1 + + 30: 176 LOAD_CONST ("binary_expr") + 178 LOAD_CONST (('%c %c %c', 0, -1, 1)) + + 1: 180 MAP_ADD 1 + + 32: 182 LOAD_CONST ("UNARY_POSITIVE") + 184 LOAD_CONST (('+',)) + + 1: 186 MAP_ADD 1 + + 33: 188 LOAD_CONST ("UNARY_NEGATIVE") + 190 LOAD_CONST (('-',)) + + 1: 192 MAP_ADD 1 + + 34: 194 LOAD_CONST ("UNARY_INVERT") + 196 LOAD_CONST ("~%c") + + 1: 198 MAP_ADD 1 + + 35: 200 LOAD_CONST ("unary_expr") + 202 LOAD_CONST (('%c%c', 1, 0)) + + 1: 204 MAP_ADD 1 + + 37: 206 LOAD_CONST ("unary_not") + 208 LOAD_CONST (('not %c', 0)) + + 1: 210 MAP_ADD 1 + 212 DICT_UPDATE 1 + 214 BUILD_MAP 0 + + 38: 216 LOAD_CONST ("unary_convert") + 218 LOAD_CONST (('`%c`', 0)) + + 1: 220 MAP_ADD 1 + + 39: 222 LOAD_CONST ("get_iter") + 224 LOAD_CONST (('iter(%c)', 0)) + + 1: 226 MAP_ADD 1 + + 40: 228 LOAD_CONST ("slice0") + 230 LOAD_CONST (('%c[:]', 0)) + + 1: 232 MAP_ADD 1 + + 41: 234 LOAD_CONST ("slice1") + 236 LOAD_CONST (('%c[%p:]', 0, (1, 100))) + + 1: 238 MAP_ADD 1 + + 42: 240 LOAD_CONST ("slice2") + 242 LOAD_CONST (('%c[:%p]', 0, (1, 100))) + + 1: 244 MAP_ADD 1 + + 43: 246 LOAD_CONST ("slice3") + 248 LOAD_CONST (('%c[%p:%p]', 0, (1, 100), (2, 100))) + + 1: 250 MAP_ADD 1 + + 45: 252 LOAD_CONST ("IMPORT_FROM") + 254 LOAD_CONST (('%{pattr}',)) + + 1: 256 MAP_ADD 1 + + 46: 258 LOAD_CONST ("load_attr") + 260 LOAD_CONST (('%c.%[1]{pattr}', 0)) + + 1: 262 MAP_ADD 1 + + 47: 264 LOAD_CONST ("LOAD_FAST") + 266 LOAD_CONST (('%{pattr}',)) + + 1: 268 MAP_ADD 1 + + 48: 270 LOAD_CONST ("LOAD_NAME") + 272 LOAD_CONST (('%{pattr}',)) + + 1: 274 MAP_ADD 1 + + 49: 276 LOAD_CONST ("LOAD_CLASSNAME") + 278 LOAD_CONST (('%{pattr}',)) + + 1: 280 MAP_ADD 1 + + 50: 282 LOAD_CONST ("LOAD_GLOBAL") + 284 LOAD_CONST (('%{pattr}',)) + + 1: 286 MAP_ADD 1 + + 51: 288 LOAD_CONST ("LOAD_DEREF") + 290 LOAD_CONST (('%{pattr}',)) + + 1: 292 MAP_ADD 1 + + 52: 294 LOAD_CONST ("LOAD_LOCALS") + 296 LOAD_CONST (('locals()',)) + + 1: 298 MAP_ADD 1 + + 53: 300 LOAD_CONST ("LOAD_ASSERT") + 302 LOAD_CONST (('%{pattr}',)) + + 1: 304 MAP_ADD 1 + + 54: 306 LOAD_CONST ("DELETE_FAST") + 308 LOAD_CONST (('%|del %{pattr}\n',)) + + 1: 310 MAP_ADD 1 + + 55: 312 LOAD_CONST ("DELETE_NAME") + 314 LOAD_CONST (('%|del %{pattr}\n',)) + + 1: 316 MAP_ADD 1 + 318 DICT_UPDATE 1 + 320 BUILD_MAP 0 + + 56: 322 LOAD_CONST ("DELETE_GLOBAL") + 324 LOAD_CONST (('%|del %{pattr}\n',)) + + 1: 326 MAP_ADD 1 + + 57: 328 LOAD_CONST ("delete_subscr") + 330 LOAD_CONST (('%|del %c[%c]\n', 0, 1)) + + 1: 332 MAP_ADD 1 + + 58: 334 LOAD_CONST ("binary_subscr") + 336 LOAD_CONST (('%c[%p]', 0, (1, 100))) + + 1: 338 MAP_ADD 1 + + 59: 340 LOAD_CONST ("binary_subscr2") + 342 LOAD_CONST (('%c[%p]', 0, (1, 100))) + + 1: 344 MAP_ADD 1 + + 60: 346 LOAD_CONST ("store_subscr") + 348 LOAD_CONST (('%c[%c]', 0, 1)) + + 1: 350 MAP_ADD 1 + + 61: 352 LOAD_CONST ("STORE_FAST") + 354 LOAD_CONST (('%{pattr}',)) + + 1: 356 MAP_ADD 1 + + 62: 358 LOAD_CONST ("STORE_NAME") + 360 LOAD_CONST (('%{pattr}',)) + + 1: 362 MAP_ADD 1 + + 63: 364 LOAD_CONST ("STORE_GLOBAL") + 366 LOAD_CONST (('%{pattr}',)) + + 1: 368 MAP_ADD 1 + + 64: 370 LOAD_CONST ("STORE_DEREF") + 372 LOAD_CONST (('%{pattr}',)) + + 1: 374 MAP_ADD 1 + + 65: 376 LOAD_CONST ("unpack") + 378 LOAD_CONST (('%C%,', (1, 5, ', '))) + + 1: 380 MAP_ADD 1 + + 66: 382 LOAD_CONST ("unpack_w_parens") + 384 LOAD_CONST (('(%C%,)', (1, 10, ', '))) + + 1: 386 MAP_ADD 1 + + 68: 388 LOAD_CONST ("unpack_list") + 390 LOAD_CONST (('[%C]', (1, 15, ', '))) + + 1: 392 MAP_ADD 1 + + 69: 394 LOAD_CONST ("build_tuple2") + 396 LOAD_CONST (('%P', (0, -1, ', ', 100))) + + 1: 398 MAP_ADD 1 + + 71: 400 LOAD_CONST ("list_iter") + 402 LOAD_CONST (('%c', 0)) + + 1: 404 MAP_ADD 1 + + 72: 406 LOAD_CONST ("list_for") + 408 LOAD_CONST ((' for %c in %c%c', 2, 0, 3)) + + 1: 410 MAP_ADD 1 + + 73: 412 LOAD_CONST ("list_if") + 414 LOAD_CONST ((' if %c%c', 0, 2)) + + 1: 416 MAP_ADD 1 + + 74: 418 LOAD_CONST ("list_if_not") + 420 LOAD_CONST ((' if not %p%c', (0, 22), 2)) + + 1: 422 MAP_ADD 1 + 424 DICT_UPDATE 1 + 426 BUILD_MAP 0 + + 75: 428 LOAD_CONST ("lc_body") + 430 LOAD_CONST (('',)) + + 1: 432 MAP_ADD 1 + + 77: 434 LOAD_CONST ("comp_body") + 436 LOAD_CONST (('',)) + + 1: 438 MAP_ADD 1 + + 78: 440 LOAD_CONST ("set_comp_body") + 442 LOAD_CONST (('%c', 0)) + + 1: 444 MAP_ADD 1 + + 79: 446 LOAD_CONST ("gen_comp_body") + 448 LOAD_CONST (('%c', 0)) + + 1: 450 MAP_ADD 1 + + 80: 452 LOAD_CONST ("dict_comp_body") + 454 LOAD_CONST (('%c:%c', 1, 0)) + + 1: 456 MAP_ADD 1 + + 82: 458 LOAD_CONST ("assign") + 460 LOAD_CONST (('%|%c = %p\n', -1, (0, 200))) + + 1: 462 MAP_ADD 1 + + 84: 464 LOAD_CONST ("augassign1") + 466 LOAD_CONST (('%|%c %c %c\n', 0, 2, 1)) + + 1: 468 MAP_ADD 1 + + 86: 470 LOAD_CONST ("augassign2") + 472 LOAD_CONST (('%|%c.%[2]{pattr} %c %c\n', 0, -3, -4)) + + 1: 474 MAP_ADD 1 + + 87: 476 LOAD_CONST ("designList") + 478 LOAD_CONST (('%c = %c', 0, -1)) + + 1: 480 MAP_ADD 1 + + 88: 482 LOAD_CONST ("and") + 484 LOAD_CONST (('%c and %c', 0, 2)) + + 1: 486 MAP_ADD 1 + + 89: 488 LOAD_CONST ("ret_and") + 490 LOAD_CONST (('%c and %c', 0, 2)) + + 1: 492 MAP_ADD 1 + + 90: 494 LOAD_CONST ("and2") + 496 LOAD_CONST (('%c', 3)) + + 1: 498 MAP_ADD 1 + + 91: 500 LOAD_CONST ("or") + 502 LOAD_CONST (('%c or %c', 0, 2)) + + 1: 504 MAP_ADD 1 + + 92: 506 LOAD_CONST ("ret_or") + 508 LOAD_CONST (('%c or %c', 0, 2)) + + 1: 510 MAP_ADD 1 + + 93: 512 LOAD_CONST ("conditional") + 514 LOAD_CONST (('%p if %p else %p', (2, 27), (0, 27), (4, 27))) + + 1: 516 MAP_ADD 1 + + 94: 518 LOAD_CONST ("conditionalTrue") + 520 LOAD_CONST (('%p if 1 else %p', (0, 27), (2, 27))) + + 1: 522 MAP_ADD 1 + + 95: 524 LOAD_CONST ("ret_cond") + 526 LOAD_CONST (('%p if %p else %p', (2, 27), (0, 27), (-1, 27))) + + 1: 528 MAP_ADD 1 + 530 DICT_UPDATE 1 + 532 BUILD_MAP 0 + + 96: 534 LOAD_CONST ("conditionalnot") + 536 LOAD_CONST (('%p if not %p else %p', (2, 27), (0, 22), (4, 27))) + + 1: 538 MAP_ADD 1 + + 97: 540 LOAD_CONST ("ret_cond_not") + 542 LOAD_CONST (('%p if not %p else %p', (2, 27), (0, 22), (-1, 27))) + + 1: 544 MAP_ADD 1 + + 98: 546 LOAD_CONST ("conditional_lambda") + 548 LOAD_CONST (('(%c if %c else %c)', 2, 0, 3)) + + 1: 550 MAP_ADD 1 + + 99: 552 LOAD_CONST ("return_lambda") + 554 LOAD_CONST (('%c', 0)) + + 1: 556 MAP_ADD 1 + +100: 558 LOAD_CONST ("compare") + 560 LOAD_CONST (('%p %[-1]{pattr} %p', (0, 19), (1, 19))) + + 1: 562 MAP_ADD 1 + +101: 564 LOAD_CONST ("cmp_list") + 566 LOAD_CONST (('%p %p', (0, 29), (1, 30))) + + 1: 568 MAP_ADD 1 + +102: 570 LOAD_CONST ("cmp_list1") + 572 LOAD_CONST (('%[3]{pattr} %p %p', (0, 19), (-2, 19))) + + 1: 574 MAP_ADD 1 + +103: 576 LOAD_CONST ("cmp_list2") + 578 LOAD_CONST (('%[1]{pattr} %p', (0, 19))) + + 1: 580 MAP_ADD 1 + +104: 582 LOAD_CONST ("funcdef") + 584 LOAD_CONST (('\n\n%|def %c\n', -2)) + + 1: 586 MAP_ADD 1 + +105: 588 LOAD_CONST ("funcdefdeco") + 590 LOAD_CONST (('\n\n%c', 0)) + + 1: 592 MAP_ADD 1 + +106: 594 LOAD_CONST ("mkfuncdeco") + 596 LOAD_CONST (('%|@%c\n%c', 0, 1)) + + 1: 598 MAP_ADD 1 + +107: 600 LOAD_CONST ("mkfuncdeco0") + 602 LOAD_CONST (('%|def %c\n', 0)) + + 1: 604 MAP_ADD 1 + +108: 606 LOAD_CONST ("classdefdeco") + 608 LOAD_CONST (('\n\n%c', 0)) + + 1: 610 MAP_ADD 1 + +109: 612 LOAD_CONST ("classdefdeco1") + 614 LOAD_CONST (('%|@%c\n%c', 0, 1)) + + 1: 616 MAP_ADD 1 + +110: 618 LOAD_CONST ("kwarg") + 620 LOAD_CONST (('%[0]{pattr}=%c', 1)) + + 1: 622 MAP_ADD 1 + +111: 624 LOAD_CONST ("kwargs") + 626 LOAD_CONST (('%D', (0, 10000, ', '))) + + 1: 628 MAP_ADD 1 + +113: 630 LOAD_CONST ("assert_expr_or") + 632 LOAD_CONST (('%c or %c', 0, 2)) + + 1: 634 MAP_ADD 1 + 636 DICT_UPDATE 1 + +114: 638 LOAD_CONST ("assert_expr_and") + 640 LOAD_CONST (('%c and %c', 0, 2)) + +115: 642 LOAD_CONST ("print_items_stmt") + 644 LOAD_CONST (('%|print %c%c,\n', 0, 2)) + +116: 646 LOAD_CONST ("print_items_nl_stmt") + 648 LOAD_CONST (('%|print %c%c\n', 0, 2)) + +117: 650 LOAD_CONST ("print_item") + 652 LOAD_CONST ((', %c', 0)) + +118: 654 LOAD_CONST ("print_nl") + 656 LOAD_CONST (('%|print\n',)) + +119: 658 LOAD_CONST ("print_to") + 660 LOAD_CONST (('%|print >> %c, %c,\n', 0, 1)) + +120: 662 LOAD_CONST ("print_to_nl") + 664 LOAD_CONST (('%|print >> %c, %c\n', 0, 1)) + +121: 666 LOAD_CONST ("print_nl_to") + 668 LOAD_CONST (('%|print >> %c\n', 0)) + +122: 670 LOAD_CONST ("print_to_items") + 672 LOAD_CONST (('%C', (0, 2, ', '))) + +123: 674 LOAD_CONST ("kv") + 676 LOAD_CONST (('%c: %c', 3, 1)) + +124: 678 LOAD_CONST ("kv2") + 680 LOAD_CONST (('%c: %c', 1, 2)) + + 1: 682 BUILD_MAP 11 + 684 DICT_UPDATE 1 + 686 STORE_NAME (TABLE_DIRECT) + 688 LOAD_COMMON_CONSTANT (None) + 690 RETURN_VALUE + diff --git a/pytest/testdata/03_big_dict-xasm-3.15.right b/pytest/testdata/03_big_dict-xasm-3.15.right new file mode 100644 index 00000000..0c127f6a --- /dev/null +++ b/pytest/testdata/03_big_dict-xasm-3.15.right @@ -0,0 +1,995 @@ +# Source code size mod 2**32: 4714 bytes + +# Method Name: +# Filename: test/simple_source/03_big_dict.py +# Argument count: 0 +# Position-only argument count: 0 +# Keyword-only arguments: 0 +# Number of locals: 0 +# Stack size: 23 +# Flags: 0x00000000 (0x0) +# First Line: 1 +# Constants: +# 0: 'BINARY_ADD' +# 1: 'BINARY_SUBTRACT' +# 2: 'BINARY_MULTIPLY' +# 3: 'BINARY_DIVIDE' +# 4: 'BINARY_MATRIX_MULTIPLY' +# 5: 'BINARY_TRUE_DIVIDE' +# 6: 'BINARY_FLOOR_DIVIDE' +# 7: 'BINARY_MODULO' +# 8: 'BINARY_POWER' +# 9: 'BINARY_LSHIFT' +# 10: 'BINARY_RSHIFT' +# 11: 'BINARY_AND' +# 12: 'BINARY_OR' +# 13: 'BINARY_XOR' +# 14: 'INPLACE_ADD' +# 15: 'INPLACE_SUBTRACT' +# 16: 'INPLACE_MULTIPLY' +# 17: 'INPLACE_MATRIX_MULTIPLY' +# 18: 'INPLACE_DIVIDE' +# 19: 'INPLACE_TRUE_DIVIDE' +# 20: 'INPLACE_FLOOR_DIVIDE' +# 21: 'INPLACE_MODULO' +# 22: 'INPLACE_POWER' +# 23: 'INPLACE_LSHIFT' +# 24: 'INPLACE_RSHIFT' +# 25: 'INPLACE_AND' +# 26: 'INPLACE_OR' +# 27: 'INPLACE_XOR' +# 28: 'binary_expr' +# 29: 'UNARY_POSITIVE' +# 30: 'UNARY_NEGATIVE' +# 31: 'UNARY_INVERT' +# 32: '~%c' +# 33: 'unary_expr' +# 34: 'unary_not' +# 35: 'unary_convert' +# 36: 'get_iter' +# 37: 'slice0' +# 38: 'slice1' +# 39: 'slice2' +# 40: 'slice3' +# 41: 'IMPORT_FROM' +# 42: 'load_attr' +# 43: 'LOAD_FAST' +# 44: 'LOAD_NAME' +# 45: 'LOAD_CLASSNAME' +# 46: 'LOAD_GLOBAL' +# 47: 'LOAD_DEREF' +# 48: 'LOAD_LOCALS' +# 49: 'LOAD_ASSERT' +# 50: 'DELETE_FAST' +# 51: 'DELETE_NAME' +# 52: 'DELETE_GLOBAL' +# 53: 'delete_subscr' +# 54: 'binary_subscr' +# 55: 'binary_subscr2' +# 56: 'store_subscr' +# 57: 'STORE_FAST' +# 58: 'STORE_NAME' +# 59: 'STORE_GLOBAL' +# 60: 'STORE_DEREF' +# 61: 'unpack' +# 62: 'unpack_w_parens' +# 63: 'unpack_list' +# 64: 'build_tuple2' +# 65: 'list_iter' +# 66: 'list_for' +# 67: 'list_if' +# 68: 'list_if_not' +# 69: 'lc_body' +# 70: 'comp_body' +# 71: 'set_comp_body' +# 72: 'gen_comp_body' +# 73: 'dict_comp_body' +# 74: 'assign' +# 75: 'augassign1' +# 76: 'augassign2' +# 77: 'designList' +# 78: 'and' +# 79: 'ret_and' +# 80: 'and2' +# 81: 'or' +# 82: 'ret_or' +# 83: 'conditional' +# 84: 'conditionalTrue' +# 85: 'ret_cond' +# 86: 'conditionalnot' +# 87: 'ret_cond_not' +# 88: 'conditional_lambda' +# 89: 'return_lambda' +# 90: 'compare' +# 91: 'cmp_list' +# 92: 'cmp_list1' +# 93: 'cmp_list2' +# 94: 'funcdef' +# 95: 'funcdefdeco' +# 96: 'mkfuncdeco' +# 97: 'mkfuncdeco0' +# 98: 'classdefdeco' +# 99: 'classdefdeco1' +# 100: 'kwarg' +# 101: 'kwargs' +# 102: 'assert_expr_or' +# 103: 'assert_expr_and' +# 104: 'print_items_stmt' +# 105: 'print_items_nl_stmt' +# 106: 'print_item' +# 107: 'print_nl' +# 108: 'print_to' +# 109: 'print_to_nl' +# 110: 'print_nl_to' +# 111: 'print_to_items' +# 112: 'kv' +# 113: 'kv2' +# 114: ('+',) +# 115: ('-',) +# 116: ('*',) +# 117: ('/',) +# 118: ('@',) +# 119: ('//',) +# 120: ('%%',) +# 121: ('**',) +# 122: ('<<',) +# 123: ('>>',) +# 124: ('&',) +# 125: ('|',) +# 126: ('^',) +# 127: ('+=',) +# 128: ('-=',) +# 129: ('*=',) +# 130: ('@=',) +# 131: ('/=',) +# 132: ('//=',) +# 133: ('%%=',) +# 134: ('**=',) +# 135: ('<<=',) +# 136: ('>>=',) +# 137: ('&=',) +# 138: ('|=',) +# 139: ('^=',) +# 140: ('%c %c %c', 0, -1, 1) +# 141: ('%c%c', 1, 0) +# 142: ('not %c', 0) +# 143: ('`%c`', 0) +# 144: ('iter(%c)', 0) +# 145: ('%c[:]', 0) +# 146: ('%c[%p:]', 0, (1, 100)) +# 147: ('%c[:%p]', 0, (1, 100)) +# 148: ('%c[%p:%p]', 0, (1, 100), (2, 100)) +# 149: ('%{pattr}',) +# 150: ('%c.%[1]{pattr}', 0) +# 151: ('locals()',) +# 152: ('%|del %{pattr}\n',) +# 153: ('%|del %c[%c]\n', 0, 1) +# 154: ('%c[%p]', 0, (1, 100)) +# 155: ('%c[%c]', 0, 1) +# 156: ('%C%,', (1, 5, ', ')) +# 157: ('(%C%,)', (1, 10, ', ')) +# 158: ('[%C]', (1, 15, ', ')) +# 159: ('%P', (0, -1, ', ', 100)) +# 160: ('%c', 0) +# 161: (' for %c in %c%c', 2, 0, 3) +# 162: (' if %c%c', 0, 2) +# 163: (' if not %p%c', (0, 22), 2) +# 164: ('',) +# 165: ('%c:%c', 1, 0) +# 166: ('%|%c = %p\n', -1, (0, 200)) +# 167: ('%|%c %c %c\n', 0, 2, 1) +# 168: ('%|%c.%[2]{pattr} %c %c\n', 0, -3, -4) +# 169: ('%c = %c', 0, -1) +# 170: ('%c and %c', 0, 2) +# 171: ('%c', 3) +# 172: ('%c or %c', 0, 2) +# 173: ('%p if %p else %p', (2, 27), (0, 27), (4, 27)) +# 174: ('%p if 1 else %p', (0, 27), (2, 27)) +# 175: ('%p if %p else %p', (2, 27), (0, 27), (-1, 27)) +# 176: ('%p if not %p else %p', (2, 27), (0, 22), (4, 27)) +# 177: ('%p if not %p else %p', (2, 27), (0, 22), (-1, 27)) +# 178: ('(%c if %c else %c)', 2, 0, 3) +# 179: ('%p %[-1]{pattr} %p', (0, 19), (1, 19)) +# 180: ('%p %p', (0, 29), (1, 30)) +# 181: ('%[3]{pattr} %p %p', (0, 19), (-2, 19)) +# 182: ('%[1]{pattr} %p', (0, 19)) +# 183: ('\n\n%|def %c\n', -2) +# 184: ('\n\n%c', 0) +# 185: ('%|@%c\n%c', 0, 1) +# 186: ('%|def %c\n', 0) +# 187: ('%[0]{pattr}=%c', 1) +# 188: ('%D', (0, 10000, ', ')) +# 189: ('%|print %c%c,\n', 0, 2) +# 190: ('%|print %c%c\n', 0, 2) +# 191: (', %c', 0) +# 192: ('%|print\n',) +# 193: ('%|print >> %c, %c,\n', 0, 1) +# 194: ('%|print >> %c, %c\n', 0, 1) +# 195: ('%|print >> %c\n', 0) +# 196: ('%C', (0, 2, ', ')) +# 197: ('%c: %c', 3, 1) +# 198: ('%c: %c', 1, 2) +# Names: +# 0: TABLE_DIRECT + + 0: + RESUME 0 + + 1: + BUILD_MAP 0 + + 2: + LOAD_CONST 0 ("BINARY_ADD") + LOAD_CONST 114 (('+',)) + + 1: + MAP_ADD 1 + + 3: + LOAD_CONST 1 ("BINARY_SUBTRACT") + LOAD_CONST 115 (('-',)) + + 1: + MAP_ADD 1 + + 4: + LOAD_CONST 2 ("BINARY_MULTIPLY") + LOAD_CONST 116 (('*',)) + + 1: + MAP_ADD 1 + + 5: + LOAD_CONST 3 ("BINARY_DIVIDE") + LOAD_CONST 117 (('/',)) + + 1: + MAP_ADD 1 + + 6: + LOAD_CONST 4 ("BINARY_MATRIX_MULTIPLY") + LOAD_CONST 118 (('@',)) + + 1: + MAP_ADD 1 + + 7: + LOAD_CONST 5 ("BINARY_TRUE_DIVIDE") + LOAD_CONST 117 (('/',)) + + 1: + MAP_ADD 1 + + 8: + LOAD_CONST 6 ("BINARY_FLOOR_DIVIDE") + LOAD_CONST 119 (('//',)) + + 1: + MAP_ADD 1 + + 9: + LOAD_CONST 7 ("BINARY_MODULO") + LOAD_CONST 120 (('%%',)) + + 1: + MAP_ADD 1 + + 10: + LOAD_CONST 8 ("BINARY_POWER") + LOAD_CONST 121 (('**',)) + + 1: + MAP_ADD 1 + + 11: + LOAD_CONST 9 ("BINARY_LSHIFT") + LOAD_CONST 122 (('<<',)) + + 1: + MAP_ADD 1 + + 12: + LOAD_CONST 10 ("BINARY_RSHIFT") + LOAD_CONST 123 (('>>',)) + + 1: + MAP_ADD 1 + + 13: + LOAD_CONST 11 ("BINARY_AND") + LOAD_CONST 124 (('&',)) + + 1: + MAP_ADD 1 + + 14: + LOAD_CONST 12 ("BINARY_OR") + LOAD_CONST 125 (('|',)) + + 1: + MAP_ADD 1 + + 15: + LOAD_CONST 13 ("BINARY_XOR") + LOAD_CONST 126 (('^',)) + + 1: + MAP_ADD 1 + + 16: + LOAD_CONST 14 ("INPLACE_ADD") + LOAD_CONST 127 (('+=',)) + + 1: + MAP_ADD 1 + + 17: + LOAD_CONST 15 ("INPLACE_SUBTRACT") + LOAD_CONST 128 (('-=',)) + + 1: + MAP_ADD 1 + + 18: + LOAD_CONST 16 ("INPLACE_MULTIPLY") + LOAD_CONST 129 (('*=',)) + + 1: + MAP_ADD 1 + BUILD_MAP 0 + + 19: + LOAD_CONST 17 ("INPLACE_MATRIX_MULTIPLY") + LOAD_CONST 130 (('@=',)) + + 1: + MAP_ADD 1 + + 20: + LOAD_CONST 18 ("INPLACE_DIVIDE") + LOAD_CONST 131 (('/=',)) + + 1: + MAP_ADD 1 + + 21: + LOAD_CONST 19 ("INPLACE_TRUE_DIVIDE") + LOAD_CONST 131 (('/=',)) + + 1: + MAP_ADD 1 + + 22: + LOAD_CONST 20 ("INPLACE_FLOOR_DIVIDE") + LOAD_CONST 132 (('//=',)) + + 1: + MAP_ADD 1 + + 23: + LOAD_CONST 21 ("INPLACE_MODULO") + LOAD_CONST 133 (('%%=',)) + + 1: + MAP_ADD 1 + + 24: + LOAD_CONST 22 ("INPLACE_POWER") + LOAD_CONST 134 (('**=',)) + + 1: + MAP_ADD 1 + + 25: + LOAD_CONST 23 ("INPLACE_LSHIFT") + LOAD_CONST 135 (('<<=',)) + + 1: + MAP_ADD 1 + + 26: + LOAD_CONST 24 ("INPLACE_RSHIFT") + LOAD_CONST 136 (('>>=',)) + + 1: + MAP_ADD 1 + + 27: + LOAD_CONST 25 ("INPLACE_AND") + LOAD_CONST 137 (('&=',)) + + 1: + MAP_ADD 1 + + 28: + LOAD_CONST 26 ("INPLACE_OR") + LOAD_CONST 138 (('|=',)) + + 1: + MAP_ADD 1 + + 29: + LOAD_CONST 27 ("INPLACE_XOR") + LOAD_CONST 139 (('^=',)) + + 1: + MAP_ADD 1 + + 30: + LOAD_CONST 28 ("binary_expr") + LOAD_CONST 140 (('%c %c %c', 0, -1, 1)) + + 1: + MAP_ADD 1 + + 32: + LOAD_CONST 29 ("UNARY_POSITIVE") + LOAD_CONST 114 (('+',)) + + 1: + MAP_ADD 1 + + 33: + LOAD_CONST 30 ("UNARY_NEGATIVE") + LOAD_CONST 115 (('-',)) + + 1: + MAP_ADD 1 + + 34: + LOAD_CONST 31 ("UNARY_INVERT") + LOAD_CONST 32 ("~%c") + + 1: + MAP_ADD 1 + + 35: + LOAD_CONST 33 ("unary_expr") + LOAD_CONST 141 (('%c%c', 1, 0)) + + 1: + MAP_ADD 1 + + 37: + LOAD_CONST 34 ("unary_not") + LOAD_CONST 142 (('not %c', 0)) + + 1: + MAP_ADD 1 + DICT_UPDATE 1 + BUILD_MAP 0 + + 38: + LOAD_CONST 35 ("unary_convert") + LOAD_CONST 143 (('`%c`', 0)) + + 1: + MAP_ADD 1 + + 39: + LOAD_CONST 36 ("get_iter") + LOAD_CONST 144 (('iter(%c)', 0)) + + 1: + MAP_ADD 1 + + 40: + LOAD_CONST 37 ("slice0") + LOAD_CONST 145 (('%c[:]', 0)) + + 1: + MAP_ADD 1 + + 41: + LOAD_CONST 38 ("slice1") + LOAD_CONST 146 (('%c[%p:]', 0, (1, 100))) + + 1: + MAP_ADD 1 + + 42: + LOAD_CONST 39 ("slice2") + LOAD_CONST 147 (('%c[:%p]', 0, (1, 100))) + + 1: + MAP_ADD 1 + + 43: + LOAD_CONST 40 ("slice3") + LOAD_CONST 148 (('%c[%p:%p]', 0, (1, 100), (2, 100))) + + 1: + MAP_ADD 1 + + 45: + LOAD_CONST 41 ("IMPORT_FROM") + LOAD_CONST 149 (('%{pattr}',)) + + 1: + MAP_ADD 1 + + 46: + LOAD_CONST 42 ("load_attr") + LOAD_CONST 150 (('%c.%[1]{pattr}', 0)) + + 1: + MAP_ADD 1 + + 47: + LOAD_CONST 43 ("LOAD_FAST") + LOAD_CONST 149 (('%{pattr}',)) + + 1: + MAP_ADD 1 + + 48: + LOAD_CONST 44 ("LOAD_NAME") + LOAD_CONST 149 (('%{pattr}',)) + + 1: + MAP_ADD 1 + + 49: + LOAD_CONST 45 ("LOAD_CLASSNAME") + LOAD_CONST 149 (('%{pattr}',)) + + 1: + MAP_ADD 1 + + 50: + LOAD_CONST 46 ("LOAD_GLOBAL") + LOAD_CONST 149 (('%{pattr}',)) + + 1: + MAP_ADD 1 + + 51: + LOAD_CONST 47 ("LOAD_DEREF") + LOAD_CONST 149 (('%{pattr}',)) + + 1: + MAP_ADD 1 + + 52: + LOAD_CONST 48 ("LOAD_LOCALS") + LOAD_CONST 151 (('locals()',)) + + 1: + MAP_ADD 1 + + 53: + LOAD_CONST 49 ("LOAD_ASSERT") + LOAD_CONST 149 (('%{pattr}',)) + + 1: + MAP_ADD 1 + + 54: + LOAD_CONST 50 ("DELETE_FAST") + LOAD_CONST 152 (('%|del %{pattr}\n',)) + + 1: + MAP_ADD 1 + + 55: + LOAD_CONST 51 ("DELETE_NAME") + LOAD_CONST 152 (('%|del %{pattr}\n',)) + + 1: + MAP_ADD 1 + DICT_UPDATE 1 + BUILD_MAP 0 + + 56: + LOAD_CONST 52 ("DELETE_GLOBAL") + LOAD_CONST 152 (('%|del %{pattr}\n',)) + + 1: + MAP_ADD 1 + + 57: + LOAD_CONST 53 ("delete_subscr") + LOAD_CONST 153 (('%|del %c[%c]\n', 0, 1)) + + 1: + MAP_ADD 1 + + 58: + LOAD_CONST 54 ("binary_subscr") + LOAD_CONST 154 (('%c[%p]', 0, (1, 100))) + + 1: + MAP_ADD 1 + + 59: + LOAD_CONST 55 ("binary_subscr2") + LOAD_CONST 154 (('%c[%p]', 0, (1, 100))) + + 1: + MAP_ADD 1 + + 60: + LOAD_CONST 56 ("store_subscr") + LOAD_CONST 155 (('%c[%c]', 0, 1)) + + 1: + MAP_ADD 1 + + 61: + LOAD_CONST 57 ("STORE_FAST") + LOAD_CONST 149 (('%{pattr}',)) + + 1: + MAP_ADD 1 + + 62: + LOAD_CONST 58 ("STORE_NAME") + LOAD_CONST 149 (('%{pattr}',)) + + 1: + MAP_ADD 1 + + 63: + LOAD_CONST 59 ("STORE_GLOBAL") + LOAD_CONST 149 (('%{pattr}',)) + + 1: + MAP_ADD 1 + + 64: + LOAD_CONST 60 ("STORE_DEREF") + LOAD_CONST 149 (('%{pattr}',)) + + 1: + MAP_ADD 1 + + 65: + LOAD_CONST 61 ("unpack") + LOAD_CONST 156 (('%C%,', (1, 5, ', '))) + + 1: + MAP_ADD 1 + + 66: + LOAD_CONST 62 ("unpack_w_parens") + LOAD_CONST 157 (('(%C%,)', (1, 10, ', '))) + + 1: + MAP_ADD 1 + + 68: + LOAD_CONST 63 ("unpack_list") + LOAD_CONST 158 (('[%C]', (1, 15, ', '))) + + 1: + MAP_ADD 1 + + 69: + LOAD_CONST 64 ("build_tuple2") + LOAD_CONST 159 (('%P', (0, -1, ', ', 100))) + + 1: + MAP_ADD 1 + + 71: + LOAD_CONST 65 ("list_iter") + LOAD_CONST 160 (('%c', 0)) + + 1: + MAP_ADD 1 + + 72: + LOAD_CONST 66 ("list_for") + LOAD_CONST 161 ((' for %c in %c%c', 2, 0, 3)) + + 1: + MAP_ADD 1 + + 73: + LOAD_CONST 67 ("list_if") + LOAD_CONST 162 ((' if %c%c', 0, 2)) + + 1: + MAP_ADD 1 + + 74: + LOAD_CONST 68 ("list_if_not") + LOAD_CONST 163 ((' if not %p%c', (0, 22), 2)) + + 1: + MAP_ADD 1 + DICT_UPDATE 1 + BUILD_MAP 0 + + 75: + LOAD_CONST 69 ("lc_body") + LOAD_CONST 164 (('',)) + + 1: + MAP_ADD 1 + + 77: + LOAD_CONST 70 ("comp_body") + LOAD_CONST 164 (('',)) + + 1: + MAP_ADD 1 + + 78: + LOAD_CONST 71 ("set_comp_body") + LOAD_CONST 160 (('%c', 0)) + + 1: + MAP_ADD 1 + + 79: + LOAD_CONST 72 ("gen_comp_body") + LOAD_CONST 160 (('%c', 0)) + + 1: + MAP_ADD 1 + + 80: + LOAD_CONST 73 ("dict_comp_body") + LOAD_CONST 165 (('%c:%c', 1, 0)) + + 1: + MAP_ADD 1 + + 82: + LOAD_CONST 74 ("assign") + LOAD_CONST 166 (('%|%c = %p\n', -1, (0, 200))) + + 1: + MAP_ADD 1 + + 84: + LOAD_CONST 75 ("augassign1") + LOAD_CONST 167 (('%|%c %c %c\n', 0, 2, 1)) + + 1: + MAP_ADD 1 + + 86: + LOAD_CONST 76 ("augassign2") + LOAD_CONST 168 (('%|%c.%[2]{pattr} %c %c\n', 0, -3, -4)) + + 1: + MAP_ADD 1 + + 87: + LOAD_CONST 77 ("designList") + LOAD_CONST 169 (('%c = %c', 0, -1)) + + 1: + MAP_ADD 1 + + 88: + LOAD_CONST 78 ("and") + LOAD_CONST 170 (('%c and %c', 0, 2)) + + 1: + MAP_ADD 1 + + 89: + LOAD_CONST 79 ("ret_and") + LOAD_CONST 170 (('%c and %c', 0, 2)) + + 1: + MAP_ADD 1 + + 90: + LOAD_CONST 80 ("and2") + LOAD_CONST 171 (('%c', 3)) + + 1: + MAP_ADD 1 + + 91: + LOAD_CONST 81 ("or") + LOAD_CONST 172 (('%c or %c', 0, 2)) + + 1: + MAP_ADD 1 + + 92: + LOAD_CONST 82 ("ret_or") + LOAD_CONST 172 (('%c or %c', 0, 2)) + + 1: + MAP_ADD 1 + + 93: + LOAD_CONST 83 ("conditional") + LOAD_CONST 173 (('%p if %p else %p', (2, 27), (0, 27), (4, 27))) + + 1: + MAP_ADD 1 + + 94: + LOAD_CONST 84 ("conditionalTrue") + LOAD_CONST 174 (('%p if 1 else %p', (0, 27), (2, 27))) + + 1: + MAP_ADD 1 + + 95: + LOAD_CONST 85 ("ret_cond") + LOAD_CONST 175 (('%p if %p else %p', (2, 27), (0, 27), (-1, 27))) + + 1: + MAP_ADD 1 + DICT_UPDATE 1 + BUILD_MAP 0 + + 96: + LOAD_CONST 86 ("conditionalnot") + LOAD_CONST 176 (('%p if not %p else %p', (2, 27), (0, 22), (4, 27))) + + 1: + MAP_ADD 1 + + 97: + LOAD_CONST 87 ("ret_cond_not") + LOAD_CONST 177 (('%p if not %p else %p', (2, 27), (0, 22), (-1, 27))) + + 1: + MAP_ADD 1 + + 98: + LOAD_CONST 88 ("conditional_lambda") + LOAD_CONST 178 (('(%c if %c else %c)', 2, 0, 3)) + + 1: + MAP_ADD 1 + + 99: + LOAD_CONST 89 ("return_lambda") + LOAD_CONST 160 (('%c', 0)) + + 1: + MAP_ADD 1 + +100: + LOAD_CONST 90 ("compare") + LOAD_CONST 179 (('%p %[-1]{pattr} %p', (0, 19), (1, 19))) + + 1: + MAP_ADD 1 + +101: + LOAD_CONST 91 ("cmp_list") + LOAD_CONST 180 (('%p %p', (0, 29), (1, 30))) + + 1: + MAP_ADD 1 + +102: + LOAD_CONST 92 ("cmp_list1") + LOAD_CONST 181 (('%[3]{pattr} %p %p', (0, 19), (-2, 19))) + + 1: + MAP_ADD 1 + +103: + LOAD_CONST 93 ("cmp_list2") + LOAD_CONST 182 (('%[1]{pattr} %p', (0, 19))) + + 1: + MAP_ADD 1 + +104: + LOAD_CONST 94 ("funcdef") + LOAD_CONST 183 (('\n\n%|def %c\n', -2)) + + 1: + MAP_ADD 1 + +105: + LOAD_CONST 95 ("funcdefdeco") + LOAD_CONST 184 (('\n\n%c', 0)) + + 1: + MAP_ADD 1 + +106: + LOAD_CONST 96 ("mkfuncdeco") + LOAD_CONST 185 (('%|@%c\n%c', 0, 1)) + + 1: + MAP_ADD 1 + +107: + LOAD_CONST 97 ("mkfuncdeco0") + LOAD_CONST 186 (('%|def %c\n', 0)) + + 1: + MAP_ADD 1 + +108: + LOAD_CONST 98 ("classdefdeco") + LOAD_CONST 184 (('\n\n%c', 0)) + + 1: + MAP_ADD 1 + +109: + LOAD_CONST 99 ("classdefdeco1") + LOAD_CONST 185 (('%|@%c\n%c', 0, 1)) + + 1: + MAP_ADD 1 + +110: + LOAD_CONST 100 ("kwarg") + LOAD_CONST 187 (('%[0]{pattr}=%c', 1)) + + 1: + MAP_ADD 1 + +111: + LOAD_CONST 101 ("kwargs") + LOAD_CONST 188 (('%D', (0, 10000, ', '))) + + 1: + MAP_ADD 1 + +113: + LOAD_CONST 102 ("assert_expr_or") + LOAD_CONST 172 (('%c or %c', 0, 2)) + + 1: + MAP_ADD 1 + DICT_UPDATE 1 + +114: + LOAD_CONST 103 ("assert_expr_and") + LOAD_CONST 170 (('%c and %c', 0, 2)) + +115: + LOAD_CONST 104 ("print_items_stmt") + LOAD_CONST 189 (('%|print %c%c,\n', 0, 2)) + +116: + LOAD_CONST 105 ("print_items_nl_stmt") + LOAD_CONST 190 (('%|print %c%c\n', 0, 2)) + +117: + LOAD_CONST 106 ("print_item") + LOAD_CONST 191 ((', %c', 0)) + +118: + LOAD_CONST 107 ("print_nl") + LOAD_CONST 192 (('%|print\n',)) + +119: + LOAD_CONST 108 ("print_to") + LOAD_CONST 193 (('%|print >> %c, %c,\n', 0, 1)) + +120: + LOAD_CONST 109 ("print_to_nl") + LOAD_CONST 194 (('%|print >> %c, %c\n', 0, 1)) + +121: + LOAD_CONST 110 ("print_nl_to") + LOAD_CONST 195 (('%|print >> %c\n', 0)) + +122: + LOAD_CONST 111 ("print_to_items") + LOAD_CONST 196 (('%C', (0, 2, ', '))) + +123: + LOAD_CONST 112 ("kv") + LOAD_CONST 197 (('%c: %c', 3, 1)) + +124: + LOAD_CONST 113 ("kv2") + LOAD_CONST 198 (('%c: %c', 1, 2)) + + 1: + BUILD_MAP 11 + DICT_UPDATE 1 + STORE_NAME 0 (TABLE_DIRECT) + LOAD_COMMON_CONSTANT 7 (None) + RETURN_VALUE + From bc304314866d691ffcee58008642f72dcf0b199a Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Thu, 28 May 2026 16:26:16 -0500 Subject: [PATCH 19/20] fix: register Python 3.14.5 as canonical version in magics and op_imports --- xdis/magics.py | 2 +- xdis/op_imports.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/xdis/magics.py b/xdis/magics.py index 93790965..7bdda285 100755 --- a/xdis/magics.py +++ b/xdis/magics.py @@ -868,7 +868,7 @@ def add_canonic_versions(release_versions: str, canonic: str) -> None: ) add_canonic_versions("3.14-dev", "3.14b3") -add_canonic_versions("3.14 3.14.0 3.14.1, 3.14.2 3.14.3 3.14.4", "3.14rc3") +add_canonic_versions("3.14 3.14.0 3.14.1, 3.14.2 3.14.3 3.14.4 3.14.5", "3.14rc3") add_canonic_versions( "3.15 3.15.0 3.15.0a1 3.15.0a0 3.15-dev 3.15.0b1", diff --git a/xdis/op_imports.py b/xdis/op_imports.py index a3725982..0042b4e7 100644 --- a/xdis/op_imports.py +++ b/xdis/op_imports.py @@ -200,6 +200,7 @@ "3.14.0": opcode_314, "3.14": opcode_314, "3.14rc3": opcode_314, + "3.14.5": opcode_314, 3.14: opcode_314, "3.15": opcode_315, 3.15: opcode_315, From 2692140efe8e5087f22d46853f51eb5e89d11c8b Mon Sep 17 00:00:00 2001 From: Quinntyx Date: Thu, 28 May 2026 16:26:20 -0500 Subject: [PATCH 20/20] chore: add Python 3.15 to cross-version tox environments --- test_crossversion/tox.ini | 2 +- test_crossversion/tox_prepare.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test_crossversion/tox.ini b/test_crossversion/tox.ini index 055c2e23..1d4dde62 100644 --- a/test_crossversion/tox.ini +++ b/test_crossversion/tox.ini @@ -1,7 +1,7 @@ [tox] min_version = 4.0 # ENV LIST MUST BE COMMA SEPARATED LIST OF PYTHON VERSIONS -env_list = 3.12, 3.13, 3.14 +env_list = 3.12, 3.13, 3.14, 3.15 [testenv] description = Check all permutations of python dis code objects with xdis code objects. diff --git a/test_crossversion/tox_prepare.ini b/test_crossversion/tox_prepare.ini index c0fa9ea1..73cb0db9 100644 --- a/test_crossversion/tox_prepare.ini +++ b/test_crossversion/tox_prepare.ini @@ -1,7 +1,7 @@ [tox] min_version = 4.0 # ENV LIST MUST BE COMMA SEPARATED LIST OF PYTHON VERSIONS -env_list = 3.12, 3.13, 3.14 +env_list = 3.12, 3.13, 3.14, 3.15 [testenv] description = Compile and serialize source templates with dis