Skip to content

Commit c99fc4e

Browse files
authored
bpo-45168: change dis output to omit missing values rather than replacing them by their index (GH-28313)
1 parent c2f1e95 commit c99fc4e

File tree

4 files changed

+28
-19
lines changed

4 files changed

+28
-19
lines changed

Doc/library/dis.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,12 +293,13 @@ details of bytecode instructions as :class:`Instruction` instances:
293293

294294
.. data:: argval
295295

296-
resolved arg value (if known), otherwise same as arg
296+
resolved arg value (if any), otherwise ``None``
297297

298298

299299
.. data:: argrepr
300300

301-
human readable description of operation argument
301+
human readable description of operation argument (if any),
302+
otherwise an empty string.
302303

303304

304305
.. data:: offset

Lib/dis.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,13 @@ def pretty_flags(flags):
125125
names.append(hex(flags))
126126
return ", ".join(names)
127127

128+
class _Unknown:
129+
def __repr__(self):
130+
return "<unknown>"
131+
132+
# Sentinel to represent values that cannot be calculated
133+
UNKNOWN = _Unknown()
134+
128135
def _get_code_object(x):
129136
"""Helper to handle methods, compiled or raw code objects, and strings."""
130137
# Extract functions from methods.
@@ -315,28 +322,28 @@ def _get_const_info(const_index, const_list):
315322
316323
Returns the dereferenced constant and its repr if the constant
317324
list is defined.
318-
Otherwise returns the constant index and its repr().
325+
Otherwise returns the sentinel value dis.UNKNOWN for the value
326+
and an empty string for its repr.
319327
"""
320-
argval = const_index
321328
if const_list is not None:
322329
argval = const_list[const_index]
323-
return argval, repr(argval)
330+
return argval, repr(argval)
331+
else:
332+
return UNKNOWN, ''
324333

325334
def _get_name_info(name_index, get_name, **extrainfo):
326335
"""Helper to get optional details about named references
327336
328337
Returns the dereferenced name as both value and repr if the name
329338
list is defined.
330-
Otherwise returns the name index and its repr().
339+
Otherwise returns the sentinel value dis.UNKNOWN for the value
340+
and an empty string for its repr.
331341
"""
332-
argval = name_index
333342
if get_name is not None:
334343
argval = get_name(name_index, **extrainfo)
335-
argrepr = argval
344+
return argval, argval
336345
else:
337-
argrepr = repr(argval)
338-
return argval, argrepr
339-
346+
return UNKNOWN, ''
340347

341348
def parse_varint(iterator):
342349
b = next(iterator)

Lib/test/test_dis.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ def cm(cls, x):
4848
""" % (_C.__init__.__code__.co_firstlineno + 1,)
4949

5050
dis_c_instance_method_bytes = """\
51-
0 LOAD_FAST 1 (1)
52-
2 LOAD_CONST 1 (1)
51+
0 LOAD_FAST 1
52+
2 LOAD_CONST 1
5353
4 COMPARE_OP 2 (==)
54-
6 LOAD_FAST 0 (0)
55-
8 STORE_ATTR 0 (0)
56-
10 LOAD_CONST 0 (0)
54+
6 LOAD_FAST 0
55+
8 STORE_ATTR 0
56+
10 LOAD_CONST 0
5757
12 RETURN_VALUE
5858
"""
5959

@@ -105,11 +105,11 @@ def _f(a):
105105

106106

107107
dis_f_co_code = """\
108-
0 LOAD_GLOBAL 0 (0)
109-
2 LOAD_FAST 0 (0)
108+
0 LOAD_GLOBAL 0
109+
2 LOAD_FAST 0
110110
4 CALL_FUNCTION 1
111111
6 POP_TOP
112-
8 LOAD_CONST 1 (1)
112+
8 LOAD_CONST 1
113113
10 RETURN_VALUE
114114
"""
115115

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Change :func:`dis.dis` output to omit op arg values that cannot be resolved due to ``co_consts``, ``co_names`` etc not being provided. Previously the oparg itself was repeated in the value field, which is not useful and can be confusing.

0 commit comments

Comments
 (0)