Merge branch 'master' into python-2.4

This commit is contained in:
rocky
2017-06-25 18:56:31 -04:00
11 changed files with 352 additions and 275 deletions

402
ChangeLog

File diff suppressed because it is too large Load Diff

8
NEWS
View File

@@ -1,4 +1,10 @@
uncompyle6 2.11.1 2016-06-18 Fleetwood
uncompyle6 2.11.1 2016-06-22
- Python 3.x annotatoin and function signature fixes
- Bump xdis version
- Small pysource bug fixes
uncompyle6 2.11.0 2016-06-18 Fleetwood
- Major improvements in fragment tracking
* Add nonterminal node in extractInfo
* tag more offsets in expressions

View File

@@ -40,7 +40,7 @@ entry_points = {
]}
ftp_url = None
install_requires = ['spark-parser >= 1.6.1, < 1.7.0',
'xdis >= 3.3.1, < 3.4.0']
'xdis >= 3.4.0, < 3.5.0', 'six']
license = 'MIT'
mailing_list = 'python-debugger@googlegroups.com'
modname = 'uncompyle6'

View File

@@ -9,7 +9,7 @@ def open(file, mode = "r", buffering = None,
newline = None, closefd = True) -> "IOBase":
return text
def foo(x: 'an argument that defaults to 5' = 5):
def foo1(x: 'an argument that defaults to 5' = 5):
print(x)
def div(a: dict(type=float, help='the dividend'),

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2016 by Rocky Bernstein
# Copyright (c) 2016-2017 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
@@ -14,6 +14,7 @@ import sys
from uncompyle6 import PYTHON3, IS_PYPY
from uncompyle6.scanners.tok import Token
from xdis.bytecode import op_size
# The byte code versions we support
PYTHON_VERSIONS = (1.5,
@@ -212,9 +213,6 @@ class Scanner(object):
result.append(offset)
return result
def op_hasArgument(self, op):
return self.op_size(op) > 1
def op_range(self, start, end):
"""
Iterate through positions of opcodes, skipping
@@ -222,26 +220,7 @@ class Scanner(object):
"""
while start < end:
yield start
start += self.op_size(self.code[start])
def next_offset(self, op, offset):
return offset + self.op_size(op)
def op_size(self, op):
"""
Return size of operator with its arguments
for given opcode <op>.
"""
if op < self.opc.HAVE_ARGUMENT:
if self.version >= 3.6:
return 2
else:
return 1
else:
if self.version >= 3.6:
return 2
else:
return 3
start += op_size(self.code[start], self.opc)
def remove_mid_line_ifs(self, ifs):
"""
@@ -273,9 +252,6 @@ class Scanner(object):
self.Token = tokenClass
return self.Token
def op_has_argument(op, opc):
return op >= opc.HAVE_ARGUMENT
def parse_fn_counts(argc):
return ((argc & 0xFF), (argc >> 8) & 0xFF, (argc >> 16) & 0x7FFF)

View File

@@ -29,8 +29,9 @@ else:
from array import array
from uncompyle6.scanner import op_has_argument, L65536
from uncompyle6.scanner import L65536
from xdis.code import iscode
from xdis.bytecode import op_has_argument, op_size
from uncompyle6.scanner import Scanner
@@ -333,7 +334,7 @@ class Scanner2(Scanner):
for i in self.op_range(0, n):
op = self.code[i]
self.prev.append(i)
if self.op_hasArgument(op):
if op_has_argument(op, self.opc):
self.prev.append(i)
self.prev.append(i)
pass
@@ -386,7 +387,7 @@ class Scanner2(Scanner):
if elem != code[i]:
match = False
break
i += self.op_size(code[i])
i += op_size(code[i], self.opc)
if match:
i = self.prev[i]
@@ -623,7 +624,7 @@ class Scanner2(Scanner):
'start': jump_back+3,
'end': end})
elif op == self.opc.SETUP_EXCEPT:
start = offset + self.op_size(op)
start = offset + op_size(op, self.opc)
target = self.get_target(offset, op)
end = self.restrict_to_parent(target, parent)
if target != end:
@@ -647,7 +648,7 @@ class Scanner2(Scanner):
setup_except_nest -= 1
elif self.code[end_finally_offset] == self.opc.SETUP_EXCEPT:
setup_except_nest += 1
end_finally_offset += self.op_size(code[end_finally_offset])
end_finally_offset += op_size(code[end_finally_offset], self.opc)
pass
# Add the except blocks
@@ -848,7 +849,7 @@ class Scanner2(Scanner):
else:
# We still have the case in 2.7 that the next instruction
# is a jump to a SETUP_LOOP target.
next_offset = target + self.op_size(self.code[target])
next_offset = target + op_size(self.code[target], self.opc)
next_op = self.code[next_offset]
if self.op_name(next_op) == 'JUMP_FORWARD':
jump_target = self.get_target(next_offset, next_op)

View File

@@ -29,10 +29,11 @@ else:
from array import array
from uncompyle6.scanner import Scanner, op_has_argument
from uncompyle6.scanner import Scanner
from xdis.code import iscode
from xdis.bytecode import Bytecode
from xdis.bytecode import Bytecode, op_has_argument, op_size
from uncompyle6.scanner import Token, parse_fn_counts
import xdis
# Get all the opcodes into globals
import xdis.opcodes.opcode_33 as op3
@@ -474,7 +475,7 @@ class Scanner3(Scanner):
self.prev = self.prev_op = [0]
for offset in self.op_range(0, codelen):
op = code[offset]
for _ in range(self.op_size(op)):
for _ in range(op_size(op, self.opc)):
self.prev_op.append(offset)
def find_jump_targets(self, debug):
@@ -524,7 +525,7 @@ class Scanner3(Scanner):
oparg = code[offset+1]
else:
oparg = code[offset+1] + code[offset+2] * 256
next_offset = self.next_offset(op, offset)
next_offset = xdis.next_offset(op, self.opc, offset)
if label is None:
if op in op3.hasjrel and op != self.opc.FOR_ITER:
@@ -570,7 +571,7 @@ class Scanner3(Scanner):
if elem != code[i]:
match = False
break
i += self.op_size(code[i])
i += op_size(code[i], self.opc)
if match is True:
i = self.prev_op[i]
@@ -763,7 +764,7 @@ class Scanner3(Scanner):
'start': jump_back+3,
'end': end})
elif op in self.pop_jump_tf:
start = offset + self.op_size(op)
start = offset + op_size(op, self.opc)
target = self.get_target(offset)
rtarget = self.restrict_to_parent(target, parent)
prev_op = self.prev_op
@@ -938,9 +939,9 @@ class Scanner3(Scanner):
# not from SETUP_EXCEPT
next_op = rtarget
if code[next_op] == self.opc.POP_BLOCK:
next_op += self.op_size(self.code[next_op])
next_op += op_size(self.code[next_op], self.opc)
if code[next_op] == self.opc.JUMP_ABSOLUTE:
next_op += self.op_size(self.code[next_op])
next_op += op_size(self.code[next_op], self.opc)
if next_op in targets:
for try_op in targets[next_op]:
come_from_op = code[try_op]
@@ -963,12 +964,12 @@ class Scanner3(Scanner):
end = self.restrict_to_parent(target, parent)
self.fixed_jumps[offset] = end
elif op == self.opc.POP_EXCEPT:
next_offset = self.next_offset(op, offset)
next_offset = xdis.next_offset(op, self.opc, offset)
target = self.get_target(next_offset)
if target > next_offset:
next_op = code[next_offset]
if (self.opc.JUMP_ABSOLUTE == next_op and
END_FINALLY != code[self.next_offset(next_op, next_offset)]):
END_FINALLY != code[xdis.next_offset(next_op, self.opc, next_offset)]):
self.fixed_jumps[next_offset] = target
self.except_targets[target] = next_offset

View File

@@ -8,6 +8,8 @@ scanner routine for Python 3.
# bytecode verification, verify(), uses JUMP_OPs from here
from xdis.opcodes import opcode_30 as opc
from xdis.bytecode import op_size
JUMP_OPs = map(lambda op: opc.opname[op], opc.hasjrel + opc.hasjabs)
JUMP_TF = frozenset([opc.JUMP_IF_FALSE, opc.JUMP_IF_TRUE])
@@ -131,7 +133,7 @@ class Scanner30(Scanner3):
'start': jump_back+3,
'end': end})
elif op in JUMP_TF:
start = offset + self.op_size(op)
start = offset + op_size(op, self.opc)
target = self.get_target(offset)
rtarget = self.restrict_to_parent(target, parent)
prev_op = self.prev_op
@@ -303,9 +305,9 @@ class Scanner30(Scanner3):
# not from SETUP_EXCEPT
next_op = rtarget
if code[next_op] == self.opc.POP_BLOCK:
next_op += self.op_size(self.code[next_op])
next_op += op_size(self.code[next_op], self.opc)
if code[next_op] == self.opc.JUMP_ABSOLUTE:
next_op += self.op_size(self.code[next_op])
next_op += op_size(self.code[next_op], self.opc)
if next_op in targets:
for try_op in targets[next_op]:
come_from_op = code[try_op]

View File

@@ -158,6 +158,9 @@ def make_function3_annotate(self, node, isLambda, nested=1,
i = len(paramnames) - len(defparams)
suffix = ''
no_paramnames = len(paramnames[:i]) == 0
for param in paramnames[:i]:
self.write(suffix, param)
suffix = ', '
@@ -180,6 +183,7 @@ def make_function3_annotate(self, node, isLambda, nested=1,
suffix = ''
for n in node:
if n == 'pos_arg':
no_paramnames = False
self.write(suffix)
param = paramnames[i]
self.write(param)
@@ -187,7 +191,11 @@ def make_function3_annotate(self, node, isLambda, nested=1,
aa = annotate_args[param]
if isinstance(aa, tuple):
aa = aa[0]
self.write(': "%s"' % aa)
self.write(': "%s"' % aa)
elif isinstance(aa, AST):
self.write(': ')
self.preorder(aa)
self.write('=')
i += 1
self.preorder(n)
@@ -200,64 +208,65 @@ def make_function3_annotate(self, node, isLambda, nested=1,
# self.println(indent, '#flags:\t', int(code.co_flags))
if kw_args + annotate_argc > 0:
if not code_has_star_arg(code):
if argc > 0:
self.write(", *, ")
else:
self.write("*, ")
pass
else:
self.write(", ")
kwargs = node[0]
last = len(kwargs)-1
i = 0
for n in node[0]:
if n == 'kwarg':
if (line_number != self.line_number):
self.write("\n" + indent)
line_number = self.line_number
self.write('%s=' % n[0].pattr)
self.preorder(n[1])
if i < last:
self.write(', ')
i += 1
if no_paramnames:
if not code_has_star_arg(code):
if argc > 0:
self.write(", *, ")
else:
self.write("*, ")
pass
pass
annotate_args = []
for n in node:
if n == 'annotate_arg':
annotate_args.append(n[0])
elif n == 'annotate_tuple':
t = n[0].attr
if t[-1] == 'return':
t = t[0:-1]
annotate_args = annotate_args[:-1]
pass
last = len(annotate_args) - 1
for i in range(len(annotate_args)):
self.write("%s: " % (t[i]))
self.preorder(annotate_args[i])
else:
self.write(", ")
kwargs = node[0]
last = len(kwargs)-1
i = 0
for n in node[0]:
if n == 'kwarg':
if (line_number != self.line_number):
self.write("\n" + indent)
line_number = self.line_number
self.write('%s=' % n[0].pattr)
self.preorder(n[1])
if i < last:
self.write(', ')
pass
i += 1
pass
break
pass
annotate_args = []
for n in node:
if n == 'annotate_arg':
annotate_args.append(n[0])
elif n == 'annotate_tuple':
t = n[0].attr
if t[-1] == 'return':
t = t[0:-1]
annotate_args = annotate_args[:-1]
pass
last = len(annotate_args) - 1
for i in range(len(annotate_args)):
self.write("%s: " % (t[i]))
self.preorder(annotate_args[i])
if i < last:
self.write(', ')
pass
pass
break
pass
pass
pass
if code_has_star_star_arg(code):
if argc > 0:
self.write(', ')
self.write('**%s' % code.co_varnames[argc + kw_pairs])
if code_has_star_star_arg(code):
if argc > 0:
self.write(', ')
self.write('**%s' % code.co_varnames[argc + kw_pairs])
if isLambda:
self.write(": ")
else:
self.write(')')
if 'return' in annotate_tuple[0].attr:
if (line_number != self.line_number):
if (line_number != self.line_number) and not no_paramnames:
self.write("\n" + indent)
line_number = self.line_number
self.write(' -> ')

View File

@@ -309,6 +309,13 @@ class SourceWalker(GenericASTTraversal, object):
if node[annotate_last] == 'annotate_tuple':
break
# FIXME: the real situation is that when derived from
# funcdef_annotate we the name has been filled in.
# But when derived from funcdefdeco it hasn't Would like a better
# way to distinquish.
if self.f.getvalue()[-4:] == 'def ':
self.write(code.attr.co_name)
# FIXME: handle and pass full annotate args
make_function3_annotate(self, node, isLambda=False,
codeNode=code, annotate_last=annotate_last)
@@ -547,6 +554,8 @@ class SourceWalker(GenericASTTraversal, object):
if self.pending_newlines:
out = out[:-self.pending_newlines]
if isinstance(out, str) and not PYTHON3:
out = unicode(out, 'utf-8')
self.f.write(out)
def println(self, *data):
@@ -569,33 +578,6 @@ class SourceWalker(GenericASTTraversal, object):
node == AST('return_stmt',
[AST('ret_expr', [NONE]), Token('RETURN_VALUE')]))
## The below doesn't work because continue may be the only thing inside an 'else'. For example
# for ...
# if ...
# else:
# continue
#
# def n_continue_stmt(self, node):
# if self.version >= 3.0 and node[0] == 'CONTINUE':
# t = node[0]
# if not t.linestart:
# # Artificially-added "continue" statements derived from JUMP_ABSOLUTE
# # don't have line numbers associated with them.
# # If this is a CONTINUE is to the same target as a JUMP_ABSOLUTE following it,
# # then the "continue" can be suppressed.
# op, offset = t.op, t.offset
# next_offset = self.scanner.next_offset(op, offset)
# scanner = self.scanner
# code = scanner.code
# if next_offset < len(code):
# next_inst = code[next_offset]
# if (scanner.opc.opname[next_inst] == 'JUMP_ABSOLUTE'
# and t.pattr == code[next_offset+1]):
# # Suppress "continue"
# import pdb; pdb.set_trace()
# self.prune()
# self.default(node)
def n_return_stmt(self, node):
if self.params['isLambda']:
self.preorder(node[0])

View File

@@ -1,3 +1,3 @@
# This file is suitable for sourcing inside bash as
# well as importing into Python
VERSION='2.11.0'
VERSION='2.11.1'