2626MAKE_FUNCTION = opmap ['MAKE_FUNCTION' ]
2727MAKE_FUNCTION_FLAGS = ('defaults' , 'kwdefaults' , 'annotations' , 'closure' )
2828
29+ LOAD_CONST = opmap ['LOAD_CONST' ]
2930
3031def _try_compile (source , name ):
3132 """Attempts to compile the given source, first as an expression and
@@ -317,19 +318,32 @@ def get_instructions(x, *, first_line=None):
317318 co .co_names , co .co_consts ,
318319 linestarts , line_offset , co_positions = co .co_positions ())
319320
320- def _get_const_info (const_index , const_list ):
321+ def _get_const_value (op , arg , co_consts ):
322+ """Helper to get the value of the const in a hasconst op.
323+
324+ Returns the dereferenced constant if this is possible.
325+ Otherwise (if it is a LOAD_CONST and co_consts is not
326+ provided) returns the dis.UNKNOWN sentinel.
327+ """
328+ assert op in hasconst
329+
330+ argval = UNKNOWN
331+ if op == LOAD_CONST :
332+ if co_consts is not None :
333+ argval = co_consts [arg ]
334+ return argval
335+
336+ def _get_const_info (op , arg , co_consts ):
321337 """Helper to get optional details about const references
322338
323- Returns the dereferenced constant and its repr if the constant
324- list is defined .
339+ Returns the dereferenced constant and its repr if the value
340+ can be calculated .
325341 Otherwise returns the sentinel value dis.UNKNOWN for the value
326342 and an empty string for its repr.
327343 """
328- if const_list is not None :
329- argval = const_list [const_index ]
330- return argval , repr (argval )
331- else :
332- return UNKNOWN , ''
344+ argval = _get_const_value (op , arg , co_consts )
345+ argrepr = repr (argval ) if argval is not UNKNOWN else ''
346+ return argval , argrepr
333347
334348def _get_name_info (name_index , get_name , ** extrainfo ):
335349 """Helper to get optional details about named references
@@ -371,14 +385,14 @@ def parse_exception_table(code):
371385 return entries
372386
373387def _get_instructions_bytes (code , varname_from_oparg = None ,
374- names = None , constants = None ,
388+ names = None , co_consts = None ,
375389 linestarts = None , line_offset = 0 ,
376390 exception_entries = (), co_positions = None ):
377391 """Iterate over the instructions in a bytecode string.
378392
379393 Generates a sequence of Instruction namedtuples giving the details of each
380394 opcode. Additional information about the code's runtime environment
381- (e.g. variable names, constants ) can be specified using optional
395+ (e.g. variable names, co_consts ) can be specified using optional
382396 arguments.
383397
384398 """
@@ -408,7 +422,7 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
408422 # raw name index for LOAD_GLOBAL, LOAD_CONST, etc.
409423 argval = arg
410424 if op in hasconst :
411- argval , argrepr = _get_const_info (arg , constants )
425+ argval , argrepr = _get_const_info (op , arg , co_consts )
412426 elif op in hasname :
413427 argval , argrepr = _get_name_info (arg , get_name )
414428 elif op in hasjabs :
@@ -457,7 +471,7 @@ def _disassemble_recursive(co, *, file=None, depth=None):
457471 _disassemble_recursive (x , file = file , depth = depth )
458472
459473def _disassemble_bytes (code , lasti = - 1 , varname_from_oparg = None ,
460- names = None , constants = None , linestarts = None ,
474+ names = None , co_consts = None , linestarts = None ,
461475 * , file = None , line_offset = 0 , exception_entries = (),
462476 co_positions = None ):
463477 # Omit the line number column entirely if we have no line number info
@@ -476,7 +490,7 @@ def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None,
476490 else :
477491 offset_width = 4
478492 for instr in _get_instructions_bytes (code , varname_from_oparg , names ,
479- constants , linestarts ,
493+ co_consts , linestarts ,
480494 line_offset = line_offset , exception_entries = exception_entries ,
481495 co_positions = co_positions ):
482496 new_source_line = (show_lineno and
@@ -557,11 +571,13 @@ def _find_imports(co):
557571 opargs = [(op , arg ) for _ , op , arg in _unpack_opargs (co .co_code )
558572 if op != EXTENDED_ARG ]
559573 for i , (op , oparg ) in enumerate (opargs ):
560- if (op == IMPORT_NAME and i >= 2
561- and opargs [i - 1 ][0 ] == opargs [i - 2 ][0 ] == LOAD_CONST ):
562- level = consts [opargs [i - 2 ][1 ]]
563- fromlist = consts [opargs [i - 1 ][1 ]]
564- yield (names [oparg ], level , fromlist )
574+ if op == IMPORT_NAME and i >= 2 :
575+ from_op = opargs [i - 1 ]
576+ level_op = opargs [i - 2 ]
577+ if (from_op [0 ] in hasconst and level_op [0 ] in hasconst ):
578+ level = _get_const_value (level_op [0 ], level_op [1 ], consts )
579+ fromlist = _get_const_value (from_op [0 ], from_op [1 ], consts )
580+ yield (names [oparg ], level , fromlist )
565581
566582def _find_store_names (co ):
567583 """Find names of variables which are written in the code
@@ -635,7 +651,7 @@ def dis(self):
635651 with io .StringIO () as output :
636652 _disassemble_bytes (co .co_code ,
637653 varname_from_oparg = co ._varname_from_oparg ,
638- names = co .co_names , constants = co .co_consts ,
654+ names = co .co_names , co_consts = co .co_consts ,
639655 linestarts = self ._linestarts ,
640656 line_offset = self ._line_offset ,
641657 file = output ,
0 commit comments