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