You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 01:09:52 +08:00
showasm and showast now accept file like objects which are used for writing the the asm or ast to.
This commit is contained in:
@@ -12,6 +12,8 @@ import sys
|
|||||||
|
|
||||||
from xdis.code import iscode
|
from xdis.code import iscode
|
||||||
from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||||
|
from uncompyle6.show import maybe_show_asm
|
||||||
|
|
||||||
|
|
||||||
class ParserError(Exception):
|
class ParserError(Exception):
|
||||||
def __init__(self, token, offset):
|
def __init__(self, token, offset):
|
||||||
@@ -506,15 +508,30 @@ class PythonParserSingle(PythonParser):
|
|||||||
call_stmt ::= expr PRINT_EXPR
|
call_stmt ::= expr PRINT_EXPR
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
def python_parser(version, co, out=sys.stdout, showasm=False,
|
def python_parser(version, co, out=sys.stdout, showasm=False,
|
||||||
parser_debug=PARSER_DEFAULT_DEBUG):
|
parser_debug=PARSER_DEFAULT_DEBUG):
|
||||||
|
"""
|
||||||
|
Parse a code object to an abstract syntax tree representation.
|
||||||
|
|
||||||
|
:param version: The python version this code is from as a float, for
|
||||||
|
example 2.6, 2.7, 3.2, 3.3, 3.4, 3.5 etc.
|
||||||
|
:param co: The code object to parse.
|
||||||
|
:param out: File like object to write the output to.
|
||||||
|
:param showasm: Flag which determines whether the disassembled code
|
||||||
|
is written to sys.stdout or not. (It is also to
|
||||||
|
pass a file like object, into which the asm will be
|
||||||
|
written).
|
||||||
|
:param parser_debug: dict containing debug flags for the spark parser.
|
||||||
|
|
||||||
|
:return: Abstract syntax tree representation of the code object.
|
||||||
|
"""
|
||||||
|
|
||||||
assert iscode(co)
|
assert iscode(co)
|
||||||
from uncompyle6.scanner import get_scanner
|
from uncompyle6.scanner import get_scanner
|
||||||
scanner = get_scanner(version)
|
scanner = get_scanner(version)
|
||||||
tokens, customize = scanner.disassemble(co)
|
tokens, customize = scanner.disassemble(co)
|
||||||
if showasm:
|
maybe_show_asm(showasm, tokens)
|
||||||
for t in tokens:
|
|
||||||
print(t)
|
|
||||||
|
|
||||||
# For heavy grammar debugging
|
# For heavy grammar debugging
|
||||||
parser_debug = {'rules': True, 'transition': True, 'reduce' : True,
|
parser_debug = {'rules': True, 'transition': True, 'reduce' : True,
|
||||||
|
@@ -34,6 +34,11 @@ from uncompyle6.semantics import pysource
|
|||||||
from uncompyle6.parser import get_python_parser
|
from uncompyle6.parser import get_python_parser
|
||||||
from uncompyle6 import parser
|
from uncompyle6 import parser
|
||||||
from uncompyle6.scanner import Token, Code, get_scanner
|
from uncompyle6.scanner import Token, Code, get_scanner
|
||||||
|
from uncompyle6.show import (
|
||||||
|
maybe_show_asm,
|
||||||
|
maybe_show_ast,
|
||||||
|
maybe_show_ast_param_default,
|
||||||
|
)
|
||||||
|
|
||||||
from uncompyle6.semantics.pysource import AST, INDENT_PER_LEVEL, NONE, PRECEDENCE, \
|
from uncompyle6.semantics.pysource import AST, INDENT_PER_LEVEL, NONE, PRECEDENCE, \
|
||||||
ParserError, TABLE_DIRECT, escape, find_all_globals, find_globals, find_none, minint, MAP
|
ParserError, TABLE_DIRECT, escape, find_all_globals, find_globals, find_none, minint, MAP
|
||||||
@@ -750,8 +755,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
ast = parser.parse(self.p, tokens, customize)
|
ast = parser.parse(self.p, tokens, customize)
|
||||||
except (parser.ParserError, AssertionError) as e:
|
except (parser.ParserError, AssertionError) as e:
|
||||||
raise ParserError(e, tokens)
|
raise ParserError(e, tokens)
|
||||||
if self.showast:
|
maybe_show_ast(self.showast, ast)
|
||||||
print(repr(ast))
|
|
||||||
return ast
|
return ast
|
||||||
|
|
||||||
# The bytecode for the end of the main routine has a
|
# The bytecode for the end of the main routine has a
|
||||||
@@ -777,8 +781,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
except (parser.ParserError, AssertionError) as e:
|
except (parser.ParserError, AssertionError) as e:
|
||||||
raise ParserError(e, tokens)
|
raise ParserError(e, tokens)
|
||||||
|
|
||||||
if self.showast:
|
maybe_show_ast(self.showast, ast)
|
||||||
print(repr(ast))
|
|
||||||
|
|
||||||
return ast
|
return ast
|
||||||
|
|
||||||
@@ -1338,12 +1341,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
if default:
|
if default:
|
||||||
if self.showast:
|
maybe_show_ast_param_default(self.showast, name, default)
|
||||||
print()
|
|
||||||
print('--', name)
|
|
||||||
print(default)
|
|
||||||
print('--')
|
|
||||||
pass
|
|
||||||
result = '%s=' % name
|
result = '%s=' % name
|
||||||
old_last_finish = self.last_finish
|
old_last_finish = self.last_finish
|
||||||
self.last_finish = len(result)
|
self.last_finish = len(result)
|
||||||
@@ -1452,6 +1450,28 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
|
|
||||||
def deparse_code(version, co, out=StringIO(), showasm=False, showast=False,
|
def deparse_code(version, co, out=StringIO(), showasm=False, showast=False,
|
||||||
showgrammar=False):
|
showgrammar=False):
|
||||||
|
"""
|
||||||
|
Convert the code object co into a python source fragment.
|
||||||
|
|
||||||
|
:param version: The python version this code is from as a float, for
|
||||||
|
example 2.6, 2.7, 3.2, 3.3, 3.4, 3.5 etc.
|
||||||
|
:param co: The code object to parse.
|
||||||
|
:param out: File like object to write the output to.
|
||||||
|
:param showasm: Flag which determines whether the disassembled code
|
||||||
|
is written to sys.stdout or not. (It is also to
|
||||||
|
pass a file like object, into which the asm will be
|
||||||
|
written).
|
||||||
|
:param showast: Flag which determines whether the constructed
|
||||||
|
abstract syntax tree is written to sys.stdout or
|
||||||
|
not. (It is also to pass a file like object, into
|
||||||
|
which the ast will be written).
|
||||||
|
:param showgrammar: Flag which determines whether the grammar
|
||||||
|
is written to sys.stdout or not. (It is also to
|
||||||
|
pass a file like object, into which the grammer
|
||||||
|
will be written).
|
||||||
|
|
||||||
|
:return: The deparsed source fragment.
|
||||||
|
"""
|
||||||
|
|
||||||
assert iscode(co)
|
assert iscode(co)
|
||||||
# store final output stream for case of error
|
# store final output stream for case of error
|
||||||
@@ -1460,9 +1480,7 @@ def deparse_code(version, co, out=StringIO(), showasm=False, showast=False,
|
|||||||
tokens, customize = scanner.disassemble(co)
|
tokens, customize = scanner.disassemble(co)
|
||||||
|
|
||||||
tokens, customize = scanner.disassemble(co)
|
tokens, customize = scanner.disassemble(co)
|
||||||
if showasm:
|
maybe_show_asm(showasm, tokens)
|
||||||
for t in tokens:
|
|
||||||
print(t)
|
|
||||||
|
|
||||||
debug_parser = dict(PARSER_DEFAULT_DEBUG)
|
debug_parser = dict(PARSER_DEFAULT_DEBUG)
|
||||||
if showgrammar:
|
if showgrammar:
|
||||||
|
@@ -77,6 +77,11 @@ from spark_parser import GenericASTTraversal, DEFAULT_DEBUG as PARSER_DEFAULT_DE
|
|||||||
from uncompyle6.scanner import Code, get_scanner
|
from uncompyle6.scanner import Code, get_scanner
|
||||||
from uncompyle6.scanners.tok import Token, NoneToken
|
from uncompyle6.scanners.tok import Token, NoneToken
|
||||||
import uncompyle6.parser as python_parser
|
import uncompyle6.parser as python_parser
|
||||||
|
from uncompyle6.show import (
|
||||||
|
maybe_show_asm,
|
||||||
|
maybe_show_ast,
|
||||||
|
maybe_show_ast_param_default,
|
||||||
|
)
|
||||||
|
|
||||||
if PYTHON3:
|
if PYTHON3:
|
||||||
from itertools import zip_longest
|
from itertools import zip_longest
|
||||||
@@ -1636,11 +1641,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
if default:
|
if default:
|
||||||
if self.showast:
|
maybe_show_ast_param_default(self.showast, name, default)
|
||||||
print()
|
|
||||||
print('--', name)
|
|
||||||
print(default)
|
|
||||||
print('--')
|
|
||||||
result = '%s=%s' % (name, self.traverse(default, indent='') )
|
result = '%s=%s' % (name, self.traverse(default, indent='') )
|
||||||
if result[-2:] == '= ': # default was 'LOAD_CONST None'
|
if result[-2:] == '= ': # default was 'LOAD_CONST None'
|
||||||
result += 'None'
|
result += 'None'
|
||||||
@@ -1835,8 +1836,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
ast = python_parser.parse(self.p, tokens, customize)
|
ast = python_parser.parse(self.p, tokens, customize)
|
||||||
except (python_parser.ParserError, AssertionError) as e:
|
except (python_parser.ParserError, AssertionError) as e:
|
||||||
raise ParserError(e, tokens)
|
raise ParserError(e, tokens)
|
||||||
if self.showast:
|
maybe_show_ast(self.showast, ast)
|
||||||
self.println(repr(ast))
|
|
||||||
return ast
|
return ast
|
||||||
|
|
||||||
# The bytecode for the end of the main routine has a
|
# The bytecode for the end of the main routine has a
|
||||||
@@ -1863,8 +1863,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
except (python_parser.ParserError, AssertionError) as e:
|
except (python_parser.ParserError, AssertionError) as e:
|
||||||
raise ParserError(e, tokens)
|
raise ParserError(e, tokens)
|
||||||
|
|
||||||
if self.showast:
|
maybe_show_ast(self.showast, ast)
|
||||||
self.println(repr(ast))
|
|
||||||
|
|
||||||
return ast
|
return ast
|
||||||
|
|
||||||
@@ -1884,9 +1883,7 @@ def deparse_code(version, co, out=sys.stdout, showasm=False, showast=False,
|
|||||||
scanner = get_scanner(version)
|
scanner = get_scanner(version)
|
||||||
|
|
||||||
tokens, customize = scanner.disassemble(co, code_objects=code_objects)
|
tokens, customize = scanner.disassemble(co, code_objects=code_objects)
|
||||||
if showasm:
|
maybe_show_asm(showasm, tokens)
|
||||||
for t in tokens:
|
|
||||||
print(t)
|
|
||||||
|
|
||||||
debug_parser = dict(PARSER_DEFAULT_DEBUG)
|
debug_parser = dict(PARSER_DEFAULT_DEBUG)
|
||||||
if showgrammar:
|
if showgrammar:
|
||||||
|
@@ -0,0 +1,58 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def maybe_show_asm(showasm, tokens):
|
||||||
|
"""
|
||||||
|
Show the asm based on the showasm flag (or file object), writing to the
|
||||||
|
appropriate stream depending on the type of the flag.
|
||||||
|
|
||||||
|
:param showasm: Flag which determines whether the disassembled code is
|
||||||
|
written to sys.stdout or not. (It is also to pass a file
|
||||||
|
like object, into which the asm will be written).
|
||||||
|
:param tokens: The asm tokens to show.
|
||||||
|
"""
|
||||||
|
if showasm:
|
||||||
|
stream = showasm if hasattr(showasm, 'write') else sys.stdout
|
||||||
|
for t in tokens:
|
||||||
|
stream.write(t)
|
||||||
|
stream.write('\n')
|
||||||
|
|
||||||
|
|
||||||
|
def maybe_show_ast(showast, ast):
|
||||||
|
"""
|
||||||
|
Show the ast based on the showast flag (or file object), writing to the
|
||||||
|
appropriate stream depending on the type of the flag.
|
||||||
|
|
||||||
|
:param showasm: Flag which determines whether the abstract syntax tree is
|
||||||
|
written to sys.stdout or not. (It is also to pass a file
|
||||||
|
like object, into which the ast will be written).
|
||||||
|
:param ast: The ast to show.
|
||||||
|
"""
|
||||||
|
if showast:
|
||||||
|
stream = showast if hasattr(showast, 'write') else sys.stdout
|
||||||
|
stream.write(repr(ast))
|
||||||
|
stream.write('\n')
|
||||||
|
|
||||||
|
|
||||||
|
def maybe_show_ast_param_default(showast, name, default):
|
||||||
|
"""
|
||||||
|
Show a function parameter with default for an ast based on the showast flag
|
||||||
|
(or file object), writing to the appropriate stream depending on the type
|
||||||
|
of the flag.
|
||||||
|
|
||||||
|
:param showasm: Flag which determines whether the function parameter with
|
||||||
|
default is written to sys.stdout or not. (It is also to
|
||||||
|
pass a file like object, into which the ast will be
|
||||||
|
written).
|
||||||
|
:param name: The function parameter name.
|
||||||
|
:param default: The function parameter default.
|
||||||
|
"""
|
||||||
|
if showast:
|
||||||
|
stream = showast if hasattr(showast, 'write') else sys.stdout
|
||||||
|
stream.write('\n')
|
||||||
|
stream.write('--' + name)
|
||||||
|
stream.write('\n')
|
||||||
|
stream.write(default)
|
||||||
|
stream.write('\n')
|
||||||
|
stream.write('--')
|
||||||
|
stream.write('\n')
|
Reference in New Issue
Block a user