You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
Start handling Pyton 2.4 bytecodes
This commit is contained in:
@@ -37,7 +37,7 @@ entry_points={
|
|||||||
]}
|
]}
|
||||||
ftp_url = None
|
ftp_url = None
|
||||||
install_requires = ['spark-parser >= 1.4.0',
|
install_requires = ['spark-parser >= 1.4.0',
|
||||||
'xdis >= 1.1.4']
|
'xdis >= 1.1.5']
|
||||||
license = 'MIT'
|
license = 'MIT'
|
||||||
mailing_list = 'python-debugger@googlegroups.com'
|
mailing_list = 'python-debugger@googlegroups.com'
|
||||||
modname = 'uncompyle6'
|
modname = 'uncompyle6'
|
||||||
|
@@ -43,7 +43,7 @@ check-disasm:
|
|||||||
|
|
||||||
#: Check deparsing bytecode 2.x only
|
#: Check deparsing bytecode 2.x only
|
||||||
check-bytecode-2:
|
check-bytecode-2:
|
||||||
$(PYTHON) test_pythonlib.py --bytecode-2.3 --bytecode-2.5 --bytecode-2.6 --bytecode-2.7
|
$(PYTHON) test_pythonlib.py --bytecode-2.3 --bytecode-2.4 --bytecode-2.5 --bytecode-2.6 --bytecode-2.7
|
||||||
|
|
||||||
#: Check deparsing bytecode 3.x only
|
#: Check deparsing bytecode 3.x only
|
||||||
check-bytecode-3:
|
check-bytecode-3:
|
||||||
@@ -57,6 +57,10 @@ check-bytecode: check-bytecode-3
|
|||||||
check-bytecode-2.3:
|
check-bytecode-2.3:
|
||||||
$(PYTHON) test_pythonlib.py --bytecode-2.3
|
$(PYTHON) test_pythonlib.py --bytecode-2.3
|
||||||
|
|
||||||
|
#: Check deparsing Python 2.4
|
||||||
|
check-bytecode-2.4:
|
||||||
|
$(PYTHON) test_pythonlib.py --bytecode-2.4
|
||||||
|
|
||||||
#: Check deparsing Python 2.5
|
#: Check deparsing Python 2.5
|
||||||
check-bytecode-2.5:
|
check-bytecode-2.5:
|
||||||
$(PYTHON) test_pythonlib.py --bytecode-2.5
|
$(PYTHON) test_pythonlib.py --bytecode-2.5
|
||||||
|
@@ -2,12 +2,12 @@
|
|||||||
""" Trivial helper program to bytecompile and run an uncompile
|
""" Trivial helper program to bytecompile and run an uncompile
|
||||||
"""
|
"""
|
||||||
import os, sys, py_compile
|
import os, sys, py_compile
|
||||||
assert len(sys.argv) == 2
|
assert len(sys.argv) >= 2
|
||||||
path = sys.argv[1]
|
|
||||||
short = os.path.basename(path)
|
|
||||||
version = sys.version[0:3]
|
version = sys.version[0:3]
|
||||||
cfile = "bytecode_%s/%s" % (version, short) + 'c'
|
for path in sys.argv[1:]:
|
||||||
print("byte-compiling %s to %s" % (path, cfile))
|
short = os.path.basename(path)
|
||||||
py_compile.compile(path, cfile)
|
cfile = "bytecode_%s/%s" % (version, short) + 'c'
|
||||||
if sys.version >= (2, 6, 0):
|
print("byte-compiling %s to %s" % (path, cfile))
|
||||||
os.system("../bin/uncompyle6 -a -t %s" % cfile)
|
py_compile.compile(path, cfile)
|
||||||
|
if sys.version >= (2, 6, 0):
|
||||||
|
os.system("../bin/uncompyle6 -a -t %s" % cfile)
|
||||||
|
BIN
test/bytecode_2.4/03_if_elif.pyc
Normal file
BIN
test/bytecode_2.4/03_if_elif.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/04_raise.pyc
Normal file
BIN
test/bytecode_2.4/04_raise.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/03_if_elif.pyc
Normal file
BIN
test/bytecode_2.7/03_if_elif.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/04_raise.pyc
Normal file
BIN
test/bytecode_2.7/04_raise.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/04_withas.pyc
Normal file
BIN
test/bytecode_2.7/04_withas.pyc
Normal file
Binary file not shown.
@@ -27,7 +27,8 @@ from fnmatch import fnmatch
|
|||||||
|
|
||||||
#----- configure this for your needs
|
#----- configure this for your needs
|
||||||
|
|
||||||
TEST_VERSIONS=('2.3.7', '2.5.6', '2.6.9', '2.7.10', '2.7.11', '3.2.6', '3.3.5', '3.4.2', '3.5.1')
|
TEST_VERSIONS=('2.3.7', '2.4.6', '2.5.6', '2.6.9', '2.7.10', '2.7.11',
|
||||||
|
'3.2.6', '3.3.5', '3.4.2', '3.5.1')
|
||||||
|
|
||||||
target_base = '/tmp/py-dis/'
|
target_base = '/tmp/py-dis/'
|
||||||
lib_prefix = os.path.join(os.environ['HOME'], '.pyenv/versions')
|
lib_prefix = os.path.join(os.environ['HOME'], '.pyenv/versions')
|
||||||
|
@@ -78,7 +78,7 @@ for vers in (2.7, 3.4, 3.5):
|
|||||||
test_options[key] = (os.path.join(src_dir, pythonlib), PYOC, key, vers)
|
test_options[key] = (os.path.join(src_dir, pythonlib), PYOC, key, vers)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
for vers in (2.3, 2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5):
|
for vers in (2.3, 2.4, 2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5):
|
||||||
bytecode = "bytecode_%s" % vers
|
bytecode = "bytecode_%s" % vers
|
||||||
key = "bytecode-%s" % vers
|
key = "bytecode-%s" % vers
|
||||||
test_options[key] = (bytecode, PYC, bytecode, vers)
|
test_options[key] = (bytecode, PYC, bytecode, vers)
|
||||||
|
@@ -591,6 +591,12 @@ def get_python_parser(version, debug_parser, compile_mode='exec'):
|
|||||||
p = parse23.Python23Parser(debug_parser)
|
p = parse23.Python23Parser(debug_parser)
|
||||||
else:
|
else:
|
||||||
p = parse23.Python23ParserSingle(debug_parser)
|
p = parse23.Python23ParserSingle(debug_parser)
|
||||||
|
elif version == 2.4:
|
||||||
|
import uncompyle6.parsers.parse24 as parse24
|
||||||
|
if compile_mode == 'exec':
|
||||||
|
p = parse24.Python24Parser(debug_parser)
|
||||||
|
else:
|
||||||
|
p = parse24.Python24ParserSingle(debug_parser)
|
||||||
elif version == 2.5:
|
elif version == 2.5:
|
||||||
import uncompyle6.parsers.parse25 as parse25
|
import uncompyle6.parsers.parse25 as parse25
|
||||||
if compile_mode == 'exec':
|
if compile_mode == 'exec':
|
||||||
|
28
uncompyle6/parsers/parse24.py
Normal file
28
uncompyle6/parsers/parse24.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Copyright (c) 2016 Rocky Bernstein
|
||||||
|
"""
|
||||||
|
spark grammar differences over Python2.5 for Python 2.4.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from uncompyle6.parser import PythonParserSingle
|
||||||
|
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||||
|
from uncompyle6.parsers.parse25 import Python25Parser
|
||||||
|
|
||||||
|
class Python24Parser(Python25Parser):
|
||||||
|
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
||||||
|
super(Python24Parser, self).__init__(debug_parser)
|
||||||
|
self.customized = {}
|
||||||
|
|
||||||
|
def p_misc24(self, args):
|
||||||
|
'''
|
||||||
|
# 2.5+ has two LOAD_CONSTs, one for the number '.'s in a relative import
|
||||||
|
importstmt ::= LOAD_CONST filler import_as
|
||||||
|
importfrom ::= LOAD_CONST filler IMPORT_NAME importlist2 POP_TOP
|
||||||
|
'''
|
||||||
|
|
||||||
|
class Python24ParserSingle(Python25Parser, PythonParserSingle):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# Check grammar
|
||||||
|
p = Python24Parser()
|
||||||
|
p.checkGrammar()
|
@@ -1,6 +1,6 @@
|
|||||||
# Copyright (c) 2016 Rocky Bernstein
|
# Copyright (c) 2016 Rocky Bernstein
|
||||||
"""
|
"""
|
||||||
spark grammar differences over Python2.6 for Python 2.6.
|
spark grammar differences over Python2.6 for Python 2.5.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from uncompyle6.parser import PythonParserSingle
|
from uncompyle6.parser import PythonParserSingle
|
||||||
@@ -41,5 +41,5 @@ class Python25ParserSingle(Python26Parser, PythonParserSingle):
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Check grammar
|
# Check grammar
|
||||||
p = Python26Parser()
|
p = Python25Parser()
|
||||||
p.checkGrammar()
|
p.checkGrammar()
|
||||||
|
@@ -26,7 +26,7 @@ if PYTHON3:
|
|||||||
# Need to work out Python 2.3. ord's in PYTHON3
|
# Need to work out Python 2.3. ord's in PYTHON3
|
||||||
PYTHON_VERSIONS = (2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5)
|
PYTHON_VERSIONS = (2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5)
|
||||||
else:
|
else:
|
||||||
PYTHON_VERSIONS = (2.3, 2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5)
|
PYTHON_VERSIONS = (2.3, 2.4, 2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5)
|
||||||
|
|
||||||
# FIXME: DRY
|
# FIXME: DRY
|
||||||
if PYTHON3:
|
if PYTHON3:
|
||||||
|
68
uncompyle6/scanners/scanner24.py
Executable file
68
uncompyle6/scanners/scanner24.py
Executable file
@@ -0,0 +1,68 @@
|
|||||||
|
# Copyright (c) 2016 by Rocky Bernstein
|
||||||
|
"""
|
||||||
|
Python 2.4 bytecode scanner/deparser
|
||||||
|
|
||||||
|
This overlaps Python's 2.4's dis module, but it can be run from
|
||||||
|
Python 3 and other versions of Python. Also, we save token
|
||||||
|
information for later use in deparsing.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import uncompyle6.scanners.scanner25 as scan
|
||||||
|
import uncompyle6.scanners.scanner2 as scan2
|
||||||
|
|
||||||
|
# bytecode verification, verify(), uses JUMP_OPs from here
|
||||||
|
from xdis.opcodes import opcode_24
|
||||||
|
JUMP_OPs = opcode_24.JUMP_OPs
|
||||||
|
|
||||||
|
# We base this off of 2.6 instead of the other way around
|
||||||
|
# because we cleaned things up this way.
|
||||||
|
# The history is that 2.7 support is the cleanest,
|
||||||
|
# then from that we got 2.6 and so on.
|
||||||
|
class Scanner24(scan.Scanner25):
|
||||||
|
def __init__(self, show_asm):
|
||||||
|
scan2.Scanner2.__init__(self, 2.4, show_asm)
|
||||||
|
self.stmt_opcodes = frozenset([
|
||||||
|
self.opc.SETUP_LOOP, self.opc.BREAK_LOOP,
|
||||||
|
self.opc.SETUP_FINALLY, self.opc.END_FINALLY,
|
||||||
|
self.opc.SETUP_EXCEPT, self.opc.POP_BLOCK,
|
||||||
|
self.opc.STORE_FAST, self.opc.DELETE_FAST,
|
||||||
|
self.opc.STORE_DEREF, self.opc.STORE_GLOBAL,
|
||||||
|
self.opc.DELETE_GLOBAL, self.opc.STORE_NAME,
|
||||||
|
self.opc.DELETE_NAME, self.opc.STORE_ATTR,
|
||||||
|
self.opc.DELETE_ATTR, self.opc.STORE_SUBSCR,
|
||||||
|
self.opc.DELETE_SUBSCR, self.opc.RETURN_VALUE,
|
||||||
|
self.opc.RAISE_VARARGS, self.opc.POP_TOP,
|
||||||
|
self.opc.PRINT_EXPR, self.opc.PRINT_ITEM,
|
||||||
|
self.opc.PRINT_NEWLINE, self.opc.PRINT_ITEM_TO,
|
||||||
|
self.opc.PRINT_NEWLINE_TO, self.opc.CONTINUE_LOOP,
|
||||||
|
self.opc.JUMP_ABSOLUTE, self.opc.EXEC_STMT,
|
||||||
|
])
|
||||||
|
|
||||||
|
# "setup" opcodes
|
||||||
|
self.setup_ops = frozenset([
|
||||||
|
self.opc.SETUP_EXCEPT, self.opc.SETUP_FINALLY,
|
||||||
|
])
|
||||||
|
|
||||||
|
# opcodes with expect a variable number pushed values whose
|
||||||
|
# count is in the opcode. For parsing we generally change the
|
||||||
|
# opcode name to include that number.
|
||||||
|
self.varargs_ops = frozenset([
|
||||||
|
self.opc.BUILD_LIST, self.opc.BUILD_TUPLE,
|
||||||
|
self.opc.BUILD_SLICE, self.opc.UNPACK_SEQUENCE,
|
||||||
|
self.opc.MAKE_FUNCTION, self.opc.CALL_FUNCTION,
|
||||||
|
self.opc.MAKE_CLOSURE, self.opc.CALL_FUNCTION_VAR,
|
||||||
|
self.opc.CALL_FUNCTION_KW, self.opc.CALL_FUNCTION_VAR_KW,
|
||||||
|
self.opc.DUP_TOPX, self.opc.RAISE_VARARGS])
|
||||||
|
|
||||||
|
# opcodes that store values into a variable
|
||||||
|
self.designator_ops = frozenset([
|
||||||
|
self.opc.STORE_FAST, self.opc.STORE_NAME,
|
||||||
|
self.opc.STORE_GLOBAL, self.opc.STORE_DEREF, self.opc.STORE_ATTR,
|
||||||
|
self.opc.STORE_SLICE_0, self.opc.STORE_SLICE_1, self.opc.STORE_SLICE_2,
|
||||||
|
self.opc.STORE_SLICE_3, self.opc.STORE_SUBSCR, self.opc.UNPACK_SEQUENCE,
|
||||||
|
self.opc.JA
|
||||||
|
])
|
||||||
|
# Python 2.7 has POP_JUMP_IF_{TRUE,FALSE}_OR_POP but < 2.7 doesn't
|
||||||
|
# Add an empty set make processing more uniform.
|
||||||
|
self.pop_jump_if_or_pop = frozenset([])
|
||||||
|
return
|
@@ -1,7 +1,4 @@
|
|||||||
# Copyright (c) 2015-2016 by Rocky Bernstein
|
# Copyright (c) 2015-2016 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
|
|
||||||
"""
|
"""
|
||||||
Python 2.5 bytecode scanner/deparser
|
Python 2.5 bytecode scanner/deparser
|
||||||
|
|
||||||
@@ -10,7 +7,6 @@ Python 3 and other versions of Python. Also, we save token
|
|||||||
information for later use in deparsing.
|
information for later use in deparsing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from xdis.opcodes.opcode_25 import *
|
|
||||||
import uncompyle6.scanners.scanner26 as scan
|
import uncompyle6.scanners.scanner26 as scan
|
||||||
import uncompyle6.scanners.scanner2 as scan2
|
import uncompyle6.scanners.scanner2 as scan2
|
||||||
|
|
||||||
|
@@ -961,8 +961,9 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
n_import_as_cont = n_import_as
|
n_import_as_cont = n_import_as
|
||||||
|
|
||||||
def n_importfrom(self, node):
|
def n_importfrom(self, node):
|
||||||
if node[0].pattr > 0:
|
relative_path_index = 0
|
||||||
node[2].pattr = '.'*node[0].pattr+node[2].pattr
|
if self.version >= 2.5 and node[relative_path_index].pattr > 0:
|
||||||
|
node[2].pattr = '.'*node[relative_path_index].pattr + node[2].pattr
|
||||||
self.default(node)
|
self.default(node)
|
||||||
|
|
||||||
n_importstar = n_importfrom
|
n_importstar = n_importfrom
|
||||||
|
Reference in New Issue
Block a user