Issue #21947: handle generator-iterator objects in dis

Patch by Clement Rouault.
This commit is contained in:
Nick Coghlan 2014-07-25 23:02:56 +10:00
parent d0d64cfb59
commit efd5df9e52
5 changed files with 26 additions and 10 deletions

View File

@ -48,8 +48,8 @@ compiled code.
.. class:: Bytecode(x, *, first_line=None, current_offset=None)
Analyse the bytecode corresponding to a function, method, string of
source code, or a code object (as returned by :func:`compile`).
Analyse the bytecode corresponding to a function, generator, method,
string of source code, or a code object (as returned by :func:`compile`).
This is a convenience wrapper around many of the functions listed below,
most notably :func:`get_instructions`, as iterating over a
@ -112,7 +112,7 @@ object isn't useful:
.. function:: code_info(x)
Return a formatted multi-line string with detailed code object information
for the supplied function, method, source code string or code object.
for the supplied function, generator, method, source code string or code object.
Note that the exact contents of code info strings are highly implementation
dependent and they may change arbitrarily across Python VMs or Python
@ -139,11 +139,11 @@ object isn't useful:
.. function:: dis(x=None, *, file=None)
Disassemble the *x* object. *x* can denote either a module, a class, a
method, a function, a code object, a string of source code or a byte sequence
of raw bytecode. For a module, it disassembles all functions. For a class,
it disassembles all methods. For a code object or sequence of raw bytecode,
it prints one line per bytecode instruction. Strings are first compiled to
code objects with the :func:`compile` built-in function before being
method, a function, a generator, a code object, a string of source code or
a byte sequence of raw bytecode. For a module, it disassembles all functions.
For a class, it disassembles all methods. For a code object or sequence of
raw bytecode, it prints one line per bytecode instruction. Strings are first
compiled to code objects with the :func:`compile` built-in function before being
disassembled. If no object is provided, this function disassembles the last
traceback.

View File

@ -29,7 +29,7 @@ def _try_compile(source, name):
return c
def dis(x=None, *, file=None):
"""Disassemble classes, methods, functions, or code.
"""Disassemble classes, methods, functions, generators, or code.
With no argument, disassemble the last traceback.
@ -41,6 +41,8 @@ def dis(x=None, *, file=None):
x = x.__func__
if hasattr(x, '__code__'): # Function
x = x.__code__
if hasattr(x, 'gi_code'): # Generator
x = x.gi_code
if hasattr(x, '__dict__'): # Class or module
items = sorted(x.__dict__.items())
for name, x1 in items:
@ -99,11 +101,13 @@ def pretty_flags(flags):
return ", ".join(names)
def _get_code_object(x):
"""Helper to handle methods, functions, strings and raw code objects"""
"""Helper to handle methods, functions, generators, strings and raw code objects"""
if hasattr(x, '__func__'): # Method
x = x.__func__
if hasattr(x, '__code__'): # Function
x = x.__code__
if hasattr(x, 'gi_code'): # Generator
x = x.gi_code
if isinstance(x, str): # Source code
x = _try_compile(x, "<disassembly>")
if hasattr(x, 'co_code'): # Code object

View File

@ -229,6 +229,9 @@ dis_traceback = """\
TRACEBACK_CODE.co_firstlineno + 4,
TRACEBACK_CODE.co_firstlineno + 5)
def _g(x):
yield x
class DisTests(unittest.TestCase):
def get_disassembly(self, func, lasti=-1, wrapper=True):
@ -314,6 +317,11 @@ class DisTests(unittest.TestCase):
method_bytecode = _C(1).__init__.__code__.co_code
self.do_disassembly_test(method_bytecode, dis_c_instance_method_bytes)
def test_disassemble_generator(self):
gen_func_disas = self.get_disassembly(_g) # Disassemble generator function
gen_disas = self.get_disassembly(_g(1)) # Disassemble generator itself
self.assertEqual(gen_disas, gen_func_disas)
def test_dis_none(self):
try:
del sys.last_traceback

View File

@ -1145,6 +1145,7 @@ Guido van Rossum
Just van Rossum
Hugo van Rossum
Saskia van Rossum
Clement Rouault
Donald Wallace Rouse II
Liam Routt
Todd Rovito

View File

@ -108,6 +108,9 @@ Core and Builtins
Library
-------
- Issue #21947: The dis module can now disassemble generator-iterator
objects based on their gi_code attribute. Patch by Clement Rouault.
- Issue #16133: The asynchat.async_chat.handle_read() method now ignores
BlockingIOError exceptions.