Minimal disassemble, ast compile and deparse work on Python 3.

Some linting
This commit is contained in:
rocky
2015-12-12 09:09:34 -05:00
parent 87a3bf1935
commit 832debeb70
8 changed files with 226 additions and 424 deletions

View File

@@ -3,7 +3,7 @@
[flake8]
exclude = .tox,./build,./trepan/processor/command/tmp
filename = *.py
ignore = C901,E113,E121,E122,E123,E125,E126,E127,E128,E129,E201,E202,E203,E221,E222,E225,E226,E241,E242,E251,E261,E271,E272,E302,E401,E501,F401,E701,E702
ignore = C901,E113,E121,E122,E123,E124,E125,E126,E127,E128,E129,E201,E202,E203,E221,E222,E225,E226,E241,E242,E251,E261,E271,E272,E302,E401,E501,F401,E701,E702
[tox]
envlist = py26, py27, pypy

View File

@@ -15,188 +15,12 @@ else:
from collections import namedtuple
NodeInfo = namedtuple("NodeInfo", "node start finish")
class FindWalker(walker.Walker, object):
stacked_params = ('f', 'indent', 'isLambda', '_globals')
def __init__(self, out, scanner, showast=0):
GenericASTTraversal.__init__(self, ast=None)
params = {
'f': out,
'indent': '',
}
self.showast = showast
self.__params = params
self.__param_stack = []
self.ERROR = None
self.prec = 100
self.return_none = False
self.mod_globs = set()
self.currentclass = None
self.pending_newlines = 0
self.found_offset = False
self.offsets = {}
f = property(lambda s: s.__params['f'],
lambda s, x: s.__params.__setitem__('f', x),
lambda s: s.__params.__delitem__('f'),
None)
indent = property(lambda s: s.__params['indent'],
lambda s, x: s.__params.__setitem__('indent', x),
lambda s: s.__params.__delitem__('indent'),
None)
isLambda = property(lambda s: s.__params['isLambda'],
lambda s, x: s.__params.__setitem__('isLambda', x),
lambda s: s.__params.__delitem__('isLambda'),
None)
_globals = property(lambda s: s.__params['_globals'],
lambda s, x: s.__params.__setitem__('_globals', x),
lambda s: s.__params.__delitem__('_globals'),
None)
def preorder(self, node=None):
if node is None:
node = self.ast
if hasattr(node, 'offset'):
start = len(self.f.getvalue())
if node.offset == self.find_offset:
self.found_offset = True
# print 'BINGO!'
try:
name = 'n_' + self.typestring(node)
if hasattr(self, name):
func = getattr(self, name)
func(node)
else:
self.default(node)
except GenericASTTraversalPruningException:
if hasattr(node, 'offset'):
self.offsets[node.offset] = NodeInfo(node = node,
start = start,
finish = len(self.f.getvalue()))
# print self.offsets[node.offset]
# print self.f.getvalue()[start:]
return
for kid in node:
self.preorder(kid)
name = name + '_exit'
if hasattr(self, name):
func = getattr(self, name)
func(node)
return
def find_source(self, offset, ast, customize, isLambda=0, returnNone=False):
"""convert AST to source code"""
self.find_offset = offset
self.found_offset = False
# FIXME; the below doesn't find self.__params
# work so we duplicate the code.
# self.gen_source(ast, customize, isLambda, returnNone)
rn = self.return_none
self.return_none = returnNone
# if code would be empty, append 'pass'
if len(ast) == 0:
self.print_(self.indent, 'pass')
else:
self.customize(customize)
result = self.traverse(ast, isLambda=isLambda)
if isLambda:
self.write(result)
else:
self.print_(result)
self.return_none = rn
# FIXME; below duplicated the code, since we don't find self.__params
def traverse(self, node, indent=None, isLambda=0):
self.__param_stack.append(self.__params)
if indent is None: indent = self.indent
p = self.pending_newlines
self.pending_newlines = 0
self.__params = {
'_globals': {},
'f': StringIO(),
'indent': indent,
'isLambda': isLambda,
}
self.preorder(node)
self.f.write('\n'*self.pending_newlines)
result = self.f.getvalue()
self.__params = self.__param_stack.pop()
self.pending_newlines = p
return result
pass
def uncompyle_find(version, co, find_offset, out=sys.stdout, showasm=0, showast=0):
assert isinstance(co, types.CodeType)
# store final output stream for case of error
__real_out = out or sys.stdout
if version == 2.7:
import uncompyle6.scanner27 as scan
scanner = scan.Scanner27()
elif version == 2.6:
import scanner26 as scan
scanner = scan.Scanner26()
elif version == 2.5:
import scanner25 as scan
scanner = scan.Scanner25()
scanner.setShowAsm(0, out)
tokens, customize = scanner.disassemble(co)
# Build AST from disassembly.
# walk = walker.Walker(out, scanner, showast=showast)
walk = FindWalker(out, scanner, showast=showast)
try:
ast = walk.build_ast(tokens, customize)
except walker.ParserError as e : # parser failed, dump disassembly
print(e, file=__real_out)
raise
del tokens # save memory
# convert leading '__doc__ = "..." into doc string
assert ast == 'stmts'
try:
if ast[0][0] == walker.ASSIGN_DOC_STRING(co.co_consts[0]):
if find_offset == 0:
walk.print_docstring('', co.co_consts[0])
return
del ast[0]
if ast[-1] == walker.RETURN_NONE:
ast.pop() # remove last node
# todo: if empty, add 'pass'
except:
pass
walk.mod_globs = walker.find_globals(ast, set())
# walk.gen_source(ast, customize)
walk.find_source(find_offset, ast, customize)
for g in walk.mod_globs:
walk.write('global %s ## Warning: Unused global' % g)
if walk.ERROR:
raise walk.ERROR
return
def uncompyle_test():
frame = inspect.currentframe()
try:
co = frame.f_code
uncompyle(2.7, co, sys.stdout, 1, 1)
print()
print('------------------------')
uncompyle_find(2.7, co, 33)
finally:
del frame

View File

@@ -42,7 +42,7 @@ class AST(UserList):
def __repr__(self, indent=''):
rv = str(self.type)
for k in self:
rv = rv + '\n' + string.replace(str(k), '\n', '\n ')
rv = rv + '\n' + str(k).replace('\n', '\n ')
return rv
@@ -753,7 +753,8 @@ def parse(tokens, customize):
p.customized[k] = None
# nop = lambda self, args: None
op = k[:string.rfind(k, '_')]
op = k[:k.rfind('_')]
if op in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET'):
rule = 'build_list ::= ' + 'expr '*v + k
elif op in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
@@ -784,7 +785,7 @@ def parse(tokens, customize):
na = (v & 0xff) # positional parameters
nk = (v >> 8) & 0xff # keyword parameters
# number of apply equiv arguments:
nak = ( len(op)-len('CALL_FUNCTION') ) / 3
nak = ( len(op)-len('CALL_FUNCTION') ) // 3
rule = 'call_function ::= expr ' + 'expr '*na + 'kwarg '*nk \
+ 'expr ' * nak + k
else:

View File

@@ -42,6 +42,7 @@ class Scanner25(scan.Scanner):
# class and names
if classname:
classname = '_' + classname.lstrip('_') + '__'
def unmangle(name):
if name.startswith(classname) and name[-2:] != '__':
return name[len(classname) - 2:]

View File

@@ -55,7 +55,6 @@ class Scanner27(scan.Scanner):
while j < start_byte:
self.lines.append(linetuple(prev_line_no, start_byte))
j += 1
last_op = self.code[self.prev[start_byte]]
(prev_start_byte, prev_line_no) = (start_byte, line_no)
while j < n:
self.lines.append(linetuple(prev_line_no, n))
@@ -63,6 +62,7 @@ class Scanner27(scan.Scanner):
# self.lines contains (block,addrLastInstr)
if classname:
classname = '_' + classname.lstrip('_') + '__'
def unmangle(name):
if name.startswith(classname) and name[-2:] != '__':
return name[len(classname) - 2:]
@@ -126,7 +126,7 @@ class Scanner27(scan.Scanner):
continue
if op in hasconst:
const = co.co_consts[oparg]
if type(const) == types.CodeType:
if isinstance(const, types.CodeType):
oparg = const
if const.co_name == '<lambda>':
assert op_name == 'LOAD_CONST'
@@ -348,8 +348,6 @@ class Scanner27(scan.Scanner):
start = _start
end = _end
parent = s
# We need to know how many new structures were added in this run
origStructCount = len(self.structs)
if op == SETUP_LOOP:
start = pos+3
@@ -444,7 +442,7 @@ class Scanner27(scan.Scanner):
'end': jmp})
i = jmp + 3
## Add the try-else block
# Add the try-else block
if end_else != start_else:
r_end_else = self.restrict_to_parent(end_else, parent)
self.structs.append({'type': 'try-else',
@@ -454,7 +452,6 @@ class Scanner27(scan.Scanner):
else:
self.fixed_jumps[i] = i+1
elif op in (PJIF, PJIT):
start = pos+3
target = self.get_target(pos, op)
@@ -491,9 +488,10 @@ class Scanner27(scan.Scanner):
pass
elif code[pre[pre[rtarget]]] == RETURN_VALUE \
and self.remove_mid_line_ifs([pos]) \
and 1 == (len(set(self.remove_mid_line_ifs(self.rem_or(start, pre[pre[rtarget]], \
(PJIF, PJIT), target))) \
| set(self.remove_mid_line_ifs(self.rem_or(start, pre[pre[rtarget]], \
and 1 == (len(set(self.remove_mid_line_ifs(self.rem_or(start,
pre[pre[rtarget]],
(PJIF, PJIT), target)))
| set(self.remove_mid_line_ifs(self.rem_or(start, pre[pre[rtarget]],
(PJIF, PJIT, JA), pre[rtarget], True))))):
pass
else:

View File

@@ -8,14 +8,13 @@ from __future__ import print_function
See main module for license.
'''
import types
import dis, types
from collections import namedtuple
from array import array
from operator import itemgetter
from uncompyle6.opcodes.opcode_27 import *
import disas as dis
import scanner as scan
import uncompyle6.scanner as scan
class Scanner27(scan.Scanner):
def __init__(self):
@@ -56,7 +55,6 @@ class Scanner27(scan.Scanner):
while j < start_byte:
self.lines.append(linetuple(prev_line_no, start_byte))
j += 1
last_op = self.code[self.prev[start_byte]]
(prev_start_byte, prev_line_no) = (start_byte, line_no)
while j < n:
self.lines.append(linetuple(prev_line_no, n))
@@ -64,6 +62,7 @@ class Scanner27(scan.Scanner):
# self.lines contains (block,addrLastInstr)
if classname:
classname = '_' + classname.lstrip('_') + '__'
def unmangle(name):
if name.startswith(classname) and name[-2:] != '__':
return name[len(classname) - 2:]
@@ -211,7 +210,7 @@ class Scanner27(scan.Scanner):
def build_stmt_indices(self):
code = self.code
start = 0;
start = 0
end = len(code)
stmt_opcodes = {
@@ -338,7 +337,7 @@ class Scanner27(scan.Scanner):
if op is None:
op = code[pos]
## Detect parent structure
# Detect parent structure
parent = self.structs[0]
start = parent['start']
end = parent['end']
@@ -349,7 +348,7 @@ class Scanner27(scan.Scanner):
start = _start
end = _end
parent = s
## We need to know how many new structures were added in this run
# We need to know how many new structures were added in this run
origStructCount = len(self.structs)
if op == SETUP_LOOP:
@@ -419,14 +418,14 @@ class Scanner27(scan.Scanner):
if target != end:
self.fixed_jumps[pos] = end
# print target, end, parent
## Add the try block
# Add the try block
self.structs.append({'type': 'try',
'start': start,
'end': end-4})
## Now isolate the except and else blocks
# Now isolate the except and else blocks
end_else = start_else = self.get_target(self.prev[end])
## Add the except blocks
# Add the except blocks
i = end
while self.code[i] != END_FINALLY:
jmp = self.next_except_jump(i)
@@ -445,7 +444,7 @@ class Scanner27(scan.Scanner):
'end': jmp})
i = jmp + 3
## Add the try-else block
# Add the try-else block
if end_else != start_else:
r_end_else = self.restrict_to_parent(end_else, parent)
self.structs.append({'type': 'try-else',
@@ -455,7 +454,6 @@ class Scanner27(scan.Scanner):
else:
self.fixed_jumps[i] = i+1
elif op in (PJIF, PJIT):
start = pos+3
target = self.get_target(pos, op)
@@ -492,9 +490,10 @@ class Scanner27(scan.Scanner):
pass
elif code[pre[pre[rtarget]]] == RETURN_VALUE \
and self.remove_mid_line_ifs([pos]) \
and 1 == (len(set(self.remove_mid_line_ifs(self.rem_or(start, pre[pre[rtarget]], \
(PJIF, PJIT), target))) \
| set(self.remove_mid_line_ifs(self.rem_or(start, pre[pre[rtarget]], \
and 1 == (len(set(self.remove_mid_line_ifs(self.rem_or(start,
pre[pre[rtarget]],
(PJIF, PJIT), target)))
| set(self.remove_mid_line_ifs(self.rem_or(start, pre[pre[rtarget]],
(PJIF, PJIT, JA), pre[rtarget], True))))):
pass
else:

View File

@@ -94,11 +94,11 @@ class GenericParser:
for k, v in list(self.edges.items()):
if v is None:
state, sym = k
if self.states.has_key(state):
if state in self.states:
self.goto(state, sym)
changes = 1
rv = self.__dict__.copy()
for s in self.states.values():
for s in list(self.states.values()):
del s.items
del rv['rule2func']
del rv['nullable']
@@ -266,7 +266,7 @@ class GenericParser:
self.states = { 0: self.makeState0() }
self.makeState(0, self._BOF)
for i in xrange(len(tokens)):
for i in range(len(tokens)):
sets.append([])
if sets[i] == []:
@@ -315,7 +315,7 @@ class GenericParser:
kitems.append((rule, self.skip(rule, pos+1)))
tcore = tuple(sorted(kitems))
if self.cores.has_key(tcore):
if tcore in self.cores:
return self.cores[tcore]
#
# Nope, doesn't exist. Compute it and the associated
@@ -339,13 +339,13 @@ class GenericParser:
nextSym = rhs[pos]
key = (X.stateno, nextSym)
if not rules.has_key(nextSym):
if not edges.has_key(key):
if nextSym not in rules:
if key not in edges:
edges[key] = None
X.T.append(nextSym)
else:
edges[key] = None
if not predicted.has_key(nextSym):
if nextSym not in predicted:
predicted[nextSym] = 1
for prule in rules[nextSym]:
ppos = self.skip(prule)
@@ -370,7 +370,7 @@ class GenericParser:
# to do this without accidentally duplicating states.
#
tcore = tuple(sorted(predicted.keys()))
if self.cores.has_key(tcore):
if tcore in self.cores:
self.edges[(k, None)] = self.cores[tcore]
return k
@@ -381,7 +381,7 @@ class GenericParser:
def goto(self, state, sym):
key = (state, sym)
if not self.edges.has_key(key):
if key not in self.edges:
#
# No transitions from state on sym.
#
@@ -579,7 +579,7 @@ class GenericParser:
for i in range(len(rhs)-1, -1, -1):
sym = rhs[i]
if not self.newrules.has_key(sym):
if sym not in self.newrules:
if sym != self._BOF:
attr[i] = tokens[k-1]
key = (item, k)
@@ -656,7 +656,7 @@ class GenericASTBuilder(GenericParser):
rv[:len(args)] = args
return rv
class GenericASTTraversalPruningException:
class GenericASTTraversalPruningException(BaseException):
pass
class GenericASTTraversal:

View File

@@ -309,9 +309,9 @@ TABLE_DIRECT = {
'kv2': ( '%c: %c', 1, 2 ),
'mapexpr': ( '{%[1]C}', (0, maxint, ', ') ),
##
## Python 2.5 Additions
##
#######################
# Python 2.5 Additions
#######################
# Import style for 2.5
'importstmt': ( '%|import %c\n', 2),
@@ -417,7 +417,7 @@ class ParserError(dparser.ParserError):
def __str__(self):
lines = ['--- This code section failed: ---']
lines.extend( map(str, self.tokens) )
lines.extend( list(map(str, self.tokens)) )
lines.extend( ['', str(self.error)] )
return '\n'.join(lines)
@@ -446,7 +446,7 @@ def find_none(node):
if not (n == 'return_stmt' or n == 'return_if_stmt'):
if find_none(n):
return True
elif n.type == 'LOAD_CONST' and n.pattr == None:
elif n.type == 'LOAD_CONST' and n.pattr is None:
return True
return False
@@ -461,8 +461,8 @@ class Walker(GenericASTTraversal, object):
'indent': '',
}
self.showast = showast
self.__params = params
self.__param_stack = []
self.params = params
self.param_stack = []
self.ERROR = None
self.prec = 100
self.return_none = False
@@ -470,37 +470,38 @@ class Walker(GenericASTTraversal, object):
self.currentclass = None
self.pending_newlines = 0
f = property(lambda s: s.__params['f'],
lambda s, x: s.__params.__setitem__('f', x),
lambda s: s.__params.__delitem__('f'),
f = property(lambda s: s.params['f'],
lambda s, x: s.params.__setitem__('f', x),
lambda s: s.params.__delitem__('f'),
None)
indent = property(lambda s: s.__params['indent'],
lambda s, x: s.__params.__setitem__('indent', x),
lambda s: s.__params.__delitem__('indent'),
indent = property(lambda s: s.params['indent'],
lambda s, x: s.params.__setitem__('indent', x),
lambda s: s.params.__delitem__('indent'),
None)
isLambda = property(lambda s: s.__params['isLambda'],
lambda s, x: s.__params.__setitem__('isLambda', x),
lambda s: s.__params.__delitem__('isLambda'),
isLambda = property(lambda s: s.params['isLambda'],
lambda s, x: s.params.__setitem__('isLambda', x),
lambda s: s.params.__delitem__('isLambda'),
None)
_globals = property(lambda s: s.__params['_globals'],
lambda s, x: s.__params.__setitem__('_globals', x),
lambda s: s.__params.__delitem__('_globals'),
_globals = property(lambda s: s.params['_globals'],
lambda s, x: s.params.__setitem__('_globals', x),
lambda s: s.params.__delitem__('_globals'),
None)
def indentMore(self, indent=TAB):
self.indent += indent
def indentLess(self, indent=TAB):
self.indent = self.indent[:-len(indent)]
def traverse(self, node, indent=None, isLambda=0):
self.__param_stack.append(self.__params)
self.param_stack.append(self.params)
if indent is None: indent = self.indent
p = self.pending_newlines
self.pending_newlines = 0
self.__params = {
self.params = {
'_globals': {},
'f': StringIO(),
'indent': indent,
@@ -509,7 +510,7 @@ class Walker(GenericASTTraversal, object):
self.preorder(node)
self.f.write('\n'*self.pending_newlines)
result = self.f.getvalue()
self.__params = self.__param_stack.pop()
self.params = self.param_stack.pop()
self.pending_newlines = p
return result
@@ -554,6 +555,7 @@ class Walker(GenericASTTraversal, object):
def print_docstring(self, indent, docstring):
quote = '"""'
self.write(indent)
# FIXME for Python3
if type(docstring) == unicode:
self.write('u')
docstring = repr(docstring.expandtabs())[2:-1]
@@ -580,7 +582,8 @@ class Walker(GenericASTTraversal, object):
# restore backslashes unescaped since raw
docstring = docstring.replace('\t', '\\')
else:
#Escape '"' if it's the last character, so it doesn't ruin the ending triple quote
# Escape '"' if it's the last character, so it doesn't
# ruin the ending triple quote
if len(docstring) and docstring[-1] == '"':
docstring = docstring[:-1] + '\\"'
# Escape triple quote anywhere
@@ -610,9 +613,8 @@ class Walker(GenericASTTraversal, object):
self.print_( indent, line )
self.print_(indent, trimmed[-1], quote)
def n_return_stmt(self, node):
if self.__params['isLambda']:
if self.params['isLambda']:
self.preorder(node[0])
self.prune()
else:
@@ -624,7 +626,7 @@ class Walker(GenericASTTraversal, object):
self.prune() # stop recursing
def n_return_if_stmt(self, node):
if self.__params['isLambda']:
if self.params['isLambda']:
self.preorder(node[0])
self.prune()
else:
@@ -730,7 +732,6 @@ class Walker(GenericASTTraversal, object):
# LOAD_CONST is a terminal, so stop processing/recursing early
self.prune()
def n_delete_subscr(self, node):
if node[-2][0] == 'build_list' and node[-2][0][-1].type.startswith('BUILD_TUPLE'):
if node[-2][0][-1] != 'BUILD_TUPLE_0':
@@ -854,13 +855,6 @@ class Walker(GenericASTTraversal, object):
self.preorder(node[1])
self.indentLess()
if_ret_at_end = False
if len(node[2][0]) >= 3:
if node[2][0][-1][0] == 'ifstmt' and node[2][0][-1][0][1][0] == 'return_if_stmts':
if_ret_at_end = True
past_else = False
prev_stmt_is_if_ret = True
for n in node[2][0]:
n[0].type = 'elifstmt'
self.preorder(n)
@@ -871,7 +865,7 @@ class Walker(GenericASTTraversal, object):
self.prune()
def n_import_as(self, node):
iname = node[0].pattr;
iname = node[0].pattr
assert node[-1][-1].type.startswith('STORE_')
sname = node[-1][-1].pattr # assume one of STORE_.... here
if iname == sname or iname.startswith(sname + '.'):
@@ -893,7 +887,7 @@ class Walker(GenericASTTraversal, object):
self.write(node[-2].attr.co_name) # = code.co_name
self.indentMore()
self.make_function(node, isLambda=0)
if len(self.__param_stack) > 1:
if len(self.param_stack) > 1:
self.write('\n\n')
else:
self.write('\n\n\n')
@@ -916,7 +910,7 @@ class Walker(GenericASTTraversal, object):
elif n == 'list_if': n = n[2]
elif n == 'list_if_not': n= n[2]
assert n == 'lc_body'
self.write( '[ ');
self.write( '[ ')
self.preorder(n[0]) # lc_body
self.preorder(node[-1]) # for/if parts
self.write( ' ]')
@@ -960,7 +954,6 @@ class Walker(GenericASTTraversal, object):
self.write(')')
self.prune()
def n_setcomp(self, node):
self.write('{')
self.comprehension_walk(node, 4)
@@ -969,7 +962,6 @@ class Walker(GenericASTTraversal, object):
n_dictcomp = n_setcomp
def n_classdef(self, node):
# class definition ('class X(A,B,C):')
cclass = self.currentclass
@@ -986,14 +978,13 @@ class Walker(GenericASTTraversal, object):
self.indentLess()
self.currentclass = cclass
if len(self.__param_stack) > 1:
if len(self.param_stack) > 1:
self.write('\n\n')
else:
self.write('\n\n\n')
self.prune()
n_classdefdeco2 = n_classdef
def print_super_classes(self, node):
@@ -1031,13 +1022,13 @@ class Walker(GenericASTTraversal, object):
# kv2 ::= DUP_TOP expr expr ROT_THREE STORE_SUBSCR
# kv3 ::= expr expr STORE_MAP
if kv == 'kv':
name = self.traverse(kv[-2], indent='');
name = self.traverse(kv[-2], indent='')
value = self.traverse(kv[1], indent=self.indent+(len(name)+2)*' ')
elif kv == 'kv2':
name = self.traverse(kv[1], indent='');
name = self.traverse(kv[1], indent='')
value = self.traverse(kv[-3], indent=self.indent+(len(name)+2)*' ')
elif kv == 'kv3':
name = self.traverse(kv[-2], indent='');
name = self.traverse(kv[-2], indent='')
value = self.traverse(kv[0], indent=self.indent+(len(name)+2)*' ')
self.write(sep, name, ': ', value)
sep = line_seperator
@@ -1046,7 +1037,6 @@ class Walker(GenericASTTraversal, object):
self.prec = p
self.prune()
def n_build_list(self, node):
"""
prettyprint a list or tuple
@@ -1113,11 +1103,9 @@ class Walker(GenericASTTraversal, object):
def engine(self, entry, startnode):
# self.print_("-----")
#self.print_(str(startnode.__dict__))
# self.print(startnode)
fmt = entry[0]
## no longer used, since BUILD_TUPLE_n is pretty printed:
##lastC = 0
arg = 1
i = 0
@@ -1139,10 +1127,9 @@ class Walker(GenericASTTraversal, object):
elif typ == '+': self.indentMore()
elif typ == '-': self.indentLess()
elif typ == '|': self.write(self.indent)
## no longer used, since BUILD_TUPLE_n is pretty printed:
# no longer used, since BUILD_TUPLE_n is pretty printed:
elif typ == ',':
if lastC == 1:
self.write(',')
pass
elif typ == 'c':
self.preorder(node[entry[arg]])
arg += 1
@@ -1154,8 +1141,8 @@ class Walker(GenericASTTraversal, object):
arg += 1
elif typ == 'C':
low, high, sep = entry[arg]
lastC = remaining = len(node[low:high])
## remaining = len(node[low:high])
remaining = len(node[low:high])
# remaining = len(node[low:high])
for subnode in node[low:high]:
self.preorder(subnode)
remaining -= 1
@@ -1165,8 +1152,8 @@ class Walker(GenericASTTraversal, object):
elif typ == 'P':
p = self.prec
low, high, sep, self.prec = entry[arg]
lastC = remaining = len(node[low:high])
## remaining = len(node[low:high])
remaining = len(node[low:high])
# remaining = len(node[low:high])
for subnode in node[low:high]:
self.preorder(subnode)
remaining -= 1
@@ -1192,9 +1179,10 @@ class Walker(GenericASTTraversal, object):
for i in mapping[1:]:
key = key[i]
pass
if table.has_key(key):
self.engine(table[key], node)
if key.type in table:
self.engine(table[key.type], node)
self.prune()
def customize(self, customize):
@@ -1202,8 +1190,8 @@ class Walker(GenericASTTraversal, object):
Special handling for opcodes that take a variable number
of arguments -- we add a new entry for each in TABLE_R.
"""
for k, v in customize.items():
if TABLE_R.has_key(k):
for k, v in list(customize.items()):
if k in TABLE_R:
continue
op = k[ :k.rfind('_') ]
if op == 'CALL_FUNCTION': TABLE_R[k] = ('%c(%P)', 0, (1, -1, ', ', 100))
@@ -1225,12 +1213,16 @@ class Walker(GenericASTTraversal, object):
str += '*%c, **%c)'
if p2[2]: p2 = (1, -3, ', ')
entry = (str, 0, p2, -3, -2)
pass
TABLE_R[k] = entry
## handled by n_mapexpr:
##if op == 'BUILD_SLICE': TABLE_R[k] = ('%C' , (0,-1,':'))
## handled by n_build_list:
##if op == 'BUILD_LIST': TABLE_R[k] = ('[%C]' , (0,-1,', '))
##elif op == 'BUILD_TUPLE': TABLE_R[k] = ('(%C%,)', (0,-1,', '))
pass
# handled by n_mapexpr:
# if op == 'BUILD_SLICE': TABLE_R[k] = ('%C' , (0,-1,':'))
# handled by n_build_list:
# if op == 'BUILD_LIST': TABLE_R[k] = ('[%C]' , (0,-1,', '))
# elif op == 'BUILD_TUPLE': TABLE_R[k] = ('(%C%,)', (0,-1,', '))
pass
return
def get_tuple_parameter(self, ast, name):
"""
@@ -1250,8 +1242,8 @@ class Walker(GenericASTTraversal, object):
# search for an assign-statement
assert ast[i][0] == 'stmt'
node = ast[i][0][0]
if node == 'assign' \
and node[0] == ASSIGN_TUPLE_PARAM(name):
if (node == 'assign'
and node[0] == ASSIGN_TUPLE_PARAM(name)):
# okay, this assigns '.n' to something
del ast[i]
# walk lhs; this
@@ -1265,7 +1257,6 @@ class Walker(GenericASTTraversal, object):
# return self.traverse(node[1])
raise Exception("Can't find tuple parameter " + name)
def make_function(self, node, isLambda, nested=1):
"""Dump function defintion, doc string, and function body."""
@@ -1342,24 +1333,12 @@ class Walker(GenericASTTraversal, object):
self.print_("(", ", ".join(params), "):")
# self.print_(indent, '#flags:\t', int(code.co_flags))
if len(code.co_consts)>0 and code.co_consts[0] != None and not isLambda: # ugly
if len(code.co_consts)>0 and code.co_consts[0] is not None and not isLambda: # ugly
# docstring exists, dump it
self.print_docstring(indent, code.co_consts[0])
code._tokens = None # save memory
assert ast == 'stmts'
#if isLambda:
# convert 'return' statement to expression
#assert len(ast[0]) == 1 wrong, see 'lambda (r,b): r,b,g'
#assert ast[-1] == 'stmt'
#assert len(ast[-1]) == 1
# assert ast[-1][0] == 'return_stmt'
# ast[-1][0].type = 'return_lambda'
#else:
# if ast[-1] == RETURN_NONE:
# Python adds a 'return None' to the
# end of any function; remove it
# ast.pop() # remove last node
all_globals = find_all_globals(ast, set())
for g in ((all_globals & self.mod_globs) | find_globals(ast, set())):