You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 01:09:52 +08:00
Add LICENSE. Add demo programs and DRY code a little
This commit is contained in:
@@ -1,12 +1,11 @@
|
|||||||
|
# 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 by Rocky Bernstein
|
||||||
|
# See LICENSE for license
|
||||||
"""
|
"""
|
||||||
Deparsing saving text fragment information indexed by offset
|
Deparsing saving text fragment information indexed by offset
|
||||||
|
|
||||||
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 by Rocky Bernstein
|
|
||||||
|
|
||||||
See main module for license.
|
|
||||||
|
|
||||||
Decompilation (walking AST)
|
Decompilation (walking AST)
|
||||||
|
|
||||||
@@ -55,6 +54,7 @@ from uncompyle6.walker import AST, NONE, find_all_globals
|
|||||||
from uncompyle6.walker import find_globals, find_none, INDENT_PER_LEVEL
|
from uncompyle6.walker import find_globals, find_none, INDENT_PER_LEVEL
|
||||||
from uncompyle6.walker import ParserError
|
from uncompyle6.walker import ParserError
|
||||||
from uncompyle6 import parser
|
from uncompyle6 import parser
|
||||||
|
from uncompyle6.scanner import Token, Code, get_scanner
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
@@ -70,13 +70,6 @@ from uncompyle6.spark import GenericASTTraversal
|
|||||||
from uncompyle6.spark import GenericASTTraversalPruningException
|
from uncompyle6.spark import GenericASTTraversalPruningException
|
||||||
from types import CodeType
|
from types import CodeType
|
||||||
|
|
||||||
try:
|
|
||||||
from uncompyle6.Scanner import Token, Code
|
|
||||||
older_uncompyle = True
|
|
||||||
except ImportError:
|
|
||||||
from uncompyle6.scanner import Token, Code
|
|
||||||
older_uncompyle = False
|
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
NodeInfo = namedtuple("NodeInfo", "node start finish")
|
NodeInfo = namedtuple("NodeInfo", "node start finish")
|
||||||
ExtractInfo = namedtuple("ExtractInfo",
|
ExtractInfo = namedtuple("ExtractInfo",
|
||||||
@@ -1118,27 +1111,7 @@ def deparse(version, co, out=StringIO(), showasm=0, showast=0):
|
|||||||
assert inspect.iscode(co)
|
assert inspect.iscode(co)
|
||||||
# store final output stream for case of error
|
# store final output stream for case of error
|
||||||
__real_out = out or sys.stdout
|
__real_out = out or sys.stdout
|
||||||
try:
|
scanner = get_scanner(version)
|
||||||
import uncompyle6.Scanner as scan
|
|
||||||
scanner = scan.Scanner(version)
|
|
||||||
except ImportError:
|
|
||||||
if version == 2.5:
|
|
||||||
import uncompyle6.scanners.scanner25 as scan
|
|
||||||
scanner = scan.Scanner25()
|
|
||||||
elif version == 2.6:
|
|
||||||
import uncompyle6.scanners.scanner26 as scan
|
|
||||||
scanner = scan.Scanner26()
|
|
||||||
elif version == 2.7:
|
|
||||||
import uncompyle6.scanners.scanner27 as scan
|
|
||||||
scanner = scan.Scanner27()
|
|
||||||
elif version == 3.2:
|
|
||||||
import uncompyle6.scanners.scanner34 as scan
|
|
||||||
scanner = scan.Scanner32()
|
|
||||||
elif version == 3.4:
|
|
||||||
import uncompyle6.scanners.scanner34 as scan
|
|
||||||
scanner = scan.Scanner34()
|
|
||||||
|
|
||||||
scanner.setShowAsm(showasm, out)
|
|
||||||
tokens, customize = scanner.disassemble(co)
|
tokens, customize = scanner.disassemble(co)
|
||||||
|
|
||||||
# Build AST from disassembly.
|
# Build AST from disassembly.
|
||||||
@@ -1146,10 +1119,7 @@ def deparse(version, co, out=StringIO(), showasm=0, showast=0):
|
|||||||
walk = Traverser(scanner, showast=showast)
|
walk = Traverser(scanner, showast=showast)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if older_uncompyle:
|
walk.ast = walk.build_ast_d(tokens, customize)
|
||||||
walk.ast = walk.build_ast_d(tokens, customize)
|
|
||||||
else:
|
|
||||||
walk.ast = walk.build_ast_d(tokens, customize)
|
|
||||||
except walker.ParserError as e : # parser failed, dump disassembly
|
except walker.ParserError as e : # parser failed, dump disassembly
|
||||||
print(e, file=__real_out)
|
print(e, file=__real_out)
|
||||||
raise
|
raise
|
||||||
|
@@ -20,6 +20,7 @@ from __future__ import print_function
|
|||||||
|
|
||||||
import importlib, inspect, os, sys
|
import importlib, inspect, os, sys
|
||||||
import uncompyle6
|
import uncompyle6
|
||||||
|
from uncompyle6.scanner import get_scanner
|
||||||
|
|
||||||
def check_object_path(path):
|
def check_object_path(path):
|
||||||
if path.endswith(".py"):
|
if path.endswith(".py"):
|
||||||
@@ -44,23 +45,7 @@ def disco(version, co, out=None):
|
|||||||
print('# Embedded file name: %s' % co.co_filename,
|
print('# Embedded file name: %s' % co.co_filename,
|
||||||
file=real_out)
|
file=real_out)
|
||||||
|
|
||||||
# Pick up appropriate scanner
|
scanner = get_scanner(version)
|
||||||
if version == 2.7:
|
|
||||||
import uncompyle6.scanners.scanner27 as scan
|
|
||||||
scanner = scan.Scanner27()
|
|
||||||
elif version == 2.6:
|
|
||||||
import uncompyle6.scanners.scanner26 as scan
|
|
||||||
scanner = scan.Scanner26()
|
|
||||||
elif version == 2.5:
|
|
||||||
import uncompyle6.scanners.scanner25 as scan
|
|
||||||
scanner = scan.Scanner25()
|
|
||||||
elif version == 3.2:
|
|
||||||
import uncompyle6.scanners.scanner32 as scan
|
|
||||||
scanner = scan.Scanner32()
|
|
||||||
elif version == 3.4:
|
|
||||||
import uncompyle6.scanners.scanner34 as scan
|
|
||||||
scanner = scan.Scanner34()
|
|
||||||
scanner.setShowAsm(True, out)
|
|
||||||
tokens, customize = scanner.disassemble(co)
|
tokens, customize = scanner.disassemble(co)
|
||||||
|
|
||||||
for t in tokens:
|
for t in tokens:
|
||||||
|
@@ -1,23 +1,16 @@
|
|||||||
from __future__ import print_function
|
# 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
|
||||||
|
"""
|
||||||
|
Spark parser for Python.
|
||||||
|
"""
|
||||||
|
|
||||||
'''
|
from uncompyle6 import PYTHON3
|
||||||
Copyright (c) 1999 John Aycock
|
from uncompyle6.spark import GenericASTBuilder
|
||||||
Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
|
||||||
Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
|
||||||
|
|
||||||
See main module for license.
|
import sys
|
||||||
'''
|
if PYTHON3:
|
||||||
|
|
||||||
__all__ = ['parse', 'AST', 'ParserError', 'Parser']
|
|
||||||
|
|
||||||
try:
|
|
||||||
from spark import GenericASTBuilder
|
|
||||||
except ImportError:
|
|
||||||
from .spark import GenericASTBuilder
|
|
||||||
|
|
||||||
import string, sys
|
|
||||||
|
|
||||||
if (sys.version_info >= (3, 0)):
|
|
||||||
intern = sys.intern
|
intern = sys.intern
|
||||||
from collections import UserList
|
from collections import UserList
|
||||||
else:
|
else:
|
||||||
@@ -794,3 +787,24 @@ def parse(tokens, customize):
|
|||||||
ast = p.parse(tokens)
|
ast = p.parse(tokens)
|
||||||
# p.cleanup()
|
# p.cleanup()
|
||||||
return ast
|
return ast
|
||||||
|
|
||||||
|
|
||||||
|
def parser(version, co, out=sys.stdout, showasm=False):
|
||||||
|
import inspect
|
||||||
|
assert inspect.iscode(co)
|
||||||
|
from uncompyle6.scanner import get_scanner
|
||||||
|
scanner = get_scanner(version)
|
||||||
|
tokens, customize = scanner.disassemble(co)
|
||||||
|
if showasm:
|
||||||
|
for t in tokens:
|
||||||
|
print(t)
|
||||||
|
|
||||||
|
return parse(tokens, customize)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
def parse_test(co):
|
||||||
|
sys_version = sys.version_info.major + (sys.version_info.minor / 10.0)
|
||||||
|
ast = parser(sys_version, co, showasm=True)
|
||||||
|
print(ast)
|
||||||
|
return
|
||||||
|
parse_test(parse_test.__code__)
|
||||||
|
@@ -2,10 +2,10 @@
|
|||||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||||
#
|
#
|
||||||
# See main module for license.
|
# See LICENSE
|
||||||
#
|
#
|
||||||
"""
|
"""
|
||||||
scanner/disassembler module. From here we call various verison-specific
|
scanner/disassembler module. From here we call various version-specific
|
||||||
scanners, e.g. for Python 2.7 or 3.4.
|
scanners, e.g. for Python 2.7 or 3.4.
|
||||||
|
|
||||||
This overlaps Python's dis module, but it can be run from Python 2 or
|
This overlaps Python's dis module, but it can be run from Python 2 or
|
||||||
@@ -16,8 +16,6 @@ for later use in deparsing.
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['Token', 'Scanner', 'Code']
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from uncompyle6 import PYTHON3
|
from uncompyle6 import PYTHON3
|
||||||
@@ -328,10 +326,32 @@ class Scanner(object):
|
|||||||
target = parent['end']
|
target = parent['end']
|
||||||
return target
|
return target
|
||||||
|
|
||||||
|
def get_scanner(version):
|
||||||
|
# Pick up appropriate scanner
|
||||||
|
if version == 2.7:
|
||||||
|
import uncompyle6.scanners.scanner27 as scan
|
||||||
|
scanner = scan.Scanner27()
|
||||||
|
elif version == 2.6:
|
||||||
|
import uncompyle6.scanners.scanner26 as scan
|
||||||
|
scanner = scan.Scanner26()
|
||||||
|
elif version == 2.5:
|
||||||
|
import uncompyle6.scanners.scanner25 as scan
|
||||||
|
scanner = scan.Scanner25()
|
||||||
|
elif version == 3.2:
|
||||||
|
import uncompyle6.scanners.scanner32 as scan
|
||||||
|
scanner = scan.Scanner32()
|
||||||
|
elif version == 3.4:
|
||||||
|
import uncompyle6.scanners.scanner34 as scan
|
||||||
|
scanner = scan.Scanner34()
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Unsupported Python version %d" % version)
|
||||||
|
return scanner
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import inspect, uncompyle6
|
import inspect, uncompyle6
|
||||||
co = inspect.currentframe().f_code
|
co = inspect.currentframe().f_code
|
||||||
tokens, customize = Scanner(uncompyle6.PYTHON_VERSION).disassemble(co)
|
tokens, customize = Scanner(uncompyle6.PYTHON_VERSION).disassemble(co)
|
||||||
|
print('-' * 30)
|
||||||
for t in tokens:
|
for t in tokens:
|
||||||
print(t)
|
print(t)
|
||||||
pass
|
pass
|
||||||
|
@@ -1,13 +1,8 @@
|
|||||||
from __future__ import print_function
|
# 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) 1999 John Aycock
|
|
||||||
Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
|
||||||
Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
|
||||||
|
|
||||||
See main module for license.
|
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
Decompilation (walking AST)
|
Decompilation (walking AST)
|
||||||
|
|
||||||
All table-driven. Step 1 determines a table (T) and a path to a
|
All table-driven. Step 1 determines a table (T) and a path to a
|
||||||
@@ -41,17 +36,19 @@ from __future__ import print_function
|
|||||||
|
|
||||||
The '%' may optionally be followed by a number (C) in square brackets, which
|
The '%' may optionally be followed by a number (C) in square brackets, which
|
||||||
makes the engine walk down to N[C] before evaluating the escape code.
|
makes the engine walk down to N[C] before evaluating the escape code.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
import sys, re
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import inspect, sys, re
|
||||||
|
|
||||||
|
from uncompyle6 import PYTHON3
|
||||||
from uncompyle6.spark import GenericASTTraversal
|
from uncompyle6.spark import GenericASTTraversal
|
||||||
from uncompyle6.parser import AST
|
from uncompyle6.parser import AST
|
||||||
from uncompyle6.scanner import Token, Code
|
from uncompyle6.scanner import Token, Code, get_scanner
|
||||||
|
|
||||||
if (sys.version_info >= (3, 0)):
|
if PYTHON3:
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
import uncompyle6
|
|
||||||
minint = -sys.maxsize-1
|
minint = -sys.maxsize-1
|
||||||
maxint = sys.maxsize
|
maxint = sys.maxsize
|
||||||
else:
|
else:
|
||||||
@@ -59,11 +56,8 @@ else:
|
|||||||
minint = -sys.maxint-1
|
minint = -sys.maxint-1
|
||||||
maxint = sys.maxint
|
maxint = sys.maxint
|
||||||
|
|
||||||
from types import CodeType
|
|
||||||
|
|
||||||
import uncompyle6.parser as dparser
|
import uncompyle6.parser as dparser
|
||||||
|
|
||||||
|
|
||||||
# Some ASTs used for comparing code fragments (like 'return None' at
|
# Some ASTs used for comparing code fragments (like 'return None' at
|
||||||
# the end of functions).
|
# the end of functions).
|
||||||
|
|
||||||
@@ -451,7 +445,7 @@ def find_none(node):
|
|||||||
class Walker(GenericASTTraversal, object):
|
class Walker(GenericASTTraversal, object):
|
||||||
stacked_params = ('f', 'indent', 'isLambda', '_globals')
|
stacked_params = ('f', 'indent', 'isLambda', '_globals')
|
||||||
|
|
||||||
def __init__(self, out, scanner, showast=0):
|
def __init__(self, out, scanner, showast=False):
|
||||||
GenericASTTraversal.__init__(self, ast=None)
|
GenericASTTraversal.__init__(self, ast=None)
|
||||||
self.scanner = scanner
|
self.scanner = scanner
|
||||||
params = {
|
params = {
|
||||||
@@ -920,7 +914,7 @@ class Walker(GenericASTTraversal, object):
|
|||||||
self.prec = 27
|
self.prec = 27
|
||||||
code = node[-5].attr
|
code = node[-5].attr
|
||||||
|
|
||||||
assert type(code) == CodeType
|
assert inspect.iscode(code)
|
||||||
code = Code(code, self.scanner, self.currentclass)
|
code = Code(code, self.scanner, self.currentclass)
|
||||||
# assert isinstance(code, Code)
|
# assert isinstance(code, Code)
|
||||||
|
|
||||||
@@ -1283,7 +1277,7 @@ class Walker(GenericASTTraversal, object):
|
|||||||
defparams = node[:node[-1].attr] # node[-1] == MAKE_xxx_n
|
defparams = node[:node[-1].attr] # node[-1] == MAKE_xxx_n
|
||||||
code = node[-2].attr
|
code = node[-2].attr
|
||||||
|
|
||||||
assert type(code) == CodeType
|
assert inspect.iscode(code)
|
||||||
code = Code(code, self.scanner, self.currentclass)
|
code = Code(code, self.scanner, self.currentclass)
|
||||||
# assert isinstance(code, Code)
|
# assert isinstance(code, Code)
|
||||||
|
|
||||||
@@ -1349,7 +1343,7 @@ class Walker(GenericASTTraversal, object):
|
|||||||
def build_class(self, code):
|
def build_class(self, code):
|
||||||
"""Dump class definition, doc string and class body."""
|
"""Dump class definition, doc string and class body."""
|
||||||
|
|
||||||
assert type(code) == CodeType
|
assert inspect.iscode(code)
|
||||||
code = Code(code, self.scanner, self.currentclass)
|
code = Code(code, self.scanner, self.currentclass)
|
||||||
# assert isinstance(code, Code)
|
# assert isinstance(code, Code)
|
||||||
|
|
||||||
@@ -1431,3 +1425,45 @@ class Walker(GenericASTTraversal, object):
|
|||||||
self.print_(repr(ast))
|
self.print_(repr(ast))
|
||||||
|
|
||||||
return ast
|
return ast
|
||||||
|
|
||||||
|
def walker(version, co, out=sys.stdout, showasm=False, showast=False):
|
||||||
|
assert inspect.iscode(co)
|
||||||
|
# store final output stream for case of error
|
||||||
|
__real_out = out or sys.stdout
|
||||||
|
scanner = get_scanner(version)
|
||||||
|
|
||||||
|
tokens, customize = scanner.disassemble(co)
|
||||||
|
if showasm:
|
||||||
|
for t in tokens:
|
||||||
|
print(t)
|
||||||
|
|
||||||
|
# Build AST from disassembly.
|
||||||
|
walk = Walker(out, scanner, showast=showast)
|
||||||
|
|
||||||
|
try:
|
||||||
|
walk.ast = walk.build_ast(tokens, customize)
|
||||||
|
except ParserError as e : # parser failed, dump disassembly
|
||||||
|
print(e, file=__real_out)
|
||||||
|
raise
|
||||||
|
|
||||||
|
del tokens # save memory
|
||||||
|
|
||||||
|
# convert leading '__doc__ = "..." into doc string
|
||||||
|
assert walk.ast == 'stmts'
|
||||||
|
walk.mod_globs = find_globals(walk.ast, set())
|
||||||
|
walk.gen_source(walk.ast, customize)
|
||||||
|
|
||||||
|
for g in walk.mod_globs:
|
||||||
|
walk.write('global %s ## Warning: Unused global' % g)
|
||||||
|
if walk.ERROR:
|
||||||
|
raise walk.ERROR
|
||||||
|
|
||||||
|
return walk
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
def walk_test(co):
|
||||||
|
sys_version = sys.version_info.major + (sys.version_info.minor / 10.0)
|
||||||
|
walker(sys_version, co, showasm=True, showast=True)
|
||||||
|
print()
|
||||||
|
return
|
||||||
|
walk_test(walk_test.__code__)
|
||||||
|
Reference in New Issue
Block a user