From 34841abe14758e0b49db842b866f2ebec7cbcf16 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 29 Dec 2015 08:23:44 -0500 Subject: [PATCH] scanner3: Python 2.6 compatibility: change set initializations. Get rid of * import opcode_*: only a little of the much-needed larger cleanup Makefile: remove 3.x bytecode checking from Python 2.x for now. DRY Makefile a little bit (but more is needed) --- README.rst | 6 +---- test/Makefile | 20 ++++++++--------- uncompyle6/opcodes/opcode_32.py | 9 ++++---- uncompyle6/opcodes/opcode_33.py | 6 ----- uncompyle6/opcodes/opcode_34.py | 4 ---- uncompyle6/scanners/scanner3.py | 38 +++++++++++++++++--------------- uncompyle6/scanners/scanner32.py | 4 ++-- 7 files changed, 38 insertions(+), 49 deletions(-) diff --git a/README.rst b/README.rst index cab9245e..9815f76a 100644 --- a/README.rst +++ b/README.rst @@ -86,11 +86,7 @@ Known Bugs/Restrictions ----------------------- Python 2 deparsing is probably as solid as the various versions of -uncompyle2. Python 3 deparsing is not as solid. Using Python 2 to -deparse Python 3 has severe limitations, due to byte code format -differences and the current inablity to retrieve code object fields across -different Python versions. (I envy the pycdc C++ code which doesn't have such -problems because they live totally outside of Python.) +uncompyle2. Python 3 deparsing is okay but not as solid. See Also -------- diff --git a/test/Makefile b/test/Makefile index f6672e4b..2ec0ab0a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -19,28 +19,28 @@ check: @$(PYTHON) -V && PYTHON_VERSION=`$(PYTHON) -V 2>&1 | cut -d ' ' -f 2 | cut -d'.' -f1,2`; \ $(MAKE) check-$$PYTHON_VERSION -#: Run working tests from Python 2.6 -check-2.6: check-bytecode-2.7 check-bytecode-2.5 - $(PYTHON) test_pythonlib.py --bytecode-2.6 --verify $(COMPILE) - -#: Run working tests from Python 2.7 -check-2.7: check-bytecode check-2.7-ok +#: Run working tests from Python 2.6 or 2.7 +check-2.6 check-2.7: check-bytecode-2 check-2.7-ok #: Run working tests from Python 3.3 -check-3.3: check-bytecode-3.3 check-bytecode-2.7 +check-3.3: check-bytecode $(PYTHON) test_pythonlib.py --bytecode-3.3 --verify $(COMPILE) #: Run working tests from Python 3.4 -check-3.4: check-bytecode-2.7 check-bytecode-3.2 - $(PYTHON) test_pythonlib.py --bytecode-3.4 --ok-2.7 --verify $(COMPILE) +check-3.4: check-bytecode check-2.7-ok #: Check deparsing only, but from a different Python version check-disasm: $(PYTHON) dis-compare.py +#: Check deparsing bytecode only +check-bytecode-2: + $(PYTHON) test_pythonlib.py --bytecode-2.5 --bytecode-2.6 --bytecode-2.7 + #: Check deparsing bytecode only check-bytecode: - $(PYTHON) test_pythonlib.py --bytecode-2.5 --bytecode-2.7 --bytecode-3.2 + $(PYTHON) test_pythonlib.py --bytecode-2.5 --bytecode-2.6 --bytecode-2.7 \ + --bytecode-3.2 --bytecode-3.3 --bytecode-3.4 #: Check deparsing Python 2.5 check-bytecode-2.5: diff --git a/uncompyle6/opcodes/opcode_32.py b/uncompyle6/opcodes/opcode_32.py index 046a08a8..ab9e83b8 100644 --- a/uncompyle6/opcodes/opcode_32.py +++ b/uncompyle6/opcodes/opcode_32.py @@ -7,10 +7,6 @@ This is a superset of Python 3.4's opcode.py with some opcodes that simplify parsing and semantic interpretation. """ -__all__ = ["cmp_op", "hasconst", "hasname", "hasjrel", "hasjabs", - "haslocal", "hascompare", "hasfree", "opname", "opmap", - "HAVE_ARGUMENT", "EXTENDED_ARG"] - cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is', 'is not', 'exception match', 'BAD') @@ -21,6 +17,7 @@ hasjabs = [] haslocal = [] hascompare = [] hasfree = [] +hasnargs = [] opmap = {} opname = [''] * 256 @@ -179,6 +176,7 @@ haslocal.append(126) def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3) def_op('CALL_FUNCTION', 131) # #args + (#kwargs << 8) +hasnargs.append(131) def_op('MAKE_FUNCTION', 132) # Number of args with default values def_op('BUILD_SLICE', 133) # Number of items def_op('MAKE_CLOSURE', 134) @@ -192,8 +190,11 @@ def_op('DELETE_DEREF', 138) hasfree.append(138) def_op('CALL_FUNCTION_VAR', 140) # #args + (#kwargs << 8) +hasnargs.append(140) def_op('CALL_FUNCTION_KW', 141) # #args + (#kwargs << 8) +hasnargs.append(141) def_op('CALL_FUNCTION_VAR_KW', 142) # #args + (#kwargs << 8) +hasnargs.append(142) jrel_op('SETUP_WITH', 143) diff --git a/uncompyle6/opcodes/opcode_33.py b/uncompyle6/opcodes/opcode_33.py index f4ed4871..392067b0 100644 --- a/uncompyle6/opcodes/opcode_33.py +++ b/uncompyle6/opcodes/opcode_33.py @@ -7,12 +7,6 @@ This is a superset of Python 3.3's opcode.py with some opcodes that simplify parsing and semantic interpretation. """ -# Note: this should look exactly like Python 3.4's opcode.py - -__all__ = ["cmp_op", "hasconst", "hasname", "hasjrel", "hasjabs", - "haslocal", "hascompare", "hasfree", "opname", "opmap", - "HAVE_ARGUMENT", "EXTENDED_ARG"] - cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is', 'is not', 'exception match', 'BAD') diff --git a/uncompyle6/opcodes/opcode_34.py b/uncompyle6/opcodes/opcode_34.py index e69ffad5..c5b8eb2e 100644 --- a/uncompyle6/opcodes/opcode_34.py +++ b/uncompyle6/opcodes/opcode_34.py @@ -7,10 +7,6 @@ This is a superset of Python 3.4's opcode.py with some opcodes that simplify parsing and semantic interpretation. """ -__all__ = ["cmp_op", "hasconst", "hasname", "hasjrel", "hasjabs", - "haslocal", "hascompare", "hasfree", "opname", "opmap", - "HAVE_ARGUMENT", "EXTENDED_ARG", "hasnargs"] - cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is', 'is not', 'exception match', 'BAD') diff --git a/uncompyle6/scanners/scanner3.py b/uncompyle6/scanners/scanner3.py index d1303117..be0fd76f 100644 --- a/uncompyle6/scanners/scanner3.py +++ b/uncompyle6/scanners/scanner3.py @@ -18,8 +18,10 @@ from uncompyle6 import PYTHON_VERSION, PYTHON3 # Get all the opcodes into globals -globals().update(dis.opmap) -from uncompyle6.opcodes.opcode_33 import * +import uncompyle6.opcodes.opcode_33 as op3 +globals().update(op3.opmap) + + import uncompyle6.scanner as scan class Code3: @@ -122,23 +124,23 @@ class Scanner3(scan.Scanner): jump_idx = 0 for jump_offset in jump_targets[offset]: tokens.append(Token('COME_FROM', None, repr(jump_offset), - offset='{}_{}'.format(offset, jump_idx))) + offset='%s_%s' % (offset, jump_idx))) jump_idx += 1 pass pass op = code[offset] - op_name = opname[op] + op_name = op3.opname[op] oparg = None; pattr = None - if op >= HAVE_ARGUMENT: + if op >= op3.HAVE_ARGUMENT: oparg = self.get_argument(offset) + extended_arg extended_arg = 0 - if op == EXTENDED_ARG: + if op == op3.EXTENDED_ARG: extended_arg = oparg * scan.L65536 continue - if op in hasconst: + if op in op3.hasconst: const = co.co_consts[oparg] if not PYTHON3 and isinstance(const, str): if const in code_objects: @@ -168,17 +170,17 @@ class Scanner3(scan.Scanner): pattr = '' else: pattr = const - elif op in hasname: + elif op in op3.hasname: pattr = names[oparg] - elif op in hasjrel: + elif op in op3.hasjrel: pattr = repr(offset + 3 + oparg) - elif op in hasjabs: + elif op in op3.hasjabs: pattr = repr(oparg) - elif op in haslocal: + elif op in op3.haslocal: pattr = varnames[oparg] - elif op in hascompare: - pattr = cmp_op[oparg] - elif op in hasfree: + elif op in op3.hascompare: + pattr = op3.cmp_op[oparg] + elif op in op3.hasfree: pattr = free[oparg] if op in (BUILD_LIST, BUILD_TUPLE, BUILD_SET, BUILD_SLICE, @@ -338,7 +340,7 @@ class Scanner3(scan.Scanner): start = 0 end = codelen = len(code) - statement_opcodes = { + statement_opcodes = set([ SETUP_LOOP, BREAK_LOOP, CONTINUE_LOOP, SETUP_FINALLY, END_FINALLY, SETUP_EXCEPT, SETUP_WITH, POP_BLOCK, STORE_FAST, DELETE_FAST, STORE_DEREF, @@ -346,15 +348,15 @@ class Scanner3(scan.Scanner): STORE_ATTR, DELETE_ATTR, STORE_SUBSCR, DELETE_SUBSCR, RETURN_VALUE, RAISE_VARARGS, POP_TOP, PRINT_EXPR, JUMP_ABSOLUTE - } + ]) statement_opcode_sequences = [(POP_JUMP_IF_FALSE, JUMP_FORWARD), (POP_JUMP_IF_FALSE, JUMP_ABSOLUTE), (POP_JUMP_IF_TRUE, JUMP_FORWARD), (POP_JUMP_IF_TRUE, JUMP_ABSOLUTE)] - designator_ops = { + designator_ops = set([ STORE_FAST, STORE_NAME, STORE_GLOBAL, STORE_DEREF, STORE_ATTR, STORE_SUBSCR, UNPACK_SEQUENCE, JUMP_ABSOLUTE - } + ]) # Compose preliminary list of indices with statements, # using plain statement opcodes diff --git a/uncompyle6/scanners/scanner32.py b/uncompyle6/scanners/scanner32.py index 44279339..b7df4969 100644 --- a/uncompyle6/scanners/scanner32.py +++ b/uncompyle6/scanners/scanner32.py @@ -11,9 +11,9 @@ from __future__ import print_function import uncompyle6.scanners.scanner3 as scan3 -import uncompyle6.opcodes.opcode_34 +import uncompyle6.opcodes.opcode_32 # verify uses JUMP_OPs from here -JUMP_OPs = uncompyle6.opcodes.opcode_34.JUMP_OPs +JUMP_OPs = uncompyle6.opcodes.opcode_32.JUMP_OPs class Scanner32(scan3.Scanner3):