You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
pydisassemble improvements; DRY scannners
disas.py: - disassembles *all* code objects found scanner*.py: - no longer need to pass in version numbers; this is obtained from the class name - no longer pass in opcodes; this is done at initialization from the scanner name - all Pythoin 3 scanners support native disassembly
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
import sys
|
||||
import os, sys
|
||||
from uncompyle6.load import load_file, check_object_path, load_module
|
||||
|
||||
def test_load():
|
||||
"""Basic test of load_file, check_object_path and load_module"""
|
||||
co = load_file(__file__)
|
||||
obj_path = check_object_path(__file__)
|
||||
version, timestamp, magic_int, co2 = load_module(obj_path)
|
||||
assert sys.version[0:3] == str(version)
|
||||
assert co == co2
|
||||
if os.path.exists(obj_path):
|
||||
version, timestamp, magic_int, co2 = load_module(obj_path)
|
||||
assert sys.version[0:3] == str(version)
|
||||
assert co == co2
|
||||
else:
|
||||
assert True, "Skipped because we can't find %s" % obj_path
|
||||
|
1
pytest/testdata/if-2.7.right
vendored
1
pytest/testdata/if-2.7.right
vendored
@@ -9,4 +9,3 @@
|
||||
12 JUMP_FORWARD 0 '15'
|
||||
15 LOAD_CONST 0 ''
|
||||
18 RETURN_VALUE ''
|
||||
|
||||
|
1
pytest/testdata/ifelse-2.7.right
vendored
1
pytest/testdata/ifelse-2.7.right
vendored
@@ -12,4 +12,3 @@
|
||||
18 STORE_NAME 2 'd'
|
||||
21 LOAD_CONST 2 ''
|
||||
24 RETURN_VALUE ''
|
||||
|
||||
|
@@ -19,6 +19,7 @@ want to run on Python 2.7.
|
||||
from __future__ import print_function
|
||||
|
||||
import os, sys
|
||||
from collections import deque
|
||||
|
||||
import uncompyle6
|
||||
from uncompyle6.code import iscode
|
||||
@@ -40,17 +41,29 @@ def disco(version, co, out=None, use_uncompyle6_format=False):
|
||||
file=real_out)
|
||||
|
||||
scanner = get_scanner(version)
|
||||
if (not use_uncompyle6_format) and hasattr(scanner, 'disassemble_native'):
|
||||
tokens, customize = scanner.disassemble_native(co, True)
|
||||
else:
|
||||
tokens, customize = scanner.disassemble(co)
|
||||
|
||||
# FIXME: This should go in another routine and
|
||||
# a queue should be kept of code to disassemble.
|
||||
for t in tokens:
|
||||
print(t.format(), file=real_out)
|
||||
print(file=out)
|
||||
disasm = scanner.disassemble_native \
|
||||
if (not use_uncompyle6_format) and hasattr(scanner, 'disassemble_native') \
|
||||
else scanner.disassemble
|
||||
|
||||
queue = deque([co])
|
||||
disco_loop(disasm, queue, real_out, use_uncompyle6_format)
|
||||
|
||||
|
||||
def disco_loop(disasm, queue, real_out, use_uncompyle6_format):
|
||||
while len(queue) > 0:
|
||||
co = queue.popleft()
|
||||
if co.co_name != '<module>':
|
||||
print('\n# %s line %d of %s' %
|
||||
(co.co_name, co.co_firstlineno, co.co_filename),
|
||||
file=real_out)
|
||||
tokens, customize = disasm(co, use_uncompyle6_format)
|
||||
for t in tokens:
|
||||
if iscode(t.pattr):
|
||||
queue.append(t.pattr)
|
||||
print(t.format(), file=real_out)
|
||||
pass
|
||||
pass
|
||||
|
||||
def disassemble_file(filename, outstream=None, native=False):
|
||||
"""
|
||||
|
@@ -50,6 +50,7 @@ class Code(object):
|
||||
class Scanner(object):
|
||||
|
||||
def __init__(self, version):
|
||||
self.version = version
|
||||
# FIXME: DRY
|
||||
if version == 2.7:
|
||||
self.opc = opcode_27
|
||||
@@ -68,6 +69,7 @@ class Scanner(object):
|
||||
else:
|
||||
raise TypeError("%s is not a Python version I know about" % version)
|
||||
|
||||
self.opname = self.opc.opname
|
||||
# FIXME: This weird Python2 behavior is not Python3
|
||||
self.resetTokenClass()
|
||||
|
||||
@@ -96,9 +98,9 @@ class Scanner(object):
|
||||
op = self.code[i]
|
||||
if op in self.opc.hasjabs+self.opc.hasjrel:
|
||||
dest = self.get_target(i, op)
|
||||
print('%i\t%s\t%i' % (i, self.opc.opname[op], dest))
|
||||
print('%i\t%s\t%i' % (i, self.opname[op], dest))
|
||||
else:
|
||||
print('%i\t%s\t' % (i, self.opc.opname[op]))
|
||||
print('%i\t%s\t' % (i, self.opname[op]))
|
||||
|
||||
def first_instr(self, start, end, instr, target=None, exact=True):
|
||||
"""
|
||||
@@ -291,27 +293,28 @@ def get_scanner(version):
|
||||
# from trepan.api import debug;
|
||||
# debug(start_opts={'startup-profile': True})
|
||||
|
||||
# FIXME: see if we can do better
|
||||
if version == 2.7:
|
||||
import uncompyle6.scanners.scanner27 as scan
|
||||
scanner = scan.Scanner27(version)
|
||||
scanner = scan.Scanner27()
|
||||
elif version == 2.6:
|
||||
import uncompyle6.scanners.scanner26 as scan
|
||||
scanner = scan.Scanner26(version)
|
||||
scanner = scan.Scanner26()
|
||||
elif version == 2.5:
|
||||
import uncompyle6.scanners.scanner25 as scan
|
||||
scanner = scan.Scanner25(version)
|
||||
scanner = scan.Scanner25()
|
||||
elif version == 3.2:
|
||||
import uncompyle6.scanners.scanner32 as scan
|
||||
scanner = scan.Scanner32(version)
|
||||
scanner = scan.Scanner32()
|
||||
elif version == 3.3:
|
||||
import uncompyle6.scanners.scanner33 as scan
|
||||
scanner = scan.Scanner33(version)
|
||||
scanner = scan.Scanner33()
|
||||
elif version == 3.4:
|
||||
import uncompyle6.scanners.scanner34 as scan
|
||||
scanner = scan.Scanner34(version)
|
||||
scanner = scan.Scanner34()
|
||||
elif version == 3.5:
|
||||
import uncompyle6.scanners.scanner35 as scan
|
||||
scanner = scan.Scanner35(version)
|
||||
scanner = scan.Scanner35()
|
||||
else:
|
||||
raise RuntimeError("Unsupported Python version %d" % version)
|
||||
return scanner
|
||||
|
@@ -1,8 +1,7 @@
|
||||
|
||||
# Copyright (c) 1999 John Aycock
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
# Copyright (c) 2015-2016 by Rocky Bernstein
|
||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||
# Copyright (c) 2015 by Rocky Bernstein
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
# Copyright (c) 1999 John Aycock
|
||||
#
|
||||
"""
|
||||
Python 2.5 bytecode scanner/deparser
|
||||
@@ -20,8 +19,8 @@ from uncompyle6.opcodes.opcode_25 import *
|
||||
import uncompyle6.scanner as scan
|
||||
|
||||
class Scanner25(scan.Scanner):
|
||||
def __init__(self, version):
|
||||
scan.Scanner.__init__(self, 2.5) # check
|
||||
def __init__(self):
|
||||
scan.Scanner.__init__(self, 2.5)
|
||||
|
||||
def disassemble(self, co, classname=None, code_objects={}):
|
||||
'''
|
||||
@@ -132,7 +131,7 @@ class Scanner25(scan.Scanner):
|
||||
extended_arg = 0
|
||||
for offset in self.op_range(0, codelen):
|
||||
op = self.code[offset]
|
||||
op_name = opname[op]
|
||||
op_name = self.opname[op]
|
||||
oparg = None; pattr = None
|
||||
|
||||
if offset in cf:
|
||||
@@ -913,10 +912,4 @@ class Scanner25(scan.Scanner):
|
||||
label = self.fixed_jumps[i]
|
||||
targets[label] = targets.get(label, []) + [i]
|
||||
return targets
|
||||
|
||||
if __name__ == "__main__":
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
tokens, customize = Scanner25().disassemble(co)
|
||||
for t in tokens:
|
||||
print(t)
|
||||
pass
|
||||
|
@@ -19,7 +19,7 @@ import dis
|
||||
import uncompyle6.scanner as scan
|
||||
|
||||
class Scanner26(scan.Scanner):
|
||||
def __init__(self, version):
|
||||
def __init__(self):
|
||||
scan.Scanner.__init__(self, 2.6)
|
||||
|
||||
def disassemble(self, co, classname=None, code_objects={}):
|
||||
@@ -130,7 +130,7 @@ class Scanner26(scan.Scanner):
|
||||
extended_arg = 0
|
||||
for offset in self.op_range(0, codelen):
|
||||
op = self.code[offset]
|
||||
op_name = opname[op]
|
||||
op_name = self.opname[op]
|
||||
oparg = None; pattr = None
|
||||
|
||||
if offset in cf:
|
||||
@@ -180,7 +180,10 @@ class Scanner26(scan.Scanner):
|
||||
elif op in haslocal:
|
||||
pattr = varnames[oparg]
|
||||
elif op in hascompare:
|
||||
pattr = cmp_op[oparg]
|
||||
try:
|
||||
pattr = cmp_op[oparg]
|
||||
except:
|
||||
from trepan.api import debug; debug()
|
||||
elif op in hasfree:
|
||||
pattr = free[oparg]
|
||||
if offset in self.toChange:
|
||||
@@ -917,8 +920,13 @@ class Scanner26(scan.Scanner):
|
||||
return targets
|
||||
|
||||
if __name__ == "__main__":
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
tokens, customize = Scanner26().disassemble(co)
|
||||
for t in tokens:
|
||||
print(t)
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
if PYTHON_VERSION == 2.6:
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
tokens, customize = Scanner26().disassemble(co)
|
||||
for t in tokens:
|
||||
print(t.format())
|
||||
else:
|
||||
print("Need to be Python 2.6 to demo; I am %s." %
|
||||
PYTHON_VERSION)
|
||||
|
@@ -22,8 +22,8 @@ from uncompyle6.opcodes.opcode_27 import * # NOQA
|
||||
import uncompyle6.scanner as scan
|
||||
|
||||
class Scanner27(scan.Scanner):
|
||||
def __init__(self, version):
|
||||
scan.Scanner.__init__(self, 2.7) # check
|
||||
def __init__(self):
|
||||
scan.Scanner.__init__(self, 2.7)
|
||||
|
||||
def disassemble(self, co, classname=None, code_objects={}):
|
||||
"""
|
||||
@@ -192,7 +192,7 @@ class Scanner27(scan.Scanner):
|
||||
tokens.append(Token(replace[offset], oparg, pattr, offset, linestart))
|
||||
return tokens, customize
|
||||
|
||||
def disassemble_native(self, co, opnames, classname=None, code_objects={}):
|
||||
def disassemble_native(self, co, classname=None, code_objects={}):
|
||||
"""
|
||||
Like disassemble3 but doesn't try to adjust any opcodes.
|
||||
"""
|
||||
@@ -728,8 +728,7 @@ class Scanner27(scan.Scanner):
|
||||
|
||||
if __name__ == "__main__":
|
||||
co = inspect.currentframe().f_code
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
tokens, customize = Scanner27(PYTHON_VERSION).disassemble(co)
|
||||
tokens, customize = Scanner27().disassemble(co)
|
||||
for t in tokens:
|
||||
print(t)
|
||||
pass
|
||||
|
@@ -45,17 +45,15 @@ import uncompyle6.scanner as scan
|
||||
|
||||
class Scanner3(scan.Scanner):
|
||||
|
||||
## FIXME opnames should be passed in here
|
||||
def __init__(self, version):
|
||||
self.version = version
|
||||
self.opnames = {} # will eventually get passed in
|
||||
scan.Scanner.__init__(self, version)
|
||||
if PYTHON3:
|
||||
super().__init__(version)
|
||||
else:
|
||||
super(Scanner3, self).__init__(version)
|
||||
|
||||
|
||||
## FIXME opnames should be moved to init
|
||||
def disassemble3(self, co, opnames, classname=None, code_objects={}):
|
||||
def disassemble3(self, co, classname=None, code_objects={}):
|
||||
"""
|
||||
Disassemble a Python 3 ode object, returning a list of 'Token'.
|
||||
Disassemble a Python 3 code object, returning a list of 'Token'.
|
||||
Various tranformations are made to assist the deparsing grammar.
|
||||
For example:
|
||||
- various types of LOAD_CONST's are categorized in terms of what they load
|
||||
@@ -65,8 +63,6 @@ class Scanner3(scan.Scanner):
|
||||
dis.disassemble().
|
||||
"""
|
||||
|
||||
self.opnames = opnames # will eventually disasppear
|
||||
|
||||
# import dis; dis.disassemble(co) # DEBUG
|
||||
|
||||
# Container for tokens
|
||||
@@ -76,7 +72,7 @@ class Scanner3(scan.Scanner):
|
||||
self.build_lines_data(co)
|
||||
self.build_prev_op()
|
||||
|
||||
bytecode = dis3.Bytecode(co, opnames)
|
||||
bytecode = dis3.Bytecode(co, self.opname)
|
||||
|
||||
# Scan for assertions. Later we will
|
||||
# turn 'LOAD_GLOBAL' to 'LOAD_ASSERT' for those
|
||||
@@ -164,7 +160,7 @@ class Scanner3(scan.Scanner):
|
||||
pattr = inst.argval
|
||||
target = self.get_target(inst.offset)
|
||||
if target < inst.offset:
|
||||
next_opname = opnames[self.code[inst.offset+3]]
|
||||
next_opname = self.opname[self.code[inst.offset+3]]
|
||||
if (inst.offset in self.stmts and
|
||||
next_opname not in ('END_FINALLY', 'POP_BLOCK')
|
||||
and inst.offset not in self.not_continue):
|
||||
@@ -187,7 +183,7 @@ class Scanner3(scan.Scanner):
|
||||
pass
|
||||
return tokens, {}
|
||||
|
||||
def disassemble3_native(self, co, opnames, classname=None, code_objects={}):
|
||||
def disassemble3_native(self, co, classname=None, code_objects={}):
|
||||
"""
|
||||
Like disassemble3 but doesn't try to adjust any opcodes.
|
||||
"""
|
||||
@@ -196,7 +192,7 @@ class Scanner3(scan.Scanner):
|
||||
|
||||
self.code = array('B', co.co_code)
|
||||
|
||||
bytecode = dis3.Bytecode(co, opnames)
|
||||
bytecode = dis3.Bytecode(co, self.opname)
|
||||
|
||||
for inst in bytecode:
|
||||
pattr = inst.argrepr
|
||||
@@ -292,7 +288,7 @@ class Scanner3(scan.Scanner):
|
||||
pass
|
||||
|
||||
op = code[offset]
|
||||
op_name = op3.opname[op]
|
||||
op_name = self.opname[op]
|
||||
|
||||
oparg = None; pattr = None
|
||||
|
||||
@@ -907,11 +903,15 @@ class Scanner3(scan.Scanner):
|
||||
return filtered
|
||||
|
||||
if __name__ == "__main__":
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
from opcode import opname
|
||||
tokens, customize = Scanner3(PYTHON_VERSION).disassemble3(co, opname)
|
||||
for t in tokens:
|
||||
print(t)
|
||||
if PYTHON_VERSION >= 3.2:
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
tokens, customize = Scanner3(PYTHON_VERSION).disassemble3(co)
|
||||
for t in tokens:
|
||||
print(t.format())
|
||||
else:
|
||||
print("Need to be Python 3.2 or greater to demo; I am %s." %
|
||||
PYTHON_VERSION)
|
||||
pass
|
||||
|
@@ -2,28 +2,38 @@
|
||||
"""
|
||||
Python 3.2 bytecode scanner/deparser
|
||||
|
||||
This overlaps various Python3.2's dis module, but it can be run from
|
||||
Python versions other than the version running this code. Notably,
|
||||
run from Python version 2. See doc comments in scanner3.py for more information.
|
||||
This sets up opcodes Python's 3.2 and calls a generalized
|
||||
scanner routine for Python 3.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import uncompyle6.scanners.scanner3 as scan3
|
||||
import uncompyle6
|
||||
|
||||
import uncompyle6.opcodes.opcode_32
|
||||
# verify uses JUMP_OPs from here
|
||||
# bytecode verification, verify(), uses JUMP_OPs from here
|
||||
JUMP_OPs = uncompyle6.opcodes.opcode_32.JUMP_OPs
|
||||
|
||||
class Scanner32(scan3.Scanner3):
|
||||
from uncompyle6.scanners.scanner3 import Scanner3
|
||||
class Scanner32(Scanner3):
|
||||
|
||||
def __init__(self):
|
||||
super(Scanner3, self).__init__(3.2)
|
||||
|
||||
def disassemble(self, co, classname=None, code_objects={}):
|
||||
return self.disassemble_generic(co, classname, code_objects=code_objects)
|
||||
|
||||
def disassemble_native(self, co, classname=None, code_objects={}):
|
||||
return self.disassemble3_native(co, classname, code_objects)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
tokens, customize = Scanner32(3.2).disassemble(co)
|
||||
for t in tokens:
|
||||
print(t)
|
||||
pass
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
if PYTHON_VERSION == 3.2:
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
tokens, customize = Scanner32().disassemble(co)
|
||||
for t in tokens:
|
||||
print(t)
|
||||
pass
|
||||
else:
|
||||
print("Need to be Python 3.2 to demo; I am %s." %
|
||||
PYTHON_VERSION)
|
||||
|
@@ -9,21 +9,32 @@ for later use in deparsing.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import uncompyle6.scanners.scanner3 as scan3
|
||||
import uncompyle6
|
||||
|
||||
import uncompyle6.opcodes.opcode_33
|
||||
# verify uses JUMP_OPs from here
|
||||
# bytecode verification, verify(), uses JUMP_OPs from here
|
||||
JUMP_OPs = uncompyle6.opcodes.opcode_33.JUMP_OPs
|
||||
|
||||
class Scanner33(scan3.Scanner3):
|
||||
from uncompyle6.scanners.scanner3 import Scanner3
|
||||
class Scanner33(Scanner3):
|
||||
|
||||
def __init__(self):
|
||||
super(Scanner3, self).__init__(3.3)
|
||||
|
||||
def disassemble(self, co, classname=None, code_objects={}):
|
||||
return self.disassemble_generic(co, classname, code_objects=code_objects)
|
||||
|
||||
def disassemble_native(self, co, classname=None, code_objects={}):
|
||||
return self.disassemble3_native(co, classname, code_objects)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
tokens, customize = Scanner33(3.3).disassemble(co)
|
||||
for t in tokens:
|
||||
print(t)
|
||||
pass
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
if PYTHON_VERSION == 3.3:
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
tokens, customize = Scanner33().disassemble(co)
|
||||
for t in tokens:
|
||||
print(t)
|
||||
pass
|
||||
else:
|
||||
print("Need to be Python 3.3 to demo; I am %s." %
|
||||
PYTHON_VERSION)
|
||||
|
@@ -2,29 +2,38 @@
|
||||
"""
|
||||
Python 3.4 bytecode scanner/deparser
|
||||
|
||||
This sets up opcodes Python's 3.5 and calls a generalized
|
||||
This sets up opcodes Python's 3.4 and calls a generalized
|
||||
scanner routine for Python 3.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
from uncompyle6.scanners.scanner3 import Scanner3
|
||||
from uncompyle6.opcodes.opcode_34 import opname as opnames
|
||||
import uncompyle6
|
||||
|
||||
# bytecode verification, verify(), uses JUMP_OPs from here
|
||||
from uncompyle6.opcodes.opcode_34 import JUMP_OPs
|
||||
|
||||
from uncompyle6.scanners.scanner3 import Scanner3
|
||||
class Scanner34(Scanner3):
|
||||
|
||||
def __init__(self):
|
||||
super(Scanner3, self).__init__(3.4)
|
||||
|
||||
def disassemble(self, co, classname=None, code_objects={}):
|
||||
return self.disassemble3(co, opnames, classname, code_objects)
|
||||
return self.disassemble3(co, classname, code_objects)
|
||||
|
||||
def disassemble_native(self, co, classname=None, code_objects={}):
|
||||
return self.disassemble3_native(co, opnames, classname, code_objects)
|
||||
return self.disassemble3_native(co, classname, code_objects)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
tokens, customize = Scanner34(3.4).disassemble(co)
|
||||
for t in tokens:
|
||||
print(t)
|
||||
pass
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
if PYTHON_VERSION >= 3.2:
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
tokens, customize = Scanner34(3.4).disassemble(co)
|
||||
for t in tokens:
|
||||
print(t)
|
||||
pass
|
||||
else:
|
||||
print("Need to be Python 3.2 or greater to demo; I am %s." %
|
||||
PYTHON_VERSION)
|
||||
|
@@ -9,22 +9,30 @@ scanner routine for Python 3.
|
||||
from __future__ import print_function
|
||||
|
||||
from uncompyle6.scanners.scanner3 import Scanner3
|
||||
from uncompyle6.opcodes.opcode_35 import opname as opnames
|
||||
|
||||
# bytecode verification, verify(), uses JUMP_OPs from here
|
||||
from uncompyle6.opcodes.opcode_35 import JUMP_OPs
|
||||
|
||||
class Scanner35(Scanner3):
|
||||
|
||||
def __init__(self):
|
||||
super(Scanner3, self).__init__(3.5)
|
||||
|
||||
def disassemble(self, co, classname=None, code_objects={}):
|
||||
return self.disassemble3(co, opnames, classname, code_objects)
|
||||
return self.disassemble3(co, classname, code_objects)
|
||||
|
||||
def disassemble_native(self, co, classname=None, code_objects={}):
|
||||
return self.disassemble3_native(co, opnames, classname, code_objects)
|
||||
return self.disassemble3_native(co, classname, code_objects)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
tokens, customize = Scanner35(3.5).disassemble(co)
|
||||
for t in tokens:
|
||||
print(t)
|
||||
pass
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
if PYTHON_VERSION == 3.5:
|
||||
import inspect
|
||||
co = inspect.currentframe().f_code
|
||||
tokens, customize = Scanner35(3.5).disassemble(co)
|
||||
for t in tokens:
|
||||
print(t.format())
|
||||
pass
|
||||
else:
|
||||
print("Need to be Python 3.5to demo; I am %s." %
|
||||
PYTHON_VERSION)
|
||||
|
@@ -1,3 +1,7 @@
|
||||
# Copyright (c) 2016 by Rocky Bernstein
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
# Copyright (c) 1999 John Aycock
|
||||
|
||||
import sys
|
||||
from uncompyle6 import PYTHON3
|
||||
|
||||
@@ -6,9 +10,9 @@ if PYTHON3:
|
||||
|
||||
class Token:
|
||||
"""
|
||||
Class representing a byte-code token.
|
||||
Class representing a byte-code instruction.
|
||||
|
||||
A byte-code token is equivalent to Python 3's dis.instruction or
|
||||
A byte-code token is equivalent to Python 3's dis.instruction or
|
||||
the contents of one line as output by dis.dis().
|
||||
"""
|
||||
# FIXME: match Python 3.4's terms:
|
||||
|
@@ -182,22 +182,22 @@ def cmp_code_objects(version, code_obj1, code_obj2, name=''):
|
||||
elif member == 'co_code':
|
||||
if version == 2.5:
|
||||
import uncompyle6.scanners.scanner25 as scan
|
||||
scanner = scan.Scanner25(version)
|
||||
scanner = scan.Scanner25()
|
||||
elif version == 2.6:
|
||||
import uncompyle6.scanners.scanner26 as scan
|
||||
scanner = scan.Scanner26(version)
|
||||
scanner = scan.Scanner26()
|
||||
elif version == 2.7:
|
||||
import uncompyle6.scanners.scanner27 as scan
|
||||
scanner = scan.Scanner27(version)
|
||||
scanner = scan.Scanner27()
|
||||
elif version == 3.2:
|
||||
import uncompyle6.scanners.scanner32 as scan
|
||||
scanner = scan.Scanner32(version)
|
||||
scanner = scan.Scanner32()
|
||||
elif version == 3.3:
|
||||
import uncompyle6.scanners.scanner33 as scan
|
||||
scanner = scan.Scanner33(version)
|
||||
scanner = scan.Scanner33()
|
||||
elif version == 3.4:
|
||||
import uncompyle6.scanners.scanner34 as scan
|
||||
scanner = scan.Scanner34(version)
|
||||
scanner = scan.Scanner34()
|
||||
|
||||
global JUMP_OPs
|
||||
JUMP_OPs = list(scan.JUMP_OPs) + ['JUMP_BACK']
|
||||
|
Reference in New Issue
Block a user