@@ -331,16 +331,77 @@ def _fstring(a, b, c, d):
331331def _g (x ):
332332 yield x
333333
334+ def _h (y ):
335+ def foo (x ):
336+ '''funcdoc'''
337+ return [x + z for z in y ]
338+ return foo
339+
340+ dis_nested_0 = """\
341+ %3d 0 LOAD_CLOSURE 0 (y)
342+ 2 BUILD_TUPLE 1
343+ 4 LOAD_CONST 1 (<code object foo at 0x..., file "%s", line %d>)
344+ 6 LOAD_CONST 2 ('_h.<locals>.foo')
345+ 8 MAKE_FUNCTION 8
346+ 10 STORE_FAST 1 (foo)
347+
348+ %3d 12 LOAD_FAST 1 (foo)
349+ 14 RETURN_VALUE
350+ """ % (_h .__code__ .co_firstlineno + 1 ,
351+ __file__ ,
352+ _h .__code__ .co_firstlineno + 1 ,
353+ _h .__code__ .co_firstlineno + 4 ,
354+ )
355+
356+ dis_nested_1 = """%s
357+ Disassembly of <code object foo at 0x..., file "%s", line %d>:
358+ %3d 0 LOAD_CLOSURE 0 (x)
359+ 2 BUILD_TUPLE 1
360+ 4 LOAD_CONST 1 (<code object <listcomp> at 0x..., file "%s", line %d>)
361+ 6 LOAD_CONST 2 ('_h.<locals>.foo.<locals>.<listcomp>')
362+ 8 MAKE_FUNCTION 8
363+ 10 LOAD_DEREF 1 (y)
364+ 12 GET_ITER
365+ 14 CALL_FUNCTION 1
366+ 16 RETURN_VALUE
367+ """ % (dis_nested_0 ,
368+ __file__ ,
369+ _h .__code__ .co_firstlineno + 1 ,
370+ _h .__code__ .co_firstlineno + 3 ,
371+ __file__ ,
372+ _h .__code__ .co_firstlineno + 3 ,
373+ )
374+
375+ dis_nested_2 = """%s
376+ Disassembly of <code object <listcomp> at 0x..., file "%s", line %d>:
377+ %3d 0 BUILD_LIST 0
378+ 2 LOAD_FAST 0 (.0)
379+ >> 4 FOR_ITER 12 (to 18)
380+ 6 STORE_FAST 1 (z)
381+ 8 LOAD_DEREF 0 (x)
382+ 10 LOAD_FAST 1 (z)
383+ 12 BINARY_ADD
384+ 14 LIST_APPEND 2
385+ 16 JUMP_ABSOLUTE 4
386+ >> 18 RETURN_VALUE
387+ """ % (dis_nested_1 ,
388+ __file__ ,
389+ _h .__code__ .co_firstlineno + 3 ,
390+ _h .__code__ .co_firstlineno + 3 ,
391+ )
392+
334393class DisTests (unittest .TestCase ):
335394
336- def get_disassembly (self , func , lasti = - 1 , wrapper = True ):
395+ maxDiff = None
396+
397+ def get_disassembly (self , func , lasti = - 1 , wrapper = True , ** kwargs ):
337398 # We want to test the default printing behaviour, not the file arg
338399 output = io .StringIO ()
339400 with contextlib .redirect_stdout (output ):
340401 if wrapper :
341- dis .dis (func )
402+ dis .dis (func , ** kwargs )
342403 else :
343- dis .disassemble (func , lasti )
404+ dis .disassemble (func , lasti , ** kwargs )
344405 return output .getvalue ()
345406
346407 def get_disassemble_as_string (self , func , lasti = - 1 ):
@@ -350,7 +411,7 @@ def strip_addresses(self, text):
350411 return re .sub (r'\b0x[0-9A-Fa-f]+\b' , '0x...' , text )
351412
352413 def do_disassembly_test (self , func , expected ):
353- got = self .get_disassembly (func )
414+ got = self .get_disassembly (func , depth = 0 )
354415 if got != expected :
355416 got = self .strip_addresses (got )
356417 self .assertEqual (got , expected )
@@ -502,15 +563,29 @@ def test_dis_traceback(self):
502563 def test_dis_object (self ):
503564 self .assertRaises (TypeError , dis .dis , object ())
504565
566+ def test_disassemble_recursive (self ):
567+ def check (expected , ** kwargs ):
568+ dis = self .get_disassembly (_h , ** kwargs )
569+ dis = self .strip_addresses (dis )
570+ self .assertEqual (dis , expected )
571+
572+ check (dis_nested_0 , depth = 0 )
573+ check (dis_nested_1 , depth = 1 )
574+ check (dis_nested_2 , depth = 2 )
575+ check (dis_nested_2 , depth = 3 )
576+ check (dis_nested_2 , depth = None )
577+ check (dis_nested_2 )
578+
579+
505580class DisWithFileTests (DisTests ):
506581
507582 # Run the tests again, using the file arg instead of print
508- def get_disassembly (self , func , lasti = - 1 , wrapper = True ):
583+ def get_disassembly (self , func , lasti = - 1 , wrapper = True , ** kwargs ):
509584 output = io .StringIO ()
510585 if wrapper :
511- dis .dis (func , file = output )
586+ dis .dis (func , file = output , ** kwargs )
512587 else :
513- dis .disassemble (func , lasti , file = output )
588+ dis .disassemble (func , lasti , file = output , ** kwargs )
514589 return output .getvalue ()
515590
516591
0 commit comments