You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
option to show asm and DRY.
Get ready for some 2.3 support
This commit is contained in:
@@ -45,12 +45,17 @@ class Code(object):
|
||||
|
||||
class Scanner(object):
|
||||
|
||||
def __init__(self, version):
|
||||
def __init__(self, version, show_asm=False):
|
||||
self.version = version
|
||||
self.show_asm = show_asm
|
||||
|
||||
# FIXME: DRY
|
||||
if version == 2.7:
|
||||
from xdis.opcodes import opcode_27
|
||||
self.opc = opcode_27
|
||||
elif version == 2.3:
|
||||
from xdis.opcodes import opcode_23
|
||||
self.opc = opcode_23
|
||||
elif version == 2.6:
|
||||
from xdis.opcodes import opcode_26
|
||||
self.opc = opcode_26
|
||||
@@ -281,7 +286,7 @@ class Scanner(object):
|
||||
target = parent['end']
|
||||
return target
|
||||
|
||||
def get_scanner(version):
|
||||
def get_scanner(version, show_asm=False):
|
||||
# Pick up appropriate scanner
|
||||
# from trepan.api import debug;
|
||||
# debug(start_opts={'startup-profile': True})
|
||||
@@ -289,25 +294,28 @@ def get_scanner(version):
|
||||
# FIXME: see if we can do better
|
||||
if version == 2.7:
|
||||
import uncompyle6.scanners.scanner27 as scan
|
||||
scanner = scan.Scanner27()
|
||||
scanner = scan.Scanner27(show_asm=show_asm)
|
||||
elif version == 2.3:
|
||||
import uncompyle6.scanners.scanner23 as scan
|
||||
scanner = scan.Scanner23(show_asm)
|
||||
elif version == 2.6:
|
||||
import uncompyle6.scanners.scanner26 as scan
|
||||
scanner = scan.Scanner26()
|
||||
scanner = scan.Scanner26(show_asm)
|
||||
elif version == 2.5:
|
||||
import uncompyle6.scanners.scanner25 as scan
|
||||
scanner = scan.Scanner25()
|
||||
scanner = scan.Scanner25(show_asm)
|
||||
elif version == 3.2:
|
||||
import uncompyle6.scanners.scanner32 as scan
|
||||
scanner = scan.Scanner32()
|
||||
scanner = scan.Scanner32(show_asm)
|
||||
elif version == 3.3:
|
||||
import uncompyle6.scanners.scanner33 as scan
|
||||
scanner = scan.Scanner33()
|
||||
scanner = scan.Scanner33(show_asm)
|
||||
elif version == 3.4:
|
||||
import uncompyle6.scanners.scanner34 as scan
|
||||
scanner = scan.Scanner34()
|
||||
scanner = scan.Scanner34(show_asm)
|
||||
elif version == 3.5:
|
||||
import uncompyle6.scanners.scanner35 as scan
|
||||
scanner = scan.Scanner35()
|
||||
scanner = scan.Scanner35(show_asm)
|
||||
else:
|
||||
raise RuntimeError("Unsupported Python version %s" % version)
|
||||
return scanner
|
||||
@@ -315,9 +323,5 @@ def get_scanner(version):
|
||||
if __name__ == "__main__":
|
||||
import inspect, uncompyle6
|
||||
co = inspect.currentframe().f_code
|
||||
scanner = get_scanner(uncompyle6.PYTHON_VERSION)
|
||||
scanner = get_scanner(uncompyle6.PYTHON_VERSION, True)
|
||||
tokens, customize = scanner.disassemble(co, {})
|
||||
print('-' * 30)
|
||||
for t in tokens:
|
||||
print(t)
|
||||
pass
|
||||
|
@@ -32,8 +32,8 @@ from xdis.bytecode import findlinestarts
|
||||
import uncompyle6.scanner as scan
|
||||
|
||||
class Scanner2(scan.Scanner):
|
||||
def __init__(self, version):
|
||||
scan.Scanner.__init__(self, version)
|
||||
def __init__(self, version, show_asm=False):
|
||||
scan.Scanner.__init__(self, version, show_asm)
|
||||
self.pop_jump_if = frozenset([self.opc.PJIF, self.opc.PJIT])
|
||||
self.jump_forward = frozenset([self.opc.JA, self.opc.JF])
|
||||
|
||||
@@ -204,6 +204,13 @@ class Scanner2(scan.Scanner):
|
||||
tokens.append(Token(op_name, oparg, pattr, offset, linestart))
|
||||
else:
|
||||
tokens.append(Token(replace[offset], oparg, pattr, offset, linestart))
|
||||
pass
|
||||
pass
|
||||
|
||||
if self.show_asm:
|
||||
for t in tokens:
|
||||
print(t)
|
||||
print()
|
||||
return tokens, customize
|
||||
|
||||
def op_size(self, op):
|
||||
|
@@ -23,8 +23,8 @@ JUMP_OPs = opcode_25.JUMP_OPs
|
||||
# The history is that 2.7 support is the cleanest,
|
||||
# then from that we got 2.6 and so on.
|
||||
class Scanner25(scan.Scanner26):
|
||||
def __init__(self):
|
||||
scan2.Scanner2.__init__(self, 2.5)
|
||||
def __init__(self, show_asm):
|
||||
scan2.Scanner2.__init__(self, 2.5, show_asm)
|
||||
self.stmt_opcodes = frozenset([
|
||||
self.opc.SETUP_LOOP, self.opc.BREAK_LOOP,
|
||||
self.opc.SETUP_FINALLY, self.opc.END_FINALLY,
|
||||
|
@@ -18,8 +18,8 @@ from xdis.opcodes import opcode_26
|
||||
JUMP_OPs = opcode_26.JUMP_OPs
|
||||
|
||||
class Scanner26(scan.Scanner2):
|
||||
def __init__(self):
|
||||
super(Scanner26, self).__init__(2.6)
|
||||
def __init__(self, show_asm=False):
|
||||
super(Scanner26, self).__init__(2.6, show_asm)
|
||||
self.stmt_opcodes = frozenset([
|
||||
self.opc.SETUP_LOOP, self.opc.BREAK_LOOP,
|
||||
self.opc.SETUP_FINALLY, self.opc.END_FINALLY,
|
||||
@@ -251,9 +251,10 @@ class Scanner26(scan.Scanner2):
|
||||
pass
|
||||
pass
|
||||
|
||||
# Debug
|
||||
# for t in tokens:
|
||||
# print t
|
||||
if self.show_asm:
|
||||
for t in tokens:
|
||||
print(t)
|
||||
print()
|
||||
return tokens, customize
|
||||
|
||||
def getOpcodeToDel(self, i):
|
||||
@@ -586,8 +587,8 @@ class Scanner26(scan.Scanner2):
|
||||
if (jump_back and jump_back != self.prev[end]
|
||||
and code[jump_back + 3] in self.jump_forward):
|
||||
if (code[self.prev[end]] == self.opc.RETURN_VALUE
|
||||
or code[self.prev[end]] == self.opc.POP_BLOCK
|
||||
and code[self.prev[self.prev[end]]] == self.opc.RETURN_VALUE):
|
||||
or (code[self.prev[end]] == self.opc.POP_BLOCK
|
||||
and code[self.prev[self.prev[end]]] == self.opc.RETURN_VALUE)):
|
||||
jump_back = None
|
||||
if not jump_back: # loop suite ends in return. wtf right?
|
||||
jump_back = self.last_instr(start, end, self.opc.JA, start, False)
|
||||
@@ -604,7 +605,7 @@ class Scanner26(scan.Scanner2):
|
||||
else:
|
||||
if self.get_target(jump_back) >= next_line_byte:
|
||||
jump_back = self.last_instr(start, end, self.opc.JA, start, False)
|
||||
if end > jump_back + 4 and code[end] in (self.opc.JF, self.opc.JA):
|
||||
if end > jump_back + 4 and code[end] in self.jump_forward:
|
||||
if code[jump_back + 4] in (self.opc.JA, self.opc.JF):
|
||||
if self.get_target(jump_back+4) == self.get_target(end):
|
||||
self.fixed_jumps[pos] = jump_back+4
|
||||
@@ -807,9 +808,7 @@ if __name__ == "__main__":
|
||||
if PYTHON_VERSION == 2.6:
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
tokens, customize = Scanner26().disassemble(co)
|
||||
for t in tokens:
|
||||
print(t.format())
|
||||
tokens, customize = Scanner26(show_asm=True).disassemble(co)
|
||||
else:
|
||||
print("Need to be Python 2.6 to demo; I am %s." %
|
||||
PYTHON_VERSION)
|
||||
|
@@ -17,8 +17,8 @@ from xdis.opcodes import opcode_27
|
||||
JUMP_OPs = opcode_27.JUMP_OPs
|
||||
|
||||
class Scanner27(Scanner2):
|
||||
def __init__(self):
|
||||
super(Scanner27, self).__init__(2.7)
|
||||
def __init__(self, show_asm=False):
|
||||
super(Scanner27, self).__init__(2.7, show_asm)
|
||||
|
||||
# opcodes that start statements
|
||||
self.stmt_opcodes = frozenset([
|
||||
|
@@ -40,8 +40,8 @@ import uncompyle6.scanner as scan
|
||||
|
||||
class Scanner3(scan.Scanner):
|
||||
|
||||
def __init__(self, version):
|
||||
super(Scanner3, self).__init__(version)
|
||||
def __init__(self, version, show_asm=False):
|
||||
super(Scanner3, self).__init__(version, show_asm)
|
||||
|
||||
def disassemble(self, co, classname=None, code_objects={}):
|
||||
"""
|
||||
|
@@ -8,16 +8,15 @@ scanner routine for Python 3.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import xdis
|
||||
|
||||
# bytecode verification, verify(), uses JUMP_OPs from here
|
||||
# JUMP_OPs = xdis.opcodes.opcode_32.JUMP_OPs
|
||||
from xdis.opcodes import opcode_32 as opc
|
||||
JUMP_OPs = map(lambda op: opc.opname[op], opc.hasjrel + opc.hasjabs)
|
||||
|
||||
from uncompyle6.scanners.scanner3 import Scanner3
|
||||
class Scanner32(Scanner3):
|
||||
|
||||
def __init__(self):
|
||||
super(Scanner3, self).__init__(3.2)
|
||||
def __init__(self, show_asm=False):
|
||||
super(Scanner3, self).__init__(3.2, show_asm)
|
||||
return
|
||||
pass
|
||||
|
||||
|
@@ -8,16 +8,15 @@ scanner routine for Python 3.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
from xdis.opcodes import opcode_33 as opc
|
||||
|
||||
# bytecode verification, verify(), uses JUMP_OPs from here
|
||||
from xdis.opcodes import opcode_33 as opc
|
||||
JUMP_OPs = map(lambda op: opc.opname[op], opc.hasjrel + opc.hasjabs)
|
||||
|
||||
from uncompyle6.scanners.scanner3 import Scanner3
|
||||
class Scanner33(Scanner3):
|
||||
|
||||
def __init__(self):
|
||||
super(Scanner3, self).__init__(3.3)
|
||||
def __init__(self, show_asm=False):
|
||||
super(Scanner3, self).__init__(3.3, show_asm)
|
||||
return
|
||||
pass
|
||||
|
||||
|
@@ -17,8 +17,8 @@ JUMP_OPs = map(lambda op: opc.opname[op], opc.hasjrel + opc.hasjabs)
|
||||
from uncompyle6.scanners.scanner3 import Scanner3
|
||||
class Scanner34(Scanner3):
|
||||
|
||||
def __init__(self):
|
||||
super(Scanner3, self).__init__(3.4)
|
||||
def __init__(self, show_asm=False):
|
||||
super(Scanner3, self).__init__(3.4, show_asm)
|
||||
return
|
||||
pass
|
||||
|
||||
|
@@ -8,17 +8,16 @@ scanner routine for Python 3.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
from xdis.opcodes import opcode_35 as opc
|
||||
|
||||
from uncompyle6.scanners.scanner3 import Scanner3
|
||||
|
||||
# bytecode verification, verify(), uses JUMP_OPs from here
|
||||
from xdis.opcodes import opcode_35 as opc
|
||||
JUMP_OPs = map(lambda op: opc.opname[op], opc.hasjrel + opc.hasjabs)
|
||||
|
||||
class Scanner35(Scanner3):
|
||||
|
||||
def __init__(self):
|
||||
super(Scanner35, self).__init__(3.5)
|
||||
def __init__(self, show_asm=False):
|
||||
super(Scanner35, self).__init__(3.5, show_asm)
|
||||
return
|
||||
pass
|
||||
|
||||
|
@@ -345,6 +345,16 @@ TABLE_DIRECT = {
|
||||
'kv2': ( '%c: %c', 1, 2 ),
|
||||
'mapexpr': ( '{%[1]C}', (0, maxint, ', ') ),
|
||||
|
||||
#######################
|
||||
# Python 2.3 Additions
|
||||
#######################
|
||||
|
||||
# Import style for 2.0-2.3
|
||||
'importstmt20': ( '%|import %c\n', 1),
|
||||
'importstar20': ( '%|from %[1]{pattr} import *\n', ),
|
||||
'importfrom20': ( '%|from %[1]{pattr} import %c\n', 2 ),
|
||||
'importlist20': ( '%C', (0, sys.maxint, ', ') ),
|
||||
|
||||
#######################
|
||||
# Python 2.5 Additions
|
||||
#######################
|
||||
@@ -526,7 +536,11 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
self.classes = []
|
||||
self.pending_newlines = 0
|
||||
self.hide_internal = True
|
||||
self.version = version
|
||||
|
||||
if 2.0 <= version <= 2.3:
|
||||
TABLE_DIRECT['tryfinallystmt'] = (
|
||||
'%|try:\n%+%c%-%|finally:\n%+%c%-\n\n', 1, 4 )
|
||||
return
|
||||
|
||||
f = property(lambda s: s.params['f'],
|
||||
@@ -1658,7 +1672,6 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
else:
|
||||
defparams = node[:args_node.attr]
|
||||
kw_args, annotate_args = (0, 0)
|
||||
pos_args = args_node.attr
|
||||
pass
|
||||
|
||||
if self.version > 3.0 and isLambda and iscode(node[-3].attr):
|
||||
|
Reference in New Issue
Block a user