Add deparse_code_with_fragments_and_map and simplify

This commit is contained in:
rocky
2018-01-24 04:23:14 -05:00
parent e193c72d12
commit 0d32ec028c
4 changed files with 42 additions and 28 deletions

View File

@@ -11,20 +11,14 @@ src_dir = get_srcdir()
os.chdir(src_dir)
@pytest.mark.parametrize(("test_tuple", "function_to_test"), [
(
('../test/bytecode_2.7/05_if.pyc', 'testdata/if-2.7.right',),
disassemble_file
),
(
('../test/bytecode_2.7/05_ifelse.pyc', 'testdata/ifelse-2.7.right',),
disassemble_file
),
@pytest.mark.parametrize(("test_tuple"), [
('../test/bytecode_2.7/05_if.pyc', 'testdata/if-2.7.right',),
('../test/bytecode_2.7/05_ifelse.pyc', 'testdata/ifelse-2.7.right',),
])
def test_funcoutput(capfd, test_tuple, function_to_test):
def test_funcoutput(capfd, test_tuple):
in_file , filename_expected = test_tuple
function_to_test(in_file, native=False)
in_file, filename_expected = test_tuple
disassemble_file(in_file)
resout, reserr = capfd.readouterr()
expected = open(filename_expected, "r").read()
if resout != expected:

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2015-2016 by Rocky Bernstein
# Copyright (c) 2015-2016, 2818 by Rocky Bernstein
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
# Copyright (c) 1999 John Aycock
@@ -13,7 +13,7 @@ that is doing the extraction.
Second, we need structured instruction information for the
(de)-parsing step. Python 3.4 and up provides this, but we still do
want to run on Python 2.7.
want to run on earlier Python versions.
"""
from __future__ import print_function
@@ -23,7 +23,6 @@ from collections import deque
import uncompyle6
from xdis.main import disassemble_file as xdisassemble_file
from xdis.code import iscode
from xdis.load import check_object_path, load_module
from uncompyle6.scanner import get_scanner
@@ -65,17 +64,13 @@ def disco_loop(disasm, queue, real_out):
pass
pass
def disassemble_file(filename, outstream=None, native=False):
def disassemble_file(filename, outstream=None):
"""
disassemble Python byte-code file (.pyc)
If given a Python source file (".py") file, we'll
try to find the corresponding compiled object.
"""
if native:
xdisassemble_file(filename, outstream)
return
filename = check_object_path(filename)
(version, timestamp, magic_int, co, is_pypy,
source_size) = load_module(filename)
@@ -90,14 +85,14 @@ def _test():
"""Simple test program to disassemble a file."""
argc = len(sys.argv)
if argc != 2:
if argc == 1 and uncompyle6.PYTHON3:
if argc == 1:
fn = __file__
else:
sys.stderr.write("usage: %s [-|CPython compiled file]\n" % __file__)
sys.exit(2)
else:
fn = sys.argv[1]
disassemble_file(fn, native=True)
disassemble_file(fn)
if __name__ == "__main__":
_test()

View File

@@ -1643,7 +1643,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
pass
def deparse_code(version, co, out=StringIO(), showasm=False, showast=False,
showgrammar=False, is_pypy=False):
showgrammar=False, is_pypy=False, walker=FragmentsWalker):
"""
Convert the code object co into a python source fragment.
@@ -1683,7 +1683,8 @@ def deparse_code(version, co, out=StringIO(), showasm=False, showast=False,
# Build AST from disassembly.
# deparsed = pysource.FragmentsWalker(out, scanner, showast=showast)
deparsed = FragmentsWalker(version, scanner, showast=showast, debug_parser=debug_parser)
deparsed = walker(version, scanner, showast=showast,
debug_parser=debug_parser)
deparsed.ast = deparsed.build_ast(tokens, customize)

View File

@@ -1,10 +1,9 @@
# Copyright (c) 2018 by Rocky Bernstein
from uncompyle6.semantics.pysource import SourceWalker, deparse_code
import uncompyle6.semantics.fragments as fragments
# FIXME: does this handle nested code, and lambda properly
class LineMapWalker(SourceWalker):
def __init__(self, *args, **kwargs):
if 'first_line' not in kwargs:
first_line = 0
def __init__(self, *args, **kwargs):
super(LineMapWalker, self).__init__(*args, **kwargs)
self.source_linemap = {}
@@ -28,6 +27,12 @@ class LineMapWalker(SourceWalker):
self.source_linemap[self.current_line_number] = node.linestart
return super(LineMapWalker, self).default(node)
class LineMapFragmentWalker(fragments.FragmentsWalker, LineMapWalker):
def __init__(self, *args, **kwargs):
super(LineMapFragmentWalker, self).__init__(*args, **kwargs)
self.source_linemap = {}
self.current_line_number = 0
def deparse_code_with_map(*args, **kwargs):
"""
Like deparse_code but saves line number correspondences.
@@ -35,13 +40,21 @@ def deparse_code_with_map(*args, **kwargs):
kwargs['walker'] = LineMapWalker
return deparse_code(*args, **kwargs)
def deparse_code_with_fragments_and_map(*args, **kwargs):
"""
Like deparse_code_with_map but saves fragments.
"""
kwargs['walker'] = LineMapFragmentWalker
return fragments.deparse_code(*args, **kwargs)
if __name__ == '__main__':
def deparse_test(co):
"This is a docstring"
import sys
sys_version = float(sys.version[0:3])
# deparsed = deparse_code(sys_version, co, showasm=True, showast=True)
deparsed = deparse_code_with_map(sys_version, co, showasm=False, showast=False,
deparsed = deparse_code_with_map(sys_version, co, showasm=False,
showast=False,
showgrammar=False)
a = 1; b = 2
print("\n")
@@ -49,5 +62,16 @@ if __name__ == '__main__':
for line_no in
sorted(deparsed.source_linemap.keys())]
print(linemap)
deparsed = deparse_code_with_fragments_and_map(sys_version,
co, showasm=False,
showast=False,
showgrammar=False)
a = 1; b = 2
print("\n")
linemap2 = [(line_no, deparsed.source_linemap[line_no])
for line_no in
sorted(deparsed.source_linemap.keys())]
print(linemap2)
assert linemap == linemap2
return
deparse_test(deparse_test.__code__)