You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +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 spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
from uncompyle6.show import maybe_show_asm
|
||||
|
||||
|
||||
class ParserError(Exception):
|
||||
def __init__(self, token, offset):
|
||||
@@ -506,15 +508,30 @@ class PythonParserSingle(PythonParser):
|
||||
call_stmt ::= expr PRINT_EXPR
|
||||
'''
|
||||
|
||||
|
||||
def python_parser(version, co, out=sys.stdout, showasm=False,
|
||||
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)
|
||||
from uncompyle6.scanner import get_scanner
|
||||
scanner = get_scanner(version)
|
||||
tokens, customize = scanner.disassemble(co)
|
||||
if showasm:
|
||||
for t in tokens:
|
||||
print(t)
|
||||
maybe_show_asm(showasm, tokens)
|
||||
|
||||
# For heavy grammar debugging
|
||||
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 import parser
|
||||
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, \
|
||||
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)
|
||||
except (parser.ParserError, AssertionError) as e:
|
||||
raise ParserError(e, tokens)
|
||||
if self.showast:
|
||||
print(repr(ast))
|
||||
maybe_show_ast(self.showast, ast)
|
||||
return ast
|
||||
|
||||
# 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:
|
||||
raise ParserError(e, tokens)
|
||||
|
||||
if self.showast:
|
||||
print(repr(ast))
|
||||
maybe_show_ast(self.showast, ast)
|
||||
|
||||
return ast
|
||||
|
||||
@@ -1338,12 +1341,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
||||
pass
|
||||
|
||||
if default:
|
||||
if self.showast:
|
||||
print()
|
||||
print('--', name)
|
||||
print(default)
|
||||
print('--')
|
||||
pass
|
||||
maybe_show_ast_param_default(self.showast, name, default)
|
||||
result = '%s=' % name
|
||||
old_last_finish = self.last_finish
|
||||
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,
|
||||
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)
|
||||
# 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)
|
||||
if showasm:
|
||||
for t in tokens:
|
||||
print(t)
|
||||
maybe_show_asm(showasm, tokens)
|
||||
|
||||
debug_parser = dict(PARSER_DEFAULT_DEBUG)
|
||||
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.scanners.tok import Token, NoneToken
|
||||
import uncompyle6.parser as python_parser
|
||||
from uncompyle6.show import (
|
||||
maybe_show_asm,
|
||||
maybe_show_ast,
|
||||
maybe_show_ast_param_default,
|
||||
)
|
||||
|
||||
if PYTHON3:
|
||||
from itertools import zip_longest
|
||||
@@ -1636,11 +1641,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
pass
|
||||
|
||||
if default:
|
||||
if self.showast:
|
||||
print()
|
||||
print('--', name)
|
||||
print(default)
|
||||
print('--')
|
||||
maybe_show_ast_param_default(self.showast, name, default)
|
||||
result = '%s=%s' % (name, self.traverse(default, indent='') )
|
||||
if result[-2:] == '= ': # default was 'LOAD_CONST None'
|
||||
result += 'None'
|
||||
@@ -1835,8 +1836,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
ast = python_parser.parse(self.p, tokens, customize)
|
||||
except (python_parser.ParserError, AssertionError) as e:
|
||||
raise ParserError(e, tokens)
|
||||
if self.showast:
|
||||
self.println(repr(ast))
|
||||
maybe_show_ast(self.showast, ast)
|
||||
return ast
|
||||
|
||||
# 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:
|
||||
raise ParserError(e, tokens)
|
||||
|
||||
if self.showast:
|
||||
self.println(repr(ast))
|
||||
maybe_show_ast(self.showast, ast)
|
||||
|
||||
return ast
|
||||
|
||||
@@ -1884,9 +1883,7 @@ def deparse_code(version, co, out=sys.stdout, showasm=False, showast=False,
|
||||
scanner = get_scanner(version)
|
||||
|
||||
tokens, customize = scanner.disassemble(co, code_objects=code_objects)
|
||||
if showasm:
|
||||
for t in tokens:
|
||||
print(t)
|
||||
maybe_show_asm(showasm, tokens)
|
||||
|
||||
debug_parser = dict(PARSER_DEFAULT_DEBUG)
|
||||
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