diff --git a/test/bytecode_2.6/06_list_ifnot_and.pyc b/test/bytecode_2.6/06_list_ifnot_and.pyc new file mode 100644 index 00000000..557b026a Binary files /dev/null and b/test/bytecode_2.6/06_list_ifnot_and.pyc differ diff --git a/test/simple_source/comprehension/06_list_ifnot_and.py b/test/simple_source/comprehension/06_list_ifnot_and.py new file mode 100644 index 00000000..18f3e2ef --- /dev/null +++ b/test/simple_source/comprehension/06_list_ifnot_and.py @@ -0,0 +1,18 @@ +# Bug from python2.6/SimpleXMLRPCServer.py +# The problem in 2.6 is handling + +# 72 JUMP_ABSOLUTE 17 (to 17) +# 75 POP_TOP +# 76 JUMP_ABSOLUTE 17 (to 17) + +# And getting: +# list_for ::= expr _for designator list_iter JUMP_BACK +# list_iter ::= list_if JUMP_BACK +# ^^^^^^^^^ added to 2.6 grammar +# list_iter ::= list_for + + +def list_public_methods(obj): + return [member for member in dir(obj) + if not member.startswith('_') and + hasattr(getattr(obj, member), '__call__')] diff --git a/uncompyle6/parser.py b/uncompyle6/parser.py index c3439154..3e93f838 100644 --- a/uncompyle6/parser.py +++ b/uncompyle6/parser.py @@ -463,11 +463,21 @@ def get_python_parser(version, debug_parser, compile_mode='exec'): # FIXME: there has to be a better way... if version < 3.0: - import uncompyle6.parsers.parse2 as parse2 - if compile_mode == 'exec': - p = parse2.Python2Parser(debug_parser) + if version == 2.6: + import uncompyle6.parsers.parse26 as parse26 + if compile_mode == 'exec': + p = parse26.Python26Parser(debug_parser) + else: + p = parse26.Python26ParserSingle(debug_parser) else: - p = parse2.Python2ParserSingle(debug_parser) + import uncompyle6.parsers.parse2 as parse2 + if compile_mode == 'exec': + p = parse2.Python2Parser(debug_parser) + else: + p = parse2.Python2ParserSingle(debug_parser) + pass + pass + pass else: import uncompyle6.parsers.parse3 as parse3 if version == 3.2: diff --git a/uncompyle6/parsers/parse26.py b/uncompyle6/parsers/parse26.py new file mode 100644 index 00000000..7b77c105 --- /dev/null +++ b/uncompyle6/parsers/parse26.py @@ -0,0 +1,23 @@ +# Copyright (c) 2016 Rocky Bernstein +""" +spark grammar differences over Python2 for Python 2.6. +""" + +from uncompyle6.parser import PythonParserSingle +from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG +from uncompyle6.parsers.parse2 import Python2Parser + +class Python26Parser(Python2Parser): + + def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG): + super(Python26Parser, self).__init__(debug_parser) + self.customized = {} + + + def p_lis_iter(self, args): + ''' + list_iter ::= list_if JUMP_BACK + ''' + +class Python26ParserSingle(Python2Parser, PythonParserSingle): + pass diff --git a/uncompyle6/scanners/scanner26.py b/uncompyle6/scanners/scanner26.py index 545fa9fd..1c5a903d 100755 --- a/uncompyle6/scanners/scanner26.py +++ b/uncompyle6/scanners/scanner26.py @@ -513,11 +513,8 @@ class Scanner26(scan.Scanner2): if op in self.pop_jump_if: target = self.get_argument(i) target += i + 3 - self.restructJump(i, target) - if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended: - i += 3 - else: i += 1 + i += self.op_size(op) i=0 while i < len(self.code): # we can't use op_range for the moment @@ -527,9 +524,17 @@ class Scanner26(scan.Scanner2): if self.code[target] == self.opc.JA: target = self.get_target(target) self.restructJump(i, target) - if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended: - i += 3 - else: i += 1 + i += self.op_size(op) + i=0 + # while i < len(self.code): # we can't use op_range for the moment + # op = self.code[i] + # name = self.opc.opname[op] + # if self.op_hasArgument(op): + # oparg = self.get_argument(i) + # print("%d %s %d" % (i, name, oparg)) + # else: + # print("%d %s" % (i, name)) + # i += self.op_size(op) def restructJump(self, pos, newTarget): if self.code[pos] not in self.opc.hasjabs + self.opc.hasjrel: @@ -698,7 +703,9 @@ class Scanner26(scan.Scanner2): # is this an if and if op == self.opc.PJIF: match = self.rem_or(start, self.next_stmt[pos], self.opc.PJIF, target) - match = self.remove_mid_line_ifs(match) + ## We can't remove mid-line ifs because line structures have changed + ## from restructBytecode(). + ## match = self.remove_mid_line_ifs(match) if match: if (code[pre[rtarget]] in (self.opc.JF, self.opc.JA) and pre[rtarget] not in self.stmts