You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
Misc refactorings
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
*_dis
|
*_dis
|
||||||
|
*.pyc
|
||||||
*~
|
*~
|
||||||
/.cache
|
/.cache
|
||||||
/.eggs
|
/.eggs
|
||||||
|
@@ -84,9 +84,10 @@ for usage help.
|
|||||||
Known Bugs/Restrictions
|
Known Bugs/Restrictions
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
Python 2 deparsing decompiles about the first 140 or so of the Python
|
Python 2 deparsing decompiles each and all the Python 2.7.10 and 2.7.11 installed packages
|
||||||
2.7.10 and 2.7.11 standard library files and all but less that 10%
|
I have on my system. All but less that 10%
|
||||||
verify. So as such, it is probably a little better than uncompyle2.
|
verify. Some of thse failures may be bugs in the verification process.
|
||||||
|
So as such, it is probably a little better than uncompyle2.
|
||||||
Other Python 2 versions do worse.
|
Other Python 2 versions do worse.
|
||||||
|
|
||||||
Python 3 deparsing before 3.5 is okay, but even there, more work is needed to
|
Python 3 deparsing before 3.5 is okay, but even there, more work is needed to
|
||||||
|
@@ -1,9 +1,6 @@
|
|||||||
# Copyright (c) 1999 John Aycock
|
|
||||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
|
||||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
|
||||||
# Copyright (c) 2015 Rocky Bernstein
|
# Copyright (c) 2015 Rocky Bernstein
|
||||||
#
|
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
# See LICENSE for license
|
# Copyright (c) 1999 John Aycock
|
||||||
"""
|
"""
|
||||||
A spark grammar for Python 2.x.
|
A spark grammar for Python 2.x.
|
||||||
|
|
||||||
@@ -20,15 +17,11 @@ from __future__ import print_function
|
|||||||
from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
|
from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
|
||||||
from uncompyle6.parsers.astnode import AST
|
from uncompyle6.parsers.astnode import AST
|
||||||
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||||
from uncompyle6 import PYTHON3
|
|
||||||
|
|
||||||
class Python2Parser(PythonParser):
|
class Python2Parser(PythonParser):
|
||||||
|
|
||||||
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
||||||
if PYTHON3:
|
super(Python2Parser, self).__init__(AST, 'stmts', debug=debug_parser)
|
||||||
super().__init__(AST, 'stmts', debug=debug_parser)
|
|
||||||
else:
|
|
||||||
super(Python2Parser, self).__init__(AST, 'stmts', debug=debug_parser)
|
|
||||||
self.customized = {}
|
self.customized = {}
|
||||||
|
|
||||||
def p_list_comprehension2(self, args):
|
def p_list_comprehension2(self, args):
|
||||||
|
@@ -49,9 +49,11 @@ class Scanner2(scan.Scanner):
|
|||||||
dis.disassemble().
|
dis.disassemble().
|
||||||
"""
|
"""
|
||||||
|
|
||||||
## FIXME: DRY with disassemble_native
|
# DEBUG
|
||||||
|
# from xdis.bytecode import Bytecode
|
||||||
# import dis; dis.disassemble(co) # DEBUG
|
# bytecode = Bytecode(co, self.opc)
|
||||||
|
# for instr in bytecode.get_instructions(co):
|
||||||
|
# print(instr._disassemble())
|
||||||
|
|
||||||
# Container for tokens
|
# Container for tokens
|
||||||
tokens = []
|
tokens = []
|
||||||
@@ -60,6 +62,7 @@ class Scanner2(scan.Scanner):
|
|||||||
Token = self.Token # shortcut
|
Token = self.Token # shortcut
|
||||||
|
|
||||||
n = self.setup_code(co)
|
n = self.setup_code(co)
|
||||||
|
|
||||||
self.build_lines_data(co, n)
|
self.build_lines_data(co, n)
|
||||||
self.build_prev_op(n)
|
self.build_prev_op(n)
|
||||||
|
|
||||||
@@ -203,75 +206,6 @@ class Scanner2(scan.Scanner):
|
|||||||
tokens.append(Token(replace[offset], oparg, pattr, offset, linestart))
|
tokens.append(Token(replace[offset], oparg, pattr, offset, linestart))
|
||||||
return tokens, customize
|
return tokens, customize
|
||||||
|
|
||||||
def disassemble_native(self, co, classname=None, code_objects={}):
|
|
||||||
"""
|
|
||||||
Like disassemble3 but doesn't try to adjust any opcodes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
## FIXME: DRY with disassemble
|
|
||||||
|
|
||||||
# Container for tokens
|
|
||||||
tokens = []
|
|
||||||
|
|
||||||
customize = {}
|
|
||||||
Token = self.Token # shortcut
|
|
||||||
|
|
||||||
n = self.setup_code(co)
|
|
||||||
self.build_lines_data(co, n)
|
|
||||||
|
|
||||||
# self.lines contains (block,addrLastInstr)
|
|
||||||
if classname:
|
|
||||||
classname = '_' + classname.lstrip('_') + '__'
|
|
||||||
|
|
||||||
def unmangle(name):
|
|
||||||
if name.startswith(classname) and name[-2:] != '__':
|
|
||||||
return name[len(classname) - 2:]
|
|
||||||
return name
|
|
||||||
|
|
||||||
free = [ unmangle(name) for name in (co.co_cellvars + co.co_freevars) ]
|
|
||||||
names = [ unmangle(name) for name in co.co_names ]
|
|
||||||
varnames = [ unmangle(name) for name in co.co_varnames ]
|
|
||||||
else:
|
|
||||||
free = co.co_cellvars + co.co_freevars
|
|
||||||
names = co.co_names
|
|
||||||
varnames = co.co_varnames
|
|
||||||
|
|
||||||
extended_arg = 0
|
|
||||||
for offset in self.op_range(0, n):
|
|
||||||
op = self.code[offset]
|
|
||||||
op_name = self.opc.opname[op]
|
|
||||||
|
|
||||||
oparg = None; pattr = None
|
|
||||||
if op >= self.opc.HAVE_ARGUMENT:
|
|
||||||
oparg = self.get_argument(offset) + extended_arg
|
|
||||||
extended_arg = 0
|
|
||||||
if op == self.opc.EXTENDED_ARG:
|
|
||||||
extended_arg = oparg * scan.L65536
|
|
||||||
continue
|
|
||||||
if op in self.opc.hasconst:
|
|
||||||
pattr = co.co_consts[oparg]
|
|
||||||
elif op in self.opc.hasname:
|
|
||||||
pattr = names[oparg]
|
|
||||||
elif op in self.opc.hasjrel:
|
|
||||||
pattr = repr(offset + 3 + oparg)
|
|
||||||
elif op in self.opc.hasjabs:
|
|
||||||
pattr = repr(oparg)
|
|
||||||
elif op in self.opc.haslocal:
|
|
||||||
pattr = varnames[oparg]
|
|
||||||
elif op in self.opc.hascompare:
|
|
||||||
pattr = self.opc.cmp_op[oparg]
|
|
||||||
elif op in self.opc.hasfree:
|
|
||||||
pattr = free[oparg]
|
|
||||||
|
|
||||||
if offset in self.linestartoffsets:
|
|
||||||
linestart = self.linestartoffsets[offset]
|
|
||||||
else:
|
|
||||||
linestart = None
|
|
||||||
|
|
||||||
tokens.append(Token(op_name, oparg, pattr, offset, linestart))
|
|
||||||
pass
|
|
||||||
return tokens, customize
|
|
||||||
|
|
||||||
def op_size(self, op):
|
def op_size(self, op):
|
||||||
"""
|
"""
|
||||||
Return size of operator with its arguments
|
Return size of operator with its arguments
|
||||||
|
@@ -73,7 +73,10 @@ class Scanner26(scan.Scanner2):
|
|||||||
dis.disassemble().
|
dis.disassemble().
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# import dis; dis.disassemble(co) # DEBUG
|
# from xdis.bytecode import Bytecode
|
||||||
|
# bytecode = Bytecode(co, self.opc)
|
||||||
|
# for instr in bytecode.get_instructions(co):
|
||||||
|
# print(instr._disassemble())
|
||||||
|
|
||||||
# Container for tokens
|
# Container for tokens
|
||||||
tokens = []
|
tokens = []
|
||||||
@@ -82,7 +85,8 @@ class Scanner26(scan.Scanner2):
|
|||||||
Token = self.Token # shortcut
|
Token = self.Token # shortcut
|
||||||
|
|
||||||
n = self.setup_code(co)
|
n = self.setup_code(co)
|
||||||
self.build_lines_data(co, n)
|
|
||||||
|
self.build_lines_data(co, n-1)
|
||||||
|
|
||||||
# linestarts contains block code adresses (addr,block)
|
# linestarts contains block code adresses (addr,block)
|
||||||
self.linestarts = list(findlinestarts(co))
|
self.linestarts = list(findlinestarts(co))
|
||||||
|
@@ -176,32 +176,6 @@ class Scanner3(scan.Scanner):
|
|||||||
pass
|
pass
|
||||||
return tokens, {}
|
return tokens, {}
|
||||||
|
|
||||||
def disassemble_native(self, co, classname=None, code_objects={}):
|
|
||||||
"""
|
|
||||||
Like disassemble3 but doesn't try to adjust any opcodes.
|
|
||||||
"""
|
|
||||||
# Container for tokens
|
|
||||||
tokens = []
|
|
||||||
|
|
||||||
self.code = array('B', co.co_code)
|
|
||||||
|
|
||||||
bytecode = Bytecode(co, self.opc)
|
|
||||||
|
|
||||||
for inst in bytecode:
|
|
||||||
pattr = inst.argrepr
|
|
||||||
opname = inst.opname
|
|
||||||
tokens.append(
|
|
||||||
Token(
|
|
||||||
type_ = opname,
|
|
||||||
attr = inst.argval,
|
|
||||||
pattr = pattr,
|
|
||||||
offset = inst.offset,
|
|
||||||
linestart = inst.starts_line,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
pass
|
|
||||||
return tokens, {}
|
|
||||||
|
|
||||||
def build_lines_data(self, code_obj):
|
def build_lines_data(self, code_obj):
|
||||||
"""
|
"""
|
||||||
Generate various line-related helper data.
|
Generate various line-related helper data.
|
||||||
|
Reference in New Issue
Block a user