Skip to content

Commit e8e151d

Browse files
gh-120780: Show attribute name for LOAD_SPECIAL in dis output (#120781)
1 parent 55596ae commit e8e151d

File tree

6 files changed

+59
-7
lines changed

6 files changed

+59
-7
lines changed

Lib/dis.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
_common_constants,
1515
_intrinsic_1_descs,
1616
_intrinsic_2_descs,
17+
_special_method_names,
1718
_specializations,
1819
_specialized_opmap,
1920
)
@@ -46,6 +47,7 @@
4647
CALL_INTRINSIC_1 = opmap['CALL_INTRINSIC_1']
4748
CALL_INTRINSIC_2 = opmap['CALL_INTRINSIC_2']
4849
LOAD_COMMON_CONSTANT = opmap['LOAD_COMMON_CONSTANT']
50+
LOAD_SPECIAL = opmap['LOAD_SPECIAL']
4951
LOAD_FAST_LOAD_FAST = opmap['LOAD_FAST_LOAD_FAST']
5052
STORE_FAST_LOAD_FAST = opmap['STORE_FAST_LOAD_FAST']
5153
STORE_FAST_STORE_FAST = opmap['STORE_FAST_STORE_FAST']
@@ -609,6 +611,8 @@ def get_argval_argrepr(self, op, arg, offset):
609611
argrepr = obj.__name__
610612
else:
611613
argrepr = repr(obj)
614+
elif deop == LOAD_SPECIAL:
615+
argrepr = _special_method_names[arg]
612616
return argval, argrepr
613617

614618
def get_instructions(x, *, first_line=None, show_caches=None, adaptive=False):

Lib/opcode.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
_intrinsic_1_descs = _opcode.get_intrinsic1_descs()
3838
_intrinsic_2_descs = _opcode.get_intrinsic2_descs()
39+
_special_method_names = _opcode.get_special_method_names()
3940
_common_constants = [AssertionError, NotImplementedError]
4041
_nb_ops = _opcode.get_nb_ops()
4142

Lib/test/test_dis.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -481,10 +481,10 @@ def _with(c):
481481
482482
%4d LOAD_FAST 0 (c)
483483
COPY 1
484-
LOAD_SPECIAL 1
484+
LOAD_SPECIAL 1 (__exit__)
485485
SWAP 2
486486
SWAP 3
487-
LOAD_SPECIAL 0
487+
LOAD_SPECIAL 0 (__enter__)
488488
CALL 0
489489
L1: POP_TOP
490490
@@ -543,10 +543,10 @@ async def _asyncwith(c):
543543
544544
%4d LOAD_FAST 0 (c)
545545
COPY 1
546-
LOAD_SPECIAL 3
546+
LOAD_SPECIAL 3 (__aexit__)
547547
SWAP 2
548548
SWAP 3
549-
LOAD_SPECIAL 2
549+
LOAD_SPECIAL 2 (__aenter__)
550550
CALL 0
551551
GET_AWAITABLE 1
552552
LOAD_CONST 0 (None)
@@ -1738,10 +1738,10 @@ def _prepare_test_cases():
17381738
Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=240, start_offset=240, starts_line=False, line_number=21, label=None, positions=None, cache_info=None),
17391739
Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=242, start_offset=242, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
17401740
Instruction(opname='COPY', opcode=58, arg=1, argval=1, argrepr='', offset=244, start_offset=244, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
1741-
Instruction(opname='LOAD_SPECIAL', opcode=91, arg=1, argval=1, argrepr='', offset=246, start_offset=246, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
1741+
Instruction(opname='LOAD_SPECIAL', opcode=91, arg=1, argval=1, argrepr='__exit__', offset=246, start_offset=246, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
17421742
Instruction(opname='SWAP', opcode=114, arg=2, argval=2, argrepr='', offset=248, start_offset=248, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
17431743
Instruction(opname='SWAP', opcode=114, arg=3, argval=3, argrepr='', offset=250, start_offset=250, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
1744-
Instruction(opname='LOAD_SPECIAL', opcode=91, arg=0, argval=0, argrepr='', offset=252, start_offset=252, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
1744+
Instruction(opname='LOAD_SPECIAL', opcode=91, arg=0, argval=0, argrepr='__enter__', offset=252, start_offset=252, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
17451745
Instruction(opname='CALL', opcode=50, arg=0, argval=0, argrepr='', offset=254, start_offset=254, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
17461746
Instruction(opname='STORE_FAST', opcode=109, arg=1, argval='dodgy', argrepr='dodgy', offset=262, start_offset=262, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
17471747
Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=264, start_offset=264, starts_line=True, line_number=26, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Show string value of LOAD_SPECIAL oparg in :mod:`dis` output.

Modules/_opcode.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "Python.h"
66
#include "compile.h"
77
#include "opcode.h"
8+
#include "internal/pycore_ceval.h"
89
#include "internal/pycore_code.h"
910
#include "internal/pycore_compile.h"
1011
#include "internal/pycore_intrinsics.h"
@@ -349,6 +350,32 @@ _opcode_get_intrinsic2_descs_impl(PyObject *module)
349350

350351
/*[clinic input]
351352
353+
_opcode.get_special_method_names
354+
355+
Return a list of special method names.
356+
[clinic start generated code]*/
357+
358+
static PyObject *
359+
_opcode_get_special_method_names_impl(PyObject *module)
360+
/*[clinic end generated code: output=fce72614cd988d17 input=25f2115560bdf163]*/
361+
{
362+
PyObject *list = PyList_New(SPECIAL_MAX + 1);
363+
if (list == NULL) {
364+
return NULL;
365+
}
366+
for (int i=0; i <= SPECIAL_MAX; i++) {
367+
PyObject *name = _Py_SpecialMethods[i].name;
368+
if (name == NULL) {
369+
Py_DECREF(list);
370+
return NULL;
371+
}
372+
PyList_SET_ITEM(list, i, name);
373+
}
374+
return list;
375+
}
376+
377+
/*[clinic input]
378+
352379
_opcode.get_executor
353380
354381
code: object
@@ -392,6 +419,7 @@ opcode_functions[] = {
392419
_OPCODE_GET_INTRINSIC1_DESCS_METHODDEF
393420
_OPCODE_GET_INTRINSIC2_DESCS_METHODDEF
394421
_OPCODE_GET_EXECUTOR_METHODDEF
422+
_OPCODE_GET_SPECIAL_METHOD_NAMES_METHODDEF
395423
{NULL, NULL, 0, NULL}
396424
};
397425

Modules/clinic/_opcode.c.h

Lines changed: 19 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)