From 85a49aec2ffed58becb59dcf9c3ae3dbe79a9a0d Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 20 Mar 2018 13:43:16 -0400 Subject: [PATCH] Work on fragments API... * Add code_deparse_around_offset * find_globals -> find_globals_and_nonlocals --- uncompyle6/semantics/fragments.py | 200 ++++++++++++++++-------------- 1 file changed, 109 insertions(+), 91 deletions(-) diff --git a/uncompyle6/semantics/fragments.py b/uncompyle6/semantics/fragments.py index 24cb6108..e3ef76ef 100644 --- a/uncompyle6/semantics/fragments.py +++ b/uncompyle6/semantics/fragments.py @@ -65,9 +65,10 @@ The node position 0 will be associated with "import". from __future__ import print_function -import re, sys +import re from xdis.code import iscode +from xdis.magics import sysinfo2float from uncompyle6.semantics import pysource from uncompyle6 import parser from uncompyle6.scanner import Token, Code, get_scanner @@ -1763,7 +1764,7 @@ def code_deparse(co, out=StringIO(), version=None, is_pypy=None, assert iscode(co) if version is None: - version = float(sys.version[0:3]) + version = sysinfo2float() if is_pypy is None: is_pypy = IS_PYPY @@ -1797,7 +1798,11 @@ def code_deparse(co, out=StringIO(), version=None, is_pypy=None, # convert leading '__doc__ = "..." into doc string assert deparsed.ast == 'stmts' - deparsed.mod_globs = pysource.find_globals(deparsed.ast, set()) + (deparsed.mod_globs, + nonlocals) = (pysource + .find_globals_and_nonlocals(deparsed.ast, + set(), set(), + co, version)) # Just when you think we've forgotten about what we # were supposed to to: Generate source from AST! @@ -1836,15 +1841,22 @@ def find_gt(a, x): return a[i] raise ValueError -def deparse_code_around_offset(name, offset, version, co, out=StringIO(), - showasm=False, showast=False, - showgrammar=False, is_pypy=False): +def code_deparse_around_offset(name, offset, co, out=StringIO(), + version=None, is_pypy=None, + debug_opts=DEFAULT_DEBUG_OPTS): """ Like deparse_code(), but given a function/module name and offset, finds the node closest to offset. If offset is not an instruction boundary, we raise an IndexError. """ - deparsed = deparse_code(version, co, out, showasm, showast, showgrammar, is_pypy) + assert iscode(co) + + if version is None: + version = sysinfo2float() + if is_pypy is None: + is_pypy = IS_PYPY + + deparsed = code_deparse(co, out, version, is_pypy, debug_opts) if (name, offset) in deparsed.offsets.keys(): # This is the easy case return deparsed @@ -1857,6 +1869,17 @@ def deparse_code_around_offset(name, offset, version, co, out=StringIO(), deparsed.offsets[name, offset] = deparsed.offsets[name, found_offset] return deparsed +# Deprecated. Here still for compatability +def deparse_code_around_offset(name, offset, version, co, out=StringIO(), + showasm=False, showast=False, + showgrammar=False, is_pypy=False): + debug_opts = { + 'asm': showasm, + 'ast': showast, + 'grammar': showgrammar + } + return code_deparse(name, offset, co, out, version, is_pypy, + debug_opts) def op_at_code_loc(code, loc, opc): """Return the instruction name at code[loc] using @@ -1893,96 +1916,91 @@ def deparsed_find(tup, deparsed, code): return nodeInfo -# if __name__ == '__main__': +if __name__ == '__main__': -# def deparse_test(co, is_pypy=IS_PYPY): -# deparsed = code_deparse(co, is_pypy=IS_PYPY) -# print("deparsed source") -# print(deparsed.text, "\n") -# print('------------------------') -# for name, offset in sorted(deparsed.offsets.keys(), -# key=lambda x: str(x[0])): -# print("name %s, offset %s" % (name, offset)) -# nodeInfo = deparsed.offsets[name, offset] -# nodeInfo2 = deparsed_find((name, offset), deparsed, co) -# assert nodeInfo == nodeInfo2 -# node = nodeInfo.node -# extractInfo = deparsed.extract_node_info(node) -# print("code: %s" % node.kind) -# # print extractInfo -# print(extractInfo.selectedText) -# print(extractInfo.selectedLine) -# print(extractInfo.markerLine) -# extractInfo, p = deparsed.extract_parent_info(node) + def deparse_test(co, is_pypy=IS_PYPY): + deparsed = code_deparse(co, is_pypy=IS_PYPY) + print("deparsed source") + print(deparsed.text, "\n") + print('------------------------') + for name, offset in sorted(deparsed.offsets.keys(), + key=lambda x: str(x[0])): + print("name %s, offset %s" % (name, offset)) + nodeInfo = deparsed.offsets[name, offset] + nodeInfo2 = deparsed_find((name, offset), deparsed, co) + assert nodeInfo == nodeInfo2 + node = nodeInfo.node + extractInfo = deparsed.extract_node_info(node) + print("code: %s" % node.kind) + # print extractInfo + print(extractInfo.selectedText) + print(extractInfo.selectedLine) + print(extractInfo.markerLine) + extractInfo, p = deparsed.extract_parent_info(node) -# if extractInfo: -# print("Contained in...") -# print(extractInfo.selectedLine) -# print(extractInfo.markerLine) -# print("code: %s" % p.kind) -# print('=' * 40) -# pass -# pass -# return + if extractInfo: + print("Contained in...") + print(extractInfo.selectedLine) + print(extractInfo.markerLine) + print("code: %s" % p.kind) + print('=' * 40) + pass + pass + return -# def deparse_test_around(offset, name, co, is_pypy=IS_PYPY): -# sys_version = sys.version_info.major + (sys.version_info.minor / 10.0) -# deparsed = deparse_code_around_offset(name, offset, sys_version, co, -# showasm=False, -# showast=False, -# showgrammar=False, -# is_pypy=IS_PYPY) -# print("deparsed source") -# print(deparsed.text, "\n") -# print('------------------------') -# for name, offset in sorted(deparsed.offsets.keys(), -# key=lambda x: str(x[0])): -# print("name %s, offset %s" % (name, offset)) -# nodeInfo = deparsed.offsets[name, offset] -# node = nodeInfo.node -# extractInfo = deparsed.extract_node_info(node) -# print("code: %s" % node.kind) -# # print extractInfo -# print(extractInfo.selectedText) -# print(extractInfo.selectedLine) -# print(extractInfo.markerLine) -# extractInfo, p = deparsed.extract_parent_info(node) -# if extractInfo: -# print("Contained in...") -# print(extractInfo.selectedLine) -# print(extractInfo.markerLine) -# print("code: %s" % p.kind) -# print('=' * 40) -# pass -# pass -# return + def deparse_test_around(offset, name, co, is_pypy=IS_PYPY): + deparsed = code_deparse_around_offset(name, offset, co) + print("deparsed source") + print(deparsed.text, "\n") + print('------------------------') + for name, offset in sorted(deparsed.offsets.keys(), + key=lambda x: str(x[0])): + print("name %s, offset %s" % (name, offset)) + nodeInfo = deparsed.offsets[name, offset] + node = nodeInfo.node + extractInfo = deparsed.extract_node_info(node) + print("code: %s" % node.kind) + # print extractInfo + print(extractInfo.selectedText) + print(extractInfo.selectedLine) + print(extractInfo.markerLine) + extractInfo, p = deparsed.extract_parent_info(node) + if extractInfo: + print("Contained in...") + print(extractInfo.selectedLine) + print(extractInfo.markerLine) + print("code: %s" % p.kind) + print('=' * 40) + pass + pass + return -# def get_code_for_fn(fn): -# return fn.__code__ + def get_code_for_fn(fn): + return fn.__code__ -# def test(): -# import os, sys + def test(): + import os, sys -# def div_test(a, b, c): -# return a / b / c + def div_test(a, b, c): + return a / b / c -# def gcd(a, b): -# if a > b: -# (a, b) = (b, a) -# pass + def gcd(a, b): + if a > b: + (a, b) = (b, a) + pass -# if a <= 0: -# return None -# if a == 1 or a == b: -# return a -# return gcd(b-a, a) + if a <= 0: + return None + if a == 1 or a == b: + return a + return gcd(b-a, a) -# # check_args(['3', '5']) -# # deparse_test(get_code_for_fn(gcd)) -# deparse_test(get_code_for_fn(div_test)) -# # deparse_test(get_code_for_fn(test)) -# # deparse_test(get_code_for_fn(FragmentsWalker.fixup_offsets)) -# # deparse_test(get_code_for_fn(FragmentsWalker.n_list)) -# print('=' * 30) -# # deparse_test_around(408, 'n_list', get_code_for_fn(FragmentsWalker.n_build_list)) -# # deparse_test(inspect.currentframe().f_code) + # check_args(['3', '5']) + # deparse_test(get_code_for_fn(gcd)) + deparse_test(get_code_for_fn(div_test)) + # deparse_test(get_code_for_fn(test)) + # deparse_test(get_code_for_fn(FragmentsWalker.fixup_offsets)) + # deparse_test(get_code_for_fn(FragmentsWalker.n_list)) + print('=' * 30) + # deparse_test_around(408, 'n_list', get_code_for_fn(FragmentsWalker.n_build_list)) + # deparse_test(inspect.currentframe().f_code)