bpo-45168: change dis output to omit missing values rather than replacing them by their index (GH-28313)

This commit is contained in:
Irit Katriel 2021-09-14 10:09:05 +01:00 committed by GitHub
parent c2f1e95337
commit c99fc4e53a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 19 deletions

View File

@ -293,12 +293,13 @@ details of bytecode instructions as :class:`Instruction` instances:
.. data:: argval
resolved arg value (if known), otherwise same as arg
resolved arg value (if any), otherwise ``None``
.. data:: argrepr
human readable description of operation argument
human readable description of operation argument (if any),
otherwise an empty string.
.. data:: offset

View File

@ -125,6 +125,13 @@ def pretty_flags(flags):
names.append(hex(flags))
return ", ".join(names)
class _Unknown:
def __repr__(self):
return "<unknown>"
# Sentinel to represent values that cannot be calculated
UNKNOWN = _Unknown()
def _get_code_object(x):
"""Helper to handle methods, compiled or raw code objects, and strings."""
# Extract functions from methods.
@ -315,28 +322,28 @@ def _get_const_info(const_index, const_list):
Returns the dereferenced constant and its repr if the constant
list is defined.
Otherwise returns the constant index and its repr().
Otherwise returns the sentinel value dis.UNKNOWN for the value
and an empty string for its repr.
"""
argval = const_index
if const_list is not None:
argval = const_list[const_index]
return argval, repr(argval)
return argval, repr(argval)
else:
return UNKNOWN, ''
def _get_name_info(name_index, get_name, **extrainfo):
"""Helper to get optional details about named references
Returns the dereferenced name as both value and repr if the name
list is defined.
Otherwise returns the name index and its repr().
Otherwise returns the sentinel value dis.UNKNOWN for the value
and an empty string for its repr.
"""
argval = name_index
if get_name is not None:
argval = get_name(name_index, **extrainfo)
argrepr = argval
return argval, argval
else:
argrepr = repr(argval)
return argval, argrepr
return UNKNOWN, ''
def parse_varint(iterator):
b = next(iterator)

View File

@ -48,12 +48,12 @@ dis_c_instance_method = """\
""" % (_C.__init__.__code__.co_firstlineno + 1,)
dis_c_instance_method_bytes = """\
0 LOAD_FAST 1 (1)
2 LOAD_CONST 1 (1)
0 LOAD_FAST 1
2 LOAD_CONST 1
4 COMPARE_OP 2 (==)
6 LOAD_FAST 0 (0)
8 STORE_ATTR 0 (0)
10 LOAD_CONST 0 (0)
6 LOAD_FAST 0
8 STORE_ATTR 0
10 LOAD_CONST 0
12 RETURN_VALUE
"""
@ -105,11 +105,11 @@ dis_f = """\
dis_f_co_code = """\
0 LOAD_GLOBAL 0 (0)
2 LOAD_FAST 0 (0)
0 LOAD_GLOBAL 0
2 LOAD_FAST 0
4 CALL_FUNCTION 1
6 POP_TOP
8 LOAD_CONST 1 (1)
8 LOAD_CONST 1
10 RETURN_VALUE
"""

View File

@ -0,0 +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.