Python 2.6 compatability via ericfrederich's patch. DRY version-checking code

This commit is contained in:
rocky
2015-12-17 20:48:54 -05:00
parent a309a77ea7
commit 2fc2d6c699
14 changed files with 72 additions and 56 deletions

View File

@@ -23,10 +23,14 @@ test check: pytest check-long
check-long: pytest
$(MAKE) -C test check-2.7
#: Run tests
#: Run quick tests
check-short: pytest
$(MAKE) -C test check-short-2.7
#: Run quick tests
check-3.4: pytest
$(MAKE) -C test check-3.4
#: check that disassembly exactly matches Python lib's dis
check-disasm:

View File

@@ -3,14 +3,19 @@
#
# Copyright (c) 2015 by Rocky Bernstein <rb@dustyfeet.com>
#
"""
Usage: pydisassemble [OPTIONS]... FILE
from __future__ import print_function
import sys, os, getopt
program = os.path.basename(__file__)
__doc__ = """
Usage: %s [OPTIONS]... FILE
Examples:
pydisassemble foo.pyc
pydisassemble foo.py
pydisassemble -o foo.pydis foo.pyc
pydisassemble -o /tmp foo.pyc
%s foo.pyc
%s foo.py
%s -o foo.pydis foo.pyc
%s -o /tmp foo.pyc
Options:
-o <path> output decompiled files to this path:
@@ -19,21 +24,16 @@ Options:
<path>
--help show this message
"""
""" % ((program,) * 5)
from __future__ import print_function
Usage_short = \
"pydissassemble [--help] [--verify] [--showasm] [--showast] [-o <path>] FILE|DIR..."
import sys, os, getopt
import os.path
"%s [--help] [--verify] [--showasm] [--showast] [-o <path>] FILE|DIR..." % program
from uncompyle6 import check_python_version
from uncompyle6.disas import disassemble_files
if sys.version[:3] != '2.7' and sys.version[:3] != '3.4':
print('Error: pydisassemble requires Python 2.7 or 3.4.', file=sys.stderr)
sys.exit(-1)
check_python_version(program)
outfile = '-'
out_base = None

View File

@@ -41,18 +41,17 @@ Extensions of generated files:
"""
from __future__ import print_function
import sys, os, getopt
program = os.path.basename(__file__)
Usage_short = \
"uncompyle6 [--help] [--verify] [--showasm] [--showast] [-o <path>] FILE|DIR..."
"%s [--help] [--verify] [--showasm] [--showast] [-o <path>] FILE|DIR..." % program
import sys, os, getopt
import os.path
from uncompyle6 import main, status_msg, verify
from uncompyle6 import main, status_msg, verify, check_python_version
import time
if sys.version[:3] != '2.7' and sys.version[:3] != '3.4':
print('Error: uncompyle6 requires Python 2.7 or 3.4.', file=sys.stderr)
sys.exit(-1)
check_python_version(program)
showasm = showast = do_verify = recurse_dirs = False
numproc = 0

View File

@@ -53,7 +53,6 @@ tests['2.2'] = ['divide_future', 'divide_no_future', 'iterators',
tests['2.3'] = tests['2.2']
tests['2.5'] = tests['2.3']
tests['2.6'] = tests['2.5']
# tests['2.7'] = ['mine'] + tests['2.6']
tests['2.7'] = [
'simple-source/branching/ifelse',
@@ -61,6 +60,7 @@ tests['2.7'] = [
# 'simple-source/call_arguments/keyword',
# 'simple-source/call_arguments/positional'
]
tests['2.6'] = tests['2.7']
def file_matches(files, root, basenames, patterns):
files.extend(

View File

@@ -6,7 +6,7 @@
from __future__ import print_function
import dis, os.path, sys
import dis, os.path
try:
from StringIO import StringIO
@@ -16,17 +16,16 @@ except ImportError:
program = os.path.basename(__file__)
__doc__ = """
Usage: {0} [OPTIONS]... FILE
Usage: %s [OPTIONS]... FILE
""".format(program)
""" % program
usage_short = "Usage: {0} [OPTIONS]... FILE".format(program)
usage_short = "Usage: %s [OPTIONS]... FILE" % program
import uncompyle6
from uncompyle6 import PYTHON_VERSION_STR, check_python_version
from uncompyle6.disas import disco
version = sys.version[:3]
def inst_fmt(inst):
if inst.starts_line:
return '\n%4d %6s\t%-17s %r' % (inst.starts_line, inst.offset, inst.opname,
@@ -39,9 +38,9 @@ def inst_fmt(inst):
def compare_ok(version, co):
out = StringIO()
if version == 2.7:
if version in (2.6, 2.7):
dis.disco(co)
return
return True
bytecode = dis.Bytecode(co)
disco(version, co, out)
@@ -61,10 +60,7 @@ def compare_ok(version, co):
i += 1
return True
if version != '2.7' and version != '3.4':
print('Error: {0} requires Python 2.7 or 3.4.'.format(program),
file=sys.stderr)
sys.exit(-1)
check_python_version(program)
# if len(sys.argv) != 2:
# print(usage_short, file=sys.stderr)
@@ -85,7 +81,7 @@ files=[
]
for base in files:
filename = "bytecode_%s/%s.pyc" % (version, base)
filename = "bytecode_%s/%s.pyc" % (PYTHON_VERSION_STR, base)
version, co = uncompyle6.load_module(filename)
ok = True
if type(co) == list:

View File

@@ -33,7 +33,7 @@ from __future__ import print_function
import os, marshal, sys, types
PYTHON_VERSION = sys.version_info.major + (sys.version_info.minor / 10.0)
# set before importing scanner
PYTHON3 = (sys.version_info >= (3, 0))
import uncompyle6
@@ -43,6 +43,21 @@ import uncompyle6.marsh
from uncompyle6 import walker, verify, magics
sys.setrecursionlimit(5000)
# We do this crazy way to support Python 2.6 which
# doesn't support version_major, and has a bug in
# floating point so we can't divide 26 by 10 and get
# 2.6
PYTHON_VERSION = sys.version_info[0]+ (sys.version_info[1] / 10.0)
PYTHON_VERSION_STR = "%s.%s" % (sys.version_info[0], sys.version_info[1])
def check_python_version(program):
if not (sys.version_info[0:2] in ((2,6), (2,7), (3,4))):
print('Error: %s requires %s Python 2.6, 2.7 or 3.4' % program,
file=sys.stderr)
sys.exit(-1)
return
__all__ = ['uncompyle_file', 'main']
def _load_file(filename):

View File

@@ -18,13 +18,15 @@ want to run on Python 2.7.
from __future__ import print_function
import importlib, inspect, os, sys
import inspect, os, sys
import uncompyle6
from uncompyle6.scanner import get_scanner
def check_object_path(path):
if path.endswith(".py"):
if uncompyle6.PYTHON3:
import importlib
path = importlib.util.cache_from_source(path)
return path
if not path.endswith(".pyc") and not path.endswith(".pyo"):

View File

@@ -47,7 +47,7 @@ def updateGlobal():
globals().update({'PJIT': opmap['JUMP_IF_TRUE']})
globals().update({'JA': opmap['JUMP_ABSOLUTE']})
globals().update({'JF': opmap['JUMP_FORWARD']})
globals().update({k.replace('+', '_'): v for (k, v) in opmap.items()})
globals().update(dict([(k.replace('+','_'),v) for (k,v) in opmap.items()]))
globals().update({'JUMP_OPs': map(lambda op: opname[op], hasjrel + hasjabs)})
# Instruction opcodes for compiled code

View File

@@ -47,7 +47,7 @@ def updateGlobal():
globals().update({'PJIT': opmap['JUMP_IF_TRUE']})
globals().update({'JA': opmap['JUMP_ABSOLUTE']})
globals().update({'JF': opmap['JUMP_FORWARD']})
globals().update({k.replace('+', '_'): v for (k, v) in opmap.items()})
globals().update(dict([(k.replace('+','_'),v) for (k,v) in opmap.items()]))
globals().update({'JUMP_OPs': map(lambda op: opname[op], hasjrel + hasjabs)})
# Instruction opcodes for compiled code

View File

@@ -43,7 +43,7 @@ def updateGlobal():
globals().update({'PJIT': opmap['POP_JUMP_IF_TRUE']})
globals().update({'JA': opmap['JUMP_ABSOLUTE']})
globals().update({'JF': opmap['JUMP_FORWARD']})
globals().update({k.replace('+', '_'): v for (k, v) in opmap.items()})
globals().update(dict([(k.replace('+','_'),v) for (k,v) in opmap.items()]))
globals().update({'JUMP_OPs': map(lambda op: opname[op], hasjrel + hasjabs)})
# Instruction opcodes for compiled code

8
uncompyle6/scanners/scanner25.py Normal file → Executable file
View File

@@ -520,7 +520,7 @@ class Scanner25(scan.Scanner):
start = 0
end = len(code)
stmt_opcodes = {
stmt_opcodes = set([
SETUP_LOOP, BREAK_LOOP, CONTINUE_LOOP,
SETUP_FINALLY, END_FINALLY, SETUP_EXCEPT,
POP_BLOCK, STORE_FAST, DELETE_FAST, STORE_DEREF,
@@ -529,15 +529,15 @@ class Scanner25(scan.Scanner):
RETURN_VALUE, RAISE_VARARGS, POP_TOP,
PRINT_EXPR, PRINT_ITEM, PRINT_NEWLINE, PRINT_ITEM_TO, PRINT_NEWLINE_TO,
JUMP_ABSOLUTE, EXEC_STMT
}
])
stmt_opcode_seqs = [(PJIF, JF), (PJIF, JA), (PJIT, JF), (PJIT, JA)]
designator_ops = {
designator_ops = set([
STORE_FAST, STORE_NAME, STORE_GLOBAL, STORE_DEREF, STORE_ATTR,
STORE_SLICE_0, STORE_SLICE_1, STORE_SLICE_2, STORE_SLICE_3,
STORE_SUBSCR, UNPACK_SEQUENCE, JA
}
])
prelim = self.all_instr(start, end, stmt_opcodes)

8
uncompyle6/scanners/scanner26.py Normal file → Executable file
View File

@@ -511,7 +511,7 @@ class Scanner26(scan.Scanner):
start = 0
end = len(code)
stmt_opcodes = {
stmt_opcodes = set([
SETUP_LOOP, BREAK_LOOP, CONTINUE_LOOP,
SETUP_FINALLY, END_FINALLY, SETUP_EXCEPT,
POP_BLOCK, STORE_FAST, DELETE_FAST, STORE_DEREF,
@@ -520,15 +520,15 @@ class Scanner26(scan.Scanner):
RETURN_VALUE, RAISE_VARARGS, POP_TOP,
PRINT_EXPR, PRINT_ITEM, PRINT_NEWLINE, PRINT_ITEM_TO, PRINT_NEWLINE_TO,
JUMP_ABSOLUTE, EXEC_STMT,
}
])
stmt_opcode_seqs = [(PJIF, JF), (PJIF, JA), (PJIT, JF), (PJIT, JA)]
designator_ops = {
designator_ops = set([
STORE_FAST, STORE_NAME, STORE_GLOBAL, STORE_DEREF, STORE_ATTR,
STORE_SLICE_0, STORE_SLICE_1, STORE_SLICE_2, STORE_SLICE_3,
STORE_SUBSCR, UNPACK_SEQUENCE, JA
}
])
prelim = self.all_instr(start, end, stmt_opcodes)

8
uncompyle6/scanners/scanner27.py Normal file → Executable file
View File

@@ -223,7 +223,7 @@ class Scanner27(scan.Scanner):
start = 0
end = len(code)
stmt_opcodes = {
stmt_opcodes = set([
SETUP_LOOP, BREAK_LOOP, CONTINUE_LOOP,
SETUP_FINALLY, END_FINALLY, SETUP_EXCEPT, SETUP_WITH,
POP_BLOCK, STORE_FAST, DELETE_FAST, STORE_DEREF,
@@ -234,15 +234,15 @@ class Scanner27(scan.Scanner):
STORE_SLICE_0, STORE_SLICE_1, STORE_SLICE_2, STORE_SLICE_3,
DELETE_SLICE_0, DELETE_SLICE_1, DELETE_SLICE_2, DELETE_SLICE_3,
JUMP_ABSOLUTE, EXEC_STMT,
}
])
stmt_opcode_seqs = [(PJIF, JF), (PJIF, JA), (PJIT, JF), (PJIT, JA)]
designator_ops = {
designator_ops = set([
STORE_FAST, STORE_NAME, STORE_GLOBAL, STORE_DEREF, STORE_ATTR,
STORE_SLICE_0, STORE_SLICE_1, STORE_SLICE_2, STORE_SLICE_3,
STORE_SUBSCR, UNPACK_SEQUENCE, JA
}
])
prelim = self.all_instr(start, end, stmt_opcodes)

View File

@@ -332,8 +332,8 @@ class Token(scanner.Token):
return 0
if JUMP_OPs and t in JUMP_OPs:
# ignore offset
return cmp(t, o.type)
return cmp(t, o.type) or cmp(self.pattr, o.pattr)
return t == o.type
return (t == o.type) or self.pattr == o.pattr
def __repr__(self):
return '%s %s (%s)' % (str(self.type), str(self.attr),