You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 09:22:40 +08:00
Compare commits
1 Commits
release-2.
...
release-2.
Author | SHA1 | Date | |
---|---|---|---|
|
39ce40004b |
46
ChangeLog
46
ChangeLog
@@ -1,50 +1,6 @@
|
||||
2016-05-02 rocky <rocky@gnu.org>
|
||||
|
||||
* __pkginfo__.py, bin/pydisassemble, bin/uncompyle6, setup.py,
|
||||
uncompyle6/__init__.py, uncompyle6/version.py: Add -V | --version
|
||||
and simplfy changing it
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/__init__.py: Expose uncompyle_file
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* test/Makefile, uncompyle6/semantics/pysource.py: Bug
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* test/Makefile, test/simple_source/expression/05_const_map.py: Add
|
||||
test for last fix. Drop 2.5 test until we figure out what's wrong
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/parsers/parse3.py, uncompyle6/scanners/scanner35.py,
|
||||
uncompyle6/semantics/pysource.py: Bug in 3.5 constant map parsing
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/__init__.py: Export module load and fns load_file,
|
||||
load_module
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* __pkginfo__.py, setup.py, uncompyle6/marsh.py: License is MIT marsh.py: remove unused import
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/parsers/parse3.py: Forgot to define Python3ParserSingle
|
||||
|
||||
2016-05-01 rocky <rocky@gnu.org>
|
||||
|
||||
* uncompyle6/parser.py, uncompyle6/parsers/parse2.py,
|
||||
uncompyle6/parsers/parse3.py: Start to DRY Python2 and Python3
|
||||
grammars Separate out 3.2, and 3.5+ specific grammar code
|
||||
|
||||
2016-04-30 rocky <rocky@gnu.org>
|
||||
|
||||
* ChangeLog, NEWS, README.rst, __pkginfo__.py: Get ready for release
|
||||
2.3.1
|
||||
* README.rst, __pkginfo__.py: Get ready for release 2.3.0
|
||||
|
||||
2016-04-30 rocky <rocky@gnu.org>
|
||||
|
||||
|
13
NEWS
13
NEWS
@@ -1,16 +1,3 @@
|
||||
uncompyle6 2.3.2 2016-05-1
|
||||
|
||||
- Add --version option standalone scripts
|
||||
- Correct License information in package
|
||||
- expose fns uncompyle_file, load_file, and load_module
|
||||
- Start to DRY Python2 and Python3 grammars Separate out 3.2, and 3.5+
|
||||
specific grammar code
|
||||
- Fix bug in 3.5+ constant map parsing
|
||||
|
||||
uncompyle6 2.3.0, 2.3.1 2016-04-30
|
||||
|
||||
- Require spark_parser >= 1.1.0
|
||||
|
||||
uncompyle6 2.2.0 2016-04-30
|
||||
|
||||
- Spark is no longer here but pulled separate package spark_parse
|
||||
|
@@ -9,7 +9,7 @@
|
||||
|
||||
# Things that change more often go here.
|
||||
copyright = """
|
||||
Copyright (C) 2015, 2016 Rocky Bernstein <rb@dustyfeet.com>.
|
||||
Copyright (C) 2015 Rocky Bernstein <rb@dustyfeet.com>.
|
||||
"""
|
||||
|
||||
classifiers = ['Development Status :: 3 - Alpha',
|
||||
@@ -31,10 +31,7 @@ classifiers = ['Development Status :: 3 - Alpha',
|
||||
author = "Rocky Bernstein, Hartmut Goebel, John Aycock, and others"
|
||||
author_email = "rb@dustyfeet.com"
|
||||
ftp_url = None
|
||||
install_requires = ['python-spark >= 1.1.0']
|
||||
license = 'GPL'
|
||||
|
||||
license = 'MIT'
|
||||
# license = 'BSDish'
|
||||
mailing_list = 'python-debugger@googlegroups.com'
|
||||
modname = 'uncompyle6'
|
||||
packages = ['uncompyle6', 'uncompyle6.opcodes', 'uncompyle6.semantics', 'uncompyle6.scanners', 'uncompyle6.parsers']
|
||||
@@ -50,6 +47,7 @@ def get_srcdir():
|
||||
return os.path.realpath(filename)
|
||||
|
||||
ns = {}
|
||||
version = '2.3.0'
|
||||
web = 'https://github.com/rocky/python-uncompyle6/'
|
||||
|
||||
# tracebacks in zip files are funky and not debuggable
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# Mode: -*- python -*-
|
||||
#
|
||||
# Copyright (c) 2015-2016 by Rocky Bernstein <rb@dustyfeet.com>
|
||||
# Copyright (c) 2015 by Rocky Bernstein <rb@dustyfeet.com>
|
||||
#
|
||||
from __future__ import print_function
|
||||
import sys, os, getopt
|
||||
@@ -9,13 +9,11 @@ import sys, os, getopt
|
||||
program = os.path.basename(__file__)
|
||||
|
||||
__doc__ = """
|
||||
Usage:
|
||||
%s [OPTIONS]... FILE
|
||||
%s [--help | -h | -V | --version]
|
||||
Usage: %s [OPTIONS]... FILE
|
||||
|
||||
Examples:
|
||||
%s foo.pyc
|
||||
%s foo.py
|
||||
%s foo.pyc
|
||||
%s foo.py
|
||||
%s -o foo.pydis foo.pyc
|
||||
%s -o /tmp foo.pyc
|
||||
|
||||
@@ -26,7 +24,7 @@ Options:
|
||||
<path>
|
||||
--help show this message
|
||||
|
||||
""" % ((program,) * 6)
|
||||
""" % ((program,) * 5)
|
||||
|
||||
|
||||
Usage_short = \
|
||||
@@ -34,7 +32,6 @@ Usage_short = \
|
||||
|
||||
from uncompyle6 import check_python_version
|
||||
from uncompyle6.disas import disassemble_files
|
||||
from uncompyle6.version import VERSION
|
||||
|
||||
check_python_version(program)
|
||||
|
||||
@@ -43,7 +40,7 @@ out_base = None
|
||||
|
||||
|
||||
try:
|
||||
opts, files = getopt.getopt(sys.argv[1:], 'hVo:', ['help', 'version'])
|
||||
opts, files = getopt.getopt(sys.argv[1:], 'ho:', ['help'])
|
||||
except getopt.GetoptError as e:
|
||||
print('%s: %s' % (os.path.basename(sys.argv[0]), e), file=sys.stderr)
|
||||
sys.exit(-1)
|
||||
@@ -51,9 +48,6 @@ except getopt.GetoptError as e:
|
||||
for opt, val in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
print(__doc__)
|
||||
sys.exit(1)
|
||||
elif opt in ('-V', '--version'):
|
||||
print("%s %s" % (program, VERSION))
|
||||
sys.exit(0)
|
||||
elif opt == '-o':
|
||||
outfile = val
|
||||
|
@@ -1,23 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
# Mode: -*- python -*-
|
||||
#
|
||||
# Copyright (c) 2015-2016 by Rocky Bernstein
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
#
|
||||
from __future__ import print_function
|
||||
import sys, os, getopt, time
|
||||
# Copyright (c) 2015 by Rocky Bernstein
|
||||
|
||||
program = os.path.basename(__file__)
|
||||
|
||||
__doc__ = """
|
||||
Usage:
|
||||
%s [OPTIONS]... [ FILE | DIR]...
|
||||
%s [--help | -h | --V | --version]
|
||||
"""
|
||||
Usage: uncompyle6 [OPTIONS]... [ FILE | DIR]...
|
||||
|
||||
Examples:
|
||||
%s foo.pyc bar.pyc # decompile foo.pyc, bar.pyc to stdout
|
||||
%s -o . foo.pyc bar.pyc # decompile to ./foo.pyc_dis and ./bar.pyc_dis
|
||||
%s -o /tmp /usr/lib/python1.5 # decompile whole library
|
||||
uncompyle6 foo.pyc bar.pyc # decompile foo.pyc, bar.pyc to stdout
|
||||
uncompyle6 -o . foo.pyc bar.pyc # decompile to ./foo.pyc_dis and ./bar.pyc_dis
|
||||
uncompyle6 -o /tmp /usr/lib/python1.5 # decompile whole library
|
||||
|
||||
Options:
|
||||
-o <path> output decompiled files to this path:
|
||||
@@ -41,25 +34,26 @@ Options:
|
||||
Debugging Options:
|
||||
--asm -a include byte-code (disables --verify)
|
||||
--grammar -g show matching grammar
|
||||
--tree -t include syntax tree (disables --verify)
|
||||
--treee -t include syntax tree (disables --verify)
|
||||
|
||||
Extensions of generated files:
|
||||
'.pyc_dis' '.pyo_dis' successfully decompiled (and verified if --verify)
|
||||
+ '_unverified' successfully decompile but --verify failed
|
||||
+ '_failed' decompile failed (contact author for enhancement)
|
||||
""" % ((program,) * 6
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
import sys, os, getopt, time
|
||||
|
||||
program = os.path.basename(__file__)
|
||||
|
||||
from uncompyle6 import verify, check_python_version
|
||||
from uncompyle6.main import main, status_msg
|
||||
from uncompyle6.version import VERSION
|
||||
|
||||
def usage():
|
||||
print("""usage:
|
||||
%s [--verify] [--asm] [--tree] [--grammar] [-o <path>] FILE|DIR...
|
||||
%s [--help | -h | --version | -V]
|
||||
""" % (program, program))
|
||||
%s [--help] [--verify] [--asm] [--tree] [--grammar] [-o <path>] FILE|DIR...
|
||||
""" % program)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -74,8 +68,8 @@ timestamp = False
|
||||
timestampfmt = "# %Y.%m.%d %H:%M:%S %Z"
|
||||
|
||||
try:
|
||||
opts, files = getopt.getopt(sys.argv[1:], 'hagtdrVo:c:p:',
|
||||
'help asm grammar recurse timestamp tree verify version '
|
||||
opts, files = getopt.getopt(sys.argv[1:], 'hagtdro:c:p:',
|
||||
'help asm grammar recurse timestamp tree verify '
|
||||
'showgrammar'.split(' '))
|
||||
except getopt.GetoptError as e:
|
||||
print('%s: %s' % (os.path.basename(sys.argv[0]), e), file=sys.stderr)
|
||||
@@ -86,9 +80,6 @@ for opt, val in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
print(__doc__)
|
||||
sys.exit(0)
|
||||
elif opt in ('-V', '--version'):
|
||||
print("%s %s" % (program, VERSION))
|
||||
sys.exit(0)
|
||||
elif opt == '--verify':
|
||||
options['do_verify'] = True
|
||||
elif opt in ('--asm', '-a'):
|
||||
|
17
setup.py
17
setup.py
@@ -2,24 +2,29 @@
|
||||
|
||||
"""Setup script for the 'uncompyle6' distribution."""
|
||||
|
||||
# Get the package information used in setup().
|
||||
# from __pkginfo__ import \
|
||||
# author, author_email, classifiers, \
|
||||
# install_requires, license, long_description, \
|
||||
# modname, packages, py_modules, \
|
||||
# short_desc, version, web, zip_safe
|
||||
|
||||
from __pkginfo__ import \
|
||||
author, author_email, \
|
||||
license, long_description, \
|
||||
long_description, \
|
||||
modname, packages, py_modules, scripts, \
|
||||
short_desc, web, zip_safe
|
||||
short_desc, version, web, zip_safe
|
||||
|
||||
__import__('pkg_resources')
|
||||
from setuptools import setup
|
||||
|
||||
exec(open('uncompyle6/version.py').read())
|
||||
|
||||
setup(
|
||||
author = author,
|
||||
author_email = author_email,
|
||||
# classifiers = classifiers,
|
||||
description = short_desc,
|
||||
# install_requires = install_requires,
|
||||
license = license,
|
||||
# license = license,
|
||||
long_description = long_description,
|
||||
py_modules = py_modules,
|
||||
name = modname,
|
||||
@@ -28,5 +33,5 @@ setup(
|
||||
url = web,
|
||||
setup_requires = ['nose>=1.0'],
|
||||
scripts = scripts,
|
||||
version = VERSION,
|
||||
version = version,
|
||||
zip_safe = zip_safe)
|
||||
|
Binary file not shown.
Binary file not shown.
@@ -1,7 +0,0 @@
|
||||
# Addresses a bug in the way Python 3.5+ handles
|
||||
# creation of map constants
|
||||
opts = {'highlight': True,
|
||||
'start_line': -1,
|
||||
'end_line': None
|
||||
}
|
||||
print(opts)
|
@@ -30,8 +30,6 @@ from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
__docformat__ = 'restructuredtext'
|
||||
|
||||
PYTHON3 = (sys.version_info >= (3, 0))
|
||||
|
||||
# We do this crazy way to support Python 2.6 which
|
||||
@@ -52,11 +50,6 @@ def check_python_version(program):
|
||||
|
||||
import uncompyle6.semantics.pysource
|
||||
import uncompyle6.semantics.fragments
|
||||
import uncompyle6.load
|
||||
|
||||
# Export some functions
|
||||
from uncompyle6.load import load_module, load_file
|
||||
from uncompyle6.main import uncompyle_file
|
||||
|
||||
# Conventience functions so you can say:
|
||||
# from uncompyle6 import deparse_code
|
||||
|
@@ -18,6 +18,7 @@ from __future__ import print_function
|
||||
import sys, types
|
||||
from struct import unpack
|
||||
|
||||
import uncompyle6.scanners.scanner3 as scan3
|
||||
from uncompyle6.magics import PYTHON_MAGIC_INT
|
||||
from uncompyle6.code import Code3
|
||||
|
||||
|
@@ -192,51 +192,6 @@ class PythonParser(GenericASTBuilder):
|
||||
load_attrs ::= load_attrs LOAD_ATTR
|
||||
'''
|
||||
|
||||
def p_list_comprehension(self, args):
|
||||
"""
|
||||
expr ::= list_compr
|
||||
list_compr ::= BUILD_LIST_0 list_iter
|
||||
|
||||
list_iter ::= list_for
|
||||
list_iter ::= list_if
|
||||
list_iter ::= list_if_not
|
||||
list_iter ::= lc_body
|
||||
|
||||
_come_from ::= COME_FROM
|
||||
_come_from ::=
|
||||
|
||||
list_if ::= expr jmp_false list_iter
|
||||
list_if_not ::= expr jmp_true list_iter
|
||||
|
||||
lc_body ::= expr LIST_APPEND
|
||||
"""
|
||||
|
||||
def p_setcomp(self, args):
|
||||
"""
|
||||
expr ::= setcomp
|
||||
|
||||
setcomp ::= LOAD_SETCOMP MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
|
||||
|
||||
stmt ::= setcomp_func
|
||||
|
||||
setcomp_func ::= BUILD_SET_0 LOAD_FAST FOR_ITER designator comp_iter
|
||||
JUMP_BACK RETURN_VALUE RETURN_LAST
|
||||
|
||||
comp_iter ::= comp_if
|
||||
comp_iter ::= comp_ifnot
|
||||
comp_iter ::= comp_for
|
||||
comp_iter ::= comp_body
|
||||
comp_body ::= set_comp_body
|
||||
comp_body ::= gen_comp_body
|
||||
comp_body ::= dict_comp_body
|
||||
set_comp_body ::= expr SET_ADD
|
||||
gen_comp_body ::= expr YIELD_VALUE POP_TOP
|
||||
dict_comp_body ::= expr expr MAP_ADD
|
||||
|
||||
comp_if ::= expr jmp_false comp_iter
|
||||
comp_ifnot ::= expr jmp_true comp_iter
|
||||
"""
|
||||
|
||||
|
||||
def parse(p, tokens, customize):
|
||||
p.add_custom_rules(tokens, customize)
|
||||
@@ -246,11 +201,12 @@ def parse(p, tokens, customize):
|
||||
|
||||
|
||||
def get_python_parser(version, debug_parser, compile_mode='exec'):
|
||||
"""Returns parser object for Python version 2 or 3, 3.2, 3.5on,
|
||||
etc., depending on the parameters passed. *compile_mode* is either
|
||||
'exec', 'eval', or 'single'. See
|
||||
https://docs.python.org/3.6/library/functions.html#compile for an
|
||||
explanation of the different modes.
|
||||
"""
|
||||
Returns parser object for Python version 2 or 3
|
||||
depending on the parameter passed. *compile_mode*
|
||||
is either 'exec', 'eval', or 'single'. See
|
||||
https://docs.python.org/3.6/library/functions.html#compile for an explanation
|
||||
of the different modes.
|
||||
"""
|
||||
|
||||
if version < 3.0:
|
||||
@@ -261,34 +217,13 @@ def get_python_parser(version, debug_parser, compile_mode='exec'):
|
||||
p = parse2.Python2ParserSingle(debug_parser)
|
||||
else:
|
||||
import uncompyle6.parsers.parse3 as parse3
|
||||
if version == 3.2:
|
||||
if compile_mode == 'exec':
|
||||
p = parse3.Python32Parser(debug_parser)
|
||||
else:
|
||||
p = parse3.Python32ParserSingle(debug_parser)
|
||||
elif version >= 3.5:
|
||||
if compile_mode == 'exec':
|
||||
p = parse3.Python35onParser(debug_parser)
|
||||
else:
|
||||
p = parse3.Python35onParserSingle(debug_parser)
|
||||
if compile_mode == 'exec':
|
||||
p = parse3.Python3Parser(debug_parser)
|
||||
else:
|
||||
if compile_mode == 'exec':
|
||||
p = parse3.Python3Parser(debug_parser)
|
||||
else:
|
||||
p = parse3.Python3ParserSingle(debug_parser)
|
||||
p = parse3.Python3ParserSingle(debug_parser)
|
||||
p.version = version
|
||||
return p
|
||||
|
||||
class PythonParserSingle(PythonParser):
|
||||
def p_call_stmt(self, args):
|
||||
'''
|
||||
# single-mode compilation. Eval-mode interactive compilation
|
||||
# drops the last rule.
|
||||
|
||||
call_stmt ::= expr POP_TOP
|
||||
call_stmt ::= expr PRINT_EXPR
|
||||
'''
|
||||
|
||||
def python_parser(version, co, out=sys.stdout, showasm=False,
|
||||
parser_debug=PARSER_DEFAULT_DEBUG):
|
||||
assert iscode(co)
|
||||
|
@@ -17,9 +17,9 @@ that a later phase can tern into a sequence of ASCII text.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
|
||||
from uncompyle6.parser import PythonParser, nop_func
|
||||
from uncompyle6.parsers.astnode import AST
|
||||
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
from uncompyle6 import PYTHON3
|
||||
|
||||
class Python2Parser(PythonParser):
|
||||
@@ -31,14 +31,52 @@ class Python2Parser(PythonParser):
|
||||
super(Python2Parser, self).__init__(AST, 'stmts', debug=debug_parser)
|
||||
self.customized = {}
|
||||
|
||||
def p_list_comprehension2(self, args):
|
||||
"""
|
||||
list_for ::= expr _for designator list_iter JUMP_BACK
|
||||
"""
|
||||
|
||||
def p_setcomp2(self, args):
|
||||
def p_list_comprehension(self, args):
|
||||
'''
|
||||
# This is different in python3 - should it be?
|
||||
expr ::= list_compr
|
||||
list_compr ::= BUILD_LIST_0 list_iter
|
||||
|
||||
list_iter ::= list_for
|
||||
list_iter ::= list_if
|
||||
list_iter ::= list_if_not
|
||||
list_iter ::= lc_body
|
||||
|
||||
_come_from ::= COME_FROM
|
||||
_come_from ::=
|
||||
|
||||
list_for ::= expr _for designator list_iter JUMP_BACK
|
||||
list_if ::= expr jmp_false list_iter
|
||||
list_if_not ::= expr jmp_true list_iter
|
||||
|
||||
lc_body ::= expr LIST_APPEND
|
||||
'''
|
||||
|
||||
def p_setcomp(self, args):
|
||||
'''
|
||||
expr ::= setcomp
|
||||
|
||||
setcomp ::= LOAD_SETCOMP MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
|
||||
|
||||
stmt ::= setcomp_func
|
||||
|
||||
setcomp_func ::= BUILD_SET_0 LOAD_FAST FOR_ITER designator comp_iter
|
||||
JUMP_BACK RETURN_VALUE RETURN_LAST
|
||||
|
||||
comp_iter ::= comp_if
|
||||
comp_iter ::= comp_ifnot
|
||||
comp_iter ::= comp_for
|
||||
comp_iter ::= comp_body
|
||||
comp_body ::= set_comp_body
|
||||
comp_body ::= gen_comp_body
|
||||
comp_body ::= dict_comp_body
|
||||
set_comp_body ::= expr SET_ADD
|
||||
gen_comp_body ::= expr YIELD_VALUE POP_TOP
|
||||
dict_comp_body ::= expr expr MAP_ADD
|
||||
|
||||
comp_if ::= expr jmp_false comp_iter
|
||||
comp_ifnot ::= expr jmp_true comp_iter
|
||||
|
||||
# This is different in python3 - shout it be?
|
||||
comp_for ::= expr _for designator comp_iter JUMP_BACK
|
||||
'''
|
||||
|
||||
@@ -571,5 +609,12 @@ class Python2Parser(PythonParser):
|
||||
raise Exception('unknown customize token %s' % k)
|
||||
self.addRule(rule, nop_func)
|
||||
|
||||
class Python2ParserSingle(Python2Parser, PythonParserSingle):
|
||||
pass
|
||||
class Python2ParserSingle(Python2Parser):
|
||||
def p_call_stmt(self, args):
|
||||
'''
|
||||
# single-mode compilation. eval-mode interactive compilation
|
||||
# drops the last rule.
|
||||
|
||||
call_stmt ::= expr POP_TOP
|
||||
call_stmt ::= expr PRINT_EXPR
|
||||
'''
|
||||
|
@@ -17,7 +17,7 @@ that a later phase can tern into a sequence of ASCII text.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
|
||||
from uncompyle6.parser import PythonParser, nop_func
|
||||
from uncompyle6.parsers.astnode import AST
|
||||
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
from uncompyle6 import PYTHON3
|
||||
@@ -42,26 +42,60 @@ class Python3Parser(PythonParser):
|
||||
pass
|
||||
return
|
||||
|
||||
def p_list_comprehension3(self, args):
|
||||
"""
|
||||
def p_list_comprehension(self, args):
|
||||
'''
|
||||
# Python3 scanner adds LOAD_LISTCOMP. Python3 does list comprehension like
|
||||
# other comprehensions (set, dictionary).
|
||||
|
||||
# listcomp is a custom Python3 rule
|
||||
# listcomp is a custom rule
|
||||
expr ::= listcomp
|
||||
|
||||
expr ::= list_compr
|
||||
list_compr ::= BUILD_LIST_0 list_iter
|
||||
|
||||
list_iter ::= list_for
|
||||
list_iter ::= list_if
|
||||
list_iter ::= list_if_not
|
||||
list_iter ::= lc_body
|
||||
|
||||
_come_from ::= COME_FROM
|
||||
_come_from ::=
|
||||
|
||||
list_for ::= expr FOR_ITER designator list_iter JUMP_BACK
|
||||
list_if ::= expr jmp_false list_iter
|
||||
list_if_not ::= expr jmp_true list_iter
|
||||
|
||||
# See also common Python p_list_comprehension
|
||||
"""
|
||||
lc_body ::= expr LIST_APPEND
|
||||
'''
|
||||
|
||||
def p_setcomp3(self, args):
|
||||
"""
|
||||
# This is different in Python 2 - should it be?
|
||||
def p_setcomp(self, args):
|
||||
'''
|
||||
expr ::= setcomp
|
||||
|
||||
setcomp ::= LOAD_SETCOMP MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
|
||||
|
||||
stmt ::= setcomp_func
|
||||
|
||||
setcomp_func ::= BUILD_SET_0 LOAD_FAST FOR_ITER designator comp_iter
|
||||
JUMP_BACK RETURN_VALUE RETURN_LAST
|
||||
|
||||
comp_iter ::= comp_if
|
||||
comp_iter ::= comp_ifnot
|
||||
comp_iter ::= comp_for
|
||||
comp_iter ::= comp_body
|
||||
comp_body ::= set_comp_body
|
||||
comp_body ::= gen_comp_body
|
||||
comp_body ::= dict_comp_body
|
||||
set_comp_body ::= expr SET_ADD
|
||||
gen_comp_body ::= expr YIELD_VALUE POP_TOP
|
||||
dict_comp_body ::= expr expr MAP_ADD
|
||||
|
||||
comp_if ::= expr jmp_false comp_iter
|
||||
comp_ifnot ::= expr jmp_true comp_iter
|
||||
|
||||
# This is different in python2 - should it be?
|
||||
comp_for ::= expr _for designator comp_iter JUMP_ABSOLUTE
|
||||
|
||||
# See also common Python p_setcomp
|
||||
"""
|
||||
'''
|
||||
|
||||
def p_grammar(self, args):
|
||||
'''
|
||||
@@ -120,6 +154,9 @@ class Python3Parser(PythonParser):
|
||||
designList ::= designator designator
|
||||
designList ::= designator DUP_TOP designList
|
||||
|
||||
# FIXME: Store local is only used in Python 3.2
|
||||
designator ::= STORE_LOCALS
|
||||
|
||||
designator ::= STORE_FAST
|
||||
designator ::= STORE_NAME
|
||||
designator ::= STORE_GLOBAL
|
||||
@@ -241,6 +278,9 @@ class Python3Parser(PythonParser):
|
||||
_ifstmts_jump ::= return_if_stmts
|
||||
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_from _come_from
|
||||
|
||||
# FIXME: this optimization is only used in Python 3.5 and beyond
|
||||
_ifstmts_jump ::= c_stmts_opt
|
||||
|
||||
iflaststmt ::= testexpr c_stmts_opt JUMP_ABSOLUTE
|
||||
|
||||
iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK
|
||||
@@ -615,12 +655,6 @@ class Python3Parser(PythonParser):
|
||||
elif opname_base in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET'):
|
||||
rule = 'build_list ::= ' + 'expr ' * token.attr + opname
|
||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||
elif self.version >= 3.5 and opname_base == 'BUILD_MAP':
|
||||
kvlist_n = "kvlist_%s" % token.attr
|
||||
rule = kvlist_n + ' ::= ' + 'expr ' * (token.attr*2)
|
||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||
rule = "mapexpr ::= %s %s" % (kvlist_n, opname)
|
||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||
elif opname_base in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
|
||||
rule = 'unpack ::= ' + opname + ' designator' * token.attr
|
||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||
@@ -659,25 +693,12 @@ class Python3Parser(PythonParser):
|
||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||
return
|
||||
|
||||
class Python32Parser(Python3Parser):
|
||||
def p_32(self, args):
|
||||
"""
|
||||
# Store locals is only used in Python 3.2
|
||||
designator ::= STORE_LOCALS
|
||||
"""
|
||||
class Python3ParserSingle(Python3Parser):
|
||||
def p_call_stmt(self, args):
|
||||
'''
|
||||
# single-mode compilation. Eval-mode interactive compilation
|
||||
# drops the last rule.
|
||||
|
||||
class Python3ParserSingle(Python3Parser, PythonParserSingle):
|
||||
pass
|
||||
|
||||
class Python32ParserSingle(Python32Parser, PythonParserSingle):
|
||||
pass
|
||||
|
||||
class Python35onParser(Python3Parser):
|
||||
def p_35on(self, args):
|
||||
"""
|
||||
# this optimization is only used in Python 3.5 and beyond
|
||||
_ifstmts_jump ::= c_stmts_opt
|
||||
"""
|
||||
|
||||
class Python35onParserSingle(Python35onParser, PythonParserSingle):
|
||||
pass
|
||||
call_stmt ::= expr POP_TOP
|
||||
call_stmt ::= expr PRINT_EXPR
|
||||
'''
|
||||
|
@@ -14,6 +14,7 @@ import dis, inspect
|
||||
from array import array
|
||||
import uncompyle6.scanners.scanner3 as scan3
|
||||
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
from uncompyle6.code import iscode
|
||||
from uncompyle6.scanner import Token
|
||||
|
||||
@@ -28,10 +29,13 @@ from uncompyle6.opcodes.opcode_35 import *
|
||||
|
||||
class Scanner35(scan3.Scanner3):
|
||||
|
||||
# Note: we can't use built-in disassembly routines, unless
|
||||
# we do post-processing like we do here.
|
||||
def disassemble(self, co, classname=None,
|
||||
code_objects={}):
|
||||
def disassemble(self, co, classname=None, code_objects={}):
|
||||
fn = self.disassemble_built_in if PYTHON_VERSION == 3.4 \
|
||||
else self.disassemble_generic
|
||||
return fn(co, classname, code_objects=code_objects)
|
||||
|
||||
def disassemble_built_in(self, co, classname=None,
|
||||
code_objects={}):
|
||||
# Container for tokens
|
||||
tokens = []
|
||||
customize = {}
|
||||
@@ -112,11 +116,17 @@ class Scanner35(scan3.Scanner3):
|
||||
pattr = const
|
||||
pass
|
||||
elif opname in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET', 'BUILD_SLICE',
|
||||
'BUILD_MAP',
|
||||
'UNPACK_SEQUENCE',
|
||||
'MAKE_FUNCTION', 'MAKE_CLOSURE',
|
||||
'DUP_TOPX', 'RAISE_VARARGS'
|
||||
):
|
||||
# if opname == 'BUILD_TUPLE' and \
|
||||
# self.code[self.prev[offset]] == LOAD_CLOSURE:
|
||||
# continue
|
||||
# else:
|
||||
# op_name = '%s_%d' % (op_name, oparg)
|
||||
# if opname != BUILD_SLICE:
|
||||
# customize[op_name] = oparg
|
||||
opname = '%s_%d' % (opname, inst.argval)
|
||||
if inst.opname != 'BUILD_SLICE':
|
||||
customize[opname] = inst.argval
|
||||
|
@@ -1148,42 +1148,29 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
"""
|
||||
p = self.prec
|
||||
self.prec = 100
|
||||
assert node[-1] == 'kvlist'
|
||||
node = node[-1] # goto kvlist
|
||||
|
||||
self.indentMore(INDENT_PER_LEVEL)
|
||||
line_seperator = ',\n' + self.indent
|
||||
sep = INDENT_PER_LEVEL[:-1]
|
||||
self.write('{')
|
||||
|
||||
if node[0].type.startswith('kvlist'):
|
||||
# Python 3.5 style key/value list in mapexpr
|
||||
l = list(node[0])
|
||||
i = 0
|
||||
while i < len(l):
|
||||
name = self.traverse(l[i], indent='')
|
||||
value = self.traverse(l[i+1], indent=self.indent+(len(name)+2)*' ')
|
||||
self.write(sep, name, ': ', value)
|
||||
sep = line_seperator
|
||||
i += 2
|
||||
else:
|
||||
assert node[-1] == 'kvlist'
|
||||
node = node[-1] # goto kvlist
|
||||
|
||||
for kv in node:
|
||||
assert kv in ('kv', 'kv2', 'kv3')
|
||||
# kv ::= DUP_TOP expr ROT_TWO expr STORE_SUBSCR
|
||||
# kv2 ::= DUP_TOP expr expr ROT_THREE STORE_SUBSCR
|
||||
# kv3 ::= expr expr STORE_MAP
|
||||
if kv == 'kv':
|
||||
name = self.traverse(kv[-2], indent='')
|
||||
value = self.traverse(kv[1], indent=self.indent+(len(name)+2)*' ')
|
||||
elif kv == 'kv2':
|
||||
name = self.traverse(kv[1], indent='')
|
||||
value = self.traverse(kv[-3], indent=self.indent+(len(name)+2)*' ')
|
||||
elif kv == 'kv3':
|
||||
name = self.traverse(kv[-2], indent='')
|
||||
value = self.traverse(kv[0], indent=self.indent+(len(name)+2)*' ')
|
||||
self.write(sep, name, ': ', value)
|
||||
sep = line_seperator
|
||||
for kv in node:
|
||||
assert kv in ('kv', 'kv2', 'kv3')
|
||||
# kv ::= DUP_TOP expr ROT_TWO expr STORE_SUBSCR
|
||||
# kv2 ::= DUP_TOP expr expr ROT_THREE STORE_SUBSCR
|
||||
# kv3 ::= expr expr STORE_MAP
|
||||
if kv == 'kv':
|
||||
name = self.traverse(kv[-2], indent='')
|
||||
value = self.traverse(kv[1], indent=self.indent+(len(name)+2)*' ')
|
||||
elif kv == 'kv2':
|
||||
name = self.traverse(kv[1], indent='')
|
||||
value = self.traverse(kv[-3], indent=self.indent+(len(name)+2)*' ')
|
||||
elif kv == 'kv3':
|
||||
name = self.traverse(kv[-2], indent='')
|
||||
value = self.traverse(kv[0], indent=self.indent+(len(name)+2)*' ')
|
||||
self.write(sep, name, ': ', value)
|
||||
sep = line_seperator
|
||||
self.write('}')
|
||||
self.indentLess(INDENT_PER_LEVEL)
|
||||
self.prec = p
|
||||
|
@@ -1,3 +0,0 @@
|
||||
# This file is suitable for sourcing inside bash as
|
||||
# well as importing into Python
|
||||
VERSION='2.3.2'
|
Reference in New Issue
Block a user