Work on fragments API...

* Add code_deparse_around_offset
* find_globals -> find_globals_and_nonlocals
This commit is contained in:
rocky
2018-03-20 13:43:16 -04:00
parent 9f2c7352e7
commit 85a49aec2f

View File

@@ -65,9 +65,10 @@ The node position 0 will be associated with "import".
from __future__ import print_function from __future__ import print_function
import re, sys import re
from xdis.code import iscode from xdis.code import iscode
from xdis.magics import sysinfo2float
from uncompyle6.semantics import pysource from uncompyle6.semantics import pysource
from uncompyle6 import parser from uncompyle6 import parser
from uncompyle6.scanner import Token, Code, get_scanner 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) assert iscode(co)
if version is None: if version is None:
version = float(sys.version[0:3]) version = sysinfo2float()
if is_pypy is None: if is_pypy is None:
is_pypy = IS_PYPY 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 # convert leading '__doc__ = "..." into doc string
assert deparsed.ast == 'stmts' 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 # Just when you think we've forgotten about what we
# were supposed to to: Generate source from AST! # were supposed to to: Generate source from AST!
@@ -1836,15 +1841,22 @@ def find_gt(a, x):
return a[i] return a[i]
raise ValueError raise ValueError
def deparse_code_around_offset(name, offset, version, co, out=StringIO(), def code_deparse_around_offset(name, offset, co, out=StringIO(),
showasm=False, showast=False, version=None, is_pypy=None,
showgrammar=False, is_pypy=False): debug_opts=DEFAULT_DEBUG_OPTS):
""" """
Like deparse_code(), but given a function/module name and Like deparse_code(), but given a function/module name and
offset, finds the node closest to offset. If offset is not an instruction boundary, offset, finds the node closest to offset. If offset is not an instruction boundary,
we raise an IndexError. 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(): if (name, offset) in deparsed.offsets.keys():
# This is the easy case # This is the easy case
return deparsed 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] deparsed.offsets[name, offset] = deparsed.offsets[name, found_offset]
return deparsed 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): def op_at_code_loc(code, loc, opc):
"""Return the instruction name at code[loc] using """Return the instruction name at code[loc] using
@@ -1893,96 +1916,91 @@ def deparsed_find(tup, deparsed, code):
return nodeInfo return nodeInfo
# if __name__ == '__main__': if __name__ == '__main__':
# def deparse_test(co, is_pypy=IS_PYPY): def deparse_test(co, is_pypy=IS_PYPY):
# deparsed = code_deparse(co, is_pypy=IS_PYPY) deparsed = code_deparse(co, is_pypy=IS_PYPY)
# print("deparsed source") print("deparsed source")
# print(deparsed.text, "\n") print(deparsed.text, "\n")
# print('------------------------') print('------------------------')
# for name, offset in sorted(deparsed.offsets.keys(), for name, offset in sorted(deparsed.offsets.keys(),
# key=lambda x: str(x[0])): key=lambda x: str(x[0])):
# print("name %s, offset %s" % (name, offset)) print("name %s, offset %s" % (name, offset))
# nodeInfo = deparsed.offsets[name, offset] nodeInfo = deparsed.offsets[name, offset]
# nodeInfo2 = deparsed_find((name, offset), deparsed, co) nodeInfo2 = deparsed_find((name, offset), deparsed, co)
# assert nodeInfo == nodeInfo2 assert nodeInfo == nodeInfo2
# node = nodeInfo.node node = nodeInfo.node
# extractInfo = deparsed.extract_node_info(node) extractInfo = deparsed.extract_node_info(node)
# print("code: %s" % node.kind) print("code: %s" % node.kind)
# # print extractInfo # print extractInfo
# print(extractInfo.selectedText) print(extractInfo.selectedText)
# print(extractInfo.selectedLine) print(extractInfo.selectedLine)
# print(extractInfo.markerLine) print(extractInfo.markerLine)
# extractInfo, p = deparsed.extract_parent_info(node) extractInfo, p = deparsed.extract_parent_info(node)
# if extractInfo: if extractInfo:
# print("Contained in...") print("Contained in...")
# print(extractInfo.selectedLine) print(extractInfo.selectedLine)
# print(extractInfo.markerLine) print(extractInfo.markerLine)
# print("code: %s" % p.kind) print("code: %s" % p.kind)
# print('=' * 40) print('=' * 40)
# pass pass
# pass pass
# return return
# def deparse_test_around(offset, name, co, is_pypy=IS_PYPY): def deparse_test_around(offset, name, co, is_pypy=IS_PYPY):
# sys_version = sys.version_info.major + (sys.version_info.minor / 10.0) deparsed = code_deparse_around_offset(name, offset, co)
# deparsed = deparse_code_around_offset(name, offset, sys_version, co, print("deparsed source")
# showasm=False, print(deparsed.text, "\n")
# showast=False, print('------------------------')
# showgrammar=False, for name, offset in sorted(deparsed.offsets.keys(),
# is_pypy=IS_PYPY) key=lambda x: str(x[0])):
# print("deparsed source") print("name %s, offset %s" % (name, offset))
# print(deparsed.text, "\n") nodeInfo = deparsed.offsets[name, offset]
# print('------------------------') node = nodeInfo.node
# for name, offset in sorted(deparsed.offsets.keys(), extractInfo = deparsed.extract_node_info(node)
# key=lambda x: str(x[0])): print("code: %s" % node.kind)
# print("name %s, offset %s" % (name, offset)) # print extractInfo
# nodeInfo = deparsed.offsets[name, offset] print(extractInfo.selectedText)
# node = nodeInfo.node print(extractInfo.selectedLine)
# extractInfo = deparsed.extract_node_info(node) print(extractInfo.markerLine)
# print("code: %s" % node.kind) extractInfo, p = deparsed.extract_parent_info(node)
# # print extractInfo if extractInfo:
# print(extractInfo.selectedText) print("Contained in...")
# print(extractInfo.selectedLine) print(extractInfo.selectedLine)
# print(extractInfo.markerLine) print(extractInfo.markerLine)
# extractInfo, p = deparsed.extract_parent_info(node) print("code: %s" % p.kind)
# if extractInfo: print('=' * 40)
# print("Contained in...") pass
# print(extractInfo.selectedLine) pass
# print(extractInfo.markerLine) return
# print("code: %s" % p.kind)
# print('=' * 40)
# pass
# pass
# return
# def get_code_for_fn(fn): def get_code_for_fn(fn):
# return fn.__code__ return fn.__code__
# def test(): def test():
# import os, sys import os, sys
# def div_test(a, b, c): def div_test(a, b, c):
# return a / b / c return a / b / c
# def gcd(a, b): def gcd(a, b):
# if a > b: if a > b:
# (a, b) = (b, a) (a, b) = (b, a)
# pass pass
# if a <= 0: if a <= 0:
# return None return None
# if a == 1 or a == b: if a == 1 or a == b:
# return a return a
# return gcd(b-a, a) return gcd(b-a, a)
# # check_args(['3', '5']) # check_args(['3', '5'])
# # deparse_test(get_code_for_fn(gcd)) # deparse_test(get_code_for_fn(gcd))
# deparse_test(get_code_for_fn(div_test)) deparse_test(get_code_for_fn(div_test))
# # deparse_test(get_code_for_fn(test)) # deparse_test(get_code_for_fn(test))
# # deparse_test(get_code_for_fn(FragmentsWalker.fixup_offsets)) # deparse_test(get_code_for_fn(FragmentsWalker.fixup_offsets))
# # deparse_test(get_code_for_fn(FragmentsWalker.n_list)) # deparse_test(get_code_for_fn(FragmentsWalker.n_list))
# print('=' * 30) print('=' * 30)
# # deparse_test_around(408, 'n_list', get_code_for_fn(FragmentsWalker.n_build_list)) # deparse_test_around(408, 'n_list', get_code_for_fn(FragmentsWalker.n_build_list))
# # deparse_test(inspect.currentframe().f_code) # deparse_test(inspect.currentframe().f_code)